diff --git a/app/lib/surface/Lank.coffee b/app/lib/surface/Lank.coffee index 565b66dc9..c64591207 100644 --- a/app/lib/surface/Lank.coffee +++ b/app/lib/surface/Lank.coffee @@ -141,6 +141,7 @@ module.exports = Lank = class Lank extends CocoClass onSurfaceTicked: (e) -> @age += e.dt playNextAction: => + return if @destroyed @playAction(@actionQueue.splice(0, 1)[0]) if @actionQueue.length playAction: (action) -> diff --git a/app/locale/fr.coffee b/app/locale/fr.coffee index a1aad2098..3f593a927 100644 --- a/app/locale/fr.coffee +++ b/app/locale/fr.coffee @@ -499,7 +499,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t writable: "éditable" # Hover over "attack" in Your Skills while playing a level to see most of this read_only: "lecture seulement" action_name: "nom" - action_cooldown: "Encaisse" + action_cooldown: "Durée" action_specific_cooldown: "Rechargement" action_damage: "Dégât" action_range: "Portée" @@ -878,7 +878,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t diplomat_i18n_page_prefix: "Vous pouvez commencer à traduire nos niveaux en allant sur notre " diplomat_i18n_page: "page de traduction" diplomat_i18n_page_suffix: ", ou notre interface et le site Web sur GitHub." - diplomat_join_pref_github: "Trouvez le fichier de langue souhaité" + diplomat_join_pref_github: "Trouvez le fichier de langue souhaité " diplomat_github_url: "sur GitHub" diplomat_join_suf_github: ", modifiez en ligne, et soumettez des requêtes. Cochez aussi cette case ci-dessous pour vous tenir à jour sur les nouveaux développements d'internationalisation !" diplomat_subscribe_desc: "Recevoir un e-mail sur le développement i18n et les niveaux à traduire." @@ -962,7 +962,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t no_singleplayer: "Aucune partie jouée pour le moment" no_multiplayer: "Aucune partie multijoueur pour le moment" no_achievements: "Aucun succès gagné pour le moment." - favorite_prefix: "Langage favori :" + favorite_prefix: "Langage favori : " favorite_postfix: "." achievements: diff --git a/app/locale/sk.coffee b/app/locale/sk.coffee index fc2697922..d7f98f4f3 100644 --- a/app/locale/sk.coffee +++ b/app/locale/sk.coffee @@ -67,9 +67,9 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak", # poll: "Poll" # Tooltip on poll button from /play next: "Ďalší" # Go from choose hero to choose inventory before playing a level change_hero: "Zmeniť hrdinu" # Go back from choose inventory to choose hero - choose_inventory: "Vyzbrojiť sa s predmetmy" + choose_inventory: "Vyzbrojiť sa s predmetmi" buy_gems: "Zakúpiť drahokamy" - subscription_required: "Vyžaduje sa rredplatné" + subscription_required: "Vyžaduje sa predplatné" older_campaigns: "Staršie kampane" anonymous: "Anonymný hráč" level_difficulty: "Obtiažnosť." @@ -457,16 +457,16 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak", # subscribe_prepaid: "Click Subscribe to use prepaid code" # using_prepaid: "Using prepaid code for monthly subscription" -# choose_hero: -# choose_hero: "Choose Your Hero" -# programming_language: "Programming Language" -# programming_language_description: "Which programming language do you want to use?" -# default: "Default" -# experimental: "Experimental" -# python_blurb: "Simple yet powerful, great for beginners and experts." -# javascript_blurb: "The language of the web. (Not the same as Java.)" -# coffeescript_blurb: "Nicer JavaScript syntax." -# clojure_blurb: "A modern Lisp." + choose_hero: + choose_hero: "Vyber svojho hrdinu" + programming_language: "Programovací jazyk" + programming_language_description: "Aký programovací jazyk chceš použiť ? " + default: "Predvolený" + experimental: "Experimentálny" + python_blurb: "Jednoduchý ale výkonný, skvelý pre začiatočníkov aj expertov" + javascript_blurb: "Jazyk webových stránok. (Nie je to Java)" + coffeescript_blurb: "Krajšia syntax pre JavaScript" + clojure_blurb: "Moderný Lisp" # lua_blurb: "Game scripting language." # io_blurb: "Simple but obscure." # status: "Status" diff --git a/app/models/User.coffee b/app/models/User.coffee index 75d081685..88eaf912f 100644 --- a/app/models/User.coffee +++ b/app/models/User.coffee @@ -119,7 +119,9 @@ module.exports = class User extends CocoModel # Signs and Portents was receiving updates after test started, and also had a big bug on March 4, so just look at test from March 5 on. # ... and stopped working well until another update on March 10, so maybe March 11+... + # ... and another round, and then basically it just isn't completing well, so we pause the test until we can fix it. getFourthLevelGroup: -> + return 'signs-and-portents' return @fourthLevelGroup if @fourthLevelGroup group = me.get('testGroupNumber') % 8 @fourthLevelGroup = switch group diff --git a/app/styles/play/level.sass b/app/styles/play/level.sass index 0c5eb05ce..cd1ba311e 100644 --- a/app/styles/play/level.sass +++ b/app/styles/play/level.sass @@ -63,7 +63,6 @@ $level-resize-transition-time: 0.5s .level-content position: relative - overflow: hidden #canvas-wrapper top: 50px @@ -128,6 +127,10 @@ $level-resize-transition-time: 0.5s top: 0px bottom: 0 @include transition(width $level-resize-transition-time ease-in-out, right $level-resize-transition-time ease-in-out) + z-index: 2 + + #game-area + position: relative overflow: hidden // Level Docs diff --git a/app/styles/play/level/tome/spell.sass b/app/styles/play/level/tome/spell.sass index ca0bf50bb..1a4781c92 100644 --- a/app/styles/play/level/tome/spell.sass +++ b/app/styles/play/level/tome/spell.sass @@ -63,6 +63,7 @@ overflow: visible // https://github.com/codecombat/codecombat/issues/1411#issuecomment-60492750 -- trying to make sure system defaults don't mess up our monospace font. font-family: Monaco, Menlo, Ubuntu Mono, Consolas, "source-code-pro", monospace !important + @include transition(height 0.25s ease-in-out) &.disabled @include opacity(0.8) diff --git a/app/styles/play/level/tome/spell_palette.sass b/app/styles/play/level/tome/spell_palette.sass index 263a793de..91a27a7ab 100644 --- a/app/styles/play/level/tome/spell_palette.sass +++ b/app/styles/play/level/tome/spell_palette.sass @@ -9,13 +9,19 @@ background-color: transparent background-size: 100% 100% z-index: 2 - //overflow-y: auto + @include transition(top 0.25s ease-in-out, height 0.25s ease-in-out) + box-shadow: 10px 4px 4px black + overflow-y: hidden .code-palette-background width: 100% + height: 592px position: absolute left: 0px z-index: -1 + background: transparent url(/images/level/code_palette_wood_background.png) + background-size: 100% 592px + overflow: visible &.controls-disabled .code-palette-background @@ -71,6 +77,9 @@ @include flex-column() @include flex-align-content-start() + &.no-help + margin-top: 3% + .property-entry-item-group display: inline-block min-height: 38px @@ -97,6 +106,15 @@ width: -webkit-calc(100% - 38px) width: calc(100% - 38px) + &.shortenize.hero .properties + .property-entry-item-group + width: 175px + + .spell-palette-entry-view + width: 137px + width: -webkit-calc(100% - 38px) + width: calc(100% - 38px) + @media only screen and (max-width: 1100px) #spell-palette-view // Make sure we have enough room for at least two columns diff --git a/app/styles/play/level/tome/tome.sass b/app/styles/play/level/tome/tome.sass index 924b72e31..d839b7a87 100644 --- a/app/styles/play/level/tome/tome.sass +++ b/app/styles/play/level/tome/tome.sass @@ -4,6 +4,7 @@ #tome-view height: 100% margin-bottom: -20px + overflow: hidden > .popover // Only those popovers which are our direct children (spell documentation) diff --git a/app/templates/play/level.jade b/app/templates/play/level.jade index c042d248c..9b8dca111 100644 --- a/app/templates/play/level.jade +++ b/app/templates/play/level.jade @@ -4,34 +4,36 @@ #control-bar-view #fullscreen-editor-background-screen(title="Click to minimize the code editor") - + #code-area #code-area-gradient.gradient #tome-view - - #canvas-wrapper - canvas(width=924, height=589)#webgl-surface - canvas(width=924, height=589)#normal-surface - #ascii-surface - #canvas-left-gradient.gradient - #canvas-top-gradient.gradient - #goals-view - - #level-flags-view - #gold-view + #game-area - #problem-alert-view + #canvas-wrapper + canvas(width=924, height=589)#webgl-surface + canvas(width=924, height=589)#normal-surface + #ascii-surface + #canvas-left-gradient.gradient + #canvas-top-gradient.gradient + #goals-view - #level-chat-view - - #multiplayer-status-view - - #playback-view - - #thang-hud + #level-flags-view - #level-dialogue-view + #gold-view + + #problem-alert-view + + #level-chat-view + + #multiplayer-status-view + + #playback-view + + #thang-hud + + #level-dialogue-view button.btn.btn-lg.btn-warning.banner.header-font#stop-real-time-playback-button(title="Stop real-time playback", data-i18n="play_level.skip") Skip diff --git a/app/templates/play/level/tome/spell_palette.jade b/app/templates/play/level/tome/spell_palette.jade index 904b8dc1a..4d9af9f42 100644 --- a/app/templates/play/level/tome/spell_palette.jade +++ b/app/templates/play/level/tome/spell_palette.jade @@ -1,4 +1,3 @@ -img(src="/images/level/code_palette_wood_background.png", draggable="false").code-palette-background span.code-palette-background if entryGroupSlugs // Non-hero; group by entry groups, or maybe nothing. @@ -13,6 +12,9 @@ if entryGroupSlugs div(class="properties properties-" + slug + " nano-content") else // Hero; group by items, no tabs. - button.btn.btn-sm.btn-info.banner#spell-palette-help-button(data-i18n="play_level.tome_help") - .properties + if showsHelp + button.btn.btn-sm.btn-info.banner#spell-palette-help-button(data-i18n="play_level.tome_help") + .properties + else + .properties.no-help diff --git a/app/views/play/level/tome/DocFormatter.coffee b/app/views/play/level/tome/DocFormatter.coffee index 49ac48d4e..bc2772db7 100644 --- a/app/views/play/level/tome/DocFormatter.coffee +++ b/app/views/play/level/tome/DocFormatter.coffee @@ -82,6 +82,8 @@ module.exports = class DocFormatter @doc.shorterName = @doc.shortName.replace ';', '' if @doc.owner is 'this' or @options.tabbify @doc.shorterName = @doc.shorterName.replace /^this\./, '' + else if (@options.language in ['python', 'lua']) and (@doc.owner is 'this' or @options.tabbify) + @doc.shorterName = @doc.shortName.replace /^self[:.]/, '' @doc.title = if @options.shortenize then @doc.shorterName else @doc.shortName # Grab the language-specific documentation for some sub-properties, if we have it. diff --git a/app/views/play/level/tome/SpellPaletteView.coffee b/app/views/play/level/tome/SpellPaletteView.coffee index c782661af..f25fc84aa 100644 --- a/app/views/play/level/tome/SpellPaletteView.coffee +++ b/app/views/play/level/tome/SpellPaletteView.coffee @@ -29,6 +29,8 @@ module.exports = class SpellPaletteView extends CocoView @session = options.session @supermodel = options.supermodel @thang = options.thang + docs = @options.level.get('documentation') ? {} + @showsHelp = docs.specificArticles?.length or docs.generalArticles?.length @createPalette() $(window).on 'resize', @onResize @@ -39,6 +41,7 @@ module.exports = class SpellPaletteView extends CocoView c.entryGroupNames = @entryGroupNames c.tabbed = _.size(@entryGroups) > 1 c.defaultGroupSlug = @defaultGroupSlug + c.showsHelp = @showsHelp c afterRender: -> @@ -72,6 +75,7 @@ module.exports = class SpellPaletteView extends CocoView if entryIndex is 0 entry.$el.addClass 'first-entry' @$el.addClass 'hero' + @$el.toggleClass 'shortenize', Boolean @shortenize @updateMaxHeight() unless application.isIPadApp afterInsert: -> @@ -83,18 +87,27 @@ module.exports = class SpellPaletteView extends CocoView updateMaxHeight: -> return unless @isHero - nColumns = Math.floor @$el.find('.properties').innerWidth() / 212 # ~212px is a good max entry width; will always have 2 columns + # We figure out how many columns we can fit, width-wise, and then guess how many rows will be needed. + # We can then assign a height based on the number of rows, and the flex layout will do the rest. + columnWidth = if @shortenize then 175 else 212 + nColumns = Math.floor @$el.find('.properties').innerWidth() / columnWidth # will always have 2 columns, since at 1024px screen we have 424px .properties columns = ({items: [], nEntries: 0} for i in [0 ... nColumns]) + orderedColumns = [] nRows = 0 - for group, entries of @entryGroups + entryGroupsByLength = _.sortBy _.keys(@entryGroups), (group) => @entryGroups[group].length + entryGroupsByLength.reverse() + for group in entryGroupsByLength + entries = @entryGroups[group] continue unless shortestColumn = _.sortBy(columns, (column) -> column.nEntries)[0] - shortestColumn.nEntries += Math.max 2, entries.length + shortestColumn.nEntries += Math.max 2, entries.length # Item portrait is two rows tall shortestColumn.items.push @entryGroupElements[group] + orderedColumns.push shortestColumn unless shortestColumn in orderedColumns nRows = Math.max nRows, shortestColumn.nEntries - for column in columns + for column in orderedColumns for item in column.items item.detach().appendTo @$el.find('.properties') - @$el.find('.properties').css('height', 19 * (nRows + 1)) + desiredHeight = 19 * (nRows + 1) + @$el.find('.properties').css('height', desiredHeight) onResize: (e) => @updateMaxHeight() @@ -151,7 +164,7 @@ module.exports = class SpellPaletteView extends CocoView count += added.length Backbone.Mediator.publish 'tome:update-snippets', propGroups: propGroups, allDocs: allDocs, language: @options.language - shortenize = count > 6 + @shortenize = count > 6 tabbify = count >= 10 @entries = [] for owner, props of propGroups @@ -163,7 +176,7 @@ module.exports = class SpellPaletteView extends CocoView console.log 'could not find doc for', prop, 'from', allDocs['__' + prop], 'for', owner, 'of', propGroups doc ?= prop if doc - @entries.push @addEntry(doc, shortenize, tabbify, owner is 'snippets') + @entries.push @addEntry(doc, @shortenize, tabbify, owner is 'snippets') groupForEntry = (entry) -> return 'more' if entry.doc.owner is 'this' and entry.doc.name in (propGroups.more ? []) entry.doc.owner @@ -229,7 +242,7 @@ module.exports = class SpellPaletteView extends CocoView Backbone.Mediator.publish 'tome:update-snippets', propGroups: propsByItem, allDocs: allDocs, language: @options.language - shortenize = propCount > 6 + @shortenize = propCount > 6 @entries = [] for itemName, props of propsByItem for prop, propIndex in props @@ -243,7 +256,7 @@ module.exports = class SpellPaletteView extends CocoView console.log 'could not find doc for', prop, 'from', allDocs['__' + prop], 'for', owner, 'of', propsByItem, 'with item', item doc ?= prop if doc - @entries.push @addEntry(doc, shortenize, false, owner is 'snippets', item, propIndex > 0) + @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 @@ -264,16 +277,6 @@ module.exports = class SpellPaletteView extends CocoView @controlsEnabled = enabled @$el.find('*').attr('disabled', not enabled) @$el.toggleClass 'controls-disabled', not enabled - @toggleBackground() - - toggleBackground: => - # TODO: make the palette background an actual background and do the CSS trick - # used in spell_list_entry.sass for disabling - background = @$el.find('img.code-palette-background')[0] - if background.naturalWidth is 0 # not loaded yet - return _.delay @toggleBackground, 100 - filters.revertImage background, 'span.code-palette-background' if @controlsEnabled - filters.darkenImage background, 'span.code-palette-background', 0.8 unless @controlsEnabled onFrameChanged: (e) -> return unless e.selectedThang?.id is @thang.id diff --git a/app/views/play/level/tome/SpellView.coffee b/app/views/play/level/tome/SpellView.coffee index 78dc7b008..797ac1154 100644 --- a/app/views/play/level/tome/SpellView.coffee +++ b/app/views/play/level/tome/SpellView.coffee @@ -568,15 +568,22 @@ module.exports = class SpellView extends CocoView @lastScreenLineCount = screenLineCount lineHeight = @ace.renderer.lineHeight or 20 tomeHeight = $('#tome-view').innerHeight() + spellPaletteView = $('#spell-palette-view') spellListTabEntryHeight = $('#spell-list-tab-entry-view').outerHeight() spellToolbarHeight = $('.spell-toolbar-view').outerHeight() - spellPaletteHeight = $('#spell-palette-view').outerHeight() - maxHeight = tomeHeight - spellListTabEntryHeight - spellToolbarHeight - spellPaletteHeight + @spellPaletteHeight ?= spellPaletteView.outerHeight() # Remember this until resize, since we change it afterward + spellPaletteAllowedHeight = Math.min @spellPaletteHeight, tomeHeight / 3 + maxHeight = tomeHeight - spellListTabEntryHeight - spellToolbarHeight - spellPaletteAllowedHeight linesAtMaxHeight = Math.floor(maxHeight / lineHeight) lines = Math.max 8, Math.min(screenLineCount + 2, linesAtMaxHeight) # 2 lines buffer is nice @ace.setOptions minLines: lines, maxLines: lines - $('#spell-palette-view').css('top', 175 + lineHeight * lines) # Move spell palette up, slightly overlapping us. + # Move spell palette up, slightly overlapping us. + newTop = 175 + lineHeight * lines + spellPaletteView.css('top', newTop) + # Expand it to bottom of tome if too short. + newHeight = Math.max @spellPaletteHeight, tomeHeight - newTop + 10 + spellPaletteView.css('height', newHeight) if @spellPaletteHeight isnt newHeight hideProblemAlert: -> Backbone.Mediator.publish 'tome:hide-problem-alert', {} @@ -1035,6 +1042,8 @@ module.exports = class SpellView extends CocoView _.delay (=> @resize()), 500 + 100 # Wait $level-resize-transition-time, plus a bit. onWindowResize: (e) => + @spellPaletteHeight = null + $('#spell-palette-view').css 'height', 'auto' # Let it go back to controlling its own height _.delay (=> @resize?()), 500 + 100 # Wait $level-resize-transition-time, plus a bit. resize: -> diff --git a/scripts/mongodb/createBulkPrepaids.js b/scripts/mongodb/createBulkPrepaids.js new file mode 100644 index 000000000..cd4d6920e --- /dev/null +++ b/scripts/mongodb/createBulkPrepaids.js @@ -0,0 +1,60 @@ +// Bulk create prepaid codes + email message + +// Usage: +// mongo <address>:<port>/<database> <script file> -u <username> -p <password> + +var num = 10; +var message = "Thanks for filling out the form. You can follow this link to enable your free teacher subscription. If you have any questions or comments, please let me know."; +var urlPrefix = "https://codecombat.com/account/subscription?_ppc="; +var creatorID = "52f94443fcb334581466a992"; + +for (var i = 0; i < num; i++) { + createPrepaid(); +} + +function createPrepaid() +{ + generateNewCode(function(code) { + if (!code) { + print("ERROR: no code"); + return; + } + criteria = { + creator: creatorID, + type: 'subscription', + status: 'active', + code: code, + properties: { + couponID: 'free' + }, + __v: 0 + }; + db.prepaids.insert(criteria); + + print(message + " " + urlPrefix + code); + }); +} + +function generateNewCode(done) +{ + function tryCode() { + code = createCode(8); + criteria = {code: code}; + if (db.prepaids.findOne(criteria)) { + return tryCode(); + } + return done(code); + } + tryCode(); +} + +function createCode(length) +{ + var text = ""; + var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + + for( var i=0; i < length; i++ ) + text += possible.charAt(Math.floor(Math.random() * possible.length)); + + return text; +} diff --git a/server/routes/mail.coffee b/server/routes/mail.coffee index 44a923160..2f698cdc4 100644 --- a/server/routes/mail.coffee +++ b/server/routes/mail.coffee @@ -706,9 +706,10 @@ sendNextStepsEmail = (user, now, daysAgo) -> return log.error "Couldn't find next level for #{user.get('email')}: #{err}" if err name = if user.get('firstName') and user.get('lastName') then "#{user.get('firstName')}" else user.get('name') name = 'hero' if not name or name is 'Anoner' - secretLevel = switch user.get('testGroupNumber') % 8 - when 0, 1, 2, 3 then name: 'Forgetful Gemsmith', slug: 'forgetful-gemsmith' - when 4, 5, 6, 7 then name: 'Signs and Portents', slug: 'signs-and-portents' + #secretLevel = switch user.get('testGroupNumber') % 8 + # when 0, 1, 2, 3 then name: 'Forgetful Gemsmith', slug: 'forgetful-gemsmith' + # when 4, 5, 6, 7 then name: 'Signs and Portents', slug: 'signs-and-portents' + secretLevel = name: 'Signs and Portents', slug: 'signs-and-portents' # We turned off this test for now and are sending everyone to forgetful-gemsmith # TODO: make this smarter, actually data-driven, looking at all available sessions shadowGuardSession = _.find sessions, levelID: 'shadow-guard'