mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-07 02:25:29 -04:00
Set up a trimmed down leaderboard showing just top players and your rank.
This commit is contained in:
parent
dbbf9ce8b3
commit
22555790b5
4 changed files with 99 additions and 81 deletions
app
server/levels
|
@ -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
|
||||
|
||||
|
|
|
@ -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!
|
|
@ -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
|
|
@ -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) =>
|
||||
|
|
Loading…
Add table
Reference in a new issue