From 5b5af5a55ac8486707a8d640e5d78637d92e63d5 Mon Sep 17 00:00:00 2001
From: Finn <finnfantparadis@gmail.com>
Date: Fri, 28 Feb 2014 12:06:26 +0100
Subject: [PATCH 001/178] Update names.coffee

Added the name "Cid" under "Soldier M".
---
 app/lib/world/names.coffee | 1 +
 1 file changed, 1 insertion(+)

diff --git a/app/lib/world/names.coffee b/app/lib/world/names.coffee
index d47f92425..7ba332f60 100644
--- a/app/lib/world/names.coffee
+++ b/app/lib/world/names.coffee
@@ -44,6 +44,7 @@ module.exports.thangNames = thangNames =
     "Huburt"
     "Sterling"
     "Alistair"
+    "Cid"
     "Remy"
     "Stormy"
     "Halle"

From 9c107f24f868b5b2ce210b60a54f91a203ebf426 Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Sat, 1 Mar 2014 03:31:36 +0400
Subject: [PATCH 002/178] Finishing ru.coffee

---
 app/locale/ru.coffee | 54 ++++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index b1102bc8e..985282a6c 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -201,15 +201,15 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     hud_continue: "Продолжить (нажмите Shift+Пробел)"
     spell_saved: "Заклинание сохранено"
 
-#  admin:
-#    av_title: "Admin Views"
-#    av_entities_sub_title: "Entities"
-#    av_entities_users_url: "Users"
-#    av_entities_active_instances_url: "Active Instances"
-#    av_other_sub_title: "Other"
-#    av_other_debug_base_url: "Base (for debugging base.jade)"
-#    u_title: "User List"
-#    lg_title: "Latest Games"
+  admin:
+    av_title: "Админ панель"
+    av_entities_sub_title: "Сущности"
+    av_entities_users_url: "Пользователи"
+    av_entities_active_instances_url: "Активные экземпляры"
+    av_other_sub_title: "Другое"
+    av_other_debug_base_url: "База (для отладки base.jade)"
+    u_title: "Список пользователей"
+    lg_title: "Последние игры"
 
   editor:
     main_title: "Редакторы CodeCombat"
@@ -224,7 +224,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     contact_us: "свяжитесь с нами!"
     hipchat_prefix: "Также вы можете найти нас в нашей"
     hipchat_url: "комнате HipChat."
-#    level_some_options: "Some Options?"
+    level_some_options: "Ещё опции"
     level_tab_thangs: "Объекты"
     level_tab_scripts: "Скрипты"
     level_tab_settings: "Настройки"
@@ -254,7 +254,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
   general:
     and: "и"
     name: "Имя"
-#    body: "Body"
+    body: "Содержание"
     version: "Версия"
     commit_msg: "Сопроводительное сообщение"
     version_history_for: "История версий для: "
@@ -418,22 +418,22 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     diplomat_join_suf_github: ", отредактируйте его онлайн и отправьте запрос на включение изменений. Кроме того, установите флажок ниже, чтобы быть в курсе новых разработок интернационализации!"
     more_about_diplomat: "Узнать больше о том, как стать Дипломатом"
     diplomat_subscribe_desc: "Получать email-ы о i18n разработках и уровнях для перевода."
-#    ambassador_summary: "Мы пытаемся создать сообщество, и каждое сообщество нуждается в службе поддержки, когда есть проблемы. У нас есть чаты, электронная почта и социальные сети, чтобы наши пользователи могли познакомиться с игрой. Если вы хотите помочь людям втянуться, получать удовольствие и учиться программированию, этот класс для вас."  # Not done yet
-#    ambassador_introduction: "This is a community we're building, and you are the connections. We've got Olark chats, emails, and social networks with lots of people to talk with and help get acquainted with the game and learn from. If you want to help people get involved and have fun, and get a good feel of the pulse of CodeCombat and where we're going, then this class might be for you."
-#    ambassador_attribute_1: "Communication skills. Be able to identify the problems players are having and help them solve them. Also, keep the rest of us informed about what players are saying, what they like and don't like and want more of!"
-#    ambassador_join_desc: "tell us a little about yourself, what you've done and what you'd be interested in doing. We'll go from there!"
-#    ambassador_join_note_strong: "Note"
-#    ambassador_join_note_desc: "One of our top priorities is to build multiplayer where players having difficulty solving levels can summon higher level wizards to help them. This will be a great way for ambassadors to do their thing. We'll keep you posted!"
-#    more_about_ambassador: "Узнать больше о том, как стать Ambassador"  # Not done yet
-#    ambassador_subscribe_desc: "Get emails on support updates and multiplayer developments."
-#    counselor_summary: "None of the above roles fit what you are interested in? Do not worry, we are on the lookout for anybody who wants a hand in the development of CodeCombat! If you are interested in teaching, game development, open source management, or anything else that you think will be relevant to us, then this class is for you."
-#    counselor_introduction_1: "Do you have life experience? A different perspective on things that can help us decide how to shape CodeCombat? Of all these roles, this will probably take the least time, but individually you may make the most difference. We're on the lookout for wisened sages, particularly in areas like: teaching, game development, open source project management, technical recruiting, entrepreneurship, or design."
-#    counselor_introduction_2: "Or really anything that is relevant to the development of CodeCombat. If you have knowledge and want to share it to help grow this project, then this class might be for you."
-#    counselor_attribute_1: "Experience, in any of the areas above or something you think might be helpful."
-#    counselor_attribute_2: "A little bit of free time!"
-#    counselor_join_desc: "tell us a little about yourself, what you've done and what you'd be interested in doing. We'll put you in our contact list and be in touch when we could use advice (not too often)."
-#    more_about_counselor: "Узнать больше о том, как стать Counselor"  # Not done yet
-#    changes_auto_save: "Changes are saved automatically when you toggle checkboxes."
+    ambassador_summary: "Мы пытаемся создать сообщество, и каждое сообщество нуждается в службе поддержки, когда есть проблемы. У нас есть чаты, электронная почта и социальные сети, чтобы наши пользователи могли познакомиться с игрой. Если вы хотите помочь людям втянуться, получать удовольствие и учиться программированию, этот класс для вас."
+    ambassador_introduction: "Это сообщество, которое мы создаём, и вы соединяете. У нас есть Olark чаты, электронная почта и социальные сети с уймой людей, с которыми нужно поговорить, помочь в ознакомлении с игрой и обучении из неё. Если вы хотите помочь людям втянуться, получать удовольствие, наслаждаться и и куда мы идём, этот класс для вас."
+    ambassador_attribute_1: "Навыки общения. Уметь определять проблемы игроков и помогать решить их. Кроме того, держите всех нас в курсе о том, что игроки говорят, что им нравится, не нравится и чего хотят больше!"
+    ambassador_join_desc: "расскажите нам немного о себе, чем вы занимались и чем хотели бы заниматься. Отсюда и начнём!"
+    ambassador_join_note_strong: "Примечание"
+    ambassador_join_note_desc: "Одним из наших главных приоритетов является создание мультиплеера, где игроки столкнутся с труднорешаемыми уровнями и могут призвать более высокоуровневых волшебников для помощи. Это будет отличным способом для послов делать свое дело. Мы будем держать вас в курсе!"
+    more_about_ambassador: "Узнать больше о том, как стать Послом"
+    ambassador_subscribe_desc: "Получать email-ы о разработке мультиплеера и обновлениях в системе поддержки."
+    counselor_summary: "Ни одна из вышеупомянутых ролей не соответствует тому, в чём вы заинтересованы? Не волнуйтесь, мы в поисках тех, кто хочет приложить руку к разработке CodeCombat! Если вы заинтересованы в обучении, разработке игр, управлением проектами с открытым исходным кодом, или в чём-нибудь ещё, что, как вы думаете, будет актуально для нас, то этот класс для вас."
+    counselor_introduction_1: "У вас есть жизненный опыт? Другая точка зрения на вещи, которые могут помочь нам решить, как формировать CodeCombat? Из всех этих ролей, эта, возможно, займёт меньше всего времени, но по отдельности, вы можете сделать наибольшие изменения. Мы в поисках морщинистых мудрецов, особенно в таких областях, как: обучение, разработка игр, управление проектами с открытым исходным кодом, технической рекрутинг, предпринимательство или дизайн."
+    counselor_introduction_2: "Или действительно всё, что имеет отношение к развитию CodeCombat. Если у вас есть знания и вы хотите поделиться ими, чтобы помочь вырастить этот проект, то этот класс для вас."
+    counselor_attribute_1: "Опыт, в любой из областей выше, или в том, что, как вы думаете, может быть полезным."
+    counselor_attribute_2: "Немного свободного времени!"
+    counselor_join_desc: "расскажите нам немного о себе, чем вы занимались и чем хотели бы заниматься. Мы поместим вас в наш список контактов и выйдем на связь, когда нам понадобится совет(не слишком часто)."
+    more_about_counselor: "Узнать больше о том, как стать Советником"
+    changes_auto_save: "Изменения сохраняются автоматически при переключении флажков."
     diligent_scribes: "Наши старательные Писари:"
     powerful_archmages: "Наши могущественные Архимаги:"
     creative_artisans: "Наши творческие Ремесленники:"

From 789b49e15f5349cba6f8060290feee0e1e698f36 Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Sat, 1 Mar 2014 03:37:11 +0400
Subject: [PATCH 003/178] Update diplomat.jade

---
 app/templates/contribute/diplomat.jade | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/templates/contribute/diplomat.jade b/app/templates/contribute/diplomat.jade
index 1c7863680..6b02823a6 100644
--- a/app/templates/contribute/diplomat.jade
+++ b/app/templates/contribute/diplomat.jade
@@ -86,7 +86,7 @@ block content
           li Slovak - Anon
           li Persian - Reza Habibi (Rehb)
           li Czech - vanous
-          li Russian - fess89, ser-storchak
+          li Russian - fess89, ser-storchak, Mr.A
           li Ukrainian - fess89
           li Italian - flauta
           li Norwegian - bardeh

From d68ff5a8997f82b433c030c65088479ad1fad633 Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Sat, 1 Mar 2014 04:54:54 +0400
Subject: [PATCH 004/178] Fix diplomat.jade building

---
 app/templates/contribute/diplomat.jade | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/templates/contribute/diplomat.jade b/app/templates/contribute/diplomat.jade
index 6b02823a6..06743761c 100644
--- a/app/templates/contribute/diplomat.jade
+++ b/app/templates/contribute/diplomat.jade
@@ -86,7 +86,7 @@ block content
           li Slovak - Anon
           li Persian - Reza Habibi (Rehb)
           li Czech - vanous
-          li Russian - fess89, ser-storchak, Mr.A
+          li Russian - fess89, ser-storchak, Mr A
           li Ukrainian - fess89
           li Italian - flauta
           li Norwegian - bardeh

From 8cc8103288d9a280e1bac2f9f440cd8e548d3fab Mon Sep 17 00:00:00 2001
From: Muhammed Thanish <mnmtanish@gmail.com>
Date: Sat, 1 Mar 2014 19:58:15 +0530
Subject: [PATCH 005/178] Add keyboard shortcuts to move the wizard

---
 app/lib/LevelBus.coffee                   | 10 ++++++++++
 app/lib/surface/Camera.coffee             | 14 +++++++++-----
 app/views/play/level/playback_view.coffee | 16 ++++++++++++++++
 3 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/app/lib/LevelBus.coffee b/app/lib/LevelBus.coffee
index 18985716b..707b0cef8 100644
--- a/app/lib/LevelBus.coffee
+++ b/app/lib/LevelBus.coffee
@@ -22,6 +22,7 @@ module.exports = class LevelBus extends Bus
     'level-show-victory': 'onVictory'
     'tome:spell-changed': 'onSpellChanged'
     'tome:spell-created': 'onSpellCreated'
+    'self-wizard:move': 'moveWizard'
 
   constructor: ->
     super(arguments...)
@@ -240,3 +241,12 @@ module.exports = class LevelBus extends Bus
   destroy: ->
     @session.off 'change:multiplayer', @onMultiplayerChanged, @
     super()
+
+  moveWizard : (x, y) =>
+    wizardSprite = @getSelfWizard()
+    position = wizardSprite.getCurrentPosition()
+    position.x += x
+    position.y += y
+    wizardSprite.setTarget(position,1000)
+    wizardSprite.updatePosition()
+    Backbone.Mediator.publish 'camera-zoom-to', position
diff --git a/app/lib/surface/Camera.coffee b/app/lib/surface/Camera.coffee
index 6c5ec946f..70ee37884 100644
--- a/app/lib/surface/Camera.coffee
+++ b/app/lib/surface/Camera.coffee
@@ -42,6 +42,7 @@ module.exports = class Camera extends CocoClass
     'level:restarted': 'onLevelRestarted'
     'sprite:mouse-down': 'onMouseDown'
     'sprite:dragged': 'onMouseDragged'
+    'camera-zoom-to': 'onZoomTo'
 
   # TODO: Fix tests to not use mainLayer
   constructor: (@canvasWidth, @canvasHeight, angle=Math.asin(0.75), hFOV=d2r(30)) ->
@@ -169,7 +170,7 @@ module.exports = class Camera extends CocoClass
   onMouseDown: (e) ->
     return if @dragDisabled
     @lastPos = {x: e.originalEvent.rawX, y: e.originalEvent.rawY}
-    
+
   onMouseDragged: (e) ->
     return if @dragDisabled
     target = @boundTarget(@target, @zoom)
@@ -180,7 +181,7 @@ module.exports = class Camera extends CocoClass
     @zoomTo newPos, @zoom, 0
     @lastPos = {x: e.originalEvent.rawX, y: e.originalEvent.rawY}
     Backbone.Mediator.publish 'camera:dragged'
-    
+
   onLevelRestarted: ->
     @setBounds(@firstBounds, false)
 
@@ -220,7 +221,7 @@ module.exports = class Camera extends CocoClass
     newTarget ?= {x:0, y:0}
     newTarget = (@newTarget or @target) if @locked
     newZoom = Math.min((Math.max @minZoom, newZoom), MAX_ZOOM)
-    
+
     thangType = @target?.sprite?.thangType
     if thangType
       @offset = _.clone(thangType.get('positions')?.torso or {x: 0, y:0})
@@ -229,7 +230,7 @@ module.exports = class Camera extends CocoClass
       @offset.y *= scale
     else
       @offset = {x: 0, y:0}
-      
+
     return if @zoom is newZoom and newTarget is newTarget.x and newTarget.y is newTarget.y
 
     @finishTween(true)
@@ -247,7 +248,7 @@ module.exports = class Camera extends CocoClass
       @target = newTarget
       @zoom = newZoom
       @updateZoom true
-      
+
   focusedOnSprite: ->
     return @target?.name
 
@@ -308,3 +309,6 @@ module.exports = class Camera extends CocoClass
     createjs.Tween.removeTweens @
     @finishTween = null
     super()
+
+  onZoomTo: (pos) ->
+    @zoomTo(@worldToSurface(pos), @zoom)
diff --git a/app/views/play/level/playback_view.coffee b/app/views/play/level/playback_view.coffee
index f9c13a9e3..404201e9e 100644
--- a/app/views/play/level/playback_view.coffee
+++ b/app/views/play/level/playback_view.coffee
@@ -36,6 +36,10 @@ module.exports = class PlaybackView extends View
     '⌘+p, p, ctrl+p': 'onTogglePlay'
     '⌘+[, ctrl+[': 'onScrubBack'
     '⌘+], ctrl+]': 'onScrubForward'
+    'w, up': 'onMoveUpKey'
+    's, down': 'onMoveDownKey'
+    'a, left': 'onMoveLeftKey'
+    'd, right': 'onMoveRightKey'
 
   constructor: ->
     super(arguments...)
@@ -215,3 +219,15 @@ module.exports = class PlaybackView extends View
     $(window).off('resize', @onWindowResize)
     @onWindowResize = null
     super()
+
+  onMoveUpKey: ->
+    Backbone.Mediator.publish 'self-wizard:move', 0, 10
+
+  onMoveDownKey: ->
+    Backbone.Mediator.publish 'self-wizard:move', 0, -10
+
+  onMoveLeftKey: ->
+    Backbone.Mediator.publish 'self-wizard:move', -10, 0
+
+  onMoveRightKey: ->
+    Backbone.Mediator.publish 'self-wizard:move', 10, 0

From 7ea92603229c362999805e9ff9b9f30681ae5b73 Mon Sep 17 00:00:00 2001
From: Muhammed Thanish <mnmtanish@gmail.com>
Date: Sun, 2 Mar 2014 01:45:49 +0530
Subject: [PATCH 006/178] Use WizardSprite

---
 app/lib/LevelBus.coffee                   | 10 ----------
 app/lib/surface/Camera.coffee             |  4 ----
 app/lib/surface/WizardSprite.coffee       | 18 ++++++++++++++----
 app/views/play/level/playback_view.coffee |  8 ++++----
 4 files changed, 18 insertions(+), 22 deletions(-)

diff --git a/app/lib/LevelBus.coffee b/app/lib/LevelBus.coffee
index 707b0cef8..18985716b 100644
--- a/app/lib/LevelBus.coffee
+++ b/app/lib/LevelBus.coffee
@@ -22,7 +22,6 @@ module.exports = class LevelBus extends Bus
     'level-show-victory': 'onVictory'
     'tome:spell-changed': 'onSpellChanged'
     'tome:spell-created': 'onSpellCreated'
-    'self-wizard:move': 'moveWizard'
 
   constructor: ->
     super(arguments...)
@@ -241,12 +240,3 @@ module.exports = class LevelBus extends Bus
   destroy: ->
     @session.off 'change:multiplayer', @onMultiplayerChanged, @
     super()
-
-  moveWizard : (x, y) =>
-    wizardSprite = @getSelfWizard()
-    position = wizardSprite.getCurrentPosition()
-    position.x += x
-    position.y += y
-    wizardSprite.setTarget(position,1000)
-    wizardSprite.updatePosition()
-    Backbone.Mediator.publish 'camera-zoom-to', position
diff --git a/app/lib/surface/Camera.coffee b/app/lib/surface/Camera.coffee
index 70ee37884..9e4701868 100644
--- a/app/lib/surface/Camera.coffee
+++ b/app/lib/surface/Camera.coffee
@@ -42,7 +42,6 @@ module.exports = class Camera extends CocoClass
     'level:restarted': 'onLevelRestarted'
     'sprite:mouse-down': 'onMouseDown'
     'sprite:dragged': 'onMouseDragged'
-    'camera-zoom-to': 'onZoomTo'
 
   # TODO: Fix tests to not use mainLayer
   constructor: (@canvasWidth, @canvasHeight, angle=Math.asin(0.75), hFOV=d2r(30)) ->
@@ -309,6 +308,3 @@ module.exports = class Camera extends CocoClass
     createjs.Tween.removeTweens @
     @finishTween = null
     super()
-
-  onZoomTo: (pos) ->
-    @zoomTo(@worldToSurface(pos), @zoom)
diff --git a/app/lib/surface/WizardSprite.coffee b/app/lib/surface/WizardSprite.coffee
index 665a93bf4..7b57b7b87 100644
--- a/app/lib/surface/WizardSprite.coffee
+++ b/app/lib/surface/WizardSprite.coffee
@@ -21,6 +21,7 @@ module.exports = class WizardSprite extends IndieSprite
     'surface:sprite-selected': 'onSpriteSelected'
     'echo-self-wizard-sprite': 'onEchoSelfWizardSprite'
     'echo-all-wizard-sprites': 'onEchoAllWizardSprites'
+    'self-wizard:move': 'moveWizard'
 
   constructor: (thangType, options) ->
     if options?.isSelf
@@ -102,7 +103,7 @@ module.exports = class WizardSprite extends IndieSprite
   defaultPos: -> x: 35, y: 24, z: @thang.depth / 2 + @thang.bobHeight
   move: (pos, duration) -> @setTarget(pos, duration)
 
-  setTarget: (newTarget, duration) ->
+  setTarget: (newTarget, duration, isLinear=false) ->
     # ignore targets you're already heading for
     targetPos = @getPosFromTarget(newTarget)
     return if @targetPos and @targetPos.x is targetPos.x and @targetPos.y is targetPos.y
@@ -115,7 +116,7 @@ module.exports = class WizardSprite extends IndieSprite
     @shoveOtherWizards(true) if @targetSprite
     @targetSprite = if isSprite then newTarget else null
     @targetPos = targetPos
-    @beginMoveTween(duration)
+    @beginMoveTween(duration, isLinear)
     @shoveOtherWizards()
     Backbone.Mediator.publish('self-wizard:target-changed', {sender:@}) if @isSelf
 
@@ -127,7 +128,7 @@ module.exports = class WizardSprite extends IndieSprite
     return target if target.x?
     return target.thang.pos
 
-  beginMoveTween: (duration=1000) ->
+  beginMoveTween: (duration=1000, isLinear=false) ->
     # clear the old tween
     createjs.Tween.removeTweens(@)
 
@@ -140,8 +141,11 @@ module.exports = class WizardSprite extends IndieSprite
       @updatePosition()
       @endMoveTween()
       return
+    if isLinear
+      ease = createjs.Ease.linear
+    else
+      ease = createjs.Ease.getPowInOut(3.0)
 
-    ease = createjs.Ease.getPowInOut(3.0)
     createjs.Tween
       .get(@)
       .to({tweenPercentage:0.0}, duration, ease)
@@ -225,3 +229,9 @@ module.exports = class WizardSprite extends IndieSprite
 
   updateMarks: ->
     super() if @displayObject.visible  # not if we hid the wiz
+
+  moveWizard : (x, y) =>
+    console.log x, y
+    position = {x: @targetPos.x+x, y: @targetPos.y+y}
+    @setTarget(position, 500, true)
+    @updatePosition()
diff --git a/app/views/play/level/playback_view.coffee b/app/views/play/level/playback_view.coffee
index 404201e9e..4a3b8cadb 100644
--- a/app/views/play/level/playback_view.coffee
+++ b/app/views/play/level/playback_view.coffee
@@ -221,13 +221,13 @@ module.exports = class PlaybackView extends View
     super()
 
   onMoveUpKey: ->
-    Backbone.Mediator.publish 'self-wizard:move', 0, 10
+    Backbone.Mediator.publish 'self-wizard:move', 0, 1
 
   onMoveDownKey: ->
-    Backbone.Mediator.publish 'self-wizard:move', 0, -10
+    Backbone.Mediator.publish 'self-wizard:move', 0, -1
 
   onMoveLeftKey: ->
-    Backbone.Mediator.publish 'self-wizard:move', -10, 0
+    Backbone.Mediator.publish 'self-wizard:move', -1, 0
 
   onMoveRightKey: ->
-    Backbone.Mediator.publish 'self-wizard:move', 10, 0
+    Backbone.Mediator.publish 'self-wizard:move', 1, 0

From a5f633961ff293cba0fc6679c482e9744e7ed650 Mon Sep 17 00:00:00 2001
From: Aditya Raisinghani <aditya.ajeet@gmail.com>
Date: Sun, 2 Mar 2014 01:48:21 +0530
Subject: [PATCH 007/178] Added log setting for production.

---
 server_setup.coffee | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/server_setup.coffee b/server_setup.coffee
index 9f94da179..3332e0428 100644
--- a/server_setup.coffee
+++ b/server_setup.coffee
@@ -8,7 +8,6 @@ database = require './server/commons/database'
 baseRoute = require './server/routes/base'
 user = require './server/users/user_handler'
 logging = require './server/commons/logging'
-
 config = require './server_config'
 
 ###Middleware setup functions implementation###
@@ -20,9 +19,16 @@ setupRequestTimeoutMiddleware = (app) ->
       self.emit('pass',message)
     next()
 
+productionLogging = (tokens, req, res)->
+  status = res.statusCode
+  color = 31
+  if(status != 200 && status != 304)
+    return '\x1b[90m' + req.method+ ' ' + req.originalUrl + ' '+ '\x1b[' + color + 'm' + res.statusCode+ ' \x1b[90m'+ (new Date - req._startTime)+ 'ms' + '\x1b[0m';
+
 setupExpressMiddleware = (app) ->
   setupRequestTimeoutMiddleware app
-  app.use(express.logger('dev'))
+  express.logger.format('prod', productionLogging)
+  app.use(express.logger('prod'))
   app.use(express.static(path.join(__dirname, 'public')))
   app.use(useragent.express())
 

From a092557973e8edca74f5bd3d58160ba971893d47 Mon Sep 17 00:00:00 2001
From: Muhammed Thanish <mnmtanish@gmail.com>
Date: Sun, 2 Mar 2014 02:13:37 +0530
Subject: [PATCH 008/178] Add camera zoomTo(pos)

---
 app/lib/surface/Camera.coffee       | 4 ++++
 app/lib/surface/WizardSprite.coffee | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/app/lib/surface/Camera.coffee b/app/lib/surface/Camera.coffee
index 9e4701868..76323e5e8 100644
--- a/app/lib/surface/Camera.coffee
+++ b/app/lib/surface/Camera.coffee
@@ -42,6 +42,7 @@ module.exports = class Camera extends CocoClass
     'level:restarted': 'onLevelRestarted'
     'sprite:mouse-down': 'onMouseDown'
     'sprite:dragged': 'onMouseDragged'
+    'camera-zoom-to': 'onZoomTo'
 
   # TODO: Fix tests to not use mainLayer
   constructor: (@canvasWidth, @canvasHeight, angle=Math.asin(0.75), hFOV=d2r(30)) ->
@@ -308,3 +309,6 @@ module.exports = class Camera extends CocoClass
     createjs.Tween.removeTweens @
     @finishTween = null
     super()
+
+  onZoomTo: (pos, time) ->
+    @zoomTo(@worldToSurface(pos), @zoom, time)
diff --git a/app/lib/surface/WizardSprite.coffee b/app/lib/surface/WizardSprite.coffee
index 7b57b7b87..1ec5ad812 100644
--- a/app/lib/surface/WizardSprite.coffee
+++ b/app/lib/surface/WizardSprite.coffee
@@ -231,7 +231,7 @@ module.exports = class WizardSprite extends IndieSprite
     super() if @displayObject.visible  # not if we hid the wiz
 
   moveWizard : (x, y) =>
-    console.log x, y
     position = {x: @targetPos.x+x, y: @targetPos.y+y}
     @setTarget(position, 500, true)
     @updatePosition()
+    Backbone.Mediator.publish 'camera-zoom-to', position, 500
\ No newline at end of file

From d7e031fd00ea3e8425a67d8243f07adc3eac8c44 Mon Sep 17 00:00:00 2001
From: Muhammed Thanish <mnmtanish@gmail.com>
Date: Sun, 2 Mar 2014 03:27:06 +0530
Subject: [PATCH 009/178] Use key.isPressed() to get movement direction

---
 app/lib/surface/WizardSprite.coffee       |  5 ++--
 app/views/play/level/playback_view.coffee | 29 +++++++++++------------
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/app/lib/surface/WizardSprite.coffee b/app/lib/surface/WizardSprite.coffee
index 1ec5ad812..236d2d77d 100644
--- a/app/lib/surface/WizardSprite.coffee
+++ b/app/lib/surface/WizardSprite.coffee
@@ -231,7 +231,8 @@ module.exports = class WizardSprite extends IndieSprite
     super() if @displayObject.visible  # not if we hid the wiz
 
   moveWizard : (x, y) =>
+    interval = 250
     position = {x: @targetPos.x+x, y: @targetPos.y+y}
-    @setTarget(position, 500, true)
+    @setTarget(position, interval, true)
     @updatePosition()
-    Backbone.Mediator.publish 'camera-zoom-to', position, 500
\ No newline at end of file
+    Backbone.Mediator.publish 'camera-zoom-to', position, interval
\ No newline at end of file
diff --git a/app/views/play/level/playback_view.coffee b/app/views/play/level/playback_view.coffee
index 4a3b8cadb..c9d11c9f0 100644
--- a/app/views/play/level/playback_view.coffee
+++ b/app/views/play/level/playback_view.coffee
@@ -36,10 +36,10 @@ module.exports = class PlaybackView extends View
     '⌘+p, p, ctrl+p': 'onTogglePlay'
     '⌘+[, ctrl+[': 'onScrubBack'
     '⌘+], ctrl+]': 'onScrubForward'
-    'w, up': 'onMoveUpKey'
-    's, down': 'onMoveDownKey'
-    'a, left': 'onMoveLeftKey'
-    'd, right': 'onMoveRightKey'
+    'up': 'onMoveKey'
+    'down': 'onMoveKey'
+    'left': 'onMoveKey'
+    'right': 'onMoveKey'
 
   constructor: ->
     super(arguments...)
@@ -220,14 +220,13 @@ module.exports = class PlaybackView extends View
     @onWindowResize = null
     super()
 
-  onMoveUpKey: ->
-    Backbone.Mediator.publish 'self-wizard:move', 0, 1
-
-  onMoveDownKey: ->
-    Backbone.Mediator.publish 'self-wizard:move', 0, -1
-
-  onMoveLeftKey: ->
-    Backbone.Mediator.publish 'self-wizard:move', -1, 0
-
-  onMoveRightKey: ->
-    Backbone.Mediator.publish 'self-wizard:move', 1, 0
+  onMoveKey: (e) ->
+    e?.preventDefault()
+    x = 0
+    y = 0
+    y = 1 if key.isPressed('up')
+    y = -1 if key.isPressed('down')
+    x = 1 if key.isPressed('right')
+    x = -1 if key.isPressed('left')
+    console.log 'onMoveKey', x, y
+    Backbone.Mediator.publish 'self-wizard:move', x, y

From 2db9fa708b1db809307fbc64c4020883844b89e1 Mon Sep 17 00:00:00 2001
From: YF <yfdyh000@gmail.com>
Date: Sun, 2 Mar 2014 07:27:15 +0800
Subject: [PATCH 010/178] Update zh-HANS.coffee

---
 app/locale/zh-HANS.coffee | 256 +++++++++++++++++++-------------------
 1 file changed, 128 insertions(+), 128 deletions(-)

diff --git a/app/locale/zh-HANS.coffee b/app/locale/zh-HANS.coffee
index 2be4960c8..13c3d3161 100644
--- a/app/locale/zh-HANS.coffee
+++ b/app/locale/zh-HANS.coffee
@@ -3,7 +3,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     loading: "读取中……"
     saving: "保存中……"
     sending: "发送中……"
-    cancel: "退出"
+    cancel: "取消"
     save: "保存"
     delay_1_sec: "1 秒"
     delay_3_sec: "3 秒"
@@ -14,31 +14,31 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 
   modal:
     close: "关闭"
-    okay: "好"
+    okay: "好的"
 
   not_found:
     page_not_found: "找不到网页"
 
   nav:
     play: "玩"
-    editor: "编辑"
+    editor: "编辑器"
     blog: "博客"
     forum: "论坛"
-    admin: "超级管理员"
+    admin: "管理"
     home: "首页"
     contribute: "贡献"
     legal: "法律"
     about: "关于"
-    contact: "联系我们"
+    contact: "联系"
     twitter_follow: "关注"
     employers: "雇佣我们"
 
   versions:
     save_version_title: "保存新版本"
-#    new_major_version: "New Major Version"
-#    cla_prefix: "To save changes, first you must agree to our"
-#    cla_url: "CLA"
-#    cla_suffix: "."
+    new_major_version: "新的重要版本"
+    cla_prefix: "要想保存更改,您必须先同意我们的"
+    cla_url: "贡献者许可协议"
+    cla_suffix: "。"
     cla_agree: "我同意"
 
   login:
@@ -63,40 +63,40 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 
   home:
     slogan: "通过游戏学习 Javascript"
-    no_ie: "抱歉!Internet Explorer 9等更旧的预览器打不开此网站。"
-    no_mobile: "CodeCombat 不是针对手机设备设计的,所以可能无法达到做好的体验!"
+    no_ie: "抱歉!Internet Explorer 9 等旧式预览器无法使用本网站。"
+    no_mobile: "CodeCombat 不是针对手机设备设计的,所以可能无法达到最好的体验!"
     play: "开始游戏"
 
   play:
     choose_your_level: "选取难度"
-    adventurer_prefix: "你可以选择以下任意关卡,或者讨论以上的关卡。"
+    adventurer_prefix: "你可以选择以下任意关卡,或者讨论以上的关卡。到"
     adventurer_forum: "冒险者论坛"
-    adventurer_suffix: "."
+    adventurer_suffix: "。"
     campaign_beginner: "新手作战"
-    campaign_beginner_description: "……在这里可以学到编程技巧。"
+    campaign_beginner_description: "……在这里你可以学习到编程技巧。"
     campaign_dev: "随机困难关卡"
     campaign_dev_description: "……在这里你可以学到做一些复杂功能的接口。"
     campaign_multiplayer: "多人竞技场"
-    campaign_multiplayer_description: "……在这里你可以和其他玩家们进行代码肉搏战。"
-    campaign_player_created: "已创建的玩家"
+    campaign_multiplayer_description: "……在这里你可以与其他玩家进行代码肉搏战。"
+    campaign_player_created: "创建玩家"
     campaign_player_created_description: "……在这里你可以与你的小伙伴的创造力战斗 <a href=\"/contribute#artisan\">技术指导</a>."
-    level_difficulty: "难度"
+    level_difficulty: "难度:"
 
   contact:
     contact_us: "联系我们"
-    welcome: "很高兴收到你的信!用这个表格给我们发邮件。 "
-    contribute_prefix: "如果你想贡献代码,请看我们的 "
-    contribute_page: "贡献代码页面"
+    welcome: "我们很乐意收到你的信!用这个表单给我们发邮件。 "
+    contribute_prefix: "如果你想贡献什么,请看我们的 "
+    contribute_page: "贡献页面"
     contribute_suffix: "!"
-    forum_prefix: "对任何公共部分,放手去干吧 "
+    forum_prefix: "对于任何公开部分,请尝试用"
     forum_page: "我们的论坛"
-    forum_suffix: "代替 "
+    forum_suffix: "代替"
     send: "意见反馈"
 
   diplomat_suggestion:
     title: "帮我们翻译 CodeCombat"
     sub_heading: "我们需要您的语言技能"
-    pitch_body: "我们开发了 CodeCombat 的英文版,但是现在我们的玩家遍布全球。很多人想玩中文(简体)版的,却不会说英语,所以如果你中英文都会,请考虑一下参加我们的翻译工作,帮忙把 CodeCombat 网站还有所有的关卡翻译成中文(简体)。"
+    pitch_body: "我们开发了 CodeCombat 的英文版,但是现在我们的玩家遍布全球。很多人英语不熟练,但很想玩简体中文版的游戏,所以如果你中英文都很熟练,请考虑参加我们的翻译工作,帮忙把 CodeCombat 网站还有所有的关卡翻译成简体中文。"
     missing_translations: "未翻译的文本将显示为英文。"
     learn_more: "了解更多有关成为翻译人员的说明"
     subscribe_as_diplomat: "提交翻译人员申请"
@@ -130,28 +130,28 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     new_password_verify: "核实"
     email_subscriptions: "邮箱验证"
     email_announcements: "通知"
-    email_notifications_description: "定期接受来自你的账户的通知。"
+    email_notifications_description: "接收来自你的账户的定期通知。"
     email_announcements_description: "接收关于 CodeCombat 最近的新闻和发展的邮件。"
     contributor_emails: "贡献者通知"
-    contribute_prefix: "我们在寻找志同道合的人!请到 "
+    contribute_prefix: "我们在寻找志同道合的人!请到"
     contribute_page: "贡献页面"
-    contribute_suffix: " 查看更多信息。"
+    contribute_suffix: "查看更多信息。"
     email_toggle: "切换所有"
     error_saving: "保存时出错"
-    saved: "保存修改"
+    saved: "更改已保存"
     password_mismatch: "密码不匹配。"
 
   account_profile:
     edit_settings: "编辑设置"
-    profile_for_prefix: "关于TA的基本资料:"
+    profile_for_prefix: "关于他的基本资料:"
     profile_for_suffix: ""
     profile: "基本资料"
-    user_not_found: "没有找到用户。检查URL?"
-    gravatar_not_found_mine: "我们找不到TA的基本资料:"
-    gravatar_not_found_email_suffix: "."
+    user_not_found: "没有找到用户。网址有错?"
+    gravatar_not_found_mine: "我们找不到他的基本资料:"
+    gravatar_not_found_email_suffix: "。"
     gravatar_signup_prefix: "去注册 "
-    gravatar_signup_suffix: " 去设置!"
-    gravatar_not_found_other: "哎呀,没有与这个人的邮箱相关的资料。"
+    gravatar_signup_suffix: " 来设置!"
+    gravatar_not_found_other: "哎呀,没有与这个邮箱相关的资料。"
     gravatar_contact: "联系"
     gravatar_websites: "网站"
     gravatar_accounts: "显示为"
@@ -198,33 +198,33 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     tome_select_spell: "选择一个法术"
     tome_select_a_thang: "选择人物来 "
     tome_available_spells: "可用的法术"
-    hud_continue: "继续(按 shift-空格)"
-    spell_saved: "输入已保存"
+    hud_continue: "继续(按 Shift-空格)"
+    spell_saved: "咒语已保存"
 
-#  admin:
-#    av_title: "Admin Views"
-#    av_entities_sub_title: "Entities"
-#    av_entities_users_url: "Users"
-#    av_entities_active_instances_url: "Active Instances"
-#    av_other_sub_title: "Other"
-#    av_other_debug_base_url: "Base (for debugging base.jade)"
-#    u_title: "User List"
-#    lg_title: "Latest Games"
+  admin:
+    av_title: "管理员视图"
+    av_entities_sub_title: "实体"
+    av_entities_users_url: "用户"
+    av_entities_active_instances_url: "活动实例"
+    av_other_sub_title: "其他"
+    av_other_debug_base_url: "Base(用于调试 base.jade)"
+    u_title: "用户列表"
+    lg_title: "最新的游戏"
 
   editor:
     main_title: "CodeCombat 编辑器"
-    main_description: "建立自己的关卡, 战役, 单位 和教育内容。我们提供所有你需要的工具!"
+    main_description: "建立你自己的关卡、 战役、单元和教育内容。我们会提供所有你需要的工具!"
     article_title: "提示编辑器"
-    article_description: "编写提示,让玩家可以使用编程概念,来通过各种的关卡和战役。"
+    article_description: "编写提示,让玩家可以使用编程概念来通过各种关卡和战役。"
     thang_title: "物体编辑器"
-    thang_description: "创建单位,并定义单位的逻辑、图形和音频。目前只支持导入Flash导出的矢量图形。"
+    thang_description: "创建单元,并定义单元的逻辑、图形和音频。目前只支持导入 Flash 导出的矢量图形。"
     level_title: "关卡编辑器"
     level_description: "所有用来创造所有难度的关卡的工具,包括脚本、上传音频和构建自定义逻辑。"
-    security_notice: "编辑器的许多主要功能并不是目前默认启动的。当我们改善完这些系统的安全性的时候,他们将会变成常用的。如果你想要马上使用这些功能,"
+    security_notice: "编辑器的许多主要功能并不是目前默认启动的。当我们改善完这些系统的安全性的时候,它们就会成为通常可用的。如果你想要马上使用这些功能,"
     contact_us: "联系我们!"
     hipchat_prefix: "你也可以在这里找到我们"
-    hipchat_url: "HipChat room."
-#    level_some_options: "Some Options?"
+    hipchat_url: "HipChat 房间。"
+    level_some_options: "有些选项?"
     level_tab_thangs: "物体"
     level_tab_scripts: "脚本"
     level_tab_settings: "设定"
@@ -239,7 +239,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     level_systems_tab_title: "目前所有系统"
     level_systems_btn_new: "创建新的系统"
     level_systems_btn_add: "增加系统"
-    level_components_title: "返回到所以物体主页"
+    level_components_title: "返回到所有物体主页"
     level_components_type: "类型"
     level_component_edit_title: "编辑组件"
     level_system_edit_title: "编辑系统"
@@ -249,12 +249,12 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 
   article:
     edit_btn_preview: "预览"
-    edit_article_title: "编辑文章"
+    edit_article_title: "编辑提示"
 
   general:
     and: "和"
     name: "姓名"
-#    body: "Body"
+    body: "正文"
     version: "版本"
     commit_msg: "提交信息"
     version_history_for: "版本历史: "
@@ -265,11 +265,11 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     message: "消息"
 
   about:
-    who_is_codecombat: "什么是CodeCombat?"
-    why_codecombat: "为什么选择CodeCombat?"
-    who_description_prefix: "一起在2013开始编写CodeCombat。在2008年时,我们也创造了"
-    who_description_suffix: "并且发展它成为第一的学习如何写中文字和日文字的Web和IOS应用"
-    who_description_ending: "现在是时候教人们如何写代码。"
+    who_is_codecombat: "什么是 CodeCombat?"
+    why_codecombat: "为什么选择 CodeCombat?"
+    who_description_prefix: "在2013年开始一起编写 CodeCombat。在2008年时,我们还创造"
+    who_description_suffix: "并且发展出了首选的学习如何写中文和日文的Web和IOS应用"
+    who_description_ending: "现在是时候教人们如何写代码了。"
 #    why_paragraph_1: "When making Skritter, George didn't know how to program and was constantly frustrated by his inability to implement his ideas. Afterwards, he tried learning, but the lessons were too slow. His housemate, wanting to reskill and stop teaching, tried Codecademy, but \"got bored.\" Each week another friend started Codecademy, then dropped off. We realized it was the same problem we'd solved with Skritter: people learning a skill via slow, intensive lessons when what they need is fast, extensive practice. We know how to fix that."
 #    why_paragraph_2: "Need to learn to code? You don't need lessons. You need to write a lot of code and have a great time doing it."
 #    why_paragraph_3_prefix: "That's what programming is about. It's gotta be fun. Not fun like"
@@ -286,61 +286,61 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 #    jeremy_description: "Customer support mage, usability tester, and community organizer; you've probably already spoken with Jeremy."
 #    michael_description: "Programmer, sys-admin, and undergrad technical wunderkind, Michael is the person keeping our servers online."
 
-#  legal:
-#    page_title: "Legal"
-#    opensource_intro: "CodeCombat is free to play and completely open source."
-#    opensource_description_prefix: "Check out "
-#    github_url: "our GitHub"
-#    opensource_description_center: "and help out if you like! CodeCombat is built on dozens of open source projects, and we love them. See "
-#    archmage_wiki_url: "our Archmage wiki"
-#    opensource_description_suffix: "for a list of the software that makes this game possible."
-#    practices_title: "Respectful Best Practices"
-#    practices_description: "These are our promises to you, the player, in slightly less legalese."
-#    privacy_title: "Privacy"
-#    privacy_description: "We will not sell any of your personal information. We intend to make money through recruitment eventually, but rest assured we will not distribute your personal information to interested companies without your explicit consent."
-#    security_title: "Security"
-#    security_description: "We strive to keep your personal information safe. As an open source project, our site is freely open to anyone to review and improve our security systems."
-#    email_title: "Email"
-#    email_description_prefix: "We will not inundate you with spam. Through"
-#    email_settings_url: "your email settings"
-#    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
-#    cost_title: "Cost"
-#    cost_description: "Currently, CodeCombat is 100% free! One of our main goals is to keep it that way, so that as many people can play as possible, regardless of place in life. If the sky darkens, we might have to charge subscriptions or for some content, but we'd rather not. With any luck, we'll be able to sustain the company with:"
-#    recruitment_title: "Recruitment"
-#    recruitment_description_prefix: "Here on CodeCombat, you're going to become a powerful wizard–not just in the game, but also in real life."
-#    url_hire_programmers: "No one can hire programmers fast enough"
-#    recruitment_description_suffix: "so once you've sharpened your skills and if you agree, we will demo your best coding accomplishments to the thousands of employers who are drooling for the chance to hire you. They pay us a little, they pay you"
-#    recruitment_description_italic: "a lot"
-#    recruitment_description_ending: "the site remains free and everybody's happy. That's the plan."
-#    copyrights_title: "Copyrights and Licenses"
-#    contributor_title: "Contributor License Agreement"
-#    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
-#    cla_url: "CLA"
-#    contributor_description_suffix: "to which you should agree before contributing."
-#    code_title: "Code - MIT"
-#    code_description_prefix: "All code owned by CodeCombat or hosted on codecombat.com, both in the GitHub repository or in the codecombat.com database, is licensed under the"
-#    mit_license_url: "MIT license"
+  legal:
+    page_title: "法律"
+    opensource_intro: "CodeCombat 是一个自由发挥,完全开源的项目。"
+    opensource_description_prefix: "查看"
+    github_url: "我们的 GitHub"
+    opensource_description_center: "并做你想做的修改吧!CodeCombat 是构筑在几十个开源项目的基础之上,我们爱它们。见"
+    archmage_wiki_url: "我们的 Archmage wiki"
+    opensource_description_suffix: "了解让这个游戏成为可能的名单。"
+    practices_title: "尊重最佳实践"
+    practices_description: "这是我们对您的承诺,即玩家,尽管这在法律用语中略显不足。"
+    privacy_title: "隐私"
+    privacy_description: "我们不会出售您的任何个人信息。我们计划最终通过招聘来盈利,但请您放心,未经您的明确同意,我们不会将您的个人信息出售有兴趣的公司。"
+    security_title: "安全"
+    security_description: "我们竭力保证您的个人信息安全性。作为一个开源项目,任何人都可以检讨并改善我们自由开放的网站的安全性。"
+    email_title: "电子邮件"
+    email_description_prefix: "我们不会发给您垃圾邮件。通过"
+    email_settings_url: "您的电子邮件设置"
+    email_description_suffix: "或者我们发送的邮件中的链接,您可以随时更改您的偏好设置或者随时取消订阅。"
+    cost_title: "花费"
+    cost_description: "目前来说,CodeCombat 是完全免费的!我们的主要目标之一也是保持目前这种方式,让尽可能多的人玩得更好,不论是否是生活中。如果天空变暗,我们可能会对某些内容采取订阅收费,但我们宁愿不那么做。运气好的话,我们可以维持公司,通过:"
+    recruitment_title: "招募"
+    recruitment_description_prefix: "在 CodeCombat 这里,你将得以成为一名法力强大的“巫师”,不只是在游戏中,更在生活中。"
+    url_hire_programmers: "没有人能以足够快速度招聘程序员,"
+    recruitment_description_suffix: "所以一旦你的技能成熟并且得到你的同意,我们将战士你的最佳编码成就给上万名雇主,希望他们垂涎欲滴。而他们支付给我们一点点报酬,并且付给你工资,"
+    recruitment_description_italic: "“一大笔”"
+    recruitment_description_ending: "。而这网站也就能保持免费,皆大欢喜。计划就是这样。"
+    copyrights_title: "版权与许可"
+    contributor_title: "贡献者许可协议"
+    contributor_description_prefix: "在本网站或者我们的 GitHub 版本库的所有贡献都依照我们的"
+    cla_url: "贡献者许可协议(CLA)"
+    contributor_description_suffix: ",而这在您贡献之前就应该已经同意。"
+    code_title: "代码 - MIT"
+    code_description_prefix: "所有由 CodeCombat 拥有或者托管在 codecombat.com 的代码,在 GitHub 版本库或者 codecombat.com 数据库,以上许可协议都依照"
+    mit_license_url: "MIT 许可证"
 #    code_description_suffix: "This includes all code in Systems and Components that are made available by CodeCombat for the purpose of creating levels."
 #    art_title: "Art/Music - Creative Commons "
 #    art_description_prefix: "All common content is available under the"
 #    cc_license_url: "Creative Commons Attribution 4.0 International License"
 #    art_description_suffix: "Common content is anything made generally available by CodeCombat for the purpose of creating Levels. This includes:"
-#    art_music: "Music"
-#    art_sound: "Sound"
-#    art_artwork: "Artwork"
-#    art_sprites: "Sprites"
+    art_music: "音乐"
+    art_sound: "声效"
+    art_artwork: "艺术品"
+    art_sprites: "小妖精"
 #    art_other: "Any and all other non-code creative works that are made available when creating Levels."
 #    art_access: "Currently there is no universal, easy system for fetching these assets. In general, fetch them from the URLs as used by the site, contact us for assistance, or help us in extending the site to make these assets more easily accessible."
 #    art_paragraph_1: "For attribution, please name and link to codecombat.com near where the source is used or where appropriate for the medium. For example:"
 #    use_list_1: "If used in a movie or another game, include codecombat.com in the credits."
 #    use_list_2: "If used on a website, include a link near the usage, for example underneath an image, or in a general attributions page where you might also mention other Creative Commons works and open source software being used on the site. Something that's already clearly referencing CodeCombat, such as a blog post mentioning CodeCombat, does not need some separate attribution."
 #    art_paragraph_2: "If the content being used is created not by CodeCombat but instead by a user of codecombat.com, attribute them instead, and follow attribution directions provided in that resource's description if there are any."
-#    rights_title: "Rights Reserved"
-#    rights_desc: "All rights are reserved for Levels themselves. This includes"
-#    rights_scripts: "Scripts"
-#    rights_unit: "Unit configuration"
-#    rights_description: "Description"
-#    rights_writings: "Writings"
+    rights_title: "版权所有"
+    rights_desc: "所有关卡由他们自己版权所有。这包括"
+    rights_scripts: "脚本"
+    rights_unit: "单元配置"
+    rights_description: "描述"
+    rights_writings: "作品"
 #    rights_media: "Media (sounds, music) and any other creative content made specifically for that Level and not made generally available when creating Levels."
 #    rights_clarification: "To clarify, anything that is made available in the Level Editor for the purpose of making levels is under CC, whereas the content created with the Level Editor or uploaded in the course of creation of Levels is not."
 #    nutshell_title: "In a Nutshell"
@@ -408,16 +408,16 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 #    scribe_join_description: "tell us a little about yourself, your experience with programming and what sort of things you'd like to write about. We'll go from there!"
 #    more_about_scribe: "Learn More About Becoming a Scribe"
 #    scribe_subscribe_desc: "Get emails about article writing announcements."
-    diplomat_summary: "在其他国家不讲英语,很多人对于CodeCombat有很大的兴趣。我们正在寻找译者,愿意花时间翻译网站的语料库的词语,这样CodeCombat就能尽快访问到世界各地。如果你想帮助CodeCombat国际化,那么这个类就是给你的。"
+    diplomat_summary: "在其他国家不讲英语,很多人对于CodeCombat有很大的兴趣。我们正在寻找愿意花时间翻译网站语料库的词语的译者,这样 CodeCombat 就能尽快地遍及世界各地。如果你想帮助 CodeCombat 的国际化,那么这个类就是给你的。"
     diplomat_introduction_pref: "如果有一件事情是从 "
     diplomat_launch_url: "launch in October"
     diplomat_introduction_suf: "学来的,Combat有相当大的兴趣在其他国家发展。我们正在构建一个译者兵团把单词一个一个的翻译,让CodeCombat尽可能地访问到世界各地。如果你喜欢偷偷地瞄一眼即将到来的内容,并让你的国民尽快学习到CodeCombat,那么这个类可能适合你。"
     diplomat_attribute_1: "会流利的英语和能翻译的语言。当传递复杂思想,难得的是能很好的同时掌握这两个。"
     diplomat_join_pref_github: "找到你自己的语言文件 "
     diplomat_github_url: "在GitHub网站"
-    diplomat_join_suf_github: "在线编辑它,然后提交一个合并请求。同时,检查下面这个盒子来关注最新的国际化开发!"
-    more_about_diplomat: "学习更多关于“成为一名外交官(翻译者)”"
-    diplomat_subscribe_desc: "接受邮件,关于国际化开发和翻译情况"
+    diplomat_join_suf_github: "在线编辑它,然后提交一个合并请求。同时,选中下面这个复选框来关注最新的国际化开发!"
+    more_about_diplomat: "了解更多“如何成为一名外交官(翻译者)”"
+    diplomat_subscribe_desc: "接受有关国际化开发和翻译情况的邮件"
 #    ambassador_summary: "We are trying to build a community, and every community needs a support team when there are troubles. We have got chats, emails, and social networks so that our users can get acquainted with the game. If you want to help people get involved, have fun, and learn some programming, then this class is for you."
 #    ambassador_introduction: "This is a community we're building, and you are the connections. We've got Olark chats, emails, and social networks with lots of people to talk with and help get acquainted with the game and learn from. If you want to help people get involved and have fun, and get a good feel of the pulse of CodeCombat and where we're going, then this class might be for you."
 #    ambassador_attribute_1: "Communication skills. Be able to identify the problems players are having and help them solve them. Also, keep the rest of us informed about what players are saying, what they like and don't like and want more of!"
@@ -433,26 +433,26 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 #    counselor_attribute_2: "A little bit of free time!"
 #    counselor_join_desc: "tell us a little about yourself, what you've done and what you'd be interested in doing. We'll put you in our contact list and be in touch when we could use advice (not too often)."
 #    more_about_counselor: "Learn More About Becoming a Counselor"
-#    changes_auto_save: "Changes are saved automatically when you toggle checkboxes."
-#    diligent_scribes: "Our Diligent Scribes:"
-#    powerful_archmages: "Our Powerful Archmages:"
-#    creative_artisans: "Our Creative Artisans:"
-#    brave_adventurers: "Our Brave Adventurers:"
-#    translating_diplomats: "Our Translating Diplomats:"
-#    helpful_ambassadors: "Our Helpful Ambassadors:"
+    changes_auto_save: "在您切换复选框时,更改将自动保存。"
+    diligent_scribes: "我们勤奋的文书:"
+    powerful_archmages: "我们强力的大法师:"
+    creative_artisans: "我们极具创意的工匠:"
+    brave_adventurers: "我们勇敢的冒险家:"
+    translating_diplomats: "我们遍及世界的外交官:"
+    helpful_ambassadors: "我们亲切的使节:"
 
-#  classes:
-#    archmage_title: "Archmage"
-#    archmage_title_description: "(Coder)"
-#    artisan_title: "Artisan"
-#    artisan_title_description: "(Level Builder)"
-#    adventurer_title: "Adventurer"
-#    adventurer_title_description: "(Level Playtester)"
-#    scribe_title: "Scribe"
-#    scribe_title_description: "(Article Editor)"
-#    diplomat_title: "Diplomat"
-#    diplomat_title_description: "(Translator)"
-#    ambassador_title: "Ambassador"
-#    ambassador_title_description: "(Support)"
-#    counselor_title: "Counselor"
-#    counselor_title_description: "(Expert/Teacher)"
+  classes:
+    archmage_title: "大法师"
+    archmage_title_description: "(代码编写人员)"
+    artisan_title: "工匠"
+    artisan_title_description: "(关卡建立人员)"
+    adventurer_title: "冒险家"
+    adventurer_title_description: "(关卡测试人员)"
+    scribe_title: "文书"
+    scribe_title_description: "(提示编辑人员)"
+    diplomat_title: "外交官"
+    diplomat_title_description: "(翻译人员)"
+    ambassador_title: "使节"
+    ambassador_title_description: "(用户支持人员)"
+    counselor_title: "顾问"
+    counselor_title_description: "(专家/导师)"

From e69e23115fe5c611ffa7fd3bf06dc1d1e3f874b3 Mon Sep 17 00:00:00 2001
From: Michael Schmatz <schmatz@umich.edu>
Date: Sat, 1 Mar 2014 16:52:17 -0800
Subject: [PATCH 011/178] Improvements to game scheduling, removed cap

---
 server/queues/scoring.coffee | 79 ++++++++++++++++++++----------------
 1 file changed, 45 insertions(+), 34 deletions(-)

diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee
index 08f0794d0..692a08b75 100644
--- a/server/queues/scoring.coffee
+++ b/server/queues/scoring.coffee
@@ -130,7 +130,7 @@ module.exports.processTaskResult = (req, res) ->
                 opponentID = _.pull(_.keys(newScoresObject), originalSessionID)
                 sessionNewScore = newScoresObject[originalSessionID].totalScore
                 opponentNewScore = newScoresObject[opponentID].totalScore
-                findNearestBetterSessionID sessionNewScore, opponentNewScore, opponentID ,opposingTeam, (err, opponentSessionID) ->
+                findNearestBetterSessionID originalSessionID, sessionNewScore, opponentNewScore, opponentID ,opposingTeam, (err, opponentSessionID) ->
                   if err? then return errors.serverError res, "There was an error finding the nearest sessionID!"
                   unless opponentSessionID then return sendResponseObject req, res, {"message":"There were no more games to rank(game is at top!"}
                     
@@ -162,9 +162,6 @@ determineIfSessionShouldContinueAndUpdateLog = (sessionID, sessionRank, cb) ->
     if totalNumberOfGamesPlayed < 5
       console.log "Number of games played is less than 5, continuing..."
       cb null, true
-    else if totalNumberOfGamesPlayed > 15
-      console.log "Too many games played, ending..."
-      cb null, false
     else
       ratio = (updatedSession.numberOfLosses - 5) / (totalNumberOfGamesPlayed)
       if ratio > 0.66
@@ -175,39 +172,53 @@ determineIfSessionShouldContinueAndUpdateLog = (sessionID, sessionRank, cb) ->
         cb null, true
       
     
-findNearestBetterSessionID = (sessionTotalScore, opponentSessionTotalScore, opponentSessionID, opposingTeam, cb) ->
-  queryParameters =
-    totalScore: 
-      $gt:opponentSessionTotalScore + 0.5
-    _id: 
-      $ne: opponentSessionID
-    "level.original": "52d97ecd32362bc86e004e87"
-    "level.majorVersion": 0
-    submitted: true
-    submittedCode:
-      $exists: true
-    team: opposingTeam
+findNearestBetterSessionID = (sessionID, sessionTotalScore, opponentSessionTotalScore, opponentSessionID, opposingTeam, cb) ->
+  retrieveAllOpponentSessionIDs sessionID, (err, opponentSessionIDs) ->
+    if err? then return cb err, null
     
-  limitNumber = 1
-
-  sortParameters =
-    totalScore: 1
-    
-  selectString = '_id totalScore'
-    
-  query = LevelSession.findOne(queryParameters)
-    .sort(sortParameters)
-    .limit(limitNumber)
-    .select(selectString)
-    .lean()
+    queryParameters =
+      totalScore: 
+        $gt:opponentSessionTotalScore
+      _id: 
+        $nin: opponentSessionIDs
+      "level.original": "52d97ecd32362bc86e004e87"
+      "level.majorVersion": 0
+      submitted: true
+      submittedCode:
+        $exists: true
+      team: opposingTeam
+      
+    limitNumber = 1
   
-  console.log "Finding session with score near #{opponentSessionTotalScore}"
-  query.exec (err, session) ->
-    if err? then return cb err, session
-    unless session then return cb err, null
-    console.log "Found session with score #{session.totalScore}"
-    cb err, session._id
+    sortParameters =
+      totalScore: 1
+      
+    selectString = '_id totalScore'
+      
+    query = LevelSession.findOne(queryParameters)
+      .sort(sortParameters)
+      .limit(limitNumber)
+      .select(selectString)
+      .lean()
+    
+    console.log "Finding session with score near #{opponentSessionTotalScore}"
+    query.exec (err, session) ->
+      if err? then return cb err, session
+      unless session then return cb err, null
+      console.log "Found session with score #{session.totalScore}"
+      cb err, session._id
 
+    
+retrieveAllOpponentSessionIDs = (sessionID, cb) ->
+  query = LevelSession.findOne({"_id":sessionID})
+    .select('matches.opponents.sessionID')
+    .lean()
+  query.exec (err, session) ->
+    if err? then return cb err, null
+    opponentSessionIDs = (match.opponents[0].sessionID for match in session.matches)
+    cb err, opponentSessionIDs
+    
+      
 calculateOpposingTeam = (sessionTeam) ->
   teams = ['ogres','humans']
   opposingTeams = _.pull teams, sessionTeam

From 488be26fd3de738dcdd8bb613acb0d7e3a1fc98e Mon Sep 17 00:00:00 2001
From: Michael Schmatz <schmatz@umich.edu>
Date: Sat, 1 Mar 2014 16:56:04 -0800
Subject: [PATCH 012/178] Tweaked ratio calculation

---
 server/queues/scoring.coffee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee
index 692a08b75..0079d34a8 100644
--- a/server/queues/scoring.coffee
+++ b/server/queues/scoring.coffee
@@ -163,7 +163,7 @@ determineIfSessionShouldContinueAndUpdateLog = (sessionID, sessionRank, cb) ->
       console.log "Number of games played is less than 5, continuing..."
       cb null, true
     else
-      ratio = (updatedSession.numberOfLosses - 5) / (totalNumberOfGamesPlayed)
+      ratio = (updatedSession.numberOfLosses) / (totalNumberOfGamesPlayed)
       if ratio > 0.66
         cb null, false
         console.log "Ratio(#{ratio}) is bad, ending simulation"

From 6c48660922ecd8c9e3f852e047d05473f4db0935 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sat, 1 Mar 2014 16:57:29 -0800
Subject: [PATCH 013/178] No save button when there's nothing to save. Messing
 with AudioPlayer playSound API a bit.

---
 app/lib/AudioPlayer.coffee              | 5 +++--
 app/lib/surface/CocoSprite.coffee       | 2 +-
 app/templates/editor/level/save.jade    | 4 ++++
 app/views/editor/level/save_view.coffee | 1 +
 4 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/app/lib/AudioPlayer.coffee b/app/lib/AudioPlayer.coffee
index 122509dcc..b5eb4f70d 100644
--- a/app/lib/AudioPlayer.coffee
+++ b/app/lib/AudioPlayer.coffee
@@ -78,8 +78,9 @@ class AudioPlayer extends CocoClass
       @preloadInterfaceSounds [name] unless filename of cache
       @soundsToPlayWhenLoaded[name] = volume
 
-  playSound: (name, volume=1) ->
-    createjs.Sound.play name, {volume: (me.get('volume') ? 1) * volume}
+  playSound: (name, volume=1, delay=0) ->
+    instance = createjs.Sound.play name, {volume: (me.get('volume') ? 1) * volume, delay: delay}
+    instance
 
 #  # TODO: load Interface sounds somehow, somewhere, somewhen
 
diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee
index 29ee32371..008519599 100644
--- a/app/lib/surface/CocoSprite.coffee
+++ b/app/lib/surface/CocoSprite.coffee
@@ -475,6 +475,6 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     return null unless sound
     delay = if withDelay and sound.delay then 1000 * sound.delay / createjs.Ticker.getFPS() else 0
     name = AudioPlayer.nameForSoundReference sound
-    instance = createjs.Sound.play name, "none", delay, 0, 0, volume
+    instance = AudioPlayer.playSound name, volume, delay
 #    console.log @thang?.id, "played sound", name, "with delay", delay, "volume", volume, "and got sound instance", instance
     instance
diff --git a/app/templates/editor/level/save.jade b/app/templates/editor/level/save.jade
index 8ada52b23..00e9e43f2 100644
--- a/app/templates/editor/level/save.jade
+++ b/app/templates/editor/level/save.jade
@@ -52,3 +52,7 @@ block modal-body-content
           label.control-label(for=id + "-version-is-major") Major Changes?
           input(id=id + "-version-is-major", name="version-is-major", type="checkbox")
           span.help-block (Could this update break anything depending on this System?)
+
+if noSaveButton
+  block modal-footer-content
+    button.btn(data-dismiss="modal", data-i18n="common.cancel") Cancel
diff --git a/app/views/editor/level/save_view.coffee b/app/views/editor/level/save_view.coffee
index a1f0ee01b..4edf03ca0 100644
--- a/app/views/editor/level/save_view.coffee
+++ b/app/views/editor/level/save_view.coffee
@@ -23,6 +23,7 @@ module.exports = class LevelSaveView extends SaveVersionModal
     context.levelNeedsSave = @level.hasLocalChanges()
     context.modifiedComponents = _.filter @supermodel.getModels(LevelComponent), @shouldSaveEntity
     context.modifiedSystems = _.filter @supermodel.getModels(LevelSystem), @shouldSaveEntity
+    context.noSaveButton = context.levelNeedsSave or context.modifiedComponents.length or context.modifiedSystems.length
     context
 
   shouldSaveEntity: (m) ->

From da2ebf857a6d2d86468c911ee6705dc0404a08e3 Mon Sep 17 00:00:00 2001
From: Muhammed Thanish <mnmtanish@gmail.com>
Date: Sun, 2 Mar 2014 14:02:30 +0530
Subject: [PATCH 014/178] Increase delay

---
 app/lib/surface/WizardSprite.coffee       |  2 +-
 app/views/play/level/playback_view.coffee | 16 ++++++++--------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/app/lib/surface/WizardSprite.coffee b/app/lib/surface/WizardSprite.coffee
index 236d2d77d..b98ae44b5 100644
--- a/app/lib/surface/WizardSprite.coffee
+++ b/app/lib/surface/WizardSprite.coffee
@@ -231,7 +231,7 @@ module.exports = class WizardSprite extends IndieSprite
     super() if @displayObject.visible  # not if we hid the wiz
 
   moveWizard : (x, y) =>
-    interval = 250
+    interval = 500
     position = {x: @targetPos.x+x, y: @targetPos.y+y}
     @setTarget(position, interval, true)
     @updatePosition()
diff --git a/app/views/play/level/playback_view.coffee b/app/views/play/level/playback_view.coffee
index c9d11c9f0..20ec9295c 100644
--- a/app/views/play/level/playback_view.coffee
+++ b/app/views/play/level/playback_view.coffee
@@ -222,11 +222,11 @@ module.exports = class PlaybackView extends View
 
   onMoveKey: (e) ->
     e?.preventDefault()
-    x = 0
-    y = 0
-    y = 1 if key.isPressed('up')
-    y = -1 if key.isPressed('down')
-    x = 1 if key.isPressed('right')
-    x = -1 if key.isPressed('left')
-    console.log 'onMoveKey', x, y
-    Backbone.Mediator.publish 'self-wizard:move', x, y
+    yMovement = 0
+    xMovement = 0
+    yMovement += 2 if key.isPressed('up')
+    yMovement -= 2 if key.isPressed('down')
+    xMovement += 2 if key.isPressed('right')
+    xMovement -= 2 if key.isPressed('left')
+    console.log 'onMoveKey', xMovement, yMovement
+    Backbone.Mediator.publish 'self-wizard:move', xMovement, yMovement

From fb57e634a5469a88c60530c23eaa6cb8cc8c2d64 Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <rubenvereecken@gmail.com>
Date: Sun, 2 Mar 2014 18:35:37 +0100
Subject: [PATCH 015/178] Patched up some grammar mistakes (Dutch-Nederlands).

---
 app/locale/nl.coffee | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/app/locale/nl.coffee b/app/locale/nl.coffee
index dd5904abe..c644b5d99 100644
--- a/app/locale/nl.coffee
+++ b/app/locale/nl.coffee
@@ -213,13 +213,13 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
 
   editor:
     main_title: "CodeCombat Editors"
-    main_description: "Maak je eigen levels, campagnes, eenheden en leermateriaal. Wij bieden alle programma's die u nodig heeft!"
+    main_description: "Maak je eigen levels, campagnes, eenheden en leermateriaal. Wij bieden alle programma's aan die u nodig heeft!"
     article_title: "Artikel Editor"
     article_description: "Schrijf artikels dat spelers een overzicht geven over programmeer concepten die kunnen gebruikt worden over een variëteit van levels en campagnes."
     thang_title: "Thang Editor"
-    thang_description: "Maak eenheden, beschrijf hun default logica, graphics en audio. Momenteel is enkel het importeren van vector graphics geëxporteerd in Flash ondersteunt."
+    thang_description: "Maak eenheden, beschrijf hun default logica, graphics en audio. Momenteel is enkel het importeren van vector graphics geëxporteerd in Flash ondersteund."
     level_title: "Level Editor"
-    level_description: "Bevat programmeurs om te programmeren, audio te uploaden, en om aangepaste logica om alle soorten levels te maken. Het is alles wat wijzelf ook gebruiken!"
+    level_description: "Bevat het gereedschap om te programmeren, audio te uploaden en aangepaste logica om alle soorten levels te maken. Het is alles wat wijzelf ook gebruiken!"
     security_notice: "Veel belangrijke elementen in deze editors zijn momenteel niet actief. Met dat wij de veiligheid van deze systemen verbeteren, zullen ook deze elementen beschikbaar worden. Indien u deze elementen al eerder wil gebruiken, "
     contact_us: "contacteer ons!"
     hipchat_prefix: "Je kan ons ook vinden in ons"

From 60f79e261d86f61ea3d6a94c64af7a85112b736e Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <rubenvereecken@gmail.com>
Date: Sun, 2 Mar 2014 19:42:56 +0100
Subject: [PATCH 016/178] Patched up tonnes of minor language mistakes
 (Dutch-Nederlands)

---
 app/locale/nl.coffee | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/app/locale/nl.coffee b/app/locale/nl.coffee
index c644b5d99..0942c88a1 100644
--- a/app/locale/nl.coffee
+++ b/app/locale/nl.coffee
@@ -219,7 +219,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     thang_title: "Thang Editor"
     thang_description: "Maak eenheden, beschrijf hun default logica, graphics en audio. Momenteel is enkel het importeren van vector graphics geëxporteerd in Flash ondersteund."
     level_title: "Level Editor"
-    level_description: "Bevat het gereedschap om te programmeren, audio te uploaden en aangepaste logica om alle soorten levels te maken. Het is alles wat wijzelf ook gebruiken!"
+    level_description: "Bevat het programma om te programmeren, audio te uploaden en aangepaste logica om alle soorten levels te maken. Het is alles wat wijzelf ook gebruiken!"
     security_notice: "Veel belangrijke elementen in deze editors zijn momenteel niet actief. Met dat wij de veiligheid van deze systemen verbeteren, zullen ook deze elementen beschikbaar worden. Indien u deze elementen al eerder wil gebruiken, "
     contact_us: "contacteer ons!"
     hipchat_prefix: "Je kan ons ook vinden in ons"
@@ -267,16 +267,16 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
   about:
     who_is_codecombat: "Wie is CodeCombat?"
     why_codecombat: "Waarom CodeCombat?"
-    who_description_prefix: "hebben samen CodeCombat opgericht in 2013. We creerden ook "
+    who_description_prefix: "hebben samen CodeCombat opgericht in 2013. We creëerden ook "
     who_description_suffix: "en in 2008, groeide het uit tot de #1 web en iOS applicatie om Chinese en Japanse karakters te leren schrijven."
     who_description_ending: "Nu is het tijd om mensen te leren programmeren."
-    why_paragraph_1: "Tijdens het maken van Skritter wist George niet hoe hij moest programmeren. Hij constant gefrustreerd doordat hij zijn ideeën niet kon verwezelijken. Nadien probeerde hij te studeren, maar te lessen gingen te traag. Ook zijn huisgenoot wou opnieuw studeren en stopte met lesgeven. Hij probeerde Codecademy maar was al snel \"verveeld\". Iedere week starte een andere vriend met Codecademy, met telkens als resultaat dat hij/zij vrij snel met de lessen stopte. We realiseerde ons dat het hetzelfde probleem was zoals we al eerder hadden opgelost met Skritter: mensen leren iets via langzame en intensieve lessen, terwijl ze het eigenlijk zo snel mogelijk nodig hebben via uitgebreide oefeningen. Wij weten hoe dat op te lossen."
+    why_paragraph_1: "Tijdens het maken van Skritter wist George niet hoe hij moest programmeren en was hij constant gefrustreerd doordat hij zijn ideeën niet kon verwezelijken. Nadien probeerde hij te studeren maar de lessen gingen te traag. Ook zijn huisgenoot wou opnieuw studeren en stopte met lesgeven. Hij probeerde Codecademy maar was al snel \"verveeld\". Iedere week startte een andere vriend met Codecademy, met telkens als resultaat dat hij/zij vrij snel met de lessen stopte. We realiseerden ons dat het hetzelfde probleem was zoals we al eerder hadden opgelost met Skritter: mensen leren iets via langzame en intensieve lessen, terwijl ze het eigenlijk zo snel mogelijk nodig hebben via uitgebreide oefeningen. Wij weten hoe dat op te lossen."
     why_paragraph_2: "Wil je leren programmeren? Je hebt geen lessen nodig. Je moet vooral veel code schrijven en je amuseren terwijl je dit doet."
     why_paragraph_3_prefix: "Dat is waar programmeren om draait. Het moet tof zijn. Niet tof zoals"
     why_paragraph_3_italic: "joepie een medaille"
     why_paragraph_3_center: "maar tof zoals"
     why_paragraph_3_italic_caps: "NEE MAMA IK MOET DIT LEVEL AF MAKEN!"
-    why_paragraph_3_suffix: "Dat is waarom CodeCombat een multiplayergame is, en niet zomaar lessen gegoten in spelformaat. We zullen niet stoppen totdat jij niet meer kan stoppen--maar deze keer, is dat een goed."
+    why_paragraph_3_suffix: "Dat is waarom CodeCombat een multiplayergame is, en niet zomaar lessen gegoten in spelformaat. We zullen niet stoppen totdat jij niet meer kan stoppen--maar deze keer, is dat iets goeds."
     why_paragraph_4: "Als je verslaafd gaat zijn aan een spel, dan is het beter om hieraan verslaafd te raken en een tovenaar van het technisch tijdperk te worden."
     why_ending: "En hallo, het is gratis."
     why_ending_url: "Start nu met toveren!"
@@ -297,15 +297,15 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     practices_title: "Goede Respectvolle gewoonten"
     practices_description: "Dit zijn onze beloften aan u, de speler, en iets minder juridische jargon."
     privacy_title: "Privacy"
-    privacy_description: "We zullen nooit jouw persoonlijke informatie verkopen. We willen geld verdienen dankzij aanwerving in verloop van tijd, maar je mag op je twee oren slapen dat wij nooit jouw persoonlijke informatie zullen verspreiden aan geïnteresseerde bedrijven zonder dat jij daar explicit met akkoord gaat."
+    privacy_description: "We zullen nooit jouw persoonlijke informatie verkopen. We willen geld verdienen dankzij aanwerving in verloop van tijd, maar je mag op je twee oren slapen dat wij nooit jouw persoonlijke informatie zullen verspreiden aan geïnteresseerde bedrijven zonder dat jij daar expliciet mee akkoord gaat."
     security_title: "Beveiliging"
     security_description: "We streven ernaar om jouw persoonlijke informatie veilig te bewaren. Onze website is open en beschikbaar voor iedereen, opdat ons beveiliging systeem kan worden nagekeken en geoptimaliseerd door iedereen die dat wil. Dit alles is mogelijk doordat we volledig open source en transparant zijn."
     email_title: "E-mail"
     email_description_prefix: "We zullen je niet overspoelen met spam. Door"
     email_settings_url: "jouw e-mail instellingen"
-    email_description_suffix: "of via urls in de emails die wij verzanden, kan je jouw instellingen wijzigen en te alle tijden uitschrijven."
+    email_description_suffix: "of via urls in de emails die wij verzenden, kan je jouw instellingen wijzigen en ten allen tijden uitschrijven."
     cost_title: "Kosten"
-    cost_description: "Momenteel, CodeCombat is 100% gratis! Één van onze doestellingen is om dit zo te houden, opdat zoveel mogelijk mensen kunnen spelen, onafhankelijk van waar je leeft of wie je bent. Als het financieel moeilijker wordt, kan het mogelijk zijn dat we gaan beginnen met abonnementen of een prijs zetten op bepaalde zaken, maar we streven ernaar om dit te verkomen. Met een beetje geluk zullen we dit voor altijd kunnen garanderen met:"
+    cost_description: "Momenteel is CodeCombat 100% gratis! Één van onze doestellingen is om dit zo te houden, opdat zoveel mogelijk mensen kunnen spelen, onafhankelijk van waar je leeft of wie je bent. Als het financieel moeilijker wordt, kan het mogelijk zijn dat we gaan beginnen met abonnementen of een prijs zetten op bepaalde zaken, maar we streven ernaar om dit te voorkomen. Met een beetje geluk zullen we dit voor altijd kunnen garanderen met:"
     recruitment_title: "Aanwervingen"
     recruitment_description_prefix: "Hier bij CodeCombat, ga je ontplooien tot een krachtige tovenoor-niet enkel virtueel, maar ook in het echt."
     url_hire_programmers: "Niemand kan snel genoeg programmeurs aanwerven"
@@ -320,20 +320,20 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     code_title: "Code - MIT"
     code_description_prefix: "Alle code in het bezit van CodeCombat of aanwezig op codecombat.com, zowel in de GitHub respository of in de codecombat.com database, is erkend onder de"
     mit_license_url: "MIT licentie"
-    code_description_suffix: "Dit geld zowel voor code in Systemen en Componenten dat publiekelijk is gemaakt met als doelstellingen het maken van levels."
+    code_description_suffix: "Dit geldt ook voor code in Systemen en Componenten dat publiekelijk is gemaakt met als doelstellingen het maken van levels."
     art_title: "Art/Music - Creative Commons "
     art_description_prefix: "Alle gemeenschappelijke inhoud valt onder de"
     cc_license_url: "Creative Commons Attribution 4.0 Internationale Licentie"
-    art_description_suffix: "Gemeenschappelijke inhoud is alles dat algemeen verkrijgen is bij CodeCombat voor het doel levels te maken. Dit omvat:"
+    art_description_suffix: "Gemeenschappelijke inhoud is alles dat algemeen verkrijgbaar is bij CodeCombat voor het doel levels te maken. Dit omvat:"
     art_music: "Muziek"
     art_sound: "Geluid"
     art_artwork: "Artwork"
     art_sprites: "Sprites"
     art_other: "Eender wat en al het creatief werk dat niet als code aanzien wordt en verkrijgbaar is bij het aanmaken van levels."
-    art_access: "Momenteel is er geen universeel en gebruiksvriendelijk voor het ophalen van deze assets. In het algemeen, worden deze opgehaald via de links zoals gebruikt door de website. Contacteer ons voor assitentie, of help ons met de website uit te breiden en de assets bereikbaarder maken."
+    art_access: "Momenteel is er geen universeel en gebruiksvriendelijk systeem voor het ophalen van deze assets. In het algemeen, worden deze opgehaald via de links zoals gebruikt door de website. Contacteer ons voor assitentie, of help ons met de website uit te breiden en de assets bereikbaarder te maken."
     art_paragraph_1: "Voor toekenning, gelieve de naam en link naar codecombat.com te plaatsen waar dit passend is voor de vorm waarin het voorkomt. Bijvoorbeeld:"
     use_list_1: "Wanneer gebruikt in een film of een ander spel, voeg codecombat.com toe in de credits."
-    use_list_2: "Wanneer toegepast op een website, inclusief een link naar het gebruik, bijvorbeeld onderaan een afbeelding. Of in een algemene webpagina waar je eventueel ook andere Create Commons werken en open source software vernoemd die je gebruikt op de website. Iets dat alreeds duidelijk is gespecificeerd met CodeCombat, zoals een blog artikel, dat CodeCombat vernoemt, heeft geen aparte vermelding nodig."
+    use_list_2: "Wanneer toegepast op een website, inclusief een link naar het gebruik, bijvoorbeeld onderaan een afbeelding. Of in een algemene webpagina waar je eventueel ook andere Create Commons werken en open source software vernoemd die je gebruikt op de website. Iets dat alreeds duidelijk is gespecificeerd met CodeCombat, zoals een blog artikel, dat CodeCombat vernoemt, heeft geen aparte vermelding nodig."
     art_paragraph_2: "Wanneer de gebruikte inhoud is gemaakt door een gebruiker van codecombat.com, vernoem hem/haar in plaats van ons. en volg verspreidingsaanwijzingen van die brons als die er zijn."
     rights_title: "Rechten Voorbehouden"
     rights_desc: "Alle rechten zijn voorbehouden voor de Levels. Dit omvat:"

From e4bf752e2030bd25eba272331c9bc854ecbf1484 Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <rubenvereecken@gmail.com>
Date: Sun, 2 Mar 2014 20:30:18 +0100
Subject: [PATCH 017/178] Changed Dutch (NL) ambassador_summary to match the
 English version

---
 app/locale/nl.coffee | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/app/locale/nl.coffee b/app/locale/nl.coffee
index 0942c88a1..57a366206 100644
--- a/app/locale/nl.coffee
+++ b/app/locale/nl.coffee
@@ -334,7 +334,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     art_paragraph_1: "Voor toekenning, gelieve de naam en link naar codecombat.com te plaatsen waar dit passend is voor de vorm waarin het voorkomt. Bijvoorbeeld:"
     use_list_1: "Wanneer gebruikt in een film of een ander spel, voeg codecombat.com toe in de credits."
     use_list_2: "Wanneer toegepast op een website, inclusief een link naar het gebruik, bijvoorbeeld onderaan een afbeelding. Of in een algemene webpagina waar je eventueel ook andere Create Commons werken en open source software vernoemd die je gebruikt op de website. Iets dat alreeds duidelijk is gespecificeerd met CodeCombat, zoals een blog artikel, dat CodeCombat vernoemt, heeft geen aparte vermelding nodig."
-    art_paragraph_2: "Wanneer de gebruikte inhoud is gemaakt door een gebruiker van codecombat.com, vernoem hem/haar in plaats van ons. en volg verspreidingsaanwijzingen van die brons als die er zijn."
+    art_paragraph_2: "Wanneer de gebruikte inhoud is gemaakt door een gebruiker van codecombat.com, vernoem hem/haar in plaats van ons en volg verspreidingsaanwijzingen van die brons als die er zijn."
     rights_title: "Rechten Voorbehouden"
     rights_desc: "Alle rechten zijn voorbehouden voor de Levels. Dit omvat:"
     rights_scripts: "Scripts"
@@ -342,15 +342,15 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     rights_description: "Beschrijvingen"
     rights_writings: "Literaire werken"
     rights_media: "Media (geluid, muziek) en eender welke creatieve inhoud, specifiek gemaakt voor dat level en niet verkrijgbaar bij het maken van levels."
-    rights_clarification: "Om het duidelijk te maken, iets dat beschikbaar is in de Level editor voor het maken van level, valt onder de CC licentie. Terwijl de inhoud gemaakt met de Level Editor of geupload in de loop van de creatie van de levels, hier not onder vallen."
+    rights_clarification: "Om het duidelijk te maken, iets dat beschikbaar is in de Level editor voor het maken van levels, valt onder de CC licentie. Terwijl de inhoud gemaakt met de Level Editor of geüpload in de loop van de creatie van de levels, hier niet onder vallen."
     nutshell_title: "In een notendop"
-    nutshell_description: "Alle midellen die wij aanbieden in de Level Editor zijn gratis te gebruiken om levels aan te maken. Maar wij behouden ons het recht om levels die gemaakt zijn op codecombat.com te beperken, en hier in de toekomst geld voor te vragen, moest dat ooit gebeuren."
+    nutshell_description: "Alle middelen die wij aanbieden in de Level Editor zijn gratis te gebruiken om levels aan te maken. Wij behouden ons echter het recht voor om levels die gemaakt zijn op codecombat.com te beperken, en hier in de toekomst geld voor te vragen, moest dat ooit gebeuren."
     canonical: "De Engelse versie van dit document is de definitieve en kanonieke versie. Bij verschillen tussen vertalingen heeft de Engelse versie voorrang."
 
   contribute:
     page_title: "Bijdragen"
     character_classes_title: "Karakter Klassen"
-    introduction_desc_intro: "We hebben hoge verwachten over CodeCombat."
+    introduction_desc_intro: "We hebben hoge verwachtingen over CodeCombat."
     introduction_desc_pref: "We willen zijn waar programmeurs van alle niveaus komen om te leren en samen te spelen, anderen introduceren aan de wondere wereld van code, en de beste delen van de gemeenschap te reflecteren. We kunnen en willen dit niet alleen doen; wat projecten zoals GitHub, Stack Overflow en Linux groots en succesvol maken, zijn de mensen die deze software gebruiken en verbeteren. Daartoe, "
     introduction_desc_github_url: "CodeCombat is volledig open source"
     introduction_desc_suf: ", en we mikken ernaar om zoveel mogelijk manieren mogelijk maken voor u om deel te nemen en dit project van zowel jou als ons te maken."
@@ -360,7 +360,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     alert_account_message_pref: "Om je te abonneren voor de klasse e-mails, moet je eerst "
     alert_account_message_suf: "."
     alert_account_message_create_url: "een account aanmaken"
-    archmage_summary: "Geïnteresserd in werken aan game graphics, user interface design, database- en serverorganisatie, multiplayer networking, physics, geluid of game engine  prestaties? Wil jij helpen een game te bouwen wat anderen leert waar jij goed in bent? We moeten nog veel doen en als jij een ervaren programmeur bent en wil ontwikkelen voor CodeCombat, dan is dit de klasse voor jou. We zouden graag je hulp hebben bij het maken van de beste programmeergame ooit."
+    archmage_summary: "Geïnteresserd in werken aan game graphics, user interface design, database- en serverorganisatie, multiplayer networking, physics, geluid of game engine prestaties? Wil jij helpen een game te bouwen wat anderen leert waar jij goed in bent? We moeten nog veel doen en als jij een ervaren programmeur bent en wil ontwikkelen voor CodeCombat, dan is dit de klasse voor jou. We zouden graag je hulp hebben bij het maken van de beste programmeergame ooit."
     archmage_introduction: "Een van de beste aspecten aan het maken van spelletjes is dat zij zoveel verschillende zaken omvatten. Visualisaties, geluid, real-time netwerken, sociale netwerken, en natuurlijk veel van de voorkomende aspecten van programmeren, van low-level database beheer en server administratie tot gebruiksvriendelijke interfaces maken. Er is veel te doen, en als jij een ervaren programmeur bent met de motivatie om je handen veel te maken met CodeCombat, dan ben je de tovenaar die wij zoeken! We zouden graag jouw help hebben met het bouwen aan het allerbeste programmeerspel ooit."
     class_attributes: "Klasse kenmerken"
     archmage_attribute_1_pref: "Ervaring met "
@@ -386,7 +386,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     artisan_join_step1: "Lees de documentatie."
     artisan_join_step2: "Maak een nieuw level en bestudeer reeds bestaande levels."
     artisan_join_step3: "Praat met ons in ons publieke (Engelstalige) HipChat kanaal voor hulp. (optioneel)"
-    artisan_join_step4: "Maak een bericht over jou level op ons forum voor feedback."
+    artisan_join_step4: "Maak een bericht over jouw level op ons forum voor feedback."
     more_about_artisan: "Leer meer over hoe je een Creatieve Ambachtsman kan worden."
     artisan_subscribe_desc: "Ontvang e-mails met nieuws over de Level Editor."
     adventurer_sumamry: "Laten we duidelijk zijn over je rol: jij bent de tank. Jij krijgt de zware klappen te verduren. We hebben mensen nodig om spiksplinternieuwe levels te proberen en te kijken hoe deze beter kunnen. De pijn zal groot zijn, het maken van een goede game is een lang proces en niemand doet het de eerste keer goed. Als jij dit kan verduren en een hoge constitution score hebt, dan is dit de klasse voor jou."
@@ -403,7 +403,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     scribe_introduction_pref: "CodeCombat is meer dan slechts een aantal levels, het zal ook een bron van kennis kennis zijn en een wiki met programmeerconcepten waar levels op in kunnen gaan. Op die manier zal elk Ambachtslied niet in detail hoeven uit te leggen wat een vergelijkingsoperator is, maar een link kunnen geven naar een artikel wat deze informatie bevat voor de speler. Net zoiets als het  "    
     scribe_introduction_url_mozilla: "Mozilla Developer Network"
     scribe_introduction_suf: " heeft gebouwd. Als jij het leuk vindt om programmeerconcepten uit te leggen in Markdown-vorm, dan is deze klasse wellicht iets voor jou."
-    scribe_attribute_1: "Taal-skills zijn praktisch alles wat je nodig hebt. Niet alleen grammatica of spelling, maar ook moeilijke ideas overbrengen aan anderen."    
+    scribe_attribute_1: "Taal-skills zijn praktisch alles wat je nodig hebt. Niet alleen grammatica of spelling, maar ook moeilijke ideeën overbrengen aan anderen."
     contact_us_url: "Contacteer ons"
     scribe_join_description: "vertel ons wat over jezelf, je ervaring met programmeren en over wat voor soort dingen je graag zou schrijven. Verder zien we wel!"    
     more_about_scribe: "Leer meer over het worden van een ijverige Klerk."    
@@ -412,22 +412,22 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     diplomat_summary: "Er is grote interesse in CodeCombat in landen waar geen Engels wordt gesproken! We zijn op zoek naar vertalers wie tijd willen spenderen aan het vertalen van de site's corpus aan woorden zodat CodeCombat zo snel mogelijk toegankelijk wordt voor heel de wereld. Als jij wilt helpen met CodeCombat internationaal maken, dan is dit de klasse voor jou."
     diplomat_introduction_pref: "Dus, als er iets is wat we geleerd hebben van de "    
     diplomat_launch_url: "release in oktober"
-    diplomat_introduction_suf: "dan is het wel dat er een significante interesse is in CodeCombat in andere landen, vooral Brazilïe! We zijn een corps aan vertalers aan het creëren dat ijverig de ene set woorden in een andere omzet om CodeCombat zo toegankelijk te maken als mogelijk in hel de wereld. Als jij het leuk vindt glimpsen op te vangen van aankomende content en deze levels zo snel mogelijk naar je landgenoten te krijgen, dan is dit de klasse voor jou."
-    diplomat_attribute_1: "Vloeiend Engels en de taal waar naar je wilt vertalen kunnen spreken. Wanneer je moeilijke ideas wilt overbrengen, is het belangrijk beide goed te kunnen!"
+    diplomat_introduction_suf: "dan is het wel dat er een significante interesse is in CodeCombat in andere landen, vooral Brazilië! We zijn een corps aan vertalers aan het creëren dat ijverig de ene set woorden in een andere omzet om CodeCombat zo toegankelijk te maken als mogelijk in heel de wereld. Als jij het leuk vindt glimpsen op te vangen van aankomende content en deze levels zo snel mogelijk naar je landgenoten te krijgen, dan is dit de klasse voor jou."
+    diplomat_attribute_1: "Vloeiend Engels en de taal waar naar je wilt vertalen kunnen spreken. Wanneer je moeilijke ideeën wilt overbrengen, is het belangrijk beide goed te kunnen!"
     diplomat_join_pref_github: "Vind jouw taal haar locale bestand "
     diplomat_github_url: "op GitHub"
-    diplomat_join_suf_github: ", edit het online, en submit een pull request. Daarnaast kun je hieronder aanvinken alsj e up-to-date wilt worden gehouden met nieuwe internationalisatie-ontwikkelingen."
+    diplomat_join_suf_github: ", edit het online, en submit een pull request. Daarnaast kun je hieronder aanvinken als je up-to-date wilt worden gehouden met nieuwe internationalisatie-ontwikkelingen."
     more_about_diplomat: "Leer meer over het worden van een geweldige Diplomaat"
     diplomat_subscribe_desc: "Ontvang e-mails over i18n ontwikkelingen en levels om te vertalen."
-    ambassador_summary: "We proberen een gemeenschap te bouwen en elke gemeenschap heeft een supportteam nodig wanneer er problemen zijn. We hebben chats, e-mails en sociale netwerken met een hoop mensen om mee te praten en wie je kunt helpen bekend te worden met het spel en er van te leren. Als jij mensen wilt helpen betrokken te raken en plezier te hebben, én een goed gevoel van de levenslijn van CodeCombat te krijgen en waar we naar toe gaan, dan is dit wellicht de klasse voor jou."    
+    ambassador_summary: "We proberen een gemeenschap te bouwen en elke gemeenschap heeft een supportteam nodig wanneer er problemen zijn. We hebben chats, e-mails en sociale netwerken zodat onze gebruikers het spel kunnen leren kennen. Als jij mensen wilt helpen betrokken te raken, plezier te hebben en wat te leren programmeren, dan is dit wellicht de klasse voor jou."
     ambassador_attribute_1: "Communicatieskills. Problemen die spelers hebben kunnen identificeren en ze helpen deze op te lossen. Verder zul je ook de rest van ons geïnformeerd houden over wat de spelers zeggen, wat ze leuk vinden, wat ze minder vinden en waar er meer van moet zijn!"
     ambassador_join_desc: "vertel ons wat over jezelf, wat je hebt gedaan en wat je graag zou doen. We zien verder wel!"    
     ambassador_join_note_strong: "Opmerking"
     ambassador_join_note_desc: "Een van onze topprioriteiten is om een multiplayer te bouwen waar spelers die moeite hebben een level op te lossen een wizard met een hoger level kunnen oproepen om te helpen. Dit zal een goede manier zijn voor ambassadeurs om hun ding te doen. We houden je op de hoogte!"    
     more_about_ambassador: "Leer meer over het worden van een behulpzame Ambassadeur"
     ambassador_subscribe_desc: "Ontvang e-mails met updates over ondersteuning en multiplayer-ontwikkelingen."    
-    counselor_summary: "Geen van de rollen hierboven in jouw interessegebied? Maak je geen zorgen, we zijn op zoek naar iedereen die wil helpen met het ontwikkelen van CodeCombat! Als je geïnteresseerd bent in lesgeven, gameontwikkeling, open source management of iets anders waarvan je denk dat het relevant voor ons is, dan is dit de klasse voor jou."
-    counselor_introduction_1: "Heb jij levenservaring? Een afwijkend perspectief op zaken die ons kunnen helpen CodeCombat te vormen? Van alle rollen neemt deze wellicht de minste tijd in, maar individiueel maak je misschien het grootste verschil. We zijn op zoek naar wijze tovenaars, vooral in het gebied van lesgeven, gameontwikkeling, open source projectmanagement, technische recrutering, ondernemerschap of design."    
+    counselor_summary: "Geen van de rollen hierboven in jouw interessegebied? Maak je geen zorgen, we zijn op zoek naar iedereen die wil helpen met het ontwikkelen van CodeCombat! Als je geïnteresseerd bent in lesgeven, gameontwikkeling, open source management of iets anders waarvan je denkt dat het relevant voor ons is, dan is dit de klasse voor jou."
+    counselor_introduction_1: "Heb jij levenservaring? Een afwijkend perspectief op zaken die ons kunnen helpen CodeCombat te vormen? Van alle rollen neemt deze wellicht de minste tijd in, maar individueel maak je misschien het grootste verschil. We zijn op zoek naar wijze tovenaars, vooral in het gebied van lesgeven, gameontwikkeling, open source projectmanagement, technische recrutering, ondernemerschap of design."
     counselor_introduction_2: "Of eigenlijk alles wat relevant is voor de ontwikkeling van CodeCombat. Als jij kennis hebt en deze wilt dezen om dit project te laten groeien, dan is dit misschien de klasse voor jou."    
     counselor_attribute_1: "Ervaring, in enig van de bovenstaande gebieden of iets anders waarvan je denkt dat het behulpzaam zal zijn."
     counselor_attribute_2: "Een beetje vrije tijd!"

From d0f416f66880a6db26aced8d02892a21fd361353 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Sun, 2 Mar 2014 12:43:21 -0800
Subject: [PATCH 018/178] Rearranging the ladder view.

---
 app/styles/play/ladder.sass                   |  10 +-
 app/templates/play/ladder.jade                |  78 ++++----
 app/templates/play/ladder/ladder_tab.jade     |  23 +++
 app/templates/play/ladder/my_matches_tab.jade |  45 +++++
 app/views/play/ladder/ladder_tab.coffee       |  97 ++++++++++
 app/views/play/ladder/my_matches_tab.coffee   | 101 ++++++++++
 app/views/play/ladder/utils.coffee            |  23 +++
 app/views/play/ladder_view.coffee             | 183 ++++--------------
 8 files changed, 372 insertions(+), 188 deletions(-)
 create mode 100644 app/templates/play/ladder/ladder_tab.jade
 create mode 100644 app/templates/play/ladder/my_matches_tab.jade
 create mode 100644 app/views/play/ladder/ladder_tab.coffee
 create mode 100644 app/views/play/ladder/my_matches_tab.coffee
 create mode 100644 app/views/play/ladder/utils.coffee

diff --git a/app/styles/play/ladder.sass b/app/styles/play/ladder.sass
index 027e755db..3ca1754e3 100644
--- a/app/styles/play/ladder.sass
+++ b/app/styles/play/ladder.sass
@@ -1,4 +1,10 @@
 #ladder-view
+  h1
+    text-align: center
+    
+  .tab-pane
+    margin-top: 10px
+  
   .score-cell
     width: 50px
     
@@ -10,10 +16,6 @@
     width: 45%
     margin: 0 2.5%
 
-  #simulation-status-text
-    display: inline
-    margin-left: 10px
-
   .name-col-cell
     max-width: 300px
     text-overflow: ellipsis
diff --git a/app/templates/play/ladder.jade b/app/templates/play/ladder.jade
index 1eb85a6f0..9e03f5f3c 100644
--- a/app/templates/play/ladder.jade
+++ b/app/templates/play/ladder.jade
@@ -2,17 +2,11 @@ extends /templates/base
 block content
 
   div#level-column
-    h3= level.get('name')
-    div#level-description
-      !{description}
-  
-    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/brawlwood-tutorial").intro-button.btn.btn-primary.btn-lg Play the Tutorial
+    h1= level.get('name')
+    
+    //if !me.get('anonymous')
+    //  a(href="/play/level/brawlwood-tutorial").intro-button.btn.btn-primary.btn-lg Play the Tutorial
 
-  hr
-  
   if me.get('anonymous')
     div#must-log-in
       p
@@ -23,41 +17,37 @@ block content
 
   else
     div#columns.row
+      div.column.col-md-2
       for team in teams
-        div.column.col-md-6
+        div.column.col-md-4
           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
\ No newline at end of file
+      div.column.col-md-2
+    
+    hr
+      
+    ul.nav.nav-pills
+      li.active
+        a(href="#ladder", data-toggle="tab") Ladder
+      li
+        a(href="#my-matches", data-toggle="tab") My Matches
+      li
+        a(href="#simulate", data-toggle="tab") Simulate
+
+    div.tab-content
+      .tab-pane.active.well#ladder
+        #ladder-tab-view
+      .tab-pane.well#my-matches
+        | My Matches Pane
+      .tab-pane.well#simulate
+        p(id="simulation-status-text")
+          if simulationStatus
+            | #{simulationStatus}
+          else
+            | By simulating games you can get your game ranked faster!
+        p
+          button.btn.btn-warning.btn-lg.highlight#simulate-button() Simulate Games!
+        if me.isAdmin()
+          p
+            button.btn.btn-danger.btn-lg.highlight#simulate-all-button() RESET AND SIMULATE GAMES
\ No newline at end of file
diff --git a/app/templates/play/ladder/ladder_tab.jade b/app/templates/play/ladder/ladder_tab.jade
new file mode 100644
index 000000000..f0c7a1b1f
--- /dev/null
+++ b/app/templates/play/ladder/ladder_tab.jade
@@ -0,0 +1,23 @@
+div#columns.row
+  for team in teams
+    div.column.col-md-6
+      table.table.table-bordered.table-condensed.table-hover
+        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.
diff --git a/app/templates/play/ladder/my_matches_tab.jade b/app/templates/play/ladder/my_matches_tab.jade
new file mode 100644
index 000000000..d07432a83
--- /dev/null
+++ b/app/templates/play/ladder/my_matches_tab.jade
@@ -0,0 +1,45 @@
+//if matches.length
+//  p#your-score
+//    span Your Current Score:
+//    span  
+//    strong= score
+
+h3.pull-left Ranked Games
+div#columns.row
+  for team in teams
+    div#matches-column.col-md-6
+      button.btn.btn-warning.pull-right.rank-button(data-session-id=team.session.id)
+        span.unavailable.hidden No New Code to Rank
+        span.rank.hidden Rank My Game!
+        span.ranking.hidden Submitting...
+        span.ranked.hidden Submitted for Ranking
+        span.failed.hidden Failed to Rank
+      
+      hr.clearfix(style="clear: both")
+
+      if matches.length
+        table.table.table-bordered.table-condensed
+          tr
+            th Result
+            th Opponent
+            th When
+          for match in matches
+            tr
+              td.state-cell
+                if match.state === 'win'
+                  span.win Win
+                if match.state === 'loss'
+                  span.loss Loss
+                if match.state === 'tie'
+                  span.tie Tie
+              td.name-cell= match.opponentName || "Anonymous"
+              td.time-cell= match.when
+              td.battle-cell
+                - var text = match.state === 'win' ? 'Watch your victory' : 'Defeat the ' + otherTeamID
+                a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{match.sessionID}")= text
+      
+      else
+        div.alert.alert-warning
+          | No ranked matches played yet!
+          | Play some competitors on the right and then come back to get your game ranked.
+      
diff --git a/app/views/play/ladder/ladder_tab.coffee b/app/views/play/ladder/ladder_tab.coffee
new file mode 100644
index 000000000..f7d22f98f
--- /dev/null
+++ b/app/views/play/ladder/ladder_tab.coffee
@@ -0,0 +1,97 @@
+CocoView = require 'views/kinds/CocoView'
+Level = require 'models/Level'
+LevelSession = require 'models/LevelSession'
+CocoCollection = require 'models/CocoCollection'
+LeaderboardCollection  = require 'collections/LeaderboardCollection'
+{teamDataFromLevel} = require './utils'
+
+HIGHEST_SCORE = 1000000
+
+class LevelSessionsCollection extends CocoCollection
+  url: ''
+  model: LevelSession
+
+  constructor: (levelID) ->
+    super()
+    @url = "/db/level/#{levelID}/all_sessions"
+
+module.exports = class LadderView extends CocoView
+  id: 'ladder-tab-view'
+  template: require 'templates/play/ladder/ladder_tab'
+  startsLoading: true
+
+  constructor: (options, @level, @sessions) ->
+    super(options)
+    @teams = teamDataFromLevel @level
+    @leaderboards = {}
+    for team in @teams
+#      teamSession = _.find @sessions.models, (session) -> session.get('team') is team.id
+      teamSession = null
+      console.log "Team session: #{JSON.stringify teamSession}"
+      @leaderboards[team.id] = new LeaderboardData(@level, team.id, teamSession)
+      @leaderboards[team.id].once 'sync', @onLeaderboardLoaded, @
+
+  onChallengersLoaded: -> @renderMaybe()
+  onLeaderboardLoaded: -> @renderMaybe()
+
+  renderMaybe: ->
+    leaderboardModels = _.values(@leaderboards)
+    return unless _.every leaderboardModels, (loader) -> loader.loaded
+    @startsLoading = false
+    @render()
+
+  getRenderData: ->
+    ctx = super()
+    ctx.level = @level
+    ctx.link = "/play/level/#{@level.get('name')}"
+    ctx.teams = @teams
+    team.leaderboard = @leaderboards[team.id] for team in @teams
+    ctx.levelID = @levelID
+    ctx
+    
+class LeaderboardData
+  constructor: (@level, @team, @session) ->
+    _.extend @, Backbone.Events
+    @topPlayers = new LeaderboardCollection(@level, {order:-1, scoreOffset: HIGHEST_SCORE, team: @team, limit: if @session then 10 else 20})
+    @topPlayers.fetch()
+    @topPlayers.comparator = (model) ->
+      return -model.get('totalScore')
+    @topPlayers.sort()
+
+    @topPlayers.once 'sync', @leaderboardPartLoaded, @
+
+#    if @session
+#      score = @session.get('totalScore') or 25
+#      @playersAbove = new LeaderboardCollection(@level, {order:1, scoreOffset: score, limit: 4, team: @team})
+#      @playersAbove.fetch()
+#      @playersAbove.once 'sync', @leaderboardPartLoaded, @
+#      @playersBelow = new LeaderboardCollection(@level, {order:-1, scoreOffset: score, limit: 4, team: @team})
+#      @playersBelow.fetch()
+#      @playersBelow.once 'sync', @leaderboardPartLoaded, @
+
+  leaderboardPartLoaded: ->
+    if @session
+      if @topPlayers.loaded # and @playersAbove.loaded and @playersBelow.loaded
+        @loaded = true
+        @fetchNames()
+    else
+      @loaded = true
+      @fetchNames()
+
+  fetchNames: ->
+    sessionCollections = [@topPlayers, @playersAbove, @playersBelow]
+    sessionCollections = (s for s in sessionCollections when s)
+    ids = []
+    for collection in sessionCollections
+      ids.push model.get('creator') for model in collection.models
+
+    success = (nameMap) =>
+      for collection in sessionCollections
+        session.set('creatorName', nameMap[session.get('creator')]) for session in collection.models
+      @trigger 'sync'
+
+    $.ajax('/db/user/-/names', {
+      data: {ids: ids}
+      type: 'POST'
+      success: success
+    })
diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
new file mode 100644
index 000000000..3a4859c83
--- /dev/null
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -0,0 +1,101 @@
+CocoView = require 'views/kinds/CocoView'
+Level = require 'models/Level'
+LevelSession = require 'models/LevelSession'
+LeaderboardCollection  = require 'collections/LeaderboardCollection'
+{teamDataFromLevel} = require './utils'
+
+module.exports = class LadderTeamView extends CocoView
+  id: 'ladder-team-view'
+  template: require 'templates/play/ladder/team'
+  startsLoading: true
+
+  events:
+    'click #rank-button': 'rankSession'
+
+  constructor: (options, @level, @sessions) ->
+    super(options)
+    @teams = teamDataFromLevel @level
+    @loadNames()
+
+  loadNames: ->
+    ids = []
+    for session in @sessions.models
+      ids.push match.opponents[0].userID for match in session.get('matches') or []
+
+    success = (@nameMap) =>
+      for match in @session.get('matches') or []
+        opponent = match.opponents[0]
+        opponent.userName = @nameMap[opponent.userID]
+      @finishRendering()
+
+    $.ajax('/db/user/-/names', {
+      data: {ids: ids}
+      type: 'POST'
+      success: success
+    })
+
+  finishRendering: ->
+    @startsLoading = false
+    @render()
+
+  getRenderData: ->
+    ctx = super()
+    ctx.level = @level
+    ctx.levelID = @level.get('slug') or @level.id
+    ctx.teams = @teams
+
+    convertMatch = (match) =>
+      opponent = match.opponents[0]
+      state = 'win'
+      state = 'loss' if match.metrics.rank > opponent.metrics.rank
+      state = 'tie' if match.metrics.rank is opponent.metrics.rank
+      {
+        state: state
+        opponentName: @nameMap[opponent.userID]
+        opponentID: opponent.userID
+        when: moment(match.date).fromNow()
+        sessionID: opponent.sessionID
+      }
+
+    for team in @teams
+      team.session = (s for s in @sessions.models when s.get('team') is team.id)[0]
+      team.readyToRank = @readyToRank(team.session)
+      team.matches = (convertMatch(match) for match in team.session.get('matches') or [])
+      team.matches.reverse()
+      team.score = (team.session.get('totalScore') or 10).toFixed(2)
+      
+    ctx
+
+  afterRender: ->
+    super()
+    @$el.find('.rank-button').each (i, el) =>
+      sessionID = button.data('session-id')
+      session = _.find @sessions.models, { id: sessionID }
+      @setRankingButtonText $(el), if @readyToRank(session) then 'rank' else 'unavailable'
+
+  readyToRank: (session) ->
+    c1 = session.get('code')
+    c2 = session.get('submittedCode')
+    c1 and not _.isEqual(c1, c2)
+
+  rankSession: (e) ->
+    button = $(e.target).closest('.rank-button')
+    sessionID = button.data('session-id')
+    session = _.find @sessions.models, { id: sessionID }
+    return unless @readyToRank(session)
+
+    @setRankingButtonText(button, 'ranking')
+    success = => @setRankingButtonText(button, 'ranked')
+    failure = => @setRankingButtonText(button, 'failed')
+
+    $.ajax '/queue/scoring', {
+      type: 'POST'
+      data: { session: sessionID }
+      success: success
+      failure: failure
+    }
+
+  setRankingButtonText: (rankButton, spanClass) ->
+    rankButton.find('span').addClass('hidden')
+    rankButton.find(".#{spanClass}").removeClass('hidden')
+    rankButton.toggleClass 'disabled', spanClass isnt 'rank'
diff --git a/app/views/play/ladder/utils.coffee b/app/views/play/ladder/utils.coffee
new file mode 100644
index 000000000..17667cbd2
--- /dev/null
+++ b/app/views/play/ladder/utils.coffee
@@ -0,0 +1,23 @@
+{hslToHex} = require 'lib/utils'
+
+module.exports.teamDataFromLevel = (level) ->
+  alliedSystem = _.find level.get('systems'), (value) -> value.config?.teams?
+  teamNames = (teamName for teamName, teamConfig of alliedSystem.config.teams when teamConfig.playable)
+  teamConfigs = alliedSystem.config.teams
+
+  teams = []
+  for team in teamNames or []
+    otherTeam = if team is 'ogres' then 'humans' else 'ogres'
+    color = teamConfigs[team].color
+    bgColor = hslToHex([color.hue, color.saturation, color.lightness + (1 - color.lightness) * 0.5])
+    primaryColor = hslToHex([color.hue, 0.5, 0.5])
+    teams.push({
+      id: team
+      name: _.string.titleize(team)
+      otherTeam: otherTeam
+      bgColor: bgColor
+      primaryColor: primaryColor
+    })
+
+  console.log 'created teams', teams
+  teams
\ No newline at end of file
diff --git a/app/views/play/ladder_view.coffee b/app/views/play/ladder_view.coffee
index 0ff4e6717..c331816b7 100644
--- a/app/views/play/ladder_view.coffee
+++ b/app/views/play/ladder_view.coffee
@@ -4,7 +4,8 @@ Simulator = require 'lib/simulator/Simulator'
 LevelSession = require 'models/LevelSession'
 CocoCollection = require 'models/CocoCollection'
 LeaderboardCollection  = require 'collections/LeaderboardCollection'
-{hslToHex} = require 'lib/utils'
+{teamDataFromLevel} = require './ladder/utils'
+LadderTabView = require './ladder/ladder_tab'
 
 HIGHEST_SCORE = 1000000
 
@@ -25,8 +26,48 @@ module.exports = class LadderView extends RootView
     'click #simulate-button': 'onSimulateButtonClick'
     'click #simulate-all-button': 'onSimulateAllButtonClick'
 
+  constructor: (options, @levelID) ->
+    super(options)
+    @level = new Level(_id:@levelID)
+    @level.fetch()
+    @level.once 'sync', @onLevelLoaded, @
+    #    @sessions = new LevelSessionsCollection(levelID)
+    #    @sessions.fetch({})
+    #    @sessions.once 'sync', @onMySessionsLoaded, @
+    @simulator = new Simulator()
+    @simulator.on 'statusUpdate', @updateSimulationStatus, @
+    @teams = []
+
+  onLevelLoaded: -> @renderMaybe()
+  onMySessionsLoaded: -> @renderMaybe()
+
+  renderMaybe: ->
+    return unless @level.loaded # and @sessions.loaded
+    @teams = teamDataFromLevel @level
+    console.log 'made teams', @teams
+    @startsLoading = false
+    @render()
+
+  getRenderData: ->
+    ctx = super()
+    ctx.level = @level
+    ctx.link = "/play/level/#{@level.get('name')}"
+    ctx.simulationStatus = @simulationStatus
+    ctx.teams = @teams
+    console.log 'ctx teams', ctx.teams
+    ctx.levelID = @levelID
+    ctx
+
+  afterRender: ->
+    super()
+    return if @startsLoading
+    @ladderTab = new LadderTabView({}, @level, @sessions)
+    @insertSubView(@ladderTab)
+
+  # Simulations
+
   onSimulateAllButtonClick: (e) ->
-    submitIDs = _.pluck @leaderboards[@teams[0]].topPlayers.models, "id"
+    submitIDs = _.pluck @leaderboards[@teams[0].id].topPlayers.models, "id"
     for ID in submitIDs
       $.ajax
         url: '/queue/scoring'
@@ -57,141 +98,3 @@ module.exports = class LadderView extends RootView
     catch e
       console.log "There was a problem with the named simulation status: #{e}"
     $("#simulation-status-text").text @simulationStatus
-
-
-  constructor: (options, @levelID) ->
-    super(options)
-    @level = new Level(_id:@levelID)
-    @level.fetch()
-    @level.once 'sync', @onLevelLoaded, @
-    @simulator = new Simulator()
-    @simulator.on 'statusUpdate', @updateSimulationStatus, @
-
-#    @sessions = new LevelSessionsCollection(levelID)
-#    @sessions.fetch({})
-#    @sessions.once 'sync', @onMySessionsLoaded, @
-
-  onLevelLoaded: -> @startLoadingPhaseTwoMaybe()
-  onMySessionsLoaded: ->
-    @startLoadingPhaseTwoMaybe()
-
-  startLoadingPhaseTwoMaybe: ->
-    return unless @level.loaded # and @sessions.loaded
-    @loadPhaseTwo()
-
-  loadPhaseTwo: ->
-    alliedSystem = _.find @level.get('systems'), (value) -> value.config?.teams?
-    teams = []
-    for teamName, teamConfig of alliedSystem.config.teams
-      continue unless teamConfig.playable
-      teams.push teamName
-    @teams = teams
-    @teamConfigs = alliedSystem.config.teams
-
-    @leaderboards = {}
-    @challengers = {}
-    for team in teams
-#      teamSession = _.find @sessions.models, (session) -> session.get('team') is team
-      teamSession = null
-      console.log "Team session: #{JSON.stringify teamSession}"
-      @leaderboards[team] = new LeaderboardData(@level, team, teamSession)
-      @leaderboards[team].once 'sync', @onLeaderboardLoaded, @
-
-  onChallengersLoaded: -> @renderMaybe()
-  onLeaderboardLoaded: -> @renderMaybe()
-
-  renderMaybe: ->
-    loaders = _.values(@leaderboards) # .concat(_.values(@challengers))
-    return unless _.every loaders, (loader) -> loader.loaded
-    @startsLoading = false
-    @render()
-
-  getRenderData: ->
-    ctx = super()
-    ctx.level = @level
-    description = @level.get('description')
-    ctx.description = if description then marked(description) else ''
-    ctx.link = "/play/level/#{@level.get('name')}"
-    ctx.simulationStatus = @simulationStatus
-    ctx.teams = []
-    ctx.levelID = @levelID
-    for team in @teams or []
-      otherTeam = if team is 'ogres' then 'humans' else 'ogres'
-      color = @teamConfigs[team].color
-      bgColor = hslToHex([color.hue, color.saturation, color.lightness + (1 - color.lightness) * 0.5])
-      primaryColor = hslToHex([color.hue, 0.5, 0.5])
-      ctx.teams.push({
-        id: team
-        name: _.string.titleize(team)
-        leaderboard: @leaderboards[team]
-        otherTeam: otherTeam
-        bgColor: bgColor
-        primaryColor: primaryColor
-      })
-    ctx
-
-class LeaderboardData
-  constructor: (@level, @team, @session) ->
-    _.extend @, Backbone.Events
-    @topPlayers = new LeaderboardCollection(@level, {order:-1, scoreOffset: HIGHEST_SCORE, team: @team, limit: if @session then 10 else 20})
-    @topPlayers.fetch()
-    @topPlayers.comparator = (model) ->
-      return -model.get('totalScore')
-    @topPlayers.sort()
-
-    @topPlayers.once 'sync', @leaderboardPartLoaded, @
-
-#    if @session
-#      score = @session.get('totalScore') or 25
-#      @playersAbove = new LeaderboardCollection(@level, {order:1, scoreOffset: score, limit: 4, team: @team})
-#      @playersAbove.fetch()
-#      @playersAbove.once 'sync', @leaderboardPartLoaded, @
-#      @playersBelow = new LeaderboardCollection(@level, {order:-1, scoreOffset: score, limit: 4, team: @team})
-#      @playersBelow.fetch()
-#      @playersBelow.once 'sync', @leaderboardPartLoaded, @
-
-  leaderboardPartLoaded: ->
-    if @session
-      if @topPlayers.loaded # and @playersAbove.loaded and @playersBelow.loaded
-        @loaded = true
-        @fetchNames()
-    else
-      @loaded = true
-      @fetchNames()
-
-  fetchNames: ->
-    sessionCollections = [@topPlayers, @playersAbove, @playersBelow]
-    sessionCollections = (s for s in sessionCollections when s)
-    ids = []
-    for collection in sessionCollections
-      ids.push model.get('creator') for model in collection.models
-
-    success = (nameMap) =>
-      for collection in sessionCollections
-        session.set('creatorName', nameMap[session.get('creator')]) for session in collection.models
-      @trigger 'sync'
-
-    $.ajax('/db/user/-/names', {
-      data: {ids: ids}
-      type: 'POST'
-      success: success
-    })
-
-class ChallengersData
-  constructor: (@level, @team, @session) ->
-    _.extend @, Backbone.Events
-    score = @session?.get('totalScore') or 25
-    @easyPlayer = new LeaderboardCollection(@level, {order:1, scoreOffset: score - 5, limit: 1, team: @team})
-    @easyPlayer.fetch()
-    @easyPlayer.once 'sync', @challengerLoaded, @
-    @mediumPlayer = new LeaderboardCollection(@level, {order:1, scoreOffset: score, limit: 1, team: @team})
-    @mediumPlayer.fetch()
-    @mediumPlayer.once 'sync', @challengerLoaded, @
-    @hardPlayer = new LeaderboardCollection(@level, {order:-1, scoreOffset: score + 5, limit: 1, team: @team})
-    @hardPlayer.fetch()
-    @hardPlayer.once 'sync', @challengerLoaded, @
-
-  challengerLoaded: ->
-    if @easyPlayer.loaded and @mediumPlayer.loaded and @hardPlayer.loaded
-      @loaded = true
-      @trigger 'sync'

From 956e2b3c40f94c577f6ca7d7892a3d729dab3097 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Sun, 2 Mar 2014 13:24:41 -0800
Subject: [PATCH 019/178] Set up the my matches tab in the new ladder view.

---
 app/templates/play/ladder.jade                |  2 +-
 app/templates/play/ladder/my_matches_tab.jade | 35 +++++++++++--------
 app/views/play/ladder/ladder_tab.coffee       |  2 +-
 app/views/play/ladder/my_matches_tab.coffee   | 19 +++++-----
 app/views/play/ladder/utils.coffee            |  1 -
 app/views/play/ladder_view.coffee             | 17 +++++----
 server/levels/level_handler.coffee            | 19 +++-------
 7 files changed, 46 insertions(+), 49 deletions(-)

diff --git a/app/templates/play/ladder.jade b/app/templates/play/ladder.jade
index 9e03f5f3c..4d056ce97 100644
--- a/app/templates/play/ladder.jade
+++ b/app/templates/play/ladder.jade
@@ -39,7 +39,7 @@ block content
       .tab-pane.active.well#ladder
         #ladder-tab-view
       .tab-pane.well#my-matches
-        | My Matches Pane
+        #my-matches-tab-view
       .tab-pane.well#simulate
         p(id="simulation-status-text")
           if simulationStatus
diff --git a/app/templates/play/ladder/my_matches_tab.jade b/app/templates/play/ladder/my_matches_tab.jade
index d07432a83..b9af08530 100644
--- a/app/templates/play/ladder/my_matches_tab.jade
+++ b/app/templates/play/ladder/my_matches_tab.jade
@@ -4,26 +4,33 @@
 //    span  
 //    strong= score
 
-h3.pull-left Ranked Games
 div#columns.row
   for team in teams
-    div#matches-column.col-md-6
-      button.btn.btn-warning.pull-right.rank-button(data-session-id=team.session.id)
-        span.unavailable.hidden No New Code to Rank
-        span.rank.hidden Rank My Game!
-        span.ranking.hidden Submitting...
-        span.ranked.hidden Submitted for Ranking
-        span.failed.hidden Failed to Rank
-      
-      hr.clearfix(style="clear: both")
-
-      if matches.length
+    div.matches-column.col-md-6
+      if team.matches.length
         table.table.table-bordered.table-condensed
+
+          tr
+            th(colspan=4, style="color: #{team.primaryColor}")
+              span Your
+              span  
+              span= team.name
+              span  
+              span Matches
+
+              button.btn.btn-sm.btn-warning.pull-right.rank-button(data-session-id=team.session.id)
+                span.unavailable.hidden No New Code to Rank
+                span.rank.hidden Rank My Game!
+                span.ranking.hidden Submitting...
+                span.ranked.hidden Submitted for Ranking
+                span.failed.hidden Failed to Rank
+
           tr
             th Result
             th Opponent
             th When
-          for match in matches
+            th
+          for match in team.matches
             tr
               td.state-cell
                 if match.state === 'win'
@@ -35,7 +42,7 @@ div#columns.row
               td.name-cell= match.opponentName || "Anonymous"
               td.time-cell= match.when
               td.battle-cell
-                - var text = match.state === 'win' ? 'Watch your victory' : 'Defeat the ' + otherTeamID
+                - var text = match.state === 'win' ? 'Watch your victory' : 'Defeat the ' + team.otherTeam
                 a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{match.sessionID}")= text
       
       else
diff --git a/app/views/play/ladder/ladder_tab.coffee b/app/views/play/ladder/ladder_tab.coffee
index f7d22f98f..96e268e3c 100644
--- a/app/views/play/ladder/ladder_tab.coffee
+++ b/app/views/play/ladder/ladder_tab.coffee
@@ -27,7 +27,7 @@ module.exports = class LadderView extends CocoView
     for team in @teams
 #      teamSession = _.find @sessions.models, (session) -> session.get('team') is team.id
       teamSession = null
-      console.log "Team session: #{JSON.stringify teamSession}"
+#      console.log "Team session: #{JSON.stringify teamSession}"
       @leaderboards[team.id] = new LeaderboardData(@level, team.id, teamSession)
       @leaderboards[team.id].once 'sync', @onLeaderboardLoaded, @
 
diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
index 3a4859c83..110a289db 100644
--- a/app/views/play/ladder/my_matches_tab.coffee
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -4,17 +4,18 @@ LevelSession = require 'models/LevelSession'
 LeaderboardCollection  = require 'collections/LeaderboardCollection'
 {teamDataFromLevel} = require './utils'
 
-module.exports = class LadderTeamView extends CocoView
-  id: 'ladder-team-view'
-  template: require 'templates/play/ladder/team'
+module.exports = class MyMatchesTabView extends CocoView
+  id: 'my-matches-tab-view'
+  template: require 'templates/play/ladder/my_matches_tab'
   startsLoading: true
 
   events:
-    'click #rank-button': 'rankSession'
+    'click .rank-button': 'rankSession'
 
   constructor: (options, @level, @sessions) ->
     super(options)
     @teams = teamDataFromLevel @level
+    @nameMap = {}
     @loadNames()
 
   loadNames: ->
@@ -23,9 +24,10 @@ module.exports = class LadderTeamView extends CocoView
       ids.push match.opponents[0].userID for match in session.get('matches') or []
 
     success = (@nameMap) =>
-      for match in @session.get('matches') or []
-        opponent = match.opponents[0]
-        opponent.userName = @nameMap[opponent.userID]
+      for session in @sessions.models
+        for match in session.get('matches') or []
+          opponent = match.opponents[0]
+          opponent.userName = @nameMap[opponent.userID]
       @finishRendering()
 
     $.ajax('/db/user/-/names', {
@@ -69,9 +71,10 @@ module.exports = class LadderTeamView extends CocoView
   afterRender: ->
     super()
     @$el.find('.rank-button').each (i, el) =>
+      button = $(el)
       sessionID = button.data('session-id')
       session = _.find @sessions.models, { id: sessionID }
-      @setRankingButtonText $(el), if @readyToRank(session) then 'rank' else 'unavailable'
+      @setRankingButtonText button, if @readyToRank(session) then 'rank' else 'unavailable'
 
   readyToRank: (session) ->
     c1 = session.get('code')
diff --git a/app/views/play/ladder/utils.coffee b/app/views/play/ladder/utils.coffee
index 17667cbd2..10f088093 100644
--- a/app/views/play/ladder/utils.coffee
+++ b/app/views/play/ladder/utils.coffee
@@ -19,5 +19,4 @@ module.exports.teamDataFromLevel = (level) ->
       primaryColor: primaryColor
     })
 
-  console.log 'created teams', teams
   teams
\ No newline at end of file
diff --git a/app/views/play/ladder_view.coffee b/app/views/play/ladder_view.coffee
index c331816b7..25d15f484 100644
--- a/app/views/play/ladder_view.coffee
+++ b/app/views/play/ladder_view.coffee
@@ -6,6 +6,7 @@ CocoCollection = require 'models/CocoCollection'
 LeaderboardCollection  = require 'collections/LeaderboardCollection'
 {teamDataFromLevel} = require './ladder/utils'
 LadderTabView = require './ladder/ladder_tab'
+MyMatchesTabView = require './ladder/my_matches_tab'
 
 HIGHEST_SCORE = 1000000
 
@@ -15,7 +16,7 @@ class LevelSessionsCollection extends CocoCollection
 
   constructor: (levelID) ->
     super()
-    @url = "/db/level/#{levelID}/all_sessions"
+    @url = "/db/level/#{levelID}/my_sessions"
 
 module.exports = class LadderView extends RootView
   id: 'ladder-view'
@@ -31,9 +32,9 @@ module.exports = class LadderView extends RootView
     @level = new Level(_id:@levelID)
     @level.fetch()
     @level.once 'sync', @onLevelLoaded, @
-    #    @sessions = new LevelSessionsCollection(levelID)
-    #    @sessions.fetch({})
-    #    @sessions.once 'sync', @onMySessionsLoaded, @
+    @sessions = new LevelSessionsCollection(levelID)
+    @sessions.fetch({})
+    @sessions.once 'sync', @onMySessionsLoaded, @
     @simulator = new Simulator()
     @simulator.on 'statusUpdate', @updateSimulationStatus, @
     @teams = []
@@ -42,9 +43,8 @@ module.exports = class LadderView extends RootView
   onMySessionsLoaded: -> @renderMaybe()
 
   renderMaybe: ->
-    return unless @level.loaded # and @sessions.loaded
+    return unless @level.loaded and @sessions.loaded
     @teams = teamDataFromLevel @level
-    console.log 'made teams', @teams
     @startsLoading = false
     @render()
 
@@ -54,15 +54,14 @@ module.exports = class LadderView extends RootView
     ctx.link = "/play/level/#{@level.get('name')}"
     ctx.simulationStatus = @simulationStatus
     ctx.teams = @teams
-    console.log 'ctx teams', ctx.teams
     ctx.levelID = @levelID
     ctx
 
   afterRender: ->
     super()
     return if @startsLoading
-    @ladderTab = new LadderTabView({}, @level, @sessions)
-    @insertSubView(@ladderTab)
+    @insertSubView(@ladderTab = new LadderTabView({}, @level, @sessions))
+    @insertSubView(@myMatchesTab = new MyMatchesTabView({}, @level, @sessions))
 
   # Simulations
 
diff --git a/server/levels/level_handler.coffee b/server/levels/level_handler.coffee
index b26e729bd..0cf0a2066 100644
--- a/server/levels/level_handler.coffee
+++ b/server/levels/level_handler.coffee
@@ -27,7 +27,7 @@ LevelHandler = class LevelHandler extends Handler
   getByRelationship: (req, res, args...) ->
     return @getSession(req, res, args[0]) if args[1] is 'session'
     return @getLeaderboard(req, res, args[0]) if args[1] is 'leaderboard'
-    return @getAllSessions(req, res, args[0]) if args[1] is 'all_sessions'
+    return @getMySessions(req, res, args[0]) if args[1] is 'my_sessions'
     return @getFeedback(req, res, args[0]) if args[1] is 'feedback'
     return @sendNotFoundError(res)
 
@@ -86,26 +86,15 @@ LevelHandler = class LevelHandler extends Handler
       # associated with the handler, because the handler might return a different type
       # of model, like in this case. Refactor to move that logic to the model instead.
 
-  getAllSessions: (req, res, id) ->
+  getMySessions: (req, res, id) ->
     @fetchLevelByIDAndHandleErrors id, req, res, (err, level) =>
       sessionQuery =
         level:
           original: level.original.toString()
           majorVersion: level.version.major
-        submitted: true
-
-      propertiesToReturn = [
-        '_id'
-        'totalScore'
-        'submitted'
-        'team'
-        'creatorName'
-      ]
-
-      query = Session
-        .find(sessionQuery)
-        .select(propertiesToReturn.join ' ')
+        creator: req.user._id+''
 
+      query = Session.find(sessionQuery)
       query.exec (err, results) =>
         if err then @sendDatabaseError(res, err) else @sendSuccess res, results
 

From bea002a8d49856e9f6a2e41e5db2a5aef1bf212f Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <ruben.vereecken@student.uantwerpen.be>
Date: Sun, 2 Mar 2014 22:59:15 +0100
Subject: [PATCH 020/178] Fixed some wrong translations

---
 app/locale/nl.coffee | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/app/locale/nl.coffee b/app/locale/nl.coffee
index 57a366206..9182c54db 100644
--- a/app/locale/nl.coffee
+++ b/app/locale/nl.coffee
@@ -8,7 +8,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     delay_1_sec: "1 seconde"
     delay_3_sec: "3 secondes"
     delay_5_sec: "5 secondes"
-    manual: "Handboek"
+    manual: "Handmatig"
     fork: "Fork"
     play: "Spelen"
 
@@ -215,11 +215,11 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     main_title: "CodeCombat Editors"
     main_description: "Maak je eigen levels, campagnes, eenheden en leermateriaal. Wij bieden alle programma's aan die u nodig heeft!"
     article_title: "Artikel Editor"
-    article_description: "Schrijf artikels dat spelers een overzicht geven over programmeer concepten die kunnen gebruikt worden over een variëteit van levels en campagnes."
+    article_description: "Schrijf artikels die spelers een overzicht geven over programmeer concepten die kunnen gebruikt worden over een variëteit van levels en campagnes."
     thang_title: "Thang Editor"
-    thang_description: "Maak eenheden, beschrijf hun default logica, graphics en audio. Momenteel is enkel het importeren van vector graphics geëxporteerd in Flash ondersteund."
+    thang_description: "Maak eenheden, beschrijf hun standaard logica, graphics en audio. Momenteel is enkel het importeren van vector graphics geëxporteerd in Flash ondersteund."
     level_title: "Level Editor"
-    level_description: "Bevat het programma om te programmeren, audio te uploaden en aangepaste logica om alle soorten levels te maken. Het is alles wat wijzelf ook gebruiken!"
+    level_description: "Bevat het programma om te programmeren, audio te uploaden en aangepaste logica te creëren om alle soorten levels te maken. Het is alles wat wijzelf ook gebruiken!"
     security_notice: "Veel belangrijke elementen in deze editors zijn momenteel niet actief. Met dat wij de veiligheid van deze systemen verbeteren, zullen ook deze elementen beschikbaar worden. Indien u deze elementen al eerder wil gebruiken, "
     contact_us: "contacteer ons!"
     hipchat_prefix: "Je kan ons ook vinden in ons"

From c3c699df490ecd8cf2d78115c7d64eb28d4e9c16 Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <ruben.vereecken@student.uantwerpen.be>
Date: Sun, 2 Mar 2014 23:28:16 +0100
Subject: [PATCH 021/178] Fixed wrong i18n name 'account_settings.autosave'.
 Added missing i18n name 'account_settings.email_notifications'

---
 app/locale/en.coffee                | 1 +
 app/locale/nl.coffee                | 3 ++-
 app/templates/account/settings.jade | 2 +-
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index 63b228460..d72b872cd 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -130,6 +130,7 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
     new_password_verify: "Verify"
     email_subscriptions: "Email Subscriptions"
     email_announcements: "Announcements"
+    email_notifications: "Notifications"
     email_notifications_description: "Get periodic notifications for your account."
     email_announcements_description: "Get emails on the latest news and developments at CodeCombat."
     contributor_emails: "Contributor Class Emails"
diff --git a/app/locale/nl.coffee b/app/locale/nl.coffee
index 9182c54db..8e762eaeb 100644
--- a/app/locale/nl.coffee
+++ b/app/locale/nl.coffee
@@ -116,7 +116,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
   account_settings:
     title: "Account Instellingen"
     not_logged_in: "Log in of maak een account om je instellingen aan te passen."
-    autosave: "Aanpassingen Worden Automatisch Opgeslagen"
+    autosave: "Aanpassingen Automatisch Opgeslagen"
     me_tab: "Ik"
     picture_tab: "Afbeelding"
     wizard_tab: "Tovenaar"
@@ -130,6 +130,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     new_password_verify: "Verifieer"
     email_subscriptions: "E-mail Abonnementen"
     email_announcements: "Aankondigingen"
+    email_notifications: "Notificaties"
     email_notifications_description: "Krijg periodieke meldingen voor jouw account."
     email_announcements_description: "Verkrijg emails over het laatste nieuws en de ontwikkelingen bij CodeCombat."
     contributor_emails: "Medewerker Klasse emails"
diff --git a/app/templates/account/settings.jade b/app/templates/account/settings.jade
index bae178865..d64936645 100644
--- a/app/templates/account/settings.jade
+++ b/app/templates/account/settings.jade
@@ -8,7 +8,7 @@ block content
     p(data-i18n="account_settings.not_logged_in") Log in or create an account to change your settings.
 
   else
-    button.btn#save-button.disabled.secret(data-i18n="account_settings.saveBackups") Changes Save Automatically
+    button.btn#save-button.disabled.secret(data-i18n="account_settings.autosave") Changes Save Automatically
   
     ul.nav.nav-pills#settings-tabs
       li

From c2d247e686d0709bca5b280f638d511cb9a2f627 Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <ruben.vereecken@student.uantwerpen.be>
Date: Mon, 3 Mar 2014 00:31:49 +0100
Subject: [PATCH 022/178] Editor tables now load i18n correctly after search.

---
 app/views/kinds/SearchView.coffee | 1 +
 1 file changed, 1 insertion(+)

diff --git a/app/views/kinds/SearchView.coffee b/app/views/kinds/SearchView.coffee
index e89d080e4..18648e386 100644
--- a/app/views/kinds/SearchView.coffee
+++ b/app/views/kinds/SearchView.coffee
@@ -77,6 +77,7 @@ module.exports = class ThangTypeHomeView extends View
     documents = @collection.models
     table = $(@tableTemplate(documents:documents))
     @$el.find('table').replaceWith(table)
+    @$el.find('table').i18n()
 
   removeOldSearch: ->
     return unless @collection?

From a8ef87c9ea0255e3c28e6c79f716f70d40778fc8 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 2 Mar 2014 16:06:22 -0800
Subject: [PATCH 023/178] Fixed a few bugs; re-enabled protectAPI for
 Brawlwood.

---
 app/lib/God.coffee                         |  6 +++---
 app/templates/editor/level/save.jade       |  4 ----
 app/templates/modal/save_version.jade      | 16 +++++++++-------
 app/views/editor/article/edit.coffee       |  2 +-
 app/views/editor/level/save_view.coffee    |  2 +-
 app/views/play/level/tome/tome_view.coffee |  2 +-
 6 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/app/lib/God.coffee b/app/lib/God.coffee
index 3f80500bf..ff92f7e31 100644
--- a/app/lib/God.coffee
+++ b/app/lib/God.coffee
@@ -194,8 +194,8 @@ class Angel
     @ids[@lastID]
 
   # https://github.com/codecombat/codecombat/issues/81 -- TODO: we need to wait for worker initialization first
-  infiniteLoopIntervalDuration: 5000  # check this often (must be more than the others added)
-  infiniteLoopTimeoutDuration: 1500  # wait this long when we check
+  infiniteLoopIntervalDuration: 7500  # check this often (must be more than the others added)
+  infiniteLoopTimeoutDuration: 2500  # wait this long when we check
   abortTimeoutDuration: 500  # give in-process or dying workers this long to give up
   constructor: (@god) ->
     @id = Angel.nextID()
@@ -227,7 +227,7 @@ class Angel
       _.delay ->
         worker.terminate()
         worker.removeEventListener 'message', onWorkerMessage
-      , 1000
+      , 2000
       @worker = null
     @
 
diff --git a/app/templates/editor/level/save.jade b/app/templates/editor/level/save.jade
index 00e9e43f2..8ada52b23 100644
--- a/app/templates/editor/level/save.jade
+++ b/app/templates/editor/level/save.jade
@@ -52,7 +52,3 @@ block modal-body-content
           label.control-label(for=id + "-version-is-major") Major Changes?
           input(id=id + "-version-is-major", name="version-is-major", type="checkbox")
           span.help-block (Could this update break anything depending on this System?)
-
-if noSaveButton
-  block modal-footer-content
-    button.btn(data-dismiss="modal", data-i18n="common.cancel") Cancel
diff --git a/app/templates/modal/save_version.jade b/app/templates/modal/save_version.jade
index 3c6a35f48..d1f8fc219 100644
--- a/app/templates/modal/save_version.jade
+++ b/app/templates/modal/save_version.jade
@@ -17,12 +17,14 @@ block modal-body-wait-content
   h3(data-i18n="common.saving") Saving...
 
 block modal-footer-content
-  #accept-cla-wrapper.alert.alert-info
-    span(data-i18n="versions.cla_prefix") To save changes, first you must agree to our
-    |  
-    strong#cla-link(data-i18n="versions.cla_url") CLA
-    span(data-i18n="versions.cla_suffix") .
-    button.btn#agreement-button(data-i18n="versions.cla_agree") I AGREE
+  if !noSaveButton
+    #accept-cla-wrapper.alert.alert-info
+      span(data-i18n="versions.cla_prefix") To save changes, first you must agree to our
+      |  
+      strong#cla-link(data-i18n="versions.cla_url") CLA
+      span(data-i18n="versions.cla_suffix") .
+      button.btn#agreement-button(data-i18n="versions.cla_agree") I AGREE
     
   button.btn(data-dismiss="modal", data-i18n="common.cancel") Cancel
-  button.btn.btn-primary#save-version-button(data-i18n="common.save") Save
+  if !noSaveButton
+    button.btn.btn-primary#save-version-button(data-i18n="common.save") Save
diff --git a/app/views/editor/article/edit.coffee b/app/views/editor/article/edit.coffee
index 05df5291d..7a2894a09 100644
--- a/app/views/editor/article/edit.coffee
+++ b/app/views/editor/article/edit.coffee
@@ -59,7 +59,7 @@ module.exports = class ArticleEditView extends View
     context
 
   openPreview: =>
-    @preview = window.open('http://localhost:3000/editor/article/x/preview', 'preview', 'height=800,width=600')
+    @preview = window.open('/editor/article/x/preview', 'preview', 'height=800,width=600')
     @preview.focus() if window.focus
     @preview.onload = => @pushChangesToPreview()
     return false
diff --git a/app/views/editor/level/save_view.coffee b/app/views/editor/level/save_view.coffee
index 4edf03ca0..e3e5ad25c 100644
--- a/app/views/editor/level/save_view.coffee
+++ b/app/views/editor/level/save_view.coffee
@@ -23,7 +23,7 @@ module.exports = class LevelSaveView extends SaveVersionModal
     context.levelNeedsSave = @level.hasLocalChanges()
     context.modifiedComponents = _.filter @supermodel.getModels(LevelComponent), @shouldSaveEntity
     context.modifiedSystems = _.filter @supermodel.getModels(LevelSystem), @shouldSaveEntity
-    context.noSaveButton = context.levelNeedsSave or context.modifiedComponents.length or context.modifiedSystems.length
+    context.noSaveButton = not (context.levelNeedsSave or context.modifiedComponents.length or context.modifiedSystems.length)
     context
 
   shouldSaveEntity: (m) ->
diff --git a/app/views/play/level/tome/tome_view.coffee b/app/views/play/level/tome/tome_view.coffee
index 11fad104b..124e54e0f 100644
--- a/app/views/play/level/tome/tome_view.coffee
+++ b/app/views/play/level/tome/tome_view.coffee
@@ -128,7 +128,7 @@ module.exports = class TomeView extends View
         spellKey = pathComponents.join '/'
         @thangSpells[thang.id].push spellKey
         unless method.cloneOf
-          skipProtectAPI = true  #@getQueryVariable("skip_protect_api") is "true"
+          skipProtectAPI = @getQueryVariable("skip_protect_api") is "true" or @options.levelID isnt 'brawlwood'
           skipFlow = @getQueryVariable("skip_flow") is "true" or @options.levelID is 'brawlwood'
           spell = @spells[spellKey] = new Spell programmableMethod: method, spellKey: spellKey, pathComponents: pathPrefixComponents.concat(pathComponents), session: @options.session, supermodel: @supermodel, skipFlow: skipFlow, skipProtectAPI: skipProtectAPI, worker: @worker
     for thangID, spellKeys of @thangSpells

From 82b250b9a3e0431918b86661744735c675c5a1cc Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 2 Mar 2014 17:51:57 -0800
Subject: [PATCH 024/178] protectAPI off again for Brawlwood, too slow for now.

---
 app/views/play/level/tome/tome_view.coffee |  1 +
 server/queues/scoring.coffee               | 74 +++++++++++-----------
 2 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/app/views/play/level/tome/tome_view.coffee b/app/views/play/level/tome/tome_view.coffee
index 124e54e0f..f7be355f6 100644
--- a/app/views/play/level/tome/tome_view.coffee
+++ b/app/views/play/level/tome/tome_view.coffee
@@ -129,6 +129,7 @@ module.exports = class TomeView extends View
         @thangSpells[thang.id].push spellKey
         unless method.cloneOf
           skipProtectAPI = @getQueryVariable("skip_protect_api") is "true" or @options.levelID isnt 'brawlwood'
+          skipProtectAPI = true  # gah, it's so slow :( and somehow still affects simulation
           skipFlow = @getQueryVariable("skip_flow") is "true" or @options.levelID is 'brawlwood'
           spell = @spells[spellKey] = new Spell programmableMethod: method, spellKey: spellKey, pathComponents: pathPrefixComponents.concat(pathComponents), session: @options.session, supermodel: @supermodel, skipFlow: skipFlow, skipProtectAPI: skipProtectAPI, worker: @worker
     for thangID, spellKeys of @thangSpells
diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee
index 0079d34a8..a1119378b 100644
--- a/server/queues/scoring.coffee
+++ b/server/queues/scoring.coffee
@@ -23,13 +23,13 @@ connectToScoringQueue = ->
       if error? then throw new Error  "There was an error registering the scoring queue: #{error}"
       scoringTaskQueue = data
       log.info "Connected to scoring task queue!"
-      
+
 module.exports.addPairwiseTaskToQueueFromRequest = (req, res) ->
   taskPair = req.body.sessions
   addPairwiseTaskToQueue req.body.sessions (err, success) ->
     if err? then return errors.serverError res, "There was an error adding pairwise tasks: #{err}"
     sendResponseObject req, res, {"message":"All task pairs were succesfully sent to the queue"}
-    
+
 
 addPairwiseTaskToQueue = (taskPair, cb) ->
   LevelSession.findOne(_id:taskPair[0]).lean().exec (err, firstSession) =>
@@ -42,9 +42,9 @@ addPairwiseTaskToQueue = (taskPair, cb) ->
         if e then return cb e, false
 
       sendEachTaskPairToTheQueue taskPairs, (taskPairError) ->
-        if taskPairError? then return cb taskPairError,false 
+        if taskPairError? then return cb taskPairError,false
         cb null, true
-        
+
 
 module.exports.createNewTask = (req, res) ->
   requestSessionID = req.body.session
@@ -105,6 +105,7 @@ module.exports.processTaskResult = (req, res) ->
     return handleTimedOutTask req, res, clientResponseObject if hasTaskTimedOut taskLogJSON.sentDate
 
     scoringTaskQueue.deleteMessage clientResponseObject.receiptHandle, (err) ->
+      console.log "Deleted message."
       if err? then return errors.badInput res, "The queue message is already back in the queue, rejecting results."
 
       logTaskComputation clientResponseObject, taskLog, (logErr) ->
@@ -117,14 +118,14 @@ module.exports.processTaskResult = (req, res) ->
 
           addMatchToSessions clientResponseObject, newScoresObject, (err, data) ->
             if err? then return errors.serverError res, "There was an error updating the sessions with the match! #{JSON.stringify err}"
-              
+
             originalSessionID = clientResponseObject.originalSessionID
             originalSessionTeam = clientResponseObject.originalSessionTeam
             originalSessionRank = parseInt clientResponseObject.originalSessionRank
-            
+
             determineIfSessionShouldContinueAndUpdateLog originalSessionID, originalSessionRank, (err, sessionShouldContinue) ->
               if err? then return errors.serverError res, "There was an error determining if the session should continue, #{err}"
-                
+
               if sessionShouldContinue
                 opposingTeam = calculateOpposingTeam(originalSessionTeam)
                 opponentID = _.pull(_.keys(newScoresObject), originalSessionID)
@@ -133,7 +134,7 @@ module.exports.processTaskResult = (req, res) ->
                 findNearestBetterSessionID originalSessionID, sessionNewScore, opponentNewScore, opponentID ,opposingTeam, (err, opponentSessionID) ->
                   if err? then return errors.serverError res, "There was an error finding the nearest sessionID!"
                   unless opponentSessionID then return sendResponseObject req, res, {"message":"There were no more games to rank(game is at top!"}
-                    
+
                   addPairwiseTaskToQueue [originalSessionID, opponentSessionID], (err, success) ->
                     if err? then return errors.serverError res, "There was an error sending the pairwise tasks to the queue!"
                     sendResponseObject req, res, {"message":"The scores were updated successfully and more games were sent to the queue!"}
@@ -141,19 +142,19 @@ module.exports.processTaskResult = (req, res) ->
                 console.log "Player lost, achieved rank #{originalSessionRank}"
                 sendResponseObject req, res, {"message":"The scores were updated successfully, person lost so no more games are being inserted!"}
 
-              
+
 determineIfSessionShouldContinueAndUpdateLog = (sessionID, sessionRank, cb) ->
-  queryParameters = 
+  queryParameters =
     _id: sessionID
-  
-  updateParameters = 
+
+  updateParameters =
     "$inc": {}
-  
-  if sessionRank is 0 
+
+  if sessionRank is 0
     updateParameters["$inc"] = {numberOfWinsAndTies: 1}
   else
     updateParameters["$inc"] = {numberOfLosses: 1}
- 
+
   LevelSession.findOneAndUpdate queryParameters, updateParameters,{select: 'numberOfWinsAndTies numberOfLosses'}, (err, updatedSession) ->
     if err? then return cb err, updatedSession
     updatedSession = updatedSession.toObject()
@@ -170,16 +171,16 @@ determineIfSessionShouldContinueAndUpdateLog = (sessionID, sessionRank, cb) ->
       else
         console.log "Ratio(#{ratio}) is good, so continuing simulations"
         cb null, true
-      
-    
+
+
 findNearestBetterSessionID = (sessionID, sessionTotalScore, opponentSessionTotalScore, opponentSessionID, opposingTeam, cb) ->
   retrieveAllOpponentSessionIDs sessionID, (err, opponentSessionIDs) ->
     if err? then return cb err, null
-    
+
     queryParameters =
-      totalScore: 
+      totalScore:
         $gt:opponentSessionTotalScore
-      _id: 
+      _id:
         $nin: opponentSessionIDs
       "level.original": "52d97ecd32362bc86e004e87"
       "level.majorVersion": 0
@@ -187,20 +188,20 @@ findNearestBetterSessionID = (sessionID, sessionTotalScore, opponentSessionTotal
       submittedCode:
         $exists: true
       team: opposingTeam
-      
+
     limitNumber = 1
-  
+
     sortParameters =
       totalScore: 1
-      
+
     selectString = '_id totalScore'
-      
+
     query = LevelSession.findOne(queryParameters)
       .sort(sortParameters)
       .limit(limitNumber)
       .select(selectString)
       .lean()
-    
+
     console.log "Finding session with score near #{opponentSessionTotalScore}"
     query.exec (err, session) ->
       if err? then return cb err, session
@@ -208,7 +209,7 @@ findNearestBetterSessionID = (sessionID, sessionTotalScore, opponentSessionTotal
       console.log "Found session with score #{session.totalScore}"
       cb err, session._id
 
-    
+
 retrieveAllOpponentSessionIDs = (sessionID, cb) ->
   query = LevelSession.findOne({"_id":sessionID})
     .select('matches.opponents.sessionID')
@@ -217,14 +218,14 @@ retrieveAllOpponentSessionIDs = (sessionID, cb) ->
     if err? then return cb err, null
     opponentSessionIDs = (match.opponents[0].sessionID for match in session.matches)
     cb err, opponentSessionIDs
-    
-      
+
+
 calculateOpposingTeam = (sessionTeam) ->
   teams = ['ogres','humans']
   opposingTeams = _.pull teams, sessionTeam
   return opposingTeams[0]
-  
-  
+
+
 validatePermissions = (req, sessionID, callback) ->
   if isUserAnonymous req then return callback null, false
   if isUserAdmin req then return callback null, true
@@ -298,17 +299,17 @@ fetchInitialSessionsToRankAgainst = (opposingTeam, callback) ->
     submittedCode:
       $exists: true
     team: opposingTeam
-  
-  sortParameters = 
+
+  sortParameters =
     totalScore: 1
-  
+
   limitNumber = 1
-  
+
   query = LevelSession.find(findParameters)
     .sort(sortParameters)
     .limit(limitNumber)
-  
-  
+
+
   query.exec callback
 
 generateTaskPairs = (submittedSessions, sessionToScore) ->
@@ -444,4 +445,3 @@ retrieveOldSessionData = (sessionID, callback) ->
       "totalScore":session.totalScore ? (25 - 1.8*(25/3))
       "id": sessionID
     callback err, oldScoreObject
-

From 4b6ebd6532a53c143a157d3d8e13c1587d35333b Mon Sep 17 00:00:00 2001
From: George Saines <gsaines@gmail.com>
Date: Sun, 2 Mar 2014 18:21:42 -0800
Subject: [PATCH 025/178] styled the victory modal a bit

---
 app/styles/play/level/modal/victory.sass    | 27 +++++++++++++++++----
 app/templates/play/level/modal/victory.jade | 16 ++++++------
 2 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/app/styles/play/level/modal/victory.sass b/app/styles/play/level/modal/victory.sass
index d29b67bcd..5e2b9e727 100644
--- a/app/styles/play/level/modal/victory.sass
+++ b/app/styles/play/level/modal/victory.sass
@@ -2,12 +2,18 @@
   p.sign-up-poke
     text-align: left
     margin-bottom: 10px
+
   .sign-up-button
+    margin-left: 20px
+
+  .next-level-button
+    margin-bottom: 10px
+    margin-right: 30px
     float: right
-    margin-left: 10px
     
   .rating
-    float: left
+    float: center
+    margin-right: 22%
     span
       margin-right: 5px
     i
@@ -30,7 +36,18 @@
     clear: both
 
   .modal-header
-    text-align: center
+    text-align: left
 
-    .victory-banner
-      width: 200px
+  .victory-banner
+    width: 450px
+    position: absolute
+    left: -150px
+
+  .modal-dialog
+    margin-left: 30%
+    padding-left: 300px
+    width: 700px
+
+  .modal-footer
+    margin: 0px
+    padding: 0px
diff --git a/app/templates/play/level/modal/victory.jade b/app/templates/play/level/modal/victory.jade
index 3509e4fe9..7a0637f8a 100644
--- a/app/templates/play/level/modal/victory.jade
+++ b/app/templates/play/level/modal/victory.jade
@@ -1,5 +1,9 @@
 // TODO: refactor to be like other modals
+
 .modal-dialog
+
+  img.victory-banner(src="/images/level/victory.png", alt="")
+
   .modal-header
     button(type='button', data-dismiss="modal", aria-hidden="true").close &times;
     h3
@@ -7,15 +11,17 @@
       span= levelName
       span(data-i18n="play_level.victory_title_suffix") Complete
 
-    img.victory-banner(src="/images/level/victory.png", alt="")
-  
   .modal-body!= body
   
   .modal-footer
+    if hasNextLevel
+      button.btn.btn-primary.next-level-button(data-dismiss="modal", data-i18n="play_level.victory_play_next_level") Play Next Level
+    else
+      a.btn.btn-primary(href="/", data-dismiss="modal", data-i18n="play_level.victory_go_home") Go Home
     if me.get('anonymous')
       p.sign-up-poke
         button.btn.btn-success.sign-up-button.btn-large(data-toggle="coco-modal", data-target="modal/signup", data-i18n="play_level.victory_sign_up") Sign Up to Save Progress
-        span(data-i18n="play_level.victory_sign_up_poke") Want to save your code? Create a free account!
+          span(data-i18n="play_level.victory_sign_up_poke") Want to save your code? Create a free account!
       p.clearfix
     else
       div.rating.secret
@@ -25,10 +31,6 @@
         i.icon-star-empty
         i.icon-star-empty
         i.icon-star-empty
-    if hasNextLevel
-      button.btn.btn-primary.next-level-button(data-dismiss="modal", data-i18n="play_level.victory_play_next_level") Play Next Level
-    else
-      a.btn.btn-primary(href="/", data-dismiss="modal", data-i18n="play_level.victory_go_home") Go Home
     if !me.get('anonymous')
       div.review.secret
         span(data-i18n="play_level.victory_review") Tell us more!

From 81466675ec4c87e8c2eb4c74c4d8e144ddfdce1c Mon Sep 17 00:00:00 2001
From: Michael Schmatz <schmatz@umich.edu>
Date: Sun, 2 Mar 2014 18:55:07 -0800
Subject: [PATCH 026/178] Scheduling fixes

---
 server/queues/scoring.coffee | 77 ++++++++++++++++++++----------------
 1 file changed, 43 insertions(+), 34 deletions(-)

diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee
index a1119378b..eb0815e38 100644
--- a/server/queues/scoring.coffee
+++ b/server/queues/scoring.coffee
@@ -107,40 +107,49 @@ module.exports.processTaskResult = (req, res) ->
     scoringTaskQueue.deleteMessage clientResponseObject.receiptHandle, (err) ->
       console.log "Deleted message."
       if err? then return errors.badInput res, "The queue message is already back in the queue, rejecting results."
-
-      logTaskComputation clientResponseObject, taskLog, (logErr) ->
-        if logErr? then return errors.serverError res, "There as a problem logging the task computation: #{logErr}"
-
-        updateSessions clientResponseObject, (updateError, newScoreArray) ->
-          if updateError? then return errors.serverError res, "There was an error updating the scores.#{updateError}"
-
-          newScoresObject = _.indexBy newScoreArray, 'id'
-
-          addMatchToSessions clientResponseObject, newScoresObject, (err, data) ->
-            if err? then return errors.serverError res, "There was an error updating the sessions with the match! #{JSON.stringify err}"
-
-            originalSessionID = clientResponseObject.originalSessionID
-            originalSessionTeam = clientResponseObject.originalSessionTeam
-            originalSessionRank = parseInt clientResponseObject.originalSessionRank
-
-            determineIfSessionShouldContinueAndUpdateLog originalSessionID, originalSessionRank, (err, sessionShouldContinue) ->
-              if err? then return errors.serverError res, "There was an error determining if the session should continue, #{err}"
-
-              if sessionShouldContinue
-                opposingTeam = calculateOpposingTeam(originalSessionTeam)
-                opponentID = _.pull(_.keys(newScoresObject), originalSessionID)
-                sessionNewScore = newScoresObject[originalSessionID].totalScore
-                opponentNewScore = newScoresObject[opponentID].totalScore
-                findNearestBetterSessionID originalSessionID, sessionNewScore, opponentNewScore, opponentID ,opposingTeam, (err, opponentSessionID) ->
-                  if err? then return errors.serverError res, "There was an error finding the nearest sessionID!"
-                  unless opponentSessionID then return sendResponseObject req, res, {"message":"There were no more games to rank(game is at top!"}
-
-                  addPairwiseTaskToQueue [originalSessionID, opponentSessionID], (err, success) ->
-                    if err? then return errors.serverError res, "There was an error sending the pairwise tasks to the queue!"
-                    sendResponseObject req, res, {"message":"The scores were updated successfully and more games were sent to the queue!"}
-              else
-                console.log "Player lost, achieved rank #{originalSessionRank}"
-                sendResponseObject req, res, {"message":"The scores were updated successfully, person lost so no more games are being inserted!"}
+        
+      LevelSession.findOne(_id: clientResponseObject.originalSessionID).lean().exec (err, levelSession) ->
+        if err? then return errors.serverError res, "There was a problem finding the level session:#{err}"
+          
+        console.log "Queue message created at: #{taskLogJSON.createdAt}, level session submitted at #{levelSession.submitDate}"
+        
+        if taskLogJSON.createdAt <= levelSession.submitDate
+          console.log "Task has been resubmitted!"
+          return sendResponseObject req, res, {"message":"The game has been resubmitted. Removing from queue..."}
+  
+        logTaskComputation clientResponseObject, taskLog, (logErr) ->
+          if logErr? then return errors.serverError res, "There as a problem logging the task computation: #{logErr}"
+  
+          updateSessions clientResponseObject, (updateError, newScoreArray) ->
+            if updateError? then return errors.serverError res, "There was an error updating the scores.#{updateError}"
+  
+            newScoresObject = _.indexBy newScoreArray, 'id'
+  
+            addMatchToSessions clientResponseObject, newScoresObject, (err, data) ->
+              if err? then return errors.serverError res, "There was an error updating the sessions with the match! #{JSON.stringify err}"
+  
+              originalSessionID = clientResponseObject.originalSessionID
+              originalSessionTeam = clientResponseObject.originalSessionTeam
+              originalSessionRank = parseInt clientResponseObject.originalSessionRank
+  
+              determineIfSessionShouldContinueAndUpdateLog originalSessionID, originalSessionRank, (err, sessionShouldContinue) ->
+                if err? then return errors.serverError res, "There was an error determining if the session should continue, #{err}"
+  
+                if sessionShouldContinue
+                  opposingTeam = calculateOpposingTeam(originalSessionTeam)
+                  opponentID = _.pull(_.keys(newScoresObject), originalSessionID)
+                  sessionNewScore = newScoresObject[originalSessionID].totalScore
+                  opponentNewScore = newScoresObject[opponentID].totalScore
+                  findNearestBetterSessionID originalSessionID, sessionNewScore, opponentNewScore, opponentID ,opposingTeam, (err, opponentSessionID) ->
+                    if err? then return errors.serverError res, "There was an error finding the nearest sessionID!"
+                    unless opponentSessionID then return sendResponseObject req, res, {"message":"There were no more games to rank(game is at top!"}
+  
+                    addPairwiseTaskToQueue [originalSessionID, opponentSessionID], (err, success) ->
+                      if err? then return errors.serverError res, "There was an error sending the pairwise tasks to the queue!"
+                      sendResponseObject req, res, {"message":"The scores were updated successfully and more games were sent to the queue!"}
+                else
+                  console.log "Player lost, achieved rank #{originalSessionRank}"
+                  sendResponseObject req, res, {"message":"The scores were updated successfully, person lost so no more games are being inserted!"}
 
 
 determineIfSessionShouldContinueAndUpdateLog = (sessionID, sessionRank, cb) ->

From 239ca83a84718f93a6ed7d28d1a3341211e10803 Mon Sep 17 00:00:00 2001
From: Michael Schmatz <schmatz@umich.edu>
Date: Sun, 2 Mar 2014 19:11:42 -0800
Subject: [PATCH 027/178] Perhaps buggy fix to scheduling

---
 server/queues/scoring.coffee | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee
index eb0815e38..5aa252679 100644
--- a/server/queues/scoring.coffee
+++ b/server/queues/scoring.coffee
@@ -84,7 +84,7 @@ module.exports.dispatchTaskToConsumer = (req, res) ->
       message.changeMessageVisibilityTimeout scoringTaskTimeoutInSeconds, (err) ->
         if err? then return errors.serverError res, "There was an error changing the message visibility timeout."
         console.log "Changed visibility timeout"
-        constructTaskLogObject getUserIDFromRequest(req),message.getReceiptHandle(), (taskLogError, taskLogObject) ->
+        constructTaskLogObject getUserIDFromRequest(req),messageBody.registrationTime, message.getReceiptHandle(), (taskLogError, taskLogObject) ->
           if taskLogError? then return errors.serverError res, "There was an error creating the task log object."
 
           taskObject.taskID = taskLogObject._id
@@ -113,7 +113,7 @@ module.exports.processTaskResult = (req, res) ->
           
         console.log "Queue message created at: #{taskLogJSON.createdAt}, level session submitted at #{levelSession.submitDate}"
         
-        if taskLogJSON.createdAt <= levelSession.submitDate
+        if taskLogJSON.registrationTime <= levelSession.submitDate
           console.log "Task has been resubmitted!"
           return sendResponseObject req, res, {"message":"The game has been resubmitted. Removing from queue..."}
   
@@ -333,7 +333,7 @@ generateTaskPairs = (submittedSessions, sessionToScore) ->
   return taskPairs
 
 sendTaskPairToQueue = (taskPair, callback) ->
-  scoringTaskQueue.sendMessage {sessions: taskPair}, 0, (err,data) -> callback? err,data
+  scoringTaskQueue.sendMessage {sessions: taskPair, registrationTime:new Date()}, 0, (err,data) -> callback? err,data
 
 getUserIDFromRequest = (req) -> if req.user? then return req.user._id else return null
 
@@ -380,9 +380,10 @@ getSessionInformation = (sessionIDString, callback) ->
     callback err, sessionInformation
 
 
-constructTaskLogObject = (calculatorUserID, messageIdentifierString, callback) ->
+constructTaskLogObject = (calculatorUserID, registrationTime, messageIdentifierString, callback) ->
   taskLogObject = new TaskLog
     "createdAt": new Date()
+    "registrationTime": registrationTime
     "calculator":calculatorUserID
     "sentDate": Date.now()
     "messageIdentifierString":messageIdentifierString

From b8b22bb739c2e36a78c2073292bb5c5633e18581 Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <ruben.vereecken@student.uantwerpen.be>
Date: Mon, 3 Mar 2014 12:45:04 +0100
Subject: [PATCH 028/178] Localized 'Create New ..' and 'Search .. Here'

---
 app/locale/en.coffee              | 6 ++++++
 app/locale/nl.coffee              | 6 ++++++
 app/templates/kinds/search.jade   | 5 +++--
 app/views/kinds/SearchView.coffee | 8 +++++++-
 4 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index d72b872cd..2afc376cd 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -247,6 +247,12 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
     create_system_title: "Create New System"
     new_component_title: "Create New Component"
     new_component_field_system: "System"
+    new_article_title: "Create a New Article"
+    new_thang_title: "Create a New Thang Type"
+    new_level_title: "Create a New Level"
+    article_search_title: "Search Articles Here"
+    thang_search_title: "Search Thang Types Here"
+    level_search_title: "Search Levels Here"
 
   article:
     edit_btn_preview: "Preview"
diff --git a/app/locale/nl.coffee b/app/locale/nl.coffee
index 8e762eaeb..929741d23 100644
--- a/app/locale/nl.coffee
+++ b/app/locale/nl.coffee
@@ -247,6 +247,12 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     create_system_title: "Maak een nieuw Systeem aan"
     new_component_title: "Maak een nieuw Component aan"
     new_component_field_system: "Systeem"
+    new_article_title: "Maak een Nieuw Artikel"
+    new_thang_title: "Maak een Nieuw Thang Type"
+    new_level_title: "Maak een Nieuw Level"
+    article_search_title: "Zoek Artikels Hier"
+    thang_search_title: "Zoek Thang Types Hier"
+    level_search_title: "Zoek Levels Hier"
 
   article:
     edit_btn_preview: "Voorbeeld"
diff --git a/app/templates/kinds/search.jade b/app/templates/kinds/search.jade
index 24547e166..eda4c0f2b 100644
--- a/app/templates/kinds/search.jade
+++ b/app/templates/kinds/search.jade
@@ -10,8 +10,9 @@ block content
   if me.get('anonymous')
     a.btn.btn-primary.open-modal-button(data-toggle="coco-modal", data-target="modal/signup", role="button") Sign Up to Create a New #{modelLabel}
   else
-    a.btn.btn-primary.open-modal-button(href='#new-model-modal', role="button", data-toggle="modal") Create a New #{modelLabel}
-  input#search(placeholder="Search #{modelLabel}s Here")
+    a.btn.btn-primary.open-modal-button(href='#new-model-modal', role="button", data-toggle="modal" data-i18n="#{currentNew}") Create a New Something
+
+  input#search(data-i18n="[placeholder]#{currentSearch}")
   hr
   div.results
     table
diff --git a/app/views/kinds/SearchView.coffee b/app/views/kinds/SearchView.coffee
index 18648e386..1198f74a1 100644
--- a/app/views/kinds/SearchView.coffee
+++ b/app/views/kinds/SearchView.coffee
@@ -28,14 +28,20 @@ module.exports = class ThangTypeHomeView extends View
 
   getRenderData: ->
     context = super()
-    context.modelLabel = @modelLabel
     switch @modelLabel
       when 'Level'
         context.currentEditor = 'editor.level_title'
+        context.currentNew = 'editor.new_level_title'
+        context.currentSearch = 'editor.level_search_title'
       when 'Thang Type'
         context.currentEditor = 'editor.thang_title'
+        context.currentNew = 'editor.new_thang_title'
+        context.currentSearch = 'editor.thang_search_title'
       when 'Article'
         context.currentEditor = 'editor.article_title'
+        context.currentNew = 'editor.new_article_title'
+        context.currentSearch = 'editor.article_search_title'
+    @$el.i18n()
     context
 
   constructor: (options) ->

From 86fd09815930e992303fef4d7711bb7648b9959c Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 3 Mar 2014 07:28:40 -0800
Subject: [PATCH 029/178] Localized WizardSprite movement hey handling to
 WizardSprite file.

---
 app/lib/surface/WizardSprite.coffee       | 25 +++++++++++++++++++----
 app/views/play/level/playback_view.coffee | 15 --------------
 2 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/app/lib/surface/WizardSprite.coffee b/app/lib/surface/WizardSprite.coffee
index b98ae44b5..58eec1dc7 100644
--- a/app/lib/surface/WizardSprite.coffee
+++ b/app/lib/surface/WizardSprite.coffee
@@ -21,7 +21,12 @@ module.exports = class WizardSprite extends IndieSprite
     'surface:sprite-selected': 'onSpriteSelected'
     'echo-self-wizard-sprite': 'onEchoSelfWizardSprite'
     'echo-all-wizard-sprites': 'onEchoAllWizardSprites'
-    'self-wizard:move': 'moveWizard'
+
+  shortcuts:
+    'up': 'onMoveKey'
+    'down': 'onMoveKey'
+    'left': 'onMoveKey'
+    'right': 'onMoveKey'
 
   constructor: (thangType, options) ->
     if options?.isSelf
@@ -230,9 +235,21 @@ module.exports = class WizardSprite extends IndieSprite
   updateMarks: ->
     super() if @displayObject.visible  # not if we hid the wiz
 
-  moveWizard : (x, y) =>
+
+  onMoveKey: (e) ->
+    return unless @isSelf
+    e?.preventDefault()
+    yMovement = 0
+    xMovement = 0
+    yMovement += 2 if key.isPressed('up')
+    yMovement -= 2 if key.isPressed('down')
+    xMovement += 2 if key.isPressed('right')
+    xMovement -= 2 if key.isPressed('left')
+    @moveWizard xMovement, yMovement
+
+  moveWizard: (x, y) ->
     interval = 500
-    position = {x: @targetPos.x+x, y: @targetPos.y+y}
+    position = {x: @targetPos.x + x, y: @targetPos.y + y}
     @setTarget(position, interval, true)
     @updatePosition()
-    Backbone.Mediator.publish 'camera-zoom-to', position, interval
\ No newline at end of file
+    Backbone.Mediator.publish 'camera-zoom-to', position, interval
diff --git a/app/views/play/level/playback_view.coffee b/app/views/play/level/playback_view.coffee
index 20ec9295c..f9c13a9e3 100644
--- a/app/views/play/level/playback_view.coffee
+++ b/app/views/play/level/playback_view.coffee
@@ -36,10 +36,6 @@ module.exports = class PlaybackView extends View
     '⌘+p, p, ctrl+p': 'onTogglePlay'
     '⌘+[, ctrl+[': 'onScrubBack'
     '⌘+], ctrl+]': 'onScrubForward'
-    'up': 'onMoveKey'
-    'down': 'onMoveKey'
-    'left': 'onMoveKey'
-    'right': 'onMoveKey'
 
   constructor: ->
     super(arguments...)
@@ -219,14 +215,3 @@ module.exports = class PlaybackView extends View
     $(window).off('resize', @onWindowResize)
     @onWindowResize = null
     super()
-
-  onMoveKey: (e) ->
-    e?.preventDefault()
-    yMovement = 0
-    xMovement = 0
-    yMovement += 2 if key.isPressed('up')
-    yMovement -= 2 if key.isPressed('down')
-    xMovement += 2 if key.isPressed('right')
-    xMovement -= 2 if key.isPressed('left')
-    console.log 'onMoveKey', xMovement, yMovement
-    Backbone.Mediator.publish 'self-wizard:move', xMovement, yMovement

From 357ef45cb09d31178b49ddd47d7d74b96b6c117a Mon Sep 17 00:00:00 2001
From: Karthig <karthig@karthig-HP-Mini-5101.(none)>
Date: Sun, 2 Mar 2014 22:33:02 -0500
Subject: [PATCH 030/178] - insert random error image into 404 page

---
 app/templates/not_found.jade | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/app/templates/not_found.jade b/app/templates/not_found.jade
index ab9d5809e..fd838b2c2 100644
--- a/app/templates/not_found.jade
+++ b/app/templates/not_found.jade
@@ -3,3 +3,8 @@ extends /templates/base
 block content
 
   h1.text-center(data-i18n="not_found.page_not_found") Page Not Found
+
+  num = Math.floor(Math.random() * 3) + 1
+
+  img(src="/images/pages/not_found/404_#{num}.png")
+

From a5adf5a1bf35fa6d917694b3da163e1e10b1fd82 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 3 Mar 2014 08:10:36 -0800
Subject: [PATCH 031/178] Tweaked status colors for production logging;
 applying it only when in production.

---
 server_setup.coffee | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/server_setup.coffee b/server_setup.coffee
index 3332e0428..9d00188a7 100644
--- a/server_setup.coffee
+++ b/server_setup.coffee
@@ -21,14 +21,23 @@ setupRequestTimeoutMiddleware = (app) ->
 
 productionLogging = (tokens, req, res)->
   status = res.statusCode
-  color = 31
-  if(status != 200 && status != 304)
-    return '\x1b[90m' + req.method+ ' ' + req.originalUrl + ' '+ '\x1b[' + color + 'm' + res.statusCode+ ' \x1b[90m'+ (new Date - req._startTime)+ 'ms' + '\x1b[0m';
+  color = 32
+  if status >= 500 then color = 31
+  else if status >= 400 then color = 33
+  else if status >= 300 then color = 36
+  elapsed = (new Date()) - req._startTime
+  elapsedColor = if elapsed < 500 then 90 else 31
+  if (status isnt 200 and status isnt 304) or elapsed > 500
+    return "\x1b[90m#{req.method} #{req.originalUrl} \x1b[#{color}m#{res.statusCode} \x1b[#{elapsedColor}m#{elapsed}ms\x1b[0m"
+  null
 
 setupExpressMiddleware = (app) ->
   setupRequestTimeoutMiddleware app
-  express.logger.format('prod', productionLogging)
-  app.use(express.logger('prod'))
+  if config.isProduction
+    express.logger.format('prod', productionLogging)
+    app.use(express.logger('prod'))
+  else
+    app.use(express.logger('dev'))
   app.use(express.static(path.join(__dirname, 'public')))
   app.use(useragent.express())
 
@@ -105,6 +114,3 @@ exports.setExpressConfigurationOptions = (app) ->
   app.set('views', __dirname + '/app/views')
   app.set('view engine', 'jade')
   app.set('view options', { layout: false })
-
-
-

From 967d6cd8890c9baf6ca3eaac51a2406aff8ae2e5 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 3 Mar 2014 08:13:53 -0800
Subject: [PATCH 032/178] Let's try this without the request timeout
 middleware, to see if we still need that.

---
 server_setup.coffee | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/server_setup.coffee b/server_setup.coffee
index 9d00188a7..ad23a6bf1 100644
--- a/server_setup.coffee
+++ b/server_setup.coffee
@@ -11,13 +11,14 @@ logging = require './server/commons/logging'
 config = require './server_config'
 
 ###Middleware setup functions implementation###
-setupRequestTimeoutMiddleware = (app) ->
-  app.use (req, res, next) ->
-    req.setTimeout 15000, ->
-      console.log 'timed out!'
-      req.abort()
-      self.emit('pass',message)
-    next()
+# 2014-03-03: Try not using this and see if it's still a problem
+#setupRequestTimeoutMiddleware = (app) ->
+#  app.use (req, res, next) ->
+#    req.setTimeout 15000, ->
+#      console.log 'timed out!'
+#      req.abort()
+#      self.emit('pass',message)
+#    next()
 
 productionLogging = (tokens, req, res)->
   status = res.statusCode
@@ -32,7 +33,7 @@ productionLogging = (tokens, req, res)->
   null
 
 setupExpressMiddleware = (app) ->
-  setupRequestTimeoutMiddleware app
+  #setupRequestTimeoutMiddleware app
   if config.isProduction
     express.logger.format('prod', productionLogging)
     app.use(express.logger('prod'))

From 9a40eb623c6537296679aaf561650c6ba43cbaed Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 3 Mar 2014 08:21:15 -0800
Subject: [PATCH 033/178] Added translation by @rdxiang of server_config.js to
 server_config.coffee

---
 server_config.coffee | 49 +++++++++++++++++++++++++++++++++++++++++
 server_config.js     | 52 --------------------------------------------
 2 files changed, 49 insertions(+), 52 deletions(-)
 create mode 100644 server_config.coffee
 delete mode 100644 server_config.js

diff --git a/server_config.coffee b/server_config.coffee
new file mode 100644
index 000000000..b13bead19
--- /dev/null
+++ b/server_config.coffee
@@ -0,0 +1,49 @@
+config = {}
+
+config.unittest = process.argv.indexOf("--unittest") > -1
+
+config.port = process.env.COCO_PORT or process.env.COCO_NODE_PORT or 3000
+config.ssl_port = process.env.COCO_SSL_PORT or process.env.COCO_SSL_NODE_PORT or 3443
+
+config.mongo =
+  port: process.env.COCO_MONGO_PORT or 27017
+  host: process.env.COCO_MONGO_HOST or "localhost"
+  db: process.env.COCO_MONGO_DATABASE_NAME or "coco"
+  mongoose_replica_string: process.env.COCO_MONGO_MONGOOSE_REPLICA_STRING or ""
+
+if config.unittest
+  config.port += 1
+  config.ssl_port += 1
+  config.mongo.host = "localhost"
+else
+  config.mongo.username = process.env.COCO_MONGO_USERNAME or ""
+  config.mongo.password = process.env.COCO_MONGO_PASSWORD or ""
+
+config.mail =
+  service: process.env.COCO_MAIL_SERVICE_NAME or "Zoho"
+  username: process.env.COCO_MAIL_SERVICE_USERNAME or ""
+  password: process.env.COCO_MAIL_SERVICE_PASSWORD or ""
+  mailchimpAPIKey: process.env.COCO_MAILCHIMP_API_KEY or ""
+  mailchimpWebhook: process.env.COCO_MAILCHIMP_WEBHOOK or "/mail/webhook"
+  sendwithusAPIKey: process.env.COCO_SENDWITHUS_API_KEY or ""
+
+config.queue =
+  accessKeyId: process.env.COCO_AWS_ACCESS_KEY_ID or ""
+  secretAccessKey: process.env.COCO_AWS_SECRET_ACCESS_KEY or ""
+  region: "us-east-1"
+  simulationQueueName: "simulationQueue"
+
+config.mongoQueue =
+  queueDatabaseName: "coco_queue"
+
+config.salt = process.env.COCO_SALT or "pepper"
+config.cookie_secret = process.env.COCO_COOKIE_SECRET or "chips ahoy"
+
+config.isProduction = config.mongo.host isnt "localhost"
+
+if not config.unittest and  not config.isProduction
+  # change artificially slow down non-static requests for testing
+  config.slow_down = false
+
+
+module.exports = config
diff --git a/server_config.js b/server_config.js
deleted file mode 100644
index 880fcfd78..000000000
--- a/server_config.js
+++ /dev/null
@@ -1,52 +0,0 @@
-var config = {};
-
-config.unittest = process.argv.indexOf('--unittest') > -1;
-
-config.port = process.env.COCO_PORT || process.env.COCO_NODE_PORT || 3000;
-config.ssl_port = 
-  process.env.COCO_SSL_PORT || process.env.COCO_SSL_NODE_PORT || 3443;
-
-config.mongo = {};
-config.mongo.port = process.env.COCO_MONGO_PORT || 27017;
-config.mongo.host = process.env.COCO_MONGO_HOST || 'localhost';
-config.mongo.db = process.env.COCO_MONGO_DATABASE_NAME || 'coco';
-config.mongo.mongoose_replica_string = process.env.COCO_MONGO_MONGOOSE_REPLICA_STRING || '';
-
-if(config.unittest) {
-  config.port += 1;
-  config.ssl_port += 1;
-  config.mongo.host = 'localhost';
-}
-
-else {
-  config.mongo.username = process.env.COCO_MONGO_USERNAME || '';
-  config.mongo.password = process.env.COCO_MONGO_PASSWORD || '';
-}
-
-config.mail = {};
-config.mail.service = process.env.COCO_MAIL_SERVICE_NAME || "Zoho";
-config.mail.username = process.env.COCO_MAIL_SERVICE_USERNAME || "";
-config.mail.password = process.env.COCO_MAIL_SERVICE_PASSWORD || "";
-config.mail.mailchimpAPIKey = process.env.COCO_MAILCHIMP_API_KEY || '';
-config.mail.mailchimpWebhook = process.env.COCO_MAILCHIMP_WEBHOOK || '/mail/webhook';
-config.mail.sendwithusAPIKey = process.env.COCO_SENDWITHUS_API_KEY || '';
-
-config.queue = {};
-config.queue.accessKeyId = process.env.COCO_AWS_ACCESS_KEY_ID || '';
-config.queue.secretAccessKey = process.env.COCO_AWS_SECRET_ACCESS_KEY || '';
-config.queue.region = 'us-east-1';
-config.queue.simulationQueueName = "simulationQueue";
-config.mongoQueue = {};
-config.mongoQueue.queueDatabaseName = "coco_queue";
-
-config.salt = process.env.COCO_SALT || 'pepper';
-config.cookie_secret = process.env.COCO_COOKIE_SECRET || 'chips ahoy';
-
-config.isProduction = config.mongo.host != 'localhost';
-
-if(!config.unittest && !config.isProduction) {
-  // change artificially slow down non-static requests for testing
-  config.slow_down = false; 
-}
-
-module.exports = config;

From b04d63d5bf41345d2ddc8926fc83f33663c7f1d4 Mon Sep 17 00:00:00 2001
From: Karthig <karthig@karthig-HP-Mini-5101.(none)>
Date: Mon, 3 Mar 2014 11:42:07 -0500
Subject: [PATCH 034/178] - create sass file to center 404 image on page

---
 app/styles/not_found.sass    | 9 +++++++++
 app/templates/not_found.jade | 2 +-
 2 files changed, 10 insertions(+), 1 deletion(-)
 create mode 100644 app/styles/not_found.sass

diff --git a/app/styles/not_found.sass b/app/styles/not_found.sass
new file mode 100644
index 000000000..677900b6d
--- /dev/null
+++ b/app/styles/not_found.sass
@@ -0,0 +1,9 @@
+@import "bootstrap/mixins"
+@import "bootstrap/variables"
+
+#not-found-view
+
+  .not-found-image
+    display: block
+    margin-left: auto
+    margin-right: auto
diff --git a/app/templates/not_found.jade b/app/templates/not_found.jade
index fd838b2c2..bc2d32d13 100644
--- a/app/templates/not_found.jade
+++ b/app/templates/not_found.jade
@@ -6,5 +6,5 @@ block content
 
   num = Math.floor(Math.random() * 3) + 1
 
-  img(src="/images/pages/not_found/404_#{num}.png")
+  img(src="/images/pages/not_found/404_#{num}.png" class="not-found-image")
 

From 8399667b49bdd0241c1b653cbfcd0cd57d404b7b Mon Sep 17 00:00:00 2001
From: Michael Schmatz <schmatz@umich.edu>
Date: Mon, 3 Mar 2014 08:47:09 -0800
Subject: [PATCH 035/178] Fixed submit date checks

---
 server/queues/scoring.coffee | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee
index 5aa252679..c527f921f 100644
--- a/server/queues/scoring.coffee
+++ b/server/queues/scoring.coffee
@@ -84,7 +84,7 @@ module.exports.dispatchTaskToConsumer = (req, res) ->
       message.changeMessageVisibilityTimeout scoringTaskTimeoutInSeconds, (err) ->
         if err? then return errors.serverError res, "There was an error changing the message visibility timeout."
         console.log "Changed visibility timeout"
-        constructTaskLogObject getUserIDFromRequest(req),messageBody.registrationTime, message.getReceiptHandle(), (taskLogError, taskLogObject) ->
+        constructTaskLogObject getUserIDFromRequest(req), message.getReceiptHandle(), (taskLogError, taskLogObject) ->
           if taskLogError? then return errors.serverError res, "There was an error creating the task log object."
 
           taskObject.taskID = taskLogObject._id
@@ -111,10 +111,9 @@ module.exports.processTaskResult = (req, res) ->
       LevelSession.findOne(_id: clientResponseObject.originalSessionID).lean().exec (err, levelSession) ->
         if err? then return errors.serverError res, "There was a problem finding the level session:#{err}"
           
-        console.log "Queue message created at: #{taskLogJSON.createdAt}, level session submitted at #{levelSession.submitDate}"
-        
-        if taskLogJSON.registrationTime <= levelSession.submitDate
-          console.log "Task has been resubmitted!"
+        supposedSubmissionDate = new Date(clientResponseObject.sessions[0].submitDate)
+          
+        if Number(supposedSubmissionDate) isnt Number(levelSession.submitDate)
           return sendResponseObject req, res, {"message":"The game has been resubmitted. Removing from queue..."}
   
         logTaskComputation clientResponseObject, taskLog, (logErr) ->
@@ -333,7 +332,7 @@ generateTaskPairs = (submittedSessions, sessionToScore) ->
   return taskPairs
 
 sendTaskPairToQueue = (taskPair, callback) ->
-  scoringTaskQueue.sendMessage {sessions: taskPair, registrationTime:new Date()}, 0, (err,data) -> callback? err,data
+  scoringTaskQueue.sendMessage {sessions: taskPair}, 0, (err,data) -> callback? err,data
 
 getUserIDFromRequest = (req) -> if req.user? then return req.user._id else return null
 
@@ -380,10 +379,9 @@ getSessionInformation = (sessionIDString, callback) ->
     callback err, sessionInformation
 
 
-constructTaskLogObject = (calculatorUserID, registrationTime, messageIdentifierString, callback) ->
+constructTaskLogObject = (calculatorUserID, messageIdentifierString, callback) ->
   taskLogObject = new TaskLog
     "createdAt": new Date()
-    "registrationTime": registrationTime
     "calculator":calculatorUserID
     "sentDate": Date.now()
     "messageIdentifierString":messageIdentifierString

From 22e80f6d24737b6ee19674deb7c43e6bf037a2f7 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Mon, 3 Mar 2014 09:03:44 -0800
Subject: [PATCH 036/178] Set up a play modal, starting to refactor wizard
 thang type loading to be shared across the site.

---
 app/models/ThangType.coffee               |   7 ++
 app/styles/play/ladder/play_modal.sass    | 108 +++++++++++++++++
 app/templates/play/ladder.jade            |   2 +-
 app/templates/play/ladder/play_modal.jade |  64 ++++++++++
 app/views/home_view.coffee                |  10 +-
 app/views/play/ladder/play_modal.coffee   | 140 ++++++++++++++++++++++
 app/views/play/ladder_view.coffee         |  11 +-
 7 files changed, 333 insertions(+), 9 deletions(-)
 create mode 100644 app/styles/play/ladder/play_modal.sass
 create mode 100644 app/templates/play/ladder/play_modal.jade
 create mode 100644 app/views/play/ladder/play_modal.coffee

diff --git a/app/models/ThangType.coffee b/app/models/ThangType.coffee
index 6aaff80a5..c162f9287 100644
--- a/app/models/ThangType.coffee
+++ b/app/models/ThangType.coffee
@@ -210,3 +210,10 @@ module.exports = class ThangType extends CocoModel
 
   onFileUploaded: =>
     console.log 'Image uploaded'
+
+wizOriginal = "52a00d55cf1818f2be00000b"
+url = "/db/thang_type/#{wizOriginal}/version"
+wizardType = new module.exports()
+wizardType.url = -> url
+wizardType.fetch()
+module.exports.wizardType = wizardType
\ No newline at end of file
diff --git a/app/styles/play/ladder/play_modal.sass b/app/styles/play/ladder/play_modal.sass
new file mode 100644
index 000000000..8dc69a5ae
--- /dev/null
+++ b/app/styles/play/ladder/play_modal.sass
@@ -0,0 +1,108 @@
+#ladder-play-modal
+  .tutorial-suggestion
+    text-align: center
+    font-size: 18px
+  
+  .play-option
+    margin-bottom: 15px
+    width: 100%
+    height: 100px
+    overflow: hidden
+    background: white
+    border: 1px solid #333
+    position: relative
+
+    -webkit-transition: opacity 0.3s ease-in-out
+    -moz-transition: opacity 0.3s ease-in-out
+    -ms-transition: opacity 0.3s ease-in-out
+    -o-transition: opacity 0.3s ease-in-out
+    transition: opacity 0.3s ease-in-out
+    
+    opacity: 0.4
+    
+    border-radius: 5px
+    
+  .play-option:hover
+    opacity: 1
+    
+  .my-icon
+    position: relative
+    left: 0
+    top: -10px
+    
+  .opponent-icon
+    position: relative
+    float: right
+    right: 0
+    top: -10px
+    -moz-transform: scaleX(-1)
+    -o-transform: scaleX(-1)
+    -webkit-transform: scaleX(-1)
+    transform: scaleX(-1)
+    filter: FlipH
+    -ms-filter: "FlipH"
+    
+  .name-label
+    border-bottom: 20px solid lightslategray
+    height: 0
+    width: 40%
+    position: absolute
+    bottom: 0
+    color: black
+    font-weight: bold
+    text-align: center
+    
+    span
+      position: relative
+      top: 1px
+      
+  .my-name
+    border-right: 15px solid transparent
+    left: 0
+    span
+      left: 3px
+    
+  .opponent-name
+    border-left: 15px solid transparent
+    right: 0
+    //text-align: right
+    span
+      right: 3px
+  
+  .difficulty
+    border-top: 25px solid darkgray
+    border-left: 20px solid transparent
+    border-right: 20px solid transparent
+    height: 0
+    width: 30%
+    position: absolute
+    left: 35%
+    top: 0
+    color: black
+    text-align: center
+    font-size: 18px
+    font-weight: bold
+
+    span
+      position: relative
+      top: -25px
+      
+  .easy-option .difficulty
+    border-top: 25px solid limegreen
+      
+  .medium-option .difficulty
+    border-top: 25px solid darkorange
+    
+  .hard-option .difficulty
+    border-top: 25px solid black
+    color: white
+
+  .vs
+    position: absolute
+    left: 40%
+    right: 40%
+    text-align: center
+    top: 35px
+    font-size: 40px
+    font-weight: bolder
+    color: black
\ No newline at end of file
diff --git a/app/templates/play/ladder.jade b/app/templates/play/ladder.jade
index 4d056ce97..18802f55d 100644
--- a/app/templates/play/ladder.jade
+++ b/app/templates/play/ladder.jade
@@ -20,7 +20,7 @@ block content
       div.column.col-md-2
       for team in teams
         div.column.col-md-4
-          a(href="/play/ladder/#{levelID}/team/#{team.id}", style="background-color: #{team.primaryColor}").play-button.btn.btn-danger.btn-block.btn-lg
+          a(style="background-color: #{team.primaryColor}", data-team=team.id).play-button.btn.btn-danger.btn-block.btn-lg
             span Play As 
             span= team.name
       div.column.col-md-2
diff --git a/app/templates/play/ladder/play_modal.jade b/app/templates/play/ladder/play_modal.jade
new file mode 100644
index 000000000..6eae0c87c
--- /dev/null
+++ b/app/templates/play/ladder/play_modal.jade
@@ -0,0 +1,64 @@
+extends /templates/modal/modal_base
+
+block modal-header-content
+  h3 Choose an Opponent
+
+block modal-body-content
+  
+  p.tutorial-suggestion
+    span Not sure what's going on?
+    |  
+    a(href="/play/level/brawlwood-tutorial") Play the tutorial first.
+
+  a(href="/play/level/#{levelID}?team=#{teamID}")
+    div.play-option
+      img(src=portraitSRC).my-icon
+      img(src=portraitSRC).opponent-icon
+      div.my-name.name-label
+        span= myName
+      div.opponent-name.name-label
+        span Simple AI
+      div.difficulty
+        span Warmup
+      div.vs VS
+  
+  if challengers.easy
+    a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.easy.sessionID}")
+      div.play-option.easy-option
+        img(src=portraitSRC).my-icon
+        img(src=portraitSRC).opponent-icon
+        div.my-name.name-label
+          span= myName
+        div.opponent-name.name-label
+          span= challengers.easy.opponentName
+        div.difficulty
+          span Easy
+        div.vs VS
+
+  if challengers.medium
+    a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.medium.sessionID}")
+      div.play-option.medium-option
+        img(src=portraitSRC).my-icon
+        img(src=portraitSRC).opponent-icon
+        div.my-name.name-label
+          span= myName
+        div.opponent-name.name-label
+          span= challengers.medium.opponentName
+        div.difficulty
+          span Medium
+        div.vs VS
+
+  if challengers.hard
+    a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.hard.sessionID}")
+      div.play-option.hard-option
+        img(src=portraitSRC).my-icon
+        img(src=portraitSRC).opponent-icon
+        div.my-name.name-label
+          span= myName
+        div.opponent-name.name-label
+          span= challengers.hard.opponentName
+        div.difficulty
+          span Hard
+        div.vs VS
+
+block modal-footer
\ No newline at end of file
diff --git a/app/views/home_view.coffee b/app/views/home_view.coffee
index 7289b4ca9..a16c1a9ba 100644
--- a/app/views/home_view.coffee
+++ b/app/views/home_view.coffee
@@ -28,12 +28,8 @@ module.exports = class HomeView extends View
     @$el.find('.modal').on 'shown.bs.modal', ->
       $('input:visible:first', @).focus()
 
-    wizOriginal = "52a00d55cf1818f2be00000b"
-    url = "/db/thang_type/#{wizOriginal}/version"
-    @wizardType = new ThangType()
-    @wizardType.url = -> url
-    @wizardType.fetch()
-    @wizardType.once 'sync', @initCanvas
+    @wizardType = ThangType.wizardType
+    if @wizardType.loaded then @initCanvas else @wizardType.once 'sync', @initCanvas, @
 
     # Try to find latest level and set "Play" link to go to that level
     if localStorage?
@@ -48,7 +44,7 @@ module.exports = class HomeView extends View
     else
       console.log("TODO: Insert here code to get latest level played from the database. If this can't be found, we just let the user play the first level.")
 
-  initCanvas: =>
+  initCanvas: ->
     @stage = new createjs.Stage($('#beginner-campaign canvas', @$el)[0])
     @createWizard()
 
diff --git a/app/views/play/ladder/play_modal.coffee b/app/views/play/ladder/play_modal.coffee
new file mode 100644
index 000000000..560397d37
--- /dev/null
+++ b/app/views/play/ladder/play_modal.coffee
@@ -0,0 +1,140 @@
+View = require 'views/kinds/ModalView'
+template = require 'templates/play/ladder/play_modal'
+ThangType = require 'models/ThangType'
+{me} = require 'lib/auth'
+
+module.exports = class LadderPlayModal extends View
+  id: "ladder-play-modal"
+  template: template
+  closeButton: true
+  startsLoading = true
+
+  constructor: (options, @level, @session, @team) ->
+    super(options)
+    @nameMap = {}
+    @otherTeam = if team is 'ogres' then 'humans' else 'ogres'
+    @startLoadingChallengersMaybe()
+    @wizardType = ThangType.wizardType
+    
+  # PART 1: Load challengers from the db unless some are in the matches
+
+  startLoadingChallengersMaybe: ->
+    matches = @session.get('matches')
+    if matches?.length then @loadNames() else @loadChallengers()
+
+  loadChallengers: ->
+    @challengers = new ChallengersData(@level, @team, @otherTeam, @session)
+    @challengers.on 'sync', @loadNames, @
+
+  # PART 2: Loading the names of the other users
+
+  loadNames: ->
+    @challengers = @getChallengers()
+    ids = (challenger.opponentID for challenger in _.values @challengers)
+
+    success = (@nameMap) =>
+      for challenger in _.values(@challengers)
+        challenger.opponentName = @nameMap[challenger.opponentID] or 'Anoner'
+      @checkWizardLoaded()
+
+    $.ajax('/db/user/-/names', {
+      data: {ids: ids}
+      type: 'POST'
+      success: success
+    })
+    
+  # PART 3: Make sure wizard is loaded
+  
+  checkWizardLoaded: ->
+    if @wizardType.loaded then @finishRendering() else @wizardType.once 'sync', @finishRendering, @
+    
+  # PART 4: Render
+
+  finishRendering: ->
+    @startsLoading = false
+    @render()
+
+  getRenderData: ->
+    ctx = super()
+    ctx.level = @level
+    ctx.levelID = @level.get('slug') or @level.id
+    ctx.teamName = _.string.titleize @team
+    ctx.teamID = @team
+    ctx.otherTeamID = @otherTeam
+    ctx.challengers = if not @startsLoading then @challengers else {}
+    ctx.portraitSRC = @wizardType.getPortraitSource()
+    ctx.myName = me.get('name') || 'Newcomer'
+    ctx
+    
+  # Choosing challengers
+
+  getChallengers: ->
+    # make an object of challengers to everything needed to link to them
+    challengers = {}
+    if @challengers
+      easyInfo = @challengeInfoFromSession(@challengers.easyPlayer.models[0])
+      mediumInfo = @challengeInfoFromSession(@challengers.mediumPlayer.models[0])
+      hardInfo = @challengeInfoFromSession(@challengers.hardPlayer.models[0])
+    else
+      matches = @session.get('matches')
+      won = (m for m in matches when m.metrics.rank < m.opponents[0].metrics.rank)
+      lost = (m for m in matches when m.metrics.rank > m.opponents[0].metrics.rank)
+      tied = (m for m in matches when m.metrics.rank is m.opponents[0].metrics.rank)
+      easyInfo = @challengeInfoFromMatches(won)
+      mediumInfo = @challengeInfoFromMatches(tied)
+      hardInfo = @challengeInfoFromMatches(lost)
+    @addChallenger easyInfo, challengers, 'easy'
+    @addChallenger mediumInfo, challengers, 'medium'
+    @addChallenger hardInfo, challengers, 'hard'
+    challengers
+
+  addChallenger: (info, challengers, title) ->
+    # check for duplicates first
+    return unless info
+    for key, value of challengers
+      return if value.sessionID is info.sessionID
+    challengers[title] = info
+
+  challengeInfoFromSession: (session) ->
+    # given a model from the db, return info needed for a link to the match
+    return unless session
+    return {
+      sessionID: session.id
+      opponentID: session.get('creator')
+    }
+
+  challengeInfoFromMatches: (matches) ->
+    return unless matches?.length
+    match = _.sample matches
+    opponent = match.opponents[0]
+    return {
+      sessionID: opponent.sessionID
+      opponentID: opponent.userID
+    }
+
+
+class ChallengersData
+  constructor: (@level, @team, @otherTeam, @session) ->
+    _.extend @, Backbone.Events
+    score = @session?.get('totalScore') or 25
+    @easyPlayer = new LeaderboardCollection(@level, {order:1, scoreOffset: score - 5, limit: 1, team: @otherTeam})
+    @easyPlayer.fetch()
+    @easyPlayer.once 'sync', @challengerLoaded, @
+    @mediumPlayer = new LeaderboardCollection(@level, {order:1, scoreOffset: score, limit: 1, team: @otherTeam})
+    @mediumPlayer.fetch()
+    @mediumPlayer.once 'sync', @challengerLoaded, @
+    @hardPlayer = new LeaderboardCollection(@level, {order:-1, scoreOffset: score + 5, limit: 1, team: @otherTeam})
+    @hardPlayer.fetch()
+    @hardPlayer.once 'sync', @challengerLoaded, @
+
+  challengerLoaded: ->
+    if @allLoaded()
+      @loaded = true
+      @trigger 'sync'
+
+  playerIDs: ->
+    collections = [@easyPlayer, @mediumPlayer, @hardPlayer]
+    (c.models[0].get('creator') for c in collections when c?.models[0])
+
+  allLoaded: ->
+    _.all [@easyPlayer.loaded, @mediumPlayer.loaded, @hardPlayer.loaded]
diff --git a/app/views/play/ladder_view.coffee b/app/views/play/ladder_view.coffee
index 25d15f484..b1d74b182 100644
--- a/app/views/play/ladder_view.coffee
+++ b/app/views/play/ladder_view.coffee
@@ -3,10 +3,11 @@ Level = require 'models/Level'
 Simulator = require 'lib/simulator/Simulator'
 LevelSession = require 'models/LevelSession'
 CocoCollection = require 'models/CocoCollection'
-LeaderboardCollection  = require 'collections/LeaderboardCollection'
 {teamDataFromLevel} = require './ladder/utils'
+
 LadderTabView = require './ladder/ladder_tab'
 MyMatchesTabView = require './ladder/my_matches_tab'
+LadderPlayModal = require './ladder/play_modal'
 
 HIGHEST_SCORE = 1000000
 
@@ -26,6 +27,7 @@ module.exports = class LadderView extends RootView
   events:
     'click #simulate-button': 'onSimulateButtonClick'
     'click #simulate-all-button': 'onSimulateAllButtonClick'
+    'click .play-button': 'onClickPlayButton'
 
   constructor: (options, @levelID) ->
     super(options)
@@ -97,3 +99,10 @@ module.exports = class LadderView extends RootView
     catch e
       console.log "There was a problem with the named simulation status: #{e}"
     $("#simulation-status-text").text @simulationStatus
+
+  onClickPlayButton: (e) ->
+    button = $(e.target).closest('.play-button')
+    teamID = button.data('team')
+    session = (s for s in @sessions.models when s.get('team') is teamID)[0]
+    modal = new LadderPlayModal({}, @level, session, teamID)
+    @openModalView modal
\ No newline at end of file

From d3b6836a06386c882890d4b266ea1734f45ec61b Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Mon, 3 Mar 2014 09:20:14 -0800
Subject: [PATCH 037/178] Fixed some bugs with the new ladder view when you
 haven't played before.

---
 app/templates/play/ladder/my_matches_tab.jade | 65 ++++++++++---------
 app/views/play/ladder/my_matches_tab.coffee   |  8 +--
 app/views/play/ladder/play_modal.coffee       |  5 +-
 3 files changed, 41 insertions(+), 37 deletions(-)

diff --git a/app/templates/play/ladder/my_matches_tab.jade b/app/templates/play/ladder/my_matches_tab.jade
index b9af08530..310beca34 100644
--- a/app/templates/play/ladder/my_matches_tab.jade
+++ b/app/templates/play/ladder/my_matches_tab.jade
@@ -7,17 +7,17 @@
 div#columns.row
   for team in teams
     div.matches-column.col-md-6
-      if team.matches.length
-        table.table.table-bordered.table-condensed
+      table.table.table-bordered.table-condensed
 
-          tr
-            th(colspan=4, style="color: #{team.primaryColor}")
-              span Your
-              span  
-              span= team.name
-              span  
-              span Matches
+        tr
+          th(colspan=4, style="color: #{team.primaryColor}")
+            span Your
+            span  
+            span= team.name
+            span  
+            span Matches
 
+            if team.session
               button.btn.btn-sm.btn-warning.pull-right.rank-button(data-session-id=team.session.id)
                 span.unavailable.hidden No New Code to Rank
                 span.rank.hidden Rank My Game!
@@ -25,28 +25,29 @@ div#columns.row
                 span.ranked.hidden Submitted for Ranking
                 span.failed.hidden Failed to Rank
 
+        tr
+          th Result
+          th Opponent
+          th When
+          th
+        for match in team.matches
           tr
-            th Result
-            th Opponent
-            th When
-            th
-          for match in team.matches
-            tr
-              td.state-cell
-                if match.state === 'win'
-                  span.win Win
-                if match.state === 'loss'
-                  span.loss Loss
-                if match.state === 'tie'
-                  span.tie Tie
-              td.name-cell= match.opponentName || "Anonymous"
-              td.time-cell= match.when
-              td.battle-cell
-                - var text = match.state === 'win' ? 'Watch your victory' : 'Defeat the ' + team.otherTeam
-                a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{match.sessionID}")= text
-      
-      else
-        div.alert.alert-warning
-          | No ranked matches played yet!
-          | Play some competitors on the right and then come back to get your game ranked.
+            td.state-cell
+              if match.state === 'win'
+                span.win Win
+              if match.state === 'loss'
+                span.loss Loss
+              if match.state === 'tie'
+                span.tie Tie
+            td.name-cell= match.opponentName || "Anonymous"
+            td.time-cell= match.when
+            td.battle-cell
+              - var text = match.state === 'win' ? 'Watch your victory' : 'Defeat the ' + team.otherTeam
+              a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{match.sessionID}")= text
+
+        if !team.matches.length
+          tr
+            td(colspan=4).alert.alert-warning
+              | No ranked matches for this team!
+              | Play against some competitors and then come back here to get your game ranked.
       
diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
index 110a289db..f4994d519 100644
--- a/app/views/play/ladder/my_matches_tab.coffee
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -62,9 +62,9 @@ module.exports = class MyMatchesTabView extends CocoView
     for team in @teams
       team.session = (s for s in @sessions.models when s.get('team') is team.id)[0]
       team.readyToRank = @readyToRank(team.session)
-      team.matches = (convertMatch(match) for match in team.session.get('matches') or [])
+      team.matches = (convertMatch(match) for match in team.session?.get('matches') or [])
       team.matches.reverse()
-      team.score = (team.session.get('totalScore') or 10).toFixed(2)
+      team.score = (team.session?.get('totalScore') or 10).toFixed(2)
       
     ctx
 
@@ -77,8 +77,8 @@ module.exports = class MyMatchesTabView extends CocoView
       @setRankingButtonText button, if @readyToRank(session) then 'rank' else 'unavailable'
 
   readyToRank: (session) ->
-    c1 = session.get('code')
-    c2 = session.get('submittedCode')
+    c1 = session?.get('code')
+    c2 = session?.get('submittedCode')
     c1 and not _.isEqual(c1, c2)
 
   rankSession: (e) ->
diff --git a/app/views/play/ladder/play_modal.coffee b/app/views/play/ladder/play_modal.coffee
index 560397d37..1a31618ad 100644
--- a/app/views/play/ladder/play_modal.coffee
+++ b/app/views/play/ladder/play_modal.coffee
@@ -2,6 +2,7 @@ View = require 'views/kinds/ModalView'
 template = require 'templates/play/ladder/play_modal'
 ThangType = require 'models/ThangType'
 {me} = require 'lib/auth'
+LeaderboardCollection = require 'collections/LeaderboardCollection'
 
 module.exports = class LadderPlayModal extends View
   id: "ladder-play-modal"
@@ -19,7 +20,7 @@ module.exports = class LadderPlayModal extends View
   # PART 1: Load challengers from the db unless some are in the matches
 
   startLoadingChallengersMaybe: ->
-    matches = @session.get('matches')
+    matches = @session?.get('matches')
     if matches?.length then @loadNames() else @loadChallengers()
 
   loadChallengers: ->
@@ -126,8 +127,10 @@ class ChallengersData
     @hardPlayer = new LeaderboardCollection(@level, {order:-1, scoreOffset: score + 5, limit: 1, team: @otherTeam})
     @hardPlayer.fetch()
     @hardPlayer.once 'sync', @challengerLoaded, @
+    console.log 'fetching challengers yes'
 
   challengerLoaded: ->
+    console.log 'challenger loaded'
     if @allLoaded()
       @loaded = true
       @trigger 'sync'

From feaeb1dc980d6b8a5732e49b22d86b87e4d94c3d Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Mon, 3 Mar 2014 10:21:51 -0800
Subject: [PATCH 038/178] Made the wizard icons colored based on user settings.

---
 app/models/ThangType.coffee               |  5 +++-
 app/templates/play/ladder/play_modal.jade | 16 +++++------
 app/views/play/ladder/play_modal.coffee   | 34 ++++++++++++++---------
 server/users/user_handler.coffee          | 12 ++++++--
 4 files changed, 43 insertions(+), 24 deletions(-)

diff --git a/app/models/ThangType.coffee b/app/models/ThangType.coffee
index c162f9287..00065b3ed 100644
--- a/app/models/ThangType.coffee
+++ b/app/models/ThangType.coffee
@@ -172,7 +172,10 @@ module.exports = class ThangType extends CocoModel
     key = spriteOptionsOrKey
     key = if _.isString(key) then key else @spriteSheetKey(@fillOptions(key))
     spriteSheet = @spriteSheets[key]
-    spriteSheet ?= @buildSpriteSheet({portraitOnly:true})
+    if not spriteSheet
+      options = if _.isPlainObject spriteOptionsOrKey then spriteOptionsOrKey else {}
+      options.portraitOnly = true
+      spriteSheet = @buildSpriteSheet(options)
     return unless spriteSheet
     canvas = $("<canvas width='#{size}' height='#{size}'></canvas>")
     stage = new createjs.Stage(canvas[0])
diff --git a/app/templates/play/ladder/play_modal.jade b/app/templates/play/ladder/play_modal.jade
index 6eae0c87c..d7f3b2c34 100644
--- a/app/templates/play/ladder/play_modal.jade
+++ b/app/templates/play/ladder/play_modal.jade
@@ -12,8 +12,8 @@ block modal-body-content
 
   a(href="/play/level/#{levelID}?team=#{teamID}")
     div.play-option
-      img(src=portraitSRC).my-icon
-      img(src=portraitSRC).opponent-icon
+      img(src=myPortrait).my-icon
+      img(src=genericPortrait).opponent-icon
       div.my-name.name-label
         span= myName
       div.opponent-name.name-label
@@ -25,8 +25,8 @@ block modal-body-content
   if challengers.easy
     a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.easy.sessionID}")
       div.play-option.easy-option
-        img(src=portraitSRC).my-icon
-        img(src=portraitSRC).opponent-icon
+        img(src=myPortrait).my-icon
+        img(src=challengers.easy.opponentImageSource||genericPortrait).opponent-icon
         div.my-name.name-label
           span= myName
         div.opponent-name.name-label
@@ -38,8 +38,8 @@ block modal-body-content
   if challengers.medium
     a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.medium.sessionID}")
       div.play-option.medium-option
-        img(src=portraitSRC).my-icon
-        img(src=portraitSRC).opponent-icon
+        img(src=myPortrait).my-icon
+        img(src=challengers.medium.opponentImageSource||genericPortrait).opponent-icon
         div.my-name.name-label
           span= myName
         div.opponent-name.name-label
@@ -51,8 +51,8 @@ block modal-body-content
   if challengers.hard
     a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.hard.sessionID}")
       div.play-option.hard-option
-        img(src=portraitSRC).my-icon
-        img(src=portraitSRC).opponent-icon
+        img(src=myPortrait).my-icon
+        img(src=challengers.hard.opponentImageSource||genericPortrait).opponent-icon
         div.my-name.name-label
           span= myName
         div.opponent-name.name-label
diff --git a/app/views/play/ladder/play_modal.coffee b/app/views/play/ladder/play_modal.coffee
index 1a31618ad..5ef5fc74c 100644
--- a/app/views/play/ladder/play_modal.coffee
+++ b/app/views/play/ladder/play_modal.coffee
@@ -24,8 +24,8 @@ module.exports = class LadderPlayModal extends View
     if matches?.length then @loadNames() else @loadChallengers()
 
   loadChallengers: ->
-    @challengers = new ChallengersData(@level, @team, @otherTeam, @session)
-    @challengers.on 'sync', @loadNames, @
+    @challengersCollection = new ChallengersData(@level, @team, @otherTeam, @session)
+    @challengersCollection.on 'sync', @loadNames, @
 
   # PART 2: Loading the names of the other users
 
@@ -35,11 +35,12 @@ module.exports = class LadderPlayModal extends View
 
     success = (@nameMap) =>
       for challenger in _.values(@challengers)
-        challenger.opponentName = @nameMap[challenger.opponentID] or 'Anoner'
+        challenger.opponentName = @nameMap[challenger.opponentID]?.name or 'Anoner'
+        challenger.opponentWizard = @nameMap[challenger.opponentID]?.wizard or {}
       @checkWizardLoaded()
 
     $.ajax('/db/user/-/names', {
-      data: {ids: ids}
+      data: {ids: ids, wizard: true}
       type: 'POST'
       success: success
     })
@@ -62,9 +63,18 @@ module.exports = class LadderPlayModal extends View
     ctx.teamName = _.string.titleize @team
     ctx.teamID = @team
     ctx.otherTeamID = @otherTeam
-    ctx.challengers = if not @startsLoading then @challengers else {}
-    ctx.portraitSRC = @wizardType.getPortraitSource()
+
+    ctx.challengers = @challengers or {}
+    for challenger in _.values ctx.challengers
+      continue unless challenger
+      if (not challenger.opponentImageSource) and challenger.opponentWizard?.colorConfig
+        challenger.opponentImageSource = @wizardType.getPortraitSource(
+          {colorConfig: challenger.opponentWizard.colorConfig})
+      
+    ctx.genericPortrait = @wizardType.getPortraitSource()
     ctx.myName = me.get('name') || 'Newcomer'
+    myColorConfig = me.get('wizard')?.colorConfig
+    ctx.myPortrait = if myColorConfig then @wizardType.getPortraitSource({colorConfig: myColorConfig}) else ctx.genericPortrait
     ctx
     
   # Choosing challengers
@@ -72,10 +82,10 @@ module.exports = class LadderPlayModal extends View
   getChallengers: ->
     # make an object of challengers to everything needed to link to them
     challengers = {}
-    if @challengers
-      easyInfo = @challengeInfoFromSession(@challengers.easyPlayer.models[0])
-      mediumInfo = @challengeInfoFromSession(@challengers.mediumPlayer.models[0])
-      hardInfo = @challengeInfoFromSession(@challengers.hardPlayer.models[0])
+    if @challengersCollection
+      easyInfo = @challengeInfoFromSession(@challengersCollection.easyPlayer.models[0])
+      mediumInfo = @challengeInfoFromSession(@challengersCollection.mediumPlayer.models[0])
+      hardInfo = @challengeInfoFromSession(@challengersCollection.hardPlayer.models[0])
     else
       matches = @session.get('matches')
       won = (m for m in matches when m.metrics.rank < m.opponents[0].metrics.rank)
@@ -127,10 +137,8 @@ class ChallengersData
     @hardPlayer = new LeaderboardCollection(@level, {order:-1, scoreOffset: score + 5, limit: 1, team: @otherTeam})
     @hardPlayer.fetch()
     @hardPlayer.once 'sync', @challengerLoaded, @
-    console.log 'fetching challengers yes'
-
+    
   challengerLoaded: ->
-    console.log 'challenger loaded'
     if @allLoaded()
       @loaded = true
       @trigger 'sync'
diff --git a/server/users/user_handler.coffee b/server/users/user_handler.coffee
index 465aae27f..87c414a55 100644
--- a/server/users/user_handler.coffee
+++ b/server/users/user_handler.coffee
@@ -114,11 +114,19 @@ UserHandler = class UserHandler extends Handler
     ids = ids.split(',') if _.isString ids
     ids = _.uniq ids
     
+    # TODO: Extend and repurpose this handler to return other public info about a user more flexibly,
+    #   say by a query parameter that lists public properties to return.
+    returnWizard = req.query.wizard or req.body.wizard
+    query = if returnWizard then {name:1, wizard:1} else {name:1}
+    
     makeFunc = (id) ->
       (callback) ->
-        User.findById(id, {name:1}).exec (err, document) ->
+        User.findById(id, query).exec (err, document) ->
           return done(err) if err
-          callback(null, document?.get('name') or '')
+          if document and returnWizard
+            callback(null, {name:document.get('name'), wizard:document.get('wizard') or {}})
+          else
+            callback(null, document?.get('name') or '')
           
     funcs = {}
     for id in ids

From 0d054bec8e8d53cd89e2e03df8b14fa91e3c17ff Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Mon, 3 Mar 2014 10:42:11 -0800
Subject: [PATCH 039/178] Refactored the universal wizard loading to happen
 silently when you import ThangType.

---
 app/models/ThangType.coffee             | 14 ++++++++------
 app/views/home_view.coffee              |  4 ++++
 app/views/play/ladder/play_modal.coffee | 16 +++++++++-------
 3 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/app/models/ThangType.coffee b/app/models/ThangType.coffee
index 00065b3ed..62f9eaa4e 100644
--- a/app/models/ThangType.coffee
+++ b/app/models/ThangType.coffee
@@ -214,9 +214,11 @@ module.exports = class ThangType extends CocoModel
   onFileUploaded: =>
     console.log 'Image uploaded'
 
-wizOriginal = "52a00d55cf1818f2be00000b"
-url = "/db/thang_type/#{wizOriginal}/version"
-wizardType = new module.exports()
-wizardType.url = -> url
-wizardType.fetch()
-module.exports.wizardType = wizardType
\ No newline at end of file
+  @loadUniversalWizard: ->
+    return @wizardType if @wizardType
+    wizOriginal = "52a00d55cf1818f2be00000b"
+    url = "/db/thang_type/#{wizOriginal}/version"
+    @wizardType = new module.exports()
+    @wizardType.url = -> url
+    @wizardType.fetch()
+    @wizardType
\ No newline at end of file
diff --git a/app/views/home_view.coffee b/app/views/home_view.coffee
index a16c1a9ba..3d9f30db2 100644
--- a/app/views/home_view.coffee
+++ b/app/views/home_view.coffee
@@ -11,6 +11,10 @@ module.exports = class HomeView extends View
   events:
     'mouseover #beginner-campaign': 'onMouseOverButton'
     'mouseout #beginner-campaign': 'onMouseOutButton'
+    
+  constructor: ->
+    super(arguments...)
+    ThangType.loadUniversalWizard()
 
   getRenderData: ->
     c = super()
diff --git a/app/views/play/ladder/play_modal.coffee b/app/views/play/ladder/play_modal.coffee
index 5ef5fc74c..30c3a116d 100644
--- a/app/views/play/ladder/play_modal.coffee
+++ b/app/views/play/ladder/play_modal.coffee
@@ -8,14 +8,14 @@ module.exports = class LadderPlayModal extends View
   id: "ladder-play-modal"
   template: template
   closeButton: true
-  startsLoading = true
+  startsLoading: true
 
   constructor: (options, @level, @session, @team) ->
     super(options)
     @nameMap = {}
     @otherTeam = if team is 'ogres' then 'humans' else 'ogres'
     @startLoadingChallengersMaybe()
-    @wizardType = ThangType.wizardType
+    @wizardType = ThangType.loadUniversalWizard()
     
   # PART 1: Load challengers from the db unless some are in the matches
 
@@ -66,15 +66,17 @@ module.exports = class LadderPlayModal extends View
 
     ctx.challengers = @challengers or {}
     for challenger in _.values ctx.challengers
-      continue unless challenger
+      continue unless challenger and @wizardType.loaded
       if (not challenger.opponentImageSource) and challenger.opponentWizard?.colorConfig
         challenger.opponentImageSource = @wizardType.getPortraitSource(
           {colorConfig: challenger.opponentWizard.colorConfig})
-      
-    ctx.genericPortrait = @wizardType.getPortraitSource()
+
+    if @wizardType.loaded
+      ctx.genericPortrait = @wizardType.getPortraitSource()
+      myColorConfig = me.get('wizard')?.colorConfig
+      ctx.myPortrait = if myColorConfig then @wizardType.getPortraitSource({colorConfig: myColorConfig}) else ctx.genericPortrait
+
     ctx.myName = me.get('name') || 'Newcomer'
-    myColorConfig = me.get('wizard')?.colorConfig
-    ctx.myPortrait = if myColorConfig then @wizardType.getPortraitSource({colorConfig: myColorConfig}) else ctx.genericPortrait
     ctx
     
   # Choosing challengers

From c5521a13114431b70a85ba7c7707f7c9e798ae7f Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Mon, 3 Mar 2014 11:04:03 -0800
Subject: [PATCH 040/178] Level now uses the universal wizard thang type.

---
 app/models/Level.coffee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/models/Level.coffee b/app/models/Level.coffee
index cb82d325a..fca1f8249 100644
--- a/app/models/Level.coffee
+++ b/app/models/Level.coffee
@@ -117,7 +117,6 @@ module.exports = class Level extends CocoModel
     else if path is '/'
       # We also we need to make sure we grab the Wizard ThangType and the Marks. Hackitrooooid!
       for [type, original] in [
-        ["Wizard", "52a00d55cf1818f2be00000b"]
         ["Highlight", "529f8fdbdacd325127000003"]
         ["Selection", "52aa5f7520fccb0000000002"]
         ["Target", "52b32ad97385ec3d03000001"]
@@ -126,4 +125,5 @@ module.exports = class Level extends CocoModel
         link = "/db/thang_type/#{original}/version"
         model = CocoModel.getOrMakeModelFromLink link, shouldLoadProjection
         models.push model if model
+      models.push ThangType.loadUniversalWizard()
     models

From ff3f3e5a07edd23845962592e12edfb54446f5e2 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Mon, 3 Mar 2014 11:11:27 -0800
Subject: [PATCH 041/178] Removed a link to the old team view.

---
 app/templates/play/ladder/ladder_tab.jade | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/app/templates/play/ladder/ladder_tab.jade b/app/templates/play/ladder/ladder_tab.jade
index f0c7a1b1f..457dd4914 100644
--- a/app/templates/play/ladder/ladder_tab.jade
+++ b/app/templates/play/ladder/ladder_tab.jade
@@ -17,7 +17,5 @@ div#columns.row
             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.
+              a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}")
+                span Battle as #{team.otherTeam}!

From 65d39e658d8b57409c7b243a3f645fad57b9ba56 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Mon, 3 Mar 2014 11:15:46 -0800
Subject: [PATCH 042/178] Removed the old team view cruft.

---
 app/lib/Router.coffee                  |   2 +-
 app/styles/play/ladder.sass            |   4 -
 app/styles/play/ladder/team.sass       |  12 --
 app/templates/play/ladder.jade         |   3 -
 app/templates/play/ladder/team.jade    | 112 --------------
 app/views/play/ladder/team_view.coffee | 195 -------------------------
 6 files changed, 1 insertion(+), 327 deletions(-)
 delete mode 100644 app/styles/play/ladder/team.sass
 delete mode 100644 app/templates/play/ladder/team.jade
 delete mode 100644 app/views/play/ladder/team_view.coffee

diff --git a/app/lib/Router.coffee b/app/lib/Router.coffee
index 43d53c479..435fdb7d4 100644
--- a/app/lib/Router.coffee
+++ b/app/lib/Router.coffee
@@ -19,7 +19,7 @@ module.exports = class CocoRouter extends Backbone.Router
     'editor/:model(/:slug_or_id)(/:subview)': 'editorModelView'
     
     # Experimenting with direct links
-    'play/ladder/:levelID/team/:team': go('play/ladder/team_view')
+#    'play/ladder/:levelID/team/:team': go('play/ladder/team_view')
 
     # db and file urls call the server directly
     'db/*path': 'routeToServer'
diff --git a/app/styles/play/ladder.sass b/app/styles/play/ladder.sass
index 3ca1754e3..6904c5739 100644
--- a/app/styles/play/ladder.sass
+++ b/app/styles/play/ladder.sass
@@ -12,10 +12,6 @@
     margin-bottom: 10px
     background-image: none
 
-  .intro-button
-    width: 45%
-    margin: 0 2.5%
-
   .name-col-cell
     max-width: 300px
     text-overflow: ellipsis
diff --git a/app/styles/play/ladder/team.sass b/app/styles/play/ladder/team.sass
deleted file mode 100644
index ca4cc9676..000000000
--- a/app/styles/play/ladder/team.sass
+++ /dev/null
@@ -1,12 +0,0 @@
-#ladder-team-view
-  #rank-button
-    margin-top: 15px
-  
-  #competitors-column .well
-    font-size: 18px
-    padding: 7px
-
-  #your-score
-    margin-top: 20px
-    text-align: center
-    font-size: 20px
\ No newline at end of file
diff --git a/app/templates/play/ladder.jade b/app/templates/play/ladder.jade
index 18802f55d..41360c85b 100644
--- a/app/templates/play/ladder.jade
+++ b/app/templates/play/ladder.jade
@@ -3,9 +3,6 @@ block content
 
   div#level-column
     h1= level.get('name')
-    
-    //if !me.get('anonymous')
-    //  a(href="/play/level/brawlwood-tutorial").intro-button.btn.btn-primary.btn-lg Play the Tutorial
 
   if me.get('anonymous')
     div#must-log-in
diff --git a/app/templates/play/ladder/team.jade b/app/templates/play/ladder/team.jade
deleted file mode 100644
index 22bfd5404..000000000
--- a/app/templates/play/ladder/team.jade
+++ /dev/null
@@ -1,112 +0,0 @@
-extends /templates/base
-block content
-
-  ol.breadcrumb
-    li
-      a(href="/") Home
-    li
-      a(href="/play/ladder/#{levelID}")= level.get('name')
-    li.active= teamName
-  
-  p
-    | In this level, you play against everyone who has ever written strategies for the opposing forces.
-    | Choose from the suggested players on the right, playing as many and as long as you like,
-    | and when you are ready to test your grand strategy against the whole ladder, return and click the rank button.
-    
-  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
-      button.btn.btn-warning.pull-right#rank-button
-        span.unavailable.hidden No New Code to Rank
-        span.rank.hidden Rank My Game!
-        span.ranking.hidden Submitting...
-        span.ranked.hidden Submitted for Ranking
-        span.failed.hidden Failed to Rank
-      
-      hr.clearfix(style="clear: both")
-
-      if matches.length
-        table.table.table-bordered.table-condensed
-          tr
-            th Result
-            th Opponent
-            th When
-          for match in matches
-            tr
-              td.state-cell
-                if match.state === 'win'
-                  span.win Win
-                if match.state === 'loss'
-                  span.loss Loss
-                if match.state === 'tie'
-                  span.tie Tie
-              td.name-cell= match.opponentName || "Anonymous"
-              td.time-cell= match.when
-              td.battle-cell
-                - var text = match.state === 'win' ? 'Watch your victory' : 'Defeat the ' + otherTeamID
-                a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{match.sessionID}")= text
-      
-      else
-        div.alert.alert-warning
-          | No ranked matches played yet!
-          | Play some competitors on the right and then come back to get your game ranked.
-      
-      // finish this once matches are available
-        
-    div#competitors-column.col-md-6
-      h3 Your Competitors
-
-      .well.text-muted
-        div.row
-          div.col-md-2
-            span.warmup Warmup
-            span : 
-          div.col-md-10
-            a(href="/play/level/#{levelID}?team=#{teamID}")
-              span.warmup Play #{teamID} vs Default #{otherTeamID}
-
-      if challengers.easy
-        .well
-          div.row.text-info.bg-info
-            div.col-md-2
-              span.easy Easy
-              span : 
-            div.col-md-10
-              a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.easy.sessionID}")
-                span Play #{teamID} vs 
-                strong= challengers.easy.opponentName
-                span  #{otherTeamID}
-            
-      if challengers.medium
-        .well
-          div.row.text-warning.bg-warning
-            div.col-md-2
-              span.medium Medium
-              span : 
-            div.col-md-10
-              a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.medium.sessionID}")
-                span Play #{teamID} vs 
-                strong= challengers.medium.opponentName
-                span  #{otherTeamID}
-
-      if challengers.hard
-        .well
-          div.row.text-danger.bg-danger
-            div.col-md-2
-              span.hard Hard
-              span : 
-            div.col-md-10
-              a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.hard.sessionID}")
-                span Play #{teamID} vs 
-                strong= challengers.hard.opponentName
-                span  #{otherTeamID}
diff --git a/app/views/play/ladder/team_view.coffee b/app/views/play/ladder/team_view.coffee
deleted file mode 100644
index 32adcbc24..000000000
--- a/app/views/play/ladder/team_view.coffee
+++ /dev/null
@@ -1,195 +0,0 @@
-RootView = require 'views/kinds/RootView'
-Level = require 'models/Level'
-LevelSession = require 'models/LevelSession'
-LeaderboardCollection  = require 'collections/LeaderboardCollection'
-
-module.exports = class LadderTeamView extends RootView
-  id: 'ladder-team-view'
-  template: require 'templates/play/ladder/team'
-  startsLoading: true
-
-  events:
-    'click #rank-button': 'rankSession'
-
-  # PART 1: Loading Level/Session
-
-  constructor: (options, @levelID, @team) ->
-    super(options)
-    @otherTeam = if team is 'ogres' then 'humans' else 'ogres'
-    @level = new Level(_id:@levelID)
-    @level.fetch()
-    @level.once 'sync', @onLevelLoaded, @
-
-    url = "/db/level/#{@levelID}/session?team=#{@team}"
-    @session = new LevelSession()
-    @session.url = -> url
-    @session.fetch()
-    @session.once 'sync', @onSessionLoaded, @
-
-  onLevelLoaded: -> @startLoadingChallengersMaybe()
-  onSessionLoaded: -> @startLoadingChallengersMaybe()
-
-  # PART 2: Loading some challengers if we don't have any matches yet
-
-  startLoadingChallengersMaybe: ->
-    return unless @level.loaded and @session.loaded
-    matches = @session.get('matches')
-    if matches?.length then @loadNames() else @loadChallengers()
-
-  loadChallengers: ->
-    @challengers = new ChallengersData(@level, @team, @otherTeam, @session)
-    @challengers.on 'sync', @loadNames, @
-
-  # PART 3: Loading the names of the other users
-
-  loadNames: ->
-    ids = []
-    ids.push match.opponents[0].userID for match in @session.get('matches') or []
-    ids = ids.concat(@challengers.playerIDs()) if @challengers
-
-    success = (@nameMap) =>
-      for match in @session.get('matches') or []
-        opponent = match.opponents[0]
-        opponent.userName = @nameMap[opponent.userID]
-      @finishRendering()
-
-    $.ajax('/db/user/-/names', {
-      data: {ids: ids}
-      type: 'POST'
-      success: success
-    })
-
-  # PART 4: Rendering
-
-  finishRendering: ->
-    @startsLoading = false
-    @render()
-
-  getRenderData: ->
-    ctx = super()
-    ctx.level = @level
-    ctx.levelID = @levelID
-    ctx.teamName = _.string.titleize @team
-    ctx.teamID = @team
-    ctx.otherTeamID = @otherTeam
-    ctx.challengers = if not @startsLoading then @getChallengers() else {}
-    ctx.readyToRank = @readyToRank()
-
-    convertMatch = (match) =>
-      opponent = match.opponents[0]
-      state = 'win'
-      state = 'loss' if match.metrics.rank > opponent.metrics.rank
-      state = 'tie' if match.metrics.rank is opponent.metrics.rank
-      {
-        state: state
-        opponentName: @nameMap[opponent.userID]
-        opponentID: opponent.userID
-        when: moment(match.date).fromNow()
-        sessionID: opponent.sessionID
-      }
-
-    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: ->
-    super()
-    @setRankingButtonText(if @readyToRank() then 'rank' else 'unavailable')
-
-  readyToRank: ->
-    c1 = @session.get('code')
-    c2 = @session.get('submittedCode')
-    c1 and not _.isEqual(c1, c2)
-
-  getChallengers: ->
-    # make an object of challengers to everything needed to link to them
-    challengers = {}
-    if @challengers
-      easyInfo = @challengeInfoFromSession(@challengers.easyPlayer.models[0])
-      mediumInfo = @challengeInfoFromSession(@challengers.mediumPlayer.models[0])
-      hardInfo = @challengeInfoFromSession(@challengers.hardPlayer.models[0])
-    else
-      matches = @session.get('matches')
-      won = (m for m in matches when m.metrics.rank < m.opponents[0].metrics.rank)
-      lost = (m for m in matches when m.metrics.rank > m.opponents[0].metrics.rank)
-      tied = (m for m in matches when m.metrics.rank is m.opponents[0].metrics.rank)
-      easyInfo = @challengeInfoFromMatches(won)
-      mediumInfo = @challengeInfoFromMatches(tied)
-      hardInfo = @challengeInfoFromMatches(lost)
-    @addChallenger easyInfo, challengers, 'easy'
-    @addChallenger mediumInfo, challengers, 'medium'
-    @addChallenger hardInfo, challengers, 'hard'
-    challengers
-
-  addChallenger: (info, challengers, title) ->
-    # check for duplicates first
-    return unless info
-    for key, value of challengers
-      return if value.sessionID is info.sessionID
-    challengers[title] = info
-
-  challengeInfoFromSession: (session) ->
-    # given a model from the db, return info needed for a link to the match
-    return unless session
-    return {
-      sessionID: session.id
-      opponentName: @nameMap[session.get('creator')] or 'Anoner'
-      opponentID: session.get('creator')
-    }
-
-  challengeInfoFromMatches: (matches) ->
-    return unless matches?.length
-    match = _.sample matches
-    opponent = match.opponents[0]
-    return {
-      sessionID: opponent.sessionID
-      opponentName: opponent.userName or 'Anoner'
-      opponentID: opponent.userID
-    }
-
-  rankSession: ->
-    return unless @readyToRank()
-    @setRankingButtonText('ranking')
-
-    success = => @setRankingButtonText('ranked')
-    failure = => @setRankingButtonText('failed')
-
-    $.ajax '/queue/scoring', {
-      type: 'POST'
-      data: { session: @session.id }
-      success: success
-      failure: failure
-    }
-
-  setRankingButtonText: (spanClass) ->
-    rankButton = $('#rank-button')
-    rankButton.find('span').addClass('hidden')
-    rankButton.find(".#{spanClass}").removeClass('hidden')
-    rankButton.toggleClass 'disabled', spanClass isnt 'rank'
-
-class ChallengersData
-  constructor: (@level, @team, @otherTeam, @session) ->
-    _.extend @, Backbone.Events
-    score = @session?.get('totalScore') or 25
-    @easyPlayer = new LeaderboardCollection(@level, {order:1, scoreOffset: score - 5, limit: 1, team: @otherTeam})
-    @easyPlayer.fetch()
-    @easyPlayer.once 'sync', @challengerLoaded, @
-    @mediumPlayer = new LeaderboardCollection(@level, {order:1, scoreOffset: score, limit: 1, team: @otherTeam})
-    @mediumPlayer.fetch()
-    @mediumPlayer.once 'sync', @challengerLoaded, @
-    @hardPlayer = new LeaderboardCollection(@level, {order:-1, scoreOffset: score + 5, limit: 1, team: @otherTeam})
-    @hardPlayer.fetch()
-    @hardPlayer.once 'sync', @challengerLoaded, @
-
-  challengerLoaded: ->
-    if @allLoaded()
-      @loaded = true
-      @trigger 'sync'
-
-  playerIDs: ->
-    collections = [@easyPlayer, @mediumPlayer, @hardPlayer]
-    (c.models[0].get('creator') for c in collections when c?.models[0])
-
-  allLoaded: ->
-    _.all [@easyPlayer.loaded, @mediumPlayer.loaded, @hardPlayer.loaded]

From 942b69ea9f1f12464972ca1881f6199e8710b212 Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <ruben.vereecken@student.uantwerpen.be>
Date: Mon, 3 Mar 2014 20:41:35 +0100
Subject: [PATCH 043/178] Created hasWriteAccess on Cocomodel, used it for
 level access

---
 app/models/CocoModel.coffee          | 21 +++++++++++++++++++++
 app/templates/editor/level/edit.jade |  7 +++----
 app/templates/kinds/search.jade      |  1 -
 app/views/editor/level/edit.coffee   |  1 +
 4 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee
index f4551b904..74dc336bf 100644
--- a/app/models/CocoModel.coffee
+++ b/app/models/CocoModel.coffee
@@ -184,4 +184,25 @@ class CocoModel extends Backbone.Model
   @isObjectID: (s) ->
     s.length is 24 and s.match(/[a-z0-9]/gi)?.length is 24
 
+  hasReadAccess: (actor) ->
+    # actor is a User object
+
+    if @get('permissions')?
+      for permission in @get('permissions')
+        if permission.target is 'public' or actor.get('_id') is permission.target
+          return true if permission.access in ['owner', 'read']
+
+    return false
+
+    hasWriteAccess: (actor) ->
+      # actor is a User object
+
+    if @get('permissions')?
+      for permission in @get('permissions')
+        if permission.target is 'public' or actor.get('_id') is permission.target
+          return true if permission.access in ['owner', 'write']
+
+    return false
+
+
 module.exports = CocoModel
diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade
index cdc97cd2a..e63cdd2b9 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -29,10 +29,9 @@ block outer_content
             
             
           ul.nav.navbar-nav.navbar-right
-            li(data-toggle="coco-modal", data-target="modal/revert", data-i18n="revert.revert").btn.btn-primary.navbar-btn#revert-button Revert
-
-            li(data-i18n="common.save").btn.btn-primary.navbar-btn#commit-level-start-button Save
-            li(data-i18n="common.fork").btn.btn-primary.navbar-btn#fork-level-start-button Fork
+            li(data-toggle="coco-modal", data-target="modal/revert", data-i18n="revert.revert", disabled=authorized === true ? undefined : "true").btn.btn-primary.navbar-btn#revert-button Revert
+            li(data-i18n="common.save", disabled=authorized === true ? undefined : "true").btn.btn-primary.navbar-btn#commit-level-start-button Save
+            li(data-i18n="common.fork", disabled=authorized === true ? undefined : "true").btn.btn-primary.navbar-btn#fork-level-start-button Fork
             li(title="⌃↩ or ⌘↩: Play preview of current level", data-i18n="common.play")#play-button.btn.btn-inverse.banner.navbar-btn Play!
 
             li.divider
diff --git a/app/templates/kinds/search.jade b/app/templates/kinds/search.jade
index eda4c0f2b..296581a47 100644
--- a/app/templates/kinds/search.jade
+++ b/app/templates/kinds/search.jade
@@ -11,7 +11,6 @@ block content
     a.btn.btn-primary.open-modal-button(data-toggle="coco-modal", data-target="modal/signup", role="button") Sign Up to Create a New #{modelLabel}
   else
     a.btn.btn-primary.open-modal-button(href='#new-model-modal', role="button", data-toggle="modal" data-i18n="#{currentNew}") Create a New Something
-
   input#search(data-i18n="[placeholder]#{currentSearch}")
   hr
   div.results
diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/edit.coffee
index bbafd529d..c79439800 100644
--- a/app/views/editor/level/edit.coffee
+++ b/app/views/editor/level/edit.coffee
@@ -63,6 +63,7 @@ module.exports = class EditorLevelView extends View
   getRenderData: (context={}) ->
     context = super(context)
     context.level = @level
+    context.authorized = me.isAdmin() or @level.hasWriteAccess(me)
     context
 
   afterRender: ->

From cc9cf64539592332f1793b2e447bec64fc820fb2 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 3 Mar 2014 11:55:26 -0800
Subject: [PATCH 044/178] Corrected link to view your own matches in
 leaderboard view.

---
 app/templates/play/ladder/ladder_tab.jade | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/templates/play/ladder/ladder_tab.jade b/app/templates/play/ladder/ladder_tab.jade
index f0c7a1b1f..8f79bd624 100644
--- a/app/templates/play/ladder/ladder_tab.jade
+++ b/app/templates/play/ladder/ladder_tab.jade
@@ -20,4 +20,4 @@ div#columns.row
               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.
+                a(href="/play/ladder/#{level.get('slug') || level.id}/team/#{team.id}") View your #{team.id} matches.

From fb75ad36e7740133dcd1fcc577bcf7f97758fe66 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Mon, 3 Mar 2014 12:04:31 -0800
Subject: [PATCH 045/178] Added team icons to the ladder play view.

---
 .../pages/play/ladder/humans_ladder_easy.png  | Bin 0 -> 22579 bytes
 .../pages/play/ladder/humans_ladder_hard.png  | Bin 0 -> 24237 bytes
 .../play/ladder/humans_ladder_medium.png      | Bin 0 -> 18770 bytes
 .../play/ladder/humans_ladder_tutorial.png    | Bin 0 -> 22473 bytes
 .../pages/play/ladder/ogres_ladder_easy.png   | Bin 0 -> 23086 bytes
 .../pages/play/ladder/ogres_ladder_hard.png   | Bin 0 -> 25821 bytes
 .../pages/play/ladder/ogres_ladder_medium.png | Bin 0 -> 23199 bytes
 .../play/ladder/ogres_ladder_tutorial.png     | Bin 0 -> 26542 bytes
 app/styles/play/ladder/play_modal.sass        |  33 ++++++++++++++++++
 app/templates/play/ladder/play_modal.jade     |  24 ++++++++-----
 app/views/play/ladder/play_modal.coffee       |   9 +++++
 11 files changed, 58 insertions(+), 8 deletions(-)
 create mode 100644 app/assets/images/pages/play/ladder/humans_ladder_easy.png
 create mode 100644 app/assets/images/pages/play/ladder/humans_ladder_hard.png
 create mode 100644 app/assets/images/pages/play/ladder/humans_ladder_medium.png
 create mode 100644 app/assets/images/pages/play/ladder/humans_ladder_tutorial.png
 create mode 100644 app/assets/images/pages/play/ladder/ogres_ladder_easy.png
 create mode 100644 app/assets/images/pages/play/ladder/ogres_ladder_hard.png
 create mode 100644 app/assets/images/pages/play/ladder/ogres_ladder_medium.png
 create mode 100644 app/assets/images/pages/play/ladder/ogres_ladder_tutorial.png

diff --git a/app/assets/images/pages/play/ladder/humans_ladder_easy.png b/app/assets/images/pages/play/ladder/humans_ladder_easy.png
new file mode 100644
index 0000000000000000000000000000000000000000..ea34dcc5b75a4a7be749482e9a4b5173f8036175
GIT binary patch
literal 22579
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

literal 0
HcmV?d00001

diff --git a/app/assets/images/pages/play/ladder/humans_ladder_hard.png b/app/assets/images/pages/play/ladder/humans_ladder_hard.png
new file mode 100644
index 0000000000000000000000000000000000000000..8cd03225d4ac184ef24c71f9bebe9e72e7a4c193
GIT binary patch
literal 24237
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
KMNUMnLSTXojnLNs

literal 0
HcmV?d00001

diff --git a/app/assets/images/pages/play/ladder/humans_ladder_medium.png b/app/assets/images/pages/play/ladder/humans_ladder_medium.png
new file mode 100644
index 0000000000000000000000000000000000000000..f4b5fdf946770cba7874cef46e7925bcd61796ff
GIT binary patch
literal 18770
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
A$p8QV

literal 0
HcmV?d00001

diff --git a/app/assets/images/pages/play/ladder/humans_ladder_tutorial.png b/app/assets/images/pages/play/ladder/humans_ladder_tutorial.png
new file mode 100644
index 0000000000000000000000000000000000000000..8e34fc9244e077c17f06102068a0a2b8254abfc9
GIT binary patch
literal 22473
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

literal 0
HcmV?d00001

diff --git a/app/assets/images/pages/play/ladder/ogres_ladder_easy.png b/app/assets/images/pages/play/ladder/ogres_ladder_easy.png
new file mode 100644
index 0000000000000000000000000000000000000000..d5e4695ff0715bd69e0db789e8b693742c214eed
GIT binary patch
literal 23086
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
LNkvXXu0mjfL5d8f

literal 0
HcmV?d00001

diff --git a/app/assets/images/pages/play/ladder/ogres_ladder_hard.png b/app/assets/images/pages/play/ladder/ogres_ladder_hard.png
new file mode 100644
index 0000000000000000000000000000000000000000..36204caf5d95697e81c8a0e1a5e17af8f41d061f
GIT binary patch
literal 25821
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

literal 0
HcmV?d00001

diff --git a/app/assets/images/pages/play/ladder/ogres_ladder_medium.png b/app/assets/images/pages/play/ladder/ogres_ladder_medium.png
new file mode 100644
index 0000000000000000000000000000000000000000..5e327d74b5ba960224a571b95ea626a5ea4ba0a6
GIT binary patch
literal 23199
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
CbO8VW

literal 0
HcmV?d00001

diff --git a/app/assets/images/pages/play/ladder/ogres_ladder_tutorial.png b/app/assets/images/pages/play/ladder/ogres_ladder_tutorial.png
new file mode 100644
index 0000000000000000000000000000000000000000..16e9527285183e766fd6af67707b93a6398cb80a
GIT binary patch
literal 26542
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%0DeL%**fUcS+&aW~=h%5-VKjBBCq|`jVr1gVPkr
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
Z{6Di-IP(%LT)+ST002ovPDHLkV1hVB$;1Ev

literal 0
HcmV?d00001

diff --git a/app/styles/play/ladder/play_modal.sass b/app/styles/play/ladder/play_modal.sass
index 8dc69a5ae..7d87d475b 100644
--- a/app/styles/play/ladder/play_modal.sass
+++ b/app/styles/play/ladder/play_modal.sass
@@ -21,14 +21,45 @@
     opacity: 0.4
     
     border-radius: 5px
+    .only-one
+      -webkit-transition: opacity 0.3s ease-in-out
+      -moz-transition: opacity 0.3s ease-in-out
+      -ms-transition: opacity 0.3s ease-in-out
+      -o-transition: opacity 0.3s ease-in-out
+      transition: opacity 0.3s ease-in-out
+      opacity: 0
     
   .play-option:hover
     opacity: 1
+    .only-one
+      opacity: 1
     
   .my-icon
     position: relative
     left: 0
     top: -10px
+    z-index: 1
+    
+  .my-team-icon
+    height: 60px
+    position: relative
+    top: -10px
+    left: 10px
+    z-index: 0
+    
+  .opponent-team-icon
+    height: 60px
+    position: relative
+    top: 10px
+    right: 10px
+    z-index: 0
+    float: right
+    -moz-transform: scaleX(-1)
+    -o-transform: scaleX(-1)
+    -webkit-transform: scaleX(-1)
+    transform: scaleX(-1)
+    filter: FlipH
+    -ms-filter: "FlipH"
     
   .opponent-icon
     position: relative
@@ -41,6 +72,7 @@
     transform: scaleX(-1)
     filter: FlipH
     -ms-filter: "FlipH"
+    z-index: 1
     
   .name-label
     border-bottom: 20px solid lightslategray
@@ -51,6 +83,7 @@
     color: black
     font-weight: bold
     text-align: center
+    z-index: 2
     
     span
       position: relative
diff --git a/app/templates/play/ladder/play_modal.jade b/app/templates/play/ladder/play_modal.jade
index d7f3b2c34..6c1cd22d6 100644
--- a/app/templates/play/ladder/play_modal.jade
+++ b/app/templates/play/ladder/play_modal.jade
@@ -12,9 +12,11 @@ block modal-body-content
 
   a(href="/play/level/#{levelID}?team=#{teamID}")
     div.play-option
-      img(src=myPortrait).my-icon
+      img(src=myPortrait).my-icon.only-one
+      img(src="/images/pages/play/ladder/"+teamID+"_ladder_tutorial.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one
       img(src=genericPortrait).opponent-icon
-      div.my-name.name-label
+      img(src="/images/pages/play/ladder/"+otherTeamID+"_ladder_tutorial.png", style="border: 1px solid #{opponentTeamColor}; background: #{opponentTeamBackgroundColor}").opponent-team-icon.img-circle
+      div.my-name.name-label.only-one
         span= myName
       div.opponent-name.name-label
         span Simple AI
@@ -25,9 +27,11 @@ block modal-body-content
   if challengers.easy
     a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.easy.sessionID}")
       div.play-option.easy-option
-        img(src=myPortrait).my-icon
+        img(src=myPortrait).my-icon.only-one
+        img(src="/images/pages/play/ladder/"+teamID+"_ladder_easy.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one
         img(src=challengers.easy.opponentImageSource||genericPortrait).opponent-icon
-        div.my-name.name-label
+        img(src="/images/pages/play/ladder/"+otherTeamID+"_ladder_easy.png", style="border: 1px solid #{opponentTeamColor}; background: #{opponentTeamBackgroundColor}").opponent-team-icon.img-circle
+        div.my-name.name-label.only-one
           span= myName
         div.opponent-name.name-label
           span= challengers.easy.opponentName
@@ -38,9 +42,11 @@ block modal-body-content
   if challengers.medium
     a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.medium.sessionID}")
       div.play-option.medium-option
-        img(src=myPortrait).my-icon
+        img(src=myPortrait).my-icon.only-one
+        img(src="/images/pages/play/ladder/"+teamID+"_ladder_medium.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one
         img(src=challengers.medium.opponentImageSource||genericPortrait).opponent-icon
-        div.my-name.name-label
+        img(src="/images/pages/play/ladder/"+otherTeamID+"_ladder_medium.png", style="border: 1px solid #{opponentTeamColor}; background: #{opponentTeamBackgroundColor}").opponent-team-icon.img-circle
+        div.my-name.name-label.only-one
           span= myName
         div.opponent-name.name-label
           span= challengers.medium.opponentName
@@ -51,9 +57,11 @@ block modal-body-content
   if challengers.hard
     a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.hard.sessionID}")
       div.play-option.hard-option
-        img(src=myPortrait).my-icon
+        img(src=myPortrait).my-icon.only-one
+        img(src="/images/pages/play/ladder/"+teamID+"_ladder_hard.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one
         img(src=challengers.hard.opponentImageSource||genericPortrait).opponent-icon
-        div.my-name.name-label
+        img(src="/images/pages/play/ladder/"+otherTeamID+"_ladder_hard.png", style="border: 1px solid #{opponentTeamColor}; background: #{opponentTeamBackgroundColor}").opponent-team-icon.img-circle
+        div.my-name.name-label.only-one
           span= myName
         div.opponent-name.name-label
           span= challengers.hard.opponentName
diff --git a/app/views/play/ladder/play_modal.coffee b/app/views/play/ladder/play_modal.coffee
index 30c3a116d..28f689b14 100644
--- a/app/views/play/ladder/play_modal.coffee
+++ b/app/views/play/ladder/play_modal.coffee
@@ -3,6 +3,7 @@ template = require 'templates/play/ladder/play_modal'
 ThangType = require 'models/ThangType'
 {me} = require 'lib/auth'
 LeaderboardCollection = require 'collections/LeaderboardCollection'
+{teamDataFromLevel} = require './utils'
 
 module.exports = class LadderPlayModal extends View
   id: "ladder-play-modal"
@@ -63,6 +64,14 @@ module.exports = class LadderPlayModal extends View
     ctx.teamName = _.string.titleize @team
     ctx.teamID = @team
     ctx.otherTeamID = @otherTeam
+    
+    teamsList = teamDataFromLevel @level
+    teams = {}
+    teams[team.id] = team for team in teamsList
+    ctx.teamColor = teams[@team].primaryColor
+    ctx.teamBackgroundColor = teams[@team].bgColor
+    ctx.opponentTeamColor = teams[@otherTeam].primaryColor
+    ctx.opponentTeamBackgroundColor = teams[@otherTeam].bgColor
 
     ctx.challengers = @challengers or {}
     for challenger in _.values ctx.challengers

From 1efb96f24ac06b9dfea414cb38ded8735daa2f37 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Mon, 3 Mar 2014 12:08:11 -0800
Subject: [PATCH 046/178] Merge branch 'master' of
 https://github.com/codecombat/codecombat

Conflicts:
	app/templates/play/ladder/ladder_tab.jade
---
 app/templates/play/ladder/ladder_tab.jade | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/templates/play/ladder/ladder_tab.jade b/app/templates/play/ladder/ladder_tab.jade
index 457dd4914..eed7e9d2c 100644
--- a/app/templates/play/ladder/ladder_tab.jade
+++ b/app/templates/play/ladder/ladder_tab.jade
@@ -18,4 +18,4 @@ div#columns.row
             td.name-col-cell= session.get('creatorName') || "Anonymous"
             td
               a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}")
-                span Battle as #{team.otherTeam}!
+                span Battle as #{team.otherTeam}!
\ No newline at end of file

From a5864c4f0c7bd5e6047e838e537ec707ef23a277 Mon Sep 17 00:00:00 2001
From: Michael Schmatz <schmatz@umich.edu>
Date: Mon, 3 Mar 2014 12:10:24 -0800
Subject: [PATCH 047/178] Live leaderboard updating

---
 app/views/play/ladder/my_matches_tab.coffee |  4 ++++
 app/views/play/ladder_view.coffee           | 13 ++++++++++++-
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
index f4994d519..00aec7c8c 100644
--- a/app/views/play/ladder/my_matches_tab.coffee
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -14,6 +14,9 @@ module.exports = class MyMatchesTabView extends CocoView
 
   constructor: (options, @level, @sessions) ->
     super(options)
+    @refreshMatches()
+    
+  refreshMatches: ->
     @teams = teamDataFromLevel @level
     @nameMap = {}
     @loadNames()
@@ -82,6 +85,7 @@ module.exports = class MyMatchesTabView extends CocoView
     c1 and not _.isEqual(c1, c2)
 
   rankSession: (e) ->
+    console.log "Clicked"
     button = $(e.target).closest('.rank-button')
     sessionID = button.data('session-id')
     session = _.find @sessions.models, { id: sessionID }
diff --git a/app/views/play/ladder_view.coffee b/app/views/play/ladder_view.coffee
index b1d74b182..bc4f0fd6d 100644
--- a/app/views/play/ladder_view.coffee
+++ b/app/views/play/ladder_view.coffee
@@ -64,7 +64,18 @@ module.exports = class LadderView extends RootView
     return if @startsLoading
     @insertSubView(@ladderTab = new LadderTabView({}, @level, @sessions))
     @insertSubView(@myMatchesTab = new MyMatchesTabView({}, @level, @sessions))
-
+    setInterval(@fetchSessionsAndRefreshViews.bind(@), 10000)
+  
+  fetchSessionsAndRefreshViews: ->
+    @sessions.fetch({"success": @refreshViews})
+    
+  refreshViews: =>
+    @ladderTab.constructor({}, @level, @sessions)
+    @myMatchesTab.refreshMatches()
+    console.log "refreshed views!"
+    
+    
+    
   # Simulations
 
   onSimulateAllButtonClick: (e) ->

From ee920afea9cdb78e933550de89c8cf4730221381 Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <ruben.vereecken@student.uantwerpen.be>
Date: Mon, 3 Mar 2014 21:13:02 +0100
Subject: [PATCH 048/178] Disabled buttons for non-owners in Article Editor

---
 app/models/CocoModel.coffee                    | 4 ++--
 app/templates/editor/article/edit.jade         | 6 +++---
 app/views/editor/article/edit.coffee           | 1 +
 app/views/editor/level/scripts_tab_view.coffee | 1 +
 4 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee
index 74dc336bf..ba4ff850c 100644
--- a/app/models/CocoModel.coffee
+++ b/app/models/CocoModel.coffee
@@ -194,8 +194,8 @@ class CocoModel extends Backbone.Model
 
     return false
 
-    hasWriteAccess: (actor) ->
-      # actor is a User object
+  hasWriteAccess: (actor) ->
+    # actor is a User object
 
     if @get('permissions')?
       for permission in @get('permissions')
diff --git a/app/templates/editor/article/edit.jade b/app/templates/editor/article/edit.jade
index a729bf67a..e7dff7cd7 100644
--- a/app/templates/editor/article/edit.jade
+++ b/app/templates/editor/article/edit.jade
@@ -10,9 +10,9 @@ block content
       li.active
         | #{article.attributes.name}
 
-  button(data-toggle="coco-modal", data-target="modal/revert", data-i18n="revert.revert").btn.btn-primary#revert-button Revert
-  button(data-i18n="article.edit_btn_preview").btn.btn-primary#preview-button Preview
-  button(data-toggle="coco-modal", data-target="modal/save_version", data-i18n="common.save").btn.btn-primary#save-button Save
+  button(data-toggle="coco-modal", data-target="modal/revert", data-i18n="revert.revert", disabled=authorized === true ? undefined : "true").btn.btn-primary#revert-button Revert
+  button(data-i18n="article.edit_btn_preview", disabled=authorized === true ? undefined : "true").btn.btn-primary#preview-button Preview
+  button(data-toggle="coco-modal", data-target="modal/save_version", data-i18n="common.save", disabled=authorized === true ? undefined : "true").btn.btn-primary#save-button Save
 
   h3(data-i18n="article.edit_article_title") Edit Article
     span
diff --git a/app/views/editor/article/edit.coffee b/app/views/editor/article/edit.coffee
index 05df5291d..d3c2d4c1c 100644
--- a/app/views/editor/article/edit.coffee
+++ b/app/views/editor/article/edit.coffee
@@ -56,6 +56,7 @@ module.exports = class ArticleEditView extends View
   getRenderData: (context={}) ->
     context = super(context)
     context.article = @article
+    context.authorized = me.isAdmin() or @article.hasWriteAccess(me)
     context
 
   openPreview: =>
diff --git a/app/views/editor/level/scripts_tab_view.coffee b/app/views/editor/level/scripts_tab_view.coffee
index 45b5c210d..9da71e31c 100644
--- a/app/views/editor/level/scripts_tab_view.coffee
+++ b/app/views/editor/level/scripts_tab_view.coffee
@@ -59,6 +59,7 @@ module.exports = class ScriptsTabView extends View
       thangIDs: thangIDs
       dimensions: @dimensions
       supermodel: @supermodel
+      readOnly: not me.isAdmin() and not @level.hasWriteAccess(me)
       callbacks:
         change: @onScriptChanged
       nodeClasses:

From 0c45b6c0e3fca4c6f6152f4dcaaf05fb605afa4c Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 3 Mar 2014 12:21:59 -0800
Subject: [PATCH 049/178] Fixes for ladder refreshing.

---
 app/views/play/ladder/ladder_tab.coffee |  7 +++++--
 app/views/play/ladder_view.coffee       | 13 ++++++-------
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/app/views/play/ladder/ladder_tab.coffee b/app/views/play/ladder/ladder_tab.coffee
index 96e268e3c..4d236fe9e 100644
--- a/app/views/play/ladder/ladder_tab.coffee
+++ b/app/views/play/ladder/ladder_tab.coffee
@@ -24,14 +24,17 @@ module.exports = class LadderView extends CocoView
     super(options)
     @teams = teamDataFromLevel @level
     @leaderboards = {}
+    @refreshLadder()
+
+  refreshLadder: ->
     for team in @teams
+      @leaderboards[team.id]?.off 'sync'
 #      teamSession = _.find @sessions.models, (session) -> session.get('team') is team.id
       teamSession = null
 #      console.log "Team session: #{JSON.stringify teamSession}"
       @leaderboards[team.id] = new LeaderboardData(@level, team.id, teamSession)
       @leaderboards[team.id].once 'sync', @onLeaderboardLoaded, @
 
-  onChallengersLoaded: -> @renderMaybe()
   onLeaderboardLoaded: -> @renderMaybe()
 
   renderMaybe: ->
@@ -48,7 +51,7 @@ module.exports = class LadderView extends CocoView
     team.leaderboard = @leaderboards[team.id] for team in @teams
     ctx.levelID = @levelID
     ctx
-    
+
 class LeaderboardData
   constructor: (@level, @team, @session) ->
     _.extend @, Backbone.Events
diff --git a/app/views/play/ladder_view.coffee b/app/views/play/ladder_view.coffee
index bc4f0fd6d..5bc430eaa 100644
--- a/app/views/play/ladder_view.coffee
+++ b/app/views/play/ladder_view.coffee
@@ -65,17 +65,16 @@ module.exports = class LadderView extends RootView
     @insertSubView(@ladderTab = new LadderTabView({}, @level, @sessions))
     @insertSubView(@myMatchesTab = new MyMatchesTabView({}, @level, @sessions))
     setInterval(@fetchSessionsAndRefreshViews.bind(@), 10000)
-  
+
   fetchSessionsAndRefreshViews: ->
     @sessions.fetch({"success": @refreshViews})
-    
+
   refreshViews: =>
-    @ladderTab.constructor({}, @level, @sessions)
+    @ladderTab.refreshLadder()
     @myMatchesTab.refreshMatches()
     console.log "refreshed views!"
-    
-    
-    
+
+
   # Simulations
 
   onSimulateAllButtonClick: (e) ->
@@ -116,4 +115,4 @@ module.exports = class LadderView extends RootView
     teamID = button.data('team')
     session = (s for s in @sessions.models when s.get('team') is teamID)[0]
     modal = new LadderPlayModal({}, @level, session, teamID)
-    @openModalView modal
\ No newline at end of file
+    @openModalView modal

From 05b4f536c10fc2811ece438e825a85b569ebc1ec Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <ruben.vereecken@student.uantwerpen.be>
Date: Mon, 3 Mar 2014 21:22:04 +0100
Subject: [PATCH 050/178] Fixed a link to point correctly

---
 app/templates/editor/article/edit.jade | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/templates/editor/article/edit.jade b/app/templates/editor/article/edit.jade
index e7dff7cd7..7c6a7136a 100644
--- a/app/templates/editor/article/edit.jade
+++ b/app/templates/editor/article/edit.jade
@@ -6,7 +6,7 @@ block content
       li
         a(href="/editor", data-i18n="editor.main_title") CodeCombat Editors
       li
-        a(href="/editor/thang", data-i18n="editor.article_title") Article Editor
+        a(href="/editor/article", data-i18n="editor.article_title") Article Editor
       li.active
         | #{article.attributes.name}
 

From 0c4a2a2f2b8b58be64889d6bb371840f6b4eadf0 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 3 Mar 2014 12:27:32 -0800
Subject: [PATCH 051/178] Multiplied visible scores by 100 for more awesome.

---
 app/templates/play/ladder/ladder_tab.jade | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/templates/play/ladder/ladder_tab.jade b/app/templates/play/ladder/ladder_tab.jade
index eed7e9d2c..c3090caa3 100644
--- a/app/templates/play/ladder/ladder_tab.jade
+++ b/app/templates/play/ladder/ladder_tab.jade
@@ -14,7 +14,7 @@ div#columns.row
         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.score-cell= Math.round(session.get('totalScore') * 100)
             td.name-col-cell= session.get('creatorName') || "Anonymous"
             td
               a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}")

From 461d66c795e0fb38852bcdf7815b9502cec6798a Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 3 Mar 2014 13:02:34 -0800
Subject: [PATCH 052/178] Typo in my matches team ranking.

---
 app/templates/play/ladder/my_matches_tab.jade | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/templates/play/ladder/my_matches_tab.jade b/app/templates/play/ladder/my_matches_tab.jade
index 310beca34..d2b543478 100644
--- a/app/templates/play/ladder/my_matches_tab.jade
+++ b/app/templates/play/ladder/my_matches_tab.jade
@@ -43,7 +43,7 @@ div#columns.row
             td.time-cell= match.when
             td.battle-cell
               - var text = match.state === 'win' ? 'Watch your victory' : 'Defeat the ' + team.otherTeam
-              a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{match.sessionID}")= text
+              a(href="/play/level/#{levelID}?team=#{team.id}&opponent=#{match.sessionID}")= text
 
         if !team.matches.length
           tr

From d66a9d6be03d42f3730b8e47c0f567f63dd0fe87 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Mon, 3 Mar 2014 13:21:05 -0800
Subject: [PATCH 053/178] Set up a generic choose tab for root views so
 hash->tab behavior is baked in.

---
 app/views/kinds/RootView.coffee         | 9 ++++++++-
 app/views/play/ladder/ladder_tab.coffee | 2 +-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/app/views/kinds/RootView.coffee b/app/views/kinds/RootView.coffee
index 6dbc36be0..b27ebb92f 100644
--- a/app/views/kinds/RootView.coffee
+++ b/app/views/kinds/RootView.coffee
@@ -38,8 +38,15 @@ module.exports = class RootView extends CocoView
     location.hash = ''
     location.hash = hash
     @buildLanguages()
+    
+  afterRender: ->
+    super(arguments...)
+    @chooseTab(location.hash.replace('#','')) if location.hash
 
-    # TODO: automate tabs to put in hashes and navigate to them here
+  chooseTab: (category) ->
+    $("a[href='##{category}']", @$el).tab('show')
+
+  # TODO: automate tabs to put in hashes when they are clicked
 
   buildLanguages: ->
     $select = @$el.find(".language-dropdown").empty()
diff --git a/app/views/play/ladder/ladder_tab.coffee b/app/views/play/ladder/ladder_tab.coffee
index 4d236fe9e..323ca86fe 100644
--- a/app/views/play/ladder/ladder_tab.coffee
+++ b/app/views/play/ladder/ladder_tab.coffee
@@ -15,7 +15,7 @@ class LevelSessionsCollection extends CocoCollection
     super()
     @url = "/db/level/#{levelID}/all_sessions"
 
-module.exports = class LadderView extends CocoView
+module.exports = class LadderTabView extends CocoView
   id: 'ladder-tab-view'
   template: require 'templates/play/ladder/ladder_tab'
   startsLoading: true

From 0aa8e7bb7d4d4219eb5ad2242dc4ee06f0bc6b39 Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <ruben.vereecken@student.uantwerpen.be>
Date: Mon, 3 Mar 2014 22:21:56 +0100
Subject: [PATCH 054/178] Added owner-based save enabling on Thang Types. NOTE
 server-sided doesn't work yet

---
 app/templates/editor/thang/edit.jade            | 9 ++++-----
 app/views/editor/article/edit.coffee            | 2 +-
 app/views/editor/level/scripts_tab_view.coffee  | 2 +-
 app/views/editor/level/settings_tab_view.coffee | 1 +
 app/views/editor/level/systems_tab_view.coffee  | 1 +
 app/views/editor/thang/colors_tab_view.coffee   | 1 +
 app/views/editor/thang/edit.coffee              | 2 ++
 7 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/app/templates/editor/thang/edit.jade b/app/templates/editor/thang/edit.jade
index c7b80fea0..af30eb2c1 100644
--- a/app/templates/editor/thang/edit.jade
+++ b/app/templates/editor/thang/edit.jade
@@ -12,9 +12,8 @@ block content
 
   img#portrait.img-thumbnail
 
-  button.btn.btn-primary#save-button(data-toggle="coco-modal", data-target="modal/save_version")
-    | Save
-  button.btn.btn-primary#revert-button(data-toggle="coco-modal", data-target="modal/revert", data-i18n="revert.revert") Revert
+  button.btn.btn-primary#save-button(data-toggle="coco-modal", data-target="modal/save_version", disabled=authorized === true ? undefined : "true") Save
+  button.btn.btn-primary#revert-button(data-toggle="coco-modal", data-target="modal/revert", data-i18n="revert.revert", disabled=authorized === true ? undefined : "true") Revert
   
   h3 Edit Thang Type: "#{thangType.attributes.name}"
 
@@ -38,9 +37,9 @@ block content
           select#animations-select
             for animation in animations
               option #{animation}
-          button.btn.btn-small.btn-primary#upload-button
+          button(disabled=authorized === true ? undefined : "true").btn.btn-small.btn-primary#upload-button
             i.icon-upload
-          button.btn.btn-small.btn-primary#clear-button
+          button(disabled=authorized === true ? undefined : "true").btn.btn-small.btn-primary#clear-button
             i.icon-remove
           input#real-upload-button(type="file")
 
diff --git a/app/views/editor/article/edit.coffee b/app/views/editor/article/edit.coffee
index d3c2d4c1c..77f95ac40 100644
--- a/app/views/editor/article/edit.coffee
+++ b/app/views/editor/article/edit.coffee
@@ -37,9 +37,9 @@ module.exports = class ArticleEditView extends View
       data: data
       filePath: "db/thang.type/#{@article.get('original')}"
       schema: Article.schema.attributes
+      readOnly: true unless me.isAdmin() or @article.hasWriteAccess(me)
       callbacks:
         change: @pushChangesToPreview
-    options.readOnly = true unless me.isAdmin()
     @treema = @$el.find('#article-treema').treema(options)
 
     @treema.build()
diff --git a/app/views/editor/level/scripts_tab_view.coffee b/app/views/editor/level/scripts_tab_view.coffee
index 9da71e31c..f0088ad21 100644
--- a/app/views/editor/level/scripts_tab_view.coffee
+++ b/app/views/editor/level/scripts_tab_view.coffee
@@ -59,7 +59,7 @@ module.exports = class ScriptsTabView extends View
       thangIDs: thangIDs
       dimensions: @dimensions
       supermodel: @supermodel
-      readOnly: not me.isAdmin() and not @level.hasWriteAccess(me)
+      readOnly: true unless me.isAdmin() or @level.hasWriteAccess(me)
       callbacks:
         change: @onScriptChanged
       nodeClasses:
diff --git a/app/views/editor/level/settings_tab_view.coffee b/app/views/editor/level/settings_tab_view.coffee
index 2dbfcf165..4e2518be6 100644
--- a/app/views/editor/level/settings_tab_view.coffee
+++ b/app/views/editor/level/settings_tab_view.coffee
@@ -29,6 +29,7 @@ module.exports = class SettingsTabView extends View
       supermodel: @supermodel
       schema: schema
       data: data
+      readOnly: true unless me.isAdmin() or @level.hasWriteAccess(me)
       callbacks: {change: @onSettingsChanged}
       thangIDs: thangIDs
       nodeClasses:
diff --git a/app/views/editor/level/systems_tab_view.coffee b/app/views/editor/level/systems_tab_view.coffee
index 23a58617a..a4b481754 100644
--- a/app/views/editor/level/systems_tab_view.coffee
+++ b/app/views/editor/level/systems_tab_view.coffee
@@ -69,6 +69,7 @@ module.exports = class SystemsTabView extends View
       supermodel: @supermodel
       schema: Level.schema.get('properties').systems
       data: systems
+      readOnly: true unless me.isAdmin() or @level.hasWriteAccess(me)
       callbacks:
         change: @onSystemsChanged
         select: @onSystemSelected
diff --git a/app/views/editor/thang/colors_tab_view.coffee b/app/views/editor/thang/colors_tab_view.coffee
index 4f42a15fc..b1ba229dc 100644
--- a/app/views/editor/thang/colors_tab_view.coffee
+++ b/app/views/editor/thang/colors_tab_view.coffee
@@ -115,6 +115,7 @@ module.exports = class ColorsTabView extends CocoView
     treemaOptions =
       data: data
       schema: schema
+      readOnly: true unless me.isAdmin() or @thangType.hasWriteAccess(me)
       callbacks:
         change: @onColorGroupsChanged
         select: @onColorGroupSelected
diff --git a/app/views/editor/thang/edit.coffee b/app/views/editor/thang/edit.coffee
index de0cc062e..a8310cdf2 100644
--- a/app/views/editor/thang/edit.coffee
+++ b/app/views/editor/thang/edit.coffee
@@ -57,6 +57,7 @@ module.exports = class ThangTypeEditView extends View
     context = super(context)
     context.thangType = @thangType
     context.animations = @getAnimationNames()
+    context.authorized = me.isAdmin() or @thangType.hasWriteAccess(me)
     context
 
   getAnimationNames: ->
@@ -328,6 +329,7 @@ module.exports = class ThangTypeEditView extends View
       schema: schema
       files: @files
       filePath: "db/thang.type/#{@thangType.get('original')}"
+      readOnly: true unless me.isAdmin() or @thangType.hasWriteAccess(me)
       callbacks:
         change: @pushChangesToPreview
         select: @onSelectNode

From b7fbf67e8946f7bb193986d4c823b1d7b01a9719 Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <ruben.vereecken@student.uantwerpen.be>
Date: Mon, 3 Mar 2014 22:52:37 +0100
Subject: [PATCH 055/178] Enabled Fork button again. Previous commits solve
 issue #455

---
 app/templates/editor/level/edit.jade | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade
index e63cdd2b9..bbf0026d5 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -31,7 +31,7 @@ block outer_content
           ul.nav.navbar-nav.navbar-right
             li(data-toggle="coco-modal", data-target="modal/revert", data-i18n="revert.revert", disabled=authorized === true ? undefined : "true").btn.btn-primary.navbar-btn#revert-button Revert
             li(data-i18n="common.save", disabled=authorized === true ? undefined : "true").btn.btn-primary.navbar-btn#commit-level-start-button Save
-            li(data-i18n="common.fork", disabled=authorized === true ? undefined : "true").btn.btn-primary.navbar-btn#fork-level-start-button Fork
+            li(data-i18n="common.fork").btn.btn-primary.navbar-btn#fork-level-start-button Fork
             li(title="⌃↩ or ⌘↩: Play preview of current level", data-i18n="common.play")#play-button.btn.btn-inverse.banner.navbar-btn Play!
 
             li.divider

From e231952fcf1e8dab32eaf8d64c935c13a2a060bf Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Mon, 3 Mar 2014 14:17:36 -0800
Subject: [PATCH 056/178] Added the jquery minicolors image.

---
 app/assets/images/jquery.minicolors.png | Bin 0 -> 77459 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 app/assets/images/jquery.minicolors.png

diff --git a/app/assets/images/jquery.minicolors.png b/app/assets/images/jquery.minicolors.png
new file mode 100644
index 0000000000000000000000000000000000000000..8fa1e9d9062696b96641450a0b0dcc8669835782
GIT binary patch
literal 77459
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
JPDHLkV1o8UQl|g_

literal 0
HcmV?d00001


From c944e78271b60d1f60891d7548d02e618334d149 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 3 Mar 2014 14:59:39 -0800
Subject: [PATCH 057/178] Ladder views now show level descvription content if
 present.

---
 app/templates/play/ladder.jade    | 5 ++++-
 app/views/play/ladder_view.coffee | 1 +
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/app/templates/play/ladder.jade b/app/templates/play/ladder.jade
index 41360c85b..b7de9c539 100644
--- a/app/templates/play/ladder.jade
+++ b/app/templates/play/ladder.jade
@@ -2,7 +2,10 @@ extends /templates/base
 block content
 
   div#level-column
-    h1= level.get('name')
+    if levelDescription
+      div!= levelDescription
+    else
+      h1= level.get('name')
 
   if me.get('anonymous')
     div#must-log-in
diff --git a/app/views/play/ladder_view.coffee b/app/views/play/ladder_view.coffee
index 5bc430eaa..8f6a046de 100644
--- a/app/views/play/ladder_view.coffee
+++ b/app/views/play/ladder_view.coffee
@@ -57,6 +57,7 @@ module.exports = class LadderView extends RootView
     ctx.simulationStatus = @simulationStatus
     ctx.teams = @teams
     ctx.levelID = @levelID
+    ctx.levelDescription = marked(@level.get('description')) if @level.get('description')
     ctx
 
   afterRender: ->

From df95e8c784422c7f53689793e58987d98f79cd8a Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 3 Mar 2014 16:19:35 -0800
Subject: [PATCH 058/178] Experimenting with using compress() in production.

---
 server/commons/Handler.coffee | 2 +-
 server_setup.coffee           | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/server/commons/Handler.coffee b/server/commons/Handler.coffee
index 2f81d0acd..ada7acad3 100644
--- a/server/commons/Handler.coffee
+++ b/server/commons/Handler.coffee
@@ -261,7 +261,7 @@ module.exports = class Handler
     tv4 = require('tv4').tv4
     res = tv4.validateMultiple(input, @jsonSchema)
     res
-    
+
   @isID: (id) -> _.isString(id) and id.length is 24 and id.match(/[a-z0-9]/gi)?.length is 24
 
   getDocumentForIdOrSlug: (idOrSlug, done) ->
diff --git a/server_setup.coffee b/server_setup.coffee
index ad23a6bf1..ff04b7b15 100644
--- a/server_setup.coffee
+++ b/server_setup.coffee
@@ -47,6 +47,8 @@ setupExpressMiddleware = (app) ->
   app.use(express.bodyParser())
   app.use(express.methodOverride())
   app.use(express.cookieSession({secret:'defenestrate'}))
+  if config.isProduction
+    app.use(express.compress())
 
 setupPassportMiddleware = (app) ->
   app.use(authentication.initialize())
@@ -115,3 +117,5 @@ exports.setExpressConfigurationOptions = (app) ->
   app.set('views', __dirname + '/app/views')
   app.set('view engine', 'jade')
   app.set('view options', { layout: false })
+  app.set('env', if config.isProduction then 'production' else 'development')
+  app.set('json spaces', 0)

From 873c560a064090b171ab9cee4e739923832aa4da Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 3 Mar 2014 16:22:50 -0800
Subject: [PATCH 059/178] Added Alexandru's Bubble Sort Bootcamp Battle to
 /play.

---
 app/views/play_view.coffee | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/app/views/play_view.coffee b/app/views/play_view.coffee
index 32e6d3bf1..9088f1cde 100644
--- a/app/views/play_view.coffee
+++ b/app/views/play_view.coffee
@@ -154,6 +154,13 @@ module.exports = class PlayView extends View
         image: '/file/db/level/526fd3043c637ece50001bb2/the_herd_icon.png'
         description: "Strike at the weak point in an array of enemies. - by Aftermath"
       }
+      {
+        name: 'Bubble Sort Bootcamp Battle'
+        difficulty: 3
+        id: 'bubble-sort-bootcamp-battle'
+        image: '/file/db/level/525ef8ef06e1ab0962000003/commanding_followers_icon.png'
+        description: "Write a bubble sort to organize your soldiers. - by Alexandru"
+      }
       {
         name: 'Enemy Artillery'
         difficulty: 1

From 619b6286619a10018ad3dddf091122a536e9b593 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Mon, 3 Mar 2014 16:39:56 -0800
Subject: [PATCH 060/178] Reworked the victory modal styling a bit.

---
 app/styles/play/level/modal/victory.sass    | 51 ++++++++++-----------
 app/templates/play/level/modal/victory.jade |  6 +--
 2 files changed, 27 insertions(+), 30 deletions(-)

diff --git a/app/styles/play/level/modal/victory.sass b/app/styles/play/level/modal/victory.sass
index 5e2b9e727..1dc9221f5 100644
--- a/app/styles/play/level/modal/victory.sass
+++ b/app/styles/play/level/modal/victory.sass
@@ -1,25 +1,35 @@
 #level-victory-modal
+  .victory-banner
+    float: right
+    width: 150px
+    position: relative
+    
+  .modal-footer
+    clear: both
+    padding-top: 15px
+  
   p.sign-up-poke
     text-align: left
     margin-bottom: 10px
-
-  .sign-up-button
-    margin-left: 20px
-
-  .next-level-button
-    margin-bottom: 10px
-    margin-right: 30px
-    float: right
     
+  .sign-up-button
+    float: right
+    margin-left: 10px
+    
+  .next-level-button
+    float: right
+    margin-left: 10px
+
   .rating
-    float: center
-    margin-right: 22%
+    float: left
+    position: relative
+    top: 5px
     span
       margin-right: 5px
     i
       cursor: pointer
       padding: 2px
-      
+
   .review
     margin-top: 5px
     width: 100%
@@ -31,23 +41,10 @@
       width: 100%
       height: 80px
       box-sizing: border-box
-    
+
   .share-buttons
+    padding-top: 15px
     clear: both
 
   .modal-header
-    text-align: left
-
-  .victory-banner
-    width: 450px
-    position: absolute
-    left: -150px
-
-  .modal-dialog
-    margin-left: 30%
-    padding-left: 300px
-    width: 700px
-
-  .modal-footer
-    margin: 0px
-    padding: 0px
+    text-align: center
diff --git a/app/templates/play/level/modal/victory.jade b/app/templates/play/level/modal/victory.jade
index 7a0637f8a..5dca8f3f6 100644
--- a/app/templates/play/level/modal/victory.jade
+++ b/app/templates/play/level/modal/victory.jade
@@ -2,8 +2,6 @@
 
 .modal-dialog
 
-  img.victory-banner(src="/images/level/victory.png", alt="")
-
   .modal-header
     button(type='button', data-dismiss="modal", aria-hidden="true").close &times;
     h3
@@ -11,7 +9,9 @@
       span= levelName
       span(data-i18n="play_level.victory_title_suffix") Complete
 
-  .modal-body!= body
+  .modal-body
+    img.victory-banner(src="/images/level/victory.png", alt="")
+    div!= body
   
   .modal-footer
     if hasNextLevel

From 7b25eeec47bea9bbaf81ed99d95d8d958be21020 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 3 Mar 2014 16:45:03 -0800
Subject: [PATCH 061/178] HUD properties now flow into columns more evenly,
 have max styling.

---
 app/templates/play/level/hud_prop.jade |  1 +
 app/views/play/level/hud_view.coffee   | 11 ++++++-----
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/app/templates/play/level/hud_prop.jade b/app/templates/play/level/hud_prop.jade
index 017129bb7..fcccab38e 100644
--- a/app/templates/play/level/hud_prop.jade
+++ b/app/templates/play/level/hud_prop.jade
@@ -7,5 +7,6 @@
   if hasBar
     span.prop-value.bar-prop
       .bar
+    span.prop-value.bar-prop-value
   else
     span.prop-value
diff --git a/app/views/play/level/hud_view.coffee b/app/views/play/level/hud_view.coffee
index 79aad4e7c..c3c35d34a 100644
--- a/app/views/play/level/hud_view.coffee
+++ b/app/views/play/level/hud_view.coffee
@@ -135,17 +135,17 @@ module.exports = class HUDView extends View
     props = @$el.find('.thang-props')
     props.find(":not(.thang-name)").remove()
     props.find('.thang-name').text(if @thang.type then "#{@thang.id} - #{@thang.type}" else @thang.id)
-    column = null
-    for prop in @thang.hudProperties ? []
+    propNames = @thang.hudProperties ? []
+    nColumns = Math.ceil propNames.length / 5
+    columns = ($('<div class="thang-props-column"></div>').appendTo(props) for i in [0 ... nColumns])
+    for prop, i in propNames
       continue if prop is 'action'
       pel = @createPropElement prop
       continue unless pel?
       if pel.find('.bar').is('*') and props.find('.bar').is('*')
         props.find('.bar-prop').last().after pel  # Keep bars together
       else
-        column ?= $('<div class="thang-props-column"></div>').appendTo props
-        column.append pel
-        column = null if column.find('.prop').length is 5
+        columns[i % nColumns].append pel
     null
 
   createActions: ->
@@ -263,6 +263,7 @@ module.exports = class HUDView extends View
       labelText = prop + ": " + @formatValue(prop, val) + " / " + @formatValue(prop, max)
       if regen
         labelText += " (+" + @formatValue(prop, regen) + "/s)"
+      pel.find('.bar-prop-value').text(Math.round(max)) if max
     else
       s = @formatValue(prop, val)
       labelText = "#{prop}: #{s}"

From 65d9186ef11a32b1eede4f2d03af51549543b08c Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 3 Mar 2014 16:55:36 -0800
Subject: [PATCH 062/178] Fixed actions showing up under dialogue bubbles on
 repeated toggling.

---
 app/views/play/level/hud_view.coffee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/views/play/level/hud_view.coffee b/app/views/play/level/hud_view.coffee
index c3c35d34a..f4580660b 100644
--- a/app/views/play/level/hud_view.coffee
+++ b/app/views/play/level/hud_view.coffee
@@ -151,7 +151,7 @@ module.exports = class HUDView extends View
   createActions: ->
     actions = @$el.find('.thang-actions tbody').empty()
     showActions = @thang.world and not _.isEmpty(@thang.actions) and 'action' in @thang.hudProperties ? []
-    @$el.find('.thang-actions').toggle showActions
+    @$el.find('.thang-actions').toggleClass 'secret', showActions
     return unless showActions
     @buildActionTimespans()
     for actionName, action of @thang.actions

From 881ec1a4b344c3c8427a712486300c404faff2b9 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Mon, 3 Mar 2014 17:03:02 -0800
Subject: [PATCH 063/178] Added a fix for files with spaces.

---
 server/routes/file.coffee | 1 +
 1 file changed, 1 insertion(+)

diff --git a/server/routes/file.coffee b/server/routes/file.coffee
index ce9f4ca7c..7a16c3709 100644
--- a/server/routes/file.coffee
+++ b/server/routes/file.coffee
@@ -13,6 +13,7 @@ module.exports.setup = (app) ->
 
 fileGet = (req, res) ->
   path = req.path[6..]
+  path = decodeURI path
   isFolder = false
   try
     objectId = mongoose.Types.ObjectId(path)

From 246bbefc912e0ba56ae13741fd3f2e8605851503 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Mon, 3 Mar 2014 17:14:13 -0800
Subject: [PATCH 064/178] Made the file uploading just overwrite files with the
 same name.

---
 app/treema-ext.coffee | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/app/treema-ext.coffee b/app/treema-ext.coffee
index 9112abaa6..674e6215a 100644
--- a/app/treema-ext.coffee
+++ b/app/treema-ext.coffee
@@ -39,6 +39,7 @@ class LiveEditingMarkup extends TreemaNode.nodeMap.ace
       filename: InkBlob.filename
       mimetype: InkBlob.mimetype
       path: @settings.filePath
+      force: true
 
     @uploadingPath = [@settings.filePath, InkBlob.filename].join('/')
     $.ajax('/file', { type: 'POST', data: body, success: @onFileUploaded })
@@ -147,9 +148,8 @@ class SoundFileTreema extends TreemaNode.nodeMap.string
       filename: InkBlob.filename
       mimetype: InkBlob.mimetype
       path: @settings.filePath
+      force: true
       
-    # Automatically overwrite if the same path was put in here before
-    body.force = true # if InkBlob.filename is @data
     @uploadingPath = [@settings.filePath, InkBlob.filename].join('/')
     $.ajax('/file', { type: 'POST', data: body, success: @onFileUploaded })
 
@@ -185,9 +185,8 @@ class ImageFileTreema extends TreemaNode.nodeMap.string
       filename: InkBlob.filename
       mimetype: InkBlob.mimetype
       path: @settings.filePath
+      force: true
 
-    # Automatically overwrite if the same path was put in here before
-    body.force = true # if InkBlob.filename is @data
     @uploadingPath = [@settings.filePath, InkBlob.filename].join('/')
     $.ajax('/file', { type: 'POST', data: body, success: @onFileUploaded })
 

From 113c71e141be7d8debbc6d63445f2eda298b2472 Mon Sep 17 00:00:00 2001
From: George Saines <gsaines@gmail.com>
Date: Mon, 3 Mar 2014 18:03:54 -0800
Subject: [PATCH 065/178] adding new hud icons

---
 app/assets/images/level/hud_info_icons.png | Bin 0 -> 8571 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 app/assets/images/level/hud_info_icons.png

diff --git a/app/assets/images/level/hud_info_icons.png b/app/assets/images/level/hud_info_icons.png
new file mode 100644
index 0000000000000000000000000000000000000000..bff08711922f2cee437293e67171e84d08edb0db
GIT binary patch
literal 8571
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
BqW=H@

literal 0
HcmV?d00001


From 9aa1d5a26ccad8c192d3722e7e36fc7d6407cf69 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 3 Mar 2014 18:50:59 -0800
Subject: [PATCH 066/178] Okay, we'll just let Cloudflare compress things.

---
 server_setup.coffee | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/server_setup.coffee b/server_setup.coffee
index ff04b7b15..d15035c53 100644
--- a/server_setup.coffee
+++ b/server_setup.coffee
@@ -47,8 +47,7 @@ setupExpressMiddleware = (app) ->
   app.use(express.bodyParser())
   app.use(express.methodOverride())
   app.use(express.cookieSession({secret:'defenestrate'}))
-  if config.isProduction
-    app.use(express.compress())
+  #app.use(express.compress()) if config.isProduction  # just let Cloudflare do it
 
 setupPassportMiddleware = (app) ->
   app.use(authentication.initialize())

From d43ff5d21729a85cf33dcd966e6d5915b78962a2 Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <ruben.vereecken@student.uantwerpen.be>
Date: Tue, 4 Mar 2014 11:24:38 +0100
Subject: [PATCH 067/178] Added an anonymous check on the Fork button

---
 app/templates/editor/level/edit.jade | 2 +-
 app/views/editor/level/edit.coffee   | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade
index bbf0026d5..7d2c7ac66 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -31,7 +31,7 @@ block outer_content
           ul.nav.navbar-nav.navbar-right
             li(data-toggle="coco-modal", data-target="modal/revert", data-i18n="revert.revert", disabled=authorized === true ? undefined : "true").btn.btn-primary.navbar-btn#revert-button Revert
             li(data-i18n="common.save", disabled=authorized === true ? undefined : "true").btn.btn-primary.navbar-btn#commit-level-start-button Save
-            li(data-i18n="common.fork").btn.btn-primary.navbar-btn#fork-level-start-button Fork
+            li(data-i18n="common.fork", disabled=anonymous ? "true": undefined).btn.btn-primary.navbar-btn#fork-level-start-button Fork
             li(title="⌃↩ or ⌘↩: Play preview of current level", data-i18n="common.play")#play-button.btn.btn-inverse.banner.navbar-btn Play!
 
             li.divider
diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/edit.coffee
index c79439800..962db3fac 100644
--- a/app/views/editor/level/edit.coffee
+++ b/app/views/editor/level/edit.coffee
@@ -64,6 +64,7 @@ module.exports = class EditorLevelView extends View
     context = super(context)
     context.level = @level
     context.authorized = me.isAdmin() or @level.hasWriteAccess(me)
+    context.anonymous = me.get('anonymous')
     context
 
   afterRender: ->

From 2f653c966e7775648fba3efc57100d3b7cff4762 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Tue, 4 Mar 2014 08:30:50 -0800
Subject: [PATCH 068/178] Simulator now swaps in empty methods when code
 doesn't compile.

---
 app/lib/simulator/Simulator.coffee | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/app/lib/simulator/Simulator.coffee b/app/lib/simulator/Simulator.coffee
index 521e810c7..f92bccb98 100644
--- a/app/lib/simulator/Simulator.coffee
+++ b/app/lib/simulator/Simulator.coffee
@@ -207,7 +207,12 @@ module.exports = class Simulator
   transpileSpell: (thang, spellKey, methodName) ->
     slugifiedThangID = _.string.slugify thang.id
     source = @currentUserCodeMap[[slugifiedThangID,methodName].join '/'] ? ""
-    @spells[spellKey].thangs[thang.id].aether.transpile source
+    aether = @spells[spellKey].thangs[thang.id].aether
+    try
+      aether.transpile source
+    catch e
+      console.log "Couldn't transpile #{spellKey}:\n#{source}\n", e
+      aether.transpile ''
 
   createAether: (methodName, method) ->
     aetherOptions =

From 195b1941eabe33186e720d6deab92918d436306f Mon Sep 17 00:00:00 2001
From: Yos Riady <yosriady@gmail.com>
Date: Wed, 5 Mar 2014 02:53:54 +0800
Subject: [PATCH 069/178] Added even more names for #53

---
 app/lib/world/names.coffee | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/app/lib/world/names.coffee b/app/lib/world/names.coffee
index 7ba332f60..a7a3f256e 100644
--- a/app/lib/world/names.coffee
+++ b/app/lib/world/names.coffee
@@ -58,6 +58,9 @@ module.exports.thangNames = thangNames =
     "Nikita"
     "Alana"
     "Lana"
+    "Joan"
+    "Helga"
+    "Annie"
   ]
   "Peasant": [
     "Yorik"
@@ -112,6 +115,8 @@ module.exports.thangNames = thangNames =
     "Roman"
     "Hunter"
     "Simon"
+    "Robin"
+    "Quinn"
   ]
   "Ogre Munchkin M": [
     "Brack"
@@ -151,13 +156,15 @@ module.exports.thangNames = thangNames =
     "Trung"
     "Axe Ox"
     "Vargutt"
+    "Grumus"
+    "Gug"
   ]
   "Ogre F": [
     "Nareng"
     "Morthrug"
     "Glonc"
     "Marghurk"
-    
+    "Martha"
   ]
   "Ogre Brawler": [
     "Grul'thock"

From 4556536df4d2f36052cc718a6313e6547aafb7b1 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Tue, 4 Mar 2014 11:15:31 -0800
Subject: [PATCH 070/178] Hooked up new HUD icons.

---
 app/assets/images/level/info_icons.png     | Bin 646 -> 0 bytes
 app/assets/images/level/prop_health.png    | Bin 513 -> 0 bytes
 app/assets/images/level/prop_inventory.png | Bin 571 -> 0 bytes
 app/assets/images/level/prop_pos.png       | Bin 576 -> 0 bytes
 app/assets/images/level/prop_target.png    | Bin 581 -> 0 bytes
 app/styles/play/level/hud.sass             |  33 +++++++++++++++++----
 app/templates/play/level/hud_prop.jade     |   2 +-
 app/views/play/level/hud_view.coffee       |   2 +-
 8 files changed, 29 insertions(+), 8 deletions(-)
 delete mode 100644 app/assets/images/level/info_icons.png
 delete mode 100644 app/assets/images/level/prop_health.png
 delete mode 100644 app/assets/images/level/prop_inventory.png
 delete mode 100644 app/assets/images/level/prop_pos.png
 delete mode 100644 app/assets/images/level/prop_target.png

diff --git a/app/assets/images/level/info_icons.png b/app/assets/images/level/info_icons.png
deleted file mode 100644
index de9ecfb6f43c4cad12d76ee4f32e8a54781d776c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 646
zcmV;10(t$3P)<h;3K|Lk000e1NJLTq001}u000gM1^@s6dZpj40006_Nkl<Zc-pm=
zziSjh6vy{Zu(6Tb%lRWQml$$h62p;$Y_O1sh-e@o7A^!*1(Y-*SS+!y5w^%5a7Eg{
zVPRvll^|H0l^`ewYUQsXf5FT9E;I0)+sPyh4t%(GZ)f-RbMG-T5k^s;X)y&ungTgj
zKB^eYJ8v>ZF{Dw*MJJ3uwJQnJXUGD%M9zKnXsN+uKIA<{uED7H^=bMRPm~}=?u2~9
zk{dAOVBnDJG2|f^f)JqRYxDH<UfW5PVDDZ18vU$|n}?P$a^P3HOGlgACBGL}${g;o
zDo3EZ{hH?Q9{|KsGPC4zAu(i9@jcZ!()6?-fxFkosB`JOi%LQDCB8cH@BOGvfHMBu
zY}3)!<C3p)%MesTP#L-A(mp+V@fIMKl1jFve0k=a&J#e4oK@i@M6hf>U%ME=@7-Gv
zBq2xuRfCurh><hbg<#)Q&dAw<Mp9I=Zv<CoYX3)2CAUc}CYT!}C|fb|4AHuf%eGb~
zAraD|elQn;0WC^4=9+Jgmhh1?DbtdR%xMJ!7MU=?!_~QTZ~X>sbS{rb-JH5W4;C&G
zD!hAVmM{<P{LeP=DQ<e@KE_i4+eC1SnuP`ekjk(vynNU}t`ga%PZ+eHuQfsH+~`N;
zaxo=zkxA^A*Rhk4{m>=(Ii7UM*^-5j8_H{;+eEOSltjDAwv=)n!Bhx3=UXrD+vsyG
z(_+*a1dB)xyInujr^V4s$oVCQuIf2YGj4hn=h4C;h<wH*zTY;7?;$gA9Iic8w5u0>
g*tSGd{pl4t24w6<%WBZ`qyPW_07*qoM6N<$g3yRBAOHXW

diff --git a/app/assets/images/level/prop_health.png b/app/assets/images/level/prop_health.png
deleted file mode 100644
index 87f3c840753e0f8d73b7a4c2fbe736c41918965a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 513
zcmV+c0{;DpP)<h;3K|Lk000e1NJLTq000gE000gM0ssI2kSe-{0005VNkl<ZC{vBm
z%T5zf0D$5D+}aMEUWS&op@3n*g1F%cOmyX2=p*=4>dK7^7Z?|4V%SJbG`hjS0wf9)
zr*rAdIdhH+U%>AbKC!<$<Ns&?B_FJ>KmML?r?sa0X4^a;-0YR+*=e(l`GI|TF#NDs
zsEs7PZ{nw?dYUagVuo5v&0x}dSVUWC1#Sn~s?E)`uQrnSi5oroy=+qkq@tGionLM*
zEeu*<6Xdw`W@9XY{k(NS25L^I2o+&M)}?lYKI#lxksq8_61a?9PA8)Yc!jL+0-Ylz
zC}f5c=<8)Jfx}iNTm71F4FgP@)e3!slaSKPQJUV{xs||)&EC(k^gtQRh{&Qx7>i%h
zNY)NF<x#(pfOWiHUlsQfO>;$MiI&u3REl?mpX2z|q(1YN8V_SF{e>&O#cYx6=8Yil
zz>2z}f4(_=k(6KZI}w5!4`c6xY@5>CTje4hjSAIfwTApONsiT@&mm29K*)bvI<{)z
zi;r#Bo^>ME*<8?Ij%LltU3wX6VOrV-4d4iQ)oF=R%dfr|Cf(_zchzl<%iBBM1g%>^
z3FkD>F**n$qjd1MW%*9kT4#$z>4T73MM6m%Oi+IT@y66CmB$XB00000NkvXXu0mjf
Dg0S#3

diff --git a/app/assets/images/level/prop_inventory.png b/app/assets/images/level/prop_inventory.png
deleted file mode 100644
index 37f147521f63e34e9723f8d9b8fa7a0a2d97ed25..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 571
zcmV-B0>u4^P)<h;3K|Lk000e1NJLTq000gE000gM0ssI2kSe-{00064Nkl<ZC{qQ&
z&ubGw6ae7&=DnFsHtE(hT579Fq!mkR(VoOZFDhacL_PK5A0vYQizmUGg5IQfGKfVg
z2ue+9n>I-|+0D+6o$>o{^GbdD-j<Xyn-<=K5Uh>U+9+X0x#{lz5tZ1Lp)3t=-Pu%1
ze)#-lm`-YOtc~*lm<WOk#2i(|`IMLekdICV-a}p(B1R;DQc2dfWXS=^I<KT8W?MQD
z5ROj=K6qj(v<3jFRDj@uKtTcoc%Nk%A&EvZTND}vF>wfJ%aG-TWXZ%vTcsF7*_f$Y
zYsicTd0~yQA%KjOl&UZW5uLM@NbWq_{?`4D5F`ug%qN|zivlS(MjMMLhy(yuBIT^v
z`>}WNLT%&5a__K@8;diW8>@n4nr6R#AAo?{H`h9?w(y3aT$*p593KxS*;4BodsQ>p
zs6pDh5Z7S)@q=>MgQH!oqYC4{Ua76E)f4IFgzzANf`KYaJJI>+IPIU423d`>5-l=S
zV;wLvULZoJ)h-<Pk|L7hv$RIFx~z|#@G71Pm3bZ%A(>yGB&i;r96f(>fB$c9l-qW@
zrKkB+Ygcb3jk(qJ_4l8456;fNc7Ni^^~>aq^zP-(i?{DSK7I7??ya>~uiuOeMoLPi
zbdm!J6;*I~Wx*MJsX5#451F_**GNa_QUC<$y%!_`05NBI{vWs`3)qrO;z$4h002ov
JPDHLkV1l3N1Tp{s

diff --git a/app/assets/images/level/prop_pos.png b/app/assets/images/level/prop_pos.png
deleted file mode 100644
index d3461a8e259b684e07591c84d4366294e1039667..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 576
zcmV-G0>Ax<P)<h;3K|Lk000e1NJLTq000gE000gM0ssI2kSe-{00069Nkl<ZC{qQ&
z%T5zf7y#h^|Ie9QJB1FWg$h=YG-zPuLUf_7jSFMq3-|&)k6ZU7x;HT~M2U$pEJV2(
z0#;$L6ldtnoHOU<_u+EC>p8Nan2^1(@|4))Fc^fvP{>awTOVXGBqPJ1Ro03Vp{;X+
zx8`oX$jpOUb&0~uJocyW^p{*U`jY+mu8q(J2od8b?hPL4D-Y9xhwTaCW_wUvPMwMN
zy|A}xiGeX5AxA_3S<+oeM{{#a?(M7D2q1;Q^OqZ`TD(4Usu_<=%{U_fsKtWeeHW|o
zaHDUaQ|VO=-qEpO^L%>2Ay-B@qscnQtt#{1TIy!-tR!%g+ZP;6t4Bo|Nc5c#&H@1k
z0Na#)W2aH96?W_Xlgt)hgZaCcYGrn6uO9CiRWd~FfOV3%cA3m&dm63lxMWQ<m&<y|
zsPVOMqe?$lqy4~x$^h#maqMxO7W(hER=a<$uEI>0<wuLj`)qeTKi$T9;`yF1NB~et
zzr|!*N>9F{3CMhN%8uB{>q)w;iwn+}whR#o0Axs}!Cfeh4|k&GK_q%fl>gfO5ulEI
zpRrIIAaDc#%F4>oxIT}Yo$B8k{~{V5u1C$t0$9hD@r~t-hybABd~zZVXGQTdl%s?n
z=yG4EGv_>QxdWe&gSD)a#N3iHtVWLL#gs?*(TS`s!$2!Si&Q%@7VtlXr5Ox_NvCiC
O0000<MNUMnLSTYC`4A8Q

diff --git a/app/assets/images/level/prop_target.png b/app/assets/images/level/prop_target.png
deleted file mode 100644
index 0f2b411ac11223b0122e32b7d380d7f1fa58ff1d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 581
zcmV-L0=oT)P)<h;3K|Lk000e1NJLTq000gE000gM0ssI2kSe-{0006ENkl<ZC{qQ&
zIZqT}00!XqyXM%Lft^_(Yajtk)<rOwXlaE}3MH|#ATerZ?JrPz8f$-mM>H|9z(_)c
z6@`V3ny71xi?A%q%+CECJ`cIL*jA__#b<J}BHd1IwF|UBY82bEJRx#KRl;;l4GX8d
zK-E`L{$Sv27NU^FD(VHWpHLf#b1P;?R`JCvCzQ+1``)T)JUR@T!1he``do2+XiJdC
zbEjoSLQR%3UIBlE=JPqfdu&%QFPg=hV9YFDp)msa#nii5`8$^nkDU7_?vQ45DHj*O
zcN^LJ>9Vw}cIi^s1;iZj1{@zJ@>i|1Nyz1b^6r@TQ0z??BO9F)F%<gV{4t1;wQ?;_
z(dt`J_fO<P!pIIfmtbN@!2Jxe)lCvvHYEh3PkywzsE3G`!S}&v11dm0Mm0cPKrso*
zxS@mrr;vc=AU;?GM)t5!BY)OTzDD*$<{a5%I)#E9`kE7jSsB*V)4#0*4vS~QwZx=^
z^=vsbWeenaFT4?3``%fmY(m-XQP3&*hbW^7kq*RK;$KTWK~S1%2D%ICYuX_C=0CO`
z+bPH)1&f+~X2?ouT}_2FN(*y27H3eqe!4O8?u=an`f{o|@HFWzwvE7gUu-5K0{T#^
z;10+>>HsDMc{?R{LzQd8CR?7XdCw`oJN3Xas?dGN5ujl0MCm6_9(Xz?n5_AK&WZk~
Tn9!vg00000NkvXXu0mjf*)9cL

diff --git a/app/styles/play/level/hud.sass b/app/styles/play/level/hud.sass
index 7858f0365..4f6a5fea3 100644
--- a/app/styles/play/level/hud.sass
+++ b/app/styles/play/level/hud.sass
@@ -95,14 +95,35 @@
         height: 100px
         @include user-select(text)
   
-        .prop
-          img
-            margin-right: 5px
-            width: 16px
-            height: 16px
-  
         .text-prop
           width: 50%
+
+        .prop-label-icon
+          $iconSize: 16px
+          display: inline-block
+          width: $iconSize
+          height: $iconSize
+          margin-right: 5px
+          background: transparent url(/images/level/hud_info_icons.png) no-repeat
+          background-size: auto $iconSize
+          float: left
+
+          &.prop-label-icon-pos
+            background-position-x: -1 * $iconSize
+          &.prop-label-icon-target
+            background-position-x: -2 * $iconSize
+          &.prop-label-icon-inventory
+            background-position-x: -3 * $iconSize
+          &.prop-label-icon-visualRange
+            background-position-x: -4 * $iconSize
+          &.prop-label-icon-attackDamage
+            background-position-x: -5 * $iconSize
+          &.prop-label-icon-attackRange
+            background-position-x: -6 * $iconSize
+          &.prop-label-icon-maxSpeed
+            background-position-x: -7 * $iconSize
+          &.prop-label-icon-gold
+            background-position-x: -8 * $iconSize
   
         .prop-value.bar-prop
           width: 100px
diff --git a/app/templates/play/level/hud_prop.jade b/app/templates/play/level/hud_prop.jade
index fcccab38e..705377d92 100644
--- a/app/templates/play/level/hud_prop.jade
+++ b/app/templates/play/level/hud_prop.jade
@@ -1,6 +1,6 @@
 .prop(name="#{prop}")
   if hasIcon
-    img.prop-label(src="/images/level/prop_#{prop}.png", alt="#{prop}")
+    span(class="prop-label prop-label-icon prop-label-icon-#{prop}")
   else
     span.prop-label #{prop}: 
     
diff --git a/app/views/play/level/hud_view.coffee b/app/views/play/level/hud_view.coffee
index f4580660b..7b036c433 100644
--- a/app/views/play/level/hud_view.coffee
+++ b/app/views/play/level/hud_view.coffee
@@ -247,7 +247,7 @@ module.exports = class HUDView extends View
       return null  # included in the bar
     context =
       prop: prop
-      hasIcon: prop in ["health", "pos", "target", "inventory", "gold"]
+      hasIcon: prop in ["health", "pos", "target", "inventory", "gold", "visualRange", "attackDamage", "attackRange", "maxSpeed"]
       hasBar: prop in ["health"]
     $(prop_template(context))
 

From e02780e4415de899f0d2ccdc5ea1b649d16e3ec7 Mon Sep 17 00:00:00 2001
From: Darredevil <alex.darredevil@gmail.com>
Date: Tue, 4 Mar 2014 21:26:52 +0200
Subject: [PATCH 071/178] Update for ro.coffee

-first 80 lines done
---
 app/locale/ro.coffee | 136 +++++++++++++++++++++----------------------
 1 file changed, 68 insertions(+), 68 deletions(-)

diff --git a/app/locale/ro.coffee b/app/locale/ro.coffee
index 454278097..6a07f8345 100644
--- a/app/locale/ro.coffee
+++ b/app/locale/ro.coffee
@@ -1,83 +1,83 @@
 module.exports = nativeDescription: "limba română", englishDescription: "Romanian", translation:
   common:
     loading: "Loading..."
-#    saving: "Saving..."
-#    sending: "Sending..."
-#    cancel: "Cancel"
-#    save: "Save"
-#    delay_1_sec: "1 second"
-#    delay_3_sec: "3 seconds"
-#    delay_5_sec: "5 seconds"
-#    manual: "Manual"
-#    fork: "Fork"
-#    play: "Play"
+    saving: "Se salvează..."
+    sending: "Se trimite..."
+    cancel: "Anulează"
+    save: "Salvează"
+    delay_1_sec: "1 secundă"
+    delay_3_sec: "3 secunde"
+    delay_5_sec: "5 secunde"
+    manual: "Manual"
+    fork: "Fork"
+    play: "Joaca"
 
-#  modal:
-#    close: "Close"
-#    okay: "Okay"
+  modal:
+    close: "Inchide"
+    okay: "Okay"
 
-#  not_found:
-#    page_not_found: "Page not found"
+  not_found:
+    page_not_found: "Pagina nu a fost gasită"
 
-#  nav:
-#    play: "Levels"
-#    editor: "Editor"
-#    blog: "Blog"
-#    forum: "Forum"
-#    admin: "Admin"
-#    home: "Home"
-#    contribute: "Contribute"
-#    legal: "Legal"
-#    about: "About"
-#    contact: "Contact"
-#    twitter_follow: "Follow"
-#    employers: "Employers"
+  nav:
+    play: "Nivele"
+    editor: "Editor"
+    blog: "Blog"
+    forum: "Forum"
+    admin: "Admin"
+    home: "Acasa"
+    contribute: "Contribuie"
+    legal: "Confidențialitate și termeni"
+    about: "Despre"
+    contact: "Contact"
+    twitter_follow: "Urmărește"
+    employers: "Angajați"
 
-#  versions:
-#    save_version_title: "Save New Version"
-#    new_major_version: "New Major Version"
-#    cla_prefix: "To save changes, first you must agree to our"
-#    cla_url: "CLA"
-#    cla_suffix: "."
-#    cla_agree: "I AGREE"
+  versions:
+    save_version_title: "Salvează noua versiune"
+    new_major_version: "Versiune nouă majoră"
+    cla_prefix: "Pentru a salva modificările mai intâi trebuie sa fiți de acord cu"
+    cla_url: "CLA"
+    cla_suffix: "."
+    cla_agree: "SUNT DE ACORD"
 
-#  login:
-#    sign_up: "Create Account"
-#    log_in: "Log In"
-#    log_out: "Log Out"
-#    recover: "recover account"
+  login:
+    sign_up: "Crează cont"
+    log_in: "Log In"
+    log_out: "Log Out"
+    recover: "recuperează cont"
 
-#  recover:
-#    recover_account_title: "Recover Account"
-#    send_password: "Send Recovery Password"
+  recover:
+    recover_account_title: "Recuperează Cont"
+    send_password: "Trimite parolă de recuperare"
 
-#  signup:
-#    create_account_title: "Create Account to Save Progress"
-#    description: "It's free. Just need a couple things and you'll be good to go:"
-#    email_announcements: "Receive announcements by email"
-#    coppa: "13+ or non-USA "
-#    coppa_why: "(Why?)"
-#    creating: "Creating Account..."
-#    sign_up: "Sign Up"
-#    log_in: "log in with password"
+  signup:
+    create_account_title: "Crează cont pentru a salva progresul"
+    description: "Este gratis. Doar câte ceva inainte si poți continua:"#contextual translation a bit off, could be better# It's free. Just need a couple things and you'll be good to go:"
+    email_announcements: "Receive announcements by email"
+    coppa: "13+ sau non-USA "
+    coppa_why: "(De ce?)"
+    creating: "Se crează contul..."
+    sign_up: "Înscrie-te"
+    log_in: "loghează-te cu parola"
 
-#  home:
-#    slogan: "Learn to Code JavaScript by Playing a Game"
-#    no_ie: "CodeCombat does not run in Internet Explorer 9 or older. Sorry!"
-#    no_mobile: "CodeCombat wasn't designed for mobile devices and may not work!"
-#    play: "Play"
+  home:
+    slogan: "Învață sa scri JavaScript jucându-te"# again sounds funny# Learn to Code JavaScript by Playing a Game"
+    no_ie: "CodeCombat does not run in Internet Explorer 9 or older. Sorry!"
+    no_mobile: "CodeCombat nu a fost proiectat pentru dispozitive mobile si s-ar putea sa nu meargâ!"
+    play: "Joacâ"
 
-#  play:
-#    choose_your_level: "Choose Your Level"
-#    adventurer_prefix: "You can jump to any level below, or discuss the levels on "
-#    adventurer_forum: "the Adventurer forum"
-#    adventurer_suffix: "."
-#    campaign_beginner: "Beginner Campaign"
-#    campaign_beginner_description: "... in which you learn the wizardry of programming."
-#    campaign_dev: "Random Harder Levels"
-#    campaign_dev_description: "... in which you learn the interface while doing something a little harder."
-#    campaign_multiplayer: "Multiplayer Arenas"
-#    campaign_multiplayer_description: "... in which you code head-to-head against other players."
+  play:
+    choose_your_level: "Alege nivelul"
+    adventurer_prefix: "Poți să sari la orice nivel de mai jos"#what do you mean by discuss?# You can jump to any level below, or discuss the levels on "
+    adventurer_forum: "forumul Aventurierului"#sonds waaaaaay too funny#the Adventurer forum"
+    adventurer_suffix: "."
+    campaign_beginner: "Campanie pentru Începători"
+    campaign_beginner_description: "... în care se învață tainele programării."
+    campaign_dev: "Nivele aleatoare mai grele"
+    campaign_dev_description: "... în care se învață interfața, cu o dificultate puțin mai mare."
+    campaign_multiplayer: "Arene Multiplayer"
+    campaign_multiplayer_description: "... în care te lupți cap-la-cap contra alti jucători."
 #    campaign_player_created: "Player-Created"
 #    campaign_player_created_description: "... in which you battle against the creativity of your fellow <a href=\"/contribute#artisan\">Artisan Wizards</a>."
 #    level_difficulty: "Difficulty: "

From 3680d628e7730221c9ee606a69fe6a7e451552aa Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Tue, 4 Mar 2014 12:06:31 -0800
Subject: [PATCH 072/178] Fixed showing generic errors.

---
 app/lib/errors.coffee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/lib/errors.coffee b/app/lib/errors.coffee
index 372507d0c..8e7fe4203 100644
--- a/app/lib/errors.coffee
+++ b/app/lib/errors.coffee
@@ -21,7 +21,7 @@ module.exports.genericFailure = (jqxhr) ->
   if existingForm[0]
     missingErrors = applyErrorsToForm(existingForm, [error])
     for error in missingErrors
-      existingForm.append($('<div class="alert"></div>').text(error.message))
+      existingForm.append($('<div class="alert alert-danger"></div>').text(error.message))
   else
     res = errorModalTemplate(
       status:jqxhr.status

From 9726840d8a4d2142989d38035639eadb85f96d67 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Tue, 4 Mar 2014 12:21:02 -0800
Subject: [PATCH 073/178] Trying to handle a case where a user did not have
 their user account created.

---
 app/lib/auth.coffee     | 5 +++++
 server/routes/db.coffee | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/app/lib/auth.coffee b/app/lib/auth.coffee
index 2af810b37..df2b2b6c3 100644
--- a/app/lib/auth.coffee
+++ b/app/lib/auth.coffee
@@ -43,7 +43,12 @@ init = ->
   module.exports.me = window.me = new User(storedUser)
   me.url = -> '/auth/whoami'
   me.fetch()
+  
+  retry = -> me.fetch() # blindly try again
+  error = -> setTimeout(retry, 1000) # blindly try again
+  me.on 'error', error, @
   me.on 'sync', ->
+    me.off 'error', error, @ if firstTime
     me.url = -> "/db/user/#{me.id}"
     trackFirstArrival() if firstTime
     if me and not me.get('testGroupNumber')?
diff --git a/server/routes/db.coffee b/server/routes/db.coffee
index 8bf2ef7eb..fec290cfa 100644
--- a/server/routes/db.coffee
+++ b/server/routes/db.coffee
@@ -11,7 +11,7 @@ module.exports.setup = (app) ->
     parts = module.split('/')
     module = parts[0]
     return getSchema(req, res, module) if parts[1] is 'schema'
-    return errors.unauthorized(res, 'Must have an identity to do anything with the db.') unless req.user
+    return errors.unauthorized(res, 'Must have an identity to do anything with the db. Do you have cookies enabled?') unless req.user
 
     try
       moduleName = module.replace '.', '_'

From a0e39480e331d69325ceb7a5d1bcf5b59ce589f4 Mon Sep 17 00:00:00 2001
From: Dominik Kundel <dominik.kundel@gmail.com>
Date: Wed, 5 Mar 2014 02:00:38 +0100
Subject: [PATCH 074/178] new UI design for executing and executed lines in ACE
 editor

---
 app/styles/play/level/tome/spell.sass       | 14 ++++++++++++--
 app/views/play/level/tome/spell_view.coffee |  4 ++--
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/app/styles/play/level/tome/spell.sass b/app/styles/play/level/tome/spell.sass
index 9066b4af5..5fdfa7c61 100644
--- a/app/styles/play/level/tome/spell.sass
+++ b/app/styles/play/level/tome/spell.sass
@@ -73,9 +73,10 @@
       .executing, .executed, .problem-marker-info, .problem-marker-warning, .problem-marker-error
         position: absolute
     .executing
-      background-color: rgba(216, 255, 255, 0.85)
+      background-color: rgba(0, 255, 0, 0.15)
+      @include gradient-striped()
     .executed
-      background-color: rgba(245, 255, 6, 0.18)
+      background-color: rgba(40, 40, 40, 0.12)
     .problem-marker-info
       background-color: rgba(196, 163, 184, 0.25)
     .problem-marker-warning
@@ -83,11 +84,20 @@
     .problem-marker-error
       background-color: rgba(110, 45, 27, 0.25)
 
+    .executing:not(.ace_gutter-cell)
+      background-size: 40px 40px
+      @include animation(progress-bar-stripes 2s linear infinite)
+
     .ace_gutter-cell.executing:not(.ace_error)
       margin-left: 1px
       background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowMjgwMTE3NDA3MjA2ODExOEE2REU4Q0M1MTM1MkIxRiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpBQjVEQUNDMzQ4RUIxMUUxOEVGRUUyNzFENDM3RDVFMCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpBQjVEQUNDMjQ4RUIxMUUxOEVGRUUyNzFENDM3RDVFMCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgTWFjaW50b3NoIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTU1MjE3RDIzMTIwNjgxMThEQkI4NTlBMjQ1QTEwOTUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDI4MDExNzQwNzIwNjgxMThBNkRFOENDNTEzNTJCMUYiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7SazaGAAAAiElEQVR42mL8//8/AzUBEwOVweA3kAWboI2jCyhgDwBx4ZH9ey5Qy4UOQHweaHg/EAtQ08sFUIMDqBmGCkC8HmgoCCtQM1ICoK5toGYsg8KzHmjo+UGbDj8AcSMwORkSnQ7xgA3QtPmApISNBTyAGrSBGl6eAMSGxBhGyIVkZT3G0fKQYgAQYACL+C2ZM6PC7AAAAABJRU5ErkJggg==)
       background-position: 0px center
 
+    .ace_gutter-cell.executed:not(.ace_error)
+      margin-left: 1px
+      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAOpJREFUeNpiYBgFpAD2NGMDIA6glmECQNyPLs5EgZnzmb783kgt1zUA8XxscixkGOYApPJZXnwz/IlFnolEwxSA1HrGX38nft10/QE2NYykRAKQ2g/EAhznXxt+PP3oA6VeBsWoAfOHn4m4DMPnmvscSYb7kfgJQPwfWQwXYMThtfdgyV9/G/+zMW8AMs+DvfPimyMw7A6QZCAsWQCpeigXFPgKTN/+LPi+5GIiIRfiiuUJUINAQIHx7/8PTJ9+NRITXFgN/DnrLCjQC+He+P4HZzIhKdkAvb6e8cdfBfbr7xxJjtmRAwACDAA0klcB6aJFbwAAAABJRU5ErkJggg==)
+      background-position: 0px center
+
     .ace_gutter-cell.comment-line
       background-position: 0px center
       background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAYAAADtc08vAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIJJREFUeNpiTF9y4j0DA4MAA5mAiRLNIMACY8yMsWAkRSPQ5Q1Aqp6JgUIwagAVDGAERsd/LOKGwGi9AJRLALL78aUVRhwp0RGIHUDxTNAFaIljP1TjBSA2gAofAOJAoIs+4E2JaACmeQFQYyK5gdhISDM2F3yA4kKg5gXExAJAgAEACuQiMh7vH10AAAAASUVORK5CYII=)
diff --git a/app/views/play/level/tome/spell_view.coffee b/app/views/play/level/tome/spell_view.coffee
index c44cfa48e..679ef7d87 100644
--- a/app/views/play/level/tome/spell_view.coffee
+++ b/app/views/play/level/tome/spell_view.coffee
@@ -478,13 +478,13 @@ module.exports = class SpellView extends View
       else
         @debugView.setVariableStates state.variables
         gotVariableStates = true
-        markerType = "text"
+        markerType = "fullLine"
       markerRange = new Range start.row, start.col, end.row, end.col
       markerRange.start = @aceDoc.createAnchor markerRange.start
       markerRange.end = @aceDoc.createAnchor markerRange.end
       markerRange.id = @aceSession.addMarker markerRange, clazz, markerType
       @markerRanges.push markerRange
-      @aceSession.addGutterDecoration start.row, clazz if clazz is 'executing'
+      @aceSession.addGutterDecoration start.row, clazz 
     @debugView.setVariableStates {} unless gotVariableStates
     null
 

From 0ec431f90ac137c382b022309bd753721e2e5111 Mon Sep 17 00:00:00 2001
From: Shrihari <gfxindia@gmail.com>
Date: Wed, 5 Mar 2014 13:46:21 +0530
Subject: [PATCH 075/178] Moved 'skip tutorial' text to locales.

---
 app/locale/ar.coffee                 | 1 +
 app/locale/bg.coffee                 | 1 +
 app/locale/cs.coffee                 | 1 +
 app/locale/da.coffee                 | 1 +
 app/locale/de.coffee                 | 1 +
 app/locale/el.coffee                 | 1 +
 app/locale/en-AU.coffee              | 1 +
 app/locale/en-GB.coffee              | 1 +
 app/locale/en-US.coffee              | 1 +
 app/locale/en.coffee                 | 1 +
 app/locale/es-419.coffee             | 1 +
 app/locale/es-ES.coffee              | 1 +
 app/locale/es.coffee                 | 1 +
 app/locale/fa.coffee                 | 1 +
 app/locale/fi.coffee                 | 1 +
 app/locale/fr.coffee                 | 1 +
 app/locale/he.coffee                 | 1 +
 app/locale/hi.coffee                 | 1 +
 app/locale/hu.coffee                 | 1 +
 app/locale/id.coffee                 | 1 +
 app/locale/it.coffee                 | 1 +
 app/locale/ja.coffee                 | 1 +
 app/locale/ko.coffee                 | 1 +
 app/locale/lt.coffee                 | 1 +
 app/locale/ms-BA.coffee              | 1 +
 app/locale/nb.coffee                 | 1 +
 app/locale/nl.coffee                 | 1 +
 app/locale/nn.coffee                 | 1 +
 app/locale/no.coffee                 | 1 +
 app/locale/pl.coffee                 | 1 +
 app/locale/pt-BR.coffee              | 1 +
 app/locale/pt-PT.coffee              | 1 +
 app/locale/pt.coffee                 | 1 +
 app/locale/ro.coffee                 | 1 +
 app/locale/ru.coffee                 | 1 +
 app/locale/sk.coffee                 | 1 +
 app/locale/sl.coffee                 | 1 +
 app/locale/sr.coffee                 | 1 +
 app/locale/sv.coffee                 | 1 +
 app/locale/th.coffee                 | 1 +
 app/locale/tr.coffee                 | 1 +
 app/locale/uk.coffee                 | 1 +
 app/locale/ur.coffee                 | 1 +
 app/locale/vi.coffee                 | 1 +
 app/locale/zh-HANS.coffee            | 1 +
 app/locale/zh-HANT.coffee            | 1 +
 app/locale/zh.coffee                 | 1 +
 app/views/play/level/hud_view.coffee | 3 ++-
 48 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/app/locale/ar.coffee b/app/locale/ar.coffee
index b1d899a65..cb4c293df 100644
--- a/app/locale/ar.coffee
+++ b/app/locale/ar.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/bg.coffee b/app/locale/bg.coffee
index 72ca47fca..6829f58fa 100644
--- a/app/locale/bg.coffee
+++ b/app/locale/bg.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "български език", englishDescri
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/cs.coffee b/app/locale/cs.coffee
index aa32f0aa2..15896ec83 100644
--- a/app/locale/cs.coffee
+++ b/app/locale/cs.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
     tome_available_spells: "Dostupná kouzla"
     hud_continue: "Pokračovat (stiskněte shift-mezera)"
     spell_saved: "Kouzlo uloženo"
+#    skip_tutorial: "skip: esc"
 
   admin:
     av_title: "Administrátorský pohled"
diff --git a/app/locale/da.coffee b/app/locale/da.coffee
index 727e8d713..c825de14d 100644
--- a/app/locale/da.coffee
+++ b/app/locale/da.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
     tome_available_spells: "Tilgængelige trylleformularer"
     hud_continue: "Fortsæt (tryk skift-mellemrum)"
     spell_saved: "Trylleformularen er gemt"
+#    skip_tutorial: "skip: esc"
 
   admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/de.coffee b/app/locale/de.coffee
index aebfcccbb..6d6bb469d 100644
--- a/app/locale/de.coffee
+++ b/app/locale/de.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra
     tome_available_spells: "Verfügbare Zauber"
     hud_continue: "Weiter (drücke Shift + Leertaste)"
     spell_saved: "Zauber gespeichert"
+#    skip_tutorial: "skip: esc"
 
   admin:
     av_title: "Administrator Übersicht"
diff --git a/app/locale/el.coffee b/app/locale/el.coffee
index 5425164b7..a03bff546 100644
--- a/app/locale/el.coffee
+++ b/app/locale/el.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "ελληνικά", englishDescription: "Gre
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/en-AU.coffee b/app/locale/en-AU.coffee
index 9c115d83d..70ec9b81e 100644
--- a/app/locale/en-AU.coffee
+++ b/app/locale/en-AU.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/en-GB.coffee b/app/locale/en-GB.coffee
index 12bac5e6f..214cf5715 100644
--- a/app/locale/en-GB.coffee
+++ b/app/locale/en-GB.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/en-US.coffee b/app/locale/en-US.coffee
index e34074395..9446407bf 100644
--- a/app/locale/en-US.coffee
+++ b/app/locale/en-US.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index 2afc376cd..dbfdb35d1 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -201,6 +201,7 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
     tome_available_spells: "Available Spells"
     hud_continue: "Continue (press shift-space)"
     spell_saved: "Spell Saved"
+    skip_tutorial: "skip: esc"
 
   admin:
     av_title: "Admin Views"
diff --git a/app/locale/es-419.coffee b/app/locale/es-419.coffee
index 476b9fa7d..3ed36701e 100644
--- a/app/locale/es-419.coffee
+++ b/app/locale/es-419.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip
     tome_available_spells: "Hechizos Disponibles"
     hud_continue: "Continuar (presionar shift+space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/es-ES.coffee b/app/locale/es-ES.coffee
index 5b911e4b1..344426f6a 100644
--- a/app/locale/es-ES.coffee
+++ b/app/locale/es-ES.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
     tome_available_spells: "Hechizos disponibles"
     hud_continue: "Continuar (pulsa Shift+Space)"
     spell_saved: "Hechizo guardado"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/es.coffee b/app/locale/es.coffee
index fabd7b970..502c1f335 100644
--- a/app/locale/es.coffee
+++ b/app/locale/es.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
     tome_available_spells: "Hechizos Disponibles"
     hud_continue: "Continuar (presionar shift+space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/fa.coffee b/app/locale/fa.coffee
index 36d6b4991..543cf7df3 100644
--- a/app/locale/fa.coffee
+++ b/app/locale/fa.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/fi.coffee b/app/locale/fi.coffee
index 35af0bb25..0182c8112 100644
--- a/app/locale/fi.coffee
+++ b/app/locale/fi.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/fr.coffee b/app/locale/fr.coffee
index c869fbe8b..2a70fe98c 100644
--- a/app/locale/fr.coffee
+++ b/app/locale/fr.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     tome_available_spells: "Sorts diponibles"
     hud_continue: "Continuer (appuie sur shift ou espace)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
   admin:
     av_title: "Vues d'administrateurs"
diff --git a/app/locale/he.coffee b/app/locale/he.coffee
index 5d39d1b87..54c89b01f 100644
--- a/app/locale/he.coffee
+++ b/app/locale/he.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/hi.coffee b/app/locale/hi.coffee
index abaae44c6..b0a6f9161 100644
--- a/app/locale/hi.coffee
+++ b/app/locale/hi.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/hu.coffee b/app/locale/hu.coffee
index 39fb5c38d..cb652101c 100644
--- a/app/locale/hu.coffee
+++ b/app/locale/hu.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
     tome_available_spells: "Elérhető varázslatok"
     hud_continue: "Folytatás (shift+space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/id.coffee b/app/locale/id.coffee
index 4c21ab17c..c2d897c22 100644
--- a/app/locale/id.coffee
+++ b/app/locale/id.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/it.coffee b/app/locale/it.coffee
index e1ecb580f..cfd2a89a9 100644
--- a/app/locale/it.coffee
+++ b/app/locale/it.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "italiano", englishDescription: "Italian", t
     tome_available_spells: "Incantesimi disponibili"
     hud_continue: "Continua (premi Maiusc-Spazio)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
   admin:
     av_title: "Vista amministratore"
diff --git a/app/locale/ja.coffee b/app/locale/ja.coffee
index 47b10f118..827987e69 100644
--- a/app/locale/ja.coffee
+++ b/app/locale/ja.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
     tome_available_spells: "利用できる呪文"
     hud_continue: "続く (Shift+Spaceキー)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
   admin:
     av_title: "管理画面"
diff --git a/app/locale/ko.coffee b/app/locale/ko.coffee
index 9b0f4c9c4..87254c99e 100644
--- a/app/locale/ko.coffee
+++ b/app/locale/ko.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/lt.coffee b/app/locale/lt.coffee
index a562a051c..ca7436fe2 100644
--- a/app/locale/lt.coffee
+++ b/app/locale/lt.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/ms-BA.coffee b/app/locale/ms-BA.coffee
index 861bce18e..2605603e6 100644
--- a/app/locale/ms-BA.coffee
+++ b/app/locale/ms-BA.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/nb.coffee b/app/locale/nb.coffee
index 92ac6f932..95fa9862f 100644
--- a/app/locale/nb.coffee
+++ b/app/locale/nb.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
     tome_available_spells: "Tilgjenglige Trylleformularer"
     hud_continue: "Fortsett (trykk shift-mellomrom)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/nl.coffee b/app/locale/nl.coffee
index 929741d23..c48fe57a5 100644
--- a/app/locale/nl.coffee
+++ b/app/locale/nl.coffee
@@ -201,6 +201,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     tome_available_spells: "Beschikbare spreuken"
     hud_continue: "Ga verder (druk shift-space)"
     spell_saved: "Spreuk Opgeslagen"
+#    skip_tutorial: "skip: esc"
 
   admin:
     av_title: "Administrator panels"
diff --git a/app/locale/nn.coffee b/app/locale/nn.coffee
index ceea3a0ea..fc1db1657 100644
--- a/app/locale/nn.coffee
+++ b/app/locale/nn.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/no.coffee b/app/locale/no.coffee
index 4dcd77714..91d8b88b9 100644
--- a/app/locale/no.coffee
+++ b/app/locale/no.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr
     tome_available_spells: "Tilgjenglige Trylleformularer"
     hud_continue: "Fortsett (trykk shift-mellomrom)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/pl.coffee b/app/locale/pl.coffee
index 826e5669c..4b0a37ec0 100644
--- a/app/locale/pl.coffee
+++ b/app/locale/pl.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish
     tome_available_spells: "Dostępne czary"
     hud_continue: "Kontynuuj (naciśnij enter)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/pt-BR.coffee b/app/locale/pt-BR.coffee
index e6a285655..84dae2d58 100644
--- a/app/locale/pt-BR.coffee
+++ b/app/locale/pt-BR.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription:
     tome_available_spells: "Feitiços Disponíveis"
     hud_continue: "Continue (tecle Shift+Space)"
     spell_saved: "Feitiço Salvo"
+#    skip_tutorial: "skip: esc"
 
   admin:
     av_title: "Visualização de Administrador"
diff --git a/app/locale/pt-PT.coffee b/app/locale/pt-PT.coffee
index 1ce48a42f..d3ab714c1 100644
--- a/app/locale/pt-PT.coffee
+++ b/app/locale/pt-PT.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P
     tome_available_spells: "Feitiços disponíveis"
     hud_continue: "Continuar (pressiona shift-space)"
     spell_saved: "Feitiço Guardado"
+#    skip_tutorial: "skip: esc"
 
   admin:
     av_title: "Visualizações de Admin"
diff --git a/app/locale/pt.coffee b/app/locale/pt.coffee
index 9aedeae92..76b378b71 100644
--- a/app/locale/pt.coffee
+++ b/app/locale/pt.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues
     tome_available_spells: "Feitiços Disponíveis"
     hud_continue: "Continue (tecle Shift+Space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/ro.coffee b/app/locale/ro.coffee
index 454278097..6cb6dfcb3 100644
--- a/app/locale/ro.coffee
+++ b/app/locale/ro.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 985282a6c..d1c7e7db2 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     tome_available_spells: "Доступные заклинания"
     hud_continue: "Продолжить (нажмите Shift+Пробел)"
     spell_saved: "Заклинание сохранено"
+#    skip_tutorial: "skip: esc"
 
   admin:
     av_title: "Админ панель"
diff --git a/app/locale/sk.coffee b/app/locale/sk.coffee
index 9050f2181..7c6dd325f 100644
--- a/app/locale/sk.coffee
+++ b/app/locale/sk.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/sl.coffee b/app/locale/sl.coffee
index 97559521a..8ebcde87e 100644
--- a/app/locale/sl.coffee
+++ b/app/locale/sl.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/sr.coffee b/app/locale/sr.coffee
index 179b74906..77f9513dd 100644
--- a/app/locale/sr.coffee
+++ b/app/locale/sr.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
     tome_available_spells: "Доступне чини"
     hud_continue: "Настави (притисни ентер)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/sv.coffee b/app/locale/sv.coffee
index b3868e937..075c1adbf 100644
--- a/app/locale/sv.coffee
+++ b/app/locale/sv.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
     tome_available_spells: "Tillgängliga Förmågor"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/th.coffee b/app/locale/th.coffee
index 9fd74d3a0..8a00dddc9 100644
--- a/app/locale/th.coffee
+++ b/app/locale/th.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/tr.coffee b/app/locale/tr.coffee
index 297c9f50d..d5f698aed 100644
--- a/app/locale/tr.coffee
+++ b/app/locale/tr.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
     tome_available_spells: "Kullanılabilir Büyüler"
     hud_continue: "Devam (ÜstKarakter+Boşluk)"
     spell_saved: "Büyü Kaydedildi"
+#    skip_tutorial: "skip: esc"
 
   admin:
     av_title: "Yönetici Görünümleri"
diff --git a/app/locale/uk.coffee b/app/locale/uk.coffee
index 3f3a375c7..d0f9f2614 100644
--- a/app/locale/uk.coffee
+++ b/app/locale/uk.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
     tome_available_spells: "Доступні закляття"
     hud_continue: "Продовжити (натисніть shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/ur.coffee b/app/locale/ur.coffee
index d36ce12ec..6090f23bc 100644
--- a/app/locale/ur.coffee
+++ b/app/locale/ur.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/vi.coffee b/app/locale/vi.coffee
index 99992f8c5..6e424c0d9 100644
--- a/app/locale/vi.coffee
+++ b/app/locale/vi.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/zh-HANS.coffee b/app/locale/zh-HANS.coffee
index 13c3d3161..c8d3a7d26 100644
--- a/app/locale/zh-HANS.coffee
+++ b/app/locale/zh-HANS.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     tome_available_spells: "可用的法术"
     hud_continue: "继续(按 Shift-空格)"
     spell_saved: "咒语已保存"
+#    skip_tutorial: "skip: esc"
 
   admin:
     av_title: "管理员视图"
diff --git a/app/locale/zh-HANT.coffee b/app/locale/zh-HANT.coffee
index aad8bbbf9..2e869ad1e 100644
--- a/app/locale/zh-HANT.coffee
+++ b/app/locale/zh-HANT.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
     tome_available_spells: "可用的法術"
     hud_continue: "繼續 (按 shift-空格)"
     spell_saved: "咒語已儲存"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/zh.coffee b/app/locale/zh.coffee
index f0afbd64b..a06033aab 100644
--- a/app/locale/zh.coffee
+++ b/app/locale/zh.coffee
@@ -200,6 +200,7 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
 #    tome_available_spells: "Available Spells"
 #    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
+#    skip_tutorial: "skip: esc"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/views/play/level/hud_view.coffee b/app/views/play/level/hud_view.coffee
index f4580660b..c2ea8cc4c 100644
--- a/app/views/play/level/hud_view.coffee
+++ b/app/views/play/level/hud_view.coffee
@@ -176,8 +176,9 @@ module.exports = class HUDView extends View
         response.button = $('button:last', group)
     else
       s = $.i18n.t('play_level.hud_continue', defaultValue: "Continue (press shift-space)")
+      sk = $.i18n.t('play_level.skip_tutorial', defaultValue: "skip: esc")
       if @shiftSpacePressed > 4 and not @escapePressed
-        @bubble.append('<span class="hud-hint">skip: esc</span>')
+        @bubble.append('<span class="hud-hint">' + sk + '</span>')
       group.append($('<button class="btn btn-small banner with-dot">' + s + ' <div class="dot"></div></button>'))
       @lastResponses = null
     @bubble.append($("<h3>#{@speaker ? 'Captain Anya'}</h3>"))

From d16d02478254ca92169e485145119d878921a887 Mon Sep 17 00:00:00 2001
From: Dominik Kundel <dominik.kundel@gmail.com>
Date: Wed, 5 Mar 2014 17:06:46 +0100
Subject: [PATCH 076/178] further changes in design of highlighting lines in
 code

---
 app/styles/play/level/tome/spell.sass       | 4 ++--
 app/views/play/level/tome/spell_view.coffee | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/app/styles/play/level/tome/spell.sass b/app/styles/play/level/tome/spell.sass
index 5fdfa7c61..5990e7885 100644
--- a/app/styles/play/level/tome/spell.sass
+++ b/app/styles/play/level/tome/spell.sass
@@ -76,7 +76,7 @@
       background-color: rgba(0, 255, 0, 0.15)
       @include gradient-striped()
     .executed
-      background-color: rgba(40, 40, 40, 0.12)
+      background-color: rgba(110, 110, 110, 0.12)
     .problem-marker-info
       background-color: rgba(196, 163, 184, 0.25)
     .problem-marker-warning
@@ -95,7 +95,7 @@
 
     .ace_gutter-cell.executed:not(.ace_error)
       margin-left: 1px
-      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAOpJREFUeNpiYBgFpAD2NGMDIA6glmECQNyPLs5EgZnzmb783kgt1zUA8XxscixkGOYApPJZXnwz/IlFnolEwxSA1HrGX38nft10/QE2NYykRAKQ2g/EAhznXxt+PP3oA6VeBsWoAfOHn4m4DMPnmvscSYb7kfgJQPwfWQwXYMThtfdgyV9/G/+zMW8AMs+DvfPimyMw7A6QZCAsWQCpeigXFPgKTN/+LPi+5GIiIRfiiuUJUINAQIHx7/8PTJ9+NRITXFgN/DnrLCjQC+He+P4HZzIhKdkAvb6e8cdfBfbr7xxJjtmRAwACDAA0klcB6aJFbwAAAABJRU5ErkJggg==)
+      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAANhJREFUeNpi/P//PwM1ARMDlcHgMrA428MAiANQBEFhSA4uynIXAOJ+dHFKXDgfiDdSxctAbzYAqQ+9U3ccQJdjIcMwByCVD8SGFEcK0DAFILUeiCcCXfeAIgOBhglADfsAxBNwqSPFy/1AbADEiUDXfSApHQJdcx+I9yPxE4AUCB8AGrYAn62M6HkZ6rX3UG4jEG8A4vNQviO2mMXrQqh3GqHcemi4gcACQobhixRQoMNiUQEaEY1k52WoKwuRhHAmE6KTDdCADdDwu4AvmRCMlOFfwAIEGAD4On+N4aXlhgAAAABJRU5ErkJggg==)
       background-position: 0px center
 
     .ace_gutter-cell.comment-line
diff --git a/app/views/play/level/tome/spell_view.coffee b/app/views/play/level/tome/spell_view.coffee
index 679ef7d87..af9d2ad7f 100644
--- a/app/views/play/level/tome/spell_view.coffee
+++ b/app/views/play/level/tome/spell_view.coffee
@@ -456,7 +456,9 @@ module.exports = class SpellView extends View
       @aceSession.removeMarker markerRange.id
     @markerRanges = []
     @aceSession.removeGutterDecoration row, 'executing' for row in [0 ... @aceSession.getLength()]
+    @aceSession.removeGutterDecoration row, 'executed' for row in [0 ... @aceSession.getLength()]
     $(@ace.container).find('.ace_gutter-cell.executing').removeClass('executing')
+    $(@ace.container).find('.ace_gutter-cell.executed').removeClass('executed')
     if not executed.length or (@spell.name is "plan" and @spellThang.castAether.metrics.statementsExecuted < 20)
       @toolbarView?.toggleFlow false
       @debugView.setVariableStates {}

From f6324807b399d7cf888315b66bccc54d74b4aad0 Mon Sep 17 00:00:00 2001
From: Shrihari <gfxindia@gmail.com>
Date: Wed, 5 Mar 2014 23:36:18 +0530
Subject: [PATCH 077/178] Moved "Skip (esc)" next to Continue button

---
 app/locale/ar.coffee                 | 4 ++--
 app/locale/bg.coffee                 | 4 ++--
 app/locale/cs.coffee                 | 2 +-
 app/locale/da.coffee                 | 2 +-
 app/locale/de.coffee                 | 2 +-
 app/locale/el.coffee                 | 4 ++--
 app/locale/en-AU.coffee              | 4 ++--
 app/locale/en-GB.coffee              | 4 ++--
 app/locale/en-US.coffee              | 4 ++--
 app/locale/en.coffee                 | 4 ++--
 app/locale/es-419.coffee             | 2 +-
 app/locale/es-ES.coffee              | 2 +-
 app/locale/es.coffee                 | 2 +-
 app/locale/fa.coffee                 | 4 ++--
 app/locale/fi.coffee                 | 4 ++--
 app/locale/fr.coffee                 | 2 +-
 app/locale/he.coffee                 | 4 ++--
 app/locale/hi.coffee                 | 4 ++--
 app/locale/hu.coffee                 | 2 +-
 app/locale/id.coffee                 | 4 ++--
 app/locale/it.coffee                 | 2 +-
 app/locale/ja.coffee                 | 2 +-
 app/locale/ko.coffee                 | 4 ++--
 app/locale/lt.coffee                 | 4 ++--
 app/locale/ms-BA.coffee              | 4 ++--
 app/locale/nb.coffee                 | 2 +-
 app/locale/nl.coffee                 | 2 +-
 app/locale/nn.coffee                 | 4 ++--
 app/locale/no.coffee                 | 2 +-
 app/locale/pl.coffee                 | 2 +-
 app/locale/pt-BR.coffee              | 2 +-
 app/locale/pt-PT.coffee              | 2 +-
 app/locale/pt.coffee                 | 2 +-
 app/locale/ro.coffee                 | 4 ++--
 app/locale/ru.coffee                 | 2 +-
 app/locale/sk.coffee                 | 4 ++--
 app/locale/sl.coffee                 | 4 ++--
 app/locale/sr.coffee                 | 2 +-
 app/locale/sv.coffee                 | 4 ++--
 app/locale/th.coffee                 | 4 ++--
 app/locale/tr.coffee                 | 2 +-
 app/locale/uk.coffee                 | 2 +-
 app/locale/ur.coffee                 | 4 ++--
 app/locale/vi.coffee                 | 4 ++--
 app/locale/zh-HANS.coffee            | 2 +-
 app/locale/zh-HANT.coffee            | 2 +-
 app/locale/zh.coffee                 | 4 ++--
 app/styles/play/level/hud.sass       | 5 +----
 app/views/play/level/hud_view.coffee | 6 +++---
 49 files changed, 75 insertions(+), 78 deletions(-)

diff --git a/app/locale/ar.coffee b/app/locale/ar.coffee
index cb4c293df..1f0584c85 100644
--- a/app/locale/ar.coffee
+++ b/app/locale/ar.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/bg.coffee b/app/locale/bg.coffee
index 6829f58fa..fd038c56c 100644
--- a/app/locale/bg.coffee
+++ b/app/locale/bg.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "български език", englishDescri
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/cs.coffee b/app/locale/cs.coffee
index 15896ec83..121f0da4f 100644
--- a/app/locale/cs.coffee
+++ b/app/locale/cs.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
     tome_available_spells: "Dostupná kouzla"
     hud_continue: "Pokračovat (stiskněte shift-mezera)"
     spell_saved: "Kouzlo uloženo"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
   admin:
     av_title: "Administrátorský pohled"
diff --git a/app/locale/da.coffee b/app/locale/da.coffee
index c825de14d..ad47c71fc 100644
--- a/app/locale/da.coffee
+++ b/app/locale/da.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
     tome_available_spells: "Tilgængelige trylleformularer"
     hud_continue: "Fortsæt (tryk skift-mellemrum)"
     spell_saved: "Trylleformularen er gemt"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
   admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/de.coffee b/app/locale/de.coffee
index 6d6bb469d..04b640ce8 100644
--- a/app/locale/de.coffee
+++ b/app/locale/de.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra
     tome_available_spells: "Verfügbare Zauber"
     hud_continue: "Weiter (drücke Shift + Leertaste)"
     spell_saved: "Zauber gespeichert"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
   admin:
     av_title: "Administrator Übersicht"
diff --git a/app/locale/el.coffee b/app/locale/el.coffee
index a03bff546..91fd4be36 100644
--- a/app/locale/el.coffee
+++ b/app/locale/el.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "ελληνικά", englishDescription: "Gre
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/en-AU.coffee b/app/locale/en-AU.coffee
index 70ec9b81e..8c36e3ef7 100644
--- a/app/locale/en-AU.coffee
+++ b/app/locale/en-AU.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/en-GB.coffee b/app/locale/en-GB.coffee
index 214cf5715..1da9d218a 100644
--- a/app/locale/en-GB.coffee
+++ b/app/locale/en-GB.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/en-US.coffee b/app/locale/en-US.coffee
index 9446407bf..9d3b2dc5a 100644
--- a/app/locale/en-US.coffee
+++ b/app/locale/en-US.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index dbfdb35d1..5ca5cf902 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -199,9 +199,9 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
     tome_select_spell: "Select a Spell"
     tome_select_a_thang: "Select Someone for "
     tome_available_spells: "Available Spells"
-    hud_continue: "Continue (press shift-space)"
+    hud_continue: "Continue (shift+space)"
     spell_saved: "Spell Saved"
-    skip_tutorial: "skip: esc"
+    skip_tutorial: "Skip (esc)"
 
   admin:
     av_title: "Admin Views"
diff --git a/app/locale/es-419.coffee b/app/locale/es-419.coffee
index 3ed36701e..3c2614713 100644
--- a/app/locale/es-419.coffee
+++ b/app/locale/es-419.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip
     tome_available_spells: "Hechizos Disponibles"
     hud_continue: "Continuar (presionar shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/es-ES.coffee b/app/locale/es-ES.coffee
index 344426f6a..e45550e08 100644
--- a/app/locale/es-ES.coffee
+++ b/app/locale/es-ES.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
     tome_available_spells: "Hechizos disponibles"
     hud_continue: "Continuar (pulsa Shift+Space)"
     spell_saved: "Hechizo guardado"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/es.coffee b/app/locale/es.coffee
index 502c1f335..b4009323b 100644
--- a/app/locale/es.coffee
+++ b/app/locale/es.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
     tome_available_spells: "Hechizos Disponibles"
     hud_continue: "Continuar (presionar shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/fa.coffee b/app/locale/fa.coffee
index 543cf7df3..28a4bd760 100644
--- a/app/locale/fa.coffee
+++ b/app/locale/fa.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/fi.coffee b/app/locale/fi.coffee
index 0182c8112..57e5151e4 100644
--- a/app/locale/fi.coffee
+++ b/app/locale/fi.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/fr.coffee b/app/locale/fr.coffee
index 2a70fe98c..1469c7269 100644
--- a/app/locale/fr.coffee
+++ b/app/locale/fr.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     tome_available_spells: "Sorts diponibles"
     hud_continue: "Continuer (appuie sur shift ou espace)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
   admin:
     av_title: "Vues d'administrateurs"
diff --git a/app/locale/he.coffee b/app/locale/he.coffee
index 54c89b01f..ddcb7484c 100644
--- a/app/locale/he.coffee
+++ b/app/locale/he.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/hi.coffee b/app/locale/hi.coffee
index b0a6f9161..596ecd1ce 100644
--- a/app/locale/hi.coffee
+++ b/app/locale/hi.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/hu.coffee b/app/locale/hu.coffee
index cb652101c..ad6cd0273 100644
--- a/app/locale/hu.coffee
+++ b/app/locale/hu.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
     tome_available_spells: "Elérhető varázslatok"
     hud_continue: "Folytatás (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/id.coffee b/app/locale/id.coffee
index c2d897c22..20d16335f 100644
--- a/app/locale/id.coffee
+++ b/app/locale/id.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/it.coffee b/app/locale/it.coffee
index cfd2a89a9..a95f98916 100644
--- a/app/locale/it.coffee
+++ b/app/locale/it.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "italiano", englishDescription: "Italian", t
     tome_available_spells: "Incantesimi disponibili"
     hud_continue: "Continua (premi Maiusc-Spazio)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
   admin:
     av_title: "Vista amministratore"
diff --git a/app/locale/ja.coffee b/app/locale/ja.coffee
index 827987e69..4c9e4dfb9 100644
--- a/app/locale/ja.coffee
+++ b/app/locale/ja.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
     tome_available_spells: "利用できる呪文"
     hud_continue: "続く (Shift+Spaceキー)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
   admin:
     av_title: "管理画面"
diff --git a/app/locale/ko.coffee b/app/locale/ko.coffee
index 87254c99e..882f3d4ac 100644
--- a/app/locale/ko.coffee
+++ b/app/locale/ko.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/lt.coffee b/app/locale/lt.coffee
index ca7436fe2..1008a8bfb 100644
--- a/app/locale/lt.coffee
+++ b/app/locale/lt.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/ms-BA.coffee b/app/locale/ms-BA.coffee
index 2605603e6..29c914f23 100644
--- a/app/locale/ms-BA.coffee
+++ b/app/locale/ms-BA.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/nb.coffee b/app/locale/nb.coffee
index 95fa9862f..db74e540d 100644
--- a/app/locale/nb.coffee
+++ b/app/locale/nb.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
     tome_available_spells: "Tilgjenglige Trylleformularer"
     hud_continue: "Fortsett (trykk shift-mellomrom)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/nl.coffee b/app/locale/nl.coffee
index c48fe57a5..508d6e384 100644
--- a/app/locale/nl.coffee
+++ b/app/locale/nl.coffee
@@ -201,7 +201,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     tome_available_spells: "Beschikbare spreuken"
     hud_continue: "Ga verder (druk shift-space)"
     spell_saved: "Spreuk Opgeslagen"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
   admin:
     av_title: "Administrator panels"
diff --git a/app/locale/nn.coffee b/app/locale/nn.coffee
index fc1db1657..c9e770bfa 100644
--- a/app/locale/nn.coffee
+++ b/app/locale/nn.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/no.coffee b/app/locale/no.coffee
index 91d8b88b9..bc0e69e0c 100644
--- a/app/locale/no.coffee
+++ b/app/locale/no.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr
     tome_available_spells: "Tilgjenglige Trylleformularer"
     hud_continue: "Fortsett (trykk shift-mellomrom)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/pl.coffee b/app/locale/pl.coffee
index 4b0a37ec0..9988be45e 100644
--- a/app/locale/pl.coffee
+++ b/app/locale/pl.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish
     tome_available_spells: "Dostępne czary"
     hud_continue: "Kontynuuj (naciśnij enter)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/pt-BR.coffee b/app/locale/pt-BR.coffee
index 84dae2d58..40f374f81 100644
--- a/app/locale/pt-BR.coffee
+++ b/app/locale/pt-BR.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription:
     tome_available_spells: "Feitiços Disponíveis"
     hud_continue: "Continue (tecle Shift+Space)"
     spell_saved: "Feitiço Salvo"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
   admin:
     av_title: "Visualização de Administrador"
diff --git a/app/locale/pt-PT.coffee b/app/locale/pt-PT.coffee
index d3ab714c1..77fb7afad 100644
--- a/app/locale/pt-PT.coffee
+++ b/app/locale/pt-PT.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P
     tome_available_spells: "Feitiços disponíveis"
     hud_continue: "Continuar (pressiona shift-space)"
     spell_saved: "Feitiço Guardado"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
   admin:
     av_title: "Visualizações de Admin"
diff --git a/app/locale/pt.coffee b/app/locale/pt.coffee
index 76b378b71..38a21790c 100644
--- a/app/locale/pt.coffee
+++ b/app/locale/pt.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues
     tome_available_spells: "Feitiços Disponíveis"
     hud_continue: "Continue (tecle Shift+Space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/ro.coffee b/app/locale/ro.coffee
index 6cb6dfcb3..3dfc71d1e 100644
--- a/app/locale/ro.coffee
+++ b/app/locale/ro.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index d1c7e7db2..57cfc1847 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     tome_available_spells: "Доступные заклинания"
     hud_continue: "Продолжить (нажмите Shift+Пробел)"
     spell_saved: "Заклинание сохранено"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
   admin:
     av_title: "Админ панель"
diff --git a/app/locale/sk.coffee b/app/locale/sk.coffee
index 7c6dd325f..c9e3e4023 100644
--- a/app/locale/sk.coffee
+++ b/app/locale/sk.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/sl.coffee b/app/locale/sl.coffee
index 8ebcde87e..b0cbdd3f5 100644
--- a/app/locale/sl.coffee
+++ b/app/locale/sl.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/sr.coffee b/app/locale/sr.coffee
index 77f9513dd..c9676fa65 100644
--- a/app/locale/sr.coffee
+++ b/app/locale/sr.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
     tome_available_spells: "Доступне чини"
     hud_continue: "Настави (притисни ентер)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/sv.coffee b/app/locale/sv.coffee
index 075c1adbf..d8b41ec50 100644
--- a/app/locale/sv.coffee
+++ b/app/locale/sv.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
     tome_select_spell: "Välj en Förmåga"
     tome_select_a_thang: "Välj Någon för "
     tome_available_spells: "Tillgängliga Förmågor"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/th.coffee b/app/locale/th.coffee
index 8a00dddc9..9b2134eb8 100644
--- a/app/locale/th.coffee
+++ b/app/locale/th.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/tr.coffee b/app/locale/tr.coffee
index d5f698aed..4a256defe 100644
--- a/app/locale/tr.coffee
+++ b/app/locale/tr.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
     tome_available_spells: "Kullanılabilir Büyüler"
     hud_continue: "Devam (ÜstKarakter+Boşluk)"
     spell_saved: "Büyü Kaydedildi"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
   admin:
     av_title: "Yönetici Görünümleri"
diff --git a/app/locale/uk.coffee b/app/locale/uk.coffee
index d0f9f2614..bf67c2138 100644
--- a/app/locale/uk.coffee
+++ b/app/locale/uk.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
     tome_available_spells: "Доступні закляття"
     hud_continue: "Продовжити (натисніть shift-space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/ur.coffee b/app/locale/ur.coffee
index 6090f23bc..8237971a3 100644
--- a/app/locale/ur.coffee
+++ b/app/locale/ur.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/vi.coffee b/app/locale/vi.coffee
index 6e424c0d9..c3a00a167 100644
--- a/app/locale/vi.coffee
+++ b/app/locale/vi.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/zh-HANS.coffee b/app/locale/zh-HANS.coffee
index c8d3a7d26..f6eebce5d 100644
--- a/app/locale/zh-HANS.coffee
+++ b/app/locale/zh-HANS.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     tome_available_spells: "可用的法术"
     hud_continue: "继续(按 Shift-空格)"
     spell_saved: "咒语已保存"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
   admin:
     av_title: "管理员视图"
diff --git a/app/locale/zh-HANT.coffee b/app/locale/zh-HANT.coffee
index 2e869ad1e..d38532973 100644
--- a/app/locale/zh-HANT.coffee
+++ b/app/locale/zh-HANT.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
     tome_available_spells: "可用的法術"
     hud_continue: "繼續 (按 shift-空格)"
     spell_saved: "咒語已儲存"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/locale/zh.coffee b/app/locale/zh.coffee
index a06033aab..aacf8fe4d 100644
--- a/app/locale/zh.coffee
+++ b/app/locale/zh.coffee
@@ -198,9 +198,9 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
+#    hud_continue: "Continue (shift+space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "skip: esc"
+#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
diff --git a/app/styles/play/level/hud.sass b/app/styles/play/level/hud.sass
index 7858f0365..9cccb690d 100644
--- a/app/styles/play/level/hud.sass
+++ b/app/styles/play/level/hud.sass
@@ -230,10 +230,7 @@
 
         .hud-hint
           font-weight: normal
-          color: #aaa
-          position: absolute
-          top: 0
-          right: 4px
+          color: #999
 
         .enter
           position: absolute
diff --git a/app/views/play/level/hud_view.coffee b/app/views/play/level/hud_view.coffee
index c2ea8cc4c..7a5c42af9 100644
--- a/app/views/play/level/hud_view.coffee
+++ b/app/views/play/level/hud_view.coffee
@@ -175,10 +175,10 @@ module.exports = class HUDView extends View
         group.append(button)
         response.button = $('button:last', group)
     else
-      s = $.i18n.t('play_level.hud_continue', defaultValue: "Continue (press shift-space)")
+      s = $.i18n.t('play_level.hud_continue', defaultValue: "Continue (shift+space)")
       sk = $.i18n.t('play_level.skip_tutorial', defaultValue: "skip: esc")
-      if @shiftSpacePressed > 4 and not @escapePressed
-        @bubble.append('<span class="hud-hint">' + sk + '</span>')
+      if not @escapePressed
+        group.append('<span class="hud-hint">' + sk + '</span>')
       group.append($('<button class="btn btn-small banner with-dot">' + s + ' <div class="dot"></div></button>'))
       @lastResponses = null
     @bubble.append($("<h3>#{@speaker ? 'Captain Anya'}</h3>"))

From ea98a9917d4993b1d066f2a949e072e693f9f80a Mon Sep 17 00:00:00 2001
From: Darredevil <alex.darredevil@gmail.com>
Date: Wed, 5 Mar 2014 20:40:14 +0200
Subject: [PATCH 078/178] Update ro

---
 app/locale/ro.coffee | 107 +++++++++++++++++++++----------------------
 1 file changed, 53 insertions(+), 54 deletions(-)

diff --git a/app/locale/ro.coffee b/app/locale/ro.coffee
index f8dd54668..6bdb8e75a 100644
--- a/app/locale/ro.coffee
+++ b/app/locale/ro.coffee
@@ -1,6 +1,6 @@
 module.exports = nativeDescription: "limba română", englishDescription: "Romanian", translation:
   common:
-    loading: "Loading..."
+    loading: "Se incarcă..."
     saving: "Se salvează..."
     sending: "Se trimite..."
     cancel: "Anulează"
@@ -53,8 +53,8 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
 
   signup:
     create_account_title: "Crează cont pentru a salva progresul"
-    description: "Este gratis. Doar câte ceva inainte si poți continua:"#contextual translation a bit off, could be better# It's free. Just need a couple things and you'll be good to go:"
-    email_announcements: "Receive announcements by email"
+    description: "Este gratis. Doar un scurt formular inainte si poți continua:"#contextual translation a bit off, could be better# It's free. Just need a couple things and you'll be good to go:"
+    email_announcements: "Primește notificări prin emaill"
     coppa: "13+ sau non-USA "
     coppa_why: "(De ce?)"
     creating: "Se crează contul..."
@@ -63,7 +63,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
 
   home:
     slogan: "Învață sa scri JavaScript jucându-te"# again sounds funny# Learn to Code JavaScript by Playing a Game"
-    no_ie: "CodeCombat does not run in Internet Explorer 9 or older. Sorry!"
+    no_ie: "CodeCombat nu merge pe Internet Explorer 9 sau mai vechi. Scuze!"
     no_mobile: "CodeCombat nu a fost proiectat pentru dispozitive mobile si s-ar putea sa nu meargâ!"
     play: "Joacâ"
 
@@ -78,59 +78,59 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
     campaign_dev_description: "... în care se învață interfața, cu o dificultate puțin mai mare."
     campaign_multiplayer: "Arene Multiplayer"
     campaign_multiplayer_description: "... în care te lupți cap-la-cap contra alti jucători."
-#    campaign_player_created: "Player-Created"
-#    campaign_player_created_description: "... in which you battle against the creativity of your fellow <a href=\"/contribute#artisan\">Artisan Wizards</a>."
-#    level_difficulty: "Difficulty: "
+    campaign_player_created: "Create de jucători"
+    campaign_player_created_description: "... în care ai ocazia să testezi creativitatea colegilor tai <a href=\"/contribute#artisan\">Artisan Wizards</a>."
+    level_difficulty: "Dificultate: "
 
-#  contact:
-#    contact_us: "Contact CodeCombat"
-#    welcome: "Good to hear from you! Use this form to send us email. "
-#    contribute_prefix: "If you're interested in contributing, check out our "
-#    contribute_page: "contribute page"
-#    contribute_suffix: "!"
-#    forum_prefix: "For anything public, please try "
-#    forum_page: "our forum"
-#    forum_suffix: " instead."
-#    send: "Send Feedback"
+  contact:
+    contact_us: "Contact CodeCombat"
+    welcome: "Folosiți acest formular pentru a ne trimite email. "
+    contribute_prefix: "Dacă sunteți interesați in a contribui uitați-vă pe "
+    contribute_page: "pagina de contribuție"
+    contribute_suffix: "!"
+    forum_prefix: "Pentru orice altceva vă rugăm sa incercați "
+    forum_page: "forumul nostru"
+    forum_suffix: " în schimb."
+    send: "Trimite Feedback"
 
   diplomat_suggestion:
-#    title: "Help translate CodeCombat!"
-#    sub_heading: "We need your language skills."
-    pitch_body: "We develop CodeCombat in English, but we already have players all over the world. Many of them want to play in Romanian but don't speak English, so if you can speak both, please consider signing up to be a Diplomat and help translate both the CodeCombat website and all the levels into Romanian."
-    missing_translations: "Until we can translate everything into Romanian, you'll see English when Romanian isn't available."
-#    learn_more: "Learn more about being a Diplomat"
-#    subscribe_as_diplomat: "Subscribe as a Diplomat"
+    title: "Ajută-ne  să traducem CodeCombat!"
+    sub_heading: "Avem nevoie de abilitățile tale lingvistice."
+    pitch_body: "We develop CodeCombat in English, but we already have players all over the world. Many of them want to play in Romanian but don't speak English, so if you can speak both, please consider signing up to be a Diplomat and help translate both the CodeCombat website and all the levels into Romanian." #are these still needed??
+    missing_translations: "Until we can translate everything into Romanian, you'll see English when Romanian isn't available." # is this still needed?
+    learn_more: "Află mai multe despre cum să fi un Diplomat"
+    subscribe_as_diplomat: "Înscrie-te ca Diplomat"
 
-#  wizard_settings:
-#    title: "Wizard Settings"
-#    customize_avatar: "Customize Your Avatar"
-#    clothes: "Clothes"
-#    trim: "Trim"
-#    cloud: "Cloud"
-#    spell: "Spell"
-#    boots: "Boots"
-#    hue: "Hue"
-#    saturation: "Saturation"
-#    lightness: "Lightness"
+  wizard_settings:
+    title: "Setări Wizard"
+    customize_avatar: "Personalizează-ți Avatarul"
+    clothes: "Haine"
+    trim: "Margine" 
+    cloud: "Nor"
+    spell: "Vrajă"
+    boots: "Încălțăminte"
+    hue: "Culoare"
+    saturation: "Saturație"
+    lightness: "Luminozitate"
 
-#  account_settings:
-#    title: "Account Settings"
-#    not_logged_in: "Log in or create an account to change your settings."
-#    autosave: "Changes Save Automatically"
-#    me_tab: "Me"
-#    picture_tab: "Picture"
-#    wizard_tab: "Wizard"
-#    password_tab: "Password"
-#    emails_tab: "Emails"
-#    gravatar_select: "Select which Gravatar photo to use"
-#    gravatar_add_photos: "Add thumbnails and photos to a Gravatar account for your email to choose an image."
-#    gravatar_add_more_photos: "Add more photos to your Gravatar account to access them here."
-#    wizard_color: "Wizard Clothes Color"
-#    new_password: "New Password"
-#    new_password_verify: "Verify"
-#    email_subscriptions: "Email Subscriptions"
-#    email_announcements: "Announcements"
-#    email_notifications_description: "Get periodic notifications for your account."
+  account_settings:
+    title: "Setări Cont"
+    not_logged_in: "Loghează-te sau crează un cont nou pentru a schimba setările."
+    autosave: "Modificările se salvează automat"
+    me_tab: "Eu"
+    picture_tab: "Poză"
+    wizard_tab: "Wizard"
+    password_tab: "Parolă"
+    emails_tab: "Email-uri"
+    gravatar_select: "Selectează ce poză Gravatar vrei să foloșesti"
+    gravatar_add_photos: "Adaugă thumbnails și poze la un cont Gravatar pentru email-ul tău pentru a alege o imagine."
+    gravatar_add_more_photos: "Adaugă mai multe poze la contul tău Gravatar pentru a le accesa aici."
+    wizard_color: "Culoare haine pentru Wizard"
+    new_password: "Parolă nouă"
+    new_password_verify: "Verifică"
+    email_subscriptions: "Subscripție Email"
+    email_announcements: "Anunțuri"
+    email_notifications_description: "Get periodic notifications for your account."
 #    email_announcements_description: "Get emails on the latest news and developments at CodeCombat."
 #    contributor_emails: "Contributor Class Emails"
 #    contribute_prefix: "We're looking for people to join our party! Check out the "
@@ -198,9 +198,8 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
 #    tome_select_spell: "Select a Spell"
 #    tome_select_a_thang: "Select Someone for "
 #    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (shift+space)"
+#    hud_continue: "Continue (press shift-space)"
 #    spell_saved: "Spell Saved"
-#    skip_tutorial: "Skip (esc)"
 
 #  admin:
 #    av_title: "Admin Views"

From 5ec06159a6cf5c6c726485941986df34ae85e1f2 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Wed, 5 Mar 2014 12:00:29 -0800
Subject: [PATCH 079/178] Fixed ChallengePost utm link. Tweaked God worker
 timeout for more reliable performance logging.

---
 README.md          | 2 +-
 app/lib/God.coffee | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 7ec226f6e..4d23640e3 100644
--- a/README.md
+++ b/README.md
@@ -52,6 +52,6 @@ Whether you're novice or pro, the CodeCombat team is ready to help you implement
 
 ----------
 
-[![](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/challengepost.png)](http://codecombat.challengepost.com/?utm_source-github&utm_medium-oswidget&utm_campaign-codecombat)
+[![](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/challengepost.png)](http://codecombat.challengepost.com/?utm_source=github&utm_medium=oswidget&utm_campaign=codecombat)
 
 [![](http://1-ps.googleusercontent.com/x/s.google-melange.appspot.com/www.google-melange.com/soc/content/2-1-20140225/images/gsoc/logo/920x156xbanner-gsoc2014.png.pagespeed.ic.gdr4t3Igca.png)](http://www.google-melange.com/gsoc/homepage/google/gsoc2014)
\ No newline at end of file
diff --git a/app/lib/God.coffee b/app/lib/God.coffee
index ff92f7e31..f7563517e 100644
--- a/app/lib/God.coffee
+++ b/app/lib/God.coffee
@@ -227,7 +227,7 @@ class Angel
       _.delay ->
         worker.terminate()
         worker.removeEventListener 'message', onWorkerMessage
-      , 2000
+      , 3000
       @worker = null
     @
 

From 7885b21b4b516a873cf288f7f9e32e4f91377530 Mon Sep 17 00:00:00 2001
From: iraladson <aladso@saic.edu>
Date: Wed, 5 Mar 2014 14:03:57 -0600
Subject: [PATCH 080/178] Update names.coffee

---
 app/lib/world/names.coffee | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/app/lib/world/names.coffee b/app/lib/world/names.coffee
index a7a3f256e..789c9b0f8 100644
--- a/app/lib/world/names.coffee
+++ b/app/lib/world/names.coffee
@@ -61,6 +61,8 @@ module.exports.thangNames = thangNames =
     "Joan"
     "Helga"
     "Annie"
+    "Lukaz"
+    "Gorgin"
   ]
   "Peasant": [
     "Yorik"
@@ -83,6 +85,8 @@ module.exports.thangNames = thangNames =
     "Bernadette"
     "Hershell"
     "Gawain"
+    "Durfkor"
+    "Paps"
   ]
   "Archer F": [
     "Phoebe"
@@ -117,6 +121,8 @@ module.exports.thangNames = thangNames =
     "Simon"
     "Robin"
     "Quinn"
+    "Arty"
+    "Gimsley"
   ]
   "Ogre Munchkin M": [
     "Brack"

From 8d046c31b990fbfdeef066422fa95954aa43253b Mon Sep 17 00:00:00 2001
From: iraladson <aladso@saic.edu>
Date: Wed, 5 Mar 2014 14:06:29 -0600
Subject: [PATCH 081/178] Update names.coffee

"Added more names for #53
---
 app/lib/world/names.coffee | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/app/lib/world/names.coffee b/app/lib/world/names.coffee
index a7a3f256e..b23f8b862 100644
--- a/app/lib/world/names.coffee
+++ b/app/lib/world/names.coffee
@@ -117,6 +117,7 @@ module.exports.thangNames = thangNames =
     "Simon"
     "Robin"
     "Quinn"
+    "Fidsdale"
   ]
   "Ogre Munchkin M": [
     "Brack"
@@ -179,6 +180,7 @@ module.exports.thangNames = thangNames =
     "Borgag"
     "Grognar"
     "Ironjaw"
+    "Tuguro"
   ]
   "Ogre Fangrider": [
     "Dreek"

From db0fc82eb08afd2243c56d9b4d8c7eb8c4e0454b Mon Sep 17 00:00:00 2001
From: Jayant Jain <jayantjain1992@gmail.com>
Date: Thu, 6 Mar 2014 01:54:09 +0530
Subject: [PATCH 082/178] Minor bugfix for freezing editor due to out of bounds
 frame index

---
 app/lib/surface/Surface.coffee | 1 +
 1 file changed, 1 insertion(+)

diff --git a/app/lib/surface/Surface.coffee b/app/lib/surface/Surface.coffee
index 5ce3bf29c..ec006d449 100644
--- a/app/lib/surface/Surface.coffee
+++ b/app/lib/surface/Surface.coffee
@@ -502,6 +502,7 @@ module.exports = Surface = class Surface extends CocoClass
       # Skip some frame updates unless we're playing and not at end (or we haven't drawn much yet)
       frameAdvanced = (@playing and @currentFrame < @world.totalFrames) or @totalFramesDrawn < 2
       @currentFrame += @world.frameRate / @options.frameRate if frameAdvanced and @playing
+      @currentFrame = Math.min(@currentFrame, @world.totalFrames - 1)
       newWorldFrame = Math.floor @currentFrame
       worldFrameAdvanced = newWorldFrame isnt oldWorldFrame
       if worldFrameAdvanced

From af265ebee851c116c362256ab7529057305ab7d0 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Wed, 5 Mar 2014 12:53:11 -0800
Subject: [PATCH 083/178] Tweaked an error message to be more generally useful.

---
 app/lib/surface/CocoSprite.coffee | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee
index 008519599..3a56f77e7 100644
--- a/app/lib/surface/CocoSprite.coffee
+++ b/app/lib/surface/CocoSprite.coffee
@@ -252,7 +252,9 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
   updateAction: ->
     action = @determineAction()
     isDifferent = action isnt @currentRootAction
-    console.error "action is", action, "for", @thang?.id, "from", @currentRootAction, @thang.action, @thang.getActionName?() if not action and @thang?.actionActivated and @thang.id is 'Artillery'
+    if not action and @thang?.actionActivated and not @stopLogging
+      console.error "action is", action, "for", @thang?.id, "from", @currentRootAction, @thang.action, @thang.getActionName?()
+      @stopLogging = true
     @queueAction(action) if isDifferent or (@thang?.actionActivated and action.name isnt 'move')
     @updateActionDirection()
 

From fc42043cb83edb9f241921a14b49c1502717fb9d Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Wed, 5 Mar 2014 12:53:48 -0800
Subject: [PATCH 084/178] Fixed #480

---
 app/models/ThangType.coffee | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/app/models/ThangType.coffee b/app/models/ThangType.coffee
index 62f9eaa4e..b28bea773 100644
--- a/app/models/ThangType.coffee
+++ b/app/models/ThangType.coffee
@@ -157,7 +157,8 @@ module.exports = class ThangType extends CocoModel
     for groupName, config of options.colorConfig or {}
       colorConfigs.push "#{groupName}:#{config.hue}|#{config.saturation}|#{config.lightness}"
     colorConfigs = colorConfigs.join ','
-    "#{@get('name')} - #{options.resolutionFactor} - #{colorConfigs}"
+    portraitOnly = !!options.portraitOnly
+    "#{@get('name')} - #{options.resolutionFactor} - #{colorConfigs} - #{portraitOnly}"
 
   getPortraitImage: (spriteOptionsOrKey, size=100) ->
     src = @getPortraitSource(spriteOptionsOrKey, size)

From b0d571c7adb431bc10b198bcada1a4ef3cd4a0ab Mon Sep 17 00:00:00 2001
From: Dominik Kundel <dominik.kundel@gmail.com>
Date: Wed, 5 Mar 2014 22:17:34 +0100
Subject: [PATCH 085/178] highlight only the executing statement

---
 app/styles/play/level/tome/spell.sass       | 2 +-
 app/views/play/level/tome/spell_view.coffee | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/styles/play/level/tome/spell.sass b/app/styles/play/level/tome/spell.sass
index 5990e7885..16473b06d 100644
--- a/app/styles/play/level/tome/spell.sass
+++ b/app/styles/play/level/tome/spell.sass
@@ -73,7 +73,7 @@
       .executing, .executed, .problem-marker-info, .problem-marker-warning, .problem-marker-error
         position: absolute
     .executing
-      background-color: rgba(0, 255, 0, 0.15)
+      background-color: rgba(0, 255, 0, 0.20)
       @include gradient-striped()
     .executed
       background-color: rgba(110, 110, 110, 0.12)
diff --git a/app/views/play/level/tome/spell_view.coffee b/app/views/play/level/tome/spell_view.coffee
index af9d2ad7f..8c98db854 100644
--- a/app/views/play/level/tome/spell_view.coffee
+++ b/app/views/play/level/tome/spell_view.coffee
@@ -480,7 +480,7 @@ module.exports = class SpellView extends View
       else
         @debugView.setVariableStates state.variables
         gotVariableStates = true
-        markerType = "fullLine"
+        markerType = "text"
       markerRange = new Range start.row, start.col, end.row, end.col
       markerRange.start = @aceDoc.createAnchor markerRange.start
       markerRange.end = @aceDoc.createAnchor markerRange.end

From 398fa3c426fba3c14fb8dcad581241ef337e58c0 Mon Sep 17 00:00:00 2001
From: Darredevil <alex.darredevil@gmail.com>
Date: Thu, 6 Mar 2014 00:12:58 +0200
Subject: [PATCH 086/178] Update ro.coffee

so much to translate....
---
 app/locale/ro.coffee | 174 +++++++++++++++++++++----------------------
 1 file changed, 87 insertions(+), 87 deletions(-)

diff --git a/app/locale/ro.coffee b/app/locale/ro.coffee
index 6bdb8e75a..3551d730b 100644
--- a/app/locale/ro.coffee
+++ b/app/locale/ro.coffee
@@ -96,8 +96,8 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
   diplomat_suggestion:
     title: "Ajută-ne  să traducem CodeCombat!"
     sub_heading: "Avem nevoie de abilitățile tale lingvistice."
-    pitch_body: "We develop CodeCombat in English, but we already have players all over the world. Many of them want to play in Romanian but don't speak English, so if you can speak both, please consider signing up to be a Diplomat and help translate both the CodeCombat website and all the levels into Romanian." #are these still needed??
-    missing_translations: "Until we can translate everything into Romanian, you'll see English when Romanian isn't available." # is this still needed?
+    pitch_body: "CodeCombat este dezvoltat in limba engleza , dar deja avem jucatări din toate colțurile lumii.Mulți dintre ei vor să joace in română și nu vorbesc engleză.Dacă poți vorbi ambele te rugăm să te gândești dacă ai dori să devi un Diplomat și să ne ajuți sa traducem atât jocul cât și site-ul." 
+    missing_translations: "Until we can translate everything into Romanian, you'll see English when Romanian isn't available." 
     learn_more: "Află mai multe despre cum să fi un Diplomat"
     subscribe_as_diplomat: "Înscrie-te ca Diplomat"
 
@@ -130,95 +130,95 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
     new_password_verify: "Verifică"
     email_subscriptions: "Subscripție Email"
     email_announcements: "Anunțuri"
-    email_notifications_description: "Get periodic notifications for your account."
-#    email_announcements_description: "Get emails on the latest news and developments at CodeCombat."
-#    contributor_emails: "Contributor Class Emails"
-#    contribute_prefix: "We're looking for people to join our party! Check out the "
-#    contribute_page: "contribute page"
-#    contribute_suffix: " to find out more."
-#    email_toggle: "Toggle All"
-#    error_saving: "Error Saving"
-#    saved: "Changes Saved"
-#    password_mismatch: "Password does not match."
+    email_notifications_description: "Primește notificări periodic pentru contul tău."
+    email_announcements_description: "Primește email-uri cu ultimele știri despre CodeCombat."
+    contributor_emails: "Contributor Class Emails"
+    contribute_prefix: "Căutăm oameni să se alăture distracției! Intră pe "
+    contribute_page: "pagina de contribuție"
+    contribute_suffix: " pentru a afla mai multe."
+    email_toggle: "Alege tot"
+    error_saving: "Salvare erori"
+    saved: "Modificări salvate"
+    password_mismatch: "Parola nu se potrivește."
 
-#  account_profile:
-#    edit_settings: "Edit Settings"
-#    profile_for_prefix: "Profile for "
-#    profile_for_suffix: ""
-#    profile: "Profile"
-#    user_not_found: "No user found. Check the URL?"
-#    gravatar_not_found_mine: "We couldn't find your profile associated with:"
-#    gravatar_not_found_email_suffix: "."
-#    gravatar_signup_prefix: "Sign up at "
-#    gravatar_signup_suffix: " to get set up!"
-#    gravatar_not_found_other: "Alas, there's no profile associated with this person's email address."
-#    gravatar_contact: "Contact"
-#    gravatar_websites: "Websites"
-#    gravatar_accounts: "As Seen On"
-#    gravatar_profile_link: "Full Gravatar Profile"
+  account_profile:
+    edit_settings: "Modifică setările"
+    profile_for_prefix: "Profil pentru "
+    profile_for_suffix: ""
+    profile: "Profil"
+    user_not_found: "Utilizator negăsit. Verifică URL-ul??"
+    gravatar_not_found_mine: "N-am putut găsi profilul asociat cu:"
+    gravatar_not_found_email_suffix: "."
+    gravatar_signup_prefix: "Înscrie-te la "
+    gravatar_signup_suffix: " pentru a fi gata!" #sounds funny # to get set up!"
+    gravatar_not_found_other: "Din păcate nu este asociat nici un profil cu această adresă de email."
+    gravatar_contact: "Contact"
+    gravatar_websites: "Website-uri"
+    gravatar_accounts: "Așa cum apare la"
+    gravatar_profile_link: "Full Gravatar Profile" #better leave this one as it is
 
-#  play_level:
-#    level_load_error: "Level could not be loaded: "
-#    done: "Done"
-#    grid: "Grid"
-#    customize_wizard: "Customize Wizard"
-#    home: "Home"
-#    guide: "Guide"
-#    multiplayer: "Multiplayer"
-#    restart: "Restart"
-#    goals: "Goals"
-#    action_timeline: "Action Timeline"
-#    click_to_select: "Click on a unit to select it."
-#    reload_title: "Reload All Code?"
-#    reload_really: "Are you sure you want to reload this level back to the beginning?"
-#    reload_confirm: "Reload All"
-#    victory_title_prefix: ""
-#    victory_title_suffix: " Complete"
-#    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_play_next_level: "Play Next Level"
-#    victory_go_home: "Go Home"
-#    victory_review: "Tell us more!"
-#    victory_hour_of_code_done: "Are You Done?"
-#    victory_hour_of_code_done_yes: "Yes, I'm finished with my Hour of Code™!"
-#    multiplayer_title: "Multiplayer Settings"
-#    multiplayer_link_description: "Give this link to anyone to have them join you."
-#    multiplayer_hint_label: "Hint:"
-#    multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
-#    multiplayer_coming_soon: "More multiplayer features to come!"
-#    guide_title: "Guide"
-#    tome_minion_spells: "Your Minions' Spells"
-#    tome_read_only_spells: "Read-Only Spells"
-#    tome_other_units: "Other Units"
-#    tome_cast_button_castable: "Cast Spell"
-#    tome_cast_button_casting: "Casting"
-#    tome_cast_button_cast: "Spell Cast"
-#    tome_autocast_delay: "Autocast Delay"
-#    tome_select_spell: "Select a Spell"
-#    tome_select_a_thang: "Select Someone for "
-#    tome_available_spells: "Available Spells"
-#    hud_continue: "Continue (press shift-space)"
-#    spell_saved: "Spell Saved"
+  play_level:
+    level_load_error: "Nivelul nu a putut fi încărcat: "
+    done: "Gata"
+    grid: "Grilă"
+    customize_wizard: "Personalizează Wizard-ul"
+    home: "Acasă"
+    guide: "Ghid"
+    multiplayer: "Multiplayer"
+    restart: "Restart"
+    goals: "Obiective"
+    action_timeline: "Timeline-ul acțiunii"
+    click_to_select: "Apasă pe o unitate pentru a o selecta."
+    reload_title: "Reîncarcă tot Codul?"
+    reload_really: "Ești sigur că vrei să reîncarci nivelul de la început?"
+    reload_confirm: "Reload All"
+    victory_title_prefix: ""
+    victory_title_suffix: " Terminat"
+    victory_sign_up: "Înscrie-te pentru a salva progresul"
+    victory_sign_up_poke: "Vrei să-ți salvezi codul? Crează un cont gratis!"
+    victory_rate_the_level: "Rate the level: "
+    victory_play_next_level: "Joacă nivelul următor"
+    victory_go_home: "Acasă"
+    victory_review: "Spune-ne mai multe!"
+    victory_hour_of_code_done: "Ai terminat?"
+    victory_hour_of_code_done_yes: "Da, am terminat Hour of Code™!"
+    multiplayer_title: "Setări Multiplayer"
+    multiplayer_link_description: "Împărtășește acest link cu cei care vor să ți se alăture."
+    multiplayer_hint_label: "Hint:"
+    multiplayer_hint: " Apasă pe link pentru a selecta tot, apoi apasă ⌘-C sau Ctrl-C pentru a copia link-ul."
+    multiplayer_coming_soon: "Mai multe feature-uri multiplayer în curând!"
+    guide_title: "Ghid"
+    tome_minion_spells: "Vrăjile Minion-ilor tăi"
+    tome_read_only_spells: "Vrăji Read-Only"
+    tome_other_units: "Alte unități"
+    tome_cast_button_castable: "Aplică Vraja"
+    tome_cast_button_casting: "Se încarcă"
+    tome_cast_button_cast: "Aplică Vraja"
+    tome_autocast_delay: "Întârziere Autocast"
+    tome_select_spell: "Alege o vrajă"
+    tome_select_a_thang: "Alege pe cineva pentru "
+    tome_available_spells: "Vrăjile disponibile"
+    hud_continue: "Continuă (apasă shift-space)"
+    spell_saved: "Vrajă salvată"
 
-#  admin:
-#    av_title: "Admin Views"
-#    av_entities_sub_title: "Entities"
-#    av_entities_users_url: "Users"
-#    av_entities_active_instances_url: "Active Instances"
-#    av_other_sub_title: "Other"
-#    av_other_debug_base_url: "Base (for debugging base.jade)"
-#    u_title: "User List"
-#    lg_title: "Latest Games"
+  admin:
+    av_title: "Admin vede"
+    av_entities_sub_title: "Entități"
+    av_entities_users_url: "Utilizatori"
+    av_entities_active_instances_url: "Instanțe active"
+    av_other_sub_title: "Altele"
+    av_other_debug_base_url: "Base (pentru debugging base.jade)"
+    u_title: "Listă utilizatori"
+    lg_title: "Ultimele jocuri"
 
-#  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"
-#    article_description: "Write articles that give players overviews of programming concepts which can be used across a variety of levels and campaigns."
-#    thang_title: "Thang Editor"
-#    thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics."
-#    level_title: "Level Editor"
+  editor:
+    main_title: "Editori CodeCombat"
+    main_description: "Construiește propriile nivele,campanii,unități și conținut educațional.Noi îți furnizăm toate uneltele necesare!"
+    article_title: "Editor Articol"
+    article_description: "Scrie articole care oferă jucătorilor cunoștințe despre conceptele de programare care pot fi folosite pe o varietate de nivele și campanii."
+    thang_title: "Editor Thang"
+    thang_description: "Construiește unități ,definește logica lor,grafica și sunetul.Momentan suportă numai importare de grafică vectorială exportată din Flash."
+    level_title: "Editor Nivele"
 #    level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!"
 #    security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, "
 #    contact_us: "contact us!"

From aa3167f30344c811d459aa21a4225d93febb2aa2 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Wed, 5 Mar 2014 15:06:20 -0800
Subject: [PATCH 087/178] Temporary hack fix while mongodb text search is
 broken.

---
 app/treema-ext.coffee | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/app/treema-ext.coffee b/app/treema-ext.coffee
index 674e6215a..1a8bdbe40 100644
--- a/app/treema-ext.coffee
+++ b/app/treema-ext.coffee
@@ -279,12 +279,23 @@ class LatestVersionReferenceNode extends TreemaNode
   search: =>
     term = @getValEl().find('input').val()
     return if term is @lastTerm
+    
+    # HACK while search is broken
+    if @collection
+      @lastTerm = term
+      @searchCallback()
+      return
+      
     @getSearchResultsEl().empty() if @lastTerm and not term
     return unless term
     @lastTerm = term
     @getSearchResultsEl().empty().append('Searching')
     @collection = new LatestVersionCollection()
-    @collection.url = "#{@url}?term=#{term}&project=true"
+
+    # HACK while search is broken
+#    @collection.url = "#{@url}?term=#{term}&project=true"
+    @collection.url = "#{@url}?term=#{''}&project=true"
+    
     @collection.fetch()
     @collection.on 'sync', @searchCallback
 
@@ -295,6 +306,10 @@ class LatestVersionReferenceNode extends TreemaNode
       row = $('<div></div>').addClass('treema-search-result-row')
       text = @formatDocument(model)
       continue unless text?
+      
+      # HACK while search is broken
+      continue unless text.toLowerCase().indexOf(@lastTerm.toLowerCase()) >= 0
+      
       row.addClass('treema-search-selected') if first
       first = false
       row.text(text)

From 99f43028a02e77473124340745ef68531351f542 Mon Sep 17 00:00:00 2001
From: Akaza Akari <tt@a-kar.in>
Date: Wed, 5 Mar 2014 19:39:14 -0800
Subject: [PATCH 088/178] Add thang sound panning for #454

---
 app/lib/AudioPlayer.coffee        | 15 +++++++++++++--
 app/lib/surface/CocoSprite.coffee |  9 ++++++++-
 app/lib/surface/Surface.coffee    |  1 +
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/app/lib/AudioPlayer.coffee b/app/lib/AudioPlayer.coffee
index b5eb4f70d..9c55282f2 100644
--- a/app/lib/AudioPlayer.coffee
+++ b/app/lib/AudioPlayer.coffee
@@ -38,6 +38,7 @@ class AudioPlayer extends CocoClass
   constructor: () ->
     super()
     @ext = if createjs.Sound.getCapability('mp3') then '.mp3' else '.ogg'
+    @camera = null
     @listenToSound()
     @createNewManifest()
     @soundsToPlayWhenLoaded = {}
@@ -51,6 +52,13 @@ class AudioPlayer extends CocoClass
     # So for now, we'll just load through SoundJS instead.
     createjs.Sound.on 'fileload', @onSoundLoaded
 
+  applyPanning: (options, pos) ->
+    sup = @camera.worldToSurface pos
+    svp = @camera.surfaceViewport
+    pan = Math.max -1, Math.min 1, ((sup.x - svp.x) - svp.width / 2) / svp.width * 2
+    # TODO: derive new volume from old one and distance ratio
+    volume: options.volume, delay: options.delay, pan: pan
+
   # PUBLIC LOADING METHODS
 
   soundForDialogue: (message, soundTriggers) ->
@@ -78,8 +86,11 @@ class AudioPlayer extends CocoClass
       @preloadInterfaceSounds [name] unless filename of cache
       @soundsToPlayWhenLoaded[name] = volume
 
-  playSound: (name, volume=1, delay=0) ->
-    instance = createjs.Sound.play name, {volume: (me.get('volume') ? 1) * volume, delay: delay}
+  playSound: (name, volume=1, delay=0, pos=null) ->
+    audioOptions = {volume: (me.get('volume') ? 1) * volume, delay: delay}
+    unless @camera is null or pos is null
+      audioOptions = @applyPanning audioOptions, pos
+    instance = createjs.Sound.play name, audioOptions
     instance
 
 #  # TODO: load Interface sounds somehow, somewhere, somewhen
diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee
index 3a56f77e7..9104f1b37 100644
--- a/app/lib/surface/CocoSprite.coffee
+++ b/app/lib/surface/CocoSprite.coffee
@@ -188,6 +188,13 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     return 0 unless @thang.bobHeight
     @thang.bobHeight * (1 + Math.sin(@age * Math.PI / @thang.bobTime))
 
+  getWorldPosition: ->
+    p1 = @thang.pos
+    if bobOffset = @getBobOffset()
+      p1 = p1.copy?() or _.clone(p1)
+      p1.z += bobOffset
+    x: p1.x, y: p1.y, z: if @thang.isLand then 0 else p1.z - @thang.depth / 2
+
   updatePosition: ->
     return unless @thang?.pos and @options.camera?
     [p0, p1] = [@lastPos, @thang.pos]
@@ -477,6 +484,6 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     return null unless sound
     delay = if withDelay and sound.delay then 1000 * sound.delay / createjs.Ticker.getFPS() else 0
     name = AudioPlayer.nameForSoundReference sound
-    instance = AudioPlayer.playSound name, volume, delay
+    instance = AudioPlayer.playSound name, volume, delay, @getWorldPosition()
 #    console.log @thang?.id, "played sound", name, "with delay", delay, "volume", volume, "and got sound instance", instance
     instance
diff --git a/app/lib/surface/Surface.coffee b/app/lib/surface/Surface.coffee
index ec006d449..c5e15813d 100644
--- a/app/lib/surface/Surface.coffee
+++ b/app/lib/surface/Surface.coffee
@@ -360,6 +360,7 @@ module.exports = Surface = class Surface extends CocoClass
     canvasHeight = parseInt(@canvas.attr('height'), 10)
     @camera?.destroy()
     @camera = new Camera canvasWidth, canvasHeight
+    AudioPlayer.camera = @camera
     @layers.push @surfaceLayer = new Layer name: "Surface", layerPriority: 0, transform: Layer.TRANSFORM_SURFACE, camera: @camera
     @layers.push @surfaceTextLayer = new Layer name: "Surface Text", layerPriority: 1, transform: Layer.TRANSFORM_SURFACE_TEXT, camera: @camera
     @layers.push @screenLayer = new Layer name: "Screen", layerPriority: 2, transform: Layer.TRANSFORM_SCREEN, camera: @camera

From 51d7bd656d1b17e35c1ff7e484e10fadf37b4ed5 Mon Sep 17 00:00:00 2001
From: Akaza Akari <tt@a-kar.in>
Date: Wed, 5 Mar 2014 19:54:58 -0800
Subject: [PATCH 089/178] Made updatePosition use getWorldPosition

---
 app/lib/surface/CocoSprite.coffee | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee
index 9104f1b37..57146866a 100644
--- a/app/lib/surface/CocoSprite.coffee
+++ b/app/lib/surface/CocoSprite.coffee
@@ -197,12 +197,9 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
 
   updatePosition: ->
     return unless @thang?.pos and @options.camera?
+    wop = @getWorldPosition()
     [p0, p1] = [@lastPos, @thang.pos]
-    if bobOffset = @getBobOffset()
-      p1 = p1.copy?() or _.clone(p1)
-      p1.z += bobOffset
     return if p0 and p0.x is p1.x and p0.y is p1.y and p0.z is p1.z and not @options.camera.tweeningZoomTo
-    wop = x: p1.x, y: p1.y, z: if @thang.isLand then 0 else p1.z - @thang.depth / 2
     sup = @options.camera.worldToSurface wop
     [@displayObject.x, @displayObject.y] = [sup.x, sup.y]
     @lastPos = p1.copy?() or _.clone(p1)

From 030da44c23ae66668405f5f7cce0fc3a5bcf778e Mon Sep 17 00:00:00 2001
From: Akaza Akari <tt@a-kar.in>
Date: Wed, 5 Mar 2014 20:12:42 -0800
Subject: [PATCH 090/178] Added volume manipulation, adjusted panning
 parameters

---
 app/lib/AudioPlayer.coffee | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/app/lib/AudioPlayer.coffee b/app/lib/AudioPlayer.coffee
index 9c55282f2..40b07974d 100644
--- a/app/lib/AudioPlayer.coffee
+++ b/app/lib/AudioPlayer.coffee
@@ -55,8 +55,9 @@ class AudioPlayer extends CocoClass
   applyPanning: (options, pos) ->
     sup = @camera.worldToSurface pos
     svp = @camera.surfaceViewport
-    pan = Math.max -1, Math.min 1, ((sup.x - svp.x) - svp.width / 2) / svp.width * 2
-    # TODO: derive new volume from old one and distance ratio
+    pan = Math.max -1, Math.min 1, ((sup.x - svp.x) - svp.width / 2) / svp.width
+    dst = @camera.distanceRatioTo pos
+    vol = Math.min 1, options.volume / Math.pow (dst + 0.2), 2
     volume: options.volume, delay: options.delay, pan: pan
 
   # PUBLIC LOADING METHODS

From 929d10588e70dfd2eb5a45169b19947256ad6b5e Mon Sep 17 00:00:00 2001
From: Akaza Akari <tt@a-kar.in>
Date: Thu, 6 Mar 2014 16:02:42 +0800
Subject: [PATCH 091/178] Translate passages on Contribute and About page

---
 app/locale/zh-HANS.coffee | 86 +++++++++++++++++++--------------------
 1 file changed, 43 insertions(+), 43 deletions(-)

diff --git a/app/locale/zh-HANS.coffee b/app/locale/zh-HANS.coffee
index f6eebce5d..4f999712c 100644
--- a/app/locale/zh-HANS.coffee
+++ b/app/locale/zh-HANS.coffee
@@ -271,16 +271,16 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     who_description_prefix: "在2013年开始一起编写 CodeCombat。在2008年时,我们还创造"
     who_description_suffix: "并且发展出了首选的学习如何写中文和日文的Web和IOS应用"
     who_description_ending: "现在是时候教人们如何写代码了。"
-#    why_paragraph_1: "When making Skritter, George didn't know how to program and was constantly frustrated by his inability to implement his ideas. Afterwards, he tried learning, but the lessons were too slow. His housemate, wanting to reskill and stop teaching, tried Codecademy, but \"got bored.\" Each week another friend started Codecademy, then dropped off. We realized it was the same problem we'd solved with Skritter: people learning a skill via slow, intensive lessons when what they need is fast, extensive practice. We know how to fix that."
-#    why_paragraph_2: "Need to learn to code? You don't need lessons. You need to write a lot of code and have a great time doing it."
-#    why_paragraph_3_prefix: "That's what programming is about. It's gotta be fun. Not fun like"
-#    why_paragraph_3_italic: "yay a badge"
-#    why_paragraph_3_center: "but fun like"
-#    why_paragraph_3_italic_caps: "NO MOM I HAVE TO FINISH THE LEVEL!"
-#    why_paragraph_3_suffix: "That's why CodeCombat is a multiplayer game, not a gamified lesson course. We won't stop until you can't stop--but this time, that's a good thing."
-#    why_paragraph_4: "If you're going to get addicted to some game, get addicted to this one and become one of the wizards of the tech age."
-#    why_ending: "And hey, it's free. "
-#    why_ending_url: "Start wizarding now!"
+    why_paragraph_1: "当我们制作 Skritter 的时候,George 不会写程序,对于不能实现他的灵感这一点很苦恼。他试着学了学,但是那些课程都太慢了。他的室友想不再教书学习新技能,试了试 CodeAcademy,但是觉得“太无聊了。”每个星期都会有个熟人尝试 CodeAcademy,然后无一例外地放弃掉。我们发现这和 Skritter 想要解决的是一个问题:人们想要的是高速学习、充分练习,得到的却是缓慢、冗长的课程。我们知道该怎么办了。"
+    why_paragraph_2: "你想学编程?你不用上课。你需要的是写好多代码,并且享受这个过程。"
+    why_paragraph_3_prefix: "这才是编程的要义。编程必须要好玩。不是"
+    why_paragraph_3_italic: "哇又一个奖章诶"
+    why_paragraph_3_center: "那种“好玩”,而是"
+    why_paragraph_3_italic_caps: "不老妈,我德先把这关打完!"
+    why_paragraph_3_suffix: "这就是为什么 CodeCombat 是个多人游戏,而不是一个游戏化的编程课。你不停,我们就不停——但这次这是件好事。"
+    why_paragraph_4: "如果你一定要对游戏上瘾,那就对这个游戏上瘾,然后成为科技时代的法师吧。"
+    why_ending: "再说,这游戏还是免费的。"
+    why_ending_url: "开始学习法术吧!"
 #    george_description: "CEO, business guy, web designer, game designer, and champion of beginning programmers everywhere."
 #    scott_description: "Programmer extraordinaire, software architect, kitchen wizard, and master of finances. Scott is the reasonable one."
 #    nick_description: "Programming wizard, eccentric motivation mage, and upside-down experimenter. Nick can do anything and chooses to build CodeCombat."
@@ -350,18 +350,18 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 
   contribute:
     page_title: "贡献"
-#    character_classes_title: "Character Classes"
-#    introduction_desc_intro: "We have high hopes for CodeCombat."
-#    introduction_desc_pref: "We want to be where programmers of all stripes come to learn and play together, introduce others to the wonderful world of coding, and reflect the best parts of the community. We can't and don't want to do that alone; what makes projects like GitHub, Stack Overflow and Linux great are the people who use them and build on them. To that end, "
-#    introduction_desc_github_url: "CodeCombat is totally open source"
-#    introduction_desc_suf: ", and we aim to provide as many ways as possible for you to take part and make this project as much yours as ours."
-#    introduction_desc_ending: "We hope you'll join our party!"
+    character_classes_title: "贡献者职业"
+    introduction_desc_intro: "我们对 CodeCombat 有很高的期望。"
+    introduction_desc_pref: "我们希望所有的程序员一起来学习和游戏,让其他人也见识到代码的美妙,并且展现出社区的最好一面。我们不能也不想独自完成这个目标:让 GitHub、Stack Overflow 和 Linux 真正伟大的是它们的用户。为了完成这个目标,"
+    introduction_desc_github_url: "我们把 CodeCombat 完全开源"
+    introduction_desc_suf: ",而且我们希望提供尽可能多的方法让你来参加这个项目,与我们一起创造。"
+    introduction_desc_ending: "我们希望你也会加入进来!"
 #    introduction_desc_signature: "- Nick, George, Scott, Michael, and Jeremy"
-#    alert_account_message_intro: "Hey there!"
-#    alert_account_message_pref: "To subscribe for class emails, you'll need to "
-#    alert_account_message_suf: "first."
-#    alert_account_message_create_url: "create an account"
-#    archmage_summary: "Interested in working on game graphics, user interface design, database and server organization, multiplayer networking, physics, sound, or game engine performance? Want to help build a game to help other people learn what you are good at? We have a lot to do and if you are an experienced programmer and want to develop for CodeCombat, this class is for you. We would love your help building the best programming game ever."
+    alert_account_message_intro: "你好!"
+    alert_account_message_pref: "要订阅贡献者邮件,你得先"
+    alert_account_message_suf: "。"
+    alert_account_message_create_url: "创建账号"
+    archmage_summary: "你对游戏图像、界面设计、数据库和服务器运营、多人在线、物理、声音、游戏引擎性能感兴趣吗?想做一个教别人编程的游戏吗?如果你有编程经验,想要开发 CodeCombat ,那就选择这个职业吧。我们会非常高兴在制作史上最好的编程游戏的过程中得到你的帮助。"
 #    archmage_introduction: "One of the best parts about building games is they synthesize so many different things. Graphics, sound, real-time networking, social networking, and of course many of the more common aspects of programming, from low-level database management, and server administration to user facing design and interface building. There's a lot to do, and if you're an experienced programmer with a hankering to really dive into the nitty-gritty of CodeCombat, this class might be for you. We would love to have your help building the best programming game ever."
 #    class_attributes: "Class Attributes"
 #    archmage_attribute_1_pref: "Knowledge in "
@@ -374,10 +374,10 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 #    join_desc_4: "and we'll go from there!"
 #    join_url_email: "Email us"
 #    join_url_hipchat: "public HipChat room"
-#    more_about_archmage: "Learn More About Becoming an Archmage"
+    more_about_archmage: "了解成为大法师的方法"
 #    archmage_subscribe_desc: "Get emails on new coding opportunities and announcements."
-#    artisan_summary_pref: "Want to design levels and expand CodeCombat's arsenal? People are playing through our content at a pace faster than we can build! Right now, our level editor is barebone, so be wary. Making levels will be a little challenging and buggy. If you have visions of campaigns spanning for-loops to"
-#    artisan_summary_suf: "then this class is for you."
+    artisan_summary_pref: "想要设计 CodeCombat 的关卡吗?人们玩的比我们做的快多了!现在我们的关卡编辑器还很基本,所以做起关卡来会有点麻烦,还会有bug。只要你有制作关卡的灵感,不管是简单的for循环还是"
+    artisan_summary_suf: "这种东西,这个职业都很适合你。"
 #    artisan_introduction_pref: "We must construct additional levels! People be clamoring for more content, and we can only build so many ourselves. Right now your workstation is level one; our level editor is barely usable even by its creators, so be wary. If you have visions of campaigns spanning for-loops to"
 #    artisan_introduction_suf: "then this class might be for you."
 #    artisan_attribute_1: "Any experience in building content like this would be nice, such as using Blizzard's level editors. But not required!"
@@ -388,52 +388,52 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 #    artisan_join_step2: "Create a new level and explore existing levels."
 #    artisan_join_step3: "Find us in our public HipChat room for help."
 #    artisan_join_step4: "Post your levels on the forum for feedback."
-#    more_about_artisan: "Learn More About Becoming an Artisan"
+    more_about_artisan: "了解成为工匠的方法"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+    adventurer_sumamry: "丑话说在前面,你就是那个挡枪子的,而且你会伤得很重。我们需要人手来测试崭新的关卡,并且提出改进意见。做一个好游戏是一个漫长的过程,没人第一次就能搞对。如果你能忍得了这些,而且身体健壮,那这个职业就是你的了。"
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
 #    adventurer_join_pref: "Either get together with (or recruit!) an Artisan and work with them, or check the box below to receive emails when there are new levels to test. We'll also be posting about levels to review on our networks like"
 #    adventurer_forum_url: "our forum"
 #    adventurer_join_suf: "so if you prefer to be notified those ways, sign up there!"
-#    more_about_adventurer: "Learn More About Becoming an Adventurer"
+    more_about_adventurer: "了解成为冒险家的方法"
 #    adventurer_subscribe_desc: "Get emails when there are new levels to test."
-#    scribe_summary_pref: "CodeCombat is not just going to be a bunch of levels. It will also be a resource of programming knowledge that players can hook into. That way, each Artisan can link to a detailed article that for the player's edification: documentation akin to what the "
-#    scribe_summary_sufx: " has built. If you enjoy explaining programming concepts, then this class is for you."
+    scribe_summary_pref: "CodeCombat 不只是一堆关卡的集合,它还是玩家们编程知识的来源。这样的话,每个工匠都能链接详尽的文档,以供玩家们学习,类似于"
+    scribe_summary_sufx: "那些。如果你喜欢解释编程概念,那这个职业适合你。"
 #    scribe_introduction_pref: "CodeCombat isn't just going to be a bunch of levels. It will also include a resource for knowledge, a wiki of programming concepts that levels can hook into. That way rather than each Artisan having to describe in detail what a comparison operator is, they can simply link their level to the Article describing them that is already written for the player's edification. Something along the lines of what the "
 #    scribe_introduction_url_mozilla: "Mozilla Developer Network"
 #    scribe_introduction_suf: " has built. If your idea of fun is articulating the concepts of programming in Markdown form, then this class might be for you."
 #    scribe_attribute_1: "Skill in words is pretty much all you need. Not only grammar and spelling, but able to convey complicated ideas to others."
 #    contact_us_url: "Contact us"
 #    scribe_join_description: "tell us a little about yourself, your experience with programming and what sort of things you'd like to write about. We'll go from there!"
-#    more_about_scribe: "Learn More About Becoming a Scribe"
+    more_about_scribe: "了解成为文书的方法"
 #    scribe_subscribe_desc: "Get emails about article writing announcements."
-    diplomat_summary: "在其他国家不讲英语,很多人对于CodeCombat有很大的兴趣。我们正在寻找愿意花时间翻译网站语料库的词语的译者,这样 CodeCombat 就能尽快地遍及世界各地。如果你想帮助 CodeCombat 的国际化,那么这个类就是给你的。"
-    diplomat_introduction_pref: "如果有一件事情是从 "
-    diplomat_launch_url: "launch in October"
-    diplomat_introduction_suf: "学来的,Combat有相当大的兴趣在其他国家发展。我们正在构建一个译者兵团把单词一个一个的翻译,让CodeCombat尽可能地访问到世界各地。如果你喜欢偷偷地瞄一眼即将到来的内容,并让你的国民尽快学习到CodeCombat,那么这个类可能适合你。"
-    diplomat_attribute_1: "会流利的英语和能翻译的语言。当传递复杂思想,难得的是能很好的同时掌握这两个。"
-    diplomat_join_pref_github: "找到你自己的语言文件 "
-    diplomat_github_url: "在GitHub网站"
-    diplomat_join_suf_github: "在线编辑它,然后提交一个合并请求。同时,选中下面这个复选框来关注最新的国际化开发!"
-    more_about_diplomat: "了解更多“如何成为一名外交官(翻译者)”"
+    diplomat_summary: "很多国家不说英文,但是人们对 CodeCombat 兴致很高!我们需要具有热情的翻译者,来把这个网站上的文字尽快带向全世界。如果你想帮我们走向全球,那这个职业适合你。"
+    diplomat_introduction_pref: "如果说我们从"
+    diplomat_launch_url: "十月的发布"
+    diplomat_introduction_suf: "中得到了什么启发:那就是全球的人对 CodeCombat 都很感兴趣。我们召集了一群翻译者,尽快地把网站上的信息翻译成各国文字。如果你对即将发布的新内容感兴趣,想让你的国家的人们玩上,就快来成为外交官吧。"
+    diplomat_attribute_1: "既会说流利的英语,也熟悉自己的语言。编程是一件很复杂的事情,而要翻译复杂的概念,你必须对两种语言都在行!"
+    diplomat_join_pref_github: "在"
+    diplomat_github_url: "GitHub"
+    diplomat_join_suf_github: "找到你的语言文件,在线编辑它,然后提交一个合并请求。同时,选中下面这个复选框来关注最新的国际化开发!"
+    more_about_diplomat: "了解成为外交官的方法"
     diplomat_subscribe_desc: "接受有关国际化开发和翻译情况的邮件"
-#    ambassador_summary: "We are trying to build a community, and every community needs a support team when there are troubles. We have got chats, emails, and social networks so that our users can get acquainted with the game. If you want to help people get involved, have fun, and learn some programming, then this class is for you."
+    ambassador_summary: "我们要建立一个社区,而当社区遇到麻烦的时候,就要支持人员出场了。我们运用 IRC、电邮、社交网站等多种平台帮助玩家熟悉游戏。如果你想帮人们参与进来,学习编程,然后玩的开心,那这个职业属于你。"
 #    ambassador_introduction: "This is a community we're building, and you are the connections. We've got Olark chats, emails, and social networks with lots of people to talk with and help get acquainted with the game and learn from. If you want to help people get involved and have fun, and get a good feel of the pulse of CodeCombat and where we're going, then this class might be for you."
 #    ambassador_attribute_1: "Communication skills. Be able to identify the problems players are having and help them solve them. Also, keep the rest of us informed about what players are saying, what they like and don't like and want more of!"
 #    ambassador_join_desc: "tell us a little about yourself, what you've done and what you'd be interested in doing. We'll go from there!"
 #    ambassador_join_note_strong: "Note"
 #    ambassador_join_note_desc: "One of our top priorities is to build multiplayer where players having difficulty solving levels can summon higher level wizards to help them. This will be a great way for ambassadors to do their thing. We'll keep you posted!"
-#    more_about_ambassador: "Learn More About Becoming an Ambassador"
+    more_about_ambassador: "了解成为使节的方法"
 #    ambassador_subscribe_desc: "Get emails on support updates and multiplayer developments."
-#    counselor_summary: "None of the above roles fit what you are interested in? Do not worry, we are on the lookout for anybody who wants a hand in the development of CodeCombat! If you are interested in teaching, game development, open source management, or anything else that you think will be relevant to us, then this class is for you."
+    counselor_summary: "以上的职业都不适合你?没关系,我们欢迎每一个想参与 CodeCombat 开发的人!如果你熟悉教学、游戏开发、开源管理,或者任何你觉得和我们有关的方面,那这个职业属于你。"
 #    counselor_introduction_1: "Do you have life experience? A different perspective on things that can help us decide how to shape CodeCombat? Of all these roles, this will probably take the least time, but individually you may make the most difference. We're on the lookout for wisened sages, particularly in areas like: teaching, game development, open source project management, technical recruiting, entrepreneurship, or design."
 #    counselor_introduction_2: "Or really anything that is relevant to the development of CodeCombat. If you have knowledge and want to share it to help grow this project, then this class might be for you."
 #    counselor_attribute_1: "Experience, in any of the areas above or something you think might be helpful."
 #    counselor_attribute_2: "A little bit of free time!"
 #    counselor_join_desc: "tell us a little about yourself, what you've done and what you'd be interested in doing. We'll put you in our contact list and be in touch when we could use advice (not too often)."
-#    more_about_counselor: "Learn More About Becoming a Counselor"
+    more_about_counselor: "了解成为顾问的方式"
     changes_auto_save: "在您切换复选框时,更改将自动保存。"
     diligent_scribes: "我们勤奋的文书:"
     powerful_archmages: "我们强力的大法师:"

From ad3019a6cbefe573e7b8d1e88cbd900ffedd3ff1 Mon Sep 17 00:00:00 2001
From: Akaza Akari <tt@a-kar.in>
Date: Thu, 6 Mar 2014 16:51:21 +0800
Subject: [PATCH 092/178] Translated more strings

---
 app/locale/zh-HANS.coffee | 80 +++++++++++++++++++--------------------
 1 file changed, 40 insertions(+), 40 deletions(-)

diff --git a/app/locale/zh-HANS.coffee b/app/locale/zh-HANS.coffee
index 4f999712c..caa2b9802 100644
--- a/app/locale/zh-HANS.coffee
+++ b/app/locale/zh-HANS.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     tome_available_spells: "可用的法术"
     hud_continue: "继续(按 Shift-空格)"
     spell_saved: "咒语已保存"
-#    skip_tutorial: "Skip (esc)"
+    skip_tutorial: "跳过(esc)"
 
   admin:
     av_title: "管理员视图"
@@ -321,32 +321,32 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     code_title: "代码 - MIT"
     code_description_prefix: "所有由 CodeCombat 拥有或者托管在 codecombat.com 的代码,在 GitHub 版本库或者 codecombat.com 数据库,以上许可协议都依照"
     mit_license_url: "MIT 许可证"
-#    code_description_suffix: "This includes all code in Systems and Components that are made available by CodeCombat for the purpose of creating levels."
-#    art_title: "Art/Music - Creative Commons "
-#    art_description_prefix: "All common content is available under the"
+    code_description_suffix: "这包括所有 CodeCombat 公开的制作关卡用的系统和组件代码。"
+    art_title: "美术和音乐 - Creative Commons"
+    art_description_prefix: "所有共通的内容都在"
 #    cc_license_url: "Creative Commons Attribution 4.0 International License"
-#    art_description_suffix: "Common content is anything made generally available by CodeCombat for the purpose of creating Levels. This includes:"
+    art_description_suffix: "条款下公开。共通内容是指所有 CodeCombat 发布出来用于制作关卡的内容。这包括:"
     art_music: "音乐"
     art_sound: "声效"
-    art_artwork: "艺术品"
-    art_sprites: "小妖精"
-#    art_other: "Any and all other non-code creative works that are made available when creating Levels."
-#    art_access: "Currently there is no universal, easy system for fetching these assets. In general, fetch them from the URLs as used by the site, contact us for assistance, or help us in extending the site to make these assets more easily accessible."
-#    art_paragraph_1: "For attribution, please name and link to codecombat.com near where the source is used or where appropriate for the medium. For example:"
-#    use_list_1: "If used in a movie or another game, include codecombat.com in the credits."
-#    use_list_2: "If used on a website, include a link near the usage, for example underneath an image, or in a general attributions page where you might also mention other Creative Commons works and open source software being used on the site. Something that's already clearly referencing CodeCombat, such as a blog post mentioning CodeCombat, does not need some separate attribution."
-#    art_paragraph_2: "If the content being used is created not by CodeCombat but instead by a user of codecombat.com, attribute them instead, and follow attribution directions provided in that resource's description if there are any."
+    art_artwork: "图画"
+    art_sprites: "精灵"
+    art_other: "所有制作关卡时公开的,不是代码的创造性产品。"
+    art_access: "目前还没有简便通用的下载素材的方式。一般来讲,从网站上使用的URL下载,或者联系我们寻找帮助。当然你也可以帮我们扩展网站,让这些资源更容易下载。"
+    art_paragraph_1: "关于署名,请说明并在使用处附近,或对媒体形式来说合适的地方提供一个 codecombat.com 的链接。举例:"
+    use_list_1: "如果是用在电影里或者其他游戏里,请在制作人员表中加入 codecombat.com 。"
+    use_list_2: "如果用在网站上,将链接在使用的地方附近,比如图片下面,或者一个你放置其他 Creative Commons 署名和开源软件协议的专门页面。如果你的内容明确提到关于 CodeCombat,那你就不需要额外署名。"
+    art_paragraph_2: "如果你使用的内容不是由 CodeCombat 制作,而是由 codecombat.com 上其他的用户制作的,那你应该给他们署名。如果相应资源的页面上有署名指示,那你应该遵循那些指示。"
     rights_title: "版权所有"
     rights_desc: "所有关卡由他们自己版权所有。这包括"
     rights_scripts: "脚本"
     rights_unit: "单元配置"
     rights_description: "描述"
     rights_writings: "作品"
-#    rights_media: "Media (sounds, music) and any other creative content made specifically for that Level and not made generally available when creating Levels."
-#    rights_clarification: "To clarify, anything that is made available in the Level Editor for the purpose of making levels is under CC, whereas the content created with the Level Editor or uploaded in the course of creation of Levels is not."
-#    nutshell_title: "In a Nutshell"
-#    nutshell_description: "Any resources we provide in the Level Editor are free to use as you like for creating Levels. But we reserve the right to restrict distribution of the Levels themselves (that are created on codecombat.com) so that they may be charged for in the future, if that's what ends up happening."
-#    canonical: "The English version of this document is the definitive, canonical version. If there are any discrepencies between translations, the English document takes precedence."
+    rights_media: "声音、音乐以及其他专门为某个关卡制作,而不对其他关卡开放的创造性内容"
+    rights_clarification: "澄清:所有在关卡编辑器里公开用于制作关卡的资源都是在CC协议下发布的,而使用关卡编辑器制作,或者在关卡制作过程中上传的内容则不是。"
+    nutshell_title: "简而言之"
+    nutshell_description: "我们在关卡编辑器里公开的任何资源,你都可以在制作关卡时随意使用,但我们保留限制在 codecombat.com 之上创建的关卡本身传播的权利,因为我们以后可能决定为它们收费。"
+    canonical: "这篇说明的英文版本是权威版本。如果各个翻译版本之间有任何冲突,以英文版为准。"
 
   contribute:
     page_title: "贡献"
@@ -362,20 +362,20 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     alert_account_message_suf: "。"
     alert_account_message_create_url: "创建账号"
     archmage_summary: "你对游戏图像、界面设计、数据库和服务器运营、多人在线、物理、声音、游戏引擎性能感兴趣吗?想做一个教别人编程的游戏吗?如果你有编程经验,想要开发 CodeCombat ,那就选择这个职业吧。我们会非常高兴在制作史上最好的编程游戏的过程中得到你的帮助。"
-#    archmage_introduction: "One of the best parts about building games is they synthesize so many different things. Graphics, sound, real-time networking, social networking, and of course many of the more common aspects of programming, from low-level database management, and server administration to user facing design and interface building. There's a lot to do, and if you're an experienced programmer with a hankering to really dive into the nitty-gritty of CodeCombat, this class might be for you. We would love to have your help building the best programming game ever."
-#    class_attributes: "Class Attributes"
-#    archmage_attribute_1_pref: "Knowledge in "
-#    archmage_attribute_1_suf: ", or a desire to learn. Most of our code is in this language. If you're a fan of Ruby or Python, you'll feel right at home. It's JavaScript, but with a nicer syntax."
-#    archmage_attribute_2: "Some experience in programming and personal initiative. We'll help you get oriented, but we can't spend much time training you."
-#    how_to_join: "How To Join"
-#    join_desc_1: "Anyone can help out! Just check out our "
-#    join_desc_2: "to get started, and check the box below to mark yourself as a brave Archmage and get the latest news by email. Want to chat about what to do or how to get more deeply involved? "
-#    join_desc_3: ", or find us in our "
-#    join_desc_4: "and we'll go from there!"
-#    join_url_email: "Email us"
-#    join_url_hipchat: "public HipChat room"
+    archmage_introduction: "制作游戏的时候,最令人激动人心的事情莫过于整合诸多的要素。图像、音响、实事网络交流、社交网络,以及从底层数据库管理到服务器运维,再到用户界面的设计和实现的各种编程方面。制作游戏有很多事情要做,因此如果你有编程经验,还有深入 CodeCombat 的细节中的干劲,你可能应该选择这个职业。我们会非常高兴在制作史上最好的编程游戏的过程中得到你的帮助。"
+    class_attributes: "职业特性"
+    archmage_attribute_1_pref: "了解"
+    archmage_attribute_1_suf: ",或者想要学习。我们的多数代码都是用它写就的。如果你喜欢 Ruby 或者 Python,那你肯定会感到很熟悉。它就是 JavaScript,但它的语法更友好。"
+    archmage_attribute_2: "编程经验和干劲。我们可以帮你走上正规,但恐怕没多少时间培训你。"
+    how_to_join: "如何加入"
+    join_desc_1: "谁都可以帮忙!先看看我们的"
+    join_desc_2: ",然后勾上下面的复选框,这样你就会作为勇敢的大法师收到我们的电邮。如果你想和开发人员聊天或者更深入地参与,可以"
+    join_desc_3: "或者去我们的"
+    join_desc_4: ",然后我们有话好说!"
+    join_url_email: "给我们发邮件"
+    join_url_hipchat: " HipChat 聊天室"
     more_about_archmage: "了解成为大法师的方法"
-#    archmage_subscribe_desc: "Get emails on new coding opportunities and announcements."
+    archmage_subscribe_desc: "通过电子邮件获得新的编码机会和公告。"
     artisan_summary_pref: "想要设计 CodeCombat 的关卡吗?人们玩的比我们做的快多了!现在我们的关卡编辑器还很基本,所以做起关卡来会有点麻烦,还会有bug。只要你有制作关卡的灵感,不管是简单的for循环还是"
     artisan_summary_suf: "这种东西,这个职业都很适合你。"
 #    artisan_introduction_pref: "We must construct additional levels! People be clamoring for more content, and we can only build so many ourselves. Right now your workstation is level one; our level editor is barely usable even by its creators, so be wary. If you have visions of campaigns spanning for-loops to"
@@ -389,7 +389,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 #    artisan_join_step3: "Find us in our public HipChat room for help."
 #    artisan_join_step4: "Post your levels on the forum for feedback."
     more_about_artisan: "了解成为工匠的方法"
-#    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
+    artisan_subscribe_desc: "通过电子邮件获得关卡编辑器更新和公告。"
     adventurer_sumamry: "丑话说在前面,你就是那个挡枪子的,而且你会伤得很重。我们需要人手来测试崭新的关卡,并且提出改进意见。做一个好游戏是一个漫长的过程,没人第一次就能搞对。如果你能忍得了这些,而且身体健壮,那这个职业就是你的了。"
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
@@ -398,7 +398,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 #    adventurer_forum_url: "our forum"
 #    adventurer_join_suf: "so if you prefer to be notified those ways, sign up there!"
     more_about_adventurer: "了解成为冒险家的方法"
-#    adventurer_subscribe_desc: "Get emails when there are new levels to test."
+    adventurer_subscribe_desc: "通过电子邮件获得新关卡通知。"
     scribe_summary_pref: "CodeCombat 不只是一堆关卡的集合,它还是玩家们编程知识的来源。这样的话,每个工匠都能链接详尽的文档,以供玩家们学习,类似于"
     scribe_summary_sufx: "那些。如果你喜欢解释编程概念,那这个职业适合你。"
 #    scribe_introduction_pref: "CodeCombat isn't just going to be a bunch of levels. It will also include a resource for knowledge, a wiki of programming concepts that levels can hook into. That way rather than each Artisan having to describe in detail what a comparison operator is, they can simply link their level to the Article describing them that is already written for the player's edification. Something along the lines of what the "
@@ -408,7 +408,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 #    contact_us_url: "Contact us"
 #    scribe_join_description: "tell us a little about yourself, your experience with programming and what sort of things you'd like to write about. We'll go from there!"
     more_about_scribe: "了解成为文书的方法"
-#    scribe_subscribe_desc: "Get emails about article writing announcements."
+    scribe_subscribe_desc: "通过电子邮件获得写作新文档的通知。"
     diplomat_summary: "很多国家不说英文,但是人们对 CodeCombat 兴致很高!我们需要具有热情的翻译者,来把这个网站上的文字尽快带向全世界。如果你想帮我们走向全球,那这个职业适合你。"
     diplomat_introduction_pref: "如果说我们从"
     diplomat_launch_url: "十月的发布"
@@ -426,13 +426,13 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 #    ambassador_join_note_strong: "Note"
 #    ambassador_join_note_desc: "One of our top priorities is to build multiplayer where players having difficulty solving levels can summon higher level wizards to help them. This will be a great way for ambassadors to do their thing. We'll keep you posted!"
     more_about_ambassador: "了解成为使节的方法"
-#    ambassador_subscribe_desc: "Get emails on support updates and multiplayer developments."
+    ambassador_subscribe_desc: "通过电子邮件获得支持系统的现状,以及多人游戏方面的新进展。"
     counselor_summary: "以上的职业都不适合你?没关系,我们欢迎每一个想参与 CodeCombat 开发的人!如果你熟悉教学、游戏开发、开源管理,或者任何你觉得和我们有关的方面,那这个职业属于你。"
-#    counselor_introduction_1: "Do you have life experience? A different perspective on things that can help us decide how to shape CodeCombat? Of all these roles, this will probably take the least time, but individually you may make the most difference. We're on the lookout for wisened sages, particularly in areas like: teaching, game development, open source project management, technical recruiting, entrepreneurship, or design."
-#    counselor_introduction_2: "Or really anything that is relevant to the development of CodeCombat. If you have knowledge and want to share it to help grow this project, then this class might be for you."
-#    counselor_attribute_1: "Experience, in any of the areas above or something you think might be helpful."
-#    counselor_attribute_2: "A little bit of free time!"
-#    counselor_join_desc: "tell us a little about yourself, what you've done and what you'd be interested in doing. We'll put you in our contact list and be in touch when we could use advice (not too often)."
+    counselor_introduction_1: "也许你有人生的经验,也许你对 CodeCombat 的发展有独特的观点。在所有这些角色中,这个角色花费的时间可能最少,但作为个人你的价值却最高。我们在寻找各方面的贤人,尤其是在教学、游戏开发、开源软件管理、技术企业招聘、创业或者设计方面的。"
+    counselor_introduction_2: "任何和 CodeCombat 的开发有关系的又可以。如果你有知识,并且希望分享给我们,帮这个项目成长,那这个职业属于你。"
+    counselor_attribute_1: "经验。上述的任何领域,或者你认为对我们有帮助的领域。"
+    counselor_attribute_2: "一点用来谈笑风生的时间!"
+    counselor_join_desc: ",向我们介绍以下你自己:你做过什么、对什么有兴趣。当我们需要你的建议的时候,我们会联系你的(不会很经常)。"
     more_about_counselor: "了解成为顾问的方式"
     changes_auto_save: "在您切换复选框时,更改将自动保存。"
     diligent_scribes: "我们勤奋的文书:"

From d3dd0eb32d6ff703622be27c970d78331117265f Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Thu, 6 Mar 2014 09:25:16 -0800
Subject: [PATCH 093/178] Fixed i18n tag typo: adventurer_sumamry ->
 adventurer_summary.

---
 app/locale/ar.coffee      |  2 +-
 app/locale/bg.coffee      |  2 +-
 app/locale/cs.coffee      |  2 +-
 app/locale/da.coffee      |  2 +-
 app/locale/de.coffee      |  2 +-
 app/locale/el.coffee      |  2 +-
 app/locale/en-AU.coffee   |  2 +-
 app/locale/en-GB.coffee   |  2 +-
 app/locale/en-US.coffee   |  2 +-
 app/locale/es-419.coffee  |  2 +-
 app/locale/es-ES.coffee   |  2 +-
 app/locale/es.coffee      |  2 +-
 app/locale/fa.coffee      |  2 +-
 app/locale/fi.coffee      |  2 +-
 app/locale/fr.coffee      |  2 +-
 app/locale/he.coffee      |  2 +-
 app/locale/hi.coffee      |  2 +-
 app/locale/hu.coffee      |  2 +-
 app/locale/id.coffee      |  2 +-
 app/locale/it.coffee      |  2 +-
 app/locale/ja.coffee      |  2 +-
 app/locale/ko.coffee      |  2 +-
 app/locale/lt.coffee      |  2 +-
 app/locale/ms-BA.coffee   |  2 +-
 app/locale/nb.coffee      |  2 +-
 app/locale/nl.coffee      | 28 ++++++++++++++--------------
 app/locale/nn.coffee      |  2 +-
 app/locale/no.coffee      |  2 +-
 app/locale/pl.coffee      |  2 +-
 app/locale/pt-BR.coffee   |  2 +-
 app/locale/pt-PT.coffee   |  2 +-
 app/locale/pt.coffee      |  2 +-
 app/locale/ro.coffee      |  8 ++++----
 app/locale/ru.coffee      |  2 +-
 app/locale/sk.coffee      |  2 +-
 app/locale/sl.coffee      |  2 +-
 app/locale/sr.coffee      |  2 +-
 app/locale/sv.coffee      |  2 +-
 app/locale/th.coffee      |  2 +-
 app/locale/tr.coffee      |  2 +-
 app/locale/uk.coffee      |  2 +-
 app/locale/ur.coffee      |  2 +-
 app/locale/vi.coffee      |  2 +-
 app/locale/zh-HANS.coffee |  2 +-
 app/locale/zh-HANT.coffee |  2 +-
 app/locale/zh.coffee      |  2 +-
 46 files changed, 62 insertions(+), 62 deletions(-)

diff --git a/app/locale/ar.coffee b/app/locale/ar.coffee
index 1f0584c85..32716882e 100644
--- a/app/locale/ar.coffee
+++ b/app/locale/ar.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/bg.coffee b/app/locale/bg.coffee
index fd038c56c..2396688fe 100644
--- a/app/locale/bg.coffee
+++ b/app/locale/bg.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "български език", englishDescri
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/cs.coffee b/app/locale/cs.coffee
index 121f0da4f..ee87db33d 100644
--- a/app/locale/cs.coffee
+++ b/app/locale/cs.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
     artisan_join_step4: "Zveřejněte vaši úroveň na fóru pro připomínkování."
     more_about_artisan: "Dozvědět se více o tom, jak se stát kreativním Řemeslníkem"
     artisan_subscribe_desc: "Dostávat emailem oznámení a informace o aktualizacích editoru úrovní."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
     adventurer_introduction: "Ujasněme si dopředu jednu věc o vaší roli: budete jako tank. Projdete ohněm. Potřebujeme někoho, kdo odzkouší zbrusu nové úrovně a pomůže identifikovat kde je možno je zlepšit. Ten boj bude ohromný - tvorba her je dlouhý proces, který nikdo nezvládne na první pokus. Máte-li na to a vydržíte-li to, pak toto je vaše skupina."
     adventurer_attribute_1: "Touha po učení se. Vy se chcete naučit programovat a my vás to chceme naučit. Jenom, v tomto případě to budete vy, kdo bude vyučovat."
     adventurer_attribute_2: "Charismatický. Buďte mírný a pečlivě artikulujte co a jak je potřeba zlepšit."
diff --git a/app/locale/da.coffee b/app/locale/da.coffee
index ad47c71fc..d3a40c86f 100644
--- a/app/locale/da.coffee
+++ b/app/locale/da.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/de.coffee b/app/locale/de.coffee
index 04b640ce8..7e9f4b9ee 100644
--- a/app/locale/de.coffee
+++ b/app/locale/de.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/el.coffee b/app/locale/el.coffee
index 91fd4be36..831c4eee9 100644
--- a/app/locale/el.coffee
+++ b/app/locale/el.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "ελληνικά", englishDescription: "Gre
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/en-AU.coffee b/app/locale/en-AU.coffee
index 8c36e3ef7..cce71adb9 100644
--- a/app/locale/en-AU.coffee
+++ b/app/locale/en-AU.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/en-GB.coffee b/app/locale/en-GB.coffee
index 1da9d218a..7dcad9c36 100644
--- a/app/locale/en-GB.coffee
+++ b/app/locale/en-GB.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/en-US.coffee b/app/locale/en-US.coffee
index 9d3b2dc5a..1bcf71a71 100644
--- a/app/locale/en-US.coffee
+++ b/app/locale/en-US.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/es-419.coffee b/app/locale/es-419.coffee
index 3c2614713..237fb3a69 100644
--- a/app/locale/es-419.coffee
+++ b/app/locale/es-419.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/es-ES.coffee b/app/locale/es-ES.coffee
index e45550e08..be9c83a7d 100644
--- a/app/locale/es-ES.coffee
+++ b/app/locale/es-ES.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
     artisan_join_step4: "Publica tus niveles en el foro para recibir comentarios críticos."
     more_about_artisan: "Aprende más sobre convertirte en un Artesano creativo"
     artisan_subscribe_desc: "Recibe correos sobre actualizaciones del editor de niveles y anuncios."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
     adventurer_introduction: "Hablemos claro sobre tu papel: eres el tanque. Vas a recibir fuertes daños. Necesitamos gente para probar nuestros flamantes niveles y ayudar a mejorarlos. El dolor será enorme; hacer buenos juegos es un proceso largo y nadie lo consigue a la primera. Si puedes resistir y tener una puntuación alta en Resistencia, entonces esta Clase es para ti."
     adventurer_attribute_1: "Estar sediento de conocimientos. Quieres aprender a programar y nosotros queremos enseñarte cómo hacerlo. Aunque en este caso es más probable que seas tú el que esté haciendo la mayor parte de la enseñanza."
     adventurer_attribute_2: "Carismático. Se amable pero claro a la hora de desglosar qué necesita ser mejorado y sugiere de qué formas podría hacerse."
diff --git a/app/locale/es.coffee b/app/locale/es.coffee
index b4009323b..f576a0c85 100644
--- a/app/locale/es.coffee
+++ b/app/locale/es.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/fa.coffee b/app/locale/fa.coffee
index 28a4bd760..a0e1c046b 100644
--- a/app/locale/fa.coffee
+++ b/app/locale/fa.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/fi.coffee b/app/locale/fi.coffee
index 57e5151e4..5c78e1914 100644
--- a/app/locale/fi.coffee
+++ b/app/locale/fi.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/fr.coffee b/app/locale/fr.coffee
index 1469c7269..330b029f8 100644
--- a/app/locale/fr.coffee
+++ b/app/locale/fr.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     artisan_join_step4: "Postez vos niveaux dans le forum pour avoir des retours."
     more_about_artisan: "En apprendre plus sur comment devenir un Artisan créatif"
     artisan_subscribe_desc: "Recevoir un email sur les annonces et mises à jour de l'éditeur de niveaux."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
     adventurer_introduction: "Soyons clair à propos de votre rôle : vous êtes le tank. Vous allez subir beaucoup de dommages. Nous avons besoin de gens pour essayer les nouveaux niveaux et aider à identifier comment améliorer les choses. La douleur sera énorme; faire de bons jeux est une longue tâche et personne n'y arrive du premier coup. Si vous pouvez résister et avez un gros score de constitution, alors cette classe est faite pour vous."
     adventurer_attribute_1: "Une soif d'apprendre. Vous voulez apprendre à développer et nous voulons vous apprendre. Vous allez toutefois faire la plupart de l'apprentissage."
     adventurer_attribute_2: "Charismatique. Soyez doux mais exprimez-vous sur ce qui a besoin d'être amélioré, et faites des propositions sur comment l'améliorer."
diff --git a/app/locale/he.coffee b/app/locale/he.coffee
index ddcb7484c..f1e34dc8e 100644
--- a/app/locale/he.coffee
+++ b/app/locale/he.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/hi.coffee b/app/locale/hi.coffee
index 596ecd1ce..c144127a5 100644
--- a/app/locale/hi.coffee
+++ b/app/locale/hi.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/hu.coffee b/app/locale/hu.coffee
index ad6cd0273..bed717d2c 100644
--- a/app/locale/hu.coffee
+++ b/app/locale/hu.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/id.coffee b/app/locale/id.coffee
index 20d16335f..9b938c230 100644
--- a/app/locale/id.coffee
+++ b/app/locale/id.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/it.coffee b/app/locale/it.coffee
index a95f98916..883ba4321 100644
--- a/app/locale/it.coffee
+++ b/app/locale/it.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "italiano", englishDescription: "Italian", t
 #    artisan_join_step4: "Post your levels on the forum for feedback."
     more_about_artisan: "Leggi di più su cosa vuol dire diventare un creativo Artigiano"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/ja.coffee b/app/locale/ja.coffee
index 4c9e4dfb9..195269c4d 100644
--- a/app/locale/ja.coffee
+++ b/app/locale/ja.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/ko.coffee b/app/locale/ko.coffee
index 882f3d4ac..55fdd32f1 100644
--- a/app/locale/ko.coffee
+++ b/app/locale/ko.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/lt.coffee b/app/locale/lt.coffee
index 1008a8bfb..64cfe04f2 100644
--- a/app/locale/lt.coffee
+++ b/app/locale/lt.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/ms-BA.coffee b/app/locale/ms-BA.coffee
index 29c914f23..e551e3e0f 100644
--- a/app/locale/ms-BA.coffee
+++ b/app/locale/ms-BA.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/nb.coffee b/app/locale/nb.coffee
index db74e540d..68569c841 100644
--- a/app/locale/nb.coffee
+++ b/app/locale/nb.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/nl.coffee b/app/locale/nl.coffee
index 508d6e384..f4c45edc5 100644
--- a/app/locale/nl.coffee
+++ b/app/locale/nl.coffee
@@ -397,28 +397,28 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     artisan_join_step4: "Maak een bericht over jouw level op ons forum voor feedback."
     more_about_artisan: "Leer meer over hoe je een Creatieve Ambachtsman kan worden."
     artisan_subscribe_desc: "Ontvang e-mails met nieuws over de Level Editor."
-    adventurer_sumamry: "Laten we duidelijk zijn over je rol: jij bent de tank. Jij krijgt de zware klappen te verduren. We hebben mensen nodig om spiksplinternieuwe levels te proberen en te kijken hoe deze beter kunnen. De pijn zal groot zijn, het maken van een goede game is een lang proces en niemand doet het de eerste keer goed. Als jij dit kan verduren en een hoge constitution score hebt, dan is dit de klasse voor jou."
+    adventurer_summary: "Laten we duidelijk zijn over je rol: jij bent de tank. Jij krijgt de zware klappen te verduren. We hebben mensen nodig om spiksplinternieuwe levels te proberen en te kijken hoe deze beter kunnen. De pijn zal groot zijn, het maken van een goede game is een lang proces en niemand doet het de eerste keer goed. Als jij dit kan verduren en een hoge constitution score hebt, dan is dit de klasse voor jou."
     adventurer_introduction: "Laten we duidelijk zijn over je rol: jij bent de tank. Jij krijgt de zware klappen te verduren. We hebben mensen nodig om spiksplinternieuwe levels te proberen en te kijken hoe deze beter kunnen. De pijn zal groot zijn, het maken van een goede game is een lang proces en niemand doet het de eerste keer goed. Als jij dit kan verduren en een hoge constitution score hebt, dan is dit de klasse voor jou."
     adventurer_attribute_1: "Een wil om te leren. Jij wilt leren hoe je programmeert en wij willen het jou leren. Je zal overigens zelf het meeste leren doen."
     adventurer_attribute_2: "Charismatisch. Wees netjes maar duidelijk over wat er beter kan en geef suggesties over hoe het beter kan."
-    adventurer_join_pref: "Werk samen met een Ambachtsman of recruteer er een, of tik het veld hieronder aan om e-mails te ontvangen wanneer er nieuwe levels zijn om te testen. We zullen ook posten over levels die beoordeeld moeten worden op onze netwerken zoals"    
+    adventurer_join_pref: "Werk samen met een Ambachtsman of recruteer er een, of tik het veld hieronder aan om e-mails te ontvangen wanneer er nieuwe levels zijn om te testen. We zullen ook posten over levels die beoordeeld moeten worden op onze netwerken zoals"
     adventurer_forum_url: "ons forum"
-    adventurer_join_suf: "dus als je liever op deze manier wordt geïnformeerd, schrijf je daar in!"    
+    adventurer_join_suf: "dus als je liever op deze manier wordt geïnformeerd, schrijf je daar in!"
     more_about_adventurer: "Leer meer over hoe je een dappere avonturier kunt worden."
     adventurer_subscribe_desc: "Ontvang e-mails wanneer er nieuwe levels zijn die getest moeten worden."
     scribe_summary_pref: "CodeCombat is meer dan slechts een aantal levels, het zal ook een bron van kennis kennis zijn en een wiki met programmeerconcepten waar levels op in kunnen gaan. Op die manier zal een Ambachtslied  een link kunnen geven naar een artikel wat past bij een level. Net zoiets als het  "
     scribe_summary_sufx: " heeft gebouwd. Als jij het leuk vindt programmeerconcepten uit te leggen, dan is deze klasse iets voor jou."
-    scribe_introduction_pref: "CodeCombat is meer dan slechts een aantal levels, het zal ook een bron van kennis kennis zijn en een wiki met programmeerconcepten waar levels op in kunnen gaan. Op die manier zal elk Ambachtslied niet in detail hoeven uit te leggen wat een vergelijkingsoperator is, maar een link kunnen geven naar een artikel wat deze informatie bevat voor de speler. Net zoiets als het  "    
+    scribe_introduction_pref: "CodeCombat is meer dan slechts een aantal levels, het zal ook een bron van kennis kennis zijn en een wiki met programmeerconcepten waar levels op in kunnen gaan. Op die manier zal elk Ambachtslied niet in detail hoeven uit te leggen wat een vergelijkingsoperator is, maar een link kunnen geven naar een artikel wat deze informatie bevat voor de speler. Net zoiets als het  "
     scribe_introduction_url_mozilla: "Mozilla Developer Network"
     scribe_introduction_suf: " heeft gebouwd. Als jij het leuk vindt om programmeerconcepten uit te leggen in Markdown-vorm, dan is deze klasse wellicht iets voor jou."
     scribe_attribute_1: "Taal-skills zijn praktisch alles wat je nodig hebt. Niet alleen grammatica of spelling, maar ook moeilijke ideeën overbrengen aan anderen."
     contact_us_url: "Contacteer ons"
-    scribe_join_description: "vertel ons wat over jezelf, je ervaring met programmeren en over wat voor soort dingen je graag zou schrijven. Verder zien we wel!"    
-    more_about_scribe: "Leer meer over het worden van een ijverige Klerk."    
-    
-    scribe_subscribe_desc: "Ontvang e-mails met aankondigingen over het schrijven van artikelen."    
+    scribe_join_description: "vertel ons wat over jezelf, je ervaring met programmeren en over wat voor soort dingen je graag zou schrijven. Verder zien we wel!"
+    more_about_scribe: "Leer meer over het worden van een ijverige Klerk."
+
+    scribe_subscribe_desc: "Ontvang e-mails met aankondigingen over het schrijven van artikelen."
     diplomat_summary: "Er is grote interesse in CodeCombat in landen waar geen Engels wordt gesproken! We zijn op zoek naar vertalers wie tijd willen spenderen aan het vertalen van de site's corpus aan woorden zodat CodeCombat zo snel mogelijk toegankelijk wordt voor heel de wereld. Als jij wilt helpen met CodeCombat internationaal maken, dan is dit de klasse voor jou."
-    diplomat_introduction_pref: "Dus, als er iets is wat we geleerd hebben van de "    
+    diplomat_introduction_pref: "Dus, als er iets is wat we geleerd hebben van de "
     diplomat_launch_url: "release in oktober"
     diplomat_introduction_suf: "dan is het wel dat er een significante interesse is in CodeCombat in andere landen, vooral Brazilië! We zijn een corps aan vertalers aan het creëren dat ijverig de ene set woorden in een andere omzet om CodeCombat zo toegankelijk te maken als mogelijk in heel de wereld. Als jij het leuk vindt glimpsen op te vangen van aankomende content en deze levels zo snel mogelijk naar je landgenoten te krijgen, dan is dit de klasse voor jou."
     diplomat_attribute_1: "Vloeiend Engels en de taal waar naar je wilt vertalen kunnen spreken. Wanneer je moeilijke ideeën wilt overbrengen, is het belangrijk beide goed te kunnen!"
@@ -429,17 +429,17 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     diplomat_subscribe_desc: "Ontvang e-mails over i18n ontwikkelingen en levels om te vertalen."
     ambassador_summary: "We proberen een gemeenschap te bouwen en elke gemeenschap heeft een supportteam nodig wanneer er problemen zijn. We hebben chats, e-mails en sociale netwerken zodat onze gebruikers het spel kunnen leren kennen. Als jij mensen wilt helpen betrokken te raken, plezier te hebben en wat te leren programmeren, dan is dit wellicht de klasse voor jou."
     ambassador_attribute_1: "Communicatieskills. Problemen die spelers hebben kunnen identificeren en ze helpen deze op te lossen. Verder zul je ook de rest van ons geïnformeerd houden over wat de spelers zeggen, wat ze leuk vinden, wat ze minder vinden en waar er meer van moet zijn!"
-    ambassador_join_desc: "vertel ons wat over jezelf, wat je hebt gedaan en wat je graag zou doen. We zien verder wel!"    
+    ambassador_join_desc: "vertel ons wat over jezelf, wat je hebt gedaan en wat je graag zou doen. We zien verder wel!"
     ambassador_join_note_strong: "Opmerking"
-    ambassador_join_note_desc: "Een van onze topprioriteiten is om een multiplayer te bouwen waar spelers die moeite hebben een level op te lossen een wizard met een hoger level kunnen oproepen om te helpen. Dit zal een goede manier zijn voor ambassadeurs om hun ding te doen. We houden je op de hoogte!"    
+    ambassador_join_note_desc: "Een van onze topprioriteiten is om een multiplayer te bouwen waar spelers die moeite hebben een level op te lossen een wizard met een hoger level kunnen oproepen om te helpen. Dit zal een goede manier zijn voor ambassadeurs om hun ding te doen. We houden je op de hoogte!"
     more_about_ambassador: "Leer meer over het worden van een behulpzame Ambassadeur"
-    ambassador_subscribe_desc: "Ontvang e-mails met updates over ondersteuning en multiplayer-ontwikkelingen."    
+    ambassador_subscribe_desc: "Ontvang e-mails met updates over ondersteuning en multiplayer-ontwikkelingen."
     counselor_summary: "Geen van de rollen hierboven in jouw interessegebied? Maak je geen zorgen, we zijn op zoek naar iedereen die wil helpen met het ontwikkelen van CodeCombat! Als je geïnteresseerd bent in lesgeven, gameontwikkeling, open source management of iets anders waarvan je denkt dat het relevant voor ons is, dan is dit de klasse voor jou."
     counselor_introduction_1: "Heb jij levenservaring? Een afwijkend perspectief op zaken die ons kunnen helpen CodeCombat te vormen? Van alle rollen neemt deze wellicht de minste tijd in, maar individueel maak je misschien het grootste verschil. We zijn op zoek naar wijze tovenaars, vooral in het gebied van lesgeven, gameontwikkeling, open source projectmanagement, technische recrutering, ondernemerschap of design."
-    counselor_introduction_2: "Of eigenlijk alles wat relevant is voor de ontwikkeling van CodeCombat. Als jij kennis hebt en deze wilt dezen om dit project te laten groeien, dan is dit misschien de klasse voor jou."    
+    counselor_introduction_2: "Of eigenlijk alles wat relevant is voor de ontwikkeling van CodeCombat. Als jij kennis hebt en deze wilt dezen om dit project te laten groeien, dan is dit misschien de klasse voor jou."
     counselor_attribute_1: "Ervaring, in enig van de bovenstaande gebieden of iets anders waarvan je denkt dat het behulpzaam zal zijn."
     counselor_attribute_2: "Een beetje vrije tijd!"
-    counselor_join_desc: "vertel ons wat over jezelf, wat je hebt gedaan en wat je graag wilt doen. We zullen je in onze contactlijst zetten en je benaderen wanneer we je advies kunnen gebruiken (niet te vaak)."    
+    counselor_join_desc: "vertel ons wat over jezelf, wat je hebt gedaan en wat je graag wilt doen. We zullen je in onze contactlijst zetten en je benaderen wanneer we je advies kunnen gebruiken (niet te vaak)."
     more_about_counselor: "Leer meer over het worden van een waardevolle Raadgever"
     changes_auto_save: "Veranderingen worden automatisch opgeslagen wanneer je het vierkantje aan- of afvinkt."
     diligent_scribes: "Onze ijverige Klerks:"
diff --git a/app/locale/nn.coffee b/app/locale/nn.coffee
index c9e770bfa..7bd5b0307 100644
--- a/app/locale/nn.coffee
+++ b/app/locale/nn.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/no.coffee b/app/locale/no.coffee
index bc0e69e0c..78fc15832 100644
--- a/app/locale/no.coffee
+++ b/app/locale/no.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/pl.coffee b/app/locale/pl.coffee
index 9988be45e..32f394f1c 100644
--- a/app/locale/pl.coffee
+++ b/app/locale/pl.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/pt-BR.coffee b/app/locale/pt-BR.coffee
index 40f374f81..be8e8079f 100644
--- a/app/locale/pt-BR.coffee
+++ b/app/locale/pt-BR.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription:
     artisan_join_step4: "Publique seus níveis no fórum para avaliação."
     more_about_artisan: "Saiba Mais Sobre Como Se Tornar Um Artesão Criativo"
     artisan_subscribe_desc: "Receba emails com novidades sobre o editor de níveis e anúncios."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
     adventurer_introduction: "Vamos ser claros sobre o seu papel: você é o tanque. Você vai tomar dano pesado. Precisamos de pessoas para experimentar níveis inéditos e ajudar a identificar como fazer as coisas melhorarem. A dor será enorme, fazer bons jogos é um processo longo e ninguém acerta na primeira vez. Se você pode suportar e ter uma alta pontuação de constituição, então esta classe pode ser para você."
     adventurer_attribute_1: "Sede de aprendizado. Você quer aprender a codificar e nós queremos ensiná-lo a codificar. Você provavelmente vai fazer a maior parte do ensino neste caso."
     adventurer_attribute_2: "Carismático. Seja gentil, mas articulado sobre o que precisa melhorar, e ofereça sugestões sobre como melhorar."
diff --git a/app/locale/pt-PT.coffee b/app/locale/pt-PT.coffee
index 77fb7afad..57278318b 100644
--- a/app/locale/pt-PT.coffee
+++ b/app/locale/pt-PT.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/pt.coffee b/app/locale/pt.coffee
index 38a21790c..ee3395e7f 100644
--- a/app/locale/pt.coffee
+++ b/app/locale/pt.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/ro.coffee b/app/locale/ro.coffee
index 3551d730b..1fee5fe47 100644
--- a/app/locale/ro.coffee
+++ b/app/locale/ro.coffee
@@ -96,8 +96,8 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
   diplomat_suggestion:
     title: "Ajută-ne  să traducem CodeCombat!"
     sub_heading: "Avem nevoie de abilitățile tale lingvistice."
-    pitch_body: "CodeCombat este dezvoltat in limba engleza , dar deja avem jucatări din toate colțurile lumii.Mulți dintre ei vor să joace in română și nu vorbesc engleză.Dacă poți vorbi ambele te rugăm să te gândești dacă ai dori să devi un Diplomat și să ne ajuți sa traducem atât jocul cât și site-ul." 
-    missing_translations: "Until we can translate everything into Romanian, you'll see English when Romanian isn't available." 
+    pitch_body: "CodeCombat este dezvoltat in limba engleza , dar deja avem jucatări din toate colțurile lumii.Mulți dintre ei vor să joace in română și nu vorbesc engleză.Dacă poți vorbi ambele te rugăm să te gândești dacă ai dori să devi un Diplomat și să ne ajuți sa traducem atât jocul cât și site-ul."
+    missing_translations: "Until we can translate everything into Romanian, you'll see English when Romanian isn't available."
     learn_more: "Află mai multe despre cum să fi un Diplomat"
     subscribe_as_diplomat: "Înscrie-te ca Diplomat"
 
@@ -105,7 +105,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
     title: "Setări Wizard"
     customize_avatar: "Personalizează-ți Avatarul"
     clothes: "Haine"
-    trim: "Margine" 
+    trim: "Margine"
     cloud: "Nor"
     spell: "Vrajă"
     boots: "Încălțăminte"
@@ -389,7 +389,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 57cfc1847..51f6d1a7e 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     artisan_join_step4: "Разместите свои уровни на форуме для обратной связи."
     more_about_artisan: "Узнать больше о том, как стать Ремесленником"
     artisan_subscribe_desc: "Получать email-ы об обновлениях редактора уровней и объявления."
-    adventurer_sumamry: "Позвольте внести ясность о вашей роли: вы танк. Вы собираетесь принять тяжелые повреждения. Нам нужны люди, чтобы испытать совершенно новые уровни и помочь определить, как сделать лучше. Боль будет огромной; создание хороших игр - длительный процесс и никто не делает это правильно в первый раз. Если вы можете выдержать и имеете высокий балл конституции (D&D), этот класс для вас."
+    adventurer_summary: "Позвольте внести ясность о вашей роли: вы танк. Вы собираетесь принять тяжелые повреждения. Нам нужны люди, чтобы испытать совершенно новые уровни и помочь определить, как сделать лучше. Боль будет огромной; создание хороших игр - длительный процесс и никто не делает это правильно в первый раз. Если вы можете выдержать и имеете высокий балл конституции (D&D), этот класс для вас."
     adventurer_introduction: "Позвольте внести ясность о вашей роли: вы танк. Вы собираетесь принять тяжелые повреждения. Нам нужны люди, чтобы испытать совершенно новые уровни и помочь определить, как сделать лучше. Боль будет огромной; создание хороших игр - длительный процесс и никто не делает это правильно в первый раз. Если вы можете выдержать и имеете высокий балл конституции (D&D), этот класс для вас."
     adventurer_attribute_1: "Жажда обучения. Вы хотите научиться программировать и мы хотим научить вас программировать. Вы, вероятно, проведёте большую часть обучения в процессе."
     adventurer_attribute_2: "Харизматичность. Будьте нежны, но ясно формулируйте, что нуждается в улучшении и вносите свои предложения по улучшению."
diff --git a/app/locale/sk.coffee b/app/locale/sk.coffee
index c9e3e4023..ae22ef336 100644
--- a/app/locale/sk.coffee
+++ b/app/locale/sk.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/sl.coffee b/app/locale/sl.coffee
index b0cbdd3f5..89b759c19 100644
--- a/app/locale/sl.coffee
+++ b/app/locale/sl.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/sr.coffee b/app/locale/sr.coffee
index c9676fa65..d3c351f39 100644
--- a/app/locale/sr.coffee
+++ b/app/locale/sr.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/sv.coffee b/app/locale/sv.coffee
index d8b41ec50..001ce3eca 100644
--- a/app/locale/sv.coffee
+++ b/app/locale/sv.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/th.coffee b/app/locale/th.coffee
index 9b2134eb8..76f1aa37d 100644
--- a/app/locale/th.coffee
+++ b/app/locale/th.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/tr.coffee b/app/locale/tr.coffee
index 4a256defe..39e268908 100644
--- a/app/locale/tr.coffee
+++ b/app/locale/tr.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/uk.coffee b/app/locale/uk.coffee
index bf67c2138..52d4fd3b4 100644
--- a/app/locale/uk.coffee
+++ b/app/locale/uk.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/ur.coffee b/app/locale/ur.coffee
index 8237971a3..75a2c2e38 100644
--- a/app/locale/ur.coffee
+++ b/app/locale/ur.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/vi.coffee b/app/locale/vi.coffee
index c3a00a167..bb7ac3b89 100644
--- a/app/locale/vi.coffee
+++ b/app/locale/vi.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/zh-HANS.coffee b/app/locale/zh-HANS.coffee
index caa2b9802..fd0e42cbf 100644
--- a/app/locale/zh-HANS.coffee
+++ b/app/locale/zh-HANS.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 #    artisan_join_step4: "Post your levels on the forum for feedback."
     more_about_artisan: "了解成为工匠的方法"
     artisan_subscribe_desc: "通过电子邮件获得关卡编辑器更新和公告。"
-    adventurer_sumamry: "丑话说在前面,你就是那个挡枪子的,而且你会伤得很重。我们需要人手来测试崭新的关卡,并且提出改进意见。做一个好游戏是一个漫长的过程,没人第一次就能搞对。如果你能忍得了这些,而且身体健壮,那这个职业就是你的了。"
+    adventurer_summary: "丑话说在前面,你就是那个挡枪子的,而且你会伤得很重。我们需要人手来测试崭新的关卡,并且提出改进意见。做一个好游戏是一个漫长的过程,没人第一次就能搞对。如果你能忍得了这些,而且身体健壮,那这个职业就是你的了。"
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/zh-HANT.coffee b/app/locale/zh-HANT.coffee
index d38532973..b6cf92b26 100644
--- a/app/locale/zh-HANT.coffee
+++ b/app/locale/zh-HANT.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
diff --git a/app/locale/zh.coffee b/app/locale/zh.coffee
index aacf8fe4d..452df3628 100644
--- a/app/locale/zh.coffee
+++ b/app/locale/zh.coffee
@@ -390,7 +390,7 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
 #    artisan_join_step4: "Post your levels on the forum for feedback."
 #    more_about_artisan: "Learn More About Becoming an Artisan"
 #    artisan_subscribe_desc: "Get emails on level editor updates and announcements."
-#    adventurer_sumamry: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
+#    adventurer_summary: "Let us be clear about your role: you are the tank. You are going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class is for you."
 #    adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
 #    adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
 #    adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."

From a03403de944d7e2f7a24de7e42c488c3f2646fa8 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Thu, 6 Mar 2014 09:35:58 -0800
Subject: [PATCH 094/178] Started some more name categories.

---
 app/lib/world/names.coffee | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/app/lib/world/names.coffee b/app/lib/world/names.coffee
index 44c446583..3b1cd0080 100644
--- a/app/lib/world/names.coffee
+++ b/app/lib/world/names.coffee
@@ -88,6 +88,9 @@ module.exports.thangNames = thangNames =
     "Durfkor"
     "Paps"
   ]
+  "Peasant F": [
+    "Hilda"
+  ]
   "Archer F": [
     "Phoebe"
     "Mira"
@@ -238,3 +241,19 @@ module.exports.thangNames = thangNames =
     "Rakash"
     "Drumbaa"
   ]
+  "Burl": [
+    "Borlit"
+    "Burlosh"
+  ]
+  "Griffin Rider": [
+    "Aeoldan"
+  ]
+  "Potion Master": [
+    "Snake"
+  ]
+  "Librarian": [
+    "Hushbaum"
+  ]
+  "Equestrian": [
+    "Reynaldo"
+  ]

From 40a32d7b43e582efaa91ccfaafde56580d023889 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Thu, 6 Mar 2014 14:53:37 -0800
Subject: [PATCH 095/178] Fixed array / string ThangState key serialization
 conflicts. Fixed #333.

---
 app/lib/world/thang_state.coffee | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/app/lib/world/thang_state.coffee b/app/lib/world/thang_state.coffee
index 964f25eda..7db97aca6 100644
--- a/app/lib/world/thang_state.coffee
+++ b/app/lib/world/thang_state.coffee
@@ -51,7 +51,8 @@ module.exports = class ThangState
     else if type is 'array'
       specialKey = storage[@frameIndex]
       value = @specialKeysToValues[specialKey]
-      value = value.split('\x1E')  # Record Separator
+      # Remove leading and trailing Group Separators and split by any Record Separators to restore the array of strings
+      value = value.substring(1, value.length - 1).split('\x1E') if value
     else
       value = storage[@frameIndex]
     value
@@ -133,7 +134,8 @@ module.exports = class ThangState
             storage[frameIndex] = specialKey
           storage[frameIndex] = specialKey
         else if type is 'array'
-          value = value.join '\x1E'  # Record Separator
+          # We make sure the array keys won't collide with any string keys by using some unprintable characters.
+          value = '\x1D' + value.join('\x1E') + '\x1D'  # Group Separator, Record Separator(s), Group Separator
           specialKey = specialValuesToKeys[value]
           unless specialKey
             specialKey = specialKeysToValues.length

From 041f4512e8c02387d3aa0ec788a7f69da9293d18 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 6 Mar 2014 15:52:09 -0800
Subject: [PATCH 096/178] Set up marks to all load dynamically, and set up
 effect marks, which appear above a thang's head and rotate between them if
 there are multiple.

---
 app/lib/surface/CocoSprite.coffee | 42 +++++++++++++++++++++++++++++--
 app/lib/surface/Mark.coffee       | 35 +++++++++++++++++++++++---
 app/lib/surface/SpriteBoss.coffee | 10 +++-----
 app/models/Level.coffee           | 10 --------
 4 files changed, 74 insertions(+), 23 deletions(-)

diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee
index 57146866a..279ef087b 100644
--- a/app/lib/surface/CocoSprite.coffee
+++ b/app/lib/surface/CocoSprite.coffee
@@ -82,6 +82,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     @imageObject?.off 'animationend', @playNextAction
     @playNextAction = null
     @displayObject?.off()
+    clearInterval @effectInterval if @effectInterval
     super()
 
   toString: -> "<CocoSprite: #{@thang?.id}>"
@@ -375,18 +376,55 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     scale *= @options.resolutionFactor if prop is 'registration'
     pos.x *= scale
     pos.y *= scale
+    if @thang
+      scaleFactor = @thang.scaleFactor ? 1
+      pos.x *= @thang.scaleFactorX ? scaleFactor
+      pos.y *= @thang.scaleFactorY ? scaleFactor
     pos
 
   updateMarks: ->
     return unless @options.camera
-    @addMark 'repair', null, @options.markThangTypes.repair if @thang?.errorsOut
+    @addMark 'repair', null, 'repair' if @thang?.errorsOut
     @marks.repair?.toggle @thang?.errorsOut
     @addMark('bounds').toggle true if @thang?.drawsBounds
     @addMark('shadow').toggle true unless @thangType.get('shadow') is 0
     mark.update() for name, mark of @marks
+#    @thang.effectNames = ['berserk', 'confused', 'controlled',  'cursed', 'fear', 'poison', 'paralyzed', 'regeneration', 'sleep', 'slowed', 'speed']
+    @updateEffectMarks() if @thang?.effectNames?.length
+    
+  updateEffectMarks: ->
+    return if _.isEqual @thang.effectNames, @previousEffectNames
+    for effect in @thang.effectNames
+      mark = @addMark effect, @options.floatingLayer, effect
+      mark.statusEffect = true
+      mark.toggle 'on'
+      mark.show()
+      
+    if @previousEffectNames
+      for effect in @previousEffectNames
+        mark = @marks[effect]
+        mark.toggle 'off'
+      
+    if @thang.effectNames.length > 1 and not @effectInterval
+      @rotateEffect()
+      @effectInterval = setInterval @rotateEffect, 1500
+      
+    else if @effectInterval and @thang.effectNames.length <= 1
+      @clearInterval @effectInterval
+      @effectInterval = null
+      
+    @previousEffectNames = @thang.effectNames
+
+  rotateEffect: =>
+    effects = (m.name for m in _.values(@marks) when m.on and m.statusEffect and m.mark)
+    effects.sort()
+    @effectIndex ?= 0
+    @effectIndex = (@effectIndex + 1) % effects.length
+    @marks[effect].hide() for effect in effects
+    @marks[effects[@effectIndex]].show()
 
   setHighlight: (to, delay) ->
-    @addMark 'highlight', @options.floatingLayer, @options.markThangTypes.highlight if to
+    @addMark 'highlight', @options.floatingLayer, 'highlight' if to
     @marks.highlight?.highlightDelay = delay
     @marks.highlight?.toggle to and not @dimmed
 
diff --git a/app/lib/surface/Mark.coffee b/app/lib/surface/Mark.coffee
index c012b537c..5a2e7689f 100644
--- a/app/lib/surface/Mark.coffee
+++ b/app/lib/surface/Mark.coffee
@@ -1,5 +1,7 @@
 CocoClass = require 'lib/CocoClass'
 Camera = require './Camera'
+ThangType = require 'models/ThangType'
+markThangTypes = {}
 
 module.exports = class Mark extends CocoClass
   subscriptions: {}
@@ -20,6 +22,7 @@ module.exports = class Mark extends CocoClass
   destroy: ->
     @mark?.parent?.removeChild @mark
     @markSprite?.destroy()
+    @thangType?.off 'sync', @onLoadedThangType, @
     @sprite = null
     super()
 
@@ -27,7 +30,9 @@ module.exports = class Mark extends CocoClass
 
   toggle: (to) ->
     return @ if to is @on
+    return @toggleTo = to unless @mark
     @on = to
+    delete @toggleTo
     if @on
       @layer.addChild @mark
       @layer.updateLayerOrder()
@@ -52,7 +57,7 @@ module.exports = class Mark extends CocoClass
       else if @name is 'debug' then @buildDebug()
       else if @thangType then @buildSprite()
       else console.error "Don't know how to build mark for", @name
-      @mark.mouseEnabled = false
+      @mark?.mouseEnabled = false
     @
 
   buildBounds: ->
@@ -126,15 +131,34 @@ module.exports = class Mark extends CocoClass
     @mark.graphics.endFill()
 
   buildSprite: ->
-    #console.log "building", @name, "with thangtype", @thangType
+    if _.isString @thangType
+      thangType = markThangTypes[@thangType]
+      return @loadThangType() if not thangType
+      @thangType = thangType
+
+    return @thangType.once 'sync', @onLoadedThangType, @ if not @thangType.loaded
     CocoSprite = require './CocoSprite'
     markSprite = new CocoSprite @thangType, @thangType.spriteOptions
     markSprite.queueAction 'idle'
     @mark = markSprite.displayObject
     @markSprite = markSprite
 
+  loadThangType: ->
+    name = @thangType
+    @thangType = new ThangType()
+    @thangType.url = -> "/db/thang.type/#{name}"
+    @thangType.once 'sync', @onLoadedThangType, @
+    @thangType.fetch()
+    markThangTypes[name] = @thangType
+    window.mtt = markThangTypes
+    
+  onLoadedThangType: ->
+    @build()
+    @toggle(@toggleTo) if @toggleTo?
+
   update: (pos=null) ->
-    return false unless @on
+    return false unless @on and @mark
+    @mark.alpha = if @hidden then 0 else 1
     @updatePosition pos
     @updateRotation()
     @updateScale()
@@ -156,10 +180,11 @@ module.exports = class Mark extends CocoClass
       pos ?= @sprite?.displayObject
     @mark.x = pos.x
     @mark.y = pos.y
-    if @name is 'highlight'
+    if @statusEffect or @name is 'highlight'
       offset = @sprite.getOffset 'aboveHead'
       @mark.x += offset.x
       @mark.y += offset.y
+      @mark.y -= 3 if @statusEffect
 
   updateRotation: ->
     if @name is 'debug' or (@name is 'shadow' and @sprite.thang?.shape in ["rectangle", "box"])
@@ -187,3 +212,5 @@ module.exports = class Mark extends CocoClass
 
   stop: -> @markSprite?.stop()
   play: -> @markSprite?.play()
+  hide: -> @hidden = true
+  show: -> @hidden = false
diff --git a/app/lib/surface/SpriteBoss.coffee b/app/lib/surface/SpriteBoss.coffee
index 130d017b7..f84d52a28 100644
--- a/app/lib/surface/SpriteBoss.coffee
+++ b/app/lib/surface/SpriteBoss.coffee
@@ -48,10 +48,6 @@ module.exports = class SpriteBoss extends CocoClass
   thangTypeFor: (type) ->
     _.find @options.thangTypes, (m) -> m.get('original') is type or m.get('name') is type
 
-  markThangTypes: ->
-    highlight: @thangTypeFor "Highlight"
-    repair: @thangTypeFor "Repair"
-
   createLayers: ->
     @spriteLayers = {}
     for [name, priority] in [
@@ -87,11 +83,11 @@ module.exports = class SpriteBoss extends CocoClass
     sprite
 
   createMarks: ->
-    @targetMark = new Mark name: 'target', camera: @camera, layer: @spriteLayers["Ground"], thangType: @thangTypeFor("Target")
-    @selectionMark = new Mark name: 'selection', camera: @camera, layer: @spriteLayers["Ground"], thangType: @thangTypeFor("Selection")
+    @targetMark = new Mark name: 'target', camera: @camera, layer: @spriteLayers["Ground"], thangType: 'target'
+    @selectionMark = new Mark name: 'selection', camera: @camera, layer: @spriteLayers["Ground"], thangType: 'selection'
 
   createSpriteOptions: (options) ->
-    _.extend options, camera: @camera, resolutionFactor: 4, groundLayer: @spriteLayers["Ground"], textLayer: @surfaceTextLayer, floatingLayer: @spriteLayers["Floating"], markThangTypes: @markThangTypes(), spriteSheetCache: @spriteSheetCache, showInvisible: @options.showInvisible
+    _.extend options, camera: @camera, resolutionFactor: 4, groundLayer: @spriteLayers["Ground"], textLayer: @surfaceTextLayer, floatingLayer: @spriteLayers["Floating"], spriteSheetCache: @spriteSheetCache, showInvisible: @options.showInvisible
 
   createIndieSprites: (indieSprites, withWizards) ->
     unless @indieSprites
diff --git a/app/models/Level.coffee b/app/models/Level.coffee
index fca1f8249..176b09aa6 100644
--- a/app/models/Level.coffee
+++ b/app/models/Level.coffee
@@ -115,15 +115,5 @@ module.exports = class Level extends CocoModel
         model = CocoModel.getOrMakeModelFromLink link, shouldLoadProjection
         models.push model if model
     else if path is '/'
-      # We also we need to make sure we grab the Wizard ThangType and the Marks. Hackitrooooid!
-      for [type, original] in [
-        ["Highlight", "529f8fdbdacd325127000003"]
-        ["Selection", "52aa5f7520fccb0000000002"]
-        ["Target", "52b32ad97385ec3d03000001"]
-        ["Repair", "52bcc4591f766a891c000003"]
-      ]
-        link = "/db/thang_type/#{original}/version"
-        model = CocoModel.getOrMakeModelFromLink link, shouldLoadProjection
-        models.push model if model
       models.push ThangType.loadUniversalWizard()
     models

From ea406bd3c7e2d9adf19e9b2a80aa91ec2fa7d849 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Thu, 6 Mar 2014 15:52:51 -0800
Subject: [PATCH 097/178] Fixed some event listeners on destroyed loaders.

---
 app/lib/God.coffee         | 2 +-
 app/lib/LevelLoader.coffee | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/app/lib/God.coffee b/app/lib/God.coffee
index f7563517e..3839013a6 100644
--- a/app/lib/God.coffee
+++ b/app/lib/God.coffee
@@ -30,7 +30,7 @@ module.exports = class God
     @createWorld()
 
   fillWorkerPool: =>
-    return unless Worker
+    return unless Worker and not @dead
     @workerPool ?= []
     if @workerPool.length < @maxWorkerPoolSize
       @workerPool.push @createWorker()
diff --git a/app/lib/LevelLoader.coffee b/app/lib/LevelLoader.coffee
index 52865a8b1..18ae9f82f 100644
--- a/app/lib/LevelLoader.coffee
+++ b/app/lib/LevelLoader.coffee
@@ -70,6 +70,7 @@ module.exports = class LevelLoader extends CocoClass
     @session.loaded and ((not @opponentSession) or @opponentSession.loaded)
 
   onSessionLoaded: ->
+    return if @destroyed
     # TODO: maybe have all non versioned models do this? Or make it work to PUT/PATCH to relative urls
     if @session.loaded
       @session.url = -> '/db/level.session/' + @id
@@ -171,6 +172,7 @@ module.exports = class LevelLoader extends CocoClass
     t0 = new Date()
     @spriteSheetsToBuild += 1
     thangType.once 'build-complete', =>
+      return if @destroyed
       @spriteSheetsBuilt += 1
       @notifyProgress()
       console.log "Built", thangType.get('name'), 'after', ((new Date()) - t0), 'ms'

From 1b61b928b0f4945173d41ec17dff01f13647ebbf Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 6 Mar 2014 16:21:06 -0800
Subject: [PATCH 098/178] Couple tweaks to the cocosprite for effect marks.

---
 app/lib/surface/CocoSprite.coffee | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee
index 279ef087b..998fdccda 100644
--- a/app/lib/surface/CocoSprite.coffee
+++ b/app/lib/surface/CocoSprite.coffee
@@ -389,10 +389,11 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     @addMark('bounds').toggle true if @thang?.drawsBounds
     @addMark('shadow').toggle true unless @thangType.get('shadow') is 0
     mark.update() for name, mark of @marks
-#    @thang.effectNames = ['berserk', 'confused', 'controlled',  'cursed', 'fear', 'poison', 'paralyzed', 'regeneration', 'sleep', 'slowed', 'speed']
+#    @thang.effectNames = ['berserk', 'confuse', 'control', 'curse', 'fear', 'poison', 'paralyze', 'regen', 'sleep', 'slow', 'speed']
     @updateEffectMarks() if @thang?.effectNames?.length
     
   updateEffectMarks: ->
+    @thang.effectNames = (e for e in @thang.effectNames when e) # hack because empty strings appear in the array
     return if _.isEqual @thang.effectNames, @previousEffectNames
     for effect in @thang.effectNames
       mark = @addMark effect, @options.floatingLayer, effect
@@ -449,6 +450,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     @labels[name]
 
   addMark: (name, layer, thangType=null) ->
+    console.log 'what are my effects?', @thang.effectNames unless name
     @marks[name] ?= new Mark name: name, sprite: @, camera: @options.camera, layer: layer ? @options.groundLayer, thangType: thangType
     @marks[name]
 

From b6335a30ae89fc70c8508c1db7c6908a42358635 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Thu, 6 Mar 2014 16:32:13 -0800
Subject: [PATCH 099/178] More fixes for empty string array serialization.

---
 app/lib/surface/CocoSprite.coffee | 14 ++++++--------
 app/lib/world/thang_state.coffee  | 14 ++++++++++----
 2 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee
index 998fdccda..daac71ec5 100644
--- a/app/lib/surface/CocoSprite.coffee
+++ b/app/lib/surface/CocoSprite.coffee
@@ -389,31 +389,30 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     @addMark('bounds').toggle true if @thang?.drawsBounds
     @addMark('shadow').toggle true unless @thangType.get('shadow') is 0
     mark.update() for name, mark of @marks
-#    @thang.effectNames = ['berserk', 'confuse', 'control', 'curse', 'fear', 'poison', 'paralyze', 'regen', 'sleep', 'slow', 'speed']
+    #@thang.effectNames = ['berserk', 'confuse', 'control', 'curse', 'fear', 'poison', 'paralyze', 'regen', 'sleep', 'slow', 'speed']
     @updateEffectMarks() if @thang?.effectNames?.length
-    
+
   updateEffectMarks: ->
-    @thang.effectNames = (e for e in @thang.effectNames when e) # hack because empty strings appear in the array
     return if _.isEqual @thang.effectNames, @previousEffectNames
     for effect in @thang.effectNames
       mark = @addMark effect, @options.floatingLayer, effect
       mark.statusEffect = true
       mark.toggle 'on'
       mark.show()
-      
+
     if @previousEffectNames
       for effect in @previousEffectNames
         mark = @marks[effect]
         mark.toggle 'off'
-      
+
     if @thang.effectNames.length > 1 and not @effectInterval
       @rotateEffect()
       @effectInterval = setInterval @rotateEffect, 1500
-      
+
     else if @effectInterval and @thang.effectNames.length <= 1
       @clearInterval @effectInterval
       @effectInterval = null
-      
+
     @previousEffectNames = @thang.effectNames
 
   rotateEffect: =>
@@ -450,7 +449,6 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     @labels[name]
 
   addMark: (name, layer, thangType=null) ->
-    console.log 'what are my effects?', @thang.effectNames unless name
     @marks[name] ?= new Mark name: name, sprite: @, camera: @options.camera, layer: layer ? @options.groundLayer, thangType: thangType
     @marks[name]
 
diff --git a/app/lib/world/thang_state.coffee b/app/lib/world/thang_state.coffee
index 7db97aca6..7ea6a9687 100644
--- a/app/lib/world/thang_state.coffee
+++ b/app/lib/world/thang_state.coffee
@@ -50,9 +50,12 @@ module.exports = class ThangState
       value = @thang.world.getThangByID @specialKeysToValues[specialKey]
     else if type is 'array'
       specialKey = storage[@frameIndex]
-      value = @specialKeysToValues[specialKey]
-      # Remove leading and trailing Group Separators and split by any Record Separators to restore the array of strings
-      value = value.substring(1, value.length - 1).split('\x1E') if value
+      valueString = @specialKeysToValues[specialKey]
+      if valueString and valueString.length > 1
+        # Trim leading Group Separator and trailing Record Separator, split by Record Separators, restore string array.
+        value = valueString.substring(1, valueString.length - 1).split '\x1E'
+      else
+        value = []
     else
       value = storage[@frameIndex]
     value
@@ -135,7 +138,10 @@ module.exports = class ThangState
           storage[frameIndex] = specialKey
         else if type is 'array'
           # We make sure the array keys won't collide with any string keys by using some unprintable characters.
-          value = '\x1D' + value.join('\x1E') + '\x1D'  # Group Separator, Record Separator(s), Group Separator
+          stringPieces = ['\x1D']  # Group Separator
+          for element in value
+            stringPieces.push element, '\x1E'  # Record Separator(s)
+          value = stringPieces.join('')
           specialKey = specialValuesToKeys[value]
           unless specialKey
             specialKey = specialKeysToValues.length

From 5b11e132b2e1ec57c44555f1f0511ab3318cef50 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 6 Mar 2014 17:13:16 -0800
Subject: [PATCH 100/178] Fixed the effect marks so they properly go away.

---
 app/lib/surface/CocoSprite.coffee | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee
index daac71ec5..5c082320b 100644
--- a/app/lib/surface/CocoSprite.coffee
+++ b/app/lib/surface/CocoSprite.coffee
@@ -390,7 +390,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     @addMark('shadow').toggle true unless @thangType.get('shadow') is 0
     mark.update() for name, mark of @marks
     #@thang.effectNames = ['berserk', 'confuse', 'control', 'curse', 'fear', 'poison', 'paralyze', 'regen', 'sleep', 'slow', 'speed']
-    @updateEffectMarks() if @thang?.effectNames?.length
+    @updateEffectMarks() if @thang?.effectNames?.length or @previousEffectNames?.length
 
   updateEffectMarks: ->
     return if _.isEqual @thang.effectNames, @previousEffectNames
@@ -403,7 +403,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     if @previousEffectNames
       for effect in @previousEffectNames
         mark = @marks[effect]
-        mark.toggle 'off'
+        mark.toggle false
 
     if @thang.effectNames.length > 1 and not @effectInterval
       @rotateEffect()

From 40e896868be316ee8e607db5c9a370c6a85c36c6 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Thu, 6 Mar 2014 17:21:24 -0800
Subject: [PATCH 101/178] Fixed CocoSprite getOffset to not apply scale to
 registration points.

---
 app/lib/surface/CocoSprite.coffee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee
index 5c082320b..5173c5141 100644
--- a/app/lib/surface/CocoSprite.coffee
+++ b/app/lib/surface/CocoSprite.coffee
@@ -376,7 +376,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     scale *= @options.resolutionFactor if prop is 'registration'
     pos.x *= scale
     pos.y *= scale
-    if @thang
+    if @thang and prop isnt 'registration'
       scaleFactor = @thang.scaleFactor ? 1
       pos.x *= @thang.scaleFactorX ? scaleFactor
       pos.y *= @thang.scaleFactorY ? scaleFactor

From a4edb76c982bf7eeecb3b03616132feefe6a7f72 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 6 Mar 2014 17:25:40 -0800
Subject: [PATCH 102/178] Fixed a couple of the bugs with marks.

---
 app/lib/surface/CocoSprite.coffee | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee
index 5c082320b..545addaa6 100644
--- a/app/lib/surface/CocoSprite.coffee
+++ b/app/lib/surface/CocoSprite.coffee
@@ -410,13 +410,14 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
       @effectInterval = setInterval @rotateEffect, 1500
 
     else if @effectInterval and @thang.effectNames.length <= 1
-      @clearInterval @effectInterval
+      clearInterval @effectInterval
       @effectInterval = null
 
     @previousEffectNames = @thang.effectNames
 
   rotateEffect: =>
     effects = (m.name for m in _.values(@marks) when m.on and m.statusEffect and m.mark)
+    return unless effects.length
     effects.sort()
     @effectIndex ?= 0
     @effectIndex = (@effectIndex + 1) % effects.length

From 45cd7e31cae2fee22c0870b4b622545f3f0c0d92 Mon Sep 17 00:00:00 2001
From: Michael Schmatz <schmatz@umich.edu>
Date: Thu, 6 Mar 2014 18:48:41 -0800
Subject: [PATCH 103/178] Made simulator level-independent

---
 app/views/play/ladder/my_matches_tab.coffee |  5 +++--
 server/queues/scoring.coffee                | 24 +++++++++++++--------
 2 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
index 00aec7c8c..6b2cf71be 100644
--- a/app/views/play/ladder/my_matches_tab.coffee
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -94,10 +94,11 @@ module.exports = class MyMatchesTabView extends CocoView
     @setRankingButtonText(button, 'ranking')
     success = => @setRankingButtonText(button, 'ranked')
     failure = => @setRankingButtonText(button, 'failed')
-
+    
+    ajaxData = { session: sessionID, levelID: @level.attributes.original, levelMajorVersion: @level.attributes.version.major }
     $.ajax '/queue/scoring', {
       type: 'POST'
-      data: { session: sessionID }
+      data: ajaxData
       success: success
       failure: failure
     }
diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee
index c527f921f..dd2a51030 100644
--- a/server/queues/scoring.coffee
+++ b/server/queues/scoring.coffee
@@ -48,6 +48,9 @@ addPairwiseTaskToQueue = (taskPair, cb) ->
 
 module.exports.createNewTask = (req, res) ->
   requestSessionID = req.body.session
+  requestLevelID = req.body.levelID
+  requestLevelMajorVersion = parseInt(req.body.levelMajorVersion)
+  
   validatePermissions req, requestSessionID, (error, permissionsAreValid) ->
     if err? then return errors.serverError res, "There was an error validating permissions"
     unless permissionsAreValid then return errors.forbidden res, "You do not have the permissions to submit that game to the leaderboard"
@@ -60,7 +63,7 @@ module.exports.createNewTask = (req, res) ->
       updateSessionToSubmit sessionToSubmit, (err, data) ->
         if err? then return errors.serverError res, "There was an error updating the session"
         opposingTeam = calculateOpposingTeam(sessionToSubmit.team)
-        fetchInitialSessionsToRankAgainst opposingTeam, (err, sessionsToRankAgainst) ->
+        fetchInitialSessionsToRankAgainst opposingTeam,requestLevelID, requestLevelMajorVersion, (err, sessionsToRankAgainst) ->
           if err? then return errors.serverError res, "There was an error fetching the sessions to rank against"
 
           taskPairs = generateTaskPairs(sessionsToRankAgainst, sessionToSubmit)
@@ -139,7 +142,10 @@ module.exports.processTaskResult = (req, res) ->
                   opponentID = _.pull(_.keys(newScoresObject), originalSessionID)
                   sessionNewScore = newScoresObject[originalSessionID].totalScore
                   opponentNewScore = newScoresObject[opponentID].totalScore
-                  findNearestBetterSessionID originalSessionID, sessionNewScore, opponentNewScore, opponentID ,opposingTeam, (err, opponentSessionID) ->
+                  
+                  levelOriginalID = levelSession.level.original
+                  levelOriginalMajorVersion = levelSession.level.majorVersion
+                  findNearestBetterSessionID levelOriginalID, levelOriginalMajorVersion, originalSessionID, sessionNewScore, opponentNewScore, opponentID ,opposingTeam, (err, opponentSessionID) ->
                     if err? then return errors.serverError res, "There was an error finding the nearest sessionID!"
                     unless opponentSessionID then return sendResponseObject req, res, {"message":"There were no more games to rank(game is at top!"}
   
@@ -181,7 +187,7 @@ determineIfSessionShouldContinueAndUpdateLog = (sessionID, sessionRank, cb) ->
         cb null, true
 
 
-findNearestBetterSessionID = (sessionID, sessionTotalScore, opponentSessionTotalScore, opponentSessionID, opposingTeam, cb) ->
+findNearestBetterSessionID = (levelOriginalID, levelMajorVersion, sessionID, sessionTotalScore, opponentSessionTotalScore, opponentSessionID, opposingTeam, cb) ->
   retrieveAllOpponentSessionIDs sessionID, (err, opponentSessionIDs) ->
     if err? then return cb err, null
 
@@ -190,8 +196,8 @@ findNearestBetterSessionID = (sessionID, sessionTotalScore, opponentSessionTotal
         $gt:opponentSessionTotalScore
       _id:
         $nin: opponentSessionIDs
-      "level.original": "52d97ecd32362bc86e004e87"
-      "level.majorVersion": 0
+      "level.original": levelOriginalID
+      "level.majorVersion": levelMajorVersion
       submitted: true
       submittedCode:
         $exists: true
@@ -298,16 +304,16 @@ updateSessionToSubmit = (sessionToUpdate, callback) ->
     numberOfLosses: 0
   LevelSession.update {_id: sessionToUpdate._id}, sessionUpdateObject, callback
 
-fetchInitialSessionsToRankAgainst = (opposingTeam, callback) ->
+fetchInitialSessionsToRankAgainst = (opposingTeam, levelID, levelMajorVersion, callback) ->
   console.log "Fetching sessions to rank against for opposing team #{opposingTeam}"
   findParameters =
-    "level.original": "52d97ecd32362bc86e004e87"
-    "level.majorVersion": 0
+    "level.original": levelID
+    "level.majorVersion": levelMajorVersion
     submitted: true
     submittedCode:
       $exists: true
     team: opposingTeam
-
+  
   sortParameters =
     totalScore: 1
 

From 6e47416d242d7d050a0f88136a4c4862cd92fb91 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Thu, 6 Mar 2014 19:09:15 -0800
Subject: [PATCH 104/178] Fixed some level IDs.

---
 app/views/editor/components/main.coffee           | 2 ++
 app/views/play/level/control_bar_view.coffee      | 2 +-
 app/views/play/level/tome/cast_button_view.coffee | 2 +-
 app/views/play/level/tome/tome_view.coffee        | 1 +
 4 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/app/views/editor/components/main.coffee b/app/views/editor/components/main.coffee
index 87a4ed3b6..fdcc55a6e 100644
--- a/app/views/editor/components/main.coffee
+++ b/app/views/editor/components/main.coffee
@@ -18,6 +18,7 @@ module.exports = class ThangComponentEditView extends CocoView
     @callback = options.callback
 
   render: =>
+    return if @destroyed
     for model in [Level, LevelComponent]
       (new model()).on 'schema-loaded', @render unless model.schema?.loaded
     if not @componentCollection
@@ -35,6 +36,7 @@ module.exports = class ThangComponentEditView extends CocoView
     @buildAddComponentTreema()
 
   onComponentsSync: =>
+    return if @destroyed
     @supermodel.addCollection @componentCollection
     @render()
 
diff --git a/app/views/play/level/control_bar_view.coffee b/app/views/play/level/control_bar_view.coffee
index 392eb4ebf..06d689f82 100644
--- a/app/views/play/level/control_bar_view.coffee
+++ b/app/views/play/level/control_bar_view.coffee
@@ -54,7 +54,7 @@ module.exports = class ControlBarView extends View
     c.ladderGame = @ladderGame
     c.homeLink = "/"
     levelID = @level.get('slug')
-    if levelID in ["brawlwood", "brawlwood-tutorial"]
+    if levelID in ["brawlwood", "brawlwood-tutorial", "dungeon-arena"]
       levelID = 'brawlwood' if levelID is 'brawlwood-tutorial'
       c.homeLink = "/play/ladder/" + levelID
     c
diff --git a/app/views/play/level/tome/cast_button_view.coffee b/app/views/play/level/tome/cast_button_view.coffee
index 98c8ab3c8..15d59f194 100644
--- a/app/views/play/level/tome/cast_button_view.coffee
+++ b/app/views/play/level/tome/cast_button_view.coffee
@@ -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 in ['brawlwood', 'brawlwood-tutorial']
+    if @levelID in ['brawlwood', 'brawlwood-tutorial', 'dungeon-arena']
       delay = 90019001
     @setAutocastDelay delay
 
diff --git a/app/views/play/level/tome/tome_view.coffee b/app/views/play/level/tome/tome_view.coffee
index f7be355f6..0d18a9f1d 100644
--- a/app/views/play/level/tome/tome_view.coffee
+++ b/app/views/play/level/tome/tome_view.coffee
@@ -130,6 +130,7 @@ module.exports = class TomeView extends View
         unless method.cloneOf
           skipProtectAPI = @getQueryVariable("skip_protect_api") is "true" or @options.levelID isnt 'brawlwood'
           skipProtectAPI = true  # gah, it's so slow :( and somehow still affects simulation
+          #skipProtectAPI = false if @options.levelID is 'dungeon-arena'
           skipFlow = @getQueryVariable("skip_flow") is "true" or @options.levelID is 'brawlwood'
           spell = @spells[spellKey] = new Spell programmableMethod: method, spellKey: spellKey, pathComponents: pathPrefixComponents.concat(pathComponents), session: @options.session, supermodel: @supermodel, skipFlow: skipFlow, skipProtectAPI: skipProtectAPI, worker: @worker
     for thangID, spellKeys of @thangSpells

From d14f8623595a93c036fc4b4231b56016e84a2ec3 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Fri, 7 Mar 2014 11:23:06 -0800
Subject: [PATCH 105/178] Ladder view can now be linked to to play against a
 specific team.

---
 app/views/play/ladder_view.coffee | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/app/views/play/ladder_view.coffee b/app/views/play/ladder_view.coffee
index 8f6a046de..723a7910d 100644
--- a/app/views/play/ladder_view.coffee
+++ b/app/views/play/ladder_view.coffee
@@ -66,6 +66,7 @@ module.exports = class LadderView extends RootView
     @insertSubView(@ladderTab = new LadderTabView({}, @level, @sessions))
     @insertSubView(@myMatchesTab = new MyMatchesTabView({}, @level, @sessions))
     setInterval(@fetchSessionsAndRefreshViews.bind(@), 10000)
+    @showPlayModal(document.location.hash[1..]) if document.location.hash and @sessions.loaded
 
   fetchSessionsAndRefreshViews: ->
     @sessions.fetch({"success": @refreshViews})
@@ -112,8 +113,9 @@ module.exports = class LadderView extends RootView
     $("#simulation-status-text").text @simulationStatus
 
   onClickPlayButton: (e) ->
-    button = $(e.target).closest('.play-button')
-    teamID = button.data('team')
+    @showPlayModal($(e.target).closest('.play-button').data('team'))
+    
+  showPlayModal: (teamID) ->
     session = (s for s in @sessions.models when s.get('team') is teamID)[0]
     modal = new LadderPlayModal({}, @level, session, teamID)
     @openModalView modal

From 5274f22467293101147095bed8d512f18d6dab50 Mon Sep 17 00:00:00 2001
From: Shrihari <gfxindia@gmail.com>
Date: Sat, 8 Mar 2014 01:10:12 +0530
Subject: [PATCH 106/178] Fixed Spell Debug View width bug

---
 app/styles/play/level/tome/spell_debug.sass       | 1 +
 app/views/play/level/tome/spell_debug_view.coffee | 4 +++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/app/styles/play/level/tome/spell_debug.sass b/app/styles/play/level/tome/spell_debug.sass
index d0f97a28f..e02326b55 100644
--- a/app/styles/play/level/tome/spell_debug.sass
+++ b/app/styles/play/level/tome/spell_debug.sass
@@ -3,6 +3,7 @@
 .spell-debug-view
   position: absolute
   z-index: 9001
+  min-width: 250px
   max-width: 400px
   padding: 10px
   background: transparent url(/images/level/popover_background.png)
diff --git a/app/views/play/level/tome/spell_debug_view.coffee b/app/views/play/level/tome/spell_debug_view.coffee
index 5f4cfdd30..c35314932 100644
--- a/app/views/play/level/tome/spell_debug_view.coffee
+++ b/app/views/play/level/tome/spell_debug_view.coffee
@@ -61,7 +61,9 @@ module.exports = class DebugView extends View
       @variableChain = chain
       offsetX = e.domEvent.offsetX ? e.clientX - $(e.domEvent.target).offset().left
       offsetY = e.domEvent.offsetY ? e.clientY - $(e.domEvent.target).offset().top
-      @pos = {left: offsetX + 50, top: offsetY + 50}
+      w = $(document).width()
+      offsetX = w - $(e.domEvent.target).offset().left - 300 if e.clientX + 300 > w
+      @pos = {left: offsetX + 50, top: offsetY + 20}
       @markerRange = new Range pos.row, start, pos.row, end
     else
       @variableChain = @markerRange = null

From 610fc0694bbf6b2750d64e10d7284b52dde8c111 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Fri, 7 Mar 2014 11:57:15 -0800
Subject: [PATCH 107/178] Turning off view caching by default now. Should help
 lower the memory footprint.

---
 app/lib/Router.coffee           | 2 +-
 app/views/kinds/CocoView.coffee | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/lib/Router.coffee b/app/lib/Router.coffee
index 435fdb7d4..db70b8c74 100644
--- a/app/lib/Router.coffee
+++ b/app/lib/Router.coffee
@@ -90,7 +90,7 @@ module.exports = class CocoRouter extends Backbone.Router
       @cache[route].fromCache = true
       return @cache[route]
     view = @getView(route)
-    @cache[route] = view unless view and view.cache is false
+    @cache[route] = view if view?.cache
     return view
     
   routeDirectly: (path, args) ->
diff --git a/app/views/kinds/CocoView.coffee b/app/views/kinds/CocoView.coffee
index 2811318c6..dbdb14146 100644
--- a/app/views/kinds/CocoView.coffee
+++ b/app/views/kinds/CocoView.coffee
@@ -10,7 +10,7 @@ makeScopeName = -> "view-scope-#{classCount++}"
 
 module.exports = class CocoView extends Backbone.View
   startsLoading: false
-  cache: true # signals to the router to keep this view around
+  cache: false # signals to the router to keep this view around
   template: -> ''
 
   events:

From cf2a0a999e63e8e45ea00d03d454d9440ab4e7da Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Fri, 7 Mar 2014 11:57:31 -0800
Subject: [PATCH 108/178] Set up the ladder play modal to point to the tutorial
 level dynamically.

---
 app/templates/play/ladder/play_modal.jade | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/templates/play/ladder/play_modal.jade b/app/templates/play/ladder/play_modal.jade
index 6c1cd22d6..5e7953896 100644
--- a/app/templates/play/ladder/play_modal.jade
+++ b/app/templates/play/ladder/play_modal.jade
@@ -8,7 +8,7 @@ block modal-body-content
   p.tutorial-suggestion
     span Not sure what's going on?
     |  
-    a(href="/play/level/brawlwood-tutorial") Play the tutorial first.
+    a(href="/play/level/#{levelID}-tutorial") Play the tutorial first.
 
   a(href="/play/level/#{levelID}?team=#{teamID}")
     div.play-option

From 4e24e2a2442ef04a3c8b9ddfbf844727b93cf874 Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Fri, 7 Mar 2014 12:10:25 -0800
Subject: [PATCH 109/178] Update ru.coffee

---
 app/locale/ru.coffee | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 51f6d1a7e..dcc68a5a2 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     tome_available_spells: "Доступные заклинания"
     hud_continue: "Продолжить (нажмите Shift+Пробел)"
     spell_saved: "Заклинание сохранено"
-#    skip_tutorial: "Skip (esc)"
+    skip_tutorial: "Пропуск (Esc)"y
 
   admin:
     av_title: "Админ панель"
@@ -298,7 +298,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     practices_title: "Лучшие уважаемые практики"
     practices_description: "Это наши обещания тебе, игрок, менее юридическим языком."
     privacy_title: "Конфиденциальность"
-    privacy_description: "Мы не будем продавать какой-либо личной информации. Мы намерены заработать деньги с помощью рекрутинга в конечном счете, но будьте уверены, мы не будем распространять вашу личную информацию заинтересованным компаниям без вашего явного согласия."
+    privacy_description: "Мы не будем продавать какой-либо личной информации. Мы намерены заработать деньги с помощью рекрутинга в конечном счёте, но будьте уверены, мы не будем распространять вашу личную информацию заинтересованным компаниям без вашего явного согласия."
     security_title: "Безопасность"
     security_description: "Мы стремимся сохранить вашу личную информацию в безопасности. Как проект с открытым исходным кодом, наш сайт в свободном доступе для всех для пересмотра и совершенствования систем безопасности."
     email_title: "Email"

From 517ef8611bc4eabb7d2e833534cb5286c785d2a1 Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Fri, 7 Mar 2014 12:13:15 -0800
Subject: [PATCH 110/178] Update ru.coffee

---
 app/locale/ru.coffee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index dcc68a5a2..0ee54cb73 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     tome_available_spells: "Доступные заклинания"
     hud_continue: "Продолжить (нажмите Shift+Пробел)"
     spell_saved: "Заклинание сохранено"
-    skip_tutorial: "Пропуск (Esc)"y
+    skip_tutorial: "Пропуск (Esc)"
 
   admin:
     av_title: "Админ панель"

From d8d917ecf9e52b742ee66ed2576ec8353fb0c6a0 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Fri, 7 Mar 2014 12:15:16 -0800
Subject: [PATCH 111/178] Set up better teardown for the ladder view.

---
 app/lib/CocoClass.coffee           | 1 +
 app/lib/simulator/Simulator.coffee | 7 ++++++-
 app/views/kinds/CocoView.coffee    | 1 +
 app/views/play/ladder_view.coffee  | 7 ++++++-
 4 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/app/lib/CocoClass.coffee b/app/lib/CocoClass.coffee
index 22dc25f64..67a8e4cac 100644
--- a/app/lib/CocoClass.coffee
+++ b/app/lib/CocoClass.coffee
@@ -20,6 +20,7 @@ module.exports = class CocoClass
   destroy: ->
     # teardown subscriptions, prevent new ones
     @stopListening?()
+    @off()
     @unsubscribeAll()
     @stopListeningToShortcuts()
     @[key] = undefined for key of @
diff --git a/app/lib/simulator/Simulator.coffee b/app/lib/simulator/Simulator.coffee
index f92bccb98..f41c0acb3 100644
--- a/app/lib/simulator/Simulator.coffee
+++ b/app/lib/simulator/Simulator.coffee
@@ -10,6 +10,11 @@ module.exports = class Simulator
     @trigger 'statusUpdate', 'Starting simulation!'
     @retryDelayInSeconds = 10
     @taskURL = '/queue/scoring'
+    
+  destroy: ->
+    @off()
+    @cleanupSimulation()
+    # TODO: More teardown?
 
   fetchAndSimulateTask: =>
     @trigger 'statusUpdate', 'Fetching simulation data!'
@@ -99,7 +104,7 @@ module.exports = class Simulator
     @fetchAndSimulateTask()
 
   cleanupSimulation: ->
-    @god.destroy()
+    @god?.destroy()
     @god = null
     @world = null
     @level = null
diff --git a/app/views/kinds/CocoView.coffee b/app/views/kinds/CocoView.coffee
index dbdb14146..806a2d25c 100644
--- a/app/views/kinds/CocoView.coffee
+++ b/app/views/kinds/CocoView.coffee
@@ -37,6 +37,7 @@ module.exports = class CocoView extends Backbone.View
 
   destroy: ->
     @stopListening()
+    @off()
     @stopListeningToShortcuts()
     @undelegateEvents() # removes both events and subs
     view.destroy() for id, view of @subviews
diff --git a/app/views/play/ladder_view.coffee b/app/views/play/ladder_view.coffee
index 723a7910d..81e2f6558 100644
--- a/app/views/play/ladder_view.coffee
+++ b/app/views/play/ladder_view.coffee
@@ -65,7 +65,7 @@ module.exports = class LadderView extends RootView
     return if @startsLoading
     @insertSubView(@ladderTab = new LadderTabView({}, @level, @sessions))
     @insertSubView(@myMatchesTab = new MyMatchesTabView({}, @level, @sessions))
-    setInterval(@fetchSessionsAndRefreshViews.bind(@), 10000)
+    @refreshInterval = setInterval(@fetchSessionsAndRefreshViews.bind(@), 10000)
     @showPlayModal(document.location.hash[1..]) if document.location.hash and @sessions.loaded
 
   fetchSessionsAndRefreshViews: ->
@@ -119,3 +119,8 @@ module.exports = class LadderView extends RootView
     session = (s for s in @sessions.models when s.get('team') is teamID)[0]
     modal = new LadderPlayModal({}, @level, session, teamID)
     @openModalView modal
+    
+  destroy: ->
+    clearInterval @refreshInterval
+    @simulator.destroy()
+    super()

From 317ae5cc329a1318874468eddebd2d99f6debd23 Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Fri, 7 Mar 2014 12:17:32 -0800
Subject: [PATCH 112/178] Update scribe.jade

---
 app/templates/contribute/scribe.jade | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/app/templates/contribute/scribe.jade b/app/templates/contribute/scribe.jade
index 9bd404ad2..eafab49b6 100644
--- a/app/templates/contribute/scribe.jade
+++ b/app/templates/contribute/scribe.jade
@@ -16,7 +16,7 @@ block content
         span  
         span(data-i18n="classes.scribe_title_description") (Article Editor)
       p
-        span(data-i18n="account_settings.scribe_introduction_pref")
+        span(data-i18n="contribute.scribe_introduction_pref")
           | CodeCombat isn't just going to be a bunch of levels.
           | It will also include a resource for knowledge, a wiki of programming concepts that levels can hook into.
           | That way rather than each Artisan having to describe in detail what a comparison operator is, they
@@ -24,7 +24,7 @@ block content
           | Something along the lines of what the 
         a(href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide", data-i18n="contribute.scribe_introduction_url_mozilla")
           | Mozilla Developer Network 
-        span(data-i18n="account_settings.scribe_introduction_suf")  
+        span(data-i18n="contribute.scribe_introduction_suf")  
           | has built. If your idea of fun is articulating the concepts of programming in Markdown form,
           | then this class might be for you.
   
@@ -77,4 +77,4 @@ block content
           li mattinsler
           
 
-    div.clearfix
\ No newline at end of file
+    div.clearfix

From b002ae376b06f9e91cf59a5f7c912b73e3640a20 Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Fri, 7 Mar 2014 12:19:14 -0800
Subject: [PATCH 113/178] Update counselor.jade

---
 app/templates/contribute/counselor.jade | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/templates/contribute/counselor.jade b/app/templates/contribute/counselor.jade
index 821a86694..36a79d8cc 100644
--- a/app/templates/contribute/counselor.jade
+++ b/app/templates/contribute/counselor.jade
@@ -38,7 +38,7 @@ block content
   
       h4(data-i18n="contribute.how_to_join") How to Join 
       p 
-        a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="contact_us_url")
+        a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="contribute.contact_us_url")
           | Contact us
         span , 
         span(data-i18n="contribute.counselor_join_desc")
@@ -46,4 +46,4 @@ block content
           | be interested in doing. We'll put you in our contact list and be in touch
           | when we could use advice (not too often).
 
-    div.clearfix
\ No newline at end of file
+    div.clearfix

From 535881b6373f02e8f22dfa083a8da7196de50a25 Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Fri, 7 Mar 2014 12:20:17 -0800
Subject: [PATCH 114/178] Update ambassador.jade

---
 app/templates/contribute/ambassador.jade | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/templates/contribute/ambassador.jade b/app/templates/contribute/ambassador.jade
index ef17d2735..dc1048ac6 100644
--- a/app/templates/contribute/ambassador.jade
+++ b/app/templates/contribute/ambassador.jade
@@ -31,7 +31,7 @@ block content
   
       h4(data-i18n="contribute.how_to_join") How to Join
       p
-        a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="contact_us_url")
+        a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="contribute.contact_us_url")
           | Contact us
         span , 
         span(data-i18n="contribute.ambassador_join_desc")

From 16f2379af9afce26e287c9baa6b36a26acd5c29e Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Fri, 7 Mar 2014 12:27:12 -0800
Subject: [PATCH 115/178] Update ru.coffee

---
 app/locale/ru.coffee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 0ee54cb73..1fdd72d87 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -400,7 +400,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     more_about_adventurer: "Узнать больше о том, как стать Искателем приключений"
     adventurer_subscribe_desc: "Получать email-ы при появлении новых уровней для тестирования."
     scribe_summary_pref: "CodeCombat будет не просто кучей уровней. Он также будет ресурсом знаний в области программирования, к которому игроки могут присоединиться. Таким образом, каждый Ремесленник может ссылаться на подробную статью для назидания игрока: документация сродни тому, что создана "
-    scribe_summary_sufx: ". Если вам нравится объяснять концепции программирования, этот класс для вас."
+    scribe_summary_suf: ". Если вам нравится объяснять концепции программирования, этот класс для вас."
     scribe_introduction_pref: "CodeCombat будет не просто кучей уровней. Он также включает в себя ресурс для познания, вики концепций программирования, которые уровни могут включать. Таким образом, вместо того, чтобы каждому Ремесленнику необходимо было подробно описывать, что такое оператор сравнения, они могут просто связать их уровень с уже написанной в назидание игрокам статьёй, описывающей их. Что-то по аналогии с "
     scribe_introduction_url_mozilla: "Mozilla Developer Network"
     scribe_introduction_suf: ". Если ваше представление о веселье это формулирование концепций программирования в форме Markdown, этот класс для вас."

From a3afa802d9eb5068af4e9b3239b74663d4f69ea9 Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Fri, 7 Mar 2014 12:33:18 -0800
Subject: [PATCH 116/178] Update ru.coffee

---
 app/locale/ru.coffee | 30 ++----------------------------
 1 file changed, 2 insertions(+), 28 deletions(-)

diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 1fdd72d87..8f2189174 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -129,6 +129,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     new_password: "Новый пароль"
     new_password_verify: "Подтверждение пароля"
     email_subscriptions: "Email-подписки"
+    email_notifications: "Уведомления"
     email_announcements: "Оповещения"
     email_notifications_description: "Получать периодические уведомления для вашего аккаунта."
     email_announcements_description: "Получать email-оповещения о последних новостях CodeCombat."
@@ -429,31 +430,4 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     ambassador_subscribe_desc: "Получать email-ы о разработке мультиплеера и обновлениях в системе поддержки."
     counselor_summary: "Ни одна из вышеупомянутых ролей не соответствует тому, в чём вы заинтересованы? Не волнуйтесь, мы в поисках тех, кто хочет приложить руку к разработке CodeCombat! Если вы заинтересованы в обучении, разработке игр, управлением проектами с открытым исходным кодом, или в чём-нибудь ещё, что, как вы думаете, будет актуально для нас, то этот класс для вас."
     counselor_introduction_1: "У вас есть жизненный опыт? Другая точка зрения на вещи, которые могут помочь нам решить, как формировать CodeCombat? Из всех этих ролей, эта, возможно, займёт меньше всего времени, но по отдельности, вы можете сделать наибольшие изменения. Мы в поисках морщинистых мудрецов, особенно в таких областях, как: обучение, разработка игр, управление проектами с открытым исходным кодом, технической рекрутинг, предпринимательство или дизайн."
-    counselor_introduction_2: "Или действительно всё, что имеет отношение к развитию CodeCombat. Если у вас есть знания и вы хотите поделиться ими, чтобы помочь вырастить этот проект, то этот класс для вас."
-    counselor_attribute_1: "Опыт, в любой из областей выше, или в том, что, как вы думаете, может быть полезным."
-    counselor_attribute_2: "Немного свободного времени!"
-    counselor_join_desc: "расскажите нам немного о себе, чем вы занимались и чем хотели бы заниматься. Мы поместим вас в наш список контактов и выйдем на связь, когда нам понадобится совет(не слишком часто)."
-    more_about_counselor: "Узнать больше о том, как стать Советником"
-    changes_auto_save: "Изменения сохраняются автоматически при переключении флажков."
-    diligent_scribes: "Наши старательные Писари:"
-    powerful_archmages: "Наши могущественные Архимаги:"
-    creative_artisans: "Наши творческие Ремесленники:"
-    brave_adventurers: "Наши отважные Искатели приключений:"
-    translating_diplomats: "Наши переводящие Дипломаты:"
-    helpful_ambassadors: "Наши полезные Послы:"
-
-  classes:
-    archmage_title: "Архимаг"
-    archmage_title_description: "(программист)"
-    artisan_title: "Ремесленник"
-    artisan_title_description: "(создатель уровней)"
-    adventurer_title: "Искатель приключений"
-    adventurer_title_description: "(тестировщик уровней)"
-    scribe_title: "Писарь"
-    scribe_title_description: "(редактор статей)"
-    diplomat_title: "Дипломат"
-    diplomat_title_description: "(переводчик)"
-    ambassador_title: "Посол"
-    ambassador_title_description: "(поддержка)"
-    counselor_title: "Советник"
-    counselor_title_description: "(эксперт/учитель)"
+    counselor_introduction_2: "Или действительно всё, что имеет отношение к развитию CodeCombat

From 683c578dcbc0e5bcffff0d38b1c313b09a514e85 Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Fri, 7 Mar 2014 12:36:17 -0800
Subject: [PATCH 117/178] Fix lolwtf deleting

---
 app/locale/ru.coffee | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 8f2189174..36bcf1ac1 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -430,4 +430,31 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     ambassador_subscribe_desc: "Получать email-ы о разработке мультиплеера и обновлениях в системе поддержки."
     counselor_summary: "Ни одна из вышеупомянутых ролей не соответствует тому, в чём вы заинтересованы? Не волнуйтесь, мы в поисках тех, кто хочет приложить руку к разработке CodeCombat! Если вы заинтересованы в обучении, разработке игр, управлением проектами с открытым исходным кодом, или в чём-нибудь ещё, что, как вы думаете, будет актуально для нас, то этот класс для вас."
     counselor_introduction_1: "У вас есть жизненный опыт? Другая точка зрения на вещи, которые могут помочь нам решить, как формировать CodeCombat? Из всех этих ролей, эта, возможно, займёт меньше всего времени, но по отдельности, вы можете сделать наибольшие изменения. Мы в поисках морщинистых мудрецов, особенно в таких областях, как: обучение, разработка игр, управление проектами с открытым исходным кодом, технической рекрутинг, предпринимательство или дизайн."
-    counselor_introduction_2: "Или действительно всё, что имеет отношение к развитию CodeCombat
+    counselor_introduction_2: "Или действительно всё, что имеет отношение к развитию CodeCombat. Если у вас есть знания и вы хотите поделиться ими, чтобы помочь вырастить этот проект, то этот класс для вас."
+    counselor_attribute_1: "Опыт, в любой из областей выше, или в том, что, как вы думаете, может быть полезным."
+    counselor_attribute_2: "Немного свободного времени!"
+    counselor_join_desc: "расскажите нам немного о себе, чем вы занимались и чем хотели бы заниматься. Мы поместим вас в наш список контактов и выйдем на связь, когда нам понадобится совет(не слишком часто)."
+    more_about_counselor: "Узнать больше о том, как стать Советником"
+    changes_auto_save: "Изменения сохраняются автоматически при переключении флажков."
+    diligent_scribes: "Наши старательные Писари:"
+    powerful_archmages: "Наши могущественные Архимаги:"
+    creative_artisans: "Наши творческие Ремесленники:"
+    brave_adventurers: "Наши отважные Искатели приключений:"
+    translating_diplomats: "Наши переводящие Дипломаты:"
+    helpful_ambassadors: "Наши полезные Послы:"
+
+  classes:
+    archmage_title: "Архимаг"
+    archmage_title_description: "(программист)"
+    artisan_title: "Ремесленник"
+    artisan_title_description: "(создатель уровней)"
+    adventurer_title: "Искатель приключений"
+    adventurer_title_description: "(тестировщик уровней)"
+    scribe_title: "Писарь"
+    scribe_title_description: "(редактор статей)"
+    diplomat_title: "Дипломат"
+    diplomat_title_description: "(переводчик)"
+    ambassador_title: "Посол"
+    ambassador_title_description: "(поддержка)"
+    counselor_title: "Советник"
+    counselor_title_description: "(эксперт/учитель)"

From be034855385fe83b706385547a9755a5e04fa32b Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Fri, 7 Mar 2014 12:58:17 -0800
Subject: [PATCH 118/178] Set up the ladder play modal to be more forthright
 getting new players to play the tutorial.

---
 app/styles/play/ladder/play_modal.sass    |   7 ++
 app/templates/play/ladder/play_modal.jade | 119 ++++++++++++----------
 app/views/play/ladder/play_modal.coffee   |  17 ++++
 3 files changed, 88 insertions(+), 55 deletions(-)

diff --git a/app/styles/play/ladder/play_modal.sass b/app/styles/play/ladder/play_modal.sass
index 7d87d475b..465052114 100644
--- a/app/styles/play/ladder/play_modal.sass
+++ b/app/styles/play/ladder/play_modal.sass
@@ -1,7 +1,14 @@
 #ladder-play-modal
+  #noob-view p
+    font-size: 30px
+  
+  #skip-tutorial-button
+    font-size: 16px
+  
   .tutorial-suggestion
     text-align: center
     font-size: 18px
+    margin: 10px 0 30px
   
   .play-option
     margin-bottom: 15px
diff --git a/app/templates/play/ladder/play_modal.jade b/app/templates/play/ladder/play_modal.jade
index 5e7953896..25d492b6f 100644
--- a/app/templates/play/ladder/play_modal.jade
+++ b/app/templates/play/ladder/play_modal.jade
@@ -5,68 +5,77 @@ block modal-header-content
 
 block modal-body-content
   
-  p.tutorial-suggestion
-    span Not sure what's going on?
-    |  
-    a(href="/play/level/#{levelID}-tutorial") Play the tutorial first.
+  div#noob-view.secret
+    a(href="/play/level/#{levelID}-tutorial").btn.btn-success.btn-block.btn-lg
+      p
+        strong Play Tutorial
+      span Recommended if you've never played before
+    span.btn.btn-primary.btn-block.btn-lg#skip-tutorial-button Skip Tutorial
 
-  a(href="/play/level/#{levelID}?team=#{teamID}")
-    div.play-option
-      img(src=myPortrait).my-icon.only-one
-      img(src="/images/pages/play/ladder/"+teamID+"_ladder_tutorial.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one
-      img(src=genericPortrait).opponent-icon
-      img(src="/images/pages/play/ladder/"+otherTeamID+"_ladder_tutorial.png", style="border: 1px solid #{opponentTeamColor}; background: #{opponentTeamBackgroundColor}").opponent-team-icon.img-circle
-      div.my-name.name-label.only-one
-        span= myName
-      div.opponent-name.name-label
-        span Simple AI
-      div.difficulty
-        span Warmup
-      div.vs VS
+  div#normal-view
   
-  if challengers.easy
-    a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.easy.sessionID}")
-      div.play-option.easy-option
+    p.tutorial-suggestion
+      strong Not sure what's going on?
+      |  
+      a(href="/play/level/#{levelID}-tutorial") Play the tutorial first.
+  
+    a(href="/play/level/#{levelID}?team=#{teamID}")
+      div.play-option
         img(src=myPortrait).my-icon.only-one
-        img(src="/images/pages/play/ladder/"+teamID+"_ladder_easy.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one
-        img(src=challengers.easy.opponentImageSource||genericPortrait).opponent-icon
-        img(src="/images/pages/play/ladder/"+otherTeamID+"_ladder_easy.png", style="border: 1px solid #{opponentTeamColor}; background: #{opponentTeamBackgroundColor}").opponent-team-icon.img-circle
+        img(src="/images/pages/play/ladder/"+teamID+"_ladder_tutorial.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one
+        img(src=genericPortrait).opponent-icon
+        img(src="/images/pages/play/ladder/"+otherTeamID+"_ladder_tutorial.png", style="border: 1px solid #{opponentTeamColor}; background: #{opponentTeamBackgroundColor}").opponent-team-icon.img-circle
         div.my-name.name-label.only-one
           span= myName
         div.opponent-name.name-label
-          span= challengers.easy.opponentName
+          span Simple AI
         div.difficulty
-          span Easy
-        div.vs VS
-
-  if challengers.medium
-    a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.medium.sessionID}")
-      div.play-option.medium-option
-        img(src=myPortrait).my-icon.only-one
-        img(src="/images/pages/play/ladder/"+teamID+"_ladder_medium.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one
-        img(src=challengers.medium.opponentImageSource||genericPortrait).opponent-icon
-        img(src="/images/pages/play/ladder/"+otherTeamID+"_ladder_medium.png", style="border: 1px solid #{opponentTeamColor}; background: #{opponentTeamBackgroundColor}").opponent-team-icon.img-circle
-        div.my-name.name-label.only-one
-          span= myName
-        div.opponent-name.name-label
-          span= challengers.medium.opponentName
-        div.difficulty
-          span Medium
-        div.vs VS
-
-  if challengers.hard
-    a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.hard.sessionID}")
-      div.play-option.hard-option
-        img(src=myPortrait).my-icon.only-one
-        img(src="/images/pages/play/ladder/"+teamID+"_ladder_hard.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one
-        img(src=challengers.hard.opponentImageSource||genericPortrait).opponent-icon
-        img(src="/images/pages/play/ladder/"+otherTeamID+"_ladder_hard.png", style="border: 1px solid #{opponentTeamColor}; background: #{opponentTeamBackgroundColor}").opponent-team-icon.img-circle
-        div.my-name.name-label.only-one
-          span= myName
-        div.opponent-name.name-label
-          span= challengers.hard.opponentName
-        div.difficulty
-          span Hard
+          span Warmup
         div.vs VS
+    
+    if challengers.easy
+      a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.easy.sessionID}")
+        div.play-option.easy-option
+          img(src=myPortrait).my-icon.only-one
+          img(src="/images/pages/play/ladder/"+teamID+"_ladder_easy.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one
+          img(src=challengers.easy.opponentImageSource||genericPortrait).opponent-icon
+          img(src="/images/pages/play/ladder/"+otherTeamID+"_ladder_easy.png", style="border: 1px solid #{opponentTeamColor}; background: #{opponentTeamBackgroundColor}").opponent-team-icon.img-circle
+          div.my-name.name-label.only-one
+            span= myName
+          div.opponent-name.name-label
+            span= challengers.easy.opponentName
+          div.difficulty
+            span Easy
+          div.vs VS
+  
+    if challengers.medium
+      a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.medium.sessionID}")
+        div.play-option.medium-option
+          img(src=myPortrait).my-icon.only-one
+          img(src="/images/pages/play/ladder/"+teamID+"_ladder_medium.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one
+          img(src=challengers.medium.opponentImageSource||genericPortrait).opponent-icon
+          img(src="/images/pages/play/ladder/"+otherTeamID+"_ladder_medium.png", style="border: 1px solid #{opponentTeamColor}; background: #{opponentTeamBackgroundColor}").opponent-team-icon.img-circle
+          div.my-name.name-label.only-one
+            span= myName
+          div.opponent-name.name-label
+            span= challengers.medium.opponentName
+          div.difficulty
+            span Medium
+          div.vs VS
+  
+    if challengers.hard
+      a(href="/play/level/#{levelID}?team=#{teamID}&opponent=#{challengers.hard.sessionID}")
+        div.play-option.hard-option
+          img(src=myPortrait).my-icon.only-one
+          img(src="/images/pages/play/ladder/"+teamID+"_ladder_hard.png", style="border: 1px solid #{teamColor}; background: #{teamBackgroundColor}").my-team-icon.img-circle.only-one
+          img(src=challengers.hard.opponentImageSource||genericPortrait).opponent-icon
+          img(src="/images/pages/play/ladder/"+otherTeamID+"_ladder_hard.png", style="border: 1px solid #{opponentTeamColor}; background: #{opponentTeamBackgroundColor}").opponent-team-icon.img-circle
+          div.my-name.name-label.only-one
+            span= myName
+          div.opponent-name.name-label
+            span= challengers.hard.opponentName
+          div.difficulty
+            span Hard
+          div.vs VS
 
 block modal-footer
\ No newline at end of file
diff --git a/app/views/play/ladder/play_modal.coffee b/app/views/play/ladder/play_modal.coffee
index 28f689b14..e5d83fc3b 100644
--- a/app/views/play/ladder/play_modal.coffee
+++ b/app/views/play/ladder/play_modal.coffee
@@ -10,6 +10,10 @@ module.exports = class LadderPlayModal extends View
   template: template
   closeButton: true
   startsLoading: true
+  @shownTutorialButton: false
+  
+  events:
+    'click #skip-tutorial-button': 'hideTutorialButtons'
 
   constructor: (options, @level, @session, @team) ->
     super(options)
@@ -56,6 +60,7 @@ module.exports = class LadderPlayModal extends View
   finishRendering: ->
     @startsLoading = false
     @render()
+    @maybeShowTutorialButtons()
 
   getRenderData: ->
     ctx = super()
@@ -87,6 +92,18 @@ module.exports = class LadderPlayModal extends View
 
     ctx.myName = me.get('name') || 'Newcomer'
     ctx
+
+  maybeShowTutorialButtons: ->
+    return if @session or LadderPlayModal.shownTutorialButton
+    @$el.find('#normal-view').addClass('secret')
+    @$el.find('.modal-header').addClass('secret')
+    @$el.find('#noob-view').removeClass('secret')
+    LadderPlayModal.shownTutorialButton = true
+
+  hideTutorialButtons: ->
+    @$el.find('#normal-view').removeClass('secret')
+    @$el.find('.modal-header').removeClass('secret')
+    @$el.find('#noob-view').addClass('secret')
     
   # Choosing challengers
 

From 17231bce06f7c37adfc89f462ea9a9d75c1241b8 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Fri, 7 Mar 2014 13:13:58 -0800
Subject: [PATCH 119/178] Added showsGuide and type properties to level.

---
 app/views/editor/level/settings_tab_view.coffee | 7 ++++++-
 server/levels/level_schema.coffee               | 3 ++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/app/views/editor/level/settings_tab_view.coffee b/app/views/editor/level/settings_tab_view.coffee
index 4e2518be6..7a1290db1 100644
--- a/app/views/editor/level/settings_tab_view.coffee
+++ b/app/views/editor/level/settings_tab_view.coffee
@@ -8,7 +8,12 @@ module.exports = class SettingsTabView extends View
   id: 'editor-level-settings-tab-view'
   className: 'tab-pane'
   template: template
-  editableSettings: ['name', 'description', 'documentation', 'nextLevel', 'background', 'victory', 'i18n', 'icon', 'goals']  # not thangs or scripts or the backend stuff
+  
+  # not thangs or scripts or the backend stuff
+  editableSettings: [
+    'name', 'description', 'documentation', 'nextLevel', 'background', 'victory', 'i18n', 'icon', 'goals',
+    'type', 'showsGuide'
+  ]
 
   subscriptions:
     'level-loaded': 'onLevelLoaded'
diff --git a/server/levels/level_schema.coffee b/server/levels/level_schema.coffee
index d0d448267..cbfb84497 100644
--- a/server/levels/level_schema.coffee
+++ b/server/levels/level_schema.coffee
@@ -226,7 +226,8 @@ _.extend LevelSchema.properties,
   i18n: {type: "object", format: 'i18n', props: ['name', 'description'], description: "Help translate this level"}
   icon: { type: 'string', format: 'image-file', title: 'Icon' }
   goals: c.array {title: 'Goals', description: 'An array of goals which are visible to the player and can trigger scripts.'}, GoalSchema
-
+  type: c.shortString(title: "Type", description: "What kind of level this is.", "enum": ['campaign', 'ladder'])
+  showsGuide: c.shortString(title: "Shows Guide", description: "If the guide is shown at the beginning of the level.", "enum": ['first-time', 'always'])
 
 c.extendBasicProperties LevelSchema, 'level'
 c.extendSearchableProperties LevelSchema

From 2f68e64dc5d728ea96203f0fc9fa3c7474c6f090 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Fri, 7 Mar 2014 13:14:27 -0800
Subject: [PATCH 120/178] Almost forgot to add to the level handler the new
 properties.

---
 server/levels/level_handler.coffee | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/server/levels/level_handler.coffee b/server/levels/level_handler.coffee
index 0cf0a2066..da79be8d6 100644
--- a/server/levels/level_handler.coffee
+++ b/server/levels/level_handler.coffee
@@ -20,6 +20,8 @@ LevelHandler = class LevelHandler extends Handler
     'i18n'
     'icon'
     'goals'
+    'type'
+    'showsGuide'
   ]
 
   postEditableProperties: ['name']

From 990a2e34e56394ee93f6d5238226b6899ccc0d7f Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Fri, 7 Mar 2014 15:15:49 -0800
Subject: [PATCH 121/178] Utilizing the new level type property in the level
 handler.

---
 server/levels/level_handler.coffee | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/server/levels/level_handler.coffee b/server/levels/level_handler.coffee
index da79be8d6..94bf33dd8 100644
--- a/server/levels/level_handler.coffee
+++ b/server/levels/level_handler.coffee
@@ -49,10 +49,11 @@ LevelHandler = class LevelHandler extends Handler
           majorVersion: level.version.major
         creator: req.user.id
 
-      # TODO: generalize this for levels that need teams
       if req.query.team?
         sessionQuery.team = req.query.team
-      else if level.name is 'Project DotA'
+
+      # TODO: generalize this for levels based on their teams
+      else if level.get('type') is 'ladder'
         sessionQuery.team = 'humans'
       
       Session.findOne(sessionQuery).exec (err, doc) =>

From 13b9a9cb5853bbe256c35d9d94ea8f8906a5bc36 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Fri, 7 Mar 2014 15:16:13 -0800
Subject: [PATCH 122/178] Added dungeon arena tutorial to a few hardcoded
 places.

---
 app/views/play/level/control_bar_view.coffee      | 2 +-
 app/views/play/level/tome/cast_button_view.coffee | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/views/play/level/control_bar_view.coffee b/app/views/play/level/control_bar_view.coffee
index 06d689f82..bae8753b6 100644
--- a/app/views/play/level/control_bar_view.coffee
+++ b/app/views/play/level/control_bar_view.coffee
@@ -54,7 +54,7 @@ module.exports = class ControlBarView extends View
     c.ladderGame = @ladderGame
     c.homeLink = "/"
     levelID = @level.get('slug')
-    if levelID in ["brawlwood", "brawlwood-tutorial", "dungeon-arena"]
+    if levelID in ["brawlwood", "brawlwood-tutorial", "dungeon-arena", "dungeon-arena-tutorial"]
       levelID = 'brawlwood' if levelID is 'brawlwood-tutorial'
       c.homeLink = "/play/ladder/" + levelID
     c
diff --git a/app/views/play/level/tome/cast_button_view.coffee b/app/views/play/level/tome/cast_button_view.coffee
index 15d59f194..af45ca57c 100644
--- a/app/views/play/level/tome/cast_button_view.coffee
+++ b/app/views/play/level/tome/cast_button_view.coffee
@@ -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 in ['brawlwood', 'brawlwood-tutorial', 'dungeon-arena']
+    if @levelID in ['brawlwood', 'brawlwood-tutorial', 'dungeon-arena', 'dungeon-arena-tutorial']
       delay = 90019001
     @setAutocastDelay delay
 

From 8fa9c9c41052eed0048c3dd7cbbbeecc8f171fe7 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Fri, 7 Mar 2014 15:18:56 -0800
Subject: [PATCH 123/178] Set up the level play view to show the guide on
 startup based on the showGuide property.

---
 app/lib/LevelLoader.coffee       |  1 +
 app/views/kinds/CocoView.coffee  |  5 +++--
 app/views/play/level_view.coffee | 27 +++++++++++++++++++++++++--
 3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/app/lib/LevelLoader.coffee b/app/lib/LevelLoader.coffee
index 18ae9f82f..a0e1d78b7 100644
--- a/app/lib/LevelLoader.coffee
+++ b/app/lib/LevelLoader.coffee
@@ -229,6 +229,7 @@ module.exports = class LevelLoader extends CocoClass
   notifyProgress: ->
     Backbone.Mediator.publish 'level-loader:progress-changed', progress: @progress()
     @initWorld() if @allDone()
+    @trigger 'progress'
     @trigger 'loaded-all' if @progress() is 1
 
   destroy: ->
diff --git a/app/views/kinds/CocoView.coffee b/app/views/kinds/CocoView.coffee
index 806a2d25c..b95abd12e 100644
--- a/app/views/kinds/CocoView.coffee
+++ b/app/views/kinds/CocoView.coffee
@@ -99,10 +99,11 @@ module.exports = class CocoView extends Backbone.View
     view = application.router.getView(target, '_modal') # could set up a system for loading cached modals, if told to
     @openModalView(view)
 
-  openModalView: (modalView) ->
-    return if @waitingModal # can only have one waiting at once
+  openModalView: (modalView, softly=false) ->
+    return if waitingModal # can only have one waiting at once
     if visibleModal
       waitingModal = modalView
+      return if softly
       return visibleModal.hide() if visibleModal.$el.is(':visible') # close, then this will get called again
       return @modalClosed(visibleModal) # was closed, but modalClosed was not called somehow
     modalView.render()
diff --git a/app/views/play/level_view.coffee b/app/views/play/level_view.coffee
index 11fa59ba3..a7faa74cb 100644
--- a/app/views/play/level_view.coffee
+++ b/app/views/play/level_view.coffee
@@ -16,6 +16,7 @@ LevelLoader = require 'lib/LevelLoader'
 LevelSession = require 'models/LevelSession'
 Level = require 'models/Level'
 LevelComponent = require 'models/LevelComponent'
+Article = require 'models/Article'
 Camera = require 'lib/surface/Camera'
 AudioPlayer = require 'lib/AudioPlayer'
 
@@ -105,7 +106,8 @@ module.exports = class PlayLevelView extends View
 
   load: ->
     @levelLoader = new LevelLoader supermodel: @supermodel, levelID: @levelID, sessionID: @sessionID, opponentSessionID: @getQueryVariable('opponent'), team: @getQueryVariable("team")
-    @levelLoader.once 'loaded-all', @onLevelLoaderLoaded
+    @levelLoader.once 'loaded-all', @onLevelLoaderLoaded, @
+    @levelLoader.on 'progress', @onLevelLoaderProgressChanged, @
     @god = new God()
 
   getRenderData: ->
@@ -124,7 +126,28 @@ module.exports = class PlayLevelView extends View
     @$el.find('#level-done-button').hide()
     super()
 
-  onLevelLoaderLoaded: =>
+  onLevelLoaderProgressChanged: ->
+    return if @seenDocs
+    return unless showFrequency = @levelLoader.level.get('showGuide')
+    session = @levelLoader.session
+    diff = new Date().getTime() - new Date(session.get('created')).getTime()
+    return if showFrequency is 'first-time' and diff > (5 * 60 * 1000)
+    return unless @levelLoader.level.loaded
+    articles = @levelLoader.supermodel.getModels Article
+    for article in articles
+      return unless article.loaded
+    @showGuide()
+
+  showGuide: ->
+    @seenDocs = true
+    DocsModal = require './level/modal/docs_modal'
+    options = {docs: @levelLoader.level.get('documentation'), supermodel: @supermodel}
+    @openModalView(new DocsModal(options), true)
+    Backbone.Mediator.subscribeOnce 'modal-closed', @onLevelLoaderLoaded, @
+    return true
+
+  onLevelLoaderLoaded: ->
+    return unless @levelLoader.progress() is 1 # double check, since closing the guide may trigger this early
     # Save latest level played in local storage
     if window.currentModal and not window.currentModal.destroyed
       @loadingScreen.showReady()

From ec86a07906f3facf802a5ddb5ce8be8b2befc347 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Fri, 7 Mar 2014 15:20:54 -0800
Subject: [PATCH 124/178] Changed Camera min/max zoom.

---
 app/lib/surface/Camera.coffee | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/lib/surface/Camera.coffee b/app/lib/surface/Camera.coffee
index 76323e5e8..07c4fbbcc 100644
--- a/app/lib/surface/Camera.coffee
+++ b/app/lib/surface/Camera.coffee
@@ -5,8 +5,8 @@ CocoClass = require 'lib/CocoClass'
 r2d = (radians) -> radians * 180 / Math.PI
 d2r = (degrees) -> degrees / 180 * Math.PI
 
-MAX_ZOOM = 8
-MIN_ZOOM = 0.1
+MAX_ZOOM = 4
+MIN_ZOOM = 0.05
 DEFAULT_ZOOM = 2.0
 DEFAULT_TARGET = {x:0, y:0}
 DEFAULT_TIME = 1000

From 98b36d299ca09793794a4dca1cdddeec8c354c7f Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Sat, 8 Mar 2014 05:05:35 +0400
Subject: [PATCH 125/178] Update article model

---
 app/views/play/level/modal/docs_modal.coffee | 3 ++-
 server/articles/article_handler.coffee       | 2 +-
 server/articles/article_schema.coffee        | 1 +
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/app/views/play/level/modal/docs_modal.coffee b/app/views/play/level/modal/docs_modal.coffee
index c7b77a287..3e9ab5cf8 100644
--- a/app/views/play/level/modal/docs_modal.coffee
+++ b/app/views/play/level/modal/docs_modal.coffee
@@ -25,7 +25,8 @@ module.exports = class DocsModal extends View
     @docs = specific.concat(general)
     marked.setOptions {gfm: true, sanitize: false, smartLists: true, breaks: false}
     @docs = _.cloneDeep(@docs)
-    doc.html = marked(doc.body) for doc in @docs
+    doc.html = marked(doc.i18n?[me.lang()]?.body or doc.body) for doc in @docs
+    doc.name = (doc.i18n?[me.lang()]?.name or doc.name) for doc in @docs
     doc.slug = _.string.slugify(doc.name) for doc in @docs
     super()
 
diff --git a/server/articles/article_handler.coffee b/server/articles/article_handler.coffee
index ac4fb4b97..b519b8b9f 100644
--- a/server/articles/article_handler.coffee
+++ b/server/articles/article_handler.coffee
@@ -3,7 +3,7 @@ Handler = require('../commons/Handler')
 
 ArticleHandler = class ArticleHandler extends Handler
   modelClass: Article
-  editableProperties: ['body', 'name']
+  editableProperties: ['body', 'name', 'i18n']
 
   hasAccess: (req) ->
     req.method is 'GET' or req.user?.isAdmin()
diff --git a/server/articles/article_schema.coffee b/server/articles/article_schema.coffee
index 08226d183..48ae42821 100644
--- a/server/articles/article_schema.coffee
+++ b/server/articles/article_schema.coffee
@@ -4,6 +4,7 @@ ArticleSchema = c.object()
 c.extendNamedProperties ArticleSchema  # name first
 
 ArticleSchema.properties.body = { type: 'string', title: 'Content', format: 'markdown' }
+ArticleSchema.properties.i18n = { type: 'object', title: 'i18n', format: 'i18n', props: ['body'] }
 
 c.extendBasicProperties(ArticleSchema, 'article')
 c.extendSearchableProperties(ArticleSchema)

From fe2ced1a67fbc7288541cc1ff02ec8491d3438cf Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Fri, 7 Mar 2014 17:37:11 -0800
Subject: [PATCH 126/178] Gave the health bar a border, made it a little more
 high res.

---
 app/lib/surface/CocoSprite.coffee   |  4 ++--
 app/lib/surface/sprite_utils.coffee | 14 +++++++++++++-
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee
index 7c7748121..cdbde389e 100644
--- a/app/lib/surface/CocoSprite.coffee
+++ b/app/lib/surface/CocoSprite.coffee
@@ -328,7 +328,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
       return if @thang.health is @lastHealth
       @lastHealth = @thang.health
       healthPct = Math.max(@thang.health / @thang.maxHealth, 0)
-      bar.scaleX = healthPct
+      bar.scaleX = healthPct / bar.baseScale
       healthOffset = @getOffset 'aboveHead'
       [bar.x, bar.y] = [healthOffset.x - bar.width / 2, healthOffset.y]
 
@@ -357,7 +357,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     bar = @healthBar = createProgressBar(healthColor, healthOffset.y)
     bar.x = healthOffset.x - bar.width / 2
     bar.name = 'health bar'
-    bar.cache 0, -bar.height / 2, bar.width, bar.height
+    bar.cache 0, -bar.height * bar.baseScale / 2, bar.width * bar.baseScale, bar.height * bar.baseScale
     @displayObject.addChild bar
 
   getActionProp: (prop, subProp, def=null) ->
diff --git a/app/lib/surface/sprite_utils.coffee b/app/lib/surface/sprite_utils.coffee
index 6d106e0aa..68984f370 100644
--- a/app/lib/surface/sprite_utils.coffee
+++ b/app/lib/surface/sprite_utils.coffee
@@ -1,16 +1,28 @@
 PROG_BAR_WIDTH = 20
 PROG_BAR_HEIGHT = 2
+PROG_BAR_SCALE = 2.5
+EDGE_SIZE = 0.3
 
 module.exports.createProgressBar = createProgressBar = (color, y, width=PROG_BAR_WIDTH, height=PROG_BAR_HEIGHT) ->
   g = new createjs.Graphics()
   g.setStrokeStyle(1)
+
+  sWidth = width * PROG_BAR_SCALE
+  sHeight = height * PROG_BAR_SCALE
+  sEdge = EDGE_SIZE * PROG_BAR_SCALE
+
+  g.beginFill(createjs.Graphics.getRGB(0, 0, 0))
+  g.drawRect(0, -sHeight/2, sWidth, sHeight, sHeight)
   g.beginFill(createjs.Graphics.getRGB(color...))
-  g.drawRoundRect(0, -1, width, height, height)
+  g.drawRoundRect(sEdge, sEdge - sHeight/2, sWidth-sEdge*2, sHeight-sEdge*2, sHeight-sEdge*2)
 
   s = new createjs.Shape(g)
   s.x = -width / 2
   s.y = y
   s.z = 100
+  s.baseScale = PROG_BAR_SCALE
+  s.scaleX = 1 / PROG_BAR_SCALE
+  s.scaleY = 1 / PROG_BAR_SCALE
   s.width = width
   s.height = height
   return s

From 2f378106caa2251c675cd4bd28576ec83a0c5fdf Mon Sep 17 00:00:00 2001
From: Michael Schmatz <schmatz@umich.edu>
Date: Fri, 7 Mar 2014 18:16:48 -0800
Subject: [PATCH 127/178] Added checking level ladder status before submitting

---
 app/views/play/ladder/my_matches_tab.coffee |  2 +-
 server/queues/scoring.coffee                | 40 ++++++++++++---------
 2 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
index 6b2cf71be..b08a15083 100644
--- a/app/views/play/ladder/my_matches_tab.coffee
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -95,7 +95,7 @@ module.exports = class MyMatchesTabView extends CocoView
     success = => @setRankingButtonText(button, 'ranked')
     failure = => @setRankingButtonText(button, 'failed')
     
-    ajaxData = { session: sessionID, levelID: @level.attributes.original, levelMajorVersion: @level.attributes.version.major }
+    ajaxData = { session: sessionID, levelID: @level.id, originalLevelID: @level.attributes.original, levelMajorVersion: @level.attributes.version.major }
     $.ajax '/queue/scoring', {
       type: 'POST'
       data: ajaxData
diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee
index dd2a51030..1e2cd3f29 100644
--- a/server/queues/scoring.coffee
+++ b/server/queues/scoring.coffee
@@ -8,6 +8,7 @@ db = require './../routes/db'
 mongoose = require 'mongoose'
 queues = require '../commons/queue'
 LevelSession = require '../levels/sessions/LevelSession'
+Level = require '../levels/Level'
 TaskLog = require './task/ScoringTask'
 bayes = new (require 'bayesian-battle')()
 
@@ -48,7 +49,8 @@ addPairwiseTaskToQueue = (taskPair, cb) ->
 
 module.exports.createNewTask = (req, res) ->
   requestSessionID = req.body.session
-  requestLevelID = req.body.levelID
+  requestLevelID = req.body.originalLevelID
+  requestCurrentLevelID = req.body.levelID
   requestLevelMajorVersion = parseInt(req.body.levelMajorVersion)
   
   validatePermissions req, requestSessionID, (error, permissionsAreValid) ->
@@ -56,21 +58,27 @@ module.exports.createNewTask = (req, res) ->
     unless permissionsAreValid then return errors.forbidden res, "You do not have the permissions to submit that game to the leaderboard"
 
     return errors.badInput res, "The session ID is invalid" unless typeof requestSessionID is "string"
-
-    fetchSessionToSubmit requestSessionID, (err, sessionToSubmit) ->
-      if err? then return errors.serverError res, "There was an error finding the given session."
-
-      updateSessionToSubmit sessionToSubmit, (err, data) ->
-        if err? then return errors.serverError res, "There was an error updating the session"
-        opposingTeam = calculateOpposingTeam(sessionToSubmit.team)
-        fetchInitialSessionsToRankAgainst opposingTeam,requestLevelID, requestLevelMajorVersion, (err, sessionsToRankAgainst) ->
-          if err? then return errors.serverError res, "There was an error fetching the sessions to rank against"
-
-          taskPairs = generateTaskPairs(sessionsToRankAgainst, sessionToSubmit)
-          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"}
+    Level.findOne({_id: requestCurrentLevelID}).lean().select('type').exec (err, levelWithType) ->
+      if err? then return errors.serverError res, "There was an error finding the level type"
+        
+      if not levelWithType.type or levelWithType.type isnt "ladder" 
+        console.log "The level type of level with ID #{requestLevelID} is #{levelWithType.type}"
+        return errors.badInput res, "That level isn't a ladder level"
+  
+      fetchSessionToSubmit requestSessionID, (err, sessionToSubmit) ->
+        if err? then return errors.serverError res, "There was an error finding the given session."
+  
+        updateSessionToSubmit sessionToSubmit, (err, data) ->
+          if err? then return errors.serverError res, "There was an error updating the session"
+          opposingTeam = calculateOpposingTeam(sessionToSubmit.team)
+          fetchInitialSessionsToRankAgainst opposingTeam,requestLevelID, requestLevelMajorVersion, (err, sessionsToRankAgainst) ->
+            if err? then return errors.serverError res, "There was an error fetching the sessions to rank against"
+  
+            taskPairs = generateTaskPairs(sessionsToRankAgainst, sessionToSubmit)
+            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.dispatchTaskToConsumer = (req, res) ->
   if isUserAnonymous(req) then return errors.forbidden res, "You need to be logged in to simulate games"

From 085fb82cc999aa7e7961434b6adbcc3df5563db9 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Fri, 7 Mar 2014 21:02:10 -0800
Subject: [PATCH 128/178] Fixed a multiplayer link and debug mark alpha.

---
 app/lib/surface/CocoSprite.coffee               | 2 +-
 app/lib/surface/Mark.coffee                     | 4 ++--
 app/lib/surface/Surface.coffee                  | 2 +-
 app/templates/play/level/modal/multiplayer.jade | 2 +-
 server/articles/article_schema.coffee           | 2 +-
 5 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee
index cdbde389e..b454031e1 100644
--- a/app/lib/surface/CocoSprite.coffee
+++ b/app/lib/surface/CocoSprite.coffee
@@ -389,7 +389,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     @addMark('bounds').toggle true if @thang?.drawsBounds
     @addMark('shadow').toggle true unless @thangType.get('shadow') is 0
     mark.update() for name, mark of @marks
-    #@thang.effectNames = ['berserk', 'confuse', 'control', 'curse', 'fear', 'poison', 'paralyze', 'regen', 'sleep', 'slow', 'speed']
+    #@thang.effectNames = ['berserk', 'confuse', 'control', 'curse', 'fear', 'poison', 'paralyze', 'regen', 'sleep', 'slow', 'haste']
     @updateEffectMarks() if @thang?.effectNames?.length or @previousEffectNames?.length
 
   updateEffectMarks: ->
diff --git a/app/lib/surface/Mark.coffee b/app/lib/surface/Mark.coffee
index 5a2e7689f..62801a60f 100644
--- a/app/lib/surface/Mark.coffee
+++ b/app/lib/surface/Mark.coffee
@@ -151,14 +151,14 @@ module.exports = class Mark extends CocoClass
     @thangType.fetch()
     markThangTypes[name] = @thangType
     window.mtt = markThangTypes
-    
+
   onLoadedThangType: ->
     @build()
     @toggle(@toggleTo) if @toggleTo?
 
   update: (pos=null) ->
     return false unless @on and @mark
-    @mark.alpha = if @hidden then 0 else 1
+    @mark.visible = not @hidden
     @updatePosition pos
     @updateRotation()
     @updateScale()
diff --git a/app/lib/surface/Surface.coffee b/app/lib/surface/Surface.coffee
index c5e15813d..feb87fc93 100644
--- a/app/lib/surface/Surface.coffee
+++ b/app/lib/surface/Surface.coffee
@@ -302,7 +302,7 @@ module.exports = Surface = class Surface extends CocoClass
       world: @world
     )
 
-    if @lastFrame < @world.totalFrames and @currentFrame >= @world.totalFrames
+    if @lastFrame < @world.totalFrames and @currentFrame >= @world.totalFrames - 1
       @spriteBoss.stop()
       @playbackOverScreen.show()
       @ended = true
diff --git a/app/templates/play/level/modal/multiplayer.jade b/app/templates/play/level/modal/multiplayer.jade
index bc8cc39b5..2135e1977 100644
--- a/app/templates/play/level/modal/multiplayer.jade
+++ b/app/templates/play/level/modal/multiplayer.jade
@@ -30,7 +30,7 @@
       if me.get('anonymous')
         p Sign in or create an account and get your solution on the leaderboard!
       else
-        a#go-to-leaderboard-button.btn.btn-primary(href="/play/ladder/#{levelSlug}/team/#{team}") Go to the leaderboard!
+        a#go-to-leaderboard-button.btn.btn-primary(href="/play/ladder/#{levelSlug}#my-matches") Go to the leaderboard!
         p You can submit your game to be ranked from the leaderboard page.
   
   .modal-footer
diff --git a/server/articles/article_schema.coffee b/server/articles/article_schema.coffee
index 48ae42821..1fd4769f7 100644
--- a/server/articles/article_schema.coffee
+++ b/server/articles/article_schema.coffee
@@ -10,4 +10,4 @@ c.extendBasicProperties(ArticleSchema, 'article')
 c.extendSearchableProperties(ArticleSchema)
 c.extendVersionedProperties(ArticleSchema, 'article')
 
-module.exports = ArticleSchema
\ No newline at end of file
+module.exports = ArticleSchema

From 68099bbd7cc505721ceddf142069a3065275fc8d Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Fri, 7 Mar 2014 21:20:09 -0800
Subject: [PATCH 129/178] Victory modal for ladder games takes you back to the
 ladder matches.

---
 app/templates/play/level/modal/victory.jade     | 4 +++-
 app/views/play/ladder_view.coffee               | 5 +++--
 app/views/play/level/modal/victory_modal.coffee | 1 +
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/app/templates/play/level/modal/victory.jade b/app/templates/play/level/modal/victory.jade
index 5dca8f3f6..45c7f567f 100644
--- a/app/templates/play/level/modal/victory.jade
+++ b/app/templates/play/level/modal/victory.jade
@@ -14,7 +14,9 @@
     div!= body
   
   .modal-footer
-    if hasNextLevel
+    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_home") Go Home
+    else if hasNextLevel
       button.btn.btn-primary.next-level-button(data-dismiss="modal", data-i18n="play_level.victory_play_next_level") Play Next Level
     else
       a.btn.btn-primary(href="/", data-dismiss="modal", data-i18n="play_level.victory_go_home") Go Home
diff --git a/app/views/play/ladder_view.coffee b/app/views/play/ladder_view.coffee
index 81e2f6558..7b6597380 100644
--- a/app/views/play/ladder_view.coffee
+++ b/app/views/play/ladder_view.coffee
@@ -72,6 +72,7 @@ module.exports = class LadderView extends RootView
     @sessions.fetch({"success": @refreshViews})
 
   refreshViews: =>
+    return if @destroyed
     @ladderTab.refreshLadder()
     @myMatchesTab.refreshMatches()
     console.log "refreshed views!"
@@ -114,12 +115,12 @@ module.exports = class LadderView extends RootView
 
   onClickPlayButton: (e) ->
     @showPlayModal($(e.target).closest('.play-button').data('team'))
-    
+
   showPlayModal: (teamID) ->
     session = (s for s in @sessions.models when s.get('team') is teamID)[0]
     modal = new LadderPlayModal({}, @level, session, teamID)
     @openModalView modal
-    
+
   destroy: ->
     clearInterval @refreshInterval
     @simulator.destroy()
diff --git a/app/views/play/level/modal/victory_modal.coffee b/app/views/play/level/modal/victory_modal.coffee
index e2fa6b607..6773982ad 100644
--- a/app/views/play/level/modal/victory_modal.coffee
+++ b/app/views/play/level/modal/victory_modal.coffee
@@ -64,6 +64,7 @@ module.exports = class VictoryModal extends View
     c.me = me
     c.hasNextLevel = _.isObject(@level.get('nextLevel')) and (@level.get('name') isnt "Mobile Artillery")
     c.levelName = @level.get('i18n')?[me.lang()]?.name ? @level.get('name')
+    c.level = @level
     if me.get 'hourOfCode'
       # Show the Hour of Code "I'm Done" tracking pixel after they played for 30 minutes
       elapsed = (new Date() - new Date(me.get('dateCreated')))

From bcd8c837b4461d841aebca2669ba66b58d489a20 Mon Sep 17 00:00:00 2001
From: Yinkan Li <liyinkan.biz@gmail.com>
Date: Sat, 8 Mar 2014 23:53:47 +0800
Subject: [PATCH 130/178] =?UTF-8?q?Update=20=EF=BC=9A=20employers=20for=20?=
 =?UTF-8?q?Chinese=20simplified?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Update : employers for Chinese simplified
---
 app/locale/zh-HANS.coffee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/locale/zh-HANS.coffee b/app/locale/zh-HANS.coffee
index fd0e42cbf..274caf775 100644
--- a/app/locale/zh-HANS.coffee
+++ b/app/locale/zh-HANS.coffee
@@ -31,7 +31,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     about: "关于"
     contact: "联系"
     twitter_follow: "关注"
-    employers: "雇佣我们"
+    employers: "招募信息"
 
   versions:
     save_version_title: "保存新版本"

From 452857e66cf7b215d5bd44c260f5681bf55dc283 Mon Sep 17 00:00:00 2001
From: Yinkan Li <liyinkan.biz@gmail.com>
Date: Sat, 8 Mar 2014 23:56:05 +0800
Subject: [PATCH 131/178] update Chinese Simplified

update
legal
concat
---
 app/locale/zh-HANS.coffee | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/locale/zh-HANS.coffee b/app/locale/zh-HANS.coffee
index 274caf775..6611b070d 100644
--- a/app/locale/zh-HANS.coffee
+++ b/app/locale/zh-HANS.coffee
@@ -27,9 +27,9 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     admin: "管理"
     home: "首页"
     contribute: "贡献"
-    legal: "法律"
+    legal: "版权声明"
     about: "关于"
-    contact: "联系"
+    contact: "联系我们"
     twitter_follow: "关注"
     employers: "招募信息"
 

From bfad68b03b0ac3212e5b76d4ea933fbad890cd13 Mon Sep 17 00:00:00 2001
From: Yinkan Li <liyinkan.biz@gmail.com>
Date: Sun, 9 Mar 2014 00:01:13 +0800
Subject: [PATCH 132/178] refine skip_tutorial
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

refine skip_tutorial
using Chinese ()
---
 app/locale/zh-HANS.coffee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/locale/zh-HANS.coffee b/app/locale/zh-HANS.coffee
index 6611b070d..21f328154 100644
--- a/app/locale/zh-HANS.coffee
+++ b/app/locale/zh-HANS.coffee
@@ -200,7 +200,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     tome_available_spells: "可用的法术"
     hud_continue: "继续(按 Shift-空格)"
     spell_saved: "咒语已保存"
-    skip_tutorial: "跳过(esc)"
+    skip_tutorial: "跳过(esc)"
 
   admin:
     av_title: "管理员视图"

From 1c44e3df1eaaa22fe253ec0210e7ee4d48e76055 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sat, 8 Mar 2014 11:37:33 -0800
Subject: [PATCH 133/178] Fixed bug with linking to #my-matches tab.

---
 app/views/play/ladder/play_modal.coffee | 16 ++++++++--------
 app/views/play/ladder_view.coffee       |  4 +++-
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/app/views/play/ladder/play_modal.coffee b/app/views/play/ladder/play_modal.coffee
index e5d83fc3b..ebe51e68d 100644
--- a/app/views/play/ladder/play_modal.coffee
+++ b/app/views/play/ladder/play_modal.coffee
@@ -11,7 +11,7 @@ module.exports = class LadderPlayModal extends View
   closeButton: true
   startsLoading: true
   @shownTutorialButton: false
-  
+
   events:
     'click #skip-tutorial-button': 'hideTutorialButtons'
 
@@ -21,7 +21,7 @@ module.exports = class LadderPlayModal extends View
     @otherTeam = if team is 'ogres' then 'humans' else 'ogres'
     @startLoadingChallengersMaybe()
     @wizardType = ThangType.loadUniversalWizard()
-    
+
   # PART 1: Load challengers from the db unless some are in the matches
 
   startLoadingChallengersMaybe: ->
@@ -49,12 +49,12 @@ module.exports = class LadderPlayModal extends View
       type: 'POST'
       success: success
     })
-    
+
   # PART 3: Make sure wizard is loaded
-  
+
   checkWizardLoaded: ->
     if @wizardType.loaded then @finishRendering() else @wizardType.once 'sync', @finishRendering, @
-    
+
   # PART 4: Render
 
   finishRendering: ->
@@ -69,7 +69,7 @@ module.exports = class LadderPlayModal extends View
     ctx.teamName = _.string.titleize @team
     ctx.teamID = @team
     ctx.otherTeamID = @otherTeam
-    
+
     teamsList = teamDataFromLevel @level
     teams = {}
     teams[team.id] = team for team in teamsList
@@ -104,7 +104,7 @@ module.exports = class LadderPlayModal extends View
     @$el.find('#normal-view').removeClass('secret')
     @$el.find('.modal-header').removeClass('secret')
     @$el.find('#noob-view').addClass('secret')
-    
+
   # Choosing challengers
 
   getChallengers: ->
@@ -165,7 +165,7 @@ class ChallengersData
     @hardPlayer = new LeaderboardCollection(@level, {order:-1, scoreOffset: score + 5, limit: 1, team: @otherTeam})
     @hardPlayer.fetch()
     @hardPlayer.once 'sync', @challengerLoaded, @
-    
+
   challengerLoaded: ->
     if @allLoaded()
       @loaded = true
diff --git a/app/views/play/ladder_view.coffee b/app/views/play/ladder_view.coffee
index 7b6597380..7ed43660e 100644
--- a/app/views/play/ladder_view.coffee
+++ b/app/views/play/ladder_view.coffee
@@ -66,7 +66,9 @@ module.exports = class LadderView extends RootView
     @insertSubView(@ladderTab = new LadderTabView({}, @level, @sessions))
     @insertSubView(@myMatchesTab = new MyMatchesTabView({}, @level, @sessions))
     @refreshInterval = setInterval(@fetchSessionsAndRefreshViews.bind(@), 10000)
-    @showPlayModal(document.location.hash[1..]) if document.location.hash and @sessions.loaded
+    hash = document.location.hash[1..] if document.location.hash
+    unless hash in ['my-matches', 'simulate', 'ladder']
+      @showPlayModal(hash) if @sessions.loaded
 
   fetchSessionsAndRefreshViews: ->
     @sessions.fetch({"success": @refreshViews})

From b0238d74a40693d616cbd40101dcf700a94372b1 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sat, 8 Mar 2014 11:50:10 -0800
Subject: [PATCH 134/178] Let's just show 200 leaderboard entries for now until
 we have paging.

---
 app/views/play/ladder/ladder_tab.coffee | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/app/views/play/ladder/ladder_tab.coffee b/app/views/play/ladder/ladder_tab.coffee
index 323ca86fe..b8b2d3615 100644
--- a/app/views/play/ladder/ladder_tab.coffee
+++ b/app/views/play/ladder/ladder_tab.coffee
@@ -55,7 +55,8 @@ module.exports = class LadderTabView extends CocoView
 class LeaderboardData
   constructor: (@level, @team, @session) ->
     _.extend @, Backbone.Events
-    @topPlayers = new LeaderboardCollection(@level, {order:-1, scoreOffset: HIGHEST_SCORE, team: @team, limit: if @session then 10 else 20})
+    limit = 200 # if @session then 10 else 20  # We need to figure out paging.
+    @topPlayers = new LeaderboardCollection(@level, {order:-1, scoreOffset: HIGHEST_SCORE, team: @team, limit: limit})
     @topPlayers.fetch()
     @topPlayers.comparator = (model) ->
       return -model.get('totalScore')

From 2861f62248483687088a473e5046f8988cfc9ec3 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Sat, 8 Mar 2014 13:06:04 -0800
Subject: [PATCH 135/178] Simple fix for a race condition where the user schema
 might load after /auth/whoami, overwriting /auth/whoami's cookie.

---
 app/models/CocoModel.coffee | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee
index ba4ff850c..919d9a6b9 100644
--- a/app/models/CocoModel.coffee
+++ b/app/models/CocoModel.coffee
@@ -22,7 +22,8 @@ class CocoModel extends Backbone.Model
     if @constructor.schema?.loaded
       @addSchemaDefaults()
     else
-      @loadSchema()
+      {me} = require 'lib/auth'
+      @loadSchema() if me?.loaded
     @once 'sync', @onLoaded, @
     @saveBackup = _.debounce(@saveBackup, 500)
 

From afbe2200a68d84dfcfd39c53046cde74f8f2fe72 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Sat, 8 Mar 2014 13:52:34 -0800
Subject: [PATCH 136/178] Fixed a bug with the new race condition fix. Moving
 the schemas to the application would be good.

---
 app/models/CocoModel.coffee        | 7 +++----
 app/views/editor/thang/edit.coffee | 1 +
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee
index 919d9a6b9..3f4c9455c 100644
--- a/app/models/CocoModel.coffee
+++ b/app/models/CocoModel.coffee
@@ -16,6 +16,7 @@ class CocoModel extends Backbone.Model
 
   initialize: ->
     super()
+    @constructor.schema ?= new CocoSchema(@urlRoot)
     if not @constructor.className
       console.error("#{@} needs a className set.")
     @markToRevert()
@@ -52,10 +53,8 @@ class CocoModel extends Backbone.Model
   @backedUp = {}
 
   loadSchema: ->
-    unless @constructor.schema
-      @constructor.schema = new CocoSchema(@urlRoot)
-      @constructor.schema.fetch()
-
+    return if @constructor.schema.loading
+    @constructor.schema.fetch()
     @constructor.schema.once 'sync', =>
       @constructor.schema.loaded = true
       @addSchemaDefaults()
diff --git a/app/views/editor/thang/edit.coffee b/app/views/editor/thang/edit.coffee
index a8310cdf2..833ce3e0e 100644
--- a/app/views/editor/thang/edit.coffee
+++ b/app/views/editor/thang/edit.coffee
@@ -42,6 +42,7 @@ module.exports = class ThangTypeEditView extends View
     @thangType = new ThangType(_id: @thangTypeID)
     @thangType.saveBackups = true
     @thangType.fetch()
+    @thangType.loadSchema()
     @thangType.schema().once 'sync', @onThangTypeSync, @
     @thangType.once 'sync', @onThangTypeSync, @
     @refreshAnimation = _.debounce @refreshAnimation, 500

From 57f1588dea9c12ff869baa9222f202ebb7b6a72f Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Sat, 8 Mar 2014 14:34:25 -0800
Subject: [PATCH 137/178] Fixed another bug related to the race condition fix.

---
 app/models/SuperModel.coffee | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/app/models/SuperModel.coffee b/app/models/SuperModel.coffee
index 36a7fab72..9ce14c75d 100644
--- a/app/models/SuperModel.coffee
+++ b/app/models/SuperModel.coffee
@@ -2,6 +2,7 @@ class SuperModel
   constructor: ->
     @models = {}
     @collections = {}
+    @schemas = {}
     _.extend(@, Backbone.Events)
 
   populateModel: (model) ->
@@ -25,8 +26,11 @@ class SuperModel
     @removeEventsFromModel(model)
 
   modelLoaded: (model) ->
+    model.loadSchema()
     schema = model.schema()
-    return schema.once('sync', => @modelLoaded(model)) unless schema.loaded
+    unless schema.loaded
+      @schemas[schema.urlRoot] = schema
+      return schema.once('sync', => @modelLoaded(model))
     refs = model.getReferencedModels(model.attributes, schema.attributes, '/', @shouldLoadProjection)
     refs = [] unless @mustPopulate is model or @shouldPopulate(model)
 #    console.log 'Loaded', model.get('name')
@@ -96,9 +100,12 @@ class SuperModel
     total = 0
     loaded = 0
 
-    for key, model of @models
+    for model in _.values @models
       total += 1
       loaded += 1 if model.loaded
+    for schema in _.values @schemas
+      total += 1
+      loaded += 1 if schema.loaded
 
     return 1.0 unless total
     return loaded / total

From be12d38e34063496b798830fead91929293c679b Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sat, 8 Mar 2014 14:38:35 -0800
Subject: [PATCH 138/178] Taking into account null rects and library
 width/height subtraction on sprite parsing.

---
 app/lib/sprites/SpriteParser.coffee | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/app/lib/sprites/SpriteParser.coffee b/app/lib/sprites/SpriteParser.coffee
index 75288c5fa..a5e1f9472 100644
--- a/app/lib/sprites/SpriteParser.coffee
+++ b/app/lib/sprites/SpriteParser.coffee
@@ -24,6 +24,11 @@ module.exports = class SpriteParser
       @animationLongKeys[longKey] = shortKey
 
   parse: (source) ->
+    # Grab the library properties' width/height so we can subtract half of each from frame bounds
+    properties = source.match(/.*lib\.properties = \{\n.*?width: (\d+),\n.*?height: (\d+)/im)
+    @width = parseInt(properties[1] ? "0", 10)
+    @height = parseInt(properties[2] ? "0", 10)
+
     options = {loc: false, range: true}
     ast = esprima.parse source, options
     blocks = @findBlocks ast, source
@@ -178,11 +183,18 @@ module.exports = class SpriteParser
                 else if arg.type is 'AssignmentExpression'
                   bounds = @grabFunctionArguments argSource.replace('rect=', ''), true
                   lastRect = bounds
+                else if arg.type is 'Literal' and arg.value is null
+                  bounds = [0, 0, 1, 1]  # Let's try this.
                 frameBounds.push bounds
           else
             console.log "Didn't have multiframe bounds for this movie clip!"
             frameBounds = [nominalBounds]
 
+          # Subtract half of width/height parsed from lib.properties
+          for bounds in frameBounds
+            bounds[0] -= @width / 2
+            bounds[1] -= @height / 2
+
           functionExpressions.push {name: name, bounds: nominalBounds, frameBounds: frameBounds, expression: node.parent.parent, kind: kind}
     @walk ast, null, gatherFunctionExpressions
     functionExpressions

From 5bde5347571950730e23f9f1b5b9bbe4a1cb2e34 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sat, 8 Mar 2014 14:53:17 -0800
Subject: [PATCH 139/178] Fixed parsing for ThangTypes that don't have
 lib.properties.

---
 app/lib/sprites/SpriteParser.coffee | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/lib/sprites/SpriteParser.coffee b/app/lib/sprites/SpriteParser.coffee
index a5e1f9472..9dd45dbcc 100644
--- a/app/lib/sprites/SpriteParser.coffee
+++ b/app/lib/sprites/SpriteParser.coffee
@@ -26,8 +26,8 @@ module.exports = class SpriteParser
   parse: (source) ->
     # Grab the library properties' width/height so we can subtract half of each from frame bounds
     properties = source.match(/.*lib\.properties = \{\n.*?width: (\d+),\n.*?height: (\d+)/im)
-    @width = parseInt(properties[1] ? "0", 10)
-    @height = parseInt(properties[2] ? "0", 10)
+    @width = parseInt(properties?[1] ? "0", 10)
+    @height = parseInt(properties?[2] ? "0", 10)
 
     options = {loc: false, range: true}
     ast = esprima.parse source, options

From b3964571e1dd752dd467c3f99f67da27acfad550 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sat, 8 Mar 2014 15:04:11 -0800
Subject: [PATCH 140/178] Fixed bug importing animations into existing
 ThangTypes that had only containers.

---
 app/lib/sprites/SpriteParser.coffee | 5 ++++-
 app/views/editor/thang/edit.coffee  | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/app/lib/sprites/SpriteParser.coffee b/app/lib/sprites/SpriteParser.coffee
index 9dd45dbcc..15fe749cd 100644
--- a/app/lib/sprites/SpriteParser.coffee
+++ b/app/lib/sprites/SpriteParser.coffee
@@ -2,7 +2,10 @@ module.exports = class SpriteParser
   constructor: (@thangTypeModel) ->
     # Create a new ThangType, or work with one we've been building
     @thangType = _.cloneDeep(@thangTypeModel.attributes.raw)
-    @thangType ?= {shapes: {}, containers: {}, animations: {}}
+    @thangType ?= {}
+    @thangType.shapes ?= {}
+    @thangType.containers ?= {}
+    @thangType.animations ?= {}
 
     # Internal parser state
     @shapeLongKeys = {}
diff --git a/app/views/editor/thang/edit.coffee b/app/views/editor/thang/edit.coffee
index 833ce3e0e..5a5d188f2 100644
--- a/app/views/editor/thang/edit.coffee
+++ b/app/views/editor/thang/edit.coffee
@@ -316,7 +316,7 @@ module.exports = class ThangTypeEditView extends View
     @thangType.set 'actions', undefined
     @clearDisplayObject()
     @treema.set('/', @getThangData())
-    
+
   getThangData: ->
     data = _.cloneDeep(@thangType.attributes)
     data = _.pick data, (value, key) => not (key in ['components'])

From 39c465720433f3c6f991c2ec362e69c8f60c7cae Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sat, 8 Mar 2014 15:43:56 -0800
Subject: [PATCH 141/178] Fixed HUD showing actions backwardly. Added rank
 numbering to leaderboard.

---
 app/templates/play/ladder/ladder_tab.jade | 6 ++++--
 app/views/play/level/hud_view.coffee      | 2 +-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/app/templates/play/ladder/ladder_tab.jade b/app/templates/play/ladder/ladder_tab.jade
index c3090caa3..9fc48c340 100644
--- a/app/templates/play/ladder/ladder_tab.jade
+++ b/app/templates/play/ladder/ladder_tab.jade
@@ -3,17 +3,19 @@ div#columns.row
     div.column.col-md-6
       table.table.table-bordered.table-condensed.table-hover
         tr
-          th(colspan=3, style="color: #{team.primaryColor}")
+          th(colspan=4, style="color: #{team.primaryColor}")
             span= team.name
             span  Leaderboard
         tr
+          th Rank
           th Score
           th.name-col-cell Name
           th
 
-        for session in team.leaderboard.topPlayers.models
+        for session, rank in team.leaderboard.topPlayers.models
           - var myRow = session.get('creator') == me.id
           tr(class=myRow ? "success" : "")
+            td.rank-cell= rank + 1
             td.score-cell= Math.round(session.get('totalScore') * 100)
             td.name-col-cell= session.get('creatorName') || "Anonymous"
             td
diff --git a/app/views/play/level/hud_view.coffee b/app/views/play/level/hud_view.coffee
index 1951e3539..662c9fc8f 100644
--- a/app/views/play/level/hud_view.coffee
+++ b/app/views/play/level/hud_view.coffee
@@ -151,7 +151,7 @@ module.exports = class HUDView extends View
   createActions: ->
     actions = @$el.find('.thang-actions tbody').empty()
     showActions = @thang.world and not _.isEmpty(@thang.actions) and 'action' in @thang.hudProperties ? []
-    @$el.find('.thang-actions').toggleClass 'secret', showActions
+    @$el.find('.thang-actions').toggleClass 'secret', not showActions
     return unless showActions
     @buildActionTimespans()
     for actionName, action of @thang.actions

From bfebd0b47ac4cf7747e710207514d27f6c5e628a Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Sun, 9 Mar 2014 04:13:30 +0400
Subject: [PATCH 142/178] Add revert i18n

---
 app/locale/ru.coffee                   | 2 ++
 app/templates/editor/article/edit.jade | 2 +-
 app/templates/editor/level/edit.jade   | 2 +-
 app/templates/editor/thang/edit.jade   | 2 +-
 app/templates/modal/revert.jade        | 2 +-
 5 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 36bcf1ac1..1cb8f0c53 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -226,6 +226,8 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     contact_us: "свяжитесь с нами!"
     hipchat_prefix: "Также вы можете найти нас в нашей"
     hipchat_url: "комнате HipChat."
+    revert: "Откатить"
+    revert_models: "Откатить Модели"
     level_some_options: "Ещё опции"
     level_tab_thangs: "Объекты"
     level_tab_scripts: "Скрипты"
diff --git a/app/templates/editor/article/edit.jade b/app/templates/editor/article/edit.jade
index 7c6a7136a..3bd861bd9 100644
--- a/app/templates/editor/article/edit.jade
+++ b/app/templates/editor/article/edit.jade
@@ -10,7 +10,7 @@ block content
       li.active
         | #{article.attributes.name}
 
-  button(data-toggle="coco-modal", data-target="modal/revert", data-i18n="revert.revert", disabled=authorized === true ? undefined : "true").btn.btn-primary#revert-button Revert
+  button(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert", disabled=authorized === true ? undefined : "true").btn.btn-primary#revert-button Revert
   button(data-i18n="article.edit_btn_preview", disabled=authorized === true ? undefined : "true").btn.btn-primary#preview-button Preview
   button(data-toggle="coco-modal", data-target="modal/save_version", data-i18n="common.save", disabled=authorized === true ? undefined : "true").btn.btn-primary#save-button Save
 
diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade
index 7d2c7ac66..4166c81a1 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -29,7 +29,7 @@ block outer_content
             
             
           ul.nav.navbar-nav.navbar-right
-            li(data-toggle="coco-modal", data-target="modal/revert", data-i18n="revert.revert", disabled=authorized === true ? undefined : "true").btn.btn-primary.navbar-btn#revert-button Revert
+            li(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert", disabled=authorized === true ? undefined : "true").btn.btn-primary.navbar-btn#revert-button Revert
             li(data-i18n="common.save", disabled=authorized === true ? undefined : "true").btn.btn-primary.navbar-btn#commit-level-start-button Save
             li(data-i18n="common.fork", disabled=anonymous ? "true": undefined).btn.btn-primary.navbar-btn#fork-level-start-button Fork
             li(title="⌃↩ or ⌘↩: Play preview of current level", data-i18n="common.play")#play-button.btn.btn-inverse.banner.navbar-btn Play!
diff --git a/app/templates/editor/thang/edit.jade b/app/templates/editor/thang/edit.jade
index af30eb2c1..52422fe9a 100644
--- a/app/templates/editor/thang/edit.jade
+++ b/app/templates/editor/thang/edit.jade
@@ -13,7 +13,7 @@ block content
   img#portrait.img-thumbnail
 
   button.btn.btn-primary#save-button(data-toggle="coco-modal", data-target="modal/save_version", disabled=authorized === true ? undefined : "true") Save
-  button.btn.btn-primary#revert-button(data-toggle="coco-modal", data-target="modal/revert", data-i18n="revert.revert", disabled=authorized === true ? undefined : "true") Revert
+  button.btn.btn-primary#revert-button(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert", disabled=authorized === true ? undefined : "true") Revert
   
   h3 Edit Thang Type: "#{thangType.attributes.name}"
 
diff --git a/app/templates/modal/revert.jade b/app/templates/modal/revert.jade
index adfd7688a..f20edd7d2 100644
--- a/app/templates/modal/revert.jade
+++ b/app/templates/modal/revert.jade
@@ -1,7 +1,7 @@
 extends /templates/modal/modal_base
 
 block modal-header-content
-  h3(data-i18n="revert.revert_models") Revert Models
+  h3(data-i18n="editor.revert_models") Revert Models
 
 block modal-body-content
   table.table.table-striped#changed-models

From f6d68055345f3e2abb2f8eb2920b49a418987814 Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Sun, 9 Mar 2014 04:31:15 +0400
Subject: [PATCH 143/178] Add password i18n

---
 app/locale/ru.coffee            | 1 +
 app/templates/modal/login.jade  | 2 +-
 app/templates/modal/signup.jade | 2 +-
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 1cb8f0c53..55c0f2fbf 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -266,6 +266,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     description: "Описание"
     or: "или"
     email: "Email"
+    password: "Пароль"
     message: "Сообщение"
 
   about:
diff --git a/app/templates/modal/login.jade b/app/templates/modal/login.jade
index ae6b8b236..bd0307824 100644
--- a/app/templates/modal/login.jade
+++ b/app/templates/modal/login.jade
@@ -9,7 +9,7 @@ block modal-body-content
       label.control-label(for="login-email", data-i18n="general.email") Email      
       input#login-email.input-large.form-control(name="email", type="email")
     .form-group
-      label.control-label(for="login-password", data-i18n="forms.password") Password      
+      label.control-label(for="login-password", data-i18n="general.password") Password      
       input#login-password.input-large.form-control(name="password", type="password")
 
 block modal-body-wait-content
diff --git a/app/templates/modal/signup.jade b/app/templates/modal/signup.jade
index d99fed9d6..2b27577d2 100644
--- a/app/templates/modal/signup.jade
+++ b/app/templates/modal/signup.jade
@@ -12,7 +12,7 @@ block modal-body-content
           label.control-label(for="signup-email", data-i18n="general.email") Email              
           input#signup-email.form-control.input-large(name="email", type="email")
         .form-group
-          label.control-label(for="signup-password", data-i18n="forms.password") Password              
+          label.control-label(for="signup-password", data-i18n="general.password") Password              
           input#signup-password.input-large.form-control(name="password", type="password")
         hr
         .form-group.checkbox

From 81084a24c63a8e8dbc6ebd837f60c2d57087333f Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Sun, 9 Mar 2014 04:36:48 +0400
Subject: [PATCH 144/178] Add admin i18n

---
 app/locale/ru.coffee                | 1 +
 app/templates/account/settings.jade | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 55c0f2fbf..6c52002e5 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -122,6 +122,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     wizard_tab: "Волшебник"
     password_tab: "Пароль"
     emails_tab: "Email-адреса"
+    admin: "Админ"
     gravatar_select: "Выберите, какое фото с Gravatar использовать"
     gravatar_add_photos: "Чтобы выбрать изображение, добавьте фото и уменьшенные изображения в ваш Gravatar-аккаунт."
     gravatar_add_more_photos: "Добавьте больше фото к вашему аккаунту в Gravatar, чтобы использовать их здесь."
diff --git a/app/templates/account/settings.jade b/app/templates/account/settings.jade
index d64936645..91b533b1b 100644
--- a/app/templates/account/settings.jade
+++ b/app/templates/account/settings.jade
@@ -34,7 +34,7 @@ block content
               input#email.form-control(name="email", type="text", value="#{me.get('email')}")
             if !isProduction
               .form-group.checkbox
-                label(for="email", data-i18n="forms.admin") Admin
+                label(for="email", data-i18n="account_settings.admin") Admin
                 input#admin(name="admin", type="checkbox", checked=me.get('permissions').indexOf('admin')>-1))
               
   

From bcaa801f880cb7004fdbb27f8e33873aced842f0 Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Sun, 9 Mar 2014 05:04:11 +0400
Subject: [PATCH 145/178] Sync en i18n

---
 app/locale/en.coffee | 6 +++++-
 app/locale/ru.coffee | 6 ++++++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index 5ca5cf902..e3c694f82 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -122,6 +122,7 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
     wizard_tab: "Wizard"
     password_tab: "Password"
     emails_tab: "Emails"
+    admin: "Admin"
     gravatar_select: "Select which Gravatar photo to use"
     gravatar_add_photos: "Add thumbnails and photos to a Gravatar account for your email to choose an image."
     gravatar_add_more_photos: "Add more photos to your Gravatar account to access them here."
@@ -226,6 +227,8 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
     contact_us: "contact us!"
     hipchat_prefix: "You can also find us in our"
     hipchat_url: "HipChat room."
+    revert: "Revert"
+    revert_models: "Revert Models"
     level_some_options: "Some Options?"
     level_tab_thangs: "Thangs"
     level_tab_scripts: "Scripts"
@@ -270,6 +273,7 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
     description: "Description"
     or: "or"
     email: "Email"
+    password: "Password"
     message: "Message"
 
   about:
@@ -407,7 +411,7 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
     more_about_adventurer: "Learn More About Becoming an Adventurer"
     adventurer_subscribe_desc: "Get emails when there are new levels to test."
     scribe_summary_pref: "CodeCombat is not just going to be a bunch of levels. It will also be a resource of programming knowledge that players can hook into. That way, each Artisan can link to a detailed article that for the player's edification: documentation akin to what the "
-    scribe_summary_sufx: " has built. If you enjoy explaining programming concepts, then this class is for you."
+    scribe_summary_suf: " has built. If you enjoy explaining programming concepts, then this class is for you."
     scribe_introduction_pref: "CodeCombat isn't just going to be a bunch of levels. It will also include a resource for knowledge, a wiki of programming concepts that levels can hook into. That way rather than each Artisan having to describe in detail what a comparison operator is, they can simply link their level to the Article describing them that is already written for the player's edification. Something along the lines of what the "
     scribe_introduction_url_mozilla: "Mozilla Developer Network"
     scribe_introduction_suf: " has built. If your idea of fun is articulating the concepts of programming in Markdown form, then this class might be for you."
diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 6c52002e5..24c129bf9 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -251,6 +251,12 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     create_system_title: "Создать новую систему"
     new_component_title: "Создать новый компонент"
     new_component_field_system: "Система"
+    new_article_title: "Создать новую статью"
+    new_thang_title: "Создать новый объект"
+    new_level_title: "Создать новый уровень"
+    article_search_title: "Искать статьи"
+    thang_search_title: "Искать типы объектов"
+    level_search_title: "Искать уровни"
 
   article:
     edit_btn_preview: "Предпросмотр"

From 59318678bac69b6d5b276e7bc0c61cbd58513df2 Mon Sep 17 00:00:00 2001
From: Alexei Nikitin <mr-a1@yandex.ru>
Date: Sun, 9 Mar 2014 05:06:53 +0400
Subject: [PATCH 146/178] Update ru

---
 app/locale/ru.coffee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 24c129bf9..0296d95d4 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -252,7 +252,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     new_component_title: "Создать новый компонент"
     new_component_field_system: "Система"
     new_article_title: "Создать новую статью"
-    new_thang_title: "Создать новый объект"
+    new_thang_title: "Создать новый тип объектов"
     new_level_title: "Создать новый уровень"
     article_search_title: "Искать статьи"
     thang_search_title: "Искать типы объектов"

From f05e8432a9eb53bfbeb8ddc62e8910438714783a Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sat, 8 Mar 2014 18:49:09 -0800
Subject: [PATCH 147/178] Starting work on ladder update emails.

---
 server/routes/mail.coffee | 149 +++++++++++++++++++++++++++++++-------
 server/sendwithus.coffee  |   3 +-
 2 files changed, 123 insertions(+), 29 deletions(-)

diff --git a/server/routes/mail.coffee b/server/routes/mail.coffee
index d5306e16a..2e693da66 100644
--- a/server/routes/mail.coffee
+++ b/server/routes/mail.coffee
@@ -4,37 +4,130 @@ User = require '../users/User.coffee'
 errors = require '../commons/errors'
 #request = require 'request'
 config = require '../../server_config'
+LevelSession = require '../levels/sessions/LevelSession.coffee'
+log = require 'winston'
+sendwithus = require '../sendwithus'
 
 #badLog = (text) ->
 #  console.log text
 #  request.post 'http://requestb.in/1brdpaz1', { form: {log: text} }
-  
+
 module.exports.setup = (app) ->
-  app.all config.mail.mailchimpWebhook, (req, res) ->
-    post = req.body
-#    badLog("Got post data: #{JSON.stringify(post, null, '\t')}")
-    
-    unless post.type in ['unsubscribe', 'profile']
-      res.send 'Bad post type'
-      return res.end()
+  app.all config.mail.mailchimpWebhook, handleMailchimpWebHook
+  app.get '/mail/cron/ladder-update', handleLadderUpdate
 
-    unless post.data.email
-      res.send 'No email provided'
-      return res.end()
+handleLadderUpdate = (req, res) ->
+  emailDays = [1, 2, 4, 7, 30]
+  now = new Date()
+  getTimeFromDaysAgo = (daysAgo) ->
+    # 2 hours before the date
+    t = now - (86400 * daysAgo + 2 * 3600) * 1000
+  for daysAgo in emailDays
+    startTime = getTimeFromDaysAgo daysAgo
+    endTime = startTime + 5 * 60 * 1000
+    # Get every session that was submitted in a 5-minute window after the time.
+    findParameters = {submitted: true, submitDate: {$gt: startTime, $lte: endTime}}
+    # TODO: think about putting screenshots in the email
+    selectString = "creator team levelID totalScore matches"
+    query = LevelSession.find(findParameters)
+      .select(selectString)
+      .lean()
+    mongoose = require 'mongoose'
+    mongoose.set 'debug', true
+    query.exec (err, results) ->
+      log.info "Yooooo got results: #{results.length}"
+      if err
+        log.error "Couldn't fetch ladder updates for", findParameters, "\nError: ", err
+        return errors.serverError res, "Ladder update email query failed: #{JSON.stringify(err)}"
+      sendLadderUpdateEmail result, daysAgo for result in results
+      res.send('')
+      res.end()
 
-    query = {'mailChimp.leid':post.data.web_id}
-    User.findOne query, (err, user) ->
+sendLadderUpdateEmail = (session, daysAgo) ->
+  User.findOne({_id: session.creator}).select("name email firstName lastName emailSubscriptions preferredLanguage").lean().exec (err, user) ->
+    if err
+      log.error "Couldn't find user for", session.creator, "from session", session._id
+      return
+    return unless user.email and 'notification' in user.emailSubscriptions
+    name = if user.firstName and user.lastName then "#{user.firstName} #{user.lastName}" else user.name
+    name = "Wizard" if not name or name is "Anoner"
+
+    sendEmail = (defeatContext, victoryContext) ->
+      # TODO: do something with the preferredLanguage?
+      context =
+        email_id: sendwithus.templates.ladder_update_email
+        #recipient:
+        #  address: user.email
+        recipient:
+           address: 'nick@codecombat.com'
+        days_ago: daysAgo
+        name: name
+        wins: session.numberOfWinsAndTies
+        losses: session.numberOfLosses
+        total_score: session.totalScore
+        team: session.team
+        level: id
+        defeat: defeatContext
+        victory: victoryContext
+      sendwithus.api.send context, (err, result) ->
+        log.error "Error sending ladder update email:", err, 'result', result
+
+    defeats = _.filter session.matches, (match) -> match.metrics.rank is 1 and match.opponents[0].metrics.rank is 0
+    victories = _.filter session.matches, (match) -> match.metrics.rank is 0
+    defeat = _.sample defeats
+    victory = _.sample victories
+    urlForMatch = (match) ->
+      "http://codecombat.com/play/ladder/#{session.levelID}?team=#{session.team}&session=#{session._id}&opponent=#{match.opponents[0].sessionID}"
+
+    onFetchedDefeatedOpponent = (err, defeatedOpponent) ->
+      if err
+        log.error "Couldn't find defeateded opponent: #{err}"
+        defeatedOpponent = null
+      victoryContext = {opponent_name: defeatedOpponent?.name ? "Anoner", url: urlForMatch(victory)} if victory
+
+      onFetchedVictoriousOpponent = (err, victoriousOpponent) ->
+        if err
+          log.error "Couldn't find victorious opponent: #{err}"
+          victoriousOpponent = null
+        defeatContext = {opponent_name: victoriousOpponent?.name ? "Anoner", url: urlForMatch(defeat)} if defeat
+        sendEmail defeatContext, victoryContext
+
+      if defeat
+        User.findOne({_id: defeat.opponents[0].userID}).select("name").lean().exec onFetchedVictoriousOpponent
+      else
+        onFetchedVictoriousOpponent null, null
+
+    if victory
+      User.findOne({_id: victory.opponents[0].userID}).select("name").lean().exec onFetchedDefeatedOpponent
+    else
+      onFetchedDefeatedOpponent null, null
+
+
+handleMailchimpWebHook = (req, res) ->
+  post = req.body
+  #badLog("Got post data: #{JSON.stringify(post, null, '\t')}")
+
+  unless post.type in ['unsubscribe', 'profile']
+    res.send 'Bad post type'
+    return res.end()
+
+  unless post.data.email
+    res.send 'No email provided'
+    return res.end()
+
+  query = {'mailChimp.leid':post.data.web_id}
+  User.findOne query, (err, user) ->
+    return errors.serverError(res) if err
+    if not user
+      return errors.notFound(res)
+
+    handleProfileUpdate(user, post) if post.type is 'profile'
+    handleUnsubscribe(user) if post.type is 'unsubscribe'
+
+    user.updatedMailChimp = true # so as not to echo back to mailchimp
+    user.save (err) ->
       return errors.serverError(res) if err
-      if not user
-        return errors.notFound(res)
-
-      handleProfileUpdate(user, post) if post.type is 'profile'
-      handleUnsubscribe(user) if post.type is 'unsubscribe'
-
-      user.updatedMailChimp = true # so as not to echo back to mailchimp
-      user.save (err) ->
-        return errors.serverError(res) if err
-        res.end('Success')
+      res.end('Success')
 
 
 handleProfileUpdate = (user, post) ->
@@ -43,19 +136,19 @@ handleProfileUpdate = (user, post) ->
   otherSubscriptions = (g for g in user.get('emailSubscriptions') when not mail.MAILCHIMP_GROUP_MAP[g])
   groups = groups.concat otherSubscriptions
   user.set 'emailSubscriptions', groups
-  
+
   fname = post.data.merges.FNAME
   user.set('firstName', fname) if fname
 
   lname = post.data.merges.LNAME
   user.set('lastName', lname) if lname
-  
+
   user.set 'mailChimp.email', post.data.email
   user.set 'mailChimp.euid', post.data.id
-  
+
 #  badLog("Updating user object to: #{JSON.stringify(user.toObject(), null, '\t')}")
-    
+
 handleUnsubscribe = (user) ->
   user.set 'emailSubscriptions', []
 
-#  badLog("Unsubscribing user object to: #{JSON.stringify(user.toObject(), null, '\t')}") 
\ No newline at end of file
+#  badLog("Unsubscribing user object to: #{JSON.stringify(user.toObject(), null, '\t')}")
diff --git a/server/sendwithus.coffee b/server/sendwithus.coffee
index a9bb41bf4..c481893bf 100644
--- a/server/sendwithus.coffee
+++ b/server/sendwithus.coffee
@@ -10,4 +10,5 @@ module.exports.setupRoutes = (app) ->
 options = { DEBUG: not config.isProduction }
 module.exports.api = new sendwithusAPI swuAPIKey, options
 module.exports.templates =
-  welcome_email: 'utnGaBHuSU4Hmsi7qrAypU'
\ No newline at end of file
+  welcome_email: 'utnGaBHuSU4Hmsi7qrAypU'
+  ladder_update_email: 'Xq3vSbDHXcjXfje7n2e7Eb'

From ed93b2bbe56ceab2ba2747fe228bd2a862de352f Mon Sep 17 00:00:00 2001
From: Darredevil <alex.darredevil@gmail.com>
Date: Sun, 9 Mar 2014 05:53:22 +0200
Subject: [PATCH 148/178] More than half done

---
 app/locale/ro.coffee | 110 +++++++++++++++++++++----------------------
 1 file changed, 55 insertions(+), 55 deletions(-)

diff --git a/app/locale/ro.coffee b/app/locale/ro.coffee
index 1fee5fe47..e9d7e3db6 100644
--- a/app/locale/ro.coffee
+++ b/app/locale/ro.coffee
@@ -219,64 +219,64 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
     thang_title: "Editor Thang"
     thang_description: "Construiește unități ,definește logica lor,grafica și sunetul.Momentan suportă numai importare de grafică vectorială exportată din Flash."
     level_title: "Editor Nivele"
-#    level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!"
-#    security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, "
-#    contact_us: "contact us!"
-#    hipchat_prefix: "You can also find us in our"
-#    hipchat_url: "HipChat room."
-#    level_some_options: "Some Options?"
-#    level_tab_thangs: "Thangs"
-#    level_tab_scripts: "Scripts"
-#    level_tab_settings: "Settings"
-#    level_tab_components: "Components"
-#    level_tab_systems: "Systems"
-#    level_tab_thangs_title: "Current Thangs"
-#    level_tab_thangs_conditions: "Starting Conditions"
-#    level_tab_thangs_add: "Add Thangs"
-#    level_settings_title: "Settings"
-#    level_component_tab_title: "Current Components"
-#    level_component_btn_new: "Create New Component"
-#    level_systems_tab_title: "Current Systems"
-#    level_systems_btn_new: "Create New System"
-#    level_systems_btn_add: "Add System"
-#    level_components_title: "Back to All Thangs"
-#    level_components_type: "Type"
-#    level_component_edit_title: "Edit Component"
-#    level_system_edit_title: "Edit System"
-#    create_system_title: "Create New System"
-#    new_component_title: "Create New Component"
-#    new_component_field_system: "System"
+    level_description: "Include uneltele pentru scriptare, upload audio, și construcție de logică costum pentru toate tipurile de nivele.Tot ce folosim noi înșine!"
+    security_notice: "Multe setări majore de securitate în aceste editoare nu sunt momentan disponibile.Pe măsură ce îmbunătățim securitatea acestor sisteme, ele vor deveni disponibile. Dacă doriți să folosiți aceste setări mai devrme, "
+    contact_us: "contactați-ne!"
+    hipchat_prefix: "Ne puteți de asemenea găsi la"
+    hipchat_url: "HipChat."
+    level_some_options: "Opțiuni?"
+    level_tab_thangs: "Thangs"
+    level_tab_scripts: "Script-uri"
+    level_tab_settings: "Setări"
+    level_tab_components: "Componente"
+    level_tab_systems: "Sisteme"
+    level_tab_thangs_title: "Thangs actuali"
+    level_tab_thangs_conditions: "Condiți inițiale"
+    level_tab_thangs_add: "Adaugă Thangs"
+    level_settings_title: "Setări"
+    level_component_tab_title: "Componente actuale"
+    level_component_btn_new: "Crează componentă nouă"
+    level_systems_tab_title: "Sisteme actuale"
+    level_systems_btn_new: "Crează sistem nou"
+    level_systems_btn_add: "Adaugă Sistem"
+    level_components_title: "Înapoi la toți Thangs"
+    level_components_type: "Tip"
+    level_component_edit_title: "Editează Componenta"
+    level_system_edit_title: "Editează Sistem"
+    create_system_title: "Crează sistem nou"
+    new_component_title: "Crează componentă nouă"
+    new_component_field_system: "Sistem"
 
-#  article:
-#    edit_btn_preview: "Preview"
-#    edit_article_title: "Edit Article"
+  article:
+    edit_btn_preview: "Preview"
+    edit_article_title: "Editează Articol"
 
-#  general:
-#    and: "and"
-#    name: "Name"
-#    body: "Body"
-#    version: "Version"
-#    commit_msg: "Commit Message"
-#    version_history_for: "Version History for: "
-#    results: "Results"
-#    description: "Description"
-#    or: "or"
-#    email: "Email"
-#    message: "Message"
+  general:
+    and: "și"
+    name: "Nume"
+    body: "Corp"
+    version: "Versiune"
+    commit_msg: "Înregistrează Mesajul"
+    version_history_for: "Versiune istorie pentru: "
+    results: "Resultate"
+    description: "Descriere"
+    or: "sau"
+    email: "Email"
+    message: "Mesaj"
 
-#  about:
-#    who_is_codecombat: "Who is CodeCombat?"
-#    why_codecombat: "Why CodeCombat?"
-#    who_description_prefix: "together started CodeCombat in 2013. We also created "
-#    who_description_suffix: "in 2008, growing it to the #1 web and iOS application for learning to write Chinese and Japanese characters."
-#    who_description_ending: "Now it's time to teach people to write code."
-#    why_paragraph_1: "When making Skritter, George didn't know how to program and was constantly frustrated by his inability to implement his ideas. Afterwards, he tried learning, but the lessons were too slow. His housemate, wanting to reskill and stop teaching, tried Codecademy, but \"got bored.\" Each week another friend started Codecademy, then dropped off. We realized it was the same problem we'd solved with Skritter: people learning a skill via slow, intensive lessons when what they need is fast, extensive practice. We know how to fix that."
-#    why_paragraph_2: "Need to learn to code? You don't need lessons. You need to write a lot of code and have a great time doing it."
-#    why_paragraph_3_prefix: "That's what programming is about. It's gotta be fun. Not fun like"
-#    why_paragraph_3_italic: "yay a badge"
-#    why_paragraph_3_center: "but fun like"
-#    why_paragraph_3_italic_caps: "NO MOM I HAVE TO FINISH THE LEVEL!"
-#    why_paragraph_3_suffix: "That's why CodeCombat is a multiplayer game, not a gamified lesson course. We won't stop until you can't stop--but this time, that's a good thing."
+  about:
+    who_is_codecombat: "Cine este CodeCombat?"  # I assume you meant (what)
+    why_codecombat: "De ce CodeCombat?"
+    who_description_prefix: "au pornit împreuna CodeCombat în 2013. Tot noi am creat "
+    who_description_suffix: "în 2008, dezvoltând aplicația web si iOS #1 de învățat cum să scri caractere Japoneze si Chinezești."
+    who_description_ending: "Acum este timpul să învățăm oamenii să scrie cod."
+    why_paragraph_1: "Când am dezolvat Skritter, George nu știa cum să programeze și era mereu frustat de inabilitatea sa de a putea implementa ideile sale. După aceea, a încercat să învețe, dar lecțiile erau prea lente. Colegul său , vrând să se reprofilze și să se lase de predat,a încercat Codecademy, dar \"s-a plictisit.\" În fiecare săptămână un alt prieten a început Codecademy, iar apoi s-a lăsat. Am realizat că este aceeași problemă care am rezolvat-u cu Skritter: oameni încercând să învețe ceva nou prin lecții lente și intensive când defapt ceea ce le trebuie sunt lecții rapide și multă practică. Noi știm cum să rezolvăm asta."
+    why_paragraph_2: "Trebuie să înveți să programezi? Nu-ți trebuie lecții. Trebuie să scri mult cod și să te distrezi făcând asta."
+    why_paragraph_3_prefix: "Despre asta este programarea. Trebuie să fie distractiv. Nu precum"
+    why_paragraph_3_italic: "wow o insignă"
+    why_paragraph_3_center: "ci"
+    why_paragraph_3_italic_caps: "TREBUIE SĂ TERMIN ACEST NIVEL!"
+    why_paragraph_3_suffix: "De aceea CodeCombat este un joc multiplayer, nu un curs transfigurat în joc. Nu ne vom opri până când tu nu te poți opri--și de data asta, e de bine."
 #    why_paragraph_4: "If you're going to get addicted to some game, get addicted to this one and become one of the wizards of the tech age."
 #    why_ending: "And hey, it's free. "
 #    why_ending_url: "Start wizarding now!"

From 82857fd0809f4201b42d66678ea2b1d3967b9a60 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sat, 8 Mar 2014 21:29:41 -0800
Subject: [PATCH 149/178] Was able to send out some emails.

---
 server/routes/mail.coffee | 60 +++++++++++++++++++++------------------
 1 file changed, 32 insertions(+), 28 deletions(-)

diff --git a/server/routes/mail.coffee b/server/routes/mail.coffee
index 2e693da66..ed6b58795 100644
--- a/server/routes/mail.coffee
+++ b/server/routes/mail.coffee
@@ -17,31 +17,31 @@ module.exports.setup = (app) ->
   app.get '/mail/cron/ladder-update', handleLadderUpdate
 
 handleLadderUpdate = (req, res) ->
+  res.send('Great work, Captain Cron! I can take it from here.')
+  res.end()
   emailDays = [1, 2, 4, 7, 30]
   now = new Date()
   getTimeFromDaysAgo = (daysAgo) ->
     # 2 hours before the date
     t = now - (86400 * daysAgo + 2 * 3600) * 1000
   for daysAgo in emailDays
+    # Get every session that was submitted in a 5-minute window after the time.
     startTime = getTimeFromDaysAgo daysAgo
     endTime = startTime + 5 * 60 * 1000
-    # Get every session that was submitted in a 5-minute window after the time.
-    findParameters = {submitted: true, submitDate: {$gt: startTime, $lte: endTime}}
+    #endTime = startTime + 1 * 60 * 60 * 1000
+    findParameters = {submitted: true, submitDate: {$gt: new Date(startTime), $lte: new Date(endTime)}}
     # TODO: think about putting screenshots in the email
-    selectString = "creator team levelID totalScore matches"
+    selectString = "creator team levelName levelID totalScore matches submitted submitDate numberOfWinsAndTies numberOfLosses"
     query = LevelSession.find(findParameters)
       .select(selectString)
       .lean()
     mongoose = require 'mongoose'
-    mongoose.set 'debug', true
-    query.exec (err, results) ->
-      log.info "Yooooo got results: #{results.length}"
-      if err
-        log.error "Couldn't fetch ladder updates for", findParameters, "\nError: ", err
-        return errors.serverError res, "Ladder update email query failed: #{JSON.stringify(err)}"
-      sendLadderUpdateEmail result, daysAgo for result in results
-      res.send('')
-      res.end()
+    do (daysAgo) ->
+      query.exec (err, results) ->
+        if err
+          log.error "Couldn't fetch ladder updates for", findParameters, "\nError: ", err
+          return errors.serverError res, "Ladder update email query failed: #{JSON.stringify(err)}"
+        sendLadderUpdateEmail result, daysAgo for result in results
 
 sendLadderUpdateEmail = (session, daysAgo) ->
   User.findOne({_id: session.creator}).select("name email firstName lastName emailSubscriptions preferredLanguage").lean().exec (err, user) ->
@@ -56,28 +56,32 @@ sendLadderUpdateEmail = (session, daysAgo) ->
       # TODO: do something with the preferredLanguage?
       context =
         email_id: sendwithus.templates.ladder_update_email
-        #recipient:
-        #  address: user.email
         recipient:
-           address: 'nick@codecombat.com'
-        days_ago: daysAgo
-        name: name
-        wins: session.numberOfWinsAndTies
-        losses: session.numberOfLosses
-        total_score: session.totalScore
-        team: session.team
-        level: id
-        defeat: defeatContext
-        victory: victoryContext
+          #address: user.email
+          address: 'nick@codecombat.com'
+          name: name
+        email_data:
+          name: name
+          days_ago: daysAgo
+          wins: session.numberOfWinsAndTies
+          losses: session.numberOfLosses
+          total_score: Math.round(session.totalScore * 100)
+          team: session.team
+          level_name: session.levelName
+          ladder_url: "http://codecombat.com/play/ladder/#{session.levelID}#my-matches"
+          defeat: defeatContext
+          victory: victoryContext
       sendwithus.api.send context, (err, result) ->
-        log.error "Error sending ladder update email:", err, 'result', result
+        log.error "Error sending ladder update email:", err, 'result', result if err
 
+    # Fetch the most recent defeat and victory, if there are any.
+    # (We could look at strongest/weakest, but we'd have to fetch everyone, or denormalize more.)
     defeats = _.filter session.matches, (match) -> match.metrics.rank is 1 and match.opponents[0].metrics.rank is 0
     victories = _.filter session.matches, (match) -> match.metrics.rank is 0
-    defeat = _.sample defeats
-    victory = _.sample victories
+    defeat = _.last defeats
+    victory = _.last victories
     urlForMatch = (match) ->
-      "http://codecombat.com/play/ladder/#{session.levelID}?team=#{session.team}&session=#{session._id}&opponent=#{match.opponents[0].sessionID}"
+      "http://codecombat.com/play/level/#{session.levelID}?team=#{session.team}&session=#{session._id}&opponent=#{match.opponents[0].sessionID}"
 
     onFetchedDefeatedOpponent = (err, defeatedOpponent) ->
       if err

From af2b43a3097514241a73a67b418f793c1d3c2f55 Mon Sep 17 00:00:00 2001
From: Darredevil <alex.darredevil@gmail.com>
Date: Sun, 9 Mar 2014 15:09:22 +0200
Subject: [PATCH 150/178] Changed description of "Get to Locations"

---
 server/levels/level_schema.coffee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/server/levels/level_schema.coffee b/server/levels/level_schema.coffee
index cbfb84497..86f774ad0 100644
--- a/server/levels/level_schema.coffee
+++ b/server/levels/level_schema.coffee
@@ -33,7 +33,7 @@ GoalSchema = c.object {title: "Goal", description: "A goal that the player can a
   team: c.shortString(title: 'Team', description: 'Name of the team this goal is for, if it is not for all of the playable teams.')
   killThangs: c.array {title: "Kill Thangs", description: "A list of Thang IDs the player should kill, or team names.", uniqueItems: true, minItems: 1, "default": ["ogres"]}, thang
   saveThangs: c.array {title: "Save Thangs", description: "A list of Thang IDs the player should save, or team names", uniqueItems: true, minItems: 1, "default": ["humans"]}, thang
-  getToLocations: c.object {title: "Get To Locations", description: "TODO: explain", required: ["who", "targets"]},
+  getToLocations: c.object {title: "Get To Locations", description: "Will be set off when any of the \"who\" touch any of the \"targets\" ", required: ["who", "targets"]},
     who: c.array {title: "Who", description: "The Thangs who must get to the target locations.", minItems: 1}, thang
     targets: c.array {title: "Targets", description: "The target locations to which the Thangs must get.", minItems: 1}, thang
   keepFromLocations: c.object {title: "Keep From Locations", description: "TODO: explain", required: ["who", "targets"]},

From adc8c8eddf72711ede377be47c8e636feaeba122 Mon Sep 17 00:00:00 2001
From: gorodsb <gorodsb@gmail.com>
Date: Sun, 9 Mar 2014 16:47:48 +0200
Subject: [PATCH 151/178] Update uk.coffee

---
 app/locale/uk.coffee | 92 ++++++++++++++++++++++----------------------
 1 file changed, 46 insertions(+), 46 deletions(-)

diff --git a/app/locale/uk.coffee b/app/locale/uk.coffee
index 52d4fd3b4..4dede7181 100644
--- a/app/locale/uk.coffee
+++ b/app/locale/uk.coffee
@@ -1,16 +1,16 @@
 module.exports = nativeDescription: "українська мова", englishDescription: "Ukranian", translation:
   common:
     loading: "Завантаження..."
-#    saving: "Saving..."
-#    sending: "Sending..."
-#    cancel: "Cancel"
-#    save: "Save"
-#    delay_1_sec: "1 second"
-#    delay_3_sec: "3 seconds"
-#    delay_5_sec: "5 seconds"
-#    manual: "Manual"
-#    fork: "Fork"
-#    play: "Play"
+#    saving: "Збереження..."
+#    sending: "Відправлення..."
+#    cancel: "Відміна"
+#    save: "Зберегти"
+#    delay_1_sec: "1 секунда"
+#    delay_3_sec: "3 секунди"
+#    delay_5_sec: "5 секунд"
+#    manual: "Інструкція"
+#    fork: "Форк"
+#    play: "Грати"
 
   modal:
     close: "Закрити"
@@ -31,28 +31,28 @@ module.exports = nativeDescription: "українська мова", englishDesc
     about: "Про нас"
     contact: "Контакти"
     twitter_follow: "Фоловити"
-#    employers: "Employers"
+#    employers: "Зайняті"
 
 #  versions:
-#    save_version_title: "Save New Version"
-#    new_major_version: "New Major Version"
-#    cla_prefix: "To save changes, first you must agree to our"
+#    save_version_title: "Зберегти нову версію"
+#    new_major_version: "Зберегти основну версію"
+#    cla_prefix: "Для збереження змін, спочатку треба погодитись з нашим"
 #    cla_url: "CLA"
 #    cla_suffix: "."
-#    cla_agree: "I AGREE"
+#    cla_agree: "Я Згоден"
 
   login:
     sign_up: "створити акаунт"
     log_in: "Увійти"
-#    log_out: "Log Out"
+#    log_out: "Вийти"
     recover: "відновити акаунт"
 
 #  recover:
-#    recover_account_title: "Recover Account"
-#    send_password: "Send Recovery Password"
+#    recover_account_title: "Відновити акаунт"
+#    send_password: "Вислати пароль відновлення"
 
   signup:
-#    create_account_title: "Create Account to Save Progress"
+#    create_account_title: "Створити акаунт, щоб зберегти прогрес"
     description: "Це безкоштовно. Просто зробіть кілька простих кроків, щоб бути готовим до гри:"
     email_announcements: "Отримувати анонси на email"
     coppa: "Ви старші 13 років або живете не в США"
@@ -102,13 +102,13 @@ module.exports = nativeDescription: "українська мова", englishDesc
     subscribe_as_diplomat: "Записатися у Дипломати"
 
 #  wizard_settings:
-#    title: "Wizard Settings"
-#    customize_avatar: "Customize Your Avatar"
-#    clothes: "Clothes"
+#    title: "Налаштування"
+#    customize_avatar: "Налаштувати аватар"
+#    clothes: "Одяг"
 #    trim: "Trim"
 #    cloud: "Cloud"
 #    spell: "Spell"
-#    boots: "Boots"
+#    boots: "Черевики"
 #    hue: "Hue"
 #    saturation: "Saturation"
 #    lightness: "Lightness"
@@ -130,7 +130,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
     new_password_verify: "Підтвердження паролю"
     email_subscriptions: "Email-підписки"
     email_announcements: "Оголошення"
-#    email_notifications_description: "Get periodic notifications for your account."
+#    email_notifications_description: "Отримувати періодичні нагадування для Вашого акаунта."
     email_announcements_description: "Отримувати електронні листи про останні новини CodeCombat."
     contributor_emails: "Підписки за класами учасників"
     contribute_prefix: "Нам потрібні люди, які приєднаються до нашої команди! Зайдіть на "
@@ -199,18 +199,18 @@ module.exports = nativeDescription: "українська мова", englishDesc
     tome_select_a_thang: "Оберіть когось для "
     tome_available_spells: "Доступні закляття"
     hud_continue: "Продовжити (натисніть shift-space)"
-#    spell_saved: "Spell Saved"
-#    skip_tutorial: "Skip (esc)"
+#    spell_saved: "Заклинання збережено"
+#    skip_tutorial: "Пропустити (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
 #    av_entities_sub_title: "Entities"
-#    av_entities_users_url: "Users"
+#    av_entities_users_url: "користувачы"
 #    av_entities_active_instances_url: "Active Instances"
-#    av_other_sub_title: "Other"
+#    av_other_sub_title: "Ынше"
 #    av_other_debug_base_url: "Base (for debugging base.jade)"
-#    u_title: "User List"
-#    lg_title: "Latest Games"
+#    u_title: "Список користувачів"
+#    lg_title: "Останні ігри"
 
 #  editor:
 #    main_title: "CodeCombat Editors"
@@ -222,8 +222,8 @@ module.exports = nativeDescription: "українська мова", englishDesc
 #    level_title: "Level Editor"
 #    level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!"
 #    security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, "
-#    contact_us: "contact us!"
-#    hipchat_prefix: "You can also find us in our"
+#    contact_us: "Зв’язатися з нами!"
+#    hipchat_prefix: "Ви можете також знайти нас в нашому"
 #    hipchat_url: "HipChat room."
 #    level_some_options: "Some Options?"
 #    level_tab_thangs: "Thangs"
@@ -253,30 +253,30 @@ module.exports = nativeDescription: "українська мова", englishDesc
 #    edit_article_title: "Edit Article"
 
 #  general:
-#    and: "and"
-#    name: "Name"
+#    and: "та"
+#    name: "Ім’я"
 #    body: "Body"
-#    version: "Version"
+#    version: "Версія"
 #    commit_msg: "Commit Message"
 #    version_history_for: "Version History for: "
-#    results: "Results"
-#    description: "Description"
-#    or: "or"
+#    results: "Результати"
+#    description: "Опис"
+#    or: "чи"
 #    email: "Email"
-#    message: "Message"
+#    message: "Повідомлення"
 
 #  about:
-#    who_is_codecombat: "Who is CodeCombat?"
-#    why_codecombat: "Why CodeCombat?"
-#    who_description_prefix: "together started CodeCombat in 2013. We also created "
+#    who_is_codecombat: "Хто є CodeCombat?"
+#    why_codecombat: "Чому CodeCombat?"
+#    who_description_prefix: "Взагалом розпочався CodeCombat у 2013. Ми також створили "
 #    who_description_suffix: "in 2008, growing it to the #1 web and iOS application for learning to write Chinese and Japanese characters."
-#    who_description_ending: "Now it's time to teach people to write code."
+#    who_description_ending: "Зараз час вчити людей аисати код."
 #    why_paragraph_1: "When making Skritter, George didn't know how to program and was constantly frustrated by his inability to implement his ideas. Afterwards, he tried learning, but the lessons were too slow. His housemate, wanting to reskill and stop teaching, tried Codecademy, but \"got bored.\" Each week another friend started Codecademy, then dropped off. We realized it was the same problem we'd solved with Skritter: people learning a skill via slow, intensive lessons when what they need is fast, extensive practice. We know how to fix that."
 #    why_paragraph_2: "Need to learn to code? You don't need lessons. You need to write a lot of code and have a great time doing it."
 #    why_paragraph_3_prefix: "That's what programming is about. It's gotta be fun. Not fun like"
 #    why_paragraph_3_italic: "yay a badge"
 #    why_paragraph_3_center: "but fun like"
-#    why_paragraph_3_italic_caps: "NO MOM I HAVE TO FINISH THE LEVEL!"
+#    why_paragraph_3_italic_caps: "НІ, МАМО, Я МУШУ ПРОЙТИ РІВЕНЬ!"
 #    why_paragraph_3_suffix: "That's why CodeCombat is a multiplayer game, not a gamified lesson course. We won't stop until you can't stop--but this time, that's a good thing."
 #    why_paragraph_4: "If you're going to get addicted to some game, get addicted to this one and become one of the wizards of the tech age."
 #    why_ending: "And hey, it's free. "
@@ -288,10 +288,10 @@ module.exports = nativeDescription: "українська мова", englishDesc
 #    michael_description: "Programmer, sys-admin, and undergrad technical wunderkind, Michael is the person keeping our servers online."
 
 #  legal:
-#    page_title: "Legal"
+#    page_title: "Юридичні нотатки"
 #    opensource_intro: "CodeCombat is free to play and completely open source."
 #    opensource_description_prefix: "Check out "
-#    github_url: "our GitHub"
+#    github_url: "наш GitHub"
 #    opensource_description_center: "and help out if you like! CodeCombat is built on dozens of open source projects, and we love them. See "
 #    archmage_wiki_url: "our Archmage wiki"
 #    opensource_description_suffix: "for a list of the software that makes this game possible."

From 6be9ff2bb7933ecae7800c497f5704f718368d25 Mon Sep 17 00:00:00 2001
From: gorodsb <gorodsb@users.noreply.github.com>
Date: Sun, 9 Mar 2014 17:54:08 +0200
Subject: [PATCH 152/178] Update uk.coffee

---
 app/locale/uk.coffee | 94 ++++++++++++++++++++++----------------------
 1 file changed, 47 insertions(+), 47 deletions(-)

diff --git a/app/locale/uk.coffee b/app/locale/uk.coffee
index 4dede7181..b7e1bcf27 100644
--- a/app/locale/uk.coffee
+++ b/app/locale/uk.coffee
@@ -1,16 +1,16 @@
 module.exports = nativeDescription: "українська мова", englishDescription: "Ukranian", translation:
   common:
     loading: "Завантаження..."
-#    saving: "Збереження..."
-#    sending: "Відправлення..."
-#    cancel: "Відміна"
-#    save: "Зберегти"
-#    delay_1_sec: "1 секунда"
-#    delay_3_sec: "3 секунди"
-#    delay_5_sec: "5 секунд"
-#    manual: "Інструкція"
-#    fork: "Форк"
-#    play: "Грати"
+    saving: "Збереження..."
+    sending: "Відправлення..."
+    cancel: "Відміна"
+    save: "Зберегти"
+    delay_1_sec: "1 секунда"
+    delay_3_sec: "3 секунди"
+    delay_5_sec: "5 секунд"
+    manual: "Інструкція"
+    fork: "Форк"
+    play: "Грати"
 
   modal:
     close: "Закрити"
@@ -31,28 +31,28 @@ module.exports = nativeDescription: "українська мова", englishDesc
     about: "Про нас"
     contact: "Контакти"
     twitter_follow: "Фоловити"
-#    employers: "Зайняті"
+    employers: "Зайняті"
 
 #  versions:
-#    save_version_title: "Зберегти нову версію"
-#    new_major_version: "Зберегти основну версію"
-#    cla_prefix: "Для збереження змін, спочатку треба погодитись з нашим"
+    save_version_title: "Зберегти нову версію"
+    new_major_version: "Зберегти основну версію"
+    cla_prefix: "Для збереження змін, спочатку треба погодитись з нашим"
 #    cla_url: "CLA"
 #    cla_suffix: "."
-#    cla_agree: "Я Згоден"
+    cla_agree: "Я Згоден"
 
   login:
     sign_up: "створити акаунт"
     log_in: "Увійти"
-#    log_out: "Вийти"
+    log_out: "Вийти"
     recover: "відновити акаунт"
 
 #  recover:
-#    recover_account_title: "Відновити акаунт"
-#    send_password: "Вислати пароль відновлення"
+    recover_account_title: "Відновити акаунт"
+    send_password: "Вислати пароль відновлення"
 
   signup:
-#    create_account_title: "Створити акаунт, щоб зберегти прогрес"
+    create_account_title: "Створити акаунт, щоб зберегти прогрес"
     description: "Це безкоштовно. Просто зробіть кілька простих кроків, щоб бути готовим до гри:"
     email_announcements: "Отримувати анонси на email"
     coppa: "Ви старші 13 років або живете не в США"
@@ -102,13 +102,13 @@ module.exports = nativeDescription: "українська мова", englishDesc
     subscribe_as_diplomat: "Записатися у Дипломати"
 
 #  wizard_settings:
-#    title: "Налаштування"
-#    customize_avatar: "Налаштувати аватар"
-#    clothes: "Одяг"
+    title: "Налаштування"
+    customize_avatar: "Налаштувати аватар"
+    clothes: "Одяг"
 #    trim: "Trim"
 #    cloud: "Cloud"
-#    spell: "Spell"
-#    boots: "Черевики"
+    spell: "аклинанняЗ"
+    boots: "Черевики"
 #    hue: "Hue"
 #    saturation: "Saturation"
 #    lightness: "Lightness"
@@ -130,7 +130,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
     new_password_verify: "Підтвердження паролю"
     email_subscriptions: "Email-підписки"
     email_announcements: "Оголошення"
-#    email_notifications_description: "Отримувати періодичні нагадування для Вашого акаунта."
+    email_notifications_description: "Отримувати періодичні нагадування для Вашого акаунта."
     email_announcements_description: "Отримувати електронні листи про останні новини CodeCombat."
     contributor_emails: "Підписки за класами учасників"
     contribute_prefix: "Нам потрібні люди, які приєднаються до нашої команди! Зайдіть на "
@@ -199,18 +199,18 @@ module.exports = nativeDescription: "українська мова", englishDesc
     tome_select_a_thang: "Оберіть когось для "
     tome_available_spells: "Доступні закляття"
     hud_continue: "Продовжити (натисніть shift-space)"
-#    spell_saved: "Заклинання збережено"
-#    skip_tutorial: "Пропустити (esc)"
+    spell_saved: "Заклинання збережено"
+    skip_tutorial: "Пропустити (esc)"
 
 #  admin:
 #    av_title: "Admin Views"
 #    av_entities_sub_title: "Entities"
-#    av_entities_users_url: "користувачы"
+    av_entities_users_url: "користувачі"
 #    av_entities_active_instances_url: "Active Instances"
 #    av_other_sub_title: "Ынше"
 #    av_other_debug_base_url: "Base (for debugging base.jade)"
-#    u_title: "Список користувачів"
-#    lg_title: "Останні ігри"
+    u_title: "Список користувачів"
+    lg_title: "Останні ігри"
 
 #  editor:
 #    main_title: "CodeCombat Editors"
@@ -222,8 +222,8 @@ module.exports = nativeDescription: "українська мова", englishDesc
 #    level_title: "Level Editor"
 #    level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!"
 #    security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, "
-#    contact_us: "Зв’язатися з нами!"
-#    hipchat_prefix: "Ви можете також знайти нас в нашому"
+    contact_us: "Зв’язатися з нами!"
+    hipchat_prefix: "Ви можете також знайти нас в нашому"
 #    hipchat_url: "HipChat room."
 #    level_some_options: "Some Options?"
 #    level_tab_thangs: "Thangs"
@@ -253,30 +253,30 @@ module.exports = nativeDescription: "українська мова", englishDesc
 #    edit_article_title: "Edit Article"
 
 #  general:
-#    and: "та"
-#    name: "Ім’я"
+    and: "та"
+    name: "Ім’я"
 #    body: "Body"
-#    version: "Версія"
+    version: "Версія"
 #    commit_msg: "Commit Message"
 #    version_history_for: "Version History for: "
-#    results: "Результати"
-#    description: "Опис"
-#    or: "чи"
-#    email: "Email"
-#    message: "Повідомлення"
+    results: "Результати"
+    description: "Опис"
+    or: "чи"
+    email: "Email"
+    message: "Повідомлення"
 
 #  about:
-#    who_is_codecombat: "Хто є CodeCombat?"
-#    why_codecombat: "Чому CodeCombat?"
-#    who_description_prefix: "Взагалом розпочався CodeCombat у 2013. Ми також створили "
+    who_is_codecombat: "Хто є CodeCombat?"
+    why_codecombat: "Чому CodeCombat?"
+    who_description_prefix: "Взагалом розпочався CodeCombat у 2013. Ми також створили "
 #    who_description_suffix: "in 2008, growing it to the #1 web and iOS application for learning to write Chinese and Japanese characters."
-#    who_description_ending: "Зараз час вчити людей аисати код."
+    who_description_ending: "Зараз час вчити людей писати код."
 #    why_paragraph_1: "When making Skritter, George didn't know how to program and was constantly frustrated by his inability to implement his ideas. Afterwards, he tried learning, but the lessons were too slow. His housemate, wanting to reskill and stop teaching, tried Codecademy, but \"got bored.\" Each week another friend started Codecademy, then dropped off. We realized it was the same problem we'd solved with Skritter: people learning a skill via slow, intensive lessons when what they need is fast, extensive practice. We know how to fix that."
 #    why_paragraph_2: "Need to learn to code? You don't need lessons. You need to write a lot of code and have a great time doing it."
 #    why_paragraph_3_prefix: "That's what programming is about. It's gotta be fun. Not fun like"
 #    why_paragraph_3_italic: "yay a badge"
 #    why_paragraph_3_center: "but fun like"
-#    why_paragraph_3_italic_caps: "НІ, МАМО, Я МУШУ ПРОЙТИ РІВЕНЬ!"
+    why_paragraph_3_italic_caps: "НІ, МАМО, Я МАЮ ПРОЙТИ РІВЕНЬ!"
 #    why_paragraph_3_suffix: "That's why CodeCombat is a multiplayer game, not a gamified lesson course. We won't stop until you can't stop--but this time, that's a good thing."
 #    why_paragraph_4: "If you're going to get addicted to some game, get addicted to this one and become one of the wizards of the tech age."
 #    why_ending: "And hey, it's free. "
@@ -288,10 +288,10 @@ module.exports = nativeDescription: "українська мова", englishDesc
 #    michael_description: "Programmer, sys-admin, and undergrad technical wunderkind, Michael is the person keeping our servers online."
 
 #  legal:
-#    page_title: "Юридичні нотатки"
+    page_title: "Юридичні нотатки"
 #    opensource_intro: "CodeCombat is free to play and completely open source."
 #    opensource_description_prefix: "Check out "
-#    github_url: "наш GitHub"
+    github_url: "наш GitHub"
 #    opensource_description_center: "and help out if you like! CodeCombat is built on dozens of open source projects, and we love them. See "
 #    archmage_wiki_url: "our Archmage wiki"
 #    opensource_description_suffix: "for a list of the software that makes this game possible."

From 9e56540cee71a041dbc8ef25800ec54d27e40f49 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 9 Mar 2014 11:03:21 -0700
Subject: [PATCH 153/178] Uncommented out some headers in uk.coffee
 localization.

---
 app/locale/uk.coffee | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/app/locale/uk.coffee b/app/locale/uk.coffee
index b7e1bcf27..e93dae8d9 100644
--- a/app/locale/uk.coffee
+++ b/app/locale/uk.coffee
@@ -33,12 +33,12 @@ module.exports = nativeDescription: "українська мова", englishDesc
     twitter_follow: "Фоловити"
     employers: "Зайняті"
 
-#  versions:
+  versions:
     save_version_title: "Зберегти нову версію"
     new_major_version: "Зберегти основну версію"
     cla_prefix: "Для збереження змін, спочатку треба погодитись з нашим"
-#    cla_url: "CLA"
-#    cla_suffix: "."
+    cla_url: "CLA"
+    cla_suffix: "."
     cla_agree: "Я Згоден"
 
   login:
@@ -47,7 +47,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
     log_out: "Вийти"
     recover: "відновити акаунт"
 
-#  recover:
+  recover:
     recover_account_title: "Відновити акаунт"
     send_password: "Вислати пароль відновлення"
 
@@ -101,7 +101,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
     learn_more: "Узнати, як стати Дипломатом"
     subscribe_as_diplomat: "Записатися у Дипломати"
 
-#  wizard_settings:
+  wizard_settings:
     title: "Налаштування"
     customize_avatar: "Налаштувати аватар"
     clothes: "Одяг"
@@ -144,11 +144,11 @@ module.exports = nativeDescription: "українська мова", englishDesc
   account_profile:
     edit_settings: "Змінити налаштування"
     profile_for_prefix: "Профіль для "
-#    profile_for_suffix: ""
+    profile_for_suffix: ""
     profile: "Профіль"
     user_not_found: "Користувача не знайдено. Будь ласка, перевірте URL."
     gravatar_not_found_mine: "Ми не можемо знайти ваш профіль, пов'язаний з:"
-#    gravatar_not_found_email_suffix: "."
+    gravatar_not_found_email_suffix: "."
     gravatar_signup_prefix: "Зареєструйтеся на "
     gravatar_signup_suffix: " щоб продовжувати"
     gravatar_not_found_other: "Нажаль, немає профіля, що пов'язаний з електронною адресою цієї людини."
@@ -172,7 +172,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
     reload_title: "Перезавантажити весь код?"
     reload_really: "Ви впевнені, що хочете перезавантажити цей рівень і почати спочатку?"
     reload_confirm: "Перезавантажити все"
-#    victory_title_prefix: ""
+    victory_title_prefix: ""
     victory_title_suffix: " закінчено"
     victory_sign_up: "Підписатися на оновлення"
     victory_sign_up_poke: "Хочете отримувати останні новини на email? Створіть безкоштовний акаунт, і ми будемо тримати вас в курсі!"
@@ -202,17 +202,17 @@ module.exports = nativeDescription: "українська мова", englishDesc
     spell_saved: "Заклинання збережено"
     skip_tutorial: "Пропустити (esc)"
 
-#  admin:
+  admin:
 #    av_title: "Admin Views"
 #    av_entities_sub_title: "Entities"
     av_entities_users_url: "користувачі"
 #    av_entities_active_instances_url: "Active Instances"
-#    av_other_sub_title: "Ынше"
+    av_other_sub_title: "Ынше"
 #    av_other_debug_base_url: "Base (for debugging base.jade)"
     u_title: "Список користувачів"
     lg_title: "Останні ігри"
 
-#  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"
@@ -252,7 +252,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
 #    edit_btn_preview: "Preview"
 #    edit_article_title: "Edit Article"
 
-#  general:
+  general:
     and: "та"
     name: "Ім’я"
 #    body: "Body"
@@ -265,7 +265,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
     email: "Email"
     message: "Повідомлення"
 
-#  about:
+  about:
     who_is_codecombat: "Хто є CodeCombat?"
     why_codecombat: "Чому CodeCombat?"
     who_description_prefix: "Взагалом розпочався CodeCombat у 2013. Ми також створили "
@@ -287,7 +287,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
 #    jeremy_description: "Customer support mage, usability tester, and community organizer; you've probably already spoken with Jeremy."
 #    michael_description: "Programmer, sys-admin, and undergrad technical wunderkind, Michael is the person keeping our servers online."
 
-#  legal:
+  legal:
     page_title: "Юридичні нотатки"
 #    opensource_intro: "CodeCombat is free to play and completely open source."
 #    opensource_description_prefix: "Check out "

From 03abbc44cb913a6398482e204e83933242fbdd7c Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 9 Mar 2014 11:46:53 -0700
Subject: [PATCH 154/178] Better error messages for missing Component
 dependencies.

---
 app/models/Level.coffee | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/app/models/Level.coffee b/app/models/Level.coffee
index 176b09aa6..c260a8178 100644
--- a/app/models/Level.coffee
+++ b/app/models/Level.coffee
@@ -52,13 +52,14 @@ module.exports = class Level extends CocoModel
       visit = (c) ->
         return if c in sorted
         lc = _.find levelComponents, {original: c.original}
-        console.error "Couldn't find lc for", c unless lc
+        console.error thang.id, "couldn't find lc for", c unless lc
         if lc.name is "Programmable"
           # Programmable always comes last
           visit c2 for c2 in _.without thang.components, c
         else
           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
           if lc.name is "Collides"
             allied = _.find levelComponents, {name: "Allied"}

From 34983059aaa9a3aa5fc7ce5394163abc6a11891c Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 9 Mar 2014 11:52:05 -0700
Subject: [PATCH 155/178] Fixed bug with trying to show challenger modals with
 no hash to indicate we should.

---
 app/views/play/ladder_view.coffee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/views/play/ladder_view.coffee b/app/views/play/ladder_view.coffee
index 7ed43660e..11283af13 100644
--- a/app/views/play/ladder_view.coffee
+++ b/app/views/play/ladder_view.coffee
@@ -67,7 +67,7 @@ module.exports = class LadderView extends RootView
     @insertSubView(@myMatchesTab = new MyMatchesTabView({}, @level, @sessions))
     @refreshInterval = setInterval(@fetchSessionsAndRefreshViews.bind(@), 10000)
     hash = document.location.hash[1..] if document.location.hash
-    unless hash in ['my-matches', 'simulate', 'ladder']
+    if hash and not (hash in ['my-matches', 'simulate', 'ladder'])
       @showPlayModal(hash) if @sessions.loaded
 
   fetchSessionsAndRefreshViews: ->

From 3e82e0b599305ee8e99c0dbbb1a45243ac39a4ef Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 9 Mar 2014 12:53:11 -0700
Subject: [PATCH 156/178] Disallow submission of non-denormalized sessions to
 ladders.

---
 app/views/play/ladder/my_matches_tab.coffee | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
index b08a15083..f0f8ecc79 100644
--- a/app/views/play/ladder/my_matches_tab.coffee
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -15,7 +15,7 @@ module.exports = class MyMatchesTabView extends CocoView
   constructor: (options, @level, @sessions) ->
     super(options)
     @refreshMatches()
-    
+
   refreshMatches: ->
     @teams = teamDataFromLevel @level
     @nameMap = {}
@@ -68,7 +68,7 @@ module.exports = class MyMatchesTabView extends CocoView
       team.matches = (convertMatch(match) for match in team.session?.get('matches') or [])
       team.matches.reverse()
       team.score = (team.session?.get('totalScore') or 10).toFixed(2)
-      
+
     ctx
 
   afterRender: ->
@@ -80,6 +80,7 @@ module.exports = class MyMatchesTabView extends CocoView
       @setRankingButtonText button, if @readyToRank(session) then 'rank' else 'unavailable'
 
   readyToRank: (session) ->
+    return false unless session?.get('levelID')  # If it hasn't been denormalized, then it's not ready.
     c1 = session?.get('code')
     c2 = session?.get('submittedCode')
     c1 and not _.isEqual(c1, c2)
@@ -94,7 +95,7 @@ module.exports = class MyMatchesTabView extends CocoView
     @setRankingButtonText(button, 'ranking')
     success = => @setRankingButtonText(button, 'ranked')
     failure = => @setRankingButtonText(button, 'failed')
-    
+
     ajaxData = { session: sessionID, levelID: @level.id, originalLevelID: @level.attributes.original, levelMajorVersion: @level.attributes.version.major }
     $.ajax '/queue/scoring', {
       type: 'POST'

From 2d32bc1ac42ca23dd28ed7614305d955ab8046b0 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 9 Mar 2014 13:22:22 -0700
Subject: [PATCH 157/178] Reduced unnecessary name fetching.

---
 app/views/play/ladder/ladder_tab.coffee     |  4 ++++
 app/views/play/ladder/my_matches_tab.coffee | 13 +++++++++----
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/app/views/play/ladder/ladder_tab.coffee b/app/views/play/ladder/ladder_tab.coffee
index b8b2d3615..466b0a402 100644
--- a/app/views/play/ladder/ladder_tab.coffee
+++ b/app/views/play/ladder/ladder_tab.coffee
@@ -74,6 +74,10 @@ class LeaderboardData
 #      @playersBelow.once 'sync', @leaderboardPartLoaded, @
 
   leaderboardPartLoaded: ->
+    # Forget loading the up-to-date names, that's way too slow for something that refreshes all the time, we learned.
+    @loaded = true
+    @trigger 'sync'
+    return
     if @session
       if @topPlayers.loaded # and @playersAbove.loaded and @playersBelow.loaded
         @loaded = true
diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
index f0f8ecc79..998b63bfa 100644
--- a/app/views/play/ladder/my_matches_tab.coffee
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -14,23 +14,28 @@ module.exports = class MyMatchesTabView extends CocoView
 
   constructor: (options, @level, @sessions) ->
     super(options)
+    @nameMap = {}
     @refreshMatches()
 
   refreshMatches: ->
     @teams = teamDataFromLevel @level
-    @nameMap = {}
     @loadNames()
 
   loadNames: ->
+    # Only fetch the names for the userIDs we don't already have in @nameMap
     ids = []
     for session in @sessions.models
-      ids.push match.opponents[0].userID for match in session.get('matches') or []
+      for match in (session.get('matches') or [])
+        id = match.opponents[0].userID
+        ids.push id unless @nameMap[id]
 
-    success = (@nameMap) =>
+    return @finishRendering() unless ids.length
+
+    success = (nameMap) =>
       for session in @sessions.models
         for match in session.get('matches') or []
           opponent = match.opponents[0]
-          opponent.userName = @nameMap[opponent.userID]
+          @nameMap[opponent.userID] = nameMap[opponent.userID]
       @finishRendering()
 
     $.ajax('/db/user/-/names', {

From e55a43b396afc8e489ac8c77273bc0f1750ee367 Mon Sep 17 00:00:00 2001
From: Rahazan <guido.reaver@gmail.com>
Date: Sun, 9 Mar 2014 23:37:25 +0100
Subject: [PATCH 158/178] Fixed some formatting of sentences

---
 app/locale/nl.coffee | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/app/locale/nl.coffee b/app/locale/nl.coffee
index f4c45edc5..eacff6de7 100644
--- a/app/locale/nl.coffee
+++ b/app/locale/nl.coffee
@@ -103,7 +103,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
 
   wizard_settings:
     title: "Tovenaar instellingen"
-    customize_avatar: "Bewerk jouw avatar"
+    customize_avatar: "Bewerk je avatar"
     clothes: "Kleren"
     trim: "Trim"
     cloud: "Wolk"
@@ -357,7 +357,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
 
   contribute:
     page_title: "Bijdragen"
-    character_classes_title: "Karakter Klassen"
+    character_classes_title: "Karakterklassen"
     introduction_desc_intro: "We hebben hoge verwachtingen over CodeCombat."
     introduction_desc_pref: "We willen zijn waar programmeurs van alle niveaus komen om te leren en samen te spelen, anderen introduceren aan de wondere wereld van code, en de beste delen van de gemeenschap te reflecteren. We kunnen en willen dit niet alleen doen; wat projecten zoals GitHub, Stack Overflow en Linux groots en succesvol maken, zijn de mensen die deze software gebruiken en verbeteren. Daartoe, "
     introduction_desc_github_url: "CodeCombat is volledig open source"
@@ -422,7 +422,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     diplomat_launch_url: "release in oktober"
     diplomat_introduction_suf: "dan is het wel dat er een significante interesse is in CodeCombat in andere landen, vooral Brazilië! We zijn een corps aan vertalers aan het creëren dat ijverig de ene set woorden in een andere omzet om CodeCombat zo toegankelijk te maken als mogelijk in heel de wereld. Als jij het leuk vindt glimpsen op te vangen van aankomende content en deze levels zo snel mogelijk naar je landgenoten te krijgen, dan is dit de klasse voor jou."
     diplomat_attribute_1: "Vloeiend Engels en de taal waar naar je wilt vertalen kunnen spreken. Wanneer je moeilijke ideeën wilt overbrengen, is het belangrijk beide goed te kunnen!"
-    diplomat_join_pref_github: "Vind jouw taal haar locale bestand "
+    diplomat_join_pref_github: "Vind van jouw taal het locale bestand "
     diplomat_github_url: "op GitHub"
     diplomat_join_suf_github: ", edit het online, en submit een pull request. Daarnaast kun je hieronder aanvinken als je up-to-date wilt worden gehouden met nieuwe internationalisatie-ontwikkelingen."
     more_about_diplomat: "Leer meer over het worden van een geweldige Diplomaat"

From 2daa70bef4f5bd9db264f10e87b1dfa5a18d5a89 Mon Sep 17 00:00:00 2001
From: Rahazan <guido.reaver@gmail.com>
Date: Sun, 9 Mar 2014 23:45:04 +0100
Subject: [PATCH 159/178] Changed manual

Manual is ambiguous, is it manual as in "manual instead of automatic" or manual as in a handbook/guide. I thought it was the latter, so I changed it here.
---
 app/locale/nl.coffee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/locale/nl.coffee b/app/locale/nl.coffee
index eacff6de7..99a0a54dc 100644
--- a/app/locale/nl.coffee
+++ b/app/locale/nl.coffee
@@ -8,7 +8,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     delay_1_sec: "1 seconde"
     delay_3_sec: "3 secondes"
     delay_5_sec: "5 secondes"
-    manual: "Handmatig"
+    manual: "Handleiding"
     fork: "Fork"
     play: "Spelen"
 

From 66b7ba40e84550e81553c0c46904f08349d49e72 Mon Sep 17 00:00:00 2001
From: Rahazan <guido.reaver@gmail.com>
Date: Sun, 9 Mar 2014 23:54:06 +0100
Subject: [PATCH 160/178] Added missing Dutch diplomats

---
 app/templates/contribute/diplomat.jade | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/templates/contribute/diplomat.jade b/app/templates/contribute/diplomat.jade
index 06743761c..9f75161de 100644
--- a/app/templates/contribute/diplomat.jade
+++ b/app/templates/contribute/diplomat.jade
@@ -73,7 +73,7 @@ block content
           li German - Dirk, faabsen, HiroP0, Anon
           li Thai - Kamolchanok Jittrepit
           li Vietnamese - An Nguyen Hoang Thien
-          li Dutch - Glen De Cauwsemaecker
+          li Dutch - Glen De Cauwsemaecker, Guido Zuidhof, Ruben Vereecken
           li Greek - Stergios
           li Latin American Spanish - Jesús Ruppel, Matthew Burt, Mariano Luzza
           li Spain Spanish - Matthew Burt, DanielRodriguezRivero, Anon

From 3d71fcbc708bee9fd0d62530ab491f79f865307e Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 9 Mar 2014 18:46:11 -0700
Subject: [PATCH 161/178] Wins, losses, and realizing that I'm not doing server
 code right.

---
 app/templates/play/ladder/my_matches_tab.jade |  6 +-----
 app/views/play/ladder/my_matches_tab.coffee   |  3 +++
 server/routes/mail.coffee                     | 16 +++++++++++++++-
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/app/templates/play/ladder/my_matches_tab.jade b/app/templates/play/ladder/my_matches_tab.jade
index d2b543478..c70192221 100644
--- a/app/templates/play/ladder/my_matches_tab.jade
+++ b/app/templates/play/ladder/my_matches_tab.jade
@@ -11,11 +11,7 @@ div#columns.row
 
         tr
           th(colspan=4, style="color: #{team.primaryColor}")
-            span Your
-            span  
-            span= team.name
-            span  
-            span Matches
+            span Your #{team.name} Matches - #{team.wins} Wins, #{team.losses} Losses
 
             if team.session
               button.btn.btn-sm.btn-warning.pull-right.rank-button(data-session-id=team.session.id)
diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
index 998b63bfa..a5e679f1b 100644
--- a/app/views/play/ladder/my_matches_tab.coffee
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -73,6 +73,9 @@ module.exports = class MyMatchesTabView extends CocoView
       team.matches = (convertMatch(match) for match in team.session?.get('matches') or [])
       team.matches.reverse()
       team.score = (team.session?.get('totalScore') or 10).toFixed(2)
+      team.wins = _.filter(team.matches, {state: 'win'}).length
+      team.ties = _.filter(team.matches, {state: 'tie'}).length
+      team.losses = _.filter(team.matches, {state: 'loss'}).length
 
     ctx
 
diff --git a/server/routes/mail.coffee b/server/routes/mail.coffee
index ed6b58795..d629883d7 100644
--- a/server/routes/mail.coffee
+++ b/server/routes/mail.coffee
@@ -5,6 +5,7 @@ errors = require '../commons/errors'
 #request = require 'request'
 config = require '../../server_config'
 LevelSession = require '../levels/sessions/LevelSession.coffee'
+Level = require '../levels/Level.coffee'
 log = require 'winston'
 sendwithus = require '../sendwithus'
 
@@ -16,9 +17,23 @@ module.exports.setup = (app) ->
   app.all config.mail.mailchimpWebhook, handleMailchimpWebHook
   app.get '/mail/cron/ladder-update', handleLadderUpdate
 
+getAllLadderScores = (next) ->
+  query = Level.find({type: 'ladder'})
+    .select('levelID')
+    .lean()
+  query.exec (err, levels) ->
+    if err
+      log.error "Couldn't fetch ladder levels. Error: ", err
+      return next []
+    for level in levels
+      for team in ['humans', 'ogres']
+        'I ... am not doing this.'
+
 handleLadderUpdate = (req, res) ->
+  log.info("Going to see about sending ladder update emails.")
   res.send('Great work, Captain Cron! I can take it from here.')
   res.end()
+  # TODO: somehow fetch the histograms
   emailDays = [1, 2, 4, 7, 30]
   now = new Date()
   getTimeFromDaysAgo = (daysAgo) ->
@@ -35,7 +50,6 @@ handleLadderUpdate = (req, res) ->
     query = LevelSession.find(findParameters)
       .select(selectString)
       .lean()
-    mongoose = require 'mongoose'
     do (daysAgo) ->
       query.exec (err, results) ->
         if err

From 5e634f9915bfc980a59bcd4d824ef45f37ca0448 Mon Sep 17 00:00:00 2001
From: Darredevil <alex.darredevil@gmail.com>
Date: Mon, 10 Mar 2014 04:10:29 +0200
Subject: [PATCH 162/178] Update ro.coffee

Almost done.
The legal stuff is the most boring thing i ever had to translate...
---
 app/locale/ro.coffee | 140 +++++++++++++++++++++----------------------
 1 file changed, 70 insertions(+), 70 deletions(-)

diff --git a/app/locale/ro.coffee b/app/locale/ro.coffee
index e9d7e3db6..531e3825f 100644
--- a/app/locale/ro.coffee
+++ b/app/locale/ro.coffee
@@ -265,7 +265,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
     message: "Mesaj"
 
   about:
-    who_is_codecombat: "Cine este CodeCombat?"  # I assume you meant (what)
+    who_is_codecombat: "Cine este CodeCombat?"  
     why_codecombat: "De ce CodeCombat?"
     who_description_prefix: "au pornit împreuna CodeCombat în 2013. Tot noi am creat "
     who_description_suffix: "în 2008, dezvoltând aplicația web si iOS #1 de învățat cum să scri caractere Japoneze si Chinezești."
@@ -277,77 +277,77 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
     why_paragraph_3_center: "ci"
     why_paragraph_3_italic_caps: "TREBUIE SĂ TERMIN ACEST NIVEL!"
     why_paragraph_3_suffix: "De aceea CodeCombat este un joc multiplayer, nu un curs transfigurat în joc. Nu ne vom opri până când tu nu te poți opri--și de data asta, e de bine."
-#    why_paragraph_4: "If you're going to get addicted to some game, get addicted to this one and become one of the wizards of the tech age."
-#    why_ending: "And hey, it's free. "
-#    why_ending_url: "Start wizarding now!"
-#    george_description: "CEO, business guy, web designer, game designer, and champion of beginning programmers everywhere."
-#    scott_description: "Programmer extraordinaire, software architect, kitchen wizard, and master of finances. Scott is the reasonable one."
-#    nick_description: "Programming wizard, eccentric motivation mage, and upside-down experimenter. Nick can do anything and chooses to build CodeCombat."
-#    jeremy_description: "Customer support mage, usability tester, and community organizer; you've probably already spoken with Jeremy."
-#    michael_description: "Programmer, sys-admin, and undergrad technical wunderkind, Michael is the person keeping our servers online."
+    why_paragraph_4: "Dacă e să devi dependent de vreun joc, devino dependent de acesta și fi un vrăjitor al noii ere tehnologice."
+    why_ending: "Nu uita, este totul gratis. "
+    why_ending_url: "Devino un vrăjitor acum!"
+    george_description: "CEO, business guy, web designer, game designer, și campion al programatorilor începători."
+    scott_description: "Programmer extraordinaire, software architect, kitchen wizard, și  maestru al finanțelor. Scott este cel rezonabil."
+    nick_description: "Programming wizard, eccentric motivation mage, and upside-down experimenter. Nick poate să facă orice si a ales să dezvolte CodeCombat."
+    jeremy_description: "Customer support mage, usability tester, and community organizer; probabil ca ați vorbit deja cu Jeremy."
+    michael_description: "Programmer, sys-admin, and undergrad technical wunderkind, Michael este cel care ține serverele in picioare."
 
-#  legal:
-#    page_title: "Legal"
-#    opensource_intro: "CodeCombat is free to play and completely open source."
-#    opensource_description_prefix: "Check out "
-#    github_url: "our GitHub"
-#    opensource_description_center: "and help out if you like! CodeCombat is built on dozens of open source projects, and we love them. See "
-#    archmage_wiki_url: "our Archmage wiki"
-#    opensource_description_suffix: "for a list of the software that makes this game possible."
-#    practices_title: "Respectful Best Practices"
-#    practices_description: "These are our promises to you, the player, in slightly less legalese."
-#    privacy_title: "Privacy"
-#    privacy_description: "We will not sell any of your personal information. We intend to make money through recruitment eventually, but rest assured we will not distribute your personal information to interested companies without your explicit consent."
-#    security_title: "Security"
-#    security_description: "We strive to keep your personal information safe. As an open source project, our site is freely open to anyone to review and improve our security systems."
-#    email_title: "Email"
-#    email_description_prefix: "We will not inundate you with spam. Through"
-#    email_settings_url: "your email settings"
-#    email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time."
-#    cost_title: "Cost"
-#    cost_description: "Currently, CodeCombat is 100% free! One of our main goals is to keep it that way, so that as many people can play as possible, regardless of place in life. If the sky darkens, we might have to charge subscriptions or for some content, but we'd rather not. With any luck, we'll be able to sustain the company with:"
-#    recruitment_title: "Recruitment"
-#    recruitment_description_prefix: "Here on CodeCombat, you're going to become a powerful wizard–not just in the game, but also in real life."
-#    url_hire_programmers: "No one can hire programmers fast enough"
-#    recruitment_description_suffix: "so once you've sharpened your skills and if you agree, we will demo your best coding accomplishments to the thousands of employers who are drooling for the chance to hire you. They pay us a little, they pay you"
-#    recruitment_description_italic: "a lot"
-#    recruitment_description_ending: "the site remains free and everybody's happy. That's the plan."
-#    copyrights_title: "Copyrights and Licenses"
-#    contributor_title: "Contributor License Agreement"
-#    contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our"
-#    cla_url: "CLA"
-#    contributor_description_suffix: "to which you should agree before contributing."
-#    code_title: "Code - MIT"
-#    code_description_prefix: "All code owned by CodeCombat or hosted on codecombat.com, both in the GitHub repository or in the codecombat.com database, is licensed under the"
-#    mit_license_url: "MIT license"
-#    code_description_suffix: "This includes all code in Systems and Components that are made available by CodeCombat for the purpose of creating levels."
-#    art_title: "Art/Music - Creative Commons "
-#    art_description_prefix: "All common content is available under the"
-#    cc_license_url: "Creative Commons Attribution 4.0 International License"
-#    art_description_suffix: "Common content is anything made generally available by CodeCombat for the purpose of creating Levels. This includes:"
-#    art_music: "Music"
-#    art_sound: "Sound"
-#    art_artwork: "Artwork"
-#    art_sprites: "Sprites"
-#    art_other: "Any and all other non-code creative works that are made available when creating Levels."
-#    art_access: "Currently there is no universal, easy system for fetching these assets. In general, fetch them from the URLs as used by the site, contact us for assistance, or help us in extending the site to make these assets more easily accessible."
-#    art_paragraph_1: "For attribution, please name and link to codecombat.com near where the source is used or where appropriate for the medium. For example:"
-#    use_list_1: "If used in a movie or another game, include codecombat.com in the credits."
-#    use_list_2: "If used on a website, include a link near the usage, for example underneath an image, or in a general attributions page where you might also mention other Creative Commons works and open source software being used on the site. Something that's already clearly referencing CodeCombat, such as a blog post mentioning CodeCombat, does not need some separate attribution."
-#    art_paragraph_2: "If the content being used is created not by CodeCombat but instead by a user of codecombat.com, attribute them instead, and follow attribution directions provided in that resource's description if there are any."
-#    rights_title: "Rights Reserved"
-#    rights_desc: "All rights are reserved for Levels themselves. This includes"
-#    rights_scripts: "Scripts"
-#    rights_unit: "Unit configuration"
-#    rights_description: "Description"
-#    rights_writings: "Writings"
-#    rights_media: "Media (sounds, music) and any other creative content made specifically for that Level and not made generally available when creating Levels."
-#    rights_clarification: "To clarify, anything that is made available in the Level Editor for the purpose of making levels is under CC, whereas the content created with the Level Editor or uploaded in the course of creation of Levels is not."
-#    nutshell_title: "In a Nutshell"
-#    nutshell_description: "Any resources we provide in the Level Editor are free to use as you like for creating Levels. But we reserve the right to restrict distribution of the Levels themselves (that are created on codecombat.com) so that they may be charged for in the future, if that's what ends up happening."
-#    canonical: "The English version of this document is the definitive, canonical version. If there are any discrepencies between translations, the English document takes precedence."
+  legal:
+    page_title: "Aspecte Legale"
+    opensource_intro: "CodeCombat este free-to-play și complet open source."
+    opensource_description_prefix: "Vizitează "
+    github_url: "pagina noastră de GitHub"
+    opensource_description_center: "și ajută-ne dacă îți place! CodeCombat este construit peste o mulțime de proiecte open source, care noi le iubim. Vizitați"
+    archmage_wiki_url: "Archmage wiki"
+    opensource_description_suffix: "pentru o listă cu software-ul care face acest joc posibil."
+#    practices_title: "Respectful Best Practices"   #not sure what you mean here? other word for /practices/?
+    practices_description: "Acestea sunt promisiunile noastre către tine, jucătorul, fără așa mulți termeni legali."
+    privacy_title: "Confidenţialitate şi termeni"
+    privacy_description: "Noi nu vom vinde nici o informație personală. Intenționăm să obținem profit prin recrutare eventual, dar stați liniștiți , nu vă vom vinde informațiile personale companiilor interesate fără consimțământul vostru explicit."
+    security_title: "Securitate"
+    security_description: "Ne străduim să vă protejăm informațiile personale. Fiind un proiect open-source, site-ul nostru oferă oricui posibilitatea de a ne revizui și îmbunătăți sistemul de securitate."
+    email_title: "Email"
+    email_description_prefix: "Noi nu vă vom inunda cu spam. Prin"
+    email_settings_url: "setările tale de email"
+    email_description_suffix: " sau prin link-urile din email-urile care vi le trimitem, puteți să schimbați preferințele și să vâ dezabonați oricând."
+    cost_title: "Cost"
+    cost_description: "Momentan, CodeCombat este 100% gratis! Unul dintre obiectele noastre principale este să îl menținem așa, astfel încât să poată juca cât mai mulți oameni. Dacă va fi nevoie , s-ar putea să percepem o plată pentru o pentru anumite servici,dar am prefera să nu o facem. Cu puțin noroc, vom putea susține compania cu:"
+    recruitment_title: "Recrutare"
+    recruitment_description_prefix: "Aici la CodeCombat, vei deveni un vrăjitor puternic nu doar în joc , ci și în viața reală."
+    url_hire_programmers: "Nimeni nu poate angaja programatori destul de rapid"
+    recruitment_description_suffix: "așa că odată ce ți-ai dezvoltat abilitățile și esti de acord, noi vom trimite un demo cu cele mai bune realizări ale tale către miile de angajatori care se omoară să pună mâna pe tine. Pe noi ne plătesc puțin, pe tine te vor plăti"
+    recruitment_description_italic: "mult"
+    recruitment_description_ending: "site-ul rămâne gratis și toată lumea este fericită. Acesta este planul."
+    copyrights_title: "Drepturi de autor și licențe"
+    contributor_title: "Acord de licență Contributor"
+    contributor_description_prefix: "Toți contribuitorii, atât pe site cât și pe GitHub-ul nostru, sunt supuși la"
+    cla_url: "ALC"
+    contributor_description_suffix: "la care trebuie să fi de accord înainte să poți contribui."
+    code_title: "Code - MIT"
+    code_description_prefix: "Tot codul deținut de CodeCombat sau hostat pe codecombat.com, atât pe GitHub cât și în baza de date codecombat.com, este licențiată sub"
+    mit_license_url: "MIT license"
+    code_description_suffix: "Asta include tot codul din Systems și Components care este oferit de către CodeCombat cu scopul de a crea nivele."
+    art_title: "Artă/Muzică - Conținut Comun "
+    art_description_prefix: "Tot conținutul creativ/artistic este valabil sub"
+    cc_license_url: "Creative Commons Attribution 4.0 International License"
+    art_description_suffix: "Conținut comun este orice făcut general valabil de către CodeCombat cu scopul de a crea nivele. Asta include:"
+    art_music: "Muzică"
+    art_sound: "Sunet"
+    art_artwork: "Artwork"
+    art_sprites: "Sprites"  #can t be translated, either suggest alternative name or must be left like this
+    art_other: "Orice si toate celelalte creații non-cod care sunt disponibile când se crează nivele."
+    art_access: "Momentan nu există nici un sistem universal,ușor pentru preluarea acestor bunuri. În general, preluați-le precum site-ul din URL-urile folosite, contactați-ne pentru asistență, sau ajutați-ne sa extindem site-ul pentru a face aceste bunuri mai ușor accesibile."
+    art_paragraph_1: "Pentru atribuire, vă rugăm numiți și lăsați referire link la codecombat.com unde este folosită sursa  sau unde este adecvat pentru mediu. De exemplu:"
+    use_list_1: "Dacă este folosit într-un film sau alt joc, includeți codecombat.com la credite."
+    use_list_2: "Dacă este folosit pe un site, includeți un link in apropiere, de exemplu sub o imagine, sau in pagina generală de atribuiri unde menționați și alte Bunuri Creative și software open source folosit pe site. Ceva care face referință explicit la CodeCombat, precum o postare pe un blog care menționează CodeCombat, nu trebuie să facă o atribuire separată."
+    art_paragraph_2: "Dacă conținutul folosit nu este creat de către CodeCombat ci de către un utilizator al codecombat.com,atunci faceți referință către ei, și urmăriți indicațiile de atribuire prevăzute în descrierea resursei dacă există."
+    rights_title: "Drepturi rezervate"
+    rights_desc: "Toate drepturile sunt rezervate pentru Nivele în sine. Asta include"
+    rights_scripts: "Script-uri"
+    rights_unit: "Configurații de unități"
+    rights_description: "Descriere"
+    rights_writings: "Scrieri"
+    rights_media: "Media (sunete, muzică) și orice alt conținut creativ dezvoltat special pentru acel nivel care nu este valabil în mod normal pentru creat nivele."
+    rights_clarification: "Pentru a clarifica, orice este valabil in Editorul de Nivele pentru scopul de a crea nivele se află sub CC,pe când conținutul creat cu Editorul de Nivele sau încărcat pentru a face nivelul nu se află." #CC stands for...?
+    nutshell_title: "Pe scurt"
+    nutshell_description: "Orice resurse vă punem la dispoziție în Editorul de Nivele puteți folosi liber cum vreți pentru a crea nivele. Dar ne rezervăm dreptul de a rezerva distribuția de nivele în sine (care sunt create pe codecombat.com) astfel încât să se poată percepe o taxă pentru ele pe vitor, dacă se va ajunge la așa ceva."
+    canonical: "The English version of this document is the definitive, canonical version. If there are any discrepencies between translations, the English document takes precedence."
 
-#  contribute:
+  contribute:
 #    page_title: "Contributing"
 #    character_classes_title: "Character Classes"
 #    introduction_desc_intro: "We have high hopes for CodeCombat."

From 69b902f62ac8a7ad6cb2cfb01a3cacad559175b4 Mon Sep 17 00:00:00 2001
From: Michael Schmatz <schmatz@umich.edu>
Date: Mon, 10 Mar 2014 08:14:28 -0700
Subject: [PATCH 163/178] Added support for score history

---
 server/levels/sessions/level_session_schema.coffee | 12 ++++++++++++
 server/queues/scoring.coffee                       |  7 ++++++-
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/server/levels/sessions/level_session_schema.coffee b/server/levels/sessions/level_session_schema.coffee
index 290422c10..ca8df4c05 100644
--- a/server/levels/sessions/level_session_schema.coffee
+++ b/server/levels/sessions/level_session_schema.coffee
@@ -146,6 +146,18 @@ _.extend LevelSessionSchema.properties,
   numberOfLosses:
     type: 'number'
     default: 0
+    
+  scoreHistory:
+    type: 'array'
+    title: 'Score History'
+    description: 'A list of objects representing the score history of a session'
+    items: 
+      title: 'Score History Point'
+      description: 'An array with the format [unix timestamp, totalScore]'
+      type: 'array'
+      items:
+        type: 'number'
+      
 
   matches:
     type: 'array'
diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee
index 1e2cd3f29..0462cd503 100644
--- a/server/queues/scoring.coffee
+++ b/server/queues/scoring.coffee
@@ -443,10 +443,15 @@ updateScoreInSession = (scoreObject,callback) ->
     if err? then return callback err, null
 
     session = session.toObject()
+    newTotalScore = scoreObject.meanStrength - 1.8 * scoreObject.standardDeviation
+    scoreHistoryAddition = [Date.now(), newTotalScore]
     updateObject =
       meanStrength: scoreObject.meanStrength
       standardDeviation: scoreObject.standardDeviation
-      totalScore: scoreObject.meanStrength - 1.8 * scoreObject.standardDeviation
+      totalScore: newTotalScore
+      $push:
+        scoreHistory: scoreHistoryAddition        
+
     LevelSession.update {"_id": scoreObject.id}, updateObject, callback
     log.info "New total score for session #{scoreObject.id} is #{updateObject.totalScore}"
 

From c6b1d9089cd5b7802291757168adfa823030603a Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 10 Mar 2014 08:45:36 -0700
Subject: [PATCH 164/178] Fixed sounds spamming on last frame.

---
 app/lib/surface/Surface.coffee | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/app/lib/surface/Surface.coffee b/app/lib/surface/Surface.coffee
index feb87fc93..5f8ae5f49 100644
--- a/app/lib/surface/Surface.coffee
+++ b/app/lib/surface/Surface.coffee
@@ -497,13 +497,15 @@ module.exports = Surface = class Surface extends CocoClass
     # seems to be a bug where only one object can register with the Ticker...
     oldFrame = @currentFrame
     oldWorldFrame = Math.floor oldFrame
+    lastFrame = @world.totalFrames - 1
     while true
       Dropper.tick()
       @trailmaster.tick() if @trailmaster
       # Skip some frame updates unless we're playing and not at end (or we haven't drawn much yet)
-      frameAdvanced = (@playing and @currentFrame < @world.totalFrames) or @totalFramesDrawn < 2
-      @currentFrame += @world.frameRate / @options.frameRate if frameAdvanced and @playing
-      @currentFrame = Math.min(@currentFrame, @world.totalFrames - 1)
+      frameAdvanced = (@playing and @currentFrame < lastFrame) or @totalFramesDrawn < 2
+      if frameAdvanced and @playing
+        @currentFrame += @world.frameRate / @options.frameRate
+        @currentFrame = Math.min @currentFrame, lastFrame
       newWorldFrame = Math.floor @currentFrame
       worldFrameAdvanced = newWorldFrame isnt oldWorldFrame
       if worldFrameAdvanced
@@ -513,6 +515,7 @@ module.exports = Surface = class Surface extends CocoClass
       break unless Dropper.drop()
     if frameAdvanced and not worldFrameAdvanced
       # We didn't end the above loop on an integer frame, so do the world state update.
+      console.log "Restore world state"
       @restoreWorldState()
 
     # these are skipped for dropped frames

From 6a71e97204743c279a8e0b8fb672659a99871688 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 10 Mar 2014 09:37:05 -0700
Subject: [PATCH 165/178] Improvements to HUD actions.

---
 app/styles/play/level/hud.sass       | 6 +++---
 app/views/play/level/hud_view.coffee | 7 ++++---
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/app/styles/play/level/hud.sass b/app/styles/play/level/hud.sass
index 0379fc151..c83b20933 100644
--- a/app/styles/play/level/hud.sass
+++ b/app/styles/play/level/hud.sass
@@ -208,11 +208,11 @@
               height: 19px
 
               div
-                @include box-sizing(border-box)
+                border-radius: 1px
                 background-color: #6BA1C8
                 height: 100%
-                border-bottom: 2px groove #201B15
-                border-right: 1px solid #201B15
+                border-bottom: 2px groove darken(#6BA1C8, 30%)
+                border-right: 1px solid darken(#6BA1C8, 10%)
                 position: absolute
                 top: 0
 
diff --git a/app/views/play/level/hud_view.coffee b/app/views/play/level/hud_view.coffee
index 662c9fc8f..9abd6d726 100644
--- a/app/views/play/level/hud_view.coffee
+++ b/app/views/play/level/hud_view.coffee
@@ -135,7 +135,7 @@ module.exports = class HUDView extends View
     props = @$el.find('.thang-props')
     props.find(":not(.thang-name)").remove()
     props.find('.thang-name').text(if @thang.type then "#{@thang.id} - #{@thang.type}" else @thang.id)
-    propNames = @thang.hudProperties ? []
+    propNames = _.without @thang.hudProperties ? [], 'action'
     nColumns = Math.ceil propNames.length / 5
     columns = ($('<div class="thang-props-column"></div>').appendTo(props) for i in [0 ... nColumns])
     for prop, i in propNames
@@ -316,11 +316,12 @@ module.exports = class HUDView extends View
     @timespans = {}
     dt = @thang.world.dt
     actionHistory = @thang.world.actionsForThang @thang.id, true
-    [lastFrame, lastAction] = [0, 'idle']
+    console.log "got actionHistory", actionHistory
+    [lastFrame, lastAction] = [0, null]
     for hist in actionHistory.concat {frame: @thang.world.totalFrames, name: 'END'}
       [newFrame, newAction] = [hist.frame, hist.name]
       continue if newAction is lastAction
-      if newFrame > lastFrame
+      if newFrame > lastFrame and lastAction
         # TODO: don't push it if it didn't exist until then
         (@timespans[lastAction] ?= []).push [lastFrame * dt, newFrame * dt]
       [lastFrame, lastAction] = [newFrame, newAction]

From 234b3f105d8ea2f74fad3fa83b8db7d360575baf Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 10 Mar 2014 10:36:28 -0700
Subject: [PATCH 166/178] Reworked ladder game victory modal main call to
 action to actually submit game for ranking.

---
 app/lib/surface/Surface.coffee                |  1 -
 app/locale/en.coffee                          |  3 +++
 app/templates/play/level/modal/victory.jade   |  6 ++++--
 app/views/play/ladder/my_matches_tab.coffee   |  1 -
 app/views/play/level/hud_view.coffee          |  1 -
 .../play/level/modal/victory_modal.coffee     | 20 +++++++++++++++++++
 6 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/app/lib/surface/Surface.coffee b/app/lib/surface/Surface.coffee
index 5f8ae5f49..fd278b8cc 100644
--- a/app/lib/surface/Surface.coffee
+++ b/app/lib/surface/Surface.coffee
@@ -515,7 +515,6 @@ module.exports = Surface = class Surface extends CocoClass
       break unless Dropper.drop()
     if frameAdvanced and not worldFrameAdvanced
       # We didn't end the above loop on an integer frame, so do the world state update.
-      console.log "Restore world state"
       @restoreWorldState()
 
     # these are skipped for dropped frames
diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index e3c694f82..2766dda9c 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -179,6 +179,9 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
     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"
     victory_review: "Tell us more!"
diff --git a/app/templates/play/level/modal/victory.jade b/app/templates/play/level/modal/victory.jade
index 45c7f567f..6329f0bbe 100644
--- a/app/templates/play/level/modal/victory.jade
+++ b/app/templates/play/level/modal/victory.jade
@@ -14,8 +14,10 @@
     div!= body
   
   .modal-footer
-    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_home") Go Home
+    if readyToRank
+      button.btn.btn-success.rank-game-button(data-i18n="play_level.victory_rank_my_game") Rank My Game
+    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
       button.btn.btn-primary.next-level-button(data-dismiss="modal", data-i18n="play_level.victory_play_next_level") Play Next Level
     else
diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
index a5e679f1b..a094aef82 100644
--- a/app/views/play/ladder/my_matches_tab.coffee
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -94,7 +94,6 @@ module.exports = class MyMatchesTabView extends CocoView
     c1 and not _.isEqual(c1, c2)
 
   rankSession: (e) ->
-    console.log "Clicked"
     button = $(e.target).closest('.rank-button')
     sessionID = button.data('session-id')
     session = _.find @sessions.models, { id: sessionID }
diff --git a/app/views/play/level/hud_view.coffee b/app/views/play/level/hud_view.coffee
index 9abd6d726..324c5e68b 100644
--- a/app/views/play/level/hud_view.coffee
+++ b/app/views/play/level/hud_view.coffee
@@ -316,7 +316,6 @@ module.exports = class HUDView extends View
     @timespans = {}
     dt = @thang.world.dt
     actionHistory = @thang.world.actionsForThang @thang.id, true
-    console.log "got actionHistory", actionHistory
     [lastFrame, lastAction] = [0, null]
     for hist in actionHistory.concat {frame: @thang.world.totalFrames, name: 'END'}
       [newFrame, newAction] = [hist.frame, hist.name]
diff --git a/app/views/play/level/modal/victory_modal.coffee b/app/views/play/level/modal/victory_modal.coffee
index 6773982ad..c71b2bcac 100644
--- a/app/views/play/level/modal/victory_modal.coffee
+++ b/app/views/play/level/modal/victory_modal.coffee
@@ -11,6 +11,7 @@ module.exports = class VictoryModal extends View
 
   events:
     'click .next-level-button': 'onPlayNextLevel'
+    'click .rank-game-button': 'onRankGame'
 
     # review events
     'mouseover .rating i': (e) -> @showStars(@starNum($(e.target)))
@@ -58,6 +59,21 @@ 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
+    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()
+
   getRenderData: ->
     c = super()
     c.body = @body
@@ -65,6 +81,10 @@ module.exports = class VictoryModal extends View
     c.hasNextLevel = _.isObject(@level.get('nextLevel')) and (@level.get('name') isnt "Mobile Artillery")
     c.levelName = @level.get('i18n')?[me.lang()]?.name ? @level.get('name')
     c.level = @level
+    if c.level.get('type') is 'ladder'
+      c1 = @session?.get('code')
+      c2 = @session?.get('submittedCode')
+      c.readyToRank = @session.get('levelID') and c1 and not _.isEqual(c1, c2)
     if me.get 'hourOfCode'
       # Show the Hour of Code "I'm Done" tracking pixel after they played for 30 minutes
       elapsed = (new Date() - new Date(me.get('dateCreated')))

From 2ed83f4b40023edff4fd189915f521df331b521b Mon Sep 17 00:00:00 2001
From: Michael Schmatz <schmatz@umich.edu>
Date: Mon, 10 Mar 2014 10:56:33 -0700
Subject: [PATCH 167/178] Sped up my_sessions using projection, bypassing auth

---
 server/levels/level_handler.coffee | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/server/levels/level_handler.coffee b/server/levels/level_handler.coffee
index 94bf33dd8..01b7eec40 100644
--- a/server/levels/level_handler.coffee
+++ b/server/levels/level_handler.coffee
@@ -89,15 +89,27 @@ LevelHandler = class LevelHandler extends Handler
       # associated with the handler, because the handler might return a different type
       # of model, like in this case. Refactor to move that logic to the model instead.
 
-  getMySessions: (req, res, id) ->
-    @fetchLevelByIDAndHandleErrors id, req, res, (err, level) =>
+  getMySessions: (req, res, slugOrID) ->
+    findParameters = {}
+    if Handler.isID slugOrID
+      findParameters["_id"] = slugOrID
+    else
+      findParameters["slug"] = slugOrID
+    selectString = 'original version.major permissions'
+    query = Level.findOne(findParameters)
+      .select(selectString)
+      .lean()
+    
+    query.exec (err, level) =>
+      return @sendDatabaseError(res, err) if err
+      return @sendNotFoundError(res) unless level?
       sessionQuery =
         level:
           original: level.original.toString()
           majorVersion: level.version.major
         creator: req.user._id+''
-
-      query = Session.find(sessionQuery)
+      
+      query = Session.find(sessionQuery).select('-screenshot')
       query.exec (err, results) =>
         if err then @sendDatabaseError(res, err) else @sendSuccess res, results
 

From d4abad88a2f479525bdf124bc8ea78f12ac713f2 Mon Sep 17 00:00:00 2001
From: Michael Schmatz <schmatz@umich.edu>
Date: Mon, 10 Mar 2014 12:57:25 -0700
Subject: [PATCH 168/178] Removed leaderboard mongo sort

---
 server/levels/level_handler.coffee | 1 -
 1 file changed, 1 deletion(-)

diff --git a/server/levels/level_handler.coffee b/server/levels/level_handler.coffee
index 01b7eec40..4a2bdd24a 100644
--- a/server/levels/level_handler.coffee
+++ b/server/levels/level_handler.coffee
@@ -140,7 +140,6 @@ LevelHandler = class LevelHandler extends Handler
     query = Session
       .find(sessionsQueryParameters)
       .limit(req.query.limit)
-      .sort(sortParameters)
       .select(selectProperties.join ' ')
 
     query.exec (err, resultSessions) =>

From 6055512ac7bc57be4add9e633e0f90656a6555c2 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 10 Mar 2014 13:20:00 -0700
Subject: [PATCH 169/178] Working on ladder updates.

---
 app/views/account/settings_view.coffee         |  4 ++--
 app/views/modal/signup_modal.coffee            |  3 ++-
 .../sessions/level_session_handler.coffee      |  2 +-
 .../sessions/level_session_schema.coffee       | 14 +++++++++-----
 server/routes/mail.coffee                      | 18 +++++++++++-------
 server/sendwithus.coffee                       |  2 +-
 server/users/user_schema.coffee                |  6 +++---
 7 files changed, 29 insertions(+), 20 deletions(-)

diff --git a/app/views/account/settings_view.coffee b/app/views/account/settings_view.coffee
index 2f609eebd..27edf27e1 100644
--- a/app/views/account/settings_view.coffee
+++ b/app/views/account/settings_view.coffee
@@ -66,7 +66,7 @@ module.exports = class SettingsView extends View
     c.photos = me.gravatarPhotoURLs()
     c.chosenPhoto = me.getPhotoURL()
     c.subs = {}
-    c.subs[sub] = 1 for sub in c.me.get('emailSubscriptions') or ['announcement', 'tester', 'level_creator', 'developer']
+    c.subs[sub] = 1 for sub in c.me.get('emailSubscriptions') or ['announcement', 'notification', 'tester', 'level_creator', 'developer']
     c
 
   getSubscriptions: ->
@@ -88,7 +88,7 @@ module.exports = class SettingsView extends View
     if res?
       forms.applyErrorsToForm(@$el, res)
       return
-      
+
     return unless me.hasLocalChanges()
 
     res = me.save()
diff --git a/app/views/modal/signup_modal.coffee b/app/views/modal/signup_modal.coffee
index 579a938cb..d1c76e3a1 100644
--- a/app/views/modal/signup_modal.coffee
+++ b/app/views/modal/signup_modal.coffee
@@ -49,8 +49,9 @@ module.exports = class SignupModalView extends View
     userObject.emailSubscriptions ?= []
     if subscribe
       userObject.emailSubscriptions.push 'announcement' unless 'announcement' in userObject.emailSubscriptions
+      userObject.emailSubscriptions.push 'notification' unless 'notification' in userObject.emailSubscriptions
     else
-      userObject.emailSubscriptions = _.without (userObject.emailSubscriptions ? []), 'announcement'
+      userObject.emailSubscriptions = _.without (userObject.emailSubscriptions ? []), 'announcement', 'notification'
     res = tv4.validateMultiple userObject, User.schema.attributes
     return forms.applyErrorsToForm(@$el, res.errors) unless res.valid
     window.tracker?.trackEvent 'Finished Signup'
diff --git a/server/levels/sessions/level_session_handler.coffee b/server/levels/sessions/level_session_handler.coffee
index dbb3324f4..d3ab07830 100644
--- a/server/levels/sessions/level_session_handler.coffee
+++ b/server/levels/sessions/level_session_handler.coffee
@@ -7,7 +7,7 @@ class LevelSessionHandler extends Handler
   modelClass: LevelSession
   editableProperties: ['multiplayer', 'players', 'code', 'completed', 'state',
                        'levelName', 'creatorName', 'levelID', 'screenshot',
-                       'chat', 'teamSpells','submitted']
+                       'chat', 'teamSpells', 'submitted', 'unsubscribed']
 
   getByRelationship: (req, res, args...) ->
     return @sendNotFoundError(res) unless args.length is 2 and args[1] is 'active'
diff --git a/server/levels/sessions/level_session_schema.coffee b/server/levels/sessions/level_session_schema.coffee
index ca8df4c05..da4395dec 100644
--- a/server/levels/sessions/level_session_schema.coffee
+++ b/server/levels/sessions/level_session_schema.coffee
@@ -122,7 +122,7 @@ _.extend LevelSessionSchema.properties,
 
   standardDeviation:
     type:'number'
-    default:25/3
+    default: 25/3
     minimum: 0
 
   totalScore:
@@ -139,25 +139,29 @@ _.extend LevelSessionSchema.properties,
 
   submittedCode:
     type: 'object'
-    
+
+  unsubscribed:
+    type: 'boolean'
+    description: 'Whether the player has opted out of receiving email updates about ladder rankings for this session.'
+
   numberOfWinsAndTies:
     type: 'number'
     default: 0
   numberOfLosses:
     type: 'number'
     default: 0
-    
+
   scoreHistory:
     type: 'array'
     title: 'Score History'
     description: 'A list of objects representing the score history of a session'
-    items: 
+    items:
       title: 'Score History Point'
       description: 'An array with the format [unix timestamp, totalScore]'
       type: 'array'
       items:
         type: 'number'
-      
+
 
   matches:
     type: 'array'
diff --git a/server/routes/mail.coffee b/server/routes/mail.coffee
index d629883d7..4ef488b67 100644
--- a/server/routes/mail.coffee
+++ b/server/routes/mail.coffee
@@ -42,8 +42,8 @@ handleLadderUpdate = (req, res) ->
   for daysAgo in emailDays
     # Get every session that was submitted in a 5-minute window after the time.
     startTime = getTimeFromDaysAgo daysAgo
-    endTime = startTime + 5 * 60 * 1000
-    #endTime = startTime + 1 * 60 * 60 * 1000
+    #endTime = startTime + 5 * 60 * 1000
+    endTime = startTime + 1 * 60 * 60 * 1000  # Debugging: make sure there's something to send
     findParameters = {submitted: true, submitDate: {$gt: new Date(startTime), $lte: new Date(endTime)}}
     # TODO: think about putting screenshots in the email
     selectString = "creator team levelName levelID totalScore matches submitted submitDate numberOfWinsAndTies numberOfLosses"
@@ -53,16 +53,19 @@ handleLadderUpdate = (req, res) ->
     do (daysAgo) ->
       query.exec (err, results) ->
         if err
-          log.error "Couldn't fetch ladder updates for", findParameters, "\nError: ", err
+          log.error "Couldn't fetch ladder updates for #{findParameters}\nError: #{err}"
           return errors.serverError res, "Ladder update email query failed: #{JSON.stringify(err)}"
+        log.info "Found #{results.length} ladder sessions to email updates about for #{daysAgo} day(s) ago."
         sendLadderUpdateEmail result, daysAgo for result in results
 
 sendLadderUpdateEmail = (session, daysAgo) ->
   User.findOne({_id: session.creator}).select("name email firstName lastName emailSubscriptions preferredLanguage").lean().exec (err, user) ->
     if err
-      log.error "Couldn't find user for", session.creator, "from session", session._id
+      log.error "Couldn't find user for #{session.creator} from session #{session._id}"
+      return
+    if not user.email or not ('notification' in user.emailSubscriptions)
+      log.info "Not sending email to #{user.email} #{user.name} because they only want emails about #{user.emailSubscriptions}"
       return
-    return unless user.email and 'notification' in user.emailSubscriptions
     name = if user.firstName and user.lastName then "#{user.firstName} #{user.lastName}" else user.name
     name = "Wizard" if not name or name is "Anoner"
 
@@ -72,7 +75,7 @@ sendLadderUpdateEmail = (session, daysAgo) ->
         email_id: sendwithus.templates.ladder_update_email
         recipient:
           #address: user.email
-          address: 'nick@codecombat.com'
+          address: 'nick@codecombat.com'  # Debugging
           name: name
         email_data:
           name: name
@@ -85,8 +88,9 @@ sendLadderUpdateEmail = (session, daysAgo) ->
           ladder_url: "http://codecombat.com/play/ladder/#{session.levelID}#my-matches"
           defeat: defeatContext
           victory: victoryContext
+      log.info "Sending ladder update email to #{context.recipient.address} with #{context.email_data.wins} wins and #{context.email_data.losses} since #{daysAgo} day(s) ago."
       sendwithus.api.send context, (err, result) ->
-        log.error "Error sending ladder update email:", err, 'result', result if err
+        log.error "Error sending ladder update email: #{err} with result #{result}" if err
 
     # Fetch the most recent defeat and victory, if there are any.
     # (We could look at strongest/weakest, but we'd have to fetch everyone, or denormalize more.)
diff --git a/server/sendwithus.coffee b/server/sendwithus.coffee
index c481893bf..659ce5ec8 100644
--- a/server/sendwithus.coffee
+++ b/server/sendwithus.coffee
@@ -11,4 +11,4 @@ options = { DEBUG: not config.isProduction }
 module.exports.api = new sendwithusAPI swuAPIKey, options
 module.exports.templates =
   welcome_email: 'utnGaBHuSU4Hmsi7qrAypU'
-  ladder_update_email: 'Xq3vSbDHXcjXfje7n2e7Eb'
+  ladder_update_email: 'JzaZxf39A4cKMxpPZUfWy4'
diff --git a/server/users/user_schema.coffee b/server/users/user_schema.coffee
index 7ae34c4af..d43a8d6b6 100644
--- a/server/users/user_schema.coffee
+++ b/server/users/user_schema.coffee
@@ -19,7 +19,7 @@ UserSchema = c.object {},
   music: {type: 'boolean', default: true}
   #autocastDelay, or more complex autocast options? I guess I'll see what I need when trying to hook up Scott's suggested autocast behavior
 
-  emailSubscriptions: c.array {uniqueItems: true, 'default': ['announcement']}, {'enum': emailSubscriptions}
+  emailSubscriptions: c.array {uniqueItems: true, 'default': ['announcement', 'notification']}, {'enum': emailSubscriptions}
 
   # server controlled
   permissions: c.array {'default': []}, c.shortString()
@@ -29,7 +29,7 @@ UserSchema = c.object {},
   mailChimp: {type: 'object'}
   hourOfCode: {type: 'boolean'}
   hourOfCodeComplete: {type: 'boolean'}
-  
+
   emailLower: c.shortString()
   nameLower: c.shortString()
   passwordHash: {type: 'string', maxLength: 256}
@@ -40,7 +40,7 @@ UserSchema = c.object {},
 
   #Internationalization stuff
   preferredLanguage: {type: 'string', default: 'en', 'enum': c.getLanguageCodeArray()}
-  
+
   signedCLA: c.date({title: 'Date Signed the CLA'})
   wizard: c.object {},
     colorConfig: c.object {additionalProperties: c.colorConfig()}

From c88c973fa714b14c51764e5669ea2c95c2aad34d Mon Sep 17 00:00:00 2001
From: Michael Schmatz <michaelschmatz@gmail.com>
Date: Mon, 10 Mar 2014 14:18:34 -0700
Subject: [PATCH 170/178] Added 2.6.0-rc1 to allowed Mongo versions

---
 bin/coco-mongodb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/bin/coco-mongodb b/bin/coco-mongodb
index be4f285ed..4ff889493 100755
--- a/bin/coco-mongodb
+++ b/bin/coco-mongodb
@@ -71,7 +71,7 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None):
 
 
 current_directory = os.path.dirname(os.path.realpath(sys.argv[0]))
-allowedMongoVersions = ["v2.5.4","v2.5.5"]
+allowedMongoVersions = ["v2.5.4","v2.5.5","v2.6.0-rc1"]
 if which("mongod") and any(i in subprocess.check_output("mongod --version",shell=True) for i in allowedMongoVersions):
     mongo_executable = "mongod"
 else:

From 6b48577e56aed5eb3a71f6f80b781d9522c6a827 Mon Sep 17 00:00:00 2001
From: Darredevil <alex.darredevil@gmail.com>
Date: Tue, 11 Mar 2014 01:03:20 +0200
Subject: [PATCH 171/178] Update ro.coffee

---
 app/locale/ro.coffee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/locale/ro.coffee b/app/locale/ro.coffee
index 531e3825f..5038a79d8 100644
--- a/app/locale/ro.coffee
+++ b/app/locale/ro.coffee
@@ -347,7 +347,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
     nutshell_description: "Orice resurse vă punem la dispoziție în Editorul de Nivele puteți folosi liber cum vreți pentru a crea nivele. Dar ne rezervăm dreptul de a rezerva distribuția de nivele în sine (care sunt create pe codecombat.com) astfel încât să se poată percepe o taxă pentru ele pe vitor, dacă se va ajunge la așa ceva."
     canonical: "The English version of this document is the definitive, canonical version. If there are any discrepencies between translations, the English document takes precedence."
 
-  contribute:
+#  contribute:
 #    page_title: "Contributing"
 #    character_classes_title: "Character Classes"
 #    introduction_desc_intro: "We have high hopes for CodeCombat."

From 6ce65488aa727899336cff7585a893b37cee97f5 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 10 Mar 2014 20:22:25 -0700
Subject: [PATCH 172/178] Added simple rank history graph. Improving ladder
 update mail.

---
 app/templates/play/ladder/my_matches_tab.jade |  4 ++++
 app/views/play/ladder/my_matches_tab.coffee   |  9 +++++++++
 app/views/play/ladder_view.coffee             |  2 +-
 server/commons/Handler.coffee                 |  4 +++-
 server/routes/mail.coffee                     | 10 +++++++---
 5 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/app/templates/play/ladder/my_matches_tab.jade b/app/templates/play/ladder/my_matches_tab.jade
index c70192221..e9bc0dd21 100644
--- a/app/templates/play/ladder/my_matches_tab.jade
+++ b/app/templates/play/ladder/my_matches_tab.jade
@@ -21,6 +21,10 @@ div#columns.row
                 span.ranked.hidden Submitted for Ranking
                 span.failed.hidden Failed to Rank
 
+        tr
+          th(colspan=4, style="color: #{team.primaryColor}")
+            img(src="https://chart.googleapis.com/chart?chs=450x125&cht=lxy&chco=#{team.chartColor}&chtt=Score+History&chts=#{team.chartColor},16,c&chf=a,s,000000FF&chls=2&chm=o,#{team.chartColor},0,4&chd=t:#{team.chartData}")
+
         tr
           th Result
           th Opponent
diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
index a094aef82..b7708c8df 100644
--- a/app/views/play/ladder/my_matches_tab.coffee
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -76,6 +76,15 @@ module.exports = class MyMatchesTabView extends CocoView
       team.wins = _.filter(team.matches, {state: 'win'}).length
       team.ties = _.filter(team.matches, {state: 'tie'}).length
       team.losses = _.filter(team.matches, {state: 'loss'}).length
+      team.scoreHistory = team.session.get('scoreHistory')
+      team.chartColor = team.primaryColor.replace '#', ''
+      times = (s[0] for s in team.scoreHistory)
+      times = (100 * (t - times[0]) / (times[times.length - 1] - times[0]) for t in times)
+      scores = (s[1] for s in team.scoreHistory)
+      lowest = _.min scores
+      highest = _.max scores
+      scores = (100 * (s - lowest) / highest for s in scores)
+      team.chartData = times.join(',') + '|' + scores.join(',')
 
     ctx
 
diff --git a/app/views/play/ladder_view.coffee b/app/views/play/ladder_view.coffee
index 11283af13..b7cf49599 100644
--- a/app/views/play/ladder_view.coffee
+++ b/app/views/play/ladder_view.coffee
@@ -65,7 +65,7 @@ module.exports = class LadderView extends RootView
     return if @startsLoading
     @insertSubView(@ladderTab = new LadderTabView({}, @level, @sessions))
     @insertSubView(@myMatchesTab = new MyMatchesTabView({}, @level, @sessions))
-    @refreshInterval = setInterval(@fetchSessionsAndRefreshViews.bind(@), 10000)
+    @refreshInterval = setInterval(@fetchSessionsAndRefreshViews.bind(@), 10 * 1000)
     hash = document.location.hash[1..] if document.location.hash
     if hash and not (hash in ['my-matches', 'simulate', 'ladder'])
       @showPlayModal(hash) if @sessions.loaded
diff --git a/server/commons/Handler.coffee b/server/commons/Handler.coffee
index ada7acad3..4460b2d22 100644
--- a/server/commons/Handler.coffee
+++ b/server/commons/Handler.coffee
@@ -123,7 +123,9 @@ module.exports = class Handler
     # Keeping it simple for now and just allowing access to the first FETCH_LIMIT results.
     query = {'original': mongoose.Types.ObjectId(id)}
     sort = {'created': -1}
-    @modelClass.find(query).limit(FETCH_LIMIT).sort(sort).exec (err, results) =>
+    selectString = 'slug name version commitMessage created'  # Is this even working?
+    @modelClass.find(query).select(selectString).lean().limit(FETCH_LIMIT).sort(sort).exec (err, results) =>
+      return @sendDatabaseError(res, err) if err
       for doc in results
         return @sendUnauthorizedError(res) unless @hasAccessToDocument(req, doc)
       res.send(results)
diff --git a/server/routes/mail.coffee b/server/routes/mail.coffee
index 4ef488b67..5ed1fad22 100644
--- a/server/routes/mail.coffee
+++ b/server/routes/mail.coffee
@@ -42,8 +42,8 @@ handleLadderUpdate = (req, res) ->
   for daysAgo in emailDays
     # Get every session that was submitted in a 5-minute window after the time.
     startTime = getTimeFromDaysAgo daysAgo
-    #endTime = startTime + 5 * 60 * 1000
-    endTime = startTime + 1 * 60 * 60 * 1000  # Debugging: make sure there's something to send
+    endTime = startTime + 5 * 60 * 1000
+    #endTime = startTime + 1.5 * 60 * 60 * 1000  # Debugging: make sure there's something to send
     findParameters = {submitted: true, submitDate: {$gt: new Date(startTime), $lte: new Date(endTime)}}
     # TODO: think about putting screenshots in the email
     selectString = "creator team levelName levelID totalScore matches submitted submitDate numberOfWinsAndTies numberOfLosses"
@@ -63,9 +63,12 @@ sendLadderUpdateEmail = (session, daysAgo) ->
     if err
       log.error "Couldn't find user for #{session.creator} from session #{session._id}"
       return
-    if not user.email or not ('notification' in user.emailSubscriptions)
+    unless user.email and ('notification' in user.emailSubscriptions)
       log.info "Not sending email to #{user.email} #{user.name} because they only want emails about #{user.emailSubscriptions}"
       return
+    unless session.levelName
+      log.info "Not sending email to #{user.email} #{user.name} because the session had no levelName in it."
+      return
     name = if user.firstName and user.lastName then "#{user.firstName} #{user.lastName}" else user.name
     name = "Wizard" if not name or name is "Anoner"
 
@@ -84,6 +87,7 @@ sendLadderUpdateEmail = (session, daysAgo) ->
           losses: session.numberOfLosses
           total_score: Math.round(session.totalScore * 100)
           team: session.team
+          team_name: session.team[0].toUpperCase() + session.team.substr(1)
           level_name: session.levelName
           ladder_url: "http://codecombat.com/play/ladder/#{session.levelID}#my-matches"
           defeat: defeatContext

From 32baf2ae7988685baeb3585a5a63b5dc1b186fa6 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 10 Mar 2014 21:30:46 -0700
Subject: [PATCH 173/178] Improved my-matches rank history and name fetching,
 ladder update emails, ladder update unsubscribes.

---
 app/templates/play/ladder/my_matches_tab.jade |  7 ++--
 app/views/play/ladder/my_matches_tab.coffee   | 21 ++++++-----
 server/routes/auth.coffee                     | 37 ++++++++++++-------
 server/routes/mail.coffee                     | 29 ++++++++-------
 4 files changed, 55 insertions(+), 39 deletions(-)

diff --git a/app/templates/play/ladder/my_matches_tab.jade b/app/templates/play/ladder/my_matches_tab.jade
index e9bc0dd21..f40b4a04d 100644
--- a/app/templates/play/ladder/my_matches_tab.jade
+++ b/app/templates/play/ladder/my_matches_tab.jade
@@ -21,9 +21,10 @@ div#columns.row
                 span.ranked.hidden Submitted for Ranking
                 span.failed.hidden Failed to Rank
 
-        tr
-          th(colspan=4, style="color: #{team.primaryColor}")
-            img(src="https://chart.googleapis.com/chart?chs=450x125&cht=lxy&chco=#{team.chartColor}&chtt=Score+History&chts=#{team.chartColor},16,c&chf=a,s,000000FF&chls=2&chm=o,#{team.chartColor},0,4&chd=t:#{team.chartData}")
+        if team.chartData
+          tr
+            th(colspan=4, style="color: #{team.primaryColor}")
+              img(src="https://chart.googleapis.com/chart?chs=450x125&cht=lxy&chco=#{team.chartColor}&chtt=Score+History&chts=#{team.chartColor},16,c&chf=a,s,000000FF&chls=2&chm=o,#{team.chartColor},0,4&chd=t:#{team.chartData}")
 
         tr
           th Result
diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
index b7708c8df..24df7fbf1 100644
--- a/app/views/play/ladder/my_matches_tab.coffee
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -35,7 +35,7 @@ module.exports = class MyMatchesTabView extends CocoView
       for session in @sessions.models
         for match in session.get('matches') or []
           opponent = match.opponents[0]
-          @nameMap[opponent.userID] = nameMap[opponent.userID]
+          @nameMap[opponent.userID] ?= nameMap[opponent.userID]
       @finishRendering()
 
     $.ajax('/db/user/-/names', {
@@ -76,15 +76,16 @@ module.exports = class MyMatchesTabView extends CocoView
       team.wins = _.filter(team.matches, {state: 'win'}).length
       team.ties = _.filter(team.matches, {state: 'tie'}).length
       team.losses = _.filter(team.matches, {state: 'loss'}).length
-      team.scoreHistory = team.session.get('scoreHistory')
-      team.chartColor = team.primaryColor.replace '#', ''
-      times = (s[0] for s in team.scoreHistory)
-      times = (100 * (t - times[0]) / (times[times.length - 1] - times[0]) for t in times)
-      scores = (s[1] for s in team.scoreHistory)
-      lowest = _.min scores
-      highest = _.max scores
-      scores = (100 * (s - lowest) / highest for s in scores)
-      team.chartData = times.join(',') + '|' + scores.join(',')
+      team.scoreHistory = team.session?.get('scoreHistory')
+      if team.scoreHistory?.length > 1
+        team.chartColor = team.primaryColor.replace '#', ''
+        times = (s[0] for s in team.scoreHistory)
+        times = ((100 * (t - times[0]) / (times[times.length - 1] - times[0])).toFixed(1) for t in times)
+        scores = (s[1] for s in team.scoreHistory)
+        lowest = _.min scores
+        highest = _.max scores
+        scores = (Math.round(100 * (s - lowest) / (highest - lowest)) for s in scores)
+        team.chartData = times.join(',') + '|' + scores.join(',')
 
     ctx
 
diff --git a/server/routes/auth.coffee b/server/routes/auth.coffee
index 2e6dbf72d..c845b28c2 100644
--- a/server/routes/auth.coffee
+++ b/server/routes/auth.coffee
@@ -2,6 +2,7 @@ authentication = require('passport')
 LocalStrategy = require('passport-local').Strategy
 User = require('../users/User')
 UserHandler = require('../users/user_handler')
+LevelSession = require '../levels/sessions/LevelSession'
 config = require '../../server_config'
 errors = require '../commons/errors'
 mail = require '../commons/mail'
@@ -21,16 +22,16 @@ module.exports.setup = (app) ->
         if passwordReset and password.toLowerCase() is passwordReset
           User.update {_id: user.get('_id')}, {passwordReset: ''}, {}, ->
           return done(null, user)
-          
+
         hash = User.hashPassword(password)
         unless user.get('passwordHash') is hash
-          return done(null, false, {message:'is wrong, wrong, wrong', property:'password'}) 
+          return done(null, false, {message:'is wrong, wrong, wrong', property:'password'})
         return done(null, user)
       )
   ))
   app.post '/auth/spy', (req, res, next) ->
     if req?.user?.isAdmin()
-      
+
       username = req.body.usernameLower
       emailLower = req.body.emailLower
       if emailLower
@@ -39,19 +40,19 @@ module.exports.setup = (app) ->
         query = {"nameLower":username}
       else
         return errors.badInput res, "You need to supply one of emailLower or username"
-        
+
       User.findOne query, (err, user) ->
         if err? then return errors.serverError res, "There was an error finding the specified user"
-        
+
         unless user then return errors.badInput res, "The specified user couldn't be found"
-          
+
         req.logIn user, (err) ->
           if err? then return errors.serverError res, "There was an error logging in with the specified"
           res.send(UserHandler.formatEntity(req, user))
           return res.end()
     else
       return errors.unauthorized res, "You must be an admin to enter espionage mode"
-      
+
   app.post('/auth/login', (req, res, next) ->
     authentication.authenticate('local', (err, user, info) ->
       return next(err) if err
@@ -87,11 +88,11 @@ module.exports.setup = (app) ->
     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
@@ -110,7 +111,7 @@ module.exports.setup = (app) ->
     User.findOne({emailLower:req.body.email.toLowerCase()}).exec((err, user) ->
       if not user
         return errors.notFound(res, [{message:'not found.', property:'email'}])
-        
+
       user.set('passwordReset', Math.random().toString(36).slice(2,7).toUpperCase())
       user.save (err) =>
         return errors.serverError(res) if err
@@ -127,12 +128,22 @@ module.exports.setup = (app) ->
           return res.end()
     )
   )
-  
+
   app.get '/auth/unsubscribe', (req, res) ->
     email = req.query.email
     unless req.query.email
       return errors.badInput res, 'No email provided to unsubscribe.'
-      
+
+    if req.query.session
+      # Unsubscribe from just one session's notifications instead.
+      return LevelSession.findOne({_id: req.query.session}).exec (err, session) ->
+        return errors.serverError res, 'Could not unsubscribe: #{req.query.session}, #{req.query.email}: #{err}' if err
+        session.set 'unsubscribed', true
+        session.save (err) ->
+          return errors.serverError res, 'Database failure.' if err
+          res.send "Unsubscribed #{req.query.email} from CodeCombat emails for #{session.levelName} #{session.team} ladder updates. Sorry to see you go! <p><a href='/play/ladder/#{session.levelID}#my-matches'>Ladder preferences</a></p>"
+          res.end()
+
     User.findOne({emailLower:req.query.email.toLowerCase()}).exec (err, user) ->
       if not user
         return errors.notFound res, "No user found with email '#{req.query.email}'"
@@ -152,4 +163,4 @@ createMailOptions = (receiver, password) ->
     replyTo: config.mail.username
     subject: "[CodeCombat] Password Reset"
     text: "You can log into your account with: #{password}"
-#
\ No newline at end of file
+#
diff --git a/server/routes/mail.coffee b/server/routes/mail.coffee
index 5ed1fad22..a9430115b 100644
--- a/server/routes/mail.coffee
+++ b/server/routes/mail.coffee
@@ -46,7 +46,7 @@ handleLadderUpdate = (req, res) ->
     #endTime = startTime + 1.5 * 60 * 60 * 1000  # Debugging: make sure there's something to send
     findParameters = {submitted: true, submitDate: {$gt: new Date(startTime), $lte: new Date(endTime)}}
     # TODO: think about putting screenshots in the email
-    selectString = "creator team levelName levelID totalScore matches submitted submitDate numberOfWinsAndTies numberOfLosses"
+    selectString = "creator team levelName levelID totalScore matches submitted submitDate"
     query = LevelSession.find(findParameters)
       .select(selectString)
       .lean()
@@ -63,8 +63,8 @@ sendLadderUpdateEmail = (session, daysAgo) ->
     if err
       log.error "Couldn't find user for #{session.creator} from session #{session._id}"
       return
-    unless user.email and ('notification' in user.emailSubscriptions)
-      log.info "Not sending email to #{user.email} #{user.name} because they only want emails about #{user.emailSubscriptions}"
+    unless user.email and ('notification' in user.emailSubscriptions) and not session.unsubscribed
+      log.info "Not sending email to #{user.email} #{user.name} because they only want emails about #{user.emailSubscriptions} - session unsubscribed: #{session.unsubscribed}"
       return
     unless session.levelName
       log.info "Not sending email to #{user.email} #{user.name} because the session had no levelName in it."
@@ -72,23 +72,32 @@ sendLadderUpdateEmail = (session, daysAgo) ->
     name = if user.firstName and user.lastName then "#{user.firstName} #{user.lastName}" else user.name
     name = "Wizard" if not name or name is "Anoner"
 
+    # Fetch the most recent defeat and victory, if there are any.
+    # (We could look at strongest/weakest, but we'd have to fetch everyone, or denormalize more.)
+    matches = _.filter session.matches, (match) -> match.date >= (new Date() - 86400 * 1000 * daysAgo)
+    defeats = _.filter matches, (match) -> match.metrics.rank is 1 and match.opponents[0].metrics.rank is 0
+    victories = _.filter matches, (match) -> match.metrics.rank is 0
+    defeat = _.last defeats
+    victory = _.last victories
+
     sendEmail = (defeatContext, victoryContext) ->
       # TODO: do something with the preferredLanguage?
       context =
         email_id: sendwithus.templates.ladder_update_email
         recipient:
-          #address: user.email
-          address: 'nick@codecombat.com'  # Debugging
+          address: user.email
+          #address: 'nick@codecombat.com'  # Debugging
           name: name
         email_data:
           name: name
           days_ago: daysAgo
-          wins: session.numberOfWinsAndTies
-          losses: session.numberOfLosses
+          wins: victories.length
+          losses: defeats.length
           total_score: Math.round(session.totalScore * 100)
           team: session.team
           team_name: session.team[0].toUpperCase() + session.team.substr(1)
           level_name: session.levelName
+          session_id: session._id
           ladder_url: "http://codecombat.com/play/ladder/#{session.levelID}#my-matches"
           defeat: defeatContext
           victory: victoryContext
@@ -96,12 +105,6 @@ sendLadderUpdateEmail = (session, daysAgo) ->
       sendwithus.api.send context, (err, result) ->
         log.error "Error sending ladder update email: #{err} with result #{result}" if err
 
-    # Fetch the most recent defeat and victory, if there are any.
-    # (We could look at strongest/weakest, but we'd have to fetch everyone, or denormalize more.)
-    defeats = _.filter session.matches, (match) -> match.metrics.rank is 1 and match.opponents[0].metrics.rank is 0
-    victories = _.filter session.matches, (match) -> match.metrics.rank is 0
-    defeat = _.last defeats
-    victory = _.last victories
     urlForMatch = (match) ->
       "http://codecombat.com/play/level/#{session.levelID}?team=#{session.team}&session=#{session._id}&opponent=#{match.opponents[0].sessionID}"
 

From eac219a2be8b7277d2985629d2abad769bfbdb1b Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 10 Mar 2014 22:03:33 -0700
Subject: [PATCH 174/178] Inserted score history graph into ladder update
 emails.

---
 app/templates/play/ladder/my_matches_tab.jade |  2 +-
 app/views/play/ladder/my_matches_tab.coffee   |  1 +
 server/routes/mail.coffee                     | 19 +++++++++++++++++--
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/app/templates/play/ladder/my_matches_tab.jade b/app/templates/play/ladder/my_matches_tab.jade
index f40b4a04d..0eb83dddb 100644
--- a/app/templates/play/ladder/my_matches_tab.jade
+++ b/app/templates/play/ladder/my_matches_tab.jade
@@ -24,7 +24,7 @@ div#columns.row
         if team.chartData
           tr
             th(colspan=4, style="color: #{team.primaryColor}")
-              img(src="https://chart.googleapis.com/chart?chs=450x125&cht=lxy&chco=#{team.chartColor}&chtt=Score+History&chts=#{team.chartColor},16,c&chf=a,s,000000FF&chls=2&chm=o,#{team.chartColor},0,4&chd=t:#{team.chartData}")
+              img(src="https://chart.googleapis.com/chart?chs=450x125&cht=lxy&chco=#{team.chartColor}&chtt=Score%3A+#{team.currentScore}&chts=#{team.chartColor},16,c&chf=a,s,000000FF&chls=2&chm=o,#{team.chartColor},0,4&chd=t:#{team.chartData}")
 
         tr
           th Result
diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
index 24df7fbf1..660114111 100644
--- a/app/views/play/ladder/my_matches_tab.coffee
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -78,6 +78,7 @@ module.exports = class MyMatchesTabView extends CocoView
       team.losses = _.filter(team.matches, {state: 'loss'}).length
       team.scoreHistory = team.session?.get('scoreHistory')
       if team.scoreHistory?.length > 1
+        team.currentScore = Math.round team.scoreHistory[team.scoreHistory.length - 1][1] * 100
         team.chartColor = team.primaryColor.replace '#', ''
         times = (s[0] for s in team.scoreHistory)
         times = ((100 * (t - times[0]) / (times[times.length - 1] - times[0])).toFixed(1) for t in times)
diff --git a/server/routes/mail.coffee b/server/routes/mail.coffee
index a9430115b..5ad2dfcd4 100644
--- a/server/routes/mail.coffee
+++ b/server/routes/mail.coffee
@@ -46,7 +46,7 @@ handleLadderUpdate = (req, res) ->
     #endTime = startTime + 1.5 * 60 * 60 * 1000  # Debugging: make sure there's something to send
     findParameters = {submitted: true, submitDate: {$gt: new Date(startTime), $lte: new Date(endTime)}}
     # TODO: think about putting screenshots in the email
-    selectString = "creator team levelName levelID totalScore matches submitted submitDate"
+    selectString = "creator team levelName levelID totalScore matches submitted submitDate scoreHistory"
     query = LevelSession.find(findParameters)
       .select(selectString)
       .lean()
@@ -69,7 +69,7 @@ sendLadderUpdateEmail = (session, daysAgo) ->
     unless session.levelName
       log.info "Not sending email to #{user.email} #{user.name} because the session had no levelName in it."
       return
-    name = if user.firstName and user.lastName then "#{user.firstName} #{user.lastName}" else user.name
+    name = if user.firstName and user.lastName then "#{user.firstName}" else user.name
     name = "Wizard" if not name or name is "Anoner"
 
     # Fetch the most recent defeat and victory, if there are any.
@@ -99,6 +99,7 @@ sendLadderUpdateEmail = (session, daysAgo) ->
           level_name: session.levelName
           session_id: session._id
           ladder_url: "http://codecombat.com/play/ladder/#{session.levelID}#my-matches"
+          score_history_graph_url: getScoreHistoryGraphURL session, daysAgo
           defeat: defeatContext
           victory: victoryContext
       log.info "Sending ladder update email to #{context.recipient.address} with #{context.email_data.wins} wins and #{context.email_data.losses} since #{daysAgo} day(s) ago."
@@ -131,6 +132,20 @@ sendLadderUpdateEmail = (session, daysAgo) ->
     else
       onFetchedDefeatedOpponent null, null
 
+getScoreHistoryGraphURL = (session, daysAgo) ->
+  # Totally duplicated in My Matches tab for now until we figure out what we're doing.
+  since = new Date() - 86400 * 1000 * daysAgo
+  scoreHistory = (s for s in session.scoreHistory ? [] when s[0] >= since)
+  return '' unless scoreHistory.length > 1
+  times = (s[0] for s in scoreHistory)
+  times = ((100 * (t - times[0]) / (times[times.length - 1] - times[0])).toFixed(1) for t in times)
+  scores = (s[1] for s in scoreHistory)
+  lowest = _.min scores
+  highest = _.max scores
+  scores = (Math.round(100 * (s - lowest) / (highest - lowest)) for s in scores)
+  currentScore = Math.round scoreHistory[scoreHistory.length - 1][1] * 100
+  chartData = times.join(',') + '|' + scores.join(',')
+  "https://chart.googleapis.com/chart?chs=600x75&cht=lxy&chtt=Score%3A+#{currentScore}&chts=222222,12,r&chf=a,s,000000FF&chls=2&chd=t:#{chartData}"
 
 handleMailchimpWebHook = (req, res) ->
   post = req.body

From 4062bba245829b185827eda47d2835bcbaa11e35 Mon Sep 17 00:00:00 2001
From: Michael Schmatz <schmatz@umich.edu>
Date: Tue, 11 Mar 2014 13:12:40 -0700
Subject: [PATCH 175/178] Created initial spectate level view

---
 app/styles/play/spectate.sass       | 152 +++++++++++++++++++++
 app/templates/play/spectate.jade    |  16 ++-
 app/views/play/spectate_view.coffee | 199 ++++++++++++++++++++++------
 3 files changed, 323 insertions(+), 44 deletions(-)
 create mode 100644 app/styles/play/spectate.sass

diff --git a/app/styles/play/spectate.sass b/app/styles/play/spectate.sass
new file mode 100644
index 000000000..9de885caa
--- /dev/null
+++ b/app/styles/play/spectate.sass
@@ -0,0 +1,152 @@
+@import "app/styles/bootstrap/mixins"
+@import "app/styles/mixins"
+
+#spectate-level-view
+  margin: 0 auto
+  @include user-select(none)
+
+  .level-content
+    position: relative
+
+  #canvas-wrapper
+    width: 55%
+    position: relative
+
+  canvas#surface
+    background-color: #ddd
+    width: 100%
+    display: block
+    z-index: 1
+
+
+  //max-width: 1680px   // guideline, but for now let's let it stretch out
+  min-width: 1024px
+  position: relative
+
+  #code-area
+    @include box-sizing(border-box)
+    padding: 10px 1%
+    width: 45%
+    background: transparent url(/images/level/wood_texture.png)
+    background-size: 100% 100%
+    position: absolute
+    right: 0
+    top: 0px
+    bottom: 0
+
+  #pointer
+    position: absolute
+    left: 0
+    top: 0
+    height: 100px
+    opacity: 0.0
+    pointer-events: none
+    z-index: 10
+
+  // Level Docs
+  .ui-effects-transfer
+    border: 2px dotted gray
+
+  .modal
+    img
+      float: right
+
+    img.diagram
+      float: none
+
+  #multiplayer-join-link
+    font-size: 12px
+
+  #level-done-button
+    position: absolute
+    right: 46%
+    top: 43px
+    @include box-shadow(4px 4px 15px black)
+
+  // Custom Buttons
+  .btn.banner
+    @include banner-button(#FFF, #333)
+    @include box-shadow(2px 2px 2px rgba(0, 0, 0, 0.5))
+    border: 1px solid black
+    text-shadow: none
+
+    $buttonConfig: 'primary' #6CA8EA, 'info' #71AACC, 'success' #90B236, 'warning' #CD6800, 'danger' #B43C20, 'inverse' #3A537F
+    @each $tuple in $buttonConfig
+      &.btn-#{nth($tuple, 1)}
+        @include banner-button(nth($tuple, 2), #FFF)
+
+  .footer .footer-link-text a
+    @include opacity(0.75)
+    @include transition(opacity .10s linear)
+
+    &:hover, &:active
+      @include opacity(1)
+
+  $GI: 0.5  // gradient intensity; can tweak this 0-1
+
+  .gradient
+    position: absolute
+    z-index: 10
+
+  #code-area-gradient
+    top: 0px
+    width: 3px
+    background: linear-gradient(to right, rgba(0,0,0,0) 0%,rgba(0,0,0,$GI) 100%)
+    left: -3px
+    bottom: 0
+
+  #hud-top-gradient
+    top: -32px
+    background: linear-gradient(to bottom, rgba(0,0,0,0) 0%,rgba(0,0,0,0.8*$GI) 100%)
+    left: 0
+    right: 0
+    bottom: 0
+    height: 3px
+
+  #canvas-left-gradient
+    left: 0px
+    width: 5px
+    background: linear-gradient(to left, rgba(0,0,0,0) 0%,rgba(0,0,0,0.8*$GI) 100%)
+    bottom: -30px
+    top: 0
+
+  #canvas-top-gradient
+    top: 0
+    height: 5px
+    left: 0
+    right: 0
+    background: linear-gradient(to top, rgba(0,0,0,0) 0%,rgba(0,0,0,0.8*$GI) 100%)
+
+  #hud-left-gradient
+    background: linear-gradient(to right, rgba(0,0,0,$GI) 0%,rgba(0,0,0,0) 100%)
+    left: 0
+    top: 0
+    height: 100%
+    width: 2%
+
+  #hud-right-gradient
+    background: linear-gradient(to right, rgba(0,0,0,0) 0%,rgba(0,0,0,$GI) 100%)
+    right: 0
+    position: absolute
+    top: 0
+    height: 100%
+    width: 2%
+
+  .footer
+    @media screen and (min-aspect-ratio: 17/10)
+      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
diff --git a/app/templates/play/spectate.jade b/app/templates/play/spectate.jade
index 9be37b46a..cfaba9234 100644
--- a/app/templates/play/spectate.jade
+++ b/app/templates/play/spectate.jade
@@ -1,16 +1,22 @@
 .level-content
   #control-bar-view
-
   #canvas-wrapper
-    canvas(width=924, height=589)#surface
+    canvas(width=1848, height=1178)#surface
     #canvas-left-gradient.gradient
     #canvas-top-gradient.gradient
-  #goals-view.hide
-  #gold-view.hide.expanded
+  #gold-view.secret.expanded
   #level-chat-view
   #playback-view
   #thang-hud
 .footer
   .content
     p(class='footer-link-text')
-      a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="nav.contact") Contact
+      a(title='Send CodeCombat a message', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="nav.contact") Contact
+    if explainHourOfCode
+      // Does not show up unless lang is en-US.
+      div.hour-of-code-explanation
+        | The 'Hour of Code' is a nationwide initiative by 
+        a(href="http://csedweek.org") Computer Science Education Week
+        | and 
+        a(href="http://code.org") Code.org
+        | to introduce millions of students to one hour of computer science and computer programming.
\ No newline at end of file
diff --git a/app/views/play/spectate_view.coffee b/app/views/play/spectate_view.coffee
index e2686e90d..17dbcf6d3 100644
--- a/app/views/play/spectate_view.coffee
+++ b/app/views/play/spectate_view.coffee
@@ -5,7 +5,6 @@ ThangType = require 'models/ThangType'
 
 # temp hard coded data
 World = require 'lib/world/world'
-docs = require 'lib/world/docs'
 
 # tools
 Surface = require 'lib/surface/Surface'
@@ -17,7 +16,9 @@ LevelLoader = require 'lib/LevelLoader'
 LevelSession = require 'models/LevelSession'
 Level = require 'models/Level'
 LevelComponent = require 'models/LevelComponent'
+Article = require 'models/Article'
 Camera = require 'lib/surface/Camera'
+AudioPlayer = require 'lib/AudioPlayer'
 
 # subviews
 TomeView = require './level/tome/tome_view'
@@ -34,8 +35,6 @@ LoadingScreen = require 'lib/LoadingScreen'
 
 PROFILE_ME = false
 
-PlayLevelView = require './level_view'
-
 module.exports = class SpectateLevelView extends View
   id: 'spectate-level-view'
   template: template
@@ -46,6 +45,8 @@ module.exports = class SpectateLevelView extends View
 
   subscriptions:
     'level-set-volume': (e) -> createjs.Sound.setVolume(e.volume)
+    'level-show-victory': 'onShowVictory'
+    'restart-level': 'onRestartLevel'
     'level-highlight-dom': 'onHighlightDom'
     'end-level-highlight-dom': 'onEndHighlight'
     'level-focus-dom': 'onFocusDom'
@@ -53,33 +54,33 @@ module.exports = class SpectateLevelView extends View
     'level-enable-controls': 'onEnableControls'
     'god:new-world-created': 'onNewWorld'
     'god:infinite-loop': 'onInfiniteLoop'
+    'level-reload-from-data': 'onLevelReloadFromData'
+    'play-next-level': 'onPlayNextLevel'
     'edit-wizard-settings': 'showWizardSettingsModal'
     'surface:world-set-up': 'onSurfaceSetUpNewWorld'
     'level:session-will-save': 'onSessionWillSave'
     'level:set-team': 'setTeam'
+    'god:new-world-created': 'loadSoundsForWorld'
 
   events:
     'click #level-done-button': 'onDonePressed'
 
+  shortcuts:
+    'ctrl+s': 'onCtrlS'
 
   constructor: (options, @levelID) ->
     console.profile?() if PROFILE_ME
     super options
-    console.log @levelID
-
-    @ogreSessionID = @getQueryVariable 'ogres'
-    @humanSessionID = @getQueryVariable 'humans'
 
+    @sessionID = @getQueryVariable 'session'
 
     $(window).on('resize', @onWindowResize)
-    @supermodel.once 'error', =>
-      msg = $.i18n.t('play_level.level_load_error', defaultValue: "Level could not be loaded.")
-      @$el.html('<div class="alert">' + msg + '</div>')
-
+    @supermodel.once 'error', @onLevelLoadError
 
     @load()
 
-
+  onLevelLoadError: (e) =>
+    application.router.navigate "/play?not_found=#{@levelID}", {trigger: true}
 
   setLevel: (@level, @supermodel) ->
     @god?.level = @level.serialize @supermodel
@@ -91,7 +92,8 @@ module.exports = class SpectateLevelView extends View
 
   load: ->
     @levelLoader = new LevelLoader supermodel: @supermodel, levelID: @levelID, sessionID: @sessionID, opponentSessionID: @getQueryVariable('opponent'), team: @getQueryVariable("team")
-    @levelLoader.once 'loaded-all', @onLevelLoaderLoaded
+    @levelLoader.once 'loaded-all', @onLevelLoaderLoaded, @
+    @levelLoader.on 'progress', @onLevelLoaderProgressChanged, @
     @god = new God()
 
   getRenderData: ->
@@ -103,30 +105,83 @@ module.exports = class SpectateLevelView extends View
     window.onPlayLevelViewLoaded? @  # still a hack
     @loadingScreen = new LoadingScreen(@$el.find('canvas')[0])
     @loadingScreen.show()
+    @$el.find('#level-done-button').hide()
     super()
 
-  onLevelLoaderLoaded: =>
-    #needs editing
-    @session = @levelLoader.session
-    @world = @levelLoader.world
-    @level = @levelLoader.level
-    @levelLoader.destroy()
-    @levelLoader = null
+  onLevelLoaderProgressChanged: ->
+    return if @seenDocs
+    return unless showFrequency = @levelLoader.level.get('showGuide')
+    session = @levelLoader.session
+    diff = new Date().getTime() - new Date(session.get('created')).getTime()
+    return if showFrequency is 'first-time' and diff > (5 * 60 * 1000)
+    return unless @levelLoader.level.loaded
+    articles = @levelLoader.supermodel.getModels Article
+    for article in articles
+      return unless article.loaded
+    @showGuide()
+
+  showGuide: ->
+    @seenDocs = true
+    DocsModal = require './level/modal/docs_modal'
+    options = {docs: @levelLoader.level.get('documentation'), supermodel: @supermodel}
+    @openModalView(new DocsModal(options), true)
+    Backbone.Mediator.subscribeOnce 'modal-closed', @onLevelLoaderLoaded, @
+    return true
+
+  onLevelLoaderLoaded: ->
+    return unless @levelLoader.progress() is 1 # double check, since closing the guide may trigger this early
+    # Save latest level played in local storage
+    if window.currentModal and not window.currentModal.destroyed
+      @loadingScreen.showReady()
+      return Backbone.Mediator.subscribeOnce 'modal-closed', @onLevelLoaderLoaded, @
+
+    localStorage["lastLevel"] = @levelID if localStorage?
+    @grabLevelLoaderData()
+    team = @getQueryVariable("team") ? @world.teamForPlayer(0)
+    @loadOpponentTeam(team)
     @loadingScreen.destroy()
     @god.level = @level.serialize @supermodel
     @god.worldClassMap = @world.classMap
-    #@setTeam @world.teamForPlayer _.size @session.get 'players'   # TODO: players aren't initialized yet?
-    @setTeam @getQueryVariable("team") ? @world.teamForPlayer(0)
+    @setTeam team
     @initSurface()
     @initGoalManager()
     @initScriptManager()
-    @insertSubviews()
+    @insertSubviews ladderGame: @otherSession?
     @initVolume()
-    @session.on 'change:multiplayer', @onMultiplayerChanged, @
     @originalSessionState = _.cloneDeep(@session.get('state'))
     @register()
     @controlBar.setBus(@bus)
     @surface.showLevel()
+    if @otherSession
+      # TODO: colorize name and cloud by team, colorize wizard by user's color config
+      @surface.createOpponentWizard id: @otherSession.get('creator'), name: @otherSession.get('creatorName'), team: @otherSession.get('team')
+
+  grabLevelLoaderData: ->
+    @session = @levelLoader.session
+    @world = @levelLoader.world
+    @level = @levelLoader.level
+    @otherSession = @levelLoader.opponentSession
+    @levelLoader.destroy()
+    @levelLoader = null
+
+  loadOpponentTeam: (myTeam) ->
+    opponentSpells = []
+    for spellTeam, spells of @session.get('teamSpells') ? @otherSession?.get('teamSpells') ? {}
+      continue if spellTeam is myTeam or not myTeam
+      opponentSpells = opponentSpells.concat spells
+
+    opponentCode = @otherSession?.get('submittedCode') or {}
+    myCode = @session.get('code') or {}
+    for spell in opponentSpells
+      [thang, spell] = spell.split '/'
+      c = opponentCode[thang]?[spell]
+      myCode[thang] ?= {}
+      if c then myCode[thang][spell] = c else delete myCode[thang][spell]
+    @session.set('code', myCode)
+    if @session.get('multiplayer') and @otherSession?
+      # For now, ladderGame will disallow multiplayer, because session code combining doesn't play nice yet.
+      @session.set 'multiplayer', false
+
 
   onSupermodelLoadedOne: =>
     @modelsLoaded ?= 0
@@ -142,38 +197,66 @@ module.exports = class SpectateLevelView extends View
     ctx.clearRect(0, 0, canvas.width, canvas.height)
     ctx.fillText("Loaded #{@modelsLoaded} thingies",50,50)
 
-  insertSubviews: ->
-    #needs editing
-    @insertSubView @tome = new TomeView levelID: @levelID, session: @session, thangs: @world.thangs, supermodel: @supermodel
+  insertSubviews: (subviewOptions) ->
+    @insertSubView @tome = new TomeView levelID: @levelID, session: @session, thangs: @world.thangs, supermodel: @supermodel, ladderGame: subviewOptions.ladderGame
     @insertSubView new PlaybackView {}
     @insertSubView new GoalsView {}
     @insertSubView new GoldView {}
     @insertSubView new HUDView {}
     @insertSubView new ChatView levelID: @levelID, sessionID: @session.id, session: @session
     worldName = @level.get('i18n')?[me.lang()]?.name ? @level.get('name')
-    @controlBar = @insertSubView new ControlBarView {worldName: worldName, session: @session, level: @level, supermodel: @supermodel, playableTeams: @world.playableTeams}
+    @controlBar = @insertSubView new ControlBarView {worldName: worldName, session: @session, level: @level, supermodel: @supermodel, playableTeams: @world.playableTeams, ladderGame: subviewOptions.ladderGame}
   #Backbone.Mediator.publish('level-set-debug', debug: true) if me.displayName() is 'Nick!'
 
   afterInsert: ->
     super()
+    @showWizardSettingsModal() if not me.get('name')
 
+  # callbacks
+
+  onCtrlS: (e) ->
+    e.preventDefault()
+
+  onLevelReloadFromData: (e) ->
+    isReload = Boolean @world
+    @setLevel e.level, e.supermodel
+    if isReload
+      @scriptManager.setScripts(e.level.get('scripts'))
+      Backbone.Mediator.publish 'tome:cast-spell'  # a bit hacky
 
   onWindowResize: (s...) ->
     $('#pointer').css('opacity', 0.0)
 
-  onDisableControls: (e) =>
+  onDisableControls: (e) ->
     return if e.controls and not ('level' in e.controls)
     @shortcutsEnabled = false
     @wasFocusedOn = document.activeElement
     $('body').focus()
 
-  onEnableControls: (e) =>
+  onEnableControls: (e) ->
     return if e.controls? and not ('level' in e.controls)
     @shortcutsEnabled = true
     $(@wasFocusedOn).focus() if @wasFocusedOn
     @wasFocusedOn = null
 
-  onDonePressed: => @showVictory()
+  onDonePressed: -> @showVictory()
+
+  onShowVictory: (e) ->
+    $('#level-done-button').show()
+    @showVictory() if e.showModal
+    setTimeout(@preloadNextLevel, 3000)
+
+  showVictory: ->
+    options = {level: @level, supermodel: @supermodel, session:@session}
+    docs = new VictoryModal(options)
+    @openModalView(docs)
+    window.tracker?.trackEvent 'Saw Victory', level: @world.name, label: @world.name
+
+  onRestartLevel: ->
+    @tome.reloadAllCode()
+    Backbone.Mediator.publish 'level:restarted'
+    $('#level-done-button', @$el).hide()
+    window.tracker?.trackEvent 'Confirmed Restart', level: @world.name, label: @world.name
 
   onNewWorld: (e) ->
     @world = e.world
@@ -183,13 +266,21 @@ module.exports = class SpectateLevelView extends View
     @openModalView new InfiniteLoopModal()
     window.tracker?.trackEvent 'Saw Initial Infinite Loop', level: @world.name, label: @world.name
 
+  onPlayNextLevel: ->
+    nextLevel = @getNextLevel()
+    nextLevelID = nextLevel.get('slug') or nextLevel.id
+    url = "/play/level/#{nextLevelID}"
+    Backbone.Mediator.publish 'router:navigate', {
+      route: url,
+      viewClass: PlayLevelView,
+      viewArgs: [{supermodel:@supermodel}, nextLevelID]}
 
   getNextLevel: ->
     nextLevelOriginal = @level.get('nextLevel')?.original
     levels = @supermodel.getModels(Level)
     return l for l in levels when l.get('original') is nextLevelOriginal
 
-  onHighlightDom: (e) =>
+  onHighlightDom: (e) ->
     if e.delay
       delay = e.delay
       delete e.delay
@@ -243,19 +334,25 @@ module.exports = class SpectateLevelView extends View
     ), 1)
 
 
-  animatePointer: =>
+  animatePointer: ->
     pointer = $('#pointer')
     pointer.css('transition', 'all 0.6s ease-out')
     pointer.css('transform', "rotate(#{@pointerRotation}rad) translate(-3px, #{@pointerRadialDistance-50}px)")
     setTimeout((=>
       pointer.css('transform', "rotate(#{@pointerRotation}rad) translate(-3px, #{@pointerRadialDistance}px)").css('transition', 'all 0.4s ease-in')), 800)
 
-  onFocusDom: (e) => $(e.selector).focus()
+  onFocusDom: (e) -> $(e.selector).focus()
 
-  onEndHighlight: =>
+  onEndHighlight: ->
     $('#pointer').css('opacity', 0.0)
     clearInterval(@pointerInterval)
 
+  onMultiplayerChanged: (e) ->
+    if @session.get('multiplayer')
+      @bus.connect()
+    else
+      @bus.removeFirebaseData =>
+        @bus.disconnect()
 
   # initialization
 
@@ -273,7 +370,7 @@ module.exports = class SpectateLevelView extends View
     @surface.camera.zoomTo({x:0, y:0}, 0.1, 0)
 
   initGoalManager: ->
-    @goalManager = new GoalManager(@world)
+    @goalManager = new GoalManager(@world, @level.get('goals'))
     @god.goalManager = @goalManager
 
   initScriptManager: ->
@@ -297,11 +394,18 @@ module.exports = class SpectateLevelView extends View
     if state.playing?
       Backbone.Mediator.publish 'level-set-playing', { playing: state.playing }
 
+  preloadNextLevel: =>
+    # TODO: Loading models in the middle of gameplay causes stuttering. Most of the improvement in loading time is simply from passing the supermodel from this level to the next, but if we can find a way to populate the level early without it being noticeable, that would be even better.
+#    return if @destroyed
+#    return if @preloaded
+#    nextLevel = @getNextLevel()
+#    @supermodel.populateModel nextLevel
+#    @preloaded = true
 
   register: ->
     @bus = LevelBus.get(@levelID, @session.id)
     @bus.setSession(@session)
-    @bus.setTeamSpellMap @tome.teamSpellMap
+    @bus.setSpells @tome.spells
     @bus.connect() if @session.get('multiplayer')
 
   onSessionWillSave: (e) ->
@@ -319,7 +423,20 @@ module.exports = class SpectateLevelView extends View
     me.team = team
     Backbone.Mediator.publish 'level:team-set', team: team
 
+  # Dynamic sound loading
+
+  loadSoundsForWorld: (e) ->
+    return if @headless
+    world = e.world
+    thangTypes = @supermodel.getModels(ThangType)
+    for [spriteName, message] in world.thangDialogueSounds()
+      continue unless thangType = _.find thangTypes, (m) -> m.get('name') is spriteName
+      continue unless sound = AudioPlayer.soundForDialogue message, thangType.get('soundTriggers')
+      AudioPlayer.preloadSoundReference sound
+
   destroy: ->
+    @supermodel?.off 'error', @onLevelLoadError
+    @levelLoader?.off 'loaded-all', @onLevelLoaderLoaded
     @levelLoader?.destroy()
     @surface?.destroy()
     @god?.destroy()
@@ -327,10 +444,14 @@ module.exports = class SpectateLevelView extends View
     @scriptManager?.destroy()
     $(window).off('resize', @onWindowResize)
     delete window.world # not sure where this is set, but this is one way to clean it up
-
     clearInterval(@pointerInterval)
     @bus?.destroy()
     #@instance.save() unless @instance.loading
     console.profileEnd?() if PROFILE_ME
-    @session.off 'change:multiplayer', @onMultiplayerChanged, @
+    @session?.off 'change:multiplayer', @onMultiplayerChanged, @
+    @onLevelLoadError = null
+    @onLevelLoaderLoaded = null
+    @onSupermodelLoadedOne = null
+    @preloadNextLevel = null
+    @saveScreenshot = null
     super()

From bba3c78107c7bc09633d013b95ee4aaae833e882 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Tue, 11 Mar 2014 13:20:52 -0700
Subject: [PATCH 176/178] Ties are not victories in the emails.

---
 app/templates/play/ladder/my_matches_tab.jade | 2 +-
 server/routes/mail.coffee                     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/templates/play/ladder/my_matches_tab.jade b/app/templates/play/ladder/my_matches_tab.jade
index 0eb83dddb..3827bd3b1 100644
--- a/app/templates/play/ladder/my_matches_tab.jade
+++ b/app/templates/play/ladder/my_matches_tab.jade
@@ -24,7 +24,7 @@ div#columns.row
         if team.chartData
           tr
             th(colspan=4, style="color: #{team.primaryColor}")
-              img(src="https://chart.googleapis.com/chart?chs=450x125&cht=lxy&chco=#{team.chartColor}&chtt=Score%3A+#{team.currentScore}&chts=#{team.chartColor},16,c&chf=a,s,000000FF&chls=2&chm=o,#{team.chartColor},0,4&chd=t:#{team.chartData}")
+              img(src="https://chart.googleapis.com/chart?chs=450x125&cht=lxy&chco=#{team.chartColor}&chtt=Score%3A+#{team.currentScore}&chts=#{team.chartColor},16,r&chf=a,s,000000FF&chls=2&chm=o,#{team.chartColor},0,4&chd=t:#{team.chartData}")
 
         tr
           th Result
diff --git a/server/routes/mail.coffee b/server/routes/mail.coffee
index 5ad2dfcd4..5a46a9006 100644
--- a/server/routes/mail.coffee
+++ b/server/routes/mail.coffee
@@ -76,7 +76,7 @@ sendLadderUpdateEmail = (session, daysAgo) ->
     # (We could look at strongest/weakest, but we'd have to fetch everyone, or denormalize more.)
     matches = _.filter session.matches, (match) -> match.date >= (new Date() - 86400 * 1000 * daysAgo)
     defeats = _.filter matches, (match) -> match.metrics.rank is 1 and match.opponents[0].metrics.rank is 0
-    victories = _.filter matches, (match) -> match.metrics.rank is 0
+    victories = _.filter matches, (match) -> match.metrics.rank is 0 and match.opponents[0].metrics.rank is 1
     defeat = _.last defeats
     victory = _.last victories
 

From 852b1c97aca6655f24799695200617f6345da280 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Tue, 11 Mar 2014 13:59:12 -0700
Subject: [PATCH 177/178] Added idle.js so we can stop refreshing the page
 forever on ladder views when they're not looking.

---
 app/application.coffee            |   9 ++-
 app/views/play/ladder_view.coffee |   4 +-
 vendor/scripts/idle.js            | 126 ++++++++++++++++++++++++++++++
 3 files changed, 135 insertions(+), 4 deletions(-)
 create mode 100644 vendor/scripts/idle.js

diff --git a/app/application.coffee b/app/application.coffee
index 6b0c7f80b..860aee96e 100644
--- a/app/application.coffee
+++ b/app/application.coffee
@@ -44,8 +44,13 @@ Application = initialize: ->
   }, (t) =>
     @router = new Router()
     @router.subscribe()
-    Object.freeze this if typeof Object.freeze is 'function'
-    @router = Router
+    @idleTracker = new Idle
+      onAway: => @userIsIdle = true
+      onAwayBack: => @userIsIdle = false
+      onHidden: => @userIsIdle = true
+      onVisible: => @userIsIdle = false
+      awayTimeout: 5 * 60 * 1000
+    @idleTracker.start()
 
 module.exports = Application
 window.application = Application
diff --git a/app/views/play/ladder_view.coffee b/app/views/play/ladder_view.coffee
index b7cf49599..e12304f96 100644
--- a/app/views/play/ladder_view.coffee
+++ b/app/views/play/ladder_view.coffee
@@ -4,6 +4,7 @@ Simulator = require 'lib/simulator/Simulator'
 LevelSession = require 'models/LevelSession'
 CocoCollection = require 'models/CocoCollection'
 {teamDataFromLevel} = require './ladder/utils'
+application = require 'application'
 
 LadderTabView = require './ladder/ladder_tab'
 MyMatchesTabView = require './ladder/my_matches_tab'
@@ -74,12 +75,11 @@ module.exports = class LadderView extends RootView
     @sessions.fetch({"success": @refreshViews})
 
   refreshViews: =>
-    return if @destroyed
+    return if @destroyed or application.userIsIdle
     @ladderTab.refreshLadder()
     @myMatchesTab.refreshMatches()
     console.log "refreshed views!"
 
-
   # Simulations
 
   onSimulateAllButtonClick: (e) ->
diff --git a/vendor/scripts/idle.js b/vendor/scripts/idle.js
new file mode 100644
index 000000000..702c8ecd2
--- /dev/null
+++ b/vendor/scripts/idle.js
@@ -0,0 +1,126 @@
+// https://github.com/shawnmclean/Idle.js
+(function() {
+  "use strict";
+  var Idle;
+
+  Idle = {};
+
+  Idle = (function() {
+    Idle.isAway = false;
+
+    Idle.awayTimeout = 3000;
+
+    Idle.awayTimestamp = 0;
+
+    Idle.awayTimer = null;
+
+    Idle.onAway = null;
+
+    Idle.onAwayBack = null;
+
+    Idle.onVisible = null;
+
+    Idle.onHidden = null;
+
+    function Idle(options) {
+      var activeMethod, activity;
+
+      if (options) {
+        this.awayTimeout = parseInt(options.awayTimeout, 10);
+        this.onAway = options.onAway;
+        this.onAwayBack = options.onAwayBack;
+        this.onVisible = options.onVisible;
+        this.onHidden = options.onHidden;
+      }
+      activity = this;
+      activeMethod = function() {
+        return activity.onActive();
+      };
+      window.onclick = activeMethod;
+      window.onmousemove = activeMethod;
+      window.onmouseenter = activeMethod;
+      window.onkeydown = activeMethod;
+      window.onscroll = activeMethod;
+      window.onmousewheel = activeMethod;
+      document.addEventListener("visibilitychange", (function() {
+        return activity.handleVisibilityChange();
+      }), false);
+      document.addEventListener("webkitvisibilitychange", (function() {
+        return activity.handleVisibilityChange();
+      }), false);
+      document.addEventListener("msvisibilitychange", (function() {
+        return activity.handleVisibilityChange();
+      }), false);
+    }
+
+    Idle.prototype.onActive = function() {
+      this.awayTimestamp = new Date().getTime() + this.awayTimeout;
+      if (this.isAway) {
+        if (this.onAwayBack) {
+          this.onAwayBack();
+        }
+        this.start();
+      }
+      this.isAway = false;
+      return true;
+    };
+
+    Idle.prototype.start = function() {
+      var activity;
+
+      this.awayTimestamp = new Date().getTime() + this.awayTimeout;
+      if (this.awayTimer !== null) {
+        clearTimeout(this.awayTimer);
+      }
+      activity = this;
+      this.awayTimer = setTimeout((function() {
+        return activity.checkAway();
+      }), this.awayTimeout + 100);
+      return this;
+    };
+
+    Idle.prototype.setAwayTimeout = function(ms) {
+      this.awayTimeout = parseInt(ms, 10);
+      return this;
+    };
+
+    Idle.prototype.checkAway = function() {
+      var activity, t;
+
+      t = new Date().getTime();
+      if (t < this.awayTimestamp) {
+        this.isAway = false;
+        activity = this;
+        this.awayTimer = setTimeout((function() {
+          return activity.checkAway();
+        }), this.awayTimestamp - t + 100);
+        return;
+      }
+      if (this.awayTimer !== null) {
+        clearTimeout(this.awayTimer);
+      }
+      this.isAway = true;
+      if (this.onAway) {
+        return this.onAway();
+      }
+    };
+
+    Idle.prototype.handleVisibilityChange = function() {
+      if (document.hidden || document.msHidden || document.webkitHidden) {
+        if (this.onHidden) {
+          return this.onHidden();
+        }
+      } else {
+        if (this.onVisible) {
+          return this.onVisible();
+        }
+      }
+    };
+
+    return Idle;
+
+  })();
+
+  window.Idle = Idle;
+
+}).call(this);

From 392534878a2c3f6aa9f48a703d7219ad9e6751f3 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Tue, 11 Mar 2014 16:31:39 -0700
Subject: [PATCH 178/178] Keeping old matches, up to 200, and showing them as
 stale. Added LevelSession.isRanking for better display of when you're still
 in the initial ranking phase.

---
 app/styles/play/ladder.sass                   | 10 +++-
 app/templates/play/ladder/my_matches_tab.jade | 17 ++++---
 app/views/play/ladder/my_matches_tab.coffee   | 17 +++++--
 .../sessions/level_session_schema.coffee      |  6 ++-
 server/queues/scoring.coffee                  | 51 ++++++++++---------
 5 files changed, 63 insertions(+), 38 deletions(-)

diff --git a/app/styles/play/ladder.sass b/app/styles/play/ladder.sass
index 6904c5739..fc9bc6abc 100644
--- a/app/styles/play/ladder.sass
+++ b/app/styles/play/ladder.sass
@@ -18,5 +18,13 @@
     white-space: nowrap
     overflow: hidden
     
+  tr.stale
+    opacity: 0.5
+
+  tr.win .state-cell
+    color: #172
+  tr.loss .state-cell
+    color: #712
+
   #must-log-in button
-    margin-right: 10px
\ No newline at end of file
+    margin-right: 10px
diff --git a/app/templates/play/ladder/my_matches_tab.jade b/app/templates/play/ladder/my_matches_tab.jade
index 3827bd3b1..8cacdb49f 100644
--- a/app/templates/play/ladder/my_matches_tab.jade
+++ b/app/templates/play/ladder/my_matches_tab.jade
@@ -17,9 +17,10 @@ div#columns.row
               button.btn.btn-sm.btn-warning.pull-right.rank-button(data-session-id=team.session.id)
                 span.unavailable.hidden No New Code to Rank
                 span.rank.hidden Rank My Game!
-                span.ranking.hidden Submitting...
-                span.ranked.hidden Submitted for Ranking
+                span.submitting.hidden Submitting...
+                span.submitted.hidden Submitted for Ranking
                 span.failed.hidden Failed to Rank
+                span.ranking.hidden Game Being Ranked
 
         if team.chartData
           tr
@@ -32,7 +33,7 @@ div#columns.row
           th When
           th
         for match in team.matches
-          tr
+          tr(class=(match.stale ? "stale " : "") + match.state)
             td.state-cell
               if match.state === 'win'
                 span.win Win
@@ -48,7 +49,11 @@ div#columns.row
 
         if !team.matches.length
           tr
-            td(colspan=4).alert.alert-warning
-              | No ranked matches for this team!
-              | Play against some competitors and then come back here to get your game ranked.
+            if team.isRanking
+              td(colspan=4).alert.alert-info
+                | Your new code is being simulated by other players for ranking.
+            else
+              td(colspan=4).alert.alert-warning
+                | No ranked matches for this team!
+                | Play against some competitors and then come back here to get your game ranked.
       
diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
index 660114111..278bcb9b0 100644
--- a/app/views/play/ladder/my_matches_tab.coffee
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -54,7 +54,7 @@ module.exports = class MyMatchesTabView extends CocoView
     ctx.levelID = @level.get('slug') or @level.id
     ctx.teams = @teams
 
-    convertMatch = (match) =>
+    convertMatch = (match, submitDate) =>
       opponent = match.opponents[0]
       state = 'win'
       state = 'loss' if match.metrics.rank > opponent.metrics.rank
@@ -65,12 +65,14 @@ module.exports = class MyMatchesTabView extends CocoView
         opponentID: opponent.userID
         when: moment(match.date).fromNow()
         sessionID: opponent.sessionID
+        stale: match.date < submitDate
       }
 
     for team in @teams
       team.session = (s for s in @sessions.models when s.get('team') is team.id)[0]
       team.readyToRank = @readyToRank(team.session)
-      team.matches = (convertMatch(match) for match in team.session?.get('matches') or [])
+      team.isRanking = team.session.get('isRanking')
+      team.matches = (convertMatch(match, team.session.get('submitDate')) for match in team.session?.get('matches') or [])
       team.matches.reverse()
       team.score = (team.session?.get('totalScore') or 10).toFixed(2)
       team.wins = _.filter(team.matches, {state: 'win'}).length
@@ -96,7 +98,12 @@ module.exports = class MyMatchesTabView extends CocoView
       button = $(el)
       sessionID = button.data('session-id')
       session = _.find @sessions.models, { id: sessionID }
-      @setRankingButtonText button, if @readyToRank(session) then 'rank' else 'unavailable'
+      rankingState = 'unavailable'
+      if @readyToRank session
+        rankingState = 'rank'
+      else if session.get 'isRanking'
+        rankingState = 'ranking'
+      @setRankingButtonText button, rankingState
 
   readyToRank: (session) ->
     return false unless session?.get('levelID')  # If it hasn't been denormalized, then it's not ready.
@@ -110,8 +117,8 @@ module.exports = class MyMatchesTabView extends CocoView
     session = _.find @sessions.models, { id: sessionID }
     return unless @readyToRank(session)
 
-    @setRankingButtonText(button, 'ranking')
-    success = => @setRankingButtonText(button, 'ranked')
+    @setRankingButtonText(button, 'submitting')
+    success = => @setRankingButtonText(button, 'submitted')
     failure = => @setRankingButtonText(button, 'failed')
 
     ajaxData = { session: sessionID, levelID: @level.id, originalLevelID: @level.attributes.original, levelMajorVersion: @level.attributes.version.major }
diff --git a/server/levels/sessions/level_session_schema.coffee b/server/levels/sessions/level_session_schema.coffee
index da4395dec..a7d742001 100644
--- a/server/levels/sessions/level_session_schema.coffee
+++ b/server/levels/sessions/level_session_schema.coffee
@@ -140,6 +140,10 @@ _.extend LevelSessionSchema.properties,
   submittedCode:
     type: 'object'
 
+  isRanking:
+    type: 'boolean'
+    description: 'Whether this session is still in the first ranking chain after being submitted.'
+
   unsubscribed:
     type: 'boolean'
     description: 'Whether the player has opted out of receiving email updates about ladder rankings for this session.'
@@ -147,6 +151,7 @@ _.extend LevelSessionSchema.properties,
   numberOfWinsAndTies:
     type: 'number'
     default: 0
+
   numberOfLosses:
     type: 'number'
     default: 0
@@ -162,7 +167,6 @@ _.extend LevelSessionSchema.properties,
       items:
         type: 'number'
 
-
   matches:
     type: 'array'
     title: 'Matches'
diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee
index 0462cd503..9577df844 100644
--- a/server/queues/scoring.coffee
+++ b/server/queues/scoring.coffee
@@ -52,7 +52,7 @@ module.exports.createNewTask = (req, res) ->
   requestLevelID = req.body.originalLevelID
   requestCurrentLevelID = req.body.levelID
   requestLevelMajorVersion = parseInt(req.body.levelMajorVersion)
-  
+
   validatePermissions req, requestSessionID, (error, permissionsAreValid) ->
     if err? then return errors.serverError res, "There was an error validating permissions"
     unless permissionsAreValid then return errors.forbidden res, "You do not have the permissions to submit that game to the leaderboard"
@@ -60,24 +60,24 @@ module.exports.createNewTask = (req, res) ->
     return errors.badInput res, "The session ID is invalid" unless typeof requestSessionID is "string"
     Level.findOne({_id: requestCurrentLevelID}).lean().select('type').exec (err, levelWithType) ->
       if err? then return errors.serverError res, "There was an error finding the level type"
-        
-      if not levelWithType.type or levelWithType.type isnt "ladder" 
+
+      if not levelWithType.type or levelWithType.type isnt "ladder"
         console.log "The level type of level with ID #{requestLevelID} is #{levelWithType.type}"
         return errors.badInput res, "That level isn't a ladder level"
-  
+
       fetchSessionToSubmit requestSessionID, (err, sessionToSubmit) ->
         if err? then return errors.serverError res, "There was an error finding the given session."
-  
+
         updateSessionToSubmit sessionToSubmit, (err, data) ->
           if err? then return errors.serverError res, "There was an error updating the session"
           opposingTeam = calculateOpposingTeam(sessionToSubmit.team)
           fetchInitialSessionsToRankAgainst opposingTeam,requestLevelID, requestLevelMajorVersion, (err, sessionsToRankAgainst) ->
             if err? then return errors.serverError res, "There was an error fetching the sessions to rank against"
-  
+
             taskPairs = generateTaskPairs(sessionsToRankAgainst, sessionToSubmit)
             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.dispatchTaskToConsumer = (req, res) ->
@@ -118,51 +118,53 @@ module.exports.processTaskResult = (req, res) ->
     scoringTaskQueue.deleteMessage clientResponseObject.receiptHandle, (err) ->
       console.log "Deleted message."
       if err? then return errors.badInput res, "The queue message is already back in the queue, rejecting results."
-        
+
       LevelSession.findOne(_id: clientResponseObject.originalSessionID).lean().exec (err, levelSession) ->
         if err? then return errors.serverError res, "There was a problem finding the level session:#{err}"
-          
+
         supposedSubmissionDate = new Date(clientResponseObject.sessions[0].submitDate)
-          
+
         if Number(supposedSubmissionDate) isnt Number(levelSession.submitDate)
           return sendResponseObject req, res, {"message":"The game has been resubmitted. Removing from queue..."}
-  
+
         logTaskComputation clientResponseObject, taskLog, (logErr) ->
           if logErr? then return errors.serverError res, "There as a problem logging the task computation: #{logErr}"
-  
+
           updateSessions clientResponseObject, (updateError, newScoreArray) ->
             if updateError? then return errors.serverError res, "There was an error updating the scores.#{updateError}"
-  
+
             newScoresObject = _.indexBy newScoreArray, 'id'
-  
+
             addMatchToSessions clientResponseObject, newScoresObject, (err, data) ->
               if err? then return errors.serverError res, "There was an error updating the sessions with the match! #{JSON.stringify err}"
-  
+
               originalSessionID = clientResponseObject.originalSessionID
               originalSessionTeam = clientResponseObject.originalSessionTeam
               originalSessionRank = parseInt clientResponseObject.originalSessionRank
-  
+
               determineIfSessionShouldContinueAndUpdateLog originalSessionID, originalSessionRank, (err, sessionShouldContinue) ->
                 if err? then return errors.serverError res, "There was an error determining if the session should continue, #{err}"
-  
+
                 if sessionShouldContinue
                   opposingTeam = calculateOpposingTeam(originalSessionTeam)
                   opponentID = _.pull(_.keys(newScoresObject), originalSessionID)
                   sessionNewScore = newScoresObject[originalSessionID].totalScore
                   opponentNewScore = newScoresObject[opponentID].totalScore
-                  
+
                   levelOriginalID = levelSession.level.original
                   levelOriginalMajorVersion = levelSession.level.majorVersion
                   findNearestBetterSessionID levelOriginalID, levelOriginalMajorVersion, originalSessionID, sessionNewScore, opponentNewScore, opponentID ,opposingTeam, (err, opponentSessionID) ->
                     if err? then return errors.serverError res, "There was an error finding the nearest sessionID!"
                     unless opponentSessionID then return sendResponseObject req, res, {"message":"There were no more games to rank(game is at top!"}
-  
+
                     addPairwiseTaskToQueue [originalSessionID, opponentSessionID], (err, success) ->
                       if err? then return errors.serverError res, "There was an error sending the pairwise tasks to the queue!"
                       sendResponseObject req, res, {"message":"The scores were updated successfully and more games were sent to the queue!"}
                 else
                   console.log "Player lost, achieved rank #{originalSessionRank}"
-                  sendResponseObject req, res, {"message":"The scores were updated successfully, person lost so no more games are being inserted!"}
+                  LevelSession.update {_id: originalSessionID}, {isRanking: false}, {multi: false}, (err, affected) ->
+                    if err? then return errors.serverError res, "There was an error marking the completed session as not being ranked."
+                    sendResponseObject req, res, {"message":"The scores were updated successfully, person lost so no more games are being inserted!"}
 
 
 determineIfSessionShouldContinueAndUpdateLog = (sessionID, sessionRank, cb) ->
@@ -285,7 +287,7 @@ updateMatchesInSession = (matchObject, sessionID, callback) ->
   currentMatchObject.opponents = opponentsArray
 
   sessionUpdateObject =
-    $push: {matches: currentMatchObject}
+    $push: {matches: {$each: [currentMatchObject], $slice: -200}}
   log.info "Updating session #{sessionID}"
   LevelSession.update {"_id":sessionID}, sessionUpdateObject, callback
 
@@ -304,12 +306,12 @@ updateSessionToSubmit = (sessionToUpdate, callback) ->
     submitted: true
     submittedCode: sessionToUpdate.code
     submitDate: new Date()
-    matches: []
     meanStrength: 25
     standardDeviation: 25/3
     totalScore: 10
     numberOfWinsAndTies: 0
     numberOfLosses: 0
+    isRanking: true
   LevelSession.update {_id: sessionToUpdate._id}, sessionUpdateObject, callback
 
 fetchInitialSessionsToRankAgainst = (opposingTeam, levelID, levelMajorVersion, callback) ->
@@ -321,7 +323,7 @@ fetchInitialSessionsToRankAgainst = (opposingTeam, levelID, levelMajorVersion, c
     submittedCode:
       $exists: true
     team: opposingTeam
-  
+
   sortParameters =
     totalScore: 1
 
@@ -449,8 +451,7 @@ updateScoreInSession = (scoreObject,callback) ->
       meanStrength: scoreObject.meanStrength
       standardDeviation: scoreObject.standardDeviation
       totalScore: newTotalScore
-      $push:
-        scoreHistory: scoreHistoryAddition        
+      $push: {scoreHistory: {$each: [scoreHistoryAddition], $slice: -1000}}
 
     LevelSession.update {"_id": scoreObject.id}, updateObject, callback
     log.info "New total score for session #{scoreObject.id} is #{updateObject.totalScore}"