Merge branch 'master' into production

This commit is contained in:
Nick Winter 2014-07-13 16:40:11 -07:00
commit cfd88dc187
20 changed files with 307 additions and 101 deletions

View file

@ -18,6 +18,7 @@ definitionSchemas =
'misc': require './schemas/definitions/misc'
init = ->
watchForErrors()
path = document.location.pathname
testing = path.startsWith '/test'
demoing = path.startsWith '/demo'
@ -79,3 +80,16 @@ initializeServices = ->
for service in services
service = require service
service()
watchForErrors = ->
currentErrors = 0
window.onerror = (msg, url, line, col, error) ->
return if currentErrors >= 3
return unless me.isAdmin() or document.location.href.search(/codecombat.com/) is -1 or document.location.href.search(/\/editor\//) isnt -1
++currentErrors
msg = "Error: #{msg}<br>Check the JS console for more."
#msg += "\nLine: #{line}" if line?
#msg += "\nColumn: #{col}" if col?
#msg += "\nError: #{error}" if error?
#msg += "\nStack: #{stack}" if stack = error?.stack
noty text: msg, layout: 'topCenter', type: 'error', killer: false, timeout: 5000, dismissQueue: true, maxVisible: 3, callback: {onClose: -> --currentErrors}

View file

@ -320,6 +320,7 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass
if ((noteGroup.script?.skippable) is false) and not options.force
@noteGroupQueue = @noteGroupQueue[i..]
@run()
@notifyScriptStateChanged()
return
@processNoteGroup(noteGroup)
@ -331,6 +332,7 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass
@noteGroupQueue = []
@resetThings()
@notifyScriptStateChanged()
onNoteGroupTimeout: (noteGroup) ->
return unless noteGroup is @currentNoteGroup

View file

@ -608,7 +608,7 @@ module.exports = Surface = class Surface extends CocoClass
ratio = current % 1
@world.frames[next].restorePartialState ratio if next > 1
frame.clearEvents() if parseInt(@currentFrame) is parseInt(@lastFrame)
@spriteBoss.updateSounds()
@spriteBoss.updateSounds() if parseInt(@currentFrame) isnt parseInt(@lastFrame)
updateState: (frameChanged) ->
# world state must have been restored in @restoreWorldState

View file

@ -54,6 +54,7 @@ module.exports.i18n = (say, target, language=me.lang(), fallback='en') ->
generalName = matches[0] if matches
for localeName, locale of say.i18n
continue if localeName is '-'
if target of locale
result = locale[target]
else continue

View file

@ -207,7 +207,11 @@ module.exports = class World
map = if kind is 'component' then @componentCodeClassMap else @systemCodeClassMap
c = map[js]
return c if c
try
c = map[js] = eval js
catch err
console.error "Couldn't compile #{kind} code:", err, "\n", js
c = map[js] = {}
c.className = name
c

View file

@ -482,7 +482,7 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
# twitter: "Twitter"
# gplus: "Google+"
# editor:
editor:
# main_title: "CodeCombat Editors"
# main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!"
# article_title: "Article Editor"
@ -501,6 +501,7 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
# revert_models: "Revert Models"
# fork_title: "Fork New Version"
# fork_creating: "Creating Fork..."
randomize: "Randomise"
# more: "More"
# wiki: "Wiki"
# live_chat: "Live Chat"

View file

@ -501,6 +501,7 @@
revert_models: "Revert Models"
fork_title: "Fork New Version"
fork_creating: "Creating Fork..."
randomize: "Randomize"
more: "More"
wiki: "Wiki"
live_chat: "Live Chat"

View file

@ -128,8 +128,8 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
forum_page: "nosso fórum"
forum_suffix: " como alternativa."
send: "Enviar Feedback"
# contact_candidate: "Contact Candidate"
# recruitment_reminder: "Use this form to reach out to candidates you are interested in interviewing. Remember that CodeCombat charges 15% of first-year salary. The fee is due upon hiring the employee and is refundable for 90 days if the employee does not remain employed. Part time, remote, and contract employees are free, as are interns."
contact_candidate: "Contactar Candidato"
recruitment_reminder: "Use este formulário para chegar a candidatos que esteja interessado em entrevistar. Lembre-se que o CodeCombat cobra 15% do salário do primeiro ano. A taxa é cobrada no momento da contratação do empregado e é reembolsável durante 90 dias, no caso de o trabalhador não se manter empregado. A empregados em part-time, no estrangeiro e a contrato não são aplicadas taxas, porque são internos."
diplomat_suggestion:
title: "Ajude a traduzir o CodeCombat!"
@ -173,7 +173,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
email_announcements: "Anúncios"
email_announcements_description: "Receba e-mails sobre as últimas novidades e desenvolvimentos no CodeCombat."
email_notifications: "Notificações"
# email_notifications_summary: "Controls for personalized, automatic email notifications related to your CodeCombat activity."
email_notifications_summary: "Controle, de uma forma personalizada e automática, os e-mails de notificações relacionados com a sua atividade no CodeCombat."
email_any_notes: "Quaisquer Notificações"
email_any_notes_description: "Desative para parar de receber todos os e-mails de notificação de atividade."
email_recruit_notes: "Oportunidades de Emprego"
@ -298,13 +298,13 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
# player_code: "Player Code"
employers:
# hire_developers_not_credentials: "Hire developers, not credentials."
# get_started: "Get Started"
# already_screened: "We've already technically screened all our candidates"
# filter_further: ", but you can also filter further:"
# filter_visa: "Visa"
# filter_visa_yes: "US Authorized"
# filter_visa_no: "Not Authorized"
hire_developers_not_credentials: "Contrate desenvolvedores, não cartas de recomendação."
get_started: "Começar"
already_screened: "Nós já selecionamos tecnicamente todos os nossos candidatos"
filter_further: ", mas ainda pode filtrar mais:"
filter_visa: "Visa"
filter_visa_yes: "Autorizado Para Trabalhar Nos EUA"
filter_visa_no: "Não Autorizado"
# filter_education_top: "Top School"
# filter_education_other: "Other"
# filter_role_web_developer: "Web Developer"
@ -326,9 +326,9 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
# pass_screen_blurb: "Review each candidate's code before reaching out. One employer found that 5x as many of our devs passed their technical screen than hiring from Hacker News."
# make_hiring_easier: "Make my hiring easier, please."
what: "O que é o CodeCombat?"
# what_blurb: "CodeCombat is a multiplayer browser programming game. Players write code to control their forces in battle against other developers. We support JavaScript, Python, Lua, Clojure, CoffeeScript, and Io."
# cost: "How much do we charge?"
# cost_blurb: "We charge 15% of first year's salary and offer a 100% money back guarantee for 90 days. We don't charge for candidates who are already actively being interviewed at your company."
what_blurb: "O CodeCombat é um jogo de programação, no navegador e multijogador. Os jogadores escrevem código para controlar as forças deles em batalha contra outros desenvolvedores. Nós suportamos JavaScript, Python, Lua, Clojure, CoffeeScript e Io."
cost: "Quanto é que cobramos?"
cost_blurb: "Cobramos 15% do salário do primeiro ano e ofereçemos uma garantia de devolução de 100% do dinheiro durante 90 dias. Não cobramos por candidatos que já estejam a ser ativamente entrevistados na sua companhia."
candidate_name: "Nome"
candidate_location: "Localização"
candidate_looking_for: "À Procura de"
@ -347,29 +347,29 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
customize_wizard: "Personalizar Feiticeiro"
home: "Início"
guide: "Guia"
multiplayer: "Multiplayer"
multiplayer: "Multijogador"
restart: "Reiniciar"
goals: "Objetivos"
# success: "Success!"
# incomplete: "Incomplete"
# timed_out: "Ran out of time"
# failing: "Failing"
action_timeline: "Linha do Tempo"
click_to_select: "Clica numa unidade para a selecionares."
reload_title: "Recarregar todo o código?"
reload_really: "Tens a certeza que queres recarregar este nível de volta ao início?"
reload_confirm: "Recarregar tudo"
success: "Successo!"
incomplete: "Incompletos"
timed_out: "Ficou sem tempo"
failing: "A falhar"
action_timeline: "Linha do Tempo de Ações"
click_to_select: "Clique numa unidade para selecioná-la."
reload_title: "Recarregar o Código Todo?"
reload_really: "Tem a certeza que quer recarregar este nível de volta ao início?"
reload_confirm: "Recarregar Tudo"
victory_title_prefix: ""
victory_title_suffix: " Concluído"
victory_sign_up: "Cria uma conta para guardar o teu progresso"
victory_sign_up_poke: "Queres guardar o teu código? Cria uma conta grátis!"
victory_rate_the_level: "Classifica este nível: "
victory_sign_up: "Criar Conta para Guardar Progresso"
victory_sign_up_poke: "Quer guardar o seu código? Crie uma conta grátis!"
victory_rate_the_level: "Classifique este nível: "
victory_return_to_ladder: "Voltar à Classificação"
victory_play_next_level: "Jogar próximo nível"
victory_go_home: "Ir para o Inicio"
victory_review: "Conta-nos mais!"
victory_hour_of_code_done: "É tudo?"
victory_hour_of_code_done_yes: "Sim, a minha Hora de Código chegou ao fim!"
victory_play_next_level: "Jogar Próximo Nível"
victory_go_home: "Ir para o Início"
victory_review: "Conte-nos mais!"
victory_hour_of_code_done: "É Tudo?"
victory_hour_of_code_done_yes: "Sim, a minha Hora de Código chegou ao fim!"
multiplayer_title: "Definições de Multiplayer"
multiplayer_link_description: "Dá este link a alguém para se juntar a ti."
multiplayer_hint_label: "Dica:"

View file

@ -30,7 +30,7 @@ module.exports = class Level extends CocoModel
visit = (system) ->
return if system.original of originalsSeen
systemModel = _.find systemModels, {original: system.original}
console.error 'Couldn\'t find model for original', system.original, 'from', systemModels unless systemModel
return console.error 'Couldn\'t find model for original', system.original, 'from', systemModels unless systemModel
for d in systemModel.dependencies or []
system2 = _.find levelSystems, {original: d.original}
visit system2
@ -61,7 +61,7 @@ module.exports = class Level extends CocoModel
for d in lc.dependencies or []
c2 = _.find thang.components, {original: d.original}
console.error thang.id, 'couldn\'t find dependent Component', d.original, 'from', lc.name unless c2
visit c2
visit c2 if c2
if lc.name is 'Collides'
allied = _.find levelComponents, {name: 'Allied'}
if allied

View file

@ -7,6 +7,7 @@ module.exports = class User extends CocoModel
@className: 'User'
@schema: require 'schemas/models/user'
urlRoot: '/db/user'
notyErrors: false
initialize: ->
super()

View file

@ -9,6 +9,9 @@ module.exports =
'note-group-ended':
{} # TODO schema
'modal-opened':
{} # TODO schema
'modal-closed':
{} # TODO schema

View file

@ -32,9 +32,6 @@ module.exports =
'level-set-grid':
{} # TODO schema
'tome:cast-spell':
{} # TODO schema
'level:restarted':
{} # TODO schema

View file

@ -1,74 +1,217 @@
module.exports =
'tome:cast-spell':
{} # TODO schema
"tome:cast-spell":
title: "Cast Spell"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when a spell is cast"
type: ["object", "undefined"]
properties:
spell:
type: "object"
thang:
type: "object"
preload:
type: "boolean"
required: []
additionalProperties: false
# TODO do we really need both 'cast-spell' and 'cast-spells'?
'tome:cast-spells':
{} # TODO schema
"tome:cast-spells":
title: "Cast Spells"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when spells are cast"
type: ["object", "undefined"]
properties:
spells:
type: "object"
preload:
type: "boolean"
required: []
additionalProperties: false
'tome:manual-cast':
{} # TODO schema
"tome:manual-cast":
title: "Manually Cast Spells"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when you wish to manually recast all spells"
type: "object"
properties: {}
required: []
additionalProperties: false
'tome:spell-created':
{} # TODO schema
"tome:spell-created":
title: "Spell Created"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published after a new spell has been created"
type: "object"
properties:
"spell": "object"
required: ["spell"]
additionalProperties: false
'tome:spell-debug-property-hovered':
{} # TODO schema
"tome:spell-debug-property-hovered":
title: "Spell Debug Property Hovered"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when you hover over a spell property"
type: "object"
properties:
"property": "string"
"owner": "string"
required: []
additionalProperties: false
'tome:toggle-spell-list':
{} # TODO schema
"tome:toggle-spell-list":
title: "Toggle Spell List"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when you toggle the dropdown for a thang's spells"
type: "undefined"
additionalProperties: false
'tome:reload-code':
{} # TODO schema
"tome:reload-code":
title: "Reload Code"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when you reset a spell to its original source"
type: "object"
properties:
"spell": "object"
required: ["spell"]
additionalProperties: false
'tome:palette-hovered':
{} # TODO schema
"tome:palette-hovered":
title: "Palette Hovered"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when you hover over a Thang in the spell palette"
type: "object"
properties:
"thang": "object"
"prop": "string"
"entry": "object"
required: ["thang", "prop", "entry"]
additionalProperties: false
'tome:palette-pin-toggled':
{} # TODO schema
"tome:palette-pin-toggled":
title: "Palette Pin Toggled"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when you pin or unpin the spell palette"
type: "object"
properties:
"entry": "object"
"pinned": "boolean"
required: ["entry", "pinned"]
additionalProperties: false
'tome:palette-clicked':
{} # TODO schema
"tome:palette-clicked":
title: "Palette Clicked"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when you click on the spell palette"
type: "object"
properties:
"thang": "object"
"prop": "string"
"entry": "object"
required: ["thang", "prop", "entry"]
additionalProperties: false
'tome:spell-statement-index-updated':
{} # TODO schema
"tome:spell-statement-index-updated":
title: "Spell Statement Index Updated"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when the spell index is updated"
type: "object"
properties:
"statementIndex": "object"
"ace": "object"
required: ["statementIndex", "ace"]
additionalProperties: false
# TODO proposition: refactor 'tome' into spell events
'spell-beautify':
{} # TODO schema
"spell-beautify":
title: "Beautify"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when you click the \"beautify\" button"
type: "object"
properties:
"spell": "object"
required: []
additionalProperties: false
'spell-step-forward':
{} # TODO schema
"spell-step-forward":
title: "Step Forward"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when you step forward in time"
type: "undefined"
additionalProperties: false
'spell-step-backward':
{} # TODO schema
"spell-step-backward":
title: "Step Backward"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when you step backward in time"
type: "undefined"
additionalProperties: false
'tome:spell-loaded':
{} # TODO schema
"tome:spell-loaded":
title: "Spell Loaded"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when a spell is loaded"
type: "object"
properties:
"spell": "object"
required: ["spell"]
additionalProperties: false
'tome:cast-spell':
{} # TODO schema
"tome:spell-changed":
title: "Spell Changed"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when a spell is changed"
type: "object"
properties:
"spell": "object"
required: ["spell"]
additionalProperties: false
'tome:spell-changed':
{} # TODO schema
"tome:editing-began":
title: "Editing Began"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when you have begun changing code"
type: "undefined"
additionalProperties: false
'tome:editing-ended':
{} # TODO schema
"tome:editing-ended":
title: "Editing Ended"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when you have stopped changing code"
type: "undefined"
additionalProperties: false
'tome:editing-began':
{} # TODO schema
"tome:problems-updated":
title: "Problems Updated"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when problems have been updated"
type: "object"
properties:
"spell": "object"
"problems": "array"
"isCast": "boolean"
required: ["spell", "problems", "isCast"]
additionalProperties: false
'tome:problems-updated':
{} # TODO schema
"tome:thang-list-entry-popover-shown":
title: "Thang List Entry Popover Shown"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when we show the popover for a thang in the master list"
type: "object"
properties:
"entry": "object"
required: ["entry"]
additionalProperties: false
'tome:thang-list-entry-popover-shown':
{} # TODO schema
'tome:spell-shown':
{} # TODO schema
'tome:focus-editor':
{} # TODO schema
"tome:spell-shown":
title: "Spell Shown"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when we show a spell"
type: "object"
properties:
"thang": "object"
"spell": "object"
required: ["thang", "spell"]
additionalProperties: false
'tome:change-language':
title: 'Tome Change Language'
@ -93,3 +236,37 @@ module.exports =
language:
type: 'string'
required: ['spell']
"tome:comment-my-code":
title: "Comment My Code"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when we comment out a chunk of your code"
type: "undefined"
additionalProperties: false
"tome:change-config":
title: "Change Config"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when you change your tome settings"
type: "undefined"
additionalProperties: false
"tome:update-snippets":
title: "Update Snippets"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published when we need to add Zatanna Snippets"
type: "object"
properties:
"propGroups": "object"
"allDocs": "object"
"language": "string"
required: ["propGroups", "allDocs"]
additionalProperties: false
# TODO proposition: add tome to name
"focus-editor":
title: "Focus Editor"
$schema: "http://json-schema.org/draft-04/schema#"
description: "Published whenever we want to give focus back to the editor"
type: "undefined"
additionalProperties: false

View file

@ -70,17 +70,17 @@ block header
a#level-watch-button
span.watch
span.glyphicon.glyphicon-eye-open
span.spl Watch
span.spl(data-i18n="common.watch") Watch
span.unwatch.secret
span.glyphicon.glyphicon-eye-close
span.spl Unwatch
span.spl(data-i18n="common.unwatch") Unwatch
li(class=anonymous ? "disabled": "")
a(data-i18n="common.fork")#fork-level-start-button Fork
li(class=anonymous ? "disabled": "")
a(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert")#revert-button Revert
li(class=anonymous ? "disabled": "")
a(data-toggle="coco-modal", data-target="modal/terrain_randomise", data-i18n="editor.randomise")#randomise-button Randomise
a(data-toggle="coco-modal", data-target="modal/terrain_randomise", data-i18n="editor.randomize")#randomise-button Randomise
li(class=anonymous ? "disabled": "")
a(data-i18n="editor.pop_i18n")#pop-level-i18n-button Populate i18n
li.divider

View file

@ -322,7 +322,7 @@ class LatestVersionReferenceNode extends TreemaNode
return unless term
@lastTerm = term
@getSearchResultsEl().empty().append('Searching')
@collection = new LatestVersionCollection()
@collection = new LatestVersionCollection([], model: @model)
# HACK while search is broken
# @collection.url = "#{@url}?term=#{term}&project=true"

View file

@ -177,6 +177,7 @@ module.exports = class CocoView extends Backbone.View
$('#modal-wrapper .modal').modal(modalOptions).on 'hidden.bs.modal', @modalClosed
window.currentModal = modalView
@getRootView().stopListeningToShortcuts(true)
Backbone.Mediator.publish 'modal-opened', {}
modalClosed: =>
visibleModal.willDisappear() if visibleModal
@ -190,7 +191,7 @@ module.exports = class CocoView extends Backbone.View
@openModalView(wm)
else
@getRootView().listenToShortcuts(true)
Backbone.Mediator.publish 'modal-closed'
Backbone.Mediator.publish 'modal-closed', {}
# Loading RootViews

View file

@ -57,6 +57,7 @@ module.exports = class SpellPaletteView extends View
allDocs = {}
for lc in lcs
for doc in (lc.get('propertyDocumentation') ? [])
continue if doc.codeLanguages and not (@options.language in doc.codeLanguages)
allDocs['__' + doc.name] ?= []
allDocs['__' + doc.name].push doc
if doc.type is 'snippet' then doc.owner = 'snippets'
@ -83,7 +84,6 @@ module.exports = class SpellPaletteView extends View
'this': 'apiProperties'
count = 0
propGroups = {}
console.log 'thang', @thang
for owner, storage of propStorage
props = _.reject @thang[storage] ? [], (prop) -> prop[0] is '_' # no private properties
added = propGroups[owner] = _.sortBy(props).slice()

View file

@ -138,7 +138,13 @@ module.exports = class PlayLevelView extends View
supermodel: @supermodel
firstOnly: true
@openModalView(new DocsModal(options), true)
Backbone.Mediator.subscribeOnce 'modal-closed', @onLevelStarted, @
onGuideOpened = ->
@guideOpenTime = new Date()
onGuideClosed = ->
application.tracker?.trackTiming new Date() - @guideOpenTime, 'Intro Guide Time', @levelID, @levelID, 100
@onLevelStarted()
Backbone.Mediator.subscribeOnce 'modal-opened', onGuideOpened, @
Backbone.Mediator.subscribeOnce 'modal-closed', onGuideClosed, @
return true
getRenderData: ->

View file

@ -5,7 +5,6 @@ async = require 'async'
errors = require '../commons/errors'
aws = require 'aws-sdk'
db = require './../routes/db'
mongoose = require 'mongoose'
queues = require '../commons/queue'
LevelSession = require '../levels/sessions/LevelSession'
Level = require '../levels/Level'
@ -125,7 +124,7 @@ module.exports.getTwoGames = (req, res) ->
#if userIsAnonymous req then return errors.unauthorized(res, 'You need to be logged in to get games.')
humansGameID = req.body.humansGameID
ogresGameID = req.body.ogresGameID
ladderGameIDs = ['greed','criss-cross','brawlwood','dungeon-arena','gold-rush']
ladderGameIDs = ['greed', 'criss-cross', 'brawlwood', 'dungeon-arena', 'gold-rush']
levelID = _.sample ladderGameIDs
unless ogresGameID and humansGameID
#fetch random games here
@ -546,7 +545,6 @@ saveNewScoresToDatabase = (newScoreArray, callback) ->
#log.info 'Saved new scores to database'
callback err, newScoreArray
updateScoreInSession = (scoreObject, callback) ->
LevelSession.findOne {'_id': scoreObject.id}, (err, session) ->
if err? then return callback err, null