mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-28 18:15:52 -05:00
Merge pull request #511 from codecombat/master
Merge master into production
This commit is contained in:
commit
797b4b0e6d
12 changed files with 91 additions and 23 deletions
|
@ -497,13 +497,15 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
# seems to be a bug where only one object can register with the Ticker...
|
# seems to be a bug where only one object can register with the Ticker...
|
||||||
oldFrame = @currentFrame
|
oldFrame = @currentFrame
|
||||||
oldWorldFrame = Math.floor oldFrame
|
oldWorldFrame = Math.floor oldFrame
|
||||||
|
lastFrame = @world.totalFrames - 1
|
||||||
while true
|
while true
|
||||||
Dropper.tick()
|
Dropper.tick()
|
||||||
@trailmaster.tick() if @trailmaster
|
@trailmaster.tick() if @trailmaster
|
||||||
# Skip some frame updates unless we're playing and not at end (or we haven't drawn much yet)
|
# Skip some frame updates unless we're playing and not at end (or we haven't drawn much yet)
|
||||||
frameAdvanced = (@playing and @currentFrame < @world.totalFrames) or @totalFramesDrawn < 2
|
frameAdvanced = (@playing and @currentFrame < lastFrame) or @totalFramesDrawn < 2
|
||||||
@currentFrame += @world.frameRate / @options.frameRate if frameAdvanced and @playing
|
if frameAdvanced and @playing
|
||||||
@currentFrame = Math.min(@currentFrame, @world.totalFrames - 1)
|
@currentFrame += @world.frameRate / @options.frameRate
|
||||||
|
@currentFrame = Math.min @currentFrame, lastFrame
|
||||||
newWorldFrame = Math.floor @currentFrame
|
newWorldFrame = Math.floor @currentFrame
|
||||||
worldFrameAdvanced = newWorldFrame isnt oldWorldFrame
|
worldFrameAdvanced = newWorldFrame isnt oldWorldFrame
|
||||||
if worldFrameAdvanced
|
if worldFrameAdvanced
|
||||||
|
|
|
@ -179,6 +179,9 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
|
||||||
victory_sign_up: "Sign Up to Save Progress"
|
victory_sign_up: "Sign Up to Save Progress"
|
||||||
victory_sign_up_poke: "Want to save your code? Create a free account!"
|
victory_sign_up_poke: "Want to save your code? Create a free account!"
|
||||||
victory_rate_the_level: "Rate the level: "
|
victory_rate_the_level: "Rate the level: "
|
||||||
|
victory_rank_my_game: "Rank My Game"
|
||||||
|
victory_ranking_game: "Submitting..."
|
||||||
|
victory_return_to_ladder: "Return to Ladder"
|
||||||
victory_play_next_level: "Play Next Level"
|
victory_play_next_level: "Play Next Level"
|
||||||
victory_go_home: "Go Home"
|
victory_go_home: "Go Home"
|
||||||
victory_review: "Tell us more!"
|
victory_review: "Tell us more!"
|
||||||
|
|
|
@ -208,11 +208,11 @@
|
||||||
height: 19px
|
height: 19px
|
||||||
|
|
||||||
div
|
div
|
||||||
@include box-sizing(border-box)
|
border-radius: 1px
|
||||||
background-color: #6BA1C8
|
background-color: #6BA1C8
|
||||||
height: 100%
|
height: 100%
|
||||||
border-bottom: 2px groove #201B15
|
border-bottom: 2px groove darken(#6BA1C8, 30%)
|
||||||
border-right: 1px solid #201B15
|
border-right: 1px solid darken(#6BA1C8, 10%)
|
||||||
position: absolute
|
position: absolute
|
||||||
top: 0
|
top: 0
|
||||||
|
|
||||||
|
|
|
@ -11,11 +11,7 @@ div#columns.row
|
||||||
|
|
||||||
tr
|
tr
|
||||||
th(colspan=4, style="color: #{team.primaryColor}")
|
th(colspan=4, style="color: #{team.primaryColor}")
|
||||||
span Your
|
span Your #{team.name} Matches - #{team.wins} Wins, #{team.losses} Losses
|
||||||
span
|
|
||||||
span= team.name
|
|
||||||
span
|
|
||||||
span Matches
|
|
||||||
|
|
||||||
if team.session
|
if team.session
|
||||||
button.btn.btn-sm.btn-warning.pull-right.rank-button(data-session-id=team.session.id)
|
button.btn.btn-sm.btn-warning.pull-right.rank-button(data-session-id=team.session.id)
|
||||||
|
|
|
@ -14,8 +14,10 @@
|
||||||
div!= body
|
div!= body
|
||||||
|
|
||||||
.modal-footer
|
.modal-footer
|
||||||
if level.get('type') === 'ladder'
|
if readyToRank
|
||||||
a.btn.btn-primary(href="/play/ladder/#{level.get('slug')}#my-matches", data-dismiss="modal", data-i18n="play_level.victory_go_home") Go Home
|
button.btn.btn-success.rank-game-button(data-i18n="play_level.victory_rank_my_game") Rank My Game
|
||||||
|
else if level.get('type') === 'ladder'
|
||||||
|
a.btn.btn-primary(href="/play/ladder/#{level.get('slug')}#my-matches", data-dismiss="modal", data-i18n="play_level.victory_go_ladder") Return to Ladder
|
||||||
else if hasNextLevel
|
else if hasNextLevel
|
||||||
button.btn.btn-primary.next-level-button(data-dismiss="modal", data-i18n="play_level.victory_play_next_level") Play Next Level
|
button.btn.btn-primary.next-level-button(data-dismiss="modal", data-i18n="play_level.victory_play_next_level") Play Next Level
|
||||||
else
|
else
|
||||||
|
|
|
@ -73,6 +73,9 @@ module.exports = class MyMatchesTabView extends CocoView
|
||||||
team.matches = (convertMatch(match) for match in team.session?.get('matches') or [])
|
team.matches = (convertMatch(match) for match in team.session?.get('matches') or [])
|
||||||
team.matches.reverse()
|
team.matches.reverse()
|
||||||
team.score = (team.session?.get('totalScore') or 10).toFixed(2)
|
team.score = (team.session?.get('totalScore') or 10).toFixed(2)
|
||||||
|
team.wins = _.filter(team.matches, {state: 'win'}).length
|
||||||
|
team.ties = _.filter(team.matches, {state: 'tie'}).length
|
||||||
|
team.losses = _.filter(team.matches, {state: 'loss'}).length
|
||||||
|
|
||||||
ctx
|
ctx
|
||||||
|
|
||||||
|
@ -91,7 +94,6 @@ module.exports = class MyMatchesTabView extends CocoView
|
||||||
c1 and not _.isEqual(c1, c2)
|
c1 and not _.isEqual(c1, c2)
|
||||||
|
|
||||||
rankSession: (e) ->
|
rankSession: (e) ->
|
||||||
console.log "Clicked"
|
|
||||||
button = $(e.target).closest('.rank-button')
|
button = $(e.target).closest('.rank-button')
|
||||||
sessionID = button.data('session-id')
|
sessionID = button.data('session-id')
|
||||||
session = _.find @sessions.models, { id: sessionID }
|
session = _.find @sessions.models, { id: sessionID }
|
||||||
|
|
|
@ -135,7 +135,7 @@ module.exports = class HUDView extends View
|
||||||
props = @$el.find('.thang-props')
|
props = @$el.find('.thang-props')
|
||||||
props.find(":not(.thang-name)").remove()
|
props.find(":not(.thang-name)").remove()
|
||||||
props.find('.thang-name').text(if @thang.type then "#{@thang.id} - #{@thang.type}" else @thang.id)
|
props.find('.thang-name').text(if @thang.type then "#{@thang.id} - #{@thang.type}" else @thang.id)
|
||||||
propNames = @thang.hudProperties ? []
|
propNames = _.without @thang.hudProperties ? [], 'action'
|
||||||
nColumns = Math.ceil propNames.length / 5
|
nColumns = Math.ceil propNames.length / 5
|
||||||
columns = ($('<div class="thang-props-column"></div>').appendTo(props) for i in [0 ... nColumns])
|
columns = ($('<div class="thang-props-column"></div>').appendTo(props) for i in [0 ... nColumns])
|
||||||
for prop, i in propNames
|
for prop, i in propNames
|
||||||
|
@ -316,11 +316,11 @@ module.exports = class HUDView extends View
|
||||||
@timespans = {}
|
@timespans = {}
|
||||||
dt = @thang.world.dt
|
dt = @thang.world.dt
|
||||||
actionHistory = @thang.world.actionsForThang @thang.id, true
|
actionHistory = @thang.world.actionsForThang @thang.id, true
|
||||||
[lastFrame, lastAction] = [0, 'idle']
|
[lastFrame, lastAction] = [0, null]
|
||||||
for hist in actionHistory.concat {frame: @thang.world.totalFrames, name: 'END'}
|
for hist in actionHistory.concat {frame: @thang.world.totalFrames, name: 'END'}
|
||||||
[newFrame, newAction] = [hist.frame, hist.name]
|
[newFrame, newAction] = [hist.frame, hist.name]
|
||||||
continue if newAction is lastAction
|
continue if newAction is lastAction
|
||||||
if newFrame > lastFrame
|
if newFrame > lastFrame and lastAction
|
||||||
# TODO: don't push it if it didn't exist until then
|
# TODO: don't push it if it didn't exist until then
|
||||||
(@timespans[lastAction] ?= []).push [lastFrame * dt, newFrame * dt]
|
(@timespans[lastAction] ?= []).push [lastFrame * dt, newFrame * dt]
|
||||||
[lastFrame, lastAction] = [newFrame, newAction]
|
[lastFrame, lastAction] = [newFrame, newAction]
|
||||||
|
|
|
@ -11,6 +11,7 @@ module.exports = class VictoryModal extends View
|
||||||
|
|
||||||
events:
|
events:
|
||||||
'click .next-level-button': 'onPlayNextLevel'
|
'click .next-level-button': 'onPlayNextLevel'
|
||||||
|
'click .rank-game-button': 'onRankGame'
|
||||||
|
|
||||||
# review events
|
# review events
|
||||||
'mouseover .rating i': (e) -> @showStars(@starNum($(e.target)))
|
'mouseover .rating i': (e) -> @showStars(@starNum($(e.target)))
|
||||||
|
@ -58,6 +59,21 @@ module.exports = class VictoryModal extends View
|
||||||
@saveReview() if @$el.find('.review textarea').val()
|
@saveReview() if @$el.find('.review textarea').val()
|
||||||
Backbone.Mediator.publish('play-next-level')
|
Backbone.Mediator.publish('play-next-level')
|
||||||
|
|
||||||
|
onRankGame: (e) ->
|
||||||
|
button = @$el.find('.rank-game-button')
|
||||||
|
button.text($.i18n.t('play_level.victory_ranking_game', defaultValue: 'Submitting...'))
|
||||||
|
button.prop 'disabled', true
|
||||||
|
ajaxData = session: @session.id, levelID: @level.id, originalLevelID: @level.get('original'), levelMajorVersion: @level.get('version').major
|
||||||
|
ladderURL = "/play/ladder/#{@level.get('slug')}#my-matches"
|
||||||
|
goToLadder = -> Backbone.Mediator.publish 'router:navigate', route: ladderURL
|
||||||
|
$.ajax '/queue/scoring',
|
||||||
|
type: 'POST'
|
||||||
|
data: ajaxData
|
||||||
|
success: goToLadder
|
||||||
|
failure: (response) ->
|
||||||
|
console.error "Couldn't submit game for ranking:", response
|
||||||
|
goToLadder()
|
||||||
|
|
||||||
getRenderData: ->
|
getRenderData: ->
|
||||||
c = super()
|
c = super()
|
||||||
c.body = @body
|
c.body = @body
|
||||||
|
@ -65,6 +81,10 @@ module.exports = class VictoryModal extends View
|
||||||
c.hasNextLevel = _.isObject(@level.get('nextLevel')) and (@level.get('name') isnt "Mobile Artillery")
|
c.hasNextLevel = _.isObject(@level.get('nextLevel')) and (@level.get('name') isnt "Mobile Artillery")
|
||||||
c.levelName = @level.get('i18n')?[me.lang()]?.name ? @level.get('name')
|
c.levelName = @level.get('i18n')?[me.lang()]?.name ? @level.get('name')
|
||||||
c.level = @level
|
c.level = @level
|
||||||
|
if c.level.get('type') is 'ladder'
|
||||||
|
c1 = @session?.get('code')
|
||||||
|
c2 = @session?.get('submittedCode')
|
||||||
|
c.readyToRank = @session.get('levelID') and c1 and not _.isEqual(c1, c2)
|
||||||
if me.get 'hourOfCode'
|
if me.get 'hourOfCode'
|
||||||
# Show the Hour of Code "I'm Done" tracking pixel after they played for 30 minutes
|
# Show the Hour of Code "I'm Done" tracking pixel after they played for 30 minutes
|
||||||
elapsed = (new Date() - new Date(me.get('dateCreated')))
|
elapsed = (new Date() - new Date(me.get('dateCreated')))
|
||||||
|
|
|
@ -89,15 +89,27 @@ LevelHandler = class LevelHandler extends Handler
|
||||||
# associated with the handler, because the handler might return a different type
|
# associated with the handler, because the handler might return a different type
|
||||||
# of model, like in this case. Refactor to move that logic to the model instead.
|
# of model, like in this case. Refactor to move that logic to the model instead.
|
||||||
|
|
||||||
getMySessions: (req, res, id) ->
|
getMySessions: (req, res, slugOrID) ->
|
||||||
@fetchLevelByIDAndHandleErrors id, req, res, (err, level) =>
|
findParameters = {}
|
||||||
|
if Handler.isID slugOrID
|
||||||
|
findParameters["_id"] = slugOrID
|
||||||
|
else
|
||||||
|
findParameters["slug"] = slugOrID
|
||||||
|
selectString = 'original version.major permissions'
|
||||||
|
query = Level.findOne(findParameters)
|
||||||
|
.select(selectString)
|
||||||
|
.lean()
|
||||||
|
|
||||||
|
query.exec (err, level) =>
|
||||||
|
return @sendDatabaseError(res, err) if err
|
||||||
|
return @sendNotFoundError(res) unless level?
|
||||||
sessionQuery =
|
sessionQuery =
|
||||||
level:
|
level:
|
||||||
original: level.original.toString()
|
original: level.original.toString()
|
||||||
majorVersion: level.version.major
|
majorVersion: level.version.major
|
||||||
creator: req.user._id+''
|
creator: req.user._id+''
|
||||||
|
|
||||||
query = Session.find(sessionQuery)
|
query = Session.find(sessionQuery).select('-screenshot')
|
||||||
query.exec (err, results) =>
|
query.exec (err, results) =>
|
||||||
if err then @sendDatabaseError(res, err) else @sendSuccess res, results
|
if err then @sendDatabaseError(res, err) else @sendSuccess res, results
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,18 @@ _.extend LevelSessionSchema.properties,
|
||||||
numberOfLosses:
|
numberOfLosses:
|
||||||
type: 'number'
|
type: 'number'
|
||||||
default: 0
|
default: 0
|
||||||
|
|
||||||
|
scoreHistory:
|
||||||
|
type: 'array'
|
||||||
|
title: 'Score History'
|
||||||
|
description: 'A list of objects representing the score history of a session'
|
||||||
|
items:
|
||||||
|
title: 'Score History Point'
|
||||||
|
description: 'An array with the format [unix timestamp, totalScore]'
|
||||||
|
type: 'array'
|
||||||
|
items:
|
||||||
|
type: 'number'
|
||||||
|
|
||||||
|
|
||||||
matches:
|
matches:
|
||||||
type: 'array'
|
type: 'array'
|
||||||
|
|
|
@ -443,10 +443,15 @@ updateScoreInSession = (scoreObject,callback) ->
|
||||||
if err? then return callback err, null
|
if err? then return callback err, null
|
||||||
|
|
||||||
session = session.toObject()
|
session = session.toObject()
|
||||||
|
newTotalScore = scoreObject.meanStrength - 1.8 * scoreObject.standardDeviation
|
||||||
|
scoreHistoryAddition = [Date.now(), newTotalScore]
|
||||||
updateObject =
|
updateObject =
|
||||||
meanStrength: scoreObject.meanStrength
|
meanStrength: scoreObject.meanStrength
|
||||||
standardDeviation: scoreObject.standardDeviation
|
standardDeviation: scoreObject.standardDeviation
|
||||||
totalScore: scoreObject.meanStrength - 1.8 * scoreObject.standardDeviation
|
totalScore: newTotalScore
|
||||||
|
$push:
|
||||||
|
scoreHistory: scoreHistoryAddition
|
||||||
|
|
||||||
LevelSession.update {"_id": scoreObject.id}, updateObject, callback
|
LevelSession.update {"_id": scoreObject.id}, updateObject, callback
|
||||||
log.info "New total score for session #{scoreObject.id} is #{updateObject.totalScore}"
|
log.info "New total score for session #{scoreObject.id} is #{updateObject.totalScore}"
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ errors = require '../commons/errors'
|
||||||
#request = require 'request'
|
#request = require 'request'
|
||||||
config = require '../../server_config'
|
config = require '../../server_config'
|
||||||
LevelSession = require '../levels/sessions/LevelSession.coffee'
|
LevelSession = require '../levels/sessions/LevelSession.coffee'
|
||||||
|
Level = require '../levels/Level.coffee'
|
||||||
log = require 'winston'
|
log = require 'winston'
|
||||||
sendwithus = require '../sendwithus'
|
sendwithus = require '../sendwithus'
|
||||||
|
|
||||||
|
@ -16,9 +17,23 @@ module.exports.setup = (app) ->
|
||||||
app.all config.mail.mailchimpWebhook, handleMailchimpWebHook
|
app.all config.mail.mailchimpWebhook, handleMailchimpWebHook
|
||||||
app.get '/mail/cron/ladder-update', handleLadderUpdate
|
app.get '/mail/cron/ladder-update', handleLadderUpdate
|
||||||
|
|
||||||
|
getAllLadderScores = (next) ->
|
||||||
|
query = Level.find({type: 'ladder'})
|
||||||
|
.select('levelID')
|
||||||
|
.lean()
|
||||||
|
query.exec (err, levels) ->
|
||||||
|
if err
|
||||||
|
log.error "Couldn't fetch ladder levels. Error: ", err
|
||||||
|
return next []
|
||||||
|
for level in levels
|
||||||
|
for team in ['humans', 'ogres']
|
||||||
|
'I ... am not doing this.'
|
||||||
|
|
||||||
handleLadderUpdate = (req, res) ->
|
handleLadderUpdate = (req, res) ->
|
||||||
|
log.info("Going to see about sending ladder update emails.")
|
||||||
res.send('Great work, Captain Cron! I can take it from here.')
|
res.send('Great work, Captain Cron! I can take it from here.')
|
||||||
res.end()
|
res.end()
|
||||||
|
# TODO: somehow fetch the histograms
|
||||||
emailDays = [1, 2, 4, 7, 30]
|
emailDays = [1, 2, 4, 7, 30]
|
||||||
now = new Date()
|
now = new Date()
|
||||||
getTimeFromDaysAgo = (daysAgo) ->
|
getTimeFromDaysAgo = (daysAgo) ->
|
||||||
|
@ -35,7 +50,6 @@ handleLadderUpdate = (req, res) ->
|
||||||
query = LevelSession.find(findParameters)
|
query = LevelSession.find(findParameters)
|
||||||
.select(selectString)
|
.select(selectString)
|
||||||
.lean()
|
.lean()
|
||||||
mongoose = require 'mongoose'
|
|
||||||
do (daysAgo) ->
|
do (daysAgo) ->
|
||||||
query.exec (err, results) ->
|
query.exec (err, results) ->
|
||||||
if err
|
if err
|
||||||
|
|
Loading…
Reference in a new issue