From a0521802505a8045d6dfc3c74bf19973254310e3 Mon Sep 17 00:00:00 2001 From: Michael Schmatz <schmatz@umich.edu> Date: Wed, 26 Feb 2014 12:14:02 -0800 Subject: [PATCH 01/13] Improved match scheduling --- app/lib/simulator/Simulator.coffee | 7 +- server/queues/scoring.coffee | 107 ++++++++++++++++++++++++----- 2 files changed, 95 insertions(+), 19 deletions(-) diff --git a/app/lib/simulator/Simulator.coffee b/app/lib/simulator/Simulator.coffee index cbaf95c4a..723c0cab3 100644 --- a/app/lib/simulator/Simulator.coffee +++ b/app/lib/simulator/Simulator.coffee @@ -108,17 +108,22 @@ module.exports = class Simulator taskResults = taskID: @task.getTaskID() receiptHandle: @task.getReceiptHandle() + originalSessionID: @task.getFirstSessionID() + originalSessionRank: -1 calculationTime: 500 sessions: [] for session in @task.getSessions() + sessionResult = sessionID: session.sessionID submitDate: session.submitDate creator: session.creator metrics: 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 return taskResults diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee index 4592ec74c..c691c235b 100644 --- a/server/queues/scoring.coffee +++ b/server/queues/scoring.coffee @@ -24,24 +24,27 @@ connectToScoringQueue = -> scoringTaskQueue = data log.info "Connected to scoring task queue!" -module.exports.addPairwiseTaskToQueue = (req, res) -> +module.exports.addPairwiseTaskToQueueFromRequest = (req, res) -> 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" - #fetch both sessions + addPairwiseTaskToQueue req.body.sessions (err, success) -> + 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) => - 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) => - if err? then return errors.serverError res, "There was an error fetching the second session" + if err? then return cb err, false try taskPairs = generateTaskPairs(secondSession, firstSession) catch e - if e then return errors.serverError res, "There was an error generating the task pairs" - - sendEachTaskPairToTheQueue taskPairs, (taskPairError) -> - if taskPairError? then return errors.serverError res, "There was an error sending the task pairs to the queue" + if e then return cb e, false - 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) -> requestSessionID = req.body.session @@ -56,8 +59,8 @@ module.exports.createNewTask = (req, res) -> updateSessionToSubmit sessionToSubmit, (err, data) -> if err? then return errors.serverError res, "There was an error updating the session" - - fetchSessionsToRankAgainst (err, sessionsToRankAgainst) -> + opposingTeam = calculateOpposingTeam(sessionToSubmit.team) + fetchInitialSessionsToRankAgainst opposingTeam, (err, sessionsToRankAgainst) -> if err? then return errors.serverError res, "There was an error fetching the sessions to rank against" taskPairs = generateTaskPairs(sessionsToRankAgainst, sessionToSubmit) @@ -114,9 +117,64 @@ module.exports.processTaskResult = (req, res) -> 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}" - console.log "Sending response object" - sendResponseObject req, res, {"message":"The scores were updated successfully!"} + originalSessionID = clientResponseObject.originalSessionID + originalSessionTeam = clientResponseObject.originalSessionTeam + originalSessionRank = parseInt clientResponseObject.originalSessionRank + console.log "The player #{originalSessionID} just achieved rank #{clientResponseObject.originalSessionRank}" + if originalSessionRank is 0 + console.log "Should submit another session into the queue!" + #fetch next session + opposingTeam = calculateOpposingTeam(originalSessionTeam) + opponentID = _.pull(_.keys(newScoresObject), originalSessionID) + sessionNewScore = newScoresObject[originalSessionID].totalScore + opponentNewScore = newScoresObject[opponentID].totalScore + findNearestBetterSessionID sessionNewScore, opponentNewScore ,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!"} +findNearestBetterSessionID = (sessionTotalScore, opponentSessionTotalScore, opposingTeam, cb) -> + queryParameters = + totalScore: + $gt:Math.max(10,opponentSessionTotalScore) + 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 #{sessionTotalScore}" + 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) -> if isUserAnonymous req then return callback null, false if isUserAdmin req then return callback null, true @@ -179,13 +237,26 @@ updateSessionToSubmit = (sessionToUpdate, callback) -> totalScore: 10 LevelSession.update {_id: sessionToUpdate._id}, sessionUpdateObject, callback -fetchSessionsToRankAgainst = (callback) -> - submittedSessionsQuery = +fetchInitialSessionsToRankAgainst = (opposingTeam, callback) -> + console.log "Fetching sessions to rank against for opposing team #{opposingTeam}" + findParameters = levelID: "project-dota" submitted: true submittedCode: $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) -> taskPairs = [] From b648098c953eb59df1dca7719019d6a9d4b101c4 Mon Sep 17 00:00:00 2001 From: Michael Schmatz <schmatz@umich.edu> Date: Wed, 26 Feb 2014 14:14:43 -0800 Subject: [PATCH 02/13] Implemented espionage mode --- app/templates/admin.jade | 12 ++++++++++++ app/views/admin_view.coffee | 29 +++++++++++++++++++++++++++++ server/routes/auth.coffee | 25 ++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/app/templates/admin.jade b/app/templates/admin.jade index 43d6769c6..feb9d9347 100644 --- a/app/templates/admin.jade +++ b/app/templates/admin.jade @@ -2,6 +2,18 @@ extends /templates/base 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 h4(data-i18n="admin.av_entities_sub_title") Entities diff --git a/app/views/admin_view.coffee b/app/views/admin_view.coffee index 941136574..e71c9acaf 100644 --- a/app/views/admin_view.coffee +++ b/app/views/admin_view.coffee @@ -1,6 +1,35 @@ +{backboneFailure, genericFailure} = require 'lib/errors' View = require 'views/kinds/RootView' template = require 'templates/admin' +storage = require 'lib/storage' module.exports = class AdminView extends View id: "admin-view" 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}" + + \ No newline at end of file diff --git a/server/routes/auth.coffee b/server/routes/auth.coffee index e5d3f9367..2e6dbf72d 100644 --- a/server/routes/auth.coffee +++ b/server/routes/auth.coffee @@ -28,7 +28,30 @@ module.exports.setup = (app) -> 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) -> authentication.authenticate('local', (err, user, info) -> return next(err) if err From ea73d91a6b07f15dd51f804129c70c6f2d3789c4 Mon Sep 17 00:00:00 2001 From: Scott Erickson <sderickson@gmail.com> Date: Wed, 26 Feb 2014 15:44:46 -0800 Subject: [PATCH 03/13] Made the docs modal larger. --- app/styles/play/level/modal/docs.sass | 2 ++ app/views/play/level/modal/docs_modal.coffee | 1 + 2 files changed, 3 insertions(+) create mode 100644 app/styles/play/level/modal/docs.sass diff --git a/app/styles/play/level/modal/docs.sass b/app/styles/play/level/modal/docs.sass new file mode 100644 index 000000000..3c25f0389 --- /dev/null +++ b/app/styles/play/level/modal/docs.sass @@ -0,0 +1,2 @@ +#docs-modal .modal-dialog + width: 800px \ No newline at end of file diff --git a/app/views/play/level/modal/docs_modal.coffee b/app/views/play/level/modal/docs_modal.coffee index fc975b84a..c7b77a287 100644 --- a/app/views/play/level/modal/docs_modal.coffee +++ b/app/views/play/level/modal/docs_modal.coffee @@ -6,6 +6,7 @@ Article = require 'models/Article' module.exports = class DocsModal extends View template: template + id: 'docs-modal' shortcuts: 'enter': 'hide' From c86feb13e86942c29b6e239eb7c5d74d860eccf0 Mon Sep 17 00:00:00 2001 From: Scott Erickson <sderickson@gmail.com> Date: Wed, 26 Feb 2014 15:56:05 -0800 Subject: [PATCH 04/13] Fixed the region and point choosers for the level editor. --- app/lib/surface/PointChooser.coffee | 1 + app/lib/surface/RegionChooser.coffee | 1 + 2 files changed, 2 insertions(+) diff --git a/app/lib/surface/PointChooser.coffee b/app/lib/surface/PointChooser.coffee index 470b10c5f..c55b1a134 100644 --- a/app/lib/surface/PointChooser.coffee +++ b/app/lib/surface/PointChooser.coffee @@ -5,6 +5,7 @@ module.exports = class PointChooser extends CocoClass super() @buildShape() @options.stage.addEventListener 'stagemousedown', @onMouseDown + @options.camera.dragDisabled = true destroy: -> @options.stage.removeEventListener 'stagemousedown', @onMouseDown diff --git a/app/lib/surface/RegionChooser.coffee b/app/lib/surface/RegionChooser.coffee index 14eb47035..d0dbdc82a 100644 --- a/app/lib/surface/RegionChooser.coffee +++ b/app/lib/surface/RegionChooser.coffee @@ -7,6 +7,7 @@ module.exports = class RegionChooser extends CocoClass @options.stage.addEventListener 'stagemousedown', @onMouseDown @options.stage.addEventListener 'stagemousemove', @onMouseMove @options.stage.addEventListener 'stagemouseup', @onMouseUp + @options.camera.dragDisabled = true destroy: -> @options.stage.removeEventListener 'stagemousedown', @onMouseDown From 172242d226cc61f4467ac69c1f7a043543912b00 Mon Sep 17 00:00:00 2001 From: Nick Winter <livelily@gmail.com> Date: Wed, 26 Feb 2014 17:06:21 -0800 Subject: [PATCH 05/13] Re-denormalize session if things have changed. Removed some logs. --- app/lib/LevelLoader.coffee | 13 ++++++++----- app/views/play/level_view.coffee | 4 ---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/app/lib/LevelLoader.coffee b/app/lib/LevelLoader.coffee index 8afc6577a..3d1aa8115 100644 --- a/app/lib/LevelLoader.coffee +++ b/app/lib/LevelLoader.coffee @@ -110,16 +110,19 @@ module.exports = class LevelLoader extends CocoClass @updateCompleted = true denormalizeSession: -> - return if @session.get 'levelName' + return if @sessionDenormalized patch = 'levelName': @level.get('name') 'levelID': @level.get('slug') or @level.id if me.id is @session.get 'creator' patch.creatorName = me.get('name') - - @session.set key, value for key, value of patch - tempSession = new LevelSession _id: @session.id - tempSession.save(patch, {patch: true}) + for key, value of patch + if @session.get(key) is value + delete patch[key] + 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 # World init diff --git a/app/views/play/level_view.coffee b/app/views/play/level_view.coffee index 7e90832c8..16a817dcd 100644 --- a/app/views/play/level_view.coffee +++ b/app/views/play/level_view.coffee @@ -141,17 +141,13 @@ module.exports = class PlayLevelView extends View otherSession = @levelLoader.opponentSession opponentCode = otherSession?.get('submittedCode') or {} - console.log "otherSession", otherSession, "opponentSpells", opponentSpells myCode = @session.get('code') or {} for spell in opponentSpells [thang, spell] = spell.split '/' c = opponentCode[thang]?[spell] - console.log "Got opponent code", c, "for", spell, "and had my code", myCode[spell] myCode[thang] ?= {} 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) - console.log "Just set session code to", _.cloneDeep(@session.get('code')) if @session.get('multiplayer') and otherSession? # For now, ladderGame will disallow multiplayer, because session code combining doesn't play nice yet. @session.set 'multiplayer', false From 0cf20b577d79ce306834367c5939704d83b64f0c Mon Sep 17 00:00:00 2001 From: Nick Winter <livelily@gmail.com> Date: Wed, 26 Feb 2014 17:23:59 -0800 Subject: [PATCH 06/13] Added a delay to the property documentation on spell debug hover. --- app/views/play/level/tome/spell_debug_view.coffee | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/views/play/level/tome/spell_debug_view.coffee b/app/views/play/level/tome/spell_debug_view.coffee index f59b84501..5f4cfdd30 100644 --- a/app/views/play/level/tome/spell_debug_view.coffee +++ b/app/views/play/level/tome/spell_debug_view.coffee @@ -82,11 +82,20 @@ module.exports = class DebugView extends View else @$el.hide() 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 - Backbone.Mediator.publish 'tome:spell-debug-property-hovered', property: null + @notifyPropertyHovered() @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: -> if @marker @ace.getSession().removeMarker @marker From f82483b9059fee86a07605b506e8da320617b183 Mon Sep 17 00:00:00 2001 From: Michael Schmatz <schmatz@umich.edu> Date: Wed, 26 Feb 2014 17:30:56 -0800 Subject: [PATCH 07/13] Changed session scheduling --- .../sessions/level_session_schema.coffee | 7 ++ server/queues/scoring.coffee | 84 ++++++++++++++----- 2 files changed, 69 insertions(+), 22 deletions(-) diff --git a/server/levels/sessions/level_session_schema.coffee b/server/levels/sessions/level_session_schema.coffee index da97b8ce5..290422c10 100644 --- a/server/levels/sessions/level_session_schema.coffee +++ b/server/levels/sessions/level_session_schema.coffee @@ -139,6 +139,13 @@ _.extend LevelSessionSchema.properties, submittedCode: type: 'object' + + numberOfWinsAndTies: + type: 'number' + default: 0 + numberOfLosses: + type: 'number' + default: 0 matches: type: 'array' diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee index c691c235b..40a6b2f21 100644 --- a/server/queues/scoring.coffee +++ b/server/queues/scoring.coffee @@ -12,7 +12,7 @@ TaskLog = require './task/ScoringTask' bayes = new (require 'bayesian-battle')() scoringTaskQueue = undefined -scoringTaskTimeoutInSeconds = 120 +scoringTaskTimeoutInSeconds = 180 module.exports.setup = (app) -> connectToScoringQueue() @@ -117,32 +117,70 @@ module.exports.processTaskResult = (req, res) -> 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 - console.log "The player #{originalSessionID} just achieved rank #{clientResponseObject.originalSessionRank}" - if originalSessionRank is 0 - console.log "Should submit another session into the queue!" - #fetch next session - opposingTeam = calculateOpposingTeam(originalSessionTeam) - opponentID = _.pull(_.keys(newScoresObject), originalSessionID) - sessionNewScore = newScoresObject[originalSessionID].totalScore - opponentNewScore = newScoresObject[opponentID].totalScore - findNearestBetterSessionID sessionNewScore, opponentNewScore ,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 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!"} -findNearestBetterSessionID = (sessionTotalScore, opponentSessionTotalScore, opposingTeam, cb) -> + +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:Math.max(10,opponentSessionTotalScore) + $gt:opponentSessionTotalScore + 0.5 + _id: + $ne: opponentSessionID levelID: "project-dota" submitted: true submittedCode: @@ -162,7 +200,7 @@ findNearestBetterSessionID = (sessionTotalScore, opponentSessionTotalScore, oppo .select(selectString) .lean() - console.log "Finding session with score near #{sessionTotalScore}" + 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 @@ -235,6 +273,8 @@ updateSessionToSubmit = (sessionToUpdate, callback) -> meanStrength: 25 standardDeviation: 25/3 totalScore: 10 + numberOfWinsAndTies: 0 + numberOfLosses: 0 LevelSession.update {_id: sessionToUpdate._id}, sessionUpdateObject, callback fetchInitialSessionsToRankAgainst = (opposingTeam, callback) -> From 081274579b7ef4a636873fc8ca8c3624344c44a6 Mon Sep 17 00:00:00 2001 From: Nick Winter <livelily@gmail.com> Date: Wed, 26 Feb 2014 17:45:08 -0800 Subject: [PATCH 08/13] Forget old goals. --- app/lib/simulator/Simulator.coffee | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/app/lib/simulator/Simulator.coffee b/app/lib/simulator/Simulator.coffee index 723c0cab3..521e810c7 100644 --- a/app/lib/simulator/Simulator.coffee +++ b/app/lib/simulator/Simulator.coffee @@ -64,7 +64,7 @@ module.exports = class Simulator setupGoalManager: -> @god.goalManager = new GoalManager @world - @god.goalManager.goals = @fetchGoalsFromWorldNoteChain() + @god.goalManager.goals = @god.level.goals @god.goalManager.goalStates = @manuallyGenerateGoalStates() commenceSimulationAndSetupCallback: -> @@ -114,7 +114,7 @@ module.exports = class Simulator sessions: [] for session in @task.getSessions() - + sessionResult = sessionID: session.sessionID submitDate: session.submitDate @@ -142,8 +142,6 @@ module.exports = class Simulator else return 1 - fetchGoalsFromWorldNoteChain: -> return @god.goalManager.world.scripts[0].noteChain[0].goals.add - manuallyGenerateGoalStates: -> goalStates = "destroy-humans": @@ -195,7 +193,7 @@ module.exports = class Simulator spellKeyComponents[0] = _.string.slugify spellKeyComponents[0] spellKey = spellKeyComponents.join '/' spellKey - + createSpellAndAssignName: (spellKey, spellName) -> @spells[spellKey] ?= {} @@ -267,10 +265,10 @@ class SimulationTask fullSpellName = [thangName,spellName].join '/' if _.contains(teamSpells, fullSpellName) teamCode[fullSpellName]=spell - + _.merge spellKeyToSourceMap, teamCode commonSpells = session.teamSpells["common"] _.merge spellKeyToSourceMap, _.pick(session.code, commonSpells) if commonSpells? - + spellKeyToSourceMap From 5c1c17c8dd3bfb37de4cc61ef7f370b2c771a2cf Mon Sep 17 00:00:00 2001 From: Nick Winter <livelily@gmail.com> Date: Wed, 26 Feb 2014 17:52:08 -0800 Subject: [PATCH 09/13] Green Guide button for attention. --- app/templates/play/level/control_bar.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/play/level/control_bar.jade b/app/templates/play/level/control_bar.jade index 59d378bc8..0cdd24241 100644 --- a/app/templates/play/level/control_bar.jade +++ b/app/templates/play/level/control_bar.jade @@ -6,7 +6,7 @@ h4.home 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 button.btn.btn-xs.btn-inverse.banner#multiplayer-button(title="Leaderboard", data-i18n="play_level.leaderboard") Leaderboard From 48122000ed8e7961458dae5377ae8c067014daee Mon Sep 17 00:00:00 2001 From: Nick Winter <livelily@gmail.com> Date: Wed, 26 Feb 2014 18:09:09 -0800 Subject: [PATCH 10/13] Gold shows up as an int in the HUD now. --- app/lib/LevelBus.coffee | 1 - app/views/play/level/hud_view.coffee | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/lib/LevelBus.coffee b/app/lib/LevelBus.coffee index 287110f98..18985716b 100644 --- a/app/lib/LevelBus.coffee +++ b/app/lib/LevelBus.coffee @@ -113,7 +113,6 @@ module.exports = class LevelBus extends Bus @changedSessionProperties.teamSpells = true @session.set({'teamSpells': @teamSpellMap}) @saveSession() - console.log spellTeam, me.team, e.spell.spellKey if spellTeam is me.team @onSpellChanged e # Save the new spell to the session, too. diff --git a/app/views/play/level/hud_view.coffee b/app/views/play/level/hud_view.coffee index 09059d20b..cc62fb047 100644 --- a/app/views/play/level/hud_view.coffee +++ b/app/views/play/level/hud_view.coffee @@ -270,7 +270,7 @@ module.exports = class HUDView extends View if prop is "rotation" return (val * 180 / Math.PI).toFixed(0) + "˚" 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 -100 < val < 100 then return val.toFixed(1) return val.toFixed(0) From 7052b0600bc0519cf03deabb0c51661c78ff1b08 Mon Sep 17 00:00:00 2001 From: Scott Erickson <sderickson@gmail.com> Date: Wed, 26 Feb 2014 18:42:39 -0800 Subject: [PATCH 11/13] Made mouse dragging not interrupt selecting units so much. --- app/lib/surface/SpriteBoss.coffee | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/lib/surface/SpriteBoss.coffee b/app/lib/surface/SpriteBoss.coffee index b5adf175c..130d017b7 100644 --- a/app/lib/surface/SpriteBoss.coffee +++ b/app/lib/surface/SpriteBoss.coffee @@ -25,6 +25,7 @@ module.exports = class SpriteBoss extends CocoClass constructor: (@options) -> super() + @dragged = 0 @options ?= {} @camera = @options.camera @surfaceLayer = @options.surfaceLayer @@ -238,11 +239,12 @@ module.exports = class SpriteBoss extends CocoClass @selectThang e.thangID, e.spellName onCameraDragged: -> - @dragged = true + @dragged += 1 onSpriteMouseUp: (e) -> 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 @selectSprite e, sprite From c26995a3a9e3dda848dc208f5b6b1f1fb39c32d0 Mon Sep 17 00:00:00 2001 From: Nick Winter <livelily@gmail.com> Date: Wed, 26 Feb 2014 18:58:25 -0800 Subject: [PATCH 12/13] Home button on ladder level goes to ladder. --- app/templates/play/level/control_bar.jade | 2 +- app/views/play/level/control_bar_view.coffee | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/app/templates/play/level/control_bar.jade b/app/templates/play/level/control_bar.jade index 0cdd24241..1cc3af07d 100644 --- a/app/templates/play/level/control_bar.jade +++ b/app/templates/play/level/control_bar.jade @@ -1,6 +1,6 @@ h4.home - a(href="/") + a(href=homeLink || "/") i.icon-home.icon-white span(data-i18n="play_level.home") Home diff --git a/app/views/play/level/control_bar_view.coffee b/app/views/play/level/control_bar_view.coffee index 7c5b22d53..685452d81 100644 --- a/app/views/play/level/control_bar_view.coffee +++ b/app/views/play/level/control_bar_view.coffee @@ -47,12 +47,17 @@ module.exports = class ControlBarView extends View text += " (#{numPlayers})" if numPlayers > 1 $('#multiplayer-button', @$el).text(text) - getRenderData: (context={}) -> - super context - context.worldName = @worldName - context.multiplayerEnabled = @session.get('multiplayer') - context.ladderGame = @ladderGame - context + getRenderData: (c={}) -> + super c + c.worldName = @worldName + c.multiplayerEnabled = @session.get('multiplayer') + c.ladderGame = @ladderGame + 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: -> options = {docs: @level.get('documentation'), supermodel: @supermodel} From ec7028af6015138e72dc957b179a8b84e0ca27c5 Mon Sep 17 00:00:00 2001 From: Scott Erickson <sderickson@gmail.com> Date: Wed, 26 Feb 2014 19:30:37 -0800 Subject: [PATCH 13/13] Fixed uploading images for articles. --- app/treema-ext.coffee | 7 ++++--- app/views/editor/article/edit.coffee | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/treema-ext.coffee b/app/treema-ext.coffee index ec105749b..9112abaa6 100644 --- a/app/treema-ext.coffee +++ b/app/treema-ext.coffee @@ -38,12 +38,13 @@ class LiveEditingMarkup extends TreemaNode.nodeMap.ace url: InkBlob.url filename: InkBlob.filename mimetype: InkBlob.mimetype - description: '' - createdFor: [] + path: @settings.filePath + + @uploadingPath = [@settings.filePath, InkBlob.filename].join('/') $.ajax('/file', { type: 'POST', data: body, success: @onFileUploaded }) onFileUploaded: (e) => - @editor.insert "" + @editor.insert "" onEditorChange: => @saveChanges() diff --git a/app/views/editor/article/edit.coffee b/app/views/editor/article/edit.coffee index f462afd40..05df5291d 100644 --- a/app/views/editor/article/edit.coffee +++ b/app/views/editor/article/edit.coffee @@ -35,6 +35,7 @@ module.exports = class ArticleEditView extends View data = $.extend(true, {}, @article.attributes) options = data: data + filePath: "db/thang.type/#{@article.get('original')}" schema: Article.schema.attributes callbacks: change: @pushChangesToPreview