mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-29 18:45:48 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
e650ab52d4
27 changed files with 413 additions and 283 deletions
BIN
app/assets/images/pages/home/boy_coding.png
Normal file
BIN
app/assets/images/pages/home/boy_coding.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
BIN
app/assets/images/pages/home/girl_coding.png
Normal file
BIN
app/assets/images/pages/home/girl_coding.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
Binary file not shown.
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 126 KiB |
BIN
app/assets/images/pages/play/modal/equip-buttons.png
Normal file
BIN
app/assets/images/pages/play/modal/equip-buttons.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
|
@ -31,4 +31,6 @@ module.exports = class FlagLank extends IndieLank
|
||||||
toggleCursor: (to) ->
|
toggleCursor: (to) ->
|
||||||
@options.isCursor = to
|
@options.isCursor = to
|
||||||
@thang.alpha = if to then 0.33 else 0.67 # 1.0 is for flags that have been placed
|
@thang.alpha = if to then 0.33 else 0.67 # 1.0 is for flags that have been placed
|
||||||
|
#@thang.action = if to then 'idle' else 'appear' # TODO: why doesn't this work? Does it not render the action or something?
|
||||||
|
@thang.action = 'appear'
|
||||||
@updateAlpha()
|
@updateAlpha()
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
SpriteBuilder = require 'lib/sprites/SpriteBuilder'
|
SpriteBuilder = require 'lib/sprites/SpriteBuilder'
|
||||||
|
|
||||||
floors = ['Dungeon Floor', 'Indoor Floor', 'Grass', 'Grass01', 'Grass02', 'Grass03', 'Grass04', 'Grass05', 'Goal Trigger', 'Obstacle', 'Sand 01', 'Sand 02', 'Sand 03', 'Sand 04', 'Sand 05', 'Sand 06', 'Talus 1', 'Talus 2', 'Talus 3', 'Talus 4', 'Talus 5', 'Talus 6', 'Firn 1', 'Firn 2', 'Firn 3', 'Firn 4', 'Firn 5', 'Firn 6', 'Ice Rink 1', 'Ice Rink 2', 'Ice Rink 3']
|
floors = ['Dungeon Floor', 'Indoor Floor', 'Grass', 'Grass01', 'Grass02', 'Grass03', 'Grass04', 'Grass05', 'Goal Trigger', 'Obstacle', 'Sand 01', 'Sand 02', 'Sand 03', 'Sand 04', 'Sand 05', 'Sand 06', 'Talus 1', 'Talus 2', 'Talus 3', 'Talus 4', 'Talus 5', 'Talus 6', 'Firn 1', 'Firn 2', 'Firn 3', 'Firn 4', 'Firn 5', 'Firn 6', 'Ice Rink 1', 'Ice Rink 2', 'Ice Rink 3', 'Firn Cliff']
|
||||||
|
|
||||||
|
cliffs = ['Dungeon Pit', 'Grass Cliffs']
|
||||||
|
|
||||||
module.exports = class SingularSprite extends createjs.Sprite
|
module.exports = class SingularSprite extends createjs.Sprite
|
||||||
childMovieClips: null
|
childMovieClips: null
|
||||||
|
@ -71,6 +73,13 @@ module.exports = class SingularSprite extends createjs.Sprite
|
||||||
@baseScaleY = @scaleY
|
@baseScaleY = @scaleY
|
||||||
if @camera and @thangType.get('name') in floors
|
if @camera and @thangType.get('name') in floors
|
||||||
@baseScaleY *= @camera.y2x
|
@baseScaleY *= @camera.y2x
|
||||||
|
else if @camera and @thangType.get('name') in cliffs
|
||||||
|
if actionName is 'idle_side'
|
||||||
|
@baseScaleX *= @camera.x2y# / 0.85
|
||||||
|
@baseScaleY *= @camera.y2x * 0.85
|
||||||
|
else
|
||||||
|
@baseScaleY *= @camera.y2x / 0.85
|
||||||
|
console.log 'it is a cliff!', actionName, @baseScaleX, @baseScaleY
|
||||||
@currentAnimation = actionName
|
@currentAnimation = actionName
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ module.exports.thangNames = thangNames =
|
||||||
'Godel'
|
'Godel'
|
||||||
'Goreball'
|
'Goreball'
|
||||||
'Gordok'
|
'Gordok'
|
||||||
'Toremon'
|
'Gorylo'
|
||||||
'Gort'
|
'Gort'
|
||||||
'Kog'
|
'Kog'
|
||||||
'Kogpole'
|
'Kogpole'
|
||||||
|
@ -37,11 +37,13 @@ module.exports.thangNames = thangNames =
|
||||||
'Oogre'
|
'Oogre'
|
||||||
'Raack'
|
'Raack'
|
||||||
'Ragtime'
|
'Ragtime'
|
||||||
|
'Raort'
|
||||||
'Rexxar'
|
'Rexxar'
|
||||||
'Skoggen'
|
'Skoggen'
|
||||||
'Smerk'
|
'Smerk'
|
||||||
'Snortt'
|
'Snortt'
|
||||||
'Thabt'
|
'Thabt'
|
||||||
|
'Toremon'
|
||||||
'Treg'
|
'Treg'
|
||||||
'Ursa'
|
'Ursa'
|
||||||
'Vorobun'
|
'Vorobun'
|
||||||
|
@ -184,6 +186,7 @@ module.exports.thangNames = thangNames =
|
||||||
'Belch'
|
'Belch'
|
||||||
'Booz'
|
'Booz'
|
||||||
'Brusentsov'
|
'Brusentsov'
|
||||||
|
'Demonik'
|
||||||
'Dronck'
|
'Dronck'
|
||||||
'Gorlog'
|
'Gorlog'
|
||||||
'Grumus'
|
'Grumus'
|
||||||
|
@ -204,7 +207,7 @@ module.exports.thangNames = thangNames =
|
||||||
'Trogdor'
|
'Trogdor'
|
||||||
'Trung'
|
'Trung'
|
||||||
'Vargutt'
|
'Vargutt'
|
||||||
'Demonik'
|
'Vyle'
|
||||||
]
|
]
|
||||||
'Ogre F': [
|
'Ogre F': [
|
||||||
# Female
|
# Female
|
||||||
|
|
|
@ -933,7 +933,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
||||||
|
|
||||||
contribute:
|
contribute:
|
||||||
page_title: "Mitwirken"
|
page_title: "Mitwirken"
|
||||||
intro_blurb: "CodeCombat ist zu 100% Open Source! Hunderte hingebungsvolle Spieler haben uns geholfen das Spiel zu dem zu machen was es heute ist. Tritt uns bei und schreibe das nächste Kapitel in CodeCombat' Aufgabe, der Welt das Programmieren zu lehren!"
|
intro_blurb: "CodeCombat ist zu 100% Open Source! Hunderte hingebungsvolle Spieler haben uns geholfen das Spiel zu dem zu machen, was es heute ist. Tritt uns bei und schreibe das nächste Kapitel in CodeCombats Mission, der Welt das Programmieren zu lehren!"
|
||||||
alert_account_message_intro: "Hey du!"
|
alert_account_message_intro: "Hey du!"
|
||||||
alert_account_message: "Um Klassen-Emails abonnieren zu können, musst du dich zuerst anmelden."
|
alert_account_message: "Um Klassen-Emails abonnieren zu können, musst du dich zuerst anmelden."
|
||||||
archmage_introduction: "Einer der größten Vorteile daran ein Spiel aufzubauen, ist es, dass so viele verschiedene Aspekte eine Rolle spielen. Grafiken, Sound, Echtzeit Networking, Social Networking und natürlich viele der gewöhnlichen Aspekte des Programmierens, von low-level Datenbankmanagement und Server Administration bis hin zum Aufbau von Design und Interface. Es gibt viel zu tun und wenn du ein erfahrener Programmierer bist, mit einer Veranlagung dazu, wirklich knallhart bei CodeCombat einzutauchen, dann könnte diese Klasse etwas für dich sein. Wir würden uns wahnsinnig über deine Hilfe dabei freuen, das beste Programmierspiel der Welt aufzubauen."
|
archmage_introduction: "Einer der größten Vorteile daran ein Spiel aufzubauen, ist es, dass so viele verschiedene Aspekte eine Rolle spielen. Grafiken, Sound, Echtzeit Networking, Social Networking und natürlich viele der gewöhnlichen Aspekte des Programmierens, von low-level Datenbankmanagement und Server Administration bis hin zum Aufbau von Design und Interface. Es gibt viel zu tun und wenn du ein erfahrener Programmierer bist, mit einer Veranlagung dazu, wirklich knallhart bei CodeCombat einzutauchen, dann könnte diese Klasse etwas für dich sein. Wir würden uns wahnsinnig über deine Hilfe dabei freuen, das beste Programmierspiel der Welt aufzubauen."
|
||||||
|
|
|
@ -293,7 +293,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
||||||
tip_scrub_shortcut: "Usa Ctrl+[ para rebobinar e Ctrl+] para avançar."
|
tip_scrub_shortcut: "Usa Ctrl+[ para rebobinar e Ctrl+] para avançar."
|
||||||
tip_guide_exists: "Clica no guia, dentro do menu do jogo (no topo da página), para informações úteis."
|
tip_guide_exists: "Clica no guia, dentro do menu do jogo (no topo da página), para informações úteis."
|
||||||
tip_open_source: "O CodeCombat é 100% open source!"
|
tip_open_source: "O CodeCombat é 100% open source!"
|
||||||
# tip_tell_friends: "Enjoying CodeCombat? Tell your friends about us!"
|
tip_tell_friends: "Estás a gostar do CodeCombat? Fala de nós aos teus amigos!"
|
||||||
tip_beta_launch: "O CodeCombat lançou o seu beta em outubro de 2013."
|
tip_beta_launch: "O CodeCombat lançou o seu beta em outubro de 2013."
|
||||||
tip_think_solution: "Pensa na solução, não no problema."
|
tip_think_solution: "Pensa na solução, não no problema."
|
||||||
tip_theory_practice: "Teoricamente, não há diferença entre a teoria e a prática. Mas na prática, há. - Yogi Berra"
|
tip_theory_practice: "Teoricamente, não há diferença entre a teoria e a prática. Mas na prática, há. - Yogi Berra"
|
||||||
|
@ -337,7 +337,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
||||||
tip_recurse: "Iterar é humano, recursar é divino. - L. Peter Deutsch"
|
tip_recurse: "Iterar é humano, recursar é divino. - L. Peter Deutsch"
|
||||||
tip_free_your_mind: "Tens de libertar tudo, Neo. Medo, dúvida e descrença. Liberta a tua mente. - Morpheus"
|
tip_free_your_mind: "Tens de libertar tudo, Neo. Medo, dúvida e descrença. Liberta a tua mente. - Morpheus"
|
||||||
tip_strong_opponents: "Até o mais forte dos adversários tem uma fraqueza. - Itachi Uchiha"
|
tip_strong_opponents: "Até o mais forte dos adversários tem uma fraqueza. - Itachi Uchiha"
|
||||||
# tip_paper_and_pen: "Before you start coding, you can always plan with a sheet of paper and a pen."
|
tip_paper_and_pen: "Antes de começares a programar, podes sempre planear com uma folha de papel e uma caneta."
|
||||||
|
|
||||||
game_menu:
|
game_menu:
|
||||||
inventory_tab: "Inventário"
|
inventory_tab: "Inventário"
|
||||||
|
@ -851,8 +851,8 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
||||||
indoor: "Interior"
|
indoor: "Interior"
|
||||||
desert: "Deserto"
|
desert: "Deserto"
|
||||||
grassy: "Relvado"
|
grassy: "Relvado"
|
||||||
# mountain: "Mountain"
|
mountain: "Montanha"
|
||||||
# glacier: "Glacier"
|
glacier: "Glaciar"
|
||||||
small: "Pequeno"
|
small: "Pequeno"
|
||||||
large: "Grande"
|
large: "Grande"
|
||||||
fork_title: "Bifurcar Nova Versão"
|
fork_title: "Bifurcar Nova Versão"
|
||||||
|
@ -1211,7 +1211,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
||||||
delta:
|
delta:
|
||||||
added: "Adicionado"
|
added: "Adicionado"
|
||||||
modified: "Modificado"
|
modified: "Modificado"
|
||||||
# not_modified: "Not Modified"
|
not_modified: "Não Modificado"
|
||||||
deleted: "Eliminado"
|
deleted: "Eliminado"
|
||||||
moved_index: "Índice Movido"
|
moved_index: "Índice Movido"
|
||||||
text_diff: "Diferença de Texto"
|
text_diff: "Diferença de Texto"
|
||||||
|
|
|
@ -1,29 +1,42 @@
|
||||||
#course-details-view
|
#course-details-view
|
||||||
|
|
||||||
.concept-completion-container
|
.concept-completion-container
|
||||||
position: relative
|
font-size: 10pt
|
||||||
.concept-completion-background
|
|
||||||
position: absolute
|
.summary-container
|
||||||
height: 100%
|
font-size: 14pt
|
||||||
left: 0px
|
|
||||||
top: 0px
|
.statistics-container
|
||||||
background-color: blue
|
|
||||||
opacity: 0.25
|
|
||||||
.concept-completed-foreground
|
|
||||||
font-size: 12pt
|
font-size: 12pt
|
||||||
|
td
|
||||||
|
padding-right: 8px
|
||||||
|
|
||||||
#editDescriptionModal .modal-dialog
|
.table-concepts-summary
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
.concept-summary
|
||||||
|
width: 100%
|
||||||
|
background-color: white
|
||||||
|
cursor: default
|
||||||
|
display: inline-block
|
||||||
|
white-space: nowrap
|
||||||
|
font-size: 9pt
|
||||||
|
font-weight: normal
|
||||||
|
border: 1px solid gray
|
||||||
|
border-radius: 5px
|
||||||
|
margin: 0px
|
||||||
|
padding: 2px
|
||||||
background-color: white
|
background-color: white
|
||||||
|
|
||||||
#editNameModal .modal-dialog
|
#editSettingsModal .modal-dialog
|
||||||
background-color: white
|
background-color: white
|
||||||
max-width: 400px
|
font-size: 14pt
|
||||||
|
|
||||||
.edit-description-input
|
.edit-description-input
|
||||||
width: 100%
|
width: 100%
|
||||||
|
|
||||||
.edit-name-input
|
.edit-name-input
|
||||||
width: 100%
|
width: 50%
|
||||||
|
|
||||||
.member-header
|
.member-header
|
||||||
cursor: pointer
|
cursor: pointer
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#courses-view
|
#courses-view
|
||||||
|
|
||||||
|
.btn-continue
|
||||||
|
margin-top: 40px
|
||||||
|
|
||||||
.center
|
.center
|
||||||
text-align: center
|
text-align: center
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,28 @@
|
||||||
|
|
||||||
#home-view
|
#home-view
|
||||||
|
|
||||||
|
#kids-coding-container
|
||||||
|
$coding-image-size: 272px
|
||||||
|
position: relative
|
||||||
|
width: 1000px + $coding-image-size
|
||||||
|
margin: 0px auto
|
||||||
|
|
||||||
|
@media screen and ( max-width: 1400px )
|
||||||
|
display: none
|
||||||
|
|
||||||
|
.kid-coding
|
||||||
|
position: absolute
|
||||||
|
z-index: 1
|
||||||
|
top: -57px
|
||||||
|
@media screen and ( max-height: 800px )
|
||||||
|
top: 50px
|
||||||
|
|
||||||
|
&#boy-coding
|
||||||
|
left: -$coding-image-size / 2
|
||||||
|
|
||||||
|
&#girl-coding
|
||||||
|
right: -$coding-image-size / 2
|
||||||
|
|
||||||
#spacer
|
#spacer
|
||||||
height: 626px
|
height: 626px
|
||||||
@media screen and ( max-height: 800px )
|
@media screen and ( max-height: 800px )
|
||||||
|
|
|
@ -365,19 +365,21 @@ $gameControlMargin: 30px
|
||||||
&:active, &.highlighted
|
&:active, &.highlighted
|
||||||
@include box-shadow(0 0 20px white)
|
@include box-shadow(0 0 20px white)
|
||||||
|
|
||||||
&.heroes
|
&.items
|
||||||
background-position: (-1 * $gameControlSize) 0px
|
background-position: (-1 * $gameControlSize) 0px
|
||||||
&.achievements
|
&.heroes
|
||||||
background-position: (-2 * $gameControlSize) 0px
|
background-position: (-2 * $gameControlSize) 0px
|
||||||
&.account
|
&.achievements
|
||||||
//background-position: (-3 * $gameControlSize) 0px
|
|
||||||
background-position: (-4 * $gameControlSize) 0px
|
|
||||||
&.settings
|
|
||||||
background-position: (-4 * $gameControlSize) 0px
|
|
||||||
&.gems
|
|
||||||
background-position: (-5 * $gameControlSize) 0px
|
|
||||||
&.poll
|
|
||||||
background-position: (-3 * $gameControlSize) 0px
|
background-position: (-3 * $gameControlSize) 0px
|
||||||
|
&.account
|
||||||
|
//background-position: (-4 * $gameControlSize) 0px
|
||||||
|
background-position: (-5 * $gameControlSize) 0px
|
||||||
|
&.settings
|
||||||
|
background-position: (-5 * $gameControlSize) 0px
|
||||||
|
&.gems
|
||||||
|
background-position: (-6 * $gameControlSize) 0px
|
||||||
|
&.poll
|
||||||
|
background-position: (-4 * $gameControlSize) 0px
|
||||||
|
|
||||||
.tooltip
|
.tooltip
|
||||||
font-size: 24px
|
font-size: 24px
|
||||||
|
|
|
@ -350,9 +350,15 @@ $itemSlotGridHeight: 51px
|
||||||
img
|
img
|
||||||
margin: 1px
|
margin: 1px
|
||||||
button
|
button
|
||||||
margin-top: -2px
|
//margin-top: -2px
|
||||||
height: 19px
|
//height: 19px
|
||||||
font-size: 12px
|
font-size: 12px
|
||||||
|
margin: -1px 1px 1px 1px
|
||||||
|
|
||||||
|
&:active, &.active
|
||||||
|
background-position: -57px * 2 0
|
||||||
|
color: white
|
||||||
|
text-shadow: 0 1px 0 black, 1px 0 0 black, -1px 0 0 black, 0 -1px 0 black
|
||||||
|
|
||||||
img
|
img
|
||||||
width: 56px
|
width: 56px
|
||||||
|
@ -360,22 +366,32 @@ $itemSlotGridHeight: 51px
|
||||||
display: block
|
display: block
|
||||||
|
|
||||||
button
|
button
|
||||||
width: 100%
|
background: transparent url(/images/pages/play/modal/equip-buttons.png)
|
||||||
height: 17px
|
width: 56px
|
||||||
border: 1px solid rgb(46,46,46)
|
height: 21px
|
||||||
background: white
|
border: 0
|
||||||
|
//border: 1px solid rgb(46,46,46)
|
||||||
|
//background: white
|
||||||
font-size: 11px
|
font-size: 11px
|
||||||
border-radius: 1px
|
border-radius: 1px
|
||||||
padding: 0
|
padding: 0 0 2px 0
|
||||||
@include transition(0.1s ease)
|
@include transition(font-size 0.1s ease)
|
||||||
|
//text-shadow: 0 1px 0 white, 1px 0 0 white, -1px 0 0 white, 0 -1px 0 white
|
||||||
|
|
||||||
|
text-transform: uppercase
|
||||||
|
font-weight: bold
|
||||||
|
color: black
|
||||||
|
text-spacing: 0px
|
||||||
|
|
||||||
&.active
|
&.active
|
||||||
background-color: rgb(81,153,236)
|
background-color: rgb(81,153,236)
|
||||||
|
|
||||||
button
|
button
|
||||||
background-color: lighten(rgb(89,136,47), 10%)
|
//background-color: lighten(rgb(89,136,47), 10%)
|
||||||
box-shadow: 1px 1px 4px #333
|
box-shadow: 1px 1px 4px #333
|
||||||
color: white
|
color: white
|
||||||
|
text-shadow: 0 1px 0 black, 1px 0 0 black, -1px 0 0 black, 0 -1px 0 black
|
||||||
|
background-position: -57px 0
|
||||||
|
|
||||||
//.status-message .should-equip-message
|
//.status-message .should-equip-message
|
||||||
// display: inline
|
// display: inline
|
||||||
|
@ -594,3 +610,12 @@ $itemSlotGridHeight: 51px
|
||||||
&.male
|
&.male
|
||||||
left: -16px
|
left: -16px
|
||||||
|
|
||||||
|
body[lang='ja'], body[lang^='zh'], body[lang='ca'], body[lang^='es'], body[lang^='pt'], body[lang='ro'], body[lang='fi'], body[lang='sv'], body[lang='uk'], body[lang='vi'], body[lang='cz']
|
||||||
|
#inventory-modal #unequipped .item button
|
||||||
|
font-weight: normal
|
||||||
|
letter-spacing: -1px
|
||||||
|
padding-bottom: 1px
|
||||||
|
|
||||||
|
body[lang='ro'], body[lang='fi'], body[lang='uk']
|
||||||
|
#inventory-modal #unequipped .item button
|
||||||
|
text-transform: none
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
block header
|
block header
|
||||||
#site-nav
|
#site-nav
|
||||||
|
block site_nav
|
||||||
a(href="/")
|
a(href="/")
|
||||||
img#nav-logo(src="/images/pages/base/logo.png", title="CodeCombat - Learn how to code by playing a game", alt="CodeCombat")
|
img#nav-logo(src="/images/pages/base/logo.png", title="CodeCombat - Learn how to code by playing a game", alt="CodeCombat")
|
||||||
div#site-nav-links
|
div#site-nav-links
|
||||||
|
|
|
@ -5,7 +5,6 @@ block content
|
||||||
//- DO NOT localize / i18n
|
//- DO NOT localize / i18n
|
||||||
|
|
||||||
div TODO: fix ugly tabs
|
div TODO: fix ugly tabs
|
||||||
div TODO: not enrolled yet
|
|
||||||
div
|
div
|
||||||
span *UNDER CONSTRUCTION, send feedback to
|
span *UNDER CONSTRUCTION, send feedback to
|
||||||
a.spl(href='mailto:team@codecombat.com') team@codecombat.com
|
a.spl(href='mailto:team@codecombat.com') team@codecombat.com
|
||||||
|
@ -14,60 +13,51 @@ block content
|
||||||
span.spl Student view
|
span.spl Student view
|
||||||
div(style='border-bottom: 1px solid black;')
|
div(style='border-bottom: 1px solid black;')
|
||||||
|
|
||||||
.modal#editNameModal
|
.modal#editSettingsModal
|
||||||
.modal-dialog
|
.modal-dialog
|
||||||
.modal-header
|
.modal-header
|
||||||
button.close(data-dismiss='modal')
|
button.close(data-dismiss='modal')
|
||||||
span ×
|
span ×
|
||||||
h3.modal-title Edit Class Name
|
h3.modal-title Edit Class Settings
|
||||||
.modal-body
|
.modal-body
|
||||||
p This title will be displayed to everyone enrolled in this class.
|
p This title will be displayed to everyone in the class.
|
||||||
|
p
|
||||||
input.edit-name-input(type='text', value="#{instance.name}")
|
input.edit-name-input(type='text', value="#{instance.name}")
|
||||||
.modal-footer
|
p This description will be displayed to everyone in the class.
|
||||||
button.btn.edit-name-save-btn(data-i18n="common.save_changes")
|
p
|
||||||
|
|
||||||
.modal#editDescriptionModal
|
|
||||||
.modal-dialog
|
|
||||||
.modal-header
|
|
||||||
button.close(data-dismiss='modal')
|
|
||||||
span ×
|
|
||||||
h3.modal-title Edit Class Description
|
|
||||||
.modal-body
|
|
||||||
p This description will be displayed to everyone enrolled in this class.
|
|
||||||
textarea.edit-description-input(rows=2)= instance.description
|
textarea.edit-description-input(rows=2)= instance.description
|
||||||
|
p Select programming languages available to the class:
|
||||||
|
p
|
||||||
|
select.form-control.select-language
|
||||||
|
option(value="Python") Python
|
||||||
|
option(value="JavaScript") JavaScript
|
||||||
|
option(value="All Languages") All Languages
|
||||||
|
p
|
||||||
|
input(type='checkbox', checked)
|
||||||
|
span.spl Show student progress to everyone in the class
|
||||||
.modal-footer
|
.modal-footer
|
||||||
button.btn.edit-description-save-btn(data-i18n="common.save_changes")
|
button.btn.btn-save-settings(data-i18n="common.save_changes")
|
||||||
|
|
||||||
h1= course.title
|
h1= instance.name
|
||||||
p= course.description
|
small.spl (#{course.title})
|
||||||
|
|
||||||
h3= instance.name
|
|
||||||
if !studentMode
|
|
||||||
span.spl
|
|
||||||
button.btn.btn-xs.edit-class-name-btn(data-toggle='modal', data-target='#editNameModal') edit class name
|
|
||||||
|
|
||||||
p
|
p
|
||||||
if instance.description
|
if instance.description
|
||||||
each line in instance.description.split('\n')
|
each line in instance.description.split('\n')
|
||||||
div= line
|
div= line
|
||||||
if !studentMode
|
|
||||||
span.spl
|
|
||||||
button.btn.btn-xs.edit-description-btn(data-toggle='modal', data-target='#editDescriptionModal') edit class description
|
|
||||||
else if !studentMode
|
|
||||||
div
|
|
||||||
button.btn.btn-xs.edit-description-btn add class description
|
|
||||||
|
|
||||||
if !studentMode
|
if !studentMode
|
||||||
.form-group
|
p
|
||||||
span.spr Select language
|
button.btn.btn-xs.btn-edit-settings(data-toggle='modal', data-target='#editSettingsModal') edit class settings
|
||||||
select.form-control.select-language
|
|
||||||
option(value="Python") Python
|
|
||||||
option(value="JavaScript") JavaScript
|
|
||||||
option(value="All Languages") All Languages
|
|
||||||
|
|
||||||
div(role='tabpanel')
|
div(role='tabpanel')
|
||||||
ul.nav.nav-tabs(role='tablist')
|
ul.nav.nav-tabs(role='tablist')
|
||||||
if !studentMode
|
if studentMode
|
||||||
|
li.active(role='presentation')
|
||||||
|
a(href='#levels', aria-controls='levels', role='tab', data-toggle='tab') Levels
|
||||||
|
li(role='presentation')
|
||||||
|
a(href='#progress', aria-controls='progress', role='tab', data-toggle='tab') Class
|
||||||
|
else
|
||||||
li.active(role='presentation')
|
li.active(role='presentation')
|
||||||
a(href='#progress', aria-controls='progress', role='tab', data-toggle='tab') Class
|
a(href='#progress', aria-controls='progress', role='tab', data-toggle='tab') Class
|
||||||
li(role='presentation')
|
li(role='presentation')
|
||||||
|
@ -76,26 +66,64 @@ block content
|
||||||
a(href='#levels', aria-controls='levels', role='tab', data-toggle='tab') Levels
|
a(href='#levels', aria-controls='levels', role='tab', data-toggle='tab') Levels
|
||||||
|
|
||||||
.tab-content
|
.tab-content
|
||||||
if !studentMode
|
if studentMode
|
||||||
|
.tab-pane.active#levels(role='tabpanel')
|
||||||
|
+levels-tab
|
||||||
|
.tab-pane#progress(role='tabpanel')
|
||||||
|
+progress-tab
|
||||||
|
else
|
||||||
.tab-pane.active#progress(role='tabpanel')
|
.tab-pane.active#progress(role='tabpanel')
|
||||||
|
+progress-tab
|
||||||
|
.tab-pane#invite(role='tabpanel')
|
||||||
|
br
|
||||||
|
p Invite students to join this class.
|
||||||
|
if course.title !== 'Introduction to Computer Science'
|
||||||
|
p Student unlock code: #{instance.code}
|
||||||
|
p Class capacity: 34/50
|
||||||
|
textarea.textarea-emails(rows=3, placeholder="Enter student emails to invite, one per line")
|
||||||
|
div(style='margin-top:10px;')
|
||||||
|
button.btn.btn-success.btn-invite Send Invites
|
||||||
|
.tab-pane#levels(role='tabpanel')
|
||||||
|
+levels-tab
|
||||||
|
|
||||||
|
mixin progress-tab
|
||||||
if instance.students
|
if instance.students
|
||||||
h3 Summary
|
.container-fluid.summary-container
|
||||||
- var averagePlaytime = Math.round(Math.random() * 30) + 30
|
.row
|
||||||
p
|
.col-md-6
|
||||||
strong(style='font-size:12pt;') Average Play Time
|
h3 Statistics
|
||||||
p #{averagePlaytime} minutes
|
table.statistics-container
|
||||||
p
|
tr
|
||||||
strong(style='font-size:12pt;') Concepts Covered
|
td Total students:
|
||||||
table.table.table-condensed
|
td #{instance.students.length}
|
||||||
|
tr
|
||||||
|
td Average level play time:
|
||||||
|
td #{stats.averageLevelPlaytime} seconds
|
||||||
|
tr
|
||||||
|
td Total play time:
|
||||||
|
td #{stats.totalPlayTime} seconds
|
||||||
|
tr
|
||||||
|
td Average levels completed:
|
||||||
|
td #{stats.averageLevelsCompleted}
|
||||||
|
tr
|
||||||
|
td Total levels completed:
|
||||||
|
td #{stats.totalLevelsCompleted}
|
||||||
|
tr
|
||||||
|
td Last level completed:
|
||||||
|
td #{stats.lastLevelCompleted}
|
||||||
|
.col-md-6
|
||||||
|
h3 Concepts Covered
|
||||||
|
table.table-concepts-summary
|
||||||
each concept in courseConcepts
|
each concept in courseConcepts
|
||||||
- var conceptCompletion = Math.round(parseFloat(conceptsCompleted[concept]) / instance.students.length * 100)
|
- var conceptCompletion = Math.round(parseFloat(conceptsCompleted[concept]) / instance.students.length * 100)
|
||||||
if isNaN(conceptCompletion)
|
if isNaN(conceptCompletion)
|
||||||
- conceptCompletion = 0
|
- conceptCompletion = 0
|
||||||
tr
|
tr
|
||||||
td.concept-completion-container
|
td.concept-completion-container
|
||||||
|
span.concept-summary(style="width:#{conceptCompletion}%;")
|
||||||
span.concept-completed-foreground(data-i18n="concepts." + concept)
|
span.concept-completed-foreground(data-i18n="concepts." + concept)
|
||||||
span.spl - #{conceptCompletion}%
|
span.spl - #{conceptCompletion}%
|
||||||
span.concept-completion-background(style="width:#{conceptCompletion}%;")
|
|
||||||
h3 Students
|
h3 Students
|
||||||
table.table.table-condensed
|
table.table.table-condensed
|
||||||
thead
|
thead
|
||||||
|
@ -163,21 +191,6 @@ block content
|
||||||
span.spl #{level}
|
span.spl #{level}
|
||||||
- i++
|
- i++
|
||||||
|
|
||||||
.tab-pane#invite(role='tabpanel')
|
|
||||||
p Invite students to join this class.
|
|
||||||
if course.title !== 'Introduction to Computer Science'
|
|
||||||
p Student unlock code: #{instance.code}
|
|
||||||
p Class capacity: 34/50
|
|
||||||
textarea.textarea-emails(rows=3, placeholder="Enter student emails to invite, one per line")
|
|
||||||
div
|
|
||||||
button.btn.btn-success.btn-invite Send Invites
|
|
||||||
|
|
||||||
.tab-pane#levels(role='tabpanel')
|
|
||||||
+levels-tab
|
|
||||||
else
|
|
||||||
.tab-pane.active#levels(role='tabpanel')
|
|
||||||
+levels-tab
|
|
||||||
|
|
||||||
mixin levels-tab
|
mixin levels-tab
|
||||||
table.table.table-striped.table-condensed
|
table.table.table-striped.table-condensed
|
||||||
thead
|
thead
|
||||||
|
|
|
@ -29,7 +29,7 @@ block content
|
||||||
each inst in instances
|
each inst in instances
|
||||||
option= inst.name
|
option= inst.name
|
||||||
.col-md-4
|
.col-md-4
|
||||||
button.btn.btn-success.btn-enter(data-course-id="#{courseID}") Enter
|
button.btn.btn-success.btn-enter Enter
|
||||||
.row.button-row.center.row-pick-class
|
.row.button-row.center.row-pick-class
|
||||||
.col-md-12
|
.col-md-12
|
||||||
div.or Or
|
div.or Or
|
||||||
|
@ -43,39 +43,34 @@ block content
|
||||||
.col-md-8
|
.col-md-8
|
||||||
input.code-input(type='text', placeholder="Enter unlock code")
|
input.code-input(type='text', placeholder="Enter unlock code")
|
||||||
.col-md-4
|
.col-md-4
|
||||||
button.btn.btn-success.btn-enroll(data-course-id="#{courseID}") Enroll
|
button.btn.btn-success.btn-enroll Enroll
|
||||||
.row.button-row.center
|
.row.button-row.center
|
||||||
.col-md-12
|
.col-md-12
|
||||||
div.or Or
|
div.or Or
|
||||||
.row.button-row.center
|
.row.button-row.center
|
||||||
.col-md-12
|
.col-md-12
|
||||||
button.btn.btn-success.btn-lg.btn-buy(data-course-id="#{courseID}") Buy this course
|
button.btn.btn-success.btn-lg.btn-buy Buy this course
|
||||||
|
|
||||||
h1.center Courses
|
h1.center Courses on CodeCombat
|
||||||
|
|
||||||
.info-container
|
.info-container
|
||||||
//- p.center.gameplay-img-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.
|
||||||
//- img(src="/images/pages/courses/101_info.png" width='800')
|
|
||||||
p A course is a selection of CodeCombat levels designed to introduce computer science concepts in a fun and engaging environment.
|
|
||||||
.container-fluid
|
.container-fluid
|
||||||
.row
|
|
||||||
.col-md-12
|
|
||||||
p.center
|
|
||||||
button.btn.btn-success.btn-lg.btn-buy Enroll Now!
|
|
||||||
.row
|
.row
|
||||||
.col-md-6
|
.col-md-6
|
||||||
div With CodeCombat courses, you and your students will:
|
|
||||||
ul
|
ul
|
||||||
li Learn more in less time
|
li Learn more in less time
|
||||||
li With no experience necesssary
|
li No coding experience necesssary
|
||||||
li Monitor student progress
|
li Easily monitor student progress
|
||||||
br
|
|
||||||
|
div Purchase a course for your entire class. It's easy to sign up your students!
|
||||||
.col-md-6
|
.col-md-6
|
||||||
p
|
.well.well-sm
|
||||||
div.praise-quote "#{praise.quote}"
|
div.praise-quote "#{praise.quote}"
|
||||||
div.caption-text - #{praise.source}
|
div.caption-text - #{praise.source}
|
||||||
|
|
||||||
//- h2.center Available Courses
|
h2.center Choose Your Course:
|
||||||
|
|
||||||
.container-fluid
|
.container-fluid
|
||||||
- var i = 0
|
- var i = 0
|
||||||
|
@ -95,13 +90,13 @@ mixin course-block(course, courseID)
|
||||||
span.spr #{course.title}
|
span.spr #{course.title}
|
||||||
strong #{course.unlocked ? '[ enrolled ]' : ''}
|
strong #{course.unlocked ? '[ enrolled ]' : ''}
|
||||||
.panel-body
|
.panel-body
|
||||||
|
.container-fluid
|
||||||
|
.row.button-row
|
||||||
|
.col-md-6
|
||||||
strong Topics
|
strong Topics
|
||||||
ul
|
ul
|
||||||
each topic in course.topics
|
each topic in course.topics
|
||||||
li= topic
|
li= topic
|
||||||
strong Hours of content: #{course.duration}
|
strong Hours of content: #{course.duration}
|
||||||
.container-fluid
|
.col-md-6.center
|
||||||
.row.button-row.center
|
button.btn.btn-lg.btn-success.btn-continue(data-toggle='modal', data-target="#continueModal", data-course-title="#{course.title}", data-course-id="#{courseID}") #{course.unlocked ? 'Continue' : 'Enter'}
|
||||||
.col-md-12
|
|
||||||
br
|
|
||||||
button.btn.btn-success.btn-continue(data-toggle='modal', data-target="#continueModal", data-course-title="#{course.title}", data-course-id="#{courseID}") #{course.unlocked ? 'Continue' : 'Enter'}
|
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
extends /templates/base
|
extends /templates/base
|
||||||
|
|
||||||
|
block append site_nav
|
||||||
|
#kids-coding-container
|
||||||
|
img#boy-coding.kid-coding(src="/images/pages/home/boy_coding.png", alt="", draggable="false")
|
||||||
|
img#girl-coding.kid-coding(src="/images/pages/home/girl_coding.png", alt="", draggable="false")
|
||||||
|
|
||||||
block outer_content
|
block outer_content
|
||||||
#spacer
|
#spacer
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,7 @@ else
|
||||||
|
|
||||||
.game-controls.header-font
|
.game-controls.header-font
|
||||||
button.btn.poll.hidden(data-i18n="[title]play.poll")
|
button.btn.poll.hidden(data-i18n="[title]play.poll")
|
||||||
|
a.btn.clans(href="/clans", data-i18n="[title]clans.clans")
|
||||||
button.btn.items(data-toggle='coco-modal', data-target='play/modal/PlayItemsModal', data-i18n="[title]play.items")
|
button.btn.items(data-toggle='coco-modal', data-target='play/modal/PlayItemsModal', data-i18n="[title]play.items")
|
||||||
button.btn.heroes(data-toggle='coco-modal', data-target='play/modal/PlayHeroesModal', data-i18n="[title]play.heroes")
|
button.btn.heroes(data-toggle='coco-modal', data-target='play/modal/PlayHeroesModal', data-i18n="[title]play.heroes")
|
||||||
button.btn.achievements(data-toggle='coco-modal', data-target='play/modal/PlayAchievementsModal', data-i18n="[title]play.achievements")
|
button.btn.achievements(data-toggle='coco-modal', data-target='play/modal/PlayAchievementsModal', data-i18n="[title]play.achievements")
|
||||||
|
@ -118,9 +119,6 @@ else
|
||||||
button#logout-button.btn.btn-illustrated.btn-warning(data-i18n="login.log_out") Log Out
|
button#logout-button.btn.btn-illustrated.btn-warning(data-i18n="login.log_out") Log Out
|
||||||
if me.isPremium()
|
if me.isPremium()
|
||||||
button.btn.btn-illustrated.btn-primary(data-i18n="nav.contact", data-toggle="coco-modal", data-target="core/ContactModal") Contact
|
button.btn.btn-illustrated.btn-primary(data-i18n="nav.contact", data-toggle="coco-modal", data-target="core/ContactModal") Contact
|
||||||
span.spl
|
|
||||||
a.btn.btn-illustrated(href='/clans', data-i18n="clans.clans") Clans
|
|
||||||
|
|
||||||
|
|
||||||
button.btn.btn-lg.btn-inverse.campaign-control-button#volume-button(data-i18n="[title]play.adjust_volume", title="Adjust volume")
|
button.btn.btn-lg.btn-inverse.campaign-control-button#volume-button(data-i18n="[title]play.adjust_volume", title="Adjust volume")
|
||||||
.glyphicon.glyphicon-volume-off
|
.glyphicon.glyphicon-volume-off
|
||||||
|
|
|
@ -10,11 +10,9 @@ module.exports = class CourseDetailsView extends RootView
|
||||||
|
|
||||||
events:
|
events:
|
||||||
'change .expand-progress-checkbox': 'onExpandedProgressCheckbox'
|
'change .expand-progress-checkbox': 'onExpandedProgressCheckbox'
|
||||||
'change .select-session': 'onChangeSession'
|
|
||||||
'change .student-mode-checkbox': 'onChangeStudent'
|
'change .student-mode-checkbox': 'onChangeStudent'
|
||||||
'click .btn-play-level': 'onClickPlayLevel'
|
'click .btn-play-level': 'onClickPlayLevel'
|
||||||
'click .edit-description-save-btn': 'onEditDescriptionSave'
|
'click .btn-save-settings': 'onClickSaveSettings'
|
||||||
'click .edit-name-save-btn': 'onEditNameSave'
|
|
||||||
'click .member-header': 'onClickMemberHeader'
|
'click .member-header': 'onClickMemberHeader'
|
||||||
'click .progress-header': 'onClickProgressHeader'
|
'click .progress-header': 'onClickProgressHeader'
|
||||||
'mouseenter .progress-level-cell': 'onMouseEnterPoint'
|
'mouseenter .progress-level-cell': 'onMouseEnterPoint'
|
||||||
|
@ -49,6 +47,14 @@ module.exports = class CourseDetailsView extends RootView
|
||||||
conceptsCompleted[concept]++
|
conceptsCompleted[concept]++
|
||||||
context.conceptsCompleted = conceptsCompleted
|
context.conceptsCompleted = conceptsCompleted
|
||||||
|
|
||||||
|
stats =
|
||||||
|
averageLevelPlaytime: _.random(30, 240)
|
||||||
|
averageLevelsCompleted: _.random(1, @course.levels.length)
|
||||||
|
stats.totalPlayTime = context.instance.students?.length * stats.averageLevelPlaytime ? 0
|
||||||
|
stats.totalLevelsCompleted = context.instance.students?.length * stats.averageLevelsCompleted ? 0
|
||||||
|
stats.lastLevelCompleted = @course.levels[@maxLastStartedIndex] ? @course.levels[@course.levels.length - 1]
|
||||||
|
context.stats = stats
|
||||||
|
|
||||||
context
|
context
|
||||||
|
|
||||||
initData: ->
|
initData: ->
|
||||||
|
@ -144,26 +150,12 @@ module.exports = class CourseDetailsView extends RootView
|
||||||
@render?()
|
@render?()
|
||||||
$('.student-mode-checkbox').attr('checked', @options.studentMode)
|
$('.student-mode-checkbox').attr('checked', @options.studentMode)
|
||||||
|
|
||||||
onChangeSession: (e) ->
|
|
||||||
@showExpandedProgress = false
|
|
||||||
newSessionValue = $(e.target).val()
|
|
||||||
for val, index in @instances when val.name is newSessionValue
|
|
||||||
@currentInstanceIndex = index
|
|
||||||
@updateLevelMaps()
|
|
||||||
@onCampaignSync()
|
|
||||||
|
|
||||||
onExpandedProgressCheckbox: (e) ->
|
onExpandedProgressCheckbox: (e) ->
|
||||||
@showExpandedProgress = $('.expand-progress-checkbox').prop('checked')
|
@showExpandedProgress = $('.expand-progress-checkbox').prop('checked')
|
||||||
# TODO: why does render reset the checkbox to be unchecked?
|
# TODO: why does render reset the checkbox to be unchecked?
|
||||||
@render?()
|
@render?()
|
||||||
$('.expand-progress-checkbox').attr('checked', @showExpandedProgress)
|
$('.expand-progress-checkbox').attr('checked', @showExpandedProgress)
|
||||||
|
|
||||||
onClickEditClassName: (e) ->
|
|
||||||
alert 'TODO: Popup for editing name for this course session'
|
|
||||||
|
|
||||||
onClickEditClassDescription: (e) ->
|
|
||||||
alert 'TODO: Popup for editing description for this course session'
|
|
||||||
|
|
||||||
onClickMemberHeader: (e) ->
|
onClickMemberHeader: (e) ->
|
||||||
@memberSort = if @memberSort is 'nameAsc' then 'nameDesc' else 'nameAsc'
|
@memberSort = if @memberSort is 'nameAsc' then 'nameDesc' else 'nameAsc'
|
||||||
@sortMembers()
|
@sortMembers()
|
||||||
|
@ -183,16 +175,12 @@ module.exports = class CourseDetailsView extends RootView
|
||||||
viewArgs: [{}, levelSlug]
|
viewArgs: [{}, levelSlug]
|
||||||
}
|
}
|
||||||
|
|
||||||
onEditDescriptionSave: (e) ->
|
onClickSaveSettings: (e) ->
|
||||||
description = $('.edit-description-input').val()
|
|
||||||
@instances[@currentInstanceIndex].description = description
|
|
||||||
$('#editDescriptionModal').modal('hide')
|
|
||||||
@render?()
|
|
||||||
|
|
||||||
onEditNameSave: (e) ->
|
|
||||||
if name = $('.edit-name-input').val()
|
if name = $('.edit-name-input').val()
|
||||||
@instances[@currentInstanceIndex].name = name
|
@instances[@currentInstanceIndex].name = name
|
||||||
$('#editNameModal').modal('hide')
|
description = $('.edit-description-input').val()
|
||||||
|
@instances[@currentInstanceIndex].description = description
|
||||||
|
$('#editSettingsModal').modal('hide')
|
||||||
@render?()
|
@render?()
|
||||||
|
|
||||||
onMouseEnterPoint: (e) ->
|
onMouseEnterPoint: (e) ->
|
||||||
|
|
|
@ -40,7 +40,7 @@ data.courses = [
|
||||||
image: '/images/pages/courses/102_info.png'
|
image: '/images/pages/courses/102_info.png'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'CS Course 3'
|
title: 'Computer Science 3'
|
||||||
description: 'Learn how to handle input.'
|
description: 'Learn how to handle input.'
|
||||||
topics: ['If Statements', 'Arithmetic', 'Input Handling']
|
topics: ['If Statements', 'Arithmetic', 'Input Handling']
|
||||||
duration: 5
|
duration: 5
|
||||||
|
@ -48,7 +48,7 @@ data.courses = [
|
||||||
image: '/images/pages/courses/103_info.png'
|
image: '/images/pages/courses/103_info.png'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'CS 4'
|
title: 'Computer Science 4'
|
||||||
description: 'Time to tackle arrays and some pvp stuff.'
|
description: 'Time to tackle arrays and some pvp stuff.'
|
||||||
topics: ['Loops', 'Break Statements', 'Arrays']
|
topics: ['Loops', 'Break Statements', 'Arrays']
|
||||||
duration: 5
|
duration: 5
|
||||||
|
@ -56,7 +56,7 @@ data.courses = [
|
||||||
image: '/images/pages/courses/104_info.png'
|
image: '/images/pages/courses/104_info.png'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Course 5'
|
title: 'Computer Science 5'
|
||||||
description: 'Time to tackle arrays and some PVP.'
|
description: 'Time to tackle arrays and some PVP.'
|
||||||
topics: ['Break Statements', 'Arrays', 'Object Literals']
|
topics: ['Break Statements', 'Arrays', 'Object Literals']
|
||||||
duration: 5
|
duration: 5
|
||||||
|
@ -64,7 +64,7 @@ data.courses = [
|
||||||
image: '/images/pages/courses/105_info.png'
|
image: '/images/pages/courses/105_info.png'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Course 6'
|
title: 'Computer Science 6'
|
||||||
description: 'For loops!'
|
description: 'For loops!'
|
||||||
topics: ['Break Statements', 'Object Literals', 'For loops']
|
topics: ['Break Statements', 'Object Literals', 'For loops']
|
||||||
duration: 5
|
duration: 5
|
||||||
|
@ -72,7 +72,7 @@ data.courses = [
|
||||||
image: '/images/pages/courses/106_info.png'
|
image: '/images/pages/courses/106_info.png'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Course 7'
|
title: 'Computer Science 7'
|
||||||
description: 'Functions!'
|
description: 'Functions!'
|
||||||
topics: ['Object Literals', 'For loops', 'Functions']
|
topics: ['Object Literals', 'For loops', 'Functions']
|
||||||
duration: 5
|
duration: 5
|
||||||
|
@ -80,7 +80,7 @@ data.courses = [
|
||||||
image: '/images/pages/courses/107_info.png'
|
image: '/images/pages/courses/107_info.png'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'CS 108'
|
title: 'Computer Science 8'
|
||||||
description: 'Maths.'
|
description: 'Maths.'
|
||||||
topics: ['For loops', 'Functions', 'Math Operations']
|
topics: ['For loops', 'Functions', 'Math Operations']
|
||||||
duration: 5
|
duration: 5
|
||||||
|
@ -88,7 +88,7 @@ data.courses = [
|
||||||
image: '/images/pages/courses/107_info.png'
|
image: '/images/pages/courses/107_info.png'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Computer Science 109'
|
title: 'Computer Science 9'
|
||||||
description: 'Vectors and strings.'
|
description: 'Vectors and strings.'
|
||||||
topics: ['Vectors', 'Advanced Strings']
|
topics: ['Vectors', 'Advanced Strings']
|
||||||
duration: 5
|
duration: 5
|
||||||
|
|
|
@ -51,6 +51,10 @@ module.exports = class CoursesView extends RootView
|
||||||
$('#continueModal').find('.btn-enroll').data('course-id', courseID)
|
$('#continueModal').find('.btn-enroll').data('course-id', courseID)
|
||||||
$('#continueModal').find('.btn-enter').data('course-id', courseID)
|
$('#continueModal').find('.btn-enter').data('course-id', courseID)
|
||||||
$('#continueModal .row-pick-class').show() if @courses[courseID]?.unlocked
|
$('#continueModal .row-pick-class').show() if @courses[courseID]?.unlocked
|
||||||
|
if courseTitle is 'Introduction to Computer Science'
|
||||||
|
$('#continueModal .btn-buy').prop('innerText', 'Get this FREE course!')
|
||||||
|
else
|
||||||
|
$('#continueModal .btn-buy').prop('innerText', 'Buy this course')
|
||||||
|
|
||||||
onClickEnroll: (e) ->
|
onClickEnroll: (e) ->
|
||||||
$('#continueModal').modal('hide')
|
$('#continueModal').modal('hide')
|
||||||
|
@ -65,7 +69,8 @@ module.exports = class CoursesView extends RootView
|
||||||
$('#continueModal').modal('hide')
|
$('#continueModal').modal('hide')
|
||||||
courseID = $(e.target).data('course-id')
|
courseID = $(e.target).data('course-id')
|
||||||
instanceName = $('.select-session').val()
|
instanceName = $('.select-session').val()
|
||||||
instanceID = index for val, index in @instances when val.name is instanceName
|
for val, index in @instances when val.name is instanceName
|
||||||
|
instanceID = index
|
||||||
viewClass = require 'views/courses/mock1/CourseDetailsView'
|
viewClass = require 'views/courses/mock1/CourseDetailsView'
|
||||||
viewArgs = [{}, courseID, instanceID]
|
viewArgs = [{}, courseID, instanceID]
|
||||||
navigationEvent = route: "/courses/mock1/#{courseID}", viewClass: viewClass, viewArgs: viewArgs
|
navigationEvent = route: "/courses/mock1/#{courseID}", viewClass: viewClass, viewArgs: viewArgs
|
||||||
|
|
|
@ -30,7 +30,7 @@ class LevelSessionsCollection extends CocoCollection
|
||||||
|
|
||||||
constructor: (model) ->
|
constructor: (model) ->
|
||||||
super()
|
super()
|
||||||
@url = "/db/user/#{me.id}/level.sessions?project=state.complete,levelID,state.difficulty"
|
@url = "/db/user/#{me.id}/level.sessions?project=state.complete,levelID,state.difficulty,playtime"
|
||||||
|
|
||||||
class CampaignsCollection extends CocoCollection
|
class CampaignsCollection extends CocoCollection
|
||||||
url: '/db/campaign'
|
url: '/db/campaign'
|
||||||
|
@ -261,6 +261,7 @@ module.exports = class CampaignView extends RootView
|
||||||
annotateLevel: (level) ->
|
annotateLevel: (level) ->
|
||||||
level.position ?= { x: 10, y: 10 }
|
level.position ?= { x: 10, y: 10 }
|
||||||
level.locked = not me.ownsLevel level.original
|
level.locked = not me.ownsLevel level.original
|
||||||
|
level.locked = true if level.slug is 'kithgard-mastery' and @calculateExperienceScore() is 0
|
||||||
level.locked = false if @levelStatusMap[level.slug] in ['started', 'complete']
|
level.locked = false if @levelStatusMap[level.slug] in ['started', 'complete']
|
||||||
level.locked = false if @editorMode
|
level.locked = false if @editorMode
|
||||||
level.locked = false if @campaign?.get('name') is 'Auditions'
|
level.locked = false if @campaign?.get('name') is 'Auditions'
|
||||||
|
@ -302,12 +303,22 @@ module.exports = class CampaignView extends RootView
|
||||||
|
|
||||||
determineNextLevel: (levels) ->
|
determineNextLevel: (levels) ->
|
||||||
foundNext = false
|
foundNext = false
|
||||||
|
dontPointTo = ['lost-viking', 'kithgard-mastery'] # Challenge levels we don't want most players bashing heads against
|
||||||
for level in levels
|
for level in levels
|
||||||
|
# Iterate through all levels in order and look to find the first unlocked one that meets all our criteria for being pointed out as the next level.
|
||||||
level.nextLevels = (reward.level for reward in level.rewards ? [] when reward.level)
|
level.nextLevels = (reward.level for reward in level.rewards ? [] when reward.level)
|
||||||
unless foundNext
|
unless foundNext
|
||||||
for nextLevelOriginal in level.nextLevels
|
for nextLevelOriginal in level.nextLevels
|
||||||
nextLevel = _.find levels, original: nextLevelOriginal
|
nextLevel = _.find levels, original: nextLevelOriginal
|
||||||
dontPointTo = ['lost-viking','kithgard-mastery']
|
|
||||||
|
# If it's a challenge level, we efficiently determine whether we actually do want to point it out.
|
||||||
|
if nextLevel and nextLevel.slug is 'kithgard-mastery' and not nextLevel.locked and not @levelStatusMap[nextLevel.slug] and @calculateExperienceScore() >= 3
|
||||||
|
unless (timesPointedOut = storage.load("pointed-out-#{nextLevel.slug}") or 0) > 3
|
||||||
|
# We may determineNextLevel more than once per render, so we can't just do this once. But we do give up after a couple highlights.
|
||||||
|
dontPointTo = _.without dontPointTo, nextLevel.slug
|
||||||
|
storage.save "pointed-out-#{nextLevel.slug}", timesPointedOut + 1
|
||||||
|
|
||||||
|
# Should we point this level out?
|
||||||
if nextLevel and not nextLevel.locked and not nextLevel.disabled and @levelStatusMap[nextLevel.slug] isnt 'complete' and nextLevel.slug not in dontPointTo and not nextLevel.replayable and (
|
if nextLevel and not nextLevel.locked and not nextLevel.disabled and @levelStatusMap[nextLevel.slug] isnt 'complete' and nextLevel.slug not in dontPointTo and not nextLevel.replayable and (
|
||||||
me.isPremium() or
|
me.isPremium() or
|
||||||
not nextLevel.requiresSubscription or
|
not nextLevel.requiresSubscription or
|
||||||
|
@ -320,6 +331,15 @@ module.exports = class CampaignView extends RootView
|
||||||
if not foundNext and levels[0] and not levels[0].locked and @levelStatusMap[levels[0].slug] isnt 'complete'
|
if not foundNext and levels[0] and not levels[0].locked and @levelStatusMap[levels[0].slug] isnt 'complete'
|
||||||
levels[0].next = true
|
levels[0].next = true
|
||||||
|
|
||||||
|
calculateExperienceScore: ->
|
||||||
|
adultPoint = me.get('ageRange') in ['18-24', '25-34', '35-44', '45-100'] # They have to have answered the poll for this, likely after Shadow Guard.
|
||||||
|
speedPoints = 0
|
||||||
|
for [levelSlug, speedThreshold] in [['dungeons-of-kithgard', 50], ['gems-in-the-deep', 55], ['shadow-guard', 55], ['forgetful-gemsmith', 40], ['true-names', 40]]
|
||||||
|
if _.find(@sessions.models, (session) -> session.get('levelID') is levelSlug)?.attributes.playtime <= speedThreshold
|
||||||
|
++speedPoints
|
||||||
|
experienceScore = adultPoint + speedPoints # 0-6 score of how likely we think they are to be experienced and ready for Kithgard Mastery
|
||||||
|
return experienceScore
|
||||||
|
|
||||||
createLine: (o1, o2) ->
|
createLine: (o1, o2) ->
|
||||||
p1 = x: o1.x, y: 0.66 * o1.y + 0.5
|
p1 = x: o1.x, y: 0.66 * o1.y + 0.5
|
||||||
p2 = x: o2.x, y: 0.66 * o2.y + 0.5
|
p2 = x: o2.x, y: 0.66 * o2.y + 0.5
|
||||||
|
|
|
@ -141,6 +141,7 @@ module.exports = class HeroVictoryModal extends ModalView
|
||||||
getRenderData: ->
|
getRenderData: ->
|
||||||
c = super()
|
c = super()
|
||||||
c.levelName = utils.i18n @level.attributes, 'name'
|
c.levelName = utils.i18n @level.attributes, 'name'
|
||||||
|
if @level.get('type', true) isnt 'hero'
|
||||||
c.victoryText = utils.i18n @level.get('victory') ? {}, 'body'
|
c.victoryText = utils.i18n @level.get('victory') ? {}, 'body'
|
||||||
earnedAchievementMap = _.indexBy(@newEarnedAchievements or [], (ea) -> ea.get('achievement'))
|
earnedAchievementMap = _.indexBy(@newEarnedAchievements or [], (ea) -> ea.get('achievement'))
|
||||||
for achievement in (@achievements?.models or [])
|
for achievement in (@achievements?.models or [])
|
||||||
|
|
|
@ -73,7 +73,7 @@ module.exports = class PollModal extends ModalView
|
||||||
onClickAnswer: (e) ->
|
onClickAnswer: (e) ->
|
||||||
$selectedAnswer = $(e.target).closest('.answer')
|
$selectedAnswer = $(e.target).closest('.answer')
|
||||||
pollVotes = @userPollsRecord.get('polls') ? {}
|
pollVotes = @userPollsRecord.get('polls') ? {}
|
||||||
pollVotes[@poll.id] = $selectedAnswer.data('answer')
|
pollVotes[@poll.id] = $selectedAnswer.data('answer').toString()
|
||||||
@userPollsRecord.set 'polls', pollVotes
|
@userPollsRecord.set 'polls', pollVotes
|
||||||
@updateAnswers true
|
@updateAnswers true
|
||||||
@userPollsRecord.save {polls: pollVotes}, {success: => @awardRandomGems?()}
|
@userPollsRecord.save {polls: pollVotes}, {success: => @awardRandomGems?()}
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
var excludedLevels = ['deadly-dungeon-rescue', 'kithgard-brawl', 'cavern-survival', 'kithgard-mastery', 'destroying-angel', 'kithgard-apprentice', 'wild-horses', 'lost-viking', 'forest-flower-grove', 'boulder-woods', 'the-trials'];
|
var excludedLevels = ['deadly-dungeon-rescue', 'kithgard-brawl', 'cavern-survival', 'kithgard-mastery', 'destroying-angel', 'kithgard-apprentice', 'wild-horses', 'lost-viking', 'forest-flower-grove', 'boulder-woods', 'the-trials'];
|
||||||
|
|
||||||
var scriptStartTime = new Date();
|
var scriptStartTime = new Date();
|
||||||
var startDay = '2015-05-10';
|
var startDay = '2015-07-01';
|
||||||
var endDay = '2015-06-11';
|
var endDay = '2015-08-06';
|
||||||
|
|
||||||
log("Dates: " + startDay + " to " + endDay);
|
log("Dates: " + startDay + " to " + endDay);
|
||||||
|
|
||||||
|
|
25
scripts/analytics/mongodb/queries/teacherSurveyCounts.js
Normal file
25
scripts/analytics/mongodb/queries/teacherSurveyCounts.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Print out teacher survey counts by day
|
||||||
|
|
||||||
|
// Usage:
|
||||||
|
// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
|
||||||
|
|
||||||
|
var surveyDayMap = {};
|
||||||
|
var cursor = db['trial.requests'].find({type: 'subscription'});
|
||||||
|
while (cursor.hasNext()) {
|
||||||
|
var doc = cursor.next();
|
||||||
|
var date = doc._id.getTimestamp();
|
||||||
|
var day = date.toISOString().substring(0, 10);
|
||||||
|
if (!surveyDayMap[day]) surveyDayMap[day] = 0;
|
||||||
|
surveyDayMap[day]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var surveysSorted = [];
|
||||||
|
for (var day in surveyDayMap) {
|
||||||
|
surveysSorted.push({day: day, count: surveyDayMap[day]});
|
||||||
|
}
|
||||||
|
surveysSorted.sort(function(a, b) {return b.day.localeCompare(a.day);});
|
||||||
|
print("Number of teacher surveys per day:")
|
||||||
|
for (var i = 0; i < surveysSorted.length; i++) {
|
||||||
|
var stars = new Array(surveysSorted[i].count + 1).join('*');
|
||||||
|
print(surveysSorted[i].day + "\t" + surveysSorted[i].count + "\t" + stars);
|
||||||
|
}
|
Loading…
Reference in a new issue