mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-28 01:55:38 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
3c7a022da0
10 changed files with 67 additions and 18 deletions
|
@ -37,14 +37,14 @@ module.exports.createUserWithoutReload = (userObject, failure=backboneFailure) -
|
|||
Backbone.Mediator.publish('created-user-without-reload')
|
||||
})
|
||||
|
||||
module.exports.loginUser = (userObject, failure=genericFailure) ->
|
||||
module.exports.loginUser = (userObject, failure=genericFailure, nextURL=null) ->
|
||||
console.log 'logging in as', userObject.email
|
||||
jqxhr = $.post('/auth/login',
|
||||
{
|
||||
username: userObject.email,
|
||||
password: userObject.password
|
||||
},
|
||||
(model) -> window.location.reload()
|
||||
(model) -> if nextURL then window.location.href = nextURL else window.location.reload()
|
||||
)
|
||||
jqxhr.fail(failure)
|
||||
|
||||
|
|
|
@ -96,8 +96,16 @@ class SoundFileTreema extends TreemaNode.nodeMap.string
|
|||
|
||||
buildValueForDisplay: (valEl, data) ->
|
||||
mimetype = "audio/#{@keyForParent}"
|
||||
mimetypes = [mimetype]
|
||||
if mimetype is 'audio/mp3'
|
||||
# https://github.com/codecombat/codecombat/issues/445
|
||||
# http://stackoverflow.com/questions/10688588/which-mime-type-should-i-use-for-mp3
|
||||
mimetypes.push 'audio/mpeg'
|
||||
else if mimetype is 'audio/ogg'
|
||||
mimetypes.push 'application/ogg'
|
||||
mimetypes.push 'video/ogg' # huh, that's what it took to be able to upload ogg sounds in Firefox
|
||||
pickButton = $('<a class="btn btn-primary btn-xs"><span class="glyphicon glyphicon-upload"></span></a>')
|
||||
.click(=> filepicker.pick {mimetypes:[mimetype]}, @onFileChosen)
|
||||
.click(=> filepicker.pick {mimetypes: mimetypes}, @onFileChosen)
|
||||
playButton = $('<a class="btn btn-primary btn-xs"><span class="glyphicon glyphicon-play"></span></a>')
|
||||
.click(@playFile)
|
||||
stopButton = $('<a class="btn btn-primary btn-xs"><span class="glyphicon glyphicon-stop"></span></a>')
|
||||
|
@ -116,7 +124,7 @@ class SoundFileTreema extends TreemaNode.nodeMap.string
|
|||
menu = $('<div class="dropdown-menu"></div>')
|
||||
files = @getFiles()
|
||||
for file in files
|
||||
continue unless file.get('contentType') is mimetype
|
||||
continue unless file.get('contentType') in mimetypes
|
||||
path = file.get('metadata').path
|
||||
filename = file.get 'filename'
|
||||
fullPath = [path, filename].join('/')
|
||||
|
|
|
@ -5,9 +5,23 @@ GoalManager = require 'lib/world/GoalManager'
|
|||
God = require 'lib/God'
|
||||
{createAetherOptions} = require 'lib/aether_utils'
|
||||
|
||||
SIMULATOR_VERSION = 1
|
||||
|
||||
simulatorInfo = {}
|
||||
if $.browser
|
||||
simulatorInfo['desktop'] = $.browser.desktop if $.browser.desktop
|
||||
simulatorInfo['name'] = $.browser.name if $.browser.name
|
||||
simulatorInfo['platform'] = $.browser.platform if $.browser.platform
|
||||
simulatorInfo['version'] = $.browser.versionNumber if $.browser.versionNumber
|
||||
|
||||
module.exports = class Simulator extends CocoClass
|
||||
constructor: (@options) ->
|
||||
@options ?= {}
|
||||
simulatorType = if @options.headlessClient then 'headless' else 'browser'
|
||||
@simulator =
|
||||
type: simulatorType
|
||||
version: SIMULATOR_VERSION
|
||||
info: simulatorInfo
|
||||
_.extend @, Backbone.Events
|
||||
@trigger 'statusUpdate', 'Starting simulation!'
|
||||
@retryDelayInSeconds = 2
|
||||
|
@ -28,10 +42,17 @@ module.exports = class Simulator extends CocoClass
|
|||
type: 'POST'
|
||||
parse: true
|
||||
data:
|
||||
'humansGameID': humanGameID
|
||||
'ogresGameID': ogresGameID
|
||||
humansGameID: humanGameID
|
||||
ogresGameID: ogresGameID
|
||||
simulator: @simulator
|
||||
error: (errorData) ->
|
||||
console.warn "There was an error fetching two games! #{JSON.stringify errorData}"
|
||||
if errorData?.responseText?.indexOf("Old simulator") isnt -1
|
||||
noty {
|
||||
text: errorData.responseText
|
||||
layout: 'center'
|
||||
type: 'error'
|
||||
}
|
||||
success: (taskData) =>
|
||||
return if @destroyed
|
||||
unless taskData
|
||||
|
@ -278,7 +299,6 @@ 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
|
||||
@simulatedByYou++
|
||||
unless @options.headlessClient
|
||||
simulatedBy = parseInt($('#simulated-by-you').text(), 10) + 1
|
||||
|
@ -307,6 +327,7 @@ module.exports = class Simulator extends CocoClass
|
|||
originalSessionRank: -1
|
||||
calculationTime: 500
|
||||
sessions: []
|
||||
simulator: @simulator
|
||||
|
||||
for session in @task.getSessions()
|
||||
sessionResult =
|
||||
|
|
|
@ -285,6 +285,7 @@ _.extend LevelSessionSchema.properties,
|
|||
codeLanguage:
|
||||
type: ['string', 'null'] # 'null' in case an opponent session got corrupted, don't care much here
|
||||
description: 'What submittedCodeLanguage the opponent used during the match'
|
||||
simulator: {type: 'object', description: 'Holds info on who simulated the match, and with what tools.'}
|
||||
|
||||
c.extendBasicProperties LevelSessionSchema, 'level.session'
|
||||
c.extendPermissionsProperties LevelSessionSchema, 'level.session'
|
||||
|
|
|
@ -31,7 +31,7 @@ div#columns.row
|
|||
th(data-i18n="general.when") When
|
||||
th
|
||||
for match in team.matches
|
||||
tr(class=(match.stale ? "stale " : "") + (match.fresh ? "fresh " : "") + match.state)
|
||||
tr(class=(match.stale ? "stale " : "") + (match.fresh ? "fresh " : "") + match.state, title=match.simulator)
|
||||
td.state-cell
|
||||
if match.state === 'win'
|
||||
span(data-i18n="general.win").win Win
|
||||
|
|
|
@ -73,7 +73,7 @@ module.exports = class AuthModal extends ModalView
|
|||
res = tv4.validateMultiple userObject, User.schema
|
||||
return forms.applyErrorsToForm(@$el, res.errors) unless res.valid
|
||||
@enableModalInProgress(@$el) # TODO: part of forms
|
||||
loginUser(userObject)
|
||||
loginUser userObject, null, window.nextURL
|
||||
|
||||
createAccount: ->
|
||||
forms.clearFormAlerts(@$el)
|
||||
|
|
|
@ -118,6 +118,7 @@ module.exports = class ScriptsTabView extends CocoView
|
|||
treema.enableTracking()
|
||||
|
||||
onScriptChanged: =>
|
||||
return unless @selectedScriptPath
|
||||
@scriptsTreema.set(@selectedScriptPath, @scriptTreema.data)
|
||||
|
||||
onThangsEdited: (e) ->
|
||||
|
|
|
@ -72,6 +72,7 @@ module.exports = class MyMatchesTabView extends CocoView
|
|||
stale: match.date < submitDate
|
||||
fresh: fresh
|
||||
codeLanguage: match.codeLanguage
|
||||
simulator: JSON.stringify(match.simulator)
|
||||
}
|
||||
|
||||
for team in @teams
|
||||
|
|
|
@ -15,6 +15,8 @@ bayes = new (require 'bayesian-battle')()
|
|||
scoringTaskQueue = undefined
|
||||
scoringTaskTimeoutInSeconds = 600
|
||||
|
||||
SIMULATOR_VERSION = 1
|
||||
|
||||
module.exports.setup = (app) -> connectToScoringQueue()
|
||||
|
||||
connectToScoringQueue = ->
|
||||
|
@ -124,6 +126,7 @@ module.exports.getTwoGames = (req, res) ->
|
|||
#if userIsAnonymous req then return errors.unauthorized(res, 'You need to be logged in to get games.')
|
||||
humansGameID = req.body.humansGameID
|
||||
ogresGameID = req.body.ogresGameID
|
||||
return if simulatorIsTooOld req, res
|
||||
#ladderGameIDs = ['greed', 'criss-cross', 'brawlwood', 'dungeon-arena', 'gold-rush', 'sky-span'] # Let's not give any extra simulations to old ladders.
|
||||
ladderGameIDs = ['dueling-grounds', 'cavern-survival', 'multiplayer-treasure-grove']
|
||||
levelID = _.sample ladderGameIDs
|
||||
|
@ -224,6 +227,8 @@ module.exports.getTwoGames = (req, res) ->
|
|||
module.exports.recordTwoGames = (req, res) ->
|
||||
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
|
||||
return if simulatorIsTooOld req, res
|
||||
req.body?.simulator?.user = '' + req.user?._id
|
||||
|
||||
yetiGuru = clientResponseObject: req.body, isRandomMatch: true
|
||||
async.waterfall [
|
||||
|
@ -442,7 +447,9 @@ getSessionInformation = (sessionIDString, callback) ->
|
|||
callback null, session
|
||||
|
||||
module.exports.processTaskResult = (req, res) ->
|
||||
return if simulatorIsTooOld req, res
|
||||
originalSessionID = req.body?.originalSessionID
|
||||
req.body?.simulator?.user = '' + req.user?._id
|
||||
yetiGuru = {}
|
||||
try
|
||||
async.waterfall [
|
||||
|
@ -578,14 +585,14 @@ addMatchToSessions = (newScoreObject, callback) ->
|
|||
matchObject.opponents = {}
|
||||
for session in @clientResponseObject.sessions
|
||||
sessionID = session.sessionID
|
||||
matchObject.opponents[sessionID] = {}
|
||||
matchObject.opponents[sessionID].sessionID = sessionID
|
||||
matchObject.opponents[sessionID].userID = session.creator
|
||||
matchObject.opponents[sessionID].name = session.name
|
||||
matchObject.opponents[sessionID].totalScore = session.totalScore
|
||||
matchObject.opponents[sessionID].metrics = {}
|
||||
matchObject.opponents[sessionID].metrics.rank = Number(newScoreObject[sessionID]?.gameRanking ? 0)
|
||||
matchObject.opponents[sessionID].codeLanguage = newScoreObject[sessionID].submittedCodeLanguage
|
||||
matchObject.opponents[sessionID] = match = {}
|
||||
match.sessionID = sessionID
|
||||
match.userID = session.creator
|
||||
match.name = session.name
|
||||
match.totalScore = session.totalScore
|
||||
match.metrics = {}
|
||||
match.metrics.rank = Number(newScoreObject[sessionID]?.gameRanking ? 0)
|
||||
match.codeLanguage = newScoreObject[sessionID].submittedCodeLanguage
|
||||
|
||||
#log.info "Match object computed, result: #{matchObject}"
|
||||
#log.info 'Writing match object to database...'
|
||||
|
@ -603,6 +610,7 @@ updateMatchesInSession = (matchObject, sessionID, callback) ->
|
|||
opponentsArray = _.toArray opponentsClone
|
||||
currentMatchObject.opponents = opponentsArray
|
||||
currentMatchObject.codeLanguage = matchObject.opponents[opponentsArray[0].sessionID].codeLanguage
|
||||
currentMatchObject.simulator = @clientResponseObject.simulator
|
||||
LevelSession.findOne {'_id': sessionID}, (err, session) ->
|
||||
session = session.toObject()
|
||||
currentMatchObject.playtime = session.playtime ? 0
|
||||
|
@ -785,3 +793,12 @@ retrieveOldSessionData = (sessionID, callback) ->
|
|||
markSessionAsDoneRanking = (sessionID, cb) ->
|
||||
#console.log 'Marking session as done ranking...'
|
||||
LevelSession.update {'_id': sessionID}, {'isRanking': false}, cb
|
||||
|
||||
simulatorIsTooOld = (req, res) ->
|
||||
clientSimulator = req.body.simulator
|
||||
return false if clientSimulator?.version >= SIMULATOR_VERSION
|
||||
message = "Old simulator version #{clientSimulator?.version}, need to clear cache and get version #{SIMULATOR_VERSION}."
|
||||
log.debug "400: #{message}"
|
||||
res.send 400, message
|
||||
res.end()
|
||||
true
|
||||
|
|
|
@ -50,7 +50,7 @@ setupErrorMiddleware = (app) ->
|
|||
res.status(err.status ? 500).send(error: "Something went wrong!")
|
||||
message = "Express error: #{req.method} #{req.path}: #{err.message}"
|
||||
log.error "#{message}, stack: #{err.stack}"
|
||||
hipchat.sendTowerHipChatMessage(message)
|
||||
hipchat.sendHipChatMessage(message, ['tower'], {papertrail: true})
|
||||
else
|
||||
next(err)
|
||||
setupExpressMiddleware = (app) ->
|
||||
|
|
Loading…
Reference in a new issue