Conflicts:
	server/queues/scoring.coffee
This commit is contained in:
Michael Schmatz 2014-05-19 19:04:47 -07:00
commit aba0120e88
34 changed files with 923 additions and 214 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -135,6 +135,7 @@ module.exports = class LevelLoader extends CocoClass
onWorldNecessitiesLoaded: =>
@initWorld()
@supermodel.clearMaxProgress()
@trigger 'world-necessities-loaded'
return if @headless and not @editorMode
thangsToLoad = _.uniq( (t.spriteName for t in @world.thangs when t.exists) )
nameModelTuples = ([thangType.get('name'), thangType] for thangType in @thangNames.models)

View file

@ -37,12 +37,16 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
possessed: false
flipped: false
flippedCount: 0
originalScaleX: null
originalScaleY: null
actionQueue: null
actions: null
rotation: 0
# Scale numbers
baseScaleX: 1 # scale + flip (for current action) / resolutionFactor.
baseScaleY: 1 # These numbers rarely change, so keep them around.
scaleFactor: 1 # Current scale adjustment. This can change rapidly.
targetScaleFactor: 1 # What the scaleFactor is going toward during a tween.
# ACTION STATE
# Actions have relations. If you say 'move', 'move_side' may play because of a direction
# relationship, and if you say 'cast', 'cast_begin' may happen first, or 'cast_end' after.
@ -71,7 +75,6 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
@ranges = []
@handledDisplayEvents = {}
@age = 0
@scaleFactor = @targetScaleFactor = 1
if @thangType.isFullyLoaded()
@setupSprite()
else
@ -94,6 +97,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
finishSetup: ->
return unless @thang
@updateBaseScale()
@update true # Reflect initial scale and other state
setUpRasterImage: ->
@ -102,8 +106,6 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
@setImageObject image
$(image.image).one 'load', => @updateScale?()
@configureMouse()
@originalScaleX = image.scaleX
@originalScaleY = image.scaleY
@imageObject.sprite = @
@imageObject.layerPriority = @thangType.get 'layerPriority'
@imageObject.name = @thang?.spriteName or @thangType.get 'name'
@ -112,14 +114,6 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
@imageObject.regY = -reg.y
@finishSetup()
destroy: ->
mark.destroy() for name, mark of @marks
label.destroy() for name, label of @labels
p.removeChild @healthBar if p = @healthBar?.parent
@imageObject?.off 'animationend', @playNextAction
clearInterval @effectInterval if @effectInterval
super()
toString: -> "<CocoSprite: #{@thang?.id}>"
buildSpriteSheet: ->
@ -139,17 +133,11 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
sprite = new createjs.Sprite(spriteSheet)
else
sprite = new createjs.Shape()
sprite.scaleX = sprite.scaleY = 1 / @options.resolutionFactor
# temp, until these are re-exported with perspective
if @options.camera and @thangType.get('name') in ['Dungeon Floor', 'Indoor Floor', 'Grass', 'Goal Trigger', 'Obstacle']
sprite.scaleY *= @options.camera.y2x
@setImageObject sprite
@addHealthBar()
@configureMouse()
# TODO: generalize this later?
@originalScaleX = sprite.scaleX
@originalScaleY = sprite.scaleY
@imageObject.sprite = @
@imageObject.layerPriority = @thangType.get 'layerPriority'
@imageObject.name = @thang?.spriteName or @thangType.get 'name'
@ -183,6 +171,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
@currentAction = action
return @hide() unless action.animation or action.container or action.relatedActions
@show()
@updateBaseScale()
return @updateActionDirection() unless action.animation or action.container
m = if action.container then "gotoAndStop" else "gotoAndPlay"
@imageObject.framerate = action.framerate or 20
@ -307,6 +296,18 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
[@imageObject.x, @imageObject.y] = [sup.x, sup.y]
@lastPos = p1.copy?() or _.clone(p1)
@hasMoved = true
updateBaseScale: ->
scale = 1
scale = @thangType.get('scale') or 1 if @isRaster
scale /= @options.resolutionFactor unless @isRaster
@baseScaleX = @baseScaleY = scale
@baseScaleX *= -1 if @getActionProp 'flipX'
@baseScaleY *= -1 if @getActionProp 'flipY'
# temp, until these are re-exported with perspective
floors = ['Dungeon Floor', 'Indoor Floor', 'Grass', 'Goal Trigger', 'Obstacle']
if @options.camera and @thangType.get('name') in floors
@baseScaleY *= @options.camera.y2x
updateScale: ->
return unless @imageObject
@ -326,8 +327,9 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
@imageObject.scaleY *= @thangType.get('scale') ? 1
[@lastThangWidth, @lastThangHeight] = [@thang.width, @thang.height]
return
scaleX = if @getActionProp 'flipX' then -1 else 1
scaleY = if @getActionProp 'flipY' then -1 else 1
scaleX = scaleY = 1
if @thangType.get('name') in ['Arrow', 'Spear']
# Scales the arrow so it appears longer when flying parallel to horizon.
# To do that, we convert angle to [0, 90] (mirroring half-planes twice), then make linear function out of it:
@ -342,18 +344,12 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
angle = 180 - angle if angle > 90
scaleX = 0.5 + 0.5 * (90 - angle) / 90
if @isRaster # scale is worked into building the sprite sheet for animations
scale = @thangType.get('scale') or 1
scaleX *= scale
scaleY *= scale
# console.error "No thang for", @ unless @thang
# TODO: support using scaleFactorX/Y from the thang object
@imageObject.scaleX = @baseScaleX * @scaleFactor * scaleX
@imageObject.scaleY = @baseScaleY * @scaleFactor * scaleY
console.error "No thang for", @ unless @thang
scaleFactorX = @thang.scaleFactorX ? @scaleFactor
scaleFactorY = @thang.scaleFactorY ? @scaleFactor
@imageObject.scaleX = @originalScaleX * scaleX * scaleFactorX
@imageObject.scaleY = @originalScaleY * scaleY * scaleFactorY
if (@thang.scaleFactor or 1) isnt @targetScaleFactor
if @thang and (@thang.scaleFactor or 1) isnt @targetScaleFactor
createjs.Tween.removeTweens(@)
createjs.Tween.get(@).to({scaleFactor:@thang.scaleFactor or 1}, 2000, createjs.Ease.elasticOut)
@targetScaleFactor = @thang.scaleFactor or 1
@ -783,3 +779,11 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
return unless @healthBar
@healthBar.x = @imageObject.x
@healthBar.y = @imageObject.y
destroy: ->
mark.destroy() for name, mark of @marks
label.destroy() for name, label of @labels
p.removeChild @healthBar if p = @healthBar?.parent
@imageObject?.off 'animationend', @playNextAction
clearInterval @effectInterval if @effectInterval
super()

View file

@ -201,7 +201,8 @@ module.exports = class Mark extends CocoClass
Backbone.Mediator.publish 'sprite:loaded'
update: (pos=null) ->
return false unless @on and @mark and @sprite?.thangType.isFullyLoaded()
return false unless @on and @mark
return false if @sprite? and not @sprite.thangType.isFullyLoaded()
@mark.visible = not @hidden
@updatePosition pos
@updateRotation()
@ -250,10 +251,12 @@ module.exports = class Mark extends CocoClass
scale = size / {selection: 128, target: 128, repair: 320, highlight: 160}[@name]
if @sprite?.thang.spriteName.search(/(dungeon|indoor).wall/i) isnt -1
scale *= 2
@mark.scaleX = @mark.scaleY = Math.min 1, scale
if @markSprite?
@mark.scaleX *= @markSprite.originalScaleX
@mark.scaleY *= @markSprite.originalScaleY
@markSprite.scaleFactor = scale
@markSprite.updateScale()
else
@mark.scaleX = @mark.scaleY = Math.min 1, scale
if @name in ['selection', 'target', 'repair']
@mark.scaleY *= @camera.y2x # code applies perspective

View file

@ -104,7 +104,11 @@ module.exports = class GoalManager extends CocoClass
notifyGoalChanges: ->
overallStatus = @checkOverallStatus()
event = {goalStates: @goalStates, goals: @goals, overallStatus: overallStatus}
event =
goalStates: @goalStates
goals: @goals
overallStatus: overallStatus
timedOut: @world.totalFrames is @world.maxTotalFrames
Backbone.Mediator.publish('goal-manager:new-goal-states', event)
checkOverallStatus: (ignoreIncomplete=false) ->

View file

@ -222,6 +222,10 @@
multiplayer: "Multiplayer"
restart: "Restart"
goals: "Goals"
success: "Success!"
incomplete: "Incomplete"
timed_out: "Ran out of time"
failing: "Failing"
action_timeline: "Action Timeline"
click_to_select: "Click on a unit to select it."
reload_title: "Reload All Code?"
@ -656,6 +660,7 @@
rank_submitted: "Submitted for Ranking"
rank_failed: "Failed to Rank"
rank_being_ranked: "Game Being Ranked"
help_simulate: "Help simulate games?"
code_being_simulated: "Your new code is being simulated by other players for ranking. This will refresh as new matches come in."
no_ranked_matches_pre: "No ranked matches for the "
no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
@ -676,6 +681,27 @@
watch_victory: "Watch your victory"
defeat_the: "Defeat the"
ladder_prizes:
title: "Tournament Prizes"
blurb_1: "These prizes will be awarded according to"
blurb_2: "the tournament rules"
blurb_3: "to the top human and ogre players."
blurb_4: "Two teams means double the prizes!"
blurb_5: "(There will be two first place winners, two second-place winners, etc.)"
rank: "Rank"
prizes: "Prizes"
total_value: "Total Value"
in_cash: "in cash"
custom_wizard: "Custom CodeCombat Wizard"
custom_avatar: "Custom CodeCombat avatar"
heap: "span for six months of \"Startup\" access"
credits: "credits"
one_month_coupon: "coupon: choose either Rails or HTML"
one_month_discount: "discount, 30% off: choose either Rails or HTML"
license: "license"
oreilly: "ebook of your choice"
multiplayer_launch:
introducing_dungeon_arena: "Introducing Dungeon Arena"
new_way: "The new way to compete with code."

View file

@ -30,7 +30,7 @@ module.exports = class ThangType extends CocoModel
isFullyLoaded: ->
# TODO: Come up with a better way to identify when the model doesn't have everything needed to build the sprite. ie when it's a projection without all the required data.
return @get('actions') or @get('raster') # needs one of these two things
getActions: ->
return {} unless @isFullyLoaded()
return @actions or @buildActions()

View file

@ -1,3 +1,4 @@
.ladder-submission-view
h3
text-decoration: underline
.help-simulate
font-weight: normal
float: right

View file

@ -74,7 +74,35 @@
#must-log-in button
margin-right: 10px
#prize_table
width: 960px
font-weight: bold
thead
font-size: 24px
tbody
tr:not(:first-child)
border-top: 10px solid #ddd
td
vertical-align: middle
&:nth-child(1), &:nth-child(3)
text-align: center
font-size: 24px
li
list-style: none
&:not(:last-child)
margin-bottom: 10px
border-bottom: 1px solid #ddd
img
margin-right: 10px
@media only screen and (max-width: 800px)
#ladder-view
#level-column img
width: 100%
width: 100%

View file

@ -5,24 +5,26 @@
left: 10px
top: -100px
@include transition(top 0.5s ease-in-out)
background-color: rgba(200,200,200,0.8)
&.brighter
background-color: rgba(200,200,200,1.0)
background-color: rgba(200,200,200,1.0)
border: black
padding: 15px 7px 5px 5px
padding: 15px 7px 2px 5px
box-sizing: border-box
border: 1px solid #333
border-radius: 5px
h3
.goals-status
font-size: 14px
margin: 0
color: black
i
margin-right: 5px
.success
color: darkgreen
.timed-out
color: darkslategray
.failure
color: darkred
.incomplete
color: darkgoldenrod
ul
padding-left: 0

View file

@ -38,7 +38,7 @@ block content
input#email.form-control(name="email", type="text", value="#{me.get('email')}")
if !isProduction
.form-group.checkbox
label(for="email", data-i18n="account_settings.admin") Admin
label(for="admin", data-i18n="account_settings.admin") Admin
input#admin(name="admin", type="checkbox", checked=me.get('permissions').indexOf('admin') != -1)

View file

@ -1,7 +1,9 @@
button.btn.btn-success.rank-button
span(data-i18n="ladder.rank_no_code").unavailable.hidden No New Code to Rank
span(data-i18n="ladder.rank_my_game").rank.hidden Rank My Game!
span(data-i18n="ladder.rank_submitting").submitting.hidden Submitting...
span(data-i18n="ladder.rank_submitted").submitted.hidden Submitted for Ranking
span(data-i18n="ladder.rank_failed").failed.hidden Failed to Rank
span(data-i18n="ladder.rank_being_ranked").ranking.hidden Game Being Ranked
span(data-i18n="ladder.rank_no_code").unavailable.secret No New Code to Rank
span(data-i18n="ladder.rank_my_game").rank.secret Rank My Game!
span(data-i18n="ladder.rank_submitting").submitting.secret Submitting...
span(data-i18n="ladder.rank_submitted").submitted.secret Submitted for Ranking
span(data-i18n="ladder.rank_failed").failed.secret Failed to Rank
span(data-i18n="ladder.rank_being_ranked").ranking.secret Game Being Ranked
a(href=simulateURL, data-i18n="ladder.help_simulate").help-simulate.secret Help simulate games?

View file

@ -45,8 +45,612 @@ block content
.tab-pane.well#simulate
#simulate-tab-view
.tab-pane.well#prizes
h1(data-i18n="ladder.prizes_remember_to_add_i18n_tags") Tournament Prizes
p(data-i18n="ladder.prizes_but_this_is_just_placeholder") Fill in the Greed prizes list here.
h1(data-i18n="ladder_prizes.title") Tournament Prizes
p
span(data-i18n="ladder_prizes.blurb_1") These prizes will be awarded according to
|
a(href="#rules", data-i18n="ladder_prizes.blurb_2") the tournament rules
|
span(data-i18n="ladder_prizes.blurb_3") to the top human and ogre players.
|
strong(data-i18n="ladder_prizes.blurb_4") Two teams means double the prizes!
|
span(data-i18n="ladder_prizes.blurb_5") (There will be two first place winners, two second-place winners, etc.)
- var base = "/images/pages/play/ladder/prize_";
table#prize_table.table
thead
tr
td(data-i18n="ladder_prizes.rank") Rank
td(data-i18n="ladder_prizes.prizes") Prizes
td(data-i18n="ladder_prizes.total_value") Total Value
tbody
tr
td 1st
td
ul.list-unstyled
li
img(src=base + "cash1.png")
span $512
span(data-i18n="ladder_prizes.in_cash") in cash
li
img(src=base + "custom_wizard.png")
span(data-i18n="ladder_prizes.custom_wizard") Custom CodeCombat Wizard
li
img(src=base + "custom_avatar.png")
span(data-i18n="ladder_prizes.custom_avatar") Custom CodeCombat avatar
li
img(src=base + "heap.png")
span
a(href="https://heapanalytics.com/") Heap Analytics
|
span(data-i18n="ladder_prizes.heap") span for six months of "Startup" access
| - $354
li
img(src=base + "firebase.png")
span
a(href="https://www.firebase.com/") Firebase
|
span(data-i18n="ladder_prizes.credits") credits
| - $300
li
img(src=base + "one_month.png")
span
a(href="https://onemonthrails.com/") One Month Rails
|
span(data-i18n="ladder_prizes.one_month_coupon") coupon: choose either Rails or HTML
| - $99
li
img(src=base + "webstorm.png")
span
a(href="http://www.jetbrains.com/webstorm/") Webstorm
|
span(data-i18n="ladder_prizes.license") license
| - $49
li
img(src=base + "oreilly.png")
span
a(href="http://shop.oreilly.com/category/ebooks.do") O'Reilly
|
span(data-i18n="ladder_prizes.oreilly") ebook of your choice
| - $40
li
img(src=base + "aws.png")
span
a(href="http://aws.amazon.com/") Amazon Web Services
|
span(data-i18n="ladder_prizes.credits") credits
| - $50
td $2054
tr
td 2nd
td
ul.list-unstyled
li
img(src=base + "cash2.png")
span $256
span(data-i18n="ladder_prizes.in_cash") in cash
li
img(src=base + "custom_avatar.png")
span(data-i18n="ladder_prizes.custom_avatar") Custom CodeCombat avatar
li
img(src=base + "heap.png")
span
a(href="https://heapanalytics.com/") Heap Analytics
|
span(data-i18n="ladder_prizes.heap") span for six months of "Startup" access
| - $354
li
img(src=base + "firebase.png")
span
a(href="https://www.firebase.com/") Firebase
|
span(data-i18n="ladder_prizes.credits") credits
| - $300
li
img(src=base + "one_month.png")
span
a(href="https://onemonthrails.com/") One Month Rails
|
span(data-i18n="ladder_prizes.one_month_discount") discount, 30% off: choose either Rails or HTML
| - $30
li
img(src=base + "webstorm.png")
span
a(href="http://www.jetbrains.com/webstorm/") Webstorm
|
span(data-i18n="ladder_prizes.license") license
| - $49
li
img(src=base + "oreilly.png")
span
a(href="http://shop.oreilly.com/category/ebooks.do") O'Reilly
|
span(data-i18n="ladder_prizes.oreilly") ebook of your choice
| - $40
li
img(src=base + "aws.png")
span
a(href="http://aws.amazon.com/") Amazon Web Services
|
span(data-i18n="ladder_prizes.credits") credits
| - $50
td $1229
tr
td 3rd
td
ul.list-unstyled
li
img(src=base + "cash2.png")
span $128
span(data-i18n="ladder_prizes.in_cash") in cash
li
img(src=base + "custom_avatar.png")
span(data-i18n="ladder_prizes.custom_avatar") Custom CodeCombat avatar
li
img(src=base + "heap.png")
span
a(href="https://heapanalytics.com/") Heap Analytics
|
span(data-i18n="ladder_prizes.heap") span for six months of "Startup" access
| - $354
li
img(src=base + "firebase.png")
span
a(href="https://www.firebase.com/") Firebase
|
span(data-i18n="ladder_prizes.credits") credits
| - $300
li
img(src=base + "one_month.png")
span
a(href="https://onemonthrails.com/") One Month Rails
|
span(data-i18n="ladder_prizes.one_month_discount") discount, 30% off: choose either Rails or HTML
| - $30
li
img(src=base + "webstorm.png")
span
a(href="http://www.jetbrains.com/webstorm/") Webstorm
|
span(data-i18n="ladder_prizes.license") license
| - $49
li
img(src=base + "oreilly.png")
span
a(href="http://shop.oreilly.com/category/ebooks.do") O'Reilly
|
span(data-i18n="ladder_prizes.oreilly") ebook of your choice
| - $40
li
img(src=base + "aws.png")
span
a(href="http://aws.amazon.com/") Amazon Web Services
|
span(data-i18n="ladder_prizes.credits") credits
| - $50
td $1101
tr
td 4th
td
ul.list-unstyled
li
img(src=base + "cash3.png")
span $64
span(data-i18n="ladder_prizes.in_cash") in cash
li
img(src=base + "heap.png")
span
a(href="https://heapanalytics.com/") Heap Analytics
|
span(data-i18n="ladder_prizes.heap") span for six months of "Startup" access
| - $354
li
img(src=base + "firebase.png")
span
a(href="https://www.firebase.com/") Firebase
|
span(data-i18n="ladder_prizes.credits") credits
| - $300
li
img(src=base + "one_month.png")
span
a(href="https://onemonthrails.com/") One Month Rails
|
span(data-i18n="ladder_prizes.one_month_discount") discount, 30% off: choose either Rails or HTML
| - $30
li
img(src=base + "webstorm.png")
span
a(href="http://www.jetbrains.com/webstorm/") Webstorm
|
span(data-i18n="ladder_prizes.license") license
| - $49
li
img(src=base + "oreilly.png")
span
a(href="http://shop.oreilly.com/category/ebooks.do") O'Reilly
|
span(data-i18n="ladder_prizes.oreilly") ebook of your choice
| - $40
li
img(src=base + "aws.png")
span
a(href="http://aws.amazon.com/") Amazon Web Services
|
span(data-i18n="ladder_prizes.credits") credits
| - $50
td $887
tr
td 5th
td
ul.list-unstyled
li
img(src=base + "cash3.png")
span $32
span(data-i18n="ladder_prizes.in_cash") in cash
li
img(src=base + "heap.png")
span
a(href="https://heapanalytics.com/") Heap Analytics
|
span(data-i18n="ladder_prizes.heap") span for six months of "Startup" access
| - $354
li
img(src=base + "firebase.png")
span
a(href="https://www.firebase.com/") Firebase
|
span(data-i18n="ladder_prizes.credits") credits
| - $300
li
img(src=base + "one_month.png")
span
a(href="https://onemonthrails.com/") One Month Rails
|
span(data-i18n="ladder_prizes.one_month_discount") discount, 30% off: choose either Rails or HTML
| - $30
li
img(src=base + "webstorm.png")
span
a(href="http://www.jetbrains.com/webstorm/") Webstorm
|
span(data-i18n="ladder_prizes.license") license
| - $49
li
img(src=base + "oreilly.png")
span
a(href="http://shop.oreilly.com/category/ebooks.do") O'Reilly
|
span(data-i18n="ladder_prizes.oreilly") ebook of your choice
| - $40
li
img(src=base + "aws.png")
span
a(href="http://aws.amazon.com/") Amazon Web Services
|
span(data-i18n="ladder_prizes.credits") credits
| - $50
td $855
tr
td 6th
td
ul.list-unstyled
li
img(src=base + "cash3.png")
span $16
span(data-i18n="ladder_prizes.in_cash") in cash
li
img(src=base + "firebase.png")
span
a(href="https://www.firebase.com/") Firebase
|
span(data-i18n="ladder_prizes.credits") credits
| - $300
li
img(src=base + "one_month.png")
span
a(href="https://onemonthrails.com/") One Month Rails
|
span(data-i18n="ladder_prizes.one_month_discount") discount, 30% off: choose either Rails or HTML
| - $30
li
img(src=base + "webstorm.png")
span
a(href="http://www.jetbrains.com/webstorm/") Webstorm
|
span(data-i18n="ladder_prizes.license") license
| - $49
li
img(src=base + "oreilly.png")
span
a(href="http://shop.oreilly.com/category/ebooks.do") O'Reilly
|
span(data-i18n="ladder_prizes.oreilly") ebook of your choice
| - $40
li
img(src=base + "aws.png")
span
a(href="http://aws.amazon.com/") Amazon Web Services
|
span(data-i18n="ladder_prizes.credits") credits
| - $50
td $485
tr
td 7th
td
ul.list-unstyled
li
img(src=base + "cash3.png")
span $8
span(data-i18n="ladder_prizes.in_cash") in cash
li
img(src=base + "firebase.png")
span
a(href="https://www.firebase.com/") Firebase
|
span(data-i18n="ladder_prizes.credits") credits
| - $300
li
img(src=base + "one_month.png")
span
a(href="https://onemonthrails.com/") One Month Rails
|
span(data-i18n="ladder_prizes.one_month_discount") discount, 30% off: choose either Rails or HTML
| - $30
li
img(src=base + "webstorm.png")
span
a(href="http://www.jetbrains.com/webstorm/") Webstorm
|
span(data-i18n="ladder_prizes.license") license
| - $49
li
img(src=base + "oreilly.png")
span
a(href="http://shop.oreilly.com/category/ebooks.do") O'Reilly
|
span(data-i18n="ladder_prizes.oreilly") ebook of your choice
| - $40
li
img(src=base + "aws.png")
span
a(href="http://aws.amazon.com/") Amazon Web Services
|
span(data-i18n="ladder_prizes.credits") credits
| - $50
td $477
tr
td 8th
td
ul.list-unstyled
li
img(src=base + "cash3.png")
span $4
span(data-i18n="ladder_prizes.in_cash") in cash
li
img(src=base + "firebase.png")
span
a(href="https://www.firebase.com/") Firebase
|
span(data-i18n="ladder_prizes.credits") credits
| - $300
li
img(src=base + "one_month.png")
span
a(href="https://onemonthrails.com/") One Month Rails
|
span(data-i18n="ladder_prizes.one_month_discount") discount, 30% off: choose either Rails or HTML
| - $30
li
img(src=base + "webstorm.png")
span
a(href="http://www.jetbrains.com/webstorm/") Webstorm
|
span(data-i18n="ladder_prizes.license") license
| - $49
li
img(src=base + "oreilly.png")
span
a(href="http://shop.oreilly.com/category/ebooks.do") O'Reilly
|
span(data-i18n="ladder_prizes.oreilly") ebook of your choice
| - $40
li
img(src=base + "aws.png")
span
a(href="http://aws.amazon.com/") Amazon Web Services
|
span(data-i18n="ladder_prizes.credits") credits
| - $50
td $473
tr
td 9th
td
ul.list-unstyled
li
img(src=base + "cash3.png")
span $2
span(data-i18n="ladder_prizes.in_cash") in cash
li
img(src=base + "firebase.png")
span
a(href="https://www.firebase.com/") Firebase
|
span(data-i18n="ladder_prizes.credits") credits
| - $300
li
img(src=base + "one_month.png")
span
a(href="https://onemonthrails.com/") One Month Rails
|
span(data-i18n="ladder_prizes.one_month_discount") discount, 30% off: choose either Rails or HTML
| - $30
li
img(src=base + "webstorm.png")
span
a(href="http://www.jetbrains.com/webstorm/") Webstorm
|
span(data-i18n="ladder_prizes.license") license
| - $49
li
img(src=base + "oreilly.png")
span
a(href="http://shop.oreilly.com/category/ebooks.do") O'Reilly
|
span(data-i18n="ladder_prizes.oreilly") ebook of your choice
| - $40
li
img(src=base + "aws.png")
span
a(href="http://aws.amazon.com/") Amazon Web Services
|
span(data-i18n="ladder_prizes.credits") credits
| - $50
td $471
tr
td 10th
td
ul.list-unstyled
li
img(src=base + "cash3.png")
span $1
span(data-i18n="ladder_prizes.in_cash") in cash
li
img(src=base + "firebase.png")
span
a(href="https://www.firebase.com/") Firebase
|
span(data-i18n="ladder_prizes.credits") credits
| - $300
li
img(src=base + "one_month.png")
span
a(href="https://onemonthrails.com/") One Month Rails
|
span(data-i18n="ladder_prizes.one_month_discount") discount, 30% off: choose either Rails or HTML
| - $30
li
img(src=base + "webstorm.png")
span
a(href="http://www.jetbrains.com/webstorm/") Webstorm
|
span(data-i18n="ladder_prizes.license") license
| - $49
li
img(src=base + "oreilly.png")
span
a(href="http://shop.oreilly.com/category/ebooks.do") O'Reilly
|
span(data-i18n="ladder_prizes.oreilly") ebook of your choice
| - $40
li
img(src=base + "aws.png")
span
a(href="http://aws.amazon.com/") Amazon Web Services
|
span(data-i18n="ladder_prizes.credits") credits
| - $50
td $470
tr
td 11 - 40
td
ul.list-unstyled
li
img(src=base + "webstorm.png")
span
a(href="http://www.jetbrains.com/webstorm/") Webstorm
|
span(data-i18n="ladder_prizes.license") license
| - $49
li
img(src=base + "oreilly.png")
span
a(href="http://shop.oreilly.com/category/ebooks.do") O'Reilly
|
span(data-i18n="ladder_prizes.oreilly") ebook of your choice
| - $40
li
img(src=base + "aws.png")
span
a(href="http://aws.amazon.com/") Amazon Web Services
|
span(data-i18n="ladder_prizes.credits") credits
| - $50
td $139
tr
td 41 - 100
td
ul.list-unstyled
li
img(src=base + "oreilly.png")
span
a(href="http://shop.oreilly.com/category/ebooks.do") O'Reilly
|
span(data-i18n="ladder_prizes.oreilly") ebook of your choice
| - $40
li
img(src=base + "aws.png")
span
a(href="http://aws.amazon.com/") Amazon Web Services
|
span(data-i18n="ladder_prizes.credits") credits
| - $50
td $90
tr
td 101+
td
ul.list-unstyled
li
img(src=base + "aws.png")
span
a(href="http://aws.amazon.com/") Amazon Web Services
|
span(data-i18n="ladder_prizes.credits") credits
| - $50
td $50
.tab-pane.well#rules
h1(data-i18n="ladder.rules_remember_to_add_i18n_tags") Tournament Rules
p(data-i18n="ladder.rules_but_this_is_just_placeholder") We probably don't have to translate legal documents from English, but we should translate any conversational summary.
h2 General
p You don't have to buy anything to participate in the tournament, and trying to pay us won't increase your odds of winning.
h2 Dates and Times
p The tournament starts on Tuesday 5/20 at 8:30AM and ends on Tuesday 6/10 at 5:30PM PDT. After the tournament finishes, we will check the games manually to prevent duplicate entries and cheating. We will email all the winners within 2 weeks of the end date.
h2 Eligilibity
p The tournament is open to anyone over the age of 13. Players are allowed to form teams to compete, but we will only be rewarding submissions, so if a team of 10 wins, they will need to split the prize.
p The tournament is NOT open to people who live in countries or states that prohibit participating or receiving a prize in a challenge (these include, but are not limited to Brazil, Quebec, Italy, Cuba, Sudan, Iran, North Korea, and Syria). Organizations involved in putting the tournament together (namely CodeCombat and all of our employees) are excluded from participating/winning prizes.
h2 Submission Requirements
p To be eligible to win prizes, players must submit their code to the Greed ladder for ranking AND defeat our default AI. Every player that submits their code to the ladder and beats our default AI will receive $50 in AWS credits as described on the
a(href="#prizes", data-toggle="tab", data-i18n="ladder.prizes") prizes page.
p There are some restrictions regarding who can use the AWS credits, please see the additional rules of use on
a(href="https://aws.amazon.com/awscredits") Amazon's AWS credits page.
h2 Submission Rights
p We reserve the right to use your submission and site identity (including username, avatar, and any information you mark as public) to promote the tournament. This is in keeping with our overall site terms of service.
h2 Judging Criteria
p We will award prizes according to player's rank on the leaderboards. We will not be evaluating code in any manual way for common traits like adequate documentation, cleanliness, etc. Although we will run a final check of all submissions to rule out duplicates and cheating, the leaderboards are a good proxy for your final rank. Your rank will change as players submit more solutions.
h2 Prizes
p Prizes will be awarded to everyone that achieves a rank covered on the
a(href="#prizes", data-toggle="tab", data-i18n="ladder.prizes") prizes page.
p Please remember that the player ranks listed on the prize page refer to ranks WITHIN a leaderboard. So if you are #2 on the Ogre leaderboard, you will get the #2 prize. Similarly, if you are #3 on the Human leaderboard, you will receive the #3 prize. As mentioned above, if you had a submission in the top 10 for both boards, we will only count your highest submission for the purposes of distributing prizes.
h2 Verifying Potential Winners
p We may ask players to identify themselves so that we can detect duplicate entries. This may be done in the form of a Facebook, Google+, or LinkedIn profile, but we may need more information. All players eligible for prizes agree that refusing to provide us with identifying information may lead to removal from the tournament.
p On a related note, if we have reason to believe that a player has intentionally submitted duplicate entries for the purpose of receiving more prizes or manipulating the leaderboards in any way, we will remove that player and all submissions we believe to be associated with them. We want this to be fair for everyone.
h2 Prize Distribution
p Different sponsors require different ways of claiming their prizes, and we will work with winners to ensure they are able to redeem their prizes in a timely fashion. For cash prizes, we will deliver the money via Paypal. We will not ship checks, money orders, or cash through the mail. We will assume reasonable international money transfer costs to deliver cash prizes through Paypal.
p Winners are responsible for any taxes associated with claiming their prizes. CodeCombat is not responsible for filing paperwork on behalf of winners for tax claims.
h2 Contact
p If you have any questions or would like to get in touch with us for any other reason, we can be reached at team@codecombat.com. You can also post to our public
a(href="http://discourse.codecombat.com/") Discourse forum.

View file

@ -1,3 +1,8 @@
ul#primary-goals-list
h3
span(data-i18n="play_level.goals") Goals
div.goals-status
strong(data-i18n="play_level.goals") Goals
span.spl.spr :
span(data-i18n="play_level.success").secret.goal-status.success Success!
span(data-i18n="play_level.incomplete").secret.goal-status.incomplete Incomplete
span(data-i18n="play_level.timed_out").secret.goal-status.timed-out Ran out of time
span(data-i18n="play_level.failing").secret.goal-status.failure Failing

View file

@ -284,7 +284,11 @@ module.exports = class ThangTypeEditView extends View
fixed = scaleValue.toFixed(1)
@scale = scaleValue
@$el.find('.scale-label').text " #{fixed}x "
@currentObject.scaleX = @currentObject.scaleY = scaleValue / resValue if @currentObject?
if @currentSprite
@currentSprite.scaleFactor = scaleValue
@currentSprite.updateScale()
else if @currentObject?
@currentObject.scaleX = @currentObject.scaleY = scaleValue / resValue
@updateGrid()
@updateDots()

View file

@ -2,11 +2,12 @@ CocoView = require 'views/kinds/CocoView'
template = require 'templates/play/common/ladder_submission'
module.exports = class LadderSubmissionView extends CocoView
class: "ladder-submission-view"
className: "ladder-submission-view"
template: template
events:
'click .rank-button': 'rankSession'
'click .help-simulate': 'onHelpSimulate'
constructor: (options) ->
super options
@ -16,9 +17,10 @@ module.exports = class LadderSubmissionView extends CocoView
getRenderData: ->
ctx = super()
ctx.readyToRank = @session?.readyToRank()
ctx.isRanking = @ession?.get('isRanking')
ctx.isRanking = @session?.get('isRanking')
ctx.simulateURL = "/play/ladder/#{@level.get('slug')}#simulate"
ctx
afterRender: ->
super()
return unless @supermodel.finished()
@ -34,9 +36,11 @@ module.exports = class LadderSubmissionView extends CocoView
@setRankingButtonText rankingState
setRankingButtonText: (spanClass) ->
@rankButton.find('span').addClass('hidden')
@rankButton.find(".#{spanClass}").removeClass('hidden')
@rankButton.find('span').hide()
@rankButton.find(".#{spanClass}").show()
@rankButton.toggleClass 'disabled', spanClass isnt 'rank'
helpSimulate = spanClass in ['submitted', 'ranking']
@$el.find('.help-simulate').toggle(helpSimulate, 'slow')
rankSession: (e) ->
return unless @session.readyToRank()
@ -86,3 +90,5 @@ module.exports = class LadderSubmissionView extends CocoView
transpiledCode[thang][spellID] = aether.transpile spell
transpiledCode
onHelpSimulate: ->
$('a[href="#simulate"]').tab('show')

View file

@ -100,6 +100,8 @@ module.exports = class LadderView extends RootView
e.stopPropagation()
e.preventDefault()
@showApologeticSignupModal()
if link and /#rules$/.test link
@$el.find('a[href="#rules"]').tab('show')
destroy: ->
clearInterval @refreshInterval

View file

@ -91,7 +91,7 @@ module.exports = class MyMatchesTabView extends CocoView
session = _.find @sessions.models, {id: sessionID}
ladderSubmissionView = new LadderSubmissionView session: session, level: @level
@insertSubView ladderSubmissionView, placeholder
ladderSubmissionView.$el.find('.rank-button').addClass 'btn-block'
ladderSubmissionView.$el.find('.rank-button').addClass 'btn-block btn-lg'
@$el.find('.score-chart-wrapper').each (i, el) =>
scoreWrapper = $(el)

View file

@ -19,13 +19,26 @@ module.exports = class GoalsView extends View
'surface:playback-ended': 'onSurfacePlaybackEnded'
events:
'mouseenter': -> @$el.css('top', -10)
'mouseleave': -> @updateTop()
'mouseenter': ->
@mouseEntered = true
@updatePlacement()
'mouseleave': ->
@mouseEntered = false
@updatePlacement()
toggleCollapse: (e) ->
@$el.toggleClass('expanded').toggleClass('collapsed')
onNewGoalStates: (e) ->
@$el.find('.goal-status').addClass 'secret'
classToShow = null
classToShow = 'success' if e.overallStatus is 'success'
classToShow = 'failure' if e.overallStatus is 'failure'
classToShow ?= 'timed-out' if e.timedOut
classToShow ?= 'incomplete'
@$el.find('.goal-status.'+classToShow).removeClass 'secret'
list = $('#primary-goals-list', @$el)
list.empty()
goals = []
@ -53,10 +66,14 @@ module.exports = class GoalsView extends View
@$el.removeClass('secret') if goals.length > 0
onSurfacePlaybackRestarted: ->
@playbackEnded = false
@$el.removeClass 'brighter'
@updatePlacement()
onSurfacePlaybackEnded: ->
@playbackEnded = true
@$el.addClass 'brighter'
@updatePlacement()
render: ->
super()
@ -64,11 +81,16 @@ module.exports = class GoalsView extends View
afterRender: ->
super()
@updateTop()
@updatePlacement()
updateTop: ->
@$el.css('top', 26 - @$el.outerHeight())
updatePlacement: ->
if @playbackEnded or @mouseEntered
# expand
@$el.css('top', -10)
else
# collapse
@$el.css('top', 26 - @$el.outerHeight())
onSetLetterbox: (e) ->
@$el.toggle not e.on
@updateTop()
@updatePlacement()

View file

@ -68,15 +68,14 @@ module.exports = class PlayLevelView extends View
shortcuts:
'ctrl+s': 'onCtrlS'
# Initial Setup #############################################################
constructor: (options, @levelID) ->
console.profile?() if PROFILE_ME
super options
if not me.get('hourOfCode') and @getQueryVariable "hour_of_code"
me.set 'hourOfCode', true
me.save()
$('body').append($("<img src='http://code.org/api/hour/begin_codecombat.png' style='visibility: hidden;'>"))
application.tracker?.trackEvent 'Hour of Code Begin', {}
@setUpHourOfCode()
@isEditorPreview = @getQueryVariable 'dev'
@sessionID = @getQueryVariable 'session'
@ -91,10 +90,12 @@ module.exports = class PlayLevelView extends View
else
@load()
application.tracker?.trackEvent 'Started Level Load', level: @levelID, label: @levelID
onLevelLoadError: (e) ->
# TODO NOW: remove this in favor of the supermodel handling it
application.router.navigate "/play?not_found=#{@levelID}", {trigger: true}
setUpHourOfCode: ->
me.set 'hourOfCode', true
me.save()
$('body').append($("<img src='http://code.org/api/hour/begin_codecombat.png' style='visibility: hidden;'>"))
application.tracker?.trackEvent 'Hour of Code Begin', {}
setLevel: (@level, givenSupermodel) ->
@supermodel.models = givenSupermodel.models
@ -112,6 +113,30 @@ module.exports = class PlayLevelView extends View
@loadStartTime = new Date()
@god = new God debugWorker: true
@levelLoader = new LevelLoader supermodel: @supermodel, levelID: @levelID, sessionID: @sessionID, opponentSessionID: @getQueryVariable('opponent'), team: @getQueryVariable("team")
@listenToOnce @levelLoader, 'world-necessities-loaded', @onWorldNecessitiesLoaded
# CocoView overridden methods ###############################################
updateProgress: (progress) ->
super(progress)
return if @seenDocs
return unless @levelLoader.session.loaded and @levelLoader.level.loaded
return unless showFrequency = @levelLoader.level.get('showsGuide')
session = @levelLoader.session
diff = new Date().getTime() - new Date(session.get('created')).getTime()
return if showFrequency is 'first-time' and diff > (5 * 60 * 1000)
articles = @levelLoader.supermodel.getModels Article
for article in articles
return unless article.loaded
@showGuide()
showGuide: ->
@seenDocs = true
DocsModal = require './level/modal/docs_modal'
options = {docs: @levelLoader.level.get('documentation'), supermodel: @supermodel}
@openModalView(new DocsModal(options), true)
Backbone.Mediator.subscribeOnce 'modal-closed', @onLevelLoaded, @
return true
getRenderData: ->
c = super()
@ -129,62 +154,26 @@ module.exports = class PlayLevelView extends View
@$el.find('#level-done-button').hide()
$('body').addClass('is-playing')
updateProgress: (progress) ->
super(progress)
if not @worldInitialized and @levelLoader.session.loaded and @levelLoader.level.loaded and @levelLoader.world and (not @levelLoader.opponentSession or @levelLoader.opponentSession.loaded)
@grabLevelLoaderData()
@onWorldInitialized()
return if @seenDocs
return unless @levelLoader.session.loaded and @levelLoader.level.loaded
return unless showFrequency = @levelLoader.level.get('showsGuide')
session = @levelLoader.session
diff = new Date().getTime() - new Date(session.get('created')).getTime()
return if showFrequency is 'first-time' and diff > (5 * 60 * 1000)
articles = @levelLoader.supermodel.getModels Article
for article in articles
return unless article.loaded
@showGuide()
afterInsert: ->
super()
@showWizardSettingsModal() if not me.get('name')
onWorldInitialized: ->
@worldInitialized = true
# Partially Loaded Setup ####################################################
onWorldNecessitiesLoaded: ->
# Called when we have enough to build the world, but not everything is loaded
@grabLevelLoaderData()
team = @getQueryVariable("team") ? @world.teamForPlayer(0)
@loadOpponentTeam(team)
@god.setLevel @level.serialize @supermodel
@god.setLevelSessionIDs if @otherSession then [@session.id, @otherSession.id] else [@session.id]
@god.setWorldClassMap @world.classMap
@setupGod()
@setTeam team
@initGoalManager()
@insertSubviews ladderGame: (@level.get('type') is "ladder")
@insertSubviews()
@initVolume()
@listenTo(@session, 'change:multiplayer', @onMultiplayerChanged)
@originalSessionState = $.extend(true, {}, @session.get('state'))
@register()
@controlBar.setBus(@bus)
showGuide: ->
@seenDocs = true
DocsModal = require './level/modal/docs_modal'
options = {docs: @levelLoader.level.get('documentation'), supermodel: @supermodel}
@openModalView(new DocsModal(options), true)
Backbone.Mediator.subscribeOnce 'modal-closed', @onLevelLoaded, @
return true
onLoaded: ->
_.defer => @onLevelLoaded()
onLevelLoaded: ->
return unless @levelLoader.progress() is 1 # double check, since closing the guide may trigger this early
@loadingView.showReady()
if window.currentModal and not window.currentModal.destroyed
return Backbone.Mediator.subscribeOnce 'modal-closed', @onLevelLoaded, @
# Save latest level played in local storage
if not (@levelLoader.level.get('type') in ['ladder', 'ladder-tutorial'])
me.set('lastLevel', @levelID)
me.save()
@levelLoader.destroy()
@levelLoader = null
@initSurface()
@initScriptManager()
grabLevelLoaderData: ->
@ -212,7 +201,78 @@ module.exports = class PlayLevelView extends View
# For now, ladderGame will disallow multiplayer, because session code combining doesn't play nice yet.
@session.set 'multiplayer', false
onLevelStarted: (e) ->
setupGod: ->
@god.setLevel @level.serialize @supermodel
@god.setLevelSessionIDs if @otherSession then [@session.id, @otherSession.id] else [@session.id]
@god.setWorldClassMap @world.classMap
setTeam: (team) ->
team = team?.team unless _.isString team
team ?= 'humans'
me.team = team
Backbone.Mediator.publish 'level:team-set', team: team
initGoalManager: ->
@goalManager = new GoalManager(@world, @level.get('goals'))
@god.setGoalManager @goalManager
insertSubviews: ->
@insertSubView @tome = new TomeView levelID: @levelID, session: @session, thangs: @world.thangs, supermodel: @supermodel
@insertSubView new PlaybackView session: @session
@insertSubView new GoalsView {}
@insertSubView new GoldView {}
@insertSubView new HUDView {}
@insertSubView new ChatView levelID: @levelID, sessionID: @session.id, session: @session
worldName = utils.i18n @level.attributes, 'name'
@controlBar = @insertSubView new ControlBarView {worldName: worldName, session: @session, level: @level, supermodel: @supermodel, playableTeams: @world.playableTeams}
#Backbone.Mediator.publish('level-set-debug', debug: true) if me.displayName() is 'Nick!'
initVolume: ->
volume = me.get('volume')
volume = 1.0 unless volume?
Backbone.Mediator.publish 'level-set-volume', volume: volume
initScriptManager: ->
@scriptManager = new ScriptManager({scripts: @world.scripts or [], view:@, session: @session})
@scriptManager.loadFromSession()
register: ->
@bus = LevelBus.get(@levelID, @session.id)
@bus.setSession(@session)
@bus.setSpells @tome.spells
@bus.connect() if @session.get('multiplayer')
# Load Completed Setup ######################################################
onLoaded: ->
_.defer => @onLevelLoaded()
onLevelLoaded: ->
# Everything is now loaded
return unless @levelLoader.progress() is 1 # double check, since closing the guide may trigger this early
@loadingView.showReady()
if window.currentModal and not window.currentModal.destroyed
return Backbone.Mediator.subscribeOnce 'modal-closed', @onLevelLoaded, @
# Save latest level played in local storage
if not (@levelLoader.level.get('type') in ['ladder', 'ladder-tutorial'])
me.set('lastLevel', @levelID)
me.save()
@levelLoader.destroy()
@levelLoader = null
@initSurface()
initSurface: ->
surfaceCanvas = $('canvas#surface', @$el)
@surface = new Surface(@world, surfaceCanvas, thangTypes: @supermodel.getModels(ThangType), playJingle: not @isEditorPreview)
worldBounds = @world.getBounds()
bounds = [{x:worldBounds.left, y:worldBounds.top}, {x:worldBounds.right, y:worldBounds.bottom}]
@surface.camera.setBounds(bounds)
@surface.camera.zoomTo({x:0, y:0}, 0.1, 0)
# Once Surface is Loaded ####################################################
onLevelStarted: ->
@surface.showLevel()
if @otherSession
# TODO: colorize name and cloud by team, colorize wizard by user's color config
@ -229,34 +289,17 @@ module.exports = class PlayLevelView extends View
application.tracker?.trackEvent 'Finished Level Load', level: @levelID, label: @levelID, loadDuration: loadDuration
application.tracker?.trackTiming loadDuration, 'Level Load Time', @levelID, @levelID
onSupermodelLoadedOne: =>
@modelsLoaded ?= 0
@modelsLoaded += 1
@updateInitString()
updateInitString: ->
return if @surface
@modelsLoaded ?= 0
canvas = @$el.find('#surface')[0]
ctx = canvas.getContext('2d')
ctx.font="20px Georgia"
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.fillText("Loaded #{@modelsLoaded} thingies",50,50)
insertSubviews: ->
@insertSubView @tome = new TomeView levelID: @levelID, session: @session, thangs: @world.thangs, supermodel: @supermodel
@insertSubView new PlaybackView session: @session
@insertSubView new GoalsView {}
@insertSubView new GoldView {}
@insertSubView new HUDView {}
@insertSubView new ChatView levelID: @levelID, sessionID: @session.id, session: @session
worldName = utils.i18n @level.attributes, 'name'
@controlBar = @insertSubView new ControlBarView {worldName: worldName, session: @session, level: @level, supermodel: @supermodel, playableTeams: @world.playableTeams}
#Backbone.Mediator.publish('level-set-debug', debug: true) if me.displayName() is 'Nick!'
afterInsert: ->
super()
@showWizardSettingsModal() if not me.get('name')
onSurfaceSetUpNewWorld: ->
return if @alreadyLoadedState
@alreadyLoadedState = true
state = @originalSessionState
if state.frame and @level.get('type') isnt 'ladder' # https://github.com/codecombat/codecombat/issues/714
Backbone.Mediator.publish 'level-set-time', { time: 0, frameOffset: state.frame }
if state.selected
# TODO: Should also restore selected spell here by saving spellName
Backbone.Mediator.publish 'level-select-sprite', { thangID: state.selected, spellName: null }
if state.playing?
Backbone.Mediator.publish 'level-set-playing', { playing: state.playing }
# callbacks
@ -412,46 +455,11 @@ module.exports = class PlayLevelView extends View
@bus.removeFirebaseData =>
@bus.disconnect()
# initialization
addPointer: ->
p = $('#pointer')
return if p.length
@$el.append($('<img src="/images/level/pointer.png" id="pointer">'))
initSurface: ->
surfaceCanvas = $('canvas#surface', @$el)
@surface = new Surface(@world, surfaceCanvas, thangTypes: @supermodel.getModels(ThangType), playJingle: not @isEditorPreview)
worldBounds = @world.getBounds()
bounds = [{x:worldBounds.left, y:worldBounds.top}, {x:worldBounds.right, y:worldBounds.bottom}]
@surface.camera.setBounds(bounds)
@surface.camera.zoomTo({x:0, y:0}, 0.1, 0)
initGoalManager: ->
@goalManager = new GoalManager(@world, @level.get('goals'))
@god.setGoalManager @goalManager
initScriptManager: ->
@scriptManager = new ScriptManager({scripts: @world.scripts or [], view:@, session: @session})
@scriptManager.loadFromSession()
initVolume: ->
volume = me.get('volume')
volume = 1.0 unless volume?
Backbone.Mediator.publish 'level-set-volume', volume: volume
onSurfaceSetUpNewWorld: ->
return if @alreadyLoadedState
@alreadyLoadedState = true
state = @originalSessionState
if state.frame and @level.get('type') isnt 'ladder' # https://github.com/codecombat/codecombat/issues/714
Backbone.Mediator.publish 'level-set-time', { time: 0, frameOffset: state.frame }
if state.selected
# TODO: Should also restore selected spell here by saving spellName
Backbone.Mediator.publish 'level-select-sprite', { thangID: state.selected, spellName: null }
if state.playing?
Backbone.Mediator.publish 'level-set-playing', { playing: state.playing }
preloadNextLevel: =>
# TODO: Loading models in the middle of gameplay causes stuttering. Most of the improvement in loading time is simply from passing the supermodel from this level to the next, but if we can find a way to populate the level early without it being noticeable, that would be even better.
# return if @destroyed
@ -460,12 +468,6 @@ module.exports = class PlayLevelView extends View
# @supermodel.populateModel nextLevel
# @preloaded = true
register: ->
@bus = LevelBus.get(@levelID, @session.id)
@bus.setSession(@session)
@bus.setSpells @tome.spells
@bus.connect() if @session.get('multiplayer')
onSessionWillSave: (e) ->
# Something interesting has happened, so (at a lower frequency), we'll save a screenshot.
#@saveScreenshot e.session
@ -475,12 +477,6 @@ module.exports = class PlayLevelView extends View
return unless screenshot = @surface?.screenshot()
session.save {screenshot: screenshot}, {patch: true}
setTeam: (team) ->
team = team?.team unless _.isString team
team ?= 'humans'
me.team = team
Backbone.Mediator.publish 'level:team-set', team: team
# Dynamic sound loading
onNewWorld: (e) ->

View file

@ -121,7 +121,7 @@ module.exports = class Handler
@modelClass.findOne(criteria, project).sort(sort).exec (err, document) ->
return done(err) if err
callback(null, document?.toObject() or null)
funcs = {}
for id in ids
return errors.badInput(res, "Given an invalid id: #{id}") unless Handler.isID(id)

View file

@ -103,7 +103,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
unless ogresGameID and humansGameID
#fetch random games here
queryParams =
@ -185,6 +185,7 @@ module.exports.recordTwoGames = (req, res) ->
sendResponseObject req, res, {"message":"The single game was submitted successfully!"}
module.exports.createNewTask = (req, res) ->
requestSessionID = req.body.session
originalLevelID = req.body.originalLevelID
@ -274,7 +275,7 @@ fetchInitialSessionsToRankAgainst = (levelMajorVersion, levelID, submittedSessio
submittedCode:
$exists: true
team: opposingTeam
sortParameters =
totalScore: 1
@ -723,9 +724,7 @@ retrieveOldSessionData = (sessionID, callback) ->
"totalScore":session.totalScore ? (25 - 1.8*(25/3))
"id": sessionID
callback err, oldScoreObject
markSessionAsDoneRanking = (sessionID, cb) ->
markSessionAsDoneRanking = (sessionID, cb) ->
#console.log "Marking session as done ranking..."
LevelSession.update {"_id":sessionID}, {"isRanking":false}, cb

View file

@ -91,8 +91,8 @@ setupFallbackRouteToIndex = (app) ->
sendMain = (req, res) ->
fs.readFile path.join(__dirname, 'public', 'main.html'), 'utf8', (err, data) ->
log.error "Error modifying main.html: #{err}" if err
# insert the user object directly into the html so the application can have it immediately
data = data.replace('"userObjectTag"', JSON.stringify(UserHandler.formatEntity(req, req.user)))
# insert the user object directly into the html so the application can have it immediately. Sanitize </script>
data = data.replace('"userObjectTag"', JSON.stringify(UserHandler.formatEntity(req, req.user)).replace('/', '\\/'))
res.send data
setupFacebookCrossDomainCommunicationRoute = (app) ->