@@ -78,12 +78,17 @@ function render(method) {
78
78
79
79
function renderAll ( ) {
80
80
$ ( '.filterchart' ) . each ( function ( ) { this . render ( ) } ) ;
81
+
82
+ // TODO make original scout page work again
81
83
list . each ( render ) ;
82
- d3 . select ( "#active" ) . text ( formatNumber ( gr_all . value ( ) ) ) ;
83
- numWins = _ . find ( winGrp . all ( ) , function ( grp ) { return grp . key == "true" } ) . value . value
84
- pctWins = Math . round ( 1000.0 * numWins / gr_all . value ( ) ) / 10.0 ;
84
+
85
+ d3 . select ( "#active" ) . text ( formatNumber ( cf_all . value ( ) ) ) ;
86
+
87
+ // TODO make original scout page work again
88
+ // numWins = _.find(winGrp.all(), function(grp) {return grp.key == "true"}).value.value
89
+ // pctWins = Math.round(1000.0 * numWins / cf_all.value()) / 10.0;
85
90
// console.log("wins:", numWins, pctWins);
86
- d3 . select ( "#winrate" ) . text ( pctWins ) ;
91
+ // d3.select("#winrate").text(pctWins);
87
92
}
88
93
89
94
function matchList ( elem ) {
@@ -127,7 +132,21 @@ function entities_url() {
127
132
return data_host ( ) + "/ents" + debug_suffix ( ) + ".csv" ;
128
133
}
129
134
130
- function filter_chart ( element , dimension , group , colorgroup , domain ) {
135
+ function cumulativize ( group ) {
136
+ // TODO can be more efficient, but does it matter.
137
+ return _ . map ( group , function ( element , index , list ) {
138
+ var allFollowingGroups = _ . rest ( list , index ) ;
139
+ var allFollowingSummary = _ . reduce ( allFollowingGroups ,
140
+ function ( memo , group ) {
141
+ return { wins : memo . wins + group . value . wins ,
142
+ games : memo . games + group . value . games } ;
143
+ } , { wins :0 , games :0 } ) ;
144
+ allFollowingSummary . value = Math . round ( 1000.0 * allFollowingSummary . wins / allFollowingSummary . games ) / 10.0 ;
145
+ return { key : element . key , value : allFollowingSummary } ;
146
+ } ) ;
147
+ }
148
+
149
+ function filter_chart ( element , dimension , group , colorgroup , domain , tooltip ) {
131
150
element . group = group ;
132
151
element . colorgroup = colorgroup ;
133
152
element . dimension = dimension ;
@@ -136,15 +155,23 @@ function filter_chart(element, dimension, group, colorgroup, domain) {
136
155
137
156
element . render = function ( ) {
138
157
var grp = this . group . all ( ) ;
139
- var colorGrp = this . colorgroup . all ( ) ;
140
-
141
- var xycolor = _ . map ( _ . zip ( grp , colorGrp ) , function ( gs ) {
158
+ // var cumColorGrp = cumulativize(colorGrp);
159
+ var data ;
160
+
161
+ if ( this . colorgroup ) {
162
+ var colorGrp = this . colorgroup . all ( ) ;
163
+ data = _ . map ( _ . zip ( grp , colorGrp ) , function ( gs ) {
142
164
var winpct = gs [ 1 ] . value . value ;
143
165
var color = winInterp ( logistic ( ( winpct - 50 ) / 10.0 ) ) ;
144
166
return { x :gs [ 0 ] . key , y :gs [ 0 ] . value . value , color :color , winpct :winpct } ;
145
- } ) ;
167
+ } ) ;
168
+ } else {
169
+ data = _ . map ( grp , function ( g ) {
170
+ return { x :g . key , y :g . value . value , color : 'steelblue' } ;
171
+ } ) ;
172
+ }
146
173
147
- this . chart . series [ 0 ] . setData ( xycolor ) ;
174
+ this . chart . series [ 0 ] . setData ( data ) ;
148
175
}
149
176
150
177
element . reset = function ( ) {
@@ -157,7 +184,7 @@ function filter_chart(element, dimension, group, colorgroup, domain) {
157
184
}
158
185
159
186
element . range_select = function ( event ) {
160
- console . log ( "Selected" , event . xAxis [ 0 ] . min , event . xAxis [ 0 ] . max , event ) ;
187
+ // console.log("Selected", event.xAxis[0].min, event.xAxis[0].max, event);
161
188
162
189
event . xAxis [ 0 ] . axis . removePlotBand ( 'plot-band-1' ) ;
163
190
@@ -182,9 +209,7 @@ function filter_chart(element, dimension, group, colorgroup, domain) {
182
209
event . preventDefault ( ) ;
183
210
} ;
184
211
185
- element . tooltip = function ( ) {
186
- return this . x + ': ' + this . y + ' games, ' + this . point . winpct + '% win.' ;
187
- } ;
212
+ element . tooltip = tooltip ;
188
213
189
214
var options = {
190
215
chart : {
@@ -254,7 +279,9 @@ function reset_click(e) {
254
279
filterchart . reset ( ) ;
255
280
}
256
281
257
- function add_filterchart ( element , dimension , group , title , domain ) {
282
+ function add_filterchart ( element , dimension , group , title , domain , addWinPct , tooltip ) {
283
+
284
+ addWinPct = typeof addWinPct !== 'undefined' ? addWinPct : true ;
258
285
259
286
var chartContainer = $ ( document . createElement ( 'div' ) ) . addClass ( 'djchart' ) ;
260
287
@@ -271,9 +298,12 @@ function add_filterchart(element, dimension, group, title, domain) {
271
298
var thechart = $ ( document . createElement ( 'div' ) ) . addClass ( 'filterchart' ) ;
272
299
chartContainer . append ( thechart ) ;
273
300
274
- var colorgroup = groupWinPct ( group . clone ( ) ) ;
301
+ var colorgroup = null ;
302
+ if ( addWinPct ) {
303
+ colorgroup = groupWinPct ( group . clone ( ) ) ;
304
+ }
275
305
276
- filter_chart ( thechart [ 0 ] , dimension , group , colorgroup , domain ) ;
306
+ filter_chart ( thechart [ 0 ] , dimension , group , colorgroup , domain , tooltip ) ;
277
307
278
308
element . append ( chartContainer ) ;
279
309
}
@@ -325,7 +355,7 @@ function scout_init() {
325
355
} ) ;
326
356
var rec_built = Date . now ( ) ;
327
357
gr_cf = crossfilter ( gamerecords ) ;
328
- gr_all = gr_cf . groupAll ( ) ;
358
+ cf_all = gr_cf . groupAll ( ) ;
329
359
330
360
raceDim = gr_cf . dimension ( function ( gr ) { return gr . player . race } ) ;
331
361
raceGrp = groupDJ ( raceDim . group ( ) ) ;
@@ -388,15 +418,232 @@ function scout_init() {
388
418
} )
389
419
} ) ;
390
420
391
- add_filterchart ( $ ( '#filtercharts' ) , lgDim , lgGrp , 'Game league' , [ 0 , 6 ] ) ;
392
- add_filterchart ( $ ( '#filtercharts' ) , asDim , asGrp , 'Player\'s Army Strength @ X minutes' , [ 0 , 2500 ] ) ;
393
- add_filterchart ( $ ( '#filtercharts' ) , oasDim , oasGrp , 'Opponent\'s Army Strength @ X minutes' , [ 0 , 2500 ] ) ;
394
- add_filterchart ( $ ( '#filtercharts' ) , wsDim , wsGrp , 'Player\'s Workers @ X minutes' , [ 0 , 60 ] ) ;
395
- add_filterchart ( $ ( '#filtercharts' ) , owsDim , owsGrp , 'Opponent\'s Workers @ X minutes' , [ 0 , 60 ] ) ;
396
- add_filterchart ( $ ( '#filtercharts' ) , mb2Dim , mb2Grp , 'Player\'s 2nd Mining Base Timing' , [ 0 , 15 ] ) ;
397
- add_filterchart ( $ ( '#filtercharts' ) , omb2Dim , omb2Grp , 'Opponent\'s 2nd Mining Base Timing' , [ 0 , 15 ] ) ;
398
- add_filterchart ( $ ( '#filtercharts' ) , durDim , durGrp , 'Game Length, minutes' , [ 0 , 40 ] ) ;
399
- add_filterchart ( $ ( '#filtercharts' ) , dateDim , dateGrp , 'Game Date' , [ Date . UTC ( 2014 , 6 , 25 ) , Date . UTC ( 2014 , 8 , 15 ) ] ) ;
421
+
422
+ tooltip = function ( ) {
423
+ return this . x + ': ' + this . y + ' games, ' + this . point . winpct + '% win.' ;
424
+ } ;
425
+
426
+ add_filterchart ( $ ( '#filtercharts' ) , lgDim , lgGrp , 'Game league' , [ 0 , 6 ] , tooltip ) ;
427
+ add_filterchart ( $ ( '#filtercharts' ) , asDim , asGrp , 'Player\'s Army Strength @ X minutes' , [ 0 , 2500 ] , tooltip ) ;
428
+ add_filterchart ( $ ( '#filtercharts' ) , oasDim , oasGrp , 'Opponent\'s Army Strength @ X minutes' , [ 0 , 2500 ] , tooltip ) ;
429
+ add_filterchart ( $ ( '#filtercharts' ) , wsDim , wsGrp , 'Player\'s Workers @ X minutes' , [ 0 , 60 ] , tooltip ) ;
430
+ add_filterchart ( $ ( '#filtercharts' ) , owsDim , owsGrp , 'Opponent\'s Workers @ X minutes' , [ 0 , 60 ] , tooltip ) ;
431
+ add_filterchart ( $ ( '#filtercharts' ) , mb2Dim , mb2Grp , 'Player\'s 2nd Mining Base Timing' , [ 0 , 15 ] , tooltip ) ;
432
+ add_filterchart ( $ ( '#filtercharts' ) , omb2Dim , omb2Grp , 'Opponent\'s 2nd Mining Base Timing' , [ 0 , 15 ] , tooltip ) ;
433
+ add_filterchart ( $ ( '#filtercharts' ) , durDim , durGrp , 'Game Length, minutes' , [ 0 , 40 ] , tooltip ) ;
434
+ add_filterchart ( $ ( '#filtercharts' ) , dateDim , dateGrp , 'Game Date' , [ Date . UTC ( 2014 , 6 , 25 ) , Date . UTC ( 2014 , 8 , 15 ) ] , tooltip ) ;
435
+
436
+ renderAll ( ) ;
437
+
438
+ var end = Date . now ( ) ;
439
+ var total_time = end - start ;
440
+ console . log ( "init took " + ( total_time / 1000 ) + " seconds" ) ;
441
+
442
+ var build_rec = ( rec_built - start ) / 1000 ;
443
+ var build_dims = ( dims_built - rec_built ) / 1000 ;
444
+ var build_chart = ( end - dims_built ) / 1000 ;
445
+ console . log ( build_rec , build_dims , build_chart ) ;
446
+ } ) ;
447
+ } ) ;
448
+
449
+
450
+ }
451
+
452
+ // TODO do this with angular rather than d3, so we can ditch d3 someday
453
+ function playerList ( elem ) {
454
+ var playersByNumGames = numGamesDim . top ( 80 ) ;
455
+
456
+ elem . each ( function ( ) {
457
+ var player = d3 . select ( this ) . selectAll ( ".player" )
458
+ . data ( playersByNumGames ) ;
459
+
460
+ var playerEnter = player . enter ( ) . append ( "tr" ) . attr ( "class" , "player" ) ;
461
+ playerEnter . append ( "td" ) . attr ( "class" , "num" ) . append ( "a" ) ;
462
+ playerEnter . append ( "td" ) . attr ( "class" , "race" ) ;
463
+ playerEnter . append ( "td" ) . attr ( "class" , "league" ) ;
464
+ playerEnter . append ( "td" ) . attr ( "class" , "apm" ) ;
465
+ playerEnter . append ( "td" ) . attr ( "class" , "num_games" ) ;
466
+ playerEnter . append ( "td" ) . attr ( "class" , "winpct" ) ;
467
+
468
+ player . exit ( ) . remove ( ) ;
469
+
470
+ player . select ( '.num a' ) . text ( function ( p ) { return p . identity_id } ) ;
471
+ player . select ( '.num a' ) . attr ( "href" , function ( p ) { return "http://ggtracker.com/players/" + p . identity_id } ) ;
472
+ player . select ( '.race' ) . text ( function ( p ) { return p . race ( ) ; } ) ;
473
+ player . select ( '.league' ) . text ( function ( p ) { return p . league ( ) ; } ) ;
474
+ player . select ( '.apm' ) . text ( function ( p ) { return p . apm ( ) ; } ) ;
475
+ player . select ( '.num_games' ) . text ( function ( p ) { return p . num_games . total ; } ) ;
476
+ player . select ( '.winpct' ) . text ( function ( p ) { return p . win_pct ( 'total' ) ; } ) ;
477
+ } ) ;
478
+ }
479
+
480
+ function scout_players_init ( ) {
481
+ var start = Date . now ( ) ;
482
+
483
+ /**
484
+ * Each player has the following defined:
485
+ *
486
+ * identity_id
487
+ * num_games[matchup] <-- where matchup is each of: PvT, PvZ, PvP...TvT and total
488
+ * num_wins[matchup]
489
+ * sum_apm <-- sum of apm over all games
490
+ * sum_league <-- sum of league over all games
491
+ * num_games_by_race[chosen_race] <-- where chosen_race is P, T, Z, R
492
+ *
493
+ * apm()
494
+ * league()
495
+ * win_pct(matchup)
496
+ * race()
497
+ */
498
+
499
+ matches = { } ;
500
+ entities = [ ] ;
501
+ players = { } ;
502
+ match_winner = { } ;
503
+ match_loser = { } ;
504
+ gamerecords = [ ] ;
505
+
506
+
507
+ var matchup_zero = { 'PvT' : 0 ,
508
+ 'PvZ' : 0 ,
509
+ 'PvP' : 0 ,
510
+ 'TvT' : 0 ,
511
+ 'TvP' : 0 ,
512
+ 'TvZ' : 0 ,
513
+ 'ZvZ' : 0 ,
514
+ 'ZvT' : 0 ,
515
+ 'ZvP' : 0 ,
516
+ 'total' : 0 } ;
517
+ var race_zero = { 'P' :0 , 'T' :0 , 'Z' :0 , 'R' :0 } ;
518
+
519
+ var apm = function ( ) {
520
+ if ( this . num_games . total == 0 ) return 0 ;
521
+ return Math . floor ( this . sum_apm / this . num_games . total ) ;
522
+ }
523
+ var league = function ( ) {
524
+ if ( this . num_games . total == 0 ) return 0 ;
525
+ return Math . floor ( 10 * this . sum_league / this . num_games . total ) / 10.0 ;
526
+ }
527
+ var win_pct = function ( matchup ) {
528
+ if ( this . num_games [ matchup ] == 0 ) return 0 ;
529
+ return Math . floor ( 1000.0 * this . num_wins [ matchup ] / this . num_games [ matchup ] ) / 10.0 ;
530
+ }
531
+ var race = function ( ) {
532
+ var num_most_played = _ . max ( _ . values ( this . num_games_by_race ) ) ;
533
+ var race_most_played = _ . find ( _ . pairs ( this . num_games_by_race ) , function ( kv ) { return kv [ 1 ] == num_most_played ; } ) [ 0 ] ;
534
+ return race_most_played ;
535
+ }
536
+
537
+ // record
538
+ record_player_in_match = function ( match , player_entity , opponent_entity ) {
539
+ var matchup = player_entity . race + 'v' + opponent_entity . race ;
540
+
541
+ var player ;
542
+ if ( ! ( player_entity . identity_id in players ) ) {
543
+ player = { identity_id : player_entity . identity_id ,
544
+ num_games : _ . clone ( matchup_zero ) ,
545
+ num_wins : _ . clone ( matchup_zero ) ,
546
+ num_games_by_race : _ . clone ( race_zero ) ,
547
+ sum_apm : 0 ,
548
+ sum_league : 0 ,
549
+ apm : apm ,
550
+ league : league ,
551
+ win_pct : win_pct ,
552
+ race : race
553
+ } ;
554
+ players [ player_entity . identity_id ] = player ;
555
+ } else {
556
+ player = players [ player_entity . identity_id ] ;
557
+ }
558
+ player . num_games [ matchup ] ++ ;
559
+ player . num_games [ 'total' ] ++ ;
560
+ player . num_games_by_race [ player_entity . chosen_race ] ++ ;
561
+ if ( player_entity . win == 'true' ) {
562
+ player . num_wins [ matchup ] ++ ;
563
+ player . num_wins [ 'total' ] ++ ;
564
+ }
565
+ player . sum_apm += player_entity . apm ;
566
+ player . sum_league += match . average_league ;
567
+ }
568
+
569
+ entity_non_numerics = [ "race" , "chosen_race" , "win" ]
570
+
571
+ d3 . csv ( matches_url ( ) , function ( error , csv_matches ) {
572
+ csv_matches . forEach ( function ( match , index ) {
573
+ match . play_date = new Date ( match . play_date ) ;
574
+ match . id = + match . id
575
+ match . average_league = + match . average_league
576
+ match . duration_minutes = + match . duration_minutes
577
+ matches [ match . id ] = match
578
+ } ) ;
579
+ d3 . csv ( entities_url ( ) , function ( error , csv_ents ) {
580
+ csv_ents . forEach ( function ( entity , index ) {
581
+
582
+ // convert numeric fields to be actual numbers
583
+ for ( var key in entity ) {
584
+ if ( ! ( _ . contains ( entity_non_numerics , key ) ) ) {
585
+ entity [ key ] = + entity [ key ] ;
586
+ }
587
+ }
588
+
589
+ if ( entity . match_id in matches ) {
590
+ match = matches [ entity . match_id ] ;
591
+ if ( entity . win == "true" ) {
592
+ match_winner [ entity . match_id ] = entity ;
593
+ } else if ( entity . win == "false" ) {
594
+ match_loser [ entity . match_id ] = entity ;
595
+ }
596
+
597
+ if ( entity . match_id in match_winner && entity . match_id in match_loser ) {
598
+ record_player_in_match ( match , match_winner [ entity . match_id ] , match_loser [ entity . match_id ] ) ;
599
+ record_player_in_match ( match , match_loser [ entity . match_id ] , match_winner [ entity . match_id ] ) ;
600
+ }
601
+ }
602
+ } ) ;
603
+
604
+ // get rid of players with less than 10 games, not useful here
605
+ players = _ . values ( players ) ;
606
+ players = _ . filter ( players , function ( player ) { return player . num_games . total >= 10 } ) ;
607
+
608
+ var rec_built = Date . now ( ) ;
609
+ p_cf = crossfilter ( players ) ;
610
+ cf_all = p_cf . groupAll ( ) ;
611
+
612
+ raceDim = p_cf . dimension ( function ( p ) { return p . race ( ) ; } ) ;
613
+ raceGrp = groupDJ ( raceDim . group ( ) ) ;
614
+
615
+ numGamesDim = p_cf . dimension ( function ( p ) { return p . num_games . total ; } ) ;
616
+ numGamesGrp = groupDJ ( numGamesDim . group ( function ( d ) { return 5 * Math . floor ( d / 5 ) ; } ) ) ;
617
+
618
+ leagueDim = p_cf . dimension ( function ( p ) { return p . league ( ) ; } ) ;
619
+ leagueGrp = groupDJ ( leagueDim . group ( function ( d ) { return Math . floor ( d * 2 ) / 2 ; } ) ) ;
620
+
621
+ winPctDim = p_cf . dimension ( function ( p ) { return p . win_pct ( 'total' ) ; } ) ;
622
+ winPctGrp = groupDJ ( winPctDim . group ( function ( d ) { return 5 * Math . floor ( d / 5 ) ; } ) ) ;
623
+
624
+ apmDim = p_cf . dimension ( function ( p ) { return p . apm ( ) ; } ) ;
625
+ apmGrp = groupDJ ( apmDim . group ( function ( d ) { return 5 * Math . floor ( d / 5 ) ; } ) ) ;
626
+
627
+ var dims_built = Date . now ( ) ;
628
+
629
+ // Render the initial lists.
630
+ list = d3 . selectAll ( ".list tbody" )
631
+ . data ( [ playerList ] ) ;
632
+
633
+ if ( false ) {
634
+
635
+ d3 . selectAll ( "#total" )
636
+ . text ( formatNumber ( p_cf . size ( ) ) ) ;
637
+ }
638
+
639
+ tooltip = function ( ) {
640
+ return this . x + ': ' + this . y + ' players.' ;
641
+ } ;
642
+
643
+ add_filterchart ( $ ( '#filtercharts' ) , numGamesDim , numGamesGrp , 'Number of Games Played' , [ 0 , 150 ] , false , tooltip ) ;
644
+ add_filterchart ( $ ( '#filtercharts' ) , leagueDim , leagueGrp , 'League' , [ 0 , 6 ] , false , tooltip ) ;
645
+ add_filterchart ( $ ( '#filtercharts' ) , winPctDim , winPctGrp , 'Win Percentage' , [ 0 , 100 ] , false , tooltip ) ;
646
+ add_filterchart ( $ ( '#filtercharts' ) , apmDim , apmGrp , 'APM' , [ 0 , 300 ] , false , tooltip ) ;
400
647
401
648
renderAll ( ) ;
402
649
0 commit comments