Mark robot#respondPattern as Public method.

--- src/robot.coffee
+++ src/robot.coffee
@@ -93,7 +93,7 @@
   respond: (regex, options, callback) ->
     @listeners.push new TextListener(@, @respondPattern(regex), options, callback)

-  # Private: Build a regular expression that matches messages addressed
+  # Public: Build a regular expression that matches messages addressed
   # directly to the robot
   #
   # regex - A RegExp for the message part that follows the robot's name/alias


require body parser

require body parser

--- src/robot.coffee
+++ src/robot.coffee
@@ -418,6 +418,7 @@

     express = require 'express'
     multipart = require 'connect-multiparty'
+    bodyParser = require 'body-parser'

     app = express()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/score.coffee
+++ src/score.coffee
@@ -1,5 +1,5 @@
 ###*
-The score module
+The score module overlays

 @name Oscillator
 @constructor


setup: Improve Error message when child fails

--- src/setup.coffee
+++ src/setup.coffee
@@ -27,10 +27,11 @@
   else
     prog = cmd.split(' ')[0]
     args = cmd.split(' ').splice(1)
+  cmd = prog + ' ' + args.join(' ')

   childoptions =
     env: env
-  debug 'participant process start', prog, args.join(' ')
+  debug 'participant process start', cmd
   child = child_process.spawn prog, args, childoptions
   returned = false
   child.on 'error', (err) ->
@@ -55,7 +56,7 @@
     debug 'child exited', code, signal
     return if returned
     returned = true
-    return callback new Error "Child exited with #{code} #{signal}"
+    return callback new Error "Child '#{cmd}' (pid=#{child.pid}) exited with #{code} #{signal}"
   return child

 participantCommands = (graph, library, only, ignore) ->


link_names fixed

link_names fixed

--- src/slack.coffee
+++ src/slack.coffee
@@ -30,7 +30,7 @@
         username   : @robot.name
         channel    : channel
         text       : str
-        link_names : @options.link_names
+        link_names : @options.link_names if @options?.link_names?

       @post "/services/hooks/hubot", args


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/tween.coffee
+++ src/tween.coffee
@@ -23,7 +23,7 @@
         I[property] = f(t)

   ###*
-  Modify the objects properties over time.
+  Modify the object's properties over time.

   player = GameObject()


GameObject.Effect

GameObject.Effect

--- src/tween.coffee
+++ src/tween.coffee
@@ -13,9 +13,9 @@

   # Add events and methods here
   self.bind "update", (elapsedTime) ->
-    t =
+    t = I.age + elapsedTime
     for property, data of I.activeTweens
-      if I.age + elapsedTime >= data.endTime
+      if t >= data.endTime
         I[property] = data.end
         I.activeTweens[property].complete?()
         delete I.activeTweens[property]


Fix code style.

Fix code style.

--- src/watch.coffee
+++ src/watch.coffee
@@ -81,7 +81,8 @@
     config.paths.config, config.paths.packageConfig
   ]

-  watched.push config.paths.config + ext for ext of require.extensions
+  Object.keys(require.extensions).forEach (ext) ->
+    watched.push config.paths.config + ext

   async.filter watched, fs_utils.exists, (watchedFiles) ->
     watcher = chokidar.watch watchedFiles,
@@ -305,7 +306,8 @@
     .on 'change', (path) ->
       # If file is special (config.coffee, package.json), restart Brunch.
       isConfigFile = possibleConfigFiles[path]
-      if isConfigFile or reInstall = path is config.paths.packageConfig
+      reInstall = path is config.paths.packageConfig
+      if isConfigFile or reInstall
         reload reInstall
       else
         # Otherwise, just update file list.


Fix filtering of optimizers based on config

Resolves gh-903

--- src/watch.coffee
+++ src/watch.coffee
@@ -400,10 +400,8 @@
         plugin.defaultEnv = '*'
       plugin.optimize ?= plugin.minify if typeof plugin.minify is 'function'
       isOptimizer = typeof plugin.optimize is 'function'
-      plugin.defaultEnv ?= if not config.optimize and isOptimizer
-        'production'
-      else
-        '*'
+      return false if not config.optimize and isOptimizer
+      plugin.defaultEnv ?= '*'
       plugin.defaultEnv is '*' or plugin.defaultEnv in config.env

     # Get compilation methods.


simpler bucket name regex

simpler bucket name regex

--- imports/ui/storage/bucket.cjsx
+++ imports/ui/storage/bucket.cjsx
@@ -42,9 +42,9 @@
             <form id="start-app-form" role="form" className="dropdown-menu dropdown-menu-right" style={padding:'1em'}>

                     Bucket name
-                    <input ref='bucketName' required pattern="/?[a-zA-Z0-9_-]+" type="text"
+                    <input ref='bucketName' required pattern="[a-zA-Z0-9_-]+" type="text"
                       className="form-control bucket-name"
-                      placeholder="A unique name. Must match /?[a-zA-Z0-9_-]+." />
+                      placeholder="A unique name. Must match [a-zA-Z0-9_-]+" />

                 <button type="submit" onClick={@copy(bucket)} className="start-app btn btn-mini">Copy</button>
             </form>


minor test changes; one test removed

minor test changes; one test removed

--- integration_test/cobalt.coffee
+++ integration_test/cobalt.coffee
@@ -62,7 +62,7 @@
       should.exist staff_api_key
       newuser = fresh_username()
       options =
-        uri: "http://#{host}/#{newuser}"
+        uri: "#{baseurl}/#{newuser}"
         form:
           apikey: staff_api_key
       request.post options, (err, resp, body) ->
@@ -156,8 +156,8 @@
         done()

     it 'SFTP works', (done) ->
-      ssh = "echo ls | sftp  #{ssh_user_args.join ' '} #{host}"
-      exec ssh, (err, stdout, stderr) ->
+      cmd = "echo ls | sftp  #{ssh_user_args.join ' '} #{host}"
+      exec cmd, (err, stdout, stderr) ->
         should.not.exist err
         done()

@@ -216,27 +216,19 @@
             jai_fini()

       describe 'with a publishing token set in scraperwiki.json', ->
-        it "doesn't allow access if wrong", (done) ->
+        it "forbids access when using wrong token", (done) ->
           scp_cmd "./integration_test/fixtures/scraperwiki-publishtoken.json", "scraperwiki.json", ->
-            request.get "#{baseurl}/#{boxname}/0987654321/http/", (err, resp, body) ->
+            url = "#{baseurl}/#{boxname}/0987654321/http/"
+            request.get url, (err, resp, body) ->
               resp.should.have.status 403
               done()

-        it "allows access with it", (done) ->
+        it "allows access when using correct token", (done) ->
           scp_cmd "./integration_test/fixtures/scraperwiki-publishtoken.json", "scraperwiki.json", ->
             request.get "#{baseurl}/#{boxname}/0123456789/http/", (err, resp, body) ->
               resp.should.have.status 200
               body.should.equal 'Testing'
               done()
-
-        it 'I am redirected for legacy URLs with / in box name', (done) ->
-            legacy_boxname = boxname.replace('.', '/')
-            request.get
-              uri: "#{baseurl}/#{legacy_boxname}/0123456789/http/index.html"
-              followRedirect:false
-              , (err, resp, body) ->
-                resp.should.have.status 301
-                done()

         it 'I am redirected to the right place for legacy URLs with / in box name', (done) ->
             legacy_boxname = boxname.replace('.', '/')
@@ -244,6 +236,7 @@
               uri: "#{baseurl}/#{legacy_boxname}/0123456789/http/index.html"
               followRedirect:true
               , (err, resp, body) ->
+                resp.request.redirects.length.should.be.above 0
                 resp.should.have.status 200
                 body.should.equal 'Testing'
                 done()


client: add webpack.NoErrorsPlugin

client: add webpack.NoErrorsPlugin

--- web/react_chat/client/webpack.config.coffee
+++ web/react_chat/client/webpack.config.coffee
@@ -21,6 +21,7 @@
     new SplitByPathPlugin [
       { path: path.resolve(__dirname, 'node_modules/'), name: 'vendor' }
     ]
+    new webpack.NoErrorsPlugin()
     new webpack.DefinePlugin
       DEBUG: JSON.stringify(DEBUG)
       'process.env.NODE_ENV': JSON.stringify(process.env.ENVIRONMENT)
@@ -32,6 +33,6 @@
   ].filter(Boolean)
   module:
     loaders: [
-      { test: /\.jsx?$/, loader: 'babel-loader?stage=1', exclude: /node_modules/ }
+      { test: /\.jsx?$/, loader: 'babel?stage=1', exclude: /node_modules/ }
     ]
   devtool: DEBUG and 'inline-source-map'


Let context handle output queue

Let context handle output queue

--- src/lib/Component.coffee
+++ src/lib/Component.coffee
@@ -214,18 +214,11 @@
       @deactivate context
       output.sendDone e

-    unless context.activated
-      if port.isAddressable()
-        debug "#{@nodeId} #{ip.type} packet on #{port.name}[#{ip.index}] didn't match preconditions"
-      else
-        debug "#{@nodeId} #{ip.type} packet on #{port.name} didn't match preconditions"
+    return if context.activated
+    if port.isAddressable()
+      debug "#{@nodeId} #{ip.type} packet on #{port.name}[#{ip.index}] didn't match preconditions"
       return
-
-    # Component fired
-    if @isOrdered()
-      # Ordered mode. Instead of sending directly, we're queueing
-      @outputQ.push result
-      do @processOutputQueue
+    debug "#{@nodeId} #{ip.type} packet on #{port.name} didn't match preconditions"
     return

   getBracketContext: (port, scope, idx) ->
@@ -390,7 +383,6 @@
     @port = @context.port
     @result = @context.result
     @scope = @context.scope
-    @activated = false

   # When preconditions are met, set component state to `activated`
   activate: ->


Added getNameParts()

Added getNameParts()

--- src/AccountsUtil.coffee
+++ src/AccountsUtil.coffee
@@ -122,6 +122,22 @@
     roles = _.toArray(arguments)
     (userId, doc) -> Roles.userIsInRole(userId, roles)

+  # Returns an object with the following, if defined:
+  #  * `name` - The full name of the user.
+  #  * `firstName` - The first name of the user.
+  #  * `lastName` - The last name of the user.
+  getNameParts: (user) ->
+    user = @resolveUser(user)
+    name = user.profile?.name
+    firstName = user.profile?.firstName
+    lastName = user.profile?.lastName
+    if name?
+      parts = name.split(/\s+/g)
+      if parts?
+        firstName ?= _.first(parts)
+        lastName ?= _.last(parts) if parts.length > 1
+    {name: name, firstName: firstName, lastName: lastName}
+
 # Set up role publications.

 if Meteor.isServer


Add links to new data files, appendix

Add links to new data files, appendix

Add links to new data downloads

--- app/lib/en_us.coffee
+++ app/lib/en_us.coffee
@@ -419,9 +419,11 @@

Blotch catalog: The resulting blotch object catalog for MRO HiRISE seasons 2 and 3 (MY29 and 30), with an applied probability cut of 0.5, i.e. when less than half of volunteers have marked an object as fan, it enters this catalog (starting with a catalog that only has fans and blotches).

HiRISE observation catalog: This file contains metadata for all HiRISE observations that were used for this catalog.

Planet Four tile catalog: This file contains data to locate all Planet Four tiles on a Mars map, using either Mars-centered fixed frame coordinates, or latitude and longitude.

+
Raw data: Planet Four raw classification data that was used in our reduction pipeline to create the fan and blotch catalog that is linked on this page (described in Appendix C of the paper, linked below). User names have been anonymized for data privacy.

+
Intermediate data products: These are the products as described in Appendix D of the paper, linked below. A researcher can apply a different cut on the probability of fan vs blotch identification using these products, reproducing a new fan catalog.

-
More details about the structure of these files can be found in Appendix E of our paper.

+
More details about the structure of these files can be found in Appendices C to E.

We acknowledge the contributions of the Planet Four volunteer community to this work here.

   '''


Add indicator to changed string

Add indicator to changed string

--- app/locale/en.coffee
+++ app/locale/en.coffee
@@ -993,7 +993,7 @@
     additional_resources_1_mid: "Course 1 Teacher's Guide"
     additional_resources_1_suff: "explanations and solutions to each level."
     additional_resources_2_pref: "Complete our"
-    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses."
+    additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses." # {change}
     additional_resources_3_pref: "Visit our"
     additional_resources_3_mid: "Teacher Forums"
     additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat."


Update nl.coffee (#4084)

Update nl.coffee (#4084)

--- app/locale/nl.coffee
+++ app/locale/nl.coffee
@@ -384,9 +384,9 @@
     last_name: "Achternaam"
     last_initial: "Eerste letter van je achternaam"
     username: "Gebruikersnaam"
-#    contact_us: "Contact Us"
-#    close_window: "Close Window"
-#    learn_more: "Learn More"
+    contact_us: "Contacteer Ons"
+    close_window: "Sluit Venster"
+    learn_more: "Lees Meer"

   units:
     second: "seconde"
@@ -405,11 +405,11 @@
     years: "jaren"

   play_level:
-#    directions: "Directions"
-#    edit_level: "Edit Level"
-#    explore_codecombat: "Explore CodeCombat"
-#    finished_hoc: "I'm finished with my Hour of Code"
-#    get_certificate: "Get your certificate!"
+    directions: "Instructies"
+    edit_level: "Edit Level"
+    explore_codecombat: "Verken CodeCombat"
+    finished_hoc: "Ik ben klaar met mijn Uur van de Code"
+    get_certificate: "Haal je certificaat!"
     level_complete: "Level Voltooid"
     completed_level: "Voltooid Level:"
     course: "Les:"
@@ -437,7 +437,7 @@
     reload_title: "Alle Code Herladen?"
     reload_really: "Weet je zeker dat je dit level tot het begin wilt herladen?"
     reload_confirm: "Herlaad Alles"
-#    test_level: "Test Level"
+    test_level: "Test Level"
     victory: "Gewonnen"
     victory_title_prefix: ""
     victory_title_suffix: " Compleet"
@@ -618,11 +618,11 @@
     price: "x{{gems}} / maand"

   subscribe:
-#    subscribe_modal_title: "CodeCombat Premium"
+    subscribe_modal_title: "CodeCombat Premium"
     comparison_blurb: "Verbeter je vaardigheden met een abonnement op CodeCombat!" # {change}
-#    premium_pricing_prefix: "Get Premium for just"
-#    premium_pricing_suffix: "and become a master coder."
-#    premium: "Premium" # Make sure the following feature translations don't go onto two lines
+    premium_pricing_prefix: "Neem Premium voor maar"
+    premium_pricing_suffix: "en word een meester programmeur."
+    premium: "Premium" # Make sure the following feature translations don't go onto two lines
     feature1: "meer dan __levelsCount__ basislevels over __worldsCount__ werelden" # {change}
     feature2: "__heroesCount__ sterke nieuwe helden met unieke vaardigheden!" # {change}
     feature3: "__bonusLevelsCount__ bonuslevels" # {change}
@@ -630,8 +630,8 @@
     feature6: "Hoogwaardige e-mail ondersteuning"
     feature7: "Besloten Clans"
     feature8: "Geen advertenties!"
-#    feature_game_dev: "Make games for your friends to play in our Game Dev Worlds"
-#    feature_web_dev: "Build websites and apps with HTML, CSS, and jQuery in our Web Dev Worlds"
+    feature_game_dev: "Maak spellen voor je vrienden om te spelen in onze Game Dev Werelden"
+    feature_web_dev: "Bouw websites en apps met HTML, CSS, en jQuery in onze Web Dev Werelden"
     free: "Gratis"
     month: "maand"
     must_be_logged: "Je moet eerst ingelogd zijn. Maak een account aan of log in in het menu hierboven."
@@ -802,7 +802,7 @@
     lisa_title: "Marktontwikkeling vertegenwoordiger" # {change}
     lisa_blurb: "Warmbloedig"
     sean_title: "Regio Manager"
-#    liz_title: "Territory Manager"
+    liz_title: "Buurt Manager"
     retrostyle_title: "Illustraties"
     retrostyle_blurb: "RetroStijl Games"
     jose_title: "Muziek"
@@ -866,46 +866,46 @@
     more_info_3: "Het is een goede plek om contact te leggen met andere leerkrachten, die CodeCombat gebruiken."
     licenses_needed: "Licentie benodigd"

-#  special_offer:
-#    special_offer: "Special Offer"
-#    project_based_title: "Project-Based Courses"
-#    project_based_description: "Web and Game Development courses feature shareable final projects."
-#    great_for_clubs_title: "Great for clubs and electives"
-#    great_for_clubs_description: "Teachers can purchase up to __maxQuantityStarterLicenses__ Starter Licenses per year."
-#    low_price_title: "Just __starterLicensePrice__ per student"
-#    low_price_description: "Starter Licenses are active for __starterLicenseLengthMonths__ months from purchase."
-#    three_great_courses: "Three great courses included in the Starter License:"
-#    license_limit_description: "Teachers can purchase up to __maxQuantityStarterLicenses__ Starter Licenses. You have already purchased __quantityAlreadyPurchased__. If you need more, contact __supportEmail__. Starter Licenses are valid for __starterLicenseLengthMonths__ months."
-#    student_starter_license: "Student Starter License"
-#    purchase_starter_licenses: "Purchase Starter Licenses"
-#    purchase_starter_licenses_to_grant: "Purchase Starter Licenses to grant access to __starterLicenseCourseList__"
-#    starter_licenses_can_be_used: "Starter Licenses can be used to assign additional courses immediately after purchase."
-#    pay_now: "Pay Now"
-#    we_accept_all_major_credit_cards: "We accept all major credit cards."
-#    cs2_description: "builds on the foundation from Introduction to Computer Science, diving into if-statements, functions, events and more."
-#    wd1_description: "introduces the basics of HTML and CSS while teaching skills needed for students to build their first webpage."
-#    gd1_description: "uses syntax students are already familiar with to show them how to build and share their own playable game levels."
-#    see_an_example_project: "see an example project"
-#    get_started_today: "Get started today!"
-#    want_all_the_courses: "Want all the courses? Request information on our Full Licenses."
-#    compare_license_types: "Compare License Types:"
-#    cs: "Computer Science"
-#    wd: "Web Development"
-#    wd1: "Web Development 1"
-#    gd: "Game Development"
-#    gd1: "Game Development 1"
-#    maximum_students: "Maximum # of Students"
-#    unlimited: "Unlimited"
-#    priority_support: "Priority support"
-#    yes: "Yes"
-#    price_per_student: "__price__ per student"
-#    pricing: "Pricing"
-#    free: "Free"
-#    purchase: "Purchase"
-#    courses_prefix: "Courses"
-#    courses_suffix: ""
-#    course_prefix: "Course"
-#    course_suffix: ""
+  special_offer:
+    special_offer: "Specialr Aanbieding"
+    project_based_title: "Project-Georienteerde Cursussen"
+    project_based_description: "Web en Game Ontwikkeling cursussen hebben deelbare eindprojecten."
+    great_for_clubs_title: "Leuk voor clubjes en keuzevakken"
+    great_for_clubs_description: "Leraren kunnen tot __maxQuantityStarterLicenses__ Starter Licenties kopen per jaar."
+    low_price_title: "Maar __starterLicensePrice__ per leerling"
+    low_price_description: "Starter Licenties zijn __starterLicenseLengthMonths__ maanden geldig na aankoop."
+    three_great_courses: "Drie geweldige cursussen in de Starter Licentie:"
+    license_limit_description: "Leraren kunnen tot __maxQuantityStarterLicenses__ Starter Licenties kopen. U heeft er al __quantityAlreadyPurchased__ gekocht. Mocht dit niet voldoende zijn, neem contact op met __supportEmail__. Starter Licenties zijn __starterLicenseLengthMonths__ maanden geldig."
+    student_starter_license: "Leerling Starter Licentie"
+    purchase_starter_licenses: "Koop Starter Licenties"
+    purchase_starter_licenses_to_grant: "Koop Starter Licenties voor toegang tot __starterLicenseCourseList__"
+    starter_licenses_can_be_used: "Starter Licenties kunnen meteen na aankoop gebruikt worden om extra cursussen toe te wijzen."
+    pay_now: "Betaal Nu"
+    we_accept_all_major_credit_cards: "We accepteren alle gangbare creditcards."
+    cs2_description: "bouwt voort op de basis van de Computer Wetenschap Introductie. Gaat verder in op if-statements, functies, events en meer."
+    wd1_description: "introduceert de basis van HTML en CSS en leert de vaardigheden die leerlingen nodig hebben om hun eerste webpagina te bouwen."
+    gd1_description: "gebruikt syntax die de leerlingen al eerder hebben gezien, waarmee ze nu hun eigen levels kunnen bouwen en delen met vrienden."
+    see_an_example_project: "bekijk een voorbeeld project"
+    get_started_today: "Begin vandaag!"
+    want_all_the_courses: "Wilt u alle cursussen? Vraag informatie aan over onze Volledige Licenties."
+    compare_license_types: "Vergelijk Licentie Types:"
+    cs: "Computer Wetenschap"
+    wd: "Web Ontwikkeling"
+    wd1: "Web Ontwikkeling 1"
+    gd: "Game Ontwikkeling"
+    gd1: "Game Ontwikkeling 1"
+    maximum_students: "Maximum aantal leerlingen"
+    unlimited: "Ongelimiteerd"
+    priority_support: "Voorrang bij vragen"
+    yes: "Ja"
+    price_per_student: "__price__ per leerling"
+    pricing: "Prijzen"
+    free: "Gratis"
+    purchase: "Koop"
+    courses_prefix: "Cursussen"
+    courses_suffix: ""
+    course_prefix: "Cursus"
+    course_suffix: ""

   teachers_quote:
     name: "Demo Formulier"
@@ -1408,11 +1408,11 @@
     web_dev_language_transition: "Alle klassen programmeren in HTML / Javascript voor deze cursus. Klassen die eerder Python hebben gebruikt zullen beginnen met extra JavaScript intro levels om de overgang te vergemakkelijken. Klassen die al met JavaScript werken slaan deze intro lessen over."

   teacher:
-#    assigning_course: "Assigning course"
+    assigning_course: "Cursus toewijzen"
     course_solution: "Cursus Oplossing"
     level_overview_solutions: "Level overzicht en Oplossingen"
-#    no_student_assigned: "No students have been assigned this course."
-#    paren_new: "(new)"
+    no_student_assigned: "Er zijn geen leerlingen toegewezen aan deze cursus."
+    paren_new: "(nieuw)"
     teacher_dashboard: "Docent Dashboard" # Navbar
     my_classes: "Mijn Klassen"
     courses: "Cursussen" # {change}
@@ -1460,16 +1460,16 @@
     sort_by: "Sorteer op"
     progress: "Voortgang"
     completed: "Behaald"
-#    practice: "Practice"
+    practice: "Oefen"
     started: "Gestart"
     click_to_view_progress: "klik om de eigenschappen te bekijken"
     no_progress: "Geen voortgang"
-#    not_required: "Not required"
+    not_required: "Niet vereist"
     select_course: "Selecteer cursus om te bekijken"
-#    progress_color_key: "Progress color key:"
-#    level_in_progress: "Level in Progress"
-#    level_not_started: "Level Not Started"
-#    project_or_arena: "Project or Arena"
+    progress_color_key: "Voortgang kleur code:"
+    level_in_progress: "Bezig met level"
+    level_not_started: "Level nog niet begonnen"
+    project_or_arena: "Project of Arena"
     students_not_assigned: "Studenten die niet zitten bij {{courseName}}"
     course_overview: "Cursus Overzicht"
     copy_class_code: "Kopieer Klas Code"
@@ -1483,11 +1483,11 @@
     assigned_msg_3: "Je hebt nog {{remainingSpots}} beschikbare licenties."
     assign_course: "Cursus toewijzen"
     not_assigned_modal_title: "Cursussen zijn niet toegewezen"
-#    not_assigned_modal_starter_body_1: "This course requires a Starter License. You do not have enough Starter Licenses available to assign this course to all __selected__ selected students."
-#    not_assigned_modal_starter_body_2: "Purchase Starter Licenses to grant access to this course."
-#    not_assigned_modal_full_body_1: "This course requires a Full License. You do not have enough Full Licenses available to assign this course to all __selected__ selected students."
-#    not_assigned_modal_full_body_2: "You only have __numFullLicensesAvailable__ Full Licenses available (__numStudentsWithoutFullLicenses__ students do not currently have a Full License active)."
-#    not_assigned_modal_full_body_3: "Please select fewer students, or reach out to __supportEmail__ for assistance."
+    not_assigned_modal_starter_body_1: "Voor deze cursus is een Starter Licentie nodig. U heeft niet genoeg Volledige Licenties beschikbaar om deze curus toe te wijzen aan de __selected__ geselecteerde leerlingen."
+    not_assigned_modal_starter_body_2: "Schaf Starter Licenties aan om toegang te verlenen tot deze cursus."
+    not_assigned_modal_full_body_1: "Voor deze cursus is een Volledige Licentie nodig. U heeft niet genoeg Volledige Licenties beschikbaar om deze curus toe te wijzen aan de __selected__ geselecteerde leerlingen."
+    not_assigned_modal_full_body_2: "U heeft maar __numFullLicensesAvailable__ Volledige Licenties beschikbaar (__numStudentsWithoutFullLicenses__ leeringen hebben momenteel geen actieve Volledige Licentie)."
+    not_assigned_modal_full_body_3: "Selecteer minder leerlingen, of neem contant op met __supportEmail__."
     assign_to_selected_students: "Toewijzen aan Geselecteerde Leerlingen"
     assigned: "Toegewezen"
     enroll_selected_students: "Schrijf Geselecteerde Leerlingen in"
@@ -1522,7 +1522,7 @@
     available_credits: "Beschikbare licenties"
     pending_credits: "Aangevraagde licenties"
     credits: "licenties"
-#    starter_licenses: "starter licenses"
+    starter_licenses: "starter licenties"
     start_date: "start datum:"
     end_date: "eind datum:"
     get_enrollments_blurb: " We helpen je met een op maat gemaakte oplossing voor jullie klas, school of gemeenschap."
@@ -1594,27 +1594,27 @@
     student_warn_detail: "Deze leerling heeft misschien hulp nodig met nieuwe concepten die in deze cursus aan bod zijn gekomen."
     student_great: "doet het heel goed in"
     student_great_detail: "Deze leerling kan misschien andere leerlingen helpen met het doorlopen van deze cursus."
-#    full_license: "Full License"
-#    starter_license: "Starter License"
-#    trial: "Trial"
-#    hoc_welcome: "Happy Computer Science Education Week"
-#    hoc_intro: "There are three ways for your class to participate in Hour of Code with CodeCombat"
-#    hoc_self_led: "Self-Led Gameplay"
-#    hoc_self_led_desc: "Students can play through two Hour of Code CodeCombat tutorials on their own"
-#    hoc_game_dev: "Game Development"
-#    hoc_and: "and"
-#    hoc_programming: "JavaScript/Python Programming"
-#    hoc_teacher_led: "Teacher-Led Lessons"
-#    hoc_teacher_led_desc1: "Download our"
-#    hoc_teacher_led_link: "Introduction to Computer Science lesson plans"
-#    hoc_teacher_led_desc2: "to introduce your students to programming concepts using offline activities"
-#    hoc_group: "Group Gameplay"
-#    hoc_group_desc_1: "Teachers can use the lessons in conjunction with our Introduction to Computer Science course to track student progress. See our"
-#    hoc_group_link: "Getting Started Guide"
-#    hoc_group_desc_2: "for more details"
-#    hoc_additional_desc1: "For additional CodeCombat resources and activities, see our"
-#    hoc_additional_desc2: "Questions"
-#    hoc_additional_contact: "Get in touch"
+    full_license: "Volledige Licentie"
+    starter_license: "Starter Licentie"
+    trial: "Uitproberen"
+    hoc_welcome: "Fijne Computer Wetenschap Educatie Week!"
+    hoc_intro: "Er zijn drie manieren waarop uw klas kan meedoen aan het Code Uur met CodeCombat"
+    hoc_self_led: "Zelfstandig Gamen"
+    hoc_self_led_desc: "Leerlingen kunnen zelfstandig 2 uur CodeCombat tutorials spelen"
+    hoc_game_dev: "Game Ontwikkeling"
+    hoc_and: "en"
+    hoc_programming: "JavaScript/Python Programmeren"
+    hoc_teacher_led: "Leraar Begeleide Lessen"
+    hoc_teacher_led_desc1: "Download onze"
+    hoc_teacher_led_link: "Introductie tot Computer Wetenschap lesplannen"
+    hoc_teacher_led_desc2: "om de leerlingen kennis te laten maken met programmeerconcepten met behulp van offline activiteiten"
+    hoc_group: "Groep Gamen"
+    hoc_group_desc_1: "Leraren kunnen de lessen samen gebruiken met onze Introductie tot Computer Wetenschap cursus om de voortgang van de studenten bij te houden. Bekijk onze"
+    hoc_group_link: "Beginners Gids"
+    hoc_group_desc_2: "voor meer details"
+    hoc_additional_desc1: "Voor meer Codecombat informatie en activiteiten, ga naar"
+    hoc_additional_desc2: "Vragen"
+    hoc_additional_contact: "Neem contact op"

   sharing:
     game: "Spel"


Update tr.coffee (#5337)

Update tr.coffee (#5337)

* update

* Update tr.coffee

* Update tr.coffee

* Update tr.coffee

--- app/locale/tr.coffee
+++ app/locale/tr.coffee
@@ -5,25 +5,25 @@
 #    meta_description: "Learn typed code through a programming game. Learn Python, JavaScript, and HTML as you solve puzzles and learn to make your own coding games and websites."
 #    built_for_teachers_title: "A Coding Game Built with Teachers in Mind"
 #    built_for_teachers_blurb: "Teaching kids to code can often feel overwhelming. CodeCombat helps all educators teach students how to code in either JavaScript or Python, two of the most popular programming languages. With a comprehensive curriculum that includes six computer science units and reinforces learning through project-based game development and web development units, kids will progress on a journey from basic syntax to recursion!"
-#    built_for_teachers_subtitle1: "Computer Science"
-#    built_for_teachers_subblurb1: "Starting with our free Introduction to Computer Science course, students master core coding concepts such as while/for loops, functions, and algorithms."
-#    built_for_teachers_subtitle2: "Game Development"
+    built_for_teachers_subtitle1: "Bilgisayar Bilimleri"
+    built_for_teachers_subblurb1: "Öğrenciler ücretsiz Bilgisayar Bilimleri Giriş kursumuzdan başlayarak, döngüler, fonksiyonlar ve algoritmalar gibi temel kodlama kavramlarını öğrenir."
+    built_for_teachers_subtitle2: "Oyun Geliştirme"
 #    built_for_teachers_subblurb2: "Learners construct mazes and use basic input handling to code their own games that can be shared with friends and family."
-#    built_for_teachers_subtitle3: "Web Development"
+    built_for_teachers_subtitle3: "Web Geliştirme"
 #    built_for_teachers_subblurb3: "Using HTML, CSS, and jQuery, learners flex their creative muscles to program their own webpages with a custom URL to share with their classmates."
 #    century_skills_title: "21st Century Skills"
-#    century_skills_blurb1: "Students Don't Just Level Up Their Hero, They Level Up Themselves"
+    century_skills_blurb1: "Öğrenciler Sadece Kahramanlarının Seviyelerini Arttırmazlar, Kendi Seviyelerini Arttırırlar"
 #    century_skills_quote1: "You mess up…so then you think about all of the possible ways to fix it, and then try again. I wouldn't be able to get here without trying hard."
 #    century_skills_subtitle1: "Critical Thinking"
 #    century_skills_subblurb1: "With coding puzzles that are naturally scaffolded into increasingly challenging levels, CodeCombat's programming game ensures kids are always practicing critical thinking."
 #    century_skills_quote2: "Everyone else was making mazes, so I thought, ‘capture the flag’ and that’s what I did."
-#    century_skills_subtitle2: "Creativity"
+    century_skills_subtitle2: "Yaratıcılık"
 #    century_skills_subblurb2: "CodeCombat encourages students to showcase their creativity by building and sharing their own games and webpages."
 #    century_skills_quote3: "If I got stuck on a level. I would work with people around me until we were all able to figure it out."
 #    century_skills_subtitle3: "Collaboration"
 #    century_skills_subblurb3: "Throughout the game, there are opportunities for students to collaborate when they get stuck and to work together using our pair programming guide."
 #    century_skills_quote4: "I’ve always had aspirations of designing video games and learning how to code ... this is giving me a great starting point."
-#    century_skills_subtitle4: "Communication"
+    century_skills_subtitle4: "İletişim"
 #    century_skills_subblurb4: "Coding requires kids to practice new forms of communication, including communicating with the computer itself and conveying their ideas using the most efficient code."
 #    classroom_in_box_title: "We Strive To:"
 #    classroom_in_box_blurb1: "Engage every student so that they believe coding is for them."
@@ -65,14 +65,14 @@
 #    for_teachers_subtitle4: "Automatic Differentiation"
 #    for_teachers_subblurb4: "Engage all learners in a diverse classroom with practice levels that adapt to each student's learning needs."
 #    game_based_blurb: "CodeCombat is a game-based computer science program where students type real code and see their characters react in real time."
-#    get_started: "Get started"
+    get_started: "Başlayalım"
 #    global_title: "Join Our Global Community of Learners and Educators"
-#    global_subtitle1: "Learners"
+#    global_subtitle1: "Öğrenciler"
 #    global_subtitle2: "Lines of Code"
-#    global_subtitle3: "Teachers"
-#    global_subtitle4: "Countries"
-#    go_to_my_classes: "Go to my classes"
-#    go_to_my_courses: "Go to my courses"
+    global_subtitle3: "Öğretmenler"
+    global_subtitle4: "Ülkeler"
+    go_to_my_classes: "Sınıfıma git"
+    go_to_my_courses: "Kursuma git"
 #    quotes_quote1: "Name any program online, I’ve tried it. None of them match up to CodeCombat. Any teacher who wants their students to learn how to code... start here!"
 #    quotes_quote2: " I was surprised about how easy and intuitive CodeCombat makes learning computer science. The scores on the AP exam were much higher than I expected and I believe CodeCombat is the reason why this was the case."
 #    quotes_quote3: "CodeCombat has been the most beneficial for teaching my students real-life coding capabilities. My husband is a software engineer and he has tested out all of my programs. He put this as his top choice."
@@ -135,7 +135,7 @@
 #    request_demo: "Request a Demo"
 #    request_quote: "Request a Quote"
 #    setup_a_class: "Set Up a Class"
-#    have_an_account: "Have an account?"
+    have_an_account: "Hesabın var mı?"
 #    logged_in_as: "You are currently logged in as"
 #    computer_science: "Our self-paced courses cover basic syntax to advanced concepts"
 #    ffa: "Free for all students"
@@ -144,19 +144,19 @@
 #    boast: "Boasts riddles that are complex enough to fascinate gamers and coders alike."
 #    winning: "A winning combination of RPG gameplay and programming homework that pulls off making kid-friendly education legitimately enjoyable."
 #    run_class: "Everything you need to run a computer science class in your school today, no CS background required."
-#    goto_classes: "Go to My Classes"
-#    view_profile: "View My Profile"
-#    view_progress: "View Progress"
+    goto_classes: "Sınıflarıma git"
+    view_profile: "Profilimi Görüntüle"
+    view_progress: "İlerlemeyi Görüntüle"
 #    go_to_courses: "Go to My Courses"
 #    want_coco: "Want CodeCombat at your school?"
-#    educator: "Educator"
-#    student: "Student"
+    educator: "Öğretmen"
+    student: "Öğrenci"

   nav:
 #    educators: "Educators"
-#    follow_us: "Follow Us"
+    follow_us: "Bizi Takip Et"
 #    general: "General"
-#    map: "Map"
+    map: "Harita"
     play: "Oyna" # The top nav bar entry where players choose which levels to play
     community: "Topluluk"
     courses: "Kurslar"
@@ -175,7 +175,7 @@
     twitter_follow: "Takip et"
     my_classrooms: "Sınıflarım"
     my_courses: "Kurslarım"
-#    my_teachers: "My Teachers"
+    my_teachers: "Öğretmenlerim"
     careers: "Kariyer"
     facebook: "Facebook"
     twitter: "Twitter"
@@ -223,9 +223,9 @@
 #    anon_signup_title_2: "Classroom Version!"
 #    anon_signup_enter_code: "Enter Class Code:"
 #    anon_signup_ask_teacher: "Don't have one? Ask your teacher!"
-#    anon_signup_create_class: "Want to create a class?"
+    anon_signup_create_class: "Sınıf oluşturmak ister misin?"
 #    anon_signup_setup_class: "Set up a class, add your students, and monitor progress!"
-#    anon_signup_create_teacher: "Create free teacher account"
+    anon_signup_create_teacher: "Ücretsiz öğretmen hesabı oluştur"
     play_as: "Olarak Oyna" # Ladder page
 #    get_course_for_class: "Assign Game Development and more to your classes!"
 #    request_licenses: "Contact our school specialists for details."
@@ -246,7 +246,7 @@
     poll: "Anket" # Tooltip on poll button from /play
     next: "İleri" # Go from choose hero to choose inventory before playing a level
     change_hero: "Kahramanı Değiştir" # Go back from choose inventory to choose hero
-#    change_hero_or_language: "Change Hero or Language"
+    change_hero_or_language: "Kahramanı veya Dili değiştir"
     buy_gems: "Değerli Taş Satın Al"
     subscribers_only: "Sadece Aboneler!"
     subscribe_unlock: "Kilidini açmak için Abone ol!"
@@ -262,58 +262,58 @@
     campaign_multiplayer_description: "Diğer oyuncularla kafa kafaya verip kodlamak için..."
 #    brain_pop_done: "You’ve defeated the Ogres with code! You win!"
 #    brain_pop_challenge: "Challenge yourself to play again using a different programming language!"
-#    replay: "Replay"
+    replay: "Tekrar"
 #    back_to_classroom: "Back to Classroom"
 #    teacher_button: "For Teachers"
 #    get_more_codecombat: "Get More CodeCombat"

-#  code:
-#    if: "if" # Keywords--these translations show up on hover, so please translate them all, even if it's kind of long. (In the code editor, they will still be in English.)
-#    else: "else"
-#    elif: "else if"
-#    while: "while"
-#    loop: "loop"
+  code:
+    if: "eğer şöyleyse..." # Keywords--these translations show up on hover, so please translate them all, even if it's kind of long. (In the code editor, they will still be in English.)
+    else: "değilse"
+    elif: "eğer şöyleyse....."
+    while: "ise"
+    loop: "döngü"
 #    for: "for"
-#    break: "break"
-#    continue: "continue"
+    break: "kır"
+    continue: "bu seferlik geç"
 #    pass: "pass"
-#    return: "return"
-#    then: "then"
+    return: "döndür"
+    then: "sonra"
 #    do: "do"
-#    end: "end"
-#    function: "function"
+    end: "son"
+    function: "fonksiyon"
 #    def: "define"
-#    var: "variable"
+    var: "değişken"
 #    self: "self"
 #    hero: "hero"
 #    this: "this"
-#    or: "or"
-#    "||": "or"
-#    and: "and"
-#    "&&": "and"
-#    not: "not"
-#    "!": "not"
+    or: "veya"
+    "||": "veya"
+    and: "ve"
+    "&&": "ve"
+    not: "değilse"
+    "!": "değilse"
 #    "=": "assign"
-#    "==": "equals"
+    "==": "eşittir"
 #    "===": "strictly equals"
-#    "!=": "does not equal"
+    "!=": "eşit değil"
 #    "!==": "does not strictly equal"
-#    ">": "is greater than"
-#    ">=": "is greater than or equal"
-#    "<": "is less than"
-#    "<=": "is less than or equal"
-#    "*": "multiplied by"
-#    "/": "divided by"
-#    "+": "plus"
-#    "-": "minus"
+    ">": "büyüktür"
+    ">=": "büyüktür veya eşittir"
+#    "<": "küçüktür"
+    "<=": "küçüktür veya eşittir"
+    "*": "çarp"
+    "/": "böl"
+    "+": "artı"
+    "-": "eksi"
 #    "+=": "add and assign"
 #    "-=": "subtract and assign"
-#    True: "True"
-#    true: "true"
-#    False: "False"
-#    false: "false"
+    True: "Doğru"
+    true: "doğru"
+    False: "Yanlış"
+    false: "yanlış"
 #    undefined: "undefined"
-#    null: "null"
+    null: "boş"
 #    nil: "nil"
 #    None: "None"

@@ -338,7 +338,7 @@
     signup_switch: "Hesap oluşturmak istiyor musun?"

   signup:
-#    complete_subscription: "Complete Subscription"
+    complete_subscription: "Aboneliği Tamamla"
     create_student_header: "Öğrenci Hesabı Oluştur"
     create_teacher_header: "Öğretmen Hesabı Oluştur"
     create_individual_header: "Bireysel Hesap Oluştur"
@@ -348,7 +348,7 @@
     creating: "Hesap oluşturuluyor..."
     sign_up: "Kaydol"
     log_in: "buradan giriş yapabilirsiniz."
-#    login: "Login"
+    login: "Giriş"
     required: "Buraya gidebilmeniz için oturum açmanız gerekli."
     login_switch: "Zaten bir hesabın var mı?"
     optional: "isteğe bağlı"
@@ -364,7 +364,7 @@
 #    account_exists: "This email is already in use:"
     sign_in: "Oturum aç"
     email_good: "E-posta iyi görünüyor!"
-#    name_taken: "Username already taken! Try {{suggestedName}}?"
+    name_taken: "Kullanıcı adı alınmış! Şunu dene {{suggestedName}}?"
     name_available: "Kullanıcı adı müsait!"
 #    name_is_email: "Username may not be an email"
     choose_type: "Hesabınızın türünü seçin:"
@@ -481,7 +481,7 @@
     rejected: "Reddedildi"
     withdrawn: "İptal Edildi"
     accept: "Kabul Et"
-#    accept_and_save: "Accept&Save"
+    accept_and_save: "Kabel Et&Kaydet"
     reject: "Reddet"
     withdraw: "Ayrıl"
     submitter: "Gönderen"
@@ -521,21 +521,21 @@
     warrior: "Savaşçı"
     ranger: "Korucu"
     wizard: "Sihirbaz"
-#    first_name: "First Name"
-#    last_name: "Last Name"
+    first_name: "Ad"
+    last_name: "Soyad"
 #    last_initial: "Last Initial"
     username: "Kullanıcı adı"
     contact_us: "Bizimle iletişime geç"
     close_window: "Pencereyi Kapat"
     learn_more: "Daha fazla bilgi edin"
-#    more: "More"
+    more: "Daha fazla"
 #    fewer: "Fewer"
 #    with: "with"

   units:
     second: "saniye"
     seconds: "saniye"
-#    sec: "sec"
+    sec: "sn"
     minute: "dakika"
     minutes: "dakika"
     hour: "saat"
@@ -550,13 +550,13 @@
     years: "yıl"

   play_level:
-#    back_to_map: "Back to Map"
+    back_to_map: "Haritaya Geri Dön"
 #    directions: "Directions"
-#    edit_level: "Edit Level"
+    edit_level: "Bölümü Düzenle"
 #    keep_learning: "Keep Learning"
-#    explore_codecombat: "Explore CodeCombat"
+    explore_codecombat: "CodeCombat'ı Keşfet"
 #    finished_hoc: "I'm finished with my Hour of Code"
-#    get_certificate: "Get your certificate!"
+    get_certificate: "Sertifikanı Al!"
 #    level_complete: "Level Complete"
     completed_level: "Seviyeyi Tamamladın:"
     course: "Kurs:"
@@ -576,7 +576,7 @@
 #    combo_not_all_concepts_used: "You used __complete__ out of the __total__ concepts possible to solve the challenge. Try to get all __total__ concepts next time!"
 #    start_challenge: "Start Challenge"
     next_game: "Sonraki Oyun"
-#    languages: "Languages"
+    languages: "Diller"
 #    programming_language: "Programming language"
     show_menu: "Oyun Menüsünü Göster"
     home: "Anasayfa" # Not used any more, will be removed soon.
@@ -632,8 +632,8 @@
     tome_reload_method: "Bu yöntem için özgün kodu yeniden yükle" # {change}
     tome_available_spells: "Kullanılabilir Büyüler"
     tome_your_skills: "Yetenekleriniz"
-#    hints: "Hints"
-#    videos: "Videos"
+    hints: "İpuçları"
+    videos: "Videolar"
 #    hints_title: "Hint {{number}}"
     code_saved: "Kod Kaydedildi"
     skip_tutorial: "Atla (ESC)"
@@ -737,19 +737,19 @@
 #    vega_character: "Vega Character"
 #    click_to_continue: "Click to Continue"

-#  apis:
+  apis:
 #    methods: "Methods"
 #    events: "Events"
 #    handlers: "Handlers"
-#    properties: "Properties"
+    properties: "Özellikler"
 #    snippets: "Snippets"
 #    spawnable: "Spawnable"
 #    html: "HTML"
-#    math: "Math"
-#    array: "Array"
-#    object: "Object"
+    math: "Matematik"
+    array: "Dizi"
+    object: "Obje"
 #    string: "String"
-#    function: "Function"
+    function: "Fonksiyon"
 #    vector: "Vector"
 #    date: "Date"
 #    jquery: "jQuery"
@@ -1013,30 +1013,30 @@
 #    hair_label: "Hair Color"
 #    skin_label: "Skin Color"

-#  skill_docs:
-#    function: "function" # skill types
-#    method: "method"
+skill_docs:
+    function: "fonksiyon" # skill types
+    method: "metot"
 #    snippet: "snippet"
-#    number: "number"
-#    array: "array"
-#    object: "object"
+    number: "numara"
+#    array: "dizi"
+    object: "obje"
 #    string: "string"
 #    writable: "writable" # Hover over "attack" in Your Skills while playing a level to see most of this
-#    read_only: "read-only"
-#    action: "Action"
-#    spell: "Spell"
+    read_only: "sadece-okunabilir"
+    action: "Hareket"
+    spell: "Büyü"
 #    action_name: "name"
 #    action_cooldown: "Takes"
-#    action_specific_cooldown: "Cooldown"
-#    action_damage: "Damage"
-#    action_range: "Range"
+    action_specific_cooldown: "Bekleme Süresi"
+    action_damage: "Hasar"
+    action_range: "Mesafe"
 #    action_radius: "Radius"
-#    action_duration: "Duration"
-#    example: "Example"
+    action_duration: "Süre"
+    example: "Örnek"
 #    ex: "ex" # Abbreviation of "example"
 #    current_value: "Current Value"
 #    default_value: "Default value"
-#    parameters: "Parameters"
+    parameters: "Parametreler"
 #    required_parameters: "Required Parameters"
 #    optional_parameters: "Optional Parameters"
 #    returns: "Returns"
@@ -1065,7 +1065,7 @@
   about:
 #    title: "About CodeCombat - Engaging Students, Empowering Teachers, Inspiring Creation"
 #    meta_description: "Our mission is to level computer science through game-based learning and make coding accessible to every learner. We believe programming is magic and want learners to be empowered to to create things from pure imagination."
-#    learn_more: "Learn More"
+    learn_more: "Daha Fazla Öğren"
 #    main_title: "If you want to learn to program, you need to write (a lot of) code."
 #    main_description: "At CodeCombat, our job is to make sure you're doing that with a smile on your face."
     mission_link: "Görev"
@@ -1123,10 +1123,10 @@
 #    story_title: "Our story so far"
 #    story_subtitle: "Since 2013, CodeCombat has grown from a mere set of sketches to a living, thriving game."
 #    story_statistic_1a: "5,000,000+"
-#    story_statistic_1b: "total players"
+    story_statistic_1b: "toplam oyuncu"
 #    story_statistic_1c: "have started their programming journey through CodeCombat"
 #    story_statistic_2a: "We’ve been translated into over 50 languages — our players hail from"
-#    story_statistic_2b: "190+ countries"
+    story_statistic_2b: "190+ ülke"
 #    story_statistic_3a: "Together, they have written"
 #    story_statistic_3b: "1 billion lines of code and counting"
 #    story_statistic_3c: "across many different programming languages"
@@ -1440,7 +1440,7 @@
 #    track_concepts8: "to join"
 #    private_require_sub: "Private clans require a subscription to create or join."

-#  courses:
+  courses:
 #    create_new_class: "Create New Class"
 #    hoc_blurb1: "Try the"
 #    hoc_blurb2: "Code, Play, Share"
@@ -1624,9 +1624,9 @@
 #    hide_change_log: "Hide changes to this course's levels"
 #    concept_videos: "Concept Videos"
 #    concept: "Concept:"
-#    basic_syntax: "Basic Syntax"
-#    while_loops: "While Loops"
-#    variables: "Variables"
+#    basic_syntax: "Temel Söz Dizimi(Syntax)"
+#    while_loops: "While Döngüleri"
+    variables: "Değişkenler"
 #    basic_syntax_desc: "Syntax is how we write code. Just as spelling and grammar are important in writing narratives and essays, syntax is important when writing code. Humans are good at figuring out what something means, even if it isn't exactly correct, but computers aren't that smart, and they need you to write very precisely."
 #    while_loops_desc: "A loop is a way of repeating actions in a program. You can use them so you don't have to keep writing repetitive code, and when you don't know exactly how many times an action will need to occur to accomplish a task."
 #    variables_desc: "Working with variables is like organizing things in shoeboxes. You give the shoebox a name, like \"School Supplies\", and then you put things inside. The exact contents of the box might change over time, but whatever's inside will always be called \"School Supplies\". In programming, variables are symbols used to store data that will change over the course of the program. Variables can hold a variety of data types, including numbers and strings."
@@ -1646,7 +1646,7 @@
 #    view_project: "View Project"
 #    edit_project: "Edit Project"

-#  teacher:
+  teacher:
 #    assigning_course: "Assigning course"
 #    back_to_top: "Back to Top"
 #    click_student_code: "Click on any level that the student has started or completed below to view the code they wrote."
@@ -1681,8 +1681,8 @@
 #    courses: "Course Guides"
 #    enrollments: "Student Licenses"
 #    resources: "Resources"
-#    help: "Help"
-#    language: "Language"
+    help: "Yardım"
+    language: "Dil"
 #    edit_class_settings: "edit class settings"
 #    access_restricted: "Account Update Required"
 #    teacher_account_required: "A teacher account is required to access this content."
@@ -1792,10 +1792,10 @@
 #    status_expired: "Expired on {{date}}"
 #    status_not_enrolled: "Not Enrolled"
 #    status_enrolled: "Expires on {{date}}"
-#    select_all: "Select All"
-#    project: "Project"
+    select_all: "Hepsini Seç"
+    project: "Proje"
 #    project_gallery: "Project Gallery"
-#    view_project: "View Project"
+    view_project: "Projeyi Görüntüle"
 #    unpublished: "(unpublished)"
 #    view_arena_ladder: "View Arena Ladder"
 #    resource_hub: "Resource Hub"
@@ -2019,7 +2019,7 @@
 #  game_dev:
 #    creator: "Creator"

-#  web_dev:
+  web_dev:
 #    image_gallery_title: "Image Gallery"
 #    select_an_image: "Select an image you want to use"
 #    scroll_down_for_more_images: "(Scroll down for more images)"
@@ -2030,9 +2030,9 @@
 #    copy_url: "Copy URL"
 #    copy_img: "Copy <img>"
 #    how_to_copy_paste: "How to Copy/Paste"
-#    copy: "Copy"
-#    paste: "Paste"
-#    back_to_editing: "Back to Editing"
+    copy: "Kopyala"
+    paste: "Yapıştır"
+    back_to_editing: "Düzenlemeye Geri Dön"

   classes:
     archmage_title: "Büyük Büyücü"
@@ -2477,7 +2477,7 @@
     bad_input: "Hatalı girdi."
     server_error: "Sunucu hatası."
     unknown: "Bilinmeyen hata." # {change}
-#    error: "ERROR"
+    error: "HATA"
 #    general_desc: "Something went wrong, and it’s probably our fault. Try waiting a bit and then refreshing the page, or visit one of the following links to get back to programming!"

   resources:
@@ -2504,7 +2504,7 @@
 #    algorithm_sum: "Algorithm Sum"
     arguments: "Argümanlar"
     arithmetic: "Aritmetik"
-#    array_2d: "2D Array"
+    array_2d: "2B Array"
 #    array_index: "Array Indexing"
 #    array_iterating: "Iterating Over Arrays"
 #    array_literals: "Array Literals"
@@ -2537,8 +2537,8 @@
 #    event_data: "Event Data"
 #    event_handlers: "Event Handlers"
 #    event_spawn: "Spawn Event"
-#    for_loops: "For Loops"
-#    for_loops_nested: "Nested For Loops"
+#    for_loops: "For Döngüleri"
+#    for_loops_nested: "İç içe For Döngüleri"
 #    for_loops_range: "For Loops Range"
 #    functions: "Functions"
 #    functions_parameters: "Parameters"
@@ -2566,14 +2566,14 @@
 #    jquery_animations: "jQuery Animations"
 #    jquery_filtering: "jQuery Element Filtering"
 #    jquery_selectors: "jQuery Selectors"
-#    length: "Array Length"
+    length: "Dizi Uzunluğu"
 #    math_coordinates: "Coordinate Math"
-#    math_geometry: "Geometry"
+    math_geometry: "Geometri"
 #    math_operations: "Math Library Operations"
 #    math_proportions: "Proportion Math"
-#    math_trigonometry: "Trigonometry"
+    math_trigonometry: "Trigonometri"
 #    object_literals: "Object Literals"
-#    parameters: "Parameters"
+    parameters: "Parametlere"
 #    programs: "Programs"
 #    properties: "Properties"
 #    property_access: "Accessing Properties"
@@ -2587,12 +2587,12 @@
 #    strings: "Strings"
 #    strings_concatenation: "String Concatenation"
 #    strings_substrings: "Substring"
-#    trees: "Data Structures - Trees"
-#    variables: "Variables"
-#    vectors: "Vectors"
+    trees: "Veri Tipleri - Ağaçlar"
+    variables: "Değişkenler"
+    vectors: "Vektörler"
 #    while_condition_loops: "While Loops with Conditionals"
-#    while_loops_simple: "While Loops"
-#    while_loops_nested: "Nested While Loops"
+    while_loops_simple: "While Döngüleri"
+    while_loops_nested: "İç içe While Döngüleri"
 #    xy_coordinates: "Coordinate Pairs"
 #    advanced_strings: "Advanced Strings" # Rest of concepts are deprecated
     algorithms: "Algoritmalar"
@@ -2607,7 +2607,7 @@
     advanced_css: "Gelişmiş CSS"
 #    advanced_web_scripting: "Advanced Web Scripting"
 #    input_handling: "Input Handling"
-#    while_loops: "While Loops"
+    while_loops: "While Döngüleri"
 #    place_game_objects: "Place game objects"
 #    construct_mazes: "Construct mazes"
 #    create_playable_game: "Create a playable, sharable game project"
@@ -2706,7 +2706,7 @@
 #    blurb_3: "to the top human and ogre players."
 #    blurb_4: "Two teams means double the prizes!"
 #    blurb_5: "(There will be two first place winners, two second-place winners, etc.)"
-#    rank: "Rank"
+    rank: "Sıralama"
 #    prizes: "Prizes"
 #    total_value: "Total Value"
 #    in_cash: "in cash"


Vi translation (#3609)

Vi translation (#3609)

* Translate into Vietnamese

* Translate and edit some Vietnamese strings

* update Vietnamese translate

* try to fix some error

* fix bugs with tab character

* update vi.coffee: play_level

* Update vi.coffee

* update vi.coffee

* update text on Home page

* Vietnamese: update legal

* vi.coffee: edit community page

* vi.coffee: update user's page

* vi.coffee: about page

* update vi.coffee

* update vi.coffee

* vi.coffee: invoices

* vi.coffee: account_prepaid

* update vi.coffee

* vi.coffee: error strings

* Update vi.coffee

* update vi.coffee

* vi.coffee: update contact form

* vi.coffee: minor update

* vi.coffee: update about page, modify some strings

--- app/locale/vi.coffee
+++ app/locale/vi.coffee
@@ -107,7 +107,7 @@
     blog: "Blog"
     forum: "Diễn đàn"
     account: "Tài khoản"
-#    my_account: "My Account"
+    my_account: "Quản lý tài khoản"
     profile: "Cá nhân"
     stats: "Chỉ số"
     code: "Code"
@@ -117,8 +117,8 @@
     about: "Chúng tôi"
     contact: "Liên hệ"
     twitter_follow: "Theo dõi"
-    students: "Dành cho học viên"
-    teachers: "Dành cho giáo viên"
+    students: "Khu vực học viên"
+    teachers: "Khu vực giáo viên"
     careers: "Cơ hội việc làm"
     facebook: "Facebook"
     twitter: "Twitter"
@@ -127,7 +127,7 @@
     learn_to_code: "Học Code!"
 #    toggle_nav: "Toggle navigation"
     jobs: "Việc làm"
-    schools: "Dành cho Trường Học"
+    schools: "Trường Học"
     educator_wiki: "Wiki cho Giáo Viên"
     get_involved: "Tham Gia"
     open_source: "Mã nguồn mở (GitHub)"
@@ -155,7 +155,7 @@
     play_as: "Chơi là" # Ladder page
     compete: "Hoàn thành!" # Course details page
     spectate: "Quan sát" # Ladder page
-    players: "Những người chơi" # Hover over a level on /play
+    players: "người chơi" # Hover over a level on /play
     hours_played: "Thời gian chơi" # Hover over a level on /play
     items: "Trang bị" # Tooltip on item shop button from /play
     unlock: "Mua" # For purchasing items and heroes
@@ -705,8 +705,8 @@
     story_link: "Chúng tôi"
     press_link: "Liên hệ"
     mission_title: "Sứ mệnh của chúng tôi: đưa lập trình đến với mọi người trên Trái Đát này."
-    mission_description_1: "Lập trình thật kì diệu. Bạn có thể sáng tạo ra một thứ gì đó từ trí tưởng tượng. Chúng tôi bắt đầu CodeCombat để cho học viên những trải nghiệm nhiệm màu khi viết code."
-    mission_description_2: "Thực tế thì, điều này cũng giúp cho bạn học nhanh hơn. Nhanh hơn RẤT NHIỀU. Bạn được thực hành thay vì chỉ đọc lý thuyết. Chúng tôi muốn đưa môi trường thực hành này đến với trường học và đến tay mọi học viên, bởi vì mọi người đều cần có cơ hội biết đến sự nhiệm màu của lập trình."
+    mission_description_1: "Lập trình thật kì diệu. Bạn có thể tạo ra một thứ gì đó chỉ từ trí tưởng tượng. Chúng tôi bắt đầu CodeCombat để đem tới cho học viên những trải nghiệm nhiệm màu khi viết code thực tế."
+    mission_description_2: "Trên thực tế, việc này giúp cho bạn học nhanh hơn. Nhanh hơn RẤT NHIỀU. Bạn được thực hành thay vì chỉ đọc lý thuyết. Chúng tôi muốn đưa môi trường thực hành này đến với trường học và đến tay mọi học sinh, bởi vì mọi người đều cần có cơ hội biết đến sự nhiệm màu của lập trình."
     team_title: "Đội ngũ của CodeCombat"
 #    team_values: "We value open and respectful dialog, where the best idea wins. Our decisions are grounded in customer research and our process is focused on delivering tangible results for them. Everyone is hands-on, from our CEO to our Github contributors, because we value growth and learning in our team."
     nick_title: "Đồng Sáng Lập, CEO" # {change}
@@ -720,11 +720,11 @@
     maka_blurb: "Người kể truyện"
     rob_title: "Kĩ Sư Phần Mềm"
     rob_blurb: "Code các thứ"
-    josh_c_title: "Game Designer"
-    josh_c_blurb: "Thiết kế game"
+    josh_c_title: "Thiết Kế Game"
+    josh_c_blurb: "Thiết kế trò chơi"
     robin_title: "Thiết Kế UX & Nghiên Cứu"
 #    robin_blurb: "Scaffolding"
-    josh_title: "Game Designer"
+    josh_title: "Thiết Kế Game"
     josh_blurb: "Floor Is Lava"
     phoenix_title: "Kĩ Sư Phần Mềm"
     nolan_title: "Giám Đốc Khu Vực"
@@ -734,13 +734,13 @@
     jose_title: "Âm Nhạc"
     jose_blurb: "Taking Off"
     community_title: "...và cộng đồng mã nguồn mở của chúng tôi"
-#    community_subtitle: "Over 450 contributors have helped build CodeCombat, with more joining every week!"
-#    community_description_1: "CodeCombat is a community project, with hundreds of players volunteering to create levels, contribute to our code to add features, fix bugs, playtest, and even translate the game into 50 languages so far. Employees, contributors and the site gain by sharing ideas and pooling effort, as does the open source community in general. The site is built on numerous open source projects, and we are open sourced to give back to the community and provide code-curious players a familiar project to explore and experiment with. Anyone can join the CodeCombat community! Check out our"
-#    community_description_link: "contribute page"
-#    community_description_2: "for more info."
-#    number_contributors: "Over 450 contributors have lent their support and time to this project."
+    community_subtitle: "Trên 450 người đã tham gia đóng góp cho CodeCombat, và con số này tiếp tục tăng lên hàng tuần!"
+    community_description_1: "CodeCombat là một dự án cộng đồng, với hàng trăm tình nguyện viên tham gia tạo các màn chơi, viết code để thêm tính năng mới, sửa lỗi, chơi thử, và thậm chí phiên dịch trò chơi sang 50 thứ tiếng khác nhau. Employees, contributors and the site gain by sharing ideas and pooling effort, as does the open source community in general. The site is built on numerous open source projects, and we are open sourced to give back to the community and provide code-curious players a familiar project to explore and experiment with. Bất cứ ai cũng có thể tham gia cộng đồng CodeCombat! Hãy ghé qua"
+    community_description_link: "trang dành cho người đóng góp"
+    community_description_2: "để biết thêm chi tiết."
+    number_contributors: "Hơn 450 người đã bỏ công sức và thời gian để đóng góp cho dự án này."
     story_title: "Hãy nghe câu chuyện của chúng tôi"
-    story_subtitle: "Từ năm 2013 cho đến nay, CodeCombat khởi nguồn chỉ là những phác thảo sơ khai đã được hiện thực hóa để trở thành một tựa game đầy lôi cuốn."
+    story_subtitle: "Kể từ năm 2013 đến nay, CodeCombat khởi nguồn chỉ là những phác thảo sơ khai đã được hiện thực hóa để trở thành một tựa game đầy lôi cuốn."
     story_statistic_1a: "5,000,000+"
     story_statistic_1b: "người chơi"
     story_statistic_1c: "đã bắt đầu đặt chân vào thế giới lập trình cùng với CodeCombat"
@@ -748,13 +748,13 @@
     story_statistic_2b: "200+ quốc gia"
     story_statistic_3a: "Cùng với nhau, họ đã viết"
     story_statistic_3b: "hơn 1 tỷ dòng code"
-    story_statistic_3c: "với rất nhiều ngôn ngữ lập trình khác nhau"
-#    story_long_way_1: "Though we've come a long way..."
-#    story_sketch_caption: "Nick's very first sketch depicting a programming game in action."
-#    story_long_way_2: "we still have much to do before we complete our quest, so..."
-#    jobs_title: "Come work with us and help write CodeCombat history!"
-#    jobs_subtitle: "Don't see a good fit but interested in keeping in touch? See our \"Create Your Own\" listing."
-#    jobs_benefits: "Employee Benefits"
+    story_statistic_3c: "bằng rất nhiều ngôn ngữ lập trình khác nhau"
+    story_long_way_1: "Mặc dù chúng tôi đã trải qua rất nhiều..."
+    story_sketch_caption: "Bản phác thảo đầu tiên của Nick mô tả một tựa game lập trình."
+    story_long_way_2: "chúng tôi vẫn còn rất nhiều điều phải làm để chinh phục sứ mệnh, vì thế..."
+    jobs_title: "Hãy tham gia cùng chúng tôi và viết nên lịch sử CodeCombat!"
+    jobs_subtitle: "Bạn muốn ứng tuyển nhưng không tìm thấy vị trí phù hợp? Hãy tham khảo mục \"Tự Ứng Tuyển\"."
+    jobs_benefits: "Quyền Lợi Nhân Viên"
 #    jobs_benefit_1: "Competitive salary and options"
 #    jobs_benefit_2: "15 day minimum vacation policy, excluding company holidays"
 #    jobs_benefit_3: "Flex time and flexible work-from-home"
@@ -766,23 +766,23 @@
 #    jobs_benefit_10: "Maternity leave: 10 weeks paid, next 6 @ 55% salary"
 #    jobs_benefit_11: "Paternity leave: 10 weeks paid"
     learn_more: "Tìm hiểu thêm"
-#    jobs_custom_title: "Create Your Own"
-#    jobs_custom_description: "Are you passionate about CodeCombat but don't see a job listed that matches your qualifications? Write us and show how you think you can contribute to our team. We'd love to hear from you!"
-#    jobs_custom_contact_1: "Send us a note at"
-#    jobs_custom_contact_2: "introducing yourself and we might get in touch in the future!"
-#    contact_title: "Press & Contact"
-#    contact_subtitle: "Need more information? Get in touch with us at"
-#    screenshots_title: "Game Screenshots"
-#    screenshots_hint: "(click to view full size)"
-#    downloads_title: "Download Assets & Information"
-    about_codecombat: "Về CodeCombat"
-    logo: "Logo"
+    jobs_custom_title: "Tự Ứng Tuyển"
+    jobs_custom_description: "Bạn hào hứng với CodeCombat nhưng không tìm thấy vị trí phù hợp? Hãy viết thư cho chúng tối và trình bày khả năng đóng góp của bạn cho đội ngũ của chúng tôi. Chúng tôi rất sẵn lòng nhận thông tin từ bạn!"
+    jobs_custom_contact_1: "Nhắn lại cho chúng tôi tại"
+    jobs_custom_contact_2: "và giới thiệu về bản thân bạn để chúng tôi có thể liên hệ lại trong tương lai!"
+    contact_title: "Báo Chí & Liên Hệ"
+    contact_subtitle: "Bạn cần thêm thông tin? Hãy liên lạc với chúng tôi tại"
+    screenshots_title: "Ảnh Chụp Màn Hình Game"
+    screenshots_hint: "(click để xem cỡ lớn)"
+    downloads_title: "Download Tài Liệu & Thông Tin"
+    about_codecombat: "Giới thiệu CodeCombat"
+    logo: "Ảnh logo"
     screenshots: "Ảnh chụp màn hình"
-#    character_art: "Character Art"
-#    download_all: "Download All"
+    character_art: "Ảnh nhân vật"
+    download_all: "Tải Xuống Tất Cả"
     previous: "Trước"
     next: "Tiếp"
-#    location_title: "We're located in downtown SF:"
+    location_title: "Chúng tôi đóng quân tại trung tâm thành phố SF:"

   teachers:
     who_for_title: "CodeCombat dành cho ai?"
@@ -855,7 +855,7 @@

   contact:
     contact_us: "Liên hệ CodeCombat"
-    welcome: "Rất vui vì được gặp bạn! Hãy điềm vào form dưới đây để gửi mail cho chúng tôi. "
+    welcome: "Chào bạn! Hãy điềm vào form dưới đây để gửi mail cho chúng tôi."
     forum_prefix: "Để tìm hiểu thêm thông tin, hãy thử ghé qua "
     forum_page: "diễn đàn của chúng tôi"
     forum_suffix: "."


Update GAConstructor.coffee

Update GAConstructor.coffee

--- dist/GAConstructor.coffee
+++ dist/GAConstructor.coffee
@@ -1,43 +1,47 @@
 Holder = ($)->
   class GAConstructor
-    @version = "0.0.8"
-    constructor:(KEY, Backbone, @isUniversal = false)->
-      window._gaq = window._gaq || []
-      _gaq.push ['_setAccount', KEY]
-      ga = document.createElement("script")
-      ga.type = "text/javascript"
-      ga.async = true
-      ga.src = @_getTrackerScript()
+    @version = "0.0.9"
+    constructor:(KEY, Backbone, displayfeatures = false)->
+      window.ga = window.ga or ->
+        (ga.q = ga.q or []).push arguments
+        return
+      ga.l = +new Date
+      ga 'create', KEY, 'auto'
+      ga('require', 'displayfeatures') if displayfeatures
+      ga 'send', 'pageview'
+      analyticsScript = @_getTrackerScript()
       s = document.getElementsByTagName("script")[0]
-      s.parentNode.insertBefore ga, s
+      s.parentNode.insertBefore analyticsScript, s
       if Backbone?
         Backbone.history.on "route",=> @trackPageView()
       else
         @trackPageView()

     _getTrackerScript: ->
+      analyticsScript = document.createElement "script"
+      analyticsScript.type = "text/javascript"
+      analyticsScript.async = true
       isSecure = document.location.protocol is 'https:'
-      if @isUniversal
-        (if isSecure then 'https://' else 'http://') + 'stats.g.doubleclick.net/dc.js'
-      else
-        (if isSecure then "https://ssl" else "http://www") + ".google-analytics.com/ga.js"
+      analyticsScript.src = (if isSecure then 'https://' else 'http://') +
+        'www.google-analytics.com/analytics.js'
+      analyticsScript

-    initElementClick:($el,category,actions="",labels="")->
+    initElementClick: ($el, category, action="", label="")->
       return if $el.attr "data-ga-click"
-      $el.click => @trackEvent category, actions, labels
-      $el.attr "data-ga-click", "#{category};#{actions};#{labels}"
+      $el.click => @trackEvent category, action, label
+      $el.attr "data-ga-click", "#{category};#{action};#{label}"
       $el

-    unlinkElementClick:($el)->
-      $el.off("click")
-      $el.attr "data-ga-click",""
+    unlinkElementClick: ($el)->
+      $el.off "click"
+      $el.attr "data-ga-click", ""

     trackPageView:->
-      path = location.protocol+ '//' + location.host  + location.pathname + location.hash
-      window._gaq.push ['_trackPageview', path]
+      path = location.protocol + '//' + location.host  + location.pathname + location.hash
+      ga 'send', 'pageview', path

-    trackEvent:(category,actions="",labels="")->
-      window._gaq.push ['_trackEvent',category, actions, "" + labels]
+    trackEvent: (category, action, label="")->
+      ga 'send', 'event', category, action, label

 if (typeof define is 'function') and (typeof define.amd is 'object') and define.amd
   define ["jquery"], ($)-> Holder($)


NEW: animateOnCreation: true prop

NEW: animateOnCreation: true prop

--- source/Art/Engine/Core/EpochedObject.coffee
+++ source/Art/Engine/Core/EpochedObject.coffee
@@ -531,6 +531,10 @@
       _addAnimator prop, options for prop, options of v

   @concreteProperty
+    animateOnCreation:
+      default: false
+      validate: (v) -> !v || v == true
+
     animators:
       default: null
       preprocess: (v) ->
@@ -693,7 +697,8 @@
     nextTick => @_elementChanged()

   getPendingCreatedAndAddedToExistingParent: ->
-    @__stateEpochCount == 0 && !(@_pendingState._parent?.__stateEpochCount == 0)
+    {_parent, _animateOnCreation} = @_pendingState
+    @__stateEpochCount == 0 && (_animateOnCreation || !(@_pendingState._parent?.__stateEpochCount == 0))

   _applyAnimators: ->
     if pendingAnimators = @_pendingState._animators


Simple CORS test works

Simple CORS test works

--- source/javascripts/tests/simple_cors.coffee
+++ source/javascripts/tests/simple_cors.coffee
@@ -5,11 +5,16 @@
     @$http = $http

   run: (callback) ->
+    a = Math.floor((Math.random() * 100000) + 1)
+    b = Math.floor((Math.random() * 100000) + 1)
     @$http(
       method: "GET"
-      url: "http://corstest-api.coshx.com:3000"
+      url: "http://corstest-api.coshx.com:4000/tests/simple_cors?a=#{a}&b=#{b}"
     ).success((data, status, headers, config) =>
-      @result = "passed"
+      if data.sum == a+b
+        @result = "passed"
+      else
+        @result = "failed"
       callback(@) if callback
     ).error (data, status, headers, config) =>
       @result = "failed"


config is not used anymore

config is not used anymore

--- test/RestaticTest.coffee
+++ test/RestaticTest.coffee
@@ -3,7 +3,6 @@

 source = "./test/demo_data/source_folder_example"
 target = "./test/demo_data/target_folder_example"
-config_file = "./test/demo_data/restatic.json"

 describe "Restatic", ->
   it "runs and generates correct output", (done) ->


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/controllable.coffee
+++ test/controllable.coffee
@@ -73,6 +73,6 @@

   player.update()

-
+  ok player.I.facing.equal(Point(-1, 0))

 module()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/controllable.coffee
+++ test/controllable.coffee
@@ -72,7 +72,7 @@

   player.update()

-  equ
+  equals player.I.velocity

 test "should correctly track facing direction", ->
   ok player.I.facing.equal(Point(1, 0))


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/controllable.coffee
+++ test/controllable.coffee
@@ -24,6 +24,8 @@

   equals player.I.x, 8

+
+
 test "should move player right while key is pressed", ->
   window.keydown.right = true


exec: trap_error code may vary: stop testing value

--- test/core/execute.coffee
+++ test/core/execute.coffee
@@ -151,5 +151,4 @@
         trap_on_error: true
       , (err) ->
         err.should.be.an.Error
-        err.code.should.eql 2
         next()


Remove extraneous newline.

Remove extraneous newline.

--- test/unit/tnmSpec.coffee
+++ test/unit/tnmSpec.coffee
@@ -54,7 +54,6 @@
             2
           else
             3
-

         it 'should calcuate the summary grade', ->
           for tf in [1..3]


[grunt] update gruntfile to use newly added fixtures

--- gruntfile.coffee
+++ gruntfile.coffee
@@ -10,29 +10,36 @@

       source:
         root: 'tests/fixtures'
-        case1: '<%= path.source.root %>/case1'
+        single: '<%= path.source.root %>/single/page.html'
+        multiple: '<%= path.source.root %>/multiple'
+        nested: '<%= path.source.root %>/nested'

       build:
         root: 'build'
-        case1: '<%= path.build.root %>/case1.json'
+        singleWithDefaults: '<%= path.build.root %>/singleWithDefaults.json'
+        multipleWithDefaults: '<%= path.build.root %>/multipleWithDefaults.json'
+        nestedWithDefaults: '<%= path.build.root %>/nestedWithDefaults.json'

   grunt.loadTasks grunt.config('path.tasks')

   grunt.config 'grayMatter',
-    case1:
-      options:
-        baseDir: '<%= path.source.case1 %>'
+    singleWithDefaults:
+      src: '<%= path.source.single %>'
+      dest: '<%= path.build.singleWithDefaults %>'
+    multipleWithDefaults:
+      src: '<%= path.source.multiple %>/*'
+      dest: '<%= path.build.multipleWithDefaults %>'
+    nestedWithDefaults:
       files: [
         expand: true
-        cwd: '<%= path.source.case1 %>'
+        cwd: '<%= path.source.nested %>'
         src: ['{,**/}*.html']
-        dest: '<%= path.build.case1 %>'
+        dest: '<%= path.build.nestedWithDefaults %>'
       ]

   grunt.config 'clean',
     build:
-      files:
-        src: ['<%= path.build.root %>/*']
+      src: ['<%= path.build.root %>/*']

   grunt.registerTask 'default', [
     'clean'


Standalone version (no QuoJS implemented)

--- gruntfile.coffee
+++ gruntfile.coffee
@@ -30,6 +30,10 @@
         '<%=folder.quo%>quo.gestures.*.coffee'
         '<%=folder.quo%>quo.output.coffee'
         '<%=folder.quo%>quo.query.coffee'
+        'source/*.coffee'
+        'source/core/*.coffee'
+        'source/class/*.coffee']
+      standalone: [
         'source/*.coffee'
         'source/core/*.coffee'
         'source/class/*.coffee']
@@ -92,37 +96,42 @@
     # TASKS
     # ==========================================================================
     concat:
-      core                : files: '<%=folder.build%>core.coffee'                 : '<%= core.coffee %>'
-      # App
-      app                 : files: '<%=folder.build%>app.coffee'                  : '<%= app.coffee %>'
-      app_appnima_user    : files: '<%=folder.build%>app.appnima.user.coffee'     : '<%= app.extension.appnima.user.coffee %>'
-      app_appnima_payment : files: '<%=folder.build%>app.appnima.payment.coffee'  : '<%= app.extension.appnima.payment.coffee %>'
-      app_carousel        : files: '<%=folder.build%>app.carousel.coffee'         : '<%= app.extension.carousel.coffee %>'
-      app_gmaps           : files: '<%=folder.build%>app.gmaps.coffee'            : '<%= app.extension.gmaps.coffee %>'
-      app_stripe          : files: '<%=folder.build%>app.stripe.coffee'           : '<%= app.extension.stripe.coffee %>'
-      app_chart           : files: '<%=folder.build%>app.chart.coffee'            : '<%= app.extension.chart.coffee %>'
+      core                : files: '<%=folder.build%>core.coffee'               : '<%= core.coffee %>'
+      standalone          : files: '<%=folder.build%>standalone.coffee'         : '<%= core.standalone %>'
+      # App
+      app                 : files: '<%=folder.build%>app.coffee'                : '<%= app.coffee %>'
+      app_appnima_user    : files: '<%=folder.build%>app.appnima.user.coffee'   : '<%= app.extension.appnima.user.coffee %>'
+      app_appnima_payment : files: '<%=folder.build%>app.appnima.payment.coffee': '<%= app.extension.appnima.payment.coffee %>'
+      app_carousel        : files: '<%=folder.build%>app.carousel.coffee'       : '<%= app.extension.carousel.coffee %>'
+      app_gmaps           : files: '<%=folder.build%>app.gmaps.coffee'          : '<%= app.extension.gmaps.coffee %>'
+      app_stripe          : files: '<%=folder.build%>app.stripe.coffee'         : '<%= app.extension.stripe.coffee %>'
+      app_chart           : files: '<%=folder.build%>app.chart.coffee'          : '<%= app.extension.chart.coffee %>'
       # Test
-      test                :   files: '<%=folder.build%>test.coffee'               : '<%= core.test %>'
+      test                :   files: '<%=folder.build%>test.coffee'             : '<%= core.test %>'

     coffee:
-      core                : files: '<%=folder.build%>core.js'                     : '<%=folder.build%>core.coffee'
-      spec                : files: '<%=folder.build%>spec.js'                     : '<%= core.spec %>'
-      # App
-      app                 : files: '<%=folder.build%>app.js'                      : '<%=folder.build%>app.coffee'
-      app_appnima_user    : files: '<%=folder.build%>app.appnima.user.js'         : '<%=folder.build%>app.appnima.user.coffee'
-      app_appnima_payment : files: '<%=folder.build%>app.appnima.payment.js'      : '<%=folder.build%>app.appnima.payment.coffee'
-      app_carousel        : files: '<%=folder.build%>app.carousel.js'             : '<%=folder.build%>app.carousel.coffee'
-      app_gmaps           : files: '<%=folder.build%>app.gmaps.js'                : '<%=folder.build%>app.gmaps.coffee'
-      app_stripe          : files: '<%=folder.build%>app.stripe.js'               : '<%=folder.build%>app.stripe.coffee'
-      app_chart           : files: '<%=folder.build%>app.chart.js'                : '<%=folder.build%>app.chart.coffee'
+      core                : files: '<%=folder.build%>core.js'                   : '<%=folder.build%>core.coffee'
+      standalone          : files: '<%=folder.build%>standalone.js'             : '<%=folder.build%>standalone.coffee'
+      spec                : files: '<%=folder.build%>spec.js'                   : '<%= core.spec %>'
+      # App
+      app                 : files: '<%=folder.build%>app.js'                    : '<%=folder.build%>app.coffee'
+      app_appnima_user    : files: '<%=folder.build%>app.appnima.user.js'       : '<%=folder.build%>app.appnima.user.coffee'
+      app_appnima_payment : files: '<%=folder.build%>app.appnima.payment.js'    : '<%=folder.build%>app.appnima.payment.coffee'
+      app_carousel        : files: '<%=folder.build%>app.carousel.js'           : '<%=folder.build%>app.carousel.coffee'
+      app_gmaps           : files: '<%=folder.build%>app.gmaps.js'              : '<%=folder.build%>app.gmaps.coffee'
+      app_stripe          : files: '<%=folder.build%>app.stripe.js'             : '<%=folder.build%>app.stripe.coffee'
+      app_chart           : files: '<%=folder.build%>app.chart.js'              : '<%=folder.build%>app.chart.coffee'
       # Test
-      test                : files: '<%=folder.build%>test.js'                     : '<%=folder.build%>test.coffee'
+      test                : files: '<%=folder.build%>test.js'                   : '<%=folder.build%>test.coffee'

     uglify:
       options:  banner: "<%= meta.banner %>"#, report: "gzip"
       core:
         options: mangle: true
         files: '<%=folder.bower%><%=pkg.name%>.js'                              : '<%=folder.build%>core.js'
+      standalone:
+        options: mangle: true
+        files: '<%=folder.bower%><%=pkg.name%>.standalone.js'                   : '<%=folder.build%>standalone.js'
       # App
       app:
         options: mangle: false
@@ -208,7 +217,7 @@
     watch:
       core:
         files: ['<%= core.coffee %>']
-        tasks: ['concat:core', 'coffee:core', 'uglify:core', 'jasmine', 'notify:core']
+        tasks: ['concat:core', 'coffee:core', 'uglify:core', 'concat:standalone', 'coffee:standalone', 'uglify:standalone', 'jasmine', 'notify:core']
       spec:
         files: ['<%= core.spec %>']
         tasks: ['coffee:spec', 'jasmine', 'notify:spec']


GitLab: handle requests correctly and use proper method call

--- servers/lib/server/handlers/api/gitlab/index.coffee
+++ servers/lib/server/handlers/api/gitlab/index.coffee
@@ -19,5 +19,16 @@

   Models = (require '../../../bongo').models

+  if not event = validateRequest req
+    return sendApiError res, 'not valid'

-  sendApiResponse res, 'ok'
+  { scope, method } = parseEvent event
+
+  if not handler = HANDLERS[scope]
+    return sendApiError res, 'not valid'
+
+  log "Processing #{method} on #{scope}..."
+
+  handler[method] req.body, (err) ->
+    if err then sendApiError res, err
+    else sendApiResponse res, 'ok'


Cleanup whitespace

Cleanup whitespace

--- client/app/Applications/Activity.kdapplication/ListItems/ActivityListItemFollow.coffee
+++ client/app/Applications/Activity.kdapplication/ListItems/ActivityListItemFollow.coffee
@@ -2,7 +2,7 @@
   cssClassMap = ->
     JTag      : "topic"
     JAccount  : "account"
-
+
   constructor:(options,data)->
     options = $.extend options,
       cssClass : "follow bucket #{cssClassMap()[data.sourceName]}"
@@ -11,15 +11,15 @@
     @anchor = new ProfileLinkView {
       origin: data.anchor
     }
-
+
     @group = new LinkGroup {
       group         : data.group
       itemsToShow   : 3
       subItemClass  : options.subItemLinkClass
     }
-
+
     @getData().on 'ItemWasAdded', -> log 'heres the event, sinan', arguments
-
+
   pistachio:->
     """

@@ -27,11 +27,11 @@
     followed
     {{> @group}}
     """
-
+
   render:->
-
+
   addCommentBox:->
-
+
   viewAppended:->
     @setTemplate @pistachio()
     @template.update()
@@ -45,15 +45,15 @@
     super options,data

     @anchor = new ProfileLinkView origin: data.anchor
-
+
   render:->
-
+
   addCommentBox:->
-
+
   viewAppended:->
     @setTemplate @pistachio()
     @template.update()
-
+
   pistachio:->
     """

@@ -63,15 +63,15 @@

 class AccountFollowBucketItemView extends FollowBucketItemView
-
+
   constructor:(options, data)->
     options.subItemLinkClass or= ProfileLinkView
     options.subItemCssClass or= 'profile'
     super

 class TagFollowBucketItemView extends FollowBucketItemView
-
+
   constructor:(options, data)->
     options.subItemLinkClass or= TagLinkView
     options.subItemCssClass or= 'topic'
-    super+    super


Add simulation throughput counter

Add simulation throughput counter

--- server/queues/scoring/scoringUtils.coffee
+++ server/queues/scoring/scoringUtils.coffee
@@ -3,6 +3,7 @@
 bayes = new (require 'bayesian-battle')()
 LevelSession = require '../../levels/sessions/LevelSession'
 User = require '../../users/User'
+perfmon = require '../../commons/perfmon'

 SIMULATOR_VERSION = 3

@@ -199,6 +200,7 @@
   incrementUserSimulationCount reqUserID, 'simulatedBy', (err) =>
     if err? then return callback err
     #console.log 'Incremented user simulation count!'
+    perfmon.client.increment 'simulations'
     unless @isRandomMatch
       incrementUserSimulationCount @levelSession.creator, 'simulatedFor', callback
     else


Implementation of regexp argument handling

--- src/Overloadable.coffee
+++ src/Overloadable.coffee
@@ -177,6 +177,13 @@

     matcherFactory.registerMatcher "function", InstanceofMatcher

+class RegExpMatcher extends AbstractMatcher
+    match: (argument, overloadSignatureElement) ->
+        return false if Utils.getClassOf(argument) isnt "string"
+        overloadSignatureElement.test argument
+
+    matcherFactory.registerMatcher "regexp", RegExpMatcher
+
 class CompiledMatcher
     constructor: (@_matcher, @_value) ->


Render manager: Add use_sort_faces. Fix sort priority. Sort objects by distance to camera instead of dot.

--- engine/render.coffee
+++ engine/render.coffee
@@ -26,6 +26,7 @@
         @compiled_shaders_this_frame = 0
         @use_frustum_culling = true
         @show_debug_frustum_culling = false
+        @use_sort_faces = true
         @unbind_textures_on_draw_viewport = true
         @probes = []
         # to simulate glClipPlane
@@ -872,18 +873,20 @@
             v = vec3.create()
             for ob in scene.mesh_passes[1]
                 ob.get_world_position_into(v)
-                ob._sqdist = -vec3.dot(v,z) - (ob.zindex * \
+                # TODO: squared dist and zindex?
+                ob._sqdist = -vec3.dist(v,cam_pos) - (ob.zindex * \
                     (ob.dimensions.x+ob.dimensions.y+ob.dimensions.z)*0.166666)
             timsort.sort scene.mesh_passes[1], (a,b)-> a._sqdist - b._sqdist

-            # Sort some meshes, for now just one per frame, with more iterations
-            # for nearby meshes (TODO: Calculate which one has more divergence)
-            idx = @render_tick % ((scene.mesh_passes[1].length * 1.5)|0)
-            idx %= scene.mesh_passes[1].length
-            remaining_meshes = 1
-            cam_name = cam.name
-            ob = scene.mesh_passes[1][idx]
-            (ob.last_lod[cam_name]?.mesh ? ob).sort_faces(cam_pos)
+            if @use_sort_faces
+                # Sort some meshes, for now just one per frame, with more iterations
+                # for nearby meshes (TODO: Calculate which one has more divergence)
+                num_meshes = scene.mesh_passes[1].length
+                idx = @render_tick % ((num_meshes * 1.5)|0)
+                idx = num_meshes - (idx % num_meshes) - 1
+                cam_name = cam.name
+                ob = scene.mesh_passes[1][idx]
+                (ob.last_lod[cam_name]?.mesh ? ob).sort_faces(cam_pos)

             for ob in scene.mesh_passes[1]
                 if ob.visible == true


Remove unused variable

Remove unused variable

--- spec/keybinding-resolver-view-spec.coffee
+++ spec/keybinding-resolver-view-spec.coffee
@@ -2,11 +2,9 @@
 {$, RootView} = require 'atom'

 describe "KeybindingResolverView", ->
-  keybindingResolver = null
-
   beforeEach ->
     atom.rootView = new RootView
-    keybindingResolver = atom.packages.activatePackage('keybinding-resolver', immediate: true)
+    atom.packages.activatePackage('keybinding-resolver', immediate: true)

   describe "when the keybinding-resolver:toggle event is triggered", ->
     it "attaches and then detaches the view", ->


Set scalacExecutablePath as Empty

Set scalacExecutablePath as Empty

--- lib/init.coffee
+++ lib/init.coffee
@@ -1,6 +1,6 @@
 module.exports =
 	configDefaults:
-		scalacExecutablePath: null
+		scalacExecutablePath: ''
 		scalacOptions: '-Xlint'

 	activate: -> console.log('activate linter-scalac')


swagger: artifact in upload

swagger: artifact in upload

--- src/routes/upload.coffee
+++ src/routes/upload.coffee
@@ -43,8 +43,6 @@
 						$ref: "#/definitions/InfolisFile"
 				400:
 					description: 'Upload failed'
-				503:
-					description: 'Backend is down.'
 				503:
 					description: 'Backend is down.'
 				500:


:bug: #338 Directly get editor from target element.

In this fix I no longer check editor is available or not, why I need
this condition check is maybe having cause of this bug.

--- lib/main.coffee
+++ lib/main.coffee
@@ -170,12 +170,12 @@
       do (char) ->
         commands["set-input-char-#{char}"] = -> @setInputChar(char)

-    scope = 'atom-text-editor:not([mini])'
+    getEditorState = @getEditorState.bind(this)
     for name, fn of commands
       do (fn) =>
-        @subscribe atom.commands.add scope, "vim-mode-plus:#{name}", (event) =>
-          if editor = atom.workspace.getActiveTextEditor()
-            fn.call(@getEditorState(editor))
+        commandName = "vim-mode-plus:#{name}"
+        @subscribe atom.commands.add 'atom-text-editor:not([mini])', commandName, ->
+          fn.call(getEditorState(@getModel()))

   consumeStatusBar: (statusBar) ->
     @statusBarManager.initialize(statusBar)


:art: Move consumerLinter's logic to _consumeLinter it'll help us work with disposables while still working.

--- lib/main.coffee
+++ lib/main.coffee
@@ -25,10 +25,9 @@
   consumeLinter: (linter) ->
     if linter instanceof Array
       for singleLinter in linter
-        @consumeLinter(singleLinter)
+        @_consumeLinter(singleLinter)
     else
-      if @_validateLinter(linter)
-        @instance.linters.push linter
+      @_consumeLinter(linter)

   consumeStatusBar: (statusBar) ->
     @instance.views.attachBottom(statusBar)
@@ -39,10 +38,9 @@
   deactivate: ->
     @instance?.deactivate()

-  _validateLinter: (linter) ->
+  _consumeLinter: (linter) ->
     if linter.grammarScopes instanceof Array and typeof linter.lint is 'function'
-      true
+      @instance.linters.push linter
     else
       err = new Error("Invalid Linter Provided")
-      atom.notifications.addError err.message, {detail: err.stack}
-      false+      atom.notifications.addError err.message, {detail: err.stack}


fix: remove dockerignore fix.

fix: remove dockerignore fix.

--- lib/main.coffee
+++ lib/main.coffee
@@ -8,13 +8,6 @@
   debug: false

   activate: (state) ->
-    dockerIgnoreScope = customFileTypes['text.ignore']
-
-    if  not dockerIgnoreScope
-      console.log 'Desactivate syntax highlighting for "source.dockerignore" from https://atom.io/packages/language-docker.'
-      customFileTypes['text.ignore'] = ['dockerignore']
-      atom.config.set 'core.customFileTypes', customFileTypes
-
     return unless atom.inDevMode() and not atom.inSpecMode()

     @subscriptions = new CompositeDisposable


:new: Add ignoredErrorTypes config

:new: Add ignoredErrorTypes config

--- lib/main.coffee
+++ lib/main.coffee
@@ -38,6 +38,12 @@
       enum: ['Left', 'Right']
       type: 'string'
       default: 'Left'
+    ignoredErrorTypes:
+      title: "Ignored Error Types"
+      type: 'array'
+      default: []
+      items:
+        type: 'string'

   activate: (state) ->
     LinterPlus = require('./linter-plus.coffee')


Add missing makeServiceType function in ST generation

--- lib/ssdp.coffee
+++ lib/ssdp.coffee
@@ -61,7 +61,7 @@
     [ 'upnp:rootdevice'
       config.uuid
       device.makeDeviceType dev.type
-    ].concat config.devices[dev.type].services
+    ].concat(device.makeServiceType(s) for s in config.devices[dev.type].services)

 # create a UDP socket, send messages, then close socket
 sendMessages = (messages, address, port) ->
@@ -92,7 +92,7 @@
         ext: ''
         usn: config.uuid + (if config.uuid is (customHeaders.nt or customHeaders.st) then '' else '::' + (customHeaders.nt or customHeaders.st))

-    # specified headers are included in every request, merge them with headers passed to function
+    # these headers are included in every request, merge them with the request specific headers
     includeHeaders = ['cache-control','server','usn','location'].concat Object.keys customHeaders

     # build message string
@@ -105,7 +105,7 @@
     for header in includeHeaders
         message.push "#{header.toUpperCase()}: #{customHeaders[header] or defaultHeaders[header]}"

-    debug message.join ', '
+    debug message.join '\n      '
     # add carriage returns and new lines as required by HTTP spec
     message.push '\r\n'
     new Buffer message.join '\r\n'
@@ -125,10 +125,11 @@
     )

 # parse headers using http module parser
+# this api is not documented nor stable, might break in the future
 parseHeaders = (msg, callback) ->
     parser = http.parsers.alloc()
-    parser.reinitialize('request')
+    parser.reinitialize 'request'
     parser.onIncoming = (req) ->
-        http.parsers.free(parser)
+        http.parsers.free parser
         callback null, req
     parser.execute msg, 0, msg.length


Add a new search path for the pghoff installer

--- lib/util.coffee
+++ lib/util.coffee
@@ -43,6 +43,9 @@
         if fs.existsSync(path.join hoffpath, 'pghoffserver.py')
             atom.config.set('pg-hoff.hoffServerPath', path.parse(hoffpath).dir)
             hoffpath = path.parse(hoffpath).dir
+        else if fs.existsSync(path.join os.homedir(), '.pghoffserver', 'src', 'pg-hoffserver', 'pghoffserver', 'pghoffserver.py')
+            atom.config.set('pg-hoff.hoffServerPath', path.join os.homedir(), '.pghoffserver', 'src', 'pg-hoffserver', 'pghoffserver')
+            hoffpath = path.parse(path.join os.homedir(), '.pghoffserver', 'src', 'pg-hoffserver', 'pghoffserver').dir
         else if hoffpath.indexOf('pghoffserver.py') != -1 and fs.existsSync(hoffpath)
             atom.config.set('pg-hoff.hoffServerPath', path.parse(path.join hoffpath, '../').dir)
             hoffpath = path.parse(path.join hoffpath, '../').dir


:fire: leftover

:fire: leftover

--- lib/view.coffee
+++ lib/view.coffee
@@ -19,13 +19,6 @@
   cancel: (view) ->
     if @vimState.operationStack.isOperatorPending()
       @emitter.emit 'did-get-input', ''
-
-# class Input extends Base
-#   @extend()
-#   complete: true
-#   recodable: true
-#
-#   constructor: (@characters) ->

 class VimNormalModeInputElement extends HTMLDivElement
   createdCallback: ->


Fuzz test inbox list

Fuzz test inbox list

--- test/fuzz.coffee
+++ test/fuzz.coffee
@@ -33,12 +33,11 @@
     completed: 'completed'

   list:
-    id: 'id'
+    id: 'listId'
     name: 'string'
     tasks: 'ids'

   pref:
-    id: 'id'
     sort: 'boolean'
     night: 'string'
     language: 'string'
@@ -59,6 +58,12 @@
   id: ->
     random.char('csx') + random.int(0, 100)

+  listId: ->
+    if random.int(0, 10) > 6
+      return 'inbox'
+    else
+      return random.id()
+
   ids: ->
     arr = []
     len = random.int(0, 10)
@@ -108,26 +113,26 @@

   model: (model) ->
     obj = {}
-    for key, value of model when key isnt 'id' and random.boolean()
+    for key, value of model when random.boolean()
       obj[key] = random[value]()
     return obj

   fullModel: (model) ->
     obj = {}
-    for key, value of model when key isnt 'id'
+    for key, value of model
       obj[key] = random[value]()
     return obj

   task: (event) ->
     model = models.task
     obj = if event is 'create' then random.fullModel(model) else random.model(model)
-    obj.id = random.id()
+    obj.id ?= random.id()
     return obj

   list: (event) ->
     model = models.list
     obj = if event is 'create' then random.fullModel(model) else random.model(model)
-    obj.id = random.id()
+    obj.id ?= random.id()
     return obj

   pref: ->


Surface write stream errors

Surface write stream errors

--- src/installer.coffee
+++ src/installer.coffee
@@ -173,12 +173,14 @@

     readStream = request.get(requestSettings)
     readStream.on 'error', (error) ->
-      callback("Unabled to download package (#{error.message}): #{packageUrl}")
+      callback("Unable to download package (#{error.message}): #{packageUrl}")
     readStream.on 'response', (response) ->
       if response.statusCode is 200
         filePath = path.join(temp.mkdirSync(), 'package.tgz')
         writeStream = fs.createWriteStream(filePath)
         readStream.pipe(writeStream)
+        writeStream.on 'error', (errror) ->
+          callback("Unable to download package (#{error.message}): #{packageUrl}")
         writeStream.on 'close', -> callback(null, filePath)
       else
         callback("Unable to download package (#{response.statusCode}): #{packageUrl}")


Jest only passes with 1 test atm. We need to fix this

--- __tests__/client/traits.coffee
+++ __tests__/client/traits.coffee
@@ -1,7 +0,0 @@
-jest
-  .dontMock "../../src/client/traits"
-  .dontMock "../../src/utils/lodash"
-
-describe "Client Traits", ()->
-  it "Calls the api gateway with the right params", ()->
-    expect(1).toBe(1)