4
4
from itsdangerous import TimedSerializer , BadTimeSignature
5
5
from sqlalchemy .sql import and_ , or_ , not_
6
6
from sqlalchemy .sql .expression import union_all
7
+ from sqlalchemy .sql .functions import coalesce
7
8
from werkzeug .utils import secure_filename
8
9
from socket import inet_aton , inet_ntoa
9
10
from passlib .hash import bcrypt_sha256
18
19
import datetime
19
20
import calendar
20
21
22
+ from scoreboard import get_standings
23
+
21
24
admin = Blueprint ('admin' , __name__ )
22
25
23
26
@@ -276,12 +279,12 @@ def delete_container(container_id):
276
279
def new_container ():
277
280
name = request .form .get ('name' )
278
281
if set (name ) <= set ('abcdefghijklmnopqrstuvwxyz0123456789-_' ):
279
- return redirect ('/ admin/containers' )
282
+ return redirect (url_for ( ' admin.list_container' ) )
280
283
buildfile = request .form .get ('buildfile' )
281
284
files = request .files .getlist ('files[]' )
282
285
create_image (name = name , buildfile = buildfile , files = files )
283
286
run_image (name )
284
- return redirect ('/ admin/containers' )
287
+ return redirect (url_for ( ' admin.list_container' ) )
285
288
286
289
287
290
@@ -291,7 +294,7 @@ def admin_chals():
291
294
if request .method == 'POST' :
292
295
chals = Challenges .query .add_columns ('id' , 'name' , 'value' , 'description' , 'category' , 'hidden' ).order_by (Challenges .value ).all ()
293
296
294
- teams_with_points = db .session .query (Solves .teamid , Teams . name ).join (Teams ).filter (
297
+ teams_with_points = db .session .query (Solves .teamid ).join (Teams ).filter (
295
298
Teams .banned == False ).group_by (
296
299
Solves .teamid ).count ()
297
300
@@ -427,7 +430,7 @@ def admin_teams(page):
427
430
page_start = results_per_page * ( page - 1 )
428
431
page_end = results_per_page * ( page - 1 ) + results_per_page
429
432
430
- teams = Teams .query .slice (page_start , page_end ).all ()
433
+ teams = Teams .query .order_by ( Teams . id . asc ()). slice (page_start , page_end ).all ()
431
434
count = db .session .query (db .func .count (Teams .id )).first ()[0 ]
432
435
pages = int (count / results_per_page ) + (count % results_per_page > 0 )
433
436
return render_template ('admin/teams.html' , teams = teams , pages = pages , curr_page = page )
@@ -442,7 +445,9 @@ def admin_team(teamid):
442
445
solves = Solves .query .filter_by (teamid = teamid ).all ()
443
446
solve_ids = [s .chalid for s in solves ]
444
447
missing = Challenges .query .filter ( not_ (Challenges .id .in_ (solve_ids ) ) ).all ()
445
- addrs = Tracking .query .filter_by (team = teamid ).order_by (Tracking .date .desc ()).group_by (Tracking .ip ).all ()
448
+ addrs = db .session .query (Tracking .ip , db .func .max (Tracking .date )) \
449
+ .filter_by (team = teamid ) \
450
+ .group_by (Tracking .ip ).all ()
446
451
wrong_keys = WrongKeys .query .filter_by (teamid = teamid ).order_by (WrongKeys .date .asc ()).all ()
447
452
awards = Awards .query .filter_by (teamid = teamid ).order_by (Awards .date .asc ()).all ()
448
453
score = user .score ()
@@ -452,10 +457,12 @@ def admin_team(teamid):
452
457
elif request .method == 'POST' :
453
458
admin_user = request .form .get ('admin' , None )
454
459
if admin_user :
455
- admin_user = 1 if admin_user == " true" else 0
460
+ admin_user = True if admin_user == ' true' else False
456
461
user .admin = admin_user
462
+ # Set user.banned to hide admins from scoreboard
457
463
user .banned = admin_user
458
464
db .session .commit ()
465
+ db .session .close ()
459
466
return jsonify ({'data' : ['success' ]})
460
467
461
468
name = request .form .get ('name' , None )
@@ -545,35 +552,21 @@ def admin_graph(graph_type):
545
552
json_data ['categories' ].append ({'category' :category , 'count' :count })
546
553
return jsonify (json_data )
547
554
elif graph_type == "solves" :
548
- solves = Solves .query .join (Teams ).filter (Teams .banned == False ).add_columns (db .func .count (Solves .chalid )).group_by (Solves .chalid ).all ()
555
+ solves_sub = db .session .query (Solves .chalid , db .func .count (Solves .chalid ).label ('solves_cnt' )) \
556
+ .join (Teams , Solves .teamid == Teams .id ).filter (Teams .banned == False ) \
557
+ .group_by (Solves .chalid ).subquery ()
558
+ solves = db .session .query (solves_sub .columns .chalid , solves_sub .columns .solves_cnt , Challenges .name ) \
559
+ .join (Challenges , solves_sub .columns .chalid == Challenges .id ).all ()
549
560
json_data = {}
550
- for chal , count in solves :
551
- json_data [chal . chal . name ] = count
561
+ for chal , count , name in solves :
562
+ json_data [name ] = count
552
563
return jsonify (json_data )
553
564
554
565
555
566
@admin .route ('/admin/scoreboard' )
556
567
@admins_only
557
568
def admin_scoreboard ():
558
- score = db .func .sum (Challenges .value ).label ('score' )
559
- scores = db .session .query (Solves .teamid .label ('teamid' ), Teams .name .label ('name' ), Teams .banned .label ('banned' ), score , Solves .date .label ('date' )) \
560
- .join (Teams ) \
561
- .join (Challenges ) \
562
- .group_by (Solves .teamid )
563
-
564
- awards = db .session .query (Teams .id .label ('teamid' ), Teams .name .label ('name' ), Teams .banned .label ('banned' ),
565
- db .func .sum (Awards .value ).label ('score' ), Awards .date .label ('date' )) \
566
- .filter (Teams .id == Awards .teamid ) \
567
- .group_by (Teams .id )
568
-
569
- results = union_all (scores , awards ).alias ('results' )
570
-
571
- standings = db .session .query (results .columns .teamid , results .columns .name , results .columns .banned ,
572
- db .func .sum (results .columns .score ).label ('score' )) \
573
- .group_by (results .columns .teamid ) \
574
- .order_by (db .func .sum (results .columns .score ).desc (), db .func .max (results .columns .date )) \
575
- .all ()
576
- db .session .close ()
569
+ standings = get_standings (admin = True )
577
570
return render_template ('admin/scoreboard.html' , teams = standings )
578
571
579
572
@@ -711,9 +704,18 @@ def admin_stats():
711
704
wrong_count = db .session .query (db .func .count (WrongKeys .id )).first ()[0 ]
712
705
solve_count = db .session .query (db .func .count (Solves .id )).first ()[0 ]
713
706
challenge_count = db .session .query (db .func .count (Challenges .id )).first ()[0 ]
714
- most_solved_chal = Solves .query .add_columns (db .func .count (Solves .chalid ).label ('solves' )).group_by (Solves .chalid ).order_by ('solves DESC' ).first ()
715
- least_solved_chal = Challenges .query .add_columns (db .func .count (Solves .chalid ).label ('solves' )).outerjoin (Solves ).group_by (Challenges .id ).order_by ('solves ASC' ).first ()
716
-
707
+
708
+ solves_raw = db .func .count (Solves .chalid ).label ('solves_raw' )
709
+ solves_sub = db .session .query (Solves .chalid , solves_raw ) \
710
+ .group_by (Solves .chalid ).subquery ()
711
+ solves_cnt = coalesce (solves_sub .columns .solves_raw , 0 ).label ('solves_cnt' )
712
+ most_solved_chal = Challenges .query .add_columns (solves_cnt ) \
713
+ .outerjoin (solves_sub , solves_sub .columns .chalid == Challenges .id ) \
714
+ .order_by (solves_cnt .desc ()).first ()
715
+ least_solved_chal = Challenges .query .add_columns (solves_cnt ) \
716
+ .outerjoin (solves_sub , solves_sub .columns .chalid == Challenges .id ) \
717
+ .order_by (solves_cnt .asc ()).first ()
718
+
717
719
db .session .close ()
718
720
719
721
return render_template ('admin/statistics.html' , team_count = teams_registered ,
0 commit comments