Keeping old matches, up to 200, and showing them as stale. Added LevelSession.isRanking for better display of when you're still in the initial ranking phase.

This commit is contained in:
Nick Winter 2014-03-11 16:31:39 -07:00
parent 852b1c97ac
commit 392534878a
5 changed files with 63 additions and 38 deletions

View file

@ -18,5 +18,13 @@
white-space: nowrap
overflow: hidden
tr.stale
opacity: 0.5
tr.win .state-cell
color: #172
tr.loss .state-cell
color: #712
#must-log-in button
margin-right: 10px
margin-right: 10px

View file

@ -17,9 +17,10 @@ div#columns.row
button.btn.btn-sm.btn-warning.pull-right.rank-button(data-session-id=team.session.id)
span.unavailable.hidden No New Code to Rank
span.rank.hidden Rank My Game!
span.ranking.hidden Submitting...
span.ranked.hidden Submitted for Ranking
span.submitting.hidden Submitting...
span.submitted.hidden Submitted for Ranking
span.failed.hidden Failed to Rank
span.ranking.hidden Game Being Ranked
if team.chartData
tr
@ -32,7 +33,7 @@ div#columns.row
th When
th
for match in team.matches
tr
tr(class=(match.stale ? "stale " : "") + match.state)
td.state-cell
if match.state === 'win'
span.win Win
@ -48,7 +49,11 @@ div#columns.row
if !team.matches.length
tr
td(colspan=4).alert.alert-warning
| No ranked matches for this team!
| Play against some competitors and then come back here to get your game ranked.
if team.isRanking
td(colspan=4).alert.alert-info
| Your new code is being simulated by other players for ranking.
else
td(colspan=4).alert.alert-warning
| No ranked matches for this team!
| Play against some competitors and then come back here to get your game ranked.

View file

@ -54,7 +54,7 @@ module.exports = class MyMatchesTabView extends CocoView
ctx.levelID = @level.get('slug') or @level.id
ctx.teams = @teams
convertMatch = (match) =>
convertMatch = (match, submitDate) =>
opponent = match.opponents[0]
state = 'win'
state = 'loss' if match.metrics.rank > opponent.metrics.rank
@ -65,12 +65,14 @@ module.exports = class MyMatchesTabView extends CocoView
opponentID: opponent.userID
when: moment(match.date).fromNow()
sessionID: opponent.sessionID
stale: match.date < submitDate
}
for team in @teams
team.session = (s for s in @sessions.models when s.get('team') is team.id)[0]
team.readyToRank = @readyToRank(team.session)
team.matches = (convertMatch(match) for match in team.session?.get('matches') or [])
team.isRanking = team.session.get('isRanking')
team.matches = (convertMatch(match, team.session.get('submitDate')) for match in team.session?.get('matches') or [])
team.matches.reverse()
team.score = (team.session?.get('totalScore') or 10).toFixed(2)
team.wins = _.filter(team.matches, {state: 'win'}).length
@ -96,7 +98,12 @@ module.exports = class MyMatchesTabView extends CocoView
button = $(el)
sessionID = button.data('session-id')
session = _.find @sessions.models, { id: sessionID }
@setRankingButtonText button, if @readyToRank(session) then 'rank' else 'unavailable'
rankingState = 'unavailable'
if @readyToRank session
rankingState = 'rank'
else if session.get 'isRanking'
rankingState = 'ranking'
@setRankingButtonText button, rankingState
readyToRank: (session) ->
return false unless session?.get('levelID') # If it hasn't been denormalized, then it's not ready.
@ -110,8 +117,8 @@ module.exports = class MyMatchesTabView extends CocoView
session = _.find @sessions.models, { id: sessionID }
return unless @readyToRank(session)
@setRankingButtonText(button, 'ranking')
success = => @setRankingButtonText(button, 'ranked')
@setRankingButtonText(button, 'submitting')
success = => @setRankingButtonText(button, 'submitted')
failure = => @setRankingButtonText(button, 'failed')
ajaxData = { session: sessionID, levelID: @level.id, originalLevelID: @level.attributes.original, levelMajorVersion: @level.attributes.version.major }

View file

@ -140,6 +140,10 @@ _.extend LevelSessionSchema.properties,
submittedCode:
type: 'object'
isRanking:
type: 'boolean'
description: 'Whether this session is still in the first ranking chain after being submitted.'
unsubscribed:
type: 'boolean'
description: 'Whether the player has opted out of receiving email updates about ladder rankings for this session.'
@ -147,6 +151,7 @@ _.extend LevelSessionSchema.properties,
numberOfWinsAndTies:
type: 'number'
default: 0
numberOfLosses:
type: 'number'
default: 0
@ -162,7 +167,6 @@ _.extend LevelSessionSchema.properties,
items:
type: 'number'
matches:
type: 'array'
title: 'Matches'

View file

@ -52,7 +52,7 @@ module.exports.createNewTask = (req, res) ->
requestLevelID = req.body.originalLevelID
requestCurrentLevelID = req.body.levelID
requestLevelMajorVersion = parseInt(req.body.levelMajorVersion)
validatePermissions req, requestSessionID, (error, permissionsAreValid) ->
if err? then return errors.serverError res, "There was an error validating permissions"
unless permissionsAreValid then return errors.forbidden res, "You do not have the permissions to submit that game to the leaderboard"
@ -60,24 +60,24 @@ module.exports.createNewTask = (req, res) ->
return errors.badInput res, "The session ID is invalid" unless typeof requestSessionID is "string"
Level.findOne({_id: requestCurrentLevelID}).lean().select('type').exec (err, levelWithType) ->
if err? then return errors.serverError res, "There was an error finding the level type"
if not levelWithType.type or levelWithType.type isnt "ladder"
if not levelWithType.type or levelWithType.type isnt "ladder"
console.log "The level type of level with ID #{requestLevelID} is #{levelWithType.type}"
return errors.badInput res, "That level isn't a ladder level"
fetchSessionToSubmit requestSessionID, (err, sessionToSubmit) ->
if err? then return errors.serverError res, "There was an error finding the given session."
updateSessionToSubmit sessionToSubmit, (err, data) ->
if err? then return errors.serverError res, "There was an error updating the session"
opposingTeam = calculateOpposingTeam(sessionToSubmit.team)
fetchInitialSessionsToRankAgainst opposingTeam,requestLevelID, requestLevelMajorVersion, (err, sessionsToRankAgainst) ->
if err? then return errors.serverError res, "There was an error fetching the sessions to rank against"
taskPairs = generateTaskPairs(sessionsToRankAgainst, sessionToSubmit)
sendEachTaskPairToTheQueue taskPairs, (taskPairError) ->
if taskPairError? then return errors.serverError res, "There was an error sending the task pairs to the queue"
sendResponseObject req, res, {"message":"All task pairs were succesfully sent to the queue"}
module.exports.dispatchTaskToConsumer = (req, res) ->
@ -118,51 +118,53 @@ module.exports.processTaskResult = (req, res) ->
scoringTaskQueue.deleteMessage clientResponseObject.receiptHandle, (err) ->
console.log "Deleted message."
if err? then return errors.badInput res, "The queue message is already back in the queue, rejecting results."
LevelSession.findOne(_id: clientResponseObject.originalSessionID).lean().exec (err, levelSession) ->
if err? then return errors.serverError res, "There was a problem finding the level session:#{err}"
supposedSubmissionDate = new Date(clientResponseObject.sessions[0].submitDate)
if Number(supposedSubmissionDate) isnt Number(levelSession.submitDate)
return sendResponseObject req, res, {"message":"The game has been resubmitted. Removing from queue..."}
logTaskComputation clientResponseObject, taskLog, (logErr) ->
if logErr? then return errors.serverError res, "There as a problem logging the task computation: #{logErr}"
updateSessions clientResponseObject, (updateError, newScoreArray) ->
if updateError? then return errors.serverError res, "There was an error updating the scores.#{updateError}"
newScoresObject = _.indexBy newScoreArray, 'id'
addMatchToSessions clientResponseObject, newScoresObject, (err, data) ->
if err? then return errors.serverError res, "There was an error updating the sessions with the match! #{JSON.stringify err}"
originalSessionID = clientResponseObject.originalSessionID
originalSessionTeam = clientResponseObject.originalSessionTeam
originalSessionRank = parseInt clientResponseObject.originalSessionRank
determineIfSessionShouldContinueAndUpdateLog originalSessionID, originalSessionRank, (err, sessionShouldContinue) ->
if err? then return errors.serverError res, "There was an error determining if the session should continue, #{err}"
if sessionShouldContinue
opposingTeam = calculateOpposingTeam(originalSessionTeam)
opponentID = _.pull(_.keys(newScoresObject), originalSessionID)
sessionNewScore = newScoresObject[originalSessionID].totalScore
opponentNewScore = newScoresObject[opponentID].totalScore
levelOriginalID = levelSession.level.original
levelOriginalMajorVersion = levelSession.level.majorVersion
findNearestBetterSessionID levelOriginalID, levelOriginalMajorVersion, originalSessionID, sessionNewScore, opponentNewScore, opponentID ,opposingTeam, (err, opponentSessionID) ->
if err? then return errors.serverError res, "There was an error finding the nearest sessionID!"
unless opponentSessionID then return sendResponseObject req, res, {"message":"There were no more games to rank(game is at top!"}
addPairwiseTaskToQueue [originalSessionID, opponentSessionID], (err, success) ->
if err? then return errors.serverError res, "There was an error sending the pairwise tasks to the queue!"
sendResponseObject req, res, {"message":"The scores were updated successfully and more games were sent to the queue!"}
else
console.log "Player lost, achieved rank #{originalSessionRank}"
sendResponseObject req, res, {"message":"The scores were updated successfully, person lost so no more games are being inserted!"}
LevelSession.update {_id: originalSessionID}, {isRanking: false}, {multi: false}, (err, affected) ->
if err? then return errors.serverError res, "There was an error marking the completed session as not being ranked."
sendResponseObject req, res, {"message":"The scores were updated successfully, person lost so no more games are being inserted!"}
determineIfSessionShouldContinueAndUpdateLog = (sessionID, sessionRank, cb) ->
@ -285,7 +287,7 @@ updateMatchesInSession = (matchObject, sessionID, callback) ->
currentMatchObject.opponents = opponentsArray
sessionUpdateObject =
$push: {matches: currentMatchObject}
$push: {matches: {$each: [currentMatchObject], $slice: -200}}
log.info "Updating session #{sessionID}"
LevelSession.update {"_id":sessionID}, sessionUpdateObject, callback
@ -304,12 +306,12 @@ updateSessionToSubmit = (sessionToUpdate, callback) ->
submitted: true
submittedCode: sessionToUpdate.code
submitDate: new Date()
matches: []
meanStrength: 25
standardDeviation: 25/3
totalScore: 10
numberOfWinsAndTies: 0
numberOfLosses: 0
isRanking: true
LevelSession.update {_id: sessionToUpdate._id}, sessionUpdateObject, callback
fetchInitialSessionsToRankAgainst = (opposingTeam, levelID, levelMajorVersion, callback) ->
@ -321,7 +323,7 @@ fetchInitialSessionsToRankAgainst = (opposingTeam, levelID, levelMajorVersion, c
submittedCode:
$exists: true
team: opposingTeam
sortParameters =
totalScore: 1
@ -449,8 +451,7 @@ updateScoreInSession = (scoreObject,callback) ->
meanStrength: scoreObject.meanStrength
standardDeviation: scoreObject.standardDeviation
totalScore: newTotalScore
$push:
scoreHistory: scoreHistoryAddition
$push: {scoreHistory: {$each: [scoreHistoryAddition], $slice: -1000}}
LevelSession.update {"_id": scoreObject.id}, updateObject, callback
log.info "New total score for session #{scoreObject.id} is #{updateObject.totalScore}"