From db2500776534e5c71d530c36d581e02bb695683f Mon Sep 17 00:00:00 2001
From: Esben Madsen <codecombat.com@minpingvin.dk>
Date: Thu, 11 Jun 2015 00:35:56 +0200
Subject: [PATCH 01/18] A bit of Danish translation pt. 2

---
 app/locale/da.coffee                     | 100 +++++++++++------------
 app/views/contribute/DiplomatView.coffee |   2 +-
 2 files changed, 51 insertions(+), 51 deletions(-)

diff --git a/app/locale/da.coffee b/app/locale/da.coffee
index 3ac820d9e..f15a5f3a2 100644
--- a/app/locale/da.coffee
+++ b/app/locale/da.coffee
@@ -260,62 +260,62 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
     victory_review: "Fortæl os mere!" # Only in old-style levels.
     victory_hour_of_code_done: "Er du færdig?"
     victory_hour_of_code_done_yes: "Ja, jeg er færdig med min Kodetime!"
-#    victory_experience_gained: "XP Gained"
-#    victory_gems_gained: "Gems Gained"
-#    victory_new_item: "New Item"
-#    victory_viking_code_school: "Holy smokes, that was a hard level you just beat! If you aren't already a software developer, you should be. You just got fast-tracked for acceptance with Viking Code School, where you can take your skills to the next level and become a professional web developer in 14 weeks."
-#    victory_become_a_viking: "Become a Viking"
+    victory_experience_gained: "XP tjent"
+    victory_gems_gained: "Diamanter tjent"
+    victory_new_item: "Nyt udstyr"
+    victory_viking_code_school: "For dælen det var en svær bane du lige slog! Hvis ikke du allerede er softwareudvikler, så burde du blive det. Du er lige kommet foran i køen til at blive accepteret hos Viking Code School, du kan tage dine evner til det næste niveau og blive en professionel webudvikler på 14 uger."
+    victory_become_a_viking: "Bliv en Viking"
     guide_title: "Instruktioner"
-#    tome_minion_spells: "Your Minions' Spells" # Only in old-style levels.
-#    tome_read_only_spells: "Read-Only Spells" # Only in old-style levels.
+    tome_minion_spells: "Dine Minions' besværgelser" # Only in old-style levels.
+    tome_read_only_spells: "Læsebesværgelser" # Only in old-style levels.
     tome_other_units: "Andre enheder" # Only in old-style levels.
-#    tome_cast_button_run: "Run"
-#    tome_cast_button_running: "Running"
-#    tome_cast_button_ran: "Ran"
-#    tome_submit_button: "Submit"
-#    tome_reload_method: "Reload original code for this method" # Title text for individual method reload button.
-#    tome_select_method: "Select a Method"
-#    tome_see_all_methods: "See all methods you can edit" # Title text for method list selector (shown when there are multiple programmable methods).
+    tome_cast_button_run: "Kør"
+    tome_cast_button_running: "Kører"
+    tome_cast_button_ran: "Kørt"
+    tome_submit_button: "Indsend"
+    tome_reload_method: "Genindlæs den originale kode til denne metode" # Title text for individual method reload button.
+    tome_select_method: "Vælg en metode"
+    tome_see_all_methods: "Se alle metoder du kan redigere" # Title text for method list selector (shown when there are multiple programmable methods).
     tome_select_a_thang: "Vælg nogen til at "
     tome_available_spells: "Tilgængelige trylleformularer"
-#    tome_your_skills: "Your Skills"
-#    tome_help: "Help"
-#    tome_current_method: "Current Method"
-#    hud_continue_short: "Continue"
-#    code_saved: "Code Saved"
+    tome_your_skills: "Dine evner"
+    tome_help: "Hjælp"
+    tome_current_method: "Nuværende metode"
+    hud_continue_short: "Fortsæt"
+    code_saved: "Kode gemt"
     skip_tutorial: "Spring over (esc)"
-#    keyboard_shortcuts: "Key Shortcuts"
-#    loading_ready: "Ready!"
-#    loading_start: "Start Level"
-#    problem_alert_title: "Fix Your Code"
-#    problem_alert_help: "Help"
-#    time_current: "Now:"
-#    time_total: "Max:"
-#    time_goto: "Go to:"
-#    non_user_code_problem_title: "Unable to Load Level"
-#    infinite_loop_title: "Infinite Loop Detected"
-#    infinite_loop_description: "The initial code to build the world never finished running. It's probably either really slow or has an infinite loop. Or there might be a bug. You can either try running this code again or reset the code to the default state. If that doesn't fix it, please let us know."
-#    check_dev_console: "You can also open the developer console to see what might be going wrong."
-#    check_dev_console_link: "(instructions)"
-#    infinite_loop_try_again: "Try Again"
-#    infinite_loop_reset_level: "Reset Level"
-#    infinite_loop_comment_out: "Comment Out My Code"
-#    tip_toggle_play: "Toggle play/paused with Ctrl+P."
-#    tip_scrub_shortcut: "Use Ctrl+[ and Ctrl+] to rewind and fast-forward."
-#    tip_guide_exists: "Click the guide, inside game menu (at the top of the page), for useful info."
-#    tip_open_source: "CodeCombat is 100% open source!"
-#    tip_beta_launch: "CodeCombat launched its beta in October, 2013."
-#    tip_think_solution: "Think of the solution, not the problem."
-#    tip_theory_practice: "In theory, there is no difference between theory and practice. But in practice, there is. - Yogi Berra"
-#    tip_error_free: "There are two ways to write error-free programs; only the third one works. - Alan Perlis"
-#    tip_debugging_program: "If debugging is the process of removing bugs, then programming must be the process of putting them in. - Edsger W. Dijkstra"
-#    tip_forums: "Head over to the forums and tell us what you think!"
-#    tip_baby_coders: "In the future, even babies will be Archmages."
-#    tip_morale_improves: "Loading will continue until morale improves."
-#    tip_all_species: "We believe in equal opportunities to learn programming for all species."
+    keyboard_shortcuts: "Tastaturgenveje"
+    loading_ready: "Klar!"
+    loading_start: "Start bane"
+    problem_alert_title: "Ret din kode"
+    problem_alert_help: "Hjælp"
+    time_current: "Nu:"
+    time_total: "Max:"
+    time_goto: "Gå til:"
+    non_user_code_problem_title: "Kan ikke indlæse banen"
+    infinite_loop_title: "Uendelig løkke detekteret"
+    infinite_loop_description: "Den indledende kode til at bygge verdenen blev aldrig færdig med at køre. Den er sandsynligvis enten meget langsom eller har en uendeligt løkke. Eller også er der en bug. Du kan enten prøve at køre denne kode igen eller nulstille koden til den oprindelige tilstand. Hvis ikke det virker må du meget gerne fortælle os det."
+    check_dev_console: "Du kan også åbne udviklerkonsollen for at se hvad der kunne være galt."
+    check_dev_console_link: "(vejledning)"
+    infinite_loop_try_again: "Prøv igen"
+    infinite_loop_reset_level: "Nulstil bane"
+    infinite_loop_comment_out: "Udkommenter min kode"
+    tip_toggle_play: "Skift mellem afspil/pause med Ctrl+P."
+    tip_scrub_shortcut: "Brug Ctrl+[ og Ctrl+] til at spole tilbage og frem."
+    tip_guide_exists: "Klik på guiden i spilmenuen (i toppen af siden) for brugbar info."
+    tip_open_source: "CodeCombat er 100% open source!"
+    tip_beta_launch: "CodeCombat søsatte sin beta i oktober, 2013."
+    tip_think_solution: "Tænk på løsningen, ikke problemet."
+    tip_theory_practice: "I teorien er der ingen forskel på teori og praksis. Men i praksis er der. - Yogi Bjørn"
+    tip_error_free: "Der findes to måder at skrive fejlfrie programmer; kun den tredje virker. - Alan Perlis"
+    tip_debugging_program: "Hvis debugging er at fjerne kodefejl, så må programmering være at proppe fejl ind i koden. - Edsger W. Dijkstra"
+    tip_forums: "Kig over i vores forum og fortæl os hvad du synes!"
+    tip_baby_coders: "I fremtiden vil selv babier være Ærketroldmænd."
+    tip_morale_improves: "Indlæsning vil fortsætte indtil moralen forbedres."
+    tip_all_species: "Vi tror på lige muligheder for at lære programmering for alle arter."
 #    tip_reticulating: "Reticulating spines."
-#    tip_harry: "Yer a Wizard, "
-#    tip_great_responsibility: "With great coding skill comes great debug responsibility."
+    tip_harry: "Du' en troldmand, "
+    tip_great_responsibility: "Med store kodeevner kommer stort fejlfindingsansvnar."
 #    tip_munchkin: "If you don't eat your vegetables, a munchkin will come after you while you're asleep."
 #    tip_binary: "There are only 10 types of people in the world: those who understand binary, and those who don't."
 #    tip_commitment_yoda: "A programmer must have the deepest commitment, the most serious mind. ~ Yoda"
diff --git a/app/views/contribute/DiplomatView.coffee b/app/views/contribute/DiplomatView.coffee
index 94a0f38b7..24fa7ef79 100644
--- a/app/views/contribute/DiplomatView.coffee
+++ b/app/views/contribute/DiplomatView.coffee
@@ -121,7 +121,7 @@ module.exports = class DiplomatView extends ContributeClassView
     vi: ['An Nguyen Hoang Thien']             # Tiếng Việt, Vietnamese
     hu: ['Anon', 'atlantisguru', 'bbeasmile', 'csuvsaregal', 'divaDseidnA', 'ferpeter', 'kinez']             # magyar, Hungarian
     th: ['Kamolchanok Jittrepit']             # ไทย, Thai
-    da: ['Anon', 'Einar Rasmussen', 'Rahazan', 'Randi Hillerøe', 'Silwing', 'marc-portier', 'sorsjen']             # dansk, Danish
+    da: ['Anon', 'Einar Rasmussen', 'Rahazan', 'Randi Hillerøe', 'Silwing', 'marc-portier', 'sorsjen', 'Zleep-Dogg']             # dansk, Danish
     ko: ['Melondonut']             # 한국어, Korean
     sk: ['Anon', 'Juraj Pecháč']             # slovenčina, Slovak
     sl: []             # slovenščina, Slovene

From fdf500cac197677238db5932f6227c21c2c104a3 Mon Sep 17 00:00:00 2001
From: Matt Lott <mattlott@live.com>
Date: Thu, 11 Jun 2015 14:32:10 -0700
Subject: [PATCH 02/18] Average level playtimes script

---
 .../mongodb/queries/averageLevelPlaytimes.js  | 136 ++++++++++++++++++
 1 file changed, 136 insertions(+)
 create mode 100644 scripts/analytics/mongodb/queries/averageLevelPlaytimes.js

diff --git a/scripts/analytics/mongodb/queries/averageLevelPlaytimes.js b/scripts/analytics/mongodb/queries/averageLevelPlaytimes.js
new file mode 100644
index 000000000..0a7f18330
--- /dev/null
+++ b/scripts/analytics/mongodb/queries/averageLevelPlaytimes.js
@@ -0,0 +1,136 @@
+// Average level playtimes by campaign
+
+// Usage:
+// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
+
+// NOTE: faster to use find() instead of aggregate()
+// NOTE: faster to ask for one level at a time.  also keeps levels in campaign order
+
+// Excluded for one reason or another
+// Some relevant code:  https://github.com/codecombat/codecombat/blob/master/app/views/play/CampaignView.coffee#L281-L292
+var excludedLevels = ['deadly-dungeon-rescue', 'kithgard-brawl', 'cavern-survival', 'kithgard-mastery', 'destroying-angel', 'kithgard-apprentice', 'wild-horses', 'lost-viking', 'forest-flower-grove', 'boulder-woods', 'the-trials'];
+
+var scriptStartTime = new Date();
+var startDay = '2015-05-10';
+var endDay = '2015-06-11';
+
+log("Dates: " + startDay + " to " + endDay);
+
+// Print out playtimes for each campaign
+var campaigns = getCampaigns();
+for (var i = 0; i < campaigns.length; i++) {
+  var campaign = campaigns[i];
+  // if (campaign.slug !== 'dungeon') continue;
+  print(campaign.slug + " (free)");
+  var total = 0;
+
+  for (var j = 0; j < campaign.free.length; j++) {
+    var levelSlug = campaign.free[j];
+    if (excludedLevels.indexOf(levelSlug) >= 0) continue;
+    var data = getPlaytimes([levelSlug]);
+    print(data[levelSlug].average + "\t" + data[levelSlug].count + "\t" + levelSlug);
+    total += data[levelSlug];
+  }
+  // print(parseInt(total/60/60) + "\t\t total hours");
+  total = 0;
+
+  print(campaign.slug + " (paid)");
+  for (var j = 0; j < campaign.paid.length; j++) {
+    var levelSlug = campaign.paid[j];
+    if (excludedLevels.indexOf(levelSlug) >= 0) continue;
+    var data = getPlaytimes([levelSlug]);
+    if (data[levelSlug]) {
+      print(data[levelSlug].average + "\t" + data[levelSlug].count + "\t" + levelSlug);
+      total += data[levelSlug];
+    }
+    else {
+      print("0\t0\t" + levelSlug);
+    }
+  }
+  // print(parseInt(total/60/60) + "\t\t total hours");
+  total = 0;
+
+  print(campaign.slug + " (replayable)");
+  for (var j = 0; j < campaign.replayable.length; j++) {
+    var levelSlug = campaign.replayable[j];
+    if (excludedLevels.indexOf(levelSlug) >= 0) continue;
+    var data = getPlaytimes([levelSlug]);
+    print(data[levelSlug].average + "\t" + data[levelSlug].count + "\t" + levelSlug);
+    total += data[levelSlug];
+  }
+  // print(parseInt(total/60/60) + "\t\t total hours");
+
+  // break;
+}
+
+log("Script runtime: " + (new Date() - scriptStartTime));
+
+function log(str) {
+  print(new Date().toISOString() + " " + str);
+}
+
+function objectIdWithTimestamp(timestamp) {
+  // Convert string date to Date object (otherwise assume timestamp is a date)
+  if (typeof(timestamp) == 'string') timestamp = new Date(timestamp);
+  // Convert date object to hex seconds since Unix epoch
+  var hexSeconds = Math.floor(timestamp/1000).toString(16);
+  // Create an ObjectId with that hex timestamp
+  var constructedObjectId = ObjectId(hexSeconds + "0000000000000000");
+  return constructedObjectId
+}
+
+function getCampaigns() {
+  var campaigns = [];
+  var cursor = db.campaigns.find({}, {slug: 1, levels: 1});
+  var allFree = 0;
+  var allpaid = 0;
+  while (cursor.hasNext()) {
+    var doc = cursor.next();
+    if (doc.slug === 'auditions') continue;
+    var campaign = {slug: doc.slug, free: [], paid: [], replayable: []};
+    for (var levelID in doc.levels) {
+      if (doc.levels[levelID].replayable) {
+        campaign.replayable.push(doc.levels[levelID].slug);
+      }
+      else if (doc.levels[levelID].requiresSubscription) {
+        campaign.paid.push(doc.levels[levelID].slug);
+      }
+      else {
+        campaign.free.push(doc.levels[levelID].slug);
+      }
+    }
+    campaigns.push(campaign);
+  }
+  return campaigns;
+}
+
+function getPlaytimes(levelSlugs) {
+  var startObj = objectIdWithTimestamp(ISODate(startDay + "T00:00:00.000Z"));
+  var endObj = objectIdWithTimestamp(ISODate(endDay + "T00:00:00.000Z"))
+  var cursor = db['level.sessions'].find({
+    $and:
+    [
+      {"state.complete": true},
+      {"playtime": {$gt: 0}},
+      {levelID: {$in: levelSlugs}},
+      {_id: {$gte: startObj}},
+      {_id: {$lt: endObj}}
+    ]
+  });
+
+  var playtimes = {};
+  while (cursor.hasNext()) {
+    var myDoc = cursor.next();
+    var levelID = myDoc.levelID;
+    if (!playtimes[levelID]) playtimes[levelID] = [];
+    playtimes[levelID].push(myDoc.playtime);
+  }
+
+  var data = {};
+  for (levelID in playtimes) {
+    var total = playtimes[levelID].reduce(function(a, b) {return a + b;});
+    data[levelID] = {count: playtimes[levelID].length, total: total};
+    data[levelID]['average'] = parseInt(total / playtimes[levelID].length);
+  }
+  return data;
+}

From c806b8865e80e93433e9e1225e49c692536ec1e8 Mon Sep 17 00:00:00 2001
From: Kevin Avignon <kevin.o.avignon@gmail.com>
Date: Sat, 13 Jun 2015 11:39:25 -0400
Subject: [PATCH 03/18] Made some changes into the french file

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

diff --git a/app/locale/fr.coffee b/app/locale/fr.coffee
index 2f1173363..64ff640d1 100644
--- a/app/locale/fr.coffee
+++ b/app/locale/fr.coffee
@@ -158,7 +158,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     unwatch: "Ne plus regarder"
     submit_patch: "Soumettre un correctif"
     submit_changes: "Soumettre des Changements"
-#    save_changes: "Save Changes"
+    save_changes: "Sauvegarder les modifications"
 
   general:
     and: "et"
@@ -263,7 +263,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     victory_experience_gained: "XP gagnée"
     victory_gems_gained: "Gemmes gagnées"
     victory_new_item: "Nouvel item"
-#    victory_viking_code_school: "Holy smokes, that was a hard level you just beat! If you aren't already a software developer, you should be. You just got fast-tracked for acceptance with Viking Code School, where you can take your skills to the next level and become a professional web developer in 14 weeks."
+    victory_viking_code_school: "Par la barbe d'Odin, c'est un niveau difficile que tu viens de compléter! Si tu n'est pas un développeur de logiciel, tu devrais l'être ! Ceci vient de te propulser dans l'école de Code Vikings où tu pourras amener tes habilités au prochain niveau et devenir un développer web profesionnel en deux semaines."
     victory_become_a_viking: "Devenez un viking"
     guide_title: "Guide"
     tome_minion_spells: "Les sorts de vos soldats" # Only in old-style levels.
@@ -455,24 +455,24 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     was_free_until: "Vous aviez un abonnement gratuit jusqu'à"
     managed_subs: "Gestion des abonnements"
     managed_subs_desc: "Ajout d'abonnements pour les autres joueurs (étudiants,enfants,etc.) for other players."
-#    managed_subs_desc_2: "Recipients must have a CodeCombat account associated with the email address you provide."
-#    group_discounts: "Group discounts"
-#    group_discounts_1: "We also offer group discounts for bulk subscriptions."
-#    group_discounts_1st: "1st subscription"
-#    group_discounts_full: "Full price"
-#    group_discounts_2nd: "Subscriptions 2-11"
-#    group_discounts_20: "20% off"
-#    group_discounts_12th: "Subscriptions 12+"
-#    group_discounts_40: "40% off"
-#    subscribing: "Subscribing..."
-#    recipient_emails_placeholder: "Enter email address to subscribe, one per line."
-#    subscribe_users: "Subscribe Users"
-#    users_subscribed: "Users subscribed:"
-#    no_users_subscribed: "No users subscribed, please double check your email addresses."
-#    current_recipients: "Current Recipients"
-#    unsubscribing: "Unsubscribing..."
-#    subscribe_prepaid: "Click Subscribe to use prepaid code"
-#    using_prepaid: "Using prepaid code for monthly subscription"
+    managed_subs_desc_2: "Recipients must have a CodeCombat account associated with the email address you provide."
+    group_discounts: "Rabais de groupes"
+    group_discounts_1: "Nous offrons des rabais de groupe pour les gros abonnements"
+    group_discounts_1st: "Premier abonnement"
+    group_discounts_full: "Plein prix"
+    group_discounts_2nd: "Abonnements 2-11"
+    group_discounts_20: "Rabais de 20%"
+    group_discounts_12th: "Abonnements 12+"
+    group_discounts_40: "Rabais de 40%"
+    subscribing: "S'inscrit..."
+    recipient_emails_placeholder: "Entrez votre courriel pour vous abonner, un par ligne."
+    subscribe_users: "Seulement pour les usagers aboonés"
+    users_subscribed: "Usagers abonnés:"
+    no_users_subscribed: "Aucun usager abonnés, veuillez vérifier vos courriels."
+    current_recipients: "Recipients courant"
+    unsubscribing: "Desincription en cours..."
+    subscribe_prepaid: "Cliquer S'abonner pour utiliser du code prépayé"
+    using_prepaid: "Utiliser le code prépayé pour un abonnement mensuel"
 
   choose_hero:
     choose_hero: "Choisissez votre héros"
@@ -500,14 +500,14 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     blocks: "Absorbe" # As in "this shield blocks this much damage"
     backstab: "Poignardé" # As in "this dagger does this much backstab damage"
     skills: "Compétences"
-#    attack_1: "Deals"
-#    attack_2: "of listed"
-#    attack_3: "weapon damage."
-#    health_1: "Gains"
-#    health_2: "of listed"
-#    health_3: "armor health."
-#    speed_1: "Moves at"
-#    speed_2: "meters per second."
+    attack_1: "Inflige"
+    attack_2: "Classé de"
+    attack_3: "Dommage causé par l'arme"
+    health_1: "Gains"
+    health_2: "Provenance de la liste"
+    health_3: "Endurance de l'armure"
+    speed_1: "Se mouvoit à"
+    speed_2: "mètres par seconde"
     available_for_purchase: "Disponible à l'achat" # Shows up when you have unlocked, but not purchased, a hero in the hero store
     level_to_unlock: "Niveau à débloquer :" # Label for which level you have to beat to unlock a particular hero (click a locked hero in the store to see)
     restricted_to_certain_heroes: "Seulement certains héros peuvent jouer ce niveau."
@@ -581,13 +581,13 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     michael_blurb: "Sys Admin"
     matt_title: "Programmeur" # {change}
     matt_blurb: "Bicycliste"
-#    cat_title: "Chief Artisan"
-#    cat_blurb: "Airbender"
-#    josh_title: "Game Designer"
-#    josh_blurb: "Floor Is Lava"
-#    jose_title: "Music"
-#    jose_blurb: "Taking Off"
-#    retrostyle_title: "Illustration"
+    cat_title: "Chef Artisan"
+    cat_blurb: "Seigneur de l'air"
+    josh_title: "Designer de jeu"
+    josh_blurb: "Le plancher est de la lave"
+    jose_title: "Musique"
+    jose_blurb: "Décollage"
+    retrostyle_title: "Illustration"
 #    retrostyle_blurb: "RetroStyle Games"
 
   teachers:
@@ -595,7 +595,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     intro_1: "CodeCombat est un jeu en ligne qui enseigne la programmation. Les élèves écrivent du code dans de vrais langages de programmation."
     intro_2: "Aucune expérience requise !"
     free_title: "Combien cela coûte-t-il ?"
-#    cost_china: "CodeCombat in China is free for the first five levels, after which it costs $9.99 USD per month for access to our other 140+ levels on our exclusive China servers."
+    cost_china: "CodeCombat en Chine est gratuit pour les cinq premiers niveaux,après le jeu coûte 9.99$ US par mois pour avoir un accès aux autres 140+ niveaux sur les serveurs exlcusifs chinois"
     free_1: "La version de base de CodeCombat est gratuite ! Il y a 70+ niveaux gratuits qui couvrent chaque concepts." # {change}
     free_2: "Un abonnement mensuel fournit l'accès à des vidéos de tutoriels ainsi qu'à des niveaux d'entraînement supplémentaires."
     teacher_subs_title: "Les enseignants reçoivent un abonnement gratuit !"
@@ -608,14 +608,14 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
     sub_includes_4: "Support email premium"
     sub_includes_5: "7 nouveaux héros avec des capacités uniques à maitriser"
     sub_includes_6: "3500 gemmes bonus chaque mois"
-#    sub_includes_7: "Private Clans"
-#    monitor_progress_title: "How do I monitor student progress?"
-#    monitor_progress_1: "Student progress can be monitored by creating a"
-#    monitor_progress_2: "for your class."
-#    monitor_progress_3: "To add a student, send them the invite link for your Clan, which is on the"
-#    monitor_progress_4: "page."
-#    monitor_progress_5: "After they join, you will see a summary of the student's progress on your Clan's page."
-#    private_clans_1: "Private Clans provide increased privacy and detailed progress information for each student."
+    sub_includes_7: "Clans Privées"
+    monitor_progress_title: "Comment puis-je faire pour surveiller les progrès des étudiants?"
+    monitor_progress_1: "Le progès des étudiants peut être surveiller en créant un"
+    monitor_progress_2: "pour votre classe"
+    monitor_progress_3: "Pour ajouter un étudiant, envoyer leur le lien contenant une invitation pour votre Clan"
+    monitor_progress_4: "page."
+    monitor_progress_5: "After they join, you will see a summary of the student's progress on your Clan's page."
+    private_clans_1: "Private Clans provide increased privacy and detailed progress information for each student."
     private_clans_2: "Pour créer un Clan privé, veuillez vous référer à la boîte à cocher 'Faire un clan privé' pendant la création du clan."
     private_clans_3: "."
     who_for_title: "A qui CodeCombat est t-il destiné ?"

From e263866a3a5e4278e61e7a0d04c96780d2bfbb6c Mon Sep 17 00:00:00 2001
From: Kevin Avignon <kevin.o.avignon@gmail.com>
Date: Sat, 13 Jun 2015 23:33:48 -0400
Subject: [PATCH 04/18] Made some update within the spanish file

---
 app/locale/es-ES.coffee | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/app/locale/es-ES.coffee b/app/locale/es-ES.coffee
index 979570579..ac4d94951 100644
--- a/app/locale/es-ES.coffee
+++ b/app/locale/es-ES.coffee
@@ -170,7 +170,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
     accepted: "Aceptado"
     rejected: "Rechazado"
     withdrawn: "Retirado"
-#    submitter: "Submitter"
+    submitter: "Submitter"
     submitted: "Enviado"
     commit_msg: "Mensaje de Asignación o Commit"
     review: "Revisión"
@@ -262,9 +262,9 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
     victory_hour_of_code_done_yes: "Si, ¡He terminado con mi hora de código!"
     victory_experience_gained: "XP Conseguida"
     victory_gems_gained: "Gemas Conseguidas"
-#    victory_new_item: "New Item"
+    victory_new_item: "Nuevo artículo"
 #    victory_viking_code_school: "Holy smokes, that was a hard level you just beat! If you aren't already a software developer, you should be. You just got fast-tracked for acceptance with Viking Code School, where you can take your skills to the next level and become a professional web developer in 14 weeks."
-#    victory_become_a_viking: "Become a Viking"
+    victory_become_a_viking: "Convertirse en un vikingo"
     guide_title: "Guía"
     tome_minion_spells: "Los hechizos de tus súbditos" # Only in old-style levels.
     tome_read_only_spells: "Hechizos de solo lectura" # Only in old-style levels.
@@ -292,8 +292,8 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
     time_current: "Ahora:"
     time_total: "Máx:"
     time_goto: "Ir a:"
-#    non_user_code_problem_title: "Unable to Load Level"
-#    infinite_loop_title: "Infinite Loop Detected"
+    non_user_code_problem_title: "No puede cargar un nivel"
+    infinite_loop_title: "Bucle infinito detectado"
 #    infinite_loop_description: "The initial code to build the world never finished running. It's probably either really slow or has an infinite loop. Or there might be a bug. You can either try running this code again or reset the code to the default state. If that doesn't fix it, please let us know."
 #    check_dev_console: "You can also open the developer console to see what might be going wrong."
 #    check_dev_console_link: "(instructions)"
@@ -332,7 +332,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
     tip_extrapolation: "Existen solo dos clases de personas: aquellos que pueden extrapolar desde información incompleta..."
     tip_superpower: "Programar es lo más parecido que tenemos a un superpoder."
     tip_control_destiny: "En el verdadero open source, tienes el derecho de controlar tu propio destino. - Linus Torvalds"
-#    tip_no_code: "No code is faster than no code."
+    tip_no_code: "Ningún código es más rápido que ningún código"
     tip_code_never_lies: "El código nunca os miente, los comentarios algunas veces. — Ron Jeffries"
     tip_reusable_software: "Antes de que el software pueda ser reutilizable, primero debe ser utilizable."
     tip_optimization_operator: "Cada lenguaje tiene un operator para optimización. En la mayoría de los lenguajes dicho operador es ‘//’"
@@ -346,7 +346,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
 #    tip_open_source_contribute: "You can help CodeCombat improve!"
     tip_recurse: "Iterar es humano, recursar es divino. - L. Peter Deutsch"
 #    tip_free_your_mind: "You have to let it all go, Neo. Fear, doubt, and disbelief. Free your mind. - Morpheus"
-#    tip_strong_opponents: "Even the strongest of opponents always has a weakness. - Itachi Uchiha"
+    tip_strong_opponents: "Incluso el más fuerte de los opositores oculta debilidad. - Itachi Uchiha"
 
   game_menu:
     inventory_tab: "Inventario"
@@ -366,14 +366,14 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
     auth_caption: "Salvar tu progreso."
 
   leaderboard:
-#    leaderboard: "Leaderboard"
+    leaderboard: "Jefe de la liga"
     view_other_solutions: "Ver Otras Soluciones" # {change}
     scores: "Puntuaciones"
 #    top_players: "Top Players by"
     day: "Hoy"
     week: "Esta semana"
 #    all: "All-Time"
-#    time: "Time"
+    time: "Tiempo"
     damage_taken: "Daño recibido"
     damage_dealt: "Daño causado"
     difficulty: "Difficultad"

From 3f3f44038e929440523853bbb8a06dfb67092c09 Mon Sep 17 00:00:00 2001
From: Ikuyadeu <ikuyadeu@yahoo.co.jp>
Date: Sun, 14 Jun 2015 17:11:26 +0900
Subject: [PATCH 05/18] Update ja.coffee

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

diff --git a/app/locale/ja.coffee b/app/locale/ja.coffee
index 191c2aa84..501dc2282 100644
--- a/app/locale/ja.coffee
+++ b/app/locale/ja.coffee
@@ -262,7 +262,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
     victory_hour_of_code_done_yes: "はい、構いません"
     victory_experience_gained: "XP獲得"
     victory_gems_gained: "ジェム獲得"
-#    victory_new_item: "New Item"
+    victory_new_item: "ニューアイテム"
 #    victory_viking_code_school: "Holy smokes, that was a hard level you just beat! If you aren't already a software developer, you should be. You just got fast-tracked for acceptance with Viking Code School, where you can take your skills to the next level and become a professional web developer in 14 weeks."
 #    victory_become_a_viking: "Become a Viking"
     guide_title: "ガイド"
@@ -292,11 +292,11 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
     time_current: "今:"
     time_total: "最大:"
     time_goto: "行く:"
-#    non_user_code_problem_title: "Unable to Load Level"
-#    infinite_loop_title: "Infinite Loop Detected"
-#    infinite_loop_description: "The initial code to build the world never finished running. It's probably either really slow or has an infinite loop. Or there might be a bug. You can either try running this code again or reset the code to the default state. If that doesn't fix it, please let us know."
-#    check_dev_console: "You can also open the developer console to see what might be going wrong."
-#    check_dev_console_link: "(instructions)"
+    non_user_code_problem_title: "レベルをロードできません"
+    infinite_loop_title: "無限ループが見つかりました"
+    infinite_loop_description: "最初のワールドを作るコードが終わりません。単に遅いか、無限ループになっているかでしょう。バグがあるのかもしれません。再試行してみたり、リセットしてデフォルトに戻すこともできます。もし直せないなら私たちに報告してください。"
+    check_dev_console: "開発者コンソールをみてなにが間違っているか見ることもできます。"
+    check_dev_console_link: "(説明書)"
     infinite_loop_try_again: "再試行する"
     infinite_loop_reset_level: "レベルをリセット"
     infinite_loop_comment_out: "マイコードをコメントアウト"
@@ -345,8 +345,8 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
     tip_hate_computers: "コンピュータを憎む人が本当に嫌いなのは下手なプログラマーだ。- ラリー・ニーヴン"
     tip_open_source_contribute: "あなたは CodeCombat をより良くすることができます!"
     tip_recurse: "繰り返しは人間、再帰は神。 - L・ピーター・ドイツ"
-#    tip_free_your_mind: "You have to let it all go, Neo. Fear, doubt, and disbelief. Free your mind. - Morpheus"
-#    tip_strong_opponents: "Even the strongest of opponents always has a weakness. - Itachi Uchiha"
+    tip_free_your_mind: "全ての雑念を捨てろ、恐怖、疑いも不信も 心を解き放つんだ - モーフィアス"
+    tip_strong_opponents: "どんな強者にも弱点というものはあるんだ… - うちは イタチ"
 
   game_menu:
     inventory_tab: "インベントリー"

From 7d637a0a27a393cd6c399fbeb068e08e11faa2ec Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 14 Jun 2015 11:07:21 -0700
Subject: [PATCH 06/18] Added a couple levels' next-campaign links.

---
 app/views/play/CampaignView.coffee                 | 2 +-
 app/views/play/level/modal/HeroVictoryModal.coffee | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/views/play/CampaignView.coffee b/app/views/play/CampaignView.coffee
index 54f4d35ca..d2629223b 100644
--- a/app/views/play/CampaignView.coffee
+++ b/app/views/play/CampaignView.coffee
@@ -352,7 +352,7 @@ module.exports = class CampaignView extends RootView
       particleKey.push level.type if level.type and level.type isnt 'hero'
       particleKey.push 'replayable' if level.replayable
       particleKey.push 'premium' if level.requiresSubscription
-      particleKey.push 'gate' if level.slug in ['kithgard-gates', 'siege-of-stonehold', 'clash-of-clones']
+      particleKey.push 'gate' if level.slug in ['kithgard-gates', 'siege-of-stonehold', 'clash-of-clones', 'summits-gate']
       particleKey.push 'hero' if level.unlocksHero and not level.unlockedHero
       particleKey.push 'item' if level.slug is 'apocalypse'  # TODO: generalize
       continue if particleKey.length is 2  # Don't show basic levels
diff --git a/app/views/play/level/modal/HeroVictoryModal.coffee b/app/views/play/level/modal/HeroVictoryModal.coffee
index c5a644044..086548fc4 100644
--- a/app/views/play/level/modal/HeroVictoryModal.coffee
+++ b/app/views/play/level/modal/HeroVictoryModal.coffee
@@ -329,7 +329,7 @@ module.exports = class HeroVictoryModal extends ModalView
       AudioPlayer.playSound name, 1
 
   getNextLevelCampaign: ->
-    {'kithgard-gates': 'forest', 'siege-of-stonehold': 'desert', 'clash-of-clones': 'mountain'}[@level.get('slug')] or @level.get 'campaign'  # Much easier to just keep this updated than to dynamically figure it out.
+    {'kithgard-gates': 'forest', 'kithgard-mastery': 'forest', 'siege-of-stonehold': 'desert', 'clash-of-clones': 'mountain'}[@level.get('slug')] or @level.get 'campaign'  # Much easier to just keep this updated than to dynamically figure it out.
 
   getNextLevelLink: ->
     link = '/play'

From f7eaf91bae1c893d062d130662771347f60555fd Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Sun, 14 Jun 2015 12:49:45 -0700
Subject: [PATCH 07/18] Hopefully making Systems editable by Artisans.

---
 server/levels/systems/level_system_handler.coffee | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/server/levels/systems/level_system_handler.coffee b/server/levels/systems/level_system_handler.coffee
index eac89caca..4c356f1d7 100644
--- a/server/levels/systems/level_system_handler.coffee
+++ b/server/levels/systems/level_system_handler.coffee
@@ -23,5 +23,8 @@ LevelSystemHandler = class LevelSystemHandler extends Handler
   hasAccess: (req) ->
     req.method is 'GET' or req.user?.isAdmin() or req.user?.isArtisan()
 
+  hasAccessToDocument: (req, document, method) ->
+    if req.user?.isArtisan() then true else super req, document, method
+
 
 module.exports = new LevelSystemHandler()

From 1c633a8ee40026013aa3e44f60ac496b0ee538aa Mon Sep 17 00:00:00 2001
From: David Liu <a.davidliu@gmail.com>
Date: Sun, 14 Jun 2015 15:25:11 -0700
Subject: [PATCH 08/18] Show correct achievement earned dates on user page

fixes #2524
---
 app/templates/user/main-user-view.jade | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/templates/user/main-user-view.jade b/app/templates/user/main-user-view.jade
index 444ec9d3d..b1bb6ec13 100644
--- a/app/templates/user/main-user-view.jade
+++ b/app/templates/user/main-user-view.jade
@@ -73,7 +73,7 @@ block append content
                 tr
                   td
                     a(href="/clans/#{clan.id}")= clan.get('name')
-                  td 
+                  td
                     if idNameMap && idNameMap[clan.get('ownerID')]
                       a(href="/user/#{clan.get('ownerID')}")= idNameMap[clan.get('ownerID')]
                     else
@@ -160,7 +160,7 @@ block append content
               each achievement, index in earnedAchievements.models
                 tr(class=index > 4 ? 'hide' : '')
                   td= achievement.get('achievementName')
-                  td= moment().format("MMMM Do YYYY", achievement.get('changed'))
+                  td= moment(achievement.get('changed')).format("MMMM Do YYYY")
                   if achievement.get('achievedAmount')
                     td= achievement.get('achievedAmount')
                   else

From fd5a99b9d0a83f771a7f6b8b1f510a4533533d86 Mon Sep 17 00:00:00 2001
From: Mihbo <s_a_n_d@bigmir.net>
Date: Mon, 15 Jun 2015 10:02:24 +0300
Subject: [PATCH 09/18] Update uk.coffee

translated some more strings
---
 app/locale/uk.coffee | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/app/locale/uk.coffee b/app/locale/uk.coffee
index 05edcae61..fc9e714b6 100644
--- a/app/locale/uk.coffee
+++ b/app/locale/uk.coffee
@@ -440,9 +440,9 @@ module.exports = nativeDescription: "Українська", englishDescription:
     parents_blurb2: "За 9.99$ на місяць, вона отримуватиме нові завдання щотижня та персональні листи підтримки від професійних програмістів." # {change}
     parents_blurb3: "Жодного ризику: 100% гарантія повернення грошей, легке скасування абонементу одним кліком."
     payment_methods: "Платіжні методи"
-#    payment_methods_title: "Accepted Payment Methods"
+    payment_methods_title: "Платіжні методи, що приймаються"
     payment_methods_blurb1: "Наразі ми приймаємо кредитні картник та Alpiay."
-#    payment_methods_blurb2: "If you require an alternate form of payment, please contact"
+    payment_methods_blurb2: "Якщо Вам необхідно використати інший спосіб оплати, будь ласка, зв'яжіться з нами."
     stripe_description: "Щомісячний абонемент"
     subscription_required_to_play: "Аби грати в цьому рівні потрібен абонемент."
     unlock_help_videos: "Підпишіться, щоб відкрити усі навчальні відео."
@@ -455,7 +455,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
     was_free_until: "У Вас був безкоштовний абонемент до "
     managed_subs: "Керовані абонементи"
     managed_subs_desc: "Додати абонементи для інших гравців (учнів, дітей тощо)"
-#    managed_subs_desc_2: "Recipients must have a CodeCombat account associated with the email address you provide."
+    managed_subs_desc_2: "Одержувачі повинні мати обліковий запис CodeCombat, пов'язаний з вказаною Вами адресою електронної пошти."
     group_discounts: "Групові знижки"
     group_discounts_1: "Ми також пропонуємо знижки для пакетних передплат."
     group_discounts_1st: "1-ий абонемент (включає Ваш)" # {change}
@@ -592,8 +592,8 @@ module.exports = nativeDescription: "Українська", englishDescription:
 
   teachers:
     title: "CodeCombat для вчителів" # {change}
-#    intro_1: "CodeCombat is an online game that teaches programming. Students write code in real programming languages."
-#    intro_2: "No experience required!"
+    intro_1: "CodeCombat - це онлайн гра, що вчить програмуванню. Студенти пишуть код на реальних мовах програмування."
+    intro_2: "Досвід не потрібен!"
     free_title: "Скільки це коштує?"
 #    cost_china: "CodeCombat in China is free for the first five levels, after which it costs $9.99 USD per month for access to our other 140+ levels on our exclusive China servers."
 #    free_1: "There are 80+ FREE levels which cover every concept."

From fa8d31774511f46b6f079f7ce7f22c88ce7e1cf3 Mon Sep 17 00:00:00 2001
From: Ikuyadeu <ikuyadeu@yahoo.co.jp>
Date: Mon, 15 Jun 2015 18:48:04 +0900
Subject: [PATCH 10/18] Update ja.coffee

---
 app/locale/ja.coffee | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/app/locale/ja.coffee b/app/locale/ja.coffee
index 501dc2282..d680d7ca9 100644
--- a/app/locale/ja.coffee
+++ b/app/locale/ja.coffee
@@ -848,23 +848,23 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
     poll_title: "投票エディター"
     back: "バック"
     revert: "戻す"
-#    revert_models: "Revert Models"
+    revert_models: "モデルを戻す"
     pick_a_terrain: "地形を選択してください"
     dungeon: "ダンジョン"
     indoor: "屋内"
     desert: "砂漠"
     grassy: "草原"
-#    small: "Small"
-#    large: "Large"
-#    fork_title: "Fork New Version"
-#    fork_creating: "Creating Fork..."
-#    generate_terrain: "Generate Terrain"
-#    more: "More"
+    small: "小さい"
+    large: "大きい"
+    fork_title: "新しいバージョンをフォークする"
+    fork_creating: "フォークを作成中"
+    generate_terrain: "地形を生成"
+    more: "さらに見る"
     wiki: "ウィキ"
     live_chat: "ライブチャット"
-#    thang_main: "Main"
-#    thang_spritesheets: "Spritesheets"
-#    thang_colors: "Colors"
+    thang_main: "メイン"
+    thang_spritesheets: "スプライトシート"
+    thang_colors: "色"
 #    level_some_options: "Some Options?"
 #    level_tab_thangs: "Thangs"
 #    level_tab_scripts: "Scripts"

From aabae7082e32023c84433f85489a35e79685279a Mon Sep 17 00:00:00 2001
From: Lai Tuan <laituan245@kaist.ac.kr>
Date: Mon, 15 Jun 2015 19:11:48 +0900
Subject: [PATCH 11/18] Add Contact section to About page #2822

---
 app/locale/en.coffee     |  4 ++++
 app/templates/about.jade | 15 ++++++++++++++-
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index d49a4ee26..4bc8ef36f 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -568,6 +568,10 @@
     why_paragraph_2_suffix: "That's why CodeCombat is a multiplayer game, not a gamified lesson course. We won't stop until you can't stop--but this time, that's a good thing."
     why_paragraph_3: "If you're going to get addicted to some game, get addicted to this one and become one of the wizards of the tech age."
     press_title: "Bloggers/Press"
+    contact_title: "Contact"
+    codecombat_inc: "CodeCombat, Inc."
+    address_part_1: "188 King St #507"
+    address_part_2: "San Francisco, CA 94107"
     press_paragraph_1_prefix: "Want to write about us? Feel free to download and use all of the resources included in our"
     press_paragraph_1_link: "press packet"
     press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
diff --git a/app/templates/about.jade b/app/templates/about.jade
index 4abc35e1e..cd217b502 100644
--- a/app/templates/about.jade
+++ b/app/templates/about.jade
@@ -47,7 +47,20 @@ block content
         a(href="https://s3.amazonaws.com/CodeCombatMisc/press_packet.zip", data-i18n="about.press_paragraph_1_link") press packet
         span(data-i18n="about.press_paragraph_1_suffix")
           | . All logos and images may be used without contacting us directly.
-    
+
+      h2(data-i18n="about.contact_title")
+        | Contact
+      p
+        span(data-i18n="about.codecombat_inc")
+          | CodeCombat, Inc.
+        br
+        span(data-i18n="about.address_part_1")
+          | 188 King St #507
+        br
+        span(data-i18n="about.address_part_2")
+          | San Francisco, CA 94107
+        br
+        a(href='mailto:team@codecombat.com') team@codecombat.com
 
     ul.col-sm-6.team-column
  

From e8a862b2cedf1bd6fead9f88d9a65762dffe289f Mon Sep 17 00:00:00 2001
From: Ikuyadeu <ikuyadeu@yahoo.co.jp>
Date: Tue, 16 Jun 2015 11:05:18 +0900
Subject: [PATCH 12/18] Update ja.coffee

---
 app/locale/ja.coffee | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/app/locale/ja.coffee b/app/locale/ja.coffee
index d680d7ca9..97d4836dc 100644
--- a/app/locale/ja.coffee
+++ b/app/locale/ja.coffee
@@ -405,24 +405,24 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
     recovered: "前のジェム購入をリカバリーしました。ページを更新してください。"
     price: "x3500 / 月"
 
-#  subscribe:
-#    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
-#    feature1: "80+ basic levels across 4 worlds"
-#    feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
-#    feature3: "60+ bonus levels"
-#    feature4: "<strong>3500 bonus gems</strong> every month!"
-#    feature5: "Video tutorials"
-#    feature6: "Premium email support"
+  subscribe:
+    comparison_blurb: "CodeCombatへ課金してスキルを磨きましょう!"
+    feature1: "80以上の基本レベルが4つの世界に"
+    feature2: "7人のパワフルな <strong>ニューヒーロー</strong> とユニークなスキル!"
+    feature3: "60以上のボーナスレベル"
+    feature4: "<strong>3500のジェム</strong>が毎月ボーナス!"
+    feature5: "ビデオチュートリアル"
+    feature6: "プレミアムメールサポート"
 #    feature7: "Private <strong>Clans</strong>"
-#    free: "Free"
-#    month: "month"
-#    subscribe_title: "Subscribe"
-#    unsubscribe: "Unsubscribe"
+    free: "無料"
+    month: "月"
+    subscribe_title: "課金"
+    unsubscribe: "無課金"
 #    confirm_unsubscribe: "Confirm Unsubscribe"
-#    never_mind: "Never Mind, I Still Love You"
-#    thank_you_months_prefix: "Thank you for supporting us these last"
-#    thank_you_months_suffix: "months."
-#    thank_you: "Thank you for supporting CodeCombat."
+    never_mind: "気にしないでください, それでもあなたが好きです"
+    thank_you_months_prefix: "私達を "
+    thank_you_months_suffix: "ヶ月サポートしてくださりありがとうございます。"
+    thank_you: "CodeCombatをサポートして下さりありがとうございます。"
 #    sorry_to_see_you_go: "Sorry to see you go! Please let us know what we could have done better."
 #    unsubscribe_feedback_placeholder: "O, what have we done?"
 #    parent_button: "Ask your parent"
@@ -603,8 +603,8 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
     teacher_subs_2: "に連絡して無料の月々のサブスクリプションを得ましょう。" # {change}
 #    teacher_subs_3: "to set up your subscription."
     sub_includes_title: "サブスクリプションの内容について"
-    sub_includes_1: "70以上の基本レベルに加えて、生徒は月々のサブスクリプションを得て次の機能が使えます:" # {change}
-    sub_includes_2: "40以上の練習レベル" # {change}
+    sub_includes_1: "80以上の基本レベルに加えて、生徒は月々のサブスクリプションを得て次の機能が使えます:"
+    sub_includes_2: "60以上の練習レベル"
     sub_includes_3: "ビデオチュートリアル"
     sub_includes_4: "メールによるサポート"
     sub_includes_5: "7人の新しいヒーローとマスターのユニークなスキル"

From ce73d87f92b342eb30bfa450d755e50ce3ca631a Mon Sep 17 00:00:00 2001
From: Mihbo <s_a_n_d@bigmir.net>
Date: Tue, 16 Jun 2015 10:27:32 +0300
Subject: [PATCH 13/18] Update uk.coffee

some more strings translated
---
 app/locale/uk.coffee | 40 ++++++++++++++++++++--------------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/app/locale/uk.coffee b/app/locale/uk.coffee
index fc9e714b6..6afe623db 100644
--- a/app/locale/uk.coffee
+++ b/app/locale/uk.coffee
@@ -626,17 +626,17 @@ module.exports = nativeDescription: "Українська", englishDescription:
 #    material_china: "Approximately 30 hours of gameplay spread over 140+ subscriber-only levels so far, with new levels every week."
 #    material_1: "Approximately 10 hours of free content and an additional 20 hours of subscriber content, with new levels every week."
 #    concepts_title: "What concepts are covered?"
-#    how_much_title: "How much does a monthly subscription cost?"
-#    how_much_1: "A"
-#    how_much_2: "monthly subscription"
-#    how_much_3: "costs $9.99, and can be cancelled anytime."
-#    how_much_4: "Additionally, we provide discounts for larger groups:"
-#    how_much_5: "We accept discounted one-time purchases and yearly subscription purchases for groups, such as a class or school.  Please contact"
-#    how_much_6: "for more details."
-#    more_info_title: "Where can I find more information?"
-#    more_info_1: "Our"
-#    more_info_2: "teachers forum"
-#    more_info_3: "is a good place to connect with fellow educators who are using CodeCombat."
+    how_much_title: "Скільки коштує місячна передплата?"
+    how_much_1: ""
+    how_much_2: "Місячна передплата"
+    how_much_3: "коштує $9.99, та може бути скасована будь-коли."
+    how_much_4: "Крім цього, ми надаємо знижки для великих груп:"
+    how_much_5: "Ми надаємо знижку на разові закупівлі та річну передплату для груп, таких як клас або школа. Будь ласка, зв'яжіться з нами"
+    how_much_6: "для отримання більш детальної інформації."
+    more_info_title: "Де я можу знайти більше інформації?"
+    more_info_1: "Наш"
+    more_info_2: "вчительський форум"
+    more_info_3: "є гарним місцем для спілкування із колегами-педагогами, котрі використовують CodeCombat."
     sys_requirements_title: "Системні вимоги"
     sys_requirements_1: "Оскільки CodeCombat — це гра, для нормальної роботи він вимагає у комп'ютерів більше, ніж відео чи текстові посібники. Ми оптимізували його для швидкої роботи в усіх сучасних браузерах і на старіших машинах, щоб кожен міг грати. І ось наші підказки, як отримати від CodeCombat якнайбільше:" # {change}
     sys_requirements_2: "Використовуйте новіші версії Chrome або Firefox." # {change}
@@ -782,27 +782,27 @@ module.exports = nativeDescription: "Українська", englishDescription:
     new_name: "Назва нового клану"
     new_description: "Опис нового клану"
     make_private: "Зробити клан приватним"
-#    subs_only: "subscribers only"
+    subs_only: "лише для підписчиків"
     create_clan: "Створити новий клан"
     public_clans: "Публічні клани"
     my_clans: "Мої клани"
     clan_name: "Назва клану"
-#    name: "Name"
-#    chieftain: "Chieftain"
+    name: "Ім'я"
+    chieftain: "Отаман"
     type: "Тип"
     edit_clan_name: "Змінити назву клану"
     edit_clan_description: "Змінити опис клану"
-#    edit_name: "edit name"
-#    edit_description: "edit description"
-#    private: "(private)"
+    edit_name: "Змінити ім'я"
+    edit_description: "Змінити опис"
+    private: "(закритий)"
     summary: "Загалом"
     average_level: "Середній рівень"
-#    average_achievements: "Average Achievements"
-    delete_clan: "Видалити калн"
+    average_achievements: "Середні досягнення"
+    delete_clan: "Видалити клан"
     leave_clan: "Покинути клан"
     join_clan: "Приєднатись до клану"
     invite_1: "Запрошення:"
-    invite_2: "*Запросіть гравців до цього Клану виславши дане посилання."
+    invite_2: "*Запросіть гравців до цього Клану, виславши дане посилання."
     members: "Учасники"
     progress: "Поступ"
     not_started_1: "не розпочато"

From 624dabd55a7c041bb27302c1de303657914fac00 Mon Sep 17 00:00:00 2001
From: Matt Lott <mattlott@live.com>
Date: Tue, 16 Jun 2015 11:12:20 -0700
Subject: [PATCH 14/18] Level completion counts script

---
 .../mongodb/queries/levelCompletionCounts.js  | 153 ++++++++++++++++++
 1 file changed, 153 insertions(+)
 create mode 100644 scripts/analytics/mongodb/queries/levelCompletionCounts.js

diff --git a/scripts/analytics/mongodb/queries/levelCompletionCounts.js b/scripts/analytics/mongodb/queries/levelCompletionCounts.js
new file mode 100644
index 000000000..de7e91ab8
--- /dev/null
+++ b/scripts/analytics/mongodb/queries/levelCompletionCounts.js
@@ -0,0 +1,153 @@
+// Level completion counts broken down into free and paid buckets
+
+// Usage:
+// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
+
+// TODO: subscriber is someone who is currently subscribed, not necessarily subscribed when they completed a level
+
+// Excluded for one reason or another
+// Some relevant code:  https://github.com/codecombat/codecombat/blob/master/app/views/play/CampaignView.coffee#L281-L292
+var excludedLevels = ['deadly-dungeon-rescue', 'kithgard-brawl', 'cavern-survival', 'kithgard-mastery', 'destroying-angel', 'kithgard-apprentice', 'wild-horses', 'lost-viking', 'forest-flower-grove', 'boulder-woods', 'the-trials'];
+
+var scriptStartTime = new Date();
+var startDay = '2015-05-16';
+var endDay = '2015-06-17';
+
+log("Dates: " + startDay + " to " + endDay);
+
+var subscribers = getSubscribers();
+log("Subscriber count: " + Object.keys(subscribers).length);
+
+var campaigns = getCampaigns();
+for (var i = 0; i < campaigns.length; i++) {
+  var campaign = campaigns[i];
+  // if (campaign.slug !== 'mountain') continue;
+
+  function printCampaign(title, prop) {
+    print(title)
+    print("Total\tFree\tSubscribers");
+    for (var j = 0; j < campaign[prop].length; j++) {
+      var levelSlug = campaign[prop][j];
+      if (excludedLevels.indexOf(levelSlug) >= 0) continue;
+      var data = getCompletionCounts([levelSlug], subscribers);
+      if (data[levelSlug]) {
+        var free = data[levelSlug].free.length;
+        var paid = data[levelSlug].paid.length;
+        var total = free + paid;
+        var paidRate = parseInt(paid / total * 100);
+        print(total + "\t" + free + "\t" + paid + "\t\t" + paidRate + "%\t" + levelSlug);
+      }
+      else {
+        print("0\t0\t0\t\t0%\t" + levelSlug);
+      }
+    }
+  }
+
+  printCampaign(campaign.slug + " (free)", "free");
+  printCampaign(campaign.slug + " (paid)", "paid");
+  printCampaign(campaign.slug + " (replayable)", "replayable");
+
+  // break;
+}
+
+log("Script runtime: " + (new Date() - scriptStartTime));
+
+function log(str) {
+  print(new Date().toISOString() + " " + str);
+}
+
+function objectIdWithTimestamp(timestamp) {
+  // Convert string date to Date object (otherwise assume timestamp is a date)
+  if (typeof(timestamp) == 'string') timestamp = new Date(timestamp);
+  // Convert date object to hex seconds since Unix epoch
+  var hexSeconds = Math.floor(timestamp/1000).toString(16);
+  // Create an ObjectId with that hex timestamp
+  var constructedObjectId = ObjectId(hexSeconds + "0000000000000000");
+  return constructedObjectId
+}
+
+function getCampaigns() {
+  var campaigns = [];
+  var cursor = db.campaigns.find({}, {slug: 1, levels: 1});
+  var allFree = 0;
+  var allpaid = 0;
+  while (cursor.hasNext()) {
+    var doc = cursor.next();
+    if (doc.slug === 'auditions') continue;
+    var campaign = {slug: doc.slug, free: [], paid: [], replayable: []};
+    for (var levelID in doc.levels) {
+      if (doc.levels[levelID].replayable) {
+        campaign.replayable.push(doc.levels[levelID].slug);
+      }
+      else if (doc.levels[levelID].requiresSubscription) {
+        campaign.paid.push(doc.levels[levelID].slug);
+      }
+      else {
+        campaign.free.push(doc.levels[levelID].slug);
+      }
+    }
+    campaigns.push(campaign);
+  }
+  return campaigns;
+}
+
+function getCompletionCounts(levelSlugs, subscribers) {
+  var startObj = objectIdWithTimestamp(ISODate(startDay + "T00:00:00.000Z"));
+  var endObj = objectIdWithTimestamp(ISODate(endDay + "T00:00:00.000Z"))
+  var cursor = db['level.sessions'].find({
+    $and:
+    [
+      {"state.complete": true},
+      {levelID: {$in: levelSlugs}},
+      {_id: {$gte: startObj}},
+      {_id: {$lt: endObj}}
+    ]
+  });
+
+  var completionCounts = {};
+  while (cursor.hasNext()) {
+    var myDoc = cursor.next();
+    var userID = myDoc.creator;
+    var levelID = myDoc.levelID;
+
+    if (!completionCounts[levelID]) completionCounts[levelID] = {free: [], paid: []};
+    if (subscribers[userID]) {
+      completionCounts[levelID].paid.push(myDoc._id.valueOf());
+    }
+    else {
+      completionCounts[levelID].free.push(myDoc._id.valueOf());
+    }
+  }
+
+  return completionCounts;
+}
+
+function getSubscribers() {
+  var cursor = db['users'].find({
+    $and:
+    [
+      {
+        $or:
+        [
+          {"stripe.sponsorID": {$exists: true}},
+          {$and:
+            [
+              {"stripe.subscriptionID": {$exists: true}},
+              {"stripe.planID": 'basic'}
+            ]
+          }
+        ]
+      },
+      {permissions: {$ne: ['admin']}},
+      {"stripe.free": {$exists: false}},
+      {"stripe.coupon": {$exists: false}},
+      {"stripe.prepaidCode": {$exists: false}}
+    ]
+  });
+
+  var subscribers = {};
+  while (cursor.hasNext()) {
+    subscribers[cursor.next()._id.valueOf()] = true;
+  }
+  return subscribers;
+}

From 593f7a9dd7ec5b845ad37d2cb10a14471fb8e9cd Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Tue, 16 Jun 2015 13:50:33 -0700
Subject: [PATCH 15/18] Some improvements for handling new art.

---
 README.md                                       |   7 +++++++
 app/assets/images/pages/about/jose_small.png    | Bin 0 -> 12436 bytes
 app/assets/images/pages/about/oleg_small.png    | Bin 0 -> 9562 bytes
 app/assets/images/pages/about/pavel_small.png   | Bin 0 -> 10492 bytes
 app/lib/surface/SingularSprite.coffee           |   2 +-
 app/templates/about.jade                        |  12 +++++++-----
 app/views/editor/thang/ThangTypeEditView.coffee |   1 +
 app/views/play/menu/InventoryModal.coffee       |   7 +++++--
 8 files changed, 21 insertions(+), 8 deletions(-)
 create mode 100644 app/assets/images/pages/about/jose_small.png
 create mode 100644 app/assets/images/pages/about/oleg_small.png
 create mode 100644 app/assets/images/pages/about/pavel_small.png

diff --git a/README.md b/README.md
index ba5af9e83..2d10a11ac 100644
--- a/README.md
+++ b/README.md
@@ -69,3 +69,10 @@ Whether you're novice or pro, the CodeCombat team is ready to help you implement
 ![Alex Crooks](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Alex%20Crooks/alex_100.png)
 ![Danny Whittaker](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Danny%20Whittaker/danny_100.png)
 ![Kevin Holland](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Kevin%20Holland/kevin_100.png)
+![Joachim Brehmer](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Joachim%20Brehmer/joachim_100.png)
+![Jose Antonini](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Jose%20Antonini/jose_antonini_100.png)
+![Oleg Ulyanicky](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Oleg%20Ulyanickiy/oleg_100.png)
+![Pavel Konstantynov](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Pavel%20Konstantinov/pavel_100.png)
+![Popey Gilbert](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Popey%20Gilbert/popey_100.png)
+![Rob Blanckaert](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Rob%20Blanckaert/rob_blanckaert_100.png)
+
diff --git a/app/assets/images/pages/about/jose_small.png b/app/assets/images/pages/about/jose_small.png
new file mode 100644
index 0000000000000000000000000000000000000000..01bb440a9e6f6a339a6dbc7d6d4a48e6f5d874ee
GIT binary patch
literal 12436
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
LQUcXTn1uW<B<hN-

literal 0
HcmV?d00001

diff --git a/app/assets/images/pages/about/oleg_small.png b/app/assets/images/pages/about/oleg_small.png
new file mode 100644
index 0000000000000000000000000000000000000000..4690ed5cc03b398d1fb375fa7ed1b8edbc4fb24c
GIT binary patch
literal 9562
zcmZvC1ymf(w)NmnaECBMaJL`<0t3Ny&;$Yu?mB321}8v}!QI^n?(Ul40fIXuXpleO
zz4yKMTd&n!r%&%A`&6w}y{algT~!Vbn+h8M0N^Re%Rv6NX8+un=zpJ1TS;1f8zfhV
z92ihFNptX59<$ccgXyU#i<&yxb3x4<P0YDG?VbLj001#h(Z8a-ISfkgX>aG?D(Wc?
z`WHg<ul$di8$|yv2+UR-q^F`zFYV}JPA|wMz{LZSz^13C7jrSQ5QWId{>S|9n>fe{
z26GbS=JxRL;PT+-a&)oe<`oeU;pXAv=Hui1i{Nzia)3cSIUQUX{_W(y{K%NQnz~p!
z!K@t}=>PExHF0!<iGx7@1p4pmKY7|a{dXV-*Z;8k%a7X=>cq{<#l!voGlE%L{7-uS
zht)q{{%!UzR{str_O~>m(k|vun4^o9qobXK)IYVOSFnd#nnTQ?W?o|4|2N`)G8OyB
zrKp;VwfSGJ|1gr^732PYbpOGNasNa2f205J+Wt%Xx4076e<S@@M@e9_a!rT>01V;^
zGE!QeNNXRl5)HIdpNu+|zn>m5W}d2AzEDEOLh45Wj?%Nl;O69c(unb6^Mho!14J#w
z_&1y>Nl7&D^TYY0#|ZF;dNg_nF~YRX6#xk}7H6twjc0#+e)xXOJX94et@2w?XjX93
z?(jbAd|vl|KJ$Mr9>JPNIJSFg{8&mhfQ%QYmTQ?s$TQOCC7oAo`V&eoRlaAd{;;+#
zbp5<3G<A00m!Ho(eNIxce1Us@KyGww{q`#U^PSIOFyxC8k}bw&C4d?~Oz9ZE_`bqA
zEm85^$W9%Ei!3021p0aNx6yLuY1qw)=V9u{SP9rFgB6hr{%>LHWi+AH>n5<oAIkA#
z^Aw-hD*b_ztElfUNxrTyrx@4ni}LcLnSqKh;byZ6BU?#|G8ZDbafJ~Ga+R!F(F~8S
z+M@_LbpNaJ--%JN3EV@Z;C1Jp_Q{C4JAJmK%T(=G4XES*!ph#W?dbP{^d%53_JaQ2
ze4^OTO10_$6zhDQ;$K;{_ES$zL(dY;{yM&|@3wy;1Ic}Mo5n6fRyk8T_>bL_8=5%d
z5Z56l^-Gqqa7w0e0$WCf{$3&~+Bg^+6Im49_miqW;A#o~Ki6_XH&adr?Q{}Fm?C!_
zFZCOZcMg7V@6M7F5ZY&ogJY&E@tpcNiaFC2Mi<ZhLg)>sX6&!4-(IXu`MV<4QvB|D
zrH2PqzWU}SPCcQ(q?Gh6h2mz|b;>6MVoGd_=x1j~QgB}!>(H3GHb0Rpx7g2J%lTb`
zKYkb5Ebx*WUcT|IC^kQ^e#^Bz=P$+Bk@G2{Ij3Z=&6+GqZ#ZIr=(nO_-X_#Z`R(T*
z-tx5zbEmPJU23NF7e%8Fje=*7x9@v)il6dQrn1%+>Xlo)li7c{J<)e(8dF$F!u!sM
zi+^zI6iajPbg}TQtp{w^TfgXEYC~k+tan~FDm`0TjUg_5dW9S@-}^2NRXgf?&&C!Q
zoF3_SQbo2!eVg=&al16!#xL)yf|2@?tsxcYxzP{iDckC~dV|P5oVjo;PIr19aEBT$
z#izG7kG$MP1KM&u-xh7;X&cq89NTv&sglK3UlF{_8~G`=C>{YQ;-UTmaRYI_ruLx@
zuK{b^i8Y*W&0G{-OYW@%uZcg4KP)RP1!oGJB@}vnq!zDk*-DH0@JVNV8`c~Yg~$TY
zIgZsz%evJ_D)Oc$*>M=6D7}NFlY+)s$tFNOF?0u~`m8%X*O^b9ny00P%f~lGF2l=8
z)gRYp+qNX4{qI0dp<_RTF|&2Qi2Zs%Dsic088E;XMccwAqtnOA@?%Zb{Q`K?%TE=T
zpe&<?eO<9n>t#PyZFxGKVU!jc$6nnI;dZa??1FG*Hd-x}5@-hA30fbezN8OX_vcMd
z@Zn<&(fTkN%3NI)`jZ78ZcXsAUdyiO^xHdj3|Ygqy8NsvYVl%g%-SrUr?2*OKS<Z2
zbo3qrn`AfN?0!FJRYBuTsI8egyvnB0tF`&H-$b5Pq?VQ^{jK9UVehW>p6f+J!yDgo
zL5><5)p=P$C9d4mDs49Q-v&Dfi<m-I{+%Pk2QR!M(v$N}dt%_F1%BR=@0?ii6N<A)
z2M*cC)+dzjnd=pw(qiHob^UClTeJ*@oG`yg$sNl$&hx)+lm0+>-mu@41$kFx{VhdV
zE<905=s@R_QBI>~1(U38x*$^h!S_vA#CK|^+g5Mx557ChLG>+7>#i#AhACgJH+)-Z
zv9f0eH5HV6MfT8QhB!w|06F!jSdx`+>`CP`oBOrkT8f1p(pc!?ort^GRUON!ku!tW
zvIW2ZXT#ZO{nRJ|fPyjBZ~ev@++Du9uk{|AD^<<wuutm(Z~|fE2!e=xvLk(>mn8b4
z-!9ka-WE778P(YArHZT15kP7_d;=KA;&k&N1$K9lQcJTY0(8>*Vw*=>EMjK_;Pmii
z-7k@S?<X*Msb_zdyuD}Cso<AxVc;HLwV(q_a=NSIeW!|(zCt+sUS}_?Kndr~lvXCa
zP9ln*Ph%<*7(uulOmw|^dFZ43Ei07AZ^(s*$@#4mQjURHRXE&zr0GOsNz5}4S9p@7
z7;i`!9yMlTU~VVNPYRp>oEvA8Iv<!XaoTR*Y}Rlb`%8(|lCW2~OX1RT_x}+-Xla%S
z>%G+S>}Y@go<Zsjs`ZjG!rXt@knu8oTABF0`qtiI>#h~iW=XE5*6l|fFW#@Je*VU#
zBw^PPxE&mP_i6H;)$*`x5(d*tt7pDD=|c|dD~1J_iQ9BVi>d!GmU?+i=cM6H>dO`^
z5~v|R9uPHx-Cq6#DfhKAVHt#^jhRJ_aWbA6qqT=}d}m<d4(xX}_xSNr=E3e2FU({%
z#oyjRvmO1kMz00|BBfP|EMjw?BglK-a56v?Z=<LzE2JqyBbqBpv`&1@cqwDn(ayIu
z^yoQNcTD3pGWTWfm4y-0>m*$N{l=j`gmVPQE<MPN#umG|NSj<0&8J-19BMIHY_-iy
z&h2#6hMd(1RpQt_J**52dF8H<5k=Y+WNb<vc?AI+i;C2Ypij-KbY2o}p}+BC=zA(&
zO__gVn1mO!@%8KRQ^{zfnbfAJlr>&s5l_v(`8%41oy`NsAtufzqJ)%5;Mbg4-|#(q
zPg{S->9B^M9>f`iye|3k0hu;$Ay;UBkrYS7O%3k`zk##A0D?6^<fN$qg;{Wcr!6T(
zQAbtr&g9QsKy@P}{a|ULmoMXK;<G6oHqE?{Pl%2`aI7O@@|g^6=U;YqVs%LTg4Y>2
z94f%&UI{c{+{CaJ{L1R157_7(AhJ3m3mda-HFq!YN_k2z#e`-sCtyYm{a{k%j^E_L
zYW&<qen}Y;u)l~jVxklP{X)6tJi7>49QqO+Q;JpvxXcg2x$mEme5wW`SJb>x-W;~-
zD)<RC{WbZ@U~w>bO2Aa^ri07$&kq9f_*>DqtwXf0Qm4pi!SXs{s4r2|Bk(EHkyqhw
zi$L&mo*D|;CC*Aj($+cZd_d|^V*jf!^cw(_Z~zMfnjP72cyVYJDmAg0>$}y9UuOKB
z=t8=k#=Z@i&<I{X{O4lekM5U`zSZl+*O{x}f|E5uK7<`PmxjSlRNiwT4waub&a46H
zvGZ#7+4YZhqF|ONg@D@Hj@dG9i~%(BhG!MZw>7q-{Z0YHd~$KBLndT==qK)mr7S5c
zvn+;@cgQ+>`*T{|f>1$L64oq)d!d0PogJEAkhThad@*S;Ay<?`4-<X*^5=nZj};jg
z17LOnQM*^C%YpC)2KWo%+ooqX%9o3*5*%_KzbgV**cJI;k^%)8ult5JJ@M7D_+w$C
z+?F5R`ixqFKH822kg)QRACirsXRmBd9|-ht*NBMCE_Wc`1381=7?EWZ%LL-Q-*qU!
zaIU7mQbB;&_;BG+>Wu<n-fnhNqS3;-ZJt_A95U%|-2DA$1l|RMVjr(5=~hc;<C<%<
z*!|`k_k$CTE*m4-%mYCLY=6vP2D9`5B+bBJ-$+#_Z@DR=kwVaZ5CH=?m}bL_NeJ2T
z)}7{Din*vhw^q(*@!^C#7WMm#pDhLOsQUhxGph+rsITl&$1yLsE`WeTopOzDeB-<!
zysJL;2qUt$eD7N)F;>Aa42DWfz*pjrZ6Y6sh6Up!b*$0X@H@E*`(sCe2aSk5P47)T
zTs;U+0aE5;lM|+^$w5{2NO|Y!&9ISxv$QHh;Ov#lImfk6!YPL$-{OYB54&c%N=J=`
zMp4OFBd=1QI;vUSg-WI+F{Lk-%qU2{fka6<;>`usli10e4@E@Qx-{39uH!ju)%v2{
zhCAcb{F(|?3>VMhO(^q<pmidi`~zyY^?WID<&&5r@5eUE0V50=QDXe?MO|2>3=Z8)
zV=44y+Qk5e`(=<T%V?1R!RMD-_2dfMEy{}M*X_%YYmBaNS1MU~>C%F=qsb1MPnS=1
z9wQ2>_qfVyYJKntbImQ|Etd&g2yCe~(#qAl2$x0EWjHlZXnRiSS!vSIOJ~`;wSTrr
ztDi0oq4PDPi;273SGvx&ACyn2oJf+iW8txoTvPcQz|l&>Ap(c>+p>>_sV=b#wX<^#
zr<2us$*f9Uc-y%|y0+P!i<fWsiMQy@;8_RIfNy`PZ$-~6L~8bj8}}?0cw8t<2f8zo
zl>*{i($0hrqKm_t9-WP`FApF1@OIn`wb>jcy$e^+c@qPP3Xt8K#q`p;0q2fvQl_+2
zqjMC|d726+l+-JRh_2Je%7!;!V>TYP677M4`Gx)5oRPnixzAD1-nO_B#w(*Hb)TtL
z^QhJeo6jT3LUvzXREA1GU$8vz6b5RpdCOMqdmB7i%rFpfw=PVz)8gS#p`h=n8K6m8
z**Pf-;Fs*lM@ww;NUK4@US}*V#tnn?3a}kU-vU;Ap;IoT2bG06Sknu_aVHoFbi`#G
zOa?f$JXtqm>7|BP+xm=FQ3^cXk{pyQD$GH}If@Fg3Lw*jjwNl#dFCsJmpTU)5rl<(
zk}Q)=JA9ZfSQhJv#$MI(Om?ebM^x4<r|nFAEfNHgn(l?({f5*jsH^a<CPEGKZZL87
zon?OTpLw05tby_(Cyf)qD?bNJAel-ODfS)FS29iiSH^9c2tHIuz`Oo&+*x|&xV%WR
z7gOc0+Y0GF&91qe`N5}->}cco?0%yiS|>ijRPT^qj85JEIlt-k<{AJ~khL!gA5bJr
zV4cy*1Wh;&UK|?X#(#;JhdT~<Z4mVve2~^n=3H(9bEW?bC4(rCVdF(TMdB0zq#u!r
zBS|bMqBQ-)ft~8)2Lu!7$;#@a>&=)WheYx)^`FHs^#!JGS4LLxh5ZdGFs96?Uz}1W
zsslZJMWlMqo43CxSff;&!)a-d*~;l`Nv2IbXx}AhA9HP+5aL*&J6mrRtfPia%k^#~
zaScqpn^>q*%UtZv4ka*|8q-X9AbCed%f%*fn!C|YtcPMJi9%nwN+t`>$obqb;7qB?
z5pG}C6A-9ckUaI{eJ19Y5XIM2%Z)o(`qW%@a|Gb0+YQ=Om_P&Rr!&QhSrlSDzVIxF
zBMS&5%R}_WtQ!4`Y?`QZdJk}(fhHlBnpYJ!eCZKafUjxLZqQRKG1Sjq&%il`3LNeX
zy?X+45o>s(lJwpZ&s{AQZV~OjNZ+Ee6Wm2(hUI%jQKZl+5ZegQ5H`OYy4)a842mG*
zK0<_*8&P>VQUDF*j`|4nog+EZy1htVm^M=lmgaIvszjS-F5c&h7H;4Y&<<&q;~Ye7
zZ~8zCc3db&WCqcj9=5M7%XI}W*LlEnU1#6yL`7TC26`1&p-MyHbZtc{+gH7QU-Jy!
z@n3}z@-{^k=YJGCvCrAqC8_59jY;xG*%Op&vpk0p*od`r`c6BSzz1Njx+;bGI+`HF
zccPAx$uT9IK197`ZZ?m#q&fIWt{#=lBBE|(m$z(e#<b}Zfl1FNPEvN^y$8!)EUl+-
zV1S5fCxn<iR#MiWT8l3AsB#w`=UE^V8Lonnhsst5US~V=xsPS?)m;swVl<H3+++Ky
z=Nz3q;fR~79xI$!s-%{=a4^jHkbxWf`|Wdg=G4?xrz?1P@`n$1GJfoFB=j*r2c7gy
zOFph<xkv&ZuYoc^B<M;ZrvQHvsgH&wRtn71B^Aq36~HeKpK~4ZaOjek8A{+`+T*Cg
z{Iv@FYW2cW-9A2Dj8qPwKFge}5|OCzr*E5bt3v?&QCMVQ@DJ1?yrPH*m7oXSjf+b~
zo&aJ?(rc-BF2Wu(Sl^2#sKk^cSTTu?KttB^D1%$Ek!Q%ivk-uQ7)Eht;&7bb?j&kc
zkaq8l4E`)J>ZM|Whe&{lE*N`zC3e4+P)A`7Fn0sV=!3?v(p+#afOlKFZ<I^HLY8nl
z-}9JE086G!z~?KX0~V?Pi^SXB=m~o|Cqb1xGqFf`NM?Lb83-i|*L0hR1%o=O)P$D<
zln@~^&kM-Wp-9-2GHa$$@9YIeDY?QUp~MKr@!nSDFxl(L+P0A~>d0$VL-7kBzeKyx
z(Paj>tU!e>ghWGQiOQPqF>T357n3U|144!{z!EXgTXCn49BVvRTw)A?S=6<G9*~Pb
zJMn}Hui|RD^_DYQg2!XxfWoQ~rs1;Mte74u#aq_ff{y8^#xXCIr7*Ye_zz$v(y!C6
zDWf#Z#J0Huy({!I1WM|ikEhj*k<!gLKv3nTsCR>xUQS~rkeb)w3Va|C#s*WkQUyU#
zofm6Blqd>ICvKJbOIK_7`fxyQBK!&YqUQ#XHyTcvq%!jo?l=jG%9M0*4ArB2@fo+I
zk)SG!gqQN2*%!c;h!UqNYH%_K-eRXQA)kaIkrZp840-~-IM^{2%k!O&YQe8Vp$(bV
z)?~$@-hl*S1wCq;4W7oPEHx#<RVjr4@jJel`z}4d#jdNTHoqV0U12T5i9E;CF?*n%
z!s2F5_r0Z=^YCCY1Swe@PAz8`wJ4fsceL!x0NeM1TV$9l8O;|t?HRkyaP7Ao`CI(H
z^e<-JTWh_C%5WC6M@82Bk%0!;Q}l(b7^lj>Fo5vOaX9*0!RE)74%fr3T@zOeY+C#?
z&!+<fV|kXFm%eT<?(v`lTNLS5FuQw+ZxBBf`Fp|hvRHTF%nUn3s(C<cl$kRBC5W}U
zd}sq()XpNc^A&0lfRTZLK8U8dD<iP0UPK(WvCR2m-8|AwoA&3bN{)@1;F;}@=bPtm
z%k{@L)zV+xuQNqkP(QeiVqJX^&5u)3u-b4_0H(XZp0miG9)7h=ISkS(&j7=ai}1R|
z$00CE+l^i4q1>CaYz7-%Y*2h#fA`6oG`H_X^r(Jw?3mdF`!f9Xt2L@=e}`{ca+=>~
zV^&VtogZ4GA|Df;(ukEG7ir*DJG9{;OjZZmwJYHYqfED9MfmNflag|yy^uG3R`)tQ
z^e0KJ)!91{DpJEu7-vi9;uMTvKBs9dqARROLM~Q<CtM$VyZN8Li;PjT^*~YTau_$q
z??TDYgDFTZKPfRXXry*!^5AI=WURwr6s;)E6?u{8vR|JbjGk93cm+bFagEu#IJHMj
z-=R_^cwR~pmhv%YkOitq|6rh{4wlCB)tkwy-4wqO!l69=TI$+xG55ohq)mtW()0zt
z2M~>nLxVkH9J%7_%=Y#r&z$}Ki}^WEL%KoKUxl9HkAzIMGo`TBqZR4lqmt)5X~(?k
z_I^SnNvmgtvFqcI*tdSRz6S|cfHx;JnkMh(?lT^!j(*&6KIf4#n@1H&;6ZIqpU<1F
zSmbK`it*l5Zu}+$)()3=gYakdVk2p;)rvKeJl@enmsTAH^5)#<3xX1*6i*Rs0Lu6M
zlL0fiiyK*OMt%<%D$?kiWwF~auY(vKI(O@AJ0pnJ(hYPbtmO>or)R>}6!pfzd@>B{
zZD}0za5WPKj70Uoa7ymqUMb^)3YMLT7;O!92C`KN<xF7#zgk3CC@B+3gbsOLwy94J
z;vcsjO}%(LcTLz6JdmCv1UCyg+z&FO)F?f0wJj3-y!7B0M7*B23)HhhWmQST$=7$%
zLDye0G5w=8FPtT1k+*QYm|&k8wew9scGA!lb+SS4+m{WigJZwdwQp`vE~Dc*;HlQ|
z29|ZW<7TQFvAoFaLfG@?D4hc>aBn`wt03RgFBei00|7_Gk?hR@T3veE;*#l-=pIXh
zfw)|<OoYAPVJqdiPv4*1k1>9vCWk>Lalo?co+6tkhV2V;%PqC)91SZu#t|eI$ZQ2P
zev`4@iMB-1$WHvM-({N9lc(x0@AWM>%UG7JG#F)XOt7eqSUt_&y`KwX_+xapN89xf
zI~0Q*t-w5v1I9dBwB@EdM}4Eyy4*V1--?#S1FswsF%u6`nn#}N4@is&z_oO`wSs=C
zQi>zC5{Gs%9A-3>xFs+g;62Iu_L0!B*XvA&>pAF0#hxS~#}pHc?tNmVrBu2;yPulw
zJ{2e45PYnR@EgvpAt#bXDctsq)Pb;tNx6OmiWS&oOplxW+%DK6Y}EPKrh75He)ty5
z-{wAWzTv^J^jWF?V38#{7?*?1jvHWL?&QQu8iQy^v>vO!k`$}P3^XrHp4GsyBMaQ`
z-56u3CQR0X{rx9!(=;dbWat5M$O}S-K_PRfRTHl?Ol*5Iv}w@cx{qW(KS>q(5FPlK
z$8`klDV4gB$U4`{Ps<Ymr>SMaLz}e&Kg|kOnk_U0<6LX!q}@tz|6NhNYdl(a?mKy2
zZ?Zcf*Wm22><Ms#L+S`{M5_Gzh$l@dGZOMm<i^=FCK*ULpLDNKRluq&#O<jkP-Py?
znD88|Awo=sx_t^FN_6B@dL-sAZNV4WH_-05;i6y3s8T$Q%n8z1_*xXRk=;mV)hpi{
zt2_5SYKY!0%g`tvw3fzfF0(&5NauLm=^B4`l<Z7AwLXX=K_8=Gx0PTeW9DGAYo4#|
z5DxJqoKx$l#KCn)Nl|8a^v51QjOroH(CQ;*MsA*qc+ZW7ic-oP&Qk&!;Kb;-#u`h?
zKqyITeP)?SMYpUWLm2kD1cK0yGn(2e@EtcY3`D&qLytNyKW^jwp!^}^bQaasZhNjC
zJ}xqg3%8;c@_n><Rqjh@vBwtoRZ)3Ea|%1P`8X;zryG#?T3(yGpfKoh>wqSk9@CeI
z60-9poX3HbL69L|$9{CLUVa|64;iBM!ZI$SdmCebP@d3)4Cv3UVYV5<J(^glO4`Zl
zpt(BK&LxvKcM(UVt+nM%`2r<4zw}ZwU>tym_@k4}P+>rVg@-|WF`O(W{?TaB^RY{e
z<mFk{uR@H|ELSc^(x$^UYfO>7{Pc%OMAj5ybby){$l2ica6TODi5XdE!6Sl*)V0^x
za9~%BMB}F2Di61wA_M-&Rnz;BKW;~=%0$JSvK2ba8$<c2e+0PTIv>IRpdsJwn+TCJ
zl6iflfefW-1C;JF;c1vlk%~q_9H4t_%pJZ-If1qhEM>dW`ymTdy+4Cb^*oRBSuUIx
z?!NoF*}nU_YO$8}X}IF{TLxj>HG@#qHO8B&FoRC2yxt>eI+E<I(yTyy%86pD<y8l#
zFd#%r7$reY135P)FN?(u?ihEANiL$*Los?~l8eR-mo5^w4m2=faofiYDYQ=MMvZ?{
zrkELSY8CP()3ee>ILum1#7P@L5%^SUrtumZq;}$nbffO$t<E16Yti@#h^{&Ro+`_}
zSy8l=?B`NTzPHtJ_fnF{X5iMyec&%$|C6DJ`F(rtwVTX+fpCkfMku`EdHC~LV7>?O
zA$upvFY8}*=eoMtkwq?1fUjtJ9|sYrJKZx?7-U*dex)u*S%#YT9AibYo{uQRD~_dd
z=YU6g2^33iu@8eg!4x?HBPoYwIXo+9Nd%%Oc;d%MfY%Ddh`i_w`4Bb6Otrp?K8PgM
zLRgMd-0S`fE+<pEvHF_JeiP4|_Q6opx8JOwKl_;6q9e2;6g}w+8EupB|A4HAeh$_O
zeMB+wzL-Do|J}OmDEfR~{X~Vfc)EH&_a+NMK6N=&K~QHh$0X-b`X_it@xWqrPk=`#
ztD^%Da8))-Rlr0Ypu2)v7GUghD>DH`e;<;g{uZX-=_w?PqNN}n_+tbpFP(_}cVXBW
zpHLT&3`aNI37!NFHm{Hqhllfe@Dc(S(mr5|=%Ml_3Zu=V_U6nl*f7RP?M&#FJd?8c
zNc-^iRH5<~=7QYOEIiR}3QJ7<WiY=|I>q`*q^kFu>QV>i9Gy?9fPL1X5=mbG(byK+
zkcybt>o-I*=NPM<P3)6xr|jIp?GBvLv5zt7X619v4IZYbaw12o<&LNG9hEOb2ZF6E
z%?ZDP`DgSFFzCBw9h`oZrVy`fc0|Xy5#|MXeHGweivA(E)N<uvGcy$G*DN-QMUQ5S
zpKW!jqa4G<6^6HC_})pfh775!zq{jha_xgM@dS$P3GGLs0H0VH0{>oif`H<fN8rz&
z`SCrdXkr0a-}#vaP+J3rO6#Z-hCR(J3c<22%I|f>G)OT3TNeqxt3+|ooORe_*cYAs
z-weuML<OG5*=!Gj22(J4W)$<AqoZHUVQwr=C%lgS<*z<m-1&UmVMJYOC^Yw{C#yKq
z`F=s@Qx3u892?>$(4wm6^GB|5IDUZ(pVS1pb3dn<W;0R%B2He`x5oqdO^36+snebg
z<&i($3*^vd^*!YbIR|G3{GH#XH1dAZo&ydcNod=3ml;D5%wm1X@&(Q>oRX)|Vq~s>
z_b&|Uors~rv8+X_T0iAZxUSXUaSU3`=x5kmiGYfN%|GfHD#|?4f-<4BvBUaJ*T^I|
zk~_HvB0a*%TZ`!1>d}<vrismJgcsGI-$XwY%xW=h#AEQVF0%q1hfP%ISa$e59xvpK
zd>!uFwYt<m+b7w##lO_STevjBw2AHbt2K1Y&=neVbe#OkeEpMnP}_1irn<5{yJS;5
zMA3MMLGX~+W%4xnS#4I&aYJ!EG4v0xm#xI7NEjUoeTeq?pp44=BZiz%OLDn{9Mc(^
zZ%GuZT3EOpG7MX+aSNn@yB=e{cKJh~#G0%BccZ~3|4BOp?V(sOgeAPn_)PJA`>sz?
zufRzntC3rOZ#cza%JSeNtJgN2=8yBH-+{7W*QNV_U4)L{xcSMa5D4_S{$}+acG9>U
zs^({o!}Ap%<1;1twpO&y;u{s+PE8q&P*o|^79?y9XVigsDrfue{Jy(};!(%`J8JT9
z&xDwsS0Qw#*eV#LE<)9Kx!y_fq6*R*Wb;6zA$6KsLr~W*-2!h_Scv1eZN3N&Eu>UJ
zYST%mmp83nwIH8M!ako(s>COka<Wofd8+_PI;sv~n;3%es0$ZnAfFu$Kmtrs3gLbZ
z&ZJjm;6}PFxjs$r(sxEiT1VuRJsimPClU|ZLl*`|n2sRx{6meXhwS_SA(8XLR5`!B
zQ-)A^ml}5~#Gra>5|-6mi~X))_w6<dI}4FaUYU&KxTFJ>{LU|>I276U`1FC4>MV($
zv|mlER$t%@S<B_QQ`haL#@aQSqQ%cxIk6{W9Rfu|Xq?JI?|#xi9Ent={i$wp<xOvy
zGsB@=1n5CVGPE*ttF4}BHiaH}Ab}b&O-&Q@<7AAcBc##&FiL;pk0injAeUh>?sB3H
z^bk#vmAG(~BY71%z*}z=s8ik@IDJ}7uCt=bZ=^(a2kWhSpfgtTx`g!Q!l1}T=O-QX
zJOw+~dx8&vF+t(w_L1!Lyo>uc!YH0h<b4l<ME!>~eUegwZ+MXOv9?|lqa|$6<f*&x
zD6z)aP^&<eZyMrA<Y?XrmDtXZPb|@ZU%i)6!a27~LK9rN=uxor^&~I(l8|m{{6*{I
z-nNRn<u?pvRFR;zIxE<G=wbQS4Y9cNJ5X{tx@V<MB&%>N<_ZCHyUd1_IYvB~)59B`
z5ir6?P>udw`JD-Vky|5cix&KL)Ak!4z?oCZ9ufGXdv;U6^vL=Z1%-N9Ml*W9C82Iv
z_MgKR>5jeb@PI{EuvR_nWHXM}RE+{P8Si$>#<Y=lSb<k}ty~RU-&4S>_DhH^yY#)B
zdk3ZnmL<L<;TZi~L`?KTLn%2jl2#nayBZpK&K;}^-mCWet{K+fz<F>K<7YwaB+j?l
z8OXK0ms^H*M_Hp2SFzChR2r14S4MI+qAfUi=@SHD)A|p+1Zet|<60QI2QNhWJ|jPn
zkmK6_oylyHj5WKv#T6>stEscDYd0o|lpQ-4ODva)u=(Bg7aww?n*ycv+Ylv?t<m8e
z16xQv$nH!IC@17oVHy~n8fsoR^vOq1tN0hg=pjD+TQ*z_9J?tw2+Ir8m^kDfm?$mF
z;ke7*Z63|A$hFPkj?Q32%*t+nrp*w-V!x8FDKV)QN9RN^mD44MxduoYLyhgyi_In}
zM@nEQLPs4HWZ)!*tb>z)W+-Y@!&{g^!M&HCzaClT)`tv8)oqnJv?p+gT!88^tmcPo
za^WL55xh}-f*Zfx$k_3Pr2A#Rs*r><Itg9gJtJ`{d@kzMM!5ZR3QFOfs!SEwIOu-?
DUUafS

literal 0
HcmV?d00001

diff --git a/app/assets/images/pages/about/pavel_small.png b/app/assets/images/pages/about/pavel_small.png
new file mode 100644
index 0000000000000000000000000000000000000000..336e3e6e63ac1ea911a2ea46e5f789389889e077
GIT binary patch
literal 10492
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%0Aku>ZE6kMd5s$4N)y4$EHTLe
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

literal 0
HcmV?d00001

diff --git a/app/lib/surface/SingularSprite.coffee b/app/lib/surface/SingularSprite.coffee
index 86a79586a..2350fcda5 100644
--- a/app/lib/surface/SingularSprite.coffee
+++ b/app/lib/surface/SingularSprite.coffee
@@ -1,6 +1,6 @@
 SpriteBuilder = require 'lib/sprites/SpriteBuilder'
 
-floors = ['Dungeon Floor', 'Indoor Floor', 'Grass', 'Grass01', 'Grass02', 'Grass03', 'Grass04', 'Grass05', 'Goal Trigger', 'Obstacle', 'Sand 01', 'Sand 02', 'Sand 03', 'Sand 04', 'Sand 05', 'Sand 06', 'Talus 1', 'Talus 2', 'Talus 3', 'Talus 4', 'Talus 5', 'Talus 6', 'Firn 1', 'Firn 2', 'Firn 3', 'Firn 4', 'Firn 5', 'Firn 6']
+floors = ['Dungeon Floor', 'Indoor Floor', 'Grass', 'Grass01', 'Grass02', 'Grass03', 'Grass04', 'Grass05', 'Goal Trigger', 'Obstacle', 'Sand 01', 'Sand 02', 'Sand 03', 'Sand 04', 'Sand 05', 'Sand 06', 'Talus 1', 'Talus 2', 'Talus 3', 'Talus 4', 'Talus 5', 'Talus 6', 'Firn 1', 'Firn 2', 'Firn 3', 'Firn 4', 'Firn 5', 'Firn 6', 'Ice Rink 1', 'Ice Rink 2', 'Ice Rink 3']
 
 module.exports = class SingularSprite extends createjs.Sprite
   childMovieClips: null
diff --git a/app/templates/about.jade b/app/templates/about.jade
index cd217b502..8fbf2577f 100644
--- a/app/templates/about.jade
+++ b/app/templates/about.jade
@@ -92,9 +92,11 @@ block content
 
         li.row
 
-          img(src="/images/pages/about/george_small.png").img-thumbnail
+          a(href="http://www.georgesaines.com/")
+            img(src="/images/pages/about/george_small.png").img-thumbnail
           .team_bio
-            h4.team_name George Saines
+            h4.team_name
+              a(href="http://www.georgesaines.com/") George Saines
             p(data-i18n="about.george_title")
               | Cofounder
             p(data-i18n="about.george_blurb")
@@ -143,7 +145,7 @@ block content
               | Floor Is Lava
     
           a(href="https://soundcloud.com/taking-off")
-            img(src="/images/pages/about/placeholder.png").img-thumbnail
+            img(src="/images/pages/about/jose_small.png").img-thumbnail
           .team_bio
             h4.team_name
               a(href="https://soundcloud.com/taking-off") Jose Antonini
@@ -155,7 +157,7 @@ block content
         li.row
     
           a(href="http://retrostylegames.com/")
-            img(src="/images/pages/about/placeholder.png").img-thumbnail
+            img(src="/images/pages/about/pavel_small.png").img-thumbnail
           .team_bio
             h4.team_name
               a(href="http://retrostylegames.com/") Pavel Konstantinov
@@ -165,7 +167,7 @@ block content
               | RetroStyle Games
 
           a(href="http://retrostylegames.com/")
-            img(src="/images/pages/about/placeholder.png").img-thumbnail
+            img(src="/images/pages/about/oleg_small.png").img-thumbnail
           .team_bio
             h4.team_name
               a(href="http://retrostylegames.com/") Oleg Ulyanickiy
diff --git a/app/views/editor/thang/ThangTypeEditView.coffee b/app/views/editor/thang/ThangTypeEditView.coffee
index df722f079..b79d3ff9a 100644
--- a/app/views/editor/thang/ThangTypeEditView.coffee
+++ b/app/views/editor/thang/ThangTypeEditView.coffee
@@ -70,6 +70,7 @@ defaultTasks =
     'Add other Components like Shoots or Casts if needed.'
     'Configure other Components, like Moves, Attackable, Attacks, etc.'
     'Override the HasAPI type if it will not be correctly inferred.'
+    'Add to Existence System power table.'
   ]
   Hero: commonTasks.concat animatedThangTypeTasks.concat purchasableTasks.concat [
     'Set the hero class.'
diff --git a/app/views/play/menu/InventoryModal.coffee b/app/views/play/menu/InventoryModal.coffee
index ed4f5a155..324412723 100644
--- a/app/views/play/menu/InventoryModal.coffee
+++ b/app/views/play/menu/InventoryModal.coffee
@@ -616,7 +616,7 @@ module.exports = class InventoryModal extends ModalView
     for slot, original of equipment
       item = _.find @items.models, (item) -> item.get('original') is original
       continue unless dollImages = item?.get('dollImages')
-      didAdd = @addDollImage slot, dollImages, heroClass, gender
+      didAdd = @addDollImage slot, dollImages, heroClass, gender, item
       slotsWithImages.push slot if didAdd if item.get('original') isnt '54ea39342b7506e891ca70f2'  # Circlet of the Magi needs hair under it
     @$el.find('#hero-image-hair').toggle not ('head' in slotsWithImages)
     @$el.find('#hero-image-thumb').toggle not ('gloves' in slotsWithImages)
@@ -626,7 +626,7 @@ module.exports = class InventoryModal extends ModalView
   removeDollImages: ->
     @$el.find('.doll-image').remove()
 
-  addDollImage: (slot, dollImages, heroClass, gender) ->
+  addDollImage: (slot, dollImages, heroClass, gender, item) ->
     heroClass = @selectedHero?.get('heroClass') ? 'Warrior'
     gender = if @selectedHero?.get('slug') in heroGenders.male then 'male' else 'female'
     didAdd = false
@@ -637,6 +637,9 @@ module.exports = class InventoryModal extends ModalView
         imageKeys = ["#{gender}", "#{gender}Thumb"]
     else if heroClass is 'Wizard' and slot is 'torso'
       imageKeys = [gender, "#{gender}Back"]
+    else if heroClass is 'Ranger' and slot is 'head' and item.get('original') in ['5441c2be4e9aeb727cc97105', '5441c3144e9aeb727cc97111']
+      # All-class headgear like faux fur hat, viking helmet is abusing ranger glove slot
+      imageKeys = ["#{gender}Ranger"]
     else
       imageKeys = [gender]
     for imageKey in imageKeys

From 5c240d89cd79eb3069bfc227009083355e9b0945 Mon Sep 17 00:00:00 2001
From: Matt Lott <mattlott@live.com>
Date: Wed, 17 Jun 2015 16:31:40 -0700
Subject: [PATCH 16/18] Cancel recipient subscriptions immediately

---
 server/payments/subscription_handler.coffee   | 53 ++++++++++++++-----
 server/routes/stripe.coffee                   |  4 ++
 .../functional/subscription.spec.coffee       | 45 +++++++---------
 3 files changed, 62 insertions(+), 40 deletions(-)

diff --git a/server/payments/subscription_handler.coffee b/server/payments/subscription_handler.coffee
index 5cd7e300b..f2a3b34b0 100644
--- a/server/payments/subscription_handler.coffee
+++ b/server/payments/subscription_handler.coffee
@@ -582,18 +582,26 @@ class SubscriptionHandler extends Handler
     email = req.body.stripe.unsubscribeEmail.trim().toLowerCase()
     return done({res: 'Database error.', code: 500}) if _.isEmpty(email)
 
+    deleteUserStripeProp = (user, propName) ->
+      stripeInfo = _.cloneDeep(user.get('stripe') ? {})
+      delete stripeInfo[propName]
+      if _.isEmpty stripeInfo
+        user.set 'stripe', undefined
+      else
+        user.set 'stripe', stripeInfo
+
     User.findOne {emailLower: email}, (err, recipient) =>
       if err
         @logSubscriptionError(user, "User lookup error. " + err)
         return done({res: 'Database error.', code: 500})
       unless recipient
-        @logSubscriptionError(user, "Recipient #{req.body.stripe.recipient} not found. " + err)
+        @logSubscriptionError(user, "Recipient #{email} not found.")
         return done({res: 'Database error.', code: 500})
 
       # Check recipient is currently sponsored
       stripeRecipient = recipient.get 'stripe' ? {}
       if stripeRecipient?.sponsorID isnt user.id
-        @logSubscriptionError(user, "Recipient #{req.body.stripe.recipient} not found. " + err)
+        @logSubscriptionError(user, "Recipient #{req.body.stripe.recipient} not found. ")
         return done({res: 'Can only unsubscribe sponsored subscriptions.', code: 403})
 
       # Find recipient subscription
@@ -603,22 +611,41 @@ class SubscriptionHandler extends Handler
           sponsoredEntry = sponsored
           break
       unless sponsoredEntry?
-        @logSubscriptionError(user, 'Unable to find sponsored subscription. ' + err)
+        @logSubscriptionError(user, 'Unable to find recipient subscription. ')
         return done({res: 'Database error.', code: 500})
 
-      # Cancel Stripe subscription
-      stripe.customers.cancelSubscription stripeInfo.customerID, sponsoredEntry.subscriptionID, { at_period_end: true }, (err) =>
-        if err or not recipient
-          @logSubscriptionError(user, "Stripe cancel sponsored subscription failed. " + err)
+      # Update recipient user
+      deleteUserStripeProp(recipient, 'sponsorID')
+      recipient.save (err) =>
+        if err
+          @logSubscriptionError(user, 'Recipient user save unsubscribe error. ' + err)
           return done({res: 'Database error.', code: 500})
 
-        delete stripeInfo.unsubscribeEmail
-        user.set('stripe', stripeInfo)
-        req.body.stripe = stripeInfo
-        user.save (err) =>
+        # Cancel Stripe subscription
+        stripe.customers.cancelSubscription stripeInfo.customerID, sponsoredEntry.subscriptionID, (err) =>
           if err
-            @logSubscriptionError(user, 'User save unsubscribe error. ' + err)
+            @logSubscriptionError(user, "Stripe cancel sponsored subscription failed. " + err)
             return done({res: 'Database error.', code: 500})
-          done()
+
+          # Update sponsor user
+          _.remove(stripeInfo.recipients, (s) -> s.userID is recipient.id)
+          delete stripeInfo.unsubscribeEmail
+          user.set('stripe', stripeInfo)
+          req.body.stripe = stripeInfo
+          user.save (err) =>
+            if err
+              @logSubscriptionError(user, 'Sponsor user save unsubscribe error. ' + err)
+              return done({res: 'Database error.', code: 500})
+
+            return done() unless stripeInfo.sponsorSubscriptionID?
+
+            # Update sponsored subscription quantity
+            options =
+              quantity: getSponsoredSubsAmount(subscriptions.basic.amount, stripeInfo.recipients.length, stripeInfo.subscriptionID?)
+            stripe.customers.updateSubscription stripeInfo.customerID, stripeInfo.sponsorSubscriptionID, options, (err, subscription) =>
+              if err
+                logStripeWebhookError(err)
+                return res.send(500, '')
+              done()
 
 module.exports = new SubscriptionHandler()
diff --git a/server/routes/stripe.coffee b/server/routes/stripe.coffee
index 0ef5abb96..0e46de9c6 100644
--- a/server/routes/stripe.coffee
+++ b/server/routes/stripe.coffee
@@ -157,6 +157,10 @@ module.exports.setup = (app) ->
         unless recipient
           logStripeWebhookError("Recipient not found #{subscription.metadata.id}")
           return res.send(500, '')
+
+        # Recipient cancellations are immediate, no work to perform if recipient's sponsorID is already gone
+        return res.send(200, '') unless recipient.get('stripe')?.sponsorID?
+
         User.findById recipient.get('stripe').sponsorID, (err, sponsor) =>
           if err
             logStripeWebhookError(err)
diff --git a/test/server/functional/subscription.spec.coffee b/test/server/functional/subscription.spec.coffee
index 9d9384800..bbf3815bd 100644
--- a/test/server/functional/subscription.spec.coffee
+++ b/test/server/functional/subscription.spec.coffee
@@ -259,6 +259,8 @@ describe 'Subscriptions', ->
     # console.log 'verifyNotSponsoring', sponsorID, recipientID
     User.findById sponsorID, (err, sponsor) ->
       expect(err).toBeNull()
+      expect(sponsor).not.toBeNull()
+      return done() unless sponsor
       stripeInfo = sponsor.get('stripe')
       return done() unless stripeInfo?.customerID?
       checkSubscriptions = (starting_after, done) ->
@@ -282,6 +284,7 @@ describe 'Subscriptions', ->
     User.findById sponsorUserID, (err, user) ->
       expect(err).toBeNull()
       expect(user).not.toBeNull()
+      return done() unless user
       sponsorStripe = user.get('stripe')
       sponsorCustomerID = sponsorStripe.customerID
       numSponsored = sponsorStripe.recipients?.length
@@ -443,7 +446,7 @@ describe 'Subscriptions', ->
           expect(err?).toEqual(false)
           done(updatedUser)
 
-  unsubscribeRecipient = (sponsor, recipient, immediately, done) ->
+  unsubscribeRecipient = (sponsor, recipient, done) ->
     # console.log 'unsubscribeRecipient', sponsor.id, recipient.id
     stripeInfo = sponsor.get('stripe')
     customerID = stripeInfo.customerID
@@ -467,20 +470,7 @@ describe 'Subscriptions', ->
       request.put {uri: userURL, json: requestBody, headers: headers }, (err, res, body) ->
         expect(err).toBeNull()
         expect(res.statusCode).toBe(200)
-
-        # Simulate subscription ending after cancellation
-        return done() unless immediately
-
-        # Simulate subscription cancelling at period end
-        stripe.customers.cancelSubscription customerID, subscriptionID, (err) ->
-          expect(err).toBeNull()
-
-          # Simulate customer.subscription.deleted webhook event
-          event = _.cloneDeep(customerSubscriptionDeletedSampleEvent)
-          event.data.object = subscription
-          request.post {uri: webhookURL, json: event}, (err, res, body) ->
-            expect(err).toBeNull()
-            done()
+        done()
 
   # Subscribe a bunch of recipients at once, used for bulk discount testing
   class SubbedRecipients
@@ -762,11 +752,11 @@ describe 'Subscriptions', ->
                       expect(err).toBeNull()
 
                       User.findById user1.id, (err, user1) ->
-                        unsubscribeRecipient user1, user2, true, ->
+                        unsubscribeRecipient user1, user2, ->
                           User.findById user1.id, (err, user1) ->
                             expect(err).toBeNull()
                             expect(user1.get('stripe').subscriptionID).toBeDefined()
-                            expect(user1.get('stripe').recipients).toBeUndefined()
+                            expect(_.isEmpty(user1.get('stripe').recipients)).toEqual(true)
                             expect(user1.isPremium()).toEqual(true)
                             User.findById user2.id, (err, user2) ->
                               verifyNotSponsoring user1.id, user2.id, ->
@@ -781,7 +771,7 @@ describe 'Subscriptions', ->
           loginNewUser (user1) ->
             subscribeRecipients user1, [user2], token, (updatedUser) ->
               User.findById user1.id, (err, user1) ->
-                unsubscribeRecipient user1, user2, true, ->
+                unsubscribeRecipient user1, user2, ->
                   verifyNotSponsoring user1.id, user2.id, ->
                     verifyNotRecipient user2.id, done
 
@@ -793,7 +783,7 @@ describe 'Subscriptions', ->
           loginNewUser (user1) ->
             subscribeRecipients user1, [user2], token, (updatedUser) ->
               User.findById user1.id, (err, user1) ->
-                unsubscribeRecipient user1, user2, false, ->
+                unsubscribeRecipient user1, user2, ->
                   subscribeRecipients user1, [user2], null, (updatedUser) ->
                     verifySponsorship user1.id, user2.id, done
 
@@ -846,7 +836,7 @@ describe 'Subscriptions', ->
                 expect(err).toBeNull()
                 subscribeRecipients user1, [user2], null, (updatedUser) ->
                   User.findById user1.id, (err, user1) ->
-                    unsubscribeRecipient user1, user2, true, ->
+                    unsubscribeRecipient user1, user2, ->
                       User.findById user1.id, (err, user1) ->
                         expect(err).toBeNull()
                         expect(user1.get('stripe').subscriptionID).toBeDefined()
@@ -1138,7 +1128,7 @@ describe 'Subscriptions', ->
                     User.findById user1.id, (err, user1) ->
 
                       # Unsubscribe recipient0
-                      unsubscribeRecipient user1, recipients.get(0), true, ->
+                      unsubscribeRecipient user1, recipients.get(0), ->
                         User.findById user1.id, (err, user1) ->
                           stripeInfo = user1.get('stripe')
                           expect(stripeInfo.recipients.length).toEqual(1)
@@ -1150,7 +1140,7 @@ describe 'Subscriptions', ->
                                 expect(subscription.quantity).toEqual(getSubscribedQuantity(1))
 
                                 # Unsubscribe recipient1
-                                unsubscribeRecipient user1, recipients.get(1), true, ->
+                                unsubscribeRecipient user1, recipients.get(1), ->
                                   User.findById user1.id, (err, user1) ->
                                     stripeInfo = user1.get('stripe')
                                     expect(stripeInfo.recipients.length).toEqual(0)
@@ -1186,7 +1176,7 @@ describe 'Subscriptions', ->
                       User.findById user1.id, (err, user1) ->
 
                         # Unsubscribe first recipient
-                        unsubscribeRecipient user1, recipients.get(0), true, ->
+                        unsubscribeRecipient user1, recipients.get(0), ->
                           User.findById user1.id, (err, user1) ->
                             stripeInfo = user1.get('stripe')
                             expect(stripeInfo.recipients.length).toEqual(recipientCount - 1)
@@ -1198,7 +1188,7 @@ describe 'Subscriptions', ->
                                   expect(subscription.quantity).toEqual(getSubscribedQuantity(recipientCount - 1))
 
                                   # Unsubscribe second recipient
-                                  unsubscribeRecipient user1, recipients.get(1), true, ->
+                                  unsubscribeRecipient user1, recipients.get(1), ->
                                     User.findById user1.id, (err, user1) ->
                                       stripeInfo = user1.get('stripe')
                                       expect(stripeInfo.recipients.length).toEqual(recipientCount - 2)
@@ -1218,7 +1208,7 @@ describe 'Subscriptions', ->
 
                                                   # Unsubscribe third recipient
                                                   verifySponsorship user1.id, recipients.get(2).id, ->
-                                                    unsubscribeRecipient user1, recipients.get(2), true, ->
+                                                    unsubscribeRecipient user1, recipients.get(2), ->
                                                       User.findById user1.id, (err, user1) ->
                                                         stripeInfo = user1.get('stripe')
                                                         expect(stripeInfo.recipients.length).toEqual(recipientCount - 3)
@@ -1252,8 +1242,9 @@ describe 'Subscriptions', ->
                   User.findById user1.id, (err, user1) ->
 
                     # Unsubscribe first recipient
-                    unsubscribeRecipient user1, recipients.get(0), true, ->
+                    unsubscribeRecipient user1, recipients.get(0), ->
                       User.findById user1.id, (err, user1) ->
+
                         stripeInfo = user1.get('stripe')
                         expect(stripeInfo.recipients.length).toEqual(recipientCount - 1)
                         verifyNotSponsoring user1.id, recipients.get(0).id, ->
@@ -1264,7 +1255,7 @@ describe 'Subscriptions', ->
                               expect(subscription.quantity).toEqual(getUnsubscribedQuantity(recipientCount - 1))
 
                               # Unsubscribe last recipient
-                              unsubscribeRecipient user1, recipients.get(recipientCount - 1), true, ->
+                              unsubscribeRecipient user1, recipients.get(recipientCount - 1), ->
                                 User.findById user1.id, (err, user1) ->
                                   stripeInfo = user1.get('stripe')
                                   expect(stripeInfo.recipients.length).toEqual(recipientCount - 2)

From 5fb8b18a31791e46af619f7675f1e14f01f0e10f Mon Sep 17 00:00:00 2001
From: Matt Lott <mattlott@live.com>
Date: Wed, 17 Jun 2015 16:35:12 -0700
Subject: [PATCH 17/18] :bug:Fix managed subs next payment UI

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

diff --git a/app/views/account/SubscriptionView.coffee b/app/views/account/SubscriptionView.coffee
index 317b4fc19..4fc341b45 100644
--- a/app/views/account/SubscriptionView.coffee
+++ b/app/views/account/SubscriptionView.coffee
@@ -306,7 +306,7 @@ class RecipientSubs
 
     options = { cache: false, url: "/db/user/#{me.id}/stripe" }
     options.success = (info) =>
-      @sponsorSub = info.subscription
+      @sponsorSub = info.sponsorSubscription
       if card = info.card
         @card = "#{card.brand}: x#{card.last4}"
       render()

From 6a4efa9a216ed5705f5ed5e51bbe9fc7e69e7e4f Mon Sep 17 00:00:00 2001
From: Nick Winter <livelily@gmail.com>
Date: Wed, 17 Jun 2015 18:17:07 -0700
Subject: [PATCH 18/18] Switching to Boom and Bust as first level of the
 forest.

---
 app/views/play/CampaignView.coffee | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/app/views/play/CampaignView.coffee b/app/views/play/CampaignView.coffee
index d2629223b..6c0199134 100644
--- a/app/views/play/CampaignView.coffee
+++ b/app/views/play/CampaignView.coffee
@@ -265,7 +265,6 @@ module.exports = class CampaignView extends RootView
     level.locked = false if @editorMode
     level.locked = false if @campaign?.get('name') is 'Auditions'
     level.locked = false if me.isInGodMode()
-    level.locked = false if level.slug is 'apocalypse'
     level.disabled = true if level.adminOnly and @levelStatusMap[level.slug] not in ['started', 'complete']
     level.disabled = false if me.isInGodMode()
     level.color = 'rgb(255, 80, 60)'
@@ -306,7 +305,7 @@ module.exports = class CampaignView extends RootView
           if nextLevel and not nextLevel.locked and not nextLevel.disabled and @levelStatusMap[nextLevel.slug] isnt 'complete' and nextLevel.slug not in dontPointTo and not nextLevel.replayable and (
             me.isPremium() or
             not nextLevel.requiresSubscription or
-            nextLevel.slug is 'apocalypse' or
+            (nextLevel.slug is 'boom-and-bust' and not @levelStatusMap['defense-of-plainswood']) or
             (nextLevel.slug is 'favorable-odds' and not @levelStatusMap['the-raised-sword'])
           )
             nextLevel.next = true
@@ -354,7 +353,7 @@ module.exports = class CampaignView extends RootView
       particleKey.push 'premium' if level.requiresSubscription
       particleKey.push 'gate' if level.slug in ['kithgard-gates', 'siege-of-stonehold', 'clash-of-clones', 'summits-gate']
       particleKey.push 'hero' if level.unlocksHero and not level.unlockedHero
-      particleKey.push 'item' if level.slug is 'apocalypse'  # TODO: generalize
+      #particleKey.push 'item' if level.slug is 'apocalypse'  # TODO: generalize
       continue if particleKey.length is 2  # Don't show basic levels
       continue unless level.hidden or _.intersection(particleKey, ['item', 'hero-ladder', 'replayable']).length
       @particleMan.addEmitter level.position.x / 100, level.position.y / 100, particleKey.join('-')