Fixed gigantor server scoring bug. Cleaned up a bit of logging and error handling. Finished not resetting scores on resubmitting.

This commit is contained in:
Nick Winter 2014-05-21 21:56:11 -07:00
parent 482965fe0f
commit 48f5347075
5 changed files with 78 additions and 56 deletions

View file

@ -34,7 +34,7 @@ module.exports = class Simulator extends CocoClass
"humansGameID": humanGameID
"ogresGameID": ogresGameID
error: (errorData) ->
console.log "There was an error fetching two games! #{JSON.stringify errorData}"
console.warn "There was an error fetching two games! #{JSON.stringify errorData}"
success: (taskData) =>
return if @destroyed
@trigger 'statusUpdate', 'Setting up simulation...'
@ -57,17 +57,16 @@ module.exports = class Simulator extends CocoClass
@setupGod()
try
@commenceSingleSimulation()
catch err
console.log err
@handleSingleSimulationError()
catch error
@handleSingleSimulationError error
commenceSingleSimulation: ->
@god.createWorld @generateSpellsObject()
Backbone.Mediator.subscribeOnce 'god:infinite-loop', @handleSingleSimulationInfiniteLoop, @
Backbone.Mediator.subscribeOnce 'god:goals-calculated', @processSingleGameResults, @
handleSingleSimulationError: ->
console.log "There was an error simulating a single game!"
handleSingleSimulationError: (error) ->
console.error "There was an error simulating a single game!", error
if @options.headlessClient
console.log "GAMERESULT:tie"
process.exit(0)
@ -81,8 +80,8 @@ module.exports = class Simulator extends CocoClass
@cleanupSimulation()
processSingleGameResults: (simulationResults) ->
console.log "Processing results!"
taskResults = @formTaskResultsObject simulationResults
console.log "Processing results:", taskResults
humanSessionRank = taskResults.sessions[0].metrics.rank
ogreSessionRank = taskResults.sessions[1].metrics.rank
if @options.headlessClient
@ -237,7 +236,7 @@ module.exports = class Simulator extends CocoClass
sendResultsBackToServer: (results) ->
@trigger 'statusUpdate', 'Simulation completed, sending results back to server!'
console.log "Sending result back to server!", results
console.log "Sending result back to server:", results
if @options.headlessClient and @options.testing
return @fetchAndSimulateTask()
@ -255,7 +254,7 @@ module.exports = class Simulator extends CocoClass
return if @destroyed
console.log "Task registration result: #{JSON.stringify result}"
@trigger 'statusUpdate', 'Results were successfully sent back to server!'
console.log "Simulated by you: " + @simulatedByYou
console.log "Simulated by you:", @simulatedByYou
@simulatedByYou++
unless @options.headlessClient
simulatedBy = parseInt($('#simulated-by-you').text(), 10) + 1
@ -477,6 +476,5 @@ class SimulationTask
spellKey = pathComponents.join '/'
@thangSpells[thang.id].push spellKey
if not method.cloneOf and spellKey is desiredSpellKey
console.log "Setting #{desiredSpellKey} from world!"
#console.log "Setting #{desiredSpellKey} from world!"
return method.source

View file

@ -185,6 +185,22 @@ module.exports.thangNames = thangNames =
"Lacos"
"Upfish"
]
"Ogre Peon M": [
"Durbo"
"Kurger"
"Mudwich"
"Ba Bo"
"Zugger"
"Toe Pod"
]
"Ogre Peon F": [
"Iblet"
"Lorba"
"Zzoya"
"Yamra"
"Greeke"
"Vapa"
]
"Ogre M": [
"Krogg"
"Dronck"

View file

@ -26,6 +26,9 @@ module.exports = class MyMatchesTabView extends CocoView
for session in @sessions.models
for match in (session.get('matches') or [])
id = match.opponents[0].userID
unless id
console.error "Found bad opponent ID in malformed match:", match, "from session", session
continue
ids.push id unless @nameMap[id]
return @finishRendering() unless ids.length
@ -35,7 +38,7 @@ module.exports = class MyMatchesTabView extends CocoView
for session in @sessions.models
for match in session.get('matches') or []
opponent = match.opponents[0]
@nameMap[opponent.userID] ?= nameMap[opponent.userID].name
@nameMap[opponent.userID] ?= nameMap[opponent.userID]?.name ? "<bad match data>"
@finishRendering()
$.ajax('/db/user/-/names', {

View file

@ -55,6 +55,7 @@ addPairwiseTaskToQueue = (taskPair, cb) ->
if taskPairError? then return cb taskPairError
cb null
# We should rip these out, probably
module.exports.resimulateAllSessions = (req, res) ->
unless isUserAdmin req then return errors.unauthorized res, "Unauthorized. Even if you are authorized, you shouldn't do this"
@ -130,7 +131,7 @@ module.exports.getTwoGames = (req, res) ->
unless ogresGameID and humansGameID
#fetch random games here
queryParams =
queryParams =
"levelID":"greed"
"submitted":true
"team":"humans"
@ -138,7 +139,7 @@ module.exports.getTwoGames = (req, res) ->
LevelSession.count queryParams, (err, numberOfHumans) =>
if err? then return errors.serverError(res, "Couldn't get the number of human games")
humanSkipCount = selectRandomSkipIndex(numberOfHumans)
ogreCountParams =
ogreCountParams =
"levelID": "greed"
"submitted":true
"team":"ogres"
@ -183,10 +184,11 @@ module.exports.getTwoGames = (req, res) ->
"creatorName": session.creatorName
"creator": session.creator
"totalScore": session.totalScore
taskObject.sessions.push sessionInformation
console.log "Dispatching random game between", taskObject.sessions[0].creatorName, "and", taskObject.sessions[1].creatorName
sendResponseObject req, res, taskObject
else
console.log "Directly simulating #{humansGameID} vs. #{ogresGameID}."
LevelSession.findOne(_id: humansGameID).lean().exec (err, humanSession) =>
if err? then return errors.serverError(res, "Couldn't find the human game")
LevelSession.findOne(_id: ogresGameID).lean().exec (err, ogreSession) =>
@ -201,23 +203,25 @@ module.exports.getTwoGames = (req, res) ->
"transpiledCode": session.transpiledCode
"teamSpells": session.teamSpells ? {}
"levelID": session.levelID
taskObject.sessions.push sessionInformation
sendResponseObject req, res, taskObject
module.exports.recordTwoGames = (req, res) ->
@clientResponseObject = req.body
sessions = req.body.sessions
console.log "Recording non-chained result of", sessions?[0]?.name, sessions[0]?.metrics?.rank, "and", sessions?[1]?.name, sessions?[1]?.metrics?.rank
yetiGuru = clientResponseObject: req.body, isRandomMatch: true
async.waterfall [
fetchLevelSession.bind(@)
updateSessions.bind(@)
indexNewScoreArray.bind(@)
addMatchToSessions.bind(@)
updateUserSimulationCounts.bind(@, req.user._id)
fetchLevelSession.bind(yetiGuru)
updateSessions.bind(yetiGuru)
indexNewScoreArray.bind(yetiGuru)
addMatchToSessions.bind(yetiGuru)
updateUserSimulationCounts.bind(yetiGuru, req.user._id)
], (err, successMessageObject) ->
if err? then return errors.serverError res, "There was an error recording the single game:#{err}"
sendResponseObject req, res, {"message":"The single game was submitted successfully!"}
module.exports.createNewTask = (req, res) ->
@ -227,12 +231,13 @@ module.exports.createNewTask = (req, res) ->
transpiledCode = req.body.transpiledCode
requestLevelMajorVersion = parseInt(req.body.levelMajorVersion)
yetiGuru = {}
async.waterfall [
validatePermissions.bind(@,req,requestSessionID)
fetchAndVerifyLevelType.bind(@,currentLevelID)
fetchSessionObjectToSubmit.bind(@, requestSessionID)
updateSessionToSubmit.bind(@, transpiledCode)
fetchInitialSessionsToRankAgainst.bind(@, requestLevelMajorVersion, originalLevelID)
validatePermissions.bind(yetiGuru,req,requestSessionID)
fetchAndVerifyLevelType.bind(yetiGuru,currentLevelID)
fetchSessionObjectToSubmit.bind(yetiGuru, requestSessionID)
updateSessionToSubmit.bind(yetiGuru, transpiledCode)
fetchInitialSessionsToRankAgainst.bind(yetiGuru, requestLevelMajorVersion, originalLevelID)
generateAndSendTaskPairsToTheQueue
], (err, successMessageObject) ->
if err? then return errors.serverError res, "There was an error submitting the game to the queue:#{err}"
@ -290,9 +295,9 @@ updateSessionToSubmit = (transpiledCode, sessionToUpdate, callback) ->
submittedCode: sessionToUpdate.code
transpiledCode: transpiledCode
submitDate: new Date()
meanStrength: 25
#meanStrength: 25 # Let's try not resetting the score on resubmission
standardDeviation: 25/3
#totalScore: 10 #this should be a fun experiment
#totalScore: 10 # Let's try not resetting the score on resubmission
numberOfWinsAndTies: 0
numberOfLosses: 0
isRanking: true
@ -334,13 +339,14 @@ generateAndSendTaskPairsToTheQueue = (sessionToRankAgainst,submittedSession, cal
module.exports.dispatchTaskToConsumer = (req, res) ->
yetiGuru = {}
async.waterfall [
checkSimulationPermissions.bind(@,req)
checkSimulationPermissions.bind(yetiGuru,req)
receiveMessageFromSimulationQueue
changeMessageVisibilityTimeout
parseTaskQueueMessage
constructTaskObject
constructTaskLogObject.bind(@, getUserIDFromRequest(req))
constructTaskLogObject.bind(yetiGuru, getUserIDFromRequest(req))
processTaskObject
], (err, taskObjectToSend) ->
if err?
@ -430,22 +436,23 @@ getSessionInformation = (sessionIDString, callback) ->
module.exports.processTaskResult = (req, res) ->
originalSessionID = req.body?.originalSessionID
yetiGuru = {}
try
async.waterfall [
verifyClientResponse.bind(@,req.body)
fetchTaskLog.bind(@)
checkTaskLog.bind(@)
deleteQueueMessage.bind(@)
fetchLevelSession.bind(@)
checkSubmissionDate.bind(@)
logTaskComputation.bind(@)
updateSessions.bind(@)
indexNewScoreArray.bind(@)
addMatchToSessions.bind(@)
updateUserSimulationCounts.bind(@, req.user._id)
determineIfSessionShouldContinueAndUpdateLog.bind(@)
findNearestBetterSessionID.bind(@)
addNewSessionsToQueue.bind(@)
verifyClientResponse.bind(yetiGuru,req.body)
fetchTaskLog.bind(yetiGuru)
checkTaskLog.bind(yetiGuru)
deleteQueueMessage.bind(yetiGuru)
fetchLevelSession.bind(yetiGuru)
checkSubmissionDate.bind(yetiGuru)
logTaskComputation.bind(yetiGuru)
updateSessions.bind(yetiGuru)
indexNewScoreArray.bind(yetiGuru)
addMatchToSessions.bind(yetiGuru)
updateUserSimulationCounts.bind(yetiGuru, req.user._id)
determineIfSessionShouldContinueAndUpdateLog.bind(yetiGuru)
findNearestBetterSessionID.bind(yetiGuru)
addNewSessionsToQueue.bind(yetiGuru)
], (err, results) ->
if err is "shouldn't continue"
markSessionAsDoneRanking originalSessionID, (err) ->
@ -461,13 +468,14 @@ module.exports.processTaskResult = (req, res) ->
sendResponseObject req, res, {"message":"The scores were updated successfully and more games were sent to the queue!"}
catch e
errors.serverError res, "There was an error processing the task result!"
verifyClientResponse = (responseObject, callback) ->
#TODO: better verification
if typeof responseObject isnt "object" or responseObject?.originalSessionID?.length isnt 24
callback "The response to that query is required to be a JSON object."
else
@clientResponseObject = responseObject
#log.info "Verified client response!"
callback null, responseObject
@ -495,7 +503,7 @@ deleteQueueMessage = (callback) ->
fetchLevelSession = (callback) ->
findParameters =
_id: @clientResponseObject.originalSessionID
query = LevelSession
.findOne(findParameters)
.lean()
@ -600,7 +608,7 @@ updateMatchesInSession = (matchObject, sessionID, callback) ->
updateUserSimulationCounts = (reqUserID,callback) ->
incrementUserSimulationCount reqUserID, 'simulatedBy', (err) =>
if err? then return callback err
incrementUserSimulationCount @levelSession.creator, 'simulatedFor', callback
incrementUserSimulationCount @levelSession.creator, 'simulatedFor', callback unless @isRandomMatch
incrementUserSimulationCount = (userID, type, callback) =>
inc = {}
@ -749,12 +757,9 @@ hasTaskTimedOut = (taskSentTimestamp) -> taskSentTimestamp + scoringTaskTimeoutI
handleTimedOutTask = (req, res, taskBody) -> errors.clientTimeout res, "The results weren't provided within the timeout"
putRankingFromMetricsIntoScoreObject = (taskObject,scoreObject) ->
putRankingFromMetricsIntoScoreObject = (taskObject, scoreObject) ->
scoreObject = _.indexBy scoreObject, 'id'
try
scoreObject[session.sessionID].gameRanking = session.metrics.rank for session in taskObject.sessions
catch e
console.log "There was an error setting gameRanking for session #{JSON.stringify session}"
scoreObject[session.sessionID].gameRanking = session.metrics.rank for session in taskObject.sessions
return scoreObject
retrieveOldSessionData = (sessionID, callback) ->

View file

@ -22,7 +22,7 @@ productionLogging = (tokens, req, res) ->
else if status >= 300 then color = 36
elapsed = (new Date()) - req._startTime
elapsedColor = if elapsed < 500 then 90 else 31
if (status isnt 200 and status isnt 304 and status isnt 302) or elapsed > 500
if (status isnt 200 and status isnt 204 and status isnt 304 and status isnt 302) or elapsed > 500
return "\x1b[90m#{req.method} #{req.originalUrl} \x1b[#{color}m#{res.statusCode} \x1b[#{elapsedColor}m#{elapsed}ms\x1b[0m"
null