Merge branch 'master' into production

This commit is contained in:
Nick Winter 2014-10-26 15:31:52 -07:00
commit c279fa65cb
12 changed files with 209 additions and 81 deletions

View file

@ -297,8 +297,10 @@
programming_language_description: "Which programming language do you want to use?" programming_language_description: "Which programming language do you want to use?"
status: "Status" status: "Status"
weapons: "Weapons" weapons: "Weapons"
attack: "Damage" # Can also translate as "Attack"
health: "Health" health: "Health"
speed: "Speed" speed: "Speed"
skills: "Skills"
save_load: save_load:
granularity_saved_games: "Saved" granularity_saved_games: "Saved"

View file

@ -203,12 +203,12 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
victory_rate_the_level: "Classifica este nível: " # Only in old-style levels. victory_rate_the_level: "Classifica este nível: " # Only in old-style levels.
victory_return_to_ladder: "Voltar à Classificação" victory_return_to_ladder: "Voltar à Classificação"
victory_play_continue: "Continuar" victory_play_continue: "Continuar"
# victory_play_skip: "Skip Ahead" victory_play_skip: "Passar à Frente"
victory_play_next_level: "Jogar Próximo Nível" victory_play_next_level: "Jogar Próximo Nível"
# victory_play_more_practice: "More Practice" victory_play_more_practice: "Mais Treino"
# victory_play_too_easy: "Too Easy" victory_play_too_easy: "Muito Fácil"
# victory_play_just_right: "Just Right" victory_play_just_right: "Perfeito"
# victory_play_too_hard: "Too Hard" victory_play_too_hard: "Muito Difícil"
victory_saving_progress: "A Guardar o Progresso" victory_saving_progress: "A Guardar o Progresso"
victory_go_home: "Ir para o Início" # Only in old-style levels. victory_go_home: "Ir para o Início" # Only in old-style levels.
victory_review: "Conta-nos mais!" # Only in old-style levels. victory_review: "Conta-nos mais!" # Only in old-style levels.
@ -1052,10 +1052,10 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
av_entities_active_instances_url: "Activar Instâncias" av_entities_active_instances_url: "Activar Instâncias"
av_entities_employer_list_url: "Lista de Empregadores" av_entities_employer_list_url: "Lista de Empregadores"
av_entities_candidates_list_url: "Lista de Candidatos" av_entities_candidates_list_url: "Lista de Candidatos"
# av_entities_user_code_problems_list_url: "User Code Problems List" av_entities_user_code_problems_list_url: "Lista de Problemas no Código do Jogador"
av_other_sub_title: "Outro" av_other_sub_title: "Outro"
av_other_debug_base_url: "Base (para depurar base.jade)" av_other_debug_base_url: "Base (para depurar base.jade)"
u_title: "Lista de Utilizadores" u_title: "Lista de Utilizadores"
# ucp_title: "User Code Problems" ucp_title: "Problemas no Código do Jogador"
lg_title: "Últimos Jogos" lg_title: "Últimos Jogos"
clas: "CLA's" clas: "CLA's"

View file

@ -79,7 +79,27 @@ $heroCanvasHeight: 265px
.hero-stats .hero-stats
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.6) text-shadow: 0 1px 1px rgba(255, 255, 255, 0.6)
font-size: 24px
.hero-class, .hero-status, .hero-skills
font-size: 14px
.hero-stat
margin: 10px 0
.progress
width: 90%
text-align: center
height: 26px
position: relative
margin: 0
.hero-stat-label
position: absolute
width: 100%
font-size: 18px
text-transform: uppercase
color: white
text-shadow: 0px 1px 0px black, 0px -1px 0px black, -1px 0px 0px black, 1px 0px 0px black
.carousel-control.left .carousel-control.left
border-top-left-radius: 10px border-top-left-radius: 10px

View file

@ -4,30 +4,33 @@ block content
h1(data-i18n="admin.ucp_title") User Code Problems h1(data-i18n="admin.ucp_title") User Code Problems
table.table.table-striped.table-bordered.table-condensed#users if fetchingData
thead(style='font-weight:bold') h3 Fetching data...
tr else
td language table.table.table-striped.table-bordered.table-condensed#users
//- td errType thead(style='font-weight:bold')
//- td errLevel tr
//- td errId td language
td levelID //- td errType
td codeSnippet //- td errLevel
td errHint //- td errId
td errMessage td levelID
//- td code td codeSnippet
td created td errHint
td errMessage
tbody //- td code
each problem in userCodeProblems td created
tr
td #{problem.language} tbody
//- td #{problem.errType} each problem in userCodeProblems
//- td #{problem.errLevel} tr
//- td #{problem.errId} td #{problem.language}
td #{problem.levelID} //- td #{problem.errType}
td #{problem.codeSnippet} //- td #{problem.errLevel}
td #{problem.errHint} //- td #{problem.errId}
td #{problem.errMessage} td #{problem.levelID}
//- td #{problem.code} td #{problem.codeSnippet}
td #{new Date(problem.created).toLocaleString()} td #{problem.errHint}
td #{problem.errMessage}
//- td #{problem.code}
td #{new Date(problem.created).toLocaleString()}

View file

@ -16,25 +16,40 @@
img img
.hero-stats .hero-stats
h2= info.fullName h2= info.fullName
p //.hero-description= info.description // Not until we have written the descriptions.
.hero-status
span(data-i18n="choose_hero.status") Status span(data-i18n="choose_hero.status") Status
span.spr : span.spr :
if hero.locked if hero.locked
| #{info.status} | #{info.status}
else else
| Available | Available
p .hero-class
span(data-i18n="choose_hero.weapons") Weapons span(data-i18n="choose_hero.weapons") Weapons
span.spr : span.spr :
| #{info.weapons} | #{info.weapons}
p for statInfo in [{name: 'attack', color: 'danger'}, {name: 'health', color: 'info'}, {name: 'speed', color: 'success'}]
span(data-i18n="choose_hero.health") Health - var tooltip = "";
span.spr : - if (statInfo.name == 'attack')
| #{info.health} - tooltip = Math.round(100 * info[statInfo.name + 'Factor']) + '% ' + info.class.toLowerCase() + ' weapon damage';
p - else if (statInfo.name == 'health')
span(data-i18n="choose_hero.speed") Speed - tooltip = Math.round(100 * info[statInfo.name + 'Factor']) + '% ' + info.class.toLowerCase() + ' armor health';
span.spr : - else if (statInfo.name == 'speed')
| #{info.speed} - tooltip = info.speedAbsolute + ' meters per second';
.hero-stat(title=tooltip)
.progress
div(class="progress-bar progress-bar-" + statInfo.color, style="width: " + (10 * info[statInfo.name]) + "%")
.hero-stat-label
span(data-i18n="choose_hero." + statInfo.name)
span.spr :
| #{info[statInfo.name]}
if info.skills
.hero-skills
span(data-i18n="choose_hero.skills") Skills
span.spr :
for skill in info.skills
code.spl.spr= skill
a.carousel-control.left(role="button", data-slide="prev", href="#hero-carousel") a.carousel-control.left(role="button", data-slide="prev", href="#hero-carousel")
span.glyphicon.glyphicon-chevron-left span.glyphicon.glyphicon-chevron-left
a.carousel-control.right(role="button", data-slide="next", href="#hero-carousel") a.carousel-control.right(role="button", data-slide="next", href="#hero-carousel")

View file

@ -10,6 +10,7 @@ module.exports = class UserCodeProblemsView extends RootView
constructor: (options) -> constructor: (options) ->
super options super options
@fetchingData = true
@getUserCodeProblems() @getUserCodeProblems()
getUserCodeProblems: -> getUserCodeProblems: ->
@ -19,9 +20,18 @@ module.exports = class UserCodeProblemsView extends RootView
# The first arg is the function name # The first arg is the function name
# The rest are the args for the function # The rest are the args for the function
lastMonth = new Date()
if lastMonth.getMonth() is 1
lastMonth.setMonth 12
lastMonth.setYear lastMonth.getYear() - 1
else
lastMonth.setMonth lastMonth.getMonth() - 1
conditions = [ conditions = [
['limit', 1000] ['limit', 1000]
['sort', '-created'] ['sort', '-created']
['where', 'created']
['gte', lastMonth.toString()]
] ]
conditions = $.param({conditions:JSON.stringify(conditions)}) conditions = $.param({conditions:JSON.stringify(conditions)})
UserCodeProblemCollection = Backbone.Collection.extend({ UserCodeProblemCollection = Backbone.Collection.extend({
@ -30,9 +40,12 @@ module.exports = class UserCodeProblemsView extends RootView
}) })
@userCodeProblems = new UserCodeProblemCollection() @userCodeProblems = new UserCodeProblemCollection()
@userCodeProblems.fetch() @userCodeProblems.fetch()
@listenTo(@userCodeProblems, 'all', @render) @listenTo @userCodeProblems, 'all', ->
@fetchingData = false
@render()
getRenderData: -> getRenderData: ->
c = super() c = super()
c.fetchingData = @fetchingData
c.userCodeProblems = (problem.attributes for problem in @userCodeProblems.models) c.userCodeProblems = (problem.attributes for problem in @userCodeProblems.models)
c c

View file

@ -65,6 +65,7 @@ module.exports = class ChooseHeroView extends CocoView
heroIndex = Math.max 0, _.findIndex(heroes, ((hero) -> hero.get('original') is heroConfig.thangType)) heroIndex = Math.max 0, _.findIndex(heroes, ((hero) -> hero.get('original') is heroConfig.thangType))
@$el.find(".hero-item:nth-child(#{heroIndex + 1}), .hero-indicator:nth-child(#{heroIndex + 1})").addClass('active') @$el.find(".hero-item:nth-child(#{heroIndex + 1}), .hero-indicator:nth-child(#{heroIndex + 1})").addClass('active')
@onHeroChanged direction: null, relatedTarget: @$el.find('.hero-item')[heroIndex] @onHeroChanged direction: null, relatedTarget: @$el.find('.hero-item')[heroIndex]
@$el.find('.hero-stat').tooltip()
onHeroChanged: (e) -> onHeroChanged: (e) ->
direction = e.direction # 'left' or 'right' direction = e.direction # 'left' or 'right'
@ -161,65 +162,125 @@ module.exports = class ChooseHeroView extends CocoView
temporaryHeroInfo = temporaryHeroInfo =
captain:
fullName: 'Captain Anya Weston'
weapons: 'Razor Discs'
status: 'Available'
health: '35'
speed: '4 m/s'
knight: knight:
fullName: 'Tharin Thunderfist' fullName: 'Tharin Thunderfist'
weapons: 'Swords' weapons: 'Swords - Short Range, No Magic'
class: 'Warrior'
description: 'Beefcake! Beefcaaake!'
status: 'Available' status: 'Available'
health: '35' attack: 8
speed: '4 m/s' attackFactor: 1.2
health: 8.5
healthFactor: 1.4
speed: 1.5
speedAbsolute: 6
captain:
fullName: 'Captain Anya Weston'
weapons: 'Swords - Short Range, No Magic'
class: 'Warrior'
description: 'Don\'t bother me, I\'m winning this fight for you.'
status: 'Available'
attack: 8
attackFactor: 1.2
health: 8.5
healthFactor: 1.4
speed: 1.5
speedAbsolute: 6
thoktar: thoktar:
fullName: 'Thoktar the Devourer' fullName: 'Thoktar the Devourer'
weapons: 'Magic' weapons: 'Wands, Staffs - Long Range, Magic'
class: 'Wizard'
description: '???'
status: 'Locked' status: 'Locked'
health: '???' attack: 5
speed: '???' attackFactor: 2
health: 4.5
healthFactor: 1.4
speed: 2.5
speedAbsolute: 7
skills: ['summonElemental', 'devour']
equestrian: equestrian:
fullName: 'Rider Reynaldo' fullName: 'Rider Reynaldo'
weapons: 'Axes' weapons: 'Crossbows, Guns - Long Range, No Magic'
class: 'Ranger'
description: '???'
status: 'Locked' status: 'Locked'
health: '???' attack: 6
speed: '???' attackFactor: 1.4
health: 7
healthFactor: 1.8
speed: 1.5
speedAbsolute: 6
skills: ['hide']
'potion-master': 'potion-master':
fullName: 'Master Snake' fullName: 'Master Snake'
weapons: 'Magic' weapons: 'Wands, Staffs - Long Range, Magic'
class: 'Wizard'
description: '???'
status: 'Locked' status: 'Locked'
health: '???' attack: 2
speed: '???' attackFactor: 0.833
health: 4
healthFactor: 1.2
speed: 6
speedAbsolute: 11
skills: ['brewPotion']
librarian: librarian:
fullName: 'Hushbaum' fullName: 'Hushbaum'
weapons: 'Magic' weapons: 'Wands, Staffs - Long Range, Magic'
class: 'Wizard'
description: '???'
status: 'Locked' status: 'Locked'
health: '???' attack: 3
speed: '???' attackFactor: 1.2
health: 4.5
healthFactor: 1.4
speed: 2.5
speedAbsolute: 7
'robot-walker': 'robot-walker':
fullName: '???' fullName: '???'
weapons: '???' weapons: '???'
class: 'Ranger'
description: '???'
status: 'Locked' status: 'Locked'
health: '???' attack: 6.5
speed: '???' attackFactor: 1.6
health: 5.5
healthFactor: 1.2
speed: 6
speedAbsolute: 11
skills: ['???', '???', '???']
'michael-heasell': 'michael-heasell':
fullName: '???' fullName: '???'
weapons: '???' weapons: '???'
class: 'Ranger'
description: '???'
status: 'Locked' status: 'Locked'
health: '???' attack: 4
speed: '???' attackFactor: 0.714
health: 5
healthFactor: 1
speed: 10
speedAbsolute: 16
skills: ['???', '???']
'ian-elliott': 'ian-elliott':
fullName: '???' fullName: '???'
weapons: '???' weapons: 'Swords - Short Range, No Magic'
class: 'Warrior'
description: '???'
status: 'Locked' status: 'Locked'
health: '???' attack: 9.5
speed: '???' attackFactor: 1.8
health: 6.5
healthFactor: 0.714
speed: 3.5
speedAbsolute: 8
skills: ['trueStrike']

View file

@ -337,7 +337,7 @@ module.exports = class InventoryView extends CocoView
'closing-the-distance': {feet: 'simple-boots', 'right-hand': 'longsword', torso: 'leather-tunic', eyes: 'crude-glasses'} 'closing-the-distance': {feet: 'simple-boots', 'right-hand': 'longsword', torso: 'leather-tunic', eyes: 'crude-glasses'}
'the-final-kithmaze': {feet: 'simple-boots', 'right-hand': 'longsword', torso: 'leather-tunic', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses'} 'the-final-kithmaze': {feet: 'simple-boots', 'right-hand': 'longsword', torso: 'leather-tunic', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses'}
'kithgard-gates': {feet: 'simple-boots', 'right-hand': 'builders-hammer'} 'kithgard-gates': {feet: 'simple-boots', 'right-hand': 'builders-hammer'}
'defence-of-plainswood': {feet: 'simple-boots', 'right-hand': 'builders-hammer'} 'defense-of-plainswood': {feet: 'simple-boots', 'right-hand': 'builders-hammer'}
# TODO: figure out leather boots for plainswood (or next one?) # TODO: figure out leather boots for plainswood (or next one?)
return unless necessaryGear = gearByLevel[@options.levelID] return unless necessaryGear = gearByLevel[@options.levelID]
if @inserted if @inserted

View file

@ -864,13 +864,13 @@ hero = [
x: 89 x: 89
y: 82 y: 82
nextLevels: nextLevels:
continue: 'defence-of-plainswood' continue: 'defense-of-plainswood'
} }
{ {
name: 'Defence of Plainswood' name: 'Defense of Plainswood'
type: 'hero' type: 'hero'
difficulty: 1 difficulty: 1
id: 'defence-of-plainswood' id: 'defense-of-plainswood'
original: '541b67f71ccc8eaae19f3c62' original: '541b67f71ccc8eaae19f3c62'
description: 'Protect the peasants from the pursuing ogres.' description: 'Protect the peasants from the pursuing ogres.'
x: 95.31 x: 95.31

View file

@ -211,7 +211,7 @@ module.exports = class HeroVictoryModal extends ModalView
else if panel.hero else if panel.hero
thangType = @thangTypes[panel.hero] thangType = @thangTypes[panel.hero]
panel.textEl.text(thangType.get('name')) panel.textEl.text(thangType.get('name'))
@playSelectionSound hero if 0.5 < ratio < 0.6 @playSelectionSound thangType if 0.5 < ratio < 0.6
if ratio is 1 if ratio is 1
panel.rootEl.removeClass('animating').find('.reward-image-container img').removeClass('pulse') panel.rootEl.removeClass('animating').find('.reward-image-container img').removeClass('pulse')
@sequentialAnimationStart = new Date() @sequentialAnimationStart = new Date()

View file

@ -5,10 +5,13 @@ startsWith = (string, substring) ->
exports.config = exports.config =
paths: paths:
public: 'public' public: 'public'
watched: ['app', 'vendor', 'test/app', 'test/demo'] watched: ['app', 'vendor', 'test/app', 'test/demo']
conventions: conventions:
ignored: (path) -> startsWith(sysPath.basename(path), '_') ignored: (path) -> startsWith(sysPath.basename(path), '_')
sourceMaps: true sourceMaps: true
overrides:
production:
sourceMaps: true
files: files:
javascripts: javascripts:
defaultExtension: 'coffee' defaultExtension: 'coffee'

View file

@ -27,6 +27,16 @@ productionLogging = (tokens, req, res) ->
return "\x1b[90m#{req.method} #{req.originalUrl} \x1b[#{color}m#{res.statusCode} \x1b[#{elapsedColor}m#{elapsed}ms\x1b[0m" return "\x1b[90m#{req.method} #{req.originalUrl} \x1b[#{color}m#{res.statusCode} \x1b[#{elapsedColor}m#{elapsed}ms\x1b[0m"
null null
developmentLogging = (tokens, req, res) ->
status = res.statusCode
color = 32
if status >= 500 then color = 31
else if status >= 400 then color = 33
else if status >= 300 then color = 36
elapsed = (new Date()) - req._startTime
elapsedColor = if elapsed < 500 then 90 else 31
"\x1b[90m#{req.method} #{req.originalUrl} \x1b[#{color}m#{res.statusCode} \x1b[#{elapsedColor}m#{elapsed}ms\x1b[0m"
setupExpressMiddleware = (app) -> setupExpressMiddleware = (app) ->
if config.isProduction if config.isProduction
express.logger.format('prod', productionLogging) express.logger.format('prod', productionLogging)
@ -35,6 +45,7 @@ setupExpressMiddleware = (app) ->
return false if req.headers.host is 'codecombat.com' # CloudFlare will gzip it for us on codecombat.com # But now it's disabled. return false if req.headers.host is 'codecombat.com' # CloudFlare will gzip it for us on codecombat.com # But now it's disabled.
compressible res.getHeader('Content-Type') compressible res.getHeader('Content-Type')
else else
express.logger.format('dev', developmentLogging)
app.use(express.logger('dev')) app.use(express.logger('dev'))
app.use(express.static(path.join(__dirname, 'public'))) app.use(express.static(path.join(__dirname, 'public')))
app.use(useragent.express()) app.use(useragent.express())