From 9455199b39324f87435b1fd989eed4e82a86ec46 Mon Sep 17 00:00:00 2001 From: Scott Erickson Date: Wed, 15 Oct 2014 16:43:26 -0400 Subject: [PATCH 01/13] Limited social media library loading to only those views that need it. --- app/Router.coffee | 17 ++++++++++++++++- app/initialize.coffee | 12 ++++-------- app/templates/base.jade | 17 +++++++++-------- app/views/kinds/RootView.coffee | 1 + app/views/modal/AuthModal.coffee | 2 +- app/views/play/ladder/LadderView.coffee | 1 + app/views/play/level/modal/VictoryModal.coffee | 1 + app/views/user/JobProfileView.coffee | 1 + 8 files changed, 34 insertions(+), 18 deletions(-) diff --git a/app/Router.coffee b/app/Router.coffee index db12c8258..437e44d9b 100644 --- a/app/Router.coffee +++ b/app/Router.coffee @@ -12,6 +12,7 @@ module.exports = class CocoRouter extends Backbone.Router @bind 'route', @_trackPageView Backbone.Mediator.subscribe 'auth:gplus-api-loaded', @onGPlusAPILoaded, @ Backbone.Mediator.subscribe 'router:navigate', @onNavigate, @ + @initializeSocialMediaServices = _.once @initializeSocialMediaServices routes: '': go('HomeView') # This will go somewhere deprecated when FrontView is done. @@ -125,7 +126,7 @@ module.exports = class CocoRouter extends Backbone.Router $('#page-container').empty().append view.el window.currentView = view @activateTab() - @renderLoginButtons() + @renderLoginButtons() if view.usesSocialMedia view.afterInsert() view.didReappear() @@ -139,8 +140,22 @@ module.exports = class CocoRouter extends Backbone.Router onGPlusAPILoaded: => @renderLoginButtons() + + initializeSocialMediaServices: -> + return if application.testing or application.demoing + services = [ + './lib/services/facebook' + './lib/services/google' + './lib/services/twitter' + './lib/services/linkedin' + ] + + for service in services + service = require service + service() renderLoginButtons: -> + @initializeSocialMediaServices() $('.share-buttons, .partner-badges').addClass('fade-in').delay(10000).removeClass('fade-in', 5000) setTimeout(FB.XFBML.parse, 10) if FB?.XFBML?.parse # Handles FB login and Like twttr?.widgets?.load?() diff --git a/app/initialize.coffee b/app/initialize.coffee index 67cc1b204..db1f2f862 100644 --- a/app/initialize.coffee +++ b/app/initialize.coffee @@ -24,9 +24,9 @@ init = -> watchForErrors() setUpIOSLogging() path = document.location.pathname - testing = path.startsWith '/test' - demoing = path.startsWith '/demo' - initializeServices() unless testing or demoing + app.testing = path.startsWith '/test' + app.demoing = path.startsWith '/demo' + initializeUtilityServices() unless app.testing or app.demoing setUpBackboneMediator() app.initialize() Backbone.history.start({ pushState: true }) @@ -74,15 +74,11 @@ setUpMoment = -> me.on 'change:preferredLanguage', (me) -> moment.lang me.get('preferredLanguage', true), {} -initializeServices = -> +initializeUtilityServices = -> services = [ './lib/services/filepicker' './lib/services/segmentio' './lib/services/olark' - './lib/services/facebook' - './lib/services/google' - './lib/services/twitter' - './lib/services/linkedin' ] for service in services diff --git a/app/templates/base.jade b/app/templates/base.jade index 47fcc4868..9bf6b1350 100644 --- a/app/templates/base.jade +++ b/app/templates/base.jade @@ -75,14 +75,15 @@ body a(href='/teachers', data-i18n="nav.teachers") Teachers if me.isAdmin() a(href='/admin', data-i18n="nav.admin") Admin - - .share-buttons - if !isIE - .g-plusone(data-href="http://codecombat.com", data-size="medium") - .fb-like(data-href="https://www.facebook.com/codecombat", data-send="false", data-layout="button_count", data-width="350", data-show-faces="true", data-ref="coco_footer_#{fbRef}") - if !isIE - a.twitter-follow-button(href="https://twitter.com/CodeCombat", data-show-count="true", data-show-screen-name="false", data-dnt="true", data-align="right", data-i18n="nav.twitter_follow") Follow - iframe.github-star-button(src="http://ghbtns.com/github-btn.html?user=codecombat&repo=codecombat&type=watch&count=true", allowtransparency="true", frameborder="0", scrolling="0", width="110", height="20") + + if usesSocialMedia + .share-buttons + if !isIE + .g-plusone(data-href="http://codecombat.com", data-size="medium") + .fb-like(data-href="https://www.facebook.com/codecombat", data-send="false", data-layout="button_count", data-width="350", data-show-faces="true", data-ref="coco_footer_#{fbRef}") + if !isIE + a.twitter-follow-button(href="https://twitter.com/CodeCombat", data-show-count="true", data-show-screen-name="false", data-dnt="true", data-align="right", data-i18n="nav.twitter_follow") Follow + iframe.github-star-button(src="http://ghbtns.com/github-btn.html?user=codecombat&repo=codecombat&type=watch&count=true", allowtransparency="true", frameborder="0", scrolling="0", width="110", height="20") .partner-badges a.mixpanel-badge(href="https://mixpanel.com/f/partner") diff --git a/app/views/kinds/RootView.coffee b/app/views/kinds/RootView.coffee index 07a0db486..f576587d5 100644 --- a/app/views/kinds/RootView.coffee +++ b/app/views/kinds/RootView.coffee @@ -70,6 +70,7 @@ module.exports = class RootView extends CocoView getRenderData: -> c = super() c.showBackground = @showBackground + c.usesSocialMedia = @usesSocialMedia c afterRender: -> diff --git a/app/views/modal/AuthModal.coffee b/app/views/modal/AuthModal.coffee index 9885b15f5..093375957 100644 --- a/app/views/modal/AuthModal.coffee +++ b/app/views/modal/AuthModal.coffee @@ -42,7 +42,7 @@ module.exports = class AuthModal extends ModalView afterInsert: -> super() - _.delay application.router.renderLoginButtons, 500 + _.delay (=> application.router.renderLoginButtons()), 500 _.delay (=> $('input:visible:first', @$el).focus()), 500 onSignupInstead: (e) -> diff --git a/app/views/play/ladder/LadderView.coffee b/app/views/play/ladder/LadderView.coffee index 32b441ebd..75c9f05fd 100644 --- a/app/views/play/ladder/LadderView.coffee +++ b/app/views/play/ladder/LadderView.coffee @@ -25,6 +25,7 @@ class LevelSessionsCollection extends CocoCollection module.exports = class LadderView extends RootView id: 'ladder-view' template: require 'templates/play/ladder/ladder' + usesSocialMedia: true subscriptions: 'application:idle-changed': 'onIdleChanged' diff --git a/app/views/play/level/modal/VictoryModal.coffee b/app/views/play/level/modal/VictoryModal.coffee index d0444fbf4..d2afe6a1c 100644 --- a/app/views/play/level/modal/VictoryModal.coffee +++ b/app/views/play/level/modal/VictoryModal.coffee @@ -28,6 +28,7 @@ module.exports = class VictoryModal extends ModalView 'enter': -> 'onPlayNextLevel' constructor: (options) -> + application.router.initializeSocialMediaServices() victory = options.level.get('victory') body = utils.i18n(victory, 'body') or 'Sorry, this level has no victory message yet.' @body = marked(body) diff --git a/app/views/user/JobProfileView.coffee b/app/views/user/JobProfileView.coffee index fe0ba9024..c360c63f5 100644 --- a/app/views/user/JobProfileView.coffee +++ b/app/views/user/JobProfileView.coffee @@ -30,6 +30,7 @@ module.exports = class JobProfileView extends UserView id: 'profile-view' template: template showBackground: false + usesSocialMedia: true subscriptions: 'auth:linkedin-api-loaded': 'onLinkedInLoaded' From 54de8482f1405defa81a1f0a28ed8da42df9b783 Mon Sep 17 00:00:00 2001 From: Nick Winter Date: Thu, 16 Oct 2014 12:08:21 -0700 Subject: [PATCH 02/13] Spell palette now hugs the spell editor, which itself shrinks as needed. --- app/lib/aether_utils.coffee | 2 + app/styles/play/level/tome/problem_alert.sass | 3 +- app/styles/play/level/tome/spell.sass | 6 +-- app/styles/play/level/tome/spell_palette.sass | 4 +- .../play/level/tome/SpellPaletteView.coffee | 4 ++ app/views/play/level/tome/SpellView.coffee | 40 ++++++++++++++++++- app/views/play/level/tome/TomeView.coffee | 3 +- 7 files changed, 52 insertions(+), 10 deletions(-) diff --git a/app/lib/aether_utils.coffee b/app/lib/aether_utils.coffee index ebc200ae2..8468bf29a 100644 --- a/app/lib/aether_utils.coffee +++ b/app/lib/aether_utils.coffee @@ -44,8 +44,10 @@ functionParameters = evaluateBoard: ['board', 'player'] getPossibleMoves: ['board'] minimax_alphaBeta: ['board', 'player', 'depth', 'alpha', 'beta'] + distanceTo: ['target'] chooseAction: [] plan: [] initializeCentroids: [] update: [] + getNearestEnemy: [] diff --git a/app/styles/play/level/tome/problem_alert.sass b/app/styles/play/level/tome/problem_alert.sass index 2fef34314..8b0a623ea 100644 --- a/app/styles/play/level/tome/problem_alert.sass +++ b/app/styles/play/level/tome/problem_alert.sass @@ -4,7 +4,8 @@ .problem-alert z-index: 10 position: absolute - bottom: -135px + // Position these at the end of the spell editor, right above the spell toolbar. + bottom: -20px left: 10px right: 10px background: transparent diff --git a/app/styles/play/level/tome/spell.sass b/app/styles/play/level/tome/spell.sass index adeeb581f..0d07f8c36 100644 --- a/app/styles/play/level/tome/spell.sass +++ b/app/styles/play/level/tome/spell.sass @@ -12,9 +12,8 @@ position: absolute left: 10px top: 48px - bottom: 121px - // Bottom relates to .palette height and padding-top right: 10px + padding-bottom: 10px z-index: 1 // Set z-index above palette display: none @@ -62,9 +61,6 @@ line-height: 20px overflow: visible - &.user-code-problem.spell-cast - @include editor-height(60px) - &.disabled @include opacity(80) .ace_cursor diff --git a/app/styles/play/level/tome/spell_palette.sass b/app/styles/play/level/tome/spell_palette.sass index 274ae31e0..4103c0311 100644 --- a/app/styles/play/level/tome/spell_palette.sass +++ b/app/styles/play/level/tome/spell_palette.sass @@ -3,10 +3,10 @@ #spell-palette-view position: absolute - bottom: 10px + padding-bottom: 10px left: 10px right: 10px - height: 140px + //height: 140px // Height relates to .tab-content height padding-top: 35px padding-left: 12px diff --git a/app/views/play/level/tome/SpellPaletteView.coffee b/app/views/play/level/tome/SpellPaletteView.coffee index 4eaf69514..fff49811f 100644 --- a/app/views/play/level/tome/SpellPaletteView.coffee +++ b/app/views/play/level/tome/SpellPaletteView.coffee @@ -48,6 +48,10 @@ module.exports = class SpellPaletteView extends CocoView $('.nano').nanoScroller() @updateCodeLanguage @options.language + afterInsert: -> + super() + _.delay => @$el?.css('bottom', 0) unless $('#spell-view').is('.shown') + updateCodeLanguage: (language) -> @options.language = language @$el.find('.code-language-logo').removeClass().addClass 'code-language-logo ' + language diff --git a/app/views/play/level/tome/SpellView.coffee b/app/views/play/level/tome/SpellView.coffee index 69699f249..d74204322 100644 --- a/app/views/play/level/tome/SpellView.coffee +++ b/app/views/play/level/tome/SpellView.coffee @@ -65,6 +65,7 @@ module.exports = class SpellView extends CocoView @problems = [] @writable = false unless me.team in @spell.permissions.readwrite # TODO: make this do anything @highlightCurrentLine = _.throttle @highlightCurrentLine, 100 + $(window).on 'resize', @onWindowResize afterRender: -> super() @@ -281,6 +282,8 @@ module.exports = class SpellView extends CocoView setThang: (thang) -> @focus() + @lastScreenLineCount = null + @updateLines() return if thang.id is @thang?.id @thang = thang @spellThang = @spell.thangs[@thang.id] @@ -305,6 +308,31 @@ module.exports = class SpellView extends CocoView return if @aceDoc.undergoingFirepadOperation # from my Firepad ACE adapter Backbone.Mediator.publish 'tome:editing-began', {} + updateLines: => + # Make sure there are always blank lines for the player to type on, and that the editor resizes to the height of the lines. + lineCount = @aceDoc.getLength() + lastLine = @aceDoc.$lines[lineCount - 1] + if lastLine isnt '' + cursorPosition = @ace.getCursorPosition() + wasAtEnd = cursorPosition.row is lineCount - 1 and cursorPosition.column is lastLine.length + @aceDoc.insertNewLine row: lineCount, column: 0 #lastLine.length + @ace.navigateLeft(1) if wasAtEnd + ++lineCount + screenLineCount = @aceSession.getScreenLength() + if screenLineCount isnt @lastScreenLineCount + @lastScreenLineCount = screenLineCount + lineHeight = @ace.renderer.lineHeight or 20 + tomeHeight = $('#tome-view').innerHeight() + spellListTabEntryHeight = $('#spell-list-tab-entry-view').outerHeight() + spellToolbarHeight = $('.spell-toolbar-view').outerHeight() + spellPaletteHeight = $('#spell-palette-view').outerHeight() + maxHeight = tomeHeight - spellListTabEntryHeight - spellToolbarHeight - spellPaletteHeight + linesAtMaxHeight = Math.floor(maxHeight / lineHeight) + lines = Math.max 8, Math.min(screenLineCount + 4, linesAtMaxHeight) + # 2 lines buffer is nice, but 4 leaves room to put problem alerts. + @ace.setOptions minLines: lines, maxLines: lines + $('#spell-palette-view').css('top', 38 + 45 + lineHeight * lines) # Move spell palette up, slightly underlapping us. + onManualCast: (e) -> cast = @$el.parent().length @recompile cast, e.realTime @@ -361,6 +389,7 @@ module.exports = class SpellView extends CocoView _.debounce @notifyEditingEnded, 1000 _.throttle @notifyEditingBegan, 250 _.throttle @notifySpellChanged, 300 + _.throttle @updateLines, 500 ] @onCodeChangeMetaHandler = => return if @eventsSuppressed @@ -695,7 +724,15 @@ module.exports = class SpellView extends CocoView @ace.setValue pretty onMaximizeToggled: (e) -> - _.delay (=> @ace?.resize true), 500 # Wait $level-resize-transition-time. + _.delay (=> @resize()), 500 + 100 # Wait $level-resize-transition-time, plus a bit. + + onWindowResize: (e) => + _.delay (=> @resize?()), 500 + 100 # Wait $level-resize-transition-time, plus a bit. + + resize: -> + @ace?.resize true + @lastScreenLineCount = null + @updateLines() onChangeEditorConfig: (e) -> aceConfig = me.get('aceConfig') ? {} @@ -739,4 +776,5 @@ module.exports = class SpellView extends CocoView @aceSession?.selection.off 'changeCursor', @onCursorActivity @destroyAceEditor(@ace) @debugView?.destroy() + $(window).off 'resize', @onWindowResize super() diff --git a/app/views/play/level/tome/TomeView.coffee b/app/views/play/level/tome/TomeView.coffee index de1f10008..9d6e961fa 100644 --- a/app/views/play/level/tome/TomeView.coffee +++ b/app/views/play/level/tome/TomeView.coffee @@ -181,6 +181,7 @@ module.exports = class TomeView extends CocoView @spellTabView = null @removeSubView @spellPaletteView if @spellPaletteView @spellPaletteView = null + @$el.find('#spell-palette-view').hide() @castButton?.$el.hide() @thangList?.$el.show() @@ -204,10 +205,10 @@ module.exports = class TomeView extends CocoView @castButton.attachTo @spellView @thangList?.$el.hide() Backbone.Mediator.publish 'tome:spell-shown', thang: thang, spell: spell + @updateSpellPalette thang, spell @spellList.setThangAndSpell thang, spell @spellView?.setThang thang @spellTabView?.setThang thang - @updateSpellPalette thang, spell updateSpellPalette: (thang, spell) -> return unless thang and @spellPaletteView?.thang isnt thang and thang.programmableProperties or thang.apiProperties From 07b988c405430f77b1ca8ccf5330927fb6ce8394 Mon Sep 17 00:00:00 2001 From: Nick Winter Date: Thu, 16 Oct 2014 12:14:04 -0700 Subject: [PATCH 03/13] Fixed gear requirements for Closing the Distance. --- app/views/game-menu/InventoryView.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/game-menu/InventoryView.coffee b/app/views/game-menu/InventoryView.coffee index 26844244f..f9ac9fc2f 100644 --- a/app/views/game-menu/InventoryView.coffee +++ b/app/views/game-menu/InventoryView.coffee @@ -334,7 +334,7 @@ module.exports = class InventoryView extends CocoView 'the-second-kithmaze': {feet: 'simple-boots', 'programming-book': 'programmaticon-i'} 'new-sight': {'right-hand': 'longsword', 'programming-book': 'programmaticon-i'} 'lowly-kithmen': {feet: 'simple-boots', 'right-hand': 'longsword', 'programming-book': 'programmaticon-i', eyes: 'crude-glasses'} - 'a-bolt-in-the-dark': {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'} 'kithgard-gates': {feet: 'simple-boots', 'right-hand': 'builders-hammer'} 'defence-of-plainswood': {feet: 'simple-boots', 'right-hand': 'builders-hammer'} From a922c9c6ef728b73359861721e814078cb41d2f9 Mon Sep 17 00:00:00 2001 From: Nick Winter Date: Thu, 16 Oct 2014 21:38:11 -0700 Subject: [PATCH 04/13] First draft of new hero spell palette that groups abilities by item. --- app/lib/LevelLoader.coffee | 4 +- app/styles/mixins.sass | 51 ++++++++ app/styles/play/level/tome/spell_palette.sass | 31 +++++ .../play/level/tome/spell_palette_entry.sass | 4 + .../play/level/tome/spell_palette.jade | 25 ++-- .../play/level/tome/spell_palette_entry.jade | 2 +- .../tome/spell_palette_entry_popover.jade | 4 + app/views/play/level/tome/DocFormatter.coffee | 2 +- .../play/level/tome/SpellPaletteView.coffee | 118 +++++++++++++++--- app/views/play/level/tome/SpellView.coffee | 16 ++- 10 files changed, 220 insertions(+), 37 deletions(-) diff --git a/app/lib/LevelLoader.coffee b/app/lib/LevelLoader.coffee index a5f19e34d..3bd7c64b3 100644 --- a/app/lib/LevelLoader.coffee +++ b/app/lib/LevelLoader.coffee @@ -105,7 +105,7 @@ module.exports = class LevelLoader extends CocoClass @loadThangsRequiredByThangType heroThangType for itemThangType in _.values(heroConfig.inventory) - url = "/db/thang.type/#{itemThangType}/version?project=name,components,original" + url = "/db/thang.type/#{itemThangType}/version?project=name,components,original,rasterIcon" if itemResource = @maybeLoadURL(url, ThangType, 'thang') @worldNecessities.push itemResource else @@ -183,7 +183,7 @@ module.exports = class LevelLoader extends CocoClass else if component.config.requiredThangTypes requiredThangTypes = requiredThangTypes.concat component.config.requiredThangTypes for thangType in requiredThangTypes - url = "/db/thang.type/#{thangType}/version?project=name,components,original" + url = "/db/thang.type/#{thangType}/version?project=name,components,original,rasterIcon" @worldNecessities.push @maybeLoadURL(url, ThangType, 'thang') onThangNamesLoaded: (thangNames) -> diff --git a/app/styles/mixins.sass b/app/styles/mixins.sass index bd58264af..18f695aac 100644 --- a/app/styles/mixins.sass +++ b/app/styles/mixins.sass @@ -58,3 +58,54 @@ -moz-filter: $filters -o-filter: $filters filter: $filters + +@mixin flexbox() + display: -webkit-box + display: -moz-box + display: -ms-flexbox + display: -webkit-flex + display: flex + +@mixin flex($values) + -webkit-box-flex: $values + -moz-box-flex: $values + -webkit-flex: $values + -ms-flex: $values + flex: $values + +@mixin order($val) + -webkit-box-ordinal-group: $val + -moz-box-ordinal-group: $val + -ms-flex-order: $val + -webkit-order: $val + order: $val + +@mixin flex-justify() + -webkit-box-pack: justify + -webkit-justify-content: space-between + -ms-flex-pack: justify + justify-content: space-between + +@mixin flex-align-content-start() + -webkit-align-content: flex-start + -ms-flex-align-content: flex-start + align-content: flex-start + +@mixin flex-center() + -webkit-box-align: center + -webkit-align-items: center + -ms-flex-align: center + align-items: center + +@mixin flex-wrap() + -webkit-flex-wrap: wrap + -ms-flex-wrap: wrap + flex-wrap: wrap + +@mixin flex-column() + -webkit-box-orient: vertical + -moz-box-orient: vertical + -ms-box-orient: vertical + -webkit-flex-direction: column + -ms-flex-direction: column + -flex-direction: column diff --git a/app/styles/play/level/tome/spell_palette.sass b/app/styles/play/level/tome/spell_palette.sass index 4103c0311..c6f7ff406 100644 --- a/app/styles/play/level/tome/spell_palette.sass +++ b/app/styles/play/level/tome/spell_palette.sass @@ -69,6 +69,37 @@ margin-right: 3px vertical-align: top + &.hero .properties + @include flexbox() + @include flex-wrap() + @include flex-column() + @include flex-align-content-start() + + .property-entry-item-group + display: inline-block + min-height: 38px + max-width: 212px + @include flexbox() + @include flex-wrap() + @include flex-center() + outline: 1px dashed #b86 + position: relative + + img.item-image + width: 38px + height: 38px + position: absolute + + &:not(:hover) img.item-image + -webkit-filter: sepia(100%) + filter: sepia(100%) + + .spell-palette-entry-view + margin-left: 38px + width: 174px + width: -webkit-calc(100% - 38px) + width: calc(100% - 38px) + .code-language-logo position: absolute width: 16px diff --git a/app/styles/play/level/tome/spell_palette_entry.sass b/app/styles/play/level/tome/spell_palette_entry.sass index b5d858db2..4be1e4b9c 100644 --- a/app/styles/play/level/tome/spell_palette_entry.sass +++ b/app/styles/play/level/tome/spell_palette_entry.sass @@ -13,6 +13,10 @@ border: 1px solid transparent cursor: pointer @include user-select(all) + height: 19px + text-overflow: ellipsis + overflow: hidden + white-space: nowrap &:hover border: 1px solid #000000 diff --git a/app/templates/play/level/tome/spell_palette.jade b/app/templates/play/level/tome/spell_palette.jade index 2344bfdaf..8ffd1e63f 100644 --- a/app/templates/play/level/tome/spell_palette.jade +++ b/app/templates/play/level/tome/spell_palette.jade @@ -1,12 +1,17 @@ img(src="/images/level/code_palette_background.png").code-palette-background span.code-palette-background -.code-language-logo -ul(class="nav nav-pills" + (tabbed ? ' multiple-tabs' : '')) - each slug, group in entryGroupSlugs - li(class=group == "this" || slug == "available-spells" ? "active" : "") - a(data-toggle="pill", data-target='#palette-tab-' + slug) - h4= entryGroupNames[group] -.tab-content - each slug, group in entryGroupSlugs - div(id="palette-tab-" + slug, class="tab-pane nano" + (group == "this" || slug == defaultGroupSlug ? " active" : "")) - div(class="properties properties-" + slug + " nano-content") +if entryGroupSlugs + // Non-hero; group by entry groups, or maybe nothing. + .code-language-logo + ul(class="nav nav-pills" + (tabbed ? ' multiple-tabs' : '')) + each slug, group in entryGroupSlugs + li(class=group == "this" || slug == "available-spells" ? "active" : "") + a(data-toggle="pill", data-target='#palette-tab-' + slug) + h4= entryGroupNames[group] + .tab-content + each slug, group in entryGroupSlugs + div(id="palette-tab-" + slug, class="tab-pane nano" + (group == "this" || slug == defaultGroupSlug ? " active" : "")) + div(class="properties properties-" + slug + " nano-content") +else + // Hero; group by items, no tabs. + .properties diff --git a/app/templates/play/level/tome/spell_palette_entry.jade b/app/templates/play/level/tome/spell_palette_entry.jade index fabec56ad..2d1a94f4d 100644 --- a/app/templates/play/level/tome/spell_palette_entry.jade +++ b/app/templates/play/level/tome/spell_palette_entry.jade @@ -1 +1 @@ -span= doc.title \ No newline at end of file +span.doc-title= doc.title \ No newline at end of file diff --git a/app/templates/play/level/tome/spell_palette_entry_popover.jade b/app/templates/play/level/tome/spell_palette_entry_popover.jade index 43a32988e..c13df8394 100644 --- a/app/templates/play/level/tome/spell_palette_entry_popover.jade +++ b/app/templates/play/level/tome/spell_palette_entry_popover.jade @@ -105,6 +105,10 @@ if doc.returns if doc.returns.description div!= marked(doc.returns.description) +if item + p + em Granted by #{item.get('name')}. + if selectedMethod p em Write the body of this method below. \ No newline at end of file diff --git a/app/views/play/level/tome/DocFormatter.coffee b/app/views/play/level/tome/DocFormatter.coffee index b966a94bc..3784139a6 100644 --- a/app/views/play/level/tome/DocFormatter.coffee +++ b/app/views/play/level/tome/DocFormatter.coffee @@ -93,7 +93,7 @@ module.exports = class DocFormatter obj[prop] = null formatPopover: -> - content = popoverTemplate doc: @doc, language: @options.language, value: @formatValue(), marked: marked, argumentExamples: (arg.example or arg.default or arg.name for arg in @doc.args ? []), writable: @options.writable, selectedMethod: @options.selectedMethod, cooldowns: @inferCooldowns() + content = popoverTemplate doc: @doc, language: @options.language, value: @formatValue(), marked: marked, argumentExamples: (arg.example or arg.default or arg.name for arg in @doc.args ? []), writable: @options.writable, selectedMethod: @options.selectedMethod, cooldowns: @inferCooldowns(), item: @options.item owner = if @doc.owner is 'this' then @options.thang else window[@doc.owner] content = content.replace /#{spriteName}/g, @options.thang.type ? @options.thang.spriteName # Prefer type, and excluded the quotes we'd get with @formatValue content.replace /\#\{(.*?)\}/g, (s, properties) => @formatValue downTheChain(owner, properties.split('.')) diff --git a/app/views/play/level/tome/SpellPaletteView.coffee b/app/views/play/level/tome/SpellPaletteView.coffee index fff49811f..621cabb69 100644 --- a/app/views/play/level/tome/SpellPaletteView.coffee +++ b/app/views/play/level/tome/SpellPaletteView.coffee @@ -4,6 +4,7 @@ template = require 'templates/play/level/tome/spell_palette' filters = require 'lib/image_filter' SpellPaletteEntryView = require './SpellPaletteEntryView' LevelComponent = require 'models/LevelComponent' +ThangType = require 'models/ThangType' EditorConfigModal = require '../modal/EditorConfigModal' N_ROWS = 4 @@ -26,6 +27,7 @@ module.exports = class SpellPaletteView extends CocoView super options @thang = options.thang @createPalette() + $(window).on 'resize', @onResize getRenderData: -> c = super() @@ -38,15 +40,26 @@ module.exports = class SpellPaletteView extends CocoView afterRender: -> super() - for group, entries of @entryGroups - groupSlug = @entryGroupSlugs[group] - for columnNumber, entryColumn of entries - col = $('
').appendTo @$el.find(".properties-#{groupSlug}") - for entry in entryColumn - col.append entry.el + if @entryGroupSlugs + for group, entries of @entryGroups + groupSlug = @entryGroupSlugs[group] + for columnNumber, entryColumn of entries + col = $('
').appendTo @$el.find(".properties-#{groupSlug}") + for entry in entryColumn + col.append entry.el + entry.render() # Render after appending so that we can access parent container for popover + $('.nano').nanoScroller() + @updateCodeLanguage @options.language + else + @entryGroupElements = {} + for group, entries of @entryGroups + @entryGroupElements[group] = itemGroup = $('
').appendTo @$el.find('.properties') + itemGroup.append $('').attr('src', entries[0].options.item.getPortraitURL()).css('top', Math.max(0, 19 * (entries.length - 2) / 2)) if entries[0].options.item?.getPortraitURL + for entry in entries + itemGroup.append entry.el entry.render() # Render after appending so that we can access parent container for popover - $('.nano').nanoScroller() - @updateCodeLanguage @options.language + @$el.addClass 'hero' + @updateMaxHeight() afterInsert: -> super() @@ -56,6 +69,24 @@ module.exports = class SpellPaletteView extends CocoView @options.language = language @$el.find('.code-language-logo').removeClass().addClass 'code-language-logo ' + language + updateMaxHeight: -> + return unless @isHero + nColumns = Math.floor @$el.find('.properties').innerWidth() / 212 # ~212px is a good max entry width; will always have 2 columns + columns = ({items: [], nEntries: 0} for i in [0 ... nColumns]) + nRows = 0 + for group, entries of @entryGroups + shortestColumn = _.sortBy(columns, (column) -> column.nEntries)[0] + shortestColumn.nEntries += Math.max 2, entries.length + shortestColumn.items.push @entryGroupElements[group] + nRows = Math.max nRows, shortestColumn.nEntries + for column in columns + for item in column.items + item.detach().appendTo @$el.find('.properties') + @$el.find('.properties').css('height', 19 * (nRows + 1)) + + onResize: (e) => + @updateMaxHeight() + createPalette: -> Backbone.Mediator.publish 'tome:palette-cleared', {thangID: @thang.id} lcs = @supermodel.getModels LevelComponent @@ -90,6 +121,12 @@ module.exports = class SpellPaletteView extends CocoView else propStorage = 'this': ['apiProperties', 'apiMethods'] + if @options.level.get('type', true) isnt 'hero' or not @options.programmable + @organizePalette propStorage, allDocs, excludedDocs + else + @organizePaletteHero propStorage, allDocs, excludedDocs + + organizePalette: (propStorage, allDocs, excludedDocs) -> count = 0 propGroups = {} for owner, storages of propStorage @@ -99,13 +136,11 @@ module.exports = class SpellPaletteView extends CocoView added = _.sortBy(props).slice() propGroups[owner] = (propGroups[owner] ? []).concat added count += added.length + Backbone.Mediator.publish 'tome:update-snippets', propGroups: propGroups, allDocs: allDocs, language: @options.language shortenize = count > 6 tabbify = count >= 10 @entries = [] - - Backbone.Mediator.publish 'tome:update-snippets', propGroups: propGroups, allDocs: allDocs, language: @options.language - for owner, props of propGroups for prop in props doc = _.find (allDocs['__' + prop] ? []), (doc) -> @@ -134,22 +169,68 @@ module.exports = class SpellPaletteView extends CocoView @defaultGroupSlug = _.string.slugify defaultGroup @entryGroupSlugs = {} @entryGroupNames = {} - iOSEntryGroups = {} for group, entries of @entryGroups @entryGroups[group] = _.groupBy entries, (entry, i) -> Math.floor i / N_ROWS @entryGroupSlugs[group] = _.string.slugify group @entryGroupNames[group] = group - iOSEntryGroups[group] = (entry.doc for entry in entries) if thisName = {coffeescript: '@', lua: 'self', clojure: 'self'}[@options.language] if @entryGroupNames.this @entryGroupNames.this = thisName - iOSEntryGroups[thisName] = iOSEntryGroups.this - delete iOSEntryGroups.this - Backbone.Mediator.publish 'tome:palette-updated', thangID: @thang.id, entryGroups: JSON.stringify(iOSEntryGroups) # TODO: make it sort these by granting items if it's a hero level - addEntry: (doc, shortenize, tabbify, isSnippet=false) -> + organizePaletteHero: (propStorage, allDocs, excludedDocs) -> + # Assign any kind of programmable properties to the items that grant them. + @isHero = true + itemThangTypes = {} + itemThangTypes[tt.get('name')] = tt for tt in @supermodel.getModels ThangType + propsByItem = {} + propCount = 0 + itemsByProp = {} + for slot, inventoryID of @thang.inventoryIDs ? {} + if item = itemThangTypes[inventoryID] + for component in item.get('components') when component.config + for owner, storages of propStorage + if props = component.config[storages] + for prop in _.sortBy(props) when prop[0] isnt '_' # no private properties + propsByItem[item.get('name')] ?= [] + propsByItem[item.get('name')].push owner: owner, prop: prop, item: item + itemsByProp[prop] = item + ++propCount + else + console.log @thang.id, "couldn't find item ThangType for", slot, inventoryID + + # Assign any unassigned properties to the hero itself. + for owner, storage of propStorage + for prop in _.reject(@thang[storage] ? [], (prop) -> itemsByProp[prop] or prop[0] is '_') # no private properties + propsByItem['Hero'] ?= [] + propsByItem['Hero'].push owner: owner, prop: prop, item: null + ++propCount + + Backbone.Mediator.publish 'tome:update-snippets', propGroups: propsByItem, allDocs: allDocs, language: @options.language + + shortenize = propCount > 6 + @entries = [] + for itemName, props of propsByItem + for prop, propIndex in props + item = prop.item + owner = prop.owner + prop = prop.prop + doc = _.find (allDocs['__' + prop] ? []), (doc) -> + return true if doc.owner is owner + return (owner is 'this' or owner is 'more') and (not doc.owner? or doc.owner is 'this') + if not doc and not excludedDocs['__' + prop] + console.log 'could not find doc for', prop, 'from', allDocs['__' + prop], 'for', owner, 'of', propGroups, 'with item', item + doc ?= prop + if doc + @entries.push @addEntry(doc, shortenize, false, owner is 'snippets', item, propIndex > 0) + @entryGroups = _.groupBy @entries, (entry) -> itemsByProp[entry.doc.name]?.get('name') ? 'Hero' + iOSEntryGroups = {} + for group, entries of @entryGroups + iOSEntryGroups[group] = (entry.doc for entry in entries) + Backbone.Mediator.publish 'tome:palette-updated', thangID: @thang.id, entryGroups: JSON.stringify(iOSEntryGroups) + + addEntry: (doc, shortenize, tabbify, isSnippet=false, item=null, showImage=false) -> writable = (if _.isString(doc) then doc else doc.name) in (@thang.apiUserProperties ? []) - new SpellPaletteEntryView doc: doc, thang: @thang, shortenize: shortenize, tabbify: tabbify, isSnippet: isSnippet, language: @options.language, writable: writable, level: @options.level + new SpellPaletteEntryView doc: doc, thang: @thang, shortenize: shortenize, tabbify: tabbify, isSnippet: isSnippet, language: @options.language, writable: writable, level: @options.level, item: item, showImage: showImage onDisableControls: (e) -> @toggleControls e, false onEnableControls: (e) -> @toggleControls e, true @@ -185,4 +266,5 @@ module.exports = class SpellPaletteView extends CocoView destroy: -> entry.destroy() for entry in @entries @toggleBackground = null + $(window).off 'resize', @onResize super() diff --git a/app/views/play/level/tome/SpellView.coffee b/app/views/play/level/tome/SpellView.coffee index d74204322..48334248b 100644 --- a/app/views/play/level/tome/SpellView.coffee +++ b/app/views/play/level/tome/SpellView.coffee @@ -209,8 +209,13 @@ module.exports = class SpellView extends CocoView addZatannaSnippets: (e) -> return unless @zatanna and @autocomplete snippetEntries = [] - for owner, props of e.propGroups + for group, props of e.propGroups for prop in props + if _.isString prop # organizePalette + owner = group + else # organizePaletteHero + owner = prop.owner + prop = prop.prop doc = _.find (e.allDocs['__' + prop] ? []), (doc) -> return true if doc.owner is owner return (owner is 'this' or owner is 'more') and (not doc.owner? or doc.owner is 'this') @@ -394,10 +399,11 @@ module.exports = class SpellView extends CocoView @onCodeChangeMetaHandler = => return if @eventsSuppressed Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'code-change', volume: 0.5 - @spell.hasChangedSignificantly @getSource(), @spellThang.aether.raw, (hasChanged) => - if not @spellThang or hasChanged - callback() for callback in onSignificantChange # Do these first - callback() for callback in onAnyChange # Then these + if @spellThang + @spell.hasChangedSignificantly @getSource(), @spellThang.aether.raw, (hasChanged) => + if not @spellThang or hasChanged + callback() for callback in onSignificantChange # Do these first + callback() for callback in onAnyChange # Then these @aceDoc.on 'change', @onCodeChangeMetaHandler setRecompileNeeded: (@recompileNeeded) => From fe66b6e9605a89d521f09bf3b90db0baaaa88d87 Mon Sep 17 00:00:00 2001 From: yjw9012 Date: Thu, 16 Oct 2014 21:39:59 -0700 Subject: [PATCH 05/13] #1668: moved the question above the dropdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit moved the question ‘which programming do you want to use?’ above the programming language dropdown. --- app/templates/game-menu/choose-hero-view.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/game-menu/choose-hero-view.jade b/app/templates/game-menu/choose-hero-view.jade index 131023084..e9f86a36a 100644 --- a/app/templates/game-menu/choose-hero-view.jade +++ b/app/templates/game-menu/choose-hero-view.jade @@ -43,11 +43,11 @@ .form .form-group.select-group + span.help-block(data-i18n="choose_hero.programming_language_description") Which programming language do you want to use? label.control-label(for="option-code-language", data-i18n="choose_hero.programming_language") Programming Language select#option-code-language(name="code-language") for option in codeLanguages option(value=option.id, selected=codeLanguage === option.id)= option.name - span.help-block(data-i18n="choose_hero.programming_language_description") Which programming language do you want to use? if level .form-group.select-group From f496823bb5a3f9f1d2f9af5ed28c14a0d0200933 Mon Sep 17 00:00:00 2001 From: Imperadeiro98 Date: Fri, 17 Oct 2014 16:38:21 +0100 Subject: [PATCH 06/13] Update level_loading.jade Removed an unused tip. --- app/templates/play/level/level_loading.jade | 1 - 1 file changed, 1 deletion(-) diff --git a/app/templates/play/level/level_loading.jade b/app/templates/play/level/level_loading.jade index 31ffd34fb..9deddc448 100644 --- a/app/templates/play/level/level_loading.jade +++ b/app/templates/play/level/level_loading.jade @@ -9,7 +9,6 @@ .progress-bar.progress-bar-success #tip-wrapper - strong.tip(data-i18n='play_level.tip_insert_positions') Shift+Click a point on the map to insert it into the spell editor. strong.tip(data-i18n='play_level.tip_toggle_play') Toggle play/paused with Ctrl+P. strong.tip(data-i18n='play_level.tip_scrub_shortcut') Ctrl+[ and Ctrl+] rewind and fast-forward. strong.tip(data-i18n='play_level.tip_guide_exists') Click the guide at the top of the page for useful info. From 7bc50ade3032ac1fa09f0e7f6b906077100cf40a Mon Sep 17 00:00:00 2001 From: Nick Winter Date: Fri, 17 Oct 2014 08:47:53 -0700 Subject: [PATCH 07/13] Fixes for spectate layout in new WebGL dual-stage mode. --- app/lib/surface/Surface.coffee | 6 ++++-- app/styles/play/spectate.sass | 10 ++++++++-- app/templates/play/spectate.jade | 3 ++- app/views/play/SpectateView.coffee | 5 +++-- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/app/lib/surface/Surface.coffee b/app/lib/surface/Surface.coffee index 617dbd279..bb2f26f86 100644 --- a/app/lib/surface/Surface.coffee +++ b/app/lib/surface/Surface.coffee @@ -522,7 +522,7 @@ module.exports = Surface = class Surface extends CocoClass newWidth = 0.55 * pageWidth newHeight = newWidth / aspectRatio return unless newWidth > 0 and newHeight > 0 - return if newWidth is oldWidth and newHeight is oldHeight + return if newWidth is oldWidth and newHeight is oldHeight and not @options.spectateGame #scaleFactor = if application.isIPadApp then 2 else 1 # Retina scaleFactor = 1 @normalCanvas.add(@webGLCanvas).attr width: newWidth * scaleFactor, height: newHeight * scaleFactor @@ -533,7 +533,9 @@ module.exports = Surface = class Surface extends CocoClass @normalStage.scaleX *= newWidth / oldWidth @normalStage.scaleY *= newHeight / oldHeight @camera.onResize newWidth, newHeight - + if @options.spectateGame + # Since normalCanvas is absolutely positioned, it needs help aligning with webGLCanvas. But not further than +149px (1920px screen). + @normalCanvas.css 'left', Math.min 149, @webGLCanvas.offset().left #- Camera focus on hero focusOnHero: -> diff --git a/app/styles/play/spectate.sass b/app/styles/play/spectate.sass index 0d48f27a9..a0f7343fa 100644 --- a/app/styles/play/spectate.sass +++ b/app/styles/play/spectate.sass @@ -42,12 +42,18 @@ position: relative margin: 0 auto - canvas#surface - background-color: #333 + canvas#webgl-surface, canvas#normal-surface display: block z-index: 1 margin: 0 auto + canvas#webgl-surface + background-color: #333 + + canvas#normal-surface + position: absolute + top: 0 + pointer-events: none min-width: 1024px position: relative diff --git a/app/templates/play/spectate.jade b/app/templates/play/spectate.jade index 7867ba9a6..80ed5c35d 100644 --- a/app/templates/play/spectate.jade +++ b/app/templates/play/spectate.jade @@ -3,7 +3,8 @@ .level-content #control-bar-view #canvas-wrapper - canvas(width=924, height=589)#surface + canvas(width=924, height=589)#webgl-surface + canvas(width=924, height=589)#normal-surface #canvas-left-gradient.gradient #canvas-top-gradient.gradient #gold-view.secret.expanded diff --git a/app/views/play/SpectateView.coffee b/app/views/play/SpectateView.coffee index 0468e227d..9c6cc5dc9 100644 --- a/app/views/play/SpectateView.coffee +++ b/app/views/play/SpectateView.coffee @@ -205,8 +205,9 @@ module.exports = class SpectateLevelView extends RootView # initialization initSurface: -> - surfaceCanvas = $('canvas#surface', @$el) - @surface = new Surface(@world, surfaceCanvas, thangTypes: @supermodel.getModels(ThangType), playJingle: not @isEditorPreview, spectateGame: true, wizards: @level.get('type', true) isnt 'hero') + webGLSurface = $('canvas#webgl-surface', @$el) + normalSurface = $('canvas#normal-surface', @$el) + @surface = new Surface(@world, normalSurface, webGLSurface, thangTypes: @supermodel.getModels(ThangType), playJingle: not @isEditorPreview, spectateGame: true, wizards: @level.get('type', true) isnt 'hero') worldBounds = @world.getBounds() bounds = [{x:worldBounds.left, y:worldBounds.top}, {x:worldBounds.right, y:worldBounds.bottom}] @surface.camera.setBounds(bounds) From 3b9feebee8b75d61601645ff29c08d50909ef702 Mon Sep 17 00:00:00 2001 From: Imperadeiro98 Date: Fri, 17 Oct 2014 17:06:25 +0100 Subject: [PATCH 08/13] Update cast_button.jade Internationalized "Submit". --- app/templates/play/level/tome/cast_button.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/play/level/tome/cast_button.jade b/app/templates/play/level/tome/cast_button.jade index bde30b02b..02facd457 100644 --- a/app/templates/play/level/tome/cast_button.jade +++ b/app/templates/play/level/tome/cast_button.jade @@ -1,3 +1,3 @@ button.btn.btn-lg.btn-inverse.banner.cast-button(title=castVerbose, data-i18n="play_level.tome_run_button_ran") Ran -button.btn.btn-lg.btn-success.banner.submit-button(title=castRealTimeVerbose) Submit +button.btn.btn-lg.btn-success.banner.submit-button(title=castRealTimeVerbose, data-i18n="play_level.tome_submit_button") Submit From 34dd1dadcad5c5e43206a6798c52f13e3a09447a Mon Sep 17 00:00:00 2001 From: Rafael Jaques Date: Fri, 17 Oct 2014 13:56:44 -0300 Subject: [PATCH 09/13] Update pt-BR.coffee --- app/locale/pt-BR.coffee | 54 ++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/app/locale/pt-BR.coffee b/app/locale/pt-BR.coffee index 407e13abf..384b9c79e 100644 --- a/app/locale/pt-BR.coffee +++ b/app/locale/pt-BR.coffee @@ -216,13 +216,13 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: tome_cast_button_castable: "Lançar" # Temporary, if tome_cast_button_run isn't translated. tome_cast_button_casting: "Conjurando" # Temporary, if tome_cast_button_running isn't translated. tome_cast_button_cast: "Feitiço" # Temporary, if tome_cast_button_ran isn't translated. -# tome_cast_button_run: "Run" -# tome_cast_button_running: "Running" -# tome_cast_button_ran: "Ran" + tome_cast_button_run: "Rodar" + tome_cast_button_running: "Rodando" + tome_cast_button_ran: "Rodado" tome_submit_button: "Enviar" -# tome_reload_method: "Reload original code for this method" # Title text for individual method reload button. + tome_reload_method: "Recarregar o código original para este método" # Title text for individual method reload button. tome_select_method: "Selecione um Método" -# tome_see_all_methods: "See all methods you can edit" # Title text for method list selector (shown when there are multiple programmable methdos). + tome_see_all_methods: "Visualizar todos os métodos que você pode editar" # Title text for method list selector (shown when there are multiple programmable methdos). tome_select_a_thang: "Selecione alguém para " tome_available_spells: "Feitiços Disponíveis" tome_your_skills: "Suas habilidades" @@ -236,14 +236,14 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: time_total: "Máximo:" time_goto: "Ir para:" infinite_loop_try_again: "Tentar novamente" -# infinite_loop_reset_level: "Reset Level" + infinite_loop_reset_level: "Resetar nível" # infinite_loop_comment_out: "Comment Out My Code" -# tip_toggle_play: "Toggle play/paused with Ctrl+P." -# tip_scrub_shortcut: "Ctrl+[ and Ctrl+] rewind and fast-forward." + tip_toggle_play: "Alterne entre rodando/pausado com Ctrl+P." + tip_scrub_shortcut: "Ctrl+[ e Ctrl+] rebobina e avança." # tip_guide_exists: "Click the guide at the top of the page for useful info." -# tip_open_source: "CodeCombat is 100% open source!" -# tip_beta_launch: "CodeCombat launched its beta in October, 2013." -# tip_think_solution: "Think of the solution, not the problem." + tip_open_source: "CodeCombat é 100% código aberto!" + tip_beta_launch: "CodeCombat lançou sua versão beta em outubro de 2013." + tip_think_solution: "Pense na solução, não no problema." # tip_theory_practice: "In theory, there is no difference between theory and practice. But in practice, there is. - Yogi Berra" # tip_error_free: "There are two ways to write error-free programs; only the third one works. - Alan Perlis" # tip_debugging_program: "If debugging is the process of removing bugs, then programming must be the process of putting them in. - Edsger W. Dijkstra" @@ -266,7 +266,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: # tip_hardware_problem: "Q: How many programmers does it take to change a light bulb? A: None, it's a hardware problem." # tip_hofstadters_law: "Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law." # tip_premature_optimization: "Premature optimization is the root of all evil. - Donald Knuth" -# tip_brute_force: "When in doubt, use brute force. - Ken Thompson" + tip_brute_force: "Na dúvida, utilize força bruta. - Ken Thompson" customize_wizard: "Personalize o feiticeiro" game_menu: @@ -277,14 +277,14 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: guide_tab: "Guia" multiplayer_tab: "Multijogador" inventory_caption: "Equipar seu herói" -# choose_hero_caption: "Choose hero, language" + choose_hero_caption: "Escolha seu herói, linguagem" # save_load_caption: "... and view history" -# options_caption: "Configure settings" + options_caption: "Configurar preferências" guide_caption: "Documentos e dicas" -# multiplayer_caption: "Play with friends!" + multiplayer_caption: "Jogue com seus amigos!" # inventory: -# choose_inventory: "Equip Items" + choose_inventory: "Equipar itens" choose_hero: choose_hero: "Escolha seu Herói" @@ -300,23 +300,23 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: granularity_change_history: "Histórico" options: -# general_options: "General Options" # Check out the Options tab in the Game Menu while playing a level + general_options: "Opções Gerais" # Check out the Options tab in the Game Menu while playing a level volume_label: "Volume" music_label: "Música" -# music_description: "Turn background music on/off." -# autorun_label: "Autorun" -# autorun_description: "Control automatic code execution." + music_description: "Ligar/desligar música de fundo." + autorun_label: "Rodar automaticamente" + autorun_description: "Controlar execução automática do código." editor_config: "Editor de Configurações" editor_config_title: "Editor de Configurações" -# editor_config_level_language_label: "Language for This Level" -# editor_config_level_language_description: "Define the programming language for this particular level." -# editor_config_default_language_label: "Default Programming Language" -# editor_config_default_language_description: "Define the programming language you want to code in when starting new levels." + editor_config_level_language_label: "Linguagem para este nível" + editor_config_level_language_description: "Definir linguagem para esse nível específico." + editor_config_default_language_label: "Linguagem de programação padrão" + editor_config_default_language_description: "Define a linguagem de programação que você quer utilizar quando iniciar novos níveis." editor_config_keybindings_label: "Teclas de Atalho" editor_config_keybindings_default: "Padrão (Ace)" editor_config_keybindings_description: "Adicionar atalhos conhecidos de editores comuns." -# editor_config_livecompletion_label: "Live Autocompletion" -# editor_config_livecompletion_description: "Displays autocomplete suggestions while typing." + editor_config_livecompletion_label: "Autocompletar durante a escrita" + editor_config_livecompletion_description: "Mostra opções de autocompletar enquanto estiver escrevendo." editor_config_invisibles_label: "Mostrar Invisíveis" editor_config_invisibles_description: "Mostrar invisíveis como espaços e tabs." editor_config_indentguides_label: "Mostrar Linhas de Identação" @@ -367,7 +367,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: forum_page: "nosso fórum" forum_suffix: " ao invés disso." send: "Enviar opinião" -# contact_candidate: "Contact Candidate" # Deprecated + contact_candidate: "Contactar Candidato" # Deprecated # recruitment_reminder: "Use this form to reach out to candidates you are interested in interviewing. Remember that CodeCombat charges 15% of first-year salary. The fee is due upon hiring the employee and is refundable for 90 days if the employee does not remain employed. Part time, remote, and contract employees are free, as are interns." # Deprecated account_settings: From a3c86215841304fd47786938ed2779a61a4408fc Mon Sep 17 00:00:00 2001 From: Rafael Jaques Date: Fri, 17 Oct 2014 16:13:20 -0300 Subject: [PATCH 10/13] Update pt-BR.coffee --- app/locale/pt-BR.coffee | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/app/locale/pt-BR.coffee b/app/locale/pt-BR.coffee index 384b9c79e..e50e91b20 100644 --- a/app/locale/pt-BR.coffee +++ b/app/locale/pt-BR.coffee @@ -257,9 +257,9 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: # tip_munchkin: "If you don't eat your vegetables, a munchkin will come after you while you're asleep." # tip_binary: "There are only 10 types of people in the world: those who understand binary, and those who don't." # tip_commitment_yoda: "A programmer must have the deepest commitment, the most serious mind. ~ Yoda" -# tip_no_try: "Do. Or do not. There is no try. - Yoda" -# tip_patience: "Patience you must have, young Padawan. - Yoda" -# tip_documented_bug: "A documented bug is not a bug; it is a feature." + tip_no_try: "Faça. Ou não faça. Não existe tentar. - Yoda" + tip_patience: "Paciência você deve ter, jovem Padawan. - Yoda" + tip_documented_bug: "Um bug documentado não é um bug; é uma funcionalidade." # tip_impossible: "It always seems impossible until it's done. - Nelson Mandela" # tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds" # tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay" @@ -368,7 +368,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: forum_suffix: " ao invés disso." send: "Enviar opinião" contact_candidate: "Contactar Candidato" # Deprecated -# recruitment_reminder: "Use this form to reach out to candidates you are interested in interviewing. Remember that CodeCombat charges 15% of first-year salary. The fee is due upon hiring the employee and is refundable for 90 days if the employee does not remain employed. Part time, remote, and contract employees are free, as are interns." # Deprecated + recruitment_reminder: "Utilize esse formulário para entrar em contato com candidatos que você esteja interessado em entrevistar. Lembre-se que o CodeCombat cobra 15% do salário do primeiro ano. A taxa de contratação é cobrada quando da contratação do empregado e é reembolsável por 90 dias, se o empregado não permanece no emprego. Empregados de meio-turno, remotos ou com contrato serão gratuitos como estagiários." # Deprecated account_settings: title: "Configurações da Conta" @@ -416,12 +416,12 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: enter: "Enter" escape: "Esc" shift: "Shift" -# cast_spell: "Cast current spell." -# run_real_time: "Run in real time." + cast_spell: "Lançar feitiço atual." + run_real_time: "Rodar em tempo real." # continue_script: "Continue past current script." # skip_scripts: "Skip past all skippable scripts." -# toggle_playback: "Toggle play/pause." -# scrub_playback: "Scrub back and forward through time." + toggle_playback: "Alternar play/pause." + scrub_playback: "Rolar para frente e para trás no tempo." # single_scrub_playback: "Scrub back and forward through time by a single frame." # scrub_execution: "Scrub through current spell execution." # toggle_debug: "Toggle debug display." @@ -979,11 +979,11 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: projects_header_2: "Projetos (Top 3)" projects_blurb: "Destaque seus projetos para impressionar os empregadores." project_name: "Nome do Projeto" -# project_name_help: "What was the project called?" + project_name_help: "Como o projeto se chama?" project_description: "Descrição" -# project_description_help: "Briefly describe the project." + project_description_help: "Descreva o projeto brevemente." project_picture: "Imagem" -# project_picture_help: "Upload a 230x115px or larger image showing off the project." + project_picture_help: "Envie uma imagem com 230x115px ou maior mostrando o projeto." project_link: "Link" project_link_help: "Link para o projeto." # player_code: "Player Code" @@ -1035,11 +1035,11 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: # inactive_developers: "Inactive Developers" admin: -# av_espionage: "Espionage" # Really not important to translate /admin controls. -# av_espionage_placeholder: "Email or username" -# av_usersearch: "User Search" -# av_usersearch_placeholder: "Email, username, name, whatever" -# av_usersearch_search: "Search" + av_espionage: "Espionagem" # Really not important to translate /admin controls. + av_espionage_placeholder: "Email ou username" + av_usersearch: "Busca de Usuário" + av_usersearch_placeholder: "Email, username, nome, qualquer coisa" + av_usersearch_search: "Buscar" av_title: "Visualização de Administrador" av_entities_sub_title: "Entidades" av_entities_users_url: "Usuários" From b8d59ed78aa9e82e4d9fa3827dbaf4449bb1adf7 Mon Sep 17 00:00:00 2001 From: Rafael Jaques Date: Fri, 17 Oct 2014 16:59:33 -0300 Subject: [PATCH 11/13] Update pt-BR.coffee --- app/locale/pt-BR.coffee | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/locale/pt-BR.coffee b/app/locale/pt-BR.coffee index e50e91b20..45261eb75 100644 --- a/app/locale/pt-BR.coffee +++ b/app/locale/pt-BR.coffee @@ -422,14 +422,14 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: # skip_scripts: "Skip past all skippable scripts." toggle_playback: "Alternar play/pause." scrub_playback: "Rolar para frente e para trás no tempo." -# single_scrub_playback: "Scrub back and forward through time by a single frame." -# scrub_execution: "Scrub through current spell execution." -# toggle_debug: "Toggle debug display." -# toggle_grid: "Toggle grid overlay." -# toggle_pathfinding: "Toggle pathfinding overlay." -# beautify: "Beautify your code by standardizing its formatting." -# maximize_editor: "Maximize/minimize code editor." -# move_wizard: "Move your Wizard around the level." + single_scrub_playback: "Rolar para frente e para trás no tempo, quadro a quadro." + scrub_execution: "Rolar através da execução do feitiço atual." + toggle_debug: "Ligar/desligar informações de debug." + toggle_grid: "Ligar/desligar exibição da grade." + toggle_pathfinding: "Ligar/desligar exibição do pathfinding (caminho)." + beautify: "Embeleze seu código a partir da padronização de formatação." + maximize_editor: "Maximizar/minimizar editor de código." + move_wizard: "Mova o Wizard pelo nível." community: main_title: "Comunidade CodeCombat" @@ -468,7 +468,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: article_title: "Editor de Artigo" thang_title: "Editor de Thang" level_title: "Editor de Nível" -# achievement_title: "Achievement Editor" + achievement_title: "Editor de Conquistas" back: "Voltar" revert: "Reverter" revert_models: "Reverter Modelos" From 7ec54720ca2a993c8a8af44116fa19451873895e Mon Sep 17 00:00:00 2001 From: Rafael Jaques Date: Fri, 17 Oct 2014 17:01:51 -0300 Subject: [PATCH 12/13] Update pt-BR.coffee --- app/locale/pt-BR.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/locale/pt-BR.coffee b/app/locale/pt-BR.coffee index 45261eb75..82986569c 100644 --- a/app/locale/pt-BR.coffee +++ b/app/locale/pt-BR.coffee @@ -218,7 +218,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: tome_cast_button_cast: "Feitiço" # Temporary, if tome_cast_button_ran isn't translated. tome_cast_button_run: "Rodar" tome_cast_button_running: "Rodando" - tome_cast_button_ran: "Rodado" + tome_cast_button_ran: "Encerrado" tome_submit_button: "Enviar" tome_reload_method: "Recarregar o código original para este método" # Title text for individual method reload button. tome_select_method: "Selecione um Método" From a65dabad04de90d2ddaa7538fe1745fdbf55eccf Mon Sep 17 00:00:00 2001 From: Nick Winter Date: Fri, 17 Oct 2014 15:25:31 -0700 Subject: [PATCH 13/13] Removed level-specific achievements from achievements list. Fixed bug with return type documentation not showing up. Reduced initial first-level arrow delay. --- app/templates/user/achievements.jade | 20 ++++++++++--------- app/views/play/WorldMapView.coffee | 2 +- app/views/play/level/tome/DocFormatter.coffee | 4 +++- app/views/user/AchievementsView.coffee | 3 +-- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/app/templates/user/achievements.jade b/app/templates/user/achievements.jade index 33833d6f3..ca44144cb 100644 --- a/app/templates/user/achievements.jade +++ b/app/templates/user/achievements.jade @@ -36,15 +36,17 @@ block append content th XP each earnedAchievement in earnedAchievements.models - var achievement = earnedAchievement.get('achievement'); - tr - td= achievement.i18nName() - td= achievement.i18nDescription() - td= moment().format("MMMM Do YYYY", earnedAchievement.get('changed')) - if achievement.isRepeatable() - td= earnedAchievement.get('achievedAmount') - else - td - td= earnedAchievement.get('earnedPoints') + if achievement.get('category') + // No level-specific achievements in here. + tr + td= achievement.i18nName() + td= achievement.i18nDescription() + td= moment().format("MMMM Do YYYY", earnedAchievement.get('changed')) + if achievement.isRepeatable() + td= earnedAchievement.get('achievedAmount') + else + td + td= earnedAchievement.get('earnedPoints') else .panel#no-achievements .panel-body(data-i18n="user.no_achievements") No achievements earned yet. diff --git a/app/views/play/WorldMapView.coffee b/app/views/play/WorldMapView.coffee index 0bcb43334..80a83eadc 100644 --- a/app/views/play/WorldMapView.coffee +++ b/app/views/play/WorldMapView.coffee @@ -97,7 +97,7 @@ module.exports = class WorldMapView extends RootView @$el.find('.level').tooltip() @$el.addClass _.string.slugify @terrain @updateVolume() - @highlightElement '.level.next', delay: 8000, duration: 20000, rotation: 0, sides: ['top'] + @highlightElement '.level.next', delay: 2000, duration: 60000, rotation: 0, sides: ['top'] onSessionsLoaded: (e) -> for session in @sessions.models diff --git a/app/views/play/level/tome/DocFormatter.coffee b/app/views/play/level/tome/DocFormatter.coffee index 3784139a6..220989f09 100644 --- a/app/views/play/level/tome/DocFormatter.coffee +++ b/app/views/play/level/tome/DocFormatter.coffee @@ -83,9 +83,11 @@ module.exports = class DocFormatter @doc.title = if @options.shortenize then @doc.shorterName else @doc.shortName # Grab the language-specific documentation for some sub-properties, if we have it. - toTranslate = [{obj: @doc, prop: 'description'}, {obj: @doc, prop: 'example'}, {obj: @doc, prop: 'returns'}] + toTranslate = [{obj: @doc, prop: 'description'}, {obj: @doc, prop: 'example'}] for arg in (@doc.args ? []) toTranslate.push {obj: arg, prop: 'example'}, {obj: arg, prop: 'description'} + if @doc.returns + toTranslate.push {obj: @doc.returns, prop: 'example'}, {obj: @doc.returns, prop: 'description'} for {obj, prop} in toTranslate if val = obj[prop]?[@options.language] obj[prop] = val diff --git a/app/views/user/AchievementsView.coffee b/app/views/user/AchievementsView.coffee index c5a7f32bb..41517c062 100644 --- a/app/views/user/AchievementsView.coffee +++ b/app/views/user/AchievementsView.coffee @@ -48,9 +48,8 @@ module.exports = class AchievementsView extends UserView # After user is loaded if @user and not @user.isAnonymous() context.earnedAchievements = @earnedAchievements - context.achievements = @achievements context.achievementsByCategory = {} - for achievement in @achievements.models + for achievement in @achievements.models when achievement.get('category') context.achievementsByCategory[achievement.get('category')] ?= [] context.achievementsByCategory[achievement.get('category')].push achievement context