mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-28 10:06:08 -05:00
Merge pull request #415 from codecombat/master
Merge master into production
This commit is contained in:
commit
ce56e5df03
50 changed files with 543 additions and 330 deletions
|
@ -1,6 +1,7 @@
|
||||||
app = require 'application'
|
app = require 'application'
|
||||||
|
auth = require 'lib/auth'
|
||||||
|
|
||||||
$ ->
|
init = ->
|
||||||
app.initialize()
|
app.initialize()
|
||||||
Backbone.history.start({ pushState: true })
|
Backbone.history.start({ pushState: true })
|
||||||
handleNormalUrls()
|
handleNormalUrls()
|
||||||
|
@ -9,6 +10,15 @@ $ ->
|
||||||
treemaExt.setup()
|
treemaExt.setup()
|
||||||
filepicker.setKey('AvlkNoldcTOU4PvKi2Xm7z')
|
filepicker.setKey('AvlkNoldcTOU4PvKi2Xm7z')
|
||||||
|
|
||||||
|
$ ->
|
||||||
|
# Make sure we're "logged in" first.
|
||||||
|
if auth.me.id
|
||||||
|
init()
|
||||||
|
else
|
||||||
|
Backbone.Mediator.subscribeOnce 'me:synced', init
|
||||||
|
|
||||||
|
window.init = init
|
||||||
|
|
||||||
handleNormalUrls = ->
|
handleNormalUrls = ->
|
||||||
# http://artsy.github.com/blog/2012/06/25/replacing-hashbang-routes-with-pushstate/
|
# http://artsy.github.com/blog/2012/06/25/replacing-hashbang-routes-with-pushstate/
|
||||||
$(document).on "click", "a[href^='/']", (event) ->
|
$(document).on "click", "a[href^='/']", (event) ->
|
||||||
|
|
|
@ -141,8 +141,8 @@ module.exports = class SpriteBuilder
|
||||||
return unless shapes.length
|
return unless shapes.length
|
||||||
colors = @initColorMap(shapes)
|
colors = @initColorMap(shapes)
|
||||||
@adjustHuesForColorMap(colors, config.hue)
|
@adjustHuesForColorMap(colors, config.hue)
|
||||||
@adjustValueForColorMap(colors, 1, config.lightness)
|
@adjustValueForColorMap(colors, 1, config.saturation)
|
||||||
@adjustValueForColorMap(colors, 2, config.saturation)
|
@adjustValueForColorMap(colors, 2, config.lightness)
|
||||||
@applyColorMap(shapes, colors)
|
@applyColorMap(shapes, colors)
|
||||||
|
|
||||||
initColorMap: (shapes) ->
|
initColorMap: (shapes) ->
|
||||||
|
|
48
app/lib/surface/CastingScreen.coffee
Normal file
48
app/lib/surface/CastingScreen.coffee
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
CocoClass = require 'lib/CocoClass'
|
||||||
|
|
||||||
|
module.exports = class CastingScreen extends CocoClass
|
||||||
|
subscriptions:
|
||||||
|
'tome:cast-spells': 'onCastingBegins'
|
||||||
|
'god:new-world-created': 'onCastingEnds'
|
||||||
|
|
||||||
|
constructor: (options) ->
|
||||||
|
super()
|
||||||
|
options ?= {}
|
||||||
|
@camera = options.camera
|
||||||
|
@layer = options.layer
|
||||||
|
console.error @toString(), "needs a camera." unless @camera
|
||||||
|
console.error @toString(), "needs a layer." unless @layer
|
||||||
|
@build()
|
||||||
|
|
||||||
|
onCastingBegins: ->
|
||||||
|
@show()
|
||||||
|
|
||||||
|
onCastingEnds: ->
|
||||||
|
@hide()
|
||||||
|
|
||||||
|
toString: -> "<CastingScreen>"
|
||||||
|
|
||||||
|
build: ->
|
||||||
|
@dimLayer = new createjs.Container()
|
||||||
|
@dimLayer.mouseEnabled = @dimLayer.mouseChildren = false
|
||||||
|
@dimLayer.layerIndex = -11
|
||||||
|
@dimLayer.addChild @dimScreen = new createjs.Shape()
|
||||||
|
@dimScreen.graphics.beginFill("rgba(0,0,0,0.5)").rect 0, 0, @camera.canvasWidth, @camera.canvasHeight
|
||||||
|
@dimLayer.cache 0, 0, @camera.canvasWidth, @camera.canvasHeight
|
||||||
|
@dimLayer.alpha = 0
|
||||||
|
@layer.addChild @dimLayer
|
||||||
|
|
||||||
|
show: ->
|
||||||
|
return if @on
|
||||||
|
@on = true
|
||||||
|
|
||||||
|
@dimLayer.alpha = 0
|
||||||
|
createjs.Tween.removeTweens @dimLayer
|
||||||
|
createjs.Tween.get(@dimLayer).to({alpha:1}, 500)
|
||||||
|
|
||||||
|
hide: ->
|
||||||
|
return unless @on
|
||||||
|
@on = false
|
||||||
|
|
||||||
|
createjs.Tween.removeTweens @dimLayer
|
||||||
|
createjs.Tween.get(@dimLayer).to({alpha:0}, 500)
|
|
@ -65,13 +65,13 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
@age = 0
|
@age = 0
|
||||||
@displayObject = new createjs.Container()
|
@displayObject = new createjs.Container()
|
||||||
if @thangType.get('actions')
|
if @thangType.get('actions')
|
||||||
@onThangTypeLoaded()
|
@setupSprite()
|
||||||
else
|
else
|
||||||
@stillLoading = true
|
@stillLoading = true
|
||||||
@thangType.fetch()
|
@thangType.fetch()
|
||||||
@thangType.once 'sync', @onThangTypeLoaded, @
|
@thangType.once 'sync', @setupSprite, @
|
||||||
|
|
||||||
onThangTypeLoaded: ->
|
setupSprite: ->
|
||||||
@stillLoading = false
|
@stillLoading = false
|
||||||
@actions = @thangType.getActions()
|
@actions = @thangType.getActions()
|
||||||
@buildFromSpriteSheet @buildSpriteSheet()
|
@buildFromSpriteSheet @buildSpriteSheet()
|
||||||
|
@ -101,6 +101,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
# temp, until these are re-exported with perspective
|
# temp, until these are re-exported with perspective
|
||||||
if @options.camera and @thangType.get('name') in ['Dungeon Floor', 'Indoor Floor', 'Grass', 'Goal Trigger', 'Obstacle']
|
if @options.camera and @thangType.get('name') in ['Dungeon Floor', 'Indoor Floor', 'Grass', 'Goal Trigger', 'Obstacle']
|
||||||
sprite.scaleY *= @options.camera.y2x
|
sprite.scaleY *= @options.camera.y2x
|
||||||
|
@displayObject.removeChild(@imageObject) if @imageObject
|
||||||
@imageObject = sprite
|
@imageObject = sprite
|
||||||
@displayObject.addChild(sprite)
|
@displayObject.addChild(sprite)
|
||||||
@addHealthBar()
|
@addHealthBar()
|
||||||
|
@ -157,6 +158,14 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
@hiding = false
|
@hiding = false
|
||||||
@updateAlpha()
|
@updateAlpha()
|
||||||
|
|
||||||
|
stop: ->
|
||||||
|
@imageObject?.stop?()
|
||||||
|
mark.stop() for name, mark of @marks
|
||||||
|
|
||||||
|
play: ->
|
||||||
|
@imageObject?.play?()
|
||||||
|
mark.play() for name, mark of @marks
|
||||||
|
|
||||||
update: ->
|
update: ->
|
||||||
# Gets the sprite to reflect what the current state of the thangs and surface are
|
# Gets the sprite to reflect what the current state of the thangs and surface are
|
||||||
return if @stillLoading
|
return if @stillLoading
|
||||||
|
@ -197,8 +206,11 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
if @thang.width isnt @lastThangWidth or @thang.height isnt @lastThangHeight
|
if @thang.width isnt @lastThangWidth or @thang.height isnt @lastThangHeight
|
||||||
[@lastThangWidth, @lastThangHeight] = [@thang.width, @thang.height]
|
[@lastThangWidth, @lastThangHeight] = [@thang.width, @thang.height]
|
||||||
bounds = @imageObject.getBounds()
|
bounds = @imageObject.getBounds()
|
||||||
@imageObject.scaleX = @thang.width * Camera.PPM / bounds.width * @thangType.get('scale') ? 1
|
@imageObject.scaleX = @thang.width * Camera.PPM / bounds.width
|
||||||
@imageObject.scaleY = @thang.height * Camera.PPM * @options.camera.y2x / bounds.height * @thangType.get('scale') ? 1
|
@imageObject.scaleY = @thang.height * Camera.PPM * @options.camera.y2x / bounds.height
|
||||||
|
unless @thang.spriteName is 'Beam'
|
||||||
|
@imageObject.scaleX *= @thangType.get('scale') ? 1
|
||||||
|
@imageObject.scaleY *= @thangType.get('scale') ? 1
|
||||||
return
|
return
|
||||||
scaleX = if @getActionProp 'flipX' then -1 else 1
|
scaleX = if @getActionProp 'flipX' then -1 else 1
|
||||||
scaleY = if @getActionProp 'flipY' then -1 else 1
|
scaleY = if @getActionProp 'flipY' then -1 else 1
|
||||||
|
|
|
@ -54,17 +54,19 @@ module.exports = class Label extends CocoClass
|
||||||
buildLabelOptions: ->
|
buildLabelOptions: ->
|
||||||
o = {}
|
o = {}
|
||||||
st = {dialogue: 'D', say: 'S', name: 'N'}[@style]
|
st = {dialogue: 'D', say: 'S', name: 'N'}[@style]
|
||||||
o.marginX = {D: 5, S: 2, N: 3}[st]
|
o.marginX = {D: 5, S: 6, N: 3}[st]
|
||||||
o.marginY = {D: 6, S: 2, N: 3}[st]
|
o.marginY = {D: 6, S: 4, N: 3}[st]
|
||||||
|
o.fontWeight = {D: "bold", S: "bold", N: "bold"}[st]
|
||||||
o.shadow = {D: false, S: true, N: true}[st]
|
o.shadow = {D: false, S: true, N: true}[st]
|
||||||
o.fontSize = {D: 25, S: 19, N: 14}[st]
|
o.shadowColor = {D: "#FFF", S: "#000", N: "#FFF"}[st]
|
||||||
|
o.fontSize = {D: 25, S: 12, N: 12}[st]
|
||||||
fontFamily = {D: "Arial", S: "Arial", N: "Arial"}[st]
|
fontFamily = {D: "Arial", S: "Arial", N: "Arial"}[st]
|
||||||
o.fontDescriptor = "#{o.fontSize}px #{fontFamily}"
|
o.fontDescriptor = "#{o.fontWeight} #{o.fontSize}px #{fontFamily}"
|
||||||
o.fontColor = {D: "#000", S: "#000", N: "#00a"}[st]
|
o.fontColor = {D: "#000", S: "#FFF", N: "#00a"}[st]
|
||||||
o.backgroundFillColor = {D: "white", S: "rgba(255, 255, 255, 0.2)", N: "rgba(255, 255, 255, 0.5)"}[st]
|
o.backgroundFillColor = {D: "white", S: "rgba(0, 0, 0, 0.4)", N: "rgba(255, 255, 255, 0.5)"}[st]
|
||||||
o.backgroundStrokeColor = {D: "black", S: "rgba(0, 0, 0, 0.2)", N: "rgba(0, 0, 0, 0.0)"}[st]
|
o.backgroundStrokeColor = {D: "black", S: "rgba(0, 0, 0, .6)", N: "rgba(0, 0, 0, 0.0)"}[st]
|
||||||
o.backgroundStrokeStyle = {D: 2, S: 1, N: 1}[st]
|
o.backgroundStrokeStyle = {D: 2, S: 1, N: 1}[st]
|
||||||
o.backgroundBorderRadius = {D: 10, S: 5, N: 3}[st]
|
o.backgroundBorderRadius = {D: 10, S: 3, N: 3}[st]
|
||||||
o.layerPriority = {D: 10, S: 5, N: 5}[st]
|
o.layerPriority = {D: 10, S: 5, N: 5}[st]
|
||||||
maxWidth = {D: 300, S: 300, N: 180}[st]
|
maxWidth = {D: 300, S: 300, N: 180}[st]
|
||||||
maxWidth = Math.max @camera.canvasWidth / 2 - 100, maxWidth # Does this do anything?
|
maxWidth = Math.max @camera.canvasWidth / 2 - 100, maxWidth # Does this do anything?
|
||||||
|
@ -79,7 +81,7 @@ module.exports = class Label extends CocoClass
|
||||||
label.lineHeight = o.fontSize + 2
|
label.lineHeight = o.fontSize + 2
|
||||||
label.x = o.marginX
|
label.x = o.marginX
|
||||||
label.y = o.marginY
|
label.y = o.marginY
|
||||||
label.shadow = new createjs.Shadow "#FFF", 1, 1, 0 if o.shadow
|
label.shadow = new createjs.Shadow o.shadowColor, 1, 1, 0 if o.shadow
|
||||||
label.layerPriority = o.layerPriority
|
label.layerPriority = o.layerPriority
|
||||||
label.name = "Sprite Label - #{@style}"
|
label.name = "Sprite Label - #{@style}"
|
||||||
o.textHeight = label.getMeasuredHeight()
|
o.textHeight = label.getMeasuredHeight()
|
||||||
|
|
|
@ -48,7 +48,7 @@ module.exports = class Mark extends CocoClass
|
||||||
build: ->
|
build: ->
|
||||||
unless @mark
|
unless @mark
|
||||||
if @name is 'bounds' then @buildBounds()
|
if @name is 'bounds' then @buildBounds()
|
||||||
else if @name is 'shadow' then @buildRadius()
|
else if @name is 'shadow' then @buildShadow()
|
||||||
else if @name is 'debug' then @buildDebug()
|
else if @name is 'debug' then @buildDebug()
|
||||||
else if @thangType then @buildSprite()
|
else if @thangType then @buildSprite()
|
||||||
else console.error "Don't know how to build mark for", @name
|
else console.error "Don't know how to build mark for", @name
|
||||||
|
@ -87,21 +87,31 @@ module.exports = class Mark extends CocoClass
|
||||||
@lastWidth = @sprite.thang.width
|
@lastWidth = @sprite.thang.width
|
||||||
@lastHeight = @sprite.thang.height
|
@lastHeight = @sprite.thang.height
|
||||||
|
|
||||||
buildRadius: ->
|
buildShadow: ->
|
||||||
# TODO: make this not just a shadow
|
width = (@sprite.thang?.width ? 0) + 0.5
|
||||||
# TODO: draw boxes and ellipses for non-circular Thangs
|
height = (@sprite.thang?.height ? 0) + 0.5
|
||||||
diameter = @sprite.thangType.get('shadow') ? @sprite.thang?.width + 0.5
|
longest = Math.max width, height
|
||||||
diameter *= Camera.PPM
|
actualLongest = @sprite.thangType.get('shadow') ? longest
|
||||||
|
width = width * actualLongest / longest
|
||||||
|
height = height * actualLongest / longest
|
||||||
|
width *= Camera.PPM
|
||||||
|
height *= Camera.PPM * @camera.y2x # TODO: doesn't work with rotation
|
||||||
@mark = new createjs.Shape()
|
@mark = new createjs.Shape()
|
||||||
@mark.mouseEnabled = false
|
@mark.mouseEnabled = false
|
||||||
@mark.graphics.beginFill "black"
|
@mark.graphics.beginFill "black"
|
||||||
@mark.graphics.drawEllipse 0, 0, diameter, diameter * @camera.y2x
|
if @sprite.thang.shape in ['ellipsoid', 'disc']
|
||||||
|
@mark.graphics.drawEllipse 0, 0, width, height
|
||||||
|
else
|
||||||
|
@mark.graphics.drawRect 0, 0, width, height
|
||||||
@mark.graphics.endFill()
|
@mark.graphics.endFill()
|
||||||
@mark.regX = diameter / 2
|
@mark.regX = width / 2
|
||||||
@mark.regY = diameter / 2 * @camera.y2x
|
@mark.regY = height / 2
|
||||||
@mark.layerIndex = 10
|
@mark.layerIndex = 10
|
||||||
#@mark.cache 0, 0, diameter, diameter # not actually faster than simple ellipse draw
|
#@mark.cache 0, 0, diameter, diameter # not actually faster than simple ellipse draw
|
||||||
|
|
||||||
|
buildRadius: ->
|
||||||
|
return # not implemented
|
||||||
|
|
||||||
buildDebug: ->
|
buildDebug: ->
|
||||||
@mark = new createjs.Shape()
|
@mark = new createjs.Shape()
|
||||||
PX = 3
|
PX = 3
|
||||||
|
@ -152,7 +162,7 @@ module.exports = class Mark extends CocoClass
|
||||||
@mark.y += offset.y
|
@mark.y += offset.y
|
||||||
|
|
||||||
updateRotation: ->
|
updateRotation: ->
|
||||||
if @name is 'debug'
|
if @name is 'debug' or (@name is 'shadow' and @sprite.thang?.shape in ["rectangle", "box"])
|
||||||
@mark.rotation = @sprite.thang.rotation * 180 / Math.PI
|
@mark.rotation = @sprite.thang.rotation * 180 / Math.PI
|
||||||
|
|
||||||
updateScale: ->
|
updateScale: ->
|
||||||
|
@ -174,3 +184,6 @@ module.exports = class Mark extends CocoClass
|
||||||
@mark.scaleX = @mark.scaleY = Math.min 1, scale
|
@mark.scaleX = @mark.scaleY = Math.min 1, scale
|
||||||
if @name in ['selection', 'target', 'repair']
|
if @name in ['selection', 'target', 'repair']
|
||||||
@mark.scaleY *= @camera.y2x # code applies perspective
|
@mark.scaleY *= @camera.y2x # code applies perspective
|
||||||
|
|
||||||
|
stop: -> @markSprite?.stop()
|
||||||
|
play: -> @markSprite?.play()
|
||||||
|
|
|
@ -20,6 +20,7 @@ module.exports = class SpriteBoss extends CocoClass
|
||||||
'level-lock-select': 'onSetLockSelect'
|
'level-lock-select': 'onSetLockSelect'
|
||||||
'level:restarted': 'onLevelRestarted'
|
'level:restarted': 'onLevelRestarted'
|
||||||
'god:new-world-created': 'onNewWorld'
|
'god:new-world-created': 'onNewWorld'
|
||||||
|
'tome:cast-spells': 'onCastSpells'
|
||||||
|
|
||||||
constructor: (@options) ->
|
constructor: (@options) ->
|
||||||
super()
|
super()
|
||||||
|
@ -205,6 +206,14 @@ module.exports = class SpriteBoss extends CocoClass
|
||||||
|
|
||||||
onNewWorld: (e) ->
|
onNewWorld: (e) ->
|
||||||
@world = @options.world = e.world
|
@world = @options.world = e.world
|
||||||
|
sprite.imageObject.play() for thangID, sprite of @sprites
|
||||||
|
@selectionMark?.play()
|
||||||
|
@targetMark?.play()
|
||||||
|
|
||||||
|
onCastSpells: ->
|
||||||
|
sprite.imageObject.stop() for thangID, sprite of @sprites
|
||||||
|
@selectionMark?.stop()
|
||||||
|
@targetMark?.stop()
|
||||||
|
|
||||||
# Selection
|
# Selection
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ CameraBorder = require './CameraBorder'
|
||||||
Layer = require './Layer'
|
Layer = require './Layer'
|
||||||
Letterbox = require './Letterbox'
|
Letterbox = require './Letterbox'
|
||||||
Dimmer = require './Dimmer'
|
Dimmer = require './Dimmer'
|
||||||
|
CastingScreen = require './CastingScreen'
|
||||||
DebugDisplay = require './DebugDisplay'
|
DebugDisplay = require './DebugDisplay'
|
||||||
CoordinateDisplay = require './CoordinateDisplay'
|
CoordinateDisplay = require './CoordinateDisplay'
|
||||||
SpriteBoss = require './SpriteBoss'
|
SpriteBoss = require './SpriteBoss'
|
||||||
|
@ -88,6 +89,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
@spriteBoss.destroy()
|
@spriteBoss.destroy()
|
||||||
@chooser?.destroy()
|
@chooser?.destroy()
|
||||||
@dimmer?.destroy()
|
@dimmer?.destroy()
|
||||||
|
@castingScreen?.destroy()
|
||||||
@stage.clear()
|
@stage.clear()
|
||||||
@musicPlayer?.destroy()
|
@musicPlayer?.destroy()
|
||||||
@stage.removeAllChildren()
|
@stage.removeAllChildren()
|
||||||
|
@ -224,7 +226,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
@currentFrame = actualCurrentFrame
|
@currentFrame = actualCurrentFrame
|
||||||
|
|
||||||
# TODO: are these needed, or perhaps do they duplicate things?
|
# TODO: are these needed, or perhaps do they duplicate things?
|
||||||
@spriteBoss.update()
|
@spriteBoss.update true
|
||||||
@onFrameChanged()
|
@onFrameChanged()
|
||||||
|
|
||||||
getCurrentFrame: ->
|
getCurrentFrame: ->
|
||||||
|
@ -299,11 +301,18 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
@lastFrame = @currentFrame
|
@lastFrame = @currentFrame
|
||||||
|
|
||||||
onCastSpells: (event) ->
|
onCastSpells: (event) ->
|
||||||
|
@casting = true
|
||||||
|
@wasPlayingWhenCastingBegan = @playing
|
||||||
|
Backbone.Mediator.publish 'level-set-playing', { playing: false }
|
||||||
|
|
||||||
createjs.Tween.removeTweens(@surfaceLayer)
|
createjs.Tween.removeTweens(@surfaceLayer)
|
||||||
createjs.Tween.get(@surfaceLayer).to({alpha:0.9}, 1000, createjs.Ease.getPowOut(4.0))
|
createjs.Tween.get(@surfaceLayer).to({alpha:0.9}, 1000, createjs.Ease.getPowOut(4.0))
|
||||||
|
|
||||||
onNewWorld: (event) ->
|
onNewWorld: (event) ->
|
||||||
return unless event.world.name is @world.name
|
return unless event.world.name is @world.name
|
||||||
|
@casting = false
|
||||||
|
Backbone.Mediator.publish 'level-set-playing', { playing: @wasPlayingWhenCastingBegan }
|
||||||
|
|
||||||
fastForwardTo = null
|
fastForwardTo = null
|
||||||
if @playing
|
if @playing
|
||||||
fastForwardTo = Math.min event.world.firstChangedFrame, @currentFrame
|
fastForwardTo = Math.min event.world.firstChangedFrame, @currentFrame
|
||||||
|
@ -340,6 +349,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
@surfaceLayer.addChild @cameraBorder = new CameraBorder bounds: @camera.bounds
|
@surfaceLayer.addChild @cameraBorder = new CameraBorder bounds: @camera.bounds
|
||||||
@screenLayer.addChild new Letterbox canvasWidth: canvasWidth, canvasHeight: canvasHeight
|
@screenLayer.addChild new Letterbox canvasWidth: canvasWidth, canvasHeight: canvasHeight
|
||||||
@spriteBoss = new SpriteBoss camera: @camera, surfaceLayer: @surfaceLayer, surfaceTextLayer: @surfaceTextLayer, world: @world, thangTypes: @options.thangTypes, choosing: @options.choosing, navigateToSelection: @options.navigateToSelection, showInvisible: @options.showInvisible
|
@spriteBoss = new SpriteBoss camera: @camera, surfaceLayer: @surfaceLayer, surfaceTextLayer: @surfaceTextLayer, world: @world, thangTypes: @options.thangTypes, choosing: @options.choosing, navigateToSelection: @options.navigateToSelection, showInvisible: @options.showInvisible
|
||||||
|
@castingScreen ?= new CastingScreen camera: @camera, layer: @screenLayer
|
||||||
@stage.enableMouseOver(10)
|
@stage.enableMouseOver(10)
|
||||||
@stage.addEventListener 'stagemousemove', @onMouseMove
|
@stage.addEventListener 'stagemousemove', @onMouseMove
|
||||||
@stage.addEventListener 'stagemousedown', @onMouseDown
|
@stage.addEventListener 'stagemousedown', @onMouseDown
|
||||||
|
@ -497,7 +507,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
updateState: (frameChanged) ->
|
updateState: (frameChanged) ->
|
||||||
# world state must have been restored in @updateSpriteSounds
|
# world state must have been restored in @updateSpriteSounds
|
||||||
@camera.updateZoom()
|
@camera.updateZoom()
|
||||||
@spriteBoss.update frameChanged
|
@spriteBoss.update frameChanged unless @casting
|
||||||
@dimmer?.setSprites @spriteBoss.sprites
|
@dimmer?.setSprites @spriteBoss.sprites
|
||||||
|
|
||||||
drawCurrentFrame: (e) ->
|
drawCurrentFrame: (e) ->
|
||||||
|
@ -508,6 +518,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
|
|
||||||
updatePaths: ->
|
updatePaths: ->
|
||||||
return unless @options.paths
|
return unless @options.paths
|
||||||
|
return if @casting
|
||||||
@hidePaths()
|
@hidePaths()
|
||||||
selectedThang = @spriteBoss.selectedSprite?.thang
|
selectedThang = @spriteBoss.selectedSprite?.thang
|
||||||
return if @world.showPaths is 'never'
|
return if @world.showPaths is 'never'
|
||||||
|
|
|
@ -24,7 +24,7 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
|
|
||||||
constructor: (thangType, options) ->
|
constructor: (thangType, options) ->
|
||||||
if options?.isSelf
|
if options?.isSelf
|
||||||
options.colorConfig = me.get('wizard')?.colorConfig or {}
|
options.colorConfig = _.cloneDeep(me.get('wizard')?.colorConfig) or {}
|
||||||
super thangType, options
|
super thangType, options
|
||||||
@isSelf = options.isSelf
|
@isSelf = options.isSelf
|
||||||
@targetPos = @thang.pos
|
@targetPos = @thang.pos
|
||||||
|
@ -59,7 +59,12 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
onMeSynced: (e) ->
|
onMeSynced: (e) ->
|
||||||
return unless @isSelf
|
return unless @isSelf
|
||||||
@setNameLabel me.displayName() if @displayObject.visible # not if we hid the wiz
|
@setNameLabel me.displayName() if @displayObject.visible # not if we hid the wiz
|
||||||
@setColorHue me.get('wizardColor1')
|
newColorConfig = me.get('wizard')?.colorConfig or {}
|
||||||
|
shouldUpdate = not _.isEqual(newColorConfig, @options.colorConfig)
|
||||||
|
@options.colorConfig = _.cloneDeep(newColorConfig)
|
||||||
|
if shouldUpdate
|
||||||
|
@setupSprite()
|
||||||
|
@playAction(@currentAction)
|
||||||
|
|
||||||
onSpriteSelected: (e) ->
|
onSpriteSelected: (e) ->
|
||||||
return unless @isSelf
|
return unless @isSelf
|
||||||
|
|
|
@ -55,7 +55,7 @@ module.exports = class World
|
||||||
@thangMap[thang.id] = thang
|
@thangMap[thang.id] = thang
|
||||||
|
|
||||||
thangDialogueSounds: ->
|
thangDialogueSounds: ->
|
||||||
if @frames.length < @totalFrames then worldShouldBeOverBeforeGrabbingDialogue
|
if @frames.length < @totalFrames then throw new Error("World should be over before grabbing dialogue")
|
||||||
[sounds, seen] = [[], {}]
|
[sounds, seen] = [[], {}]
|
||||||
for frame in @frames
|
for frame in @frames
|
||||||
for thangID, state of frame.thangStateMap
|
for thangID, state of frame.thangStateMap
|
||||||
|
@ -245,7 +245,7 @@ module.exports = class World
|
||||||
|
|
||||||
serialize: ->
|
serialize: ->
|
||||||
# Code hotspot; optimize it
|
# Code hotspot; optimize it
|
||||||
if @frames.length < @totalFrames then worldShouldBeOverBeforeSerialization
|
if @frames.length < @totalFrames then throw new Error("World Should Be Over Before Serialization")
|
||||||
[transferableObjects, nontransferableObjects] = [0, 0]
|
[transferableObjects, nontransferableObjects] = [0, 0]
|
||||||
o = {name: @name, totalFrames: @totalFrames, maxTotalFrames: @maxTotalFrames, frameRate: @frameRate, dt: @dt, victory: @victory, userCodeMap: {}, trackedProperties: {}}
|
o = {name: @name, totalFrames: @totalFrames, maxTotalFrames: @maxTotalFrames, frameRate: @frameRate, dt: @dt, victory: @victory, userCodeMap: {}, trackedProperties: {}}
|
||||||
o.trackedProperties[prop] = @[prop] for prop in @trackedProperties or []
|
o.trackedProperties[prop] = @[prop] for prop in @trackedProperties or []
|
||||||
|
|
|
@ -38,43 +38,3 @@
|
||||||
|
|
||||||
.form
|
.form
|
||||||
max-width: 600px
|
max-width: 600px
|
||||||
|
|
||||||
#wizard-settings-tab-view
|
|
||||||
#color-settings
|
|
||||||
float: left
|
|
||||||
width: 600px
|
|
||||||
margin-left: 30px
|
|
||||||
|
|
||||||
canvas
|
|
||||||
float: left
|
|
||||||
border: 2px solid black
|
|
||||||
margin: 20px
|
|
||||||
|
|
||||||
.color-group
|
|
||||||
clear: both
|
|
||||||
padding-bottom: 10px
|
|
||||||
margin-bottom: 10px
|
|
||||||
border-bottom: 1px solid gray
|
|
||||||
|
|
||||||
.name-cell
|
|
||||||
float: left
|
|
||||||
width: 100px
|
|
||||||
padding-top: 2px
|
|
||||||
|
|
||||||
input
|
|
||||||
margin-right: 10px
|
|
||||||
position: relative
|
|
||||||
top: -3px
|
|
||||||
|
|
||||||
.checkbox-cell
|
|
||||||
float: left
|
|
||||||
width: 40px
|
|
||||||
|
|
||||||
.slider-cell
|
|
||||||
margin-bottom: 10px
|
|
||||||
float: left
|
|
||||||
width: 120px
|
|
||||||
|
|
||||||
.selector
|
|
||||||
width: 100px
|
|
||||||
|
|
||||||
|
|
42
app/styles/account/wizard-settings.sass
Normal file
42
app/styles/account/wizard-settings.sass
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#wizard-settings-view
|
||||||
|
h3#loading
|
||||||
|
text-align: center
|
||||||
|
|
||||||
|
#color-settings
|
||||||
|
float: left
|
||||||
|
width: 600px
|
||||||
|
margin-left: 30px
|
||||||
|
|
||||||
|
canvas
|
||||||
|
float: left
|
||||||
|
border: 2px solid black
|
||||||
|
margin: 20px
|
||||||
|
|
||||||
|
.color-group
|
||||||
|
clear: both
|
||||||
|
padding-bottom: 10px
|
||||||
|
margin-bottom: 10px
|
||||||
|
border-bottom: 1px solid gray
|
||||||
|
|
||||||
|
.name-cell
|
||||||
|
float: left
|
||||||
|
width: 100px
|
||||||
|
padding-top: 2px
|
||||||
|
|
||||||
|
input
|
||||||
|
margin-right: 10px
|
||||||
|
position: relative
|
||||||
|
top: -3px
|
||||||
|
|
||||||
|
.checkbox-cell
|
||||||
|
float: left
|
||||||
|
width: 40px
|
||||||
|
|
||||||
|
.slider-cell
|
||||||
|
margin-bottom: 10px
|
||||||
|
float: left
|
||||||
|
width: 120px
|
||||||
|
|
||||||
|
.selector
|
||||||
|
width: 100px
|
||||||
|
|
|
@ -24,9 +24,9 @@
|
||||||
width: 300px
|
width: 300px
|
||||||
height: 80px
|
height: 80px
|
||||||
|
|
||||||
//@include transition(color .10s linear) // buggy in chrome, coloring doesn't get the right edge of the word
|
@include transition(color .10s linear)
|
||||||
|
|
||||||
&:hover a, &:active a
|
&:hover button, &:active button
|
||||||
color: #8090AA
|
color: #8090AA
|
||||||
|
|
||||||
canvas
|
canvas
|
||||||
|
|
|
@ -1,20 +1,17 @@
|
||||||
#wizard-settings-modal
|
#wizard-settings-modal
|
||||||
color: black
|
color: black
|
||||||
background: white
|
|
||||||
width: 400px
|
#wizard-settings-view #color-settings
|
||||||
|
width: 480px
|
||||||
|
|
||||||
canvas
|
canvas
|
||||||
border: 1px solid black
|
margin: 0px auto 20px
|
||||||
float: left
|
display: block
|
||||||
|
float: none
|
||||||
|
background: white
|
||||||
|
|
||||||
.settings
|
.wizard-name-line
|
||||||
width: 225px
|
text-align: center
|
||||||
margin: 10px
|
margin-bottom: 10px
|
||||||
display: inline-block
|
label
|
||||||
|
margin-right: 10px
|
||||||
.selector
|
|
||||||
margin: 10px 5px
|
|
||||||
|
|
||||||
button
|
|
||||||
margin-left: 10px
|
|
||||||
float: right
|
|
|
@ -20,3 +20,5 @@
|
||||||
white-space: nowrap
|
white-space: nowrap
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
|
|
||||||
|
#must-log-in button
|
||||||
|
margin-right: 10px
|
|
@ -5,3 +5,8 @@
|
||||||
#competitors-column .well
|
#competitors-column .well
|
||||||
font-size: 18px
|
font-size: 18px
|
||||||
padding: 7px
|
padding: 7px
|
||||||
|
|
||||||
|
#your-score
|
||||||
|
margin-top: 20px
|
||||||
|
text-align: center
|
||||||
|
font-size: 20px
|
|
@ -132,9 +132,21 @@
|
||||||
height: 100%
|
height: 100%
|
||||||
width: 2%
|
width: 2%
|
||||||
|
|
||||||
.footer:not(:hover)
|
.footer
|
||||||
@include opacity(0.6)
|
@media screen and (min-aspect-ratio: 17/10)
|
||||||
|
display: none
|
||||||
|
|
||||||
@media screen and (min-aspect-ratio: 17/10)
|
&:not(:hover)
|
||||||
#level-view .footer
|
@include opacity(0.6)
|
||||||
display: none
|
|
||||||
|
.hour-of-code-explanation
|
||||||
|
margin-top: 5px
|
||||||
|
color: white
|
||||||
|
font-size: 12px
|
||||||
|
|
||||||
|
&:not(:hover)
|
||||||
|
@include opacity(0.75)
|
||||||
|
|
||||||
|
a
|
||||||
|
color: white
|
||||||
|
text-decoration: underline
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
.executed
|
.executed
|
||||||
background-color: rgba(245, 255, 6, 0.18)
|
background-color: rgba(245, 255, 6, 0.18)
|
||||||
.problem-marker-info
|
.problem-marker-info
|
||||||
background-color: rgba(96, 63, 84, 0.25)
|
background-color: rgba(196, 163, 184, 0.25)
|
||||||
.problem-marker-warning
|
.problem-marker-warning
|
||||||
background-color: rgba(100, 65, 20, 0.25)
|
background-color: rgba(100, 65, 20, 0.25)
|
||||||
.problem-marker-error
|
.problem-marker-error
|
||||||
|
|
|
@ -9,16 +9,18 @@
|
||||||
border: 1px solid transparent
|
border: 1px solid transparent
|
||||||
cursor: pointer
|
cursor: pointer
|
||||||
@include user-select(all)
|
@include user-select(all)
|
||||||
|
::selection
|
||||||
|
background: transparent
|
||||||
|
|
||||||
&:hover
|
&:hover
|
||||||
border: 1px solid #BFF
|
border: 1px solid #000000
|
||||||
|
|
||||||
&.pinned
|
&.pinned
|
||||||
background-color: darken(#BFF, 20%)
|
background-color: darken(#FFFFFF, 25%)
|
||||||
|
|
||||||
// Pulling these colors from the most relevant textmate-theme classes
|
// Pulling these colors from the most relevant textmate-theme classes
|
||||||
&.function
|
&.function
|
||||||
color: #0000A2
|
color: #0066FF
|
||||||
&.object
|
&.object
|
||||||
color: rgb(6, 150, 14)
|
color: rgb(6, 150, 14)
|
||||||
&.string
|
&.string
|
||||||
|
|
|
@ -57,7 +57,7 @@ block content
|
||||||
a(href="http://en.gravatar.com/profiles/edit/?noclose#your-images", target="_blank", data-i18n="account_settings.gravatar_add_more_photos") Add more photos to your Gravatar account to access them here.
|
a(href="http://en.gravatar.com/profiles/edit/?noclose#your-images", target="_blank", data-i18n="account_settings.gravatar_add_more_photos") Add more photos to your Gravatar account to access them here.
|
||||||
|
|
||||||
#wizard-pane.tab-pane
|
#wizard-pane.tab-pane
|
||||||
#wizard-settings-tab-view
|
#wizard-settings-view
|
||||||
|
|
||||||
#password-pane.tab-pane
|
#password-pane.tab-pane
|
||||||
p
|
p
|
||||||
|
|
|
@ -8,7 +8,7 @@ canvas#tinting-display(width=200, height=200).img-rounded
|
||||||
span(data-i18n='wizard_settings.' + group.dasherized)= group.humanized
|
span(data-i18n='wizard_settings.' + group.dasherized)= group.humanized
|
||||||
div.sliders
|
div.sliders
|
||||||
div.slider-cell
|
div.slider-cell
|
||||||
label(for=group.humanized+"_hue", data-i18n="wizard_settigs.hue") Hue
|
label(for=group.humanized+"_hue", data-i18n="wizard_settings.hue") Hue
|
||||||
.selector(id=group.humanized+"_hue", name=group.name+'.hue', data-key='hue')
|
.selector(id=group.humanized+"_hue", name=group.name+'.hue', data-key='hue')
|
||||||
div.slider-cell
|
div.slider-cell
|
||||||
label(for=group.humanized+"_saturation", data-i18n="wizard_settings.saturation") Saturation
|
label(for=group.humanized+"_saturation", data-i18n="wizard_settings.saturation") Saturation
|
|
@ -4,19 +4,17 @@ block modal-header-content
|
||||||
h3(data-i18n="wizard_settings.title") Wizard Settings
|
h3(data-i18n="wizard_settings.title") Wizard Settings
|
||||||
|
|
||||||
block modal-body-content
|
block modal-body-content
|
||||||
h4(data-i18n="wizard_settings.customize_avatar") Customize Your Avatar
|
div.wizard-name-line.form-group
|
||||||
|
label.control-label(for="name")
|
||||||
|
| Name
|
||||||
|
input#wizard-settings-name(name="name", type="text", value="#{me.get('name')||''}")
|
||||||
|
|
||||||
canvas(width="120px", height="150px")
|
#wizard-settings-view
|
||||||
.settings
|
|
||||||
.form-vertical.form
|
block modal-body-wait-content
|
||||||
.form-group
|
h3 Saving...
|
||||||
label.control-label(for="name")
|
.progress.progress-striped.active
|
||||||
| Name
|
.progress-bar
|
||||||
button.btn.btn-mini.btn-primary#random-name Random
|
|
||||||
input#wizard-settings-name(name="name", type="text", value="#{me.get('name')||''}")
|
|
||||||
.form-group
|
|
||||||
label.control-label(for="wizardColor1") Hat Color
|
|
||||||
.selector#wizard-settings-color-1
|
|
||||||
|
|
||||||
block modal-footer-content
|
block modal-footer-content
|
||||||
button.btn.btn-primary.btn-large#wizard-settings-done(type="button", data-dismiss="modal", aria-hidden="true") Done
|
button.btn.btn-primary.btn-large#wizard-settings-done(type="button") Done
|
||||||
|
|
|
@ -6,47 +6,58 @@ block content
|
||||||
div#level-description
|
div#level-description
|
||||||
!{description}
|
!{description}
|
||||||
|
|
||||||
a(href="http://www.youtube.com/watch?v=IFvfZiJGDsw&list=HL1392928835&feature=mh_lolz").intro-button.btn.btn-primary.btn-lg Watch the Video
|
if !me.get('anonymous')
|
||||||
|
a(href="http://www.youtube.com/watch?v=IFvfZiJGDsw&list=HL1392928835&feature=mh_lolz").intro-button.btn.btn-primary.btn-lg Watch the Video
|
||||||
|
|
||||||
a(href="/play/level/ladder-tutorial").intro-button.btn.btn-primary.btn-lg Play the Tutorial
|
a(href="/play/level/ladder-tutorial").intro-button.btn.btn-primary.btn-lg Play the Tutorial
|
||||||
|
|
||||||
hr
|
hr
|
||||||
div#columns.row
|
|
||||||
for team in teams
|
|
||||||
div.column.col-md-6
|
|
||||||
a(href="/play/ladder/#{levelID}/team/#{team.id}", style="background-color: #{team.primaryColor}").play-button.btn.btn-danger.btn-block.btn-lg
|
|
||||||
span Play As
|
|
||||||
span= team.name
|
|
||||||
|
|
||||||
table.table.table-bordered.table-condensed.table-hover
|
if me.get('anonymous')
|
||||||
//(style="background-color: #{team.bgColor}")
|
div#must-log-in
|
||||||
tr
|
p
|
||||||
th(colspan=3, style="color: #{team.primaryColor}")
|
strong Please log in first before playing a ladder game.
|
||||||
span= team.name
|
button.btn.btn-primary(data-toggle="coco-modal", data-target="modal/login", data-i18n="login.log_in") Log In
|
||||||
span Leaderboard
|
button.btn.btn-primary(data-toggle="coco-modal", data-target="modal/signup", data-i18n="login.sign_up") Create Account
|
||||||
tr
|
|
||||||
th Score
|
|
||||||
th.name-col-cell Name
|
|
||||||
th
|
|
||||||
|
|
||||||
for session in team.leaderboard.topPlayers.models
|
|
||||||
- var myRow = session.get('creator') == me.id
|
|
||||||
tr(class=myRow ? "success" : "")
|
|
||||||
td.score-cell= session.get('totalScore').toFixed(2)
|
|
||||||
td.name-col-cell= session.get('creatorName') || "Anonymous"
|
|
||||||
td
|
|
||||||
if(!myRow)
|
|
||||||
a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}") Battle as #{team.otherTeam}!
|
|
||||||
else
|
|
||||||
a(href="/play/ladder/#{levelID}/team/#{team.id}") View your #{team.id} matches.
|
|
||||||
|
|
||||||
unless me.attributes.anonymous
|
else
|
||||||
hr
|
div#columns.row
|
||||||
button.btn.btn-warning.btn-lg.highlight#simulate-button(style="margin-bottom:10px;") Simulate Games!
|
for team in teams
|
||||||
p(id="simulation-status-text", style="display:inline; margin-left:10px;")
|
div.column.col-md-6
|
||||||
if simulationStatus
|
a(href="/play/ladder/#{levelID}/team/#{team.id}", style="background-color: #{team.primaryColor}").play-button.btn.btn-danger.btn-block.btn-lg
|
||||||
| #{simulationStatus}
|
span Play As
|
||||||
else
|
span= team.name
|
||||||
| By simulating games you can get your game ranked faster!
|
|
||||||
if me.isAdmin()
|
table.table.table-bordered.table-condensed.table-hover
|
||||||
button.btn.btn-danger.btn-lg.highlight#simulate-all-button(style="margin-bottom:10px; float: right;") RESET AND SIMULATE GAMES
|
//(style="background-color: #{team.bgColor}")
|
||||||
|
tr
|
||||||
|
th(colspan=3, style="color: #{team.primaryColor}")
|
||||||
|
span= team.name
|
||||||
|
span Leaderboard
|
||||||
|
tr
|
||||||
|
th Score
|
||||||
|
th.name-col-cell Name
|
||||||
|
th
|
||||||
|
|
||||||
|
for session in team.leaderboard.topPlayers.models
|
||||||
|
- var myRow = session.get('creator') == me.id
|
||||||
|
tr(class=myRow ? "success" : "")
|
||||||
|
td.score-cell= session.get('totalScore').toFixed(2)
|
||||||
|
td.name-col-cell= session.get('creatorName') || "Anonymous"
|
||||||
|
td
|
||||||
|
if(!myRow)
|
||||||
|
a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}") Battle as #{team.otherTeam}!
|
||||||
|
else
|
||||||
|
a(href="/play/ladder/#{levelID}/team/#{team.id}") View your #{team.id} matches.
|
||||||
|
|
||||||
|
unless me.attributes.anonymous
|
||||||
|
hr
|
||||||
|
button.btn.btn-warning.btn-lg.highlight#simulate-button(style="margin-bottom:10px;") Simulate Games!
|
||||||
|
p(id="simulation-status-text", style="display:inline; margin-left:10px;")
|
||||||
|
if simulationStatus
|
||||||
|
| #{simulationStatus}
|
||||||
|
else
|
||||||
|
| By simulating games you can get your game ranked faster!
|
||||||
|
if me.isAdmin()
|
||||||
|
button.btn.btn-danger.btn-lg.highlight#simulate-all-button(style="margin-bottom:10px; float: right;") RESET AND SIMULATE GAMES
|
|
@ -16,6 +16,13 @@ block content
|
||||||
p
|
p
|
||||||
| After your first submission, your code will also continuously run against other players as they rank themselves.
|
| After your first submission, your code will also continuously run against other players as they rank themselves.
|
||||||
|
|
||||||
|
if matches.length
|
||||||
|
p#your-score
|
||||||
|
span Your Current Score:
|
||||||
|
span
|
||||||
|
strong= score
|
||||||
|
|
||||||
|
|
||||||
div#columns.row
|
div#columns.row
|
||||||
div#matches-column.col-md-6
|
div#matches-column.col-md-6
|
||||||
h3.pull-left Ranked Games
|
h3.pull-left Ranked Games
|
||||||
|
|
|
@ -27,3 +27,11 @@
|
||||||
.content
|
.content
|
||||||
p(class='footer-link-text')
|
p(class='footer-link-text')
|
||||||
a(title='Send CodeCombat a message', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="nav.contact") Contact
|
a(title='Send CodeCombat a message', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="nav.contact") Contact
|
||||||
|
if explainHourOfCode
|
||||||
|
// Does not show up unless lang is en-US.
|
||||||
|
div.hour-of-code-explanation
|
||||||
|
| The 'Hour of Code' is a nationwide initiative by
|
||||||
|
a(href="http://csedweek.org") Computer Science Education Week
|
||||||
|
| and
|
||||||
|
a(href="http://code.org") Code.org
|
||||||
|
| to introduce millions of students to one hour of computer science and computer programming.
|
|
@ -1,6 +1,7 @@
|
||||||
.thang-avatar-wrapper(class="team-" + (thang.team || "neutral"))
|
.thang-avatar-wrapper(class="team-" + (thang.team || "neutral"))
|
||||||
//canvas(width=100, height=100, title=thang.id + " - " + thang.team)
|
//canvas(width=100, height=100, title=thang.id + " - " + thang.team)
|
||||||
img.img-responsive(src=avatarURL, title=thang.id + " - " + thang.team)
|
- var title = thang.id + " - " + thang.team + (thang.type ? ' - type: "' + thang.type + '"' : '')
|
||||||
|
img.img-responsive(src=avatarURL, title=title)
|
||||||
.badge.problems
|
.badge.problems
|
||||||
.badge.shared-thangs
|
.badge.shared-thangs
|
||||||
if includeName
|
if includeName
|
||||||
|
|
|
@ -4,7 +4,7 @@ template = require 'templates/account/settings'
|
||||||
forms = require('lib/forms')
|
forms = require('lib/forms')
|
||||||
User = require('models/User')
|
User = require('models/User')
|
||||||
|
|
||||||
WizardSettingsTabView = require './wizard_settings_tab_view'
|
WizardSettingsView = require './wizard_settings_view'
|
||||||
|
|
||||||
module.exports = class SettingsView extends View
|
module.exports = class SettingsView extends View
|
||||||
id: 'account-settings-view'
|
id: 'account-settings-view'
|
||||||
|
@ -26,11 +26,12 @@ module.exports = class SettingsView extends View
|
||||||
|
|
||||||
refreshPicturePane: =>
|
refreshPicturePane: =>
|
||||||
h = $(@template(@getRenderData()))
|
h = $(@template(@getRenderData()))
|
||||||
new_pane = $('#picture-pane', h)
|
newPane = $('#picture-pane', h)
|
||||||
old_pane = $('#picture-pane')
|
oldPane = $('#picture-pane')
|
||||||
active = old_pane.hasClass('active')
|
active = oldPane.hasClass('active')
|
||||||
old_pane.replaceWith(new_pane)
|
oldPane.replaceWith(newPane)
|
||||||
new_pane.addClass('active') if active
|
newPane.i18n()
|
||||||
|
newPane.addClass('active') if active
|
||||||
|
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
super()
|
super()
|
||||||
|
@ -46,9 +47,9 @@ module.exports = class SettingsView extends View
|
||||||
|
|
||||||
@chooseTab(location.hash.replace('#',''))
|
@chooseTab(location.hash.replace('#',''))
|
||||||
@updateWizardColor()
|
@updateWizardColor()
|
||||||
wizardSettingsTabView = new WizardSettingsTabView()
|
WizardSettingsView = new WizardSettingsView()
|
||||||
wizardSettingsTabView.on 'change', @save, @
|
WizardSettingsView.on 'change', @save, @
|
||||||
@insertSubView wizardSettingsTabView
|
@insertSubView WizardSettingsView
|
||||||
|
|
||||||
chooseTab: (category) ->
|
chooseTab: (category) ->
|
||||||
id = "##{category}-pane"
|
id = "##{category}-pane"
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
RootView = require 'views/kinds/RootView'
|
CocoView = require 'views/kinds/CocoView'
|
||||||
template = require 'templates/account/wizard_settings_tab'
|
template = require 'templates/account/wizard_settings'
|
||||||
{me} = require('lib/auth')
|
{me} = require('lib/auth')
|
||||||
ThangType = require 'models/ThangType'
|
ThangType = require 'models/ThangType'
|
||||||
SpriteBuilder = require 'lib/sprites/SpriteBuilder'
|
SpriteBuilder = require 'lib/sprites/SpriteBuilder'
|
||||||
|
|
||||||
module.exports = class WizardSettingsTabView extends RootView
|
module.exports = class WizardSettingsView extends CocoView
|
||||||
id: 'wizard-settings-tab-view'
|
id: 'wizard-settings-view'
|
||||||
template: template
|
template: template
|
||||||
|
startsLoading: true
|
||||||
|
|
||||||
events:
|
events:
|
||||||
'change .color-group-checkbox': (e) ->
|
'change .color-group-checkbox': (e) ->
|
||||||
|
@ -25,6 +26,7 @@ module.exports = class WizardSettingsTabView extends RootView
|
||||||
@wizardThangType.once 'sync', @initCanvas, @
|
@wizardThangType.once 'sync', @initCanvas, @
|
||||||
|
|
||||||
initCanvas: ->
|
initCanvas: ->
|
||||||
|
@startsLoading = false
|
||||||
@render()
|
@render()
|
||||||
@spriteBuilder = new SpriteBuilder(@wizardThangType)
|
@spriteBuilder = new SpriteBuilder(@wizardThangType)
|
||||||
@initStage()
|
@initStage()
|
||||||
|
@ -44,6 +46,7 @@ module.exports = class WizardSettingsTabView extends RootView
|
||||||
c
|
c
|
||||||
|
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
|
return if @startsLoading
|
||||||
wizardSettings = me.get('wizard') or {}
|
wizardSettings = me.get('wizard') or {}
|
||||||
wizardSettings.colorConfig ?= {}
|
wizardSettings.colorConfig ?= {}
|
||||||
|
|
||||||
|
@ -82,8 +85,6 @@ module.exports = class WizardSettingsTabView extends RootView
|
||||||
initStage: ->
|
initStage: ->
|
||||||
@stage = new createjs.Stage(@$el.find('canvas')[0])
|
@stage = new createjs.Stage(@$el.find('canvas')[0])
|
||||||
@updateMovieClip()
|
@updateMovieClip()
|
||||||
createjs.Ticker.setFPS 20
|
|
||||||
createjs.Ticker.addEventListener("tick", @stage)
|
|
||||||
|
|
||||||
updateMovieClip: ->
|
updateMovieClip: ->
|
||||||
return unless @wizardThangType.loaded
|
return unless @wizardThangType.loaded
|
||||||
|
@ -104,6 +105,3 @@ module.exports = class WizardSettingsTabView extends RootView
|
||||||
@movieClip.regY = reg.y
|
@movieClip.regY = reg.y
|
||||||
@stage.addChild @movieClip
|
@stage.addChild @movieClip
|
||||||
@stage.update()
|
@stage.update()
|
||||||
|
|
||||||
destroy: ->
|
|
||||||
@stage?.removeAllEventListeners()
|
|
|
@ -48,15 +48,10 @@ module.exports = class ThangsTabView extends View
|
||||||
'click #extant-thangs-filter button': 'onFilterExtantThangs'
|
'click #extant-thangs-filter button': 'onFilterExtantThangs'
|
||||||
|
|
||||||
shortcuts:
|
shortcuts:
|
||||||
'esc': -> @selectAddThang()
|
'esc': 'selectAddThang'
|
||||||
|
'delete, del, backspace': 'deleteSelectedExtantThang'
|
||||||
onFilterExtantThangs: (e) ->
|
'left': -> @moveAddThangSelection -1
|
||||||
button = $(e.target).closest('button')
|
'right': -> @moveAddThangSelection 1
|
||||||
button.button('toggle')
|
|
||||||
val = button.val()
|
|
||||||
@thangsTreema.$el.removeClass(@lastHideClass) if @lastHideClass
|
|
||||||
@thangsTreema.$el.addClass(@lastHideClass = "hide-except-#{val}") if val
|
|
||||||
|
|
||||||
|
|
||||||
constructor: (options) ->
|
constructor: (options) ->
|
||||||
super options
|
super options
|
||||||
|
@ -102,12 +97,12 @@ module.exports = class ThangsTabView extends View
|
||||||
$('#thangs-list').bind 'mousewheel', @preventBodyScrollingInThangList
|
$('#thangs-list').bind 'mousewheel', @preventBodyScrollingInThangList
|
||||||
@$el.find('#extant-thangs-filter button:first').button('toggle')
|
@$el.find('#extant-thangs-filter button:first').button('toggle')
|
||||||
|
|
||||||
# TODO: move these into the shortcuts list
|
onFilterExtantThangs: (e) ->
|
||||||
key 'left', _.bind @moveAddThangSelection, @, -1
|
button = $(e.target).closest('button')
|
||||||
key 'right', _.bind @moveAddThangSelection, @, 1
|
button.button('toggle')
|
||||||
key 'delete, del, backspace', @deleteSelectedExtantThang
|
val = button.val()
|
||||||
key 'f', => Backbone.Mediator.publish('level-set-debug', debug: not @surface.debug)
|
@thangsTreema.$el.removeClass(@lastHideClass) if @lastHideClass
|
||||||
key 'g', => Backbone.Mediator.publish('level-set-grid', grid: not @surface.gridShowing())
|
@thangsTreema.$el.addClass(@lastHideClass = "hide-except-#{val}") if val
|
||||||
|
|
||||||
preventBodyScrollingInThangList: (e) ->
|
preventBodyScrollingInThangList: (e) ->
|
||||||
@scrollTop += (if e.deltaY < 0 then 1 else -1) * 30
|
@scrollTop += (if e.deltaY < 0 then 1 else -1) * 30
|
||||||
|
|
|
@ -129,7 +129,7 @@ module.exports = class CocoView extends Backbone.View
|
||||||
# Loading RootViews
|
# Loading RootViews
|
||||||
|
|
||||||
showLoading: ($el=@$el) ->
|
showLoading: ($el=@$el) ->
|
||||||
$el.find('>').hide()
|
$el.find('>').addClass('hidden')
|
||||||
$el.append($('<div class="loading-screen"></div>')
|
$el.append($('<div class="loading-screen"></div>')
|
||||||
.append('<h2>Loading</h2>')
|
.append('<h2>Loading</h2>')
|
||||||
.append('<div class="progress progress-striped active loading"><div class="progress-bar"></div></div>'))
|
.append('<div class="progress progress-striped active loading"><div class="progress-bar"></div></div>'))
|
||||||
|
@ -138,7 +138,7 @@ module.exports = class CocoView extends Backbone.View
|
||||||
hideLoading: ->
|
hideLoading: ->
|
||||||
return unless @_lastLoading?
|
return unless @_lastLoading?
|
||||||
@_lastLoading.find('.loading-screen').remove()
|
@_lastLoading.find('.loading-screen').remove()
|
||||||
@_lastLoading.find('>').show()
|
@_lastLoading.find('>').removeClass('hidden')
|
||||||
@_lastLoading = null
|
@_lastLoading = null
|
||||||
|
|
||||||
# Loading ModalViews
|
# Loading ModalViews
|
||||||
|
|
|
@ -22,8 +22,8 @@ module.exports = class RootView extends CocoView
|
||||||
logoutUser($('#login-email').val())
|
logoutUser($('#login-email').val())
|
||||||
|
|
||||||
showWizardSettingsModal: ->
|
showWizardSettingsModal: ->
|
||||||
WizardSettingsView = require('views/modal/wizard_settings_modal')
|
WizardSettingsModal = require('views/modal/wizard_settings_modal')
|
||||||
subview = new WizardSettingsView {}
|
subview = new WizardSettingsModal {}
|
||||||
@openModalView subview
|
@openModalView subview
|
||||||
|
|
||||||
showLoading: ($el) ->
|
showLoading: ($el) ->
|
||||||
|
|
|
@ -2,79 +2,44 @@ View = require 'views/kinds/ModalView'
|
||||||
template = require 'templates/modal/wizard_settings'
|
template = require 'templates/modal/wizard_settings'
|
||||||
WizardSprite = require 'lib/surface/WizardSprite'
|
WizardSprite = require 'lib/surface/WizardSprite'
|
||||||
ThangType = require 'models/ThangType'
|
ThangType = require 'models/ThangType'
|
||||||
|
{me} = require 'lib/auth'
|
||||||
|
forms = require('lib/forms')
|
||||||
|
|
||||||
module.exports = class WizardSettingsView extends View
|
module.exports = class WizardSettingsModal extends View
|
||||||
id: "wizard-settings-modal"
|
id: "wizard-settings-modal"
|
||||||
template: template
|
template: template
|
||||||
closesOnClickOutside: false
|
closesOnClickOutside: false
|
||||||
|
|
||||||
events:
|
events:
|
||||||
'change #wizard-settings-name': 'onNameChange'
|
'change #wizard-settings-name': 'onNameChange'
|
||||||
'click #random-name': 'onRandomNameClick'
|
'click #wizard-settings-done': 'onWizardSettingsDone'
|
||||||
'click #wizard-settings-done': 'saveSettings'
|
|
||||||
|
|
||||||
render: ->
|
|
||||||
me.set('name', @randomName()) if not me.get('name')
|
|
||||||
super()
|
|
||||||
|
|
||||||
onRandomNameClick: =>
|
|
||||||
$('#wizard-settings-name').val(@randomName())
|
|
||||||
@saveSettings()
|
|
||||||
|
|
||||||
randomName: ->
|
|
||||||
return NameGenerator.getName(7, 9)
|
|
||||||
|
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
super()
|
WizardSettingsView = require 'views/account/wizard_settings_view'
|
||||||
@colorSlider = $( "#wizard-settings-color-1", @$el).slider({ animate: "fast" })
|
view = new WizardSettingsView()
|
||||||
@colorSlider.slider('value', me.get('wizardColor1')*100)
|
@insertSubView view
|
||||||
@colorSlider.on('slide',@onSliderChange)
|
|
||||||
@colorSlider.on('slidechange',@onSliderChange)
|
|
||||||
@stage = new createjs.Stage($('canvas', @$el)[0])
|
|
||||||
@saveChanges = _.debounce(@saveChanges, 1000)
|
|
||||||
|
|
||||||
wizOriginal = "52a00d55cf1818f2be00000b"
|
onNameChange: ->
|
||||||
url = "/db/thang_type/#{wizOriginal}/version"
|
|
||||||
@wizardType = new ThangType()
|
|
||||||
@wizardType.url = -> url
|
|
||||||
@wizardType.fetch()
|
|
||||||
@wizardType.once 'sync', @initCanvas
|
|
||||||
|
|
||||||
initCanvas: =>
|
|
||||||
spriteOptions = thangID: "Config Wizard", resolutionFactor: 3
|
|
||||||
@wizardSprite = new WizardSprite @wizardType, spriteOptions
|
|
||||||
@wizardSprite.setColorHue(me.get('wizardColor1'))
|
|
||||||
@wizardDisplayObject = @wizardSprite.displayObject
|
|
||||||
@wizardDisplayObject.x = 10
|
|
||||||
@wizardDisplayObject.y = 15
|
|
||||||
@wizardDisplayObject.scaleX = @wizardDisplayObject.scaleY = 3.0
|
|
||||||
@stage.addChild(@wizardDisplayObject)
|
|
||||||
@updateSpriteColor()
|
|
||||||
@stage.update()
|
|
||||||
|
|
||||||
onSliderChange: =>
|
|
||||||
@updateSpriteColor()
|
|
||||||
@saveSettings()
|
|
||||||
|
|
||||||
getColorHue: ->
|
|
||||||
@colorSlider.slider('value') / 100
|
|
||||||
|
|
||||||
updateSpriteColor: ->
|
|
||||||
colorHue = @getColorHue()
|
|
||||||
@wizardSprite.setColorHue(colorHue)
|
|
||||||
@stage.update()
|
|
||||||
|
|
||||||
onNameChange: =>
|
|
||||||
@saveSettings()
|
|
||||||
|
|
||||||
saveSettings: ->
|
|
||||||
me.set('name', $('#wizard-settings-name').val())
|
me.set('name', $('#wizard-settings-name').val())
|
||||||
me.set('wizardColor1', @getColorHue())
|
|
||||||
@saveChanges()
|
|
||||||
|
|
||||||
saveChanges: ->
|
onWizardSettingsDone: ->
|
||||||
|
forms.clearFormAlerts(@$el)
|
||||||
|
res = me.validate()
|
||||||
|
if res?
|
||||||
|
forms.applyErrorsToForm(@$el, res)
|
||||||
|
return
|
||||||
|
|
||||||
|
res = me.save()
|
||||||
|
return unless res
|
||||||
|
save = $('#save-button', @$el).text($.i18n.t('common.saving', defaultValue: 'Saving...'))
|
||||||
|
.addClass('btn-info').show().removeClass('btn-danger')
|
||||||
|
|
||||||
|
res.error =>
|
||||||
|
errors = JSON.parse(res.responseText)
|
||||||
|
forms.applyErrorsToForm(@$el, errors)
|
||||||
|
@disableModalInProgress(@$el)
|
||||||
|
res.success (model, response, options) =>
|
||||||
|
@hide()
|
||||||
|
|
||||||
|
@enableModalInProgress(@$el)
|
||||||
me.save()
|
me.save()
|
||||||
|
|
||||||
destroy: ->
|
|
||||||
@wizardSprite?.destroy()
|
|
||||||
super()
|
|
||||||
|
|
|
@ -90,6 +90,7 @@ module.exports = class LadderTeamView extends RootView
|
||||||
|
|
||||||
ctx.matches = (convertMatch(match) for match in @session.get('matches') or [])
|
ctx.matches = (convertMatch(match) for match in @session.get('matches') or [])
|
||||||
ctx.matches.reverse()
|
ctx.matches.reverse()
|
||||||
|
ctx.score = (@session.get('totalScore') or 10).toFixed(2)
|
||||||
ctx
|
ctx
|
||||||
|
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
|
|
|
@ -36,8 +36,8 @@ module.exports = class PlaybackView extends View
|
||||||
|
|
||||||
shortcuts:
|
shortcuts:
|
||||||
'⌘+p, p, ctrl+p': 'onTogglePlay'
|
'⌘+p, p, ctrl+p': 'onTogglePlay'
|
||||||
'[': 'onScrubBack'
|
'⌘+[, ctrl+[': 'onScrubBack'
|
||||||
']': 'onScrubForward'
|
'⌘+], ctrl+]': 'onScrubForward'
|
||||||
|
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super(arguments...)
|
super(arguments...)
|
||||||
|
@ -169,7 +169,7 @@ module.exports = class PlaybackView extends View
|
||||||
if @clickingSlider
|
if @clickingSlider
|
||||||
@clickingSlider = false
|
@clickingSlider = false
|
||||||
@wasPlaying = false
|
@wasPlaying = false
|
||||||
@onSetPlaying {playing: false}
|
Backbone.Mediator.publish 'level-set-playing', {playing: false}
|
||||||
@$el.find('.scrubber-handle').effect('bounce', {times: 2})
|
@$el.find('.scrubber-handle').effect('bounce', {times: 2})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ module.exports = class CastButtonView extends View
|
||||||
@spells = options.spells
|
@spells = options.spells
|
||||||
@levelID = options.levelID
|
@levelID = options.levelID
|
||||||
isMac = navigator.platform.toUpperCase().indexOf('MAC') isnt -1
|
isMac = navigator.platform.toUpperCase().indexOf('MAC') isnt -1
|
||||||
@castShortcut = "⇧↩"
|
@castShortcut = "⇧↵"
|
||||||
@castShortcutVerbose = "Shift+Enter"
|
@castShortcutVerbose = "Shift+Enter"
|
||||||
|
|
||||||
getRenderData: (context={}) ->
|
getRenderData: (context={}) ->
|
||||||
|
@ -35,7 +35,7 @@ module.exports = class CastButtonView extends View
|
||||||
# TODO: use a User setting instead of localStorage
|
# TODO: use a User setting instead of localStorage
|
||||||
delay = localStorage.getItem 'autocastDelay'
|
delay = localStorage.getItem 'autocastDelay'
|
||||||
delay ?= 5000
|
delay ?= 5000
|
||||||
if @levelID is 'project-dota'
|
if @levelID in ['project-dota', 'brawlwood', 'ladder-tutorial']
|
||||||
delay = 90019001
|
delay = 90019001
|
||||||
@setAutocastDelay delay
|
@setAutocastDelay delay
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,10 @@ module.exports = class DebugView extends View
|
||||||
@ace = options.ace
|
@ace = options.ace
|
||||||
@thang = options.thang
|
@thang = options.thang
|
||||||
@variableStates = {}
|
@variableStates = {}
|
||||||
|
@globals = {Math: Math, _: _} # ... add more as documented
|
||||||
|
for className, klass of serializedClasses
|
||||||
|
@globals[className] = klass
|
||||||
|
@onMouseMove = _.throttle @onMouseMove, 25
|
||||||
|
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
super()
|
super()
|
||||||
|
@ -30,10 +34,11 @@ module.exports = class DebugView extends View
|
||||||
@update()
|
@update()
|
||||||
|
|
||||||
onMouseMove: (e) =>
|
onMouseMove: (e) =>
|
||||||
|
return if @destroyed
|
||||||
pos = e.getDocumentPosition()
|
pos = e.getDocumentPosition()
|
||||||
endOfDoc = pos.row is @ace.getSession().getDocument().getLength() - 1
|
endOfDoc = pos.row is @ace.getSession().getDocument().getLength() - 1
|
||||||
it = new TokenIterator e.editor.session, pos.row, pos.column
|
it = new TokenIterator e.editor.session, pos.row, pos.column
|
||||||
isIdentifier = (t) -> t and (t.type is 'identifier' or t.value is 'this')
|
isIdentifier = (t) => t and (t.type is 'identifier' or t.value is 'this' or @globals[t.value])
|
||||||
while it.getCurrentTokenRow() is pos.row and not isIdentifier(token = it.getCurrentToken())
|
while it.getCurrentTokenRow() is pos.row and not isIdentifier(token = it.getCurrentToken())
|
||||||
it.stepBackward()
|
it.stepBackward()
|
||||||
break unless token
|
break unless token
|
||||||
|
@ -52,7 +57,7 @@ module.exports = class DebugView extends View
|
||||||
token = prev
|
token = prev
|
||||||
start = it.getCurrentTokenColumn()
|
start = it.getCurrentTokenColumn()
|
||||||
chain.unshift token.value
|
chain.unshift token.value
|
||||||
if token and (token.value of @variableStates or token.value is "this")
|
if token and (token.value of @variableStates or token.value is "this" or @globals[token.value])
|
||||||
@variableChain = chain
|
@variableChain = chain
|
||||||
offsetX = e.domEvent.offsetX ? e.clientX - $(e.domEvent.target).offset().left
|
offsetX = e.domEvent.offsetX ? e.clientX - $(e.domEvent.target).offset().left
|
||||||
offsetY = e.domEvent.offsetY ? e.clientY - $(e.domEvent.target).offset().top
|
offsetY = e.domEvent.offsetY ? e.clientY - $(e.domEvent.target).offset().top
|
||||||
|
@ -76,6 +81,10 @@ module.exports = class DebugView extends View
|
||||||
@$el.show().css(@pos)
|
@$el.show().css(@pos)
|
||||||
else
|
else
|
||||||
@$el.hide()
|
@$el.hide()
|
||||||
|
if @variableChain?.length is 2
|
||||||
|
Backbone.Mediator.publish 'tome:spell-debug-property-hovered', property: @variableChain[1], owner: @variableChain[0]
|
||||||
|
else
|
||||||
|
Backbone.Mediator.publish 'tome:spell-debug-property-hovered', property: null
|
||||||
@updateMarker()
|
@updateMarker()
|
||||||
|
|
||||||
updateMarker: ->
|
updateMarker: ->
|
||||||
|
@ -92,7 +101,7 @@ module.exports = class DebugView extends View
|
||||||
return "<this #{value.id}>" if value is @thang and depth
|
return "<this #{value.id}>" if value is @thang and depth
|
||||||
if depth is 2
|
if depth is 2
|
||||||
if value.constructor?.className is "Thang"
|
if value.constructor?.className is "Thang"
|
||||||
value = "<#{value.spriteName} - #{value.id}, #{if value.pos then value.pos.toString() else 'non-physical'}>"
|
value = "<#{value.type or value.spriteName} - #{value.id}, #{if value.pos then value.pos.toString() else 'non-physical'}>"
|
||||||
else
|
else
|
||||||
value = value.toString()
|
value = value.toString()
|
||||||
return value
|
return value
|
||||||
|
@ -124,8 +133,11 @@ module.exports = class DebugView extends View
|
||||||
for prop, i in chain
|
for prop, i in chain
|
||||||
if prop is "this"
|
if prop is "this"
|
||||||
value = @thang
|
value = @thang
|
||||||
|
else if i is 0
|
||||||
|
value = @variableStates[prop]
|
||||||
|
if typeof value is "undefined" then value = @globals[prop]
|
||||||
else
|
else
|
||||||
value = (if i is 0 then @variableStates else value)[prop]
|
value = value[prop]
|
||||||
keys.push prop
|
keys.push prop
|
||||||
break unless value
|
break unless value
|
||||||
if theClass = serializedClasses[value.CN]
|
if theClass = serializedClasses[value.CN]
|
||||||
|
|
|
@ -74,7 +74,7 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView
|
||||||
formatPopover: (doc) ->
|
formatPopover: (doc) ->
|
||||||
content = popoverTemplate doc: doc, marked: marked, argumentExamples: (arg.example or arg.default or arg.name for arg in doc.args ? [])
|
content = popoverTemplate doc: doc, marked: marked, argumentExamples: (arg.example or arg.default or arg.name for arg in doc.args ? [])
|
||||||
owner = @thang
|
owner = @thang
|
||||||
content = content.replace /#{spriteName}/g, @thang.spriteName # No quotes like we'd get with @formatValue
|
content = content.replace /#{spriteName}/g, @thang.type ? @thang.spriteName # Prefer type, and excluded the quotes we'd get with @formatValue
|
||||||
content.replace /\#\{(.*?)\}/g, (s, properties) => @formatValue downTheChain(owner, properties.split('.'))
|
content.replace /\#\{(.*?)\}/g, (s, properties) => @formatValue downTheChain(owner, properties.split('.'))
|
||||||
|
|
||||||
formatValue: (v) ->
|
formatValue: (v) ->
|
||||||
|
@ -101,12 +101,15 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView
|
||||||
onClick: (e) -> # Don't call super
|
onClick: (e) -> # Don't call super
|
||||||
|
|
||||||
onDropdownClick: (e) ->
|
onDropdownClick: (e) ->
|
||||||
|
return unless @controlsEnabled
|
||||||
Backbone.Mediator.publish 'tome:toggle-spell-list'
|
Backbone.Mediator.publish 'tome:toggle-spell-list'
|
||||||
|
|
||||||
onCodeReload: ->
|
onCodeReload: ->
|
||||||
|
return unless @controlsEnabled
|
||||||
Backbone.Mediator.publish "tome:reload-code", spell: @spell
|
Backbone.Mediator.publish "tome:reload-code", spell: @spell
|
||||||
|
|
||||||
onBeautifyClick: ->
|
onBeautifyClick: ->
|
||||||
|
return unless @controlsEnabled
|
||||||
Backbone.Mediator.publish "spell-beautify", spell: @spell
|
Backbone.Mediator.publish "spell-beautify", spell: @spell
|
||||||
|
|
||||||
updateReloadButton: ->
|
updateReloadButton: ->
|
||||||
|
|
|
@ -66,6 +66,7 @@ module.exports = class SpellPaletteEntryView extends View
|
||||||
'surface:frame-changed': "onFrameChanged"
|
'surface:frame-changed': "onFrameChanged"
|
||||||
'tome:palette-hovered': "onPaletteHovered"
|
'tome:palette-hovered': "onPaletteHovered"
|
||||||
'tome:palette-pin-toggled': "onPalettePinToggled"
|
'tome:palette-pin-toggled': "onPalettePinToggled"
|
||||||
|
'tome:spell-debug-property-hovered': 'onSpellDebugPropertyHovered'
|
||||||
|
|
||||||
events:
|
events:
|
||||||
'mouseenter': 'onMouseEnter'
|
'mouseenter': 'onMouseEnter'
|
||||||
|
@ -83,7 +84,11 @@ module.exports = class SpellPaletteEntryView extends View
|
||||||
@doc.shortName = @doc.shorterName = @doc.title = @doc.name
|
@doc.shortName = @doc.shorterName = @doc.title = @doc.name
|
||||||
else
|
else
|
||||||
@doc.owner ?= 'this'
|
@doc.owner ?= 'this'
|
||||||
suffix = if @doc.type is 'function' then '()' else ''
|
suffix = ''
|
||||||
|
if @doc.type is 'function'
|
||||||
|
argNames = (arg.name for arg in @doc.args ? []).join(', ')
|
||||||
|
argNames = '...' if argNames.length > 6
|
||||||
|
suffix = "(#{argNames})"
|
||||||
@doc.shortName = "#{@doc.owner}.#{@doc.name}#{suffix};"
|
@doc.shortName = "#{@doc.owner}.#{@doc.name}#{suffix};"
|
||||||
if @doc.owner is 'this' or options.tabbify
|
if @doc.owner is 'this' or options.tabbify
|
||||||
@doc.shorterName = "#{@doc.name}#{suffix}"
|
@doc.shorterName = "#{@doc.name}#{suffix}"
|
||||||
|
@ -184,6 +189,16 @@ module.exports = class SpellPaletteEntryView extends View
|
||||||
return if e.entry is @
|
return if e.entry is @
|
||||||
@otherPopoverPinned = e.pinned
|
@otherPopoverPinned = e.pinned
|
||||||
|
|
||||||
|
onSpellDebugPropertyHovered: (e) ->
|
||||||
|
matched = e.property is @doc.name and e.owner is @doc.owner
|
||||||
|
if matched and not @debugHovered
|
||||||
|
@debugHovered = true
|
||||||
|
@togglePinned() unless @popoverPinned
|
||||||
|
else if @debugHovered and not matched
|
||||||
|
@debugHovered = false
|
||||||
|
@togglePinned() if @popoverPinned
|
||||||
|
null
|
||||||
|
|
||||||
destroy: ->
|
destroy: ->
|
||||||
$('.popover.pinned').remove() if @popoverPinned # @$el.popover('destroy') doesn't work
|
$('.popover.pinned').remove() if @popoverPinned # @$el.popover('destroy') doesn't work
|
||||||
@togglePinned() if @popoverPinned
|
@togglePinned() if @popoverPinned
|
||||||
|
|
|
@ -46,24 +46,42 @@ module.exports = class SpellPaletteView extends View
|
||||||
for doc in (lc.get('propertyDocumentation') ? [])
|
for doc in (lc.get('propertyDocumentation') ? [])
|
||||||
allDocs[doc.name] ?= []
|
allDocs[doc.name] ?= []
|
||||||
allDocs[doc.name].push doc
|
allDocs[doc.name].push doc
|
||||||
|
if doc.type is 'snippet' then doc.owner = 'snippets'
|
||||||
#allDocs[doc.name] = doc for doc in (lc.get('propertyDocumentation') ? []) for lc in lcs
|
#allDocs[doc.name] = doc for doc in (lc.get('propertyDocumentation') ? []) for lc in lcs
|
||||||
|
|
||||||
props = _.sortBy @thang.programmableProperties ? []
|
propStorage =
|
||||||
snippets = _.sortBy @thang.programmableSnippets ? []
|
'this': 'programmableProperties'
|
||||||
shortenize = props.length + snippets.length > 6
|
more: 'moreProgrammableProperties'
|
||||||
tabbify = props.length + snippets.length >= 10
|
Math: 'programmableMathProperties'
|
||||||
|
Vector: 'programmableVectorProperties'
|
||||||
|
snippets: 'programmableSnippets'
|
||||||
|
count = 0
|
||||||
|
propGroups = {}
|
||||||
|
for owner, storage of propStorage
|
||||||
|
added = propGroups[owner] = _.sortBy(@thang[storage] ? []).slice()
|
||||||
|
count += added.length
|
||||||
|
|
||||||
|
shortenize = count > 6
|
||||||
|
tabbify = count >= 10
|
||||||
@entries = []
|
@entries = []
|
||||||
for type, props of {props: props.slice(), snippets: snippets.slice()}
|
for owner, props of propGroups
|
||||||
for prop in props
|
for prop in props
|
||||||
doc = allDocs[prop]?.shift() ? prop # Add one doc per instance of the prop name (this is super gimp)
|
doc = _.find (allDocs[prop] ? []), (doc) ->
|
||||||
@entries.push @addEntry(doc, shortenize, tabbify, type is 'snippets')
|
return true if doc.owner is owner
|
||||||
|
return (owner is 'this' or owner is 'more') and (not doc.owner? or doc.owner is 'this')
|
||||||
|
console.log 'could not find doc for', prop, 'from', allDocs[prop], 'for', owner, 'of', propGroups unless doc
|
||||||
|
doc ?= prop
|
||||||
|
@entries.push @addEntry(doc, shortenize, tabbify, owner is 'snippets')
|
||||||
|
groupForEntry = (entry) ->
|
||||||
|
return 'more' if entry.doc.owner is 'this' and entry.doc.name in propGroups.more
|
||||||
|
entry.doc.owner
|
||||||
@entries = _.sortBy @entries, (entry) ->
|
@entries = _.sortBy @entries, (entry) ->
|
||||||
order = ['this', 'Math', 'Vector', 'snippets']
|
order = ['this', 'more', 'Math', 'Vector', 'snippets']
|
||||||
index = order.indexOf entry.doc.owner
|
index = order.indexOf groupForEntry entry
|
||||||
index = String.fromCharCode if index is -1 then order.length else index
|
index = String.fromCharCode if index is -1 then order.length else index
|
||||||
index += entry.doc.name
|
index += entry.doc.name
|
||||||
if tabbify and _.find @entries, ((entry) -> entry.doc.owner isnt 'this')
|
if tabbify and _.find @entries, ((entry) -> entry.doc.owner isnt 'this')
|
||||||
@entryGroups = _.groupBy @entries, (entry) -> entry.doc.owner
|
@entryGroups = _.groupBy @entries, groupForEntry
|
||||||
else
|
else
|
||||||
defaultGroup = $.i18n.t("play_level.tome_available_spells", defaultValue: "Available Spells")
|
defaultGroup = $.i18n.t("play_level.tome_available_spells", defaultValue: "Available Spells")
|
||||||
@entryGroups = {}
|
@entryGroups = {}
|
||||||
|
|
|
@ -326,7 +326,10 @@ module.exports = class SpellView extends View
|
||||||
isCast = not _.isEmpty(aether.metrics) or _.some aether.problems.errors, {type: 'runtime'}
|
isCast = not _.isEmpty(aether.metrics) or _.some aether.problems.errors, {type: 'runtime'}
|
||||||
@problems = []
|
@problems = []
|
||||||
annotations = []
|
annotations = []
|
||||||
|
seenProblemKeys = {}
|
||||||
for aetherProblem, problemIndex in aether.getAllProblems()
|
for aetherProblem, problemIndex in aether.getAllProblems()
|
||||||
|
continue if aetherProblem.userInfo.key of seenProblemKeys
|
||||||
|
seenProblemKeys[aetherProblem.userInfo.key] = true
|
||||||
@problems.push problem = new Problem aether, aetherProblem, @ace, isCast and problemIndex is 0, isCast
|
@problems.push problem = new Problem aether, aetherProblem, @ace, isCast and problemIndex is 0, isCast
|
||||||
annotations.push problem.annotation if problem.annotation
|
annotations.push problem.annotation if problem.annotation
|
||||||
@aceSession.setAnnotations annotations
|
@aceSession.setAnnotations annotations
|
||||||
|
@ -452,11 +455,11 @@ module.exports = class SpellView extends View
|
||||||
markerRange.end.detach()
|
markerRange.end.detach()
|
||||||
@aceSession.removeMarker markerRange.id
|
@aceSession.removeMarker markerRange.id
|
||||||
@markerRanges = []
|
@markerRanges = []
|
||||||
@debugView.setVariableStates {}
|
|
||||||
@aceSession.removeGutterDecoration row, 'executing' for row in [0 ... @aceSession.getLength()]
|
@aceSession.removeGutterDecoration row, 'executing' for row in [0 ... @aceSession.getLength()]
|
||||||
$(@ace.container).find('.ace_gutter-cell.executing').removeClass('executing')
|
$(@ace.container).find('.ace_gutter-cell.executing').removeClass('executing')
|
||||||
if not executed.length or (@spell.name is "plan" and @spellThang.castAether.metrics.statementsExecuted < 20)
|
if not executed.length or (@spell.name is "plan" and @spellThang.castAether.metrics.statementsExecuted < 20)
|
||||||
@toolbarView?.toggleFlow false
|
@toolbarView?.toggleFlow false
|
||||||
|
@debugView.setVariableStates {}
|
||||||
return
|
return
|
||||||
lastExecuted = _.last executed
|
lastExecuted = _.last executed
|
||||||
@toolbarView?.toggleFlow true
|
@toolbarView?.toggleFlow true
|
||||||
|
@ -464,6 +467,7 @@ module.exports = class SpellView extends View
|
||||||
@toolbarView?.setCallState states[currentCallIndex], statementIndex, currentCallIndex, @spellThang.castAether.metrics
|
@toolbarView?.setCallState states[currentCallIndex], statementIndex, currentCallIndex, @spellThang.castAether.metrics
|
||||||
marked = {}
|
marked = {}
|
||||||
lastExecuted = lastExecuted[0 .. @toolbarView.statementIndex] if @toolbarView?.statementIndex?
|
lastExecuted = lastExecuted[0 .. @toolbarView.statementIndex] if @toolbarView?.statementIndex?
|
||||||
|
gotVariableStates = false
|
||||||
for state, i in lastExecuted
|
for state, i in lastExecuted
|
||||||
[start, end] = state.range
|
[start, end] = state.range
|
||||||
clazz = if i is lastExecuted.length - 1 then 'executing' else 'executed'
|
clazz = if i is lastExecuted.length - 1 then 'executing' else 'executed'
|
||||||
|
@ -473,6 +477,7 @@ module.exports = class SpellView extends View
|
||||||
markerType = "fullLine"
|
markerType = "fullLine"
|
||||||
else
|
else
|
||||||
@debugView.setVariableStates state.variables
|
@debugView.setVariableStates state.variables
|
||||||
|
gotVariableStates = true
|
||||||
markerType = "text"
|
markerType = "text"
|
||||||
markerRange = new Range start.row, start.col, end.row, end.col
|
markerRange = new Range start.row, start.col, end.row, end.col
|
||||||
markerRange.start = @aceDoc.createAnchor markerRange.start
|
markerRange.start = @aceDoc.createAnchor markerRange.start
|
||||||
|
@ -480,6 +485,7 @@ module.exports = class SpellView extends View
|
||||||
markerRange.id = @aceSession.addMarker markerRange, clazz, markerType
|
markerRange.id = @aceSession.addMarker markerRange, clazz, markerType
|
||||||
@markerRanges.push markerRange
|
@markerRanges.push markerRange
|
||||||
@aceSession.addGutterDecoration start.row, clazz if clazz is 'executing'
|
@aceSession.addGutterDecoration start.row, clazz if clazz is 'executing'
|
||||||
|
@debugView.setVariableStates {} unless gotVariableStates
|
||||||
null
|
null
|
||||||
|
|
||||||
highlightComments: ->
|
highlightComments: ->
|
||||||
|
|
|
@ -21,6 +21,7 @@ module.exports = class ThangListEntryView extends View
|
||||||
'surface:frame-changed': "onFrameChanged"
|
'surface:frame-changed': "onFrameChanged"
|
||||||
'level-set-letterbox': 'onSetLetterbox'
|
'level-set-letterbox': 'onSetLetterbox'
|
||||||
'tome:thang-list-entry-popover-shown': 'onThangListEntryPopoverShown'
|
'tome:thang-list-entry-popover-shown': 'onThangListEntryPopoverShown'
|
||||||
|
'surface:coordinates-shown': 'onSurfaceCoordinatesShown'
|
||||||
|
|
||||||
events:
|
events:
|
||||||
'click': 'onClick'
|
'click': 'onClick'
|
||||||
|
@ -86,38 +87,47 @@ module.exports = class ThangListEntryView extends View
|
||||||
|
|
||||||
onMouseEnter: (e) ->
|
onMouseEnter: (e) ->
|
||||||
return unless @controlsEnabled and @spells.length
|
return unless @controlsEnabled and @spells.length
|
||||||
@showSpells()
|
@clearTimeouts()
|
||||||
|
@showSpellsTimeout = _.delay @showSpells, 100
|
||||||
|
|
||||||
onMouseLeave: (e) ->
|
onMouseLeave: (e) ->
|
||||||
return unless @controlsEnabled and @spells.length
|
return unless @controlsEnabled and @spells.length
|
||||||
clearTimeout @hideSpellsTimeout if @hideSpellsTimeout
|
@clearTimeouts()
|
||||||
@hideSpellsTimeout = _.delay @hideSpells, 100
|
@hideSpellsTimeout = _.delay @hideSpells, 100
|
||||||
|
|
||||||
|
clearTimeouts: ->
|
||||||
|
clearTimeout @showSpellsTimeout if @showSpellsTimeout
|
||||||
|
clearTimeout @hideSpellsTimeout if @hideSpellsTimeout
|
||||||
|
@showSpellsTimeout = @hideSpellsTimeout = null
|
||||||
|
|
||||||
onThangListEntryPopoverShown: (e) ->
|
onThangListEntryPopoverShown: (e) ->
|
||||||
# I couldn't figure out how to get the mouseenter / mouseleave to always work, so this is a fallback
|
# I couldn't figure out how to get the mouseenter / mouseleave to always work, so this is a fallback
|
||||||
# to hide our popover is another Thang's popover gets shown.
|
# to hide our popover is another Thang's popover gets shown.
|
||||||
return if e.entry is @
|
return if e.entry is @
|
||||||
@hideSpells()
|
@hideSpells()
|
||||||
|
|
||||||
|
onSurfaceCoordinatesShown: (e) ->
|
||||||
|
# Definitely aren't hovering over this.
|
||||||
|
@hideSpells()
|
||||||
|
|
||||||
showSpells: =>
|
showSpells: =>
|
||||||
|
@clearTimeouts()
|
||||||
@sortSpells()
|
@sortSpells()
|
||||||
@$el.data('bs.popover').options.content = @getSpellListHTML()
|
@$el.data('bs.popover').options.content = @getSpellListHTML()
|
||||||
@$el.popover('setContent').popover('show')
|
@$el.popover('setContent').popover('show')
|
||||||
@$el.parent().parent().parent().i18n()
|
@$el.parent().parent().parent().i18n()
|
||||||
clearTimeout @hideSpellsTimeout if @hideSpellsTimeout
|
|
||||||
@hideSpellsTimeout = null
|
|
||||||
@popover = @$el.parent().parent().parent().find('.popover')
|
@popover = @$el.parent().parent().parent().find('.popover')
|
||||||
@popover.off 'mouseenter mouseleave'
|
@popover.off 'mouseenter mouseleave'
|
||||||
@popover.mouseenter (e) => @onMouseEnter()
|
@popover.mouseenter (e) => @showSpells() if @controlsEnabled
|
||||||
@popover.mouseleave (e) => @onMouseLeave()
|
@popover.mouseleave (e) => @hideSpells()
|
||||||
thangID = @thang.id
|
thangID = @thang.id
|
||||||
@popover.find('code').click (e) ->
|
@popover.find('code').click (e) ->
|
||||||
Backbone.Mediator.publish "level-select-sprite", thangID: thangID, spellName: $(@).data 'spell-name'
|
Backbone.Mediator.publish "level-select-sprite", thangID: thangID, spellName: $(@).data 'spell-name'
|
||||||
Backbone.Mediator.publish 'tome:thang-list-entry-popover-shown', entry: @
|
Backbone.Mediator.publish 'tome:thang-list-entry-popover-shown', entry: @
|
||||||
|
|
||||||
hideSpells: =>
|
hideSpells: =>
|
||||||
|
@clearTimeouts()
|
||||||
@$el.popover('hide')
|
@$el.popover('hide')
|
||||||
@hideSpellsTimeout = null
|
|
||||||
|
|
||||||
getSpellListHTML: ->
|
getSpellListHTML: ->
|
||||||
spellsPopoverTemplate {spells: @spells}
|
spellsPopoverTemplate {spells: @spells}
|
||||||
|
@ -129,13 +139,16 @@ module.exports = class ThangListEntryView extends View
|
||||||
onSetLetterbox: (e) ->
|
onSetLetterbox: (e) ->
|
||||||
if e.on then @reasonsToBeDisabled.letterbox = true else delete @reasonsToBeDisabled.letterbox
|
if e.on then @reasonsToBeDisabled.letterbox = true else delete @reasonsToBeDisabled.letterbox
|
||||||
@updateControls()
|
@updateControls()
|
||||||
|
|
||||||
onDisableControls: (e) ->
|
onDisableControls: (e) ->
|
||||||
return if e.controls and not ('surface' in e.controls) # disable selection?
|
return if e.controls and not ('surface' in e.controls) # disable selection?
|
||||||
@reasonsToBeDisabled.controls = true
|
@reasonsToBeDisabled.controls = true
|
||||||
@updateControls()
|
@updateControls()
|
||||||
|
|
||||||
onEnableControls: (e) ->
|
onEnableControls: (e) ->
|
||||||
delete @reasonsToBeDisabled.controls
|
delete @reasonsToBeDisabled.controls
|
||||||
@updateControls()
|
@updateControls()
|
||||||
|
|
||||||
updateControls: ->
|
updateControls: ->
|
||||||
enabled = _.keys(@reasonsToBeDisabled).length is 0
|
enabled = _.keys(@reasonsToBeDisabled).length is 0
|
||||||
return if enabled is @controlsEnabled
|
return if enabled is @controlsEnabled
|
||||||
|
|
|
@ -151,9 +151,15 @@ module.exports = class TomeView extends View
|
||||||
@cast()
|
@cast()
|
||||||
|
|
||||||
cast: ->
|
cast: ->
|
||||||
for spellKey, spell of @spells
|
if @options.levelID is 'project-dota'
|
||||||
for thangID, spellThang of spell.thangs
|
# For performance reasons, only includeFlow on the currently Thang.
|
||||||
spellThang.aether.options.includeFlow = spellThang.aether.originalOptions.includeFlow = spellThang is @spellView?.spellThang
|
for spellKey, spell of @spells
|
||||||
|
for thangID, spellThang of spell.thangs
|
||||||
|
hadFlow = Boolean spellThang.aether.options.includeFlow
|
||||||
|
willHaveFlow = spellThang is @spellView?.spellThang
|
||||||
|
spellThang.aether.options.includeFlow = spellThang.aether.originalOptions.includeFlow = willHaveFlow
|
||||||
|
spellThang.aether.transpile spell.source unless hadFlow is willHaveFlow
|
||||||
|
#console.log "set includeFlow to", spellThang.aether.options.includeFlow, "for", thangID, "of", spellKey
|
||||||
Backbone.Mediator.publish 'tome:cast-spells', spells: @spells
|
Backbone.Mediator.publish 'tome:cast-spells', spells: @spells
|
||||||
|
|
||||||
onToggleSpellList: (e) ->
|
onToggleSpellList: (e) ->
|
||||||
|
|
|
@ -116,6 +116,10 @@ module.exports = class PlayLevelView extends View
|
||||||
getRenderData: ->
|
getRenderData: ->
|
||||||
c = super()
|
c = super()
|
||||||
c.world = @world
|
c.world = @world
|
||||||
|
if me.get('hourOfCode') and me.lang() is 'en-US'
|
||||||
|
# Show the Hour of Code footer explanation until it's been more than a day
|
||||||
|
elapsed = (new Date() - new Date(me.get('dateCreated')))
|
||||||
|
c.explainHourOfCode = elapsed < 86400 * 1000
|
||||||
c
|
c
|
||||||
|
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
|
@ -194,7 +198,7 @@ module.exports = class PlayLevelView extends View
|
||||||
|
|
||||||
afterInsert: ->
|
afterInsert: ->
|
||||||
super()
|
super()
|
||||||
# @showWizardSettingsModal() if not me.get('name')
|
@showWizardSettingsModal() if not me.get('name')
|
||||||
|
|
||||||
# callbacks
|
# callbacks
|
||||||
|
|
||||||
|
|
|
@ -8,5 +8,5 @@ current_directory = os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||||
coco_path = os.getenv("COCO_DIR",os.path.join(current_directory,os.pardir))
|
coco_path = os.getenv("COCO_DIR",os.path.join(current_directory,os.pardir))
|
||||||
nodemon_path = coco_path + os.sep + "node_modules" + os.sep + ".bin" + os.sep + "nodemon"
|
nodemon_path = coco_path + os.sep + "node_modules" + os.sep + ".bin" + os.sep + "nodemon"
|
||||||
|
|
||||||
call(nodemon_path + " . --ext \".coffee|.js\" --watch server --watch app.js --watch server_config.js",shell=True,cwd=coco_path)
|
call(nodemon_path + " . --ext \".coffee|.js\" --watch server --watch app.js --watch server_config.js --watch server_setup.coffee",shell=True,cwd=coco_path)
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,25 @@ connectToScoringQueue = ->
|
||||||
scoringTaskQueue = data
|
scoringTaskQueue = data
|
||||||
log.info "Connected to scoring task queue!"
|
log.info "Connected to scoring task queue!"
|
||||||
|
|
||||||
|
module.exports.addPairwiseTaskToQueue = (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
|
||||||
|
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"
|
||||||
|
LevelSession.find(_id:taskPair[1]).exec (err, secondSession) =>
|
||||||
|
if err? then return errors.serverError res, "There was an error fetching the second session"
|
||||||
|
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"
|
||||||
|
|
||||||
|
sendResponseObject req, res, {"message":"All task pairs were succesfully sent to the queue"}
|
||||||
|
|
||||||
|
|
||||||
module.exports.createNewTask = (req, res) ->
|
module.exports.createNewTask = (req, res) ->
|
||||||
requestSessionID = req.body.session
|
requestSessionID = req.body.session
|
||||||
validatePermissions req, requestSessionID, (error, permissionsAreValid) ->
|
validatePermissions req, requestSessionID, (error, permissionsAreValid) ->
|
||||||
|
|
|
@ -5,6 +5,7 @@ UserHandler = require('../users/user_handler')
|
||||||
config = require '../../server_config'
|
config = require '../../server_config'
|
||||||
errors = require '../commons/errors'
|
errors = require '../commons/errors'
|
||||||
mail = require '../commons/mail'
|
mail = require '../commons/mail'
|
||||||
|
languages = require '../routes/languages'
|
||||||
|
|
||||||
module.exports.setup = (app) ->
|
module.exports.setup = (app) ->
|
||||||
authentication.serializeUser((user, done) -> done(null, user._id))
|
authentication.serializeUser((user, done) -> done(null, user._id))
|
||||||
|
@ -43,10 +44,36 @@ module.exports.setup = (app) ->
|
||||||
)
|
)
|
||||||
|
|
||||||
app.get('/auth/whoami', (req, res) ->
|
app.get('/auth/whoami', (req, res) ->
|
||||||
res.setHeader('Content-Type', 'text/json');
|
if req.user
|
||||||
|
sendSelf(req, res)
|
||||||
|
else
|
||||||
|
user = new User({anonymous:true})
|
||||||
|
user.set 'testGroupNumber', Math.floor(Math.random() * 256) # also in app/lib/auth
|
||||||
|
user.set 'preferredLanguage', languages.languageCodeFromAcceptedLanguages req.acceptedLanguages
|
||||||
|
makeNext = (req, res) -> -> sendSelf(req, res)
|
||||||
|
next = makeNext(req, res)
|
||||||
|
loginUser(req, res, user, false, next)
|
||||||
|
)
|
||||||
|
|
||||||
|
sendSelf = (req, res) ->
|
||||||
|
res.setHeader('Content-Type', 'text/json')
|
||||||
res.send(UserHandler.formatEntity(req, req.user))
|
res.send(UserHandler.formatEntity(req, req.user))
|
||||||
res.end()
|
res.end()
|
||||||
)
|
|
||||||
|
loginUser = (req, res, user, send=true, next=null) ->
|
||||||
|
user.save((err) ->
|
||||||
|
if err
|
||||||
|
return @sendDatabaseError(res, err)
|
||||||
|
|
||||||
|
req.logIn(user, (err) ->
|
||||||
|
if err
|
||||||
|
return @sendDatabaseError(res, err)
|
||||||
|
|
||||||
|
if send
|
||||||
|
return @sendSuccess(res, user)
|
||||||
|
next() if next
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
app.post('/auth/logout', (req, res) ->
|
app.post('/auth/logout', (req, res) ->
|
||||||
req.logout()
|
req.logout()
|
||||||
|
|
|
@ -6,6 +6,10 @@ scoringQueue = require '../queues/scoring'
|
||||||
module.exports.setup = (app) ->
|
module.exports.setup = (app) ->
|
||||||
scoringQueue.setup()
|
scoringQueue.setup()
|
||||||
|
|
||||||
|
#app.post '/queue/scoring/pairwise', (req, res) ->
|
||||||
|
# handler = loadQueueHandler 'scoring'
|
||||||
|
# handler.addPairwiseTaskToQueue req, res
|
||||||
|
|
||||||
app.all '/queue/*', (req, res) ->
|
app.all '/queue/*', (req, res) ->
|
||||||
setResponseHeaderToJSONContentType res
|
setResponseHeaderToJSONContentType res
|
||||||
|
|
||||||
|
@ -24,6 +28,7 @@ module.exports.setup = (app) ->
|
||||||
log.error error
|
log.error error
|
||||||
sendQueueError req, res, error
|
sendQueueError req, res, error
|
||||||
|
|
||||||
|
|
||||||
setResponseHeaderToJSONContentType = (res) -> res.setHeader('Content-Type', 'application/json')
|
setResponseHeaderToJSONContentType = (res) -> res.setHeader('Content-Type', 'application/json')
|
||||||
|
|
||||||
getQueueNameFromPath = (path) ->
|
getQueueNameFromPath = (path) ->
|
||||||
|
|
|
@ -3,7 +3,6 @@ crypto = require 'crypto'
|
||||||
request = require 'request'
|
request = require 'request'
|
||||||
User = require './User'
|
User = require './User'
|
||||||
Handler = require '../commons/Handler'
|
Handler = require '../commons/Handler'
|
||||||
languages = require '../routes/languages'
|
|
||||||
mongoose = require 'mongoose'
|
mongoose = require 'mongoose'
|
||||||
config = require '../../server_config'
|
config = require '../../server_config'
|
||||||
errors = require '../commons/errors'
|
errors = require '../commons/errors'
|
||||||
|
@ -172,28 +171,3 @@ UserHandler = class UserHandler extends Handler
|
||||||
res.end()
|
res.end()
|
||||||
|
|
||||||
module.exports = new UserHandler()
|
module.exports = new UserHandler()
|
||||||
|
|
||||||
module.exports.setupMiddleware = (app) ->
|
|
||||||
app.use (req, res, next) ->
|
|
||||||
if req.user
|
|
||||||
next()
|
|
||||||
else
|
|
||||||
user = new User({anonymous:true})
|
|
||||||
user.set 'testGroupNumber', Math.floor(Math.random() * 256) # also in app/lib/auth
|
|
||||||
user.set 'preferredLanguage', languages.languageCodeFromAcceptedLanguages req.acceptedLanguages
|
|
||||||
loginUser(req, res, user, false, next)
|
|
||||||
|
|
||||||
loginUser = (req, res, user, send=true, next=null) ->
|
|
||||||
user.save((err) ->
|
|
||||||
if err
|
|
||||||
return @sendDatabaseError(res, err)
|
|
||||||
|
|
||||||
req.logIn(user, (err) ->
|
|
||||||
if err
|
|
||||||
return @sendDatabaseError(res, err)
|
|
||||||
|
|
||||||
if send
|
|
||||||
return @sendSuccess(res, user)
|
|
||||||
next() if next
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
|
@ -40,9 +40,6 @@ setupOneSecondDelayMiddlware = (app) ->
|
||||||
if(config.slow_down)
|
if(config.slow_down)
|
||||||
app.use((req, res, next) -> setTimeout((-> next()), 1000))
|
app.use((req, res, next) -> setTimeout((-> next()), 1000))
|
||||||
|
|
||||||
setupUserMiddleware = (app) ->
|
|
||||||
user.setupMiddleware(app)
|
|
||||||
|
|
||||||
setupMiddlewareToSendOldBrowserWarningWhenPlayersViewLevelDirectly = (app) ->
|
setupMiddlewareToSendOldBrowserWarningWhenPlayersViewLevelDirectly = (app) ->
|
||||||
isOldBrowser = (req) ->
|
isOldBrowser = (req) ->
|
||||||
# https://github.com/biggora/express-useragent/blob/master/lib/express-useragent.js
|
# https://github.com/biggora/express-useragent/blob/master/lib/express-useragent.js
|
||||||
|
@ -66,7 +63,6 @@ exports.setupMiddleware = (app) ->
|
||||||
setupExpressMiddleware app
|
setupExpressMiddleware app
|
||||||
setupPassportMiddleware app
|
setupPassportMiddleware app
|
||||||
setupOneSecondDelayMiddlware app
|
setupOneSecondDelayMiddlware app
|
||||||
setupUserMiddleware app
|
|
||||||
|
|
||||||
###Routing function implementations###
|
###Routing function implementations###
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue