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) ->
|
||||
@options.isCursor = to
|
||||
@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()
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
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
|
||||
childMovieClips: null
|
||||
|
@ -71,6 +73,13 @@ module.exports = class SingularSprite extends createjs.Sprite
|
|||
@baseScaleY = @scaleY
|
||||
if @camera and @thangType.get('name') in floors
|
||||
@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
|
||||
return
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ module.exports.thangNames = thangNames =
|
|||
'Godel'
|
||||
'Goreball'
|
||||
'Gordok'
|
||||
'Toremon'
|
||||
'Gorylo'
|
||||
'Gort'
|
||||
'Kog'
|
||||
'Kogpole'
|
||||
|
@ -37,11 +37,13 @@ module.exports.thangNames = thangNames =
|
|||
'Oogre'
|
||||
'Raack'
|
||||
'Ragtime'
|
||||
'Raort'
|
||||
'Rexxar'
|
||||
'Skoggen'
|
||||
'Smerk'
|
||||
'Snortt'
|
||||
'Thabt'
|
||||
'Toremon'
|
||||
'Treg'
|
||||
'Ursa'
|
||||
'Vorobun'
|
||||
|
@ -184,6 +186,7 @@ module.exports.thangNames = thangNames =
|
|||
'Belch'
|
||||
'Booz'
|
||||
'Brusentsov'
|
||||
'Demonik'
|
||||
'Dronck'
|
||||
'Gorlog'
|
||||
'Grumus'
|
||||
|
@ -204,7 +207,7 @@ module.exports.thangNames = thangNames =
|
|||
'Trogdor'
|
||||
'Trung'
|
||||
'Vargutt'
|
||||
'Demonik'
|
||||
'Vyle'
|
||||
]
|
||||
'Ogre F': [
|
||||
# Female
|
||||
|
|
|
@ -933,7 +933,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
|||
|
||||
contribute:
|
||||
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: "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."
|
||||
|
|
|
@ -293,7 +293,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
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_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_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"
|
||||
|
@ -337,7 +337,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
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_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:
|
||||
inventory_tab: "Inventário"
|
||||
|
@ -851,8 +851,8 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
indoor: "Interior"
|
||||
desert: "Deserto"
|
||||
grassy: "Relvado"
|
||||
# mountain: "Mountain"
|
||||
# glacier: "Glacier"
|
||||
mountain: "Montanha"
|
||||
glacier: "Glaciar"
|
||||
small: "Pequeno"
|
||||
large: "Grande"
|
||||
fork_title: "Bifurcar Nova Versão"
|
||||
|
@ -1211,7 +1211,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
delta:
|
||||
added: "Adicionado"
|
||||
modified: "Modificado"
|
||||
# not_modified: "Not Modified"
|
||||
not_modified: "Não Modificado"
|
||||
deleted: "Eliminado"
|
||||
moved_index: "Índice Movido"
|
||||
text_diff: "Diferença de Texto"
|
||||
|
|
|
@ -1,29 +1,42 @@
|
|||
#course-details-view
|
||||
|
||||
.concept-completion-container
|
||||
position: relative
|
||||
.concept-completion-background
|
||||
position: absolute
|
||||
height: 100%
|
||||
left: 0px
|
||||
top: 0px
|
||||
background-color: blue
|
||||
opacity: 0.25
|
||||
.concept-completed-foreground
|
||||
font-size: 12pt
|
||||
font-size: 10pt
|
||||
|
||||
#editDescriptionModal .modal-dialog
|
||||
.summary-container
|
||||
font-size: 14pt
|
||||
|
||||
.statistics-container
|
||||
font-size: 12pt
|
||||
td
|
||||
padding-right: 8px
|
||||
|
||||
.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
|
||||
|
||||
#editNameModal .modal-dialog
|
||||
#editSettingsModal .modal-dialog
|
||||
background-color: white
|
||||
max-width: 400px
|
||||
font-size: 14pt
|
||||
|
||||
.edit-description-input
|
||||
width: 100%
|
||||
|
||||
.edit-name-input
|
||||
width: 100%
|
||||
width: 50%
|
||||
|
||||
.member-header
|
||||
cursor: pointer
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#courses-view
|
||||
|
||||
.btn-continue
|
||||
margin-top: 40px
|
||||
|
||||
.center
|
||||
text-align: center
|
||||
|
||||
|
|
|
@ -2,7 +2,29 @@
|
|||
@import "app/styles/bootstrap/variables"
|
||||
|
||||
#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
|
||||
height: 626px
|
||||
@media screen and ( max-height: 800px )
|
||||
|
|
|
@ -365,19 +365,21 @@ $gameControlMargin: 30px
|
|||
&:active, &.highlighted
|
||||
@include box-shadow(0 0 20px white)
|
||||
|
||||
&.heroes
|
||||
&.items
|
||||
background-position: (-1 * $gameControlSize) 0px
|
||||
&.achievements
|
||||
&.heroes
|
||||
background-position: (-2 * $gameControlSize) 0px
|
||||
&.account
|
||||
//background-position: (-3 * $gameControlSize) 0px
|
||||
background-position: (-4 * $gameControlSize) 0px
|
||||
&.settings
|
||||
background-position: (-4 * $gameControlSize) 0px
|
||||
&.gems
|
||||
background-position: (-5 * $gameControlSize) 0px
|
||||
&.poll
|
||||
&.achievements
|
||||
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
|
||||
font-size: 24px
|
||||
|
|
|
@ -350,9 +350,15 @@ $itemSlotGridHeight: 51px
|
|||
img
|
||||
margin: 1px
|
||||
button
|
||||
margin-top: -2px
|
||||
height: 19px
|
||||
//margin-top: -2px
|
||||
//height: 19px
|
||||
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
|
||||
width: 56px
|
||||
|
@ -360,22 +366,32 @@ $itemSlotGridHeight: 51px
|
|||
display: block
|
||||
|
||||
button
|
||||
width: 100%
|
||||
height: 17px
|
||||
border: 1px solid rgb(46,46,46)
|
||||
background: white
|
||||
background: transparent url(/images/pages/play/modal/equip-buttons.png)
|
||||
width: 56px
|
||||
height: 21px
|
||||
border: 0
|
||||
//border: 1px solid rgb(46,46,46)
|
||||
//background: white
|
||||
font-size: 11px
|
||||
border-radius: 1px
|
||||
padding: 0
|
||||
@include transition(0.1s ease)
|
||||
padding: 0 0 2px 0
|
||||
@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
|
||||
background-color: rgb(81,153,236)
|
||||
|
||||
button
|
||||
background-color: lighten(rgb(89,136,47), 10%)
|
||||
//background-color: lighten(rgb(89,136,47), 10%)
|
||||
box-shadow: 1px 1px 4px #333
|
||||
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
|
||||
// display: inline
|
||||
|
@ -594,3 +610,12 @@ $itemSlotGridHeight: 51px
|
|||
&.male
|
||||
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,49 +1,50 @@
|
|||
block header
|
||||
#site-nav
|
||||
a(href="/")
|
||||
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
|
||||
block site_nav
|
||||
a(href="/")
|
||||
img#small-nav-logo(src="/images/pages/base/logo.png", title="CodeCombat - Learn how to code by playing a game", alt="CodeCombat")
|
||||
a(href="/")
|
||||
span.glyphicon.glyphicon-home
|
||||
a(href="/about", data-i18n="nav.about")
|
||||
a(href='/teachers', data-i18n="nav.teachers") Teachers
|
||||
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
|
||||
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
|
||||
a(href="/")
|
||||
img#small-nav-logo(src="/images/pages/base/logo.png", title="CodeCombat - Learn how to code by playing a game", alt="CodeCombat")
|
||||
a(href="/")
|
||||
span.glyphicon.glyphicon-home
|
||||
a(href="/about", data-i18n="nav.about")
|
||||
a(href='/teachers', data-i18n="nav.teachers") Teachers
|
||||
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
|
||||
button.btn.btn-sm.header-font.dropdown-toggle(href="#", data-toggle="dropdown")
|
||||
if me.get('photoURL')
|
||||
img.account-settings-image(src=me.getPhotoURL(18), alt="")
|
||||
else
|
||||
i.glyphicon.glyphicon-user
|
||||
span.spl.spr(data-i18n="nav.account" href="/account")
|
||||
span.caret
|
||||
ul.dropdown-menu(role="menu")
|
||||
li.user-dropdown-header
|
||||
span.user-level= me.level()
|
||||
a(href="/user/#{me.getSlugOrID()}")
|
||||
div.img-circle(style="background-image: url(#{me.getPhotoURL()})")
|
||||
h3=me.displayName()
|
||||
li
|
||||
a(href="/user/#{me.getSlugOrID()}" data-i18n="nav.profile")
|
||||
li
|
||||
a(href="/account/settings", data-i18n="play.settings")
|
||||
li
|
||||
a(href="/account/payments", data-i18n="account.payments")
|
||||
li
|
||||
a(href="/account/subscription", data-i18n="account.subscription")
|
||||
li
|
||||
a#logout-button(data-i18n="login.log_out")
|
||||
|
||||
else
|
||||
button.btn.btn-sm.btn-primary.header-font.signup-button(data-i18n="login.sign_up")
|
||||
button.btn.btn-sm.btn-default.header-font.login-button(data-i18n="login.log_in")
|
||||
select.language-dropdown.form-control
|
||||
if me.get('anonymous') === false
|
||||
span.dropdown
|
||||
button.btn.btn-sm.header-font.dropdown-toggle(href="#", data-toggle="dropdown")
|
||||
if me.get('photoURL')
|
||||
img.account-settings-image(src=me.getPhotoURL(18), alt="")
|
||||
else
|
||||
i.glyphicon.glyphicon-user
|
||||
span.spl.spr(data-i18n="nav.account" href="/account")
|
||||
span.caret
|
||||
ul.dropdown-menu(role="menu")
|
||||
li.user-dropdown-header
|
||||
span.user-level= me.level()
|
||||
a(href="/user/#{me.getSlugOrID()}")
|
||||
div.img-circle(style="background-image: url(#{me.getPhotoURL()})")
|
||||
h3=me.displayName()
|
||||
li
|
||||
a(href="/user/#{me.getSlugOrID()}" data-i18n="nav.profile")
|
||||
li
|
||||
a(href="/account/settings", data-i18n="play.settings")
|
||||
li
|
||||
a(href="/account/payments", data-i18n="account.payments")
|
||||
li
|
||||
a(href="/account/subscription", data-i18n="account.subscription")
|
||||
li
|
||||
a#logout-button(data-i18n="login.log_out")
|
||||
|
||||
else
|
||||
button.btn.btn-sm.btn-primary.header-font.signup-button(data-i18n="login.sign_up")
|
||||
button.btn.btn-sm.btn-default.header-font.login-button(data-i18n="login.log_in")
|
||||
select.language-dropdown.form-control
|
||||
|
||||
|
||||
block outer_content
|
||||
|
|
|
@ -5,7 +5,6 @@ block content
|
|||
//- DO NOT localize / i18n
|
||||
|
||||
div TODO: fix ugly tabs
|
||||
div TODO: not enrolled yet
|
||||
div
|
||||
span *UNDER CONSTRUCTION, send feedback to
|
||||
a.spl(href='mailto:team@codecombat.com') team@codecombat.com
|
||||
|
@ -14,169 +13,183 @@ block content
|
|||
span.spl Student view
|
||||
div(style='border-bottom: 1px solid black;')
|
||||
|
||||
.modal#editNameModal
|
||||
.modal#editSettingsModal
|
||||
.modal-dialog
|
||||
.modal-header
|
||||
button.close(data-dismiss='modal')
|
||||
span ×
|
||||
h3.modal-title Edit Class Name
|
||||
h3.modal-title Edit Class Settings
|
||||
.modal-body
|
||||
p This title will be displayed to everyone enrolled in this class.
|
||||
input.edit-name-input(type='text', value="#{instance.name}")
|
||||
p This title will be displayed to everyone in the class.
|
||||
p
|
||||
input.edit-name-input(type='text', value="#{instance.name}")
|
||||
p This description will be displayed to everyone in the class.
|
||||
p
|
||||
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
|
||||
button.btn.edit-name-save-btn(data-i18n="common.save_changes")
|
||||
button.btn.btn-save-settings(data-i18n="common.save_changes")
|
||||
|
||||
.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
|
||||
.modal-footer
|
||||
button.btn.edit-description-save-btn(data-i18n="common.save_changes")
|
||||
|
||||
h1= course.title
|
||||
p= course.description
|
||||
|
||||
h3= instance.name
|
||||
if !studentMode
|
||||
span.spl
|
||||
button.btn.btn-xs.edit-class-name-btn(data-toggle='modal', data-target='#editNameModal') edit class name
|
||||
h1= instance.name
|
||||
small.spl (#{course.title})
|
||||
|
||||
p
|
||||
if instance.description
|
||||
each line in instance.description.split('\n')
|
||||
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
|
||||
.form-group
|
||||
span.spr Select language
|
||||
select.form-control.select-language
|
||||
option(value="Python") Python
|
||||
option(value="JavaScript") JavaScript
|
||||
option(value="All Languages") All Languages
|
||||
p
|
||||
button.btn.btn-xs.btn-edit-settings(data-toggle='modal', data-target='#editSettingsModal') edit class settings
|
||||
|
||||
div(role='tabpanel')
|
||||
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')
|
||||
a(href='#progress', aria-controls='progress', role='tab', data-toggle='tab') Class
|
||||
li(role='presentation')
|
||||
a(href='#invite', aria-controls='invite', role='tab', data-toggle='tab') Add Students
|
||||
li(role='presentation')
|
||||
a(href='#levels', aria-controls='levels', role='tab', data-toggle='tab') Levels
|
||||
li(role='presentation')
|
||||
a(href='#levels', aria-controls='levels', role='tab', data-toggle='tab') Levels
|
||||
|
||||
.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')
|
||||
if instance.students
|
||||
h3 Summary
|
||||
- var averagePlaytime = Math.round(Math.random() * 30) + 30
|
||||
p
|
||||
strong(style='font-size:12pt;') Average Play Time
|
||||
p #{averagePlaytime} minutes
|
||||
p
|
||||
strong(style='font-size:12pt;') Concepts Covered
|
||||
table.table.table-condensed
|
||||
+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
|
||||
.container-fluid.summary-container
|
||||
.row
|
||||
.col-md-6
|
||||
h3 Statistics
|
||||
table.statistics-container
|
||||
tr
|
||||
td Total students:
|
||||
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
|
||||
- var conceptCompletion = Math.round(parseFloat(conceptsCompleted[concept]) / instance.students.length * 100)
|
||||
if isNaN(conceptCompletion)
|
||||
- conceptCompletion = 0
|
||||
tr
|
||||
td.concept-completion-container
|
||||
span.concept-summary(style="width:#{conceptCompletion}%;")
|
||||
span.concept-completed-foreground(data-i18n="concepts." + concept)
|
||||
span.spl - #{conceptCompletion}%
|
||||
span.concept-completion-background(style="width:#{conceptCompletion}%;")
|
||||
h3 Students
|
||||
table.table.table-condensed
|
||||
thead
|
||||
tr
|
||||
th
|
||||
span.member-header.spr Name
|
||||
if memberSort === 'nameAsc'
|
||||
span.member-header.glyphicon.glyphicon-chevron-up
|
||||
else if memberSort === 'nameDesc'
|
||||
span.member-header.glyphicon.glyphicon-chevron-down
|
||||
th
|
||||
span.progress-header.spr Progress
|
||||
if memberSort === 'progressAsc'
|
||||
span.progress-header.glyphicon.glyphicon-chevron-up
|
||||
else if memberSort === 'progressDesc'
|
||||
span.progress-header.glyphicon.glyphicon-chevron-down
|
||||
else
|
||||
span(style='padding-left:16px;')
|
||||
span.progress-key.progress-key-complete complete
|
||||
span.progress-key.progress-key-started started
|
||||
span.progress-key not started
|
||||
if maxLastStartedIndex > 30
|
||||
input.expand-progress-checkbox(type='checkbox')
|
||||
span.spl.expand-progress-label(data-i18n="clans.exp_levels") Expand levels
|
||||
tbody
|
||||
each student in instance.students
|
||||
tr
|
||||
td
|
||||
a= student
|
||||
td.progress-cell
|
||||
.level-progression-concepts Concepts
|
||||
each concept in courseConcepts
|
||||
if userConceptsMap[student] && userConceptsMap[student][concept] === 'complete'
|
||||
span.spr.progress-concept-cell.progress-concept-cell-complete(data-i18n="concepts." + concept)
|
||||
else if userConceptsMap[student] && userConceptsMap[student][concept] === 'started'
|
||||
span.spr.progress-concept-cell.progress-concept-cell-started(data-i18n="concepts." + concept)
|
||||
else
|
||||
span.spr.progress-concept-cell.progress-concept-cell-not-started(data-i18n="concepts." + concept)
|
||||
|
||||
.level-progression-levels Levels
|
||||
- var i = 0
|
||||
each level in course.levels
|
||||
if userLevelStateMap[student][level] === 'complete'
|
||||
span.progress-level-cell.progress-level-cell-complete #{i + 1}
|
||||
if showExpandedProgress || i === 0 || i === course.levels.length - 1
|
||||
span.spl #{level}
|
||||
.level-popup-container
|
||||
h3 #{i + 1}. #{level}
|
||||
p
|
||||
div
|
||||
- var playTime = Math.round(Math.random() * 600)
|
||||
span Time to solve
|
||||
span : #{playTime} seconds
|
||||
div
|
||||
- var completionDate = new Date()
|
||||
- completionDate.setUTCDate(completionDate.getUTCDate() - Math.round(Math.random() * 60))
|
||||
span Completed on
|
||||
span : #{moment(completionDate).format('MMMM Do YYYY, h:mm:ss a')}
|
||||
strong(data-i18n="clans.view_solution") Click to view solution.
|
||||
else if userLevelStateMap[student][level] === 'started'
|
||||
span.progress-level-cell.progress-level-cell-started #{i + 1} #{level}
|
||||
else
|
||||
span.progress-level-cell.level-progression-level-not-started #{i + 1}
|
||||
if showExpandedProgress || i === 0
|
||||
span.spl #{level}
|
||||
- i++
|
||||
h3 Students
|
||||
table.table.table-condensed
|
||||
thead
|
||||
tr
|
||||
th
|
||||
span.member-header.spr Name
|
||||
if memberSort === 'nameAsc'
|
||||
span.member-header.glyphicon.glyphicon-chevron-up
|
||||
else if memberSort === 'nameDesc'
|
||||
span.member-header.glyphicon.glyphicon-chevron-down
|
||||
th
|
||||
span.progress-header.spr Progress
|
||||
if memberSort === 'progressAsc'
|
||||
span.progress-header.glyphicon.glyphicon-chevron-up
|
||||
else if memberSort === 'progressDesc'
|
||||
span.progress-header.glyphicon.glyphicon-chevron-down
|
||||
else
|
||||
span(style='padding-left:16px;')
|
||||
span.progress-key.progress-key-complete complete
|
||||
span.progress-key.progress-key-started started
|
||||
span.progress-key not started
|
||||
if maxLastStartedIndex > 30
|
||||
input.expand-progress-checkbox(type='checkbox')
|
||||
span.spl.expand-progress-label(data-i18n="clans.exp_levels") Expand levels
|
||||
tbody
|
||||
each student in instance.students
|
||||
tr
|
||||
td
|
||||
a= student
|
||||
td.progress-cell
|
||||
.level-progression-concepts Concepts
|
||||
each concept in courseConcepts
|
||||
if userConceptsMap[student] && userConceptsMap[student][concept] === 'complete'
|
||||
span.spr.progress-concept-cell.progress-concept-cell-complete(data-i18n="concepts." + concept)
|
||||
else if userConceptsMap[student] && userConceptsMap[student][concept] === 'started'
|
||||
span.spr.progress-concept-cell.progress-concept-cell-started(data-i18n="concepts." + concept)
|
||||
else
|
||||
span.spr.progress-concept-cell.progress-concept-cell-not-started(data-i18n="concepts." + concept)
|
||||
|
||||
.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
|
||||
.level-progression-levels Levels
|
||||
- var i = 0
|
||||
each level in course.levels
|
||||
if userLevelStateMap[student][level] === 'complete'
|
||||
span.progress-level-cell.progress-level-cell-complete #{i + 1}
|
||||
if showExpandedProgress || i === 0 || i === course.levels.length - 1
|
||||
span.spl #{level}
|
||||
.level-popup-container
|
||||
h3 #{i + 1}. #{level}
|
||||
p
|
||||
div
|
||||
- var playTime = Math.round(Math.random() * 600)
|
||||
span Time to solve
|
||||
span : #{playTime} seconds
|
||||
div
|
||||
- var completionDate = new Date()
|
||||
- completionDate.setUTCDate(completionDate.getUTCDate() - Math.round(Math.random() * 60))
|
||||
span Completed on
|
||||
span : #{moment(completionDate).format('MMMM Do YYYY, h:mm:ss a')}
|
||||
strong(data-i18n="clans.view_solution") Click to view solution.
|
||||
else if userLevelStateMap[student][level] === 'started'
|
||||
span.progress-level-cell.progress-level-cell-started #{i + 1} #{level}
|
||||
else
|
||||
span.progress-level-cell.level-progression-level-not-started #{i + 1}
|
||||
if showExpandedProgress || i === 0
|
||||
span.spl #{level}
|
||||
- i++
|
||||
|
||||
mixin levels-tab
|
||||
table.table.table-striped.table-condensed
|
||||
|
|
|
@ -29,7 +29,7 @@ block content
|
|||
each inst in instances
|
||||
option= inst.name
|
||||
.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
|
||||
.col-md-12
|
||||
div.or Or
|
||||
|
@ -43,39 +43,34 @@ block content
|
|||
.col-md-8
|
||||
input.code-input(type='text', placeholder="Enter unlock code")
|
||||
.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
|
||||
.col-md-12
|
||||
div.or Or
|
||||
.row.button-row.center
|
||||
.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
|
||||
//- p.center.gameplay-img-container
|
||||
//- 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.
|
||||
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-12
|
||||
p.center
|
||||
button.btn.btn-success.btn-lg.btn-buy Enroll Now!
|
||||
.row
|
||||
.col-md-6
|
||||
div With CodeCombat courses, you and your students will:
|
||||
ul
|
||||
li Learn more in less time
|
||||
li With no experience necesssary
|
||||
li Monitor student progress
|
||||
br
|
||||
li No coding experience necesssary
|
||||
li Easily monitor student progress
|
||||
|
||||
div Purchase a course for your entire class. It's easy to sign up your students!
|
||||
.col-md-6
|
||||
p
|
||||
.well.well-sm
|
||||
div.praise-quote "#{praise.quote}"
|
||||
div.caption-text - #{praise.source}
|
||||
|
||||
//- h2.center Available Courses
|
||||
h2.center Choose Your Course:
|
||||
|
||||
.container-fluid
|
||||
- var i = 0
|
||||
|
@ -95,13 +90,13 @@ mixin course-block(course, courseID)
|
|||
span.spr #{course.title}
|
||||
strong #{course.unlocked ? '[ enrolled ]' : ''}
|
||||
.panel-body
|
||||
strong Topics
|
||||
ul
|
||||
each topic in course.topics
|
||||
li= topic
|
||||
strong Hours of content: #{course.duration}
|
||||
.container-fluid
|
||||
.row.button-row.center
|
||||
.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'}
|
||||
.row.button-row
|
||||
.col-md-6
|
||||
strong Topics
|
||||
ul
|
||||
each topic in course.topics
|
||||
li= topic
|
||||
strong Hours of content: #{course.duration}
|
||||
.col-md-6.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'}
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
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
|
||||
#spacer
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ else
|
|||
|
||||
.game-controls.header-font
|
||||
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.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")
|
||||
|
@ -118,9 +119,6 @@ else
|
|||
button#logout-button.btn.btn-illustrated.btn-warning(data-i18n="login.log_out") Log Out
|
||||
if me.isPremium()
|
||||
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")
|
||||
.glyphicon.glyphicon-volume-off
|
||||
|
|
|
@ -10,11 +10,9 @@ module.exports = class CourseDetailsView extends RootView
|
|||
|
||||
events:
|
||||
'change .expand-progress-checkbox': 'onExpandedProgressCheckbox'
|
||||
'change .select-session': 'onChangeSession'
|
||||
'change .student-mode-checkbox': 'onChangeStudent'
|
||||
'click .btn-play-level': 'onClickPlayLevel'
|
||||
'click .edit-description-save-btn': 'onEditDescriptionSave'
|
||||
'click .edit-name-save-btn': 'onEditNameSave'
|
||||
'click .btn-save-settings': 'onClickSaveSettings'
|
||||
'click .member-header': 'onClickMemberHeader'
|
||||
'click .progress-header': 'onClickProgressHeader'
|
||||
'mouseenter .progress-level-cell': 'onMouseEnterPoint'
|
||||
|
@ -49,6 +47,14 @@ module.exports = class CourseDetailsView extends RootView
|
|||
conceptsCompleted[concept]++
|
||||
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
|
||||
|
||||
initData: ->
|
||||
|
@ -144,26 +150,12 @@ module.exports = class CourseDetailsView extends RootView
|
|||
@render?()
|
||||
$('.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) ->
|
||||
@showExpandedProgress = $('.expand-progress-checkbox').prop('checked')
|
||||
# TODO: why does render reset the checkbox to be unchecked?
|
||||
@render?()
|
||||
$('.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) ->
|
||||
@memberSort = if @memberSort is 'nameAsc' then 'nameDesc' else 'nameAsc'
|
||||
@sortMembers()
|
||||
|
@ -183,16 +175,12 @@ module.exports = class CourseDetailsView extends RootView
|
|||
viewArgs: [{}, levelSlug]
|
||||
}
|
||||
|
||||
onEditDescriptionSave: (e) ->
|
||||
description = $('.edit-description-input').val()
|
||||
@instances[@currentInstanceIndex].description = description
|
||||
$('#editDescriptionModal').modal('hide')
|
||||
@render?()
|
||||
|
||||
onEditNameSave: (e) ->
|
||||
onClickSaveSettings: (e) ->
|
||||
if name = $('.edit-name-input').val()
|
||||
@instances[@currentInstanceIndex].name = name
|
||||
$('#editNameModal').modal('hide')
|
||||
description = $('.edit-description-input').val()
|
||||
@instances[@currentInstanceIndex].description = description
|
||||
$('#editSettingsModal').modal('hide')
|
||||
@render?()
|
||||
|
||||
onMouseEnterPoint: (e) ->
|
||||
|
|
|
@ -40,7 +40,7 @@ data.courses = [
|
|||
image: '/images/pages/courses/102_info.png'
|
||||
},
|
||||
{
|
||||
title: 'CS Course 3'
|
||||
title: 'Computer Science 3'
|
||||
description: 'Learn how to handle input.'
|
||||
topics: ['If Statements', 'Arithmetic', 'Input Handling']
|
||||
duration: 5
|
||||
|
@ -48,7 +48,7 @@ data.courses = [
|
|||
image: '/images/pages/courses/103_info.png'
|
||||
},
|
||||
{
|
||||
title: 'CS 4'
|
||||
title: 'Computer Science 4'
|
||||
description: 'Time to tackle arrays and some pvp stuff.'
|
||||
topics: ['Loops', 'Break Statements', 'Arrays']
|
||||
duration: 5
|
||||
|
@ -56,7 +56,7 @@ data.courses = [
|
|||
image: '/images/pages/courses/104_info.png'
|
||||
},
|
||||
{
|
||||
title: 'Course 5'
|
||||
title: 'Computer Science 5'
|
||||
description: 'Time to tackle arrays and some PVP.'
|
||||
topics: ['Break Statements', 'Arrays', 'Object Literals']
|
||||
duration: 5
|
||||
|
@ -64,7 +64,7 @@ data.courses = [
|
|||
image: '/images/pages/courses/105_info.png'
|
||||
},
|
||||
{
|
||||
title: 'Course 6'
|
||||
title: 'Computer Science 6'
|
||||
description: 'For loops!'
|
||||
topics: ['Break Statements', 'Object Literals', 'For loops']
|
||||
duration: 5
|
||||
|
@ -72,7 +72,7 @@ data.courses = [
|
|||
image: '/images/pages/courses/106_info.png'
|
||||
},
|
||||
{
|
||||
title: 'Course 7'
|
||||
title: 'Computer Science 7'
|
||||
description: 'Functions!'
|
||||
topics: ['Object Literals', 'For loops', 'Functions']
|
||||
duration: 5
|
||||
|
@ -80,7 +80,7 @@ data.courses = [
|
|||
image: '/images/pages/courses/107_info.png'
|
||||
},
|
||||
{
|
||||
title: 'CS 108'
|
||||
title: 'Computer Science 8'
|
||||
description: 'Maths.'
|
||||
topics: ['For loops', 'Functions', 'Math Operations']
|
||||
duration: 5
|
||||
|
@ -88,7 +88,7 @@ data.courses = [
|
|||
image: '/images/pages/courses/107_info.png'
|
||||
},
|
||||
{
|
||||
title: 'Computer Science 109'
|
||||
title: 'Computer Science 9'
|
||||
description: 'Vectors and strings.'
|
||||
topics: ['Vectors', 'Advanced Strings']
|
||||
duration: 5
|
||||
|
|
|
@ -51,6 +51,10 @@ module.exports = class CoursesView extends RootView
|
|||
$('#continueModal').find('.btn-enroll').data('course-id', courseID)
|
||||
$('#continueModal').find('.btn-enter').data('course-id', courseID)
|
||||
$('#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) ->
|
||||
$('#continueModal').modal('hide')
|
||||
|
@ -65,7 +69,8 @@ module.exports = class CoursesView extends RootView
|
|||
$('#continueModal').modal('hide')
|
||||
courseID = $(e.target).data('course-id')
|
||||
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'
|
||||
viewArgs = [{}, courseID, instanceID]
|
||||
navigationEvent = route: "/courses/mock1/#{courseID}", viewClass: viewClass, viewArgs: viewArgs
|
||||
|
|
|
@ -30,7 +30,7 @@ class LevelSessionsCollection extends CocoCollection
|
|||
|
||||
constructor: (model) ->
|
||||
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
|
||||
url: '/db/campaign'
|
||||
|
@ -261,6 +261,7 @@ module.exports = class CampaignView extends RootView
|
|||
annotateLevel: (level) ->
|
||||
level.position ?= { x: 10, y: 10 }
|
||||
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 @editorMode
|
||||
level.locked = false if @campaign?.get('name') is 'Auditions'
|
||||
|
@ -302,12 +303,22 @@ module.exports = class CampaignView extends RootView
|
|||
|
||||
determineNextLevel: (levels) ->
|
||||
foundNext = false
|
||||
dontPointTo = ['lost-viking', 'kithgard-mastery'] # Challenge levels we don't want most players bashing heads against
|
||||
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)
|
||||
unless foundNext
|
||||
for nextLevelOriginal in level.nextLevels
|
||||
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 (
|
||||
me.isPremium() 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'
|
||||
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) ->
|
||||
p1 = x: o1.x, y: 0.66 * o1.y + 0.5
|
||||
p2 = x: o2.x, y: 0.66 * o2.y + 0.5
|
||||
|
|
|
@ -141,7 +141,8 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
getRenderData: ->
|
||||
c = super()
|
||||
c.levelName = utils.i18n @level.attributes, 'name'
|
||||
c.victoryText = utils.i18n @level.get('victory') ? {}, 'body'
|
||||
if @level.get('type', true) isnt 'hero'
|
||||
c.victoryText = utils.i18n @level.get('victory') ? {}, 'body'
|
||||
earnedAchievementMap = _.indexBy(@newEarnedAchievements or [], (ea) -> ea.get('achievement'))
|
||||
for achievement in (@achievements?.models or [])
|
||||
earnedAchievement = earnedAchievementMap[achievement.id]
|
||||
|
|
|
@ -73,7 +73,7 @@ module.exports = class PollModal extends ModalView
|
|||
onClickAnswer: (e) ->
|
||||
$selectedAnswer = $(e.target).closest('.answer')
|
||||
pollVotes = @userPollsRecord.get('polls') ? {}
|
||||
pollVotes[@poll.id] = $selectedAnswer.data('answer')
|
||||
pollVotes[@poll.id] = $selectedAnswer.data('answer').toString()
|
||||
@userPollsRecord.set 'polls', pollVotes
|
||||
@updateAnswers true
|
||||
@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 scriptStartTime = new Date();
|
||||
var startDay = '2015-05-10';
|
||||
var endDay = '2015-06-11';
|
||||
var startDay = '2015-07-01';
|
||||
var endDay = '2015-08-06';
|
||||
|
||||
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