SplitView: splitcomboview refactor after splitview changes

--- src/components/split/splitcomboview.coffee
+++ src/components/split/splitcomboview.coffee
@@ -1,18 +1,20 @@
 KDView      = require './../../core/view.coffee'
 KDSplitView = require './splitview.coffee'

-module.exports = class KDSplitComboView extends KDView
+module.exports = class KDSplitComboView extends KDSplitView

   constructor: (options = {}, data) ->

     options.cssClass or= "kdsplitcomboview"
+    options.sizes    or= ['100%', 0]

     super options, data

-    @init options
+    @once "viewAppended", @bound 'init'
+

   init: (options) ->
-    @addSubView @createSplitView options.direction, options.sizes, options.views
+    @createSplitView options.direction, options.sizes, options.views

   createSplitView: (type, sizes, viewsConfig) ->
     views = []
@@ -23,8 +25,7 @@
         views.push @createSplitView options.direction, options.sizes, config.views
       else
         views.push config
-
-    return new KDSplitView { type, sizes, views }
+    @splitPanel 0, { type, sizes, views }

 # Example Usage


Removed unnecessary event handler

Removed unnecessary event handler

--- lib/eslint-view.coffee
+++ lib/eslint-view.coffee
@@ -44,10 +44,6 @@
     @editorView.command 'eslint:toggle', => @toggle()
     @list.on 'mousewheel', (event) -> event.stopPropagation()

-    @filterEditorView.on 'core:confirm', (event) =>
-      console.log 'preempted'
-      false
-
   selectNextItemView: ->
     super
     false


Add missing properties

Add missing properties

--- lib/exports/emp.coffee
+++ lib/exports/emp.coffee
@@ -5,6 +5,10 @@

 module.exports =
   parser_beam_file_mod : 'atom_pl_parse_json'
+
+  EMP_APP_EXPORT_UI_PATH :'emp-template-management.Store-UI-Snippet-Export-Path'
+  EMP_APP_IMPORT_UI_PATH :'emp-template-management.Store-UI-Snippet-Import-Path'
+  EMP_APP_STORE_UI_PATH :'emp-template-management.Store-UI-Snippet-Path'

   EMP_APP_WIZARD_APP_P :'emp-debugger.Default-App-Wizard-App-Path'
   EMP_APP_WIZARD_EWP_P :'emp-debugger.Default-App-Wizard-Ewp-Path'


Replace internal property with getter in Tabs

--- bokehjs/src/coffee/models/widgets/tabs.coffee
+++ bokehjs/src/coffee/models/widgets/tabs.coffee
@@ -49,18 +49,14 @@
   type: "Tabs"
   default_view: TabsView

-  initialize: (options) ->
-    super(options)
-    @children = (tab.child for tab in @tabs)
+  @define {
+    tabs:     [ p.Array,   [] ]
+    active:   [ p.Number,  0  ]
+    callback: [ p.Instance    ]
+  }

-  @define {
-      tabs:     [ p.Array,   [] ]
-      active:   [ p.Number,  0  ]
-      callback: [ p.Instance    ]
-    }
-
-  @internal {
-      children: [ p.Array,   [] ]
+  @getters {
+    children: () -> (tab.child for tab in @tabs)
   }

   get_layoutable_children: () ->


use spatial index for point hit testing

use spatial index for point hit testing

--- bokehjs/src/coffee/renderer/glyph/quad.coffee
+++ bokehjs/src/coffee/renderer/glyph/quad.coffee
@@ -31,14 +31,10 @@

   _hit_point: (geometry) ->
     [vx, vy] = [geometry.vx, geometry.vy]
-    sx = @renderer.plot_view.canvas.vx_to_sx(vx)
-    sy = @renderer.plot_view.canvas.vy_to_sy(vy)
+    x = @renderer.xmapper.map_from_target(vx, true)
+    y = @renderer.ymapper.map_from_target(vy, true)

-    hits = []
-    for i in [0...@sleft.length]
-      if (sx >= @sleft[i] and sx <= @sright[i] and sy >= @stop[i] and
-          sy < @sbottom[i])
-        hits.push(i)
+    hits = (x[4].i for x in @index.search([x, y, x, y]))

     result = hittest.create_hit_test_result()
     result['1d'].indices = hits


Test that coffee/python sync issues are not increasing

Instead of commenting out the assertion entirely, we can require
that the problem doesn't get any worse.

--- bokehjs/test/test_common/test_defaults.coffee
+++ bokehjs/test/test_common/test_defaults.coffee
@@ -172,5 +172,9 @@
       if not check_matching_defaults(name, get_defaults(name), attrs)
         fail_count = fail_count + 1

-    # TODO this is skipped until it passes
-    #expect(fail_count).to.equal 0
+    console.error("Python/Coffee matching defaults problems: #{fail_count}")
+    # If this is failing because the problem count is now lower,
+    # then edit this number to be lower. If it's failing because
+    # it's higher, fix the newly-introduced errors. Eventually we
+    # will get to zero.
+    expect(fail_count).to.equal 63


Removed Caman Debug

Removed Caman Debug

--- assets/js/gimme/gimme.coffee
+++ assets/js/gimme/gimme.coffee
@@ -24,6 +24,5 @@
 	)

 	Caman.remoteProxy = "proxy";
-	Caman.DEBUG = true
 	Caman "#uploaded-marker", () ->
 		@brightness(5).render()


Modification of delta pinch/spread

Modification of delta pinch/spread

--- Analyzer.coffee
+++ Analyzer.coffee
@@ -276,10 +276,10 @@
 		# The scale is already sent in the event Object
 		# @informations.global.scale = @calculateScale()
 		## Spread and Pinch detection
-		if @informations.global.scale < 0.9
+		if @informations.global.scale < 1
 			@targetElement.trigger "#{digit_name(@fingers.length)}:pinch", @informations
 			@targetElement.trigger "pinch", @informations
-		else if @informations.global.scale > 1.1
+		else if @informations.global.scale > 1
 			@targetElement.trigger "#{digit_name(@fingers.length)}:spread", @informations
 			@targetElement.trigger "spread", @informations


improve offsite backup script

improve offsite backup script

--- salvus/scripts/bup/get-cloud4.coffee
+++ salvus/scripts/bup/get-cloud4.coffee
@@ -1,11 +1,16 @@
-
-# This is a backup script that I use on my laptop to efficiently pull backups from cloud4 to offsite.
+THREADS = 5
+OLDEST = '2014-12-01'

 async          = require('async')
 fs             = require('fs')
 child_process  = require('child_process')

-OLDEST = '2014-12-01'
+split = (s) ->
+    r = s.match(/\S+/g)
+    if r
+        return r
+    else
+        return []

 cmd = (s, cb) ->
     console.log(s)
@@ -21,25 +26,28 @@
 num_to_get = undefined
 f = (x, cb) ->
     i=x[0]; project_id = x[1]; j = x[2]
-    console.log("Syncing #{j}/#{num_to_get} from 10.1.#{i}.5...")
-    cmd("time rsync -axvH --delete salvus@cloud4.math.washington.edu:/home/salvus/vm/images/bup/bups/10.1.#{i}.5/#{project_id}/ bup/bups/10.1.#{i}.5/#{project_id}/", cb)
+    console.log("Syncing #{j}/#{num_to_get} -- (from 10.1.#{i}.5)...")
+    cmd("time rsync -axvH --delete --exclude /home/salvus/vm/images/bup/bups/10.1.#{i}.5/#{project_id}/cache/ salvus@cloud4.math.washington.edu:/home/salvus/vm/images/bup/bups/10.1.#{i}.5/#{project_id}/ bup/bups/10.1.#{i}.5/#{project_id}/", cb)

-g = (i, cb) ->
+g = (cb) ->
     to_get = []
     j = 0
-    for x in fs.readFileSync("bup/bups/ls-lt/10.1.#{i}.5").toString().split('\n')
-        # drwx------ 10 salvus salvus 15 2014-12-01 18:03:31.174363687 +0000 4a23c55e-fd3b-4695-a4d7-de088ebce6ca
-        v = x.split(' ')
-        if v.length < 9
-            continue
-        if v[5] < OLDEST
-            break
-        j += 1
-        to_get.push([i,v[8],j])
+    for i in [1..7]
+        for x in fs.readFileSync("bup/bups/ls-lt/10.1.#{i}.5").toString().split('\n')
+            v = split(x)
+            #console.log(x); console.log(v)
+            if v.length < 9
+                continue
+            if v[5] < OLDEST
+                console.log("Halting scan of 10.1.#{i}.5 at '#{x}'.")
+                break
+            j += 1
+            to_get.push([i,v[8],j])

     num_to_get = to_get.length
     console.log "Syncing #{num_to_get} projects from 10.1.#{i}.5"
-    async.mapLimit(to_get, 10, f, (err) -> cb?(err))
+    async.mapLimit(to_get, THREADS, f, (err) -> cb?(err))
+    cb?()

 sync_db = (cb) ->
     console.log("Syncing database backup")
@@ -49,9 +57,9 @@
     (cb) ->
        update_project_times(cb)
     (cb) ->
-       async.mapSeries([1..7], g, (err) -> cb(err))
-    #(cb) ->
-    #   sync_db(cb)
+       g(cb)
+    (cb) ->
+       sync_db(cb)
 ], (err) ->
     console.log("Done updating backups: err=#{err}")
 )


User included with classification

User included with classification

--- scripts/models/Classification.coffee
+++ scripts/models/Classification.coffee
@@ -1,5 +1,6 @@
 Spine = require 'Spine'

+User = require 'models/User'
 FrequencyRange = require 'models/FrequencyRange'

 class Classification extends Spine.Model
@@ -8,6 +9,7 @@
   @extend Spine.Model.Local

   serialize: =>
+    user: User.current.id
     frequencyRanges: (range.serialize() for range in @frequencyRanges().all())

   saveRemotely: =>


radioButton: forgot require

radioButton: forgot require

--- radio_button/index.coffee
+++ radio_button/index.coffee
@@ -1,4 +1,5 @@
 z = require 'zorium'
+Rx = require 'rx-lite'

 paperColors = require '../colors.json'
 RipplerService = require '../services/rippler'


Removed UUGA

Removed UUGA

--- src/MunKirjat/MainBundle/Resources/coffee/view/BookListView.coffee
+++ src/MunKirjat/MainBundle/Resources/coffee/view/BookListView.coffee
@@ -26,7 +26,7 @@
                     else
                         blocksInFirstColumn = amount / columns

-                    container = '
UUGA
'
+                    container = '

'

                     step = 0
                     _.each self.model.models, ((book) ->


embedly: don't create new md5 each time

embedly: don't create new md5 each time

--- server/lib/server/image_cache.coffee
+++ server/lib/server/image_cache.coffee
@@ -40,10 +40,13 @@
   # replace nonalphanumeric characters
   ext = ext.replace(/\W+/g, "")

+  md5 = crypto.createHash("md5")
   for i in [noExt, width, height]
-    md5 = crypto.createHash("md5").update(i).digest("hex")
+    md5.update(i)

-  filename = "#{imagePath}/#{md5}.#{ext}"
+  digest = md5.digest("hex")
+
+  filename = "#{imagePath}/#{digest}.#{ext}"

   serveFile = (filename, res)->
     fileStream = fs.createReadStream filename


Apps: implement search for Apps in client side

--- client/Social/Apps/AppController.coffee
+++ client/Social/Apps/AppController.coffee
@@ -21,13 +21,18 @@

     super options, data

-  loadView:(mainView)->
+  loadView:(mainView, firstRun = yes, loadFeed = no)->
+    if firstRun
+      @on "searchFilterChanged", (value) =>
+        return if value is @_searchValue
+        @_searchValue = Encoder.XSSEncode value
+        @_lastSubview.destroy?()
+        @loadView mainView, no, yes

-    mainView.createCommons()
-    @createFeed mainView
+      mainView.createCommons()
+    @createFeed mainView, loadFeed

-  createFeed:(view)->
-
+  createFeed:(view, loadFeed = no)->
     options =
       feedId                : 'apps.main'
       itemClass             : AppsListItemView
@@ -39,7 +44,11 @@
           title             : "All Apps"
           noItemFoundText   : "There is no application yet"
           dataSource        : (selector, options, callback)=>
-            KD.remote.api.JNewApp.some selector, options, callback
+            {JNewApp} = KD.remote.api
+            if @_searchValue
+              JNewApp.byRelevance @_searchValue, options, callback
+            else
+              JNewApp.some selector, options, callback
         webApps             :
           title             : "Web Apps"
           noItemFoundText   : "There is no web apps yet"
@@ -101,8 +110,9 @@

     KD.getSingleton("appManager").tell 'Feeder', 'createContentFeedController', options, (controller)=>

-      view.addSubView controller.getView()
+      view.addSubView @_lastSubview = controller.getView()
       @feedController = controller
+      controller.loadFeed() if loadFeed
       @emit 'ready'

   handleQuery:(query)->
@@ -127,3 +137,6 @@
     contentDisplay = controller.getView()
     KD.singleton('display').emit "ContentDisplayWantsToBeShown", contentDisplay
     return contentDisplay
+
+  search:(text)-> @emit "searchFilterChanged", text
+


sidebar/container: calculate shared resources

Signed-off-by: Umut Sirin <4055abbc0e40a1254e715b952ccd414607e0b365@gmail.com>

--- client/app/lib/sidebar/container.coffee
+++ client/app/lib/sidebar/container.coffee
@@ -50,9 +50,15 @@

 calculateSharedResources = (props, state) ->

-  debug 'calculateSharedResources', { props, state }
+  debug 'start calculating shared resources', { props, state }

-  return []
+  resources =
+    permanent: props.machines.filter (m) -> m.getType() is 'shared'
+    collaboration: props.machines.filter (m) -> m.getType() is 'collaboration'
+
+  debug 'shared resources are calculated', resources
+
+  return resources

 module.exports = class SidebarContainer extends React.Component


ComputeController: fix fetchStacks and fetchMachines scopes

--- client/Main/providers/computecontroller.coffee
+++ client/Main/providers/computecontroller.coffee
@@ -17,6 +17,8 @@

       @on "machineBuildCompleted", => delete @stacks

+      @fetchStacks => @emit 'ready'
+

   fetchStacks: (callback = noop)->

@@ -27,12 +29,14 @@

     KD.remote.api.JStack.some {}, (err, stacks = [])=>
       return callback err  if err?
-      callback null, @stacks = stacks
+
+      @stacks = stacks     if stacks.length > 0
+      callback null, @stacks

-  fetchMachines: (callback)->
+  fetchMachines: (callback = noop)->

-    @fetchStacks (err, stacks)->
+    @fetchStacks (err, stacks)=>
       return callback err  if err?

       machines = []


Use AppStorage for Apps Controller

Use AppStorage for Apps Controller

--- client/app/MainApp/kodingappscontroller.coffee
+++ client/app/MainApp/kodingappscontroller.coffee
@@ -35,6 +35,7 @@

   @manifests = {}

+
   # #
   # HELPERS
   # #
@@ -61,6 +62,7 @@
     super

     @kiteController = @getSingleton('kiteController')
+    @appStorage = new AppStorage 'KodingApps', '1.0'

   # #
   # FETCHERS
@@ -131,19 +133,15 @@

   fetchAppsFromDb:(callback)->

-    appManager.fetchStorage "KodingApps", "1.0", (err, storage)=>
-      if err
-        warn err
-        callback err
-      else
-        apps = storage.getAt "bucket.apps"
-        if apps and Object.keys(apps).length > 0
-          @constructor.manifests = apps
-          callback null, apps
-        else
-          callback new Error "There are no apps in the app storage."
+    @appStorage.fetchValue 'apps', (apps)->
+      if apps and Object.keys(apps).length > 0
+        @constructor.manifests = apps
+        callback null, apps
+      else
+        callback new Error "There are no apps in the app storage."

   fetchCompiledApp:(manifest, callback)->
+
     {name} = manifest
     appPath = getAppPath manifest
     indexJsPath = "#{appPath}/index.js"


Client: Sidebar: Updated class references

--- client/app/lib/components/sidebar/index.coffee
+++ client/app/lib/components/sidebar/index.coffee
@@ -1,13 +1,15 @@
-kd                            = require 'kd'
-React                         = require 'kd-react'
-ActivityFlux                  = require 'activity/flux'
-EnvironmentFlux               = require 'app/flux/environment'
-KDReactorMixin                = require 'app/flux/base/reactormixin'
-SidebarChannelsSection        = require 'app/components/sidebarchannelssection'
-SidebarMessagesSection        = require 'app/components/sidebarmessagessection'
-SidebarStackSection           = require 'app/components/sidebarstacksection'
-SidebarSharedMachinesSection  = require 'app/components/sidebarsharedmachinessection'
-Scroller                      = require 'app/components/scroller'
+kd                             = require 'kd'
+React                          = require 'kd-react'
+ReactDOM                       = require 'react-dom'
+ActivityFlux                   = require 'activity/flux'
+EnvironmentFlux                = require 'app/flux/environment'
+Scroller                       = require 'app/components/scroller'
+KDReactorMixin                 = require 'app/flux/base/reactormixin'
+SidebarStackSection            = require 'app/components/sidebarstacksection'
+SidebarChannelsSection         = require 'app/components/sidebarchannelssection'
+SidebarMessagesSection         = require 'app/components/sidebarmessagessection'
+SidebarSharedMachinesSection   = require 'app/components/sidebarsharedmachinessection'
+SharingMachineInvitationWidget = require 'app/components/sidebarmachineslistitem/sharingmachineinvitationwidget'

 module.exports = class Sidebar extends React.Component


StackTemplateList: Pass itself to callback

--- client/app/lib/stacks/stacktemplatelist.coffee
+++ client/app/lib/stacks/stacktemplatelist.coffee
@@ -39,7 +39,7 @@
         'Clone and Open Editor':
           style    : 'solid medium green'
           loader   : yes
-          callback : -> callback { action : 'CloseAndOpen', modal }
+          callback : => callback { action : 'CloneAndOpen', modal, item : this}
         "I know what I'm doing, Open Editor":
           style    : 'solid medium red'
-          callback : -> callback { action : 'OpenEditor', modal }
+          callback : => callback { action : 'OpenEditor', modal, item : this}


Fixed: model was given collection value

Fixed: model was given collection value

--- client/app/views/calendar_popover_event.coffee
+++ client/app/views/calendar_popover_event.coffee
@@ -183,13 +183,19 @@

     selfclose: ->
         # Revert if not just saved with addButton.
-        @model.fetch complete: super
+        if @model.isNew()
+            super()
+        else
+            @model.fetch complete: super

     close: ->
         # we don't reuse @selfclose because both are doing mostly the same thing
         # but are a little bit different.
         # Revert if not just saved with addButton.
-        @model.fetch complete: super
+        if @model.isNew()
+            super()
+        else
+            @model.fetch complete: super

     refresh: ->


test/myteam: change teammmembers role

test/myteam: change teammmembers role

--- client/test/lib/dashboard/myteam.coffee
+++ client/test/lib/dashboard/myteam.coffee
@@ -92,6 +92,51 @@
                     .assert.containsText selector('role', indexOfTargetUser2+1), 'Admin'
                     .end()

+  searchAndChangeRoleOfTeamMates: (browser) ->
+
+    { invitations, index } = utils.getInvitationData()
+
+    index1 = if index is 0 then 1 else index
+    indexOfTargetUser1 = if 1%index1 isnt 0 then 1 else 2
+    indexOfTargetUser2 = if 3%index1 isnt 0 then 3 else 4
+    indexOfTargetUser3 = if 5%index1 isnt 0 then 5 else 6
+
+    invitations[indexOfTargetUser1].accepted = 'Member'
+    invitations[indexOfTargetUser2].accepted = 'Admin'
+    invitations[indexOfTargetUser3].accepted = 'Member'
+    invitations[index].accepted = 'Owner'
+
+    lastPendingInvitationIndex = 0
+    invitations.forEach (invitation, i) ->
+      unless invitation.accepted
+        lastPendingInvitationIndex = i
+
+    section= '.kdcustomscrollview.HomeAppView--scroller.my-team'
+    sectionSelector = '.HomeAppView--section.teammates'
+    filterSelector = "#{sectionSelector} .kdinput.text.hitenterview"
+    listViewSelector = "#{sectionSelector} .ListView .ListView-row"
+    scrollElement = "#{sectionSelector} .ListView"
+
+    user = teamsHelpers.loginTeam browser
+    browser
+      .url myTeamLink
+      .waitForElementVisible section, 2000
+      .waitForElementVisible sectionSelector, 20000
+      .scrollToElement scrollElement
+      .waitForElementVisible selector('role', 1), 20000
+      .click selector('role', 1), ->
+        myteamhelpers.checkTeammates browser, invitations[0], action(1), action(2), selector('role', 1), no, ->
+          browser.waitForElementVisible selector('role', 1), 20000
+          browser.click selector('role', 2), ->
+            myteamhelpers.checkTeammates browser, invitations[1], action(1), action(2), selector('role', 2), no, ->
+              browser.expect.element(selector('role', index+1)).text.to.contain 'Owner'
+              browser.click selector('role', lastPendingInvitationIndex+1), ->
+                myteamhelpers.checkTeammates browser, invitations[lastPendingInvitationIndex], action(1), action(2), selector('role', lastPendingInvitationIndex+1), yes, ->
+                  browser
+                    .waitForElementNotPresent selector('fullname', lastPendingInvitationIndex+1), 20000
+                    .end()
+
+
   sendInvites: (browser) ->

     user = teamsHelpers.loginTeam browser


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/core_object.coffee
+++ test/core_object.coffee
@@ -5,6 +5,26 @@
     test: "jawsome"

   equal o.test, "jawsome"
+
+  o.test = () ->
+    equal calledBefore, true
+    equal calledAfter, false
+
+  calledBefore = false
+  calledAfter = false
+
+  o.extend
+    before:
+      test: () ->
+        calledBefore = true
+    after:
+      test: () ->
+        calledAfter = true
+
+  o.test()
+
+  equal calledBefore, true
+  equal calledAfter, true

 test "Core#attrAccessor", ->
   o = Core


Append entities in entity method

Append entities in entity method

--- source/class/molecule.coffee
+++ source/class/molecule.coffee
@@ -28,8 +28,8 @@
     if @attributes.bind?.entity? and @attributes.bind.atom? and @attributes.bind.create
       do @_bindEntityCreate

-  entity: (entities) ->
-    do @_removeAtomsEntities
+  entity: (entities, append = false) ->
+    do @_removeAtomsEntities unless append
     if @attributes.bind?.entity? and @attributes.bind.atom?
       @_addAtomEntity entity, @attributes.bind for entity in entities


modified the ignores for format

modified the ignores for format

--- test/draft3_test.coffee
+++ test/draft3_test.coffee
@@ -11,7 +11,11 @@
     refRemote: true
     uniqueItems: true
     "optional/zeroTerminatedFloats": true
-    "optional/format": true
+    "optional/format": [
+      "validation of date-time strings"
+      "validation of CSS colors"
+      "validation of host names"
+    ]

 runner.test
   constructor: draft3


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/game_object.coffee
+++ test/game_object.coffee
@@ -70,8 +70,7 @@

 test "[event] destroy", 2, ->
   o = GameObject
-  o.bind "destroy"
-    : ->
+  o.bind "destroy", ->
       ok true, "destroyed event is fired on destroy"
   .destroy()


Removed console output

Removed console output

--- test/node/module.coffee
+++ test/node/module.coffee
@@ -11,8 +11,6 @@
       dep2: './dep2'

     udefine 'nodetest', ['dep1', 'dep2'], (dep1, dep2) ->
-      console.log arguments
-
       expect(dep1).to.be.a('object')
       expect(dep1).to.have.property('number')


Tested mixins

Tested mixins

--- test/object_test.coffee
+++ test/object_test.coffee
@@ -9,7 +9,7 @@
 # This class' object should be recursovely blessed,
 # giving it access to the `@get_now` method.
 class OtherObj
-  do_stuff: -> @get_now 'quux'
+  do_stuff: -> @quux()

 module.exports = redeye_suite

@@ -28,7 +28,10 @@
       all: (keys...) -> @get key for key in keys; @for_reals()

     # Kick off by requesting 'foo' and 'baz'
-    setup: -> @request 'all', 'foo', 'baz'
+    setup: ->
+        @queue.mixin
+          quux: -> @get_now 'quux'
+        @request 'all', 'foo', 'baz'

     # Assert that all the keys get set correctly. `bar` should be a JSON blob.
     # `foo` should be twice it's `value` key. `quux` should be just 216, and


Added tests for sourcemap null when not requested

--- test/parser-test.coffee
+++ test/parser-test.coffee
@@ -12,6 +12,8 @@

       assert.isDefined result
       assert.strictEqual result.ast.name, 'My API'
+
+      assert.isNull result.sourcemap

       done()

@@ -91,6 +93,8 @@
       assert.isNull err

       assert.strictEqual result.ast.resourceGroups.length, 1
+
+      assert.isNull result.sourcemap

       resourceGroup = result.ast.resourceGroups[0]
       assert.strictEqual resourceGroup.name, ''
@@ -199,6 +203,7 @@
       assert err.message.length != 0
       assert err.code != 0
       assert.isDefined err.location
+      assert.isNull result.sourcemap

       done()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/expirable.coffee
+++ src/expirable.coffee
@@ -1,10 +1,11 @@
 Expirable = (I, self) ->
   Object.reverseMerge I,
     duration: -1
+    alpha: 1

   self.bind "update", ->
     if I.fadeOut
-      I.alhpa
+      I.alpha

     if I.duration != -1 && I.age >= I.duration
       I.active = false


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/expirable.coffee
+++ src/expirable.coffee
@@ -7,9 +7,9 @@
   startingAlpha = I.alpha

   self.bind "afterUpdate", ->
+    log I.age
+    log I.duration
     if I.fadeOut
-      log I.age
-      log I.duration
       I.alpha = (startingAlpha * (1 - (I.age / I.duration))).clamp(0, 1)

     if I.duration != -1 && I.age >= I.duration


Attach an identifier to requests

Attach an identifier to requests

--- src/components/HTTP/Server.coffee
+++ src/components/HTTP/Server.coffee
@@ -1,5 +1,6 @@
 noflo = require "noflo"
 http = require "connect"
+uuid = require "node-uuid"

 class Server extends noflo.Component
     description: "This component receives a port and host, and initializes a HTTP server for that combination. It sends out a request/response pair for each HTTP request it receives"
@@ -20,9 +21,11 @@
             @server.listen @serverPort

     sendRequest: (req, res) =>
+        req.id = do uuid
         @outPorts.request.send
             req: req
             res: res
+        , req.id
         @outPorts.request.disconnect()

 exports.getComponent = ->


test webhook

test webhook

--- src/components/LandingPage.coffee
+++ src/components/LandingPage.coffee
@@ -116,7 +116,7 @@

               when V.DONATE
                 div null,
-                  h2 null, "Hier kannst du doppelte Wirkung zeigen."
+                  h2 null, "Hier kannst Du doppelte Wirkung zeigen."
                   p null,
                     """
                     Unsere Crowdfunding Kampagne auf www.betterplace.org


minor

minor

--- coffee/hyperbolic_tessellation_test_app.coffee
+++ coffee/hyperbolic_tessellation_test_app.coffee
@@ -316,9 +316,9 @@
     t = Date.now()
     if t - lastTime > dtMax
       if drawEverything()
-        tEnd = Date.now()
+        tDraw = Date.now() - t
         #adaptively update FPS
-        dtMax = dtMax*0.9 + (tEnd - t)*2*0.1
+        dtMax = dtMax*0.9 + tDraw*2*0.1
         dirty = false
       lastTime = t
   requestAnimationFrame redrawLoop


add specs for single quote to double single quote change

--- spec/ideal-utils-spec.coffee
+++ spec/ideal-utils-spec.coffee
@@ -24,6 +24,16 @@
         editor.selectAll()
         new_text = editor.getSelectedText()
         expect(editor.getText()).toBe(".Add(' Test Text ');")
+
+    it "wraps selected text with .Add(''); and replaces all single quotes with double single quotes", ->
+      waitsForPromise ->
+        return activationPromise
+
+      runs ->
+        editor.insertText "Test ' Conversion"
+        editor.selectAll()
+        atom.commands.dispatch(workspaceElement, 'ideal-utils:wrapSQLDotAdd')
+        expect(editor.getText()).toBe(".Add(' Test '' Conversion ');")

     it "wraps selected text with .Add('') spanning multi lines with +", ->
       waitsForPromise ->
@@ -57,6 +67,25 @@
         #console.log new_text
         expect(editor.getText()).toBe(".Add(' Test ' +\n' Multiline ');\nText")

+    it "wraps selected text with .Add('') spanning multiple lines with + but does not go beyond the selection and replaces all single quotes with double single quotes", ->
+      waitsForPromise ->
+          return activationPromise
+
+      runs ->
+        editor.insertText "Test\nMultiline '\nText"
+        editor.setCursorBufferPosition([0,0])
+        editor.selectDown(1)
+        editor.selectToEndOfLine()
+        #old_text = editor.getText()
+        #console.log old_text
+        atom.commands.dispatch(workspaceElement, 'ideal-utils:wrapSQLDotAdd')
+        editor.selectAll()
+        #expected_text = "expected:\n.Add(' Test ' +\n' Multiline ');\nText"
+        #console.log expected_text
+        #new_text = "new\n" + editor.getSelectedText()
+        #console.log new_text
+        expect(editor.getText()).toBe(".Add(' Test ' +\n' Multiline '' ');\nText")
+
   describe 'when the ideal-utils:wrapSQLForUpdate event is triggered', ->
     it "wraps selected text with Add('')", ->
       waitsForPromise ->
@@ -70,6 +99,16 @@
         editor.selectAll()
         new_text = editor.getSelectedText()
         expect(editor.getText()).toBe("Add(' Test Text ');")
+
+    it "wraps selected text with Add(''); and replaces all single quotes with double single quotes", ->
+      waitsForPromise ->
+        return activationPromise
+
+      runs ->
+        editor.insertText "Test ' Conversion"
+        editor.selectAll()
+        atom.commands.dispatch(workspaceElement, 'ideal-utils:wrapSQLForUpdate')
+        expect(editor.getText()).toBe("Add(' Test '' Conversion ');")

     it "wraps selected text with Add('') spanning multi lines with +", ->
       waitsForPromise ->
@@ -102,3 +141,22 @@
         new_text = editor.getSelectedText()
         console.log new_text
         expect(editor.getText()).toBe("Add(' Test ' +\n' Multiline ');\nText")
+
+    it "wraps selected text with Add('') spanning multiple lines with + but does not go beyond the selection and replaces all single quotes with double single quotes", ->
+      waitsForPromise ->
+          return activationPromise
+
+      runs ->
+        editor.insertText "Test\nMultiline '\nText"
+        editor.setCursorBufferPosition([0,0])
+        editor.selectDown(1)
+        editor.selectToEndOfLine()
+        #old_text = editor.getText()
+        #console.log old_text
+        atom.commands.dispatch(workspaceElement, 'ideal-utils:wrapSQLForUpdate')
+        editor.selectAll()
+        #expected_text = "expected:\n.Add(' Test ' +\n' Multiline ');\nText"
+        #console.log expected_text
+        #new_text = "new\n" + editor.getSelectedText()
+        #console.log new_text
+        expect(editor.getText()).toBe("Add(' Test ' +\n' Multiline '' ');\nText")


Committing

Committing

--- coffee/codesearch.coffee
+++ coffee/codesearch.coffee
@@ -28,7 +28,7 @@
             return

         populate = (data) ->
-            display_url = jQuery("display_url").text()
+            display_url = jQuery("display-url").text()
             jQuery("ul").empty()
             for filename in data
                 li = "
#{filename}
"


Fix broken jQuery plugin

Fix broken jQuery plugin

--- coffee/datepicker.coffee
+++ coffee/datepicker.coffee
@@ -126,7 +126,7 @@
 #
 #   $(selector).datepicker()
 $.fn.datepicker = ->
-  datepicker = Datepicker.find this
+  datepicker = this.data 'datepicker'

   unless datepicker?
     this.data 'datepicker', (datepicker = new Datepicker(this))


errors: removed URLError

errors: removed URLError

--- coffee/src/errors.coffee
+++ coffee/src/errors.coffee
@@ -27,9 +27,6 @@
 ShellRegistryError = (shell, error) ->
   throw new Error "Error registering shell #{shell}. #{error ? ''}"

-URLError = ->
-  ParameterError '"url" property or function'
-
 acorn.errors.APIError = APIError
 acorn.errors.AssertionFailed = AssertionFailed
 acorn.errors.MissingParameterError = MissingParameterError
@@ -37,4 +34,3 @@
 acorn.errors.NotSupportedError = NotSupportedError
 acorn.errors.TypeError = TypeError
 acorn.errors.UnregisteredShellError = UnregisteredShellError
-acorn.errors.URLError = URLError


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/game_over.coffee
+++ src/game_over.coffee
@@ -1,5 +1,5 @@
 ###*
-The Game Over class sets up a simple game state
+The Game Over class sets up a simple game state with re

 @name update
 @methodOf TitleScreen#


Show stack traces

Show stack traces

--- test/spec_helper.coffee
+++ test/spec_helper.coffee
@@ -4,6 +4,7 @@

 chai = require 'chai'
 chai.should()
+chai.Assertion.includeStack = true
 root.expect = chai.expect
 sinon = require('sinon')


:memo: fix english of to on

:memo: fix english of to on

--- spec/text-buffer-spec.coffee
+++ spec/text-buffer-spec.coffee
@@ -697,7 +697,7 @@
       expect(getFirstMarker(markerLayers[1])).toBe(marker1)
       expect(getFirstMarker(markerLayers[2])).toBe(marker2)

-    describe "role based snapshotting of createCheckpoint, groupChangesSinceCheckpoint", ->
+    describe "role based snapshotting on createCheckpoint, groupChangesSinceCheckpoint", ->
       it "skip snapshotting of other marker layers with the same role of activeMarkerLayer", ->
         eventHandler = jasmine.createSpy('eventHandler')


Changed the angel logigng to use info instead of log, to more easily differentiate.

--- app/lib/Angel.coffee
+++ app/lib/Angel.coffee
@@ -34,7 +34,7 @@

   # say: debugging stuff, usually off; log: important performance indicators, keep on
   say: (args...) -> #@log args...
-  log: (args...) -> console.log "|#{@shared.godNick}'s #{@nick}|", args...
+  log: (args...) -> console.info "|#{@shared.godNick}'s #{@nick}|", args...

   testWorker: =>
     return if @destroyed


Simplify serialization tests

Simplify serialization tests

--- spec/text-buffer-spec.coffee
+++ spec/text-buffer-spec.coffee
@@ -846,32 +846,32 @@
       bufferB = TextBuffer.deserialize(state)

       expect(bufferB.getText()).toBe "hello there\ngood friend\r\nhow are you doing??"
-      expectSameMarkers(bufferB.getMarkerLayer(layerA.id), bufferA.getMarkerLayer(layerA.id))
+      expectSameMarkers(bufferB.getMarkerLayer(layerA.id), layerA)

       bufferA.redo()
       bufferB.redo()
       expect(bufferB.getText()).toBe "hellooo there\ngood friend\r\nhow are you doing??"
-      expectSameMarkers(bufferB.getMarkerLayer(layerA.id), bufferA.getMarkerLayer(layerA.id))
+      expectSameMarkers(bufferB.getMarkerLayer(layerA.id), layerA)

       bufferA.undo()
       bufferB.undo()
       expect(bufferB.getText()).toBe "hello there\ngood friend\r\nhow are you doing??"
-      expectSameMarkers(bufferB.getMarkerLayer(layerA.id), bufferA.getMarkerLayer(layerA.id))
+      expectSameMarkers(bufferB.getMarkerLayer(layerA.id), layerA)

       bufferA.undo()
       bufferB.undo()
       expect(bufferB.getText()).toBe "hello there\nfriend\r\nhow are you doing?"
-      expectSameMarkers(bufferB.getMarkerLayer(layerA.id), bufferA.getMarkerLayer(layerA.id))
+      expectSameMarkers(bufferB.getMarkerLayer(layerA.id), layerA)

       bufferA.undo()
       bufferB.undo()
       expect(bufferB.getText()).toBe "hello there\nworld\r\nhow are you doing?"
-      expectSameMarkers(bufferB.getMarkerLayer(layerA.id), bufferA.getMarkerLayer(layerA.id))
+      expectSameMarkers(bufferB.getMarkerLayer(layerA.id), layerA)

       bufferA.undo()
       bufferB.undo()
       expect(bufferB.getText()).toBe "hello\nworld\r\nhow are you doing?"
-      expectSameMarkers(bufferB.getMarkerLayer(layerA.id), bufferA.getMarkerLayer(layerA.id))
+      expectSameMarkers(bufferB.getMarkerLayer(layerA.id), layerA)

       # Accounts for deserialized markers when selecting the next marker's id
       marker3A = layerA.markRange([[0, 1], [2, 3]])
@@ -918,13 +918,11 @@
       bufferA = new TextBuffer(text: "hello\nworld\r\nhow are you doing?")
       markerLayerA = bufferA.getDefaultMarkerLayer()
       marker1A = bufferA.markRange([[0, 1], [1, 2]], foo: 1)
-      marker2A = bufferA.markPosition([2, 2], bar: 2)

       bufferB = TextBuffer.deserialize(bufferA.serialize())
       markerLayerB = bufferB.getDefaultMarkerLayer()
       expect(markerLayerA.id).not.toBe(markerLayerB.id)
       expect(bufferB.getMarker(marker1A.id)).toBeUndefined()
-      expect(bufferB.getMarker(marker2A.id)).toBeUndefined()

     it "serializes / deserializes the buffer's unique identifier", ->
       bufferA = new TextBuffer()


+ more tests to subkey.

+ more tests to subkey.

--- test/subkey-test.coffee
+++ test/subkey-test.coffee
@@ -450,6 +450,18 @@
       result.should.be.equal value
       result = @subkey.getSync key.slice(1), separator:'.'
       result.should.be.equal value
+    it "should get attribute with path .getSync", ->
+      key = ".myput"+Math.random()
+      path = "mypath"
+      value = Math.random()
+      @subkey.putSync key, value, path:path
+      encodedKey = getEncodedKey @db, key, path:path, @subkey
+      result = @db.data[encodedKey]
+      result.should.be.equal getEncodedValue @db, value
+      result = @subkey.getSync key, path: path
+      result.should.be.equal value
+      result = @subkey.getSync key.slice(1), separator:'.', path:path
+      result.should.be.equal value
     it "should get attribute via separator .getSync", ->
       key = "myput"+Math.random()
       value = Math.random()
@@ -472,6 +484,21 @@
         should.not.exist err
         result.should.be.equal value
         @subkey.getAsync key.slice(1), separator:'.', (err, result)=>
+          should.not.exist err
+          result.should.be.equal value
+          done()
+    it "should get attribute with path .getAsync", (done)->
+      key = ".myput"+Math.random()
+      value = Math.random()
+      path = "mypath"
+      @subkey.putSync key, value, path:path
+      encodedKey = getEncodedKey @db, key, path:path, @subkey
+      result = @db.data[encodedKey]
+      result.should.be.equal getEncodedValue @db, value
+      @subkey.getAsync key, path:path, (err, result)=>
+        should.not.exist err
+        result.should.be.equal value
+        @subkey.getAsync key.slice(1), separator:'.', path:path, (err, result)=>
           should.not.exist err
           result.should.be.equal value
           done()
@@ -529,6 +556,33 @@
         should.not.exist err
         result.should.be.equal value
         done()
+    it "should get attribute with path .get sync", ->
+      key = ".myput"+Math.random()
+      path = "mypath"
+      value = Math.random()
+      @subkey.putSync key, value, path:path
+      encodedKey = getEncodedKey @db, key, path:path, @subkey
+      result = @db.data[encodedKey]
+      result.should.be.equal getEncodedValue @db, value
+      result = @subkey.get key, path: path
+      result.should.be.equal value
+      result = @subkey.get key.slice(1), separator:'.', path:path
+      result.should.be.equal value
+    it "should get attribute with path .get async", (done)->
+      key = ".myput"+Math.random()
+      value = Math.random()
+      path = "mypath"
+      @subkey.putSync key, value, path:path
+      encodedKey = getEncodedKey @db, key, path:path, @subkey
+      result = @db.data[encodedKey]
+      result.should.be.equal getEncodedValue @db, value
+      @subkey.get key, path:path, (err, result)=>
+        should.not.exist err
+        result.should.be.equal value
+        @subkey.get key.slice(1), separator:'.', path:path, (err, result)=>
+          should.not.exist err
+          result.should.be.equal value
+          done()
     it "should get itself .get", ->
       value = Math.random()
       @subkey.putSync value


Update cs.coffee

Update cs.coffee

Finally done all translations :)

--- app/locale/cs.coffee
+++ app/locale/cs.coffee
@@ -94,15 +94,15 @@
     campaign_classic_algorithms: "Klasické algoritmy"
     campaign_classic_algorithms_description: "... ve kterých se naučíte nejoblíbenější algoritmy v IT."

-#  share_progress_modal:
-#    blurb: "You’re making great progress!  Tell someone how much you've learned with CodeCombat."
-#    email_invalid: "Email address invalid."
-#    form_blurb: "Enter their email below and we’ll show them!"
-#    form_label: "Email Address"
-#    placeholder: "email address"
-#    title: "Excellent Work, Apprentice"
-#    tell_friend: "Tell your Friend"
-#    tell_parent: "Tell your Parent"
+  share_progress_modal:
+    blurb: "Děláš velké pokroky!  Řekni někomu, co jsi se už naučil s CodeCombat."
+    email_invalid: "Neplatná e-mailová adresa."
+    form_blurb: "Vložte jejich e-mail níže a my už je kontaktujeme!"
+    form_label: "E-mailová adresa"
+    placeholder: "e-mailová adresa"
+    title: "Výborná práce, učni"
+    tell_friend: "Řekni svým přátelům"
+    tell_parent: "Řekni svým rodičům"

   login:
     sign_up: "Vytvořit účet"
@@ -141,8 +141,8 @@
     books: "Spisy"

   common:
-#    back: "Back" # When used as an action verb, like "Navigate backward"
-#    continue: "Continue" # When used as an action verb, like "Continue forward"
+    back: "Zpět" # When used as an action verb, like "Navigate backward"
+    continue: "Pokračovat" # When used as an action verb, like "Continue forward"
     loading: "Načítání..."
     saving: "Ukládání..."
     sending: "Odesílání..."
@@ -335,9 +335,9 @@
     tip_source_code: "Chci změnit svět, ale nechtějí mě dát k němu zdrojový kód."
     tip_javascript_java: "Porovnávat Javu a JavaScript je stejné, jako porovnávat auto a autoritu. - Chris Heilmann"
     tip_move_forward: "Ať už děláš cokoliv, vždy jdi dopředu. - Martin Luther King Jr."
-#    tip_google: "Have a problem you can't solve? Google it!"
-#    tip_adding_evil: "Adding a pinch of evil."
-#    tip_miss_lunch: "Anyone who has lost track of time when using a computer knows the propensity to dream, the urge to make dreams come true and the tendency to miss lunch. - Tim Berners-Lee"
+    tip_google: "Máš problém, který nemůžeš vyřešit? Vygoogluj to!"
+    tip_adding_evil: "Přidávání špetky zla."
+    tip_miss_lunch: "Každý, kdo ztratil pojem o čase při používání počítače má tendenci ke snění, chce si sny splnit a má tendeci vynechat oběd. - Tim Berners-Lee"

   game_menu:
     inventory_tab: "Inventář"
@@ -535,42 +535,42 @@
   teachers:
     title: "CodeCombat pro učitele"
     preparation_title: "Příprava"
-#    preparation_1: "CodeCombat is free to play for the core level progression and does not require students to sign up. We encourage teachers to"
-#    preparation_play_campaign: "play through the campaign"
-#    preparation_2: "to try it out, but the only thing you absolutely need to do to be ready is ensure students have access to a computer."
-#    preparation_3: "It is not necessary for teachers to be comfortable with computer science concepts for students to have fun learning with CodeCombat."
+    preparation_1: "CodeCombat je \"free-to-play\" pro hlavní postu hrou a nevyžaduje studenty se registrovat. Doporučujeme učiteům"
+    preparation_play_campaign: "zahrát si celou kampaň,"
+    preparation_2: "aby si ji vyzkoušeli, ale jediné, co potřebujete, abyste byli připraveni je zajistit studentům přístup k počítačům."
+    preparation_3: "Není potřeba, aby úplně rozuměli počítačům k tomu, aby si jejich studetni užili zábavu na CodeCombatu."
     violent_title: "Je to násilné?"
-#    violent_1: "We get this from teachers a lot due to our name. Although CodeCombat does contain cartoon violence, there is nothing graphic in either the visuals or language."
-#    violent_2: "If you are comfortable having your students play Angry Birds, you will be comfortable with CodeCombat."
+    violent_1: "Tohle slýcháváme od učitelů často kvůli našemu jménu. Přestože CodeCombat neobsahuje žádnou karikaturu násili, není zde nic grafického ani jazykového co má společného s násilím."
+    violent_2: "Pokud vám nevadí, že studenti hrají Angry Birds, nebude vám vadit ani CodeCombat."
     for_girls_title: "Je to pro holky?"
-#    for_girls_1: "There are three game modes in CodeCombat: building, puzzles, and combat. We have intentionally designed each to appeal to both boys and girls and think that the building and puzzle levels especially differentiate the game from violent triple A titles that repel female players."
-#    what_cover_title: "What do we cover?"
-#    what_cover_1: "There are 20 levels in the Hour of Code tutorial that teach and reinforce 6 specific computer science concepts:"
+    for_girls_1: "V CodeCombatu jsou tři herní módy: stavění, hádanky a souboje. Záměrně jsme každý nadesignovali, aby seděl jak klukům tak holkám a myslíme si, že stavící a hádankové úrovně nás odlišují od násilných stříleček, které odpuzují hráčky."
+    what_cover_title: "Co pokrýváme?"
+    what_cover_1: "Je zde 20 úrovní v Hour of Code tutoriálu, které učí a posilují 6 specifických konceptů počítačového programování:"
     what_cover_notation_1: "Formální zápis"
-#    what_cover_notation_2: "- builds an understanding of the importance of syntax in programming."
+    what_cover_notation_2: "- studenti se naučí důležitost syntaxe v programování."
     what_cover_methods_1: "Volání metod"
-#    what_cover_methods_2: "- familiarizes students with the syntax of object-oriented method calls."
+    what_cover_methods_2: "- seznámí studenty se syntaxí volání metod v objektově orientovaných jazycích."
     what_cover_parameters_1: "Parametry"
-#    what_cover_parameters_2: "- trains how to pass parameters to functions."
+    what_cover_parameters_2: "- trénuje, jak předávat paramtery metodám."
     what_cover_strings_1: "Stringy"
-#    what_cover_strings_2: "- teaches students about string notation and passing strings as parameters."
+    what_cover_strings_2: "- účí studenty o jmenování stringů a jejich předávání jako parametry."
     what_cover_loops_1: "Cykly"
-#    what_cover_loops_2: "- develops the abstraction of designing short programs with loops."
+    what_cover_loops_2: "- vyvíjí abstrakci designování jednoduchých programů s cykly."
     what_cover_variables_1: "Proměnné"
-#    what_cover_variables_2: "- adds the skill of referencing values that change over time."
-#    what_cover_2: "Students may continue past level 20, depending on their speed and interest, to learn two additional concepts in later levels:"
+    what_cover_variables_2: "- přidá dovednost odkazování se na hodnoty, které se časem mění."
+    what_cover_2: "Studenti mohou po 20. úrovni pokračovat dále, podle jejich rychlosti a zájmu se mohou naučit dva další koncepty v pozdějších úrovních:"
     what_cover_logic_1: "Podmínky"
-#    what_cover_logic_2: "- when and how to use if/else to control in-game outcomes."
+    what_cover_logic_2: "- kdy a jak použít if/else pro ovládání herních výsledků."
     what_cover_input_1: "Pracování s hráčovými vstupy"
-#    what_cover_input_2: "- responding to input events to create a user interface."
+    what_cover_input_2: "- reagování na vstupní události pro vytvoření uživatelského rozhraní."
     sys_requirements_title: "Systemové požadavky"
-#    sys_requirements_1: "Because CodeCombat is a game, it is more intensive for computers to run smoothly than video or written tutorials. We have optimized it to run quickly on all modern browsers and on older machines so that everyone can play. That said, here are our suggestions for getting the most out of your Hour of Code experience:"
-#    sys_requirements_2: "Use newer versions of Chrome or Firefox."
-#    sys_requirements_3: "Although CodeCombat will work on browsers as old as IE9, the performance is not as good. Chrome is best."
-#    sys_requirements_4: "Use newer computers."
-#    sys_requirements_5: "Older computers, Chromebooks, and netbooks tend to have very few system resources, which makes for a less enjoyable experience. At least 2GB of RAM is required."
-#    sys_requirements_6: "Allow players to wear headphones/earbuds to hear the audio."
-#    sys_requirements_7: "We help players learn through voiceover and sound effects, which will make classrooms noisy and distracting."
+    sys_requirements_1: "Protože CodeCombat je hra, pro počítače je to více náročnější než přehrávání videa. Optimalizovali jsme CodeCombat, aby běžel rychle na všech moderních prohlížečích a dokonce i na starších mašinách, takže každý může hrát. Takže tady jsou naše návrhy, jak si co nejvíce užít váš Hour of Code zážitek:"
+    sys_requirements_2: "Používejte nejnovější verzi Chromu nebo Firefoxu."
+    sys_requirements_3: "Přestože CodeCombat pojede na prohlížečích, které jsou stejně staré jako IE9, výkon není zas tak dobrý. Chrome is best."
+    sys_requirements_4: "Používejte nové počítače."
+    sys_requirements_5: "Starší počítače, Chromebooky a netbooky nemají takový výkon, z čehož plyne horší zážitek ze hraní. Minimálně je požadováno 2GB RAM."
+    sys_requirements_6: "Dovolte hráčům na sobě mít sluchátka, aby slyšeli zvuk ze hry."
+    sys_requirements_7: "Pomáháme hráčům se učit i pomocí zvukových efektů, což může udělat ve tříd hluk."

   versions:
     save_version_title: "Uložit novou verzi"
@@ -1013,7 +1013,7 @@
     play_counts: "Počet hraní"
     feedback: "Zpětná vazba"
     payment_info: "Info o platbě"
-#    campaigns: "Campaigns"
+    campaigns: "Kampaně"

   delta:
     added: "Přidáno"


Use contain instead of contains

Use contain instead of contains

--- spec/text-buffer-spec.coffee
+++ spec/text-buffer-spec.coffee
@@ -19,7 +19,7 @@
       expect(buffer.lineForRow(0)).toBe ''
       expect(buffer.lineEndingForRow(0)).toBe ''

-    describe "when the last line does not contains a newline", ->
+    describe "when the last line does not contain a newline", ->
       it "can be constructed with initial text", ->
         text = "hello\nworld\r\nhow are you doing?\rlast"
         buffer = new TextBuffer(text)


Fix subscribe modal typo

Fix subscribe modal typo

--- app/locale/en.coffee
+++ app/locale/en.coffee
@@ -665,7 +665,7 @@
     feature_gems: "Receive __gems__ gems per month"
     feature_heroes: "Unlock exclusive heroes"
     feature_games: "Make games for your friends"
-    feature_websites: "Build websites in apps"
+    feature_websites: "Build websites and apps"
     feature_items: "Equip more powerful items"
     month_price: "$__price__/mo"
     lifetime: "Lifetime Subscription"


add Poll french translation

add Poll french translation

--- app/locale/fr.coffee
+++ app/locale/fr.coffee
@@ -744,7 +744,7 @@
     thang_title: "Éditeur Thang"
     level_title: "Éditeur de niveau"
     achievement_title: "Éditeur de succès"
-#    poll_title: "Poll Editor"
+    poll_title: "Éditeur de sondage"
     back: "Retour"
     revert: "Annuler"
     revert_models: "Annuler les modèles"
@@ -805,8 +805,8 @@
     new_level_title_login: "Identifiez-vous pour créer un nouveau niveau"
     new_achievement_title: "Créer un nouveau succès"
     new_achievement_title_login: "Connectez vous pour créer un nouveau succès"
-#    new_poll_title: "Create a New Poll"
-#    new_poll_title_login: "Log In to Create a New Poll"
+    new_poll_title: "Créer un nouveau sondage"
+    new_poll_title_login: "Connectez vous pour créer un nouveau sondage"
     article_search_title: "Rechercher dans les articles"
     thang_search_title: "Rechercher dans les types de Thang"
     level_search_title: "Rechercher dans les niveaux"
@@ -826,7 +826,7 @@
     edit_article_title: "Éditer l'article"

 #  polls:
-#    priority: "Priority"
+#    priority: "Priorité"

   contribute:
     page_title: "Contribution"


Added more translations

Added more translations

--- app/locale/it.coffee
+++ app/locale/it.coffee
@@ -56,15 +56,15 @@
     owned: "In tuo possesso" # For items you own
     locked: "Bloccato"
     available: "Disponibile"
-#    skills_granted: "Skills Granted" # Property documentation details
+    skills_granted: "Abilità Fornite" # Property documentation details
     heroes: "Eroi" # Tooltip on hero shop button from /play
-#    achievements: "Achievements" # Tooltip on achievement list button from /play
+    achievements: "Imprese" # Tooltip on achievement list button from /play
     account: "Account" # Tooltip on account button from /play
     settings: "Impostazioni" # Tooltip on settings button from /play
     next: "Procedi" # Go from choose hero to choose inventory before playing a level
     change_hero: "Cambia Eroe" # Go back from choose inventory to choose hero
 #    choose_inventory: "Equip Items"
-#    buy_gems: "Buy Gems"
+    buy_gems: "Compra Gemme"
     older_campaigns: "Campagne precedenti"
     anonymous: "Giocatore Anonimo"
     level_difficulty: "Difficoltà: "
@@ -110,7 +110,7 @@
     sign_up: "Registrati"
     log_in: "Accedi con la password"
     social_signup: "Oppure puoi registrarti con Facebook o Google+:"
-#    required: "You need to log in before you can go that way."
+    required: "Effettua l'accesso per proseguire."

   recover:
     recover_account_title: "Recupera account"


Update nl.coffee

Update nl.coffee

Some new translations.

--- app/locale/nl.coffee
+++ app/locale/nl.coffee
@@ -611,8 +611,8 @@
     recovered: "Edelstenen aankoop hersteld. Ververs de pagina alstublieft."
     price: "x{{gems}} / maand"
 #    buy_premium: "Buy Premium"
-#    purchase: "Purchase"
-#    purchased: "Purchased"
+    purchase: "Koop"
+    purchased: "Gekocht"

   subscribe:
     subscribe_modal_title: "CodeCombat Premium"
@@ -687,34 +687,34 @@
     support_part3: "als je vragen hebt."

 #  announcement:
-#    cuddly_companions: "Cuddly Companions!"
+    cuddly_companions: "Knuffelbare Kameraden!"
 #    kindling_name: "Kindling Elemental"
 #    kindling_description: "Kindling Elementals just want to keep you warm at night. And during the day. All the time, really."
-#    griffin_name: "Baby Griffin"
+    griffin_name: "Baby Griffioen"
 #    griffin_description: "Griffins are half eagle, half lion, all adorable."
-#    raven_name: "Raven"
+    raven_name: "Raaf"
 #    raven_description: "Ravens are excellent at gathering shiny bottles full of health for you."
 #    mimic_name: "Mimic"
 #    mimic_description: "Mimics can pick up coins for you. Move them on top of coins to increase your gold supply."
 #    cougar_name: "Cougar"
 #    cougar_description: "Cougars like to earn a PhD by Purring Happily Daily."
-#    fox_name: "Blue Fox"
+    fox_name: "Blauwe Vos"
 #    fox_description: "Blue foxes are very clever and love digging in the dirt and snow!"
 #    pugicorn_name: "Pugicorn"
 #    pugicorn_description: "Pugicorns are some of the rarest creatures and cast cast spells!"
-#    wolf_name: "Wolf Pup"
+    wolf_name: "Wolvenpup"
 #    wolf_description: "Wolf pups excel in hunting, gathering, and playing a mean game of hide-and-seek!"
 #    ball_name: "Red Squeaky Ball"
 #    ball_description: "ball.squeak()"
-#    collect_pets: "Collect pets for your heroes!"
-#    each_pet: "Each pet has a unique helper ability!"
-#    upgrade_to_premium: "Become a {{subscriber}} to equip pets."
-#    play_second_kithmaze: "Play {{the_second_kithmaze}} to unlock the Wolf Pup!"
-#    the_second_kithmaze: "The Second Kithmaze"
-#    keep_playing: "Keep playing to discover the first pet!"
-#    coming_soon: "Coming soon"
-#    now_available: "Now available for subscribers!"
-#    subscriber: "subscriber"
+    collect_pets: "Verzamel huisdieren voor jouw helden!"
+    each_pet: "Elk huisdier heeft een unieke vaardigheid om jou te helpen!"
+    upgrade_to_premium: "Wordt {{subscriber}} om huisdieren een uitrusting te kunnen geven."
+    play_second_kithmaze: "Speel {{the_second_kithmaze}} om de wolvenpup vrij te spelen!"
+    the_second_kithmaze: "Het Tweede Kithof"
+    keep_playing: "KBlijf spelen om je eerste huisdier te vinden!"
+    coming_soon: "Binnenkort beschikbaar"
+    now_available: "Nu beschikbaar voor abonnees!"
+    subscriber: "abonnee"

   premium_features:
     get_premium: "Neem
CodeCombat
Premium" # Fit into the banner on the /features page
@@ -1471,9 +1471,9 @@
     cs4_curriculum_desc: "Cursus 4: leertraject, lesplannen, activiteiten en meer."
     cs1_pairprogramming: "Programmeer-activiteit voor duo's."
     cs1_pairprogramming_desc: "Laat leerlingen kennismaken met een activiteit voor duo's, wat hen helpt betere luisteraars te worden en effectiver te communiceren."
-#    gd1: "Game Development 1"
-#    gd1_guide: "Game Development 1 - Project Guide"
-#    gd1_guide_desc: "Use this to guide your students as they create their first shareable game project in 5 days."
+    gd1: "Game Ontwikkeling 1"
+    gd1_guide: "Game Ontwikkeling 1 - Handleiding"
+    gd1_guide_desc: "Use this to guide your students as they create their first shareable game project in 5 days."
     wd1: "Web Ontwikkeling 1"
     wd1_headlines: "Titels & Koppen Activiteit"
     wd1_headlines_example: "Bekijk voorbeeld oplossing"
@@ -1533,13 +1533,13 @@
     hoc_additional_contact: "Neem contact op"
     revoke_confirm: "Weet je zeker dat je de licentie van {{student_name}} wilt intrekken? De licentie kan dan weer gebruikt worden voor een andere leerling."
     revoking: "Intrekken..."
-#    unused_licenses: "You have unused Licenses that allow you to assign students paid courses when they're ready to learn more!"
-#    remember_new_courses: "Remember to assign new courses!"
-#    more_info: "More Info"
-#    how_to_assign_courses: "How to Assign Courses"
-#    select_students: "Select Students"
-#    select_instructions: "Click the checkbox next to each student you want to assign courses to."
-#    choose_course: "Choose Course"
+    unused_licenses: "Je hebt nog ongebruikte licenties die je kunt gebruiken om leerlingen toe te wijzen aan nieuwe lesmodules."
+    remember_new_courses: "Vergeet niet om nieuwe lesmodules toe te wijzen!"
+    more_info: "Meer Informatie"
+    how_to_assign_courses: "Hoe wijs je lesmodules toe"
+    select_students: "Selecteer leerlingen"
+    select_instructions: "Klik op het vakje naast iedere leerling aan wie je de lesmodule wil toewijzen."
+    choose_course: "Selecteer lesmodule"
 #    choose_instructions: "Select the course from the dropdown menu you’d like to assign, then click “Assign to Selected Students.”"
 #    push_projects: "We recommend assigning Web Development 1 or Game Development 1 after students have finished Introduction to Computer Science! See our {{resource_hub}} for more details on those courses."


Polish translation

Polish translation

--- app/locale/pl.coffee
+++ app/locale/pl.coffee
@@ -95,7 +95,7 @@
   home:
     slogan: "Naucz się programowania grając"
     no_ie: "CodeCombat nie działa na Internet Explorer 9 lub starszym. Przepraszamy!"
-    no_mobile: "CodeCombat nie został zaprojektowany dla użądzeń przenośnych więc może nie działać!"
+    no_mobile: "CodeCombat nie został zaprojektowany dla urządzeń przenośnych więc może nie działać!"
     play: "Graj"
     old_browser: "Wygląda na to, że twoja przeglądarka jest zbyt stara, by obsłużyć CodeCombat. Wybacz!"
     old_browser_suffix: "Możesz spróbowac mimo tego, ale prawdopodobnie gra nie będzie działać."
@@ -104,16 +104,16 @@
 #    multiplayer: "Multiplayer"
     for_developers: "Dla developerów"
     javascript_blurb: "Język internetu. Świetny do pisania stron, aplikacji internetowych, gier HTML5 i serwerów."
-#    python_blurb: "Simple yet powerful, Python is a great general purpose programming language."
-#    coffeescript_blurb: "Nicer JavaScript syntax."
-#    clojure_blurb: "A modern Lisp."
-#    lua_blurb: "Game scripting language."
-#    io_blurb: "Simple but obscure."
+    python_blurb: "Prosty ale potężny, Python jest świetnym językiem programowania ogólnego zastosowania."
+    coffeescript_blurb: "Przyjemniejsza składnia JavaScript."
+    clojure_blurb: "Nowoczesny Lisp."
+    lua_blurb: "Język skryptowy gier."
+    io_blurb: "Prosty lecz nieznany."

   play:
     choose_your_level: "Wybierz poziom"
-    adventurer_prefix: "Możesz wybrać jeden z poniższych poziomów lub omówić to na "
-    adventurer_forum: "forum podróżników"
+    adventurer_prefix: "Możesz wybrać jeden z poniższych poziomów lub omówić poziom na "
+    adventurer_forum: "forum Podróżników"
     adventurer_suffix: "."
     campaign_beginner: "Kampania dla początkujących"
     campaign_beginner_description: "... w której nauczysz się magii programowania"
@@ -122,14 +122,14 @@
     campaign_multiplayer: "Pola walki dla wielu graczy"
     campaign_multiplayer_description: "... w których konkurujesz z innymi graczami."
     campaign_player_created: "Stworzone przez graczy"
-    campaign_player_created_description: "... w których walczysz przeciwko dziełom Czarodziejów Rękodzielnictwa"
-#    campaign_classic_algorithms: "Classic Algorithms"
-#    campaign_classic_algorithms_description: "... in which you learn the most popular algorithms in Computer Science."
+    campaign_player_created_description: "... w których walczysz przeciwko dziełom Czarodziejów Rzemieślników"
+    campaign_classic_algorithms: "Algorytmy klasyczne"
+    campaign_classic_algorithms_description: "... gdzie nauczysz się najpopularniejszych alogrytmów w Informatyce."
     level_difficulty: "Poziom trudności: "
     play_as: "Graj jako "
     spectate: "Oglądaj"
     players: "graczy"
-#    hours_played: "hours played"
+    hours_played: "rozegranych godzin"

   contact:
     contact_us: "Kontakt z CodeCombat"
@@ -187,12 +187,12 @@
     email_announcements: "Ogłoszenia"
     email_announcements_description: "Otrzymuj powiadomienia o najnowszych wiadomościach i zmianach w CodeCombat."
     email_notifications: "Powiadomienia"
-#    email_notifications_summary: "Controls for personalized, automatic email notifications related to your CodeCombat activity."
-#    email_any_notes: "Any Notifications"
-#    email_any_notes_description: "Disable to stop all activity notification emails."
-#    email_news: "News"
-#    email_recruit_notes: "Job Opportunities"
-#    email_recruit_notes_description: "If you play really well, we may contact you about getting you a (better) job."
+    email_notifications_summary: "Ustawienia spersonalizowanych, automatycznych powiadomień mailowych zależnych od twojej aktywności w CodeCombat."
+    email_any_notes: "Wszystkie powiadomienia"
+    email_any_notes_description: "Odznacz by wyłączyć wszystkie powiadomienia email."
+    email_news: "Nowości"
+    email_recruit_notes: "Możliwości zatrudnienia"
+    email_recruit_notes_description: "Jeżeli grasz naprawdę dobrze, możemy się z tobą skontaktować by zaoferować (lepszą) pracę."
     contributor_emails: "Powiadomienia asystentów"
     contribute_prefix: "Szukamy osób, które chciałyby do nas dołączyć! Sprawdź "
     contribute_page: "stronę współpracy"
@@ -202,16 +202,16 @@
     saved: "Zmiany zapisane"
     password_mismatch: "Hasła róznią się od siebie"
     password_repeat: "Powtórz swoje hasło."
-#    job_profile: "Job Profile"
-#    job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
-#    job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
-#    sample_profile: "See a sample profile"
-#    view_profile: "View Your Profile"
+    job_profile: "Profil zatrudnienia"
+#    job_profile_approved: "Twój profil zatrudnienia został zaakceptowany przez CodeCombat. Pracodawcy będą mogli go widzieć dopóki nie oznaczysz go jako nieaktywny lub nie będzie on zmieniany przez 4 tygodnie."
+#    job_profile_explanation: "Witaj! Wypełnij to, a będziemy w kontakcie w sprawie znalezienie dla Ciebe pracy twórcy oprogramowania."
+    sample_profile: "Zobacz przykładowy profil"
+    view_profile: "Zobacz swój profil"

   account_profile:
     settings: "Ustawienia"
     edit_profile: "Edytuj Profil"
-#    done_editing: "Done Editing"
+    done_editing: "Edycja wykonana"
     profile_for_prefix: "Profil "
     profile_for_suffix: ""
 #    featured: "Featured"
@@ -362,14 +362,14 @@
     customize_wizard: "Spersonalizuj czarodzieja"
     home: "Strona główna"
 #    stop: "Stop"
-#    game_menu: "Game Menu"
+    game_menu: "Menu gry"
     guide: "Przewodnik"
     restart: "Zacznij od nowa"
     goals: "Cele"
-#    success: "Success!"
-#    incomplete: "Incomplete"
-#    timed_out: "Ran out of time"
-#    failing: "Failing"
+    success: "Sukces!"
+    incomplete: "Niekompletne"
+    timed_out: "Czas minął"
+    failing: "Niepowodzenie"
     action_timeline: "Oś czasu"
     click_to_select: "Kliknij jednostkę, by ją zaznaczyć."
     reload_title: "Przywrócić cały kod?"
@@ -401,54 +401,54 @@
     skip_tutorial: "Pomiń (esc)"
     keyboard_shortcuts: "Skróty klawiszowe"
     loading_ready: "Gotowy!"
-#    tip_insert_positions: "Shift+Click a point on the map to insert it into the spell editor."
-#    tip_toggle_play: "Toggle play/paused with Ctrl+P."
-#    tip_scrub_shortcut: "Ctrl+[ and Ctrl+] rewind and fast-forward."
-#    tip_guide_exists: "Click the guide at the top of the page for useful info."
-#    tip_open_source: "CodeCombat is 100% open source!"
-#    tip_beta_launch: "CodeCombat launched its beta in October, 2013."
-#    tip_js_beginning: "JavaScript is just the beginning."
-#    tip_think_solution: "Think of the solution, not the problem."
-#    tip_theory_practice: "In theory, there is no difference between theory and practice. But in practice, there is. - Yogi Berra"
-#    tip_error_free: "There are two ways to write error-free programs; only the third one works. - Alan Perlis"
-#    tip_debugging_program: "If debugging is the process of removing bugs, then programming must be the process of putting them in. - Edsger W. Dijkstra"
-#    tip_forums: "Head over to the forums and tell us what you think!"
-#    tip_baby_coders: "In the future, even babies will be Archmages."
-#    tip_morale_improves: "Loading will continue until morale improves."
-#    tip_all_species: "We believe in equal opportunities to learn programming for all species."
-#    tip_reticulating: "Reticulating spines."
+    tip_insert_positions: "Shift+Kliknij punkt na mapie, by umieścić go w edytorze zaklęć."
+    tip_toggle_play: "Włącz/zatrzymaj grę naciskając Ctrl+P."
+    tip_scrub_shortcut: "Ctrl+[ i Ctrl+] przesuwają czas."
+    tip_guide_exists: "Klikając Przewodnik u góry strony uzyskasz przydatne informacje."
+    tip_open_source: "CodeCombat ma w 100% otwarty kod!"
+    tip_beta_launch: "CodeCombat uruchomił fazę beta w październiku 2013."
+    tip_js_beginning: "JavaScript jest tylko początkiem."
+    tip_think_solution: "Myśl nad rozwiązaniem, nie problemem."
+    tip_theory_practice: "W teorii nie ma różnicy między teorią a praktyką. W praktyce jednak, jest. - Yogi Berra"
+    tip_error_free: "Są dwa sposoby by napisać program bez błędów. Tylko trzeci działa. - Alan Perlis"
+    tip_debugging_program: "Jeżeli debugowanie jest procesem usuwania błędów, to programowanie musi być procesem umieszczania ich. - Edsger W. Dijkstra"
+    tip_forums: "Udaj się na forum i powiedz nam co myślisz!"
+    tip_baby_coders: "W przyszłości, każde dziecko będzie Arcymagiem."
+    tip_morale_improves: "Ładowanie będzie kontynuowane gdy wzrośnie morale."
+    tip_all_species: "Wierzymy w równe szanse nauki programowania dla wszystkich gatunków."
+    tip_reticulating: "Siatkowanie kolców."
 #    tip_harry: "Yer a Wizard, "
-#    tip_great_responsibility: "With great coding skill comes great debug responsibility."
-#    tip_munchkin: "If you don't eat your vegetables, a munchkin will come after you while you're asleep."
-#    tip_binary: "There are only 10 types of people in the world: those who understand binary, and those who don't."
-#    tip_commitment_yoda: "A programmer must have the deepest commitment, the most serious mind. ~ Yoda"
-#    tip_no_try: "Do. Or do not. There is no try. - Yoda"
-#    tip_patience: "Patience you must have, young Padawan. - Yoda"
-#    tip_documented_bug: "A documented bug is not a bug; it is a feature."
-#    tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
-#    tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
-#    tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
-#    tip_hardware_problem: "Q: How many programmers does it take to change a light bulb?  A: None, it's a hardware problem."
-#    time_current: "Now:"
+    tip_great_responsibility: "Z wielką mocą programowania wiąże się wielka odpowiedzialność debugowania."
+    tip_munchkin: "Jeśli nie będziesz jadł warzyw, Munchkin przyjdzie po Ciebie w nocy."
+    tip_binary: "Jest tylko 10 typów ludzi na świecie: Ci którzy rozumieją kod binarny i ci którzy nie."
+    tip_commitment_yoda: "Programista musi najgłębsze zaangażowanie okazać. Umysł najpoważniejszy. ~ Yoda"
+    tip_no_try: "Rób. Lub nie rób. Nie ma próbowania. - Yoda"
+    tip_patience: "Cierpliwość musisz mieć, młody Padawanie. - Yoda"
+    tip_documented_bug: "Udokumentowany błąd nie jest błędem. Jest funkcją."
+    tip_impossible: "To zawsze wygląda na niemożliwe zanim zostanie zrobione. - Nelson Mandela"
+    tip_talk_is_cheap: "Gadać jest łatwo. Pokażcie mi kod. - Linus Torvalds"
+    tip_first_language: "Najbardziej zgubną rzeczą jakiej możesz się nauczyć jest twój pierwszy język programowania. - Alan Kay"
+    tip_hardware_problem: "P: Ilu programistów potrzeba by wymienić żarówkę?  O: Żadnego,to problem sprzętowy."
+    time_current: "Teraz:"
 #    time_total: "Max:"
-#    time_goto: "Go to:"
-#    infinite_loop_try_again: "Try Again"
-#    infinite_loop_reset_level: "Reset Level"
-#    infinite_loop_comment_out: "Comment Out My Code"
+    time_goto: "Idź do:"
+    infinite_loop_try_again: "Próbuj ponownie"
+    infinite_loop_reset_level: "Resetuj poziom"
+    infinite_loop_comment_out: "Comment Out My Code"

   game_menu:
-#    inventory_tab: "Inventory"
-#    choose_hero_tab: "Restart Level"
+    inventory_tab: "Ekwipunek"
+    choose_hero_tab: "Uruchom ponownie poziom"
     save_load_tab: "Zapisz/Wczytaj"
     options_tab: "Opcje"
-#    guide_tab: "Guide"
+    guide_tab: "Przewodnik"
     multiplayer_tab: "Multiplayer"
-#    inventory_caption: "Equip your hero"
+    inventory_caption: "Wyposaż swojego bohatera"
 #    choose_hero_caption: "Choose hero, language"
 #    save_load_caption: "... and view history"
-#    options_caption: "Configure settings"
-#    guide_caption: "Docs and tips"
-#    multiplayer_caption: "Play with friends!"
+    options_caption: "Ustaw opcje"
+    guide_caption: "Dokumenty i wskazówki"
+    multiplayer_caption: "Graj ze znajomymi!"

 #  inventory:
 #    temp: "Temp"
@@ -461,23 +461,23 @@
 #    granularity_change_history: "History"

   options:
-#    general_options: "General Options"
-#    volume_label: "Volume"
+    general_options: "Opcje ogólne"
+    volume_label: "Głośność"
     music_label: "Muzyka"
     music_description: "Wł/Wył muzykę w tle."
     autorun_label: "Autostart"
     autorun_description: "Ustawia automatyczne wykonywanie kodu."
     editor_config: "Konfiguracja edytora"
     editor_config_title: "Konfiguracja edytora"
-#    editor_config_level_language_label: "Language for This Level"
-#    editor_config_level_language_description: "Define the programming language for this particular level."
-#    editor_config_default_language_label: "Default Programming Language"
-#    editor_config_default_language_description: "Define the programming language you want to code in when starting new levels."
+    editor_config_level_language_label: "Język dla tego poziomu"
+    editor_config_level_language_description: "Ustaw język programowania dla tego konkretnego poziomu."
+    editor_config_default_language_label: "Domyślny język programowania"
+    editor_config_default_language_description: "Wybierz język programowania którego użyjesz na początku poziomów."
     editor_config_keybindings_label: "Przypisania klawiszy"
     editor_config_keybindings_default: "Domyślny (Ace)"
     editor_config_keybindings_description: "Dodaje skróty znane z popularnych edytorów."
-#    editor_config_livecompletion_label: "Live Autocompletion"
-#    editor_config_livecompletion_description: "Displays autocomplete suggestions while typing."
+    editor_config_livecompletion_label: "Podpowiedzi na żywo"
+    editor_config_livecompletion_description: "Wyświetl sugestie autouzupełnienia podczas pisania."
     editor_config_invisibles_label: "Pokaż białe znaki"
     editor_config_invisibles_description: "Wyświetla białe znaki takie jak spacja czy tabulator."
     editor_config_indentguides_label: "Pokaż linijki wcięć"
@@ -490,25 +490,25 @@

   multiplayer:
     multiplayer_title: "Ustawienia multiplayer"
-#    multiplayer_toggle: "Enable multiplayer"
-#    multiplayer_toggle_description: "Allow others to join your game."
+    multiplayer_toggle: "Aktywuj multiplayer"
+    multiplayer_toggle_description: "Pozwól innym dołączyć do twojej gry."
     multiplayer_link_description: "Przekaż ten link, jeśli chcesz, by ktoś do ciebie dołączył."
     multiplayer_hint_label: "Podpowiedź:"
     multiplayer_hint: "Kliknij link by zaznaczyć wszystko, potem wciśnij Cmd-C lub Ctrl-C by skopiować ten link."
     multiplayer_coming_soon: "Wkrótce więcej opcji multiplayer"
-#    multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
-
-#  keyboard_shortcuts:
-#    keyboard_shortcuts: "Keyboard Shortcuts"
-#    space: "Space"
+    multiplayer_sign_in_leaderboard: "Zaloguj się lub zarejestruj by umieścić wynik na tablicy wyników."
+
+  keyboard_shortcuts:
+    keyboard_shortcuts: "Skróty klawiszowe"
+    space: "Spacja"
 #    enter: "Enter"
 #    escape: "Escape"
 #    shift: "Shift"
-#    cast_spell: "Cast current spell."
-#    run_real_time: "Run in real time."
-#    continue_script: "Continue past current script."
+    cast_spell: "Rzuć aktualny czar."
+    run_real_time: "Uruchom \"na żywo\"."
+    continue_script: "Kontynuuj ostatni skrypt."
 #    skip_scripts: "Skip past all skippable scripts."
-#    toggle_playback: "Toggle play/pause."
+    toggle_playback: "Graj/pauzuj."
 #    scrub_playback: "Scrub back and forward through time."
 #    single_scrub_playback: "Scrub back and forward through time by a single frame."
 #    scrub_execution: "Scrub through current spell execution."


Fix lolwtf deleting

Fix lolwtf deleting

--- app/locale/ru.coffee
+++ app/locale/ru.coffee
@@ -430,4 +430,31 @@
     ambassador_subscribe_desc: "Получать email-ы о разработке мультиплеера и обновлениях в системе поддержки."
     counselor_summary: "Ни одна из вышеупомянутых ролей не соответствует тому, в чём вы заинтересованы? Не волнуйтесь, мы в поисках тех, кто хочет приложить руку к разработке CodeCombat! Если вы заинтересованы в обучении, разработке игр, управлением проектами с открытым исходным кодом, или в чём-нибудь ещё, что, как вы думаете, будет актуально для нас, то этот класс для вас."
     counselor_introduction_1: "У вас есть жизненный опыт? Другая точка зрения на вещи, которые могут помочь нам решить, как формировать CodeCombat? Из всех этих ролей, эта, возможно, займёт меньше всего времени, но по отдельности, вы можете сделать наибольшие изменения. Мы в поисках морщинистых мудрецов, особенно в таких областях, как: обучение, разработка игр, управление проектами с открытым исходным кодом, технической рекрутинг, предпринимательство или дизайн."
-    counselor_introduction_2: "Или действительно всё, что имеет отношение к развитию CodeCombat
+    counselor_introduction_2: "Или действительно всё, что имеет отношение к развитию CodeCombat. Если у вас есть знания и вы хотите поделиться ими, чтобы помочь вырастить этот проект, то этот класс для вас."
+    counselor_attribute_1: "Опыт, в любой из областей выше, или в том, что, как вы думаете, может быть полезным."
+    counselor_attribute_2: "Немного свободного времени!"
+    counselor_join_desc: "расскажите нам немного о себе, чем вы занимались и чем хотели бы заниматься. Мы поместим вас в наш список контактов и выйдем на связь, когда нам понадобится совет(не слишком часто)."
+    more_about_counselor: "Узнать больше о том, как стать Советником"
+    changes_auto_save: "Изменения сохраняются автоматически при переключении флажков."
+    diligent_scribes: "Наши старательные Писари:"
+    powerful_archmages: "Наши могущественные Архимаги:"
+    creative_artisans: "Наши творческие Ремесленники:"
+    brave_adventurers: "Наши отважные Искатели приключений:"
+    translating_diplomats: "Наши переводящие Дипломаты:"
+    helpful_ambassadors: "Наши полезные Послы:"
+
+  classes:
+    archmage_title: "Архимаг"
+    archmage_title_description: "(программист)"
+    artisan_title: "Ремесленник"
+    artisan_title_description: "(создатель уровней)"
+    adventurer_title: "Искатель приключений"
+    adventurer_title_description: "(тестировщик уровней)"
+    scribe_title: "Писарь"
+    scribe_title_description: "(редактор статей)"
+    diplomat_title: "Дипломат"
+    diplomat_title_description: "(переводчик)"
+    ambassador_title: "Посол"
+    ambassador_title_description: "(поддержка)"
+    counselor_title: "Советник"
+    counselor_title_description: "(эксперт/учитель)"


Update vi.coffee

Update vi.coffee

--- app/locale/vi.coffee
+++ app/locale/vi.coffee
@@ -143,7 +143,7 @@
     publish: "Chia sẻ"
     create: "Làm mới"
     fork: "Nĩa"
-    play: "Các cấp độ" # When used as an action verb, like "Play next level"
+    play: "Chơi" # When used as an action verb, like "Play next level"
     retry: "Chơi lại"
     actions: "Các Hành Động"
     info: "Thông tin"


Fix "Accept" header test for Zepto 1.1.6

The "Accept" header values differ slightly between Zepto 1.0 and 1.1,
but they start with the same string.

--- test/unit/accept.coffee
+++ test/unit/accept.coffee
@@ -12,7 +12,7 @@
           env = JSON.parse env

         if @win.Zepto?
-          equal env['HTTP_ACCEPT'], "*/*;q=0.5, text/javascript, application/javascript"
+          equal env['HTTP_ACCEPT'].indexOf("*/*;q=0.5, text/javascript, application/javascript"), 0
         else
           equal env['HTTP_ACCEPT'], "*/*;q=0.5, text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
         start()


Fetch client using identifiers in request payload

--- node_modules_koding/bongo/lib/expressify.coffee
+++ node_modules_koding/bongo/lib/expressify.coffee
@@ -5,17 +5,28 @@

   (req, res, next) ->

-    { channelName, queue: requestQueue } = req.body
+    {
+      channelName
+      queue: requestQueue
+      sessionToken
+      userArea
+    } = req.body

     unless requestQueue?.length
       return res.status(400).end()

     responseQueue = new Array requestQueue.length

-    workQueue = requestQueue.map (message, i) -> ->
-      bongo.handleRequest channelName, { message }, (secretName, callbackId, args) ->
-        bongo.scrubResponse callbackId, args, (message) ->
-          responseQueue[i] = message
-          workQueue.fin()
+    bongo.fetchClient sessionToken, userArea, (client) ->

-    dash workQueue, -> res.send responseQueue
+      unless client
+        console.log "bongo.fetchClient: #{sessionToken} not found in #{userArea}"
+        return res.status(500).send 'An error occcurred'
+
+      workQueue = requestQueue.map (message, i) -> ->
+        bongo.handleRequest channelName, { message, client }, (secretName, callbackId, args) ->
+          bongo.scrubResponse callbackId, args, (message) ->
+            responseQueue[i] = message
+            workQueue.fin()
+
+      dash workQueue, -> res.send responseQueue


Fixed ids.

Fixed ids.

--- tasks/markdown_jade.coffee
+++ tasks/markdown_jade.coffee
@@ -224,7 +224,7 @@
         process: (contents, path) ->
           html = grunt.template.process contents, data: _.extend({
               section: _.last(leavePath)
-              ids: parts
+              ids: leavePath
               all: data
               root: leavePath[0]
             }, _options.data)


bugfix

bugfix

--- src/interface.coffee
+++ src/interface.coffee
@@ -17,7 +17,6 @@
     this.knownLabels = {}
     this.lastUsedLabel = ''

-    # iterate over all tokens and save them in an array
     this.initLabels()
     this.initTokens()
     this.initKeyboardEventHandler()
@@ -26,7 +25,7 @@
     super

   initLabels: ->
-    $('.label-set .token').each (_, element) ->
+    $('.interfaces-staging >:not(.template) .label-set .token').each (_, element) ->
       $label = $(element)
       id = "label-#{$label.data('id')}"
       label = $label.data('label')
@@ -138,30 +137,32 @@
     keyIsPressed = (keyId) ->
       _this.keyMap.indexOf(keyId) >= 0

-    _this.saveAnnotation() if keyIsPressed(13) # enter
-    _this.skip() if keyIsPressed(27) # escape
+    this.saveAnnotation() if keyIsPressed(13) # enter
+    this.skip() if keyIsPressed(27) # escape

     # all other bindings require a token to be selected
     return if this.selectedTokenIndex < 0

     # backspace or delete
     if keyIsPressed(8) || keyIsPressed(46)
-      _this.removeChunkWithIndex(this.selectedTokenIndex)
+      this.removeChunkWithIndex(this.selectedTokenIndex)

     # shift
     if keyIsPressed(16)
-      _this.removeTokenFromChunk('left') if keyIsPressed(37) # key '->'
-      _this.removeTokenFromChunk('right') if keyIsPressed(39) # key '->'
-      _this.selectNextChunk('left') if keyIsPressed(9) # key 'tab'
+      this.removeTokenFromChunk('left') if keyIsPressed(37) # key '->'
+      this.removeTokenFromChunk('right') if keyIsPressed(39) # key '->'
+      this.selectNextChunk('left') if keyIsPressed(9) # key 'tab'

     else
-      _this.changeTokenKind('label-0') if keyIsPressed(49) # key '1'
-      _this.changeTokenKind('label-1') if keyIsPressed(50) # key '2'
-      _this.changeTokenKind('label-2') if keyIsPressed(51) # key '3'
-      _this.changeTokenKind('label-3') if keyIsPressed(52) # key '4'
-      _this.addTokenToChunk('left') if keyIsPressed(37) # key '<-'
-      _this.addTokenToChunk('right') if keyIsPressed(39) # key '->'
-      _this.selectNextChunk('right') if keyIsPressed(9) # key 'tab'
+      this.addTokenToChunk('left') if keyIsPressed(37) # key '<-'
+      this.addTokenToChunk('right') if keyIsPressed(39) # key '->'
+      this.selectNextChunk('right') if keyIsPressed(9) # key 'tab'
+
+      knownLabelsCount = Object.keys(this.knownLabels).length
+      this.changeTokenKind('label-0') if keyIsPressed(49) # key '1'
+      this.changeTokenKind('label-1') if keyIsPressed(50) && knownLabelsCount >= 2 # key '2'
+      this.changeTokenKind('label-2') if keyIsPressed(51) && knownLabelsCount >= 3 # key '3'
+      this.changeTokenKind('label-3') if keyIsPressed(52) && knownLabelsCount == 4 # key '4'

   createChunkWithTokens: (clickedTokenIndex, hoveredTokenIndex, additive=false) ->
     # find first / last and check if one or both belong to a chunk (and get real first / last indices)


Fix scrolling at checkpoint

Fix scrolling at checkpoint

--- src/lib/Level.coffee
+++ src/lib/Level.coffee
@@ -167,7 +167,7 @@

     Crafty.one 'ShipSpawned', =>
       @_playersActive = yes
-      #@_scrollWall.scrollWall(@_forcedSpeed)
+      @_scrollWall.scrollWall(@_forcedSpeed)

     Crafty('Player').each (index) ->
       spawnPosition = ->


Ensure component list has been loaded before building network, refs #49

--- src/lib/NoFlo.coffee
+++ src/lib/NoFlo.coffee
@@ -267,17 +267,12 @@
     network = new NoFlo graph
     network.debug = debug

-    connect = ->
+    # Ensure components are loaded before continuing
+    network.loader.listComponents ->
+      network.addNode node for node in graph.nodes
       network.addEdge edge for edge in graph.edges
       network.addInitial initializer for initializer in graph.initializers
       callback network if callback
-
-    todo = graph.nodes.length
-    for node in graph.nodes
-      network.addNode node, ->
-        todo--
-        return unless todo is 0
-        do connect

     network


Fix a test failure caused by non-existing default directory in test environment

--- spec/notational-velocity-spec.coffee
+++ spec/notational-velocity-spec.coffee
@@ -7,11 +7,16 @@
 # or `fdescribe`). Remove the `f` to unfocus the block.

 describe "NotationalVelocity", ->
+  defaultDirectory = atom.config.get('notational-velocity.directory')
   activationPromise = null

   beforeEach ->
     atom.workspaceView = new WorkspaceView
     activationPromise = atom.packages.activatePackage('notational-velocity')
+    atom.config.set('notational-velocity.directory', 'testdata')
+
+  afterEach ->
+    atom.config.set('notational-velocity.directory', defaultDirectory)

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


Added addsrc js and concat index.js

Added addsrc js and concat index.js

--- gulp/client-scripts.coffee
+++ gulp/client-scripts.coffee
@@ -44,4 +44,8 @@
     .pipe sourcemaps.init()
     .pipe coffee()

-    # TODO: add JS files to bundle+    # add javascript files to bundle
+    .pipe addsrc('app/**/*.js')
+
+    # bring everything together with index.js (concat)
+    .pipe gulpif config.concat, concat 'index.js'


Fund to (max gift)x10 when too low

Fund to (max gift)x10 when too low

--- src/lib/tango.coffee
+++ src/lib/tango.coffee
@@ -8,7 +8,7 @@
     acct = process.env.HUBOT_TANGOCARD_ACCOUNT
     cc = process.env.HUBOT_TANGOCARD_CC
     auth = process.env.HUBOT_TANGOCARD_AUTH
-    amtToFund = (process.env.HUBOT_HIGHFIVE_AWARD_LIMIT || 150) * 2 * 100 # in cents
+    amtToFund = (process.env.HUBOT_HIGHFIVE_AWARD_LIMIT || 150) * 10 * 100 # in cents

     order: (msg, from_user, to_user, dollars, reason, callback) ->


Typo corrected.

Typo corrected.

--- tests/test-https.coffee
+++ tests/test-https.coffee
@@ -25,7 +25,7 @@
       cert: fs.readFileSync(__dirname + "/../data/cert.pem")
     }

-    # Creating new HTTP server.
+    # Creating new HTTPS server.
     @server = https.createServer basic, options, (req, res) ->
       res.end "Welcome to private area - #{req.user}!"
     # Start server.


Update pt-BR.coffee

Update pt-BR.coffee

--- app/locale/pt-BR.coffee
+++ app/locale/pt-BR.coffee
@@ -422,14 +422,14 @@
 #    skip_scripts: "Skip past all skippable scripts."
     toggle_playback: "Alternar play/pause."
     scrub_playback: "Rolar para frente e para trás no tempo."
-#    single_scrub_playback: "Scrub back and forward through time by a single frame."
-#    scrub_execution: "Scrub through current spell execution."
-#    toggle_debug: "Toggle debug display."
-#    toggle_grid: "Toggle grid overlay."
-#    toggle_pathfinding: "Toggle pathfinding overlay."
-#    beautify: "Beautify your code by standardizing its formatting."
-#    maximize_editor: "Maximize/minimize code editor."
-#    move_wizard: "Move your Wizard around the level."
+    single_scrub_playback: "Rolar para frente e para trás no tempo, quadro a quadro."
+    scrub_execution: "Rolar através da execução do feitiço atual."
+    toggle_debug: "Ligar/desligar informações de debug."
+    toggle_grid: "Ligar/desligar exibição da grade."
+    toggle_pathfinding: "Ligar/desligar exibição do pathfinding (caminho)."
+    beautify: "Embeleze seu código a partir da padronização de formatação."
+    maximize_editor: "Maximizar/minimizar editor de código."
+    move_wizard: "Mova o Wizard pelo nível."

   community:
     main_title: "Comunidade CodeCombat"
@@ -468,7 +468,7 @@
     article_title: "Editor de Artigo"
     thang_title: "Editor de Thang"
     level_title: "Editor de Nível"
-#    achievement_title: "Achievement Editor"
+    achievement_title: "Editor de Conquistas"
     back: "Voltar"
     revert: "Reverter"
     revert_models: "Reverter Modelos"


whitespace and comments

whitespace and comments

--- lingsim.coffee
+++ lingsim.coffee
@@ -19,6 +19,7 @@
   sum: (numbers) ->
     _.reduce numbers, (memo, n) -> memo + n

+  # safe inverse
   inv: (n) ->
     if n is 0 then 0 else 1/n

@@ -37,8 +38,6 @@
   # return a random letter from the first n
   randomAlpha: (n) =>
     @alpha @randomRange(0,n)
-
-

 Utils = new Utilities()


implemented random genome generation

implemented random genome generation

--- lingsim.coffee
+++ lingsim.coffee
@@ -29,6 +29,18 @@
   count: (array, iterator) =>
     @sum _.map(array, (x) => if iterator(x) then 1 else 0)

+  # return a letter of the alphabet
+  # n = 0 -> a, n = 1 -> b, n = 2 -> c, ...
+  alpha: (n) =>
+    String.fromCharCode 101 + n
+
+  # return a random letter from the first n
+  randomAlpha: (n) =>
+    @alpha @randomRange(0,n)
+
+
+
+
 Utils = new Utilities()

 class Language
@@ -39,8 +51,7 @@

   generateGenome: =>
     @genome = []
-    _.times GENOME_SIZE, => @genome.push
-
+    _.times GENOME_SIZE, => @genome.push Utils.alpha()

   distance: (otherLanguage) =>
     Utils.editDistance @genome, otherLanguage.genome


Quick ref

Quick ref

--- src/menus/linux.cson
+++ src/menus/linux.cson
@@ -9,8 +9,9 @@
   {
     label: '&View'
     submenu: [
-      { label: '&Decrease on 20%', accelerator: 'Ctrl+Minus', command: 'application:decrease-zoom' }
-      { label: '&Encrease on 20%', accelerator: 'Ctrl+Plus', command: 'application:encrease-zoom' }
+      #buggy key bindings in atom
+      { label: '&Decrease on 20%', accelerator: 'Ctrl-=', command: 'application:decrease-zoom' }
+      { label: '&Encrease on 20%', accelerator: 'Ctrl+=', command: 'application:encrease-zoom' }
       { label: '&Rezet zoom', accelerator: 'Ctrl+0', command: 'application:reset-zoom' }
     ]
   }


Change dimensions

Change dimensions

--- app/scripts/main.coffee
+++ app/scripts/main.coffee
@@ -26,8 +26,8 @@

     canvas = document.querySelector 'canvas'

-    canvas.width = 1024
-    canvas.height = 768
+    canvas.width = 800
+    canvas.height = 600

     game = window.game = new Ld30.Game(canvas)


cleanup

cleanup

--- apps/auth/routes.coffee
+++ apps/auth/routes.coffee
@@ -23,6 +23,6 @@
     code          : req.query['token']
     ).end((err, response) ->
       (err or response?.body.error_description)
-      req.login new CurrentUser(accessToken: token), ->
+      req.login new CurrentUser(accessToken: response?.body.access_token), ->
         res.redirect req.query['redirect-to'] or req.get('Referrer') or '/'
   )


only use og show route

only use og show route

--- apps/show/routes.coffee
+++ apps/show/routes.coffee
@@ -3,7 +3,7 @@
 PartnerShow = require '../../models/partner_show'

 @index = (req, res, next) ->
-  return next() if res.locals.sd.SHOW_METAPHYSICS is 'true'
+  # return next() if res.locals.sd.SHOW_METAPHYSICS is 'true'
   show = new PartnerShow id: req.params.id

   Q.all [
@@ -50,4 +50,6 @@
       artworks: show.related().artworks
       jsonLD: stringifyJSONForWeb show.toJSONLD()

-  .catch next
+  .catch (err)->
+    console.log 'err', err
+    next()


SocialWorker: Tests: add new storage size tests, separate test case for snapshotId

--- workers/social/lib/social/models/computeproviders/koding.test.coffee
+++ workers/social/lib/social/models/computeproviders/koding.test.coffee
@@ -52,35 +52,24 @@
     # default options for create test suite
     generateDefaultOptions = (options) ->

-      _options =
+      return _.extend
         label        : generateRandomString()
         region       : 'us-east-1'
-        storage      : '1'
+        storage      : '3'
         snapshotId   : 'someSnapshotId'
         instanceType : 't2.micro'
-
-      _options = _.extend _options, options
-
-      return _options
+      , options

     it 'should be able to succeed with valid request', (done) ->

       withCreatedUser ({ client, user, account, group }) ->
-
         client.r = { user, account, group }
-        snapshot = {}
-
-        queue = [
-
-          ->
-            createSnapshot { originId : account.getId() }, (err, snapshot_) ->
-              expect(err).to.not.exist
-              snapshot = snapshot_
-              queue.next()
-
-          ->
-            options = generateDefaultOptions { snapshotId : snapshot.getId() }
+
+        queue = [
+
+          ->
+            options = generateDefaultOptions()
             Koding.create client, options, (err, data) ->
               expect(err).to.not.exist
               expect(data.meta).to.be.an 'object'
@@ -100,15 +89,61 @@
         daisy queue

+    it 'should be able to succeed when snapshotId provided', (done) ->
+
+      withCreatedUser ({ client, user, account, group }) ->
+
+          client.r = { user, account, group }
+          snapshot = {}
+
+          queue = [
+
+            ->
+              createSnapshot { originId : account.getId() }, (err, snapshot_) ->
+                expect(err).to.not.exist
+                snapshot = snapshot_
+                queue.next()
+
+            ->
+              options = generateDefaultOptions { snapshotId : snapshot.getId() }
+              Koding.create client, options, (err, data) ->
+                console.log data.meta
+                expect(err).to.not.exist
+                expect(data.meta).to.be.an 'object'
+                expect(data.meta.type).to.be.equal 'aws'
+                expect(data.meta.region).to.be.equal options.region
+                expect(data.meta.source_ami).to.be.empty
+                expect(data.meta.storage_size.toString()).to.be.equal options.storage
+                expect(data.meta.alwaysOn).to.be.false
+                expect(data.label).to.be.a 'string'
+                expect(data.credential).to.be.equal user.username
+                queue.next()
+
+            -> done()
+
+          ]
+
+          daisy queue
+
+
     it 'should fail if storage is not valid', (done) ->

       withCreatedUser ({ client, user, account }) ->
-        client.r = {}
-
-        options = generateDefaultOptions { storage : 'notValidStorage' }
-        Koding.create client, options, (err) ->
-          expect(err?.message).to.be.equal 'Requested storage size is not valid.'
-          done()
+        client.r = { user, account }
+
+        queue         = []
+        storageValues = ['notValidStorage', '2', '101']
+
+        storageValues.forEach (storageValue) ->
+          queue.push ->
+            options = generateDefaultOptions { storage : storageValue }
+            Koding.create client, options, (err) ->
+              expect(err?.message).to.be.equal 'Requested storage size is not valid.'
+              queue.next()
+
+        queue.push -> done()
+
+        daisy queue

     it 'should fail if storage exceeds allowed size', (done) ->
@@ -129,7 +164,7 @@
           ->
             expectedError = "Total limit of #{userPlan.storage}GB storage
                               limit has been reached."
-            options = generateDefaultOptions { storage : '1000' }
+            options = generateDefaultOptions { storage : '10' }
             Koding.create client, options, (err) ->
               expect(err?.message).to.be.equal expectedError
               queue.next()


Tests...

Tests...

--- test/strawpoll_test.coffee
+++ test/strawpoll_test.coffee
@@ -13,4 +13,4 @@
     require('../src/strawpoll')(@robot)

   it 'registers a respond listener', ->
-    expect(@robot.respond).to.have.been.calledWith(/strawpoll/, 1, 2, 3)
+    expect(@robot.respond).to.have.been.calledWith(/strawpoll/, /1/, /2/, /3/)


prevent intermittent test failures

prevent intermittent test failures

--- test/ultrawave_test.coffee
+++ test/ultrawave_test.coffee
@@ -28,23 +28,27 @@
   describe 'Constructor', ->

     it 'can be created with a url', ->
-      ultrawave = new Ultrawave 'ws:localhost'
+      server = new GroupServer port: port += 1
+      ultrawave = new Ultrawave "ws:localhost:#{port}"

     it 'can be created with a PeerGroup instance', ->
-      ultrawave = new Ultrawave new PeerGroup url: 'ws:localhost'
+      server = new GroupServer port: port += 1
+      ultrawave = new Ultrawave new PeerGroup url: "ws:localhost:#{port}"

     it 'throws when neither a url or PeerGroup is provided', ->
       assert.throws -> new Ultrawave

   describe 'Cursor', ->
-    assert Ultrawave.Cursor
+    it 'should be exposed', ->
+      assert Ultrawave.Cursor

   describe '#_applyRemoteChange', ->

     it 'should apply changes directly when clock is later than last
         clock', (done) ->

-      ultrawave = new Ultrawave "ws:localhost"
+      server = new GroupServer port: port += 1
+      ultrawave = new Ultrawave "ws:localhost:#{port}"

       clock = new VectorClock id: 'a', a: 2
       args = ['b',2]
@@ -63,7 +67,8 @@

     it 'should ignore changes that have already been applied', ->

-      ultrawave = new Ultrawave "ws:localhost"
+      server = new GroupServer port: port += 1
+      ultrawave = new Ultrawave "ws:localhost:#{port}"

       clock = new VectorClock id: 'a', a: 2
       args = [1,2]
@@ -82,7 +87,8 @@
     it 'should apply changes in order when clock is before earlier
         clock', (done) ->

-      ultrawave = new Ultrawave "ws:localhost"
+      server = new GroupServer port: port += 1
+      ultrawave = new Ultrawave "ws:localhost:#{port}"

       changes = [
         [{}, {id: 'a', a: 1}, 'set', [0,1]]
@@ -120,7 +126,8 @@

     it 'should use peer id to resolve ambiguous ordering of chnages', ->

-      ultrawave = new Ultrawave "ws:localhost"
+      server = new GroupServer port: port += 1
+      ultrawave = new Ultrawave "ws:localhost:#{port}"

       handle =
         data: -> {}


Fix for issue #17

Fix for issue #17

Added a fix for issue #17, where a pane could not be found. The fix is a
little lazy, as it only catches the error and does nothing (though, that
should be enough).

--- lib/pinned-tabs.coffee
+++ lib/pinned-tabs.coffee
@@ -126,9 +126,12 @@

             # Decrease the pinned tab counter if it was a pinned tab
             return unless axis = document.querySelector('.tab-bar').parentNode.parentNode
-            paneNode = axis.children[paneIndex].querySelector('.tab-bar')
-            if paneNode.children[tabIndex].classList.contains('pinned')
-                self.PinnedTabsState.data[paneIndex] -= 1
+            try
+                paneNode = axis.children[paneIndex].querySelector('.tab-bar')
+                if paneNode.children[tabIndex].classList.contains('pinned')
+                    self.PinnedTabsState.data[paneIndex] -= 1
+            catch error
+                return

     # Method to pin the active tab.


arraystream: unnecessary comment/code

arraystream: unnecessary comment/code

--- lib/understream.coffee
+++ lib/understream.coffee
@@ -33,7 +33,7 @@
     super _(@options).extend objectMode: true
   _read: (size) =>
     debug "_read #{size} #{JSON.stringify @arr[0]}"
-    @push @arr.shift() or null # Shift returns undefined when the array is empty but we want to push null
+    @push @arr.shift()

 class DevNull extends Writable
   constructor: -> super objectMode: true


Remove logging

Remove logging

--- Email/EmailNotifier.coffee
+++ Email/EmailNotifier.coffee
@@ -37,7 +37,6 @@

                 for email in emails
                     do (email) =>
-                        console.log "Emailing #{email}"
                         # Send the email
                         nodemailer.send_mail {
                             to : email