Merge branch 'master' into play-button

This commit is contained in:
Tay Yang Shun 2014-02-27 14:09:37 +08:00
commit 04895a9204
20 changed files with 259 additions and 53 deletions

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
#docs-modal .modal-dialog
width: 800px

View file

@ -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

View file

@ -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

View file

@ -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 "![#{e.metadata.name}](/file/#{e._id})" @editor.insert "![#{e.metadata.name}](/file/#{@uploadingPath})"
onEditorChange: => onEditorChange: =>
@saveChanges() @saveChanges()

View file

@ -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}"

View file

@ -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

View file

@ -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}

View file

@ -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)

View file

@ -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'

View file

@ -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

View file

@ -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

View file

@ -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'

View file

@ -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 = []

View file

@ -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