mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-29 23:43:51 -04:00
Merge branch 'master' into play-button
This commit is contained in:
commit
04895a9204
20 changed files with 259 additions and 53 deletions
app
lib
styles/play/level/modal
templates
treema-ext.coffeeviews
server
|
@ -113,7 +113,6 @@ module.exports = class LevelBus extends Bus
|
||||||
@changedSessionProperties.teamSpells = true
|
@changedSessionProperties.teamSpells = true
|
||||||
@session.set({'teamSpells': @teamSpellMap})
|
@session.set({'teamSpells': @teamSpellMap})
|
||||||
@saveSession()
|
@saveSession()
|
||||||
console.log spellTeam, me.team, e.spell.spellKey
|
|
||||||
if spellTeam is me.team
|
if spellTeam is me.team
|
||||||
@onSpellChanged e # Save the new spell to the session, too.
|
@onSpellChanged e # Save the new spell to the session, too.
|
||||||
|
|
||||||
|
|
|
@ -110,16 +110,19 @@ module.exports = class LevelLoader extends CocoClass
|
||||||
@updateCompleted = true
|
@updateCompleted = true
|
||||||
|
|
||||||
denormalizeSession: ->
|
denormalizeSession: ->
|
||||||
return if @session.get 'levelName'
|
return if @sessionDenormalized
|
||||||
patch =
|
patch =
|
||||||
'levelName': @level.get('name')
|
'levelName': @level.get('name')
|
||||||
'levelID': @level.get('slug') or @level.id
|
'levelID': @level.get('slug') or @level.id
|
||||||
if me.id is @session.get 'creator'
|
if me.id is @session.get 'creator'
|
||||||
patch.creatorName = me.get('name')
|
patch.creatorName = me.get('name')
|
||||||
|
for key, value of patch
|
||||||
@session.set key, value for key, value of patch
|
if @session.get(key) is value
|
||||||
tempSession = new LevelSession _id: @session.id
|
delete patch[key]
|
||||||
tempSession.save(patch, {patch: true})
|
unless _.isEmpty patch
|
||||||
|
@session.set key, value for key, value of patch
|
||||||
|
tempSession = new LevelSession _id: @session.id
|
||||||
|
tempSession.save(patch, {patch: true})
|
||||||
@sessionDenormalized = true
|
@sessionDenormalized = true
|
||||||
|
|
||||||
# World init
|
# World init
|
||||||
|
|
|
@ -64,7 +64,7 @@ module.exports = class Simulator
|
||||||
|
|
||||||
setupGoalManager: ->
|
setupGoalManager: ->
|
||||||
@god.goalManager = new GoalManager @world
|
@god.goalManager = new GoalManager @world
|
||||||
@god.goalManager.goals = @fetchGoalsFromWorldNoteChain()
|
@god.goalManager.goals = @god.level.goals
|
||||||
@god.goalManager.goalStates = @manuallyGenerateGoalStates()
|
@god.goalManager.goalStates = @manuallyGenerateGoalStates()
|
||||||
|
|
||||||
commenceSimulationAndSetupCallback: ->
|
commenceSimulationAndSetupCallback: ->
|
||||||
|
@ -108,17 +108,22 @@ module.exports = class Simulator
|
||||||
taskResults =
|
taskResults =
|
||||||
taskID: @task.getTaskID()
|
taskID: @task.getTaskID()
|
||||||
receiptHandle: @task.getReceiptHandle()
|
receiptHandle: @task.getReceiptHandle()
|
||||||
|
originalSessionID: @task.getFirstSessionID()
|
||||||
|
originalSessionRank: -1
|
||||||
calculationTime: 500
|
calculationTime: 500
|
||||||
sessions: []
|
sessions: []
|
||||||
|
|
||||||
for session in @task.getSessions()
|
for session in @task.getSessions()
|
||||||
|
|
||||||
sessionResult =
|
sessionResult =
|
||||||
sessionID: session.sessionID
|
sessionID: session.sessionID
|
||||||
submitDate: session.submitDate
|
submitDate: session.submitDate
|
||||||
creator: session.creator
|
creator: session.creator
|
||||||
metrics:
|
metrics:
|
||||||
rank: @calculateSessionRank session.sessionID, simulationResults.goalStates, @task.generateTeamToSessionMap()
|
rank: @calculateSessionRank session.sessionID, simulationResults.goalStates, @task.generateTeamToSessionMap()
|
||||||
|
if session.sessionID is taskResults.originalSessionID
|
||||||
|
taskResults.originalSessionRank = sessionResult.metrics.rank
|
||||||
|
taskResults.originalSessionTeam = session.team
|
||||||
taskResults.sessions.push sessionResult
|
taskResults.sessions.push sessionResult
|
||||||
|
|
||||||
return taskResults
|
return taskResults
|
||||||
|
@ -137,8 +142,6 @@ module.exports = class Simulator
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
fetchGoalsFromWorldNoteChain: -> return @god.goalManager.world.scripts[0].noteChain[0].goals.add
|
|
||||||
|
|
||||||
manuallyGenerateGoalStates: ->
|
manuallyGenerateGoalStates: ->
|
||||||
goalStates =
|
goalStates =
|
||||||
"destroy-humans":
|
"destroy-humans":
|
||||||
|
@ -190,7 +193,7 @@ module.exports = class Simulator
|
||||||
spellKeyComponents[0] = _.string.slugify spellKeyComponents[0]
|
spellKeyComponents[0] = _.string.slugify spellKeyComponents[0]
|
||||||
spellKey = spellKeyComponents.join '/'
|
spellKey = spellKeyComponents.join '/'
|
||||||
spellKey
|
spellKey
|
||||||
|
|
||||||
|
|
||||||
createSpellAndAssignName: (spellKey, spellName) ->
|
createSpellAndAssignName: (spellKey, spellName) ->
|
||||||
@spells[spellKey] ?= {}
|
@spells[spellKey] ?= {}
|
||||||
|
@ -262,10 +265,10 @@ class SimulationTask
|
||||||
fullSpellName = [thangName,spellName].join '/'
|
fullSpellName = [thangName,spellName].join '/'
|
||||||
if _.contains(teamSpells, fullSpellName)
|
if _.contains(teamSpells, fullSpellName)
|
||||||
teamCode[fullSpellName]=spell
|
teamCode[fullSpellName]=spell
|
||||||
|
|
||||||
_.merge spellKeyToSourceMap, teamCode
|
_.merge spellKeyToSourceMap, teamCode
|
||||||
commonSpells = session.teamSpells["common"]
|
commonSpells = session.teamSpells["common"]
|
||||||
_.merge spellKeyToSourceMap, _.pick(session.code, commonSpells) if commonSpells?
|
_.merge spellKeyToSourceMap, _.pick(session.code, commonSpells) if commonSpells?
|
||||||
|
|
||||||
|
|
||||||
spellKeyToSourceMap
|
spellKeyToSourceMap
|
||||||
|
|
|
@ -5,6 +5,7 @@ module.exports = class PointChooser extends CocoClass
|
||||||
super()
|
super()
|
||||||
@buildShape()
|
@buildShape()
|
||||||
@options.stage.addEventListener 'stagemousedown', @onMouseDown
|
@options.stage.addEventListener 'stagemousedown', @onMouseDown
|
||||||
|
@options.camera.dragDisabled = true
|
||||||
|
|
||||||
destroy: ->
|
destroy: ->
|
||||||
@options.stage.removeEventListener 'stagemousedown', @onMouseDown
|
@options.stage.removeEventListener 'stagemousedown', @onMouseDown
|
||||||
|
|
|
@ -7,6 +7,7 @@ module.exports = class RegionChooser extends CocoClass
|
||||||
@options.stage.addEventListener 'stagemousedown', @onMouseDown
|
@options.stage.addEventListener 'stagemousedown', @onMouseDown
|
||||||
@options.stage.addEventListener 'stagemousemove', @onMouseMove
|
@options.stage.addEventListener 'stagemousemove', @onMouseMove
|
||||||
@options.stage.addEventListener 'stagemouseup', @onMouseUp
|
@options.stage.addEventListener 'stagemouseup', @onMouseUp
|
||||||
|
@options.camera.dragDisabled = true
|
||||||
|
|
||||||
destroy: ->
|
destroy: ->
|
||||||
@options.stage.removeEventListener 'stagemousedown', @onMouseDown
|
@options.stage.removeEventListener 'stagemousedown', @onMouseDown
|
||||||
|
|
|
@ -25,6 +25,7 @@ module.exports = class SpriteBoss extends CocoClass
|
||||||
|
|
||||||
constructor: (@options) ->
|
constructor: (@options) ->
|
||||||
super()
|
super()
|
||||||
|
@dragged = 0
|
||||||
@options ?= {}
|
@options ?= {}
|
||||||
@camera = @options.camera
|
@camera = @options.camera
|
||||||
@surfaceLayer = @options.surfaceLayer
|
@surfaceLayer = @options.surfaceLayer
|
||||||
|
@ -238,11 +239,12 @@ module.exports = class SpriteBoss extends CocoClass
|
||||||
@selectThang e.thangID, e.spellName
|
@selectThang e.thangID, e.spellName
|
||||||
|
|
||||||
onCameraDragged: ->
|
onCameraDragged: ->
|
||||||
@dragged = true
|
@dragged += 1
|
||||||
|
|
||||||
onSpriteMouseUp: (e) ->
|
onSpriteMouseUp: (e) ->
|
||||||
return if key.shift and @options.choosing
|
return if key.shift and @options.choosing
|
||||||
return @dragged = false if @dragged
|
return @dragged = 0 if @dragged > 3
|
||||||
|
@dragged = 0
|
||||||
sprite = if e.sprite?.thang?.isSelectable then e.sprite else null
|
sprite = if e.sprite?.thang?.isSelectable then e.sprite else null
|
||||||
@selectSprite e, sprite
|
@selectSprite e, sprite
|
||||||
|
|
||||||
|
|
2
app/styles/play/level/modal/docs.sass
Normal file
2
app/styles/play/level/modal/docs.sass
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#docs-modal .modal-dialog
|
||||||
|
width: 800px
|
|
@ -2,6 +2,18 @@ extends /templates/base
|
||||||
|
|
||||||
block content
|
block content
|
||||||
|
|
||||||
|
h3 Espionage mode
|
||||||
|
h5 Please enter the email/username of the person you want to spy on
|
||||||
|
.form
|
||||||
|
.form-group
|
||||||
|
label.control-label Email
|
||||||
|
input#user-email
|
||||||
|
.form-group
|
||||||
|
label.control-label Username
|
||||||
|
input#user-username
|
||||||
|
|
||||||
|
button.btn.btn-primary.btn-large#enter-espionage-mode 007
|
||||||
|
|
||||||
h3(data-i18n="admin.av_title") Admin Views
|
h3(data-i18n="admin.av_title") Admin Views
|
||||||
|
|
||||||
h4(data-i18n="admin.av_entities_sub_title") Entities
|
h4(data-i18n="admin.av_entities_sub_title") Entities
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
h4.home
|
h4.home
|
||||||
|
|
||||||
a(href="/")
|
a(href=homeLink || "/")
|
||||||
i.icon-home.icon-white
|
i.icon-home.icon-white
|
||||||
span(data-i18n="play_level.home") Home
|
span(data-i18n="play_level.home") Home
|
||||||
|
|
||||||
h4.title #{worldName}
|
h4.title #{worldName}
|
||||||
|
|
||||||
button.btn.btn-xs.btn-inverse.banner#docs-button(title="Show level instructions", data-i18n="play_level.guide") Guide
|
button.btn.btn-xs.btn-success.banner#docs-button(title="Show level instructions", data-i18n="play_level.guide") Guide
|
||||||
|
|
||||||
if ladderGame
|
if ladderGame
|
||||||
button.btn.btn-xs.btn-inverse.banner#multiplayer-button(title="Leaderboard", data-i18n="play_level.leaderboard") Leaderboard
|
button.btn.btn-xs.btn-inverse.banner#multiplayer-button(title="Leaderboard", data-i18n="play_level.leaderboard") Leaderboard
|
||||||
|
|
|
@ -38,12 +38,13 @@ class LiveEditingMarkup extends TreemaNode.nodeMap.ace
|
||||||
url: InkBlob.url
|
url: InkBlob.url
|
||||||
filename: InkBlob.filename
|
filename: InkBlob.filename
|
||||||
mimetype: InkBlob.mimetype
|
mimetype: InkBlob.mimetype
|
||||||
description: ''
|
path: @settings.filePath
|
||||||
createdFor: []
|
|
||||||
|
@uploadingPath = [@settings.filePath, InkBlob.filename].join('/')
|
||||||
$.ajax('/file', { type: 'POST', data: body, success: @onFileUploaded })
|
$.ajax('/file', { type: 'POST', data: body, success: @onFileUploaded })
|
||||||
|
|
||||||
onFileUploaded: (e) =>
|
onFileUploaded: (e) =>
|
||||||
@editor.insert ""
|
@editor.insert ""
|
||||||
|
|
||||||
onEditorChange: =>
|
onEditorChange: =>
|
||||||
@saveChanges()
|
@saveChanges()
|
||||||
|
|
|
@ -1,6 +1,35 @@
|
||||||
|
{backboneFailure, genericFailure} = require 'lib/errors'
|
||||||
View = require 'views/kinds/RootView'
|
View = require 'views/kinds/RootView'
|
||||||
template = require 'templates/admin'
|
template = require 'templates/admin'
|
||||||
|
storage = require 'lib/storage'
|
||||||
|
|
||||||
module.exports = class AdminView extends View
|
module.exports = class AdminView extends View
|
||||||
id: "admin-view"
|
id: "admin-view"
|
||||||
template: template
|
template: template
|
||||||
|
|
||||||
|
events:
|
||||||
|
'click #enter-espionage-mode': 'enterEspionageMode'
|
||||||
|
|
||||||
|
enterEspionageMode: ->
|
||||||
|
userEmail = $("#user-email").val().toLowerCase()
|
||||||
|
username = $("#user-username").val().toLowerCase()
|
||||||
|
|
||||||
|
userIdentifier = userEmail || username
|
||||||
|
postData =
|
||||||
|
usernameLower: username
|
||||||
|
emailLower: userEmail
|
||||||
|
|
||||||
|
$.ajax
|
||||||
|
type: "POST",
|
||||||
|
url: "/auth/spy"
|
||||||
|
data: postData
|
||||||
|
success: @espionageSuccess
|
||||||
|
error: @espionageFailure
|
||||||
|
|
||||||
|
espionageSuccess: (model) ->
|
||||||
|
storage.save('whoami',model)
|
||||||
|
window.location.reload()
|
||||||
|
espionageFailure: (jqxhr, status,error)->
|
||||||
|
console.log "There was an error entering espionage mode: #{error}"
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ module.exports = class ArticleEditView extends View
|
||||||
data = $.extend(true, {}, @article.attributes)
|
data = $.extend(true, {}, @article.attributes)
|
||||||
options =
|
options =
|
||||||
data: data
|
data: data
|
||||||
|
filePath: "db/thang.type/#{@article.get('original')}"
|
||||||
schema: Article.schema.attributes
|
schema: Article.schema.attributes
|
||||||
callbacks:
|
callbacks:
|
||||||
change: @pushChangesToPreview
|
change: @pushChangesToPreview
|
||||||
|
|
|
@ -47,12 +47,17 @@ module.exports = class ControlBarView extends View
|
||||||
text += " (#{numPlayers})" if numPlayers > 1
|
text += " (#{numPlayers})" if numPlayers > 1
|
||||||
$('#multiplayer-button', @$el).text(text)
|
$('#multiplayer-button', @$el).text(text)
|
||||||
|
|
||||||
getRenderData: (context={}) ->
|
getRenderData: (c={}) ->
|
||||||
super context
|
super c
|
||||||
context.worldName = @worldName
|
c.worldName = @worldName
|
||||||
context.multiplayerEnabled = @session.get('multiplayer')
|
c.multiplayerEnabled = @session.get('multiplayer')
|
||||||
context.ladderGame = @ladderGame
|
c.ladderGame = @ladderGame
|
||||||
context
|
c.homeLink = "/"
|
||||||
|
levelID = @level.get('slug')
|
||||||
|
if levelID in ["project-dota", "brawlwood", "ladder-tutorial"]
|
||||||
|
levelID = 'project-dota' if levelID is 'ladder-tutorial'
|
||||||
|
c.homeLink = "/play/ladder/" + levelID
|
||||||
|
c
|
||||||
|
|
||||||
showGuideModal: ->
|
showGuideModal: ->
|
||||||
options = {docs: @level.get('documentation'), supermodel: @supermodel}
|
options = {docs: @level.get('documentation'), supermodel: @supermodel}
|
||||||
|
|
|
@ -270,7 +270,7 @@ module.exports = class HUDView extends View
|
||||||
if prop is "rotation"
|
if prop is "rotation"
|
||||||
return (val * 180 / Math.PI).toFixed(0) + "˚"
|
return (val * 180 / Math.PI).toFixed(0) + "˚"
|
||||||
if typeof val is 'number'
|
if typeof val is 'number'
|
||||||
if Math.round(val) == val then return val.toFixed(0) # int
|
if Math.round(val) == val or prop is 'gold' then return val.toFixed(0) # int
|
||||||
if -10 < val < 10 then return val.toFixed(2)
|
if -10 < val < 10 then return val.toFixed(2)
|
||||||
if -100 < val < 100 then return val.toFixed(1)
|
if -100 < val < 100 then return val.toFixed(1)
|
||||||
return val.toFixed(0)
|
return val.toFixed(0)
|
||||||
|
|
|
@ -6,6 +6,7 @@ Article = require 'models/Article'
|
||||||
|
|
||||||
module.exports = class DocsModal extends View
|
module.exports = class DocsModal extends View
|
||||||
template: template
|
template: template
|
||||||
|
id: 'docs-modal'
|
||||||
|
|
||||||
shortcuts:
|
shortcuts:
|
||||||
'enter': 'hide'
|
'enter': 'hide'
|
||||||
|
|
|
@ -82,11 +82,20 @@ module.exports = class DebugView extends View
|
||||||
else
|
else
|
||||||
@$el.hide()
|
@$el.hide()
|
||||||
if @variableChain?.length is 2
|
if @variableChain?.length is 2
|
||||||
Backbone.Mediator.publish 'tome:spell-debug-property-hovered', property: @variableChain[1], owner: @variableChain[0]
|
clearTimeout @hoveredPropertyTimeout if @hoveredPropertyTimeout
|
||||||
|
@hoveredPropertyTimeout = _.delay @notifyPropertyHovered, 500
|
||||||
else
|
else
|
||||||
Backbone.Mediator.publish 'tome:spell-debug-property-hovered', property: null
|
@notifyPropertyHovered()
|
||||||
@updateMarker()
|
@updateMarker()
|
||||||
|
|
||||||
|
notifyPropertyHovered: =>
|
||||||
|
clearTimeout @hoveredPropertyTimeout if @hoveredPropertyTimeout
|
||||||
|
@hoveredPropertyTimeout = null
|
||||||
|
oldHoveredProperty = @hoveredProperty
|
||||||
|
@hoveredProperty = if @variableChain?.length is 2 then owner: @variableChain[0], property: @variableChain[1] else {}
|
||||||
|
unless _.isEqual oldHoveredProperty, @hoveredProperty
|
||||||
|
Backbone.Mediator.publish 'tome:spell-debug-property-hovered', @hoveredProperty
|
||||||
|
|
||||||
updateMarker: ->
|
updateMarker: ->
|
||||||
if @marker
|
if @marker
|
||||||
@ace.getSession().removeMarker @marker
|
@ace.getSession().removeMarker @marker
|
||||||
|
|
|
@ -141,17 +141,13 @@ module.exports = class PlayLevelView extends View
|
||||||
|
|
||||||
otherSession = @levelLoader.opponentSession
|
otherSession = @levelLoader.opponentSession
|
||||||
opponentCode = otherSession?.get('submittedCode') or {}
|
opponentCode = otherSession?.get('submittedCode') or {}
|
||||||
console.log "otherSession", otherSession, "opponentSpells", opponentSpells
|
|
||||||
myCode = @session.get('code') or {}
|
myCode = @session.get('code') or {}
|
||||||
for spell in opponentSpells
|
for spell in opponentSpells
|
||||||
[thang, spell] = spell.split '/'
|
[thang, spell] = spell.split '/'
|
||||||
c = opponentCode[thang]?[spell]
|
c = opponentCode[thang]?[spell]
|
||||||
console.log "Got opponent code", c, "for", spell, "and had my code", myCode[spell]
|
|
||||||
myCode[thang] ?= {}
|
myCode[thang] ?= {}
|
||||||
if c then myCode[thang][spell] = c else delete myCode[thang][spell]
|
if c then myCode[thang][spell] = c else delete myCode[thang][spell]
|
||||||
console.log "Going to set session code from", _.cloneDeep(myCode)
|
|
||||||
@session.set('code', myCode)
|
@session.set('code', myCode)
|
||||||
console.log "Just set session code to", _.cloneDeep(@session.get('code'))
|
|
||||||
if @session.get('multiplayer') and otherSession?
|
if @session.get('multiplayer') and otherSession?
|
||||||
# For now, ladderGame will disallow multiplayer, because session code combining doesn't play nice yet.
|
# For now, ladderGame will disallow multiplayer, because session code combining doesn't play nice yet.
|
||||||
@session.set 'multiplayer', false
|
@session.set 'multiplayer', false
|
||||||
|
|
|
@ -139,6 +139,13 @@ _.extend LevelSessionSchema.properties,
|
||||||
|
|
||||||
submittedCode:
|
submittedCode:
|
||||||
type: 'object'
|
type: 'object'
|
||||||
|
|
||||||
|
numberOfWinsAndTies:
|
||||||
|
type: 'number'
|
||||||
|
default: 0
|
||||||
|
numberOfLosses:
|
||||||
|
type: 'number'
|
||||||
|
default: 0
|
||||||
|
|
||||||
matches:
|
matches:
|
||||||
type: 'array'
|
type: 'array'
|
||||||
|
|
|
@ -12,7 +12,7 @@ TaskLog = require './task/ScoringTask'
|
||||||
bayes = new (require 'bayesian-battle')()
|
bayes = new (require 'bayesian-battle')()
|
||||||
|
|
||||||
scoringTaskQueue = undefined
|
scoringTaskQueue = undefined
|
||||||
scoringTaskTimeoutInSeconds = 120
|
scoringTaskTimeoutInSeconds = 180
|
||||||
|
|
||||||
|
|
||||||
module.exports.setup = (app) -> connectToScoringQueue()
|
module.exports.setup = (app) -> connectToScoringQueue()
|
||||||
|
@ -24,24 +24,27 @@ connectToScoringQueue = ->
|
||||||
scoringTaskQueue = data
|
scoringTaskQueue = data
|
||||||
log.info "Connected to scoring task queue!"
|
log.info "Connected to scoring task queue!"
|
||||||
|
|
||||||
module.exports.addPairwiseTaskToQueue = (req, res) ->
|
module.exports.addPairwiseTaskToQueueFromRequest = (req, res) ->
|
||||||
taskPair = req.body.sessions
|
taskPair = req.body.sessions
|
||||||
#unless isUserAdmin req then return errors.forbidden res, "You do not have the permissions to submit that game to the leaderboard"
|
addPairwiseTaskToQueue req.body.sessions (err, success) ->
|
||||||
#fetch both sessions
|
if err? then return errors.serverError res, "There was an error adding pairwise tasks: #{err}"
|
||||||
|
sendResponseObject req, res, {"message":"All task pairs were succesfully sent to the queue"}
|
||||||
|
|
||||||
|
|
||||||
|
addPairwiseTaskToQueue = (taskPair, cb) ->
|
||||||
LevelSession.findOne(_id:taskPair[0]).lean().exec (err, firstSession) =>
|
LevelSession.findOne(_id:taskPair[0]).lean().exec (err, firstSession) =>
|
||||||
if err? then return errors.serverError res, "There was an error fetching the first session in the pair"
|
if err? then return cb err, false
|
||||||
LevelSession.find(_id:taskPair[1]).exec (err, secondSession) =>
|
LevelSession.find(_id:taskPair[1]).exec (err, secondSession) =>
|
||||||
if err? then return errors.serverError res, "There was an error fetching the second session"
|
if err? then return cb err, false
|
||||||
try
|
try
|
||||||
taskPairs = generateTaskPairs(secondSession, firstSession)
|
taskPairs = generateTaskPairs(secondSession, firstSession)
|
||||||
catch e
|
catch e
|
||||||
if e then return errors.serverError res, "There was an error generating the task pairs"
|
if e then return cb e, false
|
||||||
|
|
||||||
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"}
|
sendEachTaskPairToTheQueue taskPairs, (taskPairError) ->
|
||||||
|
if taskPairError? then return cb taskPairError,false
|
||||||
|
cb null, true
|
||||||
|
|
||||||
|
|
||||||
module.exports.createNewTask = (req, res) ->
|
module.exports.createNewTask = (req, res) ->
|
||||||
requestSessionID = req.body.session
|
requestSessionID = req.body.session
|
||||||
|
@ -56,8 +59,8 @@ module.exports.createNewTask = (req, res) ->
|
||||||
|
|
||||||
updateSessionToSubmit sessionToSubmit, (err, data) ->
|
updateSessionToSubmit sessionToSubmit, (err, data) ->
|
||||||
if err? then return errors.serverError res, "There was an error updating the session"
|
if err? then return errors.serverError res, "There was an error updating the session"
|
||||||
|
opposingTeam = calculateOpposingTeam(sessionToSubmit.team)
|
||||||
fetchSessionsToRankAgainst (err, sessionsToRankAgainst) ->
|
fetchInitialSessionsToRankAgainst opposingTeam, (err, sessionsToRankAgainst) ->
|
||||||
if err? then return errors.serverError res, "There was an error fetching the sessions to rank against"
|
if err? then return errors.serverError res, "There was an error fetching the sessions to rank against"
|
||||||
|
|
||||||
taskPairs = generateTaskPairs(sessionsToRankAgainst, sessionToSubmit)
|
taskPairs = generateTaskPairs(sessionsToRankAgainst, sessionToSubmit)
|
||||||
|
@ -114,9 +117,102 @@ module.exports.processTaskResult = (req, res) ->
|
||||||
|
|
||||||
addMatchToSessions clientResponseObject, newScoresObject, (err, data) ->
|
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}"
|
if err? then return errors.serverError res, "There was an error updating the sessions with the match! #{JSON.stringify err}"
|
||||||
console.log "Sending response object"
|
|
||||||
sendResponseObject req, res, {"message":"The scores were updated successfully!"}
|
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
|
||||||
|
findNearestBetterSessionID 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!"}
|
||||||
|
|
||||||
|
|
||||||
|
determineIfSessionShouldContinueAndUpdateLog = (sessionID, sessionRank, cb) ->
|
||||||
|
queryParameters =
|
||||||
|
_id: sessionID
|
||||||
|
|
||||||
|
updateParameters =
|
||||||
|
"$inc": {}
|
||||||
|
|
||||||
|
if sessionRank is 0
|
||||||
|
updateParameters["$inc"] = {numberOfWinsAndTies: 1}
|
||||||
|
else
|
||||||
|
updateParameters["$inc"] = {numberOfLosses: 1}
|
||||||
|
|
||||||
|
LevelSession.findOneAndUpdate queryParameters, updateParameters,{select: 'numberOfWinsAndTies numberOfLosses'}, (err, updatedSession) ->
|
||||||
|
if err? then return cb err, updatedSession
|
||||||
|
updatedSession = updatedSession.toObject()
|
||||||
|
|
||||||
|
totalNumberOfGamesPlayed = updatedSession.numberOfWinsAndTies + updatedSession.numberOfLosses
|
||||||
|
if totalNumberOfGamesPlayed < 5
|
||||||
|
console.log "Number of games played is less than 5, continuing..."
|
||||||
|
cb null, true
|
||||||
|
else if totalNumberOfGamesPlayed > 15
|
||||||
|
console.log "Too many games played, ending..."
|
||||||
|
cb null, false
|
||||||
|
else
|
||||||
|
ratio = (updatedSession.numberOfLosses - 5) / (totalNumberOfGamesPlayed)
|
||||||
|
if ratio > 0.66
|
||||||
|
cb null, false
|
||||||
|
console.log "Ratio(#{ratio}) is bad, ending simulation"
|
||||||
|
else
|
||||||
|
console.log "Ratio(#{ratio}) is good, so continuing simulations"
|
||||||
|
cb null, true
|
||||||
|
|
||||||
|
|
||||||
|
findNearestBetterSessionID = (sessionTotalScore, opponentSessionTotalScore, opponentSessionID, opposingTeam, cb) ->
|
||||||
|
queryParameters =
|
||||||
|
totalScore:
|
||||||
|
$gt:opponentSessionTotalScore + 0.5
|
||||||
|
_id:
|
||||||
|
$ne: opponentSessionID
|
||||||
|
levelID: "project-dota"
|
||||||
|
submitted: true
|
||||||
|
submittedCode:
|
||||||
|
$exists: true
|
||||||
|
team: opposingTeam
|
||||||
|
|
||||||
|
limitNumber = 1
|
||||||
|
|
||||||
|
sortParameters =
|
||||||
|
totalScore: 1
|
||||||
|
|
||||||
|
selectString = '_id totalScore'
|
||||||
|
|
||||||
|
query = LevelSession.findOne(queryParameters)
|
||||||
|
.sort(sortParameters)
|
||||||
|
.limit(limitNumber)
|
||||||
|
.select(selectString)
|
||||||
|
.lean()
|
||||||
|
|
||||||
|
console.log "Finding session with score near #{opponentSessionTotalScore}"
|
||||||
|
query.exec (err, session) ->
|
||||||
|
if err? then return cb err, session
|
||||||
|
unless session then return cb err, null
|
||||||
|
console.log "Found session with score #{session.totalScore}"
|
||||||
|
cb err, session._id
|
||||||
|
|
||||||
|
calculateOpposingTeam = (sessionTeam) ->
|
||||||
|
teams = ['ogres','humans']
|
||||||
|
opposingTeams = _.pull teams, sessionTeam
|
||||||
|
return opposingTeams[0]
|
||||||
|
|
||||||
|
|
||||||
validatePermissions = (req, sessionID, callback) ->
|
validatePermissions = (req, sessionID, callback) ->
|
||||||
if isUserAnonymous req then return callback null, false
|
if isUserAnonymous req then return callback null, false
|
||||||
if isUserAdmin req then return callback null, true
|
if isUserAdmin req then return callback null, true
|
||||||
|
@ -177,15 +273,30 @@ updateSessionToSubmit = (sessionToUpdate, callback) ->
|
||||||
meanStrength: 25
|
meanStrength: 25
|
||||||
standardDeviation: 25/3
|
standardDeviation: 25/3
|
||||||
totalScore: 10
|
totalScore: 10
|
||||||
|
numberOfWinsAndTies: 0
|
||||||
|
numberOfLosses: 0
|
||||||
LevelSession.update {_id: sessionToUpdate._id}, sessionUpdateObject, callback
|
LevelSession.update {_id: sessionToUpdate._id}, sessionUpdateObject, callback
|
||||||
|
|
||||||
fetchSessionsToRankAgainst = (callback) ->
|
fetchInitialSessionsToRankAgainst = (opposingTeam, callback) ->
|
||||||
submittedSessionsQuery =
|
console.log "Fetching sessions to rank against for opposing team #{opposingTeam}"
|
||||||
|
findParameters =
|
||||||
levelID: "project-dota"
|
levelID: "project-dota"
|
||||||
submitted: true
|
submitted: true
|
||||||
submittedCode:
|
submittedCode:
|
||||||
$exists: true
|
$exists: true
|
||||||
LevelSession.find submittedSessionsQuery, callback
|
team: opposingTeam
|
||||||
|
|
||||||
|
sortParameters =
|
||||||
|
totalScore: 1
|
||||||
|
|
||||||
|
limitNumber = 1
|
||||||
|
|
||||||
|
query = LevelSession.find(findParameters)
|
||||||
|
.sort(sortParameters)
|
||||||
|
.limit(limitNumber)
|
||||||
|
|
||||||
|
|
||||||
|
query.exec callback
|
||||||
|
|
||||||
generateTaskPairs = (submittedSessions, sessionToScore) ->
|
generateTaskPairs = (submittedSessions, sessionToScore) ->
|
||||||
taskPairs = []
|
taskPairs = []
|
||||||
|
|
|
@ -28,7 +28,30 @@ module.exports.setup = (app) ->
|
||||||
return done(null, user)
|
return done(null, user)
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
app.post '/auth/spy', (req, res, next) ->
|
||||||
|
if req?.user?.isAdmin()
|
||||||
|
|
||||||
|
username = req.body.usernameLower
|
||||||
|
emailLower = req.body.emailLower
|
||||||
|
if emailLower
|
||||||
|
query = {"emailLower":emailLower}
|
||||||
|
else if username
|
||||||
|
query = {"nameLower":username}
|
||||||
|
else
|
||||||
|
return errors.badInput res, "You need to supply one of emailLower or username"
|
||||||
|
|
||||||
|
User.findOne query, (err, user) ->
|
||||||
|
if err? then return errors.serverError res, "There was an error finding the specified user"
|
||||||
|
|
||||||
|
unless user then return errors.badInput res, "The specified user couldn't be found"
|
||||||
|
|
||||||
|
req.logIn user, (err) ->
|
||||||
|
if err? then return errors.serverError res, "There was an error logging in with the specified"
|
||||||
|
res.send(UserHandler.formatEntity(req, user))
|
||||||
|
return res.end()
|
||||||
|
else
|
||||||
|
return errors.unauthorized res, "You must be an admin to enter espionage mode"
|
||||||
|
|
||||||
app.post('/auth/login', (req, res, next) ->
|
app.post('/auth/login', (req, res, next) ->
|
||||||
authentication.authenticate('local', (err, user, info) ->
|
authentication.authenticate('local', (err, user, info) ->
|
||||||
return next(err) if err
|
return next(err) if err
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue