@@ -68,7 +68,7 @@ export const getRankings = async (environment: Environment): Promise<RankingResu
68
68
return acc ;
69
69
} ;
70
70
71
- const participants = ( await UserRepository . getUsersOfRole ( Role . Participant ) ) . reduce ( reduceFunc , { } ) ;
71
+ const participants = ( await UserRepository . getUsersOfRole ( Role . Participant ) ) . filter ( p => ! p . disabled ) . reduce ( reduceFunc , { } ) ;
72
72
let scores : Score [ ] = [ ] ;
73
73
74
74
// For each participant, calculate their score
@@ -137,28 +137,17 @@ export const getRankings = async (environment: Environment): Promise<RankingResu
137
137
138
138
// Least moves and most completed mazes
139
139
// -------------------------
140
- const leastMoves = await pgQuery < AwardWithProps < { exitCount : number ; moveCount : string } > > (
140
+ const leastMoves = await pgQuery < AwardWithProps < { exitCount : string ; moveCount : string } > > (
141
141
`
142
- WITH exit_counts AS (
143
- SELECT user_id, COUNT(*) as exit_count
144
- FROM actions
145
- WHERE maze_id = ANY($1) AND action_type = $2 AND success = true
146
- GROUP BY user_id
147
- ),
148
- move_counts AS (
149
- SELECT user_id, COUNT(*) as move_count
150
- FROM actions
151
- WHERE maze_id = ANY($1) AND action_type = $3
152
- GROUP BY user_id
153
- )
154
- SELECT e.user_id, e.exit_count, m.move_count
155
- FROM exit_counts e
156
- JOIN move_counts m ON e.user_id = m.user_id
157
- WHERE e.exit_count = (SELECT MAX(exit_count) FROM exit_counts)
158
- AND m.move_count = (SELECT MIN(move_count) FROM move_counts)
159
- ORDER BY e.exit_count DESC, m.move_count ASC
142
+ SELECT users.id as user_id,
143
+ (SELECT COUNT(*) FROM actions WHERE user_id = users.id AND action_type = $1 AND success = TRUE) AS exit_count,
144
+ (SELECT COUNT(*) FROM actions WHERE user_id = users.id AND action_type = $2 AND success = TRUE) AS move_count
145
+ FROM users
146
+ WHERE role = $3
147
+ ORDER BY exit_count DESC, move_count ASC
148
+ LIMIT 1;
160
149
` ,
161
- [ mazeIds , ActionType . Exit , ActionType . Move ] ,
150
+ [ ActionType . Exit , ActionType . Move , Role . Participant ] ,
162
151
) ;
163
152
164
153
const leastMovesAward : Award = {
@@ -169,18 +158,13 @@ export const getRankings = async (environment: Environment): Promise<RankingResu
169
158
170
159
// *AWARD* Least Moves
171
160
if ( leastMoves . length > 0 ) {
172
- // Because the query is ordered by exit_count DESC and move_count ASC, the first item represents the least moves
173
- const minMoveCount = leastMoves [ 0 ] . moveCount ;
174
- for ( const result of leastMoves ) {
175
- if ( result . moveCount != minMoveCount ) {
176
- break ;
177
- }
161
+ const result = leastMoves [ 0 ] ;
162
+
163
+ leastMovesAward . winners . push ( {
164
+ userName : participants [ result . userId . toString ( ) ] . name ,
165
+ value : result . exitCount ,
166
+ } ) ;
178
167
179
- leastMovesAward . winners . push ( {
180
- userName : participants [ result . userId . toString ( ) ] . name ,
181
- value : result . moveCount ,
182
- } ) ;
183
- }
184
168
awards . push ( leastMovesAward ) ;
185
169
}
186
170
@@ -243,6 +227,43 @@ export const getRankings = async (environment: Environment): Promise<RankingResu
243
227
}
244
228
}
245
229
230
+ // Most Cheese Eaten
231
+ // -------------------------
232
+ const cheeseDropped = await pgQuery < AwardWithProps < { cheeseCount : number } > > (
233
+ `
234
+ SELECT user_id, COUNT(*) as cheese_count
235
+ FROM actions
236
+ WHERE maze_id = ANY($1) AND action_type = $2 AND success = true
237
+ GROUP BY user_id
238
+ ORDER BY cheese_count DESC
239
+ ` ,
240
+ [ mazeIds , ActionType . Drop ] ,
241
+ ) ;
242
+
243
+ const mostCheeseDroppedAward : Award = {
244
+ name : "Cheese Hoarder" ,
245
+ description : "The rat who dropped the most cheese" ,
246
+ winners : [ ] ,
247
+ } ;
248
+
249
+ // *AWARD* Most Cheese Eaten
250
+ if ( cheeseDropped . length > 0 ) {
251
+ // Because the query is ordered by cheese_count DESC, the first item represents the most cheese eaten
252
+ const maxCheeseCount = cheeseDropped [ 0 ] . cheeseCount ;
253
+ for ( const result of cheeseDropped ) {
254
+ if ( result . cheeseCount != maxCheeseCount ) {
255
+ break ;
256
+ }
257
+
258
+ mostCheeseDroppedAward . winners . push ( {
259
+ userName : participants [ result . userId . toString ( ) ] . name ,
260
+ value : result . cheeseCount ,
261
+ } ) ;
262
+ }
263
+
264
+ awards . push ( mostCheeseDroppedAward ) ;
265
+ }
266
+
246
267
// Most smells
247
268
// -------------------------
248
269
const mostSmells = await pgQuery < AwardWithProps < { smellCount : number } > > (
@@ -416,13 +437,16 @@ export const getRankings = async (environment: Environment): Promise<RankingResu
416
437
// -------------------------
417
438
const mostFailedActions = await pgQuery < AwardWithProps < { failCount : number } > > (
418
439
`
419
- SELECT user_id, COUNT(*) as fail_count
420
- FROM actions
421
- WHERE maze_id = ANY($1) AND success = false
422
- GROUP BY user_id
423
- ORDER BY fail_count DESC
440
+ SELECT
441
+ users.id as user_id,
442
+ (SELECT COUNT(*) FROM actions WHERE user_id = users.id AND success = FALSE) AS fail_count
443
+ FROM users
444
+ WHERE role = $1
445
+ AND disabled = FALSE
446
+ ORDER BY fail_count DESC
447
+ LIMIT 1;
424
448
` ,
425
- [ mazeIds ] ,
449
+ [ Role . Participant ] ,
426
450
) ;
427
451
428
452
const mostFailedActionsAward : Award = {
@@ -494,14 +518,16 @@ export const getRankings = async (environment: Environment): Promise<RankingResu
494
518
// -------------------------
495
519
const lastToHitAPI = await pgQuery < AwardWithProps < { lastHit : string } > > (
496
520
`
497
- SELECT user_id, MAX(time_ts) as last_hit
498
- FROM analytics
499
- WHERE user_id = ANY($1)
500
- GROUP BY user_id
501
- ORDER BY last_hit DESC
502
- LIMIT 1
521
+ SELECT first_hits.user_id, first_hits.time_ts AS last_hit
522
+ FROM (SELECT user_id, u.name AS name, MIN(time_ts) AS time_ts
523
+ FROM analytics a
524
+ LEFT JOIN users u ON a.user_id = u.id
525
+ WHERE role = $1
526
+ GROUP BY user_id, name) first_hits
527
+ ORDER BY first_hits.time_ts DESC
528
+ LIMIT 1;
503
529
` ,
504
- [ Object . keys ( participants ) ] ,
530
+ [ Role . Participant ] ,
505
531
) ;
506
532
const lastToHitAPIAward : Award = {
507
533
name : "Procrastinator" ,
@@ -520,16 +546,15 @@ export const getRankings = async (environment: Environment): Promise<RankingResu
520
546
521
547
// Hit the API first (Sandbox OR Competition)
522
548
// -------------------------
523
- const firstToHitAPI = await pgQuery < AwardWithProps < { firstHit : string } > > (
549
+ const firstToHitAPI = await pgQuery < AwardWithProps < { name : string ; firstHit : string } > > (
524
550
`
525
- SELECT user_id, MIN(time_ts) as first_hit
526
- FROM analytics
527
- WHERE user_id = ANY($1)
528
- GROUP BY user_id
529
- ORDER BY first_hit ASC
530
- LIMIT 1
551
+ SELECT user_id, u.name as name, MIN(time_ts) as first_hit
552
+ FROM analytics a left join users u on u.id = a.user_id
553
+ GROUP BY user_id, u.name
554
+ ORDER BY first_hit ASC
555
+ LIMIT 1
531
556
` ,
532
- [ Object . keys ( participants ) ] ,
557
+ [ ] ,
533
558
) ;
534
559
535
560
const firstToHitAPIAward : Award = {
@@ -541,7 +566,7 @@ export const getRankings = async (environment: Environment): Promise<RankingResu
541
566
// *AWARD* First to hit the API
542
567
if ( firstToHitAPI . length > 0 ) {
543
568
firstToHitAPIAward . winners . push ( {
544
- userName : participants [ firstToHitAPI [ 0 ] . userId . toString ( ) ] . name ,
569
+ userName : firstToHitAPI [ 0 ] . name ,
545
570
value : firstToHitAPI [ 0 ] . firstHit ,
546
571
} ) ;
547
572
awards . push ( firstToHitAPIAward ) ;
0 commit comments