mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-12-03 12:27:19 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
d73328ef54
6 changed files with 250 additions and 150 deletions
|
@ -11,7 +11,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
for_beginners: "Für Afänger"
|
for_beginners: "Für Afänger"
|
||||||
multiplayer: "Multiplayer" # Not currently shown on home page
|
multiplayer: "Multiplayer" # Not currently shown on home page
|
||||||
for_developers: "Für Entwickler" # Not currently shown on home page.
|
for_developers: "Für Entwickler" # Not currently shown on home page.
|
||||||
# or_ipad: "Or download for iPad"
|
or_ipad: "Oder lads fürs iPad abä"
|
||||||
|
|
||||||
nav:
|
nav:
|
||||||
play: "Levels" # The top nav bar entry where players choose which levels to play
|
play: "Levels" # The top nav bar entry where players choose which levels to play
|
||||||
|
@ -58,7 +58,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
owned: "Scho gkauft" # For items you own
|
owned: "Scho gkauft" # For items you own
|
||||||
locked: "Nonig freischaltbar"
|
locked: "Nonig freischaltbar"
|
||||||
# purchasable: "Purchasable" # For a hero you unlocked but haven't purchased
|
# purchasable: "Purchasable" # For a hero you unlocked but haven't purchased
|
||||||
# available: "Available"
|
available: "vorhandä"
|
||||||
# skills_granted: "Skills Granted" # Property documentation details
|
# skills_granted: "Skills Granted" # Property documentation details
|
||||||
heroes: "Helde" # Tooltip on hero shop button from /play
|
heroes: "Helde" # Tooltip on hero shop button from /play
|
||||||
achievements: "Achievements" # Tooltip on achievement list button from /play
|
achievements: "Achievements" # Tooltip on achievement list button from /play
|
||||||
|
@ -93,15 +93,15 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
# campaign_classic_algorithms: "Classic Algorithms"
|
# campaign_classic_algorithms: "Classic Algorithms"
|
||||||
# campaign_classic_algorithms_description: "... in which you learn the most popular algorithms in Computer Science."
|
# campaign_classic_algorithms_description: "... in which you learn the most popular algorithms in Computer Science."
|
||||||
|
|
||||||
# share_progress_modal:
|
share_progress_modal:
|
||||||
# blurb: "You’re making great progress! Tell someone how much you've learned with CodeCombat."
|
blurb: "Du machsch grossi Fortschritts! Verzells öperem wieviel du glernt häsch mit CodeCombat."
|
||||||
# email_invalid: "Email address invalid."
|
email_invalid: "Email Adrässä isch falsch."
|
||||||
# form_blurb: "Enter their email below and we’ll show them!"
|
# form_blurb: "Enter their email below and we’ll show them!"
|
||||||
# form_label: "Email Address"
|
form_label: "Email Adrässä"
|
||||||
# placeholder: "email address"
|
placeholder: "Email Adrässä"
|
||||||
# title: "Excellent Work, Apprentice"
|
# title: "Excellent Work, Apprentice"
|
||||||
# tell_friend: "Tell your Friend"
|
tell_friend: "Sägs dim Kolleg oder dinere Kollegin"
|
||||||
# tell_parent: "Tell your Parent"
|
tell_parent: "Sägs dinä Elterä"
|
||||||
|
|
||||||
login:
|
login:
|
||||||
sign_up: "Account erstelle"
|
sign_up: "Account erstelle"
|
||||||
|
@ -130,13 +130,13 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
send_password: "Recovery Password sende"
|
send_password: "Recovery Password sende"
|
||||||
# recovery_sent: "Recovery email sent."
|
# recovery_sent: "Recovery email sent."
|
||||||
|
|
||||||
# items:
|
items:
|
||||||
# primary: "Primary"
|
# primary: "Primary"
|
||||||
# secondary: "Secondary"
|
# secondary: "Secondary"
|
||||||
# armor: "Armor"
|
# armor: "Armor"
|
||||||
# accessories: "Accessories"
|
# accessories: "Accessories"
|
||||||
# misc: "Misc"
|
misc: "Diverses"
|
||||||
# books: "Books"
|
books: "Büecher"
|
||||||
|
|
||||||
common:
|
common:
|
||||||
# back: "Back" # When used as an action verb, like "Navigate backward"
|
# back: "Back" # When used as an action verb, like "Navigate backward"
|
||||||
|
@ -154,8 +154,8 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
play: "Spiele" # When used as an action verb, like "Play next level"
|
play: "Spiele" # When used as an action verb, like "Play next level"
|
||||||
retry: "nomol versuche"
|
retry: "nomol versuche"
|
||||||
# actions: "Actions"
|
# actions: "Actions"
|
||||||
# info: "Info"
|
info: "Info"
|
||||||
# help: "Help"
|
help: "Hilf"
|
||||||
# watch: "Watch"
|
# watch: "Watch"
|
||||||
# unwatch: "Unwatch"
|
# unwatch: "Unwatch"
|
||||||
submit_patch: "Patch ireiche"
|
submit_patch: "Patch ireiche"
|
||||||
|
@ -184,7 +184,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
# redo_shortcut: "(Ctrl+Shift+Z)"
|
# redo_shortcut: "(Ctrl+Shift+Z)"
|
||||||
# play_preview: "Play preview of current level"
|
# play_preview: "Play preview of current level"
|
||||||
result: "Resultat"
|
result: "Resultat"
|
||||||
# results: "Results"
|
results: "Resultat"
|
||||||
description: "Beschriibig"
|
description: "Beschriibig"
|
||||||
or: "oder"
|
or: "oder"
|
||||||
# subject: "Subject"
|
# subject: "Subject"
|
||||||
|
@ -205,9 +205,9 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
hard: "Schwer"
|
hard: "Schwer"
|
||||||
player: "Spieler"
|
player: "Spieler"
|
||||||
player_level: "Stufe" # Like player level 5, not like level: Dungeons of Kithgard
|
player_level: "Stufe" # Like player level 5, not like level: Dungeons of Kithgard
|
||||||
# warrior: "Warrior"
|
warrior: "Krieger"
|
||||||
# ranger: "Ranger"
|
# ranger: "Ranger"
|
||||||
# wizard: "Wizard"
|
wizard: "Zauberer"
|
||||||
|
|
||||||
units:
|
units:
|
||||||
second: "Sekunde"
|
second: "Sekunde"
|
||||||
|
@ -235,15 +235,15 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
restart: "Neu starte"
|
restart: "Neu starte"
|
||||||
goals: "Ziel"
|
goals: "Ziel"
|
||||||
goal: "Goal"
|
goal: "Goal"
|
||||||
# running: "Running..."
|
running: "s lauft..."
|
||||||
success: "Erfolg!"
|
success: "Erfolg!"
|
||||||
incomplete: "Unvollständig"
|
incomplete: "Unvollständig"
|
||||||
timed_out: "Ziit abglaufe"
|
timed_out: "Ziit abglaufe"
|
||||||
failing: "Fehler"
|
failing: "Fehler"
|
||||||
action_timeline: "Aktionsziitleiste"
|
action_timeline: "Aktionsziitleiste"
|
||||||
click_to_select: "Klick uf e Einheit zum sie uswähle."
|
click_to_select: "Klick uf e Einheit zum sie uswähle."
|
||||||
# control_bar_multiplayer: "Multiplayer"
|
control_bar_multiplayer: "Mehrspiiler"
|
||||||
# control_bar_join_game: "Join Game"
|
control_bar_join_game: "Mitspiilä"
|
||||||
reload: "Neu lade"
|
reload: "Neu lade"
|
||||||
reload_title: "De ganze Code neu lade?"
|
reload_title: "De ganze Code neu lade?"
|
||||||
reload_really: "Bisch sicher du willsch level neu lade bis zrugg zum Afang?"
|
reload_really: "Bisch sicher du willsch level neu lade bis zrugg zum Afang?"
|
||||||
|
@ -256,8 +256,8 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
victory_rate_the_level: "Bewerte das Level: " # Only in old-style levels.
|
victory_rate_the_level: "Bewerte das Level: " # Only in old-style levels.
|
||||||
victory_return_to_ladder: "Zrugg zum letzte Level"
|
victory_return_to_ladder: "Zrugg zum letzte Level"
|
||||||
victory_play_continue: "Wiiter spile"
|
victory_play_continue: "Wiiter spile"
|
||||||
# victory_saving_progress: "Saving Progress"
|
victory_saving_progress: "Fortschritt abspaicherä"
|
||||||
# victory_go_home: "Go Home" # Only in old-style levels.
|
victory_go_home: "Goon Hai" # Only in old-style levels.
|
||||||
victory_review: "Verzell üs meh!" # Only in old-style levels.
|
victory_review: "Verzell üs meh!" # Only in old-style levels.
|
||||||
victory_hour_of_code_done: "Bisch fertig?"
|
victory_hour_of_code_done: "Bisch fertig?"
|
||||||
victory_hour_of_code_done_yes: "Jo, ich bin fertig mit mim Hour of Code™!"
|
victory_hour_of_code_done_yes: "Jo, ich bin fertig mit mim Hour of Code™!"
|
||||||
|
@ -272,21 +272,21 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
# tome_cast_button_ran: "Ran"
|
# tome_cast_button_ran: "Ran"
|
||||||
# tome_submit_button: "Submit"
|
# tome_submit_button: "Submit"
|
||||||
# tome_reload_method: "Reload original code for this method" # Title text for individual method reload button.
|
# tome_reload_method: "Reload original code for this method" # Title text for individual method reload button.
|
||||||
# tome_select_method: "Select a Method"
|
tome_select_method: "Wähl a Methodä"
|
||||||
# tome_see_all_methods: "See all methods you can edit" # Title text for method list selector (shown when there are multiple programmable methdos).
|
# tome_see_all_methods: "See all methods you can edit" # Title text for method list selector (shown when there are multiple programmable methdos).
|
||||||
tome_select_a_thang: "Wähl öpper us für"
|
tome_select_a_thang: "Wähl öpper us für"
|
||||||
tome_available_spells: "Verfüegbari Zaubersprüch"
|
tome_available_spells: "Verfüegbari Zaubersprüch"
|
||||||
# tome_your_skills: "Your Skills"
|
tome_your_skills: "Dini Fähigkaitä"
|
||||||
tome_help: "Hilf"
|
tome_help: "Hilf"
|
||||||
# tome_current_method: "Current Method"
|
tome_current_method: "Aktuelli Modus"
|
||||||
# hud_continue_short: "Continue"
|
hud_continue_short: "Wiitermache"
|
||||||
code_saved: "Code gpeicheret"
|
code_saved: "Code gpeicheret"
|
||||||
skip_tutorial: "Überspringe (esc)"
|
skip_tutorial: "Überspringe (esc)"
|
||||||
keyboard_shortcuts: "Shortcuts"
|
keyboard_shortcuts: "Shortcuts"
|
||||||
# loading_ready: "Ready!"
|
loading_ready: "Berait!"
|
||||||
loading_start: "Level starte"
|
loading_start: "Level starte"
|
||||||
# problem_alert_title: "Fix Your Code"
|
problem_alert_title: "Reparier diin Code"
|
||||||
# problem_alert_help: "Help"
|
problem_alert_help: "Hilf"
|
||||||
time_current: "Jetzt:"
|
time_current: "Jetzt:"
|
||||||
time_total: "Max:"
|
time_total: "Max:"
|
||||||
time_goto: "Goh zu:"
|
time_goto: "Goh zu:"
|
||||||
|
@ -341,18 +341,18 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
|
|
||||||
game_menu:
|
game_menu:
|
||||||
# inventory_tab: "Inventory"
|
# inventory_tab: "Inventory"
|
||||||
# save_load_tab: "Save/Load"
|
save_load_tab: "Spaicherä/Ladä"
|
||||||
# options_tab: "Options"
|
options_tab: "Optionä"
|
||||||
# guide_tab: "Guide"
|
# guide_tab: "Guide"
|
||||||
# guide_video_tutorial: "Video Tutorial"
|
# guide_video_tutorial: "Video Tutorial"
|
||||||
# guide_tips: "Tips"
|
guide_tips: "Tipps"
|
||||||
multiplayer_tab: "Multiplayer"
|
multiplayer_tab: "Multiplayer"
|
||||||
# auth_tab: "Sign Up"
|
# auth_tab: "Sign Up"
|
||||||
# inventory_caption: "Equip your hero"
|
# inventory_caption: "Equip your hero"
|
||||||
# choose_hero_caption: "Choose hero, language"
|
# choose_hero_caption: "Choose hero, language"
|
||||||
# save_load_caption: "... and view history"
|
# save_load_caption: "... and view history"
|
||||||
# options_caption: "Configure settings"
|
# options_caption: "Configure settings"
|
||||||
# guide_caption: "Docs and tips"
|
guide_caption: "Doku und Tipps"
|
||||||
# multiplayer_caption: "Play with friends!"
|
# multiplayer_caption: "Play with friends!"
|
||||||
# auth_caption: "Save your progress."
|
# auth_caption: "Save your progress."
|
||||||
|
|
||||||
|
|
|
@ -454,8 +454,8 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
||||||
no_users_subscribed: "No se suscribieron usuarios, por favor revisa las direcciones de email."
|
no_users_subscribed: "No se suscribieron usuarios, por favor revisa las direcciones de email."
|
||||||
current_recipients: "Recipientes actuales"
|
current_recipients: "Recipientes actuales"
|
||||||
unsubscribing: "Desuscribiendo..."
|
unsubscribing: "Desuscribiendo..."
|
||||||
# subscribe_prepaid: "Click Subscribe to use prepaid code"
|
subscribe_prepaid: "Click en suscribirse para utlizar un código prepago"
|
||||||
# using_prepaid: "Using prepaid code for monthly subscription"
|
using_prepaid: "Usar código prepago para una suscribción mensual"
|
||||||
|
|
||||||
choose_hero:
|
choose_hero:
|
||||||
choose_hero: "Elige tu héroe"
|
choose_hero: "Elige tu héroe"
|
||||||
|
@ -572,40 +572,40 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
||||||
josh_blurb: "El piso es Lava"
|
josh_blurb: "El piso es Lava"
|
||||||
jose_title: "Música"
|
jose_title: "Música"
|
||||||
jose_blurb: "Despegar"
|
jose_blurb: "Despegar"
|
||||||
retrostyle_title: "Ilustracin"
|
retrostyle_title: "Ilustración"
|
||||||
retrostyle_blurb: "Juegos con estilo Retro"
|
retrostyle_blurb: "Juegos con estilo Retro"
|
||||||
|
|
||||||
teachers:
|
teachers:
|
||||||
title: "CodeCombat para Profesores" # {change}
|
title: "CodeCombat para Profesores" # {change}
|
||||||
# intro_1: "CodeCombat is an online game that teaches programming. Students write code in real programming languages."
|
intro_1: "CodeCombat es un juego online que enseña a programar.Los estudiantes escriben código en idiomas de programación real."
|
||||||
# intro_2: "No experience required!"
|
intro_2: "No se necesita experiencia previa!"
|
||||||
# free_title: "How much does it cost?"
|
free_title: "¿Cuanto cuesta?"
|
||||||
# cost_china: "CodeCombat in China is free for the first five levels, after which it costs $9.99 per month for access to our other 120+ levels on our exclusive China servers."
|
# cost_china: "CodeCombat in China is free for the first five levels, after which it costs $9.99 per month for access to our other 120+ levels on our exclusive China servers."
|
||||||
# free_1: "CodeCombat Basic is FREE! There are 70+ free levels which cover every concept."
|
# free_1: "CodeCombat Basic is FREE! There are 70+ free levels which cover every concept."
|
||||||
# free_2: "A monthly subscription provides access to video tutorials and extra practice levels."
|
# free_2: "A monthly subscription provides access to video tutorials and extra practice levels."
|
||||||
# teacher_subs_title: "Teachers get free subscriptions!"
|
teacher_subs_title: "¡Los amestros obtienen subscripciones gratuitas!"
|
||||||
# teacher_subs_1: "Please contact"
|
# teacher_subs_1: "Please contact"
|
||||||
# teacher_subs_2: "to set up a free monthly subscription."
|
teacher_subs_2: "to set up a free monthly subscriptiron."
|
||||||
# sub_includes_title: "What is included in the subscription?"
|
sub_includes_title: "¿Qué se incluye en la suscripción?"
|
||||||
# sub_includes_1: "In additional to the 70+ basic levels, students with a monthly subscription get access to these additional features:"
|
sub_includes_1: "Adicionalmente a los más de 70 niveles básicos, los estudiantes con una suscripción mensual obtienen acceso a estas características adicionales:"
|
||||||
# sub_includes_2: "40+ practice levels"
|
sub_includes_2: "Más de 40 niveles de práctica"
|
||||||
# sub_includes_3: "Video tutorials"
|
sub_includes_3: "Video tutoriales"
|
||||||
# sub_includes_4: "Premium email support"
|
# sub_includes_4: "Premium email support"
|
||||||
# sub_includes_5: "7 new heroes with unique skills to master"
|
sub_includes_5: "7 heroes nuevos con habilidades unicas que dominar"
|
||||||
# sub_includes_6: "3500 bonus gems every month"
|
sub_includes_6: "bonificación de 3500 gemas cada mes"
|
||||||
# who_for_title: "Who is CodeCombat for?"
|
who_for_title: "¿Para quienes es CodeCombat?"
|
||||||
# who_for_1: "We recommend CodeCombat for students aged 9 and up. No prior programming experience is needed."
|
# who_for_1: "We recommend CodeCombat for students aged 9 and up. No prior programming experience is needed."
|
||||||
# who_for_2: "We've designed CodeCombat to appeal to both boys and girls."
|
# who_for_2: "We've designed CodeCombat to appeal to both boys and girls."
|
||||||
# material_title: "How much material is there?"
|
# material_title: "How much material is there?"
|
||||||
# material_china: "Approximately 22 hours of gameplay spread over 120+ subscriber-only levels so far, with 5 new levels every week."
|
# material_china: "Approximately 22 hours of gameplay spread over 120+ subscriber-only levels so far, with 5 new levels every week."
|
||||||
# material_1: "Approximately 8 hours of free content and an additional 14 hours of subscriber content, with 5 new levels every week."
|
# material_1: "Approximately 8 hours of free content and an additional 14 hours of subscriber content, with 5 new levels every week."
|
||||||
# concepts_title: "What concepts are covered?"
|
# concepts_title: "What concepts are covered?"
|
||||||
# how_much_title: "How much does a monthly subscription cost?"
|
how_much_title: "¿Cuánto cuesta una subscripción mensual?"
|
||||||
# how_much_1: "A"
|
how_much_1: "una"
|
||||||
# how_much_2: "monthly subscription"
|
how_much_2: "suscribción mensual"
|
||||||
# how_much_3: "costs $9.99, and can be cancelled anytime."
|
how_much_3: "Cuesta u$s9.99, y puede ser cancelada en cualquier momento."
|
||||||
# how_much_4: "Additionally, we provide discounts for larger groups:"
|
how_much_4: "Adicionalmente, nosotros otorgamos descuentos a grupos grandes:"
|
||||||
# group_discounts_1: "We also offer group discounts for bulk subscriptions."
|
group_discounts_1: "También ofrecemos descuentes grupales para suscripciones en masa."
|
||||||
sys_requirements_title: "Requerimientos del sistema"
|
sys_requirements_title: "Requerimientos del sistema"
|
||||||
sys_requirements_1: "Debido que CodeCombat es un juego, es más difícil para las computadoras correrlo en relación a un tutorial escrito o un video. Para que todos puedan jugar, hemos optimizado la web para correr rápidamente en todos los navegadores modernos y en maquinas antiguas. Dicho esto, aquí están nuestras sugerencias para sacar el máximo provecho de su experiencia en la Hora del Código:" # {change}
|
sys_requirements_1: "Debido que CodeCombat es un juego, es más difícil para las computadoras correrlo en relación a un tutorial escrito o un video. Para que todos puedan jugar, hemos optimizado la web para correr rápidamente en todos los navegadores modernos y en maquinas antiguas. Dicho esto, aquí están nuestras sugerencias para sacar el máximo provecho de su experiencia en la Hora del Código:" # {change}
|
||||||
sys_requirements_2: "Usar una versión actualizada del navegador Chrome o Firefox." # {change}
|
sys_requirements_2: "Usar una versión actualizada del navegador Chrome o Firefox." # {change}
|
||||||
|
@ -941,7 +941,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
||||||
fight: "Pelea!"
|
fight: "Pelea!"
|
||||||
watch_victory: "Observa tu Victoria"
|
watch_victory: "Observa tu Victoria"
|
||||||
defeat_the: "Derrota a"
|
defeat_the: "Derrota a"
|
||||||
# tournament_started: ", started"
|
tournament_started: ", iniciado"
|
||||||
tournament_ends: "Final de Torneo"
|
tournament_ends: "Final de Torneo"
|
||||||
tournament_ended: "Finalizó el Torneo"
|
tournament_ended: "Finalizó el Torneo"
|
||||||
tournament_rules: "Reglas del Torneo"
|
tournament_rules: "Reglas del Torneo"
|
||||||
|
|
|
@ -64,7 +64,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
achievements: "Logros" # Tooltip on achievement list button from /play
|
achievements: "Logros" # Tooltip on achievement list button from /play
|
||||||
account: "Cuenta" # Tooltip on account button from /play
|
account: "Cuenta" # Tooltip on account button from /play
|
||||||
settings: "Ajustes" # Tooltip on settings button from /play
|
settings: "Ajustes" # Tooltip on settings button from /play
|
||||||
# poll: "Poll" # Tooltip on poll button from /play
|
poll: "Encuesta" # Tooltip on poll button from /play
|
||||||
next: "Siguiente Heroe" # Go from choose hero to choose inventory before playing a level
|
next: "Siguiente Heroe" # Go from choose hero to choose inventory before playing a level
|
||||||
change_hero: "Seleccionar Heroe" # Go back from choose inventory to choose hero
|
change_hero: "Seleccionar Heroe" # Go back from choose inventory to choose hero
|
||||||
choose_inventory: "Equipar Objetos"
|
choose_inventory: "Equipar Objetos"
|
||||||
|
@ -77,7 +77,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
awaiting_levels_adventurer_prefix: "Liberamos cinco niveles cada semana."
|
awaiting_levels_adventurer_prefix: "Liberamos cinco niveles cada semana."
|
||||||
awaiting_levels_adventurer: "Regístrate como Aventurero"
|
awaiting_levels_adventurer: "Regístrate como Aventurero"
|
||||||
awaiting_levels_adventurer_suffix: "para ser el primero en jugar nuevos niveles."
|
awaiting_levels_adventurer_suffix: "para ser el primero en jugar nuevos niveles."
|
||||||
# adjust_volume: "Adjust volume"
|
adjust_volume: "Ajustar volúmen"
|
||||||
choose_your_level: "Elige tu nivel" # The rest of this section is the old play view at /play-old and isn't very important.
|
choose_your_level: "Elige tu nivel" # The rest of this section is the old play view at /play-old and isn't very important.
|
||||||
adventurer_prefix: "Puedes elegir cualquier pantalla o charlar en "
|
adventurer_prefix: "Puedes elegir cualquier pantalla o charlar en "
|
||||||
adventurer_forum: "el foro del aventurero "
|
adventurer_forum: "el foro del aventurero "
|
||||||
|
@ -93,15 +93,15 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
campaign_classic_algorithms: "Algoritmos Clasicos"
|
campaign_classic_algorithms: "Algoritmos Clasicos"
|
||||||
campaign_classic_algorithms_description: "... donde aprendes los algoritmos mas populares de la informatica."
|
campaign_classic_algorithms_description: "... donde aprendes los algoritmos mas populares de la informatica."
|
||||||
|
|
||||||
# share_progress_modal:
|
share_progress_modal:
|
||||||
# blurb: "You’re making great progress! Tell someone how much you've learned with CodeCombat."
|
blurb: "¡Estás teniendo un gran progreso! Cuéntale a alguien que tanto habeis aprendido con CodeCombat."
|
||||||
# email_invalid: "Email address invalid."
|
email_invalid: "La dirección de correo electrónico no es válida."
|
||||||
# form_blurb: "Enter their email below and we’ll show them!"
|
form_blurb: "¡Introduzca su correo electrónico y nosotros les mostraremos!"
|
||||||
# form_label: "Email Address"
|
form_label: "Correo Electrónico"
|
||||||
# placeholder: "email address"
|
placeholder: "correo electrónico"
|
||||||
# title: "Excellent Work, Apprentice"
|
title: "Excelente Trabajo Aprendiz"
|
||||||
# tell_friend: "Tell your Friend"
|
tell_friend: "Decirle a un amigo"
|
||||||
# tell_parent: "Tell your Parent"
|
tell_parent: "Decirle a mis padres"
|
||||||
|
|
||||||
login:
|
login:
|
||||||
sign_up: "Crear una cuenta"
|
sign_up: "Crear una cuenta"
|
||||||
|
@ -139,8 +139,8 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
books: "Libros"
|
books: "Libros"
|
||||||
|
|
||||||
common:
|
common:
|
||||||
# back: "Back" # When used as an action verb, like "Navigate backward"
|
back: "Volver" # When used as an action verb, like "Navigate backward"
|
||||||
# continue: "Continue" # When used as an action verb, like "Continue forward"
|
continue: "Continuar" # When used as an action verb, like "Continue forward"
|
||||||
loading: "Cargando..."
|
loading: "Cargando..."
|
||||||
saving: "Guardando..."
|
saving: "Guardando..."
|
||||||
sending: "Enviando..."
|
sending: "Enviando..."
|
||||||
|
@ -154,7 +154,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
play: "Jugar" # When used as an action verb, like "Play next level"
|
play: "Jugar" # When used as an action verb, like "Play next level"
|
||||||
retry: "Reintentar"
|
retry: "Reintentar"
|
||||||
actions: "Acciones"
|
actions: "Acciones"
|
||||||
# info: "Info"
|
info: "Información"
|
||||||
help: "Ayuda"
|
help: "Ayuda"
|
||||||
watch: "Mirar"
|
watch: "Mirar"
|
||||||
unwatch: "Pasar"
|
unwatch: "Pasar"
|
||||||
|
@ -172,16 +172,16 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
rejected: "Rechazado"
|
rejected: "Rechazado"
|
||||||
# withdrawn: "Withdrawn"
|
# withdrawn: "Withdrawn"
|
||||||
# submitter: "Submitter"
|
# submitter: "Submitter"
|
||||||
# submitted: "Submitted"
|
submitted: "Enviado"
|
||||||
commit_msg: "Mensaje de Asignación o Commit"
|
commit_msg: "Mensaje de Asignación o Commit"
|
||||||
# review: "Review"
|
# review: "Review"
|
||||||
version_history: "Historial de versión"
|
version_history: "Historial de versión"
|
||||||
version_history_for: "Historial de las versiones de: "
|
version_history_for: "Historial de las versiones de: "
|
||||||
select_changes: "Selecciona dos cambios más abajo para ver la diferencia."
|
select_changes: "Selecciona dos cambios más abajo para ver la diferencia."
|
||||||
undo_prefix: "Deshacer"
|
undo_prefix: "Deshacer"
|
||||||
# undo_shortcut: "(Ctrl+Z)"
|
undo_shortcut: "(Ctrl+Z)"
|
||||||
redo_prefix: "Rehacer"
|
redo_prefix: "Rehacer"
|
||||||
# redo_shortcut: "(Ctrl+Shift+Z)"
|
redo_shortcut: "(Ctrl+Shift+Z)" #tal vez sea mejor usar el común Control+Y
|
||||||
play_preview: "Reproducir una vista previa del nivel actual"
|
play_preview: "Reproducir una vista previa del nivel actual"
|
||||||
result: "Resultado"
|
result: "Resultado"
|
||||||
results: "Resultados"
|
results: "Resultados"
|
||||||
|
@ -205,8 +205,8 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
hard: "Difícil"
|
hard: "Difícil"
|
||||||
player: "Jugador"
|
player: "Jugador"
|
||||||
player_level: "Nivel" # Like player level 5, not like level: Dungeons of Kithgard
|
player_level: "Nivel" # Like player level 5, not like level: Dungeons of Kithgard
|
||||||
# warrior: "Warrior"
|
warrior: "Guerrero"
|
||||||
# ranger: "Ranger"
|
# ranger: "Ranger" #guardabosques?
|
||||||
wizard: "Mago"
|
wizard: "Mago"
|
||||||
|
|
||||||
units:
|
units:
|
||||||
|
@ -326,18 +326,18 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
tip_superpower: "Programar es lo más parecido que tenemos a un superpoder."
|
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_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_no_code: "No code is faster than no code."
|
||||||
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
|
tip_code_never_lies: "El código nunca os miente, los comentarios algunas veces. — Ron Jeffries"
|
||||||
# tip_reusable_software: "Before software can be reusable it first has to be usable."
|
# 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_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"
|
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
|
||||||
# tip_source_code: "I want to change the world but they would not give me the source code."
|
# tip_source_code: "I want to change the world but they would not give me the source code."
|
||||||
# tip_javascript_java: "Java is to JavaScript what Car is to Carpet. - Chris Heilmann"
|
# tip_javascript_java: "Java is to JavaScript what Car is to Carpet. - Chris Heilmann"
|
||||||
# tip_move_forward: "Whatever you do, keep moving forward. - Martin Luther King Jr."
|
# tip_move_forward: "Whatever you do, keep moving forward. - Martin Luther King Jr."
|
||||||
# tip_google: "Have a problem you can't solve? Google it!"
|
tip_google: "¿Teneis un problema que no podeis resolver? ¡Googleadlo!"
|
||||||
# tip_adding_evil: "Adding a pinch of evil."
|
# tip_adding_evil: "Adding a pinch of evil."
|
||||||
# tip_hate_computers: "That's the thing about people who think they hate computers. What they really hate is lousy programmers. - Larry Niven"
|
# tip_hate_computers: "That's the thing about people who think they hate computers. What they really hate is lousy programmers. - Larry Niven"
|
||||||
# tip_open_source_contribute: "You can help CodeCombat improve!"
|
# tip_open_source_contribute: "You can help CodeCombat improve!"
|
||||||
# tip_recurse: "To iterate is human, to recurse divine. - L. Peter Deutsch"
|
tip_recurse: "Iterar es humano, recursar es divino. - L. Peter Deutsch"
|
||||||
|
|
||||||
game_menu:
|
game_menu:
|
||||||
inventory_tab: "Inventario"
|
inventory_tab: "Inventario"
|
||||||
|
@ -356,18 +356,18 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
multiplayer_caption: "Juega con amigos!"
|
multiplayer_caption: "Juega con amigos!"
|
||||||
auth_caption: "Salvar tu progreso."
|
auth_caption: "Salvar tu progreso."
|
||||||
|
|
||||||
# leaderboard:
|
leaderboard:
|
||||||
# leaderboard: "Leaderboard"
|
# leaderboard: "Leaderboard"
|
||||||
# view_other_solutions: "View Other Solutions"
|
# view_other_solutions: "View Other Solutions"
|
||||||
# scores: "Scores"
|
scores: "Puntuaciones"
|
||||||
# top_players: "Top Players by"
|
# top_players: "Top Players by"
|
||||||
# day: "Today"
|
day: "Hoy"
|
||||||
# week: "This Week"
|
week: "Esta semana"
|
||||||
# all: "All-Time"
|
# all: "All-Time"
|
||||||
# time: "Time"
|
# time: "Time"
|
||||||
# damage_taken: "Damage Taken"
|
# damage_taken: "Damage Taken"
|
||||||
# damage_dealt: "Damage Dealt"
|
# damage_dealt: "Damage Dealt"
|
||||||
# difficulty: "Difficulty"
|
difficulty: "Difficultad"
|
||||||
# gold_collected: "Gold Collected"
|
# gold_collected: "Gold Collected"
|
||||||
|
|
||||||
inventory:
|
inventory:
|
||||||
|
@ -402,16 +402,16 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
|
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
|
||||||
# feature3: "30+ bonus levels"
|
# feature3: "30+ bonus levels"
|
||||||
# feature4: "<strong>3500 bonus gems</strong> every month!"
|
# feature4: "<strong>3500 bonus gems</strong> every month!"
|
||||||
# feature5: "Video tutorials"
|
feature5: "Vídeo tutoriales"
|
||||||
# feature6: "Premium email support"
|
# feature6: "Premium email support"
|
||||||
# free: "Free"
|
free: "Gratis"
|
||||||
# month: "month"
|
month: "mes"
|
||||||
subscribe_title: "Suscríbete"
|
subscribe_title: "Suscríbete"
|
||||||
# unsubscribe: "Unsubscribe"
|
# unsubscribe: "Unsubscribe"
|
||||||
# confirm_unsubscribe: "Confirm Unsubscribe"
|
# confirm_unsubscribe: "Confirm Unsubscribe"
|
||||||
# never_mind: "Never Mind, I Still Love You"
|
# never_mind: "Never Mind, I Still Love You"
|
||||||
# thank_you_months_prefix: "Thank you for supporting us these last"
|
# thank_you_months_prefix: "Thank you for supporting us these last"
|
||||||
# thank_you_months_suffix: "months."
|
thank_you_months_suffix: "meses."
|
||||||
# thank_you: "Thank you for supporting CodeCombat."
|
# thank_you: "Thank you for supporting CodeCombat."
|
||||||
# sorry_to_see_you_go: "Sorry to see you go! Please let us know what we could have done better."
|
# sorry_to_see_you_go: "Sorry to see you go! Please let us know what we could have done better."
|
||||||
# unsubscribe_feedback_placeholder: "O, what have we done?"
|
# unsubscribe_feedback_placeholder: "O, what have we done?"
|
||||||
|
@ -470,7 +470,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
lua_blurb: "Lenguaje Script para Juegos."
|
lua_blurb: "Lenguaje Script para Juegos."
|
||||||
io_blurb: "Simple pero oscuro."
|
io_blurb: "Simple pero oscuro."
|
||||||
status: "Estado"
|
status: "Estado"
|
||||||
# hero_type: "Type"
|
hero_type: "Tipo"
|
||||||
weapons: "Armas"
|
weapons: "Armas"
|
||||||
weapons_warrior: "Espadas - Corto Alcance, Sin Magia"
|
weapons_warrior: "Espadas - Corto Alcance, Sin Magia"
|
||||||
weapons_ranger: "Ballestas, Pistolas - Largo Alcance, Sin Magia"
|
weapons_ranger: "Ballestas, Pistolas - Largo Alcance, Sin Magia"
|
||||||
|
@ -570,12 +570,12 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
# cat_blurb: "Airbender"
|
# cat_blurb: "Airbender"
|
||||||
# josh_title: "Game Designer"
|
# josh_title: "Game Designer"
|
||||||
# josh_blurb: "Floor Is Lava"
|
# josh_blurb: "Floor Is Lava"
|
||||||
# jose_title: "Music"
|
jose_title: "Música"
|
||||||
# jose_blurb: "Taking Off"
|
# jose_blurb: "Taking Off"
|
||||||
# retrostyle_title: "Illustration"
|
# retrostyle_title: "Illustration"
|
||||||
# retrostyle_blurb: "RetroStyle Games"
|
# retrostyle_blurb: "RetroStyle Games"
|
||||||
|
|
||||||
# teachers:
|
teachers:
|
||||||
# title: "CodeCombat: Info for Teachers"
|
# title: "CodeCombat: Info for Teachers"
|
||||||
# intro_1: "CodeCombat is an online game that teaches programming. Students write code in real programming languages."
|
# intro_1: "CodeCombat is an online game that teaches programming. Students write code in real programming languages."
|
||||||
# intro_2: "No experience required!"
|
# intro_2: "No experience required!"
|
||||||
|
@ -602,7 +602,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
# concepts_title: "What concepts are covered?"
|
# concepts_title: "What concepts are covered?"
|
||||||
# how_much_title: "How much does a monthly subscription cost?"
|
# how_much_title: "How much does a monthly subscription cost?"
|
||||||
# how_much_1: "A"
|
# how_much_1: "A"
|
||||||
# how_much_2: "monthly subscription"
|
how_much_2: "suscripción mensual"
|
||||||
# how_much_3: "costs $9.99, and can be cancelled anytime."
|
# how_much_3: "costs $9.99, and can be cancelled anytime."
|
||||||
# how_much_4: "Additionally, we provide discounts for larger groups:"
|
# how_much_4: "Additionally, we provide discounts for larger groups:"
|
||||||
# group_discounts_1: "We also offer group discounts for bulk subscriptions."
|
# group_discounts_1: "We also offer group discounts for bulk subscriptions."
|
||||||
|
@ -751,7 +751,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
pick_a_terrain: "Escoge un Terreno"
|
pick_a_terrain: "Escoge un Terreno"
|
||||||
# dungeon: "Dungeon"
|
# dungeon: "Dungeon"
|
||||||
# indoor: "Indoor"
|
# indoor: "Indoor"
|
||||||
# desert: "Desert"
|
desert: "Desierto" #desert like take a desert in desert? :P
|
||||||
grassy: "Cubierto de hierba"
|
grassy: "Cubierto de hierba"
|
||||||
small: "Pequeño"
|
small: "Pequeño"
|
||||||
# large: "Large"
|
# large: "Large"
|
||||||
|
@ -818,7 +818,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
# achievement_query_goals: "Key achievement off of level goals"
|
# achievement_query_goals: "Key achievement off of level goals"
|
||||||
level_completion: "Porcentaje de Nivel Completado"
|
level_completion: "Porcentaje de Nivel Completado"
|
||||||
pop_i18n: "Poblar I18N"
|
pop_i18n: "Poblar I18N"
|
||||||
# tasks: "Tasks"
|
tasks: "Tareas"
|
||||||
# clear_storage: "Clear your local changes"
|
# clear_storage: "Clear your local changes"
|
||||||
|
|
||||||
article:
|
article:
|
||||||
|
@ -998,11 +998,11 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
service: "Servicio"
|
service: "Servicio"
|
||||||
price: "Precio"
|
price: "Precio"
|
||||||
gems: "Joyas"
|
gems: "Joyas"
|
||||||
# active: "Active"
|
active: "Activo"
|
||||||
# subscribed: "Subscribed"
|
# subscribed: "Subscribed"
|
||||||
# unsubscribed: "Unsubscribed"
|
# unsubscribed: "Unsubscribed"
|
||||||
# active_until: "Active Until"
|
# active_until: "Active Until"
|
||||||
# cost: "Cost"
|
cost: "Costo"
|
||||||
next_payment: "Siguiente Pago"
|
next_payment: "Siguiente Pago"
|
||||||
card: "Tarjeta"
|
card: "Tarjeta"
|
||||||
status_unsubscribed_active: "No estás suscrito y no seras facturado, pero tu cuenta sigue activa por ahora."
|
status_unsubscribed_active: "No estás suscrito y no seras facturado, pero tu cuenta sigue activa por ahora."
|
||||||
|
@ -1078,7 +1078,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
feedback: "Apoyo"
|
feedback: "Apoyo"
|
||||||
payment_info: "Información de Pago"
|
payment_info: "Información de Pago"
|
||||||
# campaigns: "Campaigns"
|
# campaigns: "Campaigns"
|
||||||
# poll: "Poll"
|
poll: "Encuesta"
|
||||||
# user_polls_record: "Poll Voting History"
|
# user_polls_record: "Poll Voting History"
|
||||||
|
|
||||||
delta:
|
delta:
|
||||||
|
|
|
@ -2,8 +2,8 @@ RootView = require 'views/core/RootView'
|
||||||
template = require 'templates/admin/analytics-subscriptions'
|
template = require 'templates/admin/analytics-subscriptions'
|
||||||
RealTimeCollection = require 'collections/RealTimeCollection'
|
RealTimeCollection = require 'collections/RealTimeCollection'
|
||||||
|
|
||||||
|
# TODO: Add last N subscribers table
|
||||||
# TODO: Add revenue line
|
# TODO: Add revenue line
|
||||||
# TODO: Add LTV line
|
|
||||||
# TODO: Graphing code copied/mangled from campaign editor level view. OMG, DRY.
|
# TODO: Graphing code copied/mangled from campaign editor level view. OMG, DRY.
|
||||||
|
|
||||||
require 'vendor/d3'
|
require 'vendor/d3'
|
||||||
|
@ -14,14 +14,15 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
|
|
||||||
constructor: (options) ->
|
constructor: (options) ->
|
||||||
super options
|
super options
|
||||||
|
@resetData()
|
||||||
if me.isAdmin()
|
if me.isAdmin()
|
||||||
@refreshData()
|
@refreshData()
|
||||||
_.delay (=> @refreshData()), 30 * 60 * 1000
|
_.delay (=> @refreshData()), 30 * 60 * 1000
|
||||||
|
|
||||||
getRenderData: ->
|
getRenderData: ->
|
||||||
context = super()
|
context = super()
|
||||||
context.analytics = @analytics
|
context.analytics = @analytics ? graphs: []
|
||||||
context.subs = @subs ? []
|
context.subs = _.cloneDeep(@subs ? []).reverse()
|
||||||
context.total = @total ? 0
|
context.total = @total ? 0
|
||||||
context.cancelled = @cancelled ? 0
|
context.cancelled = @cancelled ? 0
|
||||||
context.monthlyChurn = @monthlyChurn ? 0.0
|
context.monthlyChurn = @monthlyChurn ? 0.0
|
||||||
|
@ -31,14 +32,26 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
super()
|
super()
|
||||||
@updateAnalyticsGraphs()
|
@updateAnalyticsGraphs()
|
||||||
|
|
||||||
refreshData: ->
|
resetData: ->
|
||||||
return unless me.isAdmin()
|
|
||||||
@analytics = graphs: []
|
@analytics = graphs: []
|
||||||
@subs = []
|
@subs = []
|
||||||
@total = 0
|
@total = 0
|
||||||
@cancelled = 0
|
@cancelled = 0
|
||||||
@monthlyChurn = 0.0
|
@monthlyChurn = 0.0
|
||||||
onSuccess = (subs) =>
|
|
||||||
|
refreshData: ->
|
||||||
|
return unless me.isAdmin()
|
||||||
|
@resetData()
|
||||||
|
|
||||||
|
options =
|
||||||
|
url: '/db/subscription/-/subscriptions'
|
||||||
|
method: 'GET'
|
||||||
|
options.error = (model, response, options) =>
|
||||||
|
return if @destroyed
|
||||||
|
console.error 'Failed to get subscriptions', response
|
||||||
|
options.success = (subs, response, options) =>
|
||||||
|
return if @destroyed
|
||||||
|
@resetData()
|
||||||
subDayMap = {}
|
subDayMap = {}
|
||||||
for sub in subs
|
for sub in subs
|
||||||
startDay = sub.start.substring(0, 10)
|
startDay = sub.start.substring(0, 10)
|
||||||
|
@ -63,15 +76,9 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
sub.total = @total
|
sub.total = @total
|
||||||
startedLastMonth += sub.started if @subs.length - i < 31
|
startedLastMonth += sub.started if @subs.length - i < 31
|
||||||
@monthlyChurn = @cancelled / startedLastMonth * 100.0
|
@monthlyChurn = @cancelled / startedLastMonth * 100.0
|
||||||
|
|
||||||
@updateAnalyticsGraphData()
|
@updateAnalyticsGraphData()
|
||||||
@render()
|
@render?()
|
||||||
@supermodel.addRequestResource('subscriptions', {
|
@supermodel.addRequestResource('get_subscriptions', options, 0).load()
|
||||||
url: '/db/subscription/-/subscriptions'
|
|
||||||
method: 'GET'
|
|
||||||
success: onSuccess
|
|
||||||
}, 0).load()
|
|
||||||
|
|
||||||
|
|
||||||
updateAnalyticsGraphData: ->
|
updateAnalyticsGraphData: ->
|
||||||
# console.log 'updateAnalyticsGraphData'
|
# console.log 'updateAnalyticsGraphData'
|
||||||
|
@ -79,6 +86,8 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
# Currently only one graph
|
# Currently only one graph
|
||||||
@analytics.graphs = [graphID: 'total-subs', lines: []]
|
@analytics.graphs = [graphID: 'total-subs', lines: []]
|
||||||
|
|
||||||
|
timeframeDays = 60
|
||||||
|
|
||||||
return unless @subs?.length > 0
|
return unless @subs?.length > 0
|
||||||
|
|
||||||
# TODO: Where should this metadata live?
|
# TODO: Where should this metadata live?
|
||||||
|
@ -86,16 +95,24 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
totalSubsID = 'total-subs'
|
totalSubsID = 'total-subs'
|
||||||
startedSubsID = 'started-subs'
|
startedSubsID = 'started-subs'
|
||||||
cancelledSubsID = 'cancelled-subs'
|
cancelledSubsID = 'cancelled-subs'
|
||||||
|
netSubsID = 'net-subs'
|
||||||
lineMetadata = {}
|
lineMetadata = {}
|
||||||
lineMetadata[totalSubsID] =
|
lineMetadata[totalSubsID] =
|
||||||
description: 'Total Active Subscriptions'
|
description: 'Total Active Subscriptions'
|
||||||
color: 'green'
|
color: 'green'
|
||||||
|
strokeWidth: 1
|
||||||
lineMetadata[startedSubsID] =
|
lineMetadata[startedSubsID] =
|
||||||
description: 'New Subscriptions'
|
description: 'New Subscriptions'
|
||||||
color: 'blue'
|
color: 'blue'
|
||||||
|
strokeWidth: 1
|
||||||
lineMetadata[cancelledSubsID] =
|
lineMetadata[cancelledSubsID] =
|
||||||
description: 'Cancelled Subscriptions'
|
description: 'Cancelled Subscriptions'
|
||||||
color: 'red'
|
color: 'red'
|
||||||
|
strokeWidth: 1
|
||||||
|
lineMetadata[netSubsID] =
|
||||||
|
description: '7-day Average Net Subscriptions'
|
||||||
|
color: 'black'
|
||||||
|
strokeWidth: 4
|
||||||
|
|
||||||
days = (sub.day for sub in @subs)
|
days = (sub.day for sub in @subs)
|
||||||
if days.length > 0
|
if days.length > 0
|
||||||
|
@ -132,7 +149,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
levelPoints[i].x = i
|
levelPoints[i].x = i
|
||||||
levelPoints[i].pointID = "#{totalSubsID}#{i}"
|
levelPoints[i].pointID = "#{totalSubsID}#{i}"
|
||||||
|
|
||||||
levelPoints.splice(0, levelPoints.length - 60) if levelPoints.length > 60
|
levelPoints.splice(0, levelPoints.length - timeframeDays) if levelPoints.length > timeframeDays
|
||||||
|
|
||||||
@analytics.graphs[0].lines.push
|
@analytics.graphs[0].lines.push
|
||||||
lineID: totalSubsID
|
lineID: totalSubsID
|
||||||
|
@ -166,7 +183,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
levelPoints[i].x = i
|
levelPoints[i].x = i
|
||||||
levelPoints[i].pointID = "#{startedSubsID}#{i}"
|
levelPoints[i].pointID = "#{startedSubsID}#{i}"
|
||||||
|
|
||||||
levelPoints.splice(0, levelPoints.length - 60) if levelPoints.length > 60
|
levelPoints.splice(0, levelPoints.length - timeframeDays) if levelPoints.length > timeframeDays
|
||||||
|
|
||||||
@analytics.graphs[0].lines.push
|
@analytics.graphs[0].lines.push
|
||||||
lineID: startedSubsID
|
lineID: startedSubsID
|
||||||
|
@ -178,16 +195,21 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
max: d3.max(@subs, (d) -> d.started)
|
max: d3.max(@subs, (d) -> d.started)
|
||||||
|
|
||||||
## Cancelled
|
## Cancelled
|
||||||
|
averageCancelled = 0
|
||||||
|
|
||||||
# Build line data
|
# Build line data
|
||||||
levelPoints = []
|
levelPoints = []
|
||||||
|
cancelled = []
|
||||||
for sub, i in @subs
|
for sub, i in @subs
|
||||||
|
if i >= @subs.length - 30
|
||||||
|
cancelled.push sub.cancelled
|
||||||
levelPoints.push
|
levelPoints.push
|
||||||
x: i
|
x: i
|
||||||
y: sub.cancelled
|
y: sub.cancelled
|
||||||
day: sub.day
|
day: sub.day
|
||||||
pointID: "#{cancelledSubsID}#{i}"
|
pointID: "#{cancelledSubsID}#{i}"
|
||||||
values: []
|
values: []
|
||||||
|
averageCancelled = cancelled.reduce((a, b) -> a + b) / cancelled.length
|
||||||
|
|
||||||
# Ensure points for each day
|
# Ensure points for each day
|
||||||
for day, i in days
|
for day, i in days
|
||||||
|
@ -200,7 +222,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
levelPoints[i].x = i
|
levelPoints[i].x = i
|
||||||
levelPoints[i].pointID = "#{cancelledSubsID}#{i}"
|
levelPoints[i].pointID = "#{cancelledSubsID}#{i}"
|
||||||
|
|
||||||
levelPoints.splice(0, levelPoints.length - 60) if levelPoints.length > 60
|
levelPoints.splice(0, levelPoints.length - timeframeDays) if levelPoints.length > timeframeDays
|
||||||
|
|
||||||
@analytics.graphs[0].lines.push
|
@analytics.graphs[0].lines.push
|
||||||
lineID: cancelledSubsID
|
lineID: cancelledSubsID
|
||||||
|
@ -211,6 +233,52 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
min: 0
|
min: 0
|
||||||
max: d3.max(@subs, (d) -> d.started)
|
max: d3.max(@subs, (d) -> d.started)
|
||||||
|
|
||||||
|
## 7-Day Net Subs
|
||||||
|
|
||||||
|
# Build line data
|
||||||
|
levelPoints = []
|
||||||
|
sevenNets = []
|
||||||
|
for sub, i in @subs
|
||||||
|
net = 0
|
||||||
|
if i >= @subs.length - 30
|
||||||
|
sevenNets.push sub.started - sub.cancelled
|
||||||
|
else
|
||||||
|
sevenNets.push sub.started - averageCancelled
|
||||||
|
if sevenNets.length > 7
|
||||||
|
sevenNets.shift()
|
||||||
|
if sevenNets.length is 7
|
||||||
|
net = sevenNets.reduce((a, b) -> a + b) / 7
|
||||||
|
levelPoints.push
|
||||||
|
x: i
|
||||||
|
y: net
|
||||||
|
day: sub.day
|
||||||
|
pointID: "#{netSubsID}#{i}"
|
||||||
|
values: []
|
||||||
|
|
||||||
|
# Ensure points for each day
|
||||||
|
for day, i in days
|
||||||
|
if levelPoints.length <= i or levelPoints[i].day isnt day
|
||||||
|
prevY = if i > 0 then levelPoints[i - 1].y else 0.0
|
||||||
|
levelPoints.splice i, 0,
|
||||||
|
y: prevY
|
||||||
|
day: day
|
||||||
|
values: []
|
||||||
|
levelPoints[i].x = i
|
||||||
|
levelPoints[i].pointID = "#{netSubsID}#{i}"
|
||||||
|
|
||||||
|
levelPoints.splice(0, levelPoints.length - timeframeDays) if levelPoints.length > timeframeDays
|
||||||
|
|
||||||
|
@analytics.graphs[0].lines.push
|
||||||
|
lineID: netSubsID
|
||||||
|
enabled: true
|
||||||
|
points: levelPoints
|
||||||
|
description: lineMetadata[netSubsID].description
|
||||||
|
lineColor: lineMetadata[netSubsID].color
|
||||||
|
strokeWidth: lineMetadata[netSubsID].strokeWidth
|
||||||
|
min: 0
|
||||||
|
max: d3.max(@subs, (d) -> d.started)
|
||||||
|
|
||||||
|
|
||||||
updateAnalyticsGraphs: ->
|
updateAnalyticsGraphs: ->
|
||||||
# Build d3 graphs
|
# Build d3 graphs
|
||||||
return unless @analytics?.graphs?.length > 0
|
return unless @analytics?.graphs?.length > 0
|
||||||
|
@ -229,7 +297,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
svg = d3.select(containerSelector).append("svg")
|
svg = d3.select(containerSelector).append("svg")
|
||||||
.attr("width", containerWidth)
|
.attr("width", containerWidth)
|
||||||
.attr("height", containerHeight)
|
.attr("height", containerHeight)
|
||||||
width = containerWidth - margin * 2 - yAxisWidth * graphLineCount
|
width = containerWidth - margin * 2 - yAxisWidth * 2
|
||||||
height = containerHeight - margin * 2 - xAxisHeight - keyHeight * graphLineCount
|
height = containerHeight - margin * 2 - xAxisHeight - keyHeight * graphLineCount
|
||||||
currentLine = 0
|
currentLine = 0
|
||||||
for line in graph.lines
|
for line in graph.lines
|
||||||
|
@ -251,36 +319,39 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
.call(xAxis)
|
.call(xAxis)
|
||||||
.selectAll("text")
|
.selectAll("text")
|
||||||
.attr("dy", ".35em")
|
.attr("dy", ".35em")
|
||||||
.attr("transform", "translate(" + (margin + yAxisWidth * (graphLineCount - 1)) + "," + (height + margin) + ")")
|
.attr("transform", "translate(" + (margin + yAxisWidth) + "," + (height + margin) + ")")
|
||||||
.style("text-anchor", "start")
|
.style("text-anchor", "start")
|
||||||
|
|
||||||
|
if line.lineID is 'started-subs'
|
||||||
# Horizontal guidelines
|
# Horizontal guidelines
|
||||||
# svg.selectAll(".line")
|
marks = (Math.round(i * line.max / 5) for i in [1...5])
|
||||||
# .data([10, 30, 50, 70, 90])
|
svg.selectAll(".line")
|
||||||
# .enter()
|
.data(marks)
|
||||||
# .append("line")
|
.enter()
|
||||||
# .attr("x1", margin + yAxisWidth * graphLineCount)
|
.append("line")
|
||||||
# .attr("y1", (d) -> margin + yRange(d))
|
.attr("x1", margin + yAxisWidth * 2)
|
||||||
# .attr("x2", margin + yAxisWidth * graphLineCount + width)
|
.attr("y1", (d) -> margin + yRange(d))
|
||||||
# .attr("y2", (d) -> margin + yRange(d))
|
.attr("x2", margin + yAxisWidth * 2 + width)
|
||||||
# .attr("stroke", line.lineColor)
|
.attr("y2", (d) -> margin + yRange(d))
|
||||||
# .style("opacity", "0.5")
|
.attr("stroke", line.lineColor)
|
||||||
|
.style("opacity", "0.5")
|
||||||
|
|
||||||
# y-Axis
|
if currentLine < 2
|
||||||
yAxisRange = d3.scale.linear().range([height, 0]).domain([line.min, line.max])
|
# y-Axis
|
||||||
yAxis = d3.svg.axis()
|
yAxisRange = d3.scale.linear().range([height, 0]).domain([line.min, line.max])
|
||||||
.scale(yRange)
|
yAxis = d3.svg.axis()
|
||||||
.orient("left")
|
.scale(yRange)
|
||||||
svg.append("g")
|
.orient("left")
|
||||||
.attr("class", "y axis")
|
svg.append("g")
|
||||||
.attr("transform", "translate(" + (margin + yAxisWidth * currentLine) + "," + margin + ")")
|
.attr("class", "y axis")
|
||||||
.style("color", line.lineColor)
|
.attr("transform", "translate(" + (margin + yAxisWidth * currentLine) + "," + margin + ")")
|
||||||
.call(yAxis)
|
.style("color", line.lineColor)
|
||||||
.selectAll("text")
|
.call(yAxis)
|
||||||
.attr("y", 0)
|
.selectAll("text")
|
||||||
.attr("x", 0)
|
.attr("y", 0)
|
||||||
.attr("fill", line.lineColor)
|
.attr("x", 0)
|
||||||
.style("text-anchor", "start")
|
.attr("fill", line.lineColor)
|
||||||
|
.style("text-anchor", "start")
|
||||||
|
|
||||||
# Key
|
# Key
|
||||||
svg.append("line")
|
svg.append("line")
|
||||||
|
@ -302,7 +373,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
.data(line.points)
|
.data(line.points)
|
||||||
.enter()
|
.enter()
|
||||||
.append("circle")
|
.append("circle")
|
||||||
.attr("transform", "translate(" + (margin + yAxisWidth * graphLineCount) + "," + margin + ")")
|
.attr("transform", "translate(" + (margin + yAxisWidth * 2) + "," + margin + ")")
|
||||||
.attr("cx", (d) -> xRange(d.x))
|
.attr("cx", (d) -> xRange(d.x))
|
||||||
.attr("cy", (d) -> yRange(d.y))
|
.attr("cy", (d) -> yRange(d.y))
|
||||||
.attr("r", 2)
|
.attr("r", 2)
|
||||||
|
@ -316,8 +387,8 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
|
||||||
.interpolate("linear")
|
.interpolate("linear")
|
||||||
svg.append("path")
|
svg.append("path")
|
||||||
.attr("d", d3line(line.points))
|
.attr("d", d3line(line.points))
|
||||||
.attr("transform", "translate(" + (margin + yAxisWidth * graphLineCount) + "," + margin + ")")
|
.attr("transform", "translate(" + (margin + yAxisWidth * 2) + "," + margin + ")")
|
||||||
.style("stroke-width", 1)
|
.style("stroke-width", line.strokeWidth)
|
||||||
.style("stroke", line.lineColor)
|
.style("stroke", line.lineColor)
|
||||||
.style("fill", "none")
|
.style("fill", "none")
|
||||||
currentLine++
|
currentLine++
|
||||||
|
|
27
scripts/analytics/mongodb/queries/campaignLevelCounts.js
Normal file
27
scripts/analytics/mongodb/queries/campaignLevelCounts.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// Print out campaign level counts
|
||||||
|
|
||||||
|
// Usage:
|
||||||
|
// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
|
||||||
|
|
||||||
|
var cursor = db.campaigns.find({}, {slug: 1, levels: 1});
|
||||||
|
var allFree = 0;
|
||||||
|
var allPremium = 0;
|
||||||
|
while (cursor.hasNext()) {
|
||||||
|
var doc = cursor.next();
|
||||||
|
if (doc.slug === 'auditions') continue;
|
||||||
|
var free = 0;
|
||||||
|
var premium = 0;
|
||||||
|
for (var levelID in doc.levels) {
|
||||||
|
if (doc.levels[levelID].requiresSubscription) {
|
||||||
|
premium++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
free++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print(free + " " + premium + " " + (free + premium) + " " + doc.slug);
|
||||||
|
|
||||||
|
allFree += free;
|
||||||
|
allPremium += premium;
|
||||||
|
}
|
||||||
|
print(allFree + " " + allPremium + " " + (allFree + allPremium) + " overall");
|
|
@ -13,8 +13,8 @@ if(config.stripe.secretKey.indexOf('sk_test_')==0) {
|
||||||
stripe = require('stripe')(config.stripe.secretKey);
|
stripe = require('stripe')(config.stripe.secretKey);
|
||||||
|
|
||||||
var range = {
|
var range = {
|
||||||
gt: ''+(new Date('2015-02-01').getTime()/1000),
|
gt: ''+(new Date('2015-03-01').getTime()/1000),
|
||||||
lt: ''+(new Date('2015-03-01').getTime()/1000)
|
lt: ''+(new Date('2015-04-01').getTime()/1000)
|
||||||
};
|
};
|
||||||
|
|
||||||
begin = function(starting_after) {
|
begin = function(starting_after) {
|
||||||
|
@ -25,12 +25,14 @@ begin = function(starting_after) {
|
||||||
stripe.invoices.list(query, onInvoicesReceived);
|
stripe.invoices.list(query, onInvoicesReceived);
|
||||||
}
|
}
|
||||||
|
|
||||||
customersPaid = []
|
customersPaid = [];
|
||||||
|
|
||||||
onInvoicesReceived = function(err, invoices) {
|
onInvoicesReceived = function(err, invoices) {
|
||||||
for(var i in invoices.data) {
|
for(var i in invoices.data) {
|
||||||
var invoice = invoices.data[i];
|
var invoice = invoices.data[i];
|
||||||
if(!invoice.paid) { continue; }
|
if(!invoice.paid) { continue; }
|
||||||
|
if(!invoice.total) { continue; } // not paying anything!
|
||||||
|
//console.log(invoice);
|
||||||
customersPaid.push(invoice.customer);
|
customersPaid.push(invoice.customer);
|
||||||
}
|
}
|
||||||
if(invoices.has_more) {
|
if(invoices.has_more) {
|
||||||
|
@ -38,10 +40,10 @@ onInvoicesReceived = function(err, invoices) {
|
||||||
begin(invoices.data[i].id);
|
begin(invoices.data[i].id);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log('How many customers paid for a subscription:', _.unique(customersPaid).length);
|
console.log('--- Actual active total customers:', _.unique(customersPaid).length);
|
||||||
loadNewCustomers();
|
loadNewCustomers();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
loadNewCustomers = function(starting_after) {
|
loadNewCustomers = function(starting_after) {
|
||||||
query = {created: range, limit: 100};
|
query = {created: range, limit: 100};
|
||||||
|
@ -49,7 +51,7 @@ loadNewCustomers = function(starting_after) {
|
||||||
query.starting_after = starting_after;
|
query.starting_after = starting_after;
|
||||||
}
|
}
|
||||||
stripe.customers.list(query, onCustomersReceived);
|
stripe.customers.list(query, onCustomersReceived);
|
||||||
}
|
};
|
||||||
|
|
||||||
newCustomersPaid = [];
|
newCustomersPaid = [];
|
||||||
|
|
||||||
|
@ -64,8 +66,8 @@ onCustomersReceived = function(err, customers) {
|
||||||
loadNewCustomers(customers.data[i].id);
|
loadNewCustomers(customers.data[i].id);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log('How many new customers paid for a subscription:', newCustomersPaid.length);
|
console.log('--- Actual new customers:', newCustomersPaid.length);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
begin();
|
begin();
|
Loading…
Reference in a new issue