From 1971ddcefbf336e0e12794fea050d9b3130f63fa Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Fri, 4 Apr 2014 10:12:22 -0700
Subject: [PATCH 1/5] Moved somethingLoaded calls until after calls that would
 register more to load. A probably suboptimal way of making sure the progress
 numerator never reaches the progress denominator until it's actually time.

---
 app/views/play/ladder/ladder_tab.coffee | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/app/views/play/ladder/ladder_tab.coffee b/app/views/play/ladder/ladder_tab.coffee
index ae8c92259..419712b68 100644
--- a/app/views/play/ladder/ladder_tab.coffee
+++ b/app/views/play/ladder/ladder_tab.coffee
@@ -40,19 +40,19 @@ module.exports = class LadderTabView extends CocoView
 
   checkFriends: ->
     return if @checked or (not window.FB) or (not window.gapi)
-    @somethingLoaded("social_network_apis")
     @checked = true
     
     @addSomethingToLoad("facebook_status")
     FB.getLoginStatus (response) =>
       @facebookStatus = response.status
-      @somethingLoaded("facebook_status")
       @loadFacebookFriends() if @facebookStatus is 'connected'
+      @somethingLoaded("facebook_status")
 
     if application.gplusHandler.loggedIn is undefined
       @listenToOnce(application.gplusHandler, 'checked-state', @gplusSessionStateLoaded)
     else
       @gplusSessionStateLoaded()
+    @somethingLoaded("social_network_apis")
 
   # FACEBOOK
 
@@ -67,10 +67,10 @@ module.exports = class LadderTabView extends CocoView
     FB.api '/me/friends', @onFacebookFriendsLoaded
     
   onFacebookFriendsLoaded: (response) =>
-    @somethingLoaded("facebook_friends")
     @facebookData = response.data
     @loadFacebookFriendSessions()
-    
+    @somethingLoaded("facebook_friends")
+
   loadFacebookFriendSessions: ->
     levelFrag = "#{@level.get('original')}.#{@level.get('version').major}"
     url = "/db/level/#{levelFrag}/leaderboard_facebook_friends"
@@ -105,10 +105,10 @@ module.exports = class LadderTabView extends CocoView
       application.gplusHandler.loadFriends @gplusFriendsLoaded
 
   gplusFriendsLoaded: (friends) =>
-    @somethingLoaded("gplus_friends")
     @gplusData = friends.items
     @loadGPlusFriendSessions()
-    
+    @somethingLoaded("gplus_friends")
+
   loadGPlusFriendSessions: ->
     levelFrag = "#{@level.get('original')}.#{@level.get('version').major}"
     url = "/db/level/#{levelFrag}/leaderboard_gplus_friends"

From 7019bb6dea28c0cb5c31a5a7d475e478f662b863 Mon Sep 17 00:00:00 2001
From: Michael Schmatz <michaelschmatz@gmail.com>
Date: Fri, 4 Apr 2014 13:38:36 -0700
Subject: [PATCH 2/5] Added score histogram to ladder tab

---
 app/styles/play/ladder/ladder_tab.sass  | 22 +++++++-
 app/views/play/ladder/ladder_tab.coffee | 72 +++++++++++++++++++++++++
 server/levels/level_handler.coffee      | 13 +++++
 3 files changed, 106 insertions(+), 1 deletion(-)

diff --git a/app/styles/play/ladder/ladder_tab.sass b/app/styles/play/ladder/ladder_tab.sass
index d4878511a..7e8c261f5 100644
--- a/app/styles/play/ladder/ladder_tab.sass
+++ b/app/styles/play/ladder/ladder_tab.sass
@@ -3,4 +3,24 @@
     max-width: 150px
     white-space: nowrap
     overflow: hidden
-    text-overflow: ellipsis
\ No newline at end of file
+    text-overflow: ellipsis
+    
+  .bar rect
+    fill: steelblue
+    shape-rendering: crispEdges
+    
+  .bar text
+    fill: #fff
+    
+  .specialbar rect
+    fill: red
+    
+    
+  .axis path, .axis line
+    fill: none
+    stroke: #000
+    shape-rendering: crispEdges
+  .x.axis
+    color: red
+    
+    
\ No newline at end of file
diff --git a/app/views/play/ladder/ladder_tab.coffee b/app/views/play/ladder/ladder_tab.coffee
index db4eff8ad..9ff828899 100644
--- a/app/views/play/ladder/ladder_tab.coffee
+++ b/app/views/play/ladder/ladder_tab.coffee
@@ -140,6 +140,18 @@ module.exports = class LadderTabView extends CocoView
     return if @loadingFacebookFriends or @loadingLeaderboards or @loadingGPlusFriends
     @startsLoading = false
     @render()
+    
+  render: ->
+    super()
+
+    @$el.find('.histogram-display').each (i, el) =>
+      histogramWrapper = $(el)
+      team = _.find @teams, name: histogramWrapper.data('team-name')
+      histogramData = null
+      $.when(
+        $.get("/db/level/#{@level.get('slug')}/histogram_data?team=#{team.name.toLowerCase()}", (data) -> histogramData = data)
+      ).then =>
+        @generateHistogram(histogramWrapper, histogramData, team.name.toLowerCase())
 
   getRenderData: ->
     ctx = super()
@@ -153,6 +165,66 @@ module.exports = class LadderTabView extends CocoView
     ctx.onGPlus = application.gplusHandler.loggedIn
     ctx
 
+  generateHistogram: (histogramElement, histogramData, teamName) ->
+    #renders twice, hack fix
+    if $("#"+histogramElement.attr("id")).has("svg").length then return
+    histogramData = histogramData.map (d) -> d*100
+      
+    margin =
+      top: 20
+      right: 20
+      bottom: 30
+      left: 0
+
+    width = 300 - margin.left - margin.right
+    height = 125 - margin.top - margin.bottom
+    
+    formatCount = d3.format(",.0")
+    
+    x = d3.scale.linear().domain([-3000,6000]).range([0,width])
+
+    data = d3.layout.histogram().bins(x.ticks(20))(histogramData)
+    y = d3.scale.linear().domain([0,d3.max(data, (d) -> d.y)]).range([height,0])
+    
+    #create the x axis
+    xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(5).outerTickSize(0)
+    
+    svg = d3.select("#"+histogramElement.attr("id")).append("svg")
+      .attr("width", width + margin.left + margin.right)
+      .attr("height", height + margin.top + margin.bottom)
+    .append("g")
+      .attr("transform","translate(#{margin.left},#{margin.top})")
+    
+    bar = svg.selectAll(".bar")
+      .data(data)
+    .enter().append("g")
+      .attr("class","bar")
+      .attr("transform", (d) -> "translate(#{x(d.x)},#{y(d.y)})")  
+    
+    bar.append("rect")
+      .attr("x",1)
+      .attr("width",width/20)
+      .attr("height", (d) -> height - y(d.y))
+    if @leaderboards[teamName].session?
+      playerScore = @leaderboards[teamName].session.get('totalScore') * 100
+      scorebar = svg.selectAll(".specialbar")
+        .data([playerScore])
+        .enter().append("g")
+        .attr("class","specialbar")
+        .attr("transform", "translate(#{x(playerScore)},#{y(9001)})")
+      
+      scorebar.append("rect")
+        .attr("x",1)
+        .attr("width",3)
+        .attr("height",height - y(9001))
+      
+    #Translate the x-axis up
+    svg.append("g")
+      .attr("class", "x axis")
+      .attr("transform","translate(0," + height + ")")
+      .call(xAxis)
+    
+    
   consolidateFriends: ->
     allFriendSessions = (@facebookFriendSessions or []).concat(@gplusFriendSessions or [])
     sessions = _.uniq allFriendSessions, false, (session) -> session._id
diff --git a/server/levels/level_handler.coffee b/server/levels/level_handler.coffee
index c58738d20..ad26fe0e1 100644
--- a/server/levels/level_handler.coffee
+++ b/server/levels/level_handler.coffee
@@ -36,6 +36,7 @@ LevelHandler = class LevelHandler extends Handler
     return @getRandomSessionPair(req,res,args[0]) if args[1] is 'random_session_pair'
     return @getLeaderboardFacebookFriends(req, res, args[0]) if args[1] is 'leaderboard_facebook_friends'
     return @getLeaderboardGPlusFriends(req, res, args[0]) if args[1] is 'leaderboard_gplus_friends'
+    return @getHistogramData(req, res, args[0]) if args[1] is 'histogram_data'
     
     return @sendNotFoundError(res)
 
@@ -118,6 +119,18 @@ LevelHandler = class LevelHandler extends Handler
       query = Session.find(sessionQuery).select('-screenshot')
       query.exec (err, results) =>
         if err then @sendDatabaseError(res, err) else @sendSuccess res, results
+          
+  getHistogramData: (req, res,slug) ->
+    query = Session.aggregate [
+      {$match: {"levelID":slug, "submitted": true, "team":req.query.team}}
+      {$project: {totalScore: 1, _id: 0}}
+    ]
+    
+    query.exec (err, data) =>
+      if err? then return @sendDatabaseError res, err
+      valueArray = _.pluck data, "totalScore"
+      @sendSuccess res, valueArray
+    
 
   getLeaderboard: (req, res, id) ->
     sessionsQueryParameters = @makeLeaderboardQueryParameters(req, id)

From 2093049f5c6cb9176b290c740d6aa848579efb6a Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Fri, 4 Apr 2014 13:59:40 -0700
Subject: [PATCH 3/5] Fixed a bug with the profile view caused by the new page
 loading system.

---
 app/templates/account/profile.jade    |  2 +-
 app/views/account/profile_view.coffee | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/app/templates/account/profile.jade b/app/templates/account/profile.jade
index 7cd6d0750..65dc9786b 100644
--- a/app/templates/account/profile.jade
+++ b/app/templates/account/profile.jade
@@ -16,7 +16,7 @@ block content
     else
       span(data-i18n="account_profile.profile") Profile
 
-  if loading
+  if loadingProfile
     p(data-i18n="common.loading") Loading...
 
   else if !user.get('emailHash')
diff --git a/app/views/account/profile_view.coffee b/app/views/account/profile_view.coffee
index 32faec138..f61f7f1e2 100644
--- a/app/views/account/profile_view.coffee
+++ b/app/views/account/profile_view.coffee
@@ -5,21 +5,21 @@ User = require 'models/User'
 module.exports = class ProfileView extends View
   id: "profile-view"
   template: template
-  loading: true
+  loadingProfile: true
 
   constructor: (options, @userID) ->
     super options
     @user = User.getByID(@userID)
-    @loading = false if 'gravatarProfile' of @user
+    @loadingProfile = false if 'gravatarProfile' of @user
     @listenTo(@user, 'change', @userChanged)
     @listenTo(@user, 'error', @userError)
 
   userChanged: (user) ->
-    @loading = false if 'gravatarProfile' of user
+    @loadingProfile = false if 'gravatarProfile' of user
     @render()
 
   userError: (user) ->
-    @loading = false
+    @loadingProfile = false
     @render()
 
   getRenderData: ->
@@ -28,7 +28,7 @@ module.exports = class ProfileView extends View
     grav = grav.entry[0] if grav
     addedContext =
       user: @user
-      loading: @loading
+      loadingProfile: @loadingProfile
       myProfile: @user.id is context.me.id
       grav: grav
       photoURL: @user.getPhotoURL()

From 0684bcff9c7cf8b48ed1e7aa9432d7e1dd7a3304 Mon Sep 17 00:00:00 2001
From: Michael Schmatz <michaelschmatz@gmail.com>
Date: Fri, 4 Apr 2014 14:22:30 -0700
Subject: [PATCH 4/5] Improved styling on graphs

---
 app/styles/play/ladder/ladder_tab.sass      | 15 +++++++++++----
 app/styles/play/ladder/my_matches_tab.sass  | 18 +++++++++++++++++-
 app/views/play/ladder/ladder_tab.coffee     |  5 ++++-
 app/views/play/ladder/my_matches_tab.coffee | 12 ++++++------
 4 files changed, 38 insertions(+), 12 deletions(-)

diff --git a/app/styles/play/ladder/ladder_tab.sass b/app/styles/play/ladder/ladder_tab.sass
index 7e8c261f5..0fe05bc9e 100644
--- a/app/styles/play/ladder/ladder_tab.sass
+++ b/app/styles/play/ladder/ladder_tab.sass
@@ -13,14 +13,21 @@
     fill: #fff
     
   .specialbar rect
-    fill: red
+    fill: #555555
     
     
   .axis path, .axis line
     fill: none
-    stroke: #000
+    stroke: #555555
     shape-rendering: crispEdges
-  .x.axis
-    color: red
+    
+  .humans-bar
+    fill: #bf3f3f
+    shape-rendering: crispEdges
+  .ogres-bar
+    fill: #3f44bf
+    shape-rendering: crispEdges
+  text
+    fill: #555555
     
     
\ No newline at end of file
diff --git a/app/styles/play/ladder/my_matches_tab.sass b/app/styles/play/ladder/my_matches_tab.sass
index 3483dcf38..a68f12225 100644
--- a/app/styles/play/ladder/my_matches_tab.sass
+++ b/app/styles/play/ladder/my_matches_tab.sass
@@ -1,7 +1,7 @@
 #my-matches-tab-view
   .axis path, .axis line
     fill: none
-    stroke: #000
+    stroke: #555
     shape-rendering: crispEdges
   .x.axis.path
     display: none
@@ -10,4 +10,20 @@
     fill: none
     stroke: steelblue
     stroke-width: 1.5px
+    
+  .humans-line
+    fill: none
+    stroke: #bf3f3f
+    stroke-width: 1.5px
+   
+  .ogres-line
+    fill: none
+    stroke: #3f44bf
+    stroke-width: 1.5px
 
+  .axis text
+    stroke: none
+    fill: #555555
+    shape-rendering: crispEdges
+    
+    
\ No newline at end of file
diff --git a/app/views/play/ladder/ladder_tab.coffee b/app/views/play/ladder/ladder_tab.coffee
index 922e917ba..b4ae1e62f 100644
--- a/app/views/play/ladder/ladder_tab.coffee
+++ b/app/views/play/ladder/ladder_tab.coffee
@@ -191,11 +191,14 @@ module.exports = class LadderTabView extends CocoView
       .attr("height", height + margin.top + margin.bottom)
     .append("g")
       .attr("transform","translate(#{margin.left},#{margin.top})")
+    barClass = "bar"
+    if teamName.toLowerCase() is "ogres" then barClass = "ogres-bar"
+    if teamName.toLowerCase() is "humans" then barClass = "humans-bar"
     
     bar = svg.selectAll(".bar")
       .data(data)
     .enter().append("g")
-      .attr("class","bar")
+      .attr("class",barClass)
       .attr("transform", (d) -> "translate(#{x(d.x)},#{y(d.y)})")  
     
     bar.append("rect")
diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
index 94e4f4731..e3f0fc62a 100644
--- a/app/views/play/ladder/my_matches_tab.coffee
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -117,12 +117,10 @@ module.exports = class MyMatchesTabView extends CocoView
     @$el.find('.score-chart-wrapper').each (i, el) =>
       scoreWrapper = $(el)
       team = _.find @teams, name: scoreWrapper.data('team-name')
-      @generateScoreLineChart(scoreWrapper.attr('id'), team.scoreHistory)
+      @generateScoreLineChart(scoreWrapper.attr('id'), team.scoreHistory, team.name)
       
 
-  generateScoreLineChart: (wrapperID, scoreHistory) =>
-    
-    
+  generateScoreLineChart: (wrapperID, scoreHistory,teamName) =>
     margin = 
       top: 20
       right: 20
@@ -167,10 +165,12 @@ module.exports = class MyMatchesTabView extends CocoView
       .attr("dy", ".75em")
       .style("text-anchor","end")
       .text("Score")
-    
+    lineClass = "line"
+    if teamName.toLowerCase() is "ogres" then lineClass = "ogres-line"
+    if teamName.toLowerCase() is "humans" then lineClass = "humans-line"
     svg.append("path")
       .datum(data)
-      .attr("class","line")
+      .attr("class",lineClass)
       .attr("d",line)
     
     

From 2411269f2b57557f23632428eb3f5333090b5932 Mon Sep 17 00:00:00 2001
From: Michael Schmatz <michaelschmatz@gmail.com>
Date: Fri, 4 Apr 2014 14:55:55 -0700
Subject: [PATCH 5/5] Added rank/number of sessions text

---
 app/styles/play/ladder/ladder_tab.sass  |  9 +++++++++
 app/views/play/ladder/ladder_tab.coffee | 15 ++++++++++++++-
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/app/styles/play/ladder/ladder_tab.sass b/app/styles/play/ladder/ladder_tab.sass
index 0fe05bc9e..6d65cc5a6 100644
--- a/app/styles/play/ladder/ladder_tab.sass
+++ b/app/styles/play/ladder/ladder_tab.sass
@@ -30,4 +30,13 @@
   text
     fill: #555555
     
+  .rank-text
+    font-size: 15px
+    fill: #555555
+    
+  .humans-rank-text
+    fill: #bf3f3f
+    
+  .ogres-rank-text
+    fill: #3f44bf
     
\ No newline at end of file
diff --git a/app/views/play/ladder/ladder_tab.coffee b/app/views/play/ladder/ladder_tab.coffee
index b4ae1e62f..635d7c69d 100644
--- a/app/views/play/ladder/ladder_tab.coffee
+++ b/app/views/play/ladder/ladder_tab.coffee
@@ -217,7 +217,20 @@ module.exports = class LadderTabView extends CocoView
         .attr("x",1)
         .attr("width",3)
         .attr("height",height - y(9001))
-      
+    rankClass = "rank-text"
+    if teamName.toLowerCase() is "ogres" then rankClass = "rank-text ogres-rank-text"
+    if teamName.toLowerCase() is "humans" then rankClass = "rank-text humans-rank-text"
+    
+    message = "#{histogramData.length} players"
+    if @leaderboards[teamName].session? then message="#{@leaderboards[teamName].myRank}/#{histogramData.length}"
+    svg.append("g")
+      .append("text")
+      .attr("class",rankClass)
+      .attr("y",0)
+      .attr("text-anchor","end")
+      .attr("x",width)
+      .text(message)
+        
     #Translate the x-axis up
     svg.append("g")
       .attr("class", "x axis")