Merge branch 'master' into production

This commit is contained in:
Nick Winter 2014-05-18 13:46:47 -07:00
commit 83df107cdf
24 changed files with 244 additions and 248 deletions

View file

@ -188,10 +188,17 @@ self.retrieveValueFromFrame = function retrieveValueFromFrame(args) {
{
try
{
var flowStates = self.debugWorld.userCodeMap[currentThangID][currentSpellID].flow.states;
//we have to go to the second last flowState as we run the world for one additional frame
//to collect the flow
value = _.last(flowStates[flowStates.length - 1].statements).variables[prop];
if (Aether.globals[prop])
{
value = Aether.globals[prop];
}
else
{
var flowStates = self.debugWorld.userCodeMap[currentThangID][currentSpellID].flow.states;
//we have to go to the second last flowState as we run the world for one additional frame
//to collect the flow
value = _.last(flowStates[flowStates.length - 1].statements).variables[prop];
}
}
catch (e)
{

View file

@ -69,7 +69,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
@marks = {}
@labels = {}
@ranges = []
@handledAoEs = {}
@handledDisplayEvents = {}
@age = 0
@scaleFactor = @targetScaleFactor = 1
if @thangType.isFullyLoaded()
@ -213,6 +213,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
@updatePosition()
frameChanged = frameChanged or @targetScaleFactor isnt @scaleFactor
if frameChanged
@handledDisplayEvents = {}
@updateScale() # must happen before rotation
@updateAlpha()
@updateRotation()
@ -220,6 +221,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
@updateStats()
@updateGold()
@showAreaOfEffects()
@showTextEvents()
@updateHealthBar()
@updateMarks()
@updateLabels()
@ -228,9 +230,9 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
return unless @thang?.currentEvents
for event in @thang.currentEvents
continue unless event.startsWith 'aoe-'
continue if @handledAoEs[event]
continue if @handledDisplayEvents[event]
@handledAoEs[event] = true
@handledDisplayEvents[event] = true
args = JSON.parse(event[4...])
pos = @options.camera.worldToSurface {x:args[0], y:args[1]}
circle = new createjs.Shape()
@ -248,7 +250,31 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
.call =>
return if @destroyed
@options.groundLayer.removeChild circle
delete @handledAoEs[event]
delete @handledDisplayEvents[event]
showTextEvents: ->
return unless @thang?.currentEvents
for event in @thang.currentEvents
continue unless event.startsWith 'text-'
continue if @handledDisplayEvents[event]
@handledDisplayEvents[event] = true
options = JSON.parse(event[5...])
label = new createjs.Text options.text, "bold #{options.size or 16}px Arial", options.color or '#FFF'
label.shadow = new createjs.Shadow '#000', 0, 0, 2
offset = @getOffset 'aboveHead'
[label.x, label.y] = [@imageObject.x + offset.x - label.getMeasuredWidth() / 2, @imageObject.y + offset.y]
@options.floatingLayer.addChild label
window.labels ?= []
window.labels.push label
label.alpha = 0
createjs.Tween.get(label)
.to({y:label.y-2, alpha:1}, 200, createjs.Ease.linear)
.to({y:label.y-12}, 1000, createjs.Ease.linear)
.to({y:label.y-22, alpha:0}, 1000, createjs.Ease.linear)
.call =>
return if @destroyed
@options.floatingLayer.removeChild label
cache: ->
bounds = @imageObject.getBounds()
@ -472,7 +498,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
Backbone.Mediator.publish ourEventName, newEvent
addHealthBar: ->
return unless @thang?.health? and "health" in (@thang?.hudProperties ? [])
return unless @thang?.health? and "health" in (@thang?.hudProperties ? []) and @options.floatingLayer
healthColor = healthColors[@thang?.team] ? healthColors["neutral"]
healthOffset = @getOffset 'aboveHead'
bar = @healthBar = createProgressBar(healthColor, healthOffset)

View file

@ -20,7 +20,7 @@ module.exports = class Mark extends CocoClass
@build()
destroy: ->
createjs.Tween.removeTweens @mark
createjs.Tween.removeTweens @mark if @mark
@mark?.parent?.removeChild @mark
@markSprite?.destroy()
@sprite = null

View file

@ -591,12 +591,14 @@ module.exports = Surface = class Surface extends CocoClass
@mouseInBounds = mib
restoreWorldState: ->
@world.getFrame(@getCurrentFrame()).restoreState()
frame = @world.getFrame(@getCurrentFrame())
frame.restoreState()
current = Math.max(0, Math.min(@currentFrame, @world.totalFrames - 1))
if current - Math.floor(current) > 0.01
next = Math.ceil current
ratio = current % 1
@world.frames[next].restorePartialState ratio if next > 1
frame.clearEvents() if parseInt(@currentFrame) is parseInt(@lastFrame)
@spriteBoss.updateSounds()
updateState: (frameChanged) ->

View file

@ -36,6 +36,8 @@ module.exports = class WorldFrame
#console.log "Frame", @time, "restoring state for", thang.id, "in particular and saying it don't exist"
return
thangState.restore()
clearEvents: -> thang.currentEvents = [] for thang in @world.thangs
toString: ->
map = ((' ' for x in [0 .. @world.width]) \

View file

@ -233,8 +233,6 @@
victory_sign_up: "Sign Up to Save Progress"
victory_sign_up_poke: "Want to save your code? Create a free account!"
victory_rate_the_level: "Rate the level: "
victory_rank_my_game: "Rank My Game"
victory_ranking_game: "Submitting..."
victory_return_to_ladder: "Return to Ladder"
victory_play_next_level: "Play Next Level"
victory_go_home: "Go Home"

View file

@ -36,11 +36,11 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
nav:
play: "Jugar"
# community: "Community"
community: "Comunidad"
editor: "Editor"
blog: "Blog"
forum: "Foro"
# account: "Account"
account: "Cuenta"
admin: "Admin"
home: "Inicio"
contribute: "Colaborar"
@ -152,7 +152,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
autosave: "Los cambios se guardan automáticamente"
me_tab: "Yo"
picture_tab: "Foto"
# upload_picture: "Upload a picture"
upload_picture: "Sube una imagen"
wizard_tab: "Mago"
password_tab: "Contraseña"
emails_tab: "Correos electrónicos"
@ -168,7 +168,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
# email_any_notes: "Any Notifications"
# email_any_notes_description: "Disable to stop all activity notification emails."
# email_recruit_notes: "Job Opportunities"
# email_recruit_notes_description: "If you play really well, we may contact you about getting you a (better) job."
email_recruit_notes_description: "Si tu juegas realmente bien, puede que contactemos contigo para que consigas un trabajo (mejor)."
contributor_emails: "Correos para colaboradores"
contribute_prefix: "¡Buscamos gente que se una a nuestro comunidad! Comprueba la "
contribute_page: "página de colaboraciones"
@ -180,8 +180,8 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
job_profile: "Perfil de trabajo"
job_profile_approved: "Tu perfil de trabajo ha sido aprobado por CodeCombat. Los empleadores podrán verlo hasta que lo marques como inactivo o no haya sido cambiado durante cuatro semanas."
job_profile_explanation: "¡Hola! Rellena esto y estaremos en contacto para hablar sobre encontrarte un trabajo como desarrollador de software."
# sample_profile: "See a sample profile"
# view_profile: "View Your Profile"
sample_profile: "Mira un perfil de ejemplo"
view_profile: "Mira tu perfil"
account_profile:
edit_settings: "Ajustes"
@ -199,7 +199,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
employers:
want_to_hire_our_players: "¿Quieres contratar jugadores expertos de CodeCombat?"
# see_candidates: "Click here to see our candidates"
see_candidates: "Click aquí para ver a nuestros candidatos"
candidates_count_prefix: "Actualmente tenemos "
candidates_count_many: "muchos"
candidates_count_suffix: "desarrolladores altamente cualificados, y examinados atentamente, buscando trabajo."
@ -210,8 +210,8 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
candidate_top_skills: "Mejores Habilidades"
candidate_years_experience: "Años Exp"
candidate_last_updated: "Última actualización"
# candidate_approved: "Us?"
# candidate_active: "Them?"
candidate_approved: "¿Nosotros?"
candidate_active: "¿Ellos?"
play_level:
level_load_error: "No se pudo cargar el nivel: "
@ -246,7 +246,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
multiplayer_hint_label: "Pista:"
multiplayer_hint: " Haz un click en el link para que se seleccione, después utiliza Ctrl-C o ⌘-C para copiar el link."
multiplayer_coming_soon: "¡Más opciones de Multijugador están por venir!"
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
multiplayer_sign_in_leaderboard: "Logueate o crea una cuentra para guardar tus resultados en la tabla de clasificación."
guide_title: "Guía"
tome_minion_spells: "Los hechizos de tus súbditos"
tome_read_only_spells: "Hechizos de solo lectura"
@ -321,9 +321,9 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
lg_title: "Últimos Juegos"
clas: "CLAs"
# community:
# level_editor: "Level Editor"
# main_title: "CodeCombat Community"
community:
level_editor: "Editor de niveles"
main_title: "Comunidad de CodeCombat"
# facebook: "Facebook"
# twitter: "Twitter"
# gplus: "Google+"
@ -337,7 +337,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
thang_description: "Construye unidades, su lógica predeterminada, gráficos y audio. Actualmente sólo se permite importar gráficos vectoriales exportados de Flash."
level_title: "Editor de Niveles"
level_description: "Incluye las herramientas para escribir scripts, subir audio, y construir una lógica personalidad con la que crear todo tipo de niveles. ¡Todo lo que usamos nosotros!"
# got_questions: "Questions about using the CodeCombat editors?"
got_questions: "¿Preguntas sobre el uso de los editores CodeCombat?"
contact_us: "¡Contacta con nosotros!"
hipchat_prefix: "También puedes encontrarnos en nuestra"
hipchat_url: "sala de HipChat."
@ -379,9 +379,9 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
new_article_title: "Crear un nuevo artículo"
new_thang_title: "Crea un nuevo tipo de objeto"
new_level_title: "Crear un nuevo nivel"
# new_article_title_signup: "Sign Up to Create a New Article"
new_article_title_signup: "Registrarte para crear un nuevo artículo"
# new_thang_title_signup: "Sign Up to Create a New Thang Type"
# new_level_title_signup: "Sign Up to Create a New Level"
new_level_title_signup: "Registrarte para crear un nuevo nivel"
article_search_title: "Buscar artículos aquí"
thang_search_title: "Busca tipos de objetos aquí"
level_search_title: "Buscar niveles aquí"
@ -651,11 +651,11 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
simple_ai: "IA sencilla"
warmup: "calentamiento"
vs: "VS"
# friends_playing: "Friends Playing"
# sign_up_for_friends: "Sign up to play with your friends!"
# social_connect_blurb: "Connect and play against your friends!"
# invite_friends_to_battle: "Invite your friends to join you in battle!"
# fight: "Fight!"
friends_playing: "Amigos jugando"
sign_up_for_friends: "¡Registrate para jugar con tus amigos!"
social_connect_blurb: "¡Conectate y juega contra tus amigos!"
invite_friends_to_battle: "¡Invita a tus amigos a unirse a la batalla!"
fight: "¡Pelea!"
# watch_victory: "Watch your victory"
# defeat_the: "Defeat the"
@ -700,15 +700,15 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
user_profile: "Perfil de usuario"
patches: "Parches"
model: "Modelo"
# system: "System"
# component: "Component"
# components: "Components"
system: "Sistema"
component: "Componente"
components: "Componentes"
# thang: "Thang"
# thangs: "Thangs"
# level_session: "Your Session"
# opponent_session: "Opponent Session"
# article: "Article"
# user_names: "User Names"
# files: "Files"
# top_simulators: "Top Simulators"
# source_document: "Source Document"
level_session: "Tu sesión"
opponent_session: "Sesión del oponente"
article: "Artículo"
user_names: "Nombres de usuarios"
files: "Archivos"
top_simulators: "Top simuladores"
source_document: "Documento fuente"

View file

@ -0,0 +1,3 @@
.ladder-submission-view
h3
text-decoration: underline

View file

@ -0,0 +1,7 @@
button.btn.btn-success.rank-button
span(data-i18n="ladder.rank_no_code").unavailable.hidden No New Code to Rank
span(data-i18n="ladder.rank_my_game").rank.hidden Rank My Game!
span(data-i18n="ladder.rank_submitting").submitting.hidden Submitting...
span(data-i18n="ladder.rank_submitted").submitted.hidden Submitted for Ranking
span(data-i18n="ladder.rank_failed").failed.hidden Failed to Rank
span(data-i18n="ladder.rank_being_ranked").ranking.hidden Game Being Ranked

View file

@ -31,6 +31,11 @@ block content
a(href="#my-matches", data-toggle="tab", data-i18n="ladder.my_matches") My Matches
li
a(href="#simulate", data-toggle="tab", data-i18n="ladder.simulate") Simulate
if level.get('name') == 'Greed'
li
a(href="#prizes", data-toggle="tab", data-i18n="ladder.prizes") Prizes
li
a(href="#rules", data-toggle="tab", data-i18n="ladder.rules") Rules
div.tab-content
.tab-pane.active.well#ladder
@ -39,3 +44,9 @@ block content
#my-matches-tab-view
.tab-pane.well#simulate
#simulate-tab-view
.tab-pane.well#prizes
h1(data-i18n="ladder.prizes_remember_to_add_i18n_tags") Tournament Prizes
p(data-i18n="ladder.prizes_but_this_is_just_placeholder") Fill in the Greed prizes list here.
.tab-pane.well#rules
h1(data-i18n="ladder.rules_remember_to_add_i18n_tags") Tournament Rules
p(data-i18n="ladder.rules_but_this_is_just_placeholder") We probably don't have to translate legal documents from English, but we should translate any conversational summary.

View file

@ -1,9 +1,3 @@
//if matches.length
// p#your-score
// span Your Current Score:
// span
// strong= score
div#columns.row
for team in teams
div.matches-column.col-md-6
@ -23,21 +17,13 @@ div#columns.row
if team.session
tr
th(colspan=4)
button.btn.btn-warning.btn-block.rank-button(data-session-id=team.session.id)
span(data-i18n="ladder.rank_no_code").unavailable.hidden No New Code to Rank
span(data-i18n="ladder.rank_my_game").rank.hidden Rank My Game!
span(data-i18n="ladder.rank_submitting").submitting.hidden Submitting...
span(data-i18n="ladder.rank_submitted").submitted.hidden Submitted for Ranking
span(data-i18n="ladder.rank_failed").failed.hidden Failed to Rank
span(data-i18n="ladder.rank_being_ranked").ranking.hidden Game Being Ranked
.ladder-submission-view(data-session-id=team.session.id)
if team.chartData
if team.scoreHistory
tr
th(colspan=4, style="color: #{team.primaryColor}")
div(class="score-chart-wrapper", data-team-name=team.name, id="score-chart-#{team.name}")
tr
th(data-i18n="general.result") Result
th(data-i18n="general.opponent") Opponent

View file

@ -29,7 +29,7 @@ block modal-body-content
if me.get('anonymous')
p(data-i18n="play_level.multiplayer_sign_in_leaderboard") Sign in or create an account and get your solution on the leaderboard.
else if readyToRank
button.btn.btn-success.rank-game-button(data-i18n="play_level.victory_rank_my_game") Rank My Game
.ladder-submission-view
else
a.btn.btn-primary(href="/play/ladder/#{levelSlug}#my-matches", data-i18n="play_level.victory_go_ladder") Return to Ladder

View file

@ -12,7 +12,7 @@ block modal-body-content
block modal-footer-content
if readyToRank
button.btn.btn-success.rank-game-button(data-i18n="play_level.victory_rank_my_game") Rank My Game
.ladder-submission-view
else if level.get('type') === 'ladder'
a.btn.btn-primary(href="/play/ladder/#{level.get('slug')}#my-matches", data-dismiss="modal", data-i18n="play_level.victory_go_ladder") Return to Ladder
else if hasNextLevel

View file

@ -221,8 +221,8 @@ module.exports = class ThangTypeEditView extends View
@showMovieClip(animationName)
else
@showSprite(animationName)
@updateScale()
@updateRotation()
@updateScale() # must happen after update rotation, because updateRotation calls the sprite update() method.
showMovieClip: (animationName) ->
vectorParser = new SpriteBuilder(@thangType)
@ -279,11 +279,12 @@ module.exports = class ThangTypeEditView extends View
@currentSprite.update(true)
updateScale: =>
value = (@scaleSlider.slider('value') + 1) / 10
fixed = value.toFixed(1)
@scale = value
resValue = (@resolutionSlider.slider('value') + 1) / 10
scaleValue = (@scaleSlider.slider('value') + 1) / 10
fixed = scaleValue.toFixed(1)
@scale = scaleValue
@$el.find('.scale-label').text " #{fixed}x "
@currentObject.scaleX = @currentObject.scaleY = value if @currentObject?
@currentObject.scaleX = @currentObject.scaleY = scaleValue / resValue if @currentObject?
@updateGrid()
@updateDots()

View file

@ -0,0 +1,88 @@
CocoView = require 'views/kinds/CocoView'
template = require 'templates/play/common/ladder_submission'
module.exports = class LadderSubmissionView extends CocoView
class: "ladder-submission-view"
template: template
events:
'click .rank-button': 'rankSession'
constructor: (options) ->
super options
@session = options.session
@level = options.level
getRenderData: ->
ctx = super()
ctx.readyToRank = @session?.readyToRank()
ctx.isRanking = @ession?.get('isRanking')
ctx
afterRender: ->
super()
return unless @supermodel.finished()
@rankButton = @$el.find('.rank-button')
@updateButton()
updateButton: ->
rankingState = 'unavailable'
if @session?.readyToRank()
rankingState = 'rank'
else if @session?.get 'isRanking'
rankingState = 'ranking'
@setRankingButtonText rankingState
setRankingButtonText: (spanClass) ->
@rankButton.find('span').addClass('hidden')
@rankButton.find(".#{spanClass}").removeClass('hidden')
@rankButton.toggleClass 'disabled', spanClass isnt 'rank'
rankSession: (e) ->
return unless @session.readyToRank()
@setRankingButtonText 'submitting'
success = =>
@setRankingButtonText 'submitted' unless @destroyed
Backbone.Mediator.publish 'ladder:game-submitted', session: @session, level: @level
failure = (jqxhr, textStatus, errorThrown) =>
console.log jqxhr.responseText
@setRankingButtonText 'failed' unless @destroyed
transpiledCode = @transpileSession()
ajaxData =
session: @session.id
levelID: @level.id
originalLevelID: @level.get('original')
levelMajorVersion: @level.get('version').major
transpiledCode: transpiledCode
$.ajax '/queue/scoring', {
type: 'POST'
data: ajaxData
success: success
error: failure
}
transpileSession: ->
submittedCode = @session.get('code')
transpiledCode = {}
for thang, spells of submittedCode
transpiledCode[thang] = {}
for spellID, spell of spells
unless _.contains(@session.get('teamSpells')[@session.get('team')], thang + "/" + spellID) then continue
#DRY this
aetherOptions =
problems: {}
language: "javascript"
functionName: spellID
functionParameters: []
yieldConditionally: spellID is "plan"
globals: ['Vector', '_']
protectAPI: true
includeFlow: false
if spellID is "hear" then aetherOptions["functionParameters"] = ["speaker","message","data"]
aether = new Aether aetherOptions
transpiledCode[thang][spellID] = aether.transpile spell
transpiledCode

View file

@ -2,6 +2,7 @@ CocoView = require 'views/kinds/CocoView'
Level = require 'models/Level'
LevelSession = require 'models/LevelSession'
LeaderboardCollection = require 'collections/LeaderboardCollection'
LadderSubmissionView = require 'views/play/common/ladder_submission_view'
{teamDataFromLevel} = require './utils'
module.exports = class MyMatchesTabView extends CocoView
@ -9,9 +10,6 @@ module.exports = class MyMatchesTabView extends CocoView
template: require 'templates/play/ladder/my_matches_tab'
startsLoading: true
events:
'click .rank-button': 'rankSession'
constructor: (options, @level, @sessions) ->
super(options)
@nameMap = {}
@ -49,8 +47,6 @@ module.exports = class MyMatchesTabView extends CocoView
@startsLoading = false
@render()
getRenderData: ->
ctx = super()
ctx.level = @level
@ -84,36 +80,18 @@ module.exports = class MyMatchesTabView extends CocoView
scoreHistory = team.session?.get('scoreHistory')
if scoreHistory?.length > 1
team.scoreHistory = scoreHistory
scoreHistory = _.last scoreHistory, 100 # Chart URL needs to be under 2048 characters for GET
team.currentScore = Math.round scoreHistory[scoreHistory.length - 1][1] * 100
team.chartColor = team.primaryColor.replace '#', ''
#times = (s[0] for s in scoreHistory)
#times = ((100 * (t - times[0]) / (times[times.length - 1] - times[0])).toFixed(1) for t in times)
# Let's try being independent of time.
times = (i for s, i in scoreHistory)
scores = (s[1] for s in scoreHistory)
lowest = _.min scores #.concat([0])
highest = _.max scores #.concat(50)
scores = (Math.round(100 * (s - lowest) / (highest - lowest)) for s in scores)
team.chartData = times.join(',') + '|' + scores.join(',')
team.minScore = Math.round(100 * lowest)
team.maxScore = Math.round(100 * highest)
ctx
afterRender: ->
super()
@$el.find('.rank-button').each (i, el) =>
button = $(el)
sessionID = button.data('session-id')
@$el.find('.ladder-submission-view').each (i, el) =>
placeholder = $(el)
sessionID = placeholder.data('session-id')
session = _.find @sessions.models, {id: sessionID}
rankingState = 'unavailable'
if session.readyToRank()
rankingState = 'rank'
else if session.get 'isRanking'
rankingState = 'ranking'
@setRankingButtonText button, rankingState
ladderSubmissionView = new LadderSubmissionView session: session, level: @level
@insertSubView ladderSubmissionView, placeholder
ladderSubmissionView.$el.find('.rank-button').addClass 'btn-block'
@$el.find('.score-chart-wrapper').each (i, el) =>
scoreWrapper = $(el)
@ -170,59 +148,3 @@ module.exports = class MyMatchesTabView extends CocoView
.datum(data)
.attr("class",lineClass)
.attr("d",line)
rankSession: (e) ->
button = $(e.target).closest('.rank-button')
sessionID = button.data('session-id')
session = _.find @sessions.models, {id: sessionID}
return unless session.readyToRank()
@setRankingButtonText(button, 'submitting')
success = =>
@setRankingButtonText(button, 'submitted') unless @destroyed
failure = (jqxhr, textStatus, errorThrown) =>
console.log jqxhr.responseText
@setRankingButtonText(button, 'failed') unless @destroyed
transpiledCode = @transpileSession session
ajaxData =
session: sessionID
levelID: @level.id
originalLevelID: @level.attributes.original
levelMajorVersion: @level.attributes.version.major
transpiledCode: transpiledCode
$.ajax '/queue/scoring', {
type: 'POST'
data: ajaxData
success: success
error: failure
}
transpileSession: (session) ->
submittedCode = session.get('code')
transpiledCode = {}
for thang, spells of submittedCode
transpiledCode[thang] = {}
for spellID, spell of spells
unless _.contains(session.get('teamSpells')[session.get('team')], thang + "/" + spellID) then continue
#DRY this
aetherOptions =
problems: {}
language: "javascript"
functionName: spellID
functionParameters: []
yieldConditionally: spellID is "plan"
globals: ['Vector', '_']
protectAPI: true
includeFlow: false
if spellID is "hear" then aetherOptions["functionParameters"] = ["speaker","message","data"]
aether = new Aether aetherOptions
transpiledCode[thang][spellID] = aether.transpile spell
transpiledCode
setRankingButtonText: (rankButton, spanClass) ->
rankButton.find('span').addClass('hidden')
rankButton.find(".#{spanClass}").removeClass('hidden')
rankButton.toggleClass 'disabled', spanClass isnt 'rank'

View file

@ -1,15 +1,18 @@
View = require 'views/kinds/ModalView'
template = require 'templates/play/level/modal/multiplayer'
{me} = require('lib/auth')
{me} = require 'lib/auth'
LadderSubmissionView = require 'views/play/common/ladder_submission_view'
module.exports = class MultiplayerModal extends View
id: 'level-multiplayer-modal'
template: template
subscriptions:
'ladder:game-submitted': 'onGameSubmitted'
events:
'click textarea': 'onClickLink'
'change #multiplayer': 'updateLinkSection'
'click .rank-game-button': 'onRankGame'
constructor: (options) ->
super(options)
@ -36,10 +39,16 @@ module.exports = class MultiplayerModal extends View
afterRender: ->
super()
@updateLinkSection()
@ladderSubmissionView = new LadderSubmissionView session: @session, level: @level
@insertSubView @ladderSubmissionView, @$el.find('.ladder-submission-view')
onClickLink: (e) ->
e.target.select()
onGameSubmitted: (e) ->
ladderURL = "/play/ladder/#{@level.get('slug')}#my-matches"
Backbone.Mediator.publish 'router:navigate', route: ladderURL
updateLinkSection: ->
multiplayer = @$el.find('#multiplayer').prop('checked')
la = @$el.find('#link-area')
@ -50,48 +59,5 @@ module.exports = class MultiplayerModal extends View
multiplayer = Boolean(@$el.find('#multiplayer').prop('checked'))
@session.set('multiplayer', multiplayer)
onRankGame: (e) ->
button = @$el.find('.rank-game-button')
button.text($.i18n.t('play_level.victory_ranking_game', defaultValue: 'Submitting...'))
button.prop 'disabled', true
ajaxData =
session: @session.id
levelID: @level.id
originalLevelID: @level.get('original')
levelMajorVersion: @level.get('version').major
transpiledCode: @transpileSession(@session)
ladderURL = "/play/ladder/#{@level.get('slug')}#my-matches"
goToLadder = -> Backbone.Mediator.publish 'router:navigate', route: ladderURL
$.ajax '/queue/scoring',
type: 'POST'
data: ajaxData
success: goToLadder
failure: (response) ->
console.error "Couldn't submit game for ranking:", response
goToLadder()
transpileSession: (session) ->
submittedCode = session.get('code')
transpiledCode = {}
for thang, spells of submittedCode
transpiledCode[thang] = {}
for spellID, spell of spells
unless _.contains(session.get('teamSpells')[session.get('team')], thang + "/" + spellID) then continue
#DRY this
aetherOptions =
problems: {}
language: "javascript"
functionName: spellID
functionParameters: []
yieldConditionally: spellID is "plan"
globals: ['Vector', '_']
protectAPI: true
includeFlow: false
if spellID is "hear" then aetherOptions["functionParameters"] = ["speaker","message","data"]
aether = new Aether aetherOptions
transpiledCode[thang][spellID] = aether.transpile spell
transpiledCode
destroy: ->
super()

View file

@ -1,6 +1,7 @@
View = require 'views/kinds/ModalView'
template = require 'templates/play/level/modal/victory'
{me} = require 'lib/auth'
LadderSubmissionView = require 'views/play/common/ladder_submission_view'
LevelFeedback = require 'models/LevelFeedback'
utils = require 'lib/utils'
@ -8,9 +9,11 @@ module.exports = class VictoryModal extends View
id: 'level-victory-modal'
template: template
subscriptions:
'ladder:game-submitted': 'onGameSubmitted'
events:
'click .next-level-button': 'onPlayNextLevel'
'click .rank-game-button': 'onRankGame'
# review events
'mouseover .rating i': (e) -> @showStars(@starNum($(e.target)))
@ -58,48 +61,9 @@ module.exports = class VictoryModal extends View
@saveReview() if @$el.find('.review textarea').val()
Backbone.Mediator.publish('play-next-level')
onRankGame: (e) ->
button = @$el.find('.rank-game-button')
button.text($.i18n.t('play_level.victory_ranking_game', defaultValue: 'Submitting...'))
button.prop 'disabled', true
ajaxData =
session: @session.id
levelID: @level.id
originalLevelID: @level.get('original')
levelMajorVersion: @level.get('version').major
transpiledCode: @transpileSession @session
onGameSubmitted: (e) ->
ladderURL = "/play/ladder/#{@level.get('slug')}#my-matches"
goToLadder = -> Backbone.Mediator.publish 'router:navigate', route: ladderURL
$.ajax '/queue/scoring',
type: 'POST'
data: ajaxData
success: goToLadder
failure: (response) ->
console.error "Couldn't submit game for ranking:", response
goToLadder()
transpileSession: (session) ->
submittedCode = session.get('code')
transpiledCode = {}
for thang, spells of submittedCode
transpiledCode[thang] = {}
for spellID, spell of spells
#DRY this
unless _.contains(session.get('teamSpells')[session.get('team')], thang + "/" + spellID) then continue
aetherOptions =
problems: {}
language: "javascript"
functionName: spellID
functionParameters: []
yieldConditionally: spellID is "plan"
globals: ['Vector', '_']
protectAPI: true
includeFlow: false
if spellID is "hear" then aetherOptions["functionParameters"] = ["speaker","message","data"]
aether = new Aether aetherOptions
transpiledCode[thang][spellID] = aether.transpile spell
transpiledCode
Backbone.Mediator.publish 'router:navigate', route: ladderURL
getRenderData: ->
c = super()
@ -126,6 +90,8 @@ module.exports = class VictoryModal extends View
afterRender: ->
super()
@ladderSubmissionView = new LadderSubmissionView session: @session, level: @level
@insertSubView @ladderSubmissionView, @$el.find('.ladder-submission-view')
afterInsert: ->
super()

View file

@ -79,7 +79,7 @@ module.exports = class CastButtonView extends View
async.some _.values(@spells), (spell, callback) =>
spell.hasChangedSignificantly spell.getSource(), null, callback
, (castable) =>
Backbone.Mediator.publish 'tome:spell-has-changed-significantly-calculation', hasChangedSignificantly: castable
@castButtonGroup.toggleClass('castable', castable).toggleClass('casting', @casting)
if @casting
s = $.i18n.t("play_level.tome_cast_button_casting", defaultValue: "Casting")

View file

@ -17,6 +17,7 @@ module.exports = class DebugView extends View
'tome:spell-shown': 'changeCurrentThangAndSpell'
'tome:cast-spells': 'onTomeCast'
'surface:frame-changed': 'onFrameChanged'
'tome:spell-has-changed-significantly-calculation': 'onSpellChangedCalculation'
events: {}
@ -34,6 +35,8 @@ module.exports = class DebugView extends View
@cache = {}
@lastFrameRequested = -1
@workerIsSimulating = false
@spellHasChanged = false
pad2: (num) ->
@ -145,11 +148,17 @@ module.exports = class DebugView extends View
onFrameChanged: (data) ->
@currentFrame = data.frame
@frameRate = data.world.frameRate
onSpellChangedCalculation: (data) ->
@spellHasChanged = data.hasChangedSignificantly
update: ->
if @variableChain
if @variableChain.length is 2 and @variableChain[0] is "this"
if @spellHasChanged
@setTooltipText("You've changed this spell! \nPlease recast to use the hover debugger.")
else if @variableChain.length is 2 and @variableChain[0] is "this"
@setTooltipKeyAndValue(@variableChain.join("."),@stringifyValue(@thang[@variableChain[1]],0))
else if @variableChain.length is 1 and Aether.globals[@variableChain[0]]
@setTooltipKeyAndValue(@variableChain.join("."),@stringifyValue(Aether.globals[@variableChain[0]],0))
else if @workerIsSimulating
@setTooltipText("World is simulating, please wait...")
else if @currentFrame is @lastFrameRequested and (cacheValue = @retrieveValueFromCache(@thang.id, @spell.name, @variableChain, @currentFrame))

View file

@ -360,7 +360,7 @@ module.exports = class SpellView extends View
displayAether: (aether) ->
@displayedAether = aether
isCast = not _.isEmpty(aether.metrics) or _.some aether.problems.errors, {type: 'runtime'}
isCast = isCast or @language isnt 'javascript' # Since we don't have linting for other languages
isCast = isCast or @spell.language isnt 'javascript' # Since we don't have linting for other languages
problem.destroy() for problem in @problems # Just in case another problem was added since clearAetherDisplay() ran.
@problems = []
annotations = []

View file

@ -35,7 +35,7 @@ path = __dirname
m = require 'module'
request = require 'request'
Deferred = require "JQDeferred"
originalLoader = m._load
unhook = () ->
@ -90,6 +90,7 @@ GLOBAL.$ = GLOBAL.jQuery = (input) ->
append: (input)-> exports: ()->
cookies = request.jar()
$.when = Deferred.when
$.ajax = (options) ->
responded = false

View file

@ -56,7 +56,7 @@
"graceful-fs": "~2.0.1",
"node-force-domain": "~0.1.0",
"mailchimp-api": "2.0.x",
"express-useragent": "~0.0.9",
"express-useragent": "~0.0.9",
"gridfs-stream": "0.4.x",
"stream-buffers": "0.2.x",
"sendwithus": "2.0.x",
@ -66,7 +66,8 @@
"webworker-threads": "~0.4.11",
"node-gyp": "~0.13.0",
"aether": "~0.2.3",
"JASON": "~0.1.3"
"JASON": "~0.1.3",
"JQDeferred": "^2.1.0"
},
"devDependencies": {
"jade": "0.33.x",
@ -97,7 +98,7 @@
"karma": "~0.10.9",
"karma-coverage": "~0.1.4",
"compressible": "~1.0.1",
"jasmine-spec-reporter":"~0.3.0"
"jasmine-spec-reporter": "~0.3.0"
},
"license": "MIT for the code, and CC-BY for the art and music",
"private": true,

View file

@ -449,7 +449,7 @@ addMatchToSessions = (newScoreObject, callback) ->
matchObject.opponents[sessionID].name = session.name
matchObject.opponents[sessionID].totalScore = session.totalScore
matchObject.opponents[sessionID].metrics = {}
matchObject.opponents[sessionID].metrics.rank = Number(newScoreObject[sessionID].gameRanking)
matchObject.opponents[sessionID].metrics.rank = Number(newScoreObject[sessionID]?.gameRanking ? 0)
#log.info "Match object computed, result: #{matchObject}"
#log.info "Writing match object to database..."