Merge branch 'master' into production

This commit is contained in:
Nick Winter 2015-01-22 12:27:21 -08:00
commit 867e180dbd
68 changed files with 869 additions and 275 deletions

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "български език", englishDescri
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -11,7 +11,7 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
for_beginners: "Per a principiants"
multiplayer: "Multijugador" # Not currently shown on home page
for_developers: "Per a Desenvolupadors" # Not currently shown on home page.
or_ipad: "O descarrega-la per iPad"
or_ipad: "O descarrèga'l per iPad"
nav:
play: "Nivells" # The top nav bar entry where players choose which levels to play
@ -42,10 +42,10 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
diplomat_suggestion:
title: "Ajuda a traduir CodeCombat!" # This shows up when a player switches to a non-English language using the language selector.
sub_heading: "Neccesitem les teves habilitats lingüístiques."
pitch_body: "Hem desembolupat CodeCombat en Anglès, peró tenim jugadors per tot el món. Molts d'ells volen jugar en Català, però no parlen anglès, per tant si pots parlar ambdós llengües, siusplau considereu iniciar sesió per a ser Diplomàtic i ajudar a traduir la web de CodeCombat i tots els seus nivell en Català."
pitch_body: "Hem desenvolupat CodeCombat en Anglès, peró tenim jugadors per tot el món. Molts d'ells volen jugar en Català, però no parlen anglès, per tant si pots parlar ambdós llengües, siusplau considereu iniciar sesió per a ser Diplomàtic i ajudar a traduir la web de CodeCombat i tots els seus nivell en Català."
missing_translations: "Fins que puguem traduir-ho tot en Català, veuràs en anglès quant sigui possible."
learn_more: "Apren més sobre seru un diplomàtic"
subscribe_as_diplomat: "Subscriute com a diplomàtic"
learn_more: "Aprèn més sobre seru un diplomàtic"
subscribe_as_diplomat: "Subscriu-te com a diplomàtic"
play:
play_as: "Jugar com" # Ladder page
@ -55,32 +55,32 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
items: "Objectes" # Tooltip on item shop button from /play
unlock: "Desbloquejar" # For purchasing items and heroes
confirm: "Confirmar"
owned: "En propietat" # For items you own
owned: "Adquirit" # For items you own
locked: "Bloquejat"
purchasable: "Comprable" # For a hero you unlocked but haven't purchased
available: "Disponible"
# skills_granted: "Skills Granted" # Property documentation details
skills_granted: "Habilitats Garantides" # Property documentation details
heroes: "Herois" # Tooltip on hero shop button from /play
achievements: "Triomfs" # Tooltip on achievement list button from /play
account: "Conta" # Tooltip on account button from /play
account: "Compte" # Tooltip on account button from /play
settings: "Configuració" # Tooltip on settings button from /play
next: "Següent" # Go from choose hero to choose inventory before playing a level
change_hero: "Canviar heroi" # Go back from choose inventory to choose hero
choose_inventory: "Equipar objectes"
buy_gems: "Compra Gemes"
buy_gems: "Comprar Gemes"
campaign_desert: "Campanya del desert"
campaign_forest: "Campanya del bosc"
# campaign_dungeon: "Dungeon Campaign"
subscription_required: "Subscripció requerida"
campaign_forest: "Campanya del Bosc"
campaign_dungeon: "Campanya de la Masmorra"
subscription_required: "Subscripció necessària"
free: "Gratuit"
subscribed: "Subscrit"
older_campaigns: "Campanyes antigues"
anonymous: "Jugador anònim"
level_difficulty: "Dificultat: "
campaign_beginner: "Campanya del principiant"
# awaiting_levels_adventurer_prefix: "We release five levels per week."
# awaiting_levels_adventurer: "Sign up as an Adventurer"
# awaiting_levels_adventurer_suffix: "to be the first to play new levels."
awaiting_levels_adventurer_prefix: "Fem cinc nivells per setmana"
awaiting_levels_adventurer: "Inicia sessió com aventurer"
awaiting_levels_adventurer_suffix: "sigues el primer en jugar els nous nivells"
# adjust_volume: "Adjust volume"
choose_your_level: "Escull el teu nivell" # The rest of this section is the old play view at /play-old and isn't very important.
adventurer_prefix: "Pots saltar a qualsevols dels nivells de més abaix, o discutir els nivells de més amunt."
@ -102,14 +102,14 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
log_in: "Iniciar Sessió"
logging_in: "Iniciant Sessió"
log_out: "Tancar Sessió"
# forgot_password: "Forgot your password?"
# authenticate_gplus: "Authenticate G+"
# load_profile: "Load G+ Profile"
forgot_password: "Contrasenya oblidada?"
authenticate_gplus: "Inicia amb G+"
load_profile: "Carrega un perfil de G+"
# load_email: "Load G+ Email"
finishing: "Acabant"
# sign_in_with_facebook: "Sign in with Facebook"
# sign_in_with_gplus: "Sign in with G+"
signup_switch: "Vols crear un compte?"
sign_in_with_facebook: "Inicia amb Facebook"
sign_in_with_gplus: "Inicia amb G+"
signup_switch: "Vols crear-te un compte?"
signup:
email_announcements: "Rebre anuncis via email"
@ -118,7 +118,7 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
log_in: "Iniciar sessió amb la teva contrasenya"
social_signup: "O, pots iniciar sesió desde Facebook o G+:"
required: "Neccesites iniciar sesió abans ."
login_switch: "Ja tens compte?"
login_switch: "Ja tens un compte?"
recover:
recover_account_title: "Recuperar Compte"
@ -127,7 +127,7 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
items:
primary: "Primari"
secondary: "Secondari"
secondary: "Secundari"
armor: "Armadura"
accessories: "Accessoris"
# misc: "Misc"
@ -317,6 +317,12 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Inventari"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
tip_brute_force: "V případě pochybností, použijte brute force. - Ken Thompson"
tip_extrapolation: "Jsou jenom dva druhy lidí: ti, kteří mohou extrapolovat z nekompletních dat..."
tip_superpower: "Kódování by se téměř dalo srovnávat se superschopnostmi."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Inventář"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription:
tip_brute_force: "Im Zweifelsfall, verwende rohe Gewalt. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Inventar"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
tip_brute_force: "Verwende im Zweifelsfall rohe Gewalt. - Ken Thompson"
tip_extrapolation: "Es gibt nur zwei Sorten Menschen, diejenigen die aus unvollständigen Informationen Schlüsse ziehen können, ..."
tip_superpower: "Programmieren ist das näheste zu einer Superkraft was wir haben."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Inventar"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@
tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
tip_superpower: "Coding is the closest thing we have to a superpower."
tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
tip_no_code: "No code is faster than no code."
tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
tip_reusable_software: "Before software can be reusable it first has to be usable."
tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
tip_brute_force: "Cuando tengas duda, usa la fuerza bruta. - Ken Thompson"
tip_extrapolation: "Solo hay dos tipos de personas: Esas que pueden extrapolar desde información incompleta..."
tip_superpower: "Programar es lo más cercano que tenemos a superpoderes."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Inventario"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
tip_brute_force: "Cuando haya dudas, usa la fuerza bruta. - Ken Thompson"
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: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Inventario"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
tip_brute_force: "En cas de doute, utiliser la force brute. - Ken Thompson"
tip_extrapolation: "Il y a seulement deux types de personnes : celles qui peuvent extrapoler à partir de données incomplètes..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Inventaire"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Galego", englishDescription: "Galician", tr
tip_brute_force: "Cando haxa dúbidas, usa a forza bruta. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Inventario"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
tip_brute_force: "Ha kérdésesa helyzet, használj nyers erőt. - Ken Thompson"
tip_extrapolation: "Csak két fajta ember létezik. Az egyik, aki extrapolál hiányos adatokból..."
tip_superpower: "A programozás képessége van legközelebb a szuperképességekhez."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Raktár"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Inventario"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Македонски", englishDescription:
tip_brute_force: "Кога не си сигурен, користи 'brute force'. - Ken Thompson"
tip_extrapolation: "Има само два вида на луѓе: оние кои можат да екстраполираат од некомплетни податоци..."
tip_superpower: "Програмирањето е способност, најблиска до супермоќ, која ја имаме."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Utstyr"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
tip_brute_force: "Als je twijfelt, gebruik brute kracht. - Ken Thompson"
tip_extrapolation: "Er zijn maar 2 soorten van mensen: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Inventaris"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Inventaris"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Ekwipunek"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Português do Brasil", englishDescription:
tip_brute_force: "Na dúvida, utilize força bruta. - Ken Thompson"
tip_extrapolation: "Existem dois tipos de pessoa: aqueles que podem extrapolar apartir de dados incompletos..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Inventário"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
tip_brute_force: "Quando em dúvida, usa a força bruta. - Ken Thompson"
tip_extrapolation: "Há apenas dois tipos de pessoas: aquelas que conseguem tirar uma conclusão a partir de dados reduzidos..."
tip_superpower: "A programação é a coisa mais próxima de um superpoder que temos."
tip_control_destiny: "Em open source a sério, tens o direito de controlares o teu próprio destino. - Linus Torvalds"
tip_no_code: "Nenhum código é mais rápido que código não existente."
tip_code_never_lies: "O código nunca mente, mas os comentários às vezes sim. — Ron Jeffries"
tip_reusable_software: "Antes de um software poder ser reutilizável, primeiro tem de ser utilizável."
tip_optimization_operator: "Todas as linguagens têm um operador de otimização. Na maior parte delas esse operador é //."
tip_lines_of_code: "Medir o progresso em programação pelo número de linhas de código é como medir o progresso da construção de um avião pelo peso. — Bill Gates"
game_menu:
inventory_tab: "Inventário"
@ -721,7 +727,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
# scribe_introduction_pref: "CodeCombat isn't just going to be a bunch of levels. It will also include a resource for knowledge, a wiki of programming concepts that levels can hook into. That way rather than each Artisan having to describe in detail what a comparison operator is, they can simply link their level to the Article describing them that is already written for the player's edification. Something along the lines of what the "
# scribe_introduction_url_mozilla: "Mozilla Developer Network"
# scribe_introduction_suf: " has built. If your idea of fun is articulating the concepts of programming in Markdown form, then this class might be for you."
# scribe_attribute_1: "Skill in words is pretty much all you need. Not only grammar and spelling, but able to convey complicated ideas to others."
scribe_attribute_1: "Habilidade com palavras é basicamente do que precisas. Não apenas gramática e ortografia, mas seres capaz de explicar ideias complicadas a outros."
contact_us_url: "Contacta-nos"
scribe_join_description: "fala-nos um bocado de ti, a tua experiência com a programação e o tipo de coisas sobre o qual gostavas de escrever. Começamos a partir daí!"
scribe_subscribe_desc: "Receber e-mails sobre anúncios relativos à escrita de artigos."
@ -739,7 +745,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
# ambassador_introduction: "This is a community we're building, and you are the connections. We've got forums, emails, and social networks with lots of people to talk with and help get acquainted with the game and learn from. If you want to help people get involved and have fun, and get a good feel of the pulse of CodeCombat and where we're going, then this class might be for you."
# ambassador_attribute_1: "Communication skills. Be able to identify the problems players are having and help them solve them. Also, keep the rest of us informed about what players are saying, what they like and don't like and want more of!"
# ambassador_join_desc: "tell us a little about yourself, what you've done and what you'd be interested in doing. We'll go from there!"
# ambassador_join_note_strong: "Note"
ambassador_join_note_strong: "Nota"
# ambassador_join_note_desc: "One of our top priorities is to build multiplayer where players having difficulty solving levels can summon higher level wizards to help them. This will be a great way for ambassadors to do their thing. We'll keep you posted!"
ambassador_subscribe_desc: "Receber e-mails relativos a novidades do suporte e desenvolvimentos do modo multijogador."
changes_auto_save: "As alterações são guardadas automaticamente quando clicas nas caixas."
@ -1102,8 +1108,8 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
# education_degree: "Degree"
# education_degree_help: "What was your degree and field of study?"
# education_duration: "Dates"
# education_duration_help: "When?"
# education_description: "Description"
education_duration_help: "Quando?"
education_description: "Descrição"
# education_description_help: "Highlight anything about this educational experience. (140 chars; optional)"
# our_notes: "CodeCombat's Notes"
# remarks: "Remarks"
@ -1118,7 +1124,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
project_picture: "Imagem"
# project_picture_help: "Upload a 230x115px or larger image showing off the project."
project_link: "Ligação"
# project_link_help: "Link to the project."
project_link_help: "Ligação para o projeto."
player_code: "Código do Jogador"
employers:

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
tip_brute_force: "Когда сомневаешься используй грубую силу. - Кен Томпсон"
tip_extrapolation: "Есть два типа людей: те, кто могут экстраполировать неполные данные..."
tip_superpower: "Программирование делает нас ближе к обретению суперсилы."
tip_control_destiny: "В настоящей среде открытого кода у вас есть право контролировать свою судьбу. - Linus Torvalds"
tip_no_code: "Нет кода быстрее, чем его отсутствие."
tip_code_never_lies: "Код никогда не врет. Комментарии - иногда. — Ron Jeffries"
tip_reusable_software: "Прежде, чем программное обеспечение станет повторно используемым, оно должно стать в принципе используемым."
tip_optimization_operator: "В каждом языке есть оператор оптимизации. В большинстве языков это оператор //"
tip_lines_of_code: "Измерение прогресса программирования в строках кода - это как измерять прогресс построения самолета по его весу. — Bill Gates"
game_menu:
inventory_tab: "Инвентарь"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Utrustning"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Envanter"

View file

@ -81,7 +81,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
awaiting_levels_adventurer_prefix: "Ми випускаємо 5 рівнів на тиждень."
awaiting_levels_adventurer: "Увійди як Шукач пригод"
awaiting_levels_adventurer_suffix: "стань одним з перших, хто їх спробує."
# adjust_volume: "Adjust volume"
adjust_volume: "Підлаштувати гучність"
choose_your_level: "Оберіть свій рівень" # The rest of this section is the old play view at /play-old and isn't very important.
adventurer_prefix: "Ви можете грати у будь-який рівень з наведених нижче або обговорювати рівні на "
adventurer_forum: "форумі Шукачів пригод"
@ -160,21 +160,21 @@ module.exports = nativeDescription: "Українська", englishDescription:
date: "Дата"
body: "Тіло"
version: "Версія"
# pending: "Pending"
# accepted: "Accepted"
# rejected: "Rejected"
pending: "Очікування"
accepted: "Прийнято"
rejected: "Відхилено"
# withdrawn: "Withdrawn"
# submitter: "Submitter"
# submitted: "Submitted"
submitted: "Відправлено"
commit_msg: "Доручити повідомлення"
review: "Огляд"
version_history: "Історія"
version_history_for: "Історія версій для: "
select_changes: "Оберіть дві зміни нижче, щоб побачити відмінності."
# undo_prefix: "Undo"
# undo_shortcut: "(Ctrl+Z)"
# redo_prefix: "Redo"
# redo_shortcut: "(Ctrl+Shift+Z)"
undo_prefix: "Відмінити"
undo_shortcut: "(Ctrl+Z)"
redo_prefix: "Повторити"
redo_shortcut: "(Ctrl+Shift+Z)"
play_preview: "Попередній перегляд поточного рівня"
result: "Результат"
results: "Результати"
@ -198,9 +198,9 @@ module.exports = nativeDescription: "Українська", englishDescription:
hard: "Важкий"
player: "Гравець"
player_level: "Рівень" # Like player level 5, not like level: Dungeons of Kithgard
# warrior: "Warrior"
warrior: "Воїн"
# ranger: "Ranger"
# wizard: "Wizard"
wizard: "Чаклун"
units:
second: "Секунда"
@ -317,14 +317,20 @@ module.exports = nativeDescription: "Українська", englishDescription:
tip_brute_force: "Якщо Ви сумніваєтеся, використовуйте перебір - Кен Томсон"
tip_extrapolation: "Існує 2 типи людей: які можуть екстраполюватись від неповних даних..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "Інвентар"
save_load_tab: "Зберегти/Завантажити"
options_tab: "Параметри"
guide_tab: "Довідник"
guide_video_tutorial: "Відео Посібник"
# guide_tips: "Tips"
guide_video_tutorial: "Відео-посібник"
guide_tips: "Поради"
multiplayer_tab: "Мультиплеєр"
auth_tab: "Вийти"
inventory_caption: "Екіпіруйте свого героя"
@ -338,7 +344,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
inventory:
choose_inventory: "Екіпіруйте предмети"
equipped_item: "Екіпіровано"
# required_purchase_title: "Required"
required_purchase_title: "Потребує"
available_item: "Доступно"
restricted_title: "Обмежено"
should_equip: "(предмети одягаються подвійним кліком)"
@ -480,7 +486,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
versions:
save_version_title: "Зберегти нову версію"
new_major_version: "Зберегти основну версію"
# submitting_patch: "Submitting Patch..."
submitting_patch: "Відправка патчу..."
cla_prefix: "Для збереження змін спочатку треба погодитись з нашим"
cla_url: "CLA"
cla_suffix: "."
@ -493,12 +499,12 @@ module.exports = nativeDescription: "Українська", englishDescription:
forum_page: "наш форум"
forum_suffix: "."
# faq_prefix: "There's also a"
# faq: "FAQ"
faq: "ЧаПи"
# subscribe_prefix: "If you need help figuring out a level, please"
# subscribe: "buy a CodeCombat subscription"
# subscribe_suffix: "and we'll be happy to help you with your code."
# subscriber_support: "Since you're a CodeCombat subscriber, your email will get our priority support."
# screenshot_included: "Screenshot included."
screenshot_included: "Приєднано зняток."
where_reply: "Куди ми повинні відповісти?"
send: "Надіслати відгук"
contact_candidate: "Сконтактуватися з кандидатом" # Deprecated
@ -583,7 +589,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
classes:
archmage_title: "Архімаг"
archmage_title_description: "(Програміст)"
# archmage_summary: "If you are a developer interested in coding educational games, become an archmage to help us build CodeCombat!"
archmage_summary: "Якщо ви зацікавлені в програмуванні навчальних ігор, станьте архімагом аби допомогти нам створювати CodeCombat!"
artisan_title: "Ремісник"
artisan_title_description: "(Створювач рівнів)"
# artisan_summary: "Build and share levels for you and your friends to play. Become an Artisan to learn the art of teaching others to program."
@ -592,10 +598,10 @@ module.exports = nativeDescription: "Українська", englishDescription:
# adventurer_summary: "Get our new levels (even our subscriber content) for free one week early and help us work out bugs before our public release."
scribe_title: "Писар"
scribe_title_description: "(Редактор статей)"
# scribe_summary: "Good code needs good documentation. Write, edit, and improve the docs read by millions of players across the globe."
scribe_summary: "Хороший код потребує хорошої документації. Пишіть, редагуйте, та покращуйте документацію, яку побачать мільйони гравців зі всього світу."
diplomat_title: "Дипломат"
diplomat_title_description: "(Перекладач)"
# diplomat_summary: "CodeCombat is localized in 45+ languages by our Diplomats. Help us out and contribute translations."
diplomat_summary: "За допомогою наших дипломатів CodeCombat локалізовано більш ніж 45 мовами. Ви також можете допомогти з перекладом."
ambassador_title: "Посланець"
ambassador_title_description: "(Підтримка)"
# ambassador_summary: "Tame our forum users and provide direction for those with questions. Our ambassadors represent CodeCombat to the world."
@ -610,12 +616,12 @@ module.exports = nativeDescription: "Українська", englishDescription:
revert: "Повернутись"
revert_models: "Моделі повернення"
pick_a_terrain: "Обрати лашдшафт"
# dungeon: "Dungeon"
# indoor: "Indoor"
# desert: "Desert"
dungeon: "Темниця"
indoor: "Кімната"
desert: "Пустеля"
grassy: "Подвір'я"
small: "Малий"
# large: "Large"
large: "Великий"
fork_title: "Форк нової версії"
fork_creating: "Створення форку..."
generate_terrain: "Згенерувати ландшафт"
@ -636,12 +642,12 @@ module.exports = nativeDescription: "Українська", englishDescription:
level_tab_thangs_all: "Усі"
level_tab_thangs_conditions: "Початковий статус"
level_tab_thangs_add: "Додати об'єкти"
# add_components: "Add Components"
# component_configs: "Component Configurations"
add_components: "Додати коментарі"
component_configs: "Налаштування компонента"
# config_thang: "Double click to configure a thang"
delete: "Видалити"
duplicate: "Дублікат"
# stop_duplicate: "Stop Duplicate"
duplicate: "Дублювати"
stop_duplicate: "Зупинити дублювання"
rotate: "Повернути"
level_settings_title: "Налаштування"
level_component_tab_title: "Поточні компоненти"
@ -676,7 +682,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
achievement_query_goals: "Ключове досягнення випадає з цілей рівня"
level_completion: "Рівень завершено"
pop_i18n: "Додати I18N"
# tasks: "Tasks"
tasks: "Завдання"
article:
edit_btn_preview: "Перегляд"
@ -885,7 +891,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
leaderboard: "Таблиця лідерів"
user_schema: "Схема користувача"
user_profile: "Профайл користувача"
# patch: "Patch"
patch: "Патч"
patches: "Патчі"
patched_model: "Вихідний документ"
model: "Модель"
@ -1069,7 +1075,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
# basics_looking_for_internship: "Internship"
# basics_looking_for_help: "What kind of developer position do you want?"
# name_header: "Fill in your name"
# name_anonymous: "Anonymous Developer"
name_anonymous: "Анонімний розробник"
# name_help: "Name you want employers to see, like 'Nick Winter'."
# short_description_header: "Write a short description of yourself"
# short_description_blurb: "Add a tagline to help an employer quickly learn more about you."

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
tip_brute_force: "拿不准时就用穷举法。 - Ken Thompson"
tip_extrapolation: "世界上只有两类人:一类人能够根据不完整的数据进行推断……"
tip_superpower: "编程是我们拥有的最接近超能力的技能"
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "道具箱"
@ -853,9 +859,9 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
subscribed: "已订阅"
unsubscribed: "取消订阅"
# active_until: "Active Until"
# cost: "Cost"
cost: "花费"
# next_payment: "Next Payment"
# card: "Card"
card: "银行卡"
# status_unsubscribed_active: "You're not subscribed and won't be billed, but your account is still active for now."
# status_unsubscribed: "Get access to new levels, heroes, items, and bonus gems with a CodeCombat subscription!"
@ -910,14 +916,14 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
# candidate_sessions: "Candidate Sessions"
# user_remark: "User Remark"
# user_remarks: "User Remarks"
# versions: "Versions"
versions: "版本"
items: "物品"
heroes: "英雄"
achievement: "成就"
# clas: "CLAs"
# play_counts: "Play Counts"
feedback: "反馈"
# payment_info: "Payment Info"
payment_info: "付款信息"
delta:
added: "被添加"
@ -996,15 +1002,15 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
nutshell_description: "我们在关卡编辑器里公开的任何资源,你都可以在制作关卡时随意使用,但我们保留限制在 codecombat.com 之上创建的关卡本身传播的权利,因为我们以后可能决定为它们收费。"
canonical: "这篇说明的英文版本是权威版本。如果各个翻译版本之间有任何冲突,以英文版为准。"
# ladder_prizes:
ladder_prizes:
# title: "Tournament Prizes" # This section was for an old tournament and doesn't need new translations now.
# blurb_1: "These prizes will be awarded according to"
# blurb_2: "the tournament rules"
# blurb_3: "to the top human and ogre players."
# blurb_4: "Two teams means double the prizes!"
# blurb_5: "(There will be two first place winners, two second-place winners, etc.)"
# rank: "Rank"
# prizes: "Prizes"
rank: "排名"
prizes: "奖项"
# total_value: "Total Value"
# in_cash: "in cash"
# custom_wizard: "Custom CodeCombat Wizard"
@ -1122,7 +1128,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
player_code: "玩家代码"
employers:
# deprecation_warning_title: "Sorry, CodeCombat is not recruiting right now."
deprecation_warning_title: "抱歉CodeCombat现不招募雇员。"
# deprecation_warning: "We are focusing on beginner levels instead of finding expert developers for the time being."
# hire_developers_not_credentials: "Hire developers, not credentials." # We are not actively recruiting right now, so there's no need to add new translations for the rest of this section.
# get_started: "Get Started"
@ -1162,10 +1168,10 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
candidate_top_skills: "高级技能"
candidate_years_experience: "多年工作经验"
candidate_last_updated: "最后一次更新"
# candidate_who: "Who"
# featured_developers: "Featured Developers"
# other_developers: "Other Developers"
# inactive_developers: "Inactive Developers"
candidate_who: "谁?"
featured_developers: "主要开发者"
other_developers: "其他开发者"
inactive_developers: "不活跃的开发者"
admin:
# av_espionage: "Espionage" # Really not important to translate /admin controls.

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
inventory_tab: "倉庫"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "吴语", englishDescription: "Wuu (Simplifi
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# game_menu:
# inventory_tab: "Inventory"

View file

@ -317,6 +317,12 @@ module.exports = nativeDescription: "吳語", englishDescription: "Wuu (Traditio
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
game_menu:
# inventory_tab: "Inventory"

View file

@ -54,13 +54,13 @@ module.exports = class LevelSession extends CocoModel
return if @shouldAvoidCorruptData attrs
super attrs, options
increaseDifficulty: ->
increaseDifficulty: (callback) ->
state = @get('state') ? {}
state.difficulty = (state.difficulty ? 0) + 1
delete state.lastUnsuccessfulSubmissionTime
@set 'state', state
@save()
@trigger 'change-difficulty'
@save null, success: callback
timeUntilResubmit: ->
state = @get('state') ? {}

View file

@ -52,6 +52,7 @@ _.extend CampaignSchema.properties, {
#- denormalized from Level
name: { type: 'string', format: 'hidden' }
description: { type: 'string', format: 'hidden' }
i18n: { type: 'object', format: 'hidden' }
requiresSubscription: { type: 'boolean' }
type: {'enum': ['campaign', 'ladder', 'ladder-tutorial', 'hero', 'hero-ladder', 'hero-coop']}
slug: { type: 'string', format: 'hidden' }

View file

@ -1,8 +1,16 @@
#campaign-analytics-modal
td
font-size: 9pt
max-width: 60px
td.completion-rate
max-width: 1000px
td.level
max-width: 1000px
.modal-dialog
width: 75%
width: 85%
.level-name-container
position: relative
max-width: 1000px
.level-name-background
position: absolute
height: 100%
@ -12,6 +20,7 @@
opacity: 0.25
.level-completion-container
position: relative
max-width: 1000px
.level-completion-background
position: absolute
height: 100%

View file

@ -7,21 +7,32 @@ block modal-header-content
input.form-control#input-startday(type='text', style='width:100px;', value=campaignCompletions.startDay)
input.form-control#input-endday(type='text', style='width:100px;', value=campaignCompletions.endDay)
button.btn.btn-default.btn-sm#reload-button(style='margin-left:10px;') Reload
div(style='font-size:10px') Double-click row to open level details.
label(style='font-size:10px;font-weight:normal;')
span Double-click row to open level details.
span   
input#option-show-left-game(type='checkbox', checked=showLeftGame)
span Show Left Game
span   
input#option-show-subscriptions(type='checkbox', checked=showSubscriptions)
span Show Subscriptions
block modal-body-content
if campaignCompletions && campaignCompletions.levels
table.table.table-bordered.table-condensed.table-hover(style='font-size:10pt')
thead
tr
td Level
td.level Level
td Started
td Finished
td Left Game
td LG %
td.completion-rate Completion %
td Playtime (s)
td LG/s
td Completion %
if showLeftGame
td Left Game
td LG %
td LG/s
if showSubscriptions
td Sub Shown
td Sub Purchased
tbody
- for (var i = 0; i < campaignCompletions.levels.length; i++)
tr.level(data-level-slug=campaignCompletions.levels[i].level)
@ -29,26 +40,6 @@ block modal-body-content
span.level-name-background(style="width:#{campaignCompletions.levels[i].usersRemaining || 0}%;")
td= campaignCompletions.levels[i].started
td= campaignCompletions.levels[i].finished
td= campaignCompletions.levels[i].dropped
if campaignCompletions.levels[i].dropPercentage
if campaignCompletions.top3DropPercentage && campaignCompletions.top3DropPercentage.indexOf(campaignCompletions.levels[i].level) >= 0
td(style='background-color:pink;')= campaignCompletions.levels[i].dropPercentage.toFixed(2)
else
td= campaignCompletions.levels[i].dropPercentage.toFixed(2)
else
td
if campaignCompletions.levels[i].averagePlaytime
td.level-playtime-container= campaignCompletions.levels[i].averagePlaytime.toFixed(2)
span.level-playtime-background(style="width:#{campaignCompletions.levels[i].playtimePercentage || 0}%;")
else
td
if campaignCompletions.levels[i].droppedPerSecond
if campaignCompletions.top3DropPerSecond && campaignCompletions.top3DropPerSecond.indexOf(campaignCompletions.levels[i].level) >= 0
td(style='background-color:pink;')= campaignCompletions.levels[i].droppedPerSecond.toFixed(2)
else
td= campaignCompletions.levels[i].droppedPerSecond.toFixed(2)
else
td
if campaignCompletions.levels[i].completionRate
if campaignCompletions.top3 && campaignCompletions.top3.indexOf(campaignCompletions.levels[i].level) >= 0
td.level-completion-container(style='background-color:lightblue;')= campaignCompletions.levels[i].completionRate.toFixed(2)
@ -59,8 +50,32 @@ block modal-body-content
else
td.level-completion-container= campaignCompletions.levels[i].completionRate.toFixed(2)
svg.level-completion-background(id="background#{campaignCompletions.levels[i].level}")
else
td.completion-rate
if campaignCompletions.levels[i].averagePlaytime
td.level-playtime-container= campaignCompletions.levels[i].averagePlaytime.toFixed(2)
span.level-playtime-background(style="width:#{campaignCompletions.levels[i].playtimePercentage || 0}%;")
else
td
if showLeftGame
td= campaignCompletions.levels[i].dropped
if campaignCompletions.levels[i].dropPercentage
if campaignCompletions.top3DropPercentage && campaignCompletions.top3DropPercentage.indexOf(campaignCompletions.levels[i].level) >= 0
td(style='background-color:pink;')= campaignCompletions.levels[i].dropPercentage.toFixed(2)
else
td= campaignCompletions.levels[i].dropPercentage.toFixed(2)
else
td
if campaignCompletions.levels[i].droppedPerSecond
if campaignCompletions.top3DropPerSecond && campaignCompletions.top3DropPerSecond.indexOf(campaignCompletions.levels[i].level) >= 0
td(style='background-color:pink;')= campaignCompletions.levels[i].droppedPerSecond.toFixed(2)
else
td= campaignCompletions.levels[i].droppedPerSecond.toFixed(2)
else
td
if showSubscriptions
td= campaignCompletions.levels[i].subsShown
td= campaignCompletions.levels[i].subsPurchased
else
div Loading...

View file

@ -16,9 +16,10 @@ block header
span.glyphicon-home.glyphicon
ul.nav.navbar-nav.navbar-right
li#analytics-button
a
span.glyphicon-stats.glyphicon
if me.isAdmin()
li#analytics-button
a
span.glyphicon-stats.glyphicon
if me.isAdmin()
li#save-button
a

View file

@ -5,8 +5,15 @@
a(href="/editor/level/#{level.get('slug')}", target="_blank") (edit)
p= level.get('description')
if analytics.startDay && analytics.endDay
.input-group.input-group-sm
input.form-control#input-startday(type='text', style='width:100px;', value=analytics.startDay)
input.form-control#input-endday(type='text', style='width:100px;', value=analytics.endDay)
button.btn.btn-default.btn-sm#reload-button(style='margin-left:10px;') Reload
h4 Completion Rates
if levelCompletions
if analytics.levelCompletions.loading
div Loading...
else
table.table.table-bordered.table-condensed.table-hover(style='font-size:10pt')
thead
tr
@ -14,48 +21,43 @@
td Started
td Finished
td Completion %
if levelHelps && levelHelps.length === levelCompletions.length
if analytics.levelHelps.levels.length === analytics.levelCompletions.levels.length
td Helps Clicked
td Helps / Started
td Help Videos
td Videos / Started
tbody
- for (var i = 0; i < levelCompletions.length; i++)
- for (var i = 0; i < analytics.levelCompletions.levels.length; i++)
tr
td= levelCompletions[i].created
td= levelCompletions[i].started
td= levelCompletions[i].finished
td= levelCompletions[i].rate
if levelHelps && levelHelps.length === levelCompletions.length
td= levelHelps[i].alertHelps + levelHelps[i].paletteHelps
td= ((levelHelps[i].alertHelps + levelHelps[i].paletteHelps) / levelCompletions[i].started).toFixed(2)
td= levelHelps[i].videoStarts
td= (levelHelps[i].videoStarts / levelCompletions[i].started).toFixed(2)
else
div Loading...
td= analytics.levelCompletions.levels[i].created
td= analytics.levelCompletions.levels[i].started
td= analytics.levelCompletions.levels[i].finished
td= analytics.levelCompletions.levels[i].rate
if analytics.levelHelps.levels.length === analytics.levelCompletions.levels.length && analytics.levelCompletions.levels[i].created == analytics.levelHelps.levels[i].day
td= analytics.levelHelps.levels[i].alertHelps + analytics.levelHelps.levels[i].paletteHelps
td= ((analytics.levelHelps.levels[i].alertHelps + analytics.levelHelps.levels[i].paletteHelps) / analytics.levelCompletions.levels[i].started).toFixed(2)
td= analytics.levelHelps.levels[i].videoStarts
td= (analytics.levelHelps.levels[i].videoStarts / analytics.levelCompletions.levels[i].started).toFixed(2)
h4 Average Playtimes
if levelPlaytimes
if analytics.levelPlaytimes.loading
div Loading...
else
table.table.table-bordered.table-condensed.table-hover(style='font-size:10pt')
thead
tr
td Date
td Average (s)
tbody
- for (var i = 0; i < levelPlaytimes.length; i++)
- for (var i = 0; i < analytics.levelPlaytimes.levels.length; i++)
tr
td= levelPlaytimes[i].created
td= levelPlaytimes[i].average.toFixed(2)
else
div Loading...
td= analytics.levelPlaytimes.levels[i].created
td= analytics.levelPlaytimes.levels[i].average.toFixed(2)
h4 Common Problems
if commonProblems
if commonProblems.startDay
if commonProblems.endDay
div(style='font-size:10pt') #{commonProblems.startDay} to #{commonProblems.endDay}
else
div(style='font-size:10pt') #{commonProblems.startDay} to today
if analytics.commonProblems.loading
div Loading...
else
table.table.table-bordered.table-condensed.table-hover(style='font-size:10pt')
thead
tr
@ -64,18 +66,18 @@
td Error Hint
td Count
tbody
- for (var i = 0; i < commonProblems.length && i < 20; i++)
- for (var i = 0; i < analytics.commonProblems.levels.length && i < 20; i++)
tr
td= commonProblems[i].language
td= commonProblems[i].message
td= commonProblems[i].hint
td= commonProblems[i].count
else
div Loading...
td= analytics.commonProblems.levels[i].language
td= analytics.commonProblems.levels[i].message
td= analytics.commonProblems.levels[i].hint
td= analytics.commonProblems.levels[i].count
h4 Recent Sessions
if recentSessions
div(style='font-size:10pt') Latest #{recentSessions.length} sessions for this level
if analytics.recentSessions.loading
div Loading...
else
div(style='font-size:10pt') Latest #{analytics.recentSessions.levels.length} sessions for this level
div(style='font-size:10pt') Double-click row to open player and session
table.table.table-bordered.table-condensed.table-hover(style='font-size:10pt')
thead
@ -87,19 +89,17 @@
td Complete
td Changed
tbody
- for (var i = 0; i < recentSessions.length; i++)
tr.recent-session(data-player-id=recentSessions[i].creator, data-session-id=recentSessions[i]._id)
td= recentSessions[i]._id
td= recentSessions[i].creatorName || recentSessions[i].creator
td= recentSessions[i].codeLanguage
td= recentSessions[i].playtime
if recentSessions[i].state && recentSessions[i].state.complete
td= recentSessions[i].state.complete
- for (var i = 0; i < analytics.recentSessions.levels.length; i++)
tr.recent-session(data-player-id=analytics.recentSessions.levels[i].creator, data-session-id=analytics.recentSessions.levels[i]._id)
td= analytics.recentSessions.levels[i]._id
td= analytics.recentSessions.levels[i].creatorName || analytics.recentSessions.levels[i].creator
td= analytics.recentSessions.levels[i].codeLanguage
td= analytics.recentSessions.levels[i].playtime
if analytics.recentSessions.levels[i].state && analytics.recentSessions.levels[i].state.complete
td= analytics.recentSessions.levels[i].state.complete
else
td false
td= recentSessions[i].changed
else
div Loading...
td= analytics.recentSessions.levels[i].changed
if level.get('tasks')
.tasks

View file

@ -7,7 +7,7 @@
each level in levels
if !level.hidden
div(style="left: #{level.position.x}%; bottom: #{level.position.y}%; background-color: #{level.color}", class="level" + (level.next ? " next" : "") + (level.disabled ? " disabled" : "") + (level.locked ? " locked" : "") + " " + levelStatusMap[level.slug] || "", data-level-slug=level.slug, data-level-original=level.original, title=level.name + (level.disabled ? ' (Coming Soon to Adventurers)' : ''))
div(style="left: #{level.position.x}%; bottom: #{level.position.y}%; background-color: #{level.color}", class="level" + (level.next ? " next" : "") + (level.disabled ? " disabled" : "") + (level.locked ? " locked" : "") + " " + levelStatusMap[level.slug] || "", data-level-slug=level.slug, data-level-original=level.original, title=i18n(level, 'name') + (level.disabled ? ' (Coming Soon to Adventurers)' : ''))
if level.unlocksHero && !level.unlockedHero
img.hero-portrait(src=level.unlocksHero.img)
a(href=level.type == 'hero' ? '#' : level.disabled ? "/play" : "/play/#{level.levelPath || 'level'}/#{level.slug}", disabled=level.disabled, data-level-slug=level.slug, data-level-path=level.levelPath || 'level', data-level-name=level.name)
@ -20,8 +20,9 @@
div(style="left: #{level.position.x}%; bottom: #{level.position.y}%", class="level-shadow" + (level.next ? " next" : "") + " " + levelStatusMap[level.slug] || "")
.level-info-container(data-level-slug=level.slug, data-level-path=level.levelPath || 'level', data-level-name=level.name)
div(class="level-info " + (levelStatusMap[level.slug] || ""))
h3= level.name + (level.disabled ? " (Coming soon!)" : (level.locked ? " (Locked)" : ""))
.level-description= level.description
h3= i18n(level, 'name') + (level.disabled ? " (Coming soon!)" : (level.locked ? " (Locked)" : ""))
- var description = i18n(level, 'description') || level.description || ""
.level-description!= marked(description)
if level.disabled
p
span.spr(data-i18n="play.awaiting_levels_adventurer_prefix") We release five levels per week.
@ -36,7 +37,7 @@
span(data-i18n="play.players") players
span.spr , #{Math.round(playCount.playtime / 3600)}
span(data-i18n="play.hours_played") hours played
.campaign-label= campaign.get('name')
.campaign-label= i18n(campaign.attributes, 'name')
if isIPadApp && !level.disabled && !level.locked
button.btn.btn-success.btn-lg.start-level(data-i18n="common.play") Play

View file

@ -57,3 +57,9 @@
strong.tip.rare
span(data-i18n='play_level.tip_harry') Yer a Wizard,
span= me.get('name', true)
strong.tip.rare(data-i18n='play_level.tip_control_destiny') In real open source, you have the right to control your own destiny. - Linus Torvalds
strong.tip.rare(data-i18n='play_level.tip_no_code') No code is faster than no code.
strong.tip.rare(data-i18n='play_level.tip_code_never_lies') Code never lies, comments sometimes do. — Ron Jeffries
strong.tip.rare(data-i18n='play_level.tip_reusable_software') Before software can be reusable it first has to be usable.
strong.tip.rare(data-i18n='play_level.tip_optimization_operator') Every language has an optimization operator. In most languages that operator is //
strong.tip.rare(data-i18n='play_level.tip_lines_of_code') Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates

View file

@ -14,13 +14,19 @@ module.exports = class CampaignAnalyticsModal extends ModalView
events:
'click #reload-button': 'onClickReloadButton'
'dblclick .level': 'onDblClickLevel'
'change #option-show-left-game': 'updateShowLeftGame'
'change #option-show-subscriptions': 'updateShowSubscriptions'
constructor: (options, @campaignHandle, @campaignCompletions) ->
super options
@getCampaignAnalytics() unless @campaignCompletions?.levels?
@showLeftGame = true
@showSubscriptions = true
@getCampaignAnalytics() if me.isAdmin()
getRenderData: ->
c = super()
c.showLeftGame = @showLeftGame
c.showSubscriptions = @showSubscriptions
c.campaignCompletions = @campaignCompletions
c
@ -30,6 +36,14 @@ module.exports = class CampaignAnalyticsModal extends ModalView
$("#input-endday").datepicker dateFormat: "yy-mm-dd"
@addCompletionLineGraphs()
updateShowLeftGame: ->
@showLeftGame = @$el.find('#option-show-left-game').prop('checked')
@render()
updateShowSubscriptions: ->
@showSubscriptions = @$el.find('#option-show-subscriptions').prop('checked')
@render()
onClickReloadButton: () =>
startDay = $('#input-startday').val()
endDay = $('#input-endday').val()
@ -45,6 +59,7 @@ module.exports = class CampaignAnalyticsModal extends ModalView
@hide()
addCompletionLineGraphs: ->
# TODO: no line graphs if some levels without completion rates?
return unless @campaignCompletions.levels
for level in @campaignCompletions.levels
days = []
@ -109,17 +124,19 @@ module.exports = class CampaignAnalyticsModal extends ModalView
# Chain these together so we can calculate relative metrics (e.g. left game per second)
@getCampaignLevelCompletions startDay, endDay, () =>
@render()
@render?()
@getCompaignLevelDrops startDay, endDay, () =>
@render()
@render?()
@getCampaignAveragePlaytimes startDayDashed, endDayDashed, () =>
@render()
@render?()
@getCampaignLevelSubscriptions startDay, endDay, () =>
@render?()
getCampaignAveragePlaytimes: (startDay, endDay, doneCallback) =>
# Fetch level average playtimes
# Needs date format yyyy-mm-dd
success = (data) =>
return if @destroyed
return doneCallback() if @destroyed
# console.log 'getCampaignAveragePlaytimes success', data
levelAverages = {}
maxPlaytime = 0
@ -161,7 +178,7 @@ module.exports = class CampaignAnalyticsModal extends ModalView
getCampaignLevelCompletions: (startDay, endDay, doneCallback) =>
# Needs date format yyyymmdd
success = (data) =>
return if @destroyed
return doneCallback() if @destroyed
# console.log 'getCampaignLevelCompletions success', data
countCompletions = (item) ->
item.started = _.reduce item.days, ((result, current) -> result + current.started), 0
@ -217,7 +234,7 @@ module.exports = class CampaignAnalyticsModal extends ModalView
@campaignCompletions.top3DropPercentage = _.pluck sortedLevels[0..2], 'level'
doneCallback()
return unless @campaignCompletions?.levels?
return doneCallback() unless @campaignCompletions?.levels?
levelSlugs = _.pluck @campaignCompletions.levels, 'level'
request = @supermodel.addRequestResource 'level_drops', {
@ -227,3 +244,28 @@ module.exports = class CampaignAnalyticsModal extends ModalView
success: success
}, 0
request.load()
getCampaignLevelSubscriptions: (startDay, endDay, doneCallback) =>
# Fetch level subscriptions
# Needs date format yyyymmdd
success = (data) =>
return doneCallback() if @destroyed
# console.log 'getCampaignLevelSubscriptions success', data
levelSubs = {}
for item in data
levelSubs[item.level] = shown: item.shown, purchased: item.purchased
for level in @campaignCompletions.levels
level.subsShown = levelSubs[level.level]?.shown
level.subsPurchased = levelSubs[level.level]?.purchased
doneCallback()
return doneCallback() unless @campaignCompletions?.levels?
levelSlugs = _.pluck @campaignCompletions.levels, 'level'
request = @supermodel.addRequestResource 'campaign_subscriptions', {
url: '/db/analytics_perday/-/level_subscriptions'
data: {startDay: startDay, endDay: endDay, slugs: levelSlugs}
method: 'POST'
success: success
}, 0
request.load()

View file

@ -11,6 +11,7 @@ module.exports = class CampaignLevelView extends CocoView
events:
'click .close': 'onClickClose'
'click #reload-button': 'onClickReloadButton'
'dblclick .recent-session': 'onDblClickRecentSession'
constructor: (options, @level) ->
@ -20,26 +21,28 @@ module.exports = class CampaignLevelView extends CocoView
@listenToOnce @fullLevel, 'sync', => @render?()
@levelSlug = @level.get('slug')
@getCommonLevelProblems()
@getLevelCompletions()
@getLevelHelps()
@getLevelPlaytimes()
@getRecentSessions()
@getAnalytics()
getRenderData: ->
c = super()
c.level = if @fullLevel.loaded then @fullLevel else @level
c.commonProblems = @commonProblems
c.levelCompletions = @levelCompletions
c.levelHelps = @levelHelps
c.levelPlaytimes = @levelPlaytimes
c.recentSessions = @recentSessions
c.analytics = @analytics
c
afterRender: ->
super()
$("#input-startday").datepicker dateFormat: "yy-mm-dd"
$("#input-endday").datepicker dateFormat: "yy-mm-dd"
onClickClose: ->
@$el.addClass('hidden')
@trigger 'hidden'
onClickReloadButton: () =>
startDay = $('#input-startday').val()
endDay = $('#input-endday').val()
@getAnalytics startDay, endDay
onDblClickRecentSession: (e) ->
# Admin view of players' code
return unless me.isAdmin()
@ -48,91 +51,124 @@ module.exports = class CampaignLevelView extends CocoView
session = new LevelSession _id: row.data 'session-id'
@openModalView new ModelModal models: [session, player]
getCommonLevelProblems: ->
# Fetch last 30 days of common level problems
startDay = utils.getUTCDay -29
startDay = "#{startDay[0..3]}-#{startDay[4..5]}-#{startDay[6..7]}"
getAnalytics: (startDay, endDay) =>
if startDay?
startDayDashed = startDay
startDay = startDay.replace(/-/g, '')
else
startDay = utils.getUTCDay -14
startDayDashed = "#{startDay[0..3]}-#{startDay[4..5]}-#{startDay[6..7]}"
if endDay?
endDayDashed = endDay
endDay = endDay.replace(/-/g, '')
else
endDay = utils.getUTCDay -1
endDayDashed = "#{endDay[0..3]}-#{endDay[4..5]}-#{endDay[6..7]}"
success = (data) =>
return if @destroyed
@commonProblems = data
@commonProblems.startDay = startDay
@analytics =
startDay: startDayDashed
endDay: endDayDashed
commonProblems:
levels: []
loading: true
levelCompletions:
levels: []
loading: true
levelHelps:
levels: []
loading: true
levelPlaytimes:
levels: []
loading: true
recentSessions:
levels: []
loading: true
@render()
@getCommonLevelProblems startDayDashed, endDayDashed, () =>
@analytics.commonProblems.loading = false
@render()
@getLevelCompletions startDay, endDay, () =>
@analytics.levelCompletions.loading = false
@render()
@getLevelHelps startDay, endDay, () =>
@analytics.levelHelps.loading = false
@render()
@getLevelPlaytimes startDayDashed, endDayDashed, () =>
@analytics.levelPlaytimes.loading = false
@render()
@getRecentSessions () =>
@analytics.recentSessions.loading = false
@render()
getCommonLevelProblems: (startDay, endDay, doneCallback) ->
success = (data) =>
return doneCallback() if @destroyed
@analytics.commonProblems.levels = data
doneCallback()
# TODO: Why do we need this url dash?
request = @supermodel.addRequestResource 'common_problems', {
url: '/db/user_code_problem/-/common_problems'
data: {startDay: startDay, slug: @levelSlug}
data: {startDay: startDay, endDay: endDay, slug: @levelSlug}
method: 'POST'
success: success
}, 0
request.load()
getLevelCompletions: ->
# Fetch last 14 days of level completion counts
getLevelCompletions: (startDay, endDay, doneCallback) ->
success = (data) =>
return if @destroyed
return doneCallback() if @destroyed
data.sort (a, b) -> if a.created < b.created then 1 else -1
mapFn = (item) ->
item.rate = (item.finished / item.started * 100).toFixed(2)
item
@levelCompletions = _.map data, mapFn, @
@render()
@analytics.levelCompletions.levels = _.map data, mapFn, @
doneCallback()
startDay = utils.getUTCDay -14
# TODO: Why do we need this url dash?
request = @supermodel.addRequestResource 'level_completions', {
url: '/db/analytics_perday/-/level_completions'
data: {startDay: startDay, slug: @levelSlug}
data: {startDay: startDay, endDay: endDay, slug: @levelSlug}
method: 'POST'
success: success
}, 0
request.load()
getLevelHelps: ->
# Fetch last 14 days of level completion counts
getLevelHelps: (startDay, endDay, doneCallback) ->
success = (data) =>
return if @destroyed
@levelHelps = data.sort (a, b) -> if a.created < b.created then 1 else -1
@render()
startDay = utils.getUTCDay -14
return doneCallback() if @destroyed
@analytics.levelHelps.levels = data.sort (a, b) -> if a.day < b.day then 1 else -1
doneCallback()
request = @supermodel.addRequestResource 'level_helps', {
url: '/db/analytics_perday/-/level_helps'
data: {startDay: startDay, slugs: [@levelSlug]}
data: {startDay: startDay, endDay: endDay, slugs: [@levelSlug]}
method: 'POST'
success: success
}, 0
request.load()
getLevelPlaytimes: ->
# Fetch last 14 days of level average playtimes
getLevelPlaytimes: (startDay, endDay, doneCallback) ->
success = (data) =>
return if @destroyed
@levelPlaytimes = data.sort (a, b) -> if a.created < b.created then 1 else -1
@render()
return doneCallback() if @destroyed
@analytics.levelPlaytimes.levels = data.sort (a, b) -> if a.created < b.created then 1 else -1
doneCallback()
startDay = utils.getUTCDay -13
startDay = "#{startDay[0..3]}-#{startDay[4..5]}-#{startDay[6..7]}"
# TODO: Why do we need this url dash?
request = @supermodel.addRequestResource 'playtime_averages', {
url: '/db/level/-/playtime_averages'
data: {startDay: startDay, slugs: [@levelSlug]}
data: {startDay: startDay, endDay: endDay, slugs: [@levelSlug]}
method: 'POST'
success: success
}, 0
request.load()
getRecentSessions: ->
getRecentSessions: (doneCallback) ->
limit = 100
success = (data) =>
return if @destroyed
@recentSessions = data
@render()
return doneCallback() if @destroyed
@analytics.recentSessions.levels = data
doneCallback()
# TODO: Why do we need this url dash?
request = @supermodel.addRequestResource 'level_sessions_recent', {

View file

@ -170,6 +170,8 @@ module.exports = class CampaignView extends RootView
styles.push "top: #{ac.position.y}%"
ac.style = styles.join('; ')
return true
context.marked = marked
context.i18n = utils.i18n
context
afterRender: ->
@ -340,7 +342,7 @@ module.exports = class CampaignView extends RootView
onWindowResize: (e) =>
mapHeight = iPadHeight = 1536
mapWidth = {dungeon: 2350, forest: 2500, desert: 2350}[@terrain] or 2350
mapWidth = {dungeon: 2350, forest: 2500, auditions: 2500, desert: 2350, mountain: 2422}[@terrain] or 2350
aspectRatio = mapWidth / mapHeight
pageWidth = @$el.width()
pageHeight = @$el.height()

View file

@ -110,7 +110,7 @@ module.exports = class LevelLoadingView extends CocoView
onClickStartSubscription: (e) ->
@openModalView new SubscribeModal()
window.tracker?.trackEvent 'Show subscription modal', category: 'Subscription', label: 'level loading', level: @options.level.get('name') ? 'unknown'
window.tracker?.trackEvent 'Show subscription modal', category: 'Subscription', label: 'level loading', level: @options.level.get('slug')
onSubscribed: ->
document.location.reload()

View file

@ -523,8 +523,11 @@ module.exports = class PlayLevelView extends RootView
return if @destroyed
# TODO: Show a victory dialog specific to hero-ladder level
if @goalManager.checkOverallStatus() is 'success' and not @options.realTimeMultiplayerSessionID?
@session.increaseDifficulty() if @level.get 'replayable'
Backbone.Mediator.publish 'level:show-victory', showModal: true
showModalFn = -> Backbone.Mediator.publish 'level:show-victory', showModal: true
if @level.get 'replayable'
@session.increaseDifficulty showModalFn
else
showModalFn()
destroy: ->
@levelLoader?.destroy()

View file

@ -16,10 +16,80 @@
// TODO: Are Mixpanel rates accounting for finishing steps likely to be completed in the future?
// TODO: Use Mixpanel export API to investigate
// TODO: Output documents updated/inserted
try {
var scriptStartTime = new Date();
var analyticsStringCache = {};
var scriptStartTime = new Date();
var analyticsStringCache = {};
// Look at last 30 days, same as Mixpanel
var numDays = 30;
var startDay = new Date();
today = startDay.toISOString().substr(0, 10);
startDay.setUTCDate(startDay.getUTCDate() - numDays);
startDay = startDay.toISOString().substr(0, 10);
var levelCompletionFunnel = ['Started Level', 'Saw Victory'];
var levelHelpEvents = ['Problem alert help clicked', 'Spell palette help clicked', 'Start help video'];
log("Today is " + today);
log("Start day is " + startDay);
log("Funnel events are " + levelCompletionFunnel);
log("Getting level completion data...");
var levelCompletionData = getLevelFunnelData(startDay, levelCompletionFunnel);
log("Inserting aggregated level completion data...");
for (level in levelCompletionData) {
for (day in levelCompletionData[level]) {
if (today === day) continue; // Never save data for today because it's incomplete
for (event in levelCompletionData[level][day]) {
insertEventCount(event, level, day, levelCompletionData[level][day][event]);
}
}
}
log("Getting level drop counts...");
var levelDropCounts = getLevelDropCounts(startDay, levelCompletionFunnel);
log("Inserting level drop counts...");
for (level in levelDropCounts) {
for (day in levelDropCounts[level]) {
if (today === day) continue; // Never save data for today because it's incomplete
insertEventCount('User Dropped', level, day, levelDropCounts[level][day]);
}
}
log("Getting level help counts...");
var levelHelpCounts = getLevelHelpCounts(startDay, levelHelpEvents);
log("Inserting level help counts...");
for (level in levelHelpCounts) {
for (day in levelHelpCounts[level]) {
if (today === day) continue; // Never save data for today because it's incomplete
for (event in levelHelpCounts[level][day]) {
insertEventCount(event, level, day, levelHelpCounts[level][day][event]);
}
}
}
log("Getting level subscription counts...");
var levelSubscriptionCounts = getLevelSubscriptionCounts(startDay);
log("Inserting level subscription counts...");
for (level in levelSubscriptionCounts) {
for (day in levelSubscriptionCounts[level]) {
if (today === day) continue; // Never save data for today because it's incomplete
for (event in levelSubscriptionCounts[level][day]) {
insertEventCount(event, level, day, levelSubscriptionCounts[level][day][event]);
}
}
}
log("Script runtime: " + (new Date() - scriptStartTime));
}
catch(err) {
log("ERROR: " + err);
printjson(err);
}
// *** Helper functions ***
function log(str) {
print(new Date().toISOString() + " " + str);
@ -229,6 +299,82 @@ function getLevelHelpCounts(startDay, events) {
return levelEventData;
}
function getLevelSubscriptionCounts(startDay) {
// Counts subscriptions shown per day, only for events that have levels
// Subscription purchased event counts are attributed to last shown subscription modal event's day and level
if (!startDay) return {};
var startObj = objectIdWithTimestamp(ISODate(startDay + "T00:00:00.000Z"));
var queryParams = {$and: [
{_id: {$gte: startObj}},
{$or: [
{$and: [{'event': 'Show subscription modal'}, {'properties.level': {$exists: true}}]},
{'event': 'Finished subscription purchase'}]
}
]};
var cursor = db['analytics.log.events'].find(queryParams);
// Map ordering: user, event, level, day
// Map ordering: user, event, day
var userDataMap = {};
while (cursor.hasNext()) {
var doc = cursor.next();
var created = doc._id.getTimestamp().toISOString();
var day = created.substring(0, 10);
var event = doc.event;
var user = doc.user;
if (!userDataMap[user]) userDataMap[user] = {};
if (event === 'Show subscription modal') {
var level = doc.properties.level;
// TODO: This is for legacy data.
// TODO: Event tracking updated to use level slug for loading level view on ~1/21/15
level = level.toLowerCase().replace(/ /g, '-');
if (!userDataMap[user][event]) userDataMap[user][event] = {};
if (!userDataMap[user][event][level] || userDataMap[user][event][level].localeCompare(day) > 0) {
userDataMap[user][event][level] = day;
}
}
else if (event === 'Finished subscription purchase') {
if (!userDataMap[user][event] || userDataMap[user][event].localeCompare(day) > 0) {
userDataMap[user][event] = day;
}
} else {
continue;
}
}
// Data: level, day, event
var levelFunnelData = {};
for (user in userDataMap) {
if (userDataMap[user]['Show subscription modal']) {
var lastDay = null;
var lastLevel = null;
for (level in userDataMap[user]['Show subscription modal']) {
var day = userDataMap[user]['Show subscription modal'][level];
if (!lastDay || lastDay.localeCompare(day) > 0) {
lastDay = day;
lastLevel = level;
}
if (!levelFunnelData[level]) levelFunnelData[level] = {};
if (!levelFunnelData[level][day]) levelFunnelData[level][day] = {};
if (!levelFunnelData[level][day][event]) levelFunnelData[level][day]['Show subscription modal'] = 0;
levelFunnelData[level][day]['Show subscription modal']++;
}
if (lastDay && userDataMap[user]['Finished subscription purchase']) {
if (!levelFunnelData[lastLevel][lastDay]['Finished subscription purchase']) {
levelFunnelData[lastLevel][lastDay]['Finished subscription purchase'] = 0;
}
levelFunnelData[lastLevel][lastDay]['Finished subscription purchase']++;
}
}
}
return levelFunnelData;
}
function insertEventCount(event, level, day, count) {
// analytics.perdays schema in server/analytics/AnalyticsPeryDay.coffee
day = day.replace(/-/g, '');
@ -264,60 +410,3 @@ function insertEventCount(event, level, day, count) {
// }
}
}
try {
// Look at last 30 days, same as Mixpanel
var numDays = 30;
var startDay = new Date();
today = startDay.toISOString().substr(0, 10);
startDay.setUTCDate(startDay.getUTCDate() - numDays);
startDay = startDay.toISOString().substr(0, 10);
var levelCompletionFunnel = ['Started Level', 'Saw Victory'];
var levelHelpEvents = ['Problem alert help clicked', 'Spell palette help clicked', 'Start help video'];
log("Today is " + today);
log("Start day is " + startDay);
log("Funnel events are " + levelCompletionFunnel);
log("Getting level completion data...");
var levelCompletionData = getLevelFunnelData(startDay, levelCompletionFunnel);
log("Inserting aggregated level completion data...");
for (level in levelCompletionData) {
for (day in levelCompletionData[level]) {
if (today === day) continue; // Never save data for today because it's incomplete
for (event in levelCompletionData[level][day]) {
insertEventCount(event, level, day, levelCompletionData[level][day][event]);
}
}
}
log("Getting level drop counts...");
var levelDropCounts = getLevelDropCounts(startDay, levelCompletionFunnel)
log("Inserting level drop counts...");
for (level in levelDropCounts) {
for (day in levelDropCounts[level]) {
if (today === day) continue; // Never save data for today because it's incomplete
insertEventCount('User Dropped', level, day, levelDropCounts[level][day]);
}
}
log("Getting level help counts...");
var levelHelpCounts = getLevelHelpCounts(startDay, levelHelpEvents)
log("Inserting level help counts...");
for (level in levelHelpCounts) {
for (day in levelHelpCounts[level]) {
if (today === day) continue; // Never save data for today because it's incomplete
for (event in levelHelpCounts[level][day]) {
insertEventCount(event, level, day, levelHelpCounts[level][day][event]);
}
}
}
}
catch(err) {
log("ERROR: " + err);
printjson(err);
}
log("Script runtime: " + (new Date() - scriptStartTime));

View file

@ -10,13 +10,15 @@ class AnalyticsPerDayHandler extends Handler
jsonSchema: require '../../app/schemas/models/analytics_perday'
hasAccess: (req) ->
req.method in ['GET'] or req.user?.isAdmin()
req.user?.isAdmin() or false
getByRelationship: (req, res, args...) ->
return @sendForbiddenError res unless @hasAccess req
return @getCampaignCompletionsBySlug(req, res) if args[1] is 'campaign_completions'
return @getLevelCompletionsBySlug(req, res) if args[1] is 'level_completions'
return @getLevelDropsBySlugs(req, res) if args[1] is 'level_drops'
return @getLevelHelpsBySlugs(req, res) if args[1] is 'level_helps'
return @getLevelSubscriptionsBySlugs(req, res) if args[1] is 'level_subscriptions'
super(arguments...)
getCampaignCompletionsBySlug: (req, res) ->
@ -334,4 +336,73 @@ class AnalyticsPerDayHandler extends Handler
@levelHelpsCache[cacheKey] = helps
@sendSuccess res, helps
getLevelSubscriptionsBySlugs: (req, res) ->
# Send back an array of level subscriptions shown and purchased counts
# Parameters:
# slugs - level slugs
# startDay - Inclusive, optional, YYYYMMDD e.g. '20141214'
# endDay - Exclusive, optional, YYYYMMDD e.g. '20141216'
levelSlugs = req.query.slugs or req.body.slugs
startDay = req.query.startDay or req.body.startDay
endDay = req.query.endDay or req.body.endDay
# log.warn "level_subscriptions levelSlugs='#{levelSlugs}' startDay=#{startDay} endDay=#{endDay}"
return @sendSuccess res, [] unless levelSlugs?
# Cache results in app server memory for 1 day
@levelSubscriptionsCache ?= {}
@levelSubscriptionsCachedSince ?= new Date()
if (new Date()) - @levelSubscriptionsCachedSince > 86400 * 1000
@levelSubscriptionsCache = {}
@levelSubscriptionsCachedSince = new Date()
cacheKey = levelSlugs.join ''
cacheKey += 's' + startDay if startDay?
cacheKey += 'e' + endDay if endDay?
return @sendSuccess res, subscriptions if subscriptions = @levelSubscriptionsCache[cacheKey]
findQueryParams = {v: {$in: ['Show subscription modal', 'Finished subscription purchase', 'all'].concat(levelSlugs)}}
AnalyticsString.find(findQueryParams).exec (err, documents) =>
if err? then return @sendDatabaseError res, err
levelStringIDSlugMap = {}
for doc in documents
showSubEventID = doc._id if doc.v is 'Show subscription modal'
finishSubEventID = doc._id if doc.v is 'Finished subscription purchase'
filterEventID = doc._id if doc.v is 'all'
levelStringIDSlugMap[doc._id] = doc.v if doc.v in levelSlugs
return @sendSuccess res, [] unless showSubEventID? and finishSubEventID? and filterEventID?
queryParams = {$and: [
{e: {$in: [showSubEventID, finishSubEventID]}},
{f: filterEventID},
{l: {$in: Object.keys(levelStringIDSlugMap)}}
]}
queryParams["$and"].push {d: {$gte: startDay}} if startDay?
queryParams["$and"].push {d: {$lt: endDay}} if endDay?
AnalyticsPerDay.find(queryParams).exec (err, documents) =>
if err? then return @sendDatabaseError res, err
levelEventCounts = {}
for doc in documents
levelEventCounts[doc.l] ?= {}
levelEventCounts[doc.l][doc.e] ?= 0
levelEventCounts[doc.l][doc.e] += doc.c
subscriptions = []
for levelID of levelEventCounts
for eventID of levelEventCounts[levelID]
subsShown = levelEventCounts[levelID][eventID] if parseInt(eventID) is showSubEventID
subsPurchased = levelEventCounts[levelID][eventID] if parseInt(eventID) is finishSubEventID
subscriptions.push
level: levelStringIDSlugMap[levelID]
shown: subsShown ? 0
purchased: subsPurchased ? 0
@levelSubscriptionsCache[cacheKey] = subscriptions
@sendSuccess res, subscriptions
module.exports = new AnalyticsPerDayHandler()

View file

@ -24,7 +24,13 @@ class UserCodeProblemHandler extends Handler
ucp.set('creator', req.user._id)
ucp
hasAccess: (req) ->
return true if req.user?.isAdmin()
return true if req.method.toLowerCase() is 'post'
false
getByRelationship: (req, res, args...) ->
return @sendForbiddenError res unless @hasAccess req
return @getCommonLevelProblemsBySlug(req, res) if args[1] is 'common_problems'
super(arguments...)