Merge branch 'master' into production

This commit is contained in:
Nicholas Winter 2015-09-12 06:55:30 -07:00
commit 3cba4b23eb
22 changed files with 459 additions and 153 deletions

View file

@ -206,3 +206,40 @@ module.exports.getCoursesPrice = getSponsoredSubsAmount = (courses, seats=20) ->
else
pricePerSeat = parseInt(totalPricePerSeat)
seats * pricePerSeat
module.exports.getCoursePraise = getCoursePraise = ->
praise = [
{
quote: "The kids love it."
source: "Leo Joseph Tran, Athlos Leadership Academy"
},
{
quote: "My students have been using the site for a couple of weeks and they love it."
source: "Scott Hatfield, Computer Applications Teacher, School Technology Coordinator, Eastside Middle School"
},
{
quote: "Thanks for the captivating site. My eighth graders love it."
source: "Janet Cook, Ansbach Middle/High School"
},
{
quote: "My students have started working on CodeCombat and love it! I love that they are learning coding and problem solving skills without them even knowing it!!"
source: "Kristin Huff, Special Education Teacher, Webb City School District"
},
{
quote: "I recently introduced Code Combat to a few of my fifth graders and they are loving it!"
source: "Shauna Hamman, Fifth Grade Teacher, Four Peaks Elementary School"
},
{
quote: "Overall I think it's a fantastic service. Variables, arrays, loops, all covered in very fun and imaginative ways. Every kid who has tried it is a fan."
source: "Aibinder Andrew, Technology Teacher"
},
{
quote: "I love what you have created. The kids are so engaged."
source: "Desmond Smith, 4KS Academy"
},
{
quote: "My students love the website and I hope on having content structured around it in the near future."
source: "Michael Leonard, Science Teacher, Clearwater Central Catholic High School"
}
]
praise[_.random(0, praise.length - 1)]

View file

@ -485,46 +485,46 @@ module.exports = nativeDescription: "български език", englishDescri
# subscribe_prepaid: "Click Subscribe to use prepaid code"
# using_prepaid: "Using prepaid code for monthly subscription"
# choose_hero:
# choose_hero: "Choose Your Hero"
# programming_language: "Programming Language"
# programming_language_description: "Which programming language do you want to use?"
# default: "Default"
# experimental: "Experimental"
# python_blurb: "Simple yet powerful, great for beginners and experts."
# javascript_blurb: "The language of the web. (Not the same as Java.)"
# coffeescript_blurb: "Nicer JavaScript syntax."
# clojure_blurb: "A modern Lisp."
# lua_blurb: "Game scripting language."
# io_blurb: "Simple but obscure."
# status: "Status"
# hero_type: "Type"
# weapons: "Weapons"
# weapons_warrior: "Swords - Short Range, No Magic"
# weapons_ranger: "Crossbows, Guns - Long Range, No Magic"
# weapons_wizard: "Wands, Staffs - Long Range, Magic"
# attack: "Damage" # Can also translate as "Attack"
# health: "Health"
# speed: "Speed"
# regeneration: "Regeneration"
# range: "Range" # As in "attack or visual range"
# blocks: "Blocks" # As in "this shield blocks this much damage"
# backstab: "Backstab" # As in "this dagger does this much backstab damage"
# skills: "Skills"
# attack_1: "Deals"
# attack_2: "of listed"
# attack_3: "weapon damage."
# health_1: "Gains"
# health_2: "of listed"
# health_3: "armor health."
# speed_1: "Moves at"
# speed_2: "meters per second."
# available_for_purchase: "Available for Purchase" # Shows up when you have unlocked, but not purchased, a hero in the hero store
# level_to_unlock: "Level to unlock:" # Label for which level you have to beat to unlock a particular hero (click a locked hero in the store to see)
# restricted_to_certain_heroes: "Only certain heroes can play this level."
choose_hero:
choose_hero: "Избери си герой"
programming_language: "Език за програмиране"
programming_language_description: "Кой език за програмиране би искал да използваш?"
default: "По подразбиране"
experimental: "Експериментално"
python_blurb: "Прост,но мощен, идеален за начинаещи и експерти."
javascript_blurb: "Езикът на мрежата. (Не е същия като Java.)"
coffeescript_blurb: "По-добър синтаксис от JavaScript."
clojure_blurb: "Модерен Lisp."
lua_blurb: "Скриптен език за игри."
io_blurb: "Прост, но неизвестен."
status: "Статус"
hero_type: "Тип"
weapons: "Оръжия"
weapons_warrior: "Мечове - Къс Обсег, Без Магия"
weapons_ranger: "Арбалети, Пистолети - Далечен Обсег, Без магия"
weapons_wizard: "Жезли, Принадлежности - Далечен Обсег, Магия"
attack: "Щета" # Може също да се преведе като "Атака"
health: "Здраве"
speed: "Скорост"
regeneration: "Възстановяване"
range: "Обсег" # както в "обсег на атаката или визуален обсег"
blocks: "Защита" # както в "този щит може да те защити от много удари"
backstab: "Удар в гърба" # както в "тази кама може да е много опасна при удар в гърба"
skills: "Умения"
attack_1: "Количество"
attack_2: "на изброените"
attack_3: "щети от оръжия."
health_1: "Печалби"
health_2: "от изброените"
health_3: "защитни брони."
speed_1: "Движения"
speed_2: "в метри за секунда"
available_for_purchase: "На разположение за закупуване" # Показва се когато сте достигнали, но не сте закупили герой от магазина за герои "
level_to_unlock: "Ниво на отключване:" # Етикет за нивото, което трябва да достигнеш за да отключиш определен герой (кликни на заключения герой в магазина за да видиш)
restricted_to_certain_heroes: "Само определени герои могат да играят това ниво."
# skill_docs:
# writable: "writable" # Hover over "attack" in Your Skills while playing a level to see most of this
# writable: "writable" # Hover over "attack" in Your Skils while playing a level to see most of this
# read_only: "read-only"
# action_name: "name"
# action_cooldown: "Takes"

View file

@ -255,8 +255,8 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
victory_new_item: "Objeto Nuevo"
victory_viking_code_school: "Santo cielo, Holy smokes, el nivel que acabas de pasar era dificil! Si todavía no eres un desarrollador de software, deberías serlo. Acabas de conseguir una aceptación por vía rápida con la Escuela Vikinga de Có, donde tú puedes llevar tus habilidades al siguiente nivel y convertirteen un desarrollador web profesional en 14 semanas."
victory_become_a_viking: "Conviértete en un Vikingo"
# victory_bloc: "Great work! Your skills are improving, and someone's taking notice. If you've considered becoming a software developer, this may be your lucky day. Bloc is an online bootcamp that pairs you 1-on-1 with an expert mentor who will help train you into a professional developer! By beating A Mayhem of Munchkins, you're now eligible for a $500 price reduction with the code: CCRULES"
# victory_bloc_cta: "Meet your mentor learn about Bloc"
# victory_bloc: "¡Buen trabajo! Tus habilidades están mejorando, y alguien ya se dió cuenta. Si has considerado convertirte en un desarrollador de software, este podría ser tu día de suerte. Bloc es un online bootcamp que te pairs 1-on-1 with an expert mentor who will help train you into a professional developer! By beating A Mayhem of Munchkins, you're now eligible for a $500 price reduction with the code: CCRULES"
victory_bloc_cta: "Conoce a tu mentor aprende acerca de Bloc"
guide_title: "Guía"
tome_minion_spells: "Hechizos de tus Secuaces" # Only in old-style levels.
tome_read_only_spells: "Hechizos de Sólo Lectura" # Only in old-style levels.
@ -438,19 +438,19 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
payment_methods_blurb1: "Actualmente aceptamos tarjetas de credito y Alipay."
payment_methods_blurb2: "Si necesitas una forma alternativa de pago, por favor contactarse"
# sale_already_subscribed: "You're already subscribed!"
# sale_blurb1: "Save 35%"
sale_blurb1: "Ahorra 35%"
# sale_blurb2: "off regular subscription price of $120 for a whole year!" # {changed}
# sale_button: "Sale!"
# sale_button_title: "Save 35% when you purchase a 1 year subscription"
# sale_click_here: "Click Here"
# sale_ends: "Ends"
sale_click_here: "Haz Click Aquí"
sale_ends: "Termina"
# sale_extended: "*Existing subscriptions will be extended by 1 year."
# sale_feature_here: "Here's what you'll get:"
# sale_feature2: "Access to 9 powerful <strong>new heroes</strong> with unique skills!"
# sale_feature4: "<strong>42,000 bonus gems</strong> awarded immediately!"
# sale_continue: "Ready to continue adventuring?"
# sale_limited_time: "Limited time offer!"
# sale_new_heroes: "New heroes!"
sale_limited_time: "¡Oferta por tiempo limitado!"
sale_new_heroes: "¡Nuevos héroes!"
# sale_title: "Back to School Sale"
# sale_view_button: "Buy 1 year subscription for"
stripe_description: "Suscripción Mensual"
@ -547,7 +547,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
options:
general_options: "Opciones Generales" # Check out the Options tab in the Game Menu while playing a level
volume_label: "Volumen"
volume_label: "Volúmen"
music_label: "Música"
music_description: "Música encendida/apagada."
editor_config: "Config. de Editor"
@ -582,7 +582,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
press_paragraph_1_link: "paquete de prensa"
press_paragraph_1_suffix: ". Todos los logos e imágenes pueden ser usados sin contactarnos directamente."
team: "Equipo"
george_title: "CEO" # {change}
george_title: "Director Ejecutivo"
george_blurb: "Negociante"
scott_title: "Programador" # {change}
scott_blurb: "Razonable"
@ -665,10 +665,10 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
denied_2: "denegada."
contact_1: "Por favor contáctenos"
contact_2: "si tiene más preguntas."
# description_1: "We offer free subscriptions to teachers for evaluation purposes. You can find more information on our"
# description_1: "Ofrecemos free subscriptions to teachers for evaluation purposes. You can find more information on our"
description_2: "página"
description_3: "de maestros."
# description_4: "Please fill out this quick survey and well email you setup instructions."
# description_4: "Por favor fill out this quick survey and well email you setup instructions."
email: "Dirección de email"
school: "Nombre del colegio"
location: "Nombre de la ciudad"
@ -688,7 +688,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
cla_url: "CLA"
cla_suffix: "."
cla_agree: "ACEPTO"
# owner_approve: "An owner will need to approve it before your changes will become visible."
owner_approve: "Un dueño necesitará aprobarlo antes de que tus cambios puedan ser visibles."
contact:
contact_us: "Contacta a CodeCombat"
@ -779,12 +779,12 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
introduction: "Mira las maneras en las que puedes involucrarte adelante y decide qué es más divertido. ¡Queremos trabajar contigo!"
level_editor_prefix: "Usar CodeCombat"
level_editor_suffix: "para crear y editar niveles. Los han creado niveles para sus clases, amigos, hackatones, estudiantes, familiares. Si crear un nuevo juego luce intimidante puedes ¡comenzar con base en uno nuestro!"
thang_editor_prefix: "Nosotros llamamos a las unidades del juego 'thangs'. Usa el"
thang_editor_prefix: "Nosotros llamamos a las unidades del juego 'Tiliches'. Usa el"
thang_editor_suffix: "para modificar el arte de CodeCombat. Permite a las unidades lanzar proyectiles, altera la dirección de una animación, cambia los puntos de vida de una unidad o sube tu propio sprite de vectores."
article_editor_prefix: "¿Ves algún error en nuestros documentos? ¿Quieres hacer algunas instrucciones para tus propias creaciones? Revisa el"
article_editor_suffix: "y ayuda a los jugadores de CodeCombat conseguir lo más posible de su tiempo jugando."
find_us: "Encuentranos en etsos sitios"
# social_github: "Check out all our code on GitHub"
social_github: "Checa todo nuestro código en el GitHub"
social_blog: "Lee el blog de CodeCombat en Sett"
social_discource: "Unite a la discusión en nuestro foro"
social_facebook: "Me Gusta CodeCombat en Facebook"
@ -806,7 +806,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
my_clans: "Mis Clanes"
clan_name: "Nombre del clan"
name: "Nombre"
# chieftain: "Chieftain"
chieftain: "Cacique/Líder" #Chieftain/Leader literally
type: "Tipo"
edit_clan_name: "Editar el nombre del Clan"
edit_clan_description: "Editar descripción del clan"
@ -836,7 +836,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
latest_achievement: "último logro"
playtime: "Tiempo de juego"
last_played: "Último jugado"
# leagues_explanation: "Play in a league against other clan members in these multiplayer arena instances."
# leagues_explanation: "Juega en una liga contra otros miembros del clan en these multiplayer arena instances."
classes:
archmage_title: "Archimago"
@ -861,7 +861,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
editor:
main_title: "Editor de CodeCombat"
article_title: "Editor de Artículo"
thang_title: "Editor de Thangs"
thang_title: "Editor de Tiliches"
level_title: "Editor de Nivel"
achievement_title: "Editor de logros"
poll_title: "Editor de Encuesta"
@ -884,23 +884,23 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
wiki: "Wiki"
live_chat: "Chat en vivo"
thang_main: "Principal"
thang_spritesheets: "Spritesheets"
thang_spritesheets: "Hojas de figuras( para animaciones )"
thang_colors: "Colores"
level_some_options: "¿Algunas opciones?"
level_tab_thangs: "Thangs"
level_tab_thangs: "Tiliches" #Verificar cual es mejor: Cachivache, Tiliche, Artilugio, Bagatela, Cosa
level_tab_scripts: "Scripts"
level_tab_settings: "Opciones"
level_tab_components: "Componentes"
level_tab_systems: "Sistemas"
level_tab_docs: "Documentación"
level_tab_thangs_title: "Thangs Actuales"
level_tab_thangs_title: "Tiliches Actuales"
level_tab_thangs_all: "Todo"
level_tab_thangs_conditions: "Condiciones Iniciales"
level_tab_thangs_add: "Agregar Thangs"
# level_tab_thangs_search: "Search thangs"
level_tab_thangs_add: "Agregar Tiliches"
level_tab_thangs_search: "Buscar thangs"
add_components: "Agregar Componentes"
component_configs: "Configuraciones del Componente"
config_thang: "Doble clic para configurar un thang"
config_thang: "Doble clic para configurar un Tiliche"
delete: "Borrar"
duplicate: "Duplicar"
stop_duplicate: "Parar de Duplicar"
@ -911,7 +911,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
level_systems_tab_title: "Sistemas Actuales"
level_systems_btn_new: "Crear Nuevo Sistema"
level_systems_btn_add: "Agregar Sistema"
level_components_title: "Regresar a todos los Thangs"
level_components_title: "Regresar a todos los Tiliches"
level_components_type: "Tipo"
level_component_edit_title: "Editar Componente"
level_component_config_schema: "Config Schema"
@ -921,17 +921,17 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
new_component_title: "Crear Nuevo Componente"
new_component_field_system: "Sistema"
new_article_title: "Crear un Nuevo Artículo"
new_thang_title: "Crear un Nuevo tipo de Thang"
new_thang_title: "Crear un Nuevo tipo de Tiliche"
new_level_title: "Crear un Nuevo Nivel"
new_article_title_login: "Ingresa para Crear un Nuevo Artículo"
new_thang_title_login: "Ingresa para crear un nuevo tipo de Thang"
new_thang_title_login: "Ingresa para crear un nuevo tipo de Tiliche"
new_level_title_login: "Ingresa para Crear un Nuevo Nivel"
new_achievement_title: "Crear un Nuevo Logro"
new_achievement_title_login: "Ingresa para Crear un Nuevo Logro"
new_poll_title: "Crear una nueva encuesta"
new_poll_title_login: "Ingresa para crear una nueva encuesta"
article_search_title: "Buscar Artículos aquí"
thang_search_title: "Buscar tipos de Thang aquí"
thang_search_title: "Buscar tipos de Tiliche aquí"
level_search_title: "Buscar Niveles aquí"
achievement_search_title: "Buscar logros"
poll_search_title: "Buscar Encuesta"
@ -943,8 +943,8 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
pop_i18n: "Poblar I18N"
tasks: "Tareas"
clear_storage: "Borrar tus cambios locales"
# add_system_title: "Add Systems to Level"
# done_adding: "Done Adding"
add_system_title: "Agregar Sistemas al Level"
done_adding: "Se terminó de agregar"
article:
edit_btn_preview: "Vista previa"
@ -1026,7 +1026,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
my_matches: "Mis Partidas"
simulate: "Simular"
simulation_explanation: "¡Simulando tus juegos puedes mejorar tu posición más rápido!"
# simulation_explanation_leagues: "You will mainly help simulate games for allied players in your clans and courses."
# simulation_explanation_leagues: "Principalmente ayudarás a simular juegos for allied players in your clans and courses."
simulate_games: "¡Simular Juegos!"
simulate_all: "REINICIAR Y SIMULAR JUEGOS"
games_simulated_by: "Juegos simulados por ti:"
@ -1047,7 +1047,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
rank_failed: "Fallo al Clasificar"
rank_being_ranked: "Juego Siendo Clasificado"
rank_last_submitted: "Presentado"
help_simulate: "Ayudar simulando juego?"
help_simulate: "¿Ayudar simulando juego?"
code_being_simulated: "Tu nuevo código está siendo simulado por otros jugadores para clasificación. Esto se refrescará a medida que vengan nuevas partidas."
no_ranked_matches_pre: "Sin partidas clasificadas para el "
no_ranked_matches_post: " equipo! Juega en contra de algunos competidores y luego vuelve aquí para ver tu juego clasificado."
@ -1077,7 +1077,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
tournament_blurb_blog: "en nuestro blog"
rules: "Reglas"
winners: "Ganadores"
# league: "League"
league: "Liga"
user:
stats: "Estados"
@ -1093,7 +1093,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
no_achievements: "Sin Logros todavía."
favorite_prefix: "Idioma favorito "
favorite_postfix: "."
not_member_of_clans: "No se es miembro de ningún clan todavía."
not_member_of_clans: "No eres miembro de ningún clan todavía."
achievements:
last_earned: "Último Ganado"
@ -1118,7 +1118,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
no_recent_games: "No juegos jugados duramente las últimas dos semanas."
payments: "Pagos"
purchased: "Comprado"
# sale: "Sale"
sale: "Venta"
subscription: "Suscripción"
invoices: "Facturas"
service_apple: "Apple"
@ -1128,14 +1128,14 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
price: "Precio"
gems: "Gemas"
active: "Activo"
subscribed: "Suscripto"
unsubscribed: "Insuscripto"
subscribed: "Suscrito"
unsubscribed: "Desuscrito"
active_until: "Activo Hasta"
cost: "Costo"
next_payment: "Próximo Pago"
card: "Tarjeta"
status_unsubscribed_active: "No estas suscripto y no se te cobrará, pero tu cuenta está activa por ahora."
status_unsubscribed: "Obtén acceso a nuevos niveles, heroés, items y gemas extras con la suscripción a CodeCombat!"
status_unsubscribed_active: "No estas suscrito y no se te cobrará, pero tu cuenta está activa por ahora."
status_unsubscribed: "¡Obtén acceso a nuevos niveles, héroes, items y gemas extras con la suscripción a CodeCombat!"
account_invoices:
amount: "Cantidad en dólares."
@ -1181,13 +1181,13 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
systems: "Sistemas"
component: "Componente"
components: "Componentes"
thang: "Thang"
thangs: "Thangs"
thang: "Tiliche"
thangs: "Tiliches"
level_session: "Tu Sesión"
opponent_session: "Sesión del Oponente"
article: "Artícule"
user_names: "Nombres de usuario"
thang_names: "Nombres de thang"
thang_names: "Nombres de Tiliche"
files: "Archivos"
top_simulators: "Mejores simuladores"
source_document: "Documento fuente"
@ -1211,35 +1211,35 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
poll: "Encuesta"
user_polls_record: "Historia de Visitas de Encuestas"
# concepts:
# advanced_strings: "Advanced Strings"
# algorithms: "Algorithms"
# arguments: "Arguments"
# arithmetic: "Arithmetic"
# arrays: "Arrays"
# basic_syntax: "Basic Syntax"
# boolean_logic: "Boolean Logic"
concepts:
advanced_strings: "Manipulación Avanzada de Cadenas" #used Advanced Strings Handling instead of Advanced Strings
algorithms: "Algoritmos"
arguments: "Argumentos"
arithmetic: "Aritmética"
arrays: "Arreglos"
basic_syntax: "Sintaxis Básica"
boolean_logic: "Lógica Booleana"
# break_statements: "Break Statements"
# classes: "Classes"
classes: "Clases"
# continue_statements: "Continue Statements"
# for_loops: "For Loops"
# functions: "Functions"
# graphics: "Graphics"
for_loops: "Ciclos For"
functions: "Funciones"
graphics: "Gráficos"
# if_statements: "If Statements"
# input_handling: "Input Handling"
# math_operations: "Math Operations"
math_operations: "Operaciones Matemáticas"
# object_literals: "Object Literals"
# parameters: "Parameters"
# strings: "Strings"
# variables: "Variables"
# vectors: "Vectors"
# while_loops: "Loops"
# recursion: "Recursion"
parameters: "Parámetros"
strings: "Cadenas"
variables: "Variables"
vectors: "Vectores"
while_loops: "Ciclos While"
recursion: "Recursividad"
delta:
added: "Agregado"
modified: "Modificado"
# not_modified: "Not Modified"
not_modified: "No Modificado"
deleted: "Borrado"
moved_index: "Índice movido"
text_diff: "Diferir Texto"

View file

@ -7,6 +7,7 @@ _.extend CourseSchema.properties,
campaignID: c.objectId()
concepts: c.array {title: 'Programming Concepts', uniqueItems: true}, c.concept
description: {type: 'string'}
duration: {trype: 'number', description: 'Approximate hours of content'}
pricePerSeat: {type: 'number', description: 'Price per seat in USD cents.'}
screenshot: c.url {title: 'URL', description: 'Link to course screenshot.'}

View file

@ -0,0 +1,68 @@
#courses-view
.center
text-align: center
.code-input
width: 100%
.course-image
width: 100%
.course-panel
margin: 20px
.faq-blurb
font-size: 14px
.continue-dialog .modal-dialog
background-color: white
max-width: 400px
.instruction-label
font-size: 14pt
.or
margin-bottom: 20px
font-size: 14pt
.btn-enroll
margin-top: 20px
.center
text-align: center
.concepts-container
width: 200px
.contact-container
margin-top: 20px
text-align: center
.info-container
margin: 0% 10%
font-size: 18px
.monitoring-img-container
margin-top: 10px
.praise-caption
font-size: 14px
.praise-quote
font-size: 20px
font-style: italic
.progress-container
font-size: 20px
.img-quote
height: 160px
.popover
z-index: 1050
min-width: 400px
h3
background: transparent
border: 0
font-size: 30px

View file

@ -1,4 +1,4 @@
#course-details-view
#course-details-mock-view
.section-selector
margin-bottom: 0px

View file

@ -1,4 +1,4 @@
#course-enroll-view
#course-enroll-mock-view
.btn-buy
margin: 20px 0px

View file

@ -1,4 +1,4 @@
#courses-view
#courses-mock-view
.center
text-align: center

View file

@ -13,7 +13,6 @@ block header
a(href='/clans', data-i18n="clans.clans") Clans
a(href='http://discourse.codecombat.com/', data-i18n="nav.forum")
a(href='/community', data-i18n="nav.community")
//a(href='/play/ladder', data-i18n="home.multiplayer").multiplayer-nav-link
if me.get('anonymous') === false
span.dropdown
@ -63,6 +62,7 @@ block footer
a(href='http://blog.codecombat.com/', data-i18n="nav.blog")
a(href='/contribute', tabindex=-1, data-i18n="nav.contribute") Contribute
a(href='/legal', tabindex=-1, data-i18n="nav.legal") Legal
a(href='/play/ladder', tabindex=-1, data-i18n="home.multiplayer").multiplayer-nav-link
if me.isAdmin()
a(href='/admin', data-i18n="nav.admin") Admin

View file

@ -16,8 +16,6 @@ table.table
block tableBody
for document in documents
- var data = document.attributes;
- if(data.slug == 'ace-of-coders' && new Date() < new Date(1441863900000))
- continue;
tr(class=document.getOwner() == me.id ? 'mine' : '')
td
a(href="/editor/#{page}/#{data.slug || data._id}")

View file

@ -8,19 +8,136 @@ block content
span *UNDER CONSTRUCTION, please send feedback to
a.spl(href='mailto:team@codecombat.com') team@codecombat.com
h1(style='text-align: center;') Courses
br
if studentMode
+student-main
else
+teacher-main
.container-fluid
.row(style='font-size: 20px;')
.col-md-3
.col-md-3 Name
.col-md-3 Description
.col-md-3 Concepts
each course in courses
.row(style='border-top: 1px solid gray; padding: 10px;')
.col-md-3
img(src="#{course.get('screenshot')}", style="width: 100%;")
.col-md-3
p= course.get('name')
a(href="/editor/campaign/#{course.get('campaignID')}") Campaign (levels)
.col-md-3= course.get('description')
.col-md-3= course.get('concepts').join(' ')
- var i = 0
while i < courses.length
.row
+course-block(courses[i], instances)
- i++
if i < courses.length
+course-block(courses[i], instances)
- i++
mixin student-main
button.btn.btn-warning.btn-teacher Teachers Click Here
h1.center Courses on CodeCombat
mixin teacher-main
button.btn.btn-warning.btn-student Students Click Here
h1.center Courses on CodeCombat
.info-container
p Courses are designed to introduce computer science concepts using CodeCombat's fun and engaging environment. CodeCombat levels are organized around key topics to encourage progressive learning, over the course of 5 hours.
.container-fluid
.row
.col-md-6
ul
li Learn more in less time
li No coding experience necesssary
li Easily monitor student progress
p Purchase a course for your entire class. It's easy to sign up your students!
p.faq-blurb
span.spr See the courses
a.spr.courses-faq FAQ
span for more information.
.col-md-6
img.img-quote(src="/images/pages/courses/coco_complab.png")
p
.well.well-sm
div.praise-quote "#{praise.quote}"
div.praise-caption - #{praise.source}
h2.center Choose Your Course:
mixin student-dialog(course)
.modal.continue-dialog(id="continueModal#{course.id}")
.modal-dialog
.modal-header
button.close(data-dismiss='modal')
span &times;
h3.modal-title= course.get('name')
.modal-body
.container-fluid
.row.button-row
.col-md-12
.well.well-sm
p
div.instruction-label Enter an unlock code
.container-fluid
.row
.col-md-8
input.code-input(type='text', placeholder="Enter unlock code")
.col-md-4
button.btn.btn-success.btn-enroll Enroll
mixin teacher-dialog(course)
.modal.continue-dialog(id="continueModal#{course.id}")
.modal-dialog
.modal-header
button.close(data-dismiss='modal')
span &times;
h3.modal-title= course.get('name')
.modal-body
.container-fluid
if enrolledCourses[course.id]
.row.button-row.row-pick-class
.col-md-12
.well.well-sm
p
div.instruction-label Pick from your current classes
.container-fluid
.row
.col-md-8
select.form-control.select-session
each inst in instances
if inst.get('name')
option(value="#{inst.id}")= inst.get('name')
else
option(value="#{inst.id}") *unnamed*
.col-md-4
button.btn.btn-success.btn-enter(data-course-id="#{course.id}") Enter
.row.button-row.center.row-pick-class
.col-md-12
div.or Or
.row.button-row.center
.col-md-12
button.btn.btn-success.btn-lg.btn-buy(data-course-id="#{course.id}") Buy this course
mixin course-block(course)
if studentMode
+student-dialog(course)
else
+teacher-dialog(course)
.col-md-6
.well.panel.course-panel(class=enrolledCourses[course.id] ? 'panel-success' : 'panel-info')
.panel-heading
.panel-title
span.spr #{course.get('name')}
strong #{enrolledCourses[course.id] ? '[ enrolled ]' : ''}
.panel-body
.container-fluid
.row
.col-md-12
p
img.course-image(src="#{course.get('screenshot')}")
.row.button-row
.col-md-6
strong Topics
ul
each concept in course.get('concepts')
li(data-i18n="concepts." + concept)
strong Hours of content: #{course.get('duration')}
.col-md-6.center(style='margin-top: 40px;')
if studentMode
if enrolledCourses[course.id]
a.btn.btn-lg.btn-success.btn-continue(href="/courses/#{course.id}?student=true") Continue
else
button.btn.btn-lg.btn-success.btn-continue(data-toggle='modal', data-target="#continueModal#{course.id}") Enter
else if enrolledCourses[course.id]
button.btn.btn-lg.btn-success.btn-continue(data-toggle='modal', data-target="#continueModal#{course.id}") Continue
else
button.btn.btn-lg.btn-success.btn-buy(data-course-id="#{course.id}") #{course.get('pricePerSeat') === 0 ? 'Get FREE course' : 'Buy course'}

View file

@ -17,8 +17,6 @@ if campaign
a(href=level.type == 'hero' ? '#' : level.disabled ? "/play" : "/play/#{level.levelPath || 'level'}/#{level.slug}", disabled=level.disabled, data-level-slug=level.slug, data-level-path=level.levelPath || 'level', data-level-name=level.name)
if level.slug == 'lost-viking'
img.star(src="/file/db/thang.type/5441c3144e9aeb727cc97111/portrait.png")
else if level.slug == 'robot-ragnarok'
img.star(src="/file/db/thang.type/54ea35fd2b7506e891ca70d5/portrait.png")
else if level.requiresSubscription
img.star(src="/images/pages/play/star.png")
if levelStatusMap[level.slug] === 'complete'

View file

@ -191,7 +191,6 @@ module.exports = class ClanDetailsView extends RootView
name: utils.i18n(campaign.attributes, 'fullName') or utils.i18n(campaign.attributes, 'name')
levels: []
for levelID, level of campaign.get('levels')
continue if level.slug is 'ace-of-coders' and new Date() < new Date(1441863900000)
campaignLevelProgression.levels.push
ID: levelID
slug: level.slug

View file

@ -20,7 +20,7 @@ module.exports = class CourseEnrollView extends RootView
subscriptions:
'stripe:received-token': 'onStripeReceivedToken'
constructor: (options, @courseID=0) ->
constructor: (options, @courseID) ->
super options
@courseID ?= options.courseID
@seats = 20
@ -99,7 +99,7 @@ module.exports = class CourseEnrollView extends RootView
createClass: (token) ->
data =
name: $('.class-name').val()
name: @className
seats: @seats
token: token
data.courseID = @selectedCourse.id if @selectedCourse

View file

@ -1,18 +1,95 @@
RootView = require 'views/core/RootView'
template = require 'templates/courses/courses'
app = require 'core/application'
CocoCollection = require 'collections/CocoCollection'
Course = require 'models/Course'
CourseInstance = require 'models/CourseInstance'
RootView = require 'views/core/RootView'
template = require 'templates/courses/courses'
utils = require 'core/utils'
module.exports = class CoursesView extends RootView
id: 'courses-view'
template: template
events:
'click .btn-buy': 'onClickBuy'
'click .btn-enroll': 'onClickEnroll'
'click .btn-enter': 'onClickEnter'
'click .btn-student': 'onClickStudent'
'click .btn-teacher': 'onClickTeacher'
constructor: (options) ->
super options
super(options)
@praise = utils.getCoursePraise()
@studentMode = utils.getQueryVariable('student', false) or options.studentMode
@courses = new CocoCollection([], { url: "/db/course", model: Course})
@supermodel.loadCollection(@courses, 'courses')
@courseInstances = new CocoCollection([], { url: "/db/user/#{me.id}/course_instances", model: CourseInstance})
@listenToOnce @courseInstances, 'sync', @onCourseInstancesLoaded
@supermodel.loadCollection(@courseInstances, 'course_instances')
getRenderData: ->
context = super()
context.courses = @courses.models ? []
context.enrolledCourses = @enrolledCourses ? {}
context.instances = @courseInstances.models ? []
context.praise = @praise
context.studentMode = @studentMode
context
afterRender: ->
super()
@setupCoursesFAQPopover()
onCourseInstancesLoaded: ->
@enrolledCourses = {}
@enrolledCourses[courseInstance.get('courseID')] = true for courseInstance in @courseInstances.models
setupCoursesFAQPopover: ->
popoverTitle = "<h3>Courses FAQ<button type='button' class='close' onclick='$(&#39;.courses-faq&#39;).popover(&#39;hide&#39;);'>&times;</button></h3>"
popoverContent = "<p><strong>Q:</strong> What's the difference between these courses and the single player game?</p>"
popoverContent += "<p><strong>A:</strong> The single player game is designed for individuals, while the courses are designed for classes.</p>"
popoverContent += "<p>The single player game has items, gems, hero selection, leveling up, and in-app purchases. Courses have classroom management features and streamlined student-focused level pacing.</p>"
@$el.find('.courses-faq').popover(
animation: true
html: true
placement: 'top'
trigger: 'click'
title: popoverTitle
content: popoverContent
container: @$el
).on 'shown.bs.popover', =>
application.tracker?.trackEvent 'Subscription payment methods hover'
onClickBuy: (e) ->
courseID = $(e.target).data('course-id')
route = "/courses/enroll/#{courseID}"
viewClass = require 'views/courses/CourseEnrollView'
viewArgs = [{}, courseID]
navigationEvent = route: route, viewClass: viewClass, viewArgs: viewArgs
Backbone.Mediator.publish 'router:navigate', navigationEvent
onClickEnroll: (e) ->
alert('TODO: redeem course prepaid and navigate to correct course instance')
onClickEnter: (e) ->
$('.continue-dialog').modal('hide')
courseID = $(e.target).data('course-id')
courseInstanceID = $('.select-session').val()
viewClass = require 'views/courses/CourseDetailsView'
viewArgs = [{courseInstanceID:courseInstanceID}, courseID]
navigationEvent = route: "/courses/#{courseID}", viewClass: viewClass, viewArgs: viewArgs
Backbone.Mediator.publish 'router:navigate', navigationEvent
onClickStudent: (e) ->
route = "/courses?student=true"
viewClass = require 'views/courses/CoursesView'
viewArgs = [studentMode: true]
navigationEvent = route: route, viewClass: viewClass, viewArgs: viewArgs
Backbone.Mediator.publish 'router:navigate', navigationEvent
onClickTeacher: (e) ->
route = "/courses?student=false"
viewClass = require 'views/courses/CoursesView'
viewArgs = [studentMode: false]
navigationEvent = route: route, viewClass: viewClass, viewArgs: viewArgs
Backbone.Mediator.publish 'router:navigate', navigationEvent

View file

@ -6,7 +6,7 @@ CocoCollection = require 'collections/CocoCollection'
Campaign = require 'models/Campaign'
module.exports = class CourseDetailsView extends RootView
id: 'course-details-view'
id: 'course-details-mock-view'
template: template
events:

View file

@ -3,7 +3,7 @@ RootView = require 'views/core/RootView'
template = require 'templates/courses/mock1/course-enroll'
module.exports = class CourseEnrollView extends RootView
id: 'course-enroll-view'
id: 'course-enroll-mock-view'
template: template
events:

View file

@ -4,7 +4,7 @@ RootView = require 'views/core/RootView'
template = require 'templates/courses/mock1/courses'
module.exports = class CoursesView extends RootView
id: 'courses-view'
id: 'courses-mock-view'
template: template
events:

View file

@ -55,6 +55,13 @@ module.exports = class LadderHomeView extends RootView
context
heroArenas = [
{
name: 'Ace of Coders'
difficulty: 3
id: 'ace-of-coders'
image: '/file/db/level/55de80407a57948705777e89/Ace-of-Coders-banner.png'
description: 'Battle for control over the icy treasure chests as your gigantic warrior marshals his armies against his mirror-match nemesis.'
}
{
name: 'Zero Sum'
difficulty: 3
@ -62,13 +69,6 @@ heroArenas = [
image: '/file/db/level/550363b4ec31df9c691ab629/MAR26-Banner_Zero%20Sum.png'
description: 'Unleash your coding creativity in both gold gathering and battle tactics in this alpine mirror match between red sorcerer and blue sorcerer.'
}
{
name: 'Ace of Coders'
difficulty: 3
id: 'ace-of-coders'
image: '/file/db/level/550363b4ec31df9c691ab629/MAR26-Banner_Zero%20Sum.png'
description: 'Battle for control over the icy treasure chests as your gigantic warrior marshals his armies against his mirror-match nemesis.'
}
{
name: 'Cavern Survival'
difficulty: 1
@ -99,8 +99,6 @@ heroArenas = [
}
]
heroArenas = _.reject heroArenas, id: 'ace-of-coders' if new Date() < new Date(1441863900000)
oldArenas = [
{
name: 'Criss-Cross'

View file

@ -267,7 +267,7 @@ module.exports = class CampaignView extends RootView
level.locked = false if @campaign?.get('name') is 'Auditions'
level.locked = false if @campaign?.get('name') is 'Intro'
level.locked = false if me.isInGodMode()
level.locked = false if level.slug is 'robot-ragnarok'
#level.locked = false if level.slug is 'robot-ragnarok'
level.disabled = true if level.adminOnly and @levelStatusMap[level.slug] not in ['started', 'complete']
level.disabled = false if me.isInGodMode()
level.color = 'rgb(255, 80, 60)'
@ -324,8 +324,7 @@ module.exports = class CampaignView extends RootView
me.isPremium() or
not nextLevel.requiresSubscription or
(nextLevel.slug is 'boom-and-bust' and not @levelStatusMap['defense-of-plainswood']) or
(nextLevel.slug is 'favorable-odds' and not @levelStatusMap['the-raised-sword']) or
(nextLevel.slug is 'robot-ragnarok' and @levelStatusMap['the-raised-sword'])
(nextLevel.slug is 'favorable-odds' and not @levelStatusMap['the-raised-sword'])
)
nextLevel.next = true
foundNext = true
@ -381,7 +380,7 @@ module.exports = class CampaignView extends RootView
particleKey.push 'premium' if level.requiresSubscription
particleKey.push 'gate' if level.slug in ['kithgard-gates', 'siege-of-stonehold', 'clash-of-clones', 'summits-gate']
particleKey.push 'hero' if level.unlocksHero and not level.unlockedHero
particleKey.push 'item' if level.slug is 'robot-ragnarok' # TODO: generalize
#particleKey.push 'item' if level.slug is 'robot-ragnarok' # TODO: generalize
continue if particleKey.length is 2 # Don't show basic levels
continue unless level.hidden or _.intersection(particleKey, ['item', 'hero-ladder', 'replayable']).length
@particleMan.addEmitter level.position.x / 100, level.position.y / 100, particleKey.join('-')

View file

@ -4,10 +4,9 @@
// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
// NOTE: uses name as unique identifier, so changing the name will insert a new course
// NOTE: concepts should match actual campaign levels
// NOTE: pricePerSeat in USD cents
var documents =
var courses =
[
{
name: "Introduction to Computer Science",
@ -15,6 +14,7 @@ var documents =
campaignID: ObjectId("55b29efd1cd6abe8ce07db0d"),
concepts: ['basic_syntax', 'arguments', 'while_loops', 'strings', 'variables'],
description: "Learn basic syntax, while loops, and the CodeCombat environment.",
duration: NumberInt(1),
pricePerSeat: NumberInt(0),
screenshot: "/images/pages/courses/101_info.png"
},
@ -24,6 +24,7 @@ var documents =
campaignID: ObjectId("55b29efd1cd6abe8ce07db0d"),
concepts: ['basic_syntax', 'arguments', 'while_loops', 'strings', 'variables', 'if_statements'],
description: "Introduce Arguments, Variables, If Statements, and Arithmetic.",
duration: NumberInt(5),
pricePerSeat: NumberInt(400),
screenshot: "/images/pages/courses/102_info.png"
},
@ -33,16 +34,30 @@ var documents =
campaignID: ObjectId("55b29efd1cd6abe8ce07db0d"),
concepts: ['if_statements', 'arithmetic'],
description: "Learn how to handle input.",
duration: NumberInt(5),
pricePerSeat: NumberInt(400),
screenshot: "/images/pages/courses/103_info.png"
}
];
for (var i = 0; i < documents.length; i++) {
var doc = documents[i];
db.courses.update({name: doc.name}, doc, {upsert: true});
print("Finding course concepts..");
for (var i = 0; i < courses.length; i++) {
var concepts = {};
var cursor = db.campaigns.find({_id: courses[i].campaignID}, {'levels': 1});
if (cursor.hasNext()) {
var doc = cursor.next();
for (var levelID in doc.levels) {
for (var j = 0; j < doc.levels[levelID].concepts.length; j++) {
concepts[doc.levels[levelID].concepts[j]] = true;
}
}
}
courses[i].concepts = Object.keys(concepts);
}
function log(str) {
print(new Date().toISOString() + " " + str);
print("Updating courses..");
for (var i = 0; i < courses.length; i++) {
db.courses.update({name: courses[i].name}, courses[i], {upsert: true});
}
print("Done.");

View file

@ -66,7 +66,7 @@ getRandomSessions = (user, callback) ->
# Sampling by level: we pick a level, then find a human and ogre session for that level, one at random, one biased towards recent submissions.
#ladderLevelIDs = ['greed', 'criss-cross', 'brawlwood', 'dungeon-arena', 'gold-rush', 'sky-span'] # Let's not give any extra simulations to old ladders.
ladderLevelIDs = ['dueling-grounds', 'cavern-survival', 'multiplayer-treasure-grove', 'harrowland', 'zero-sum', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders']
ladderLevelIDs = ['dueling-grounds', 'cavern-survival', 'multiplayer-treasure-grove', 'harrowland', 'zero-sum', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders', 'ace-of-coders']
sampleByLevel = (callback) ->
levelID = _.sample ladderLevelIDs
favorRecentHumans = Math.random() < 0.5 # We pick one session favoring recent submissions, then find another one uniformly to play against
@ -76,7 +76,6 @@ findRandomSession = (queryParams, callback) ->
# In MongoDB 3.2, we will be able to easily get a random document with aggregate $sample: https://jira.mongodb.org/browse/SERVER-533
queryParams.submitted = true
favorRecent = queryParams.favorRecent
favorRecent = false # temp, for Ace of Coders tournament
delete queryParams.favorRecent
if favorRecent
return findRecentRandomSession queryParams, callback