mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-29 14:19:48 -04:00
Merge branch 'master' into production
This commit is contained in:
commit
c761e8de3b
33 changed files with 389 additions and 238 deletions
app
lib
locale
schemas
styles
templates
account
courses
play/level/modal
views
server
campaigns
classrooms
commons
levels
queues/scoring
users
test/server/functional
|
@ -20,6 +20,7 @@ module.exports = class LevelBus extends Bus
|
|||
'tome:spell-changed': 'onSpellChanged'
|
||||
'tome:spell-created': 'onSpellCreated'
|
||||
'tome:cast-spells': 'onCastSpells'
|
||||
'tome:winnability-updated': 'onWinnabilityUpdated'
|
||||
'application:idle-changed': 'onIdleChanged'
|
||||
'goal-manager:new-goal-states': 'onNewGoalStates'
|
||||
'god:new-world-created': 'onNewWorldCreated'
|
||||
|
@ -119,6 +120,11 @@ module.exports = class LevelBus extends Bus
|
|||
@changedSessionProperties.state = true
|
||||
@saveSession()
|
||||
|
||||
onWinnabilityUpdated: (e) ->
|
||||
return unless @onPoint() and e.winnable
|
||||
return unless e.level.get('slug') in ['ace-of-coders'] # Mirror matches don't otherwise show victory, so we win here.
|
||||
@onVictory()
|
||||
|
||||
onNewWorldCreated: (e) ->
|
||||
return unless @onPoint()
|
||||
# Record the flag history.
|
||||
|
|
|
@ -440,12 +440,12 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
payment_methods_blurb2: "Si necesitas una forma alternativa de pago, por favor contactarse"
|
||||
sale_already_subscribed: "¡Ya estás subscrito!"
|
||||
sale_blurb1: "Ahorra 35%"
|
||||
sale_blurb2: "de descuento en el precio regular de una subscripción de $120 USD por un año completo!"
|
||||
sale_blurb2: "de descuento en el precio regular de una suscripción de $120 USD por un año completo!"
|
||||
sale_button: "Venta!"
|
||||
sale_button_title: "Ahorra 35% al adquirir una subscripción por 1 año"
|
||||
sale_button_title: "Ahorra 35% al adquirir una suscripción por 1 año"
|
||||
sale_click_here: "Haz Click Aquí"
|
||||
sale_ends: "Termina"
|
||||
sale_extended: "*Las subscripciones existentes se extenderán por un año."
|
||||
sale_extended: "*Las suscripciones existentes se extenderán por un año."
|
||||
sale_feature_here: "Esto es lo que obtendrás:"
|
||||
sale_feature2: "¡Acceso a 9 poderosos <strong>nuevos héroes</strong> con habilidades únicas!"
|
||||
sale_feature4: "¡Una bonificación inmediata de <strong>42,000 gemas</strong>!"
|
||||
|
@ -453,9 +453,9 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
sale_limited_time: "¡Oferta por tiempo limitado!"
|
||||
sale_new_heroes: "¡Nuevos héroes!"
|
||||
sale_title: "Venta de regreso a clases"
|
||||
sale_view_button: "Compra la subscripción de 1 año por"
|
||||
sale_view_button: "Compra la suscripción de 1 año por"
|
||||
stripe_description: "Suscripción Mensual"
|
||||
stripe_description_year_sale: "Subscripción por 1 año (35% descuento)"
|
||||
stripe_description_year_sale: "Suscripción por 1 año (35% descuento)"
|
||||
subscription_required_to_play: "Necesitas una suscripción para jugar este nivel."
|
||||
unlock_help_videos: "Suscríbete para desbloquear todos los video tutoriales."
|
||||
personal_sub: "Suscripción Personal" # Accounts Subscription View below
|
||||
|
@ -598,12 +598,12 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
jose_blurb: "Despegar"
|
||||
retrostyle_title: "Ilustración"
|
||||
retrostyle_blurb: "Juegos con estilo Retro"
|
||||
# rob_title: "Compiler Engineer"
|
||||
# rob_blurb: "Codes things and stuff"
|
||||
# josh_c_title: "Game Designer"
|
||||
# josh_c_blurb: "Designs games"
|
||||
# carlos_title: "Region Manager, Brazil"
|
||||
# carlos_blurb: "Celery Man"
|
||||
rob_title: "Ingeniero de Compilación"
|
||||
rob_blurb: "Hace código y demás"
|
||||
josh_c_title: "Diseñador de Juegos"
|
||||
josh_c_blurb: "Diseña juegos"
|
||||
carlos_title: "Manager de Región, Brasil"
|
||||
carlos_blurb: "Hombre apio"
|
||||
|
||||
teachers:
|
||||
more_info: "Información para profesores"
|
||||
|
@ -613,8 +613,8 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
cost_premium_server: "CodeCombat es gratis para lso primeros 5 niveles, después de ellos cuesta $9.99 USD mensuales para accesar a nuestros otros más de 190 niveles en nuestraos exclusivos servidores específicos para cada país."
|
||||
free_1: "Hay más de 110 niveles gratis que cubren cada concepto."
|
||||
free_2: "Una suscripción mensual le da acceso a tutoriales en vídeo y niveles extra para practicar."
|
||||
teacher_subs_title: "¡Los amestros obtienen subscripciones gratuitas!"
|
||||
teacher_subs_0: "Ofrecemos subscripciones gratuitas a profesores con propósitos de evaluación."
|
||||
teacher_subs_title: "¡Los amestros obtienen suscripciones gratuitas!"
|
||||
teacher_subs_0: "Ofrecemos suscripciones gratuitas a profesores con propósitos de evaluación."
|
||||
teacher_subs_1: "Por favor llene nuestra"
|
||||
teacher_subs_2: "Encuesta para maestros"
|
||||
teacher_subs_3: "para configurar su suscripción."
|
||||
|
@ -642,7 +642,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
material_premium_server: "Aproximadamente 22 horas de juego repartidas en más de 120 niveles sólo para suscriptores, con cinco nueveos niveles cada semana." # {change}
|
||||
material_1: "Aproximadamente 8 horas de contenido gratis y un adicional de 14 horas de contenido de suscriptores, con cinco nueveos niveles cada semana." # {change}
|
||||
concepts_title: "¿Qué conceptos están cubiertos?"
|
||||
how_much_title: "¿Cuánto cuesta una subscripción mensual?"
|
||||
how_much_title: "¿Cuánto cuesta una suscripción mensual?"
|
||||
how_much_1: "una"
|
||||
how_much_2: "suscribción mensual"
|
||||
how_much_3: "Cuesta u$s9.99, y puede ser cancelada en cualquier momento."
|
||||
|
@ -724,8 +724,8 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
wrong_password: "Contraseña incorrecta"
|
||||
upload_picture: "Sube una imagen"
|
||||
delete_this_account: "Borrar esta cuenta permanentemente"
|
||||
# reset_progress_tab: "Reset All Progress"
|
||||
# reset_your_progress: "Clear all your progress and start over"
|
||||
reset_progress_tab: "Reiniciar Todo Progreso"
|
||||
reset_your_progress: "Limpiar todo tu progreso y comenzar de nuevo"
|
||||
god_mode: "Modo Dios"
|
||||
password_tab: "Contraseña"
|
||||
emails_tab: "Correos"
|
||||
|
@ -733,7 +733,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
new_password: "Nueva Contraseña"
|
||||
new_password_verify: "Verificar"
|
||||
type_in_email: "Ingrese su correo electrónico para confirmar la eliminación de su cuenta."
|
||||
# type_in_email_progress: "Type in your email to confirm deleting your progress."
|
||||
type_in_email_progress: "Ingrese su correo para confirmar la eliminación de su progreso."
|
||||
type_in_password: "Asimismo, ingrese su contraseña."
|
||||
email_subscriptions: "Suscripciones de Email"
|
||||
email_subscriptions_none: "No tienes suscripciones."
|
||||
|
@ -857,7 +857,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
track_concepts6b: "Ordene a sus miembros por nombre o progreso"
|
||||
track_concepts7: "Requiere invitación"
|
||||
track_concepts8: "para unirse"
|
||||
private_require_sub: "Los clanes privados requieren una subscripción para crearlos o unírseles."
|
||||
private_require_sub: "Los clanes privados requieren una suscripción para crearlos o unírseles."
|
||||
|
||||
courses:
|
||||
course: "Curso"
|
||||
|
@ -1254,26 +1254,26 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
success: "Listo, fue cobrado. Gracias!"
|
||||
|
||||
account_prepaid:
|
||||
purchase_code: "Adquirir un Código de Subscripción"
|
||||
# purchase_code1: "Subscription Codes can be redeemed to add premium subscription time to one or more CodeCombat accounts."
|
||||
# purchase_code2: "Each CodeCombat account can only redeem a particular Subscription Code once."
|
||||
# purchase_code3: "Subscription Code months will be added to the end of any existing subscription on the account."
|
||||
purchase_code: "Adquirir un Código de Suscripción"
|
||||
purchase_code1: "Los códigos de suscripción pueden ser canjeados para agregar tiempo de suscripción premium para una o más cuentas CodeCombat."
|
||||
purchase_code2: "Cada cuenta CodeCombat puede canjear una sola vez un Código de Suscripción en particular."
|
||||
purchase_code3: "Los meses del Código de Suscripción serán agregados al final de la suscripción existente de la cuenta."
|
||||
users: "Usuarios"
|
||||
months: "Meses"
|
||||
purchase_total: "Total"
|
||||
purchase_button: "Enviar Adquisición"
|
||||
your_codes: "Tus Códigos:" # {change}
|
||||
redeem_codes: "Reclamar un Código de Subscripción"
|
||||
redeem_codes: "Reclamar un Código de Suscripción"
|
||||
prepaid_code: "Código Prepagado"
|
||||
# lookup_code: "Lookup prepaid code"
|
||||
# apply_account: "Apply to your account"
|
||||
# copy_link: "You can copy the code's link and send it to someone."
|
||||
lookup_code: "Buscar código prepagado"
|
||||
apply_account: "Aplicara tu cuenta"
|
||||
copy_link: "Puedes copiarl el enlace del código y enviarlo a alguien."
|
||||
quantity: "Cantidad"
|
||||
redeemed: "Reclamado"
|
||||
no_codes: "¡Aún sin códigos!"
|
||||
# you_can1: "You can"
|
||||
# you_can2: "purchase a prepaid code"
|
||||
# you_can3: "that can be applied to your own account or given to others."
|
||||
you_can1: "Puedes"
|
||||
you_can2: "comprar un código prepagado"
|
||||
you_can3: "que puede ser aplicado a tu propia cuenta o regalado a otros."
|
||||
|
||||
loading_error:
|
||||
could_not_load: "Error cargando del servidor"
|
||||
|
|
|
@ -81,7 +81,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
campaign_multiplayer: "Arene multigiocatore"
|
||||
campaign_multiplayer_description: "... nelle quali programmi faccia a faccia contro altri giocatori."
|
||||
# campaign_old_multiplayer: "(Deprecated) Old Multiplayer Arenas"
|
||||
# campaign_old_multiplayer_description: "Relics of a more civilized age. No simulations are run for these older, hero-less multiplayer arenas."
|
||||
campaign_old_multiplayer_description: "Reliquie di un'epoca più civilizzata. Nessuna simulazione viene eseguita per queste arene multi-giocatore più vecchie e senza eroi" #"Relics of a more civilized age. No simulations are run for these older, hero-less multiplayer arenas."
|
||||
|
||||
share_progress_modal:
|
||||
blurb: "Stai facendo grandi progressi! Dì ai tuoi genitori quanto hai imparato con CodeCombat."
|
||||
|
@ -159,9 +159,9 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
accepted: "Accettate"
|
||||
rejected: "Rifiutate"
|
||||
withdrawn: "Ritirate"
|
||||
# accept: "Accept"
|
||||
# reject: "Reject"
|
||||
# withdraw: "Withdraw"
|
||||
accept: "Accetta" #"Accept"
|
||||
reject: "Rifiuta" #"Reject"
|
||||
withdraw: "Ritirati" #"Withdraw"
|
||||
submitter: "Autore"
|
||||
submitted: "Data creazione"
|
||||
commit_msg: "Messaggio di commit"
|
||||
|
@ -217,7 +217,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
|
||||
play_level:
|
||||
done: "Fatto"
|
||||
# next_game: "Next game"
|
||||
next_game: "Prossimo gioco" #"Next game"
|
||||
# show_menu: "Show game menu"
|
||||
home: "Pagina iniziale" # Not used any more, will be removed soon.
|
||||
level: "Livello" # Like "Level: Dungeons of Kithgard"
|
||||
|
@ -296,7 +296,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
tip_scrub_shortcut: "Usa Ctrl+[ e Ctrl+] per tornare indietro o avanzare rapidamente."
|
||||
tip_guide_exists: "Clicca sulla Guida, nel menù di gioco (in alto nella pagina), per informazioni utili."
|
||||
tip_open_source: "CodeCombat è 100% open source!"
|
||||
# tip_tell_friends: "Enjoying CodeCombat? Tell your friends about us!"
|
||||
tip_tell_friends: "Ti piace CodeCombat? Parla di noi ai tuoi amici!" #"Enjoying CodeCombat? Tell your friends about us!"
|
||||
tip_beta_launch: "CodeCombat è stato lanciato in beta nell'ottobre 2013."
|
||||
tip_think_solution: "Pensa alla soluzione, non al problema."
|
||||
tip_theory_practice: "In teoria, non c'è alcuna differenza tra teoria e pratica. Ma in pratica, c'è. - Yogi Berra"
|
||||
|
@ -304,20 +304,20 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
tip_debugging_program: "Se il debug è il processo di rimuovere i bug, allora programmare deve essere il processo di crearli. - Edsger W. Dijkstra"
|
||||
tip_forums: "Visita i nostri forum e facci sapere cosa pensi!"
|
||||
tip_baby_coders: "Nel futuro, persino i neonati saranno Arcimaghi."
|
||||
# tip_morale_improves: "Loading will continue until morale improves."
|
||||
tip_morale_improves: "Il caricamento continuerà fino a che il morale migliora." #"Loading will continue until morale improves."
|
||||
tip_all_species: "Crediamo che chiunque debba avere le stesse opportunità di imparare a programmare."
|
||||
# tip_reticulating: "Reticulating spines."
|
||||
# tip_harry: "Yer a Wizard, "
|
||||
tip_great_responsibility: "Da grandi abilità di programmazione derivano grandi responsabilità."
|
||||
tip_munchkin: "Se non mangi la tua verdura, un munchkin verrà a cercarti mentre dormi."
|
||||
# tip_binary: "There are only 10 types of people in the world: those who understand binary, and those who don't."
|
||||
# tip_commitment_yoda: "A programmer must have the deepest commitment, the most serious mind. ~ Yoda"
|
||||
tip_binary: "Ci sono solo 10 tipi di persone al mondo: quelli che capiscono il binario, e quelli che non lo capiscono." #"There are only 10 types of people in the world: those who understand binary, and those who don't."
|
||||
tip_commitment_yoda: "Un programmatore il più profondo impegno, la mente più seria deve avere. ~ Yoda" #"A programmer must have the deepest commitment, the most serious mind. ~ Yoda"
|
||||
tip_no_try: "Fare o non fare. Questo non è provare. - Yoda"
|
||||
tip_patience: "Pazienza devi avere, giovane Padawan. - Yoda"
|
||||
tip_documented_bug: "Un bug documentato non è bug; è una feature."
|
||||
tip_impossible: "Sembra sempre impossibile fino a quando non ci si riesce. - Nelson Mandela"
|
||||
tip_talk_is_cheap: "A parlare sono bravi tutti. Mostrami il codice. - Linus Torvalds"
|
||||
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
|
||||
tip_first_language: "La cosa più disastrosa che potrai mai imparare è il tuo primo linguaggio di programmazione. - Alan Kay" #"The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
|
||||
tip_hardware_problem: "Quanti programmatori servono per cambiare una lampadina? Nessuno, è un problema di hardware."
|
||||
tip_hofstadters_law: "Legge di Hofstadter: Ci vuole sempre più del previsto, anche quando tieni conto della legge di Hofstadter."
|
||||
tip_premature_optimization: "L'ottimizzazione prematura è l'origine di tutti i mali. - Donald Knuth"
|
||||
|
@ -327,9 +327,9 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
tip_control_destiny: "Nel vero open source, hai il diritto di controllare il propio destino. - Linus Torvalds"
|
||||
tip_no_code: "Nessun codice è più veloce di nessun codice."
|
||||
tip_code_never_lies: "Il codice non mente mai, ma i commenti a volte lo fanno. — Ron Jeffries"
|
||||
# tip_reusable_software: "Before software can be reusable it first has to be usable."
|
||||
tip_reusable_software: "Prima che un software sia riusabile deve intanto essere usabile." #"Before software can be reusable it first has to be usable."
|
||||
tip_optimization_operator: "Ogni linguaggio ha un operatore di ottimizzazione. Nella maggior parte dei casi questo operatore è ‘//’"
|
||||
# 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: "Misurare l'avanzamento di un programma dalle righe di codice è come misurare l'avanzamento nella costruzione di un aereo dal peso. - Bill Gates" #"Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
|
||||
tip_source_code: "Vorrei cambiare il mondo, ma non mi danno il codice sorgente."
|
||||
tip_javascript_java: "Java sta a JavaScript come Cane sta a Canestro. - Chris Heilmann"
|
||||
tip_move_forward: "Qualsiasi cosa tu faccia, vai sempre avanti. - Martin Luther King Jr."
|
||||
|
@ -340,8 +340,8 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
tip_recurse: "Iterare e umano, usare la ricorsione è divino. - L. Peter Deutsch"
|
||||
tip_free_your_mind: "Devi liberarti di tutto questo, Neo. Paura, dubbio, sfiducia. Libera la tua mente. - Morpheus"
|
||||
tip_strong_opponents: "Anche il più tenace degli avversari ha sempre una debolezza. - Itachi Uchiha"
|
||||
# tip_paper_and_pen: "Before you start coding, you can always plan with a sheet of paper and a pen."
|
||||
# tip_solve_then_write: "First, solve the problem. Then, write the code. - John Johnson"
|
||||
tip_paper_and_pen: "Prima di iniziare a programmare, puoi sempre progettare con un foglio di carta e una penna." #"Before you start coding, you can always plan with a sheet of paper and a pen."
|
||||
tip_solve_then_write: "Prima, risolvi il problema. Poi, scrivi il codice. - John Johnson" #"First, solve the problem. Then, write the code. - John Johnson"
|
||||
|
||||
game_menu:
|
||||
inventory_tab: "Inventario"
|
||||
|
@ -410,7 +410,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
feature7: "Clan <strong>privati</strong>"
|
||||
free: "Gratis"
|
||||
month: "mese"
|
||||
# must_be_logged: "You must be logged in first. Please create an account or log in from the menu above."
|
||||
must_be_logged: "Devi aver prima effettuato il login. Crea un account o effettua il login dal menu superiore." #"You must be logged in first. Please create an account or log in from the menu above."
|
||||
subscribe_title: "Abbonati"
|
||||
unsubscribe: "Disabbonati"
|
||||
confirm_unsubscribe: "Conferma disabbonamento"
|
||||
|
@ -438,10 +438,10 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
payment_methods_title: "Metodi di Pagamento Accetati"
|
||||
payment_methods_blurb1: "Attualmente accettiamo come metodi di pagamento la carta di credito e Alipay."
|
||||
payment_methods_blurb2: "Se necessiti di un forma di pagamento diverso.Per favore contattaci"
|
||||
# sale_already_subscribed: "You're already subscribed!"
|
||||
sale_already_subscribed: "Sei già abbonato!" #"You're already subscribed!"
|
||||
sale_blurb1: "Risparmia il 35%"
|
||||
# sale_blurb2: "off regular subscription price of $120 for a whole year!"
|
||||
# sale_button: "Sale!"
|
||||
sale_button: "Saldi!" #"Sale!"
|
||||
sale_button_title: "Risparmi il 35% quando compri l'abbonamento per 1 anno"
|
||||
sale_click_here: "Clicca qui"
|
||||
# sale_ends: "Ends"
|
||||
|
@ -472,14 +472,14 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
# group_discounts_1: "We also offer group discounts for bulk subscriptions."
|
||||
group_discounts_1st: "Prima sottoscrizione"
|
||||
group_discounts_full: "Prezzo completo"
|
||||
# group_discounts_2nd: "Subscriptions 2-11"
|
||||
group_discounts_2nd: "Sottoscrizione 2-11" #"Subscriptions 2-11"
|
||||
group_discounts_20: "20% disconto"
|
||||
# group_discounts_12th: "Subscriptions 12+"
|
||||
group_discounts_12th: "Sottoscrizione 12+" #"Subscriptions 12+"
|
||||
group_discounts_40: "40% di sconto"
|
||||
# subscribing: "Subscribing..."
|
||||
# recipient_emails_placeholder: "Enter email address to subscribe, one per line."
|
||||
subscribe_users: "Sottoscrivere Utenti"
|
||||
users_subscribed: "Utenti sottoscritti:"
|
||||
subscribe_users: "Iscrivere Utenti"
|
||||
users_subscribed: "Utenti iscritti:"
|
||||
# no_users_subscribed: "No users subscribed, please double check your email addresses."
|
||||
# current_recipients: "Current Recipients"
|
||||
# unsubscribing: "Unsubscribing"
|
||||
|
@ -527,8 +527,8 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
skill_docs:
|
||||
writable: "scrivibile" # Hover over "attack" in Your Skills while playing a level to see most of this
|
||||
read_only: "sola lettura"
|
||||
# action: "Action"
|
||||
# spell: "Spell"
|
||||
action: "Azione" #"Action"
|
||||
spell: "Incantesimo" #"Spell"
|
||||
action_name: "nome"
|
||||
action_cooldown: "Richiede"
|
||||
action_specific_cooldown: "Riposo"
|
||||
|
@ -721,11 +721,11 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
picture_tab: "Immagine"
|
||||
delete_account_tab: "Cancella il tuo account"
|
||||
wrong_email: "Indirizzo email sbagliato"
|
||||
# wrong_password: "Wrong Password"
|
||||
wrong_password: "Password Sbagliata" #"Wrong Password"
|
||||
upload_picture: "Carica immagine"
|
||||
delete_this_account: "Cancella questo account per sempre"
|
||||
# reset_progress_tab: "Reset All Progress"
|
||||
# reset_your_progress: "Clear all your progress and start over"
|
||||
reset_your_progress: "Cancella tutti i tuoi progressi e inizia da capo" #"Clear all your progress and start over"
|
||||
# god_mode: "God Mode"
|
||||
password_tab: "Password"
|
||||
emails_tab: "Email"
|
||||
|
@ -733,8 +733,8 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
new_password: "Nuova password"
|
||||
new_password_verify: "Verifica"
|
||||
type_in_email: "Scrivi il tuo indirizzo email per confermare la cancellazione" # {change}
|
||||
# type_in_email_progress: "Type in your email to confirm deleting your progress."
|
||||
# type_in_password: "Also, type in your password."
|
||||
type_in_email_progress: "Inserisci la tua email per confermare la cancellazione dei tuoi progressi." #"Type in your email to confirm deleting your progress."
|
||||
type_in_password: "Inoltre, inserisci la tua password." #"Also, type in your password."
|
||||
email_subscriptions: "Iscrizioni alle email"
|
||||
email_subscriptions_none: "Nessuna iscrizione."
|
||||
email_announcements: "Annunci email"
|
||||
|
@ -765,7 +765,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
keyboard_shortcuts: "Scorciatoie da tastiera"
|
||||
space: "Spazio"
|
||||
enter: "Invio"
|
||||
# press_enter: "press enter"
|
||||
press_enter: "premi invio" #"press enter"
|
||||
escape: "Esc"
|
||||
shift: "Maiusc"
|
||||
run_code: "Esegui codice attuale."
|
||||
|
@ -792,7 +792,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
article_editor_prefix: "Hai trovato un errore in uno dei nostri documenti? Vuoi creare delle istruzioni per una delle tue creazioni? Vai a"
|
||||
article_editor_suffix: "e aiuta i giocatori di CodeCombat ad ottenere il massimo mentre giocano a programmare."
|
||||
find_us: "Dove trovarci"
|
||||
# social_github: "Check out all our code on GitHub"
|
||||
social_github: "Esplora tutto il nostro codice su GitHub" #"Check out all our code on GitHub"
|
||||
social_blog: "Leggi il blog di CodeCombat su Sett"
|
||||
social_discource: "Partecipa alle discussioni nel nostro forum Discourse"
|
||||
social_facebook: "Metti 'mi piace' a CodeCombat su Facebook"
|
||||
|
@ -809,7 +809,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
make_private: "Rendi clan privato"
|
||||
subs_only: "solo per abbonati"
|
||||
create_clan: "Crea nuovo clan"
|
||||
# private_preview: "Preview"
|
||||
private_preview: "Anteprima" #"Preview"
|
||||
public_clans: "Clan pubblici"
|
||||
my_clans: "I miei clan"
|
||||
clan_name: "Nome clan"
|
||||
|
@ -979,8 +979,8 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
indoor: "Interno"
|
||||
desert: "Deserto"
|
||||
grassy: "Erboso"
|
||||
# mountain: "Mountain"
|
||||
# glacier: "Glacier"
|
||||
mountain: "Montagna" #"Mountain"
|
||||
glacier: "Ghiacciaio" #"Glacier"
|
||||
small: "Piccolo"
|
||||
large: "Grande"
|
||||
# fork_title: "Fork New Version"
|
||||
|
@ -1189,8 +1189,8 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
# red_ai: "Red AI" # "Red AI Wins", at end of multiplayer match playback
|
||||
# blue_ai: "Blue AI"
|
||||
# wins: "Wins" # At end of multiplayer match playback
|
||||
# humans: "Red" # Ladder page display team name
|
||||
# ogres: "Blue"
|
||||
humans: "Rosso" #"Red" # Ladder page display team name
|
||||
ogres: "Blu" #"Blue"
|
||||
|
||||
user:
|
||||
stats: "Statistiche"
|
||||
|
@ -1226,7 +1226,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
purchased: "Acquistato"
|
||||
# sale: "Sale"
|
||||
subscription: "Abbonamento"
|
||||
# invoices: "Invoices"
|
||||
invoices: "Fatture" #"Invoices"
|
||||
service_apple: "Apple"
|
||||
service_web: "Web"
|
||||
# paid_on: "Paid On"
|
||||
|
@ -1287,7 +1287,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
# bad_input: "Bad input."
|
||||
server_error: "Errore server."
|
||||
unknown: "Errore sconosciuto."
|
||||
# error: "ERROR"
|
||||
error: "ERRORE" #"ERROR"
|
||||
|
||||
resources:
|
||||
sessions: "Sessioni"
|
||||
|
@ -1343,27 +1343,27 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
concepts:
|
||||
# advanced_strings: "Advanced Strings"
|
||||
algorithms: "Algoritmi"
|
||||
# arguments: "Arguments"
|
||||
# arithmetic: "Arithmetic"
|
||||
# arrays: "Arrays"
|
||||
# basic_syntax: "Basic Syntax"
|
||||
# boolean_logic: "Boolean Logic"
|
||||
arguments: "Argomenti" #"Arguments"
|
||||
arithmetic: "Aritmetica" #"Arithmetic"
|
||||
arrays: "Array"
|
||||
basic_syntax: "Sintassi di base" #"Basic Syntax"
|
||||
boolean_logic: "Logica Booleana" #"Boolean Logic"
|
||||
# break_statements: "Break Statements"
|
||||
# classes: "Classes"
|
||||
classes: "Classi" #"Classes"
|
||||
# continue_statements: "Continue Statements"
|
||||
# for_loops: "For Loops"
|
||||
# functions: "Functions"
|
||||
# graphics: "Graphics"
|
||||
for_loops: "Cicli For" #"For Loops"
|
||||
functions: "Funzioni" #"Functions"
|
||||
graphics: "Grafici" #"Graphics"
|
||||
# if_statements: "If Statements"
|
||||
# input_handling: "Input Handling"
|
||||
# math_operations: "Math Operations"
|
||||
input_handling: "Gestione dell'Input" #"Input Handling"
|
||||
math_operations: "Operazioni Matematiche" #"Math Operations"
|
||||
# object_literals: "Object Literals"
|
||||
# parameters: "Parameters"
|
||||
# strings: "Strings"
|
||||
# variables: "Variables"
|
||||
# vectors: "Vectors"
|
||||
# while_loops: "Loops"
|
||||
# recursion: "Recursion"
|
||||
parameters: "Parametri" #"Parameters"
|
||||
strings: "Stringhe" #"Strings"
|
||||
variables: "Variabili" #"Variables"
|
||||
vectors: "Vettori" #"Vectors"
|
||||
while_loops: "Cicli" #"Loops"
|
||||
recursion: "Ricorsione" #"Recursion"
|
||||
|
||||
# delta:
|
||||
# added: "Added"
|
||||
|
|
|
@ -598,12 +598,12 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
jose_blurb: "放轻松"
|
||||
retrostyle_title: "插画师"
|
||||
retrostyle_blurb: "复古风格的游戏"
|
||||
# rob_title: "Compiler Engineer"
|
||||
# rob_blurb: "Codes things and stuff"
|
||||
# josh_c_title: "Game Designer"
|
||||
# josh_c_blurb: "Designs games"
|
||||
# carlos_title: "Region Manager, Brazil"
|
||||
# carlos_blurb: "Celery Man"
|
||||
rob_title: "编译器工程师"
|
||||
rob_blurb: "编代码之类的"
|
||||
josh_c_title: "游戏设计师"
|
||||
josh_c_blurb: "设计游戏" # or what
|
||||
carlos_title: "地区经理, 巴西"
|
||||
carlos_blurb: "食草男" # unless you have a better one for "celery man"
|
||||
|
||||
teachers:
|
||||
more_info: "教师的说明"
|
||||
|
@ -724,16 +724,16 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
wrong_password: "密码错误"
|
||||
upload_picture: "上传一张图片"
|
||||
delete_this_account: "永久删除账户"
|
||||
# reset_progress_tab: "Reset All Progress"
|
||||
# reset_your_progress: "Clear all your progress and start over"
|
||||
reset_progress_tab: "重置所有进度"
|
||||
reset_your_progress: "清除记录并重新开始"
|
||||
god_mode: "上帝模式"
|
||||
password_tab: "密码"
|
||||
emails_tab: "邮件"
|
||||
admin: "管理"
|
||||
new_password: "新密码"
|
||||
new_password_verify: "再次输入密码"
|
||||
type_in_email: "输入您的邮箱地址来确认删除"
|
||||
# type_in_email_progress: "Type in your email to confirm deleting your progress."
|
||||
type_in_email: "输入您的邮箱地址"
|
||||
type_in_email_progress: "输入邮箱地址来确认删除"
|
||||
type_in_password: "同样的,输入您的密码。"
|
||||
email_subscriptions: "邮箱订阅"
|
||||
email_subscriptions_none: "取消订阅"
|
||||
|
@ -846,17 +846,17 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
last_played: "最后玩了"
|
||||
leagues_explanation: "在部落里与其他成员组成联盟一起参加下面的多人竞技场。"
|
||||
# track_concepts1: "Track concepts"
|
||||
# track_concepts2a: "learned by each student"
|
||||
# track_concepts2b: "learned by each member"
|
||||
# track_concepts3a: "Track levels completed for each student"
|
||||
# track_concepts3b: "Track levels completed for each member"
|
||||
# track_concepts4a: "See your students'"
|
||||
# track_concepts4b: "See your members'"
|
||||
# track_concepts5: "solutions"
|
||||
# track_concepts6a: "Sort students by name or progress"
|
||||
# track_concepts6b: "Sort members by name or progress"
|
||||
# track_concepts7: "Requires invitation"
|
||||
# track_concepts8: "to join"
|
||||
track_concepts2a: "由每位学生学习"
|
||||
track_concepts2b: "由每位成员学习"
|
||||
track_concepts3a: "查看每位同学达到的等级"
|
||||
track_concepts3b: "查看每位成员达到的等级"
|
||||
track_concepts4a: "查看你的学生"
|
||||
track_concepts4b: "查看你的成员"
|
||||
track_concepts5: "解决方案"
|
||||
track_concepts6a: "按姓名或进度排序学生"
|
||||
track_concepts6b: "按姓名或进度排序成员"
|
||||
track_concepts7: "需要邀请"
|
||||
track_concepts8: "来加入"
|
||||
# private_require_sub: "Private clans require a subscription to create or join."
|
||||
|
||||
courses:
|
||||
|
@ -1258,27 +1258,27 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
# purchase_code1: "Subscription Codes can be redeemed to add premium subscription time to one or more CodeCombat accounts."
|
||||
# purchase_code2: "Each CodeCombat account can only redeem a particular Subscription Code once."
|
||||
# purchase_code3: "Subscription Code months will be added to the end of any existing subscription on the account."
|
||||
# users: "Users"
|
||||
users: "玩家"
|
||||
# months: "Months"
|
||||
purchase_total: "总共"
|
||||
purchase_button: "提交购买"
|
||||
your_codes: "你的订阅码:" # {change}
|
||||
redeem_codes: "兑换订阅码"
|
||||
# prepaid_code: "Prepaid Code"
|
||||
# lookup_code: "Lookup prepaid code"
|
||||
# apply_account: "Apply to your account"
|
||||
# copy_link: "You can copy the code's link and send it to someone."
|
||||
# quantity: "Quantity"
|
||||
# redeemed: "Redeemed"
|
||||
# no_codes: "No codes yet!"
|
||||
# you_can1: "You can"
|
||||
# you_can2: "purchase a prepaid code"
|
||||
# you_can3: "that can be applied to your own account or given to others."
|
||||
prepaid_code: "预购码"
|
||||
lookup_code: "查看预购码"
|
||||
apply_account: "使用到您的账户"
|
||||
copy_link: "您可以复制此代码链接发送给别人。"
|
||||
quantity: "数量"
|
||||
redeemed: "兑换"
|
||||
no_codes: "还没有兑换码!"
|
||||
you_can1: "您可以"
|
||||
you_can2: "购买一个预购码"
|
||||
you_can3: "使用在您的账户或者给其他人。"
|
||||
|
||||
loading_error:
|
||||
could_not_load: "载入失败"
|
||||
connection_failure: "连接失败。"
|
||||
unauthorized: "您需要登录才行。 您是不是把 cookies 禁用了?"
|
||||
unauthorized: "您需要登录才行。您是不是禁用了cookie?"
|
||||
forbidden: "您没有权限。"
|
||||
not_found: "没找到。"
|
||||
not_allowed: "方法不允许。"
|
||||
|
|
|
@ -26,6 +26,7 @@ MongoFindQuerySchema =
|
|||
{type: 'object'}
|
||||
{type: 'boolean'}
|
||||
]
|
||||
properties: {}
|
||||
additionalProperties: false
|
||||
definitions: {}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ _.extend ClassroomSchema.properties,
|
|||
ownerID: c.objectId()
|
||||
description: {type: 'string'}
|
||||
code: c.shortString(title: "Unique code to redeem")
|
||||
aceConfig:
|
||||
language: {type: 'string', 'enum': ['python', 'javascript']}
|
||||
|
||||
c.extendBasicProperties ClassroomSchema, 'Classroom'
|
||||
|
||||
|
|
|
@ -169,6 +169,11 @@ _.extend LevelSessionSchema.properties,
|
|||
chat:
|
||||
type: 'array'
|
||||
|
||||
ladderAchievementDifficulty:
|
||||
type: 'integer'
|
||||
minimum: 0
|
||||
description: 'What ogre AI difficulty, 0-4, this human session has beaten in a multiplayer arena.'
|
||||
|
||||
meanStrength:
|
||||
type: 'number'
|
||||
|
||||
|
|
|
@ -136,6 +136,7 @@ module.exports =
|
|||
|
||||
'tome:winnability-updated': c.object {title: 'Winnability Updated', description: 'When we think we can now win (or can no longer win), we may want to emphasize the submit button versus the run button (or vice versa), so this fires when we get new goal states (even preloaded goal states) suggesting success or failure change.', required: ['winnable']},
|
||||
winnable: {type: 'boolean'}
|
||||
level: {type: 'object'}
|
||||
|
||||
# Problem Alert
|
||||
'tome:show-problem-alert': c.object {title: 'Show Problem Alert', description: 'A problem alert needs to be shown.', required: ['problem']},
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
|
||||
img.media-object
|
||||
width: 300px
|
||||
|
||||
.edit-classroom-small
|
||||
cursor: pointer
|
||||
&:hover
|
||||
color: grey
|
||||
|
||||
#fixed-area
|
||||
position: fixed
|
||||
|
|
|
@ -190,7 +190,7 @@
|
|||
// border-bottom: 1px dotted rgba(0, 51, 255, 0.25)
|
||||
|
||||
.ace_text-layer .ace_comment
|
||||
color: rgb(78, 38, 226)
|
||||
color: #1900AD
|
||||
|
||||
.ace_text-layer .ace_variable
|
||||
// https://github.com/codecombat/codecombat/issues/6
|
||||
|
|
|
@ -80,28 +80,26 @@ block content
|
|||
span.spr(data-i18n="[title]account_prepaid.copy_link;general.code", title="You can copy the code's link and send it to someone.")
|
||||
span.glyphicon.glyphicon-question-sign(aria-hidden="true")
|
||||
th(data-i18n="account_prepaid.months")
|
||||
th(data-i18n="account_prepaid.quantity")
|
||||
th Remaining Users
|
||||
th Total Users
|
||||
th(data-i18n="user.status")
|
||||
for code in codes.models
|
||||
if code.get('type') === 'terminal_subscription'
|
||||
- var owner = (code.get('creator') == me.id ? true : false)
|
||||
- var properties = code.get('properties')
|
||||
- var redeemers = code.get('redeemers')
|
||||
if redeemers
|
||||
- var redeemed = redeemers.length
|
||||
else
|
||||
- var redeemed = '0'
|
||||
- var redeemed = redeemers ? redeemers.length : 0
|
||||
tr
|
||||
td
|
||||
a(href="/account/prepaid?_ppc=#{code.get('code')}")= code.get('code')
|
||||
td= properties.months || '-'
|
||||
if owner
|
||||
td= code.get('maxRedeemers') - redeemed
|
||||
else
|
||||
td -
|
||||
if owner
|
||||
td= code.get('maxRedeemers')
|
||||
td(data-i18n="account.purchased")
|
||||
else
|
||||
td -
|
||||
td -
|
||||
td(data-i18n="account_prepaid.redeemed")
|
||||
else
|
||||
p(data-i18n="account_prepaid.no_codes")
|
||||
|
|
24
app/templates/courses/classroom-settings-modal.jade
Normal file
24
app/templates/courses/classroom-settings-modal.jade
Normal file
|
@ -0,0 +1,24 @@
|
|||
extends /templates/core/modal-base
|
||||
|
||||
block modal-header-content
|
||||
button.close(data-dismiss='modal')
|
||||
span ×
|
||||
h3.modal-title(data-i18n="courses.edit_settings1")
|
||||
|
||||
block modal-body-content
|
||||
.form
|
||||
.form-group
|
||||
label(data-i18n="courses.title")
|
||||
input.form-control.settings-name-input(type='text', value="#{view.classroom.get('name') || ''}")
|
||||
.form-group
|
||||
label(data-i18n="courses.description")
|
||||
textarea.form-control.settings-description-input(rows=2)= view.classroom.get('description')
|
||||
.form-group
|
||||
label(data-i18n="choose_hero.programming_language")
|
||||
select.form-control#programming-language-select
|
||||
- var aceConfig = view.classroom.get('aceConfig') || {};
|
||||
option(value="python", selected=aceConfig.language==='python') Python
|
||||
option(value="javascript", selected=aceConfig.language==='javascript') JavaScript
|
||||
|
||||
block modal-footer-content
|
||||
button#save-settings-btn.btn(data-i18n="common.save_changes")
|
|
@ -53,12 +53,7 @@ block content
|
|||
if courseInstance.get('description')
|
||||
each line in courseInstance.get('description').split('\n')
|
||||
div= line
|
||||
// TODO: migrate these settings to classrooms
|
||||
//if adminMode && courseInstance
|
||||
// +settings-dialog
|
||||
// p
|
||||
// button.btn.btn-xs(data-toggle='modal', data-target='#settingsModal', data-i18n="courses.edit_settings")
|
||||
|
||||
|
||||
div.well.well-sm(role='tabpanel')
|
||||
ul.nav.nav-pills(role='tablist')
|
||||
if adminMode
|
||||
|
@ -292,27 +287,3 @@ mixin levels-tab
|
|||
if levelConceptMap[levelID][concept]
|
||||
span.spr.progress-level-cell.progress-level-cell-not-started(data-i18n="concepts." + concept)
|
||||
|
||||
mixin settings-dialog
|
||||
.modal#settingsModal
|
||||
.modal-dialog
|
||||
.modal-header
|
||||
button.close(data-dismiss='modal')
|
||||
span ×
|
||||
h3.modal-title(data-i18n="courses.edit_settings1")
|
||||
.modal-body
|
||||
.form
|
||||
.form-group
|
||||
label(data-i18n="courses.title")
|
||||
input.form-control.settings-name-input(type='text', value="#{courseInstance.get('name') || ''}")
|
||||
.form-group
|
||||
label(data-i18n="courses.description")
|
||||
textarea.form-control.settings-description-input(rows=2)= courseInstance.get('description')
|
||||
.form-group
|
||||
label(data-i18n="choose_hero.programming_language")
|
||||
select.form-control#programming-language-select
|
||||
- var aceConfig = view.courseInstance.get('aceConfig') || {};
|
||||
option(value="python", selected=aceConfig.language==='python') Python
|
||||
option(value="javascript", selected=aceConfig.language==='javascript') JavaScript
|
||||
|
||||
.modal-footer
|
||||
button.btn.btn-save-settings(data-i18n="common.save_changes")
|
||||
|
|
|
@ -102,7 +102,15 @@ block content
|
|||
a.btn.btn-default.btn-xs(href="/courses/purchase") Add
|
||||
|
||||
for classroom in view.classrooms.models
|
||||
h2= classroom.get('name')
|
||||
h2
|
||||
span.spr= classroom.get('name')
|
||||
- var language = (classroom.get('aceConfig') || {}).language || 'python';
|
||||
if language === 'python'
|
||||
img(src="/images/common/code_languages/python_icon.png")
|
||||
if language === 'javascript'
|
||||
img(src="/images/common/code_languages/javascript_icon.png")
|
||||
small.spl.edit-classroom-small(data-classroom-id=classroom.id)
|
||||
span.glyphicon.glyphicon-pencil
|
||||
|
||||
- var courseInstances = view.courseInstances.where({classroomID: classroom.id})
|
||||
|
||||
|
@ -111,6 +119,9 @@ block content
|
|||
.progress-bar(style="width: 100%")
|
||||
|
||||
else
|
||||
- var description = classroom.get('description');
|
||||
if description
|
||||
p= description
|
||||
table.table
|
||||
tr
|
||||
th Student
|
||||
|
|
|
@ -26,48 +26,49 @@ block modal-body-content
|
|||
textarea(data-i18n="[placeholder]play_level.victory_review_placeholder")
|
||||
.clearfix
|
||||
|
||||
for achievement in achievements
|
||||
- var animate = achievement.completed && !achievement.completedAWhileAgo
|
||||
.achievement-panel(class=achievement.completedAWhileAgo ? 'earned' : '' data-achievement-id=achievement.id data-animate=animate)
|
||||
- var rewards = achievement.get('rewards') || {};
|
||||
|
||||
div.achievement-description= achievement.description
|
||||
|
||||
div.achievement-rewards
|
||||
- var worth = achievement.worth;
|
||||
- var previousWorth = achievement.previousWorth;
|
||||
- var gems = achievement.gems;
|
||||
- var previousGems = achievement.previousGems;
|
||||
if worth
|
||||
.reward-panel.numerical.xp(data-number=worth, data-number-unit='xp', data-previous-number=previousWorth || 0)
|
||||
.reward-image-container(class=animate ? 'pending-reward-image' : 'show')
|
||||
img(src="/images/pages/play/level/modal/reward_icon_xp.png")
|
||||
.reward-text= animate ? '+0' : '+'+worth
|
||||
if level.get('type', true) === 'hero' || level.get('type') == 'hero-ladder'
|
||||
for achievement in achievements
|
||||
- var animate = achievement.completed && !achievement.completedAWhileAgo
|
||||
.achievement-panel(class=achievement.completedAWhileAgo ? 'earned' : '' data-achievement-id=achievement.id data-animate=animate)
|
||||
- var rewards = achievement.get('rewards') || {};
|
||||
|
||||
if gems
|
||||
.reward-panel.numerical.gems(data-number=gems, data-number-unit='gem', data-previous-number=previousGems || 0)
|
||||
.reward-image-container(class=animate ? 'pending-reward-image' : 'show')
|
||||
img(src="/images/pages/play/level/modal/reward_icon_gems.png")
|
||||
.reward-text= animate ? '+0' : '+'+gems
|
||||
|
||||
if rewards.heroes
|
||||
for hero in rewards.heroes
|
||||
- var hero = thangTypes[hero];
|
||||
.reward-panel.hero(data-hero-thang-type=hero.get('original'))
|
||||
.reward-image-container(class=animate ? 'pending-reward-image' : 'show')
|
||||
img(src=hero.getPortraitURL())
|
||||
.reward-text= animate ? 'New Hero' : hero.get('name')
|
||||
div.achievement-description= achievement.description
|
||||
|
||||
if rewards.items
|
||||
for item in rewards.items
|
||||
- var item = thangTypes[item];
|
||||
.reward-panel.item(data-item-thang-type=item.get('original'))
|
||||
div.achievement-rewards
|
||||
- var worth = achievement.worth;
|
||||
- var previousWorth = achievement.previousWorth;
|
||||
- var gems = achievement.gems;
|
||||
- var previousGems = achievement.previousGems;
|
||||
if worth
|
||||
.reward-panel.numerical.xp(data-number=worth, data-number-unit='xp', data-previous-number=previousWorth || 0)
|
||||
.reward-image-container(class=animate ? 'pending-reward-image' : 'show')
|
||||
img(src=item.getPortraitURL())
|
||||
if animate
|
||||
.reward-text(data-i18n="play_level.victory_new_item") New Item
|
||||
else
|
||||
.reward-text= i18n(item.attributes, 'name')
|
||||
img(src="/images/pages/play/level/modal/reward_icon_xp.png")
|
||||
.reward-text= animate ? '+0' : '+'+worth
|
||||
|
||||
if gems
|
||||
.reward-panel.numerical.gems(data-number=gems, data-number-unit='gem', data-previous-number=previousGems || 0)
|
||||
.reward-image-container(class=animate ? 'pending-reward-image' : 'show')
|
||||
img(src="/images/pages/play/level/modal/reward_icon_gems.png")
|
||||
.reward-text= animate ? '+0' : '+'+gems
|
||||
|
||||
if rewards.heroes
|
||||
for hero in rewards.heroes
|
||||
- var hero = thangTypes[hero];
|
||||
.reward-panel.hero(data-hero-thang-type=hero.get('original'))
|
||||
.reward-image-container(class=animate ? 'pending-reward-image' : 'show')
|
||||
img(src=hero.getPortraitURL())
|
||||
.reward-text= animate ? 'New Hero' : hero.get('name')
|
||||
|
||||
if rewards.items
|
||||
for item in rewards.items
|
||||
- var item = thangTypes[item];
|
||||
.reward-panel.item(data-item-thang-type=item.get('original'))
|
||||
.reward-image-container(class=animate ? 'pending-reward-image' : 'show')
|
||||
img(src=item.getPortraitURL())
|
||||
if animate
|
||||
.reward-text(data-i18n="play_level.victory_new_item") New Item
|
||||
else
|
||||
.reward-text= i18n(item.attributes, 'name')
|
||||
|
||||
block modal-footer-content
|
||||
#totals
|
||||
|
|
|
@ -38,7 +38,7 @@ module.exports = class RootView extends CocoView
|
|||
showNewAchievement: (achievement, earnedAchievement) ->
|
||||
earnedAchievement.set('notified', true)
|
||||
earnedAchievement.patch()
|
||||
return if achievement.get('collection') is 'level.sessions'
|
||||
return if achievement.get('collection') is 'level.sessions' and not achievement.get('query')?.team
|
||||
#return if @isIE() # Some bugs in IE right now, TODO fix soon! # Maybe working now with not caching achievement fetches in CocoModel?
|
||||
new AchievementPopup achievement: achievement, earnedAchievement: earnedAchievement
|
||||
|
||||
|
|
26
app/views/courses/ClassroomSettingsModal.coffee
Normal file
26
app/views/courses/ClassroomSettingsModal.coffee
Normal file
|
@ -0,0 +1,26 @@
|
|||
ModalView = require 'views/core/ModalView'
|
||||
template = require 'templates/courses/classroom-settings-modal'
|
||||
|
||||
module.exports = class AddLevelSystemModal extends ModalView
|
||||
id: 'classroom-settings-modal'
|
||||
template: template
|
||||
|
||||
events:
|
||||
'click #save-settings-btn': 'onClickSaveSettingsButton'
|
||||
|
||||
initialize: (options) ->
|
||||
@classroom = options.classroom
|
||||
|
||||
onClickSaveSettingsButton: ->
|
||||
return unless @classroom
|
||||
if name = $('.settings-name-input').val()
|
||||
@classroom.set('name', name)
|
||||
description = $('.settings-description-input').val()
|
||||
@classroom.set('description', description)
|
||||
@classroom.set('aceConfig', {
|
||||
language: @$('#programming-language-select').val()
|
||||
})
|
||||
@classroom.patch()
|
||||
@hide()
|
||||
|
||||
|
|
@ -19,7 +19,6 @@ module.exports = class CourseDetailsView extends RootView
|
|||
events:
|
||||
'change .progress-expand-checkbox': 'onCheckExpandedProgress'
|
||||
'click .btn-play-level': 'onClickPlayLevel'
|
||||
'click .btn-save-settings': 'onClickSaveSettings'
|
||||
'click .btn-select-instance': 'onClickSelectInstance'
|
||||
'click .progress-member-header': 'onClickMemberHeader'
|
||||
'click .progress-header': 'onClickProgressHeader'
|
||||
|
@ -228,19 +227,6 @@ module.exports = class CourseDetailsView extends RootView
|
|||
getLevelURL: (levelSlug) ->
|
||||
"/play/level/#{levelSlug}?course=#{@courseID}&course-instance=#{@courseInstanceID}"
|
||||
|
||||
onClickSaveSettings: (e) ->
|
||||
return unless @courseInstance
|
||||
if name = $('.settings-name-input').val()
|
||||
@courseInstance.set('name', name)
|
||||
description = $('.settings-description-input').val()
|
||||
console.log 'onClickSaveSettings', description
|
||||
@courseInstance.set('description', description)
|
||||
@courseInstance.set('aceConfig', {
|
||||
language: @$('#programming-language-select').val()
|
||||
})
|
||||
@courseInstance.patch()
|
||||
$('#settingsModal').modal('hide')
|
||||
|
||||
onClickSelectInstance: (e) ->
|
||||
courseInstanceID = $('.select-instance').val()
|
||||
@noCourseInstanceSelected = false
|
||||
|
|
|
@ -11,6 +11,7 @@ RootView = require 'views/core/RootView'
|
|||
template = require 'templates/courses/teacher-courses-view'
|
||||
utils = require 'core/utils'
|
||||
InviteToClassroomModal = require 'views/courses/InviteToClassroomModal'
|
||||
ClassroomSettingsModal = require 'views/courses/ClassroomSettingsModal'
|
||||
|
||||
module.exports = class TeacherCoursesView extends RootView
|
||||
id: 'teacher-courses-view'
|
||||
|
@ -22,6 +23,7 @@ module.exports = class TeacherCoursesView extends RootView
|
|||
'click .course-instance-membership-checkbox': 'onClickCourseInstanceMembershipCheckbox'
|
||||
'click #save-changes-btn': 'onClickSaveChangesButton'
|
||||
'click #manage-tab-link': 'onClickManageTabLink'
|
||||
'click .edit-classroom-small': 'onClickEditClassroomSmall'
|
||||
|
||||
constructor: (options) ->
|
||||
super(options)
|
||||
|
@ -71,6 +73,13 @@ module.exports = class TeacherCoursesView extends RootView
|
|||
@renderSelectors('#manage-tab-pane')
|
||||
@$('#manage-tab-pane').toggleClass('active', isActive)
|
||||
|
||||
onClickEditClassroomSmall: (e) ->
|
||||
classroomID = $(e.target).closest('small').data('classroom-id')
|
||||
classroom = @classrooms.get(classroomID)
|
||||
modal = new ClassroomSettingsModal({classroom: classroom})
|
||||
@openModalView(modal)
|
||||
@listenToOnce modal, 'hide', @renderManageTab
|
||||
|
||||
onClickAddStudentsButton: (e) ->
|
||||
classroomID = $(e.target).data('classroom-id')
|
||||
classroom = @classrooms.get(classroomID)
|
||||
|
|
|
@ -33,7 +33,7 @@ class LevelSessionsCollection extends CocoCollection
|
|||
@url = "/db/user/#{me.id}/level.sessions?project=state.complete,levelID,state.difficulty,playtime"
|
||||
|
||||
class CampaignsCollection extends CocoCollection
|
||||
url: '/db/campaign'
|
||||
url: '/db/campaign/-/overworld'
|
||||
model: Campaign
|
||||
project: ['name', 'fullName', 'description', 'i18n']
|
||||
|
||||
|
@ -427,7 +427,8 @@ module.exports = class CampaignView extends RootView
|
|||
onSessionsLoaded: (e) ->
|
||||
return if @editorMode
|
||||
for session in @sessions.models
|
||||
@levelStatusMap[session.get('levelID')] = if session.get('state')?.complete then 'complete' else 'started'
|
||||
unless @levelStatusMap[session.get('levelID')] is 'complete' # Don't overwrite a complete session with an incomplete one
|
||||
@levelStatusMap[session.get('levelID')] = if session.get('state')?.complete then 'complete' else 'started'
|
||||
@levelDifficultyMap[session.get('levelID')] = session.get('state').difficulty if session.get('state')?.difficulty
|
||||
@render()
|
||||
@loadUserPollsRecord() unless me.get 'anonymous'
|
||||
|
|
|
@ -48,7 +48,7 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
@session = options.session
|
||||
@level = options.level
|
||||
@thangTypes = {}
|
||||
if @level.get('type', true) is 'hero'
|
||||
if @level.get('type', true) in ['hero', 'hero-ladder', 'course', 'course-ladder']
|
||||
achievements = new CocoCollection([], {
|
||||
url: "/db/achievement?related=#{@session.get('level').original}"
|
||||
model: Achievement
|
||||
|
@ -212,7 +212,7 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
|
||||
afterRender: ->
|
||||
super()
|
||||
@$el.toggleClass 'with-achievements', @level.get('type', true) is 'hero'
|
||||
@$el.toggleClass 'with-achievements', @level.get('type', true) in ['hero', 'hero-ladder']
|
||||
return unless @supermodel.finished()
|
||||
@playSelectionSound hero, true for original, hero of @thangTypes # Preload them
|
||||
@updateSavingProgressStatus()
|
||||
|
@ -222,8 +222,8 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
@insertSubView @ladderSubmissionView, @$el.find('.ladder-submission-view')
|
||||
|
||||
initializeAnimations: ->
|
||||
if @level.get('type', true) is 'hero'
|
||||
@updateXPBars 0
|
||||
return @endSequentialAnimations() unless @level.get('type', true) in ['hero', 'hero-ladder']
|
||||
@updateXPBars 0
|
||||
#playVictorySound = => @playSound 'victory-title-appear' # TODO: actually add this
|
||||
@$el.find('#victory-header').delay(250).queue(->
|
||||
$(@).removeClass('out').dequeue()
|
||||
|
@ -253,7 +253,7 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
|
||||
beginSequentialAnimations: ->
|
||||
return if @destroyed
|
||||
return unless @level.get('type', true) is 'hero'
|
||||
return unless @level.get('type', true) in ['hero', 'hero-ladder']
|
||||
@sequentialAnimatedPanels = _.map(@animatedPanels.find('.reward-panel'), (panel) -> {
|
||||
number: $(panel).data('number')
|
||||
previousNumber: $(panel).data('previous-number')
|
||||
|
|
|
@ -56,7 +56,7 @@ module.exports = class CastButtonView extends CocoView
|
|||
@$el.find('.submit-button').hide() # Hide Submit for the first few until they run it once.
|
||||
if @options.session.get('state')?.complete and @options.level.get 'hidesRealTimePlayback'
|
||||
@$el.find('.done-button').show()
|
||||
if @options.level.get('slug') is 'thornbush-farm'# and not @options.session.get('state')?.complete
|
||||
if @options.level.get('slug') in ['course-thornbush-farm', 'thornbush-farm']
|
||||
@$el.find('.submit-button').hide() # Hide submit until first win so that script can explain it.
|
||||
@updateReplayability()
|
||||
@updateLadderSubmissionViews()
|
||||
|
@ -114,17 +114,17 @@ module.exports = class CastButtonView extends CocoView
|
|||
return if @winnable is winnable
|
||||
@winnable = winnable
|
||||
@$el.toggleClass 'winnable', @winnable
|
||||
Backbone.Mediator.publish 'tome:winnability-updated', winnable: @winnable
|
||||
Backbone.Mediator.publish 'tome:winnability-updated', winnable: @winnable, level: @options.level
|
||||
if @options.level.get 'hidesRealTimePlayback'
|
||||
@$el.find('.done-button').toggle @winnable
|
||||
else if @winnable and @options.level.get('slug') is 'thornbush-farm'
|
||||
else if @winnable and @options.level.get('slug') in ['course-thornbush-farm', 'thornbush-farm']
|
||||
@$el.find('.submit-button').show() # Hide submit until first win so that script can explain it.
|
||||
|
||||
onGoalsCalculated: (e) ->
|
||||
# When preloading, with real-time playback enabled, we highlight the submit button when we think they'll win.
|
||||
return unless e.preload
|
||||
return if @options.level.get 'hidesRealTimePlayback'
|
||||
return if @options.level.get('slug') is 'thornbush-farm' # Don't show it until they actually win for this first one.
|
||||
return if @options.level.get('slug') in ['course-thornbush-farm', 'thornbush-farm'] # Don't show it until they actually win for this first one.
|
||||
@onNewGoalStates e
|
||||
|
||||
updateCastButton: ->
|
||||
|
|
|
@ -31,6 +31,7 @@ module.exports = class PlayAchievementsModal extends ModalView
|
|||
'rewards'
|
||||
'collection'
|
||||
'function'
|
||||
'query'
|
||||
])
|
||||
|
||||
earnedAchievementsFetcher = new CocoCollection([], {url: '/db/earned_achievement', model: EarnedAchievement})
|
||||
|
@ -72,8 +73,10 @@ module.exports = class PlayAchievementsModal extends ModalView
|
|||
@onEverythingLoaded()
|
||||
|
||||
onEverythingLoaded: =>
|
||||
@achievements.set(@achievements.filter((m) -> m.get('collection') isnt 'level.sessions'))
|
||||
console.log 'got achievements', m.attributes for m in @achievements.models
|
||||
@achievements.set(@achievements.filter((m) -> m.get('collection') isnt 'level.sessions' or m.get('query')?.team))
|
||||
for achievement in @achievements.models
|
||||
console.log 'kept achievement', achievement.attributes
|
||||
if earned = @earnedMap[achievement.id]
|
||||
achievement.earned = earned
|
||||
achievement.earnedDate = earned.getCreationDate()
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
"mongoose-cache": "~0.1.4",
|
||||
"node-force-domain": "~0.1.0",
|
||||
"node-gyp": "~0.13.0",
|
||||
"node-statsd": "^0.1.1",
|
||||
"passport": "0.1.x",
|
||||
"passport-local": "0.1.x",
|
||||
"redis": "",
|
||||
|
|
|
@ -52,8 +52,22 @@ CampaignHandler = class CampaignHandler extends Handler
|
|||
documents = (@formatEntity(req, doc) for doc in documents)
|
||||
@sendSuccess(res, documents)
|
||||
|
||||
getOverworld: (req, res) ->
|
||||
return @sendForbiddenError(res) if not @hasAccess(req)
|
||||
q = @modelClass.find {}, slug: 1, adjacentCampaigns: 1, fullName: 1, description: 1, color: 1
|
||||
q.exec (err, documents) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
formatCampaign = (doc) =>
|
||||
obj = @formatEntity(req, doc)
|
||||
obj.adjacentCampaigns = _.mapValues(obj.adjacentCampaigns, (a) -> _.pick(a, ['showIfUnlocked', 'color', 'name', 'description' ]))
|
||||
obj
|
||||
documents = (formatCampaign(doc) for doc in documents)
|
||||
@sendSuccess(res, documents)
|
||||
|
||||
getByRelationship: (req, res, args...) ->
|
||||
relationship = args[1]
|
||||
return @getOverworld(req,res) if args[0] is '-' and relationship is 'overworld'
|
||||
|
||||
if relationship in ['levels', 'achievements']
|
||||
projection = {}
|
||||
if req.query.project
|
||||
|
|
|
@ -11,6 +11,7 @@ ClassroomSchema.statics.privateProperties = []
|
|||
ClassroomSchema.statics.editableProperties = [
|
||||
'description'
|
||||
'name'
|
||||
'aceConfig'
|
||||
]
|
||||
|
||||
ClassroomSchema.statics.generateNewCode = (done) ->
|
||||
|
|
43
server/commons/perfmon.coffee
Normal file
43
server/commons/perfmon.coffee
Normal file
|
@ -0,0 +1,43 @@
|
|||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
config = require '../../server_config'
|
||||
StatsD = require 'node-statsd'
|
||||
|
||||
if config.statsd
|
||||
realClient = new StatsD(config.statsd)
|
||||
else
|
||||
mock = new StatsD(mock: true)
|
||||
|
||||
exports.client = realClient or mock
|
||||
exports.middleware = (req, res, next) ->
|
||||
|
||||
req.statsd = exports.client
|
||||
if realClient
|
||||
time = process.hrtime();
|
||||
cleanup = ->
|
||||
res.removeListener 'finish', recordMetrics
|
||||
res.removeListener 'error', cleanup
|
||||
res.removeListener 'close', cleanup
|
||||
|
||||
recordMetrics = ->
|
||||
diff = process.hrtime(time);
|
||||
ms = (diff[0] * 1000 + diff[1] / 1e6);
|
||||
path = req.route?.path or '/*'
|
||||
stat = req.method + "." + path.replace /[^A-Za-z0-9]+/g, '_'
|
||||
realClient.timing stat, ms
|
||||
|
||||
|
||||
res.once 'finish', recordMetrics
|
||||
res.once 'error', cleanup
|
||||
res.once 'close', cleanup
|
||||
else
|
||||
req.statsd = mock
|
||||
|
||||
next() unless not next
|
||||
|
||||
exports.trace = (name, callback) ->
|
||||
return callback unless realClient
|
||||
time = process.hrtime()
|
||||
(args...) ->
|
||||
realClient.timing name, ms
|
||||
return callback.apply(this, args)
|
|
@ -11,6 +11,7 @@ log = require 'winston'
|
|||
Campaign = require '../campaigns/Campaign'
|
||||
Course = require '../courses/Course'
|
||||
CourseInstance = require '../courses/CourseInstance'
|
||||
Classroom = require '../classrooms/Classroom'
|
||||
|
||||
LevelHandler = class LevelHandler extends Handler
|
||||
modelClass: Level
|
||||
|
@ -129,10 +130,16 @@ LevelHandler = class LevelHandler extends Handler
|
|||
courses = _.filter(courses, (course) -> course.get('campaignID').toString() in campaignStrings)
|
||||
courseStrings = (course.id.toString() for course in courses)
|
||||
courseInstances = _.filter(courseInstances, (courseInstance) -> courseInstance.get('courseID').toString() in courseStrings)
|
||||
aceConfigs = (ci.get('aceConfig') for ci in courseInstances)
|
||||
aceConfig = _.filter(aceConfigs)[0] or {}
|
||||
req.codeLanguage = aceConfig.language
|
||||
@createAndSaveNewSession(sessionQuery, req, res)
|
||||
classroomIDs = (courseInstance.get('classroomID') for courseInstance in courseInstances)
|
||||
classroomIDs = _.filter _.uniq classroomIDs, false, (objectID='') -> objectID.toString()
|
||||
if classroomIDs.length
|
||||
Classroom.find({ _id: { $in: classroomIDs }}).exec (err, classrooms) =>
|
||||
aceConfigs = (c.get('aceConfig') for c in classrooms)
|
||||
aceConfig = _.filter(aceConfigs)[0] or {}
|
||||
req.codeLanguage = aceConfig.language
|
||||
@createAndSaveNewSession(sessionQuery, req, res)
|
||||
else
|
||||
@createAndSaveNewSession(sessionQuery, req, res)
|
||||
else
|
||||
return @sendPaymentRequiredError(res, 'You must be in a course which includes this level to play it')
|
||||
|
||||
|
|
|
@ -52,12 +52,13 @@ module.exports.calculateSessionScores = (callback) ->
|
|||
|
||||
retrieveOldSessionData = (sessionID, callback) ->
|
||||
formatOldScoreObject = (session) =>
|
||||
oldScoreObject =
|
||||
oldScoreObject =
|
||||
standardDeviation: session.standardDeviation ? 25/3
|
||||
meanStrength: session.meanStrength ? 25
|
||||
totalScore: session.totalScore ? (25 - 1.8*(25/3))
|
||||
id: sessionID
|
||||
submittedCodeLanguage: session.submittedCodeLanguage
|
||||
ladderAchievementDifficulty: session.ladderAchievementDifficulty
|
||||
if session.leagues?.length
|
||||
_.find(@clientResponseObject.sessions, sessionID: sessionID).leagues = session.leagues
|
||||
oldScoreObject.leagues = []
|
||||
|
@ -74,7 +75,7 @@ retrieveOldSessionData = (sessionID, callback) ->
|
|||
return formatOldScoreObject @levelSession if sessionID is @levelSession?._id # No need to fetch again
|
||||
|
||||
query = _id: sessionID
|
||||
selection = 'standardDeviation meanStrength totalScore submittedCodeLanguage leagues'
|
||||
selection = 'standardDeviation meanStrength totalScore submittedCodeLanguage leagues ladderAchievementDifficulty'
|
||||
LevelSession.findOne(query).select(selection).lean().exec (err, session) ->
|
||||
return callback err, {'error': 'There was an error retrieving the session.'} if err?
|
||||
callback err, formatOldScoreObject session
|
||||
|
@ -150,6 +151,13 @@ module.exports.addMatchToSessionsAndUpdate = (newScoreObject, callback) ->
|
|||
async.each sessionIDs, updateMatchesInSession.bind(@, matchObject), (err) ->
|
||||
callback err
|
||||
|
||||
ladderBenchmarkAIs =
|
||||
'564ba6cea33967be1312ae59': 0
|
||||
'564ba830a33967be1312ae61': 1
|
||||
'564ba91aa33967be1312ae65': 2
|
||||
'564ba95ca33967be1312ae69': 3
|
||||
'564ba9b7a33967be1312ae6d': 4
|
||||
|
||||
updateMatchesInSession = (matchObject, sessionID, callback) ->
|
||||
currentMatchObject = {}
|
||||
currentMatchObject.date = matchObject.date
|
||||
|
@ -163,6 +171,11 @@ updateMatchesInSession = (matchObject, sessionID, callback) ->
|
|||
#currentMatchObject.randomSeed = parseInt(@clientResponseObject.randomSeed or 0, 10) # Uncomment when actively debugging simulation mismatches
|
||||
sessionUpdateObject = @levelSessionUpdates[sessionID]
|
||||
sessionUpdateObject.$push.matches = {$each: [currentMatchObject], $slice: -200}
|
||||
if currentMatchObject.metrics.rank is 0 and defeatedAI = ladderBenchmarkAIs[currentMatchObject.opponents[0].userID]
|
||||
mySession = _.find @clientResponseObject.sessions, sessionID: sessionID
|
||||
newLadderAchievementDifficulty = Math.max defeatedAI, mySession.ladderAchievementDifficulty || 0
|
||||
if newLadderAchievementDifficulty isnt mySession.ladderAchievementDifficulty
|
||||
sessionUpdateObject.ladderAchievementDifficulty = newLadderAchievementDifficulty
|
||||
|
||||
myScoreObject = @newScoresObject[sessionID]
|
||||
opponentSession = _.find @clientResponseObject.sessions, (session) -> session.sessionID isnt sessionID
|
||||
|
|
|
@ -459,6 +459,7 @@ UserHandler = class UserHandler extends Handler
|
|||
sendMail emailParams
|
||||
|
||||
getPrepaidCodes: (req, res) ->
|
||||
return @sendSuccess(res, []) unless req.user?
|
||||
orQuery = [{ creator: req.user._id }, { 'redeemers.userID' : req.user._id }]
|
||||
Prepaid.find({}).or(orQuery).exec (err, documents) =>
|
||||
@sendSuccess(res, documents)
|
||||
|
|
|
@ -84,5 +84,10 @@ if not config.unittest and not config.isProduction
|
|||
# change artificially slow down non-static requests for testing
|
||||
config.slow_down = false
|
||||
|
||||
if process.env.COCO_STATSD_HOST
|
||||
config.statsd =
|
||||
host: process.env.COCO_STATSD_HOST
|
||||
port: process.env.COCO_STATSD_PORT or 8125
|
||||
prefix: process.env.COCO_STATSD_PREFIX or ''
|
||||
|
||||
module.exports = config
|
||||
|
|
|
@ -8,6 +8,7 @@ compressible = require 'compressible'
|
|||
geoip = require 'geoip-lite'
|
||||
|
||||
database = require './server/commons/database'
|
||||
perfmon = require './server/commons/perfmon'
|
||||
baseRoute = require './server/routes/base'
|
||||
user = require './server/users/user_handler'
|
||||
logging = require './server/commons/logging'
|
||||
|
@ -127,8 +128,11 @@ setupRedirectMiddleware = (app) ->
|
|||
nameOrID = req.path.split('/')[3]
|
||||
res.redirect 301, "/user/#{nameOrID}/profile"
|
||||
|
||||
setupPerfMonMiddleware = (app) ->
|
||||
app.use perfmon.middleware
|
||||
|
||||
exports.setupMiddleware = (app) ->
|
||||
setupPerfMonMiddleware app
|
||||
setupCountryRedirectMiddleware app, "china", "CN", "zh", "tokyo"
|
||||
setupCountryRedirectMiddleware app, "brazil", "BR", "pt-BR", "saoPaulo"
|
||||
setupMiddlewareToSendOldBrowserWarningWhenPlayersViewLevelDirectly app
|
||||
|
|
|
@ -68,29 +68,41 @@ describe 'GET /db/level/<id>/session', ->
|
|||
course.save (err) ->
|
||||
|
||||
expect(err).toBeNull()
|
||||
|
||||
|
||||
loginJoe (joe) ->
|
||||
|
||||
courseInstance = new CourseInstance({
|
||||
name: 'Course Instance'
|
||||
members: [
|
||||
joe.get('_id')
|
||||
]
|
||||
courseID: ObjectId(course.id)
|
||||
classroom = new Classroom({
|
||||
name: 'Test Classroom'
|
||||
members: [ joe.get('_id') ]
|
||||
aceConfig: { language: 'javascript' }
|
||||
})
|
||||
|
||||
courseInstance.save (err) ->
|
||||
|
||||
classroom.save (err, classroom) ->
|
||||
|
||||
expect(err).toBeNull()
|
||||
done()
|
||||
|
||||
courseInstance = new CourseInstance({
|
||||
name: 'Course Instance'
|
||||
members: [
|
||||
joe.get('_id')
|
||||
]
|
||||
courseID: ObjectId(course.id)
|
||||
classroomID: ObjectId(classroom.id)
|
||||
})
|
||||
|
||||
courseInstance.save (err) ->
|
||||
|
||||
expect(err).toBeNull()
|
||||
done()
|
||||
|
||||
it 'creates a new session if the user is in a course with that level', (done) ->
|
||||
loginJoe (joe) ->
|
||||
|
||||
url = getURL("/db/level/#{levelID}/session")
|
||||
|
||||
request.get { uri: url }, (err, res, body) ->
|
||||
request.get { uri: url, json: true }, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body.codeLanguage).toBe('javascript')
|
||||
done()
|
||||
|
||||
it 'does not create a new session if the user is not in a course with that level', (done) ->
|
||||
|
|
Loading…
Add table
Reference in a new issue