From 750d94c47840d67d9129749fcf8c8dd8fb7eda5e Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <rubenvereecken@gmail.com>
Date: Thu, 10 Jul 2014 10:30:23 +0200
Subject: [PATCH 01/33] Noty errors don't show up on user save fails anymore

---
 app/models/User.coffee | 1 +
 1 file changed, 1 insertion(+)

diff --git a/app/models/User.coffee b/app/models/User.coffee
index 1086e1373..bd796c201 100644
--- a/app/models/User.coffee
+++ b/app/models/User.coffee
@@ -6,6 +6,7 @@ module.exports = class User extends CocoModel
   @className: 'User'
   @schema: require 'schemas/models/user'
   urlRoot: '/db/user'
+  notyErrors: false
 
   initialize: ->
     super()

From a8d369ed1a957c10fb528ba30228fe2f89201482 Mon Sep 17 00:00:00 2001
From: Jeff Hemphill <jhemphill@fb.com>
Date: Sat, 12 Jul 2014 00:35:01 -0700
Subject: [PATCH 02/33] Add schemas for tome subscriptions

---
 app/schemas/subscriptions/play.coffee |   3 -
 app/schemas/subscriptions/tome.coffee | 273 +++++++++++++++++++++-----
 2 files changed, 225 insertions(+), 51 deletions(-)

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

From f9c92d2731fe561c993b4b7f888f146ed3d1ea01 Mon Sep 17 00:00:00 2001
From: Maryann Vellanikaran <maryann+android@brilliant.org>
Date: Sat, 12 Jul 2014 15:45:53 -0700
Subject: [PATCH 03/33] Add space before "Contribute"

Before: http://cl.ly/image/0p1f1P1D0P2d
After: http://cl.ly/image/3a0x12070C28
---
 app/templates/community.jade | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/templates/community.jade b/app/templates/community.jade
index 755e55cf4..05abba019 100644
--- a/app/templates/community.jade
+++ b/app/templates/community.jade
@@ -80,6 +80,6 @@ block content
             a(href="/contribute#ambassador", data-i18n="classes.ambassador_title") 
             | : support our community of educators and coders.
 
-        | Check out the
+        | Check out the 
         a(href="/contribute", data-i18n="nav.contribute") 
         |  page to find out more about the roles and how you can get started.

From b1aa0a1973ccef725570bf6620d4923308065641 Mon Sep 17 00:00:00 2001
From: Dmitry <spellhunter92@gmail.com>
Date: Sun, 13 Jul 2014 15:33:50 +0400
Subject: [PATCH 04/33] update ru.coffee

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

diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 77fa0be45..0be2feb62 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -173,7 +173,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     email_announcements: "Оповещения"
     email_announcements_description: "Получать email-оповещения о последних новостях CodeCombat."
     email_notifications: "Уведомления"
-#    email_notifications_summary: "Controls for personalized, automatic email notifications related to your CodeCombat activity."
+    email_notifications_summary: "Настройки автоматических email уведомлений, основанных на вашей активности на CodeCombat."
     email_any_notes: "Все уведомления"
     email_any_notes_description: "Отключите, чтобы больше не получать извещения."
     email_recruit_notes: "Возможности для работы"
@@ -399,8 +399,8 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     editor_config_keybindings_label: "Сочетания клавиш"
     editor_config_keybindings_default: "По умолчанию (Ace)"
     editor_config_keybindings_description: "Добавляет дополнительные сочетания, известные из популярных редакторов."
-#    editor_config_livecompletion_label: "Live Autocompletion"
-#    editor_config_livecompletion_description: "Displays autocomplete suggestions while typing."
+    editor_config_livecompletion_label: "Автозаполнение"
+    editor_config_livecompletion_description: "Показывать варианты автозаполнения во время печати."
     editor_config_invisibles_label: "Показывать непечатные символы"
     editor_config_invisibles_description: "Отображение непечатных символов, таких как пробелы или табуляции."
     editor_config_indentguides_label: "Показывать направляющие отступов"
@@ -451,8 +451,8 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     enter: "Enter"
     escape: "Escape"
     cast_spell: "Произнести текущее заклинание."
-#    continue_script: "Continue past current script."
-#    skip_scripts: "Skip past all skippable scripts."
+    continue_script: "Продолжить текущий скрипт."
+    skip_scripts: "Пропустить все возможные скрипты."
     toggle_playback: "Переключить проигрывание/паузу."
     scrub_playback: "Перемотка назад и вперед во времени."
 #    single_scrub_playback: "Scrub back and forward through time by a single frame."
@@ -535,10 +535,10 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     new_thang_title: "Создать новый тип объектов"
     new_level_title: "Создать новый уровень"
     new_article_title_login: "Войти, чтобы создать новую статью"
-#    new_thang_title_login: "Log In to Create a New Thang Type"
-    new_level_title_login: "Войти чтобы создать новый уровень"
-#    new_achievement_title: "Create a New Achievement"
-#    new_achievement_title_login: "Log In to Create a New Achievement"
+    new_thang_title_login: "Войти, чтобы создать новый тип объектов"
+    new_level_title_login: "Войти, чтобы создать новый уровень"
+    new_achievement_title: "Создать новое достижение"
+    new_achievement_title_login: "Войти, чтобы создать новое достижение"
     article_search_title: "Искать статьи"
     thang_search_title: "Искать типы объектов"
     level_search_title: "Искать уровни"
@@ -795,8 +795,8 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     rank_submitted: "Отправлено для оценки"
     rank_failed: "Сбой в оценке"
     rank_being_ranked: "Игра оценивается"
-#    rank_last_submitted: "submitted "
-#    help_simulate: "Help simulate games?"
+    rank_last_submitted: "отправлено "
+    help_simulate: "Нужна помощь в симуляции игр?"
     code_being_simulated: "Ваш новый код участвует в симуляции других игроков для оценки. Обновление будет при поступлении новых матчей."
     no_ranked_matches_pre: "Нет оценённых матчей для команды"
     no_ranked_matches_post: "! Сыграйте против нескольких противников и возвращайтесь сюда для оценки вашей игры."
@@ -809,19 +809,19 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     simple_ai: "Простой ИИ"
     warmup: "Разминка"
     vs: "против"
-#    friends_playing: "Friends Playing"
-#    log_in_for_friends: "Log in to play with your friends!"
-#    social_connect_blurb: "Connect and play against your friends!"
+    friends_playing: "Друзья в игре"
+    log_in_for_friends: "Войти, чтобы поиграть с друзьями!"
+    social_connect_blurb: "Зайти и играть против друзей!"
     invite_friends_to_battle: "Пригласить друзей присоединиться к вам в сражении!"
     fight: "В бой!"
-#    watch_victory: "Watch your victory"
-#    defeat_the: "Defeat the"
-#    tournament_ends: "Tournament ends"
-#    tournament_ended: "Tournament ended"
-#    tournament_rules: "Tournament Rules"
-#    tournament_blurb: "Write code, collect gold, build armies, crush foes, win prizes, and upgrade your career in our $40,000 Greed tournament! Check out the details"
-#    tournament_blurb_blog: "on our blog"
-#    rules: "Rules"
+    watch_victory: "Смотрите за вашей победой"
+    defeat_the: "Уничтожил"
+    tournament_ends: "Турнир заканчивается"
+    tournament_ended: "Турнир закончился"
+    tournament_rules: "Правила турнира"
+    tournament_blurb: "Пишите код, собирайте золото, стройте армию, крушите противников, получайте призы и улучшайте вашу карьеру в нашем $40,000 турнире жадности! Узнайте больше"
+    tournament_blurb_blog: "в нашем блоге"
+    rules: "Правила"
     winners: "Победители"
 
 #  ladder_prizes:

From 49e6ed13bad093644f27edaee4b288facad9ac55 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 13 Jul 2014 09:07:58 -0700
Subject: [PATCH 05/33] Fixed LatestVersionReferenceNode's collection
 initialization.

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

diff --git a/app/treema-ext.coffee b/app/treema-ext.coffee
index c7b6fac65..d5fda7677 100644
--- a/app/treema-ext.coffee
+++ b/app/treema-ext.coffee
@@ -249,9 +249,9 @@ class JavaScriptTreema extends CodeTreema
 class InternationalizationNode extends TreemaNode.nodeMap.object
   findLanguageName: (languageCode) ->
     # to get around mongoose emtpy object bug, there's a prop in the object which needs to be ignored
-    return '' if languageCode is '-' 
+    return '' if languageCode is '-'
     locale[languageCode]?.nativeDescription or "#{languageCode} Not Found"
-    
+
   getChildren: ->
     res = super(arguments...)
     res = (r for r in res when r[0] isnt '-')
@@ -322,7 +322,7 @@ class LatestVersionReferenceNode extends TreemaNode
     return unless term
     @lastTerm = term
     @getSearchResultsEl().empty().append('Searching')
-    @collection = new LatestVersionCollection()
+    @collection = new LatestVersionCollection([], model: @model)
 
     # HACK while search is broken
 #    @collection.url = "#{@url}?term=#{term}&project=true"

From 868a6ed43b64323d4d41439f7028d1d8dd1b4411 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 13 Jul 2014 09:31:31 -0700
Subject: [PATCH 06/33] Fixed a couple i18n issues. Fixed #1302.

---
 app/locale/en-GB.coffee              | 3 ++-
 app/locale/en.coffee                 | 1 +
 app/models/Level.coffee              | 4 ++--
 app/templates/editor/level/edit.jade | 6 +++---
 4 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/app/locale/en-GB.coffee b/app/locale/en-GB.coffee
index cea2078f9..6399f9413 100644
--- a/app/locale/en-GB.coffee
+++ b/app/locale/en-GB.coffee
@@ -482,7 +482,7 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
 #    twitter: "Twitter"
 #    gplus: "Google+"
 
-#  editor:
+  editor:
 #    main_title: "CodeCombat Editors"
 #    main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!"
 #    article_title: "Article Editor"
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+    randomize: "Randomise"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index 69373ccfb..69f5afda6 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -501,6 +501,7 @@
     revert_models: "Revert Models"
     fork_title: "Fork New Version"
     fork_creating: "Creating Fork..."
+    randomize: "Randomize"
     more: "More"
     wiki: "Wiki"
     live_chat: "Live Chat"
diff --git a/app/models/Level.coffee b/app/models/Level.coffee
index 6ae47f25e..f28bb9b00 100644
--- a/app/models/Level.coffee
+++ b/app/models/Level.coffee
@@ -30,7 +30,7 @@ module.exports = class Level extends CocoModel
     visit = (system) ->
       return if system.original of originalsSeen
       systemModel = _.find systemModels, {original: system.original}
-      console.error 'Couldn\'t find model for original', system.original, 'from', systemModels unless systemModel
+      return console.error 'Couldn\'t find model for original', system.original, 'from', systemModels unless systemModel
       for d in systemModel.dependencies or []
         system2 = _.find levelSystems, {original: d.original}
         visit system2
@@ -61,7 +61,7 @@ module.exports = class Level extends CocoModel
           for d in lc.dependencies or []
             c2 = _.find thang.components, {original: d.original}
             console.error thang.id, 'couldn\'t find dependent Component', d.original, 'from', lc.name unless c2
-            visit c2
+            visit c2 if c2
           if lc.name is 'Collides'
             allied = _.find levelComponents, {name: 'Allied'}
             if allied
diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade
index e446f7613..09776b637 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -70,17 +70,17 @@ block header
               a#level-watch-button
                 span.watch
                   span.glyphicon.glyphicon-eye-open
-                  span.spl Watch
+                  span.spl(data-i18n="common.watch") Watch
                 span.unwatch.secret
                   span.glyphicon.glyphicon-eye-close
-                  span.spl Unwatch
+                  span.spl(data-i18n="common.unwatch") Unwatch
                   
             li(class=anonymous ? "disabled": "")
               a(data-i18n="common.fork")#fork-level-start-button Fork
             li(class=anonymous ? "disabled": "")
               a(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert")#revert-button Revert
             li(class=anonymous ? "disabled": "")
-              a(data-toggle="coco-modal", data-target="modal/terrain_randomise", data-i18n="editor.randomise")#randomise-button Randomise
+              a(data-toggle="coco-modal", data-target="modal/terrain_randomise", data-i18n="editor.randomize")#randomise-button Randomise
             li(class=anonymous ? "disabled": "")
               a(data-i18n="editor.pop_i18n")#pop-level-i18n-button Populate i18n
             li.divider

From 843ed97643bd1bb78a9482e6e04d0c6125e77370 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Sun, 13 Jul 2014 10:05:58 -0700
Subject: [PATCH 07/33] Another fix for mongoose i18n locale object hack.

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

diff --git a/app/lib/utils.coffee b/app/lib/utils.coffee
index 430a9d8fb..ae556a431 100644
--- a/app/lib/utils.coffee
+++ b/app/lib/utils.coffee
@@ -54,6 +54,7 @@ module.exports.i18n = (say, target, language=me.lang(), fallback='en') ->
   generalName = matches[0] if matches
 
   for localeName, locale of say.i18n
+    continue if localeName is '-'
     if target of locale
       result = locale[target]
     else continue

From 3d510b98d6434854fc850703734f011492004354 Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <rubenvereecken@gmail.com>
Date: Sun, 13 Jul 2014 20:49:13 +0200
Subject: [PATCH 08/33] Express now removes all trailing slashes.

---
 server_setup.coffee | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/server_setup.coffee b/server_setup.coffee
index 7f2b11ce6..30beb95aa 100644
--- a/server_setup.coffee
+++ b/server_setup.coffee
@@ -70,11 +70,17 @@ setupMiddlewareToSendOldBrowserWarningWhenPlayersViewLevelDirectly = (app) ->
     return next() if req.query['try-old-browser-anyway'] or not isOldBrowser req
     res.sendfile(path.join(__dirname, 'public', 'index_old_browser.html'))
 
+setupTrailingSlashRemovingMiddleware = (app) ->
+  app.use (req, res, next) ->
+    return res.redirect 301, req.url[...-1] if req.url.length > 1 and req.url.slice(-1) is '/'
+    next()
+
 exports.setupMiddleware = (app) ->
   setupMiddlewareToSendOldBrowserWarningWhenPlayersViewLevelDirectly app
   setupExpressMiddleware app
   setupPassportMiddleware app
   setupOneSecondDelayMiddleware app
+  setupTrailingSlashRemovingMiddleware app
 
 ###Routing function implementations###
 

From e60832bcfaa98e27d67ac69545944535a4fc635e Mon Sep 17 00:00:00 2001
From: Dmitry <spellhunter92@gmail.com>
Date: Sun, 13 Jul 2014 23:13:42 +0400
Subject: [PATCH 09/33] Update ru.coffee

some fixes
---
 app/locale/ru.coffee | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 0be2feb62..4ecae8dcc 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -173,7 +173,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     email_announcements: "Оповещения"
     email_announcements_description: "Получать email-оповещения о последних новостях CodeCombat."
     email_notifications: "Уведомления"
-    email_notifications_summary: "Настройки автоматических email уведомлений, основанных на вашей активности на CodeCombat."
+    email_notifications_summary: "Настройки автоматических email-уведомлений, основанных на вашей активности на CodeCombat."
     email_any_notes: "Все уведомления"
     email_any_notes_description: "Отключите, чтобы больше не получать извещения."
     email_recruit_notes: "Возможности для работы"
@@ -400,7 +400,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     editor_config_keybindings_default: "По умолчанию (Ace)"
     editor_config_keybindings_description: "Добавляет дополнительные сочетания, известные из популярных редакторов."
     editor_config_livecompletion_label: "Автозаполнение"
-    editor_config_livecompletion_description: "Показывать варианты автозаполнения во время печати."
+    editor_config_livecompletion_description: "Отображение вариантов автозаполнения во время печати."
     editor_config_invisibles_label: "Показывать непечатные символы"
     editor_config_invisibles_description: "Отображение непечатных символов, таких как пробелы или табуляции."
     editor_config_indentguides_label: "Показывать направляющие отступов"
@@ -811,15 +811,15 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     vs: "против"
     friends_playing: "Друзья в игре"
     log_in_for_friends: "Войти, чтобы поиграть с друзьями!"
-    social_connect_blurb: "Зайти и играть против друзей!"
+    social_connect_blurb: "Свяжите учетную запись и  играйте против друзей!"
     invite_friends_to_battle: "Пригласить друзей присоединиться к вам в сражении!"
     fight: "В бой!"
-    watch_victory: "Смотрите за вашей победой"
-    defeat_the: "Уничтожил"
+    watch_victory: "Наблюдать за победой"
+    defeat_the: "Победить"
     tournament_ends: "Турнир заканчивается"
     tournament_ended: "Турнир закончился"
     tournament_rules: "Правила турнира"
-    tournament_blurb: "Пишите код, собирайте золото, стройте армию, крушите противников, получайте призы и улучшайте вашу карьеру в нашем $40,000 турнире жадности! Узнайте больше"
+    tournament_blurb: "Пишите код, собирайте золото, стройте армию, крушите противников, получайте призы и улучшайте вашу карьеру в нашем \"$40,000 турнире жадности\"! Узнайте больше"
     tournament_blurb_blog: "в нашем блоге"
     rules: "Правила"
     winners: "Победители"

From 3b6d17286ba7d62b06c5fcb6cee8e6a3e457bb89 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Sun, 13 Jul 2014 11:13:26 -0700
Subject: [PATCH 10/33] Small tweak to lower the number of repeated calls to
 SpriteBoss.updateSounds.

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

diff --git a/app/lib/surface/Surface.coffee b/app/lib/surface/Surface.coffee
index fd745d8ec..f435f8110 100644
--- a/app/lib/surface/Surface.coffee
+++ b/app/lib/surface/Surface.coffee
@@ -608,7 +608,7 @@ module.exports = Surface = class Surface extends CocoClass
       ratio = current % 1
       @world.frames[next].restorePartialState ratio if next > 1
     frame.clearEvents() if parseInt(@currentFrame) is parseInt(@lastFrame)
-    @spriteBoss.updateSounds()
+    @spriteBoss.updateSounds() if parseInt(@currentFrame) isnt parseInt(@lastFrame)
 
   updateState: (frameChanged) ->
     # world state must have been restored in @restoreWorldState

From be223197df86e0399ab3f0c8848c2b6620a4e0c4 Mon Sep 17 00:00:00 2001
From: Jayant Jain <jayantjain1992@gmail.com>
Date: Sun, 13 Jul 2014 23:38:35 +0530
Subject: [PATCH 11/33] Updates i18n tags and en.coffee

---
 app/locale/en.coffee                       | 4 ++++
 app/templates/modal/terrain_randomise.jade | 4 ++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index 69f5afda6..ff0713176 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -499,6 +499,10 @@
     back: "Back"
     revert: "Revert"
     revert_models: "Revert Models"
+    randomise: "Randomise"
+    pick_a_terrain: "Pick A Terrain"
+    small: "Small"
+    grassy: "Grassy"
     fork_title: "Fork New Version"
     fork_creating: "Creating Fork..."
     randomize: "Randomize"
diff --git a/app/templates/modal/terrain_randomise.jade b/app/templates/modal/terrain_randomise.jade
index 9ac509c68..8ea39185e 100644
--- a/app/templates/modal/terrain_randomise.jade
+++ b/app/templates/modal/terrain_randomise.jade
@@ -8,8 +8,8 @@ block modal-body-content
     a(href="#")
         div.choose-option(data-preset-type="grassy", data-preset-size="small")
           div.preset-size.name-label
-            span(data-i18n="ladder.small") Small
+            span(data-i18n="editor.small") Small
           div.preset-name
-            span(data-i18n="ladder.grassy") Grassy
+            span(data-i18n="editor.grassy") Grassy
     //- for model in models
 block modal-footer

From 1e5edb5efde8df31b8b8e84fb56939dc1cc488d0 Mon Sep 17 00:00:00 2001
From: Jayant Jain <jayantjain1992@gmail.com>
Date: Sun, 13 Jul 2014 23:45:24 +0530
Subject: [PATCH 12/33] Moves randomise modal template and view to
 editor/level/modal

---
 app/templates/editor/level/edit.jade                            | 2 +-
 app/templates/{ => editor/level}/modal/terrain_randomise.jade   | 0
 .../{ => editor/level}/modal/terrain_randomise_modal.coffee     | 2 +-
 3 files changed, 2 insertions(+), 2 deletions(-)
 rename app/templates/{ => editor/level}/modal/terrain_randomise.jade (100%)
 rename app/views/{ => editor/level}/modal/terrain_randomise_modal.coffee (98%)

diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade
index 09776b637..8f7e2a3b4 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -80,7 +80,7 @@ block header
             li(class=anonymous ? "disabled": "")
               a(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert")#revert-button Revert
             li(class=anonymous ? "disabled": "")
-              a(data-toggle="coco-modal", data-target="modal/terrain_randomise", data-i18n="editor.randomize")#randomise-button Randomise
+              a(data-toggle="coco-modal", data-target="editor/level/modal/terrain_randomise", data-i18n="editor.randomise")#randomise-button Randomise
             li(class=anonymous ? "disabled": "")
               a(data-i18n="editor.pop_i18n")#pop-level-i18n-button Populate i18n
             li.divider
diff --git a/app/templates/modal/terrain_randomise.jade b/app/templates/editor/level/modal/terrain_randomise.jade
similarity index 100%
rename from app/templates/modal/terrain_randomise.jade
rename to app/templates/editor/level/modal/terrain_randomise.jade
diff --git a/app/views/modal/terrain_randomise_modal.coffee b/app/views/editor/level/modal/terrain_randomise_modal.coffee
similarity index 98%
rename from app/views/modal/terrain_randomise_modal.coffee
rename to app/views/editor/level/modal/terrain_randomise_modal.coffee
index d737f929f..9e10e5a4e 100644
--- a/app/views/modal/terrain_randomise_modal.coffee
+++ b/app/views/editor/level/modal/terrain_randomise_modal.coffee
@@ -1,5 +1,5 @@
 ModalView = require 'views/kinds/ModalView'
-template = require 'templates/modal/terrain_randomise'
+template = require 'templates/editor/level/modal/terrain_randomise'
 CocoModel = require 'models/CocoModel'
 
 clusters = {

From b934d22cbdd5fb44b14825b369ee6a89c6e6e760 Mon Sep 17 00:00:00 2001
From: Jayant Jain <jayantjain1992@gmail.com>
Date: Mon, 14 Jul 2014 01:28:21 +0530
Subject: [PATCH 13/33] Batches insertion of thangs to treema to speed up
 terrain generation

---
 app/views/editor/level/thangs_tab_view.coffee | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/app/views/editor/level/thangs_tab_view.coffee b/app/views/editor/level/thangs_tab_view.coffee
index e594b00be..304cdab34 100644
--- a/app/views/editor/level/thangs_tab_view.coffee
+++ b/app/views/editor/level/thangs_tab_view.coffee
@@ -225,9 +225,11 @@ module.exports = class ThangsTabView extends View
     @editThang thangID: e.thang.id
 
   onRandomiseTerrain: (e) ->
+    @thangsBatch = []
     for thang in e.thangs
       @selectAddThangType thang.id
-      @addThang @addThangType, thang.pos
+      @addThang @addThangType, thang.pos, true
+    @batchInsert()
     @selectAddThangType null
 
   # TODO: figure out a good way to have all Surface clicks and Treema clicks just proxy in one direction, so we can maintain only one way of handling selection and deletion
@@ -397,7 +399,11 @@ module.exports = class ThangsTabView extends View
     id = treema?.data?.id
     @editThang thangID: id if id
 
-  addThang: (thangType, pos) ->
+  batchInsert: ->
+    @thangsTreema.set '', @thangsBatch
+    @thangsBatch = []
+
+  addThang: (thangType, pos, batchInsert = false) ->
     thangID = Thang.nextID(thangType.get('name'), @world) until thangID and not @thangsTreema.get "id=#{thangID}"
     if @cloneSourceThang
       components = _.cloneDeep @thangsTreema.get "id=#{@cloneSourceThang.id}/components"
@@ -408,7 +414,10 @@ module.exports = class ThangsTabView extends View
     physical = _.find components, (c) -> c.config?.pos?
     physical.config.pos = x: pos.x, y: pos.y, z: physical.config.pos.z if physical
     thang = thangType: thangType.get('original'), id: thangID, components: components
-    @thangsTreema.insert '', thang
+    if batchInsert
+      @thangsBatch.push thang
+    else 
+      @thangsTreema.insert '', thang
 
   editThang: (e) ->
     if e.target  # click event

From deecd7d2ff3f9d26a8705f6b88dbc8b0da2b9546 Mon Sep 17 00:00:00 2001
From: Jayant Jain <jayantjain1992@gmail.com>
Date: Mon, 14 Jul 2014 01:30:39 +0530
Subject: [PATCH 14/33] Deletes previously randomised thangs when generating
 again

---
 app/views/editor/level/thangs_tab_view.coffee | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/app/views/editor/level/thangs_tab_view.coffee b/app/views/editor/level/thangs_tab_view.coffee
index 304cdab34..e2685f6fa 100644
--- a/app/views/editor/level/thangs_tab_view.coffee
+++ b/app/views/editor/level/thangs_tab_view.coffee
@@ -226,6 +226,9 @@ module.exports = class ThangsTabView extends View
 
   onRandomiseTerrain: (e) ->
     @thangsBatch = []
+    for id in @randomiseThangIDs?
+      @thangsTreema.delete "id=#{id}"
+    @randomiseThangIDs = []
     for thang in e.thangs
       @selectAddThangType thang.id
       @addThang @addThangType, thang.pos, true
@@ -405,6 +408,7 @@ module.exports = class ThangsTabView extends View
 
   addThang: (thangType, pos, batchInsert = false) ->
     thangID = Thang.nextID(thangType.get('name'), @world) until thangID and not @thangsTreema.get "id=#{thangID}"
+    @randomiseThangIDs.push thangID
     if @cloneSourceThang
       components = _.cloneDeep @thangsTreema.get "id=#{@cloneSourceThang.id}/components"
       @selectAddThang null

From ebfb329da738ae83243685810f13ebb8423db33d Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Sun, 13 Jul 2014 13:11:45 -0700
Subject: [PATCH 15/33] Fixed a bug where pressing escape would not properly
 end scripts in the session state.

---
 app/lib/scripts/ScriptManager.coffee | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/app/lib/scripts/ScriptManager.coffee b/app/lib/scripts/ScriptManager.coffee
index 0ba6ae9bd..cea2b14ee 100644
--- a/app/lib/scripts/ScriptManager.coffee
+++ b/app/lib/scripts/ScriptManager.coffee
@@ -320,6 +320,7 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass
       if ((noteGroup.script?.skippable) is false) and not options.force
         @noteGroupQueue = @noteGroupQueue[i..]
         @run()
+        @notifyScriptStateChanged()
         return
 
       @processNoteGroup(noteGroup)
@@ -331,6 +332,7 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass
     @noteGroupQueue = []
 
     @resetThings()
+    @notifyScriptStateChanged()
 
   onNoteGroupTimeout: (noteGroup) ->
     return unless noteGroup is @currentNoteGroup

From bd7c2d0d368efd547d59e5a63ce45214d8ef16f1 Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <rubenvereecken@gmail.com>
Date: Sun, 13 Jul 2014 20:09:18 +0200
Subject: [PATCH 16/33] Bootstrappified Wizard Settings modal

---
 app/styles/modal/wizard_settings.sass    | 10 +++++-----
 app/templates/modal/wizard_settings.jade | 11 +++++++----
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/app/styles/modal/wizard_settings.sass b/app/styles/modal/wizard_settings.sass
index 09c4bc10e..7ba94a9c3 100644
--- a/app/styles/modal/wizard_settings.sass
+++ b/app/styles/modal/wizard_settings.sass
@@ -9,9 +9,9 @@
     display: block
     float: none
     background: white
-    
-  .wizard-name-line
+
+  #wizard-settings-name-wrapper
+    padding-left: 0px !important
+
+  .help-block
     text-align: center
-    margin-bottom: 10px
-    label
-      margin-right: 10px
\ No newline at end of file
diff --git a/app/templates/modal/wizard_settings.jade b/app/templates/modal/wizard_settings.jade
index ea22506ec..5d7d91a6b 100644
--- a/app/templates/modal/wizard_settings.jade
+++ b/app/templates/modal/wizard_settings.jade
@@ -4,10 +4,13 @@ block modal-header-content
   h3(data-i18n="wizard_settings.title2") Customize Your Character
 
 block modal-body-content
-  div.wizard-name-line.form-group
-    label.control-label(for="name")
-      | Your Wizardly Name:
-    input#wizard-settings-name(name="name", type="text", value="#{me.get('name')||''}")
+  form.form-horizontal
+    div.form-group
+      .row
+        label.control-label.col-sm-6(for="name")
+          | Your Wizardly Name:
+        #wizard-settings-name-wrapper.col-sm-4
+          input#wizard-settings-name.form-control.input-sm(name="name", type="text", value="#{me.get('name')||''}")
 
   #wizard-settings-view
 

From 6dc2a48b759ff1a8a6b78710d879f942e5b81db1 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 13 Jul 2014 16:07:15 -0700
Subject: [PATCH 17/33] Tracking time spent reading initial guides.

---
 app/schemas/subscriptions/misc.coffee | 3 +++
 app/views/kinds/CocoView.coffee       | 3 ++-
 app/views/play/level_view.coffee      | 8 +++++++-
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/app/schemas/subscriptions/misc.coffee b/app/schemas/subscriptions/misc.coffee
index 87ff86cac..439464851 100644
--- a/app/schemas/subscriptions/misc.coffee
+++ b/app/schemas/subscriptions/misc.coffee
@@ -9,6 +9,9 @@ module.exports =
   'note-group-ended':
     {} # TODO schema
 
+  'modal-opened':
+    {} # TODO schema
+
   'modal-closed':
     {} # TODO schema
 
diff --git a/app/views/kinds/CocoView.coffee b/app/views/kinds/CocoView.coffee
index 21b432dd7..264e3539c 100644
--- a/app/views/kinds/CocoView.coffee
+++ b/app/views/kinds/CocoView.coffee
@@ -177,6 +177,7 @@ module.exports = class CocoView extends Backbone.View
     $('#modal-wrapper .modal').modal(modalOptions).on 'hidden.bs.modal', @modalClosed
     window.currentModal = modalView
     @getRootView().stopListeningToShortcuts(true)
+    Backbone.Mediator.publish 'modal-opened', {}
 
   modalClosed: =>
     visibleModal.willDisappear() if visibleModal
@@ -190,7 +191,7 @@ module.exports = class CocoView extends Backbone.View
       @openModalView(wm)
     else
       @getRootView().listenToShortcuts(true)
-      Backbone.Mediator.publish 'modal-closed'
+      Backbone.Mediator.publish 'modal-closed', {}
 
   # Loading RootViews
 
diff --git a/app/views/play/level_view.coffee b/app/views/play/level_view.coffee
index 70a93f6b2..e2669b2b0 100644
--- a/app/views/play/level_view.coffee
+++ b/app/views/play/level_view.coffee
@@ -138,7 +138,13 @@ module.exports = class PlayLevelView extends View
       supermodel: @supermodel
       firstOnly: true
     @openModalView(new DocsModal(options), true)
-    Backbone.Mediator.subscribeOnce 'modal-closed', @onLevelStarted, @
+    onGuideOpened = ->
+      @guideOpenTime = new Date()
+    onGuideClosed = ->
+      application.tracker?.trackTiming new Date() - @guideOpenTime, 'Intro Guide Time', @levelID, @levelID, 100
+      @onLevelStarted()
+    Backbone.Mediator.subscribeOnce 'modal-opened', onGuideOpened, @
+    Backbone.Mediator.subscribeOnce 'modal-closed', onGuideClosed, @
     return true
 
   getRenderData: ->

From ffb8f9575ec5ace6dca65bb84d1c87e14767b3e0 Mon Sep 17 00:00:00 2001
From: Pete DiSalvo <pdisalvo486@gmail.com>
Date: Sun, 13 Jul 2014 19:31:34 -0400
Subject: [PATCH 18/33] Added point marker shape, and split updateSize method
 into helpers.

---
 app/lib/surface/CoordinateDisplay.coffee | 59 +++++++++++++++++++-----
 1 file changed, 47 insertions(+), 12 deletions(-)

diff --git a/app/lib/surface/CoordinateDisplay.coffee b/app/lib/surface/CoordinateDisplay.coffee
index 87302f37a..3892d1903 100644
--- a/app/lib/surface/CoordinateDisplay.coffee
+++ b/app/lib/surface/CoordinateDisplay.coffee
@@ -25,9 +25,11 @@ module.exports = class CoordinateDisplay extends createjs.Container
     @mouseEnabled = @mouseChildren = false
     @addChild @background = new createjs.Shape()
     @addChild @label = new createjs.Text('', 'bold 16px Arial', '#FFFFFF')
+    @addChild @pointMarker = new createjs.Shape()
     @label.name = 'Coordinate Display Text'
     @label.shadow = new createjs.Shadow('#000000', 1, 1, 0)
     @background.name = 'Coordinate Display Background'
+    @pointMarker.name = 'Point Marker'
 
   onMouseOver: (e) -> @mouseInBounds = true
   onMouseOut: (e) -> @mouseInBounds = false
@@ -60,26 +62,58 @@ module.exports = class CoordinateDisplay extends createjs.Container
     return unless @label.parent
     @removeChild @label
     @removeChild @background
+    @removeChild @pointMarker
     @uncache()
 
   updateSize: ->
     margin = 3
-    radius = 2.5
-    width = @label.getMeasuredWidth() + 2 * margin
-    height = @label.getMeasuredHeight() + 2 * margin
-    @label.regX = @background.regX = width / 2
-    @label.regY = @background.regY = height / 2
-    @label.regX -= margin
-    @label.regY -= margin
+    contentWidth = @label.getMeasuredWidth() + (2 * margin)
+    contentHeight = @label.getMeasuredHeight() + (2 * margin)
+
+    # Shift all contents up so marker is at pointer (affects container cache position)
+    @label.regY = @background.regY = @pointMarker.regY = contentHeight
+
+    pointMarkerStroke = 2
+    pointMarkerLength = 3
+    contributionsToTotalSize = []
+    contributionsToTotalSize = contributionsToTotalSize.concat @updateCoordinates contentWidth, contentHeight, pointMarkerStroke
+    contributionsToTotalSize = contributionsToTotalSize.concat @updatePointMarker contentHeight, pointMarkerLength, pointMarkerStroke
+
+    totalWidth = contentWidth + contributionsToTotalSize.reduce (a, b) -> a + b
+    totalHeight = contentHeight + contributionsToTotalSize.reduce (a, b) -> a + b
+    [totalWidth, totalHeight]
+
+  updateCoordinates: (contentWidth, contentHeight, initialXYOffset) ->
+    gap = 2
+    labelAndBgMarkerOffset = initialXYOffset * gap
+
+    # Center label horizontally and vertically
+    @label.x = contentWidth / 2 - (@label.getMeasuredWidth() / 2) + labelAndBgMarkerOffset
+    @label.y = contentHeight / 2 - (@label.getMeasuredHeight() / 2) - labelAndBgMarkerOffset
+
     @background.graphics
       .clear()
       .beginFill('rgba(0,0,0,0.4)')
       .beginStroke('rgba(0,0,0,0.6)')
-      .setStrokeStyle(1)
-      .drawRoundRect(0, 0, width, height, radius)
+      .setStrokeStyle(backgroundStroke = 1)
+      .drawRoundRect(labelAndBgMarkerOffset, -labelAndBgMarkerOffset, contentWidth, contentHeight, radius = 2.5)
       .endFill()
       .endStroke()
-    [width, height]
+    contributionsToTotalSize = [labelAndBgMarkerOffset, backgroundStroke]
+
+  updatePointMarker: (contentHeight, length, strokeSize) ->
+    shiftToLineupWithGrid = strokeSize / 2
+    pointMarkerInitialX = strokeSize - shiftToLineupWithGrid
+    pointMarkerInitialY = contentHeight - strokeSize + shiftToLineupWithGrid
+    @pointMarker.graphics
+      .beginStroke('rgb(142, 198, 67')
+      .setStrokeStyle(strokeSize, 'square')
+      .moveTo(pointMarkerInitialX, pointMarkerInitialY)
+      .lineTo(pointMarkerInitialX, pointMarkerInitialY - length)
+      .moveTo(pointMarkerInitialX, pointMarkerInitialY)
+      .lineTo(pointMarkerInitialX + length, pointMarkerInitialY)
+      .endStroke()
+    contributionsToTotalSize = [strokeSize]
 
   show: =>
     return unless @mouseInBounds and @lastPos and not @destroyed
@@ -87,8 +121,9 @@ module.exports = class CoordinateDisplay extends createjs.Container
     [width, height] = @updateSize()
     sup = @camera.worldToSurface @lastPos
     @x = sup.x
-    @y = sup.y - 2.5
+    @y = sup.y
     @addChild @background
     @addChild @label
-    @cache -width / 2, -height / 2, width, height
+    @addChild @pointMarker
+    @cache 0, -height, width, height
     Backbone.Mediator.publish 'surface:coordinates-shown', {}

From 6eea28dc19b2fbeb9d9b28f6683984f0efec3569 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 13 Jul 2014 16:40:03 -0700
Subject: [PATCH 19/33] Error handling for syntax errors in component code.

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

diff --git a/app/lib/world/world.coffee b/app/lib/world/world.coffee
index 3e929ef77..eb496133b 100644
--- a/app/lib/world/world.coffee
+++ b/app/lib/world/world.coffee
@@ -207,7 +207,11 @@ module.exports = class World
     map = if kind is 'component' then @componentCodeClassMap else @systemCodeClassMap
     c = map[js]
     return c if c
-    c = map[js] = eval js
+    try
+      c = map[js] = eval js
+    catch err
+      console.error "Couldn't compile #{kind} code:", err, "\n", js
+      c = map[js] = {}
     c.className = name
     c
 

From 2a5a366c12281c6f1f143c56759edb442cfab5be Mon Sep 17 00:00:00 2001
From: Michael Schmatz <michaelschmatz@gmail.com>
Date: Sun, 13 Jul 2014 17:22:04 -0700
Subject: [PATCH 20/33] Made language selection in opponent modal

---
 app/locale/ar.coffee                      |  2 ++
 app/locale/bg.coffee                      |  2 ++
 app/locale/ca.coffee                      |  2 ++
 app/locale/cs.coffee                      |  2 ++
 app/locale/da.coffee                      |  2 ++
 app/locale/de-AT.coffee                   |  2 ++
 app/locale/de-CH.coffee                   |  2 ++
 app/locale/de-DE.coffee                   |  2 ++
 app/locale/de.coffee                      |  2 ++
 app/locale/el.coffee                      |  2 ++
 app/locale/en-AU.coffee                   |  2 ++
 app/locale/en-GB.coffee                   |  1 +
 app/locale/en-US.coffee                   |  2 ++
 app/locale/en.coffee                      |  1 +
 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.coffee                      |  2 ++
 app/locale/nb.coffee                      |  2 ++
 app/locale/nl-BE.coffee                   |  2 ++
 app/locale/nl-NL.coffee                   |  2 ++
 app/locale/nl.coffee                      |  2 ++
 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                      |  2 ++
 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-WUU-HANS.coffee             |  2 ++
 app/locale/zh-WUU-HANT.coffee             |  2 ++
 app/locale/zh.coffee                      |  2 ++
 app/templates/play/ladder/play_modal.jade |  7 ++++--
 app/views/play/ladder/play_modal.coffee   | 26 +++++++++++++++++++++--
 57 files changed, 137 insertions(+), 4 deletions(-)

diff --git a/app/locale/ar.coffee b/app/locale/ar.coffee
index 329ce4a32..93541c165 100644
--- a/app/locale/ar.coffee
+++ b/app/locale/ar.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/bg.coffee b/app/locale/bg.coffee
index 2c71d71a8..409851289 100644
--- a/app/locale/bg.coffee
+++ b/app/locale/bg.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "български език", englishDescri
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "български език", englishDescri
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/ca.coffee b/app/locale/ca.coffee
index 963ab4e9d..ba2af7aa7 100644
--- a/app/locale/ca.coffee
+++ b/app/locale/ca.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/cs.coffee b/app/locale/cs.coffee
index 33a31ceac..7e2a61ef2 100644
--- a/app/locale/cs.coffee
+++ b/app/locale/cs.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/da.coffee b/app/locale/da.coffee
index d6fb0dfd3..7d137506e 100644
--- a/app/locale/da.coffee
+++ b/app/locale/da.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/de-AT.coffee b/app/locale/de-AT.coffee
index 482c2eeab..227969de6 100644
--- a/app/locale/de-AT.coffee
+++ b/app/locale/de-AT.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription:
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription:
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/de-CH.coffee b/app/locale/de-CH.coffee
index 0e045f99c..dbbd647bf 100644
--- a/app/locale/de-CH.coffee
+++ b/app/locale/de-CH.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/de-DE.coffee b/app/locale/de-DE.coffee
index 59dbeab1f..b08f8bbd5 100644
--- a/app/locale/de-DE.coffee
+++ b/app/locale/de-DE.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
     revert_models: "Models zurücksetzen."
     fork_title: "Forke neue Version"
     fork_creating: "Erzeuge Fork..."
+#    randomize: "Randomize"
     more: "Mehr"
     wiki: "Wiki"
     live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
     choose_opponent: "Wähle einen Gegner"
+#    select_your_language: "Select your language!"
     tutorial_play: "Spiele Tutorial"
     tutorial_recommended: "Empfohlen, wenn du noch nie zuvor gespielt hast."
     tutorial_skip: "Überspringe Tutorial"
diff --git a/app/locale/de.coffee b/app/locale/de.coffee
index a2f22679c..61ef7caf1 100644
--- a/app/locale/de.coffee
+++ b/app/locale/de.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra
     revert_models: "Models zurücksetzen."
     fork_title: "Forke neue Version"
     fork_creating: "Erzeuge Fork..."
+#    randomize: "Randomize"
     more: "Mehr"
     wiki: "Wiki"
     live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
     choose_opponent: "Wähle einen Gegner"
+#    select_your_language: "Select your language!"
     tutorial_play: "Spiele Tutorial"
     tutorial_recommended: "Empfohlen, wenn du noch nie zuvor gespielt hast."
     tutorial_skip: "Überspringe Tutorial"
diff --git a/app/locale/el.coffee b/app/locale/el.coffee
index 4583ce9dc..890553148 100644
--- a/app/locale/el.coffee
+++ b/app/locale/el.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "ελληνικά", englishDescription: "Gre
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "ελληνικά", englishDescription: "Gre
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/en-AU.coffee b/app/locale/en-AU.coffee
index 8f073d7d7..6842729ee 100644
--- a/app/locale/en-AU.coffee
+++ b/app/locale/en-AU.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/en-GB.coffee b/app/locale/en-GB.coffee
index 6399f9413..18966f32d 100644
--- a/app/locale/en-GB.coffee
+++ b/app/locale/en-GB.coffee
@@ -802,6 +802,7 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/en-US.coffee b/app/locale/en-US.coffee
index ce19759c6..a1bb56e05 100644
--- a/app/locale/en-US.coffee
+++ b/app/locale/en-US.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index 69f5afda6..837b52deb 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -802,6 +802,7 @@
     no_ranked_matches_pre: "No ranked matches for the "
     no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
     choose_opponent: "Choose an Opponent"
+    select_your_language: "Select your language!"
     tutorial_play: "Play Tutorial"
     tutorial_recommended: "Recommended if you've never played before"
     tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/es-419.coffee b/app/locale/es-419.coffee
index 6c8fb4120..b75646620 100644
--- a/app/locale/es-419.coffee
+++ b/app/locale/es-419.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip
     no_ranked_matches_pre: "Sin partidas clasificadas para el "
     no_ranked_matches_post: " equipo! Juega en contra de algunos competidores y luego vuelve aquí para ver tu juego clasificado."
     choose_opponent: "Escoge un Oponente"
+#    select_your_language: "Select your language!"
     tutorial_play: "Juega el Tutorial"
     tutorial_recommended: "Recomendado si nunca has jugado antes"
     tutorial_skip: "Saltar Tutorial"
diff --git a/app/locale/es-ES.coffee b/app/locale/es-ES.coffee
index a011e016e..c049eb731 100644
--- a/app/locale/es-ES.coffee
+++ b/app/locale/es-ES.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
     revert_models: "Revertir Modelos"
     fork_title: "Bifurcar nueva versión"
     fork_creating: "Creando bifurcación..."
+#    randomize: "Randomize"
     more: "Más"
     wiki: "Wiki"
     live_chat: "Chat en directo"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
     no_ranked_matches_pre: "No hay partidas calificadas para "
     no_ranked_matches_post: " equipo! Juega contra otros competidores y luego vuelve aquí para que tu partida aparezca en la clasificación."
     choose_opponent: "Elige un contrincante"
+#    select_your_language: "Select your language!"
     tutorial_play: "Jugar el Tutorial"
     tutorial_recommended: "Recomendado si no has jugado antes."
     tutorial_skip: "Saltar el Tutorial"
diff --git a/app/locale/es.coffee b/app/locale/es.coffee
index 80a6e5284..5281292f0 100644
--- a/app/locale/es.coffee
+++ b/app/locale/es.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
     tutorial_play: "Jugar Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
     tutorial_skip: "Saltar Tutorial"
diff --git a/app/locale/fa.coffee b/app/locale/fa.coffee
index 5b1ca0e81..6256c0e4e 100644
--- a/app/locale/fa.coffee
+++ b/app/locale/fa.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/fi.coffee b/app/locale/fi.coffee
index 83148a058..2d905bec1 100644
--- a/app/locale/fi.coffee
+++ b/app/locale/fi.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/fr.coffee b/app/locale/fr.coffee
index af1a2116d..d0e5817ac 100644
--- a/app/locale/fr.coffee
+++ b/app/locale/fr.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     revert_models: "Annuler les modèles"
     fork_title: "Fork une nouvelle version"
     fork_creating: "Créer un Fork..."
+#    randomize: "Randomize"
     more: "Plus"
     wiki: "Wiki"
     live_chat: "Chat en live"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     no_ranked_matches_pre: "Pas de match classé pour l'équipe "
     no_ranked_matches_post: "! Affronte d'autres compétiteurs et reviens ici pour classer ta partie."
     choose_opponent: "Choisir un Adversaire"
+#    select_your_language: "Select your language!"
     tutorial_play: "Jouer au Tutoriel"
     tutorial_recommended: "Recommendé si tu n'as jamais joué avant"
     tutorial_skip: "Passer le Tutoriel"
diff --git a/app/locale/he.coffee b/app/locale/he.coffee
index e512e32fc..a0fdeee6b 100644
--- a/app/locale/he.coffee
+++ b/app/locale/he.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/hi.coffee b/app/locale/hi.coffee
index 57fc1b082..43674f6a6 100644
--- a/app/locale/hi.coffee
+++ b/app/locale/hi.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/hu.coffee b/app/locale/hu.coffee
index 84c761e11..3a7889e63 100644
--- a/app/locale/hu.coffee
+++ b/app/locale/hu.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/id.coffee b/app/locale/id.coffee
index 6951b4b67..2db554260 100644
--- a/app/locale/id.coffee
+++ b/app/locale/id.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/it.coffee b/app/locale/it.coffee
index 783e6c297..925eb0b28 100644
--- a/app/locale/it.coffee
+++ b/app/locale/it.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
     no_ranked_matches_pre: "Nessuna partita valutata per "
     no_ranked_matches_post: " squadra! Gioca contro altri avversari e poi torna qui affinchè la tua partita venga valutata."
     choose_opponent: "Scegli un avversario"
+#    select_your_language: "Select your language!"
     tutorial_play: "Gioca il Tutorial"
     tutorial_recommended: "Consigliato se questa è la tua primissima partita"
     tutorial_skip: "Salta il Tutorial"
diff --git a/app/locale/ja.coffee b/app/locale/ja.coffee
index b4a088cb0..60e7e4c2e 100644
--- a/app/locale/ja.coffee
+++ b/app/locale/ja.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/ko.coffee b/app/locale/ko.coffee
index bb32495d4..f12d29fa8 100644
--- a/app/locale/ko.coffee
+++ b/app/locale/ko.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
     revert_models: "모델 되돌리기"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/lt.coffee b/app/locale/lt.coffee
index 6c3df3e2c..4ce34b72f 100644
--- a/app/locale/lt.coffee
+++ b/app/locale/lt.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/ms.coffee b/app/locale/ms.coffee
index 5c97c5b2f..5dd010d55 100644
--- a/app/locale/ms.coffee
+++ b/app/locale/ms.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/nb.coffee b/app/locale/nb.coffee
index a56bcf571..cec0a46b1 100644
--- a/app/locale/nb.coffee
+++ b/app/locale/nb.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/nl-BE.coffee b/app/locale/nl-BE.coffee
index d0fa2550e..3123b8ed5 100644
--- a/app/locale/nl-BE.coffee
+++ b/app/locale/nl-BE.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
     revert_models: "keer wijziging model terug"
     fork_title: "Kloon naar nieuwe versie"
     fork_creating: "Kloon aanmaken..."
+#    randomize: "Randomize"
     more: "Meer"
     wiki: "Wiki"
     live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
     no_ranked_matches_pre: "Geen beoordeelde wedstrijden voor het"
     no_ranked_matches_post: " team! Speel tegen enkele tegenstanders en kom terug hier om uw spel te laten beoordelen."
     choose_opponent: "Kies een tegenstander"
+#    select_your_language: "Select your language!"
     tutorial_play: "Speel de Tutorial"
     tutorial_recommended: "Aanbevolen als je nog niet eerder hebt gespeeld"
     tutorial_skip: "Sla Tutorial over"
diff --git a/app/locale/nl-NL.coffee b/app/locale/nl-NL.coffee
index cffcdbb90..f0844876e 100644
--- a/app/locale/nl-NL.coffee
+++ b/app/locale/nl-NL.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
     revert_models: "keer wijziging model terug"
     fork_title: "Kloon naar nieuwe versie"
     fork_creating: "Kloon aanmaken..."
+#    randomize: "Randomize"
     more: "Meer"
     wiki: "Wiki"
     live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
     no_ranked_matches_pre: "Geen beoordeelde wedstrijden voor het"
     no_ranked_matches_post: " team! Speel tegen enkele tegenstanders en kom terug hier om uw spel te laten beoordelen."
     choose_opponent: "Kies een tegenstander"
+#    select_your_language: "Select your language!"
     tutorial_play: "Speel de Tutorial"
     tutorial_recommended: "Aanbevolen als je nog niet eerder hebt gespeeld"
     tutorial_skip: "Sla Tutorial over"
diff --git a/app/locale/nl.coffee b/app/locale/nl.coffee
index a3dffd22a..2162df73a 100644
--- a/app/locale/nl.coffee
+++ b/app/locale/nl.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     revert_models: "keer wijziging model terug"
     fork_title: "Kloon naar nieuwe versie"
     fork_creating: "Kloon aanmaken..."
+#    randomize: "Randomize"
     more: "Meer"
     wiki: "Wiki"
     live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
     no_ranked_matches_pre: "Geen beoordeelde wedstrijden voor het"
     no_ranked_matches_post: " team! Speel tegen enkele tegenstanders en kom terug hier om uw spel te laten beoordelen."
     choose_opponent: "Kies een tegenstander"
+#    select_your_language: "Select your language!"
     tutorial_play: "Speel de Tutorial"
     tutorial_recommended: "Aanbevolen als je nog niet eerder hebt gespeeld"
     tutorial_skip: "Sla Tutorial over"
diff --git a/app/locale/nn.coffee b/app/locale/nn.coffee
index 8b208c04c..21016cee4 100644
--- a/app/locale/nn.coffee
+++ b/app/locale/nn.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/no.coffee b/app/locale/no.coffee
index 12fea1777..f4e85c765 100644
--- a/app/locale/no.coffee
+++ b/app/locale/no.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/pl.coffee b/app/locale/pl.coffee
index b5b4c1fc1..695ba2937 100644
--- a/app/locale/pl.coffee
+++ b/app/locale/pl.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish
     revert_models: "Przywróć wersję"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish
     no_ranked_matches_pre: "Brak ocenionych pojedynków dla drużyny "
     no_ranked_matches_post: " ! Zagraj przeciwko kilku oponentom i wróc tutaj, aby uzyskać ocenę gry."
     choose_opponent: "Wybierz przeciwnika"
+#    select_your_language: "Select your language!"
     tutorial_play: "Rozegraj samouczek"
     tutorial_recommended: "Zalecane, jeśli wcześniej nie grałeś"
     tutorial_skip: "Pomiń samouczek"
diff --git a/app/locale/pt-BR.coffee b/app/locale/pt-BR.coffee
index 5d2401c91..b678dbdf2 100644
--- a/app/locale/pt-BR.coffee
+++ b/app/locale/pt-BR.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription:
     revert_models: "Reverter Modelos"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
     more: "Mais"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription:
     no_ranked_matches_pre: "Sem partidas classificadas para o "
     no_ranked_matches_post: " time! Jogue contra alguns competidores e então volte aqui para ter seu jogo classificado."
     choose_opponent: "Escolha um Oponente"
+#    select_your_language: "Select your language!"
     tutorial_play: "Jogue o Tutorial"
     tutorial_recommended: "Recomendado se você nunca jogou antes"
     tutorial_skip: "Pular Tutorial"
diff --git a/app/locale/pt-PT.coffee b/app/locale/pt-PT.coffee
index 47bdd3772..6a36a4a65 100644
--- a/app/locale/pt-PT.coffee
+++ b/app/locale/pt-PT.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
     revert_models: "Reverter Modelos"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
     no_ranked_matches_pre: "Sem jogos classificados pela equipa "
     no_ranked_matches_post: "! Joga contra alguns adversários e volta aqui para veres o teu jogo classificado."
     choose_opponent: "Escolhe um Adversário"
+#    select_your_language: "Select your language!"
     tutorial_play: "Jogar Tutorial"
     tutorial_recommended: "Recomendado se nunca jogaste antes"
     tutorial_skip: "Saltar Tutorial"
diff --git a/app/locale/pt.coffee b/app/locale/pt.coffee
index dd75d506b..ae5e903a3 100644
--- a/app/locale/pt.coffee
+++ b/app/locale/pt.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/ro.coffee b/app/locale/ro.coffee
index 2f2ad4c65..fa367f2fd 100644
--- a/app/locale/ro.coffee
+++ b/app/locale/ro.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
     revert_models: "Resetează Modelele"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
     no_ranked_matches_pre: "Nici un meci de clasament pentru "
     no_ranked_matches_post: " echipă! Joacă împotriva unor concurenți și revino apoi aici pentr a-ți plasa meciul in clasament."
     choose_opponent: "Alege un adversar"
+#    select_your_language: "Select your language!"
     tutorial_play: "Joacă Tutorial-ul"
     tutorial_recommended: "Recomandat dacă nu ai mai jucat niciodată înainte"
     tutorial_skip: "Sari peste Tutorial"
diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee
index 4ecae8dcc..2a9a29870 100644
--- a/app/locale/ru.coffee
+++ b/app/locale/ru.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     revert_models: "Откатить Модели"
     fork_title: "Форк новой версии"
     fork_creating: "Создание форка..."
+#    randomize: "Randomize"
     more: "Ещё"
     wiki: "Вики"
     live_chat: "Онлайн-чат"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
     no_ranked_matches_pre: "Нет оценённых матчей для команды"
     no_ranked_matches_post: "! Сыграйте против нескольких противников и возвращайтесь сюда для оценки вашей игры."
     choose_opponent: "Выберите противника"
+#    select_your_language: "Select your language!"
     tutorial_play: "Пройти обучение"
     tutorial_recommended: "Рекомендуется, если вы раньше никогда не играли"
     tutorial_skip: "Пропустить обучение"
diff --git a/app/locale/sk.coffee b/app/locale/sk.coffee
index d2db15a1a..bee1b7edf 100644
--- a/app/locale/sk.coffee
+++ b/app/locale/sk.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/sl.coffee b/app/locale/sl.coffee
index 4323e23c1..e75b5df8f 100644
--- a/app/locale/sl.coffee
+++ b/app/locale/sl.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/sr.coffee b/app/locale/sr.coffee
index 801791e04..6ea2af629 100644
--- a/app/locale/sr.coffee
+++ b/app/locale/sr.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/sv.coffee b/app/locale/sv.coffee
index 30fcc2758..49ed0652c 100644
--- a/app/locale/sv.coffee
+++ b/app/locale/sv.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
     revert_models: "Återställ modeller"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
     no_ranked_matches_pre: "Inga rankade matcher för "
     no_ranked_matches_post: " laget! Spela mot några motståndare och kom sedan tillbaka it för att få din match rankad."
     choose_opponent: "Välj en motståndare"
+#    select_your_language: "Select your language!"
     tutorial_play: "Spela tutorial"
     tutorial_recommended: "Rekommenderas om du aldrig har spelat tidigare"
     tutorial_skip: "Hoppa över tutorial"
diff --git a/app/locale/th.coffee b/app/locale/th.coffee
index f78ae1e8b..d97529f7b 100644
--- a/app/locale/th.coffee
+++ b/app/locale/th.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/tr.coffee b/app/locale/tr.coffee
index fe40f5120..fed1c455a 100644
--- a/app/locale/tr.coffee
+++ b/app/locale/tr.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
     revert_models: "Önceki Modeller"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/uk.coffee b/app/locale/uk.coffee
index 8b222c5e5..51d3d34f0 100644
--- a/app/locale/uk.coffee
+++ b/app/locale/uk.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
     revert_models: "Моделі повернення"
     fork_title: "Нова версія Форк"
     fork_creating: "Створення Форк..."
+#    randomize: "Randomize"
     more: "Більше"
     wiki: "Wiki"
     live_chat: "Online чат"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/ur.coffee b/app/locale/ur.coffee
index 814c472da..f00732c1b 100644
--- a/app/locale/ur.coffee
+++ b/app/locale/ur.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/vi.coffee b/app/locale/vi.coffee
index c2489165f..8d6ece181 100644
--- a/app/locale/vi.coffee
+++ b/app/locale/vi.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/zh-HANS.coffee b/app/locale/zh-HANS.coffee
index 611fdba2e..e2436529f 100644
--- a/app/locale/zh-HANS.coffee
+++ b/app/locale/zh-HANS.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
     revert_models: "还原模式"
     fork_title: "派生新版本"
     fork_creating: "正在执行派生..."
+#    randomize: "Randomize"
     more: "更多"
     wiki: "维基"
     live_chat: "在线聊天"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
     choose_opponent: "选择一个对手"
+#    select_your_language: "Select your language!"
     tutorial_play: "玩教程"
     tutorial_recommended: "如果你从未玩过的话,推荐先玩下教程"
     tutorial_skip: "跳过教材"
diff --git a/app/locale/zh-HANT.coffee b/app/locale/zh-HANT.coffee
index 3c0785dfe..e936fd9a3 100644
--- a/app/locale/zh-HANT.coffee
+++ b/app/locale/zh-HANT.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/zh-WUU-HANS.coffee b/app/locale/zh-WUU-HANS.coffee
index 91a2eb0d1..4e063c0f6 100644
--- a/app/locale/zh-WUU-HANS.coffee
+++ b/app/locale/zh-WUU-HANS.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "吴语", englishDescription: "Wuu (Simplifi
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "吴语", englishDescription: "Wuu (Simplifi
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/locale/zh-WUU-HANT.coffee b/app/locale/zh-WUU-HANT.coffee
index 368667c74..2ef6d05f0 100644
--- a/app/locale/zh-WUU-HANT.coffee
+++ b/app/locale/zh-WUU-HANT.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "吳語", englishDescription: "Wuu (Traditio
     revert_models: "還原模式"
     fork_title: "派生新版本"
     fork_creating: "徠搭執行派生..."
+#    randomize: "Randomize"
     more: "無數"
     wiki: "維基"
     live_chat: "上線白嗒"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "吳語", englishDescription: "Wuu (Traditio
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
     choose_opponent: "揀一個對手"
+#    select_your_language: "Select your language!"
     tutorial_play: "攪教程"
     tutorial_recommended: "假使爾從來朆攪過個話,建議爾先畀教程攪攪相"
     tutorial_skip: "跳過教程"
diff --git a/app/locale/zh.coffee b/app/locale/zh.coffee
index b9c9d40fb..f7f8d98a0 100644
--- a/app/locale/zh.coffee
+++ b/app/locale/zh.coffee
@@ -501,6 +501,7 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
 #    revert_models: "Revert Models"
 #    fork_title: "Fork New Version"
 #    fork_creating: "Creating Fork..."
+#    randomize: "Randomize"
 #    more: "More"
 #    wiki: "Wiki"
 #    live_chat: "Live Chat"
@@ -801,6 +802,7 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
 #    no_ranked_matches_pre: "No ranked matches for the "
 #    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
 #    choose_opponent: "Choose an Opponent"
+#    select_your_language: "Select your language!"
 #    tutorial_play: "Play Tutorial"
 #    tutorial_recommended: "Recommended if you've never played before"
 #    tutorial_skip: "Skip Tutorial"
diff --git a/app/templates/play/ladder/play_modal.jade b/app/templates/play/ladder/play_modal.jade
index c3a0eb074..ba7321a1e 100644
--- a/app/templates/play/ladder/play_modal.jade
+++ b/app/templates/play/ladder/play_modal.jade
@@ -13,13 +13,16 @@ block modal-body-content
     span.btn.btn-primary.btn-block.btn-lg#skip-tutorial-button(data-i18n="ladder.tutorial_skip") Skip Tutorial
 
   div#normal-view
-  
     if tutorialLevelExists
       p.tutorial-suggestion
         strong(data-i18n="ladder.tutorial_not_sure") Not sure what's going on?
         |  
         a(href="/play/level/#{levelID}-tutorial", data-i18n="ladder.tutorial_play_first") Play the tutorial first.
-  
+    h4.language-selection(data-i18n="ladder.select_your_language") Select your language!
+    .form-group.select-group
+      select#tome-language(name="language")
+        for option in languages
+          option(value=option.id selected=(language === option.id))= option.name
     a(href="/play/level/#{levelID}?team=#{teamID}")
       div.play-option
         img(src=myPortrait).my-icon.only-one
diff --git a/app/views/play/ladder/play_modal.coffee b/app/views/play/ladder/play_modal.coffee
index e54e79a18..d1a1e74fa 100644
--- a/app/views/play/ladder/play_modal.coffee
+++ b/app/views/play/ladder/play_modal.coffee
@@ -15,16 +15,31 @@ module.exports = class LadderPlayModal extends View
 
   events:
     'click #skip-tutorial-button': 'hideTutorialButtons'
+    'change #tome-language': 'updateLanguage'
 
+  defaultAceConfig:
+    language: 'javascript'
+    keyBindings: 'default'
+    invisibles: false
+    indentGuides: false
+    behaviors: false
+    liveCompletion: true
+    
   constructor: (options, @level, @session, @team) ->
     super(options)
     @nameMap = {}
     @otherTeam = if team is 'ogres' then 'humans' else 'ogres'
     @startLoadingChallengersMaybe()
     @wizardType = ThangType.loadUniversalWizard()
+    
+  updateLanguage: ->
+    aceConfig = _.cloneDeep me.get('aceConfig') ? {}
+    aceConfig = _.defaults aceConfig, @defaultAceConfig
+    aceConfig.language = @$el.find('#tome-language').val()
+    me.set 'aceConfig', aceConfig
+    me.patch()
 
   # 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()
@@ -73,7 +88,14 @@ module.exports = class LadderPlayModal extends View
     ctx.teamID = @team
     ctx.otherTeamID = @otherTeam
     ctx.tutorialLevelExists = @tutorialLevelExists
-
+    ctx.languages = [
+      {id: 'javascript', name: 'JavaScript'}
+      {id: 'coffeescript', name: 'CoffeeScript'}
+      {id: 'python', name: 'Python (Experimental)'}
+      {id: 'clojure', name: 'Clojure (Experimental)'}
+      {id: 'lua', name: 'Lua (Experimental)'}
+      {id: 'io', name: 'Io (Experimental)'}
+    ]
     teamsList = teamDataFromLevel @level
     teams = {}
     teams[team.id] = team for team in teamsList

From f92b29a4a3eabfc635098267e289ae09b1edaf0b Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 13 Jul 2014 17:25:17 -0700
Subject: [PATCH 21/33] Added rotate to Vector APIs.

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

diff --git a/app/lib/world/vector.coffee b/app/lib/world/vector.coffee
index a17e5d077..712d99d64 100644
--- a/app/lib/world/vector.coffee
+++ b/app/lib/world/vector.coffee
@@ -2,13 +2,13 @@
 class Vector
   @className: 'Vector'
   # Class methods for nondestructively operating
-  for name in ['add', 'subtract', 'multiply', 'divide', 'limit', 'normalize']
+  for name in ['add', 'subtract', 'multiply', 'divide', 'limit', 'normalize', 'rotate']
     do (name) ->
       Vector[name] = (a, b, useZ) ->
         a.copy()[name](b, useZ)
 
   isVector: true
-  apiProperties: ['x', 'y', 'z', 'magnitude', 'heading', 'distance', 'dot', 'equals', 'copy', 'distanceSquared']
+  apiProperties: ['x', 'y', 'z', 'magnitude', 'heading', 'distance', 'dot', 'equals', 'copy', 'distanceSquared', 'rotate']
 
   constructor: (@x=0, @y=0, @z=0) ->
 

From 493ebd07e63d5f01e76b0300a39f3059c1e4d862 Mon Sep 17 00:00:00 2001
From: Jayant Jain <jayantjain1992@gmail.com>
Date: Mon, 14 Jul 2014 06:01:09 +0530
Subject: [PATCH 22/33] Changes randomise to randomize

---
 app/locale/en.coffee                          |  1 -
 .../level/modal/terrain_randomize.sass}       |  2 +-
 app/templates/editor/level/edit.jade          |  2 +-
 ..._randomise.jade => terrain_randomize.jade} |  0
 ....coffee => terrain_randomize_modal.coffee} | 28 +++++++++----------
 app/views/editor/level/thangs_tab_view.coffee | 11 ++++----
 6 files changed, 22 insertions(+), 22 deletions(-)
 rename app/styles/{terrain_randomise.sass => editor/level/modal/terrain_randomize.sass} (99%)
 rename app/templates/editor/level/modal/{terrain_randomise.jade => terrain_randomize.jade} (100%)
 rename app/views/editor/level/modal/{terrain_randomise_modal.coffee => terrain_randomize_modal.coffee} (88%)

diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index ff0713176..abee995de 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -499,7 +499,6 @@
     back: "Back"
     revert: "Revert"
     revert_models: "Revert Models"
-    randomise: "Randomise"
     pick_a_terrain: "Pick A Terrain"
     small: "Small"
     grassy: "Grassy"
diff --git a/app/styles/terrain_randomise.sass b/app/styles/editor/level/modal/terrain_randomize.sass
similarity index 99%
rename from app/styles/terrain_randomise.sass
rename to app/styles/editor/level/modal/terrain_randomize.sass
index e6cf29bec..892d4d52f 100644
--- a/app/styles/terrain_randomise.sass
+++ b/app/styles/editor/level/modal/terrain_randomize.sass
@@ -1,4 +1,4 @@
-#terrain-randomise-modal
+#terrain-randomize-modal
 
   .choose-option
     margin-bottom: 15px
diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade
index 8f7e2a3b4..d8e806903 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -80,7 +80,7 @@ block header
             li(class=anonymous ? "disabled": "")
               a(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert")#revert-button Revert
             li(class=anonymous ? "disabled": "")
-              a(data-toggle="coco-modal", data-target="editor/level/modal/terrain_randomise", data-i18n="editor.randomise")#randomise-button Randomise
+              a(data-toggle="coco-modal", data-target="editor/level/modal/terrain_randomize", data-i18n="editor.randomize")#randomize-button Randomize
             li(class=anonymous ? "disabled": "")
               a(data-i18n="editor.pop_i18n")#pop-level-i18n-button Populate i18n
             li.divider
diff --git a/app/templates/editor/level/modal/terrain_randomise.jade b/app/templates/editor/level/modal/terrain_randomize.jade
similarity index 100%
rename from app/templates/editor/level/modal/terrain_randomise.jade
rename to app/templates/editor/level/modal/terrain_randomize.jade
diff --git a/app/views/editor/level/modal/terrain_randomise_modal.coffee b/app/views/editor/level/modal/terrain_randomize_modal.coffee
similarity index 88%
rename from app/views/editor/level/modal/terrain_randomise_modal.coffee
rename to app/views/editor/level/modal/terrain_randomize_modal.coffee
index 9e10e5a4e..57c5b2158 100644
--- a/app/views/editor/level/modal/terrain_randomise_modal.coffee
+++ b/app/views/editor/level/modal/terrain_randomize_modal.coffee
@@ -1,5 +1,5 @@
 ModalView = require 'views/kinds/ModalView'
-template = require 'templates/editor/level/modal/terrain_randomise'
+template = require 'templates/editor/level/modal/terrain_randomize'
 CocoModel = require 'models/CocoModel'
 
 clusters = {
@@ -69,13 +69,13 @@ sizes = {
   }
 }
 
-module.exports = class TerrainRandomiseModal extends ModalView
-  id: 'terrain-randomise-modal'
+module.exports = class TerrainRandomizeModal extends ModalView
+  id: 'terrain-randomize-modal'
   template: template
   thangs = []
 
   events:
-    'click .choose-option': 'onRandomise'
+    'click .choose-option': 'onRandomize'
 
   onRevertModel: (e) ->
     id = $(e.target).val()
@@ -83,25 +83,25 @@ module.exports = class TerrainRandomiseModal extends ModalView
     $(e.target).closest('tr').remove()
     @reloadOnClose = true
 
-  onRandomise: (e) ->
+  onRandomize: (e) ->
     target = $(e.target)
     presetType = target.attr 'data-preset-type'
     presetSize = target.attr 'data-preset-size'
-    @randomiseThangs presetType, presetSize
-    Backbone.Mediator.publish('randomise:terrain-generated', 
+    @randomizeThangs presetType, presetSize
+    Backbone.Mediator.publish('randomize:terrain-generated', 
       'thangs': @thangs
     )
     @hide()
 
-  randomiseThangs: (presetName, presetSize) ->
+  randomizeThangs: (presetName, presetSize) ->
     preset = presets[presetName]
     presetSize = sizes[presetSize]
     @thangs = []
-    @randomiseFloor preset, presetSize
-    @randomiseBorder preset, presetSize
-    @randomiseDecorations preset, presetSize
+    @randomizeFloor preset, presetSize
+    @randomizeBorder preset, presetSize
+    @randomizeDecorations preset, presetSize
 
-  randomiseFloor: (preset, presetSize) ->
+  randomizeFloor: (preset, presetSize) ->
     for i in _.range(0, presetSize.x, sizes.floorSize.x)
       for j in _.range(0, presetSize.y, sizes.floorSize.y)
         @thangs.push {
@@ -112,7 +112,7 @@ module.exports = class TerrainRandomiseModal extends ModalView
           }
         }
 
-  randomiseBorder: (preset, presetSize) ->
+  randomizeBorder: (preset, presetSize) ->
     for i in _.range(0-sizes.floorSize.x/2+sizes.borderSize.x, presetSize.x-sizes.floorSize.x/2, sizes.borderSize.x)
       @thangs.push {
         'id': @getRandomThang(preset.borders)
@@ -145,7 +145,7 @@ module.exports = class TerrainRandomiseModal extends ModalView
         }
       }
 
-  randomiseDecorations: (preset, presetSize)->
+  randomizeDecorations: (preset, presetSize)->
     for name, decoration of preset.decorations
       for num in _.range(_.random(decoration.num[0], decoration.num[1]))
         center = 
diff --git a/app/views/editor/level/thangs_tab_view.coffee b/app/views/editor/level/thangs_tab_view.coffee
index e2685f6fa..03f594f7a 100644
--- a/app/views/editor/level/thangs_tab_view.coffee
+++ b/app/views/editor/level/thangs_tab_view.coffee
@@ -43,7 +43,7 @@ module.exports = class ThangsTabView extends View
     'sprite:mouse-up': 'onSpriteMouseUp'
     'sprite:double-clicked': 'onSpriteDoubleClicked'
     'surface:stage-mouse-up': 'onStageMouseUp'
-    'randomise:terrain-generated': 'onRandomiseTerrain'
+    'randomize:terrain-generated': 'onRandomizeTerrain'
 
   events:
     'click #extant-thangs-filter button': 'onFilterExtantThangs'
@@ -224,11 +224,12 @@ module.exports = class ThangsTabView extends View
     return unless e.thang
     @editThang thangID: e.thang.id
 
-  onRandomiseTerrain: (e) ->
+  onRandomizeTerrain: (e) ->
+    console.log 'here'
     @thangsBatch = []
-    for id in @randomiseThangIDs?
+    for id in @randomizeThangIDs?
       @thangsTreema.delete "id=#{id}"
-    @randomiseThangIDs = []
+    @randomizeThangIDs = []
     for thang in e.thangs
       @selectAddThangType thang.id
       @addThang @addThangType, thang.pos, true
@@ -408,7 +409,7 @@ module.exports = class ThangsTabView extends View
 
   addThang: (thangType, pos, batchInsert = false) ->
     thangID = Thang.nextID(thangType.get('name'), @world) until thangID and not @thangsTreema.get "id=#{thangID}"
-    @randomiseThangIDs.push thangID
+    @randomizeThangIDs.push thangID
     if @cloneSourceThang
       components = _.cloneDeep @thangsTreema.get "id=#{@cloneSourceThang.id}/components"
       @selectAddThang null

From b1b9f87ebe307e9d89ddee47cbb6cb10fa93de3f Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 13 Jul 2014 17:34:51 -0700
Subject: [PATCH 23/33] Fixed root test view URL to not need the trailing
 slash.

---
 app/lib/Router.coffee | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/app/lib/Router.coffee b/app/lib/Router.coffee
index 02d7432b9..21b382e99 100644
--- a/app/lib/Router.coffee
+++ b/app/lib/Router.coffee
@@ -17,7 +17,9 @@ module.exports = class CocoRouter extends Backbone.Router
     'editor/:model(/:slug_or_id)(/:subview)': 'editorModelView'
 
     # Direct links
+    'test': go('TestView')
     'test/*subpath': go('TestView')
+    'demo': go('DemoView')
     'demo/*subpath': go('DemoView')
     'play/ladder/:levelID': go('play/ladder/ladder_view')
     'play/ladder': go('play/ladder_home')

From 1d9afbabd25e1f5c819156bd28829b381a95242f Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 13 Jul 2014 18:38:24 -0700
Subject: [PATCH 24/33] Fixes for duplicate Thang IDs and reverting randomized
 Thangs.

---
 app/views/editor/level/thangs_tab_view.coffee | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/app/views/editor/level/thangs_tab_view.coffee b/app/views/editor/level/thangs_tab_view.coffee
index 03f594f7a..a1b92966a 100644
--- a/app/views/editor/level/thangs_tab_view.coffee
+++ b/app/views/editor/level/thangs_tab_view.coffee
@@ -225,11 +225,9 @@ module.exports = class ThangsTabView extends View
     @editThang thangID: e.thang.id
 
   onRandomizeTerrain: (e) ->
-    console.log 'here'
     @thangsBatch = []
-    for id in @randomizeThangIDs?
-      @thangsTreema.delete "id=#{id}"
-    @randomizeThangIDs = []
+    nonRandomThangs = (thang for thang in @thangsTreema.get('') when not /Random/.test thang.id)
+    @thangsTreema.set '', nonRandomThangs
     for thang in e.thangs
       @selectAddThangType thang.id
       @addThang @addThangType, thang.pos, true
@@ -404,12 +402,14 @@ module.exports = class ThangsTabView extends View
     @editThang thangID: id if id
 
   batchInsert: ->
-    @thangsTreema.set '', @thangsBatch
+    @thangsTreema.set '', @thangsTreema.get('').concat(@thangsBatch)
     @thangsBatch = []
 
-  addThang: (thangType, pos, batchInsert = false) ->
-    thangID = Thang.nextID(thangType.get('name'), @world) until thangID and not @thangsTreema.get "id=#{thangID}"
-    @randomizeThangIDs.push thangID
+  addThang: (thangType, pos, batchInsert=false) ->
+    if batchInsert
+      thangID = "Random #{thangType.get('name')} #{@thangsBatch.length}"
+    else
+      thangID = Thang.nextID(thangType.get('name'), @world) until thangID and not @thangsTreema.get "id=#{thangID}"
     if @cloneSourceThang
       components = _.cloneDeep @thangsTreema.get "id=#{@cloneSourceThang.id}/components"
       @selectAddThang null
@@ -421,7 +421,7 @@ module.exports = class ThangsTabView extends View
     thang = thangType: thangType.get('original'), id: thangID, components: components
     if batchInsert
       @thangsBatch.push thang
-    else 
+    else
       @thangsTreema.insert '', thang
 
   editThang: (e) ->

From bd47b3bc83f22d365780307c050aebbfd0d9d444 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 13 Jul 2014 18:53:01 -0700
Subject: [PATCH 25/33] Fixed #1210 based on #1313.

---
 app/assets/javascripts/workers/worker_world.js | 6 ++++++
 headless_client/worker_world.coffee            | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/app/assets/javascripts/workers/worker_world.js b/app/assets/javascripts/workers/worker_world.js
index 78331cbb8..04d63ea5d 100644
--- a/app/assets/javascripts/workers/worker_world.js
+++ b/app/assets/javascripts/workers/worker_world.js
@@ -298,6 +298,9 @@ self.setupDebugWorldToRunUntilFrame = function (args) {
         }
         Math.random = self.debugWorld.rand.randf;  // so user code is predictable
         Aether.replaceBuiltin("Math", Math);
+        replacedLoDash = _.runInContext(self);
+        for(var key in replacedLoDash)
+          _[key] = replacedLoDash[key];
     }
     self.debugWorld.totalFrames = args.frame; //hack to work around error checking
     self.currentDebugWorldFrame = args.frame;
@@ -353,6 +356,9 @@ self.runWorld = function runWorld(args) {
   }
   Math.random = self.world.rand.randf;  // so user code is predictable
   Aether.replaceBuiltin("Math", Math);
+  replacedLoDash = _.runInContext(self);
+  for(var key in replacedLoDash)
+    _[key] = replacedLoDash[key];
   self.postMessage({type: 'start-load-frames'});
   self.world.loadFrames(self.onWorldLoaded, self.onWorldError, self.onWorldLoadProgress);
 };
diff --git a/headless_client/worker_world.coffee b/headless_client/worker_world.coffee
index c683c4f1d..fadfc9519 100644
--- a/headless_client/worker_world.coffee
+++ b/headless_client/worker_world.coffee
@@ -91,6 +91,8 @@ work = () ->
       return
     Math.random = self.world.rand.randf # so user code is predictable
     Aether.replaceBuiltin('Math', Math)
+    replacedLoDash = _.runInContext(self)
+    _[key] = replacedLoDash[key] for key, val of replacedLoDash
     console.log 'Loading frames.'
 
     self.postMessage type: 'start-load-frames'

From c13c7db4ed692deb024a6c7bd6d83b06b4bb7e0f Mon Sep 17 00:00:00 2001
From: Jayant Jain <jayantjain1992@gmail.com>
Date: Mon, 14 Jul 2014 08:11:33 +0530
Subject: [PATCH 26/33] Less geometric random borders for the terrain generator

---
 .../modal/terrain_randomize_modal.coffee      | 51 ++++++++++---------
 1 file changed, 27 insertions(+), 24 deletions(-)

diff --git a/app/views/editor/level/modal/terrain_randomize_modal.coffee b/app/views/editor/level/modal/terrain_randomize_modal.coffee
index 57c5b2158..cf631d54c 100644
--- a/app/views/editor/level/modal/terrain_randomize_modal.coffee
+++ b/app/views/editor/level/modal/terrain_randomize_modal.coffee
@@ -66,6 +66,7 @@ sizes = {
   'borderSize': {
     'x':4
     'y':4
+    'thickness':2
   }
 }
 
@@ -114,36 +115,38 @@ module.exports = class TerrainRandomizeModal extends ModalView
 
   randomizeBorder: (preset, presetSize) ->
     for i in _.range(0-sizes.floorSize.x/2+sizes.borderSize.x, presetSize.x-sizes.floorSize.x/2, sizes.borderSize.x)
-      @thangs.push {
-        'id': @getRandomThang(preset.borders)
-        'pos': {
-          'x': i
-          'y': 0-sizes.floorSize.x/2
+      for j in _.range(sizes.borderSize.thickness)
+        @thangs.push {
+          'id': @getRandomThang(preset.borders)
+          'pos': {
+            'x': i + _.random(-sizes.borderSize.x/2, sizes.borderSize.x/2)
+            'y': 0 - sizes.floorSize.x/2 + _.random(-sizes.borderSize.x/2, sizes.borderSize.x/2)
+          }
         }
-      }
-      @thangs.push {
-        'id': @getRandomThang(preset.borders)
-        'pos': {
-          'x': i
-          'y': presetSize.y - sizes.borderSize.y
+        @thangs.push {
+          'id': @getRandomThang(preset.borders)
+          'pos': {
+            'x': i + _.random(-sizes.borderSize.x/2, sizes.borderSize.x/2)
+            'y': presetSize.y - sizes.borderSize.y + _.random(-sizes.borderSize.x/2, sizes.borderSize.x/2)
+          }
         }
-      }
 
     for i in _.range(0-sizes.floorSize.y/2, presetSize.y-sizes.borderSize.y, sizes.borderSize.y)
-      @thangs.push {
-        'id': @getRandomThang(preset.borders)
-        'pos': {
-          'x': 0-sizes.floorSize.x/2+sizes.borderSize.x
-          'y': i
+      for j in _.range(3)
+        @thangs.push {
+          'id': @getRandomThang(preset.borders)
+          'pos': {
+            'x': 0-sizes.floorSize.x/2+sizes.borderSize.x + _.random(-sizes.borderSize.y/2, sizes.borderSize.y/2)
+            'y': i + _.random(-sizes.borderSize.y/2, sizes.borderSize.y/2)
+          }
         }
-      }
-      @thangs.push {
-        'id': @getRandomThang(preset.borders)
-        'pos': {
-          'x': presetSize.x - sizes.borderSize.x - sizes.floorSize.x/2
-          'y': i
+        @thangs.push {
+          'id': @getRandomThang(preset.borders)
+          'pos': {
+            'x': presetSize.x - sizes.borderSize.x - sizes.floorSize.x/2 + _.random(-sizes.borderSize.y/2, sizes.borderSize.y/2)
+            'y': i + _.random(-sizes.borderSize.y/2, sizes.borderSize.y/2)
+          }
         }
-      }
 
   randomizeDecorations: (preset, presetSize)->
     for name, decoration of preset.decorations

From 1a016394fe1b925206bed91494f4213b74aa00f0 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 13 Jul 2014 20:19:51 -0700
Subject: [PATCH 27/33] Starting to show opponent code languages.

---
 app/lib/surface/SpriteBoss.coffee             |  2 +-
 app/lib/surface/WizardSprite.coffee           |  5 +++++
 app/schemas/models/level_session.coffee       |  3 +++
 app/styles/play/ladder/ladder_tab.sass        |  6 ++++++
 app/styles/play/ladder/my_matches_tab.sass    |  6 ++++++
 app/styles/play/ladder/play_modal.sass        | 14 ++++++++++++--
 app/templates/play/ladder/ladder_tab.jade     |  6 ++++--
 app/templates/play/ladder/my_matches_tab.jade |  8 +++++---
 app/templates/play/ladder/play_modal.jade     |  7 +++++++
 app/views/play/ladder/my_matches_tab.coffee   |  1 +
 app/views/play/ladder/play_modal.coffee       |  8 +++++---
 app/views/play/level_view.coffee              |  2 +-
 server/levels/level_handler.coffee            |  2 +-
 server/queues/scoring.coffee                  |  3 +++
 14 files changed, 60 insertions(+), 13 deletions(-)

diff --git a/app/lib/surface/SpriteBoss.coffee b/app/lib/surface/SpriteBoss.coffee
index 2c2664a6b..fb30b505a 100644
--- a/app/lib/surface/SpriteBoss.coffee
+++ b/app/lib/surface/SpriteBoss.coffee
@@ -106,7 +106,7 @@ module.exports = class SpriteBoss extends CocoClass
 
   createOpponentWizard: (opponent) ->
     # TODO: colorize name and cloud by team, colorize wizard by user's color config, level-specific wizard spawn points
-    sprite = @createWizardSprite thangID: opponent.id, name: opponent.name
+    sprite = @createWizardSprite thangID: opponent.id, name: opponent.name, codeLanguage: opponent.codeLanguage
     if not opponent.levelSlug or opponent.levelSlug is 'brawlwood'
       sprite.targetPos = if opponent.team is 'ogres' then {x: 52, y: 52} else {x: 28, y: 28}
     else if opponent.levelSlug is 'dungeon-arena'
diff --git a/app/lib/surface/WizardSprite.coffee b/app/lib/surface/WizardSprite.coffee
index 9c25c0c7f..5d929147c 100644
--- a/app/lib/surface/WizardSprite.coffee
+++ b/app/lib/surface/WizardSprite.coffee
@@ -54,6 +54,11 @@ module.exports = class WizardSprite extends IndieSprite
     @updateRotation()
     # Don't call general update() because Thang isn't built yet
 
+  setNameLabel: (name) ->
+    if @options.codeLanguage and @options.codeLanguage isnt 'javascript' and not @isSelf
+      name += " (#{@options.codeLanguage})"  # TODO: move on second line, capitalize properly
+    super name
+
   onPlayerStatesChanged: (e) ->
     for playerID, state of e.states
       continue unless playerID is @thang.id
diff --git a/app/schemas/models/level_session.coffee b/app/schemas/models/level_session.coffee
index a4e655ded..f4f629914 100644
--- a/app/schemas/models/level_session.coffee
+++ b/app/schemas/models/level_session.coffee
@@ -239,6 +239,9 @@ _.extend LevelSessionSchema.properties,
                     title: 'Opponent Rank'
                     description: 'The opponent\'s ranking in a given match'
                     type: 'number'
+              codeLanguage:
+                type: 'string'
+                description: 'What submittedCodeLanguage the opponent used during the match'
 
 c.extendBasicProperties LevelSessionSchema, 'level.session'
 c.extendPermissionsProperties LevelSessionSchema, 'level.session'
diff --git a/app/styles/play/ladder/ladder_tab.sass b/app/styles/play/ladder/ladder_tab.sass
index cdc5025aa..c92726c9c 100644
--- a/app/styles/play/ladder/ladder_tab.sass
+++ b/app/styles/play/ladder/ladder_tab.sass
@@ -50,3 +50,9 @@
 
   td
     padding: 1px 2px
+
+  .code-language-cell
+    padding: 0 10px
+    background: transparent url(/images/pages/home/language_logo_javascript.png) no-repeat center center
+    background-size: contain
+    height: 19px
diff --git a/app/styles/play/ladder/my_matches_tab.sass b/app/styles/play/ladder/my_matches_tab.sass
index 99e01f997..741a3a534 100644
--- a/app/styles/play/ladder/my_matches_tab.sass
+++ b/app/styles/play/ladder/my_matches_tab.sass
@@ -37,3 +37,9 @@
 
   td
     padding: 1px 2px
+
+  .code-language-cell
+    padding: 0 10px
+    background: transparent url(/images/pages/home/language_logo_javascript.png) no-repeat center center
+    background-size: contain
+    height: 19px
diff --git a/app/styles/play/ladder/play_modal.sass b/app/styles/play/ladder/play_modal.sass
index 465052114..3587c557f 100644
--- a/app/styles/play/ladder/play_modal.sass
+++ b/app/styles/play/ladder/play_modal.sass
@@ -95,7 +95,17 @@
     span
       position: relative
       top: 1px
-      
+
+    .code-language
+      position: absolute
+      background: transparent url(/images/pages/home/language_logo_javascript.png) no-repeat center center
+      background-size: contain
+      width: 40px
+      height: 40px
+      right: -5px
+      top: -15px
+      display: block
+
   .my-name
     border-right: 15px solid transparent
     left: 0
@@ -145,4 +155,4 @@
     top: 35px
     font-size: 40px
     font-weight: bolder
-    color: black
\ No newline at end of file
+    color: black
diff --git a/app/templates/play/ladder/ladder_tab.jade b/app/templates/play/ladder/ladder_tab.jade
index 9a5cf746a..4d682243a 100644
--- a/app/templates/play/ladder/ladder_tab.jade
+++ b/app/templates/play/ladder/ladder_tab.jade
@@ -4,13 +4,13 @@ div#columns.row
       div(id="histogram-display-#{team.name}", class="histogram-display",data-team-name=team.name)
       table.table.table-bordered.table-condensed.table-hover
         tr
-          th
+          th(colspan=2)
           th(colspan=3, style="color: #{team.primaryColor}")
             span= team.name
             span  
             span(data-i18n="ladder.leaderboard") Leaderboard
         tr
-          th
+          th(colspan=2)
           th(data-i18n="general.score") Score
           th(data-i18n="general.name").name-col-cell Name
           th
@@ -21,6 +21,7 @@ div#columns.row
         for session, rank in topSessions
           - var myRow = session.get('creator') == me.id
           tr(class=myRow ? "success" : "", data-player-id=session.get('creator'), data-session-id=session.id)
+            td.code-language-cell(style="background-image: url(/images/pages/home/language_logo_" + session.get('submittedCodeLanguage') + ".png)")
             td.rank-cell= rank + 1
             td.score-cell= Math.round(session.get('totalScore') * 100)
             td.name-col-cell= session.get('creatorName') || "Anonymous"
@@ -34,6 +35,7 @@ div#columns.row
           for session in team.leaderboard.nearbySessions()
             - var myRow = session.get('creator') == me.id
             tr(class=myRow ? "success" : "", data-player-id=session.get('creator'), data-session-id=session.id)
+              td.code-language-cell(style="background-image: url(/images/pages/home/language_logo_" + session.get('submittedCodeLanguage') + ".png)")
               td.rank-cell= session.rank
               td.score-cell= Math.round(session.get('totalScore') * 100)
               td.name-col-cell= session.get('creatorName') || "Anonymous"
diff --git a/app/templates/play/ladder/my_matches_tab.jade b/app/templates/play/ladder/my_matches_tab.jade
index 4d91d0757..a08f6651b 100644
--- a/app/templates/play/ladder/my_matches_tab.jade
+++ b/app/templates/play/ladder/my_matches_tab.jade
@@ -4,7 +4,7 @@ div#columns.row
       table.table.table-bordered.table-condensed
 
         tr
-          th(colspan=4, style="color: #{team.primaryColor}")
+          th(colspan=5, style="color: #{team.primaryColor}")
             span(data-i18n="ladder.summary_your") Your 
             |#{team.name}
             |  
@@ -16,16 +16,17 @@ div#columns.row
 
         if team.session
           tr
-            th(colspan=4)
+            th(colspan=5)
               .ladder-submission-view(data-session-id=team.session.id)
 
         if team.scoreHistory
           tr
-            th(colspan=4, style="color: #{team.primaryColor}")
+            th(colspan=5, style="color: #{team.primaryColor}")
               div(class="score-chart-wrapper", data-team-name=team.name, id="score-chart-#{team.name}")
 
         tr
           th(data-i18n="general.result") Result
+          th
           th(data-i18n="general.opponent") Opponent
           th(data-i18n="general.when") When
           th
@@ -38,6 +39,7 @@ div#columns.row
                 span(data-i18n="general.loss").loss Loss
               if match.state === 'tie'
                 span(data-i18n="general.tie").tie Tie
+            td.code-language-cell(style="background-image: url(/images/pages/home/language_logo_" + match.codeLanguage +  ".png)")
             td.name-cell= match.opponentName || "Anonymous"
             td.time-cell= match.when
             td.battle-cell
diff --git a/app/templates/play/ladder/play_modal.jade b/app/templates/play/ladder/play_modal.jade
index ba7321a1e..841203b2f 100644
--- a/app/templates/play/ladder/play_modal.jade
+++ b/app/templates/play/ladder/play_modal.jade
@@ -33,6 +33,7 @@ block modal-body-content
           span= myName
         div.opponent-name.name-label
           span(data-i18n="ladder.simple_ai") Simple AI
+          //span.code-language(style="background-image: url(/images/pages/home/language_logo_javascript.png)")
         div.difficulty
           span(data-i18n="ladder.warmup") Warmup
         div(data-i18n="ladder.vs").vs VS
@@ -48,6 +49,8 @@ block modal-body-content
             span= myName
           div.opponent-name.name-label
             span= challengers.easy.opponentName
+            if challengers.easy.codeLanguage
+              span.code-language(style="background-image: url(/images/pages/home/language_logo_" + challengers.easy.codeLanguage + ".png)")
           div.difficulty
             span(data-i18n="general.easy") Easy
           div(data-i18n="ladder.vs").vs VS
@@ -63,6 +66,8 @@ block modal-body-content
             span= myName
           div.opponent-name.name-label
             span= challengers.medium.opponentName
+            if challengers.medium.codeLanguage
+              span.code-language(style="background-image: url(/images/pages/home/language_logo_" + challengers.medium.codeLanguage + ".png)")
           div.difficulty
             span(data-i18n="general.medium") Medium
           div(data-i18n="ladder.vs").vs VS
@@ -78,6 +83,8 @@ block modal-body-content
             span= myName
           div.opponent-name.name-label
             span= challengers.hard.opponentName
+            if challengers.hard.codeLanguage
+              span.code-language(style="background-image: url(/images/pages/home/language_logo_" + challengers.hard.codeLanguage + ".png)")
           div.difficulty
             span(data-i18n="general.hard") Hard
           div(data-i18n="ladder.vs").vs VS
diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee
index 458b3c441..fc82ce441 100644
--- a/app/views/play/ladder/my_matches_tab.coffee
+++ b/app/views/play/ladder/my_matches_tab.coffee
@@ -73,6 +73,7 @@ module.exports = class MyMatchesTabView extends CocoView
         sessionID: opponent.sessionID
         stale: match.date < submitDate
         fresh: fresh
+        codeLanguage: match.codeLanguage
       }
 
     for team in @teams
diff --git a/app/views/play/ladder/play_modal.coffee b/app/views/play/ladder/play_modal.coffee
index d1a1e74fa..41bf1e22b 100644
--- a/app/views/play/ladder/play_modal.coffee
+++ b/app/views/play/ladder/play_modal.coffee
@@ -24,14 +24,14 @@ module.exports = class LadderPlayModal extends View
     indentGuides: false
     behaviors: false
     liveCompletion: true
-    
+
   constructor: (options, @level, @session, @team) ->
     super(options)
     @nameMap = {}
     @otherTeam = if team is 'ogres' then 'humans' else 'ogres'
     @startLoadingChallengersMaybe()
     @wizardType = ThangType.loadUniversalWizard()
-    
+
   updateLanguage: ->
     aceConfig = _.cloneDeep me.get('aceConfig') ? {}
     aceConfig = _.defaults aceConfig, @defaultAceConfig
@@ -176,7 +176,8 @@ module.exports = class LadderPlayModal extends View
     return unless session
     return {
       sessionID: session.id
-      opponentID: session.get('creator')
+      opponentID: session.get 'creator'
+      codeLanguage: session.get 'submittedCodeLanguage'
     }
 
   challengeInfoFromMatches: (matches) ->
@@ -186,6 +187,7 @@ module.exports = class LadderPlayModal extends View
     return {
       sessionID: opponent.sessionID
       opponentID: opponent.userID
+      codeLanguage: opponent.codeLanguage
     }
 
 class ChallengersData
diff --git a/app/views/play/level_view.coffee b/app/views/play/level_view.coffee
index e2669b2b0..c15fe7c6e 100644
--- a/app/views/play/level_view.coffee
+++ b/app/views/play/level_view.coffee
@@ -287,7 +287,7 @@ module.exports = class PlayLevelView extends View
     @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'), levelSlug: @level.get('slug')
+      @surface.createOpponentWizard id: @otherSession.get('creator'), name: @otherSession.get('creatorName'), team: @otherSession.get('team'), levelSlug: @level.get('slug'), codeLanguage: @otherSession.get('submittedCodeLanguage')
     @loadingView?.unveil()
 
   onLoadingViewUnveiled: (e) ->
diff --git a/server/levels/level_handler.coffee b/server/levels/level_handler.coffee
index 0843b0ffc..bcda60e1c 100644
--- a/server/levels/level_handler.coffee
+++ b/server/levels/level_handler.coffee
@@ -155,7 +155,7 @@ LevelHandler = class LevelHandler extends Handler
 
     sortParameters =
       'totalScore': req.query.order
-    selectProperties = ['totalScore', 'creatorName', 'creator']
+    selectProperties = ['totalScore', 'creatorName', 'creator', 'submittedCodeLanguage']
 
     query = Session
       .find(sessionsQueryParameters)
diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee
index b92fe5017..9f68f0cc1 100644
--- a/server/queues/scoring.coffee
+++ b/server/queues/scoring.coffee
@@ -579,6 +579,7 @@ addMatchToSessions = (newScoreObject, callback) ->
     matchObject.opponents[sessionID].totalScore = session.totalScore
     matchObject.opponents[sessionID].metrics = {}
     matchObject.opponents[sessionID].metrics.rank = Number(newScoreObject[sessionID]?.gameRanking ? 0)
+    matchObject.opponents[sessionID].codeLanguage = newScoreObject[sessionID].submittedCodeLanguage
 
   #log.info "Match object computed, result: #{matchObject}"
   #log.info 'Writing match object to database...'
@@ -595,6 +596,7 @@ updateMatchesInSession = (matchObject, sessionID, callback) ->
   opponentsClone = _.omit opponentsClone, sessionID
   opponentsArray = _.toArray opponentsClone
   currentMatchObject.opponents = opponentsArray
+  currentMatchObject.codeLanguage = matchObject.opponents[opponentsArray[0].sessionID].codeLanguage
   LevelSession.findOne {'_id': sessionID}, (err, session) ->
     session = session.toObject()
     currentMatchObject.playtime = session.playtime ? 0
@@ -770,6 +772,7 @@ retrieveOldSessionData = (sessionID, callback) ->
       'meanStrength': session.meanStrength ? 25
       'totalScore': session.totalScore ? (25 - 1.8*(25/3))
       'id': sessionID
+      'submittedCodeLanguage': session.submittedCodeLanguage
     callback err, oldScoreObject
 
 markSessionAsDoneRanking = (sessionID, cb) ->

From ca3a2b620babc27cc1656f22988ba744166e8936 Mon Sep 17 00:00:00 2001
From: Inez KEMENES <kinez@users.noreply.github.com>
Date: Mon, 14 Jul 2014 07:22:19 +0200
Subject: [PATCH 28/33] Update hu.coffee

I must have made a mistake again. I have deleted a star instead of a double cross and some lines disappeared. Sorry! Please correct.
---
 app/locale/hu.coffee | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/locale/hu.coffee b/app/locale/hu.coffee
index 3a7889e63..673b3ec90 100644
--- a/app/locale/hu.coffee
+++ b/app/locale/hu.coffee
@@ -173,8 +173,8 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
     email_announcements: "Bejelentések"
     email_announcements_description: "Szeretnél levelet kapni a legújabb fejlesztéseinkről?"
     email_notifications: "Értesítések"
-#    email_notifications_summary: "Controls for personalized, automatic email notifications related to your CodeCombat activity."
-    email_any_notes: "Bármely értesítés"
+    email_notifications_summary: CodeCombat tevékenységedre vonatkozó személyre szóló, automatikus értesítések beállításai."
+    email_any_notes: "Bármely megjegyzés"
     email_any_notes_description: "Minden tevékenységgel kapcsolatos e-mail értesítés letiltása."
     email_recruit_notes: "Álláslehetőségek"
     email_recruit_notes_description: "Ha igazán jól játszol lehet, hogy felveszzük veled a kapcsolatot és megbeszéljük, hogy szerezzünk-e neked egy (jobb) állást."

From 0f4a7df9825fdd9b849d303d8e414d4809a4b75f Mon Sep 17 00:00:00 2001
From: Tery Lim <kumabotz@gmail.com>
Date: Mon, 14 Jul 2014 13:56:27 +0800
Subject: [PATCH 29/33] Use spl instead of trailing space for spacing

---
 app/templates/community.jade | 62 ++++++++++++++++++------------------
 1 file changed, 31 insertions(+), 31 deletions(-)

diff --git a/app/templates/community.jade b/app/templates/community.jade
index 05abba019..396a5a416 100644
--- a/app/templates/community.jade
+++ b/app/templates/community.jade
@@ -1,7 +1,7 @@
 extends /templates/base
 
 block content
-  
+
   h1(data-i18n="community.main_title") CodeCombat Community
 
   p There are dozens of ways you can get involved with CodeCombat. Check out the resources we've built, decide what sounds the most fun, and we look forward to working with you!
@@ -15,13 +15,13 @@ block content
       p We have built several tools that enable users to get not only edit, but also build new game content!
 
         ul
-          li 
+          li
             a(href="/editor/level", data-i18n="community.level_editor")
             | : fork, edit, or build your own CodeCombat levels. New levels can be kept private or published to the community.
-          li 
+          li
             a(href="/editor/thang", data-i18n="editor.thang_title")
             | : modify or import new art assets for the game using our powerful editor.
-          li 
+          li
             a(href="/editor/article", data-i18n="editor.article_title")
             | : edit or create documentation used in CodeCombat levels.
 
@@ -35,51 +35,51 @@ block content
 
         ul
 
-          li We write about our progress and current projects on our 
-            a(href="http://blog.codecombat.com", data-i18n="nav.blog")
+          li We write about our progress and current projects on our
+            a.spl(href="http://blog.codecombat.com", data-i18n="nav.blog")
             | .
-          li Participate in our active user community by checking out our 
-            a(href="http://discourse.codecombat.com", data-i18n="nav.forum") 
+          li Participate in our active user community by checking out our
+            a.spl(href="http://discourse.codecombat.com", data-i18n="nav.forum")
             | .
-          li For regular news about learning to code, games, and education, check out our 
-            a(href="https://www.facebook.com/codecombat", data-i18n="community.facebook") 
+          li For regular news about learning to code, games, and education, check out our
+            a.spl(href="https://www.facebook.com/codecombat", data-i18n="community.facebook")
             | .
-          li For realtime status or to have a quick chat, follow us on 
-            a(href="https://twitter.com/CodeCombat", data-i18n="community.twitter") 
+          li For realtime status or to have a quick chat, follow us on
+            a.spl(href="https://twitter.com/CodeCombat", data-i18n="community.twitter")
             | .
-          li Don't like Facebook? We're on 
-            a(href="https://plus.google.com/115285980638641924488/posts", data-i18n="community.gplus") 
+          li Don't like Facebook? We're on
+            a.spl(href="https://plus.google.com/115285980638641924488/posts", data-i18n="community.gplus")
             | .
-          li You can also find us in our 
-            a(href="http://www.hipchat.com/g3plnOKqa", data-i18n="editor.hipchat_url")
+          li You can also find us in our
+            a.spl(href="http://www.hipchat.com/g3plnOKqa", data-i18n="editor.hipchat_url")
 
     .community_columns
 
       h2 Contribute
 
-      p Put your skills to use helping us teach the world to code. We have a lot of roles you can consider, and if we don't have a role for you, let us know: 
+      p Put your skills to use helping us teach the world to code. We have a lot of roles you can consider, and if we don't have a role for you, let us know:
 
         ul
 
-          li 
-            a(href="/contribute#archmage", data-i18n="classes.archmage_title") 
+          li
+            a(href="/contribute#archmage", data-i18n="classes.archmage_title")
             | : contribute by writing code.
-          li 
-            a(href="/contribute#artisan", data-i18n="classes.artisan_title") 
+          li
+            a(href="/contribute#artisan", data-i18n="classes.artisan_title")
             | : build new game levels.
-          li 
-            a(href="/contribute#adventurer", data-i18n="classes.adventurer_title") 
+          li
+            a(href="/contribute#adventurer", data-i18n="classes.adventurer_title")
             | : test new game levels.
-          li 
-            a(href="/contribute#scribe", data-i18n="classes.scribe_title") 
+          li
+            a(href="/contribute#scribe", data-i18n="classes.scribe_title")
             | : write educational documentation.
-          li 
-            a(href="/contribute#diplomat", data-i18n="classes.diplomat_title") 
+          li
+            a(href="/contribute#diplomat", data-i18n="classes.diplomat_title")
             | : translate site content.
-          li 
-            a(href="/contribute#ambassador", data-i18n="classes.ambassador_title") 
+          li
+            a(href="/contribute#ambassador", data-i18n="classes.ambassador_title")
             | : support our community of educators and coders.
 
-        | Check out the 
-        a(href="/contribute", data-i18n="nav.contribute") 
+        | Check out the
+        a.spl(href="/contribute", data-i18n="nav.contribute")
         |  page to find out more about the roles and how you can get started.

From 42cf0b5cce3fd6cc6ab19d26ec636af183395426 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 14 Jul 2014 07:30:18 -0700
Subject: [PATCH 30/33] Added missing starting quote.

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

diff --git a/app/locale/hu.coffee b/app/locale/hu.coffee
index 673b3ec90..1eafea9df 100644
--- a/app/locale/hu.coffee
+++ b/app/locale/hu.coffee
@@ -173,7 +173,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
     email_announcements: "Bejelentések"
     email_announcements_description: "Szeretnél levelet kapni a legújabb fejlesztéseinkről?"
     email_notifications: "Értesítések"
-    email_notifications_summary: CodeCombat tevékenységedre vonatkozó személyre szóló, automatikus értesítések beállításai."
+    email_notifications_summary: "CodeCombat tevékenységedre vonatkozó személyre szóló, automatikus értesítések beállításai."
     email_any_notes: "Bármely megjegyzés"
     email_any_notes_description: "Minden tevékenységgel kapcsolatos e-mail értesítés letiltása."
     email_recruit_notes: "Álláslehetőségek"

From f1c8983de2bfb73f424e9d0ff5a783767fe6ed16 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 14 Jul 2014 08:40:36 -0700
Subject: [PATCH 31/33] Don't ask for team again if we already have a child
 window.

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

diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade
index d8e806903..c1f372e29 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -49,7 +49,7 @@ block header
         
         if level.get('type') === 'ladder'
           li.dropdown
-            a(data-toggle='dropdown')
+            a(data-toggle='dropdown').play-with-team-parent
               span.glyphicon-play.glyphicon
             ul.dropdown-menu
               li.dropdown-header Play As Which Team?
diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/edit.coffee
index eb9e879c0..18bc8edf5 100644
--- a/app/views/editor/level/edit.coffee
+++ b/app/views/editor/level/edit.coffee
@@ -26,6 +26,7 @@ module.exports = class EditorLevelView extends View
   events:
     'click #play-button': 'onPlayLevel'
     'click .play-with-team-button': 'onPlayLevel'
+    'click .play-with-team-parent': 'onPlayLevelTeamSelect'
     'click #commit-level-start-button': 'startCommittingLevel'
     'click #fork-level-start-button': 'startForkingLevel'
     'click #level-history-button': 'showVersionHistory'
@@ -77,6 +78,12 @@ module.exports = class EditorLevelView extends View
     @listenTo @patchesView, 'accepted-patch', -> location.reload()
     @$el.find('#level-watch-button').find('> span').toggleClass('secret') if @level.watching()
 
+  onPlayLevelTeamSelect: (e) ->
+    if @childWindow and not @childWindow.closed
+      # We already have a child window open, so we don't need to ask for a team; we'll use its existing team.
+      e.stopImmediatePropagation()
+      @onPlayLevel e
+
   onPlayLevel: (e) ->
     team = $(e.target).data('team')
     sendLevel = =>

From 7446c9ee08398ac97ddb025561379bf4bd9f5092 Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Mon, 14 Jul 2014 09:38:55 -0700
Subject: [PATCH 32/33] Don't break as badly on long method names and small
 windows. Make sure we can always see the spell tool buttons.

---
 .../play/level/tome/spell_list_entry.sass     | 17 +++++++++-----
 .../play/level/tome/spell_list_tab_entry.jade | 22 +++++++++----------
 2 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/app/styles/play/level/tome/spell_list_entry.sass b/app/styles/play/level/tome/spell_list_entry.sass
index 8f8683c41..565330c7c 100644
--- a/app/styles/play/level/tome/spell_list_entry.sass
+++ b/app/styles/play/level/tome/spell_list_entry.sass
@@ -13,13 +13,14 @@
   $childMargin: 2px
   $childSize: $height - 2 * $childMargin
   height: $height
-  width: 80%
-  width: -webkit-calc(100% - 100px)
-  width: calc(100% - 100px)
+  width: 90%
+  width: -webkit-calc(100% - 50px)
+  width: calc(100% - 50px)
   padding: 0px 8px
   border-width: 3px
   border-image: url(/images/level/code_editor_tab_background.png) 4 fill repeat
-  text-align: center
+  white-space: nowrap
+  position: relative
 
   &.read-only
     background: linear-gradient(to bottom, rgba(0,0,0,0.2) 0%,rgba(0,0,0,0.2) 100%), url(/images/level/code_editor_tab_background.png)
@@ -34,6 +35,11 @@
   .spell-list-button, .thang-avatar-wrapper
     float: left
 
+  .spell-tool-buttons
+    position: absolute
+    right: 0px
+    top: 0px
+
   .reload-code
     float: right
     display: none
@@ -66,6 +72,7 @@
 
   code
     margin-top: 7px
+    font-size: 1vw
 
 .spell-list-entry-view:not(.spell-tab)
   cursor: pointer
@@ -110,4 +117,4 @@ html.no-borderimage
     border-width: 0
     border-image: none
     background: transparent url(/images/level/code_editor_tab_background.png) no-repeat
-    background-size: 100% 100%
\ No newline at end of file
+    background-size: 100% 100%
diff --git a/app/templates/play/level/tome/spell_list_tab_entry.jade b/app/templates/play/level/tome/spell_list_tab_entry.jade
index 9199b8a48..d896baa5c 100644
--- a/app/templates/play/level/tome/spell_list_tab_entry.jade
+++ b/app/templates/play/level/tome/spell_list_tab_entry.jade
@@ -4,15 +4,15 @@
 
 code #{methodSignature}
 
-.btn.btn-small.fullscreen-code(title="Expand code editor")
-  i.icon-fullscreen
-  i.icon-resize-small
-    
-.btn.btn-small.reload-code(title="Reload original code for " + spell.name)
-  i.icon-repeat
+.spell-tool-buttons
+  .btn.btn-small.fullscreen-code(title="Expand code editor")
+    i.icon-fullscreen
+    i.icon-resize-small
+      
+  .btn.btn-small.reload-code(title="Reload original code for " + spell.name)
+    i.icon-repeat
+  
+  .btn.btn-small.beautify-code(title="Ctrl+Shift+B: Beautify code for " + spell.name)
+    i.icon-magnet
 
-.btn.btn-small.beautify-code(title="Ctrl+Shift+B: Beautify code for " + spell.name)
-  i.icon-magnet
-
-
-.clearfix
\ No newline at end of file
+  .clearfix
\ No newline at end of file

From ae4a5eb4607ac02f5d5fa57385700d2970334353 Mon Sep 17 00:00:00 2001
From: Ruben Vereecken <rubenvereecken@gmail.com>
Date: Mon, 14 Jul 2014 18:52:23 +0200
Subject: [PATCH 33/33] Deduplicated bootstrap include

---
 app/styles/bootstrap.scss | 1 -
 config.coffee             | 2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)
 delete mode 100644 app/styles/bootstrap.scss

diff --git a/app/styles/bootstrap.scss b/app/styles/bootstrap.scss
deleted file mode 100644
index 457a7ab36..000000000
--- a/app/styles/bootstrap.scss
+++ /dev/null
@@ -1 +0,0 @@
-@import "bootstrap/bootstrap";
\ No newline at end of file
diff --git a/config.coffee b/config.coffee
index 940a8e688..26c7687ca 100644
--- a/config.coffee
+++ b/config.coffee
@@ -64,7 +64,7 @@ exports.config =
         'stylesheets/app.css': /^(app|vendor|bower_components)/
       order:
         before: [
-          'app/styles/bootstrap.scss'
+          'app/styles/bootstrap/*'
           'vendor/styles/nanoscroller.scss'
         ]
     templates: