Set up a trimmed down leaderboard showing just top players and your rank.

This commit is contained in:
Scott Erickson 2014-03-20 14:40:17 -07:00
parent dbbf9ce8b3
commit 22555790b5
4 changed files with 99 additions and 81 deletions
app
styles/play
templates/play/ladder
views/play/ladder
server/levels

View file

@ -5,8 +5,12 @@
.tab-pane
margin-top: 10px
.rank-cell, .fight-cell
text-align: center
.score-cell
width: 50px
text-align: center
.play-button
margin-bottom: 10px
@ -22,6 +26,12 @@
white-space: nowrap
overflow: hidden
.ellipsis-row
text-align: center
td
padding: 1px 2px
tr.stale
opacity: 0.5

View file

@ -3,23 +3,39 @@ div#columns.row
div.column.col-md-6
table.table.table-bordered.table-condensed.table-hover
tr
th(colspan=4, style="color: #{team.primaryColor}")
th
th(colspan=3, style="color: #{team.primaryColor}")
span= team.name
span
span(data-i18n="ladder.leaderboard") Leaderboard
tr
th(data-i18n="general.rank") Rank
th
th(data-i18n="general.score") Score
th(data-i18n="general.name").name-col-cell Name
th
for session, rank in team.leaderboard.topPlayers.models
- var topSessions = team.leaderboard.topPlayers.models;
- var inTheTop = team.leaderboard.inTopSessions();
- if(!inTheTop) topSessions = topSessions.slice(0, 10);
for session, rank in topSessions
- var myRow = session.get('creator') == me.id
tr(class=myRow ? "success" : "")
td.rank-cell= rank + 1
td.score-cell= Math.round(session.get('totalScore') * 100)
td.name-col-cell= session.get('creatorName') || "Anonymous"
td
td.fight-cell
a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}")
span(data-i18n="ladder.battle_as") Battle as
| #{team.otherTeam}!
span(data-i18n="ladder.fight") Fight!
if !inTheTop
tr(class="active")
td(colspan=4).ellipsis-row ...
for session in team.leaderboard.nearbySessions()
- var myRow = session.get('creator') == me.id
tr(class=myRow ? "success" : "")
td.rank-cell= session.rank
td.score-cell= Math.round(session.get('totalScore') * 100)
td.name-col-cell= session.get('creatorName') || "Anonymous"
td.fight-cell
a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}")
span(data-i18n="ladder.fight") Fight!

View file

@ -29,9 +29,7 @@ module.exports = class LadderTabView extends CocoView
refreshLadder: ->
for team in @teams
@leaderboards[team.id]?.off 'sync'
# teamSession = _.find @sessions.models, (session) -> session.get('team') is team.id
teamSession = null
# console.log "Team session: #{JSON.stringify teamSession}"
teamSession = _.find @sessions.models, (session) -> session.get('team') is team.id
@leaderboards[team.id] = new LeaderboardData(@level, team.id, teamSession)
@leaderboards[team.id].once 'sync', @onLeaderboardLoaded, @
@ -55,51 +53,43 @@ module.exports = class LadderTabView extends CocoView
class LeaderboardData
constructor: (@level, @team, @session) ->
_.extend @, Backbone.Events
limit = 200 # if @session then 10 else 20 # We need to figure out paging.
@topPlayers = new LeaderboardCollection(@level, {order:-1, scoreOffset: HIGHEST_SCORE, team: @team, limit: limit})
@topPlayers.fetch()
@topPlayers.comparator = (model) ->
return -model.get('totalScore')
@topPlayers.sort()
@topPlayers = new LeaderboardCollection(@level, {order:-1, scoreOffset: HIGHEST_SCORE, team: @team, limit: 20})
promises = []
promises.push @topPlayers.fetch()
@topPlayers.once 'sync', @onceLeaderboardPartLoaded, @
@topPlayers.once 'sync', @leaderboardPartLoaded, @
if @session
score = @session.get('totalScore') or 10
@playersAbove = new LeaderboardCollection(@level, {order:1, scoreOffset: score, limit: 4, team: @team})
promises.push @playersAbove.fetch()
@playersAbove.once 'sync', @onceLeaderboardPartLoaded, @
@playersBelow = new LeaderboardCollection(@level, {order:-1, scoreOffset: score, limit: 4, team: @team})
promises.push @playersBelow.fetch()
@playersBelow.once 'sync', @onceLeaderboardPartLoaded, @
level = "#{level.get('original')}.#{level.get('version').major}"
success = (@myRank) =>
promises.push $.ajax "/db/level/#{level}/leaderboard_rank?scoreOffset=#{@session.get('totalScore')}&team=#{@team}", {success}
$.when(promises...).then @onLoad
# if @session
# score = @session.get('totalScore') or 25
# @playersAbove = new LeaderboardCollection(@level, {order:1, scoreOffset: score, limit: 4, team: @team})
# @playersAbove.fetch()
# @playersAbove.once 'sync', @leaderboardPartLoaded, @
# @playersBelow = new LeaderboardCollection(@level, {order:-1, scoreOffset: score, limit: 4, team: @team})
# @playersBelow.fetch()
# @playersBelow.once 'sync', @leaderboardPartLoaded, @
leaderboardPartLoaded: ->
# Forget loading the up-to-date names, that's way too slow for something that refreshes all the time, we learned.
onLoad: =>
@loaded = true
@trigger 'sync'
return
if @session
if @topPlayers.loaded # and @playersAbove.loaded and @playersBelow.loaded
@loaded = true
@fetchNames()
else
@loaded = true
@fetchNames()
fetchNames: ->
sessionCollections = [@topPlayers, @playersAbove, @playersBelow]
sessionCollections = (s for s in sessionCollections when s)
ids = []
for collection in sessionCollections
ids.push model.get('creator') for model in collection.models
success = (nameMap) =>
for collection in sessionCollections
session.set('creatorName', nameMap[session.get('creator')]) for session in collection.models
@trigger 'sync'
$.ajax('/db/user/-/names', {
data: {ids: ids}
type: 'POST'
success: success
})
# TODO: cache user ids -> names mapping, and load them here as needed,
# and apply them to sessions. Fetching each and every time is too costly.
inTopSessions: ->
return me.id in (session.attributes.creator for session in @topPlayers.models)
nearbySessions: ->
return unless @session
l = []
above = @playersAbove.models
above.reverse()
l = l.concat(above)
l.push @session
l = l.concat(@playersBelow.models)
if @myRank
startRank = @myRank - 4
session.rank = startRank + i for session, i in l
l

View file

@ -30,6 +30,7 @@ LevelHandler = class LevelHandler extends Handler
getByRelationship: (req, res, args...) ->
return @getSession(req, res, args[0]) if args[1] is 'session'
return @getLeaderboard(req, res, args[0]) if args[1] is 'leaderboard'
return @getMyLeaderboardRank(req, res, args[0]) if args[1] is 'leaderboard_rank'
return @getMySessions(req, res, args[0]) if args[1] is 'my_sessions'
return @getFeedback(req, res, args[0]) if args[1] is 'feedback'
return @getRandomSessionPair(req,res,args[0]) if args[1] is 'random_session_pair'
@ -118,28 +119,11 @@ LevelHandler = class LevelHandler extends Handler
if err then @sendDatabaseError(res, err) else @sendSuccess res, results
getLeaderboard: (req, res, id) ->
@validateLeaderboardRequestParameters req
[original, version] = id.split '.'
version = parseInt(version) ? 0
scoreQuery = {}
scoreQuery[if req.query.order is 1 then "$gte" else "$lte"] = req.query.scoreOffset
sessionsQueryParameters =
level:
original: original
majorVersion: version
team: req.query.team
totalScore: scoreQuery
submitted: true
sessionsQueryParameters = @makeLeaderboardQueryParameters(req, id)
sortParameters =
"totalScore": req.query.order
selectProperties = [
'totalScore'
'creatorName'
'creator'
]
selectProperties = ['totalScore', 'creatorName', 'creator']
query = Session
.find(sessionsQueryParameters)
@ -152,6 +136,33 @@ LevelHandler = class LevelHandler extends Handler
resultSessions ?= []
@sendSuccess res, resultSessions
getMyLeaderboardRank: (req, res, id) ->
req.query.order = 1
sessionsQueryParameters = @makeLeaderboardQueryParameters(req, id)
Session.count sessionsQueryParameters, (err, count) =>
return @sendDatabaseError(res, err) if err
res.send JSON.stringify(count + 1)
makeLeaderboardQueryParameters: (req, id) ->
@validateLeaderboardRequestParameters req
[original, version] = id.split '.'
version = parseInt(version) ? 0
scoreQuery = {}
scoreQuery[if req.query.order is 1 then "$gt" else "$lt"] = req.query.scoreOffset
query =
level:
original: original
majorVersion: version
team: req.query.team
totalScore: scoreQuery
submitted: true
query
validateLeaderboardRequestParameters: (req) ->
req.query.order = parseInt(req.query.order) ? -1
req.query.scoreOffset = parseFloat(req.query.scoreOffset) ? 100000
req.query.team ?= 'humans'
req.query.limit = parseInt(req.query.limit) ? 20
getLeaderboardFriends: (req, res, id) ->
friendIDs = req.body.friendIDs or []
@ -222,15 +233,6 @@ LevelHandler = class LevelHandler extends Handler
@sendSuccess res, sessions
validateLeaderboardRequestParameters: (req) ->
req.query.order = parseInt(req.query.order) ? -1
req.query.scoreOffset = parseFloat(req.query.scoreOffset) ? 100000
req.query.team ?= 'humans'
req.query.limit = parseInt(req.query.limit) ? 20
getFeedback: (req, res, id) ->
return @sendNotFoundError(res) unless req.user
@fetchLevelByIDAndHandleErrors id, req, res, (err, level) =>