mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-24 16:17:57 -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'
|
||||
auth = require 'lib/auth'
|
||||
|
||||
$ ->
|
||||
init = ->
|
||||
app.initialize()
|
||||
Backbone.history.start({ pushState: true })
|
||||
handleNormalUrls()
|
||||
|
@ -9,6 +10,15 @@ $ ->
|
|||
treemaExt.setup()
|
||||
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 = ->
|
||||
# http://artsy.github.com/blog/2012/06/25/replacing-hashbang-routes-with-pushstate/
|
||||
$(document).on "click", "a[href^='/']", (event) ->
|
||||
|
|
|
@ -141,8 +141,8 @@ module.exports = class SpriteBuilder
|
|||
return unless shapes.length
|
||||
colors = @initColorMap(shapes)
|
||||
@adjustHuesForColorMap(colors, config.hue)
|
||||
@adjustValueForColorMap(colors, 1, config.lightness)
|
||||
@adjustValueForColorMap(colors, 2, config.saturation)
|
||||
@adjustValueForColorMap(colors, 1, config.saturation)
|
||||
@adjustValueForColorMap(colors, 2, config.lightness)
|
||||
@applyColorMap(shapes, colors)
|
||||
|
||||
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
|
||||
@displayObject = new createjs.Container()
|
||||
if @thangType.get('actions')
|
||||
@onThangTypeLoaded()
|
||||
@setupSprite()
|
||||
else
|
||||
@stillLoading = true
|
||||
@thangType.fetch()
|
||||
@thangType.once 'sync', @onThangTypeLoaded, @
|
||||
@thangType.once 'sync', @setupSprite, @
|
||||
|
||||
onThangTypeLoaded: ->
|
||||
setupSprite: ->
|
||||
@stillLoading = false
|
||||
@actions = @thangType.getActions()
|
||||
@buildFromSpriteSheet @buildSpriteSheet()
|
||||
|
@ -101,6 +101,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
# 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
|
||||
@displayObject.removeChild(@imageObject) if @imageObject
|
||||
@imageObject = sprite
|
||||
@displayObject.addChild(sprite)
|
||||
@addHealthBar()
|
||||
|
@ -157,6 +158,14 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
@hiding = false
|
||||
@updateAlpha()
|
||||
|
||||
stop: ->
|
||||
@imageObject?.stop?()
|
||||
mark.stop() for name, mark of @marks
|
||||
|
||||
play: ->
|
||||
@imageObject?.play?()
|
||||
mark.play() for name, mark of @marks
|
||||
|
||||
update: ->
|
||||
# Gets the sprite to reflect what the current state of the thangs and surface are
|
||||
return if @stillLoading
|
||||
|
@ -197,8 +206,11 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
if @thang.width isnt @lastThangWidth or @thang.height isnt @lastThangHeight
|
||||
[@lastThangWidth, @lastThangHeight] = [@thang.width, @thang.height]
|
||||
bounds = @imageObject.getBounds()
|
||||
@imageObject.scaleX = @thang.width * Camera.PPM / bounds.width * @thangType.get('scale') ? 1
|
||||
@imageObject.scaleY = @thang.height * Camera.PPM * @options.camera.y2x / bounds.height * @thangType.get('scale') ? 1
|
||||
@imageObject.scaleX = @thang.width * Camera.PPM / bounds.width
|
||||
@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
|
||||
scaleX = if @getActionProp 'flipX' then -1 else 1
|
||||
scaleY = if @getActionProp 'flipY' then -1 else 1
|
||||
|
|
|
@ -54,17 +54,19 @@ module.exports = class Label extends CocoClass
|
|||
buildLabelOptions: ->
|
||||
o = {}
|
||||
st = {dialogue: 'D', say: 'S', name: 'N'}[@style]
|
||||
o.marginX = {D: 5, S: 2, N: 3}[st]
|
||||
o.marginY = {D: 6, S: 2, N: 3}[st]
|
||||
o.marginX = {D: 5, S: 6, 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.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]
|
||||
o.fontDescriptor = "#{o.fontSize}px #{fontFamily}"
|
||||
o.fontColor = {D: "#000", S: "#000", N: "#00a"}[st]
|
||||
o.backgroundFillColor = {D: "white", S: "rgba(255, 255, 255, 0.2)", 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.fontDescriptor = "#{o.fontWeight} #{o.fontSize}px #{fontFamily}"
|
||||
o.fontColor = {D: "#000", S: "#FFF", N: "#00a"}[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, .6)", N: "rgba(0, 0, 0, 0.0)"}[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]
|
||||
maxWidth = {D: 300, S: 300, N: 180}[st]
|
||||
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.x = o.marginX
|
||||
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.name = "Sprite Label - #{@style}"
|
||||
o.textHeight = label.getMeasuredHeight()
|
||||
|
|
|
@ -48,7 +48,7 @@ module.exports = class Mark extends CocoClass
|
|||
build: ->
|
||||
unless @mark
|
||||
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 @thangType then @buildSprite()
|
||||
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
|
||||
@lastHeight = @sprite.thang.height
|
||||
|
||||
buildRadius: ->
|
||||
# TODO: make this not just a shadow
|
||||
# TODO: draw boxes and ellipses for non-circular Thangs
|
||||
diameter = @sprite.thangType.get('shadow') ? @sprite.thang?.width + 0.5
|
||||
diameter *= Camera.PPM
|
||||
buildShadow: ->
|
||||
width = (@sprite.thang?.width ? 0) + 0.5
|
||||
height = (@sprite.thang?.height ? 0) + 0.5
|
||||
longest = Math.max width, height
|
||||
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.mouseEnabled = false
|
||||
@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.regX = diameter / 2
|
||||
@mark.regY = diameter / 2 * @camera.y2x
|
||||
@mark.regX = width / 2
|
||||
@mark.regY = height / 2
|
||||
@mark.layerIndex = 10
|
||||
#@mark.cache 0, 0, diameter, diameter # not actually faster than simple ellipse draw
|
||||
|
||||
buildRadius: ->
|
||||
return # not implemented
|
||||
|
||||
buildDebug: ->
|
||||
@mark = new createjs.Shape()
|
||||
PX = 3
|
||||
|
@ -152,7 +162,7 @@ module.exports = class Mark extends CocoClass
|
|||
@mark.y += offset.y
|
||||
|
||||
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
|
||||
|
||||
updateScale: ->
|
||||
|
@ -174,3 +184,6 @@ module.exports = class Mark extends CocoClass
|
|||
@mark.scaleX = @mark.scaleY = Math.min 1, scale
|
||||
if @name in ['selection', 'target', 'repair']
|
||||
@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:restarted': 'onLevelRestarted'
|
||||
'god:new-world-created': 'onNewWorld'
|
||||
'tome:cast-spells': 'onCastSpells'
|
||||
|
||||
constructor: (@options) ->
|
||||
super()
|
||||
|
@ -205,6 +206,14 @@ module.exports = class SpriteBoss extends CocoClass
|
|||
|
||||
onNewWorld: (e) ->
|
||||
@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
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ CameraBorder = require './CameraBorder'
|
|||
Layer = require './Layer'
|
||||
Letterbox = require './Letterbox'
|
||||
Dimmer = require './Dimmer'
|
||||
CastingScreen = require './CastingScreen'
|
||||
DebugDisplay = require './DebugDisplay'
|
||||
CoordinateDisplay = require './CoordinateDisplay'
|
||||
SpriteBoss = require './SpriteBoss'
|
||||
|
@ -88,6 +89,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@spriteBoss.destroy()
|
||||
@chooser?.destroy()
|
||||
@dimmer?.destroy()
|
||||
@castingScreen?.destroy()
|
||||
@stage.clear()
|
||||
@musicPlayer?.destroy()
|
||||
@stage.removeAllChildren()
|
||||
|
@ -224,7 +226,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@currentFrame = actualCurrentFrame
|
||||
|
||||
# TODO: are these needed, or perhaps do they duplicate things?
|
||||
@spriteBoss.update()
|
||||
@spriteBoss.update true
|
||||
@onFrameChanged()
|
||||
|
||||
getCurrentFrame: ->
|
||||
|
@ -299,11 +301,18 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@lastFrame = @currentFrame
|
||||
|
||||
onCastSpells: (event) ->
|
||||
@casting = true
|
||||
@wasPlayingWhenCastingBegan = @playing
|
||||
Backbone.Mediator.publish 'level-set-playing', { playing: false }
|
||||
|
||||
createjs.Tween.removeTweens(@surfaceLayer)
|
||||
createjs.Tween.get(@surfaceLayer).to({alpha:0.9}, 1000, createjs.Ease.getPowOut(4.0))
|
||||
|
||||
onNewWorld: (event) ->
|
||||
return unless event.world.name is @world.name
|
||||
@casting = false
|
||||
Backbone.Mediator.publish 'level-set-playing', { playing: @wasPlayingWhenCastingBegan }
|
||||
|
||||
fastForwardTo = null
|
||||
if @playing
|
||||
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
|
||||
@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
|
||||
@castingScreen ?= new CastingScreen camera: @camera, layer: @screenLayer
|
||||
@stage.enableMouseOver(10)
|
||||
@stage.addEventListener 'stagemousemove', @onMouseMove
|
||||
@stage.addEventListener 'stagemousedown', @onMouseDown
|
||||
|
@ -497,7 +507,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
updateState: (frameChanged) ->
|
||||
# world state must have been restored in @updateSpriteSounds
|
||||
@camera.updateZoom()
|
||||
@spriteBoss.update frameChanged
|
||||
@spriteBoss.update frameChanged unless @casting
|
||||
@dimmer?.setSprites @spriteBoss.sprites
|
||||
|
||||
drawCurrentFrame: (e) ->
|
||||
|
@ -508,6 +518,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
|
||||
updatePaths: ->
|
||||
return unless @options.paths
|
||||
return if @casting
|
||||
@hidePaths()
|
||||
selectedThang = @spriteBoss.selectedSprite?.thang
|
||||
return if @world.showPaths is 'never'
|
||||
|
|
|
@ -24,7 +24,7 @@ module.exports = class WizardSprite extends IndieSprite
|
|||
|
||||
constructor: (thangType, options) ->
|
||||
if options?.isSelf
|
||||
options.colorConfig = me.get('wizard')?.colorConfig or {}
|
||||
options.colorConfig = _.cloneDeep(me.get('wizard')?.colorConfig) or {}
|
||||
super thangType, options
|
||||
@isSelf = options.isSelf
|
||||
@targetPos = @thang.pos
|
||||
|
@ -59,7 +59,12 @@ module.exports = class WizardSprite extends IndieSprite
|
|||
onMeSynced: (e) ->
|
||||
return unless @isSelf
|
||||
@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) ->
|
||||
return unless @isSelf
|
||||
|
|
|
@ -55,7 +55,7 @@ module.exports = class World
|
|||
@thangMap[thang.id] = thang
|
||||
|
||||
thangDialogueSounds: ->
|
||||
if @frames.length < @totalFrames then worldShouldBeOverBeforeGrabbingDialogue
|
||||
if @frames.length < @totalFrames then throw new Error("World should be over before grabbing dialogue")
|
||||
[sounds, seen] = [[], {}]
|
||||
for frame in @frames
|
||||
for thangID, state of frame.thangStateMap
|
||||
|
@ -245,7 +245,7 @@ module.exports = class World
|
|||
|
||||
serialize: ->
|
||||
# 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]
|
||||
o = {name: @name, totalFrames: @totalFrames, maxTotalFrames: @maxTotalFrames, frameRate: @frameRate, dt: @dt, victory: @victory, userCodeMap: {}, trackedProperties: {}}
|
||||
o.trackedProperties[prop] = @[prop] for prop in @trackedProperties or []
|
||||
|
|
|
@ -38,43 +38,3 @@
|
|||
|
||||
.form
|
||||
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
|
||||
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
|
||||
|
||||
canvas
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
#wizard-settings-modal
|
||||
color: black
|
||||
background: white
|
||||
width: 400px
|
||||
|
||||
#wizard-settings-view #color-settings
|
||||
width: 480px
|
||||
|
||||
canvas
|
||||
border: 1px solid black
|
||||
float: left
|
||||
margin: 0px auto 20px
|
||||
display: block
|
||||
float: none
|
||||
background: white
|
||||
|
||||
.settings
|
||||
width: 225px
|
||||
margin: 10px
|
||||
display: inline-block
|
||||
|
||||
.selector
|
||||
margin: 10px 5px
|
||||
|
||||
button
|
||||
margin-left: 10px
|
||||
float: right
|
||||
.wizard-name-line
|
||||
text-align: center
|
||||
margin-bottom: 10px
|
||||
label
|
||||
margin-right: 10px
|
|
@ -20,3 +20,5 @@
|
|||
white-space: nowrap
|
||||
overflow: hidden
|
||||
|
||||
#must-log-in button
|
||||
margin-right: 10px
|
|
@ -5,3 +5,8 @@
|
|||
#competitors-column .well
|
||||
font-size: 18px
|
||||
padding: 7px
|
||||
|
||||
#your-score
|
||||
margin-top: 20px
|
||||
text-align: center
|
||||
font-size: 20px
|
|
@ -132,9 +132,21 @@
|
|||
height: 100%
|
||||
width: 2%
|
||||
|
||||
.footer:not(:hover)
|
||||
@include opacity(0.6)
|
||||
.footer
|
||||
@media screen and (min-aspect-ratio: 17/10)
|
||||
display: none
|
||||
|
||||
@media screen and (min-aspect-ratio: 17/10)
|
||||
#level-view .footer
|
||||
display: none
|
||||
&:not(:hover)
|
||||
@include opacity(0.6)
|
||||
|
||||
.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
|
||||
background-color: rgba(245, 255, 6, 0.18)
|
||||
.problem-marker-info
|
||||
background-color: rgba(96, 63, 84, 0.25)
|
||||
background-color: rgba(196, 163, 184, 0.25)
|
||||
.problem-marker-warning
|
||||
background-color: rgba(100, 65, 20, 0.25)
|
||||
.problem-marker-error
|
||||
|
|
|
@ -9,16 +9,18 @@
|
|||
border: 1px solid transparent
|
||||
cursor: pointer
|
||||
@include user-select(all)
|
||||
::selection
|
||||
background: transparent
|
||||
|
||||
&:hover
|
||||
border: 1px solid #BFF
|
||||
border: 1px solid #000000
|
||||
|
||||
&.pinned
|
||||
background-color: darken(#BFF, 20%)
|
||||
background-color: darken(#FFFFFF, 25%)
|
||||
|
||||
// Pulling these colors from the most relevant textmate-theme classes
|
||||
&.function
|
||||
color: #0000A2
|
||||
color: #0066FF
|
||||
&.object
|
||||
color: rgb(6, 150, 14)
|
||||
&.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.
|
||||
|
||||
#wizard-pane.tab-pane
|
||||
#wizard-settings-tab-view
|
||||
#wizard-settings-view
|
||||
|
||||
#password-pane.tab-pane
|
||||
p
|
||||
|
|
|
@ -8,7 +8,7 @@ canvas#tinting-display(width=200, height=200).img-rounded
|
|||
span(data-i18n='wizard_settings.' + group.dasherized)= group.humanized
|
||||
div.sliders
|
||||
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')
|
||||
div.slider-cell
|
||||
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
|
||||
|
||||
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")
|
||||
.settings
|
||||
.form-vertical.form
|
||||
.form-group
|
||||
label.control-label(for="name")
|
||||
| Name
|
||||
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
|
||||
#wizard-settings-view
|
||||
|
||||
block modal-body-wait-content
|
||||
h3 Saving...
|
||||
.progress.progress-striped.active
|
||||
.progress-bar
|
||||
|
||||
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
|
||||
!{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
|
||||
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
|
||||
//(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
|
||||
if me.get('anonymous')
|
||||
div#must-log-in
|
||||
p
|
||||
strong Please log in first before playing a ladder game.
|
||||
button.btn.btn-primary(data-toggle="coco-modal", data-target="modal/login", data-i18n="login.log_in") Log In
|
||||
button.btn.btn-primary(data-toggle="coco-modal", data-target="modal/signup", data-i18n="login.sign_up") Create Account
|
||||
|
||||
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
|
||||
else
|
||||
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
|
||||
//(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
|
||||
| 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#matches-column.col-md-6
|
||||
h3.pull-left Ranked Games
|
||||
|
|
|
@ -27,3 +27,11 @@
|
|||
.content
|
||||
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
|
||||
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"))
|
||||
//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.shared-thangs
|
||||
if includeName
|
||||
|
|
|
@ -4,7 +4,7 @@ template = require 'templates/account/settings'
|
|||
forms = require('lib/forms')
|
||||
User = require('models/User')
|
||||
|
||||
WizardSettingsTabView = require './wizard_settings_tab_view'
|
||||
WizardSettingsView = require './wizard_settings_view'
|
||||
|
||||
module.exports = class SettingsView extends View
|
||||
id: 'account-settings-view'
|
||||
|
@ -26,11 +26,12 @@ module.exports = class SettingsView extends View
|
|||
|
||||
refreshPicturePane: =>
|
||||
h = $(@template(@getRenderData()))
|
||||
new_pane = $('#picture-pane', h)
|
||||
old_pane = $('#picture-pane')
|
||||
active = old_pane.hasClass('active')
|
||||
old_pane.replaceWith(new_pane)
|
||||
new_pane.addClass('active') if active
|
||||
newPane = $('#picture-pane', h)
|
||||
oldPane = $('#picture-pane')
|
||||
active = oldPane.hasClass('active')
|
||||
oldPane.replaceWith(newPane)
|
||||
newPane.i18n()
|
||||
newPane.addClass('active') if active
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
|
@ -46,9 +47,9 @@ module.exports = class SettingsView extends View
|
|||
|
||||
@chooseTab(location.hash.replace('#',''))
|
||||
@updateWizardColor()
|
||||
wizardSettingsTabView = new WizardSettingsTabView()
|
||||
wizardSettingsTabView.on 'change', @save, @
|
||||
@insertSubView wizardSettingsTabView
|
||||
WizardSettingsView = new WizardSettingsView()
|
||||
WizardSettingsView.on 'change', @save, @
|
||||
@insertSubView WizardSettingsView
|
||||
|
||||
chooseTab: (category) ->
|
||||
id = "##{category}-pane"
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
RootView = require 'views/kinds/RootView'
|
||||
template = require 'templates/account/wizard_settings_tab'
|
||||
CocoView = require 'views/kinds/CocoView'
|
||||
template = require 'templates/account/wizard_settings'
|
||||
{me} = require('lib/auth')
|
||||
ThangType = require 'models/ThangType'
|
||||
SpriteBuilder = require 'lib/sprites/SpriteBuilder'
|
||||
|
||||
module.exports = class WizardSettingsTabView extends RootView
|
||||
id: 'wizard-settings-tab-view'
|
||||
module.exports = class WizardSettingsView extends CocoView
|
||||
id: 'wizard-settings-view'
|
||||
template: template
|
||||
startsLoading: true
|
||||
|
||||
events:
|
||||
'change .color-group-checkbox': (e) ->
|
||||
|
@ -25,6 +26,7 @@ module.exports = class WizardSettingsTabView extends RootView
|
|||
@wizardThangType.once 'sync', @initCanvas, @
|
||||
|
||||
initCanvas: ->
|
||||
@startsLoading = false
|
||||
@render()
|
||||
@spriteBuilder = new SpriteBuilder(@wizardThangType)
|
||||
@initStage()
|
||||
|
@ -44,6 +46,7 @@ module.exports = class WizardSettingsTabView extends RootView
|
|||
c
|
||||
|
||||
afterRender: ->
|
||||
return if @startsLoading
|
||||
wizardSettings = me.get('wizard') or {}
|
||||
wizardSettings.colorConfig ?= {}
|
||||
|
||||
|
@ -82,8 +85,6 @@ module.exports = class WizardSettingsTabView extends RootView
|
|||
initStage: ->
|
||||
@stage = new createjs.Stage(@$el.find('canvas')[0])
|
||||
@updateMovieClip()
|
||||
createjs.Ticker.setFPS 20
|
||||
createjs.Ticker.addEventListener("tick", @stage)
|
||||
|
||||
updateMovieClip: ->
|
||||
return unless @wizardThangType.loaded
|
||||
|
@ -104,6 +105,3 @@ module.exports = class WizardSettingsTabView extends RootView
|
|||
@movieClip.regY = reg.y
|
||||
@stage.addChild @movieClip
|
||||
@stage.update()
|
||||
|
||||
destroy: ->
|
||||
@stage?.removeAllEventListeners()
|
|
@ -48,15 +48,10 @@ module.exports = class ThangsTabView extends View
|
|||
'click #extant-thangs-filter button': 'onFilterExtantThangs'
|
||||
|
||||
shortcuts:
|
||||
'esc': -> @selectAddThang()
|
||||
|
||||
onFilterExtantThangs: (e) ->
|
||||
button = $(e.target).closest('button')
|
||||
button.button('toggle')
|
||||
val = button.val()
|
||||
@thangsTreema.$el.removeClass(@lastHideClass) if @lastHideClass
|
||||
@thangsTreema.$el.addClass(@lastHideClass = "hide-except-#{val}") if val
|
||||
|
||||
'esc': 'selectAddThang'
|
||||
'delete, del, backspace': 'deleteSelectedExtantThang'
|
||||
'left': -> @moveAddThangSelection -1
|
||||
'right': -> @moveAddThangSelection 1
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
|
@ -102,12 +97,12 @@ module.exports = class ThangsTabView extends View
|
|||
$('#thangs-list').bind 'mousewheel', @preventBodyScrollingInThangList
|
||||
@$el.find('#extant-thangs-filter button:first').button('toggle')
|
||||
|
||||
# TODO: move these into the shortcuts list
|
||||
key 'left', _.bind @moveAddThangSelection, @, -1
|
||||
key 'right', _.bind @moveAddThangSelection, @, 1
|
||||
key 'delete, del, backspace', @deleteSelectedExtantThang
|
||||
key 'f', => Backbone.Mediator.publish('level-set-debug', debug: not @surface.debug)
|
||||
key 'g', => Backbone.Mediator.publish('level-set-grid', grid: not @surface.gridShowing())
|
||||
onFilterExtantThangs: (e) ->
|
||||
button = $(e.target).closest('button')
|
||||
button.button('toggle')
|
||||
val = button.val()
|
||||
@thangsTreema.$el.removeClass(@lastHideClass) if @lastHideClass
|
||||
@thangsTreema.$el.addClass(@lastHideClass = "hide-except-#{val}") if val
|
||||
|
||||
preventBodyScrollingInThangList: (e) ->
|
||||
@scrollTop += (if e.deltaY < 0 then 1 else -1) * 30
|
||||
|
|
|
@ -129,7 +129,7 @@ module.exports = class CocoView extends Backbone.View
|
|||
# Loading RootViews
|
||||
|
||||
showLoading: ($el=@$el) ->
|
||||
$el.find('>').hide()
|
||||
$el.find('>').addClass('hidden')
|
||||
$el.append($('<div class="loading-screen"></div>')
|
||||
.append('<h2>Loading</h2>')
|
||||
.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: ->
|
||||
return unless @_lastLoading?
|
||||
@_lastLoading.find('.loading-screen').remove()
|
||||
@_lastLoading.find('>').show()
|
||||
@_lastLoading.find('>').removeClass('hidden')
|
||||
@_lastLoading = null
|
||||
|
||||
# Loading ModalViews
|
||||
|
|
|
@ -22,8 +22,8 @@ module.exports = class RootView extends CocoView
|
|||
logoutUser($('#login-email').val())
|
||||
|
||||
showWizardSettingsModal: ->
|
||||
WizardSettingsView = require('views/modal/wizard_settings_modal')
|
||||
subview = new WizardSettingsView {}
|
||||
WizardSettingsModal = require('views/modal/wizard_settings_modal')
|
||||
subview = new WizardSettingsModal {}
|
||||
@openModalView subview
|
||||
|
||||
showLoading: ($el) ->
|
||||
|
|
|
@ -2,79 +2,44 @@ View = require 'views/kinds/ModalView'
|
|||
template = require 'templates/modal/wizard_settings'
|
||||
WizardSprite = require 'lib/surface/WizardSprite'
|
||||
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"
|
||||
template: template
|
||||
closesOnClickOutside: false
|
||||
|
||||
events:
|
||||
'change #wizard-settings-name': 'onNameChange'
|
||||
'click #random-name': 'onRandomNameClick'
|
||||
'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)
|
||||
'click #wizard-settings-done': 'onWizardSettingsDone'
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
@colorSlider = $( "#wizard-settings-color-1", @$el).slider({ animate: "fast" })
|
||||
@colorSlider.slider('value', me.get('wizardColor1')*100)
|
||||
@colorSlider.on('slide',@onSliderChange)
|
||||
@colorSlider.on('slidechange',@onSliderChange)
|
||||
@stage = new createjs.Stage($('canvas', @$el)[0])
|
||||
@saveChanges = _.debounce(@saveChanges, 1000)
|
||||
WizardSettingsView = require 'views/account/wizard_settings_view'
|
||||
view = new WizardSettingsView()
|
||||
@insertSubView view
|
||||
|
||||
wizOriginal = "52a00d55cf1818f2be00000b"
|
||||
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: ->
|
||||
onNameChange: ->
|
||||
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()
|
||||
|
||||
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.reverse()
|
||||
ctx.score = (@session.get('totalScore') or 10).toFixed(2)
|
||||
ctx
|
||||
|
||||
afterRender: ->
|
||||
|
|
|
@ -36,8 +36,8 @@ module.exports = class PlaybackView extends View
|
|||
|
||||
shortcuts:
|
||||
'⌘+p, p, ctrl+p': 'onTogglePlay'
|
||||
'[': 'onScrubBack'
|
||||
']': 'onScrubForward'
|
||||
'⌘+[, ctrl+[': 'onScrubBack'
|
||||
'⌘+], ctrl+]': 'onScrubForward'
|
||||
|
||||
constructor: ->
|
||||
super(arguments...)
|
||||
|
@ -169,7 +169,7 @@ module.exports = class PlaybackView extends View
|
|||
if @clickingSlider
|
||||
@clickingSlider = false
|
||||
@wasPlaying = false
|
||||
@onSetPlaying {playing: false}
|
||||
Backbone.Mediator.publish 'level-set-playing', {playing: false}
|
||||
@$el.find('.scrubber-handle').effect('bounce', {times: 2})
|
||||
)
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ module.exports = class CastButtonView extends View
|
|||
@spells = options.spells
|
||||
@levelID = options.levelID
|
||||
isMac = navigator.platform.toUpperCase().indexOf('MAC') isnt -1
|
||||
@castShortcut = "⇧↩"
|
||||
@castShortcut = "⇧↵"
|
||||
@castShortcutVerbose = "Shift+Enter"
|
||||
|
||||
getRenderData: (context={}) ->
|
||||
|
@ -35,7 +35,7 @@ module.exports = class CastButtonView extends View
|
|||
# TODO: use a User setting instead of localStorage
|
||||
delay = localStorage.getItem 'autocastDelay'
|
||||
delay ?= 5000
|
||||
if @levelID is 'project-dota'
|
||||
if @levelID in ['project-dota', 'brawlwood', 'ladder-tutorial']
|
||||
delay = 90019001
|
||||
@setAutocastDelay delay
|
||||
|
||||
|
|
|
@ -21,6 +21,10 @@ module.exports = class DebugView extends View
|
|||
@ace = options.ace
|
||||
@thang = options.thang
|
||||
@variableStates = {}
|
||||
@globals = {Math: Math, _: _} # ... add more as documented
|
||||
for className, klass of serializedClasses
|
||||
@globals[className] = klass
|
||||
@onMouseMove = _.throttle @onMouseMove, 25
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
|
@ -30,10 +34,11 @@ module.exports = class DebugView extends View
|
|||
@update()
|
||||
|
||||
onMouseMove: (e) =>
|
||||
return if @destroyed
|
||||
pos = e.getDocumentPosition()
|
||||
endOfDoc = pos.row is @ace.getSession().getDocument().getLength() - 1
|
||||
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())
|
||||
it.stepBackward()
|
||||
break unless token
|
||||
|
@ -52,7 +57,7 @@ module.exports = class DebugView extends View
|
|||
token = prev
|
||||
start = it.getCurrentTokenColumn()
|
||||
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
|
||||
offsetX = e.domEvent.offsetX ? e.clientX - $(e.domEvent.target).offset().left
|
||||
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)
|
||||
else
|
||||
@$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: ->
|
||||
|
@ -92,7 +101,7 @@ module.exports = class DebugView extends View
|
|||
return "<this #{value.id}>" if value is @thang and depth
|
||||
if depth is 2
|
||||
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
|
||||
value = value.toString()
|
||||
return value
|
||||
|
@ -124,8 +133,11 @@ module.exports = class DebugView extends View
|
|||
for prop, i in chain
|
||||
if prop is "this"
|
||||
value = @thang
|
||||
else if i is 0
|
||||
value = @variableStates[prop]
|
||||
if typeof value is "undefined" then value = @globals[prop]
|
||||
else
|
||||
value = (if i is 0 then @variableStates else value)[prop]
|
||||
value = value[prop]
|
||||
keys.push prop
|
||||
break unless value
|
||||
if theClass = serializedClasses[value.CN]
|
||||
|
|
|
@ -74,7 +74,7 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView
|
|||
formatPopover: (doc) ->
|
||||
content = popoverTemplate doc: doc, marked: marked, argumentExamples: (arg.example or arg.default or arg.name for arg in doc.args ? [])
|
||||
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('.'))
|
||||
|
||||
formatValue: (v) ->
|
||||
|
@ -101,12 +101,15 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView
|
|||
onClick: (e) -> # Don't call super
|
||||
|
||||
onDropdownClick: (e) ->
|
||||
return unless @controlsEnabled
|
||||
Backbone.Mediator.publish 'tome:toggle-spell-list'
|
||||
|
||||
onCodeReload: ->
|
||||
return unless @controlsEnabled
|
||||
Backbone.Mediator.publish "tome:reload-code", spell: @spell
|
||||
|
||||
onBeautifyClick: ->
|
||||
return unless @controlsEnabled
|
||||
Backbone.Mediator.publish "spell-beautify", spell: @spell
|
||||
|
||||
updateReloadButton: ->
|
||||
|
|
|
@ -66,6 +66,7 @@ module.exports = class SpellPaletteEntryView extends View
|
|||
'surface:frame-changed': "onFrameChanged"
|
||||
'tome:palette-hovered': "onPaletteHovered"
|
||||
'tome:palette-pin-toggled': "onPalettePinToggled"
|
||||
'tome:spell-debug-property-hovered': 'onSpellDebugPropertyHovered'
|
||||
|
||||
events:
|
||||
'mouseenter': 'onMouseEnter'
|
||||
|
@ -83,7 +84,11 @@ module.exports = class SpellPaletteEntryView extends View
|
|||
@doc.shortName = @doc.shorterName = @doc.title = @doc.name
|
||||
else
|
||||
@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};"
|
||||
if @doc.owner is 'this' or options.tabbify
|
||||
@doc.shorterName = "#{@doc.name}#{suffix}"
|
||||
|
@ -184,6 +189,16 @@ module.exports = class SpellPaletteEntryView extends View
|
|||
return if e.entry is @
|
||||
@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: ->
|
||||
$('.popover.pinned').remove() if @popoverPinned # @$el.popover('destroy') doesn't work
|
||||
@togglePinned() if @popoverPinned
|
||||
|
|
|
@ -46,24 +46,42 @@ module.exports = class SpellPaletteView extends View
|
|||
for doc in (lc.get('propertyDocumentation') ? [])
|
||||
allDocs[doc.name] ?= []
|
||||
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
|
||||
|
||||
props = _.sortBy @thang.programmableProperties ? []
|
||||
snippets = _.sortBy @thang.programmableSnippets ? []
|
||||
shortenize = props.length + snippets.length > 6
|
||||
tabbify = props.length + snippets.length >= 10
|
||||
propStorage =
|
||||
'this': 'programmableProperties'
|
||||
more: 'moreProgrammableProperties'
|
||||
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 = []
|
||||
for type, props of {props: props.slice(), snippets: snippets.slice()}
|
||||
for owner, props of propGroups
|
||||
for prop in props
|
||||
doc = allDocs[prop]?.shift() ? prop # Add one doc per instance of the prop name (this is super gimp)
|
||||
@entries.push @addEntry(doc, shortenize, tabbify, type is 'snippets')
|
||||
doc = _.find (allDocs[prop] ? []), (doc) ->
|
||||
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) ->
|
||||
order = ['this', 'Math', 'Vector', 'snippets']
|
||||
index = order.indexOf entry.doc.owner
|
||||
order = ['this', 'more', 'Math', 'Vector', 'snippets']
|
||||
index = order.indexOf groupForEntry entry
|
||||
index = String.fromCharCode if index is -1 then order.length else index
|
||||
index += entry.doc.name
|
||||
if tabbify and _.find @entries, ((entry) -> entry.doc.owner isnt 'this')
|
||||
@entryGroups = _.groupBy @entries, (entry) -> entry.doc.owner
|
||||
@entryGroups = _.groupBy @entries, groupForEntry
|
||||
else
|
||||
defaultGroup = $.i18n.t("play_level.tome_available_spells", defaultValue: "Available Spells")
|
||||
@entryGroups = {}
|
||||
|
|
|
@ -326,7 +326,10 @@ module.exports = class SpellView extends View
|
|||
isCast = not _.isEmpty(aether.metrics) or _.some aether.problems.errors, {type: 'runtime'}
|
||||
@problems = []
|
||||
annotations = []
|
||||
seenProblemKeys = {}
|
||||
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
|
||||
annotations.push problem.annotation if problem.annotation
|
||||
@aceSession.setAnnotations annotations
|
||||
|
@ -452,11 +455,11 @@ module.exports = class SpellView extends View
|
|||
markerRange.end.detach()
|
||||
@aceSession.removeMarker markerRange.id
|
||||
@markerRanges = []
|
||||
@debugView.setVariableStates {}
|
||||
@aceSession.removeGutterDecoration row, 'executing' for row in [0 ... @aceSession.getLength()]
|
||||
$(@ace.container).find('.ace_gutter-cell.executing').removeClass('executing')
|
||||
if not executed.length or (@spell.name is "plan" and @spellThang.castAether.metrics.statementsExecuted < 20)
|
||||
@toolbarView?.toggleFlow false
|
||||
@debugView.setVariableStates {}
|
||||
return
|
||||
lastExecuted = _.last executed
|
||||
@toolbarView?.toggleFlow true
|
||||
|
@ -464,6 +467,7 @@ module.exports = class SpellView extends View
|
|||
@toolbarView?.setCallState states[currentCallIndex], statementIndex, currentCallIndex, @spellThang.castAether.metrics
|
||||
marked = {}
|
||||
lastExecuted = lastExecuted[0 .. @toolbarView.statementIndex] if @toolbarView?.statementIndex?
|
||||
gotVariableStates = false
|
||||
for state, i in lastExecuted
|
||||
[start, end] = state.range
|
||||
clazz = if i is lastExecuted.length - 1 then 'executing' else 'executed'
|
||||
|
@ -473,6 +477,7 @@ module.exports = class SpellView extends View
|
|||
markerType = "fullLine"
|
||||
else
|
||||
@debugView.setVariableStates state.variables
|
||||
gotVariableStates = true
|
||||
markerType = "text"
|
||||
markerRange = new Range start.row, start.col, end.row, end.col
|
||||
markerRange.start = @aceDoc.createAnchor markerRange.start
|
||||
|
@ -480,6 +485,7 @@ module.exports = class SpellView extends View
|
|||
markerRange.id = @aceSession.addMarker markerRange, clazz, markerType
|
||||
@markerRanges.push markerRange
|
||||
@aceSession.addGutterDecoration start.row, clazz if clazz is 'executing'
|
||||
@debugView.setVariableStates {} unless gotVariableStates
|
||||
null
|
||||
|
||||
highlightComments: ->
|
||||
|
|
|
@ -21,6 +21,7 @@ module.exports = class ThangListEntryView extends View
|
|||
'surface:frame-changed': "onFrameChanged"
|
||||
'level-set-letterbox': 'onSetLetterbox'
|
||||
'tome:thang-list-entry-popover-shown': 'onThangListEntryPopoverShown'
|
||||
'surface:coordinates-shown': 'onSurfaceCoordinatesShown'
|
||||
|
||||
events:
|
||||
'click': 'onClick'
|
||||
|
@ -86,38 +87,47 @@ module.exports = class ThangListEntryView extends View
|
|||
|
||||
onMouseEnter: (e) ->
|
||||
return unless @controlsEnabled and @spells.length
|
||||
@showSpells()
|
||||
@clearTimeouts()
|
||||
@showSpellsTimeout = _.delay @showSpells, 100
|
||||
|
||||
onMouseLeave: (e) ->
|
||||
return unless @controlsEnabled and @spells.length
|
||||
clearTimeout @hideSpellsTimeout if @hideSpellsTimeout
|
||||
@clearTimeouts()
|
||||
@hideSpellsTimeout = _.delay @hideSpells, 100
|
||||
|
||||
clearTimeouts: ->
|
||||
clearTimeout @showSpellsTimeout if @showSpellsTimeout
|
||||
clearTimeout @hideSpellsTimeout if @hideSpellsTimeout
|
||||
@showSpellsTimeout = @hideSpellsTimeout = null
|
||||
|
||||
onThangListEntryPopoverShown: (e) ->
|
||||
# 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.
|
||||
return if e.entry is @
|
||||
@hideSpells()
|
||||
|
||||
onSurfaceCoordinatesShown: (e) ->
|
||||
# Definitely aren't hovering over this.
|
||||
@hideSpells()
|
||||
|
||||
showSpells: =>
|
||||
@clearTimeouts()
|
||||
@sortSpells()
|
||||
@$el.data('bs.popover').options.content = @getSpellListHTML()
|
||||
@$el.popover('setContent').popover('show')
|
||||
@$el.parent().parent().parent().i18n()
|
||||
clearTimeout @hideSpellsTimeout if @hideSpellsTimeout
|
||||
@hideSpellsTimeout = null
|
||||
@popover = @$el.parent().parent().parent().find('.popover')
|
||||
@popover.off 'mouseenter mouseleave'
|
||||
@popover.mouseenter (e) => @onMouseEnter()
|
||||
@popover.mouseleave (e) => @onMouseLeave()
|
||||
@popover.mouseenter (e) => @showSpells() if @controlsEnabled
|
||||
@popover.mouseleave (e) => @hideSpells()
|
||||
thangID = @thang.id
|
||||
@popover.find('code').click (e) ->
|
||||
Backbone.Mediator.publish "level-select-sprite", thangID: thangID, spellName: $(@).data 'spell-name'
|
||||
Backbone.Mediator.publish 'tome:thang-list-entry-popover-shown', entry: @
|
||||
|
||||
hideSpells: =>
|
||||
@clearTimeouts()
|
||||
@$el.popover('hide')
|
||||
@hideSpellsTimeout = null
|
||||
|
||||
getSpellListHTML: ->
|
||||
spellsPopoverTemplate {spells: @spells}
|
||||
|
@ -129,13 +139,16 @@ module.exports = class ThangListEntryView extends View
|
|||
onSetLetterbox: (e) ->
|
||||
if e.on then @reasonsToBeDisabled.letterbox = true else delete @reasonsToBeDisabled.letterbox
|
||||
@updateControls()
|
||||
|
||||
onDisableControls: (e) ->
|
||||
return if e.controls and not ('surface' in e.controls) # disable selection?
|
||||
@reasonsToBeDisabled.controls = true
|
||||
@updateControls()
|
||||
|
||||
onEnableControls: (e) ->
|
||||
delete @reasonsToBeDisabled.controls
|
||||
@updateControls()
|
||||
|
||||
updateControls: ->
|
||||
enabled = _.keys(@reasonsToBeDisabled).length is 0
|
||||
return if enabled is @controlsEnabled
|
||||
|
|
|
@ -151,9 +151,15 @@ module.exports = class TomeView extends View
|
|||
@cast()
|
||||
|
||||
cast: ->
|
||||
for spellKey, spell of @spells
|
||||
for thangID, spellThang of spell.thangs
|
||||
spellThang.aether.options.includeFlow = spellThang.aether.originalOptions.includeFlow = spellThang is @spellView?.spellThang
|
||||
if @options.levelID is 'project-dota'
|
||||
# For performance reasons, only includeFlow on the currently Thang.
|
||||
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
|
||||
|
||||
onToggleSpellList: (e) ->
|
||||
|
|
|
@ -116,6 +116,10 @@ module.exports = class PlayLevelView extends View
|
|||
getRenderData: ->
|
||||
c = super()
|
||||
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
|
||||
|
||||
afterRender: ->
|
||||
|
@ -194,7 +198,7 @@ module.exports = class PlayLevelView extends View
|
|||
|
||||
afterInsert: ->
|
||||
super()
|
||||
# @showWizardSettingsModal() if not me.get('name')
|
||||
@showWizardSettingsModal() if not me.get('name')
|
||||
|
||||
# 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))
|
||||
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
|
||||
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) ->
|
||||
requestSessionID = req.body.session
|
||||
validatePermissions req, requestSessionID, (error, permissionsAreValid) ->
|
||||
|
|
|
@ -5,6 +5,7 @@ UserHandler = require('../users/user_handler')
|
|||
config = require '../../server_config'
|
||||
errors = require '../commons/errors'
|
||||
mail = require '../commons/mail'
|
||||
languages = require '../routes/languages'
|
||||
|
||||
module.exports.setup = (app) ->
|
||||
authentication.serializeUser((user, done) -> done(null, user._id))
|
||||
|
@ -43,10 +44,36 @@ module.exports.setup = (app) ->
|
|||
)
|
||||
|
||||
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.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) ->
|
||||
req.logout()
|
||||
|
|
|
@ -6,6 +6,10 @@ scoringQueue = require '../queues/scoring'
|
|||
module.exports.setup = (app) ->
|
||||
scoringQueue.setup()
|
||||
|
||||
#app.post '/queue/scoring/pairwise', (req, res) ->
|
||||
# handler = loadQueueHandler 'scoring'
|
||||
# handler.addPairwiseTaskToQueue req, res
|
||||
|
||||
app.all '/queue/*', (req, res) ->
|
||||
setResponseHeaderToJSONContentType res
|
||||
|
||||
|
@ -24,6 +28,7 @@ module.exports.setup = (app) ->
|
|||
log.error error
|
||||
sendQueueError req, res, error
|
||||
|
||||
|
||||
setResponseHeaderToJSONContentType = (res) -> res.setHeader('Content-Type', 'application/json')
|
||||
|
||||
getQueueNameFromPath = (path) ->
|
||||
|
|
|
@ -3,7 +3,6 @@ crypto = require 'crypto'
|
|||
request = require 'request'
|
||||
User = require './User'
|
||||
Handler = require '../commons/Handler'
|
||||
languages = require '../routes/languages'
|
||||
mongoose = require 'mongoose'
|
||||
config = require '../../server_config'
|
||||
errors = require '../commons/errors'
|
||||
|
@ -172,28 +171,3 @@ UserHandler = class UserHandler extends Handler
|
|||
res.end()
|
||||
|
||||
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)
|
||||
app.use((req, res, next) -> setTimeout((-> next()), 1000))
|
||||
|
||||
setupUserMiddleware = (app) ->
|
||||
user.setupMiddleware(app)
|
||||
|
||||
setupMiddlewareToSendOldBrowserWarningWhenPlayersViewLevelDirectly = (app) ->
|
||||
isOldBrowser = (req) ->
|
||||
# https://github.com/biggora/express-useragent/blob/master/lib/express-useragent.js
|
||||
|
@ -66,7 +63,6 @@ exports.setupMiddleware = (app) ->
|
|||
setupExpressMiddleware app
|
||||
setupPassportMiddleware app
|
||||
setupOneSecondDelayMiddlware app
|
||||
setupUserMiddleware app
|
||||
|
||||
###Routing function implementations###
|
||||
|
||||
|
|
Loading…
Reference in a new issue