From fde11d8f0d56bd97626e9bbb00846ab004aebaff Mon Sep 17 00:00:00 2001 From: Scott Erickson Date: Wed, 6 Jan 2016 13:48:54 -0800 Subject: [PATCH 01/10] Add fill defaults button to solutions treema node in level editor --- .../component/ThangComponentConfigView.coffee | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/app/views/editor/component/ThangComponentConfigView.coffee b/app/views/editor/component/ThangComponentConfigView.coffee index 084d72eae..8f8580043 100644 --- a/app/views/editor/component/ThangComponentConfigView.coffee +++ b/app/views/editor/component/ThangComponentConfigView.coffee @@ -73,6 +73,7 @@ module.exports = class ThangComponentConfigView extends CocoView 'acceleration': nodes.AccelerationNode 'thang-type': nodes.ThangTypeNode 'item-thang-type': nodes.ItemThangTypeNode + 'solutions': SolutionsNode @editThangTreema = @$el.find('.treema').treema treemaOptions @editThangTreema.build() @@ -94,3 +95,30 @@ module.exports = class ThangComponentConfigView extends CocoView class ComponentConfigNode extends TreemaObjectNode nodeDescription: 'Component Property' + +class SolutionsNode extends TreemaArrayNode + buildValueForDisplay: (valEl, data) -> + btn = $('') + btn.on('click', @onClickFillDefaults) + valEl.append(btn) + + onClickFillDefaults: (e) => + e.preventDefault() + sources = {} + if source = @parent.data.source + sources.javascript = source + + sources = { javascript: @parent.data.source } + _.extend sources, @parent.data.languages or {} + solutions = _.clone(@data) + for language in _.keys(sources) + source = sources[language] + solution = _.findWhere(solutions, {language: language}) + continue if solution + solutions.push({ + source: source + language: language + passes: true + }) + + @set('/', solutions) \ No newline at end of file From 93b9aa3c2c1432dd6a157e5a7a5854ff66d1e748 Mon Sep 17 00:00:00 2001 From: Scott Erickson Date: Wed, 6 Jan 2016 16:11:28 -0800 Subject: [PATCH 02/10] Add DesignElementsView (mostly complete) --- app/core/Router.coffee | 1 + app/templates/admin.jade | 2 + app/templates/admin/design-elements-view.jade | 456 ++++++++++++++++++ app/views/admin/DesignElementsView.coffee | 16 + 4 files changed, 475 insertions(+) create mode 100644 app/templates/admin/design-elements-view.jade create mode 100644 app/views/admin/DesignElementsView.coffee diff --git a/app/core/Router.coffee b/app/core/Router.coffee index 6e6bcb5df..e4025a118 100644 --- a/app/core/Router.coffee +++ b/app/core/Router.coffee @@ -27,6 +27,7 @@ module.exports = class CocoRouter extends Backbone.Router 'admin': go('admin/MainAdminView') 'admin/clas': go('admin/CLAsView') + 'admin/design-elements': go('admin/DesignElementsView') 'admin/files': go('admin/FilesView') 'admin/analytics': go('admin/AnalyticsView') 'admin/analytics/subscriptions': go('admin/AnalyticsSubscriptionsView') diff --git a/app/templates/admin.jade b/app/templates/admin.jade index 864fe1041..795bc9190 100644 --- a/app/templates/admin.jade +++ b/app/templates/admin.jade @@ -49,6 +49,8 @@ block content ul li a(href="/admin/analytics/subscriptions") Subscriptions + li + a(href="/admin/design-elements") Design Elements if me.isAdmin() hr diff --git a/app/templates/admin/design-elements-view.jade b/app/templates/admin/design-elements-view.jade new file mode 100644 index 000000000..d50cdb3e3 --- /dev/null +++ b/app/templates/admin/design-elements-view.jade @@ -0,0 +1,456 @@ +.well.container-fluid + h1 Bootstrap CSS + + .row + .col-sm-6 + .panel.panel-default + .panel-heading + a#tables.panel-title(href="#tables") Tables + + .panel-body + mixin table-content + tr + th # + th First Name + th Last Name + th Username + tr + th 1 + td Mark + td Otto + td @mdo + tr + th 2 + td Jacob + td Thornton + td @fat + tr + th 3 + td Larry + td the Bird + td @twitter + + h3 Basic + table.table + +table-content + + h3 Bordered + table.table.table-bordered + +table-content + + h3 Striped + table.table.table-striped + +table-content + + .col-sm-6 + .panel.panel-default + .panel-heading + a#tables.panel-title(href="#tables") Tables + + .panel-body + + h3 Hover + table.table.table-hover + +table-content + + h3 Condensed + table.table.table-condensed + +table-content + + h3 Context + table.table + tr.active + td Active + tr.success + td Success + tr.info + td Info + tr.warning + td Warning + tr.danger + td Danger + + .col-sm-3 + .panel.panel-default + .panel-heading + a#headers.panel-title(href="#headers") Headers + + .panel-body + h1 Header 1 + small.spl secondary text + h2 Header 2 + small.spl secondary text + h3 Header 3 + small.spl secondary text + h4 Header 4 + small.spl secondary text + h5 Header 5 + small.spl secondary text + h6 Header 6 + small.spl secondary text + + .panel.panel-default + .panel-heading + a#user-input.panel-title(href="#user-input") User input + + .panel-body + kbd ctrl + , + + .panel.panel-default + .panel-heading + a#horizontal-rule.panel-title(href="#horizontal-rule") Horizontal Rule + + .panel-body + div Text above + hr + div Text below + + .col-sm-3 + + .panel.panel-default + .panel-heading + a#forms.panel-title(href="#forms") Forms + + .panel-body + h3 Default + .form + .form-group + label.control-label Input + input.form-control + + .form-group + label.control-label Textarea + textarea.form-control + .help-block Help block + + .form-group + label.control-label Select + select.form-control + option Option 1 + option Option 2 + + .form-group + label Disabled + input.form-control(disabled=true) + + .form-group.has-error + label.control-label Validation error + input.form-control + + .form-group + label Large input + input.form-control.input-lg + + .form-group + label Small input + input.form-control.input-sm + + .col-sm-3 + .panel.panel-default + .panel-heading + a#buttons.panel-title(href="#buttons") Buttons + + .panel-body + div + button.btn.btn-default Default + span.spr + button.btn.btn-primary Primary + span.spr + button.btn.btn-success Success + span.spr + button.btn.btn-info Info + span.spr + button.btn.btn-warning Warning + span.spr + button.btn.btn-danger Danger + span.spr + button.btn.btn-default(disabled=true) Disabled + + + hr + + div + button.btn.btn-default.btn-lg Large + span.spr + button.btn.btn-default Default + span.spr + button.btn.btn-default.btn-sm Small + span.spr + button.btn.btn-default.btn-xs Extra small + + hr + + div + button.btn.btn-default.btn-illustrated Default illustrated + span.spr + button.btn.btn-primary.btn-illustrated Primary illustrated + span.spr + button.btn.btn-success.btn-illustrated Success illustrated + span.spr + button.btn.btn-info.btn-illustrated Info illustrated + span.spr + button.btn.btn-warning.btn-illustrated Warning illustrated + span.spr + button.btn.btn-danger.btn-illustrated Danger illustrated + + .panel.panel-default + .panel-heading + a#contextual-text.panel-title(href="#contextual-text") Contextual text + + .panel-body + p.text-muted Muted text + p.text-primary Primary text + p.text-success Success text + p.text-info Info text + p.text-warning Warning text + p.text-danger Danger text + + h1 Bootstrap Components + + .row + .col-sm-3 + + .panel.panel-default + .panel-heading + a#dropdowns.panel-title(href="#dropdowns") Dropdowns + + .panel-body + .btn-group + button.btn.btn-default.dropdown-toggle(data-toggle="dropdown") Dropdown Button + ul.dropdown-menu + li + a Action + li + a Another action + + .panel.panel-default + .panel-heading + a#navs.panel-title(href="#navs") Navs + + .panel-body + ul.nav.nav-tabs + li.active + a Home + li + a Profile + li + a Message + + hr + + ul.nav.nav-pills + li.active + a Home + li + a Profile + li + a Message + + .panel.panel-default + .panel-heading + a#navbars.panel-title(href="#navbars") Navbars + + .panel-body + nav.navbar.navbar-default + .container-fluid + .navbar-header + button.navbar-toggle.collapsed(data-toggle="collapse", data-target="#main-nav") + span.glyphicon.glyphicon-option-horizontal + a.navbar-brand Brand + + .collapse.navbar-collapse#main-nav + ul.nav.navbar-nav + li.active + a Link + li + a Link + + .panel.panel-default + .panel-heading + a#breadcrumbs.panel-title(href="#breadcrumbs") Breadcrumbs + + .panel-body + ol.breadcrumb + li Home + li Library + li.active Data + + .panel.panel-default + .panel-heading + a#labels.panel-title(href="#labels") Labels + .panel-body + span.label.label-default default + span.spr + span.label.label-primary primary + span.spr + span.label.label-success success + span.spr + span.label.label-info info + span.spr + span.label.label-warning warning + span.spr + span.label.label-danger danger + + .col-sm-3 + .panel.panel-default + .panel-heading + a#alerts.panel-title(href="#alerts") Alerts + + .panel-body + .alert.alert-success Success + .alert.alert-info Info + .alert.alert-warning Warning + .alert.alert-danger Danger + + .panel.panel-default + .panel-heading + a#progress-bars.panel-title(href="#progress-bars") Progress Bars + + .panel-body + strong Default + .progress + .progress-bar(style="width: 50%") + + strong Striped Active + .progress.progress-striped.active + .progress-bar(style="width: 50%") + + strong Contextual + .progress + .progress-bar.progress-bar-success(style="width: 25%") Success + .progress-bar.progress-bar-info(style="width: 25%") Info + .progress-bar.progress-bar-warning(style="width: 25%") Warning + .progress-bar.progress-bar-danger(style="width: 25%") Danger + + .col-sm-3 + .panel.panel-default + .panel-heading + a#list-groups.panel-title(href="#list-groups") List Groups + + .panel-body + ul.list-group + li.list-group-item List group item 1 + li.list-group-item List group item 2 + li.list-group-item List group item 3 + + .panel.panel-info + .panel-heading + .panel-title Info Panel w/Title + .panel-body And body + .panel-footer And footer + + .panel.panel-primary + .panel-heading + .panel-title Primary Panel w/Title + .panel-body And body + .panel-footer And footer + + .panel.panel-default + .panel-heading + .panel-title Default Panel w/Title + .panel-body And body + .panel-footer And footer + + .col-sm-3 + .panel.panel-success + .panel-heading + .panel-title Success Panel w/Title + .panel-body And body + .panel-footer And footer + + .panel.panel-warning + .panel-heading + .panel-title warning Panel w/Title + .panel-body And body + .panel-footer And footer + + .panel.panel-danger + .panel-heading + .panel-title Danger Panel w/Title + .panel-body And body + .panel-footer And footer + + .col-sm-3 + .panel.panel-default + .panel-heading + a#wells.panel-title(href="#wells") Wells + + .panel-body + .well Well! + .well.well-lg Large well! + .well.well-sm Small well! + + h1 Bootstrap JavaScript + + .row + .col-sm-6 + .panel.panel-default + .panel-heading + a#modals.panel-title(href="#modals") Default Modal + + .panel-body(style="background: lightgrey")#modal-1 + include /templates/core/modal-base + + .col-sm-6 + .panel.panel-default + .panel-heading + a.panel-title Plain Modal + + .panel-body(style="background: lightgrey")#modal-2 + include /templates/core/modal-base + + .row + .col-sm-3 + .panel.panel-default + .panel-heading + a#tooltips.panel-title(href="#tooltips") Tooltips + + .panel-body + button#tooltip.btn.btn-default(title="tooltip text!", data-placement="right", data-trigger="manual") Button w/Tooltip + + .col-sm-3 + .panel.panel-default + .panel-heading + a#popovers.panel-title(href="#popovers") Popovers + + .panel-body + button#popover.btn.btn-default(title="Popover title" data-content="Popover content" data-trigger="manual") Button w/Popover + + + h1 jQuery UI + + .row + .col-sm-3 + .panel.panel-default + .panel-heading + a#autocomplete.panel-title(href="#autocomplete") Autocomplete + + .panel-body + + .col-sm-3 + .panel.panel-default + .panel-heading + a#slider.panel-title(href="#slider") Slider + + .panel-body + + h1 Other + + .row + .col-sm-3 + .panel.panel-default + .panel-heading + a#gems.panel-title(href="#gems") Gems + .panel-body + .gem.gem-20 + .gem.gem-25 + .gem.gem-30 + .gem.gem-40 + .gem.gem-60 + + .col-sm-3 + .panel.panel-default + .panel-heading + a#no-border-image.panel-title(href="#no-border-image") No Border Image + + .panel-body \ No newline at end of file diff --git a/app/views/admin/DesignElementsView.coffee b/app/views/admin/DesignElementsView.coffee new file mode 100644 index 000000000..e725f9ba5 --- /dev/null +++ b/app/views/admin/DesignElementsView.coffee @@ -0,0 +1,16 @@ +RootView = require 'views/core/RootView' +template = require 'templates/admin/design-elements-view' + +module.exports = class DesignElementsView extends RootView + id: 'design-elements-view' + template: template + + afterInsert: -> + super() + # hack to get hash links to work. Make this general? + hash = document.location.hash + document.location.hash = '' + setTimeout((-> document.location.hash = hash), 10) + @$('#modal-2').find('.background-wrapper').addClass('plain') + setTimeout((=> @$('#tooltip').tooltip('show')), 20) + setTimeout((=> @$('#popover').popover('show')), 20) \ No newline at end of file From 5941c4b27ffd4a867007400baa0458cefc7ead79 Mon Sep 17 00:00:00 2001 From: Scott Erickson Date: Wed, 6 Jan 2016 16:33:50 -0800 Subject: [PATCH 03/10] Add autocomplete and slider to design elements view, limit showing javascript widgets automagically --- app/templates/admin/design-elements-view.jade | 6 ++-- app/views/admin/DesignElementsView.coffee | 34 +++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/app/templates/admin/design-elements-view.jade b/app/templates/admin/design-elements-view.jade index d50cdb3e3..9ad8d2bfe 100644 --- a/app/templates/admin/design-elements-view.jade +++ b/app/templates/admin/design-elements-view.jade @@ -406,7 +406,7 @@ a#tooltips.panel-title(href="#tooltips") Tooltips .panel-body - button#tooltip.btn.btn-default(title="tooltip text!", data-placement="right", data-trigger="manual") Button w/Tooltip + button#tooltip.btn.btn-default(title="tooltip text!", data-placement="right", data-trigger="click") Button w/Tooltip .col-sm-3 .panel.panel-default @@ -414,7 +414,7 @@ a#popovers.panel-title(href="#popovers") Popovers .panel-body - button#popover.btn.btn-default(title="Popover title" data-content="Popover content" data-trigger="manual") Button w/Popover + button#popover.btn.btn-default(title="Popover title" data-content="Popover content" data-trigger="click") Button w/Popover h1 jQuery UI @@ -426,6 +426,7 @@ a#autocomplete.panel-title(href="#autocomplete") Autocomplete .panel-body + input#tags .col-sm-3 .panel.panel-default @@ -433,6 +434,7 @@ a#slider.panel-title(href="#slider") Slider .panel-body + #slider-example h1 Other diff --git a/app/views/admin/DesignElementsView.coffee b/app/views/admin/DesignElementsView.coffee index e725f9ba5..b8e564824 100644 --- a/app/views/admin/DesignElementsView.coffee +++ b/app/views/admin/DesignElementsView.coffee @@ -12,5 +12,35 @@ module.exports = class DesignElementsView extends RootView document.location.hash = '' setTimeout((-> document.location.hash = hash), 10) @$('#modal-2').find('.background-wrapper').addClass('plain') - setTimeout((=> @$('#tooltip').tooltip('show')), 20) - setTimeout((=> @$('#popover').popover('show')), 20) \ No newline at end of file + if hash is '#tooltips' + setTimeout((=> @$('#tooltip').tooltip('show')), 20) + if hash is '#popovers' + setTimeout((=> @$('#popover').popover('show')), 20) + tags = [ + "ActionScript", + "AppleScript", + "Asp", + "BASIC", + "C", + "C++", + "Clojure", + "COBOL", + "ColdFusion", + "Erlang", + "Fortran", + "Groovy", + "Haskell", + "Java", + "JavaScript", + "Lisp", + "Perl", + "PHP", + "Python", + "Ruby", + "Scala", + "Scheme" + ] + @$('#tags').autocomplete({source: tags}) + if hash is '#autocomplete' + setTimeout((=> @$('#tags').autocomplete("search", "t")), 20) + @$('#slider-example').slider() \ No newline at end of file From 13b9d81e4cd432d2290eb95f5247b8cc8a34315c Mon Sep 17 00:00:00 2001 From: Scott Erickson Date: Thu, 7 Jan 2016 09:40:35 -0800 Subject: [PATCH 04/10] Fix some demo views --- app/core/ModuleLoader.coffee | 1 + app/views/DemoView.coffee | 27 ++++------- config.coffee | 2 +- .../achievement/AchievementGet.demo.coffee | 4 +- .../common/LevelSessionCodeView.demo.coffee | 8 ++-- .../views/common/level-session.fixture.coffee | 47 +++++++++++++++++++ test/demo/views/common/level.fixture.coffee | 21 +++++++++ .../AddThangComponentsModal.demo.coffee | 2 +- 8 files changed, 87 insertions(+), 25 deletions(-) create mode 100644 test/demo/views/common/level-session.fixture.coffee create mode 100644 test/demo/views/common/level.fixture.coffee diff --git a/app/core/ModuleLoader.coffee b/app/core/ModuleLoader.coffee index f11a5591d..401b35735 100644 --- a/app/core/ModuleLoader.coffee +++ b/app/core/ModuleLoader.coffee @@ -21,6 +21,7 @@ module.exports = ModuleLoader = class ModuleLoader extends CocoClass # vendor libraries aren't actually wrapped with common.js, so short circuit those requires return {} if _.string.startsWith(name, 'vendor/') return {} if name is 'tests' + return {} if name is 'demo-app' name = 'core/auth' if name is 'lib/auth' # proxy for iPad until it's been updated to use the new, refactored location. TODO: remove this return func(name, loaderPath) _.extend wrapped, window.require # for functions like 'list' diff --git a/app/views/DemoView.coffee b/app/views/DemoView.coffee index b59ccdcb3..c250ea355 100644 --- a/app/views/DemoView.coffee +++ b/app/views/DemoView.coffee @@ -6,6 +6,9 @@ requireUtils = require 'lib/requireUtils' DEMO_REQUIRE_PREFIX = 'test/demo/' DEMO_URL_PREFIX = '/demo/' +require 'vendor/jasmine-bundle' +require 'demo-app' + ### What are demo files? @@ -33,24 +36,8 @@ module.exports = DemoView = class DemoView extends RootView constructor: (options, @subPath='') -> super(options) @subPath = @subPath[1..] if @subPath[0] is '/' - @loadDemoingLibs() unless DemoView.loaded - - loadDemoingLibs: -> - DemoView.loaded = true - @queue = new createjs.LoadQueue() - @queue.on('complete', @scriptsLoaded, @) - window.jasmine = {} # so that mock-ajax properly loads. It expects jasmine to be loaded - for f in ['mock-ajax', 'demo-app'] - @queue.loadFile({ - src: "/javascripts/#{f}.js" - type: createjs.LoadQueue.JAVASCRIPT - }) - - scriptsLoaded: -> @initDemoFiles() @children = requireUtils.parseImmediateChildren(@demoFiles, @subPath, DEMO_REQUIRE_PREFIX, DEMO_URL_PREFIX) - @render() - @runDemo() # RENDER DATA @@ -61,6 +48,10 @@ module.exports = DemoView = class DemoView extends RootView parts = @subPath.split('/') c.currentFolder = parts[parts.length-1] or parts[parts.length-2] or 'All' c + + afterInsert: -> + super() + @runDemo() # RUNNING DEMOS @@ -82,6 +73,7 @@ module.exports = DemoView = class DemoView extends RootView jasmine.Ajax.install() view = demoFunc() return unless view + @ranDemo = true if view instanceof ModalView @openModalView(view) else @@ -97,4 +89,5 @@ module.exports = DemoView = class DemoView extends RootView destroy: -> # hack to get jasmine tests to properly run again on clicking links, and make sure if you # leave this page (say, back to the main site) that test stuff doesn't follow you. - document.location.reload() + if @ranDemo + document.location.reload() diff --git a/config.coffee b/config.coffee index 8edc4f604..3085e53d9 100644 --- a/config.coffee +++ b/config.coffee @@ -130,7 +130,7 @@ exports.config = #- test, demo libraries 'javascripts/app/tests.js': regJoin('^test/app/') - 'javascripts/demo-app.js': regJoin('^test/demo/') + 'javascripts/app/demo-app.js': regJoin('^test/demo/') #- More output files are generated at the below diff --git a/test/demo/views/achievement/AchievementGet.demo.coffee b/test/demo/views/achievement/AchievementGet.demo.coffee index 697843c2e..661f20fb6 100644 --- a/test/demo/views/achievement/AchievementGet.demo.coffee +++ b/test/demo/views/achievement/AchievementGet.demo.coffee @@ -1,6 +1,6 @@ CocoModel = require 'models/CocoModel' -RootView = require 'views/kinds/RootView' -utils = require 'lib/utils' +RootView = require 'views/core/RootView' +utils = require 'core/utils' Achievement = require 'models/Achievement' EarnedAchievement = require 'models/EarnedAchievement' fixtures = require '../../fixtures/achievements' diff --git a/test/demo/views/common/LevelSessionCodeView.demo.coffee b/test/demo/views/common/LevelSessionCodeView.demo.coffee index a7aa3810e..11648ac02 100644 --- a/test/demo/views/common/LevelSessionCodeView.demo.coffee +++ b/test/demo/views/common/LevelSessionCodeView.demo.coffee @@ -1,13 +1,13 @@ LevelSessionCodeView = require 'views/common/LevelSessionCodeView' LevelSession = require 'models/LevelSession' -levelSessionData = {"_id":"5317ad4909098828ed071f4d","level":{"original":"53173f76c269d400000543c2","majorVersion":0},"team":"humans","levelID":"dungeon-arena","levelName":"Dungeon Arena","submitted":true,"totalScore":38.4584087145667,"code":{"programmable-librarian":{"chooseAction":"// The Librarian is a spellcaster with a fireball attack\n// plus three useful spells: 'slow', 'regen', and 'haste'.\n// Slow makes a target move and attack at half speed for 5s.\n// Regen makes a target heal 10 hp/s for 10s.\n// Haste speeds up a target by 4x for 5s, once per match.\n\nvar enemies = this.getEnemies();\nif (enemies.length === 0) return; // Chill if all enemies are dead.\nvar enemy = this.getNearest(enemies);\nif (this.canCast('slow', enemy)) {\n // Slow the enemy, or chase if out of range (30m).\n this.castSlow(enemy);\n if (this.distance(enemy) <= 50)\n this.say(\"Not so fast, \" + enemy.type + \" \" + enemy.id);\n}\nelse {\n this.attack(enemy);\n}\nvar base = this.getFriends()[0];\nvar d = base.distance(enemy);\n// You can also command your troops with this.say():\n//this.say(\"Defend!\", {targetPos: {x: 30, y: 30}}));\n//this.say(\"Attack!\", {target: enemy});\n//this.say(\"Move!\", {targetPos: {x: 50, y: 40});\n"},"human-base":{"chooseAction":"// This is the code for your base. Decide which unit to build each frame.\n// Units you build will go into the this.built array.\n// Destroy the enemy base within 60 seconds!\n// Check out the Guide at the top for more info.\n\n// CHOOSE YOUR HERO! You can only build one hero.\nvar hero;\n//hero = 'tharin'; // A fierce knight with battlecry abilities.\nhero = 'hushbaum'; // A fiery spellcaster hero.\n\nif(hero && !this.builtHero) {\n this.builtHero = this.build(hero);\n return;\n}\n\n// Soldiers are hard-to-kill, low damage melee units with 2s build cooldown.\n// Archers are fragile but deadly ranged units with 2.5s build cooldown.\nvar buildOrder = ['soldier', 'soldier', 'soldier', 'soldier', 'archer'];\nvar type = buildOrder[this.built.length % buildOrder.length];\n//this.say('Unit #' + this.built.length + ' will be a ' + type);\nthis.build(type);"},"hushbaum":{"chooseAction":"var enemy = this.getNearestEnemy();\nif (enemy) {\n if (!enemy.hasEffect('slow')) {\n this.say(\"Not so fast, \" + enemy.type + \" \" + enemy.id);\n this.castSlow(enemy);\n }\n else {\n this.attack(enemy);\n }\n}\nelse {\n this.move({x: 70, y: 30});\n}\n"},"tharin":{"chooseAction":"var enemies = this.getEnemies();\nvar enemy = this.getNearest(enemies);\nif (!this.getCooldown('warcry')) {\n this.warcry();\n}\nelse if (enemy) {\n this.attack(enemy);\n}\nelse {\n this.move({x: 10, y: 30});\n}\n"},"tharin-1":{"chooseAction":"var __interceptThis=(function(){var G=this;return function($this,sandbox){if($this==G){return sandbox;}return $this;};})();\nreturn (function (__global) {\n var tmp0, tmp1;\n tmp1 = function () {\n _aether.logCallStart(this._aetherUserInfo); var enemies, enemy, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17, tmp18, tmp19, tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26;\n tmp2 = 'use strict';\n tmp3 = __interceptThis(this, __global);\n tmp4 = 'getEnemies';\n _aether.logStatementStart([{ofs: 0, row: 0, col: 0}, {ofs: 32, row: 0, col: 32}]); enemies = tmp3[tmp4](); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 0, row: 0, col: 0}, {ofs: 32, row: 0, col: 32}], \"var enemies = this.getEnemies();\", this._aetherUserInfo);\n tmp5 = __interceptThis(this, __global);\n tmp6 = 'getNearest';\n tmp7 = enemies;\n _aether.logStatementStart([{ofs: 33, row: 1, col: 0}, {ofs: 70, row: 1, col: 37}]); enemy = tmp5[tmp6](tmp7); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 33, row: 1, col: 0}, {ofs: 70, row: 1, col: 37}], \"var enemy = this.getNearest(enemies);\", this._aetherUserInfo);\n tmp10 = __interceptThis(this, __global);\n tmp11 = 'getCooldown';\n _aether.logStatementStart([{ofs: 93, row: 2, col: 22}, {ofs: 101, row: 2, col: 30}]); tmp12 = 'warcry'; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 93, row: 2, col: 22}, {ofs: 101, row: 2, col: 30}], \"'warcry'\", this._aetherUserInfo);\n _aether.logStatementStart([{ofs: 76, row: 2, col: 5}, {ofs: 102, row: 2, col: 31}]); tmp9 = tmp10[tmp11](tmp12); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 76, row: 2, col: 5}, {ofs: 102, row: 2, col: 31}], \"this.getCooldown('warcry')\", this._aetherUserInfo);\n _aether.logStatementStart([{ofs: 75, row: 2, col: 4}, {ofs: 102, row: 2, col: 31}]); tmp8 = !tmp9; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 75, row: 2, col: 4}, {ofs: 102, row: 2, col: 31}], \"!this.getCooldown('warcry')\", this._aetherUserInfo);\n if (tmp8) {\n tmp13 = __interceptThis(this, __global);\n tmp14 = 'warcry';\n _aether.logStatementStart([{ofs: 110, row: 3, col: 4}, {ofs: 123, row: 3, col: 17}]); tmp15 = tmp13[tmp14](); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 110, row: 3, col: 4}, {ofs: 123, row: 3, col: 17}], \"this.warcry()\", this._aetherUserInfo);\n } else {\n tmp16 = enemy;\n if (tmp16) {\n tmp17 = __interceptThis(this, __global);\n tmp18 = 'attack';\n tmp19 = enemy;\n _aether.logStatementStart([{ofs: 149, row: 6, col: 4}, {ofs: 167, row: 6, col: 22}]); tmp20 = tmp17[tmp18](tmp19); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 149, row: 6, col: 4}, {ofs: 167, row: 6, col: 22}], \"this.attack(enemy)\", this._aetherUserInfo);\n } else {\n tmp21 = __interceptThis(this, __global);\n tmp22 = 'move';\n _aether.logStatementStart([{ofs: 196, row: 9, col: 18}, {ofs: 198, row: 9, col: 20}]); tmp24 = 10; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 196, row: 9, col: 18}, {ofs: 198, row: 9, col: 20}], \"10\", this._aetherUserInfo);\n _aether.logStatementStart([{ofs: 203, row: 9, col: 25}, {ofs: 205, row: 9, col: 27}]); tmp25 = 30; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 203, row: 9, col: 25}, {ofs: 205, row: 9, col: 27}], \"30\", this._aetherUserInfo);\n _aether.logStatementStart([{ofs: 192, row: 9, col: 14}, {ofs: 206, row: 9, col: 28}]); tmp23 = {\n x: tmp24,\n y: tmp25\n }; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 192, row: 9, col: 14}, {ofs: 206, row: 9, col: 28}], \"{x: 10, y: 30}\", this._aetherUserInfo);\n _aether.logStatementStart([{ofs: 182, row: 9, col: 4}, {ofs: 207, row: 9, col: 29}]); tmp26 = tmp21[tmp22](tmp23); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 182, row: 9, col: 4}, {ofs: 207, row: 9, col: 29}], \"this.move({x: 10, y: 30})\", this._aetherUserInfo);\n }\n }\n _aether.logCallEnd(); return;\n };\n tmp0 = 'chooseAction';\n __global[tmp0] = tmp1;\n}(this));"},"programmable-tharin":{"chooseAction":"/*this.getFriends();\nthis.attack(this.getEnemies()[0]);\nreturn;\n*/\n \n\n/* TODO:\n If they fully base race us, we actually do want to produce archers since they DPS faster\n The effective DPS on soldiers is better if they attack us\n but worse if they straight race us\n\n //not sure if this is good but...\n if they're attacking our base with a small number of units\n we should make archers and get them to defend\n*/\n/*\nreturn;\n// Tharin is a melee fighter with shield, warcry, and terrify skills.\n// this.shield() lets him take one-third damage while defending.\n// this.warcry() gives allies within 10m 30% haste for 5s, every 10s.\n// this.terrify() sends foes within 30m fleeing for 5s, once per match.\nvar friends = this.getFriends();\nvar enemies = this.getEnemies();\nif (enemies.length === 0) return; // Chill if all enemies are dead.\nvar enemy = this.getNearest(enemies);\nvar furthestFriendX = 30;\nfor (var i = 0; i < friends.length; ++i) {\n var friend = friends[i];\n furthestFriendX = Math.max(friend.pos.x, furthestFriendX);\n} \nif (!this.getCooldown('warcry') && friends.length > 5) {\n this.warcry();\n} \nelse if ((this.now() > 15 || this.health < 150) && !this.getCooldown('terrify')) {\n this.terrify();\n}\nelse if (this.health < 75 && this.pos.x > furthestFriendX - 5) {\n this.move({x: 10, y: 27});\n}\nelse if (this.pos.x > furthestFriendX - 1 && this.now() < 50) {\n this.shield();\n}\nelse {\n this.attack(enemy);\n}\nthis.say(\"Defend!\", {targetPos: {x: 30, y: Infinity}});\n\n// You can also command your troops with this.say():\n//this.say(\"Defend!\", {targetPos: {x: 30, y: 30}}));\n//this.say(\"Attack!\", {target: enemy});\n//this.say(\"Move!\", {targetPos: {x: 40, y: 40});\n\n// You can store state on this across frames:\n//this.lastHealth = this.health;\n*/"}},"teamSpells":{"ogres":["programmable-brawler/chooseAction","programmable-shaman/chooseAction","ogre-base/chooseAction"],"humans":["programmable-librarian/chooseAction","programmable-tharin/chooseAction","human-base/chooseAction"]},"submittedCodeLanguage":"javascript","playtime":9753,"codeLanguage":"javascript"} -levelData = {"_id":"53c997066567c600002a43d0","name":"Dungeon Arena","icon":"db/level/53173f76c269d400000543c2/11_dungeon.png","banner":"db/level/53173f76c269d400000543c2/dungeon_arena.png","employerDescription":"Players:\n* Attempt to destroy the enemy base.\n* Choose and control heroes to attack with.\n* Choose which types of lesser units to build and have limited control over them.\n* Try to write strategies that counter other enemy strategies.\n* Play on a small map.","systems":[],"thangs":[],"scripts":[],"documentation":{"generalArticles":[],"specificArticles":[]},"description":"This level is indescribably flarmy!","version":{"minor":0,"major":0,"isLatestMajor":true,"isLatestMinor":true}}; +levelSessionData = require './level-session.fixture' +levelData = require './level.fixture'; module.exports = -> session = new LevelSession(levelSessionData) v = new LevelSessionCodeView({session:session}) request = jasmine.Ajax.requests.mostRecent() - request.response({status: 200, responseText: JSON.stringify(levelData)}) - console.log 'okay should be fine' + request.respondWith({status: 200, responseText: JSON.stringify(levelData)}) + v.render() v diff --git a/test/demo/views/common/level-session.fixture.coffee b/test/demo/views/common/level-session.fixture.coffee new file mode 100644 index 000000000..cf2eeb197 --- /dev/null +++ b/test/demo/views/common/level-session.fixture.coffee @@ -0,0 +1,47 @@ +module.exports = { + "_id": "5317ad4909098828ed071f4d", + "level": { + "original": "53173f76c269d400000543c2", + "majorVersion": 0 + }, + "team": "humans", + "levelID": "dungeon-arena", + "levelName": "Dungeon Arena", + "submitted": true, + "totalScore": 38.4584087145667, + "code": { + "programmable-librarian": { + "chooseAction": "// The Librarian is a spellcaster with a fireball attack\n// plus three useful spells: 'slow', 'regen', and 'haste'.\n// Slow makes a target move and attack at half speed for 5s.\n// Regen makes a target heal 10 hp/s for 10s.\n// Haste speeds up a target by 4x for 5s, once per match.\n\nvar enemies = this.getEnemies();\nif (enemies.length === 0) return; // Chill if all enemies are dead.\nvar enemy = this.getNearest(enemies);\nif (this.canCast('slow', enemy)) {\n // Slow the enemy, or chase if out of range (30m).\n this.castSlow(enemy);\n if (this.distance(enemy) <= 50)\n this.say(\"Not so fast, \" + enemy.type + \" \" + enemy.id);\n}\nelse {\n this.attack(enemy);\n}\nvar base = this.getFriends()[0];\nvar d = base.distance(enemy);\n// You can also command your troops with this.say():\n//this.say(\"Defend!\", {targetPos: {x: 30, y: 30}}));\n//this.say(\"Attack!\", {target: enemy});\n//this.say(\"Move!\", {targetPos: {x: 50, y: 40});\n" + }, + "human-base": { + "chooseAction": "// This is the code for your base. Decide which unit to build each frame.\n// Units you build will go into the this.built array.\n// Destroy the enemy base within 60 seconds!\n// Check out the Guide at the top for more info.\n\n// CHOOSE YOUR HERO! You can only build one hero.\nvar hero;\n//hero = 'tharin'; // A fierce knight with battlecry abilities.\nhero = 'hushbaum'; // A fiery spellcaster hero.\n\nif(hero && !this.builtHero) {\n this.builtHero = this.build(hero);\n return;\n}\n\n// Soldiers are hard-to-kill, low damage melee units with 2s build cooldown.\n// Archers are fragile but deadly ranged units with 2.5s build cooldown.\nvar buildOrder = ['soldier', 'soldier', 'soldier', 'soldier', 'archer'];\nvar type = buildOrder[this.built.length % buildOrder.length];\n//this.say('Unit #' + this.built.length + ' will be a ' + type);\nthis.build(type);" + }, + "hushbaum": { + "chooseAction": "var enemy = this.getNearestEnemy();\nif (enemy) {\n if (!enemy.hasEffect('slow')) {\n this.say(\"Not so fast, \" + enemy.type + \" \" + enemy.id);\n this.castSlow(enemy);\n }\n else {\n this.attack(enemy);\n }\n}\nelse {\n this.move({x: 70, y: 30});\n}\n" + }, + "tharin": { + "chooseAction": "var enemies = this.getEnemies();\nvar enemy = this.getNearest(enemies);\nif (!this.getCooldown('warcry')) {\n this.warcry();\n}\nelse if (enemy) {\n this.attack(enemy);\n}\nelse {\n this.move({x: 10, y: 30});\n}\n" + }, + "tharin-1": { + "chooseAction": "var __interceptThis=(function(){var G=this;return function($this,sandbox){if($this==G){return sandbox;}return $this;};})();\nreturn (function (__global) {\n var tmp0, tmp1;\n tmp1 = function () {\n _aether.logCallStart(this._aetherUserInfo); var enemies, enemy, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17, tmp18, tmp19, tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26;\n tmp2 = 'use strict';\n tmp3 = __interceptThis(this, __global);\n tmp4 = 'getEnemies';\n _aether.logStatementStart([{ofs: 0, row: 0, col: 0}, {ofs: 32, row: 0, col: 32}]); enemies = tmp3[tmp4](); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 0, row: 0, col: 0}, {ofs: 32, row: 0, col: 32}], \"var enemies = this.getEnemies();\", this._aetherUserInfo);\n tmp5 = __interceptThis(this, __global);\n tmp6 = 'getNearest';\n tmp7 = enemies;\n _aether.logStatementStart([{ofs: 33, row: 1, col: 0}, {ofs: 70, row: 1, col: 37}]); enemy = tmp5[tmp6](tmp7); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 33, row: 1, col: 0}, {ofs: 70, row: 1, col: 37}], \"var enemy = this.getNearest(enemies);\", this._aetherUserInfo);\n tmp10 = __interceptThis(this, __global);\n tmp11 = 'getCooldown';\n _aether.logStatementStart([{ofs: 93, row: 2, col: 22}, {ofs: 101, row: 2, col: 30}]); tmp12 = 'warcry'; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 93, row: 2, col: 22}, {ofs: 101, row: 2, col: 30}], \"'warcry'\", this._aetherUserInfo);\n _aether.logStatementStart([{ofs: 76, row: 2, col: 5}, {ofs: 102, row: 2, col: 31}]); tmp9 = tmp10[tmp11](tmp12); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 76, row: 2, col: 5}, {ofs: 102, row: 2, col: 31}], \"this.getCooldown('warcry')\", this._aetherUserInfo);\n _aether.logStatementStart([{ofs: 75, row: 2, col: 4}, {ofs: 102, row: 2, col: 31}]); tmp8 = !tmp9; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 75, row: 2, col: 4}, {ofs: 102, row: 2, col: 31}], \"!this.getCooldown('warcry')\", this._aetherUserInfo);\n if (tmp8) {\n tmp13 = __interceptThis(this, __global);\n tmp14 = 'warcry';\n _aether.logStatementStart([{ofs: 110, row: 3, col: 4}, {ofs: 123, row: 3, col: 17}]); tmp15 = tmp13[tmp14](); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 110, row: 3, col: 4}, {ofs: 123, row: 3, col: 17}], \"this.warcry()\", this._aetherUserInfo);\n } else {\n tmp16 = enemy;\n if (tmp16) {\n tmp17 = __interceptThis(this, __global);\n tmp18 = 'attack';\n tmp19 = enemy;\n _aether.logStatementStart([{ofs: 149, row: 6, col: 4}, {ofs: 167, row: 6, col: 22}]); tmp20 = tmp17[tmp18](tmp19); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 149, row: 6, col: 4}, {ofs: 167, row: 6, col: 22}], \"this.attack(enemy)\", this._aetherUserInfo);\n } else {\n tmp21 = __interceptThis(this, __global);\n tmp22 = 'move';\n _aether.logStatementStart([{ofs: 196, row: 9, col: 18}, {ofs: 198, row: 9, col: 20}]); tmp24 = 10; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 196, row: 9, col: 18}, {ofs: 198, row: 9, col: 20}], \"10\", this._aetherUserInfo);\n _aether.logStatementStart([{ofs: 203, row: 9, col: 25}, {ofs: 205, row: 9, col: 27}]); tmp25 = 30; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 203, row: 9, col: 25}, {ofs: 205, row: 9, col: 27}], \"30\", this._aetherUserInfo);\n _aether.logStatementStart([{ofs: 192, row: 9, col: 14}, {ofs: 206, row: 9, col: 28}]); tmp23 = {\n x: tmp24,\n y: tmp25\n }; _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 192, row: 9, col: 14}, {ofs: 206, row: 9, col: 28}], \"{x: 10, y: 30}\", this._aetherUserInfo);\n _aether.logStatementStart([{ofs: 182, row: 9, col: 4}, {ofs: 207, row: 9, col: 29}]); tmp26 = tmp21[tmp22](tmp23); _aether.vars['enemies'] = typeof enemies == 'undefined' ? undefined : enemies; _aether.vars['enemy'] = typeof enemy == 'undefined' ? undefined : enemy; _aether.vars['chooseAction'] = typeof chooseAction == 'undefined' ? undefined : chooseAction; _aether.logStatement([{ofs: 182, row: 9, col: 4}, {ofs: 207, row: 9, col: 29}], \"this.move({x: 10, y: 30})\", this._aetherUserInfo);\n }\n }\n _aether.logCallEnd(); return;\n };\n tmp0 = 'chooseAction';\n __global[tmp0] = tmp1;\n}(this));" + }, + "programmable-tharin": { + "chooseAction": "/*this.getFriends();\nthis.attack(this.getEnemies()[0]);\nreturn;\n*/\n \n\n/* TODO:\n If they fully base race us, we actually do want to produce archers since they DPS faster\n The effective DPS on soldiers is better if they attack us\n but worse if they straight race us\n\n //not sure if this is good but...\n if they're attacking our base with a small number of units\n we should make archers and get them to defend\n*/\n/*\nreturn;\n// Tharin is a melee fighter with shield, warcry, and terrify skills.\n// this.shield() lets him take one-third damage while defending.\n// this.warcry() gives allies within 10m 30% haste for 5s, every 10s.\n// this.terrify() sends foes within 30m fleeing for 5s, once per match.\nvar friends = this.getFriends();\nvar enemies = this.getEnemies();\nif (enemies.length === 0) return; // Chill if all enemies are dead.\nvar enemy = this.getNearest(enemies);\nvar furthestFriendX = 30;\nfor (var i = 0; i < friends.length; ++i) {\n var friend = friends[i];\n furthestFriendX = Math.max(friend.pos.x, furthestFriendX);\n} \nif (!this.getCooldown('warcry') && friends.length > 5) {\n this.warcry();\n} \nelse if ((this.now() > 15 || this.health < 150) && !this.getCooldown('terrify')) {\n this.terrify();\n}\nelse if (this.health < 75 && this.pos.x > furthestFriendX - 5) {\n this.move({x: 10, y: 27});\n}\nelse if (this.pos.x > furthestFriendX - 1 && this.now() < 50) {\n this.shield();\n}\nelse {\n this.attack(enemy);\n}\nthis.say(\"Defend!\", {targetPos: {x: 30, y: Infinity}});\n\n// You can also command your troops with this.say():\n//this.say(\"Defend!\", {targetPos: {x: 30, y: 30}}));\n//this.say(\"Attack!\", {target: enemy});\n//this.say(\"Move!\", {targetPos: {x: 40, y: 40});\n\n// You can store state on this across frames:\n//this.lastHealth = this.health;\n*/" + } + }, + "teamSpells": { + "ogres": [ + "programmable-brawler/chooseAction", + "programmable-shaman/chooseAction", + "ogre-base/chooseAction" + ], + "humans": [ + "programmable-librarian/chooseAction", + "programmable-tharin/chooseAction", + "human-base/chooseAction" + ] + }, + "submittedCodeLanguage": "javascript", + "playtime": 9753, + "codeLanguage": "javascript" +} \ No newline at end of file diff --git a/test/demo/views/common/level.fixture.coffee b/test/demo/views/common/level.fixture.coffee new file mode 100644 index 000000000..b08950d16 --- /dev/null +++ b/test/demo/views/common/level.fixture.coffee @@ -0,0 +1,21 @@ +module.exports = { + "_id": "53c997066567c600002a43d0", + "name": "Dungeon Arena", + "icon": "db/level/53173f76c269d400000543c2/11_dungeon.png", + "banner": "db/level/53173f76c269d400000543c2/dungeon_arena.png", + "employerDescription": "Players:\n* Attempt to destroy the enemy base.\n* Choose and control heroes to attack with.\n* Choose which types of lesser units to build and have limited control over them.\n* Try to write strategies that counter other enemy strategies.\n* Play on a small map.", + "systems": [], + "thangs": [], + "scripts": [], + "documentation": { + "generalArticles": [], + "specificArticles": [] + }, + "description": "This level is indescribably flarmy!", + "version": { + "minor": 0, + "major": 0, + "isLatestMajor": true, + "isLatestMinor": true + } +} \ No newline at end of file diff --git a/test/demo/views/editor/component/AddThangComponentsModal.demo.coffee b/test/demo/views/editor/component/AddThangComponentsModal.demo.coffee index a2d5be343..3f0c0d99f 100644 --- a/test/demo/views/editor/component/AddThangComponentsModal.demo.coffee +++ b/test/demo/views/editor/component/AddThangComponentsModal.demo.coffee @@ -155,6 +155,6 @@ response = module.exports = -> view = new AddThangComponentsModal({skipOriginals:['52437c851d9e25b8dc000008']}) # FollowsNearest original console.log jasmine.Ajax.requests.all() - jasmine.Ajax.requests.mostRecent().response({status: 200, responseText: JSON.stringify(response)}) + jasmine.Ajax.requests.mostRecent().respondWith({status: 200, responseText: JSON.stringify(response)}) view.render() return view \ No newline at end of file From a10aec256f5e2b9ef45d9a8a0d3fe7110b8b3798 Mon Sep 17 00:00:00 2001 From: Scott Erickson Date: Thu, 7 Jan 2016 09:54:02 -0800 Subject: [PATCH 05/10] Set upper limit to max seats you can purchase at once --- app/templates/courses/purchase-courses-view.jade | 13 ++++++++----- app/views/courses/PurchaseCoursesView.coffee | 4 +++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/templates/courses/purchase-courses-view.jade b/app/templates/courses/purchase-courses-view.jade index 3bba3b638..1ee184029 100644 --- a/app/templates/courses/purchase-courses-view.jade +++ b/app/templates/courses/purchase-courses-view.jade @@ -78,11 +78,14 @@ block content br p.text-center#price-form-group - strong - span(data-i18n="account_prepaid.purchase_total") - span.spr : #{view.numberOfStudents} - span(data-i18n="courses.enrollments") - span.spl x $#{(view.pricePerStudent/100).toFixed(2)} = #{view.getPriceString()} + if view.numberOfStudentsIsValid() + strong + span(data-i18n="account_prepaid.purchase_total") + span.spr : #{view.numberOfStudents} + span(data-i18n="courses.enrollments") + span.spl x $#{(view.pricePerStudent/100).toFixed(2)} = #{view.getPriceString()} + else + strong Invalid number of students p.text-center button#purchase-btn.btn.btn-lg.btn-success.uppercase(data-i18n="courses.purchase_now") diff --git a/app/views/courses/PurchaseCoursesView.coffee b/app/views/courses/PurchaseCoursesView.coffee index a97c32cd9..bf721b031 100644 --- a/app/views/courses/PurchaseCoursesView.coffee +++ b/app/views/courses/PurchaseCoursesView.coffee @@ -72,10 +72,12 @@ module.exports = class PurchaseCoursesView extends RootView updatePrice: -> @renderSelectors '#price-form-group' + + numberOfStudentsIsValid: -> @numberOfStudents > 0 and @numberOfStudents < 100000 onClickPurchaseButton: -> return @openModalView new AuthModal() if me.isAnonymous() - if @numberOfStudents < 1 or not _.isFinite(@numberOfStudents) + unless @numberOfStudentsIsValid() alert("Please enter the maximum number of students needed for your class.") return From 2f4079084bf4c53675c6fb62f7102dfd8bafa9a4 Mon Sep 17 00:00:00 2001 From: durianboy Date: Fri, 8 Jan 2016 05:04:30 +0800 Subject: [PATCH 06/10] Update zh-HANT.coffee MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 我需要有人告訴我我這樣算是上傳pull請求嗎? I need someone to tell me have I PULL by propose file change? --- app/locale/zh-HANT.coffee | 510 +++++++++++++++++++------------------- 1 file changed, 255 insertions(+), 255 deletions(-) diff --git a/app/locale/zh-HANT.coffee b/app/locale/zh-HANT.coffee index e44d7d277..712217e57 100644 --- a/app/locale/zh-HANT.coffee +++ b/app/locale/zh-HANT.coffee @@ -2,10 +2,10 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese home: slogan: "玩遊戲學程式" no_ie: "抱歉!Internet Explorer 8 等舊的瀏覽器打不開此網站" # Warning that only shows up in IE8 and older - no_mobile: "CodeCombat不是針對手機設備設計的,所以可能會出問題!" # Warning that shows up on mobile devices + no_mobile: "CodeCombat不是針對行動裝置設計的,所以可能會出問題!" # Warning that shows up on mobile devices play: "開始遊戲" # The big play button that opens up the campaign view. # play_campaign_version: "Play Campaign Version" # Shows up under big play button if you only play /courses - old_browser: "嗯... 您的瀏覽器太老了跑不動CodeCombat,抱歉!" # Warning that shows up on really old Firefox/Chrome/Safari + old_browser: "嗯…您的瀏覽器太老了跑不動CodeCombat,抱歉!" # Warning that shows up on really old Firefox/Chrome/Safari old_browser_suffix: "您還是可以試試看,但它應該不能運行。" ipad_browser: "抱歉,CodeCombat不能在iPad上的瀏覽器運行,但好消息是我們的iPad App正在等待蘋果公司審核。" campaign: "戰役" @@ -71,35 +71,35 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese poll: "投票" # Tooltip on poll button from /play next: "下一步" # Go from choose hero to choose inventory before playing a level change_hero: "更換英雄" # Go back from choose inventory to choose hero - buy_gems: "購買鑽石" + buy_gems: "購買寶石" subscription_required: "需要訂購" anonymous: "匿名玩家" level_difficulty: "難度" # play_classroom_version: "Play Classroom Version" # Choose a level in campaign version that you also can play in one of your courses campaign_beginner: "新手指南" - awaiting_levels_adventurer_prefix: "我們每周將釋出新的關卡。" # {change} + awaiting_levels_adventurer_prefix: "我們每週將釋出新的關卡。" # {change} awaiting_levels_adventurer: "註冊成為冒險家" - awaiting_levels_adventurer_suffix: "成為第一個挑戰新關卡的冒險家吧!" + awaiting_levels_adventurer_suffix: "成為第一個挑戰新關卡的冒險家吧!" adjust_volume: "調整音量" campaign_multiplayer: "多人競技場" - campaign_multiplayer_description: "...在這裡您可以和其他玩家進行對戰。" + campaign_multiplayer_description: "…在這裡您可以和其他玩家進行對戰。" campaign_old_multiplayer: "(過時的)舊多人競技場" campaign_old_multiplayer_description: "多個文明時代的遺跡。已沒有模擬運行這些陳舊、英雄蕪絕的多人競技場。" share_progress_modal: - blurb: "您正在建立優秀的進度! 告訴您的家長, 您從CodeCombat學到了什麼!" # {change} - email_invalid: "郵件地址無效." - form_blurb: "在底下輸入他們的郵件並且我們將秀給他們!" + blurb: "您正在建立優秀的進度!告訴您的家長,您從CodeCombat學到了什麼!" # {change} + email_invalid: "郵件地址無效" + form_blurb: "在底下輸入他們的郵件並且我們將秀給他們!" form_label: "郵件地址" placeholder: "郵件地址" - title: "出色的作品, 學徒" + title: "出色的作品,學徒" login: sign_up: "註冊" log_in: "登入" logging_in: "登入中" log_out: "登出" - forgot_password: "忘記密碼?" + forgot_password: "忘記密碼?" authenticate_gplus: "以 Google+ 帳號登入" load_profile: "讀取 Google+ 個人簡介" finishing: "結束" @@ -109,19 +109,19 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese signup: email_announcements: "通過郵件接收通知" - creating: "帳號建立中..." + creating: "帳號建立中…" sign_up: "註冊" log_in: "登入" required: "在這麼做之前必須先登入。" login_switch: "已經有申請帳號了嗎?" school_name: "就讀學校及所在城市" optional: "選填" - school_name_placeholder: "範例: XX中學, 台北" + school_name_placeholder: "範例:XX中學,台北" recover: recover_account_title: "復原帳號" send_password: "送出新密碼" - recovery_sent: "密碼重置的信件已寄出." + recovery_sent: "密碼重置的信件已寄出" items: primary: "主要武器" @@ -134,9 +134,9 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese common: back: "向後瀏覽" # When used as an action verb, like "Navigate backward" continue: "繼續前進" # When used as an action verb, like "Continue forward" - loading: "載入中..." - saving: "儲存中..." - sending: "發送中...." + loading: "載入中…" + saving: "儲存中…" + sending: "發送中…" send: "送出" cancel: "取消" save: "存檔" @@ -186,7 +186,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese email: "郵件" password: "密碼" message: "訊息" - code: "代碼" + code: "程式碼" ladder: "升級比賽" when: "當" opponent: "對手" @@ -213,18 +213,18 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese hours: "小時" day: "日" days: "日" - week: "周" - weeks: "周" + week: "週" + weeks: "週" month: "個月" months: "個月" year: "年" years: "年" play_level: - completed_level: "完成關卡:" - course: "課程:" + completed_level: "完成關卡:" + course: "課程:" done: "完成" - next_level: "下一個關卡:" + next_level: "下一個關卡:" next_game: "下一個遊戲" show_menu: "顯示遊戲菜單" home: "首頁" # Not used any more, will be removed soon. @@ -235,8 +235,8 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese restart: "重新開始" goals: "目標" goal: "目標" - running: "執行中..." - success: "成功!" + running: "執行中…" + success: "成功!" incomplete: "未完成" timed_out: "時間用盡" failing: "失敗" @@ -251,25 +251,25 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese victory_title_suffix: "完成" victory_sign_up: "保存進度" victory_sign_up_poke: "想保存您的程式碼?建立一個免費帳號吧!" - victory_rate_the_level: "評估關卡: " # {change} + victory_rate_the_level: "評估關卡:" # {change} victory_return_to_ladder: "返回升級比賽模式" victory_saving_progress: "儲存進度" victory_go_home: "返回首頁" victory_review: "給我們回饋!" - victory_review_placeholder: "關卡如何?" + victory_review_placeholder: "關卡如何?" victory_hour_of_code_done: "您完成了嗎?" victory_hour_of_code_done_yes: "是的,我完成了我的程式碼!" victory_experience_gained: "取得經驗值" victory_gems_gained: "取得寶石" victory_new_item: "新的物品" - victory_viking_code_school: "太厲害了, 您剛完成了非常困難的關卡! 如果您想成為一個軟件開發人員,您就應該去試一下Viking Code School。在這裡您可以把您的知識增長到另一個台階。只需要14個星期您就能成為一個專業的網頁開發人員。" + victory_viking_code_school: "太厲害了,您剛完成了非常困難的關卡!如果您想成為一個軟體開發人員,您就應該去試一下Viking Code School。在這裡您可以把您的知識增長到另一個台階。只需要14個星期您就能成為一個專業的網頁開發人員。" victory_become_a_viking: "成為一個維京人。" guide_title: "指南" tome_cast_button_run: "運作" tome_cast_button_running: "運作中" tome_cast_button_ran: "已運作" tome_submit_button: "送出" - tome_reload_method: "重新載入該方法的原代碼" # Title text for individual method reload button. + tome_reload_method: "重新載入該方法的原程式碼" # Title text for individual method reload button. tome_select_method: "選擇一個方法" tome_see_all_methods: "查看所有可編輯的方法" # Title text for method list selector (shown when there are multiple programmable methods). tome_select_a_thang: "選擇一個人物來施放" @@ -282,67 +282,67 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese loading_ready: "準備!" loading_start: "開始戰役" problem_alert_title: "修正您的程式碼" - time_current: "現在:" - time_total: "最大值:" - time_goto: "前往:" + time_current: "現在:" + time_total: "最大值:" + time_goto: "前往:" non_user_code_problem_title: "無法加載關卡" - infinite_loop_title: "檢測到無限循環" - infinite_loop_description: "建立世界的初始代碼還沒有運行完畢。這可能是真的很慢或出現無限循環,或者存在一個bug。您可以嘗試再次運行這段代碼,或重置代碼為默認狀態。如果還是解決不了問題,請聯繫我們。" + infinite_loop_title: "檢測到無限迴圈" + infinite_loop_description: "建立世界的初始程式碼還沒有運行完畢。這可能是真的很慢或出現無限迴圈,或者存在一個bug。您可以嘗試再次運行這段程式碼,或重置程式碼為默認狀態。如果還是解決不了問題,請聯繫我們。" check_dev_console: "您也可以打開開發者界面看一下有什麼可能出錯了。" check_dev_console_link: "(說明)" infinite_loop_try_again: "再試一次" infinite_loop_reset_level: "重置關卡" infinite_loop_comment_out: "在我的程式碼中加入注解" tip_toggle_play: "使用 Ctrl+P 切換 播放/暫停。" - tip_scrub_shortcut: "Ctrl+[ 快退; Ctrl+] 快進。" + tip_scrub_shortcut: "Ctrl+[ 快退;Ctrl+] 快進。" tip_guide_exists: "點擊頁面上方的指南,可獲得更多有用的訊息。" - tip_open_source: "「CodeCombat」100% 開源!" - tip_tell_friends: "喜歡Codecombat?那就把它介紹給朋友!" + tip_open_source: "「CodeCombat」100% 開源!" + tip_tell_friends: "喜歡Codecombat?那就把它介紹給朋友!" tip_beta_launch: "「CodeCombat」在2013年10月進入 BETA 測試。" - tip_think_solution: "思考解決方法而不是問題." - tip_theory_practice: "理論上, 理論和實作之間是沒有區別. 但是實作上, 這兩者是有區別的. - Yogi Berra" - tip_error_free: "有兩種方式可以寫出沒有錯誤的程式; 但只有第三種可以達到預期效果. - Alan Perlis" - tip_debugging_program: "如果除錯是一種清除錯誤的過程, 那麼編寫程式就是一種放置錯誤的過程. - Edsger W. Dijkstra" - tip_forums: "前往論壇並且告訴我們您所思考的!" - tip_baby_coders: "在未來, 就算小孩也能成為大法師." - tip_morale_improves: "直到士氣提升之前,載入的動作將持續." + tip_think_solution: "思考解決方法而不是問題。" + tip_theory_practice: "理論上,理論和實作之間是沒有區別。但是實作上,這兩者是有區別的。 - Yogi Berra" + tip_error_free: "有兩種方式可以寫出沒有錯誤的程式;但只有第三種可以達到預期效果。 - Alan Perlis" + tip_debugging_program: "如果除錯是一種清除錯誤的過程,那麼編寫程式就是一種放置錯誤的過程。 - Edsger W. Dijkstra" + tip_forums: "前往論壇並且告訴我們您所思考的!" + tip_baby_coders: "在未來,就算小孩也能成為大法師。" + tip_morale_improves: "直到士氣提升之前,載入的動作將持續。" tip_all_species: "我們相信所有民族都有平等的機會學習編寫程式" tip_reticulating: "網格狀鋸齒(指卡頓現象)" - tip_harry: "巫師, " - tip_great_responsibility: "隨著擁有強大的編程技巧,除錯的責任將越大." - tip_munchkin: "如果您不吃掉您的蔬菜,那小矮人將在您沈睡時找到您." - tip_binary: "只有2種人在這世上: 那些懂2進位的,和哪些不懂得." - tip_commitment_yoda: "一個程序員必須擁有強烈的責任感和一顆認真的心. ~ Yoda《星球大戰》" - tip_no_try: "做,或者不做。這邊不存在嘗試的選項. - Yoda《星球大戰》" - tip_patience: "年輕的學徒,您必須擁有耐心. - Yoda《星球大戰》" - tip_documented_bug: "一個寫在文件裡的錯誤不是錯誤;它是功能." - tip_impossible: "事情總是看起來不可能直到它成真那刻. - Nelson Mandela" - tip_talk_is_cheap: "多說無益,放「碼」過來. - Linus Torvalds" - tip_first_language: "您經歷的第一門程式語言是最慘痛的事情. - Alan Kay" - tip_hardware_problem: "Q: 換一顆燈泡需要多少位程序員? A: 一位也不用,它是個硬體問題。" - tip_hofstadters_law: "Hofstadter 定律: 完成一件複雜的事花費的時間總是超乎預期, 甚至您早已知道這個現象( Hofstadter 定律)。" + tip_harry: "巫師," + tip_great_responsibility: "隨著擁有強大的編程技巧,除錯的責任將越大。" + tip_munchkin: "如果您不吃掉您的蔬菜,那小矮人將在您沉睡時找到您。" + tip_binary: "只有2種人在這世上:那些懂2進位的,和哪些不懂得。" + tip_commitment_yoda: "一個程式員必須擁有強烈的責任感和一顆認真的心。 ~ Yoda《星際大戰》" + tip_no_try: "做,或者不做。這邊不存在嘗試的選項。 - Yoda《星際大戰》" + tip_patience: "年輕的學徒,您必須擁有耐心。 - Yoda《星際大戰》" + tip_documented_bug: "一個寫在文件裡的錯誤不是錯誤;它是功能。" + tip_impossible: "事情總是看起來不可能直到它成真那刻。 - Nelson Mandela" + tip_talk_is_cheap: "多說無益,放「碼」過來。 - Linus Torvalds" + tip_first_language: "您經歷的第一門程式語言是最慘痛的事情。 - Alan Kay" + tip_hardware_problem: "Q: 換一顆燈泡需要多少位程式員? A: 一位也不用,它是個硬體問題。" + tip_hofstadters_law: "Hofstadter 定律:完成一件複雜的事花費的時間總是超乎預期,甚至您早已知道這個現象( Hofstadter 定律)。" tip_premature_optimization: "過早的優化是萬惡之源。 - Donald Knuth" - tip_brute_force: "當您游移不定時, 就是用暴力解。 - Ken Thompson" - tip_extrapolation: "只有 2 種人在這世上: 一種人是能夠根據不完整資訊而推斷..." + tip_brute_force: "當您游移不定時,就是用暴力解。 - Ken Thompson" + tip_extrapolation: "只有 2 種人在這世上:一種人是能夠根據不完整資訊而推斷…" tip_superpower: "編程讓我們最接近擁有超能力。" - tip_control_destiny: "在真正的開源, 您有權利控制自己的命運。 - Linus Torvalds" - tip_no_code: "在速度上,沒有任何代碼可以超過無代碼" - tip_code_never_lies: "代碼從不說謊, 但註釋偶爾會。 — Ron Jeffries" + tip_control_destiny: "在真正的開源,您有權利控制自己的命運。 - Linus Torvalds" + tip_no_code: "在速度上,沒有任何程式碼可以超過無程式碼" + tip_code_never_lies: "程式碼從不說謊,但註釋偶爾會。 — Ron Jeffries" tip_reusable_software: "在軟體被重複使用前,它必須能用。" - tip_optimization_operator: "每種語言都有一個優化的運算符號. 對大部份而言,那符號是‘//’" - tip_lines_of_code: "使用代碼行數來管理開發進度就好像使用秤重器來管理建造飛機。 — Bill Gates" - tip_source_code: "我想改變世界但他們不給我源代碼" + tip_optimization_operator: "每種語言都有一個優化的運算符號。對大部份而言,那符號是‘//’" + tip_lines_of_code: "使用程式碼行數來管理開發進度就好像使用秤重器來管理建造飛機。 — Bill Gates" + tip_source_code: "我想改變世界但他們不給我原始碼" tip_javascript_java: "Java 和 JavaScript 的關係就好比馬和馬雲。 - Chris Heilmann" - tip_move_forward: "不論做什麼, 保持前進. - Martin Luther King Jr." - tip_google: "擁有一個您不能解決的問題? Google它!" + tip_move_forward: "不論做什麼,保持前進。 - Martin Luther King Jr." + tip_google: "擁有一個您不能解決的問題?Google它!" tip_adding_evil: "增加一個邪惡掐揑。" - tip_hate_computers: "關於自我覺得恨透電腦的那群人. 其實他們真正應該恨的事情是糟糕的程序員。 - Larry Niven" + tip_hate_computers: "關於自我覺得恨透電腦的那群人。其實他們真正應該恨的事情是糟糕的程式員。 - Larry Niven" tip_open_source_contribute: "您可以幫助「CodeCombat」提高!" tip_recurse: "迭代者人也,遞歸者神也 - L. Peter Deutsch" tip_free_your_mind: "放下一切私心雜念,丟棄害怕、疑問和拒信,解放您的思維。 - 莫菲斯《駭客任務》" - tip_strong_opponents: "即使是最强大的對手也有弱点的。 - 宇智波鼬《火影忍者》" + tip_strong_opponents: "即使是最强大的對手也有弱點的。 - 宇智波鼬《火影忍者》" tip_paper_and_pen: "在您開始編碼之前,您可以隨時用一張紙和一支筆作計劃。" - tip_solve_then_write: "要先想清楚問題如何解決, 再進行編碼的動作. - John Johnson" + tip_solve_then_write: "要先想清楚問題如何解決,再進行編碼的動作。 - John Johnson" game_menu: inventory_tab: "倉庫" @@ -354,19 +354,19 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese multiplayer_tab: "多人遊戲" auth_tab: "註冊" inventory_caption: "裝備您的英雄" - choose_hero_caption: "選擇英雄, 語言" - save_load_caption: "... 觀看歷史紀錄" + choose_hero_caption: "選擇英雄,語言" + save_load_caption: "…觀看歷史紀錄" options_caption: "設置設定" guide_caption: "文件與小撇步" - multiplayer_caption: "跟朋友一起玩!" - auth_caption: "儲存進度." + multiplayer_caption: "跟朋友一起玩!" + auth_caption: "儲存進度" leaderboard: view_other_solutions: "查看其他解法" scores: "分數" top_players: "頂級玩家由" day: "今天" - week: "這周" + week: "這週" all: "長期以來" time: "時間" damage_taken: "遭受的攻擊" @@ -390,22 +390,22 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese few_gems: "一些寶石" pile_gems: "一堆寶石" chest_gems: "一箱寶石" - purchasing: "購買中..." + purchasing: "購買中…" declined: "您的信用卡被拒絕" - retrying: "伺服器錯誤, 正在重試。" + retrying: "伺服器錯誤,正在重試。" prompt_title: "寶石不足" - prompt_body: "想要取得更多?" + prompt_body: "想要取得更多?" prompt_button: "進入商店" recovered: "先前購買的寶石已回復,請重新載入頁面。" price: "x3500 / 月" subscribe: - comparison_blurb: "訂閱 CodeCombat 來磨練您的技巧!" + comparison_blurb: "訂閱 CodeCombat 來磨練您的技巧!" feature1: "110 個以上的基本關卡散佈在4張地圖中" - feature2: "10 個強壯的新英雄並每隻都有不同技巧!" + feature2: "10 個強壯的新英雄並每位都有不同技巧!" feature3: "80 個以上的額外關卡" - feature4: "每個月3500顆額外寶石!" - feature5: "視頻教學" + feature4: "每個月3500顆額外寶石!" + feature5: "影片教學" feature6: "頂級信箱支援" feature7: "私人 部落" free: "免費" @@ -417,27 +417,27 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese never_mind: "沒關係,我仍然愛您" thank_you_months_prefix: "感謝您這幾個" thank_you_months_suffix: "月來的支持" - thank_you: "感謝您支持CodeCombat." - sorry_to_see_you_go: "捨不得您離開! 請讓我們知道我們如何做得更好." - unsubscribe_feedback_placeholder: "我們做錯事了嗎?" + thank_you: "感謝您支持CodeCombat" + sorry_to_see_you_go: "捨不得您離開!請讓我們知道我們如何做得更好。" + unsubscribe_feedback_placeholder: "我們做錯事了嗎?" parent_button: "詢問您的父母" - parent_email_description: "我們將寄信向他們說明,所以他們能放心幫您訂閱 CodeCombat." - parent_email_input_invalid: "信箱位址無效." + parent_email_description: "我們將寄信向他們說明,所以他們能放心幫您訂閱 CodeCombat。" + parent_email_input_invalid: "信箱位址無效" parent_email_input_label: "父母信箱位址" parent_email_input_placeholder: "輸入父母信箱" parent_email_send: "寄信" - parent_email_sent: "已寄信!" - parent_email_title: "您父母信箱是?" + parent_email_sent: "已寄信!" + parent_email_title: "您父母信箱是?" parents: "致家長" - parents_title: "親愛的家長: 您的孩子將要學習編程. 您會支持孩子發展嗎?" + parents_title: "親愛的家長:您的孩子將要學習編程。您會支持孩子發展嗎?" parents_blurb1: "您的孩子已經玩了 __nLevels__ 關,並且學習了編程基礎。請您為了培養他們的興趣而給他們訂閱,他們能繼續玩下去。" - parents_blurb1a: "不要懷疑計算機編程能力將是您的孩子作為一個成年人的基本技能。到2020年,77%的工作將會需要編碼能力,並且軟件工程師將在世界各地成為高需求職業。您知道要計算機科學是收入最高的大學學位。" - parents_blurb2: "每月支付 ${{price}} 美金, 他們每週獲得新挑戰以及使用信件取得專業程式員的幫助。" - parents_blurb3: "沒有風險: 保證 100% 退費, 一步取消訂閱。" + parents_blurb1a: "不要懷疑計算機編程能力將是您的孩子作為一個成年人的基本技能。到2020年,77%的工作將會需要編碼能力,並且軟體工程師將在世界各地成為高需求職業。您知道要計算機科學是收入最高的大學學位。" + parents_blurb2: "每月支付 ${{price}} 美金,他們每週獲得新挑戰以及使用信件取得專業程式員的幫助。" + parents_blurb3: "沒有風險:保證 100% 退費,一步取消訂閱。" payment_methods: "付費方法" payment_methods_title: "可接受的付款方式" payment_methods_blurb1: "我們現有的付費方式有信用卡和支付寶" # {change} - payment_methods_blurb2: "如果您想用其他付費方式,請聯繫我們" + payment_methods_blurb2: "如果您想用其他付費方式,請聯繫我們" sale_button: "促銷!" sale_button_title: "年費訂閱能節省 ${{discount}} 的費用" stripe_description: "每月訂閱" @@ -445,16 +445,16 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese subscription_required_to_play: "您將需要訂閱來開啟這關。" unlock_help_videos: "訂閱來解開所有鎖住得教學影片。" personal_sub: "個人訂閱" # Accounts Subscription View below - loading_info: "正在加載訂閱內容···" + loading_info: "正在加載訂閱內容…" managed_by: "管理" will_be_cancelled: "將被取消" currently_free: "您目前有一個免費訂閱" currently_free_until: "您目前有一個訂閱,直到" was_free_until: "您有過一個免費訂閱,直到" managed_subs: "管理訂閱" - subscribing: "訂閱中・・・" + subscribing: "訂閱中…" current_recipients: "當前收件人" - unsubscribing: "取消訂閱中・・・" # {change} + unsubscribing: "取消訂閱中…" # {change} subscribe_prepaid: "點擊訂閱來使用預付代碼" using_prepaid: "使用預付費代碼進行每月訂閱" @@ -474,8 +474,8 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese hero_type: "種類" weapons: "武器" weapons_warrior: "刀劍 - 短距離、非魔法" - weapons_ranger: "十字弓, 槍砲 - 長距離、非魔法" - weapons_wizard: "魔杖, 法杖 - 長距離、魔法" + weapons_ranger: "十字弓、槍砲 - 長距離、非魔法" + weapons_wizard: "魔杖、法杖 - 長距離、魔法" attack: "傷害" # Can also translate as "Attack" health: "血量" speed: "速度" @@ -493,7 +493,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese speed_1: "移動速度" speed_2: "公尺每秒。" available_for_purchase: "可以購買" # Shows up when you have unlocked, but not purchased, a hero in the hero store - level_to_unlock: "解鎖關卡:" # Label for which level you have to beat to unlock a particular hero (click a locked hero in the store to see) + level_to_unlock: "解鎖關卡:" # Label for which level you have to beat to unlock a particular hero (click a locked hero in the store to see) restricted_to_certain_heroes: "特定英雄才可遊玩此關卡。" skill_docs: @@ -539,11 +539,11 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese editor_config_behaviors_description: "自動填入小括號、大括號以及引號。" about: - why_codecombat: "為什麼使用CodeCombat?" - why_paragraph_1: "想學程式嗎? 您不需要課程。您需要的只是大量的時間去\"玩\"程式。" + why_codecombat: "為什麼使用CodeCombat?" + why_paragraph_1: "想學程式嗎?您不需要課程。您需要的只是大量的時間去\"玩\"程式。" why_paragraph_2_prefix: "寫程式應該是有趣的。當然不是" why_paragraph_2_italic: "「耶!拿到獎章了。」" - why_paragraph_2_center: "的有趣, 而是" + why_paragraph_2_center: "的有趣,而是" why_paragraph_2_italic_caps: "「媽我不要出去玩,我要寫完這段!」" why_paragraph_2_suffix: "般引人入勝。這是為甚麼CodeCombat被設計成多人對戰「遊戲」,而不是遊戲化「課程」。在您對這遊戲無法自拔之前,我們是不會放棄的─當然,這個遊戲,將是有益於您的。" why_paragraph_3: "如果您要沉迷遊戲的話,就來沉迷CodeCombat,成為科技時代的魔法師吧!" @@ -571,7 +571,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese retrostyle_title: "插畫師" retrostyle_blurb: "復古風格的遊戲" rob_title: "編譯工程師" - rob_blurb: "編寫一些的代碼" + rob_blurb: "編寫一些的程式碼" josh_c_title: "遊戲設計師" josh_c_blurb: "設計遊戲" carlos_title: "區經理 - 巴西" @@ -583,7 +583,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese who_for_title: "誰是CodeCombat的使用對象呢?" who_for_1: "我們建議讓9歲及以上的學生使用CodeCombat。無需任何編程經驗。" # {change} who_for_2: "我們設計CodeCombat來吸引男生女生。" # {change} - more_info_title: "我可以在哪裡找到更多信息?" + more_info_title: "我可以在哪裡找到更多訊息?" more_info_1: "我們的" more_info_2: "教師論壇" more_info_3: "是個與其他使用CodeCombat的教育工作者聯繫的良好平台。" @@ -591,7 +591,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese teachers_survey: title: "教師調查" must_be_logged: "您需要先登入。請先註冊或者在上方的目錄中點擊登入。" - retrieving: "檢索信息中..." + retrieving: "檢索資料中…" being_reviewed_1: "您的免費訂閱試用申請正在" # {change} being_reviewed_2: "審核。" approved_1: "您的免費訂閱試用申請已被" # {change} @@ -603,7 +603,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese denied_2: "拒絕。" contact_1: "請聯繫" contact_2: "如果您有更多的疑問。" - description_1: "我們為教師提供免費訂閱用評估的目的。您可以找到更多的信息在我們的" + description_1: "我們為教師提供免費訂閱用評估的目的。您可以找到更多的訊息在我們的" # description_1b: "You can find more information on our" description_2: "教師" description_3: "頁面。" @@ -613,7 +613,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese location: "城市" age_students: "您的學生年齡為多少?" under: "低於" - other: "其他:" + other: "其他:" amount_students: "請問您有多少學生需要教導?" hear_about: "您是怎麼知道CodeCombat的?" fill_fields: "請填寫所有問題。" @@ -622,27 +622,27 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese versions: save_version_title: "保存新版本" new_major_version: "新的重要版本" - submitting_patch: "正在提交修補..." - cla_prefix: "想保存修改, 您必須先保存我們的" + submitting_patch: "正在提交修補…" + cla_prefix: "想保存修改,您必須先保存我們的" cla_url: "貢獻者許可協議" cla_suffix: "。" cla_agree: "我同意" - owner_approve: "您所做出的修改必须经拥有者确认才能生效。" + owner_approve: "您所做出的修改必須經擁有者確認才能生效。" contact: contact_us: "聯繫我們" - welcome: "很高興收到您的信!用這個表格給我們發電郵。 " - forum_prefix: "如果有任何問題, 請至" + welcome: "很高興收到您的信!用這個表格給我們發電郵。" + forum_prefix: "如果有任何問題,請至" forum_page: "論壇" forum_suffix: "討論。" faq_prefix: "這裡還有一個" faq: "FAQ" - subscribe_prefix: "如果您需要幫助來解決關卡, 請" + subscribe_prefix: "如果您需要幫助來解決關卡,請" subscribe: "訂閱CodeCombat" - subscribe_suffix: "並且我們樂意提供代碼相關的協助." - subscriber_support: "您已經是個CodeCombat訂閱者, 我們將提供優先的協助." - screenshot_included: "包含螢幕截圖." - where_reply: "我們回覆到?" + subscribe_suffix: "並且我們樂意提供程式碼相關的協助。" + subscriber_support: "您已經是個CodeCombat訂閱者,我們將提供優先的協助。" + screenshot_included: "包含螢幕截圖。" + where_reply: "我們回覆到?" send: "意見反饋" account_settings: @@ -666,7 +666,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese new_password: "新密碼" new_password_verify: "確認密碼" type_in_email: "輸入您的Email來確認刪除" - type_in_email_progress: "輸入您的Email, 確認您真的要刪除進度" + type_in_email_progress: "輸入您的Email,確認您真的要刪除進度" type_in_password: "還有輸入您的密碼。" email_subscriptions: "訂閱" email_subscriptions_none: "無Email訂閱" @@ -682,7 +682,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese contributor_emails: "貢獻者電郵" contribute_prefix: "我們在尋找志同道合的人!請到 " contribute_page: "貢獻頁面" - contribute_suffix: " 查看更多信息。" + contribute_suffix: " 查看更多訊息。" email_toggle: "全選" error_saving: "保存時發生錯誤" saved: "修改已儲存" @@ -707,20 +707,20 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese toggle_debug: "顯示/關閉除錯訊息" toggle_grid: "顯示/關閉網格提示" toggle_pathfinding: "顯示/關閉路徑尋找提示" - beautify: "利用標準格式來美化您的代碼" - maximize_editor: "最大化/最小化代碼編輯器" + beautify: "利用標準格式來美化您的程式碼" + maximize_editor: "最大化/最小化程式碼編輯器" community: main_title: "CodeCombat社群" - introduction: "查看您可能可以參與的項目以及選擇最吸引您的項目. 我們期待與您一起工作!" + introduction: "查看您可能可以參與的項目以及選擇最吸引您的項目。我們期待與您一起工作!" level_editor_prefix: "使用CodeCombat" - level_editor_suffix: "來創造和編輯關卡。 許多人已經創造關卡用在課堂或黑客松,或者給予朋友或兄弟姐妹。如果您覺得創建一個全新的關卡非常困難,您可以先從現成的開始做起!" - thang_editor_prefix: "我們稱呼遊戲中的單位叫'thangs'。 使用" - thang_editor_suffix: "來修改CodeCombat的原材料。 讓遊戲中的東西可以扔砲彈,修改遊戲動畫的方向,調整單位的生命值,或者上傳自製的素材。" - article_editor_prefix: "看到有錯誤在我們的文件中嗎? 想要自己設計指令嗎? 查看我們的" - article_editor_suffix: "以及幫助CodeCombat玩家獲得更多知識在遊戲中。" - find_us: "通過這些網站連繫我們" - social_github: "在GitHub上查看我們的代碼" + level_editor_suffix: "來創造和編輯關卡。許多人已經創造關卡用在課堂或黑客松,或者給予朋友或兄弟姊妹。如果您覺得創建一個全新的關卡非常困難,您可以先從現成的開始做起!" + thang_editor_prefix: "我們稱呼遊戲中的單位叫'thangs'。使用" + thang_editor_suffix: "來修改CodeCombat的原材料。讓遊戲中的東西可以扔砲彈,修改遊戲動畫的方向,調整單位的生命值,或者上傳自製的素材。" + article_editor_prefix: "看到有錯誤在我們的文件中嗎?想要自己設計指令嗎?查看我們的" + article_editor_suffix: "以及幫助CodeCombat玩家在遊戲中獲得更多知識。" + find_us: "透過這些網站連繫我們" + social_github: "在GitHub上查看我們的程式碼" social_blog: "閱讀CodeCombat在Sett上的部落格" social_discource: "加入我們在Discourse論壇上的討論" social_facebook: "關注CodeCombat的Facebook" @@ -738,7 +738,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese subs_only: "只限訂閱" create_clan: "創建新的部落" private_preview: "預覽" -# private_clans: "Private Clans" +# private_clans: "private clans" public_clans: "公共部落" my_clans: "我的部落" clan_name: "部落名字" @@ -828,8 +828,8 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese send_invites: "發送邀請" title: "標題" description: "描述" - creating_class: "課堂創建中···" - purchasing_course: "購買課程中···" + creating_class: "課堂創建中…" + purchasing_course: "購買課程中…" buy_course: "購買課程" buy_course1: "購買這個課程" create_class: "創建課堂" @@ -850,7 +850,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese teachers_click: "老師點擊這裡" students_click: "學生點擊這裡" courses_on_coco: "CodeCombat上的課程" - designed_to: "CodeCombat課程的宗旨是在使用CodeCombat生動有趣的環境下教授計算機科學的課目。整個CodeCombat的關卡是圍繞著計算機科學的重點,並激勵學生們自主向上學習在5小時的過程內。" + designed_to: "CodeCombat課程的宗旨是在使用CodeCombat生動有趣的環境下教授計算機科學的課目。整個CodeCombat的關卡是圍繞著計算機科學的重點,並激勵學生們在5小時的過程內自主向上學習。" more_in_less: "以最少的時間學習最多的知識" no_experience: "無需編程經驗" easy_monitor: "容易管理學生的進程" @@ -1020,19 +1020,19 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese archmage_summary: "如果您是個在coding教育遊戲有興趣的開發者,成為大法師來幫助我們建立CodeCombat!" artisan_title: "工匠" artisan_title_description: "(Level Builder)" - artisan_summary: "建造遊戲關卡並且分享給您的朋友們。 成為工匠來幫助其他人學習編程。" + artisan_summary: "建造遊戲關卡並且分享給您的朋友們。成為工匠來幫助其他人學習編程。" adventurer_title: "冒險家" adventurer_title_description: "(Level Playtester)" - adventurer_summary: "提前一周免費取得我們新的關卡(甚至是訂閱的內容)並且提前在釋出前幫助我們找出錯誤。" + adventurer_summary: "提前一週免費取得我們新的關卡(甚至是訂閱的內容)並且提前在釋出前幫助我們找出錯誤。" scribe_title: "文書" scribe_title_description: "(Article Editor)" - scribe_summary: "好的程式需要好的文件。 來自全世界數百萬的玩家一起編寫, 編輯和提升文件的可讀性。" + scribe_summary: "好的程式需要好的文件。來自全世界數百萬的玩家一起編寫,編輯和提升文件的可讀性。" diplomat_title: "外交官" diplomat_title_description: "(Translator)" - diplomat_summary: "借由我們的外交官,CodeCombat已翻譯到45種以上的語言。 幫助我們並且貢獻翻譯。" + diplomat_summary: "藉由我們的外交官,CodeCombat已翻譯到45種以上的語言。幫助我們並且貢獻翻譯。" ambassador_title: "使節" ambassador_title_description: "(Support)" - ambassador_summary: "安撫我們論壇的用戶並且提供發問者適當的方向。 我們的使節代表CodeCombat面對全世界。" + ambassador_summary: "安撫我們論壇的用戶並且提供發問者適當的方向。我們的使節代表CodeCombat面對全世界。" editor: main_title: "CodeCombat編輯器" @@ -1054,7 +1054,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese small: "小的" large: "大的" fork_title: "產生新分支" - fork_creating: "產生分支中..." + fork_creating: "產生分支中…" generate_terrain: "產生地形" more: "更多" wiki: "維基" @@ -1062,7 +1062,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese thang_main: "主要" thang_spritesheets: "圖集" thang_colors: "顏色" - level_some_options: "有哪些選項?" + level_some_options: "有哪些選項?" level_tab_thangs: "物體" level_tab_scripts: "腳本" level_tab_settings: "設定" @@ -1111,8 +1111,8 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese level_search_title: "在這搜尋關卡" achievement_search_title: "搜尋成就" poll_search_title: "搜尋投票" - read_only_warning2: "注意: 您不能在這儲存任何編輯, 因為您尚未登入." - no_achievements: "尚未有任何成就加入到這關卡中." + read_only_warning2: "注意:您不能在這儲存任何編輯,因為您尚未登入。" + no_achievements: "尚未有任何成就加入到這關卡中。" achievement_query_misc: "關閉成就欄的雜項" achievement_query_goals: "關閉成就欄的關卡目標" level_completion: "關卡完成" @@ -1131,81 +1131,81 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese contribute: page_title: "貢獻" - intro_blurb: "CodeCombat 是 100% 開源! 上百位專注的玩家已經幫助我們建造到今天的程度. 加入我們並完成下一章 CodeCombat 的冒險給全世界參與!" - alert_account_message_intro: "您好!" - alert_account_message: "為了訂閱課程信件, 您將必須先登入." - archmage_introduction: "在建造遊戲中,其中一個最美好的事情是需要整合許多不同東西:圖像、 聲音、及時網路和社群網路。以及許多不同層面的編程,從底層數據庫管理,到用戶界面的設計和實現。 這裡有許多事情需要完成, 如果您是個有經驗的程序員並且熱衷于深入處理 CodeCombat 的本質,那麼這職業就是為您打造的。 我們將很高興擁有您的幫助來打造有史以來最優質的編程遊戲。" + intro_blurb: "CodeCombat 是 100% 開源!上百位專注的玩家已經幫助我們建造到今天的程度。加入我們並完成下一章 CodeCombat 的冒險給全世界參與!" + alert_account_message_intro: "您好!" + alert_account_message: "為了訂閱課程信件,您將必須先登入。" + archmage_introduction: "在建造遊戲中,其中一個最美好的事情是需要整合許多不同東西:圖像、 聲音、及時網路和社群網路。以及許多不同層面的編程,從底層數據庫管理,到用戶界面的設計和實現。這裡有許多事情需要完成,如果您是個有經驗的程式員並且熱衷於深入處理 CodeCombat 的本質,那麼這職業就是為您打造的。我們將很高興擁有您的幫助來打造有史以來最優質的編程遊戲。" class_attributes: "職業說明" - archmage_attribute_1_pref: "熟悉于" - archmage_attribute_1_suf: ", 或者渴望去學習。 我們大部份的程式以這個語言寫成。 如果您是個 Ruby 或 Python 的粉絲, 您將感覺到歸屬感。 它是個JavaScript, 但是擁有更佳的文法。" - archmage_attribute_2: "一些程式經驗和個人的衝勁。 我們將幫助您找到方向, 但是我們不會花費太多時間訓練您。" + archmage_attribute_1_pref: "熟悉於" + archmage_attribute_1_suf: ",或者渴望去學習。我們大部份的程式以這個語言寫成。如果您是個 Ruby 或 Python 的粉絲,您將感覺到歸屬感。它是個JavaScript,但是擁有更佳的文法。" + archmage_attribute_2: "一些程式經驗和個人的衝勁。我們將幫助您找到方向,但是我們不會花費太多時間訓練您。" how_to_join: "如何加入" - join_desc_1: "任何人都可加入我們! 只需確認我們的" - join_desc_2: "來開始, 並且勾選底下的條件來宣告您成為勇敢的大法師和借由郵件獲得我們最新的消息。 想要討論可做的事或者更加深入地參與? " - join_desc_3: ", 或者找到我們在" - join_desc_4: "讓我們從這開始!" + join_desc_1: "任何人都可加入我們!只需確認我們的" + join_desc_2: "來開始,並且勾選底下的條件來宣告您成為勇敢的大法師和藉由郵件獲得我們最新的消息。想要討論可做的事或者更加深入地參與?" + join_desc_3: ",或者找到我們在" + join_desc_4: "讓我們從這開始!" join_url_email: "發信給我們" join_url_hipchat: "公共的Slack房間" archmage_subscribe_desc: "取得郵件關於新的編程機會和公告。" - artisan_introduction_pref: "我們必須建造更多的關卡! 大家為了更多的內容在高聲吶喊, 但只靠我們只能建造這麼多。 現在您的工作場所就是一關; 我們的關卡編輯器是勉強可用的, 所以請小心. 只要您有新的靈感,不論從簡單的 for-loops 到" - artisan_introduction_suf: ", 那個這職業會適合您。" - artisan_attribute_1: "任何的創建內容經驗都是加分的, 例如使用過Blizzard的關卡編輯器。 但不是必須的!" - artisan_attribute_2: "渴望去完成許多測試和迭代。 為了製作好關卡, 您需要把它交給別人去玩並且觀察他們如何玩, 之後準備找到一堆東西去修改。" - artisan_attribute_3: "暫且擁有探險者般的忍耐力。 我們的關卡編輯器非常的陽春,有些地方非常不易使用。 我們已經提前告知囉!" - artisan_join_desc: "按照以下步驟使用關卡編輯器:" + artisan_introduction_pref: "我們必須建造更多的關卡!大家為了更多的內容在高聲吶喊,但只靠我們只能建造這麼多。現在您的工作場所就是一關;我們的關卡編輯器是勉強可用的,所以請小心。只要您有新的靈感,不論從簡單的 for-loops 到" + artisan_introduction_suf: ",那個這職業會適合您。" + artisan_attribute_1: "任何的創建內容經驗都是加分的,例如使用過Blizzard的關卡編輯器。但不是必須的!" + artisan_attribute_2: "渴望去完成許多測試和迭代。為了製作好關卡,您需要把它交給別人去玩並且觀察他們如何玩,之後準備找到一堆東西去修改。" + artisan_attribute_3: "暫且擁有探險者般的忍耐力。我們的關卡編輯器非常的陽春,有些地方非常不易使用。我們已經提前告知囉!" + artisan_join_desc: "按照以下步驟使用關卡編輯器:" artisan_join_step1: "閱讀文擋。" artisan_join_step2: "創建新的關卡並且探索已存在的關卡。" artisan_join_step3: "在公共的Slack房間裡找到我們尋求幫助。" artisan_join_step4: "公佈您的關卡到論壇中尋求回饋。" artisan_subscribe_desc: "取得郵件關於關卡編輯器更新和公告。" - adventurer_introduction: "讓我們清楚的定義您的角色: 您是部坦克。 您將遭受許多傷害。 我們需要玩家來嘗試我們全新的關卡並且幫助我們找出如何讓事情變得更好。 那痛苦將是巨大的; 製作優秀的遊戲是個長遠的過程並且沒有人可以第一次就把事情做對。 如果您可以忍受並且抵抗力高, 那麼這職業也許適合您。" - adventurer_attribute_1: "渴望學習。 您想要學習如何編程並且我們想要教導您如何編程。 儘管您將可能在這情況中獨自完成大部分教學。" - adventurer_attribute_2: "魅力十足的。 直率但如紳士般的指出需要改進的地方, 並且提供如何改進的建議。" - adventurer_join_pref: "無論是與其餘工匠們一起共事, 或者勾選底下的條件來借由郵件獲得我們最新需要測試的關卡。 我們也將公佈需要評估的關卡在我們的網站上,例如:" + adventurer_introduction: "讓我們清楚的定義您的角色:您是部坦克。您將遭受許多傷害。我們需要玩家來嘗試我們全新的關卡並且幫助我們找出如何讓事情變得更好。那痛苦將是巨大的;製作優秀的遊戲是個長遠的過程並且沒有人可以第一次就把事情做對。如果您可以忍受並且抵抗力高,那麼這職業也許適合您。" + adventurer_attribute_1: "渴望學習。您想要學習如何編程並且我們想要教導您如何編程。儘管您將可能在這情況中獨自完成大部分教學。" + adventurer_attribute_2: "魅力十足的。直率但如紳士般的指出需要改進的地方,並且提供如何改進的建議。" + adventurer_join_pref: "無論是與其餘工匠們一起共事,或者勾選底下的條件來藉由郵件獲得我們最新需要測試的關卡。我們也將公佈需要評估的關卡在我們的網站上,例如:" adventurer_forum_url: "我們的論壇" - adventurer_join_suf: "所以如果您更加喜歡借由這方式被通知, 在那些網站上登錄吧!" + adventurer_join_suf: "所以如果您更加喜歡藉由這方式被通知,在那些網站上登錄吧!" adventurer_subscribe_desc: "當有新關卡需要測試時取得郵件。" - scribe_introduction_pref: "CodeCombat不只是將擁有一堆關卡。 它將也包含知識資源, 一種充滿編程概念的wiki並且每道關卡都將蘊含著這樣的概念。 在這概念下, 不只每位工匠必須描述針對每個細節提出講解, 他們製作的關卡還可以簡單地和wiki中的編程概念產生連結。 某些東西已經在" + scribe_introduction_pref: "CodeCombat不只是將擁有一堆關卡。它將也包含知識資源,一種充滿編程概念的wiki並且每道關卡都將蘊含著這樣的概念。在這概念下,不只每位工匠必須描述針對每個細節提出講解,他們製作的關卡還可以簡單地和wiki中的編程概念產生連結。某些東西已經在" scribe_introduction_url_mozilla: "Mozilla 開發者社群" - scribe_introduction_suf: "完成。 如果您的有趣意見是可以在 Markdown 形式下闡述編程概念, 那麼這職業也許適合您。" - scribe_attribute_1: "文字的技巧幾乎是您全部所需要的。 不只是文法和拼字, 但還需傳達複雜概念給閱讀的人。" + scribe_introduction_suf: "完成。如果您的有趣意見是可以在 Markdown 形式下闡述編程概念,那麼這職業也許適合您。" + scribe_attribute_1: "文字的技巧幾乎是您全部所需要的。不只是文法和拼字,但還需傳達複雜概念給閱讀的人。" contact_us_url: "聯繫我們" - scribe_join_description: "告訴我們更多關於您的資訊, 您的編程經驗和一些您喜歡寫下的東西。 我們將從這些地方開始!" + scribe_join_description: "告訴我們更多關於您的資訊,您的編程經驗和一些您喜歡寫下的東西。我們將從這些地方開始!" scribe_subscribe_desc: "取得公告關於寫作文章的郵件。" - diplomat_introduction_pref: "所以, 如果說我們從" + diplomat_introduction_pref: "所以,如果說我們從" diplomat_launch_url: " 十月的那次上線 " - diplomat_introduction_suf: "中得到了怎樣的啟發: 那就是在許多國家有許多人對CodeCombat產生興趣! 我們正在建立一群翻譯者,急於將一組組的英文翻譯成各國語言讓CodeCombat可以讓全世界更多人都可以接觸。 如果您喜歡搶先閱讀新內容並且讓您的國人都可以儘速的擁有, 那麼這職業也許適合您。" - diplomat_attribute_1: "擁有流利的英文並且喜歡翻譯某種語言。 當傳遞複雜想法時, 您必須這兩種語言都是熟悉的!" - diplomat_i18n_page_prefix: "您可以開始從我們的" + diplomat_introduction_suf: "中得到了怎樣的啟發:那就是在許多國家有許多人對CodeCombat產生興趣!我們正在建立一群翻譯者,急於將一組組的英文翻譯成各國語言讓CodeCombat可以讓全世界更多人都可以接觸。如果您喜歡搶先閱讀新內容並且讓您的國人都可以儘速的擁有,那麼這職業也許適合您。" + diplomat_attribute_1: "擁有流利的英文並且喜歡翻譯某種語言。當傳遞複雜想法時,您必須這兩種語言都是熟悉的!" + diplomat_i18n_page_prefix: "您可以從我們的" diplomat_i18n_page: " 翻譯頁面 " - diplomat_i18n_page_suffix: "翻譯我們的關卡, 或者從我們在 GitHub 上的頁面。" + diplomat_i18n_page_suffix: "或者從我們在 GitHub 上的頁面開始翻譯我們的關卡。" diplomat_join_pref_github: "在" diplomat_github_url: " GitHub " - diplomat_join_suf_github: "找到您的語言文件 (繁體中文的是: codecombat/app/locale/zh-HANT.coffee), 在線編輯它, 並且上傳一個 pull 請求。 另外, 勾選底下的條件來借由郵件獲得及時的國際化開發!" + diplomat_join_suf_github: "找到您的語言文件 (繁體中文的是:codecombat/app/locale/zh-HANT.coffee),在線編輯它,並且上傳一個 pull 請求。另外,勾選底下的條件來藉由郵件獲得及時的國際化開發!" diplomat_subscribe_desc: "取得國際化開發和待翻譯關卡的郵件。" - ambassador_introduction: "這是個我們正在建立的社群, 您將是我們與世界的連接點。 我們在論壇, 郵件, 社群網路上和許多人交談並且幫助彼此熟悉遊戲以及互相學習。 如果您想要幫助其它人參與並且從中獲得許多樂趣, 以及樂於感受CodeCombat的脈搏和我們將前往的地方, 那麼這職業也許適合您。" - ambassador_attribute_1: "溝通技巧。 可以找到玩家正面臨的問題並且幫助他們解決。 另外, 保持與我們聯繫玩家們討論的, 喜愛的, 厭惡的以及想要的!" - ambassador_join_desc: "告訴我們更多關於您的資訊, 您已完成的事情和您喜歡做的事情。 我們將從這些地方開始!" + ambassador_introduction: "這是個我們正在建立的社群,您將是我們與世界的連接點。我們在論壇、郵件、社群網路上和許多人交談並且幫助彼此熟悉遊戲以及互相學習。如果您想要幫助其他人參與並且從中獲得許多樂趣,以及樂於感受CodeCombat的脈搏和我們將前往的地方,那麼這職業也許適合您。" + ambassador_attribute_1: "溝通技巧。可以找到玩家正面臨的問題並且幫助他們解決。另外,保持與我們聯繫玩家們討論的、喜愛的、厭惡的以及想要的!" + ambassador_join_desc: "告訴我們更多關於您的資訊,您已完成的事情和您喜歡做的事情。我們將從這些地方開始!" ambassador_join_note_strong: "注意" - ambassador_join_note_desc: "其中一件我們優先要做的事情是建立多人連線, 玩家將面臨獨自難以解決的關卡而且可以招喚更高等級的法師來幫助。 這將對於使節是一個很棒的方式來完成自己的責任。 我們會及時地向大家公佈!" + ambassador_join_note_desc: "其中一件我們優先要做的事情是建立多人連線,玩家將面臨難以獨自解決的關卡而且可以招喚更高等級的法師來幫助。這將對於使節是一個很棒的方式來完成自己的責任。我們會及時地向大家公佈!" ambassador_subscribe_desc: "取得更新和多人連線開發的郵件。" - changes_auto_save: "當您勾選後, 改變將自動儲存。" - diligent_scribes: "我們勤奮的文書:" - powerful_archmages: "我們強勁的大法師:" - creative_artisans: "我們創意的工匠:" - brave_adventurers: "我們勇敢的冒險家:" - translating_diplomats: "我們翻譯中的外交官:" - helpful_ambassadors: "我們善於幫助的使節:" + changes_auto_save: "當您勾選後,改變將自動儲存。" + diligent_scribes: "我們勤奮的文書:" + powerful_archmages: "我們強勁的大法師:" + creative_artisans: "我們創意的工匠:" + brave_adventurers: "我們勇敢的冒險家:" + translating_diplomats: "我們翻譯中的外交官:" + helpful_ambassadors: "我們善於幫助的使節:" ladder: - please_login: "在參與對弈前請先登入." + please_login: "在參與對弈前請先登入。" my_matches: "我的對手" simulate: "模擬" - simulation_explanation: "通過模擬遊戲,您可以使您的遊戲更快得到評分!" + simulation_explanation: "通過模擬遊戲,您可以使您的遊戲更快得到評分!" simulation_explanation_leagues: "你會主要給在你的部落或者課程的同伴幫忙模擬遊戲。" - simulate_games: "模擬遊戲!" - games_simulated_by: "您模擬過的次數:" - games_simulated_for: "替您模擬的次數:" + simulate_games: "模擬遊戲!" + games_simulated_by: "您模擬過的次數:" + games_simulated_for: "替您模擬的次數:" games_in_queue: "遊戲正在列隊中:" games_simulated: "遊戲已模擬" games_played: "玩過的遊戲" @@ -1214,33 +1214,33 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese battle_as: "我要扮演 " summary_your: "您的 " summary_matches: "對手 - " - summary_wins: " 勝利, " + summary_wins: " 勝利," summary_losses: " 失敗" rank_no_code: "沒有新程式碼可評分" - rank_my_game: "對我的遊戲評分!" - rank_submitting: "上傳中..." + rank_my_game: "對我的遊戲評分!" + rank_submitting: "上傳中…" rank_submitted: "已上傳以求評分" rank_failed: "評分失敗" rank_being_ranked: "已評分" rank_last_submitted: "已上傳 " - help_simulate: "模擬遊戲需要幫助?" - code_being_simulated: "您的新代碼正在被其他人模擬評分中. 分數將隨每次新的配對而更新." - no_ranked_matches_pre: "對這個隊伍尚未有評分過的配對!" - no_ranked_matches_post: " 在別人的戰場上扮演競爭者並且回到這使您的代碼接受評分." + help_simulate: "模擬遊戲需要幫助?" + code_being_simulated: "您的新程式碼正在被其他人模擬評分中。分數將隨每次新的配對而更新。" + no_ranked_matches_pre: "對這個隊伍尚未有評分過的配對!" + no_ranked_matches_post: " 在別人的戰場上扮演競爭者並且回到這使您的程式碼接受評分。" choose_opponent: "選擇對手" - select_your_language: "選擇您的語言!" + select_your_language: "選擇您的語言!" tutorial_play: "教學" tutorial_recommended: "如果您尚未玩過,推薦先嘗試教學" tutorial_skip: "略過教學" - tutorial_not_sure: "不確定發生啥事?" - tutorial_play_first: "先嘗試教學." + tutorial_not_sure: "不確定發生啥事?" + tutorial_play_first: "先嘗試教學" simple_ai: "簡單人工智慧" # {change} warmup: "熱身" friends_playing: "與朋友連線" - log_in_for_friends: "登入與朋友一起玩!" - social_connect_blurb: "連線並擊敗您的朋友!" - invite_friends_to_battle: "邀請您的朋友加入此戰鬥!" - fight: "戰鬥!" + log_in_for_friends: "登入與朋友一起玩!" + social_connect_blurb: "連線並擊敗您的朋友!" + invite_friends_to_battle: "邀請您的朋友加入此戰鬥!" + fight: "戰鬥!" watch_victory: "觀看您的勝利" defeat_the: "擊敗" watch_battle: "觀看戰役" @@ -1248,9 +1248,9 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese tournament_ends: "錦標賽結束" tournament_ended: "錦標賽已結束" tournament_rules: "錦標賽規則" - tournament_blurb: "寫下程式碼, 收集金幣, 建立軍隊, 粉碎敵人, 贏得獎項,在我們價值$40,000的Greed錦標賽中升級您的職業! 查看" - tournament_blurb_criss_cross: "贏得競賽, 建造道路, 智勝對手, 收集寶石, 在我們的Criss-Crossand錦標賽中升級您的職業! 查看" - tournament_blurb_zero_sum: "在紅方法師和藍方法師的山峰對決中,同時在收集金幣和戰術上發揮你的代碼創造力。競賽在3月27日開始,在4月6日(星期一)的下午5點(PDT太平洋時區)結束。為樂趣和榮耀競賽吧!瀏覽了解更多" + tournament_blurb: "寫下程式碼,收集金幣,建立軍隊,粉碎敵人,贏得獎項,在我們價值$40,000的Greed錦標賽中升級您的職業!查看" + tournament_blurb_criss_cross: "贏得競賽,建造道路,智勝對手,收集寶石,在我們的Criss-Crossand錦標賽中升級您的職業!查看" + tournament_blurb_zero_sum: "在紅方法師和藍方法師的山峰對決中,同時在收集金幣和戰術上發揮你的程式碼創造力。競賽在3月27日開始,在4月6日(星期一)的下午5點(PDT太平洋時區)結束。為樂趣和榮耀競賽吧!瀏覽了解更多" tournament_blurb_ace_of_coders: "我的主場我主宰,在寒天雪地的冰原上和自己鏡像大戰一場吧!本次比賽將由9月16日星期三開辦到10月14日下午5點PDT。詳情請查看" tournament_blurb_blog: "我們的部落格" rules: "規則" @@ -1267,13 +1267,13 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese singleplayer_title: "單人遊戲等級" multiplayer_title: "多人遊戲等級" achievements_title: "成就" - last_played: "最後游玩" + last_played: "最後遊玩" status: "狀態" status_completed: "已完成" status_unfinished: "未完成" - no_singleplayer: "還沒有玩過單人遊戲." - no_multiplayer: "還沒有玩過多 人遊戲." - no_achievements: "還沒有取得成就." + no_singleplayer: "還沒有玩過單人遊戲" + no_multiplayer: "還沒有玩過多人遊戲" + no_achievements: "還沒有取得成就" favorite_prefix: "語言喜好為" favorite_postfix: "." not_member_of_clans: "還不是任何一個部落裡的成員。" @@ -1296,8 +1296,8 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese purchased: "已購買" subscription: "訂閱" invoices: "收據" - service_apple: "設備: Apple" - service_web: "設備: Web" + service_apple: "設備:Apple" + service_web: "設備:Web" paid_on: "支付" service: "服務" price: "價格" @@ -1309,8 +1309,8 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese cost: "花費" next_payment: "下次付款" card: "信用卡" - status_unsubscribed_active: "您尚未訂閱並且將不會收到賬單,但是您的帳號現在仍然是有效的." - status_unsubscribed: "借由訂閱CodeCombat,取得存取新關卡,新英雄,新物品和額外寶石的資格!" + status_unsubscribed_active: "您尚未訂閱並且將不會收到賬單,但是您的帳號現在仍然是有效的。" + status_unsubscribed: "藉由訂閱CodeCombat,取得存取新關卡、新英雄、新物品和額外寶石的資格!" account_invoices: amount: "金額(美元)" @@ -1318,7 +1318,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese invalid_amount: "請輸入美元金額。" not_logged_in: "登錄或創建一個帳戶來獲取發票。" pay: "付費發票" - purchasing: "購買中···" + purchasing: "購買中…" retrying: "服務器錯誤,重試中。" success: "支付成功。謝謝!" @@ -1339,7 +1339,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese # copy_link: "You can copy the code's link and send it to someone." # quantity: "Quantity" # redeemed: "Redeemed" -# no_codes: "No codes yet!" +# no_codes: "No codes yet!" # you_can1: "You can" # you_can2: "purchase a prepaid code" # you_can3: "that can be applied to your own account or given to others." @@ -1347,7 +1347,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese loading_error: could_not_load: "從伺服器載入失敗" connection_failure: "連線失敗。" - unauthorized: "您需要先登錄。 您把cookies禁用了嗎?" + unauthorized: "您需要先登錄。您把cookies禁用了嗎?" forbidden: "您沒有權限。" not_found: "沒找到。" not_allowed: "方法不被允許。" @@ -1370,7 +1370,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese gplus_friend_sessions: "Google+ 朋友會話" leaderboard: "排行榜" user_schema: "用戶模式" - user_profile: "用戶信息" + user_profile: "用戶資料" patch: "修補" patches: "修補" patched_model: "資源文擋" @@ -1426,11 +1426,11 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese arithmetic: "四則運算" arrays: "陣列" basic_syntax: "基本語法" - boolean_logic: "布爾邏輯" + boolean_logic: "布林邏輯" break_statements: "Break語句" classes: "類" continue_statements: "Continue 語句" - for_loops: "For循環" + for_loops: "For迴圈" functions: "函數" graphics: "圖形" if_statements: "If語句" @@ -1439,9 +1439,9 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese object_literals: "對象常量" parameters: "參數" strings: "字符串" - variables: "變量" + variables: "變數" vectors: "向量" - while_loops: "循環" + while_loops: "while迴圈" recursion: "遞歸" delta: @@ -1461,7 +1461,7 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese multiplayer_link_description: "把這個連結告訴同伴們,一起玩吧。" multiplayer_hint_label: "提示:" multiplayer_hint: " 點擊全選,然後按 ⌘-C 或 Ctrl-C 複製連結。" - multiplayer_coming_soon: "請期待更多的多人關卡!" + multiplayer_coming_soon: "請期待更多的多人關卡!" multiplayer_sign_in_leaderboard: "註冊並且登入帳號,就可以將您的成就放在排行榜上。" legal: @@ -1469,55 +1469,55 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese opensource_intro: "CodeCombat是完全的開源。" opensource_description_prefix: "查看 " github_url: "我們的 GitHub" - opensource_description_center: "並且如果有興趣也歡迎您的幫助! CodeCombat是建立在許多的開源專案上, 並且我們深愛它們。 查看 " + opensource_description_center: "並且如果有興趣也歡迎您的幫助! CodeCombat是建立在許多的開源專案上,並且我們深愛它們。查看 " archmage_wiki_url: "我們的大法師wiki" opensource_description_suffix: " 尋求創造這款遊戲的相關軟體列表。" practices_title: "值得尊敬的最佳實踐" - practices_description: "這些是我們給您, 給玩家的承諾, 儘管這在法律上略顯不足。" + practices_description: "這些是我們給您,給玩家的承諾,儘管這在法律上略顯不足。" privacy_title: "隱私" privacy_description: "我們將不會賣出任何關於您個人的資訊。" security_title: "安全" - security_description: "我們渴望保持您的個人資訊是安全的. 身為一個開源的專案, 我們的網站是開放給任何人來檢視並且提升我們的安全系統。" + security_description: "我們渴望保持您的個人資訊是安全的。身為一個開源的專案,我們的網站是開放給任何人來檢視並且提升我們的安全系統。" email_title: "郵件" - email_description_prefix: "我們將不會使您的信箱氾濫的收到垃圾信。 不論" + email_description_prefix: "我們將不會使您的信箱氾濫的收到垃圾信。不論" email_settings_url: " 在您的郵件設定 " - email_description_suffix: "或在我們送出的信件上都有留著我們的聯結, 您可以更改您的喜好並且輕易的隨時取消訂閱。" + email_description_suffix: "或在我們送出的信件上都有留著我們的聯結,您可以更改您的喜好並且輕易的隨時取消訂閱。" cost_title: "花費" - cost_description: "CodeCombat在核心的關卡是全部免費, 但只要花費一個月${{price}}美金來訂閱, 您將在每個月取得額外的關卡和{{gems}}顆寶石。 您可以輕易地取消訂閱並且保證取得100%的退費。" + cost_description: "CodeCombat在核心的關卡是全部免費,但只要花費一個月${{price}}美金來訂閱,您將在每個月取得額外的關卡和{{gems}}顆寶石。您可以輕易地取消訂閱並且保證取得100%的退費。" copyrights_title: "版權和許可" contributor_title: "貢獻者許可協議" - contributor_description_prefix: "所有在本網站或是 GitHub 代碼庫上的貢獻都依照我們的" + contributor_description_prefix: "所有在本網站或是 GitHub 程式碼庫上的貢獻都依照我們的" cla_url: "貢獻者許可協議" - contributor_description_suffix: "而這在您貢獻之前就應該已经同意。" + contributor_description_suffix: "而這在您貢獻之前就應該已經同意。" code_title: "Code - MIT" - code_description_prefix: "所有由 CodeCombat 擁有或是托管在 codecombat.com 的代码,在 GitHub 代碼庫或者 codecombat.com 數據庫,以上許可協議都依照" + code_description_prefix: "所有由 CodeCombat 擁有或是托管在 codecombat.com 的程式碼,在 GitHub 程式碼庫或者 codecombat.com 數據庫,以上許可協議都依照" mit_license_url: "MIT license" - code_description_suffix: "這包括所有 CodeCombat 公開製作關卡用的系统和組件代碼。" + code_description_suffix: "這包括所有 CodeCombat 公開製作關卡用的系统和組件程式碼。" art_title: "藝術/音樂 - Creative Commons " art_description_prefix: "所有共通的内容都在" cc_license_url: "Creative Commons Attribution 4.0 International License" - art_description_suffix: "共通内容是指所有 CodeCombat 發佈出来用于製作關卡的内容。包括:" + art_description_suffix: "共通内容是指所有 CodeCombat 發佈出來用於製作關卡的内容。包括:" art_music: "音樂" art_sound: "聲音" art_artwork: "藝術作品" art_sprites: "貼圖" - art_other: "所有製作關卡時公開的,不是代碼的創造性產品。" - art_access: "目前還没有簡便通用的下载素材方式。 一般来說,從網站上使用的URL下载,或者聯繫我们尋求幫助。 當然您也可以幫助我们拓展網站,使這些資源更容易下載。" - art_paragraph_1: "為了歸屬, 請在使用處或適當的地方說明, 或者留下一個聯結至codecombat.com. 例如:" - use_list_1: "如果使用在電影或者另一款遊戲中, 請在製作人員表中加入codecombat.com" - use_list_2: "如果使用在網站上, 請在使用處留下codecombat.com, 例如在圖片下面或一個您專門放置Creative Commons和開源專案的地方. 如果您的内容明確提到關於 CodeCombat, 那您就不需要額外署名." - art_paragraph_2: "如果您使用的內容非由CodeCombat製作但由一位codecombat.com中的使用者, 那您應該署名他。 並且如果相對應的頁面上有標記署名指示, 那您應該遵照其指示。" + art_other: "所有製作關卡時公開的,不是程式碼的創造性產品。" + art_access: "目前還没有簡便通用的下載素材方式。一般來說,從網站上使用的URL下載,或者聯繫我們尋求幫助。當然您也可以幫助我們拓展網站,使這些資源更容易下載。" + art_paragraph_1: "為了歸屬,請在使用處或適當的地方說明,或者留下一個聯結至codecombat.com。例如:" + use_list_1: "如果使用在電影或者另一款遊戲中,請在製作人員表中加入codecombat.com" + use_list_2: "如果使用在網站上,請在使用處留下codecombat.com,例如在圖片下面或一個您專門放置Creative Commons和開源專案的地方。如果您的内容明確提到關於 CodeCombat,那您就不需要額外署名。" + art_paragraph_2: "如果您使用的內容非由CodeCombat製作但由一位codecombat.com中的使用者,那您應該署名他。並且如果相對應的頁面上有標記署名指示,那您應該遵照其指示。" rights_title: "保留權利" - rights_desc: "所有版權由關卡本身擁有, 這包含:" + rights_desc: "所有版權由關卡本身擁有,這包含:" rights_scripts: "腳本" rights_unit: "單元配置" rights_description: "描述" rights_writings: "寫作" - rights_media: "聲音、音樂以及其他專門為某道關卡製作, 而不對其他關卡開放的創造性内容。" - rights_clarification: "澄清一下, 所有在關卡编辑器裡公開用於制作關卡的資源都是在CC協議下發佈的, 然而使用關卡编辑器製作,或者在關卡製作過程中上傳的内容则不是." + rights_media: "聲音、音樂以及其他專門為某道關卡製作,而不對其他關卡開放的創造性内容。" + rights_clarification: "澄清一下,所有在關卡編輯器裡公開用於製作關卡的資源都是在CC協議下發佈的,然而使用關卡編輯器製作,或者在關卡製作過程中上傳的内容則不是。" nutshell_title: "簡而言之" - nutshell_description: "我们在關卡编辑器里公開的任何資源, 您都可以在製作關卡時隨意使用, 但我们保留在 codecombat.com 之上創建的關卡本身傳播的權利, 因为我们往後可能決定以它們收費." - canonical: "我們宣告這篇說明的英文版本是權威版本。 如果各個翻譯版本之間有任何衝突, 以英文版為準。" + nutshell_description: "我們在關卡編輯器裡公開的任何資源,您都可以在製作關卡時隨意使用,但我們保留在 codecombat.com 之上創建的關卡本身傳播的權利,因為我們往後可能決定以它們收費。" + canonical: "我們宣告這篇說明的英文版本是權威版本。如果各個翻譯版本之間有任何衝突,以英文版為準。" # third_party_title: "Third Party Services" # third_party_description: "CodeCombat uses the following third party services (among others):" @@ -1525,9 +1525,9 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese title: "錦標賽獎項" # This section was for an old tournament and doesn't need new translations now. blurb_1: "依據" blurb_2: "錦標賽規則" - blurb_3: ", 這些獎項將被頒發給頂尖的人類和怪物玩家." - blurb_4: "兩隊意指獎項是兩倍!" - blurb_5: "(將有兩個第一名, 兩個第二名, etc.)" + blurb_3: ",這些獎項將被頒發給頂尖的人類和怪物玩家。" + blurb_4: "兩隊意指獎項是兩倍!" + blurb_5: "(將有兩個第一名、兩個第二名,以此類推。)" rank: "排名" prizes: "獎項" total_value: "總價值" @@ -1536,8 +1536,8 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese custom_avatar: "定制 CodeCombat 頭像" heap: "給六個月的\"Startup\"訪問" credits: "信譽" - one_month_coupon: "優惠: 選擇 Rails 或者 HTML" - one_month_discount: "折扣 30% : 選擇 Rails 或者 HTML" + one_month_coupon: "優惠:選擇 Rails 或者 HTML" + one_month_discount: "折扣 30%:選擇 Rails 或者 HTML" license: "許可證" oreilly: "您選擇的電子書" @@ -1545,16 +1545,16 @@ module.exports = nativeDescription: "繁體中文", englishDescription: "Chinese av_espionage: "Espionage" # Really not important to translate /admin controls. av_espionage_placeholder: "信箱或用戶名" av_usersearch: "用戶搜尋" - av_usersearch_placeholder: "信箱, 用戶名, 姓名, 任何東西" + av_usersearch_placeholder: "信箱、用戶名、姓名,任何東西" av_usersearch_search: "搜尋" av_title: "管理員視野" av_entities_sub_title: "商業個體" av_entities_users_url: "使用者" av_entities_active_instances_url: "有效實例" - av_entities_user_code_problems_list_url: "用戶代碼問題列表" + av_entities_user_code_problems_list_url: "用戶程式碼問題列表" av_other_sub_title: "其他" av_other_debug_base_url: "Base (用於測試 base.jade)" u_title: "用戶列表" - ucp_title: "用戶代碼問題" + ucp_title: "用戶程式碼問題" lg_title: "最新遊戲" clas: "貢獻者許可協議" From 070324e9c5b25d5fb0cd2ce590242837887f552d Mon Sep 17 00:00:00 2001 From: durianboy Date: Fri, 8 Jan 2016 05:34:47 +0800 Subject: [PATCH 07/10] Update zh-HANT.coffee From 017dea696f753dbfcb27557e2e11cb43f54c62cc Mon Sep 17 00:00:00 2001 From: Matt Lott Date: Thu, 7 Jan 2016 15:45:46 -0800 Subject: [PATCH 08/10] Remove HoC extra 2 months trial enrollments --- app/templates/teachers-free-trial.jade | 3 --- server/sendwithus.coffee | 2 +- server/trial_requests/TrialRequest.coffee | 22 ++-------------------- 3 files changed, 3 insertions(+), 24 deletions(-) diff --git a/app/templates/teachers-free-trial.jade b/app/templates/teachers-free-trial.jade index 133ebd98b..0dbb89113 100644 --- a/app/templates/teachers-free-trial.jade +++ b/app/templates/teachers-free-trial.jade @@ -31,9 +31,6 @@ block content span.spl(data-i18n="teachers_survey.contact_2") else p(data-i18n="teachers_survey.description_1") - p - strong.spr Hour of Code Special! - span Complete the survey by December 31st and enroll all your students in the paid courses for 2 months. p span.spr(data-i18n="teachers_survey.description_1b") a(href='/teachers', data-i18n="teachers_survey.description_2") diff --git a/server/sendwithus.coffee b/server/sendwithus.coffee index 121090628..a43c53834 100644 --- a/server/sendwithus.coffee +++ b/server/sendwithus.coffee @@ -22,5 +22,5 @@ module.exports.templates = plain_text_email: 'tem_85UvKDCCNPXsFckERTig6Y' next_steps_email: 'tem_RDHhTG5inXQi8pthyqWr5D' course_invite_email: 'tem_u6D2EFWYC5Ptk38bSykjsU' - teacher_free_trial: 'tem_sqdvLCZRwoDQc6jAf5RrQE' + teacher_free_trial: 'tem_R7d9Hpoba9SceQNiYSXBak' teacher_free_trial_hoc: 'tem_4ZSY9wsA9Qwn4wBFmZgPdc' diff --git a/server/trial_requests/TrialRequest.coffee b/server/trial_requests/TrialRequest.coffee index 079a8f100..a5de8f871 100644 --- a/server/trial_requests/TrialRequest.coffee +++ b/server/trial_requests/TrialRequest.coffee @@ -21,32 +21,14 @@ TrialRequestSchema.pre 'save', (next) -> prepaid.save (err) => if err log.error "Trial request prepaid creation error: #{err}" - - # Special HoC trial: Add 500 course headcount with end date - endDate = new Date() - endDate.setUTCMonth(endDate.getUTCMonth() + 2) - prepaid = new Prepaid - creator: @get('applicant') - type: 'course' - maxRedeemers: 500 - properties: - endDate: endDate - trialRequestID: @get('_id') - prepaid.save (err) => - if err - log.error "Trial request prepaid creation error: #{err}" - next() + next() TrialRequestSchema.post 'save', (doc) -> if doc.get('status') is 'approved' - endDate = new Date() - endDate.setUTCMonth(endDate.getUTCMonth() + 2) emailParams = recipient: address: doc.get('properties')?.email - email_id: sendwithus.templates.teacher_free_trial_hoc - email_data: - endDate: endDate.toDateString() + email_id: sendwithus.templates.teacher_free_trial sendwithus.api.send emailParams, (err, result) => log.error "sendwithus trial request approved error: #{err}, result: #{result}" if err From d74b61fd964dd74c9a5f9683f42e29881de10a0f Mon Sep 17 00:00:00 2001 From: Matt Lott Date: Thu, 7 Jan 2016 16:14:33 -0800 Subject: [PATCH 09/10] Update approved trial request server test --- spec/server/functional/trial_request.spec.coffee | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/spec/server/functional/trial_request.spec.coffee b/spec/server/functional/trial_request.spec.coffee index 8077fd2d0..cbcae5c89 100644 --- a/spec/server/functional/trial_request.spec.coffee +++ b/spec/server/functional/trial_request.spec.coffee @@ -129,15 +129,11 @@ describe 'Trial Requests', -> Prepaid.find {'properties.trialRequestID': doc.get('_id')}, (err, prepaids) -> expect(err).toBeNull() return done(err) if err - expect(prepaids.length).toEqual(2) - for prepaid in prepaids - expect(prepaid.get('type')).toEqual('course') - expect(prepaid.get('creator')).toEqual(user.get('_id')) - if prepaid.get('properties').endDate - expect(prepaid.get('maxRedeemers')).toEqual(500) - expect(prepaid.get('properties').endDate).toBeGreaterThan(new Date()) - else - expect(prepaid.get('maxRedeemers')).toEqual(2) + expect(prepaids.length).toEqual(1) + prepaid = prepaids[0] + expect(prepaid.get('type')).toEqual('course') + expect(prepaid.get('creator')).toEqual(user.get('_id')) + expect(prepaid.get('maxRedeemers')).toEqual(2) done() it 'Deny trial request', (done) -> From 213f3edd0dc490efbc734af5fe53192d85e815c6 Mon Sep 17 00:00:00 2001 From: Matt Lott Date: Fri, 8 Jan 2016 10:25:21 -0800 Subject: [PATCH 10/10] Update /about team section --- app/locale/en.coffee | 36 +++++----- app/styles/about.sass | 8 ++- app/templates/about.jade | 150 ++++++++++++++------------------------- 3 files changed, 76 insertions(+), 118 deletions(-) diff --git a/app/locale/en.coffee b/app/locale/en.coffee index 2b26d42b1..823d17cdb 100644 --- a/app/locale/en.coffee +++ b/app/locale/en.coffee @@ -553,34 +553,30 @@ press_paragraph_1_link: "press packet" press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly." team: "Team" - george_title: "Cofounder" - george_blurb: "Businesser" - scott_title: "Cofounder" - scott_blurb: "Reasonable One" - nick_title: "Cofounder" + nick_title: "Cofounder, CEO" # {change} nick_blurb: "Motivation Guru" - michael_title: "Programmer" - michael_blurb: "Sys Admin" - matt_title: "Cofounder" + matt_title: "Cofounder, CTO" # {change} matt_blurb: "Bicyclist" - cat_title: "Chief Artisan" + cat_title: "Game Designer" # {change} cat_blurb: "Airbender" - josh_title: "Game Designer" - josh_blurb: "Floor Is Lava" - jose_title: "Music" - jose_blurb: "Taking Off" - retrostyle_title: "Illustration" - retrostyle_blurb: "RetroStyle Games" - rob_title: "Compiler Engineer" + scott_title: "Cofounder, Software Engineer" # {change} + scott_blurb: "Reasonable One" + maka_title: "Customer Advocate" + maka_blurb: "Storyteller" + rob_title: "Software Engineer" # {change} rob_blurb: "Codes things and stuff" josh_c_title: "Game Designer" josh_c_blurb: "Designs games" - carlos_title: "Region Manager, Brazil" - carlos_blurb: "Celery Man" - maka_title: "Customer Advocate" - maka_blurb: "Storyteller" robin_title: "UX Design & Research" robin_blurb: "Scaffolding" + josh_title: "Game Designer" + josh_blurb: "Floor Is Lava" + retrostyle_title: "Illustration" + retrostyle_blurb: "RetroStyle Games" + jose_title: "Music" + jose_blurb: "Taking Off" + carlos_title: "Region Manager, Brazil" + carlos_blurb: "Celery Man" teachers: who_for_title: "Who is CodeCombat for?" diff --git a/app/styles/about.sass b/app/styles/about.sass index ccb7787f7..d067f2455 100644 --- a/app/styles/about.sass +++ b/app/styles/about.sass @@ -23,8 +23,14 @@ margin: 0px 10px 22px 0px .team_name + font-size: 20px margin-top: 0 .team_bio width: 150px - float: left \ No newline at end of file + float: left + + div + font-size: 12px + line-height: 14px + padding-bottom: 5px \ No newline at end of file diff --git a/app/templates/about.jade b/app/templates/about.jade index e4c139ce0..a420ab3cf 100644 --- a/app/templates/about.jade +++ b/app/templates/about.jade @@ -73,67 +73,74 @@ block content h2(data-i18n="about.team") Team + // Full time + a(href="http://www.nickwinter.net") img(src="/images/pages/about/nick_small.png").img-thumbnail .team_bio h4.team_name a(href="http://www.nickwinter.net") Nick Winter - p(data-i18n="about.nick_title") - | Cofounder - p(data-i18n="about.nick_blurb") - | Motivation Guru + div(data-i18n="about.nick_title") + div(data-i18n="about.nick_blurb") a(href="http://www.mattlott.com/") img(src="/images/pages/about/matt_small.png").img-thumbnail .team_bio h4.team_name a(href="http://www.mattlott.com/") Matt Lott - p(data-i18n="about.matt_title") - | Cofounder - p(data-i18n="about.matt_blurb") - | Bicyclist + div(data-i18n="about.matt_title") + div(data-i18n="about.matt_blurb") li.row - a(href="http://www.georgesaines.com/") - img(src="/images/pages/about/george_small.png").img-thumbnail - .team_bio - h4.team_name - a(href="http://www.georgesaines.com/") George Saines - p(data-i18n="about.george_title") - | Cofounder - p(data-i18n="about.george_blurb") - | Businesser - a(href="http://cat.zdh.com/") img(src="/images/pages/about/cat_small.png").img-thumbnail .team_bio h4.team_name a(href="http://cat.zdh.com/") Catherine Weresow - p(data-i18n="about.cat_title") - | Chief Artisan - p(data-i18n="about.cat_blurb") - | Airbender - - li.row + div(data-i18n="about.cat_title") + div(data-i18n="about.cat_blurb") img(src="/images/pages/about/scott_small.png").img-thumbnail .team_bio h4.team_name Scott Erickson - p(data-i18n="about.scott_title") - | Cofounder - p(data-i18n="about.scott_blurb") - | Reasonable one + div(data-i18n="about.scott_title") + div(data-i18n="about.scott_blurb") - a(href="http://michaelschmatz.com") - img(src="/images/pages/about/michael_small.png").img-thumbnail + li.row + + img(src="/images/pages/about/maka_small.png").img-thumbnail + .team_bio + h4.team_name Michael 'Maka' Gradin + div(data-i18n="about.maka_title") + div(data-i18n="about.maka_blurb") + + a(href="http://basicer.com/") + img(src="/images/pages/about/rob_small.png").img-thumbnail .team_bio h4.team_name - a(href="http://michaelschmatz.com/") Michael Schmatz - p(data-i18n="about.michael_title") - | Programmer - p(data-i18n="about.michael_blurb") - | Sys Admin + a(href="http://basicer.com/") Rob Blanckaert + div(data-i18n="about.rob_title") + div(data-i18n="about.rob_blurb") + + li.row + + img(src="/images/pages/about/josh_c_small.png").img-thumbnail + .team_bio + h4.team_name Josh Callebaut + div(data-i18n="about.josh_c_title") + div(data-i18n="about.josh_c_blurb") + + a(href="http://robinyang.com/") + img(src="/images/pages/about/robin_small.png").img-thumbnail + .team_bio + h4.team_name + a(href="http://robinyang.com/") Robin Yang + div(data-i18n="about.robin_title") + div(data-i18n="about.robin_blurb") + + + // Part time / contract li.row @@ -142,20 +149,16 @@ block content .team_bio h4.team_name a(href="http://floor.is/lava/") Josh Lee - p(data-i18n="about.josh_title") - | Game Designer - p(data-i18n="about.josh_blurb") - | Floor Is Lava + div(data-i18n="about.josh_title") + div(data-i18n="about.josh_blurb") a(href="https://soundcloud.com/taking-off") img(src="/images/pages/about/jose_small.png").img-thumbnail .team_bio h4.team_name a(href="https://soundcloud.com/taking-off") Jose Antonini - p(data-i18n="about.jose_title") - | Music - p(data-i18n="about.jose_blurb") - | Taking Off + div(data-i18n="about.jose_title") + div(data-i18n="about.jose_blurb") li.row @@ -164,69 +167,22 @@ block content .team_bio h4.team_name a(href="http://retrostylegames.com/") Pavel Konstantinov - p(data-i18n="about.retrostyle_title") - | Illustration - p(data-i18n="about.retrostyle_blurb") - | RetroStyle Games + div(data-i18n="about.retrostyle_title") + div(data-i18n="about.retrostyle_blurb") a(href="http://retrostylegames.com/") img(src="/images/pages/about/oleg_small.png").img-thumbnail .team_bio h4.team_name a(href="http://retrostylegames.com/") Oleg Ulyanickiy - p(data-i18n="about.retrostyle_title") - | Illustration - p(data-i18n="about.retrostyle_blurb") - | RetroStyle Games - - li.row - - a(href="http://basicer.com/") - img(src="/images/pages/about/rob_small.png").img-thumbnail - .team_bio - h4.team_name - a(href="http://basicer.com/") Rob Blanckaert - p(data-i18n="about.rob_title") - | Compiler Engineer - p(data-i18n="about.rob_blurb") - | Codes things and stuff. - - img(src="/images/pages/about/josh_c_small.png").img-thumbnail - .team_bio - h4.team_name - | Josh Callebaut - p(data-i18n="about.josh_c_title") - | Game Designer - p(data-i18n="about.josh_c_blurb") - | Designs games. + div(data-i18n="about.retrostyle_title") + div(data-i18n="about.retrostyle_blurb") li.row img(src="/images/pages/about/carlos_small.png").img-thumbnail .team_bio - h4.team_name - | Carlos Maia - p(data-i18n="about.carlos_title") - | Region Manager, Brazil - p(data-i18n="about.carlos_blurb") - | Celery Man + h4.team_name Carlos Maia + div(data-i18n="about.carlos_title") + div(data-i18n="about.carlos_blurb") - img(src="/images/pages/about/maka_small.png").img-thumbnail - .team_bio - h4.team_name - | Michael 'Maka' Gradin - p(data-i18n="about.maka_title") - | Customer Advocate - p(data-i18n="about.maka_blurb") - | Storyteller - - li.row - - img(src="/images/pages/about/robin_small.png").img-thumbnail - .team_bio - h4.team_name - | Robin Yang - p(data-i18n="about.robin_title") - | UX Design & Research - p(data-i18n="about.robin_blurb") - | Scaffolding \ No newline at end of file