Fix a transaction interpretation edge case

--- app/src/models/operation.coffee
+++ app/src/models/operation.coffee
@@ -32,7 +32,8 @@
       outputValue = _(accountOutputs).reduce(((m, o) -> m.add(o.value)), ledger.Amount.fromSatoshi(0))
       value = outputValue.subtract(inputValue)
     else
-      outputs = _(tx.outputs).filter((o) -> _(o.nodes).some((n) -> n?[1] isnt 1 and n?[0] is index))
+      hasOwnInputs = _(tx.inputs).filter((i) -> _(i.nodes).some((n) -> n?[0] is index)).length > 0
+      outputs = _(tx.outputs).filter((o) -> _(o.nodes).some((n) -> (!hasOwnInputs or n?[1] isnt 1) and n?[0] is index))
       value = _(outputs).reduce(((m, o) -> m.add(o.value)), ledger.Amount.fromSatoshi(0))
     @_createOperationFromTransaction(uid, "reception", tx, value, account)


Typo.

Typo.

--- tests.coffee
+++ tests.coffee
@@ -1,5 +1,5 @@
 class ServerAutorunTestCase extends ClassyTestCase
-  @testName: 'server-sutorun'
+  @testName: 'server-autorun'

   setUpServer: ->
     @collection ?= new Mongo.Collection 'test_collection'


Bugfix: WebGLCanvas doesn't render on construction

--- app/tamarind/WebGLCanvas.coffee
+++ app/tamarind/WebGLCanvas.coffee
@@ -74,6 +74,8 @@

     unless @gl
       throw new Error('Could not create WebGL context for canvas')
+
+    @_doFrame()

     return


Fixed ACE3 Settings Entry snippet indentation per ACE3 standards

--- snippets/language-sqf.cson
+++ snippets/language-sqf.cson
@@ -25,11 +25,11 @@
     'prefix': 'ace_settings_entry'
     'body': """
       class GVAR(${1:name}) {
-        displayName = CSTRING(${2:stringDisplayName});
-        description = CSTRING(${3:stringDescription});
-        isClientSettable = ${4:[0/1]};
-        typeName = "${5:[BOOL/SCALAR/STRING/ARRAY/COLOR]]}";
-        value = ${6:[Number]};
+          displayName = CSTRING(${2:stringDisplayName});
+          description = CSTRING(${3:stringDescription});
+          isClientSettable = ${4:[0/1]};
+          typeName = "${5:[BOOL/SCALAR/STRING/ARRAY/COLOR]]}";
+          value = ${6:[Number]};
       };
     """
     'description': 'ACE_Settings Entry (without SCALAR values)'


fix me

fix me

--- app/views/home-page-view.coffee
+++ app/views/home-page-view.coffee
@@ -79,9 +79,8 @@
     if actions['cancle']
       placeholder = true
       mediator.publish 'play', 'dundundun', 1
+      # code

-
-      # code

   draw: =>
     # Resize canvas to window size


Fix catch up with rendering

Fix catch up with rendering

That's insane oO
I must have been drunk or stoned while comitting this, i mean seriously? what the fuck?

--- app/views/home-page-view.coffee
+++ app/views/home-page-view.coffee
@@ -103,10 +103,11 @@
         lvl.update()
         @lastPhysicsUpdate += PHYSICS_LOOP

-    while @lastRenderUpdate < timeNow
-      @draw()
-      lvl.physicsManager.world.DrawDebugData() if debug
-      @lastRenderUpdate += RENDER_LOOP
+    renderDelte = timeNow - @lastRenderUpdate - RENDER_LOOP
+    if renderDelte > 0
+        @draw()
+        lvl.physicsManager.world.DrawDebugData() if debug
+        @lastRenderUpdate = timeNow

     if debug
       timeToRender = Date.now() - timeNow


chore - updated gulp dev to not depend on shell scripts & node-dev, used foreman instead due to heroku


Propagating MSON sample's filename as name of the top-level object.

--- scripts/generate-samples-ast.coffee
+++ scripts/generate-samples-ast.coffee
@@ -16,12 +16,12 @@

 # Parses given MSON and passes resulting AST to the callback.
-parse = (mson, cb) ->
+parse = (topLevelName, mson, cb) ->
   indentedMson = ("    #{line}" for line in mson.split '\n').join '\n'

   # Dummy API Blueprint
   blueprint = """
-    # Name [/]
+    # #{topLevelName} [/]

     + Attributes
     #{indentedMson}
@@ -54,7 +54,7 @@
 generate = (filename, cb) ->
   async.waterfall [
     (next) -> readMsonFile filename, next
-    parse
+    (mson, next) -> parse filename, mson, next
     (ast, next) -> writeAstFile filename, ast, next
   ], cb


Whitespace and extraneous semicolon removal

Some of these changes were noticed when doing experiments with the
CoffeeScriptRedux compiler, which is a bit stricter than the original.

--- src/range.coffee
+++ src/range.coffee
@@ -422,12 +422,13 @@
     # Node.compareDocumentPosition() to decide when to set the
     # commonAncestorContainer and bail out.

-    contains = if not document.compareDocumentPosition?
-                 # IE
-                 (a, b) -> a.contains(b)
-               else
-                 # Everyone else
-                 (a, b) -> a.compareDocumentPosition(b) & 16
+    contains =
+      if not document.compareDocumentPosition?
+        # IE
+        (a, b) -> a.contains(b)
+      else
+        # Everyone else
+        (a, b) -> a.compareDocumentPosition(b) & 16

     $(range.startContainer).parents().each ->
       if contains(this, range.endContainer)


debug routing

debug routing

--- router.coffee
+++ router.coffee
@@ -23,21 +23,18 @@

 # Proxy server that uses route table defined earlier
 proxyServer = httpProxy.createServer (req, res, proxy) ->
+    buffer = httpProxy.buffer(req)
+
     port = defaultPort
     for route of routes
         if req.url.match("^" + route)
             req.url = req.url.substring(route.length)
-            console.log req.url
             port = routes[route]

-            res.writeHead 200,
-                'Set-Cookie': 'mycookie=' + route
-                'Content-Type': 'text/plain'
-
-
     proxy.proxyRequest req, res,
+        host: 'localhost'
         port: port
-        host: 'localhost'
+        buffer: buffer

 # Start proxy server
 proxyServer.listen proxyPort


Create an authenticated user if necessary.

--- src/xo.coffee
+++ src/xo.coffee
@@ -549,19 +549,28 @@
     @_authenticationProviders.remove(provider)

   authenticateUser: $coroutine (credentials) ->
+    # TODO: remove when email has been replaced by username
+    if credentials.email?
+      credentials.username = credentials.email
+    else if credentials.username?
+      credentials.email = credentials.username
+
     iterator = @_authenticationProviders[Symbol.iterator]()

     while not (current = iterator.next()).done
       try
-        userId = $wait(current.value(credentials))
-        return userId if userId instanceof $User
-
-        user = $wait @users.first(userId)
+        result = $wait(current.value(credentials))
+        return result if result instanceof $User
+
+        # TODO: replace email by username
+        if result.username?
+          result.email = result.username
+          delete result.username
+
+        user = $wait @users.first(result)
         return user if user

-        #return @users.create
-        console.log('TODO: create user')
-        return false
+        return @users.create(result.email)
       catch e
         console.error(e)
     return false


Update ambush.coffee

Update ambush.coffee

--- src/ambush.coffee
+++ src/ambush.coffee
@@ -26,7 +26,7 @@
     users = robot.brain.usersForFuzzyName(msg.match[1].trim())
     if users.length is 1
       user = users[0]
-      appendAmbush(robot.brain.data.ambushes, user, msg.message.user, "#{msg.match[2]} sent at #{new Date()}")
+      appendAmbush(robot.brain.data.ambushes, user, msg.message.user, "#{msg.match[2]} ")
       msg.send "Ambush prepared"
     else if users.length > 1
       msg.send "Too many bitches like that"


Minor changes.

Minor changes.

--- src/api/vm.coffee
+++ src/api/vm.coffee
@@ -144,10 +144,12 @@
     name_description: { type: 'string', optional: true }

     # Number of virtual CPUs to allocate.
-    CPUs: { 'type': integer, optional: true }
+    CPUs: { type: 'integer', optional: true }

     # Memory to allocate (in bytes).
-    memory: { 'type': integer, optional: true }
+    #
+    # Note: static_min ≤ dynamic_min ≤ dynamic_max ≤ static_max
+    memory: { type: 'integer', optional: true }
   }

   try
@@ -159,13 +161,14 @@

   # Some settings can only be changed when the VM is halted.
   if 'CPUs' of params and VM.power_state isnt 'Halted'
-    @throw 'INVALID_PARAMS'
+    @throw 'INVALID_PARAMS', 'cannot change CPUs when the VM is not halted'

   for param, field of {
     CPUs: 'VCPUs_at_startup'
-    memory: 'memory_dynamic_max'
+    memory: 'memory_static_max'
     'name_label'
     'name_description'
   }
-    if field of params?
-      xapi.call "VM.set_#{field}", VM.ref, params[param]
+    continue unless param of params
+
+    xapi.call "VM.set_#{field}", VM.ref, "#{params[param]}"


Change plan name to payasyougo1

Change plan name to payasyougo1

--- js/inner.coffee
+++ js/inner.coffee
@@ -385,7 +385,7 @@
       parallel: 8
       limits: null,
       support: "Email"
-      plan: "payg1"
+      plan: "payasyougo1"
       price: 0
     ,
       title: "Fast"


Added timer_tick method to Game class

Added timer_tick method to Game class

--- game.coffee
+++ game.coffee
@@ -32,6 +32,24 @@
   getCurrentLines: ->
     p.current_line for p in @players

+  timer_tick: ->
+    console.log "Tick!"
+    new_time = SynchronizedTime.getTime()
+    elapsed_time = new_time - @old_time
+
+    for player in @players
+      lastpos = player.lastPos()
+      if lastpos.direction == Game.NORTH
+        player.addToLine(new paper.Point(lastpos.x - (Game.VELOCITY * elapsed_time), lastpos.y))
+      else if lastpos.direction == Game.SOUTH
+        player.addToLine(new paper.Point(lastpos.x + (Game.VELOCITY * elapsed_time), lastpos.y))
+      else if lastpos.direction == Game.EAST
+        player.addToLine(new paper.Point(lastpos.x, lastpos.y + (Game.VELOCITY * elapsed_time)))
+      else if lastpos.direction == Game.WEST
+        player.addToLine(new paper.Point(lastpos.x, lastpos.y - (Game.VELOCITY * elapsed_time)))
+
+    @old_time = new_time
+
   add_listener: (listener) ->
     @listeners.append(listener)


Fix free mobile (#418)

Fix free mobile (#418)

--- server/konnectors/freemobile.coffee
+++ server/konnectors/freemobile.coffee
@@ -250,7 +250,7 @@
     # - Import overall pdf with name YYYYMM_freemobile.pdf

     isMultiline = $('div[class="consommation"]').length > 1
-    $('div[class="factLigne hide "]').each ->
+    $('div.factLigne.is-hidden').each ->
         amount = $($(this).find('.montant')).text()
         amount = amount.replace '€', ''
         amount = parseFloat amount


Added "build" task, without executing the connection.

--- Gulpfile.coffee
+++ Gulpfile.coffee
@@ -77,5 +77,5 @@
 	gulp.watch path.watch.views, ['views']

 gulp.task 'default', ['scripts', 'styles', 'views', 'connect', 'watch']
-
-gulp.task 'start', ['scripts', 'styles', 'views', 'connect-prod']+gulp.task 'start', ['scripts', 'styles', 'views', 'connect-prod']
+gulp.task 'build', ['scripts', 'styles', 'views']


Allow `into` option in Controller::render to change the yield that gets replaced.

Closes #192

--- src/batman.coffee
+++ src/batman.coffee
@@ -1787,7 +1787,7 @@
     if view = options.view
       Batman.currentApp?.prevent 'ready'
       view.on 'ready', ->
-        Batman.DOM.replace 'main', view.get('node')
+        Batman.DOM.replace (options.into || 'main'), view.get('node')
         Batman.currentApp?.allow 'ready'
         Batman.currentApp?.fire 'ready'
     view


Don't need a double arrow here.

Don't need a double arrow here.

--- spec/draggable_spec.coffee
+++ spec/draggable_spec.coffee
@@ -305,7 +305,7 @@
                 it 'should be called with the draggable and the event as arguments', ->
                   expect(helperConfig).toHaveBeenCalledWith(@$draggable.get(0), jasmine.any(jQuery.Event))

-            describe 'the helper', =>
+            describe 'the helper', ->

               it 'should be positioned absolutely', ->
                 expect(@appendedElement).toHaveCss { position: 'absolute' }


add test

add test

--- spec/operators-spec.coffee
+++ spec/operators-spec.coffee
@@ -1574,6 +1574,17 @@
       keydown '.'
       expect(editor.getText()).toBe "abababccc123\nabababccc4567"

+    it "stores for repeating only the last batch of characters", ->
+      keydown 'i'
+      editor.insertText("abc")
+      atom.commands.dispatch editorElement, 'vim-mode:move-left-insert'
+      editor.insertText("de")
+      keydown 'escape'
+      expect(editor.getText()).toBe "abdec123\nabdec4567"
+
+      keydown '.'
+      expect(editor.getText()).toBe "abddeec123\nabddeec4567"
+
   describe 'the a keybinding', ->
     beforeEach ->
       editor.setText('')


Squish all the printing into one call

Squish all the printing into one call

--- src/browser/main.coffee
+++ src/browser/main.coffee
@@ -84,10 +84,13 @@
   compileCache.setAtomHomeDirectory(process.env.ATOM_HOME)

 fullVersion = ->
-  process.stdout.write("Atom    : #{app.getVersion()}\n")
-  process.stdout.write("Electron: #{process.versions.electron}\n")
-  process.stdout.write("Chrome  : #{process.versions.chrome}\n")
-  process.stdout.write("Node    : #{process.versions.node}\n")
+  process.stdout.write """
+    Atom    : #{app.getVersion()}
+    Electron: #{process.versions.electron}
+    Chrome  : #{process.versions.chrome}
+    Node    : #{process.versions.node}
+
+  """

 parseCommandLine = ->
   version = app.getVersion()


Correct order of refresh steps

Correct order of refresh steps

--- spec/root-view-spec.coffee
+++ spec/root-view-spec.coffee
@@ -19,12 +19,12 @@
     viewState = null

     refreshRootViewAndProject = ->
-      project2 = atom.replicate().get('project')
-      atom.project = project2
       rootViewState = atom.rootView.serialize()
       atom.project.getState().serializeForPersistence()
+      project2 = atom.replicate().get('project')
       atom.rootView.remove()
       atom.project.destroy()
+      atom.project = project2
       atom.rootView = atom.deserializers.deserialize(rootViewState)
       atom.rootView.attachToDom()


Test tree view context menu

Test tree view context menu

--- spec/todo-show-spec.coffee
+++ spec/todo-show-spec.coffee
@@ -191,6 +191,40 @@
         expect(todos[0].text).toBe 'Comment in C'
         expect(todos[0].file).toBe 'sample.c'

+  describe 'when the tree view context menu is selected', ->
+    beforeEach ->
+      atom.commands.dispatch(workspaceElement, 'todo-show:find-in-workspace')
+      waitsForPromise -> activationPromise
+      runs ->
+        waitsFor ->
+          !showTodoModule.showTodoView.isSearching() and showTodoModule.showTodoView.isVisible()
+
+    it 'searches for todos in the selected folder', ->
+      expect(showTodoModule.collection.getTodosCount()).toBe nTodos
+
+      event =
+        target:
+          getAttribute: ->
+            path.join(__dirname, 'fixtures/sample1/sample.c')
+      showTodoModule.show(undefined, event)
+
+      waitsFor -> !showTodoModule.showTodoView.isSearching()
+      runs ->
+        expect(showTodoModule.collection.getCustomPath()).toBe 'sample.c'
+        expect(showTodoModule.collection.scope).toBe 'custom'
+        expect(showTodoModule.collection.getTodosCount()).toBe 1
+
+    it 'handles missing path in event argument', ->
+      event =
+        target:
+          getAttribute: ->
+            undefined
+      showTodoModule.show(undefined, event)
+
+      waitsFor -> !showTodoModule.showTodoView.isSearching()
+      runs ->
+        expect(showTodoModule.collection.getTodosCount()).toBe nTodos
+
   describe 'status bar indicator', ->
     todoIndicatorClass = '.status-bar .todo-status-bar-indicator'


Construct Workspace with all dependencies in specs

--- spec/workspace-spec.coffee
+++ spec/workspace-spec.coffee
@@ -17,6 +17,7 @@
     atom.workspace = workspace = new Workspace({
       config: atom.config, project: atom.project, packageManager: atom.packages,
       grammarRegistry: atom.grammars, notificationManager: atom.notifications,
+      clipboard: atom.clipboard, viewRegistry: atom.views,
       setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'),
       setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion()
     })
@@ -33,8 +34,9 @@
       atom.workspace = new Workspace({
         config: atom.config, project: atom.project, packageManager: atom.packages,
         grammarRegistry: atom.grammars, notificationManager: atom.notifications,
+        clipboard: atom.clipboard, viewRegistry: atom.views,
         setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'),
-        setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion()
+        setDocumentEdited: setDocumentEdited
       })
       atom.workspace.deserialize(workspaceState, atom.deserializers)

@@ -631,6 +633,7 @@
       workspace2 = new Workspace({
         config: atom.config, project: atom.project, packageManager: atom.packages,
         grammarRegistry: atom.grammars, notificationManager: atom.notifications,
+        clipboard: atom.clipboard, viewRegistry: atom.views,
         setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'),
         setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion()
       })
@@ -689,6 +692,7 @@
         workspace2 = new Workspace({
           config: atom.config, project: atom.project, packageManager: atom.packages,
           grammarRegistry: atom.grammars, notificationManager: atom.notifications,
+          clipboard: atom.clipboard, viewRegistry: atom.views,
           setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'),
           setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion()
         })


Added unit tests to check newline char saving

--- specs/somewhereSpec.coffee
+++ specs/somewhereSpec.coffee
@@ -60,6 +60,10 @@
     it "should return a new collection with 1 element on save", ->
       item = db.save 'books', title: 'Testable JavaScript'
       expect(db.database.books.length).to.equal 1
+
+    it "should return the item save with new line char", ->
+      item = db.save 'books', title: 'Beyond the line: \r\n The Good Way'
+      expect(item.title).to.equal 'Beyond the line: \r\n The Good Way'

   describe "Check findOne, find, update and remove methods", ->
     db = new DB './mochaTest.json'
@@ -152,5 +156,17 @@
       item = db.remove 'users', '12345'
       expect(item).to.equal false

+    it "should save an item with newline char", ->
+      user =
+        username: 'martinfowler'
+        name: 'Martin'
+        blog: 'martinfowler.com'
+        source: 'twitter'
+        description: 'Programmer, Loud Mouth. \r\n ThoughtWorker'
+      item = db.save 'users', user
+      result = db.findOne 'users', username: 'martinfowler'
+      expect(result.name).to.equal 'Martin'
+      expect(result.description).to.equal 'Programmer, Loud Mouth. \r\n ThoughtWorker'
+
     it "should clear the database file", ->
-      do db.clear+      do db.clear


Send chunked

Send chunked

--- test/appveyor.coffee
+++ test/appveyor.coffee
@@ -21,13 +21,14 @@
   uri.pathname = path
   uri.headers =
     'Content-Type': 'application/json'
-    'Content-Length': data.length
+    # 'Content-Length': data.length
   q = http.request uri, (res)->
     res.on 'data', ->
     res.on 'end', ->
   q.on 'error', ->
     console.error 'HTTP error!'
-  q.end data
+  q.write data
+  q.end()

 events =
   pending: 'Ignored'


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com


initial specs for new set function

initial specs for new set function

--- test/mainSpec.coffee
+++ test/mainSpec.coffee
@@ -27,9 +27,10 @@
         it 'should properly extend context', ->
           expect(_(context).keys()).toEqual ['jasmine']
           JasmineSugar.setup(context)
-          expect(_(context).keys()).toEqual ['jasmine', 'it', 'fit']
+          expect(_(context).keys()).toEqual ['jasmine', 'it', 'fit', 'set']
           expect(typeof(context.it)).toBe 'function'
           expect(typeof(context.fit)).toBe 'function'
+          expect(typeof(context.set)).toBe 'function'

       describe 'jasmine without getEnv() present on origin context', ->
         beforeEach ->
@@ -86,4 +87,3 @@
           expect(JasmineMock.fit).toHaveBeenCalled()
           expect(JasmineMock.fit.calls.count()).toBe 1
           expect(JasmineMock.fit.calls.argsFor(0)).toEqual args
-


ace mode for LiveScript and stylus

ace mode for LiveScript and stylus

--- assets/js/services/modes.coffee
+++ assets/js/services/modes.coffee
@@ -54,6 +54,10 @@
       less:
         title: "Less"
         extensions: ["less"]
+      livescript:
+        title: "LiveScript"
+        extensions: ["ls"]
+        snips: true
       lua:
         title: "Lua"
         extensions: ["lua"]
@@ -85,6 +89,9 @@
       scss:
         title: "SCSS"
         extensions: ["scss"]
+      stylus:
+        title: "Stylus"
+        extensions: ["styl"]
       ruby:
         title: "Ruby"
         extensions: ["rb", "rbx"]


add proxy for http traffic

add proxy for http traffic

--- server.coffee
+++ server.coffee
@@ -389,10 +389,12 @@
 app.get "/communities/:community/:topic", renderIndexPage

-
-port = process.env.PORT || 8090
 if nconf.get("NODE_ENV") == "development"
-  http.createServer(app).listen port
+  http.createServer(app).listen 8090
 else
+  proxyServer = express.createServer()
+  proxyServer.get "*", (req, res) ->
+    res.redirect "https://gitcommunities.com" + req.url
+  proxyServer.listen 80
   https.createServer(sslOptions, app).listen 443
-console.log "server started on port #{port}. Open http://localhost:#{port} in your browser"  +console.log "server started on port"


Distinguish between partner and server disconnects

--- server.coffee
+++ server.coffee
@@ -135,7 +135,6 @@
 			console.log "#{ dtNow() } #{ data.message }"

 	leaveHandler = ->
-		console.log "#{ conn.id } disconnected"
 		lobby = lobby.filter (v) ->
 			return v.id != conn.id
 		if conn.partner?
@@ -143,7 +142,9 @@
 			conn.partner.partner = null

 	conn.on 'leave', ->
+		console.log "#{ conn.id } disconnected from their partner"
 		leaveHandler()

 	conn.on 'close', (data) ->
+		console.log "#{ conn.id } disconnected from the server"
 		leaveHandler()


Update server.coffee

Update server.coffee

Test if the selector passed to remove() is a String or Object else return 0

--- server.coffee
+++ server.coffee
@@ -990,7 +990,8 @@
   ###
   remove: (selector, callback) ->
     @_debug "[FilesCollection] [remove(#{JSON.stringify(selector)})]"
-    check selector, Match.OneOf Object, String
+    if !Match.test(selector, Match.OneOf(String, Object))
+      return 0
     check callback, Match.Optional Function

     files = @collection.find selector


Revert percentage-correction for now

Revert percentage-correction for now

--- server.coffee
+++ server.coffee
@@ -212,11 +212,11 @@
 		score = value[1]
 		resultsObj[pos+1] = userId # one-based

-		vCnt = voteCnt
-		if (rankings = Db.personal(userId).get('rankings', roundId)) and rankings[1] and rankings[2]
-			vCnt-- # this user voted as well, but couldn't have voted for him/herself
-
-		percsObj[pos+1] = Math.round(score / (vCnt * 3) * 100)
+		#vCnt = voteCnt
+		#if (rankings = Db.personal(userId).get('rankings', roundId)) and rankings[1] and rankings[2]
+		#	vCnt-- # this user voted as well, but couldn't have voted for him/herself
+
+		percsObj[pos+1] = Math.round(score / (voteCnt * 3) * 100)
 			# this uses the max-score of 3 (see above as well) to calculate
 			# the percentage of max possible points received
 		break if pos is 2 # pos 0, 1, 2


fix game removal issue

fix game removal issue

--- server.coffee
+++ server.coffee
@@ -94,15 +94,16 @@
         lobby.emit('netrunner', {type: "games", games: games, notification: "ting"})

       when "leave-lobby"
-        gameid = socket.gameid
+        gid = socket.gameid
         removePlayer(socket)
         if socket.request.user
-          socket.broadcast.to(gameid).emit('netrunner', {type: "say", user: "__system__", text: "#{socket.request.user.username} left the game."})
+          socket.broadcast.to(gid).emit('netrunner', {type: "say", user: "__system__", text: "#{socket.request.user.username} left the game."})

       when "leave-game"
+        gid = socket.gameid
+        removePlayer(socket)
         msg.action = "quit"
-        removePlayer(socket)
-        game = games[socket.gameid]
+        game = games[gid]
         requester.send(JSON.stringify(msg)) if game and game.players.length > 1

       when "join"


ClampBounds docs

ClampBounds docs

--- src/clamp_bounds.coffee
+++ src/clamp_bounds.coffee
@@ -28,18 +28,6 @@
   # => 311.5 # The default App.height (320) - half the player's height

-

-# Shoot Timeout
-player = GameObject()
-
-player.cooldown "shootTimer"
-
-player.I.shootTimer = 10 # => Pew! Pew!
-
-player.I.update()
-
-player.I.shootTimer # => 9
-

 @name Cooldown
 @module


Support \cite in figure captions, fix \ref. #109

--- client/import.iced
+++ client/import.iced
@@ -244,6 +244,19 @@
           abbrev: abbrev
           url: match[2][1...-1]

+  processCites = (tex) ->
+    tex.replace /\\cite\s*(?:\[([^\[\]]*)\]\s*)?{([^{}]*)}/g, (match, p1, p2) ->
+      '[' + (
+        for cite in p2.split ','
+          cite = cite.trim()
+          bib = bibs[cite]
+          if bib?
+            "\\href{#{bib.url}}{#{bib.abbrev}}"
+          else
+            console.warn "Missing bib url for '#{cite}'" unless bib?
+            cite
+      ).join(', ') + (if p1? then ", #{p1}" else '') + ']'
+
   ## Extract figures.
   figures = {}
   for filename, content of zip.files
@@ -264,7 +277,7 @@
               console.warn "Missing file for \\includegraphics{#{graphics}}"
             graphics.push filename
           caption = /\\caption\s*{((?:[^{}]|{[^{}]*})*)}/.exec p2
-          caption = caption[1]
+          caption = processCites caption[1]
           labels = []
           lr = /\\label\s*{((?:[^{}]|{[^{}]*})*)}/g
           while (match = lr.exec p2)?
@@ -285,17 +298,7 @@
       tex = tex
       .replace /%.*$\n?/mg, ''
       .replace /\\begin\s*{(wrap)?figure}[^\0]*?\\end\s*{(wrap)?figure}\s*/g, ''
-      .replace /\\cite\s*(?:\[([^\[\]]*)\]\s*)?{([^{}]*)}/g, (match, p1, p2) ->
-        '[' + (
-          for cite in p2.split ','
-            cite = cite.trim()
-            bib = bibs[cite]
-            if bib?
-              "\\href{#{bib.url}}{#{bib.abbrev}}"
-            else
-              console.warn "Missing bib url for '#{cite}'" unless bib?
-              cite
-        ).join(', ') + (if p1? then ", #{p1}" else '') + ']'
+      tex = processCites tex
       depths = []
       start = null
       labels = {}
@@ -332,7 +335,7 @@
       for message in messages
         attach = []
         message.body = message.body
-        .replace /\\ref\s*{([^{}]*)}/, (match, p1) ->
+        .replace /\\ref\s*{([^{}]*)}/g, (match, p1) ->
           if p1 of labels
             labels[p1]
           else if p1 of figures


Make the linter happy

Make the linter happy

--- framer/Components/SliderComponent.coffee
+++ framer/Components/SliderComponent.coffee
@@ -23,6 +23,7 @@

 	constructor: (options) ->
 		super options
+

 class exports.SliderComponent extends Layer


config: separate hyperplane public and private urls

--- src/config.coffee
+++ src/config.coffee
@@ -15,7 +15,7 @@
           REPLACE_ENV_HYPERPLANE_ADMIN_PASSWORD? and
             REPLACE_ENV_HYPERPLANE_ADMIN_PASSWORD or
           'insecurepassword'
-  HYPERPLANE_API_URL: process.env.PUBLIC_HYPERPLANE_API_URL or
+  HYPERPLANE_API_URL: process.env.HYPERPLANE_API_URL or
           REPLACE_ENV_PUBLIC_HYPERPLANE_API_URL? and
             REPLACE_ENV_PUBLIC_HYPERPLANE_API_URL or
           'http://localhost:50180'


Fix up logic and indentation problems.

Fix up logic and indentation problems.

--- script/worker.coffee
+++ script/worker.coffee
@@ -2,16 +2,16 @@
 spawn       = require('child_process').spawn
 Repository  = require('../models/repository').Repository
 Build       = require('../models/build').Build
-resque      = require('../config/resque')
+Resque      = require('../config/resque').Connection
 mongoose    = require('../config/mongoose')
 redis       = require('../config/redis')
 ObjectId    = require('mongoose').Types.ObjectId

-Jobs =
+Jobs =
   succeed: (arg, callback) ->
     callback

-  fail: (arg, callback) ->
+  fail: (arg, callback) ->
     callback new Error 'fail'

   build: (build, callback) ->
@@ -27,123 +27,123 @@
       if err
         throw err

-      console.log 'Repository found, id:['+repository._id+'] url:['+repository.url+'], num builds:['+repository.builds.length+']'
-
-      buildRepository = repository
+        console.log 'Repository found, id:['+repository._id+'] url:['+repository.url+'], num builds:['+repository.builds.length+']'
+
+        buildRepository = repository

-      build = repository.builds.id buildId
+        build = repository.builds.id buildId

-      buildStart = ->
-        build.startedAt = Date.now()
-        build.running   = true
-        repository.save (err) ->
-          if err
-            throw err
-          spawnCloneDir
+        buildStart = ->
+          build.startedAt = Date.now()
+          build.running   = true
+          repository.save (err) ->
+            if err
+              throw err
+            spawnCloneDir

-      spawnCloneDir = ->
-        name = 'mkdir';
-        workingDir = ['/tmp/', 'dripio', repository.ownerName, repository.name, Date.now()].join('_');
-        console.log "making directory ["+workingDir+"]..."
-        cmds[name] = spawn('mkdir',['-vp',workingDir])
-        cmdOut.bind(name, spawnClone)
+        spawnCloneDir = ->
+          name = 'mkdir'
+          workingDir = ['/tmp/', 'dripio', repository.ownerName, repository.name, Date.now()].join('_')
+          console.log "making directory ["+workingDir+"]..."
+          cmds[name] = spawn('mkdir',['-vp',workingDir])
+          cmdOut.bind(name, spawnClone)

-      spawnClone = ->
-        name = 'clone'
-        console.log "cloning ["+repository.url+"]..."
-        cmds[name] = spawn('git', ['clone',repository.url, workingDir], {cwd: workingDir, setsid: false})
-        cmdOut.bind(name, spawnCheckout)
-
-      spawnCheckout = ->
-        name = 'checkout'
-        console.log "checkout ["+build.branch+"]..."
-        cmds[name] = spawn('git', ['checkout',build.branch], {cwd: workingDir, setsid: false})
-        cmdOut.bind(name, spawnNpmInstall)
+        spawnClone = ->
+          name = 'clone'
+          console.log "cloning ["+repository.url+"]..."
+          cmds[name] = spawn('git', ['clone',repository.url, workingDir], {cwd: workingDir, setsid: false})
+          cmdOut.bind(name, spawnCheckout)
+
+        spawnCheckout = ->
+          name = 'checkout'
+          console.log "checkout ["+build.branch+"]..."
+          cmds[name] = spawn('git', ['checkout',build.branch], {cwd: workingDir, setsid: false})
+          cmdOut.bind(name, spawnNpmInstall)

-      spawnNpmInstall = ->
-        name = 'npm_install'
-        console.log("running npm install...")
-        cmds[name] = spawn('npm',['install'], {cwd: workingDir})
-        cmdOut.bind(name, spawnNpmTest)
+        spawnNpmInstall = ->
+          name = 'npm_install'
+          console.log("running npm install...")
+          cmds[name] = spawn('npm',['install'], {cwd: workingDir})
+          cmdOut.bind(name, spawnNpmTest)

-      spawnNpmTest = ->
-        name = 'npm_test'
-        console.log("running npm test...")
-        cmds[name] = spawn('npm',['test'], {cwd: workingDir})
-        cmdOut.bind(name, buildFinish)
+        spawnNpmTest = ->
+          name = 'npm_test'
+          console.log("running npm test...")
+          cmds[name] = spawn('npm',['test'], {cwd: workingDir})
+          cmdOut.bind(name, buildFinish)

-      buildFinish = ->
-        name = 'finish'
-        build.finishedAt = Date.now()
-        console.log("finishing build and cleaning-up ["+build.finishedAt+"]...")
-        build.completed  = true
-        build.running    = false
-        build.successful = stepsSuccessful
-        repository.save (err) ->
-          if err
-            throw err
-
-        cmds[name] = spawn('rm',['-vrf', workingDir])
-        cmdOut.bind(name)
+        buildFinish = ->
+          name = 'finish'
+          build.finishedAt = Date.now()
+          console.log("finishing build and cleaning-up ["+build.finishedAt+"]...")
+          build.completed  = true
+          build.running    = false
+          build.successful = stepsSuccessful
+          repository.save (err) ->
+            if err
+              throw err
+
+          cmds[name] = spawn('rm',['-vrf', workingDir])
+          cmdOut.bind(name)

-      cmdOut =
-        bind: (name, next) ->
-          spawn = cmds[name]
-          this.stdout(spawn,name)
-          this.stderr(spawn,name)
-          this.exit(spawn,name,next)
+        cmdOut =
+          bind: (name, next) ->
+            spawn = cmds[name]
+            this.stdout(spawn,name)
+            this.stderr(spawn,name)
+            this.exit(spawn,name,next)

-        stdout: (spawn, name) ->
-          spawn.stdout.on 'data', (data) ->
-            console.log 'stdout '+name+' ['+workingDir+']: ' + data
-            redis.rpush "builds:" + build.id, data, ->
-              console.log "Issued write to redis"
-            outputBuffer.push data
+          stdout: (spawn, name) ->
+            spawn.stdout.on 'data', (data) ->
+              console.log 'stdout '+name+' ['+workingDir+']: ' + data
+              redis.rpush "builds:" + build.id, data, ->
+                console.log "Issued write to redis"
+              outputBuffer.push data

-        stderr: (spawn, name) ->
-          spawn.stderr.on 'data', (data) ->
-            console.log 'stderr '+name+' ['+workingDir+']: ' + data
-            redis.rpush "builds:" + build.id, data, ->
-              console.log "Issued write to redis"
-            outputBuffer.push data
+          stderr: (spawn, name) ->
+            spawn.stderr.on 'data', (data) ->
+              console.log 'stderr '+name+' ['+workingDir+']: ' + data
+              redis.rpush "builds:" + build.id, data, ->
+                console.log "Issued write to redis"
+              outputBuffer.push data

-        exit: (spawn, name, next) ->
-          spawn.on 'exit', (code) ->
-            console.log 'exit '+name+' ['+workingDir+'] code: ' + code
-
-            buildRepository.save (err) ->
-              if err
-                throw err
-
-            if code == 0
-              console.log 'clean exit; calling next() if present'
-              stepsSuccessful = true
-
-              if typeof(next) == 'function'
-                next
-            else
-              console.log 'unclean exit; not progressing to next, typeof: '+typeof(next)
-              stepsSuccessful = false
-              build.finishedAt = Date.now()
-
-              console.log "finishing build at ["+build.finishedAt+"]..."
-              build.completed  = true
-              build.running    = false
-              build.successful = stepsSuccessful
-              repository.save (err) ->
+          exit: (spawn, name, next) ->
+            spawn.on 'exit', (code) ->
+              console.log 'exit '+name+' ['+workingDir+'] code: ' + code
+
+              buildRepository.save (err) ->
                 if err
                   throw err
+
+              if code == 0
+                console.log 'clean exit; calling next() if present'
+                stepsSuccessful = true
+
+                if typeof(next) == 'function'
+                  next
+              else
+                console.log 'unclean exit; not progressing to next, typeof: '+typeof(next)
+                stepsSuccessful = false
+                build.finishedAt = Date.now()

-      buildStart
-
-    console.log 'Build finished.'
+                console.log "finishing build at ["+build.finishedAt+"]..."
+                build.completed  = true
+                build.running    = false
+                build.successful = stepsSuccessful
+                repository.save (err) ->
+                  if err
+                    throw err

-    callback build
+        buildStart
+
+        console.log 'Build finished.'

-worker        = resque.worker('builder', Jobs)
-workerCleanup = require('../lib/worker.js').workerCleanup
+        callback build
+
+worker        = Resque.worker('builder', Jobs)
+workerCleanup = require('../lib/worker').workerCleanup

 worker.on 'job', (worker, queue, job) ->
   console.log 'Attempting job; worker: ' + worker + ' queue: ' + queue + ' job: ' + job

-worker.start
+worker.start()


fix cursor position munging

fix cursor position munging

--- kapuut/edit.coffee
+++ kapuut/edit.coffee
@@ -74,7 +74,9 @@
                 console.log getQuestion()
             else
                 locked = yes
+                position = questionEditor.getCursorPosition()
                 questionEditor.setValue getQuestion().text, 1
+                questionEditor.moveCursorToPosition position
             locked = no

     quizPropChange = (selector, name) ->


:penguin: Map F11 to toggle full screen

:penguin: Map F11 to toggle full screen

--- keymaps/linux.cson
+++ keymaps/linux.cson
@@ -11,6 +11,7 @@
   'ctrl-alt-p': 'window:run-package-specs'
   'ctrl-alt-s': 'application:run-all-specs'
   'ctrl-shift-o': 'application:open-dev'
+  'F11': 'window:toggle-full-screen'

   # Sublime Parity
   'ctrl-N': 'application:new-window'


Fix path encoding on server

Fix path encoding on server

--- Learn-server/handleImage.coffee
+++ Learn-server/handleImage.coffee
@@ -1,6 +1,7 @@

 fs = require 'fs'
 crypto = require 'crypto'
+path = require 'path'

 createHashID = ->
   crypto.createHash('sha1').update("#{Math.random()}").digest('hex');
@@ -8,7 +9,7 @@
 module.exports = (file, callback) ->
   return callback("No `image` file. Make sure the `image` field is being set.") unless file

-  path = "#{global.image_path}#{createHashID()}_#{file.name}"
+  path = path.normalize "#{global.image_path}#{createHashID()}_#{file.name}"
   fs.rename file.path, path, (error) ->
     return callback(error) if error
     callback null, path


tried the hearts again

tried the hearts again

--- scripts/karma.coffee
+++ scripts/karma.coffee
@@ -57,7 +57,7 @@
      'Yeah, Fuck'

   doubleIncrementResponse: ->
-     '<3 <3'
+     '♥ ♥'

   get: (thing) ->
     k = if @cache[thing] then @cache[thing] else 0


activity: activate search back in public channels

--- client/activity/lib/components/publicchatpane/index.coffee
+++ client/activity/lib/components/publicchatpane/index.coffee
@@ -63,7 +63,7 @@
     { thread } = @props

     footerInnerComponent = if @channel 'isParticipant'
-    then <ChatInputWidget onSubmit={@bound 'onSubmit'} thread={thread}  />
+    then <ChatInputWidget onSubmit={@bound 'onSubmit'} thread= {thread} enableSearch={yes} />
     else @renderFollowChannel()

     <footer className="PublicChatPane-footer">


Client: Activity: Passed addIntegration, inviteOthers and  startCollaboration event handler props to champagne component

--- client/activity/lib/components/publicchatpane/index.coffee
+++ client/activity/lib/components/publicchatpane/index.coffee
@@ -3,8 +3,8 @@
 immutable       = require 'immutable'
 ActivityFlux    = require 'activity/flux'
 ChatPane        = require 'activity/components/chatpane'
+ChatInputFlux   = require 'activity/flux/chatinput'
 ChatInputWidget = require 'activity/components/chatinputwidget'
-

 module.exports = class PublicChatPane extends React.Component
@@ -43,6 +43,24 @@
     ActivityFlux.actions.channel.followChannel @channel 'id'

+  startCollaboration: (event) ->
+
+    kd.utils.stopDOMEvent event
+    console.log 'startCollaboration clicked!'
+
+
+  inviteOthers: (event) ->
+
+    kd.utils.stopDOMEvent event
+    ChatInputFlux.actions.value.setValue @props.thread.get('channelId'), '/invite '
+
+
+  addIntegration: (event) ->
+
+    kd.utils.stopDOMEvent event
+    ChatInputFlux.actions.value.setValue @props.thread.get('channelId'), '/'
+
+
   renderFollowChannel: ->

     <div className="PublicChatPane-subscribeContainer">
@@ -74,11 +92,14 @@
   render: ->

     <ChatPane
-      thread     = { @props.thread }
-      className  = "PublicChatPane"
-      messages   = { @props.messages }
-      onSubmit   = { @bound 'onSubmit' }
-      onLoadMore = { @bound 'onLoadMore' }
+      thread             = { @props.thread }
+      className          = "PublicChatPane"
+      messages           = { @props.messages }
+      onSubmit           = { @bound 'onSubmit' }
+      onLoadMore         = { @bound 'onLoadMore' }
+      inviteOthers       = { @bound 'inviteOthers' }
+      addIntegration     = { @bound 'addIntegration' }
+      startCollaboration = { @bound 'startCollaboration' }
     >
       {@renderFooter()}
     </ChatPane>


Workspace: Removed dummy terminal resizing stuff.

--- client/app/CommonViews/workspace/panes/terminalpane.coffee
+++ client/app/CommonViews/workspace/panes/terminalpane.coffee
@@ -8,8 +8,6 @@

     @createWebTermView()
     @webterm.on "WebTermConnected", (@remote) => @onWebTermConnected()
-
-    @on "PaneResized", @bound "forceResize"

   createWebTermView: ->
     @webterm           = new WebTermView
@@ -30,16 +28,6 @@
         @runCommand command
         @triedAgain = yes

-  viewAppended: ->
-    super
-    @forceResize()
-
-  forceResize: ->
-    # TODO: fatihacet - temp fix, 37 is the height of top header bar.
-    # I need to set split view's height as its normal height - 37.
-    # It will be fixed, when I am done with KDSplitComboView.
-    @setHeight @parent.getHeight() - 37
-
   pistachio: ->
     """
       {{> @header}}


Use hostnameAlias instead hostname.

Use hostnameAlias instead hostname.

--- client/landing/app/MainApp/VirtualizationController.coffee
+++ client/landing/app/MainApp/VirtualizationController.coffee
@@ -121,7 +121,7 @@
         return new KDNotificationView
           title : err.message or "Something bad happened while creating VM"
       else
-        KD.getSingleton("finderController").mountVm vm.hostname
+        KD.getSingleton("finderController").mountVm vm.hostnameAlias
         vmController.emit 'VMListChanged'
         vmController.showVMDetails vm

@@ -196,8 +196,8 @@
       else vmController.createPaidVM()

   showVMDetails: (vm)->
-    vmName = vm.hostname
-    url    = "https://#{vm.hostname}"
+    vmName = vm.hostnameAlias
+    url    = "https://#{vm.hostnameAlias}"

     content = """
                 <div class="item">


Add Cursor::getMarker() method

Add Cursor::getMarker() method

--- src/cursor.coffee
+++ src/cursor.coffee
@@ -171,6 +171,10 @@
   Section: Cursor Position Details
   ###

+  # Public: Returns the underlying {Marker} for the cursor.
+  # Useful with overlay {Decoration}s.
+  getMarker: -> @marker
+
   # Public: Identifies if the cursor is surrounded by whitespace.
   #
   # "Surrounded" here means that the character directly before and after the


Prevent compilation of test files into app.js.

--- brunch-config.coffee
+++ brunch-config.coffee
@@ -1,7 +1,8 @@
 exports.config =
   files:
     javascripts:
-      joinTo: 'js/app.js'
+      joinTo:
+        'js/app.js': /^(vendor|bower_components|app)/

     stylesheets:
       joinTo: 'css/app.css'


triggers

triggers

--- src/drizzy.coffee
+++ src/drizzy.coffee
@@ -190,22 +190,12 @@
 ]

 module.exports = (robot) ->
-  robot.respond /simpsons quote me\b/i, (msg) ->
-     msg.send msg.random quotes
-
-  robot.respond /simpsons image me\b/i, (msg) ->
-      simpsonMe(msg, 1)
-
-  robot.respond /simpsons version\b/i, (msg) ->
+  robot.respond /drizzy quote me\b/i, (msg) ->
+      msg.send msg.random quotes
+
+  robot.respond /drake quote me\b/i, (msg) ->
+      msg.send msg.random quotes
+
+  robot.respond /drizzy version\b/i, (msg) ->
       msg.send require('../package').version

-    simpsonMe = (msg, num) ->
-      msg.http("https://api.imgur.com/3/gallery/r/TheSimpsons.json")
-       .headers(Authorization: 'Client-ID 8e4f0ec64cc27f6')
-       .get() (err, res, body) ->
-         content = JSON.parse(body)
-         if content.data and content.data.length > 0
-           msg.send (msg.random content.data).link
-         else
-           msg.send "D'oh!  No response from Imgur."
-


Added ability to fetch user summary using custom URL

--- scripts/steam.coffee
+++ scripts/steam.coffee
@@ -61,13 +61,20 @@
             msg.match[2] += if msg.match[2].slice(-1) is "s" then "'" else "'s"
             msg.reply "#{msg.match[2]} Steam ID is: #{id}"

-    robot.respond /steam status (\d+)/i, (msg) ->
-        steam_request msg, "/ISteamUser/GetPlayerSummaries", steamids: msg.match[1], (object) ->
-            player = object.response.players[0]
-            status = if player.communityvisibilitystate is 1 then 'Unavailable (Private)' else personaStates[player.personastate]
-            lastOnline = moment.unix(player.lastlogoff).fromNow()
-            msg.reply "#{msg.match[1]} belongs to #{player.personaname} who is currently #{status} and was last online #{lastOnline}."
-        , 2
+    robot.respond /steam status (.*)/i, (msg) ->
+        summary = (steamID) ->
+            steam_request msg, "/ISteamUser/GetPlayerSummaries", steamids: steamID, (object) ->
+                player = object.response.players[0]
+                status = if player.communityvisibilitystate is 1 then 'Unavailable (Private)' else personaStates[player.personastate]
+                lastOnline = moment.unix(player.lastlogoff).fromNow()
+                msg.reply "#{msg.match[1]} belongs to #{player.personaname} who is currently #{status} and was last online #{lastOnline}."
+            , 2
+
+        if msg.match[1].match /\d{17}/
+            summary msg.match[1]
+        else
+            getSteamID msg, msg.match[1], (steamID) ->
+                summary steamID

     robot.respond /dota history (.*)/i, (msg) ->
         [command, value] = msg.match
@@ -133,8 +140,8 @@
                 if msg.match[2].match /\d{17}/
                     playerInfo getCommunityID(msg.match[2])
                 else
-                    getSteamID msg, msg.match[2], (id) ->
-                        playerInfo getCommunityID(id)
+                    getSteamID msg, msg.match[2], (steamID) ->
+                        playerInfo getCommunityID(steamID)

 getSteamID = (msg, customURL, handler) ->
     steam_request msg, "/ISteamUser/ResolveVanityURL", vanityurl: customURL, (object) ->


Avoid exceptions when a live editor is compared with a destroyed one

--- src/editor.coffee
+++ src/editor.coffee
@@ -174,7 +174,8 @@
   # Returns a {Boolean}.
   isEqual: (other) ->
     return false unless other instanceof Editor
-    @buffer.getPath() == other.buffer.getPath() and
+    @isAlive() == other.isAlive() and
+      @buffer.getPath() == other.buffer.getPath() and
       @getScrollTop() == other.getScrollTop() and
       @getScrollLeft() == other.getScrollLeft() and
       @getCursorScreenPosition().isEqual(other.getCursorScreenPosition())


remove debugging changes

remove debugging changes

--- src/editor.coffee
+++ src/editor.coffee
@@ -239,12 +239,11 @@
     this.doSilently( =>
       trackDelta.call(this, =>
         @selection.preserve( =>
-          #Scribe.Normalizer.breakBlocks(@root)
+          Scribe.Normalizer.breakBlocks(@root)
           lines = @doc.lines.toArray()
           lineNode = @root.firstChild
           _.each(lines, (line, index) =>
             while line.node != lineNode
-              debugger
               if line.node.parentNode == @root
                 @doc.normalizer.normalizeLine(lineNode)
                 newLine = @doc.insertLineBefore(lineNode, line)


update dns record when renaming node

update dns record when renaming node

--- code/linode.coffee
+++ code/linode.coffee
@@ -62,8 +62,17 @@
       @client.call 'linode.update',
           'LinodeID': instance.id
           'Label': newname
-         , (err, res) ->
-           callback err
+         , (err, res) =>
+           @client.call 'domain.resource.list',
+             DomainID: 352960
+             , (err, res) =>
+               r = _.find res, (x) =>
+                 x.NAME == name
+               @client.call 'domain.resource.update',
+                 DomainID: 352960
+                 ResourceID: r.RESOURCEID
+                 Name: newname
+                 , callback

   @get_comment: (name, callback) ->
     @get name, (instance) =>


errors: MaxStanzaSizeExceeded extends Error

--- src/errors.coffee
+++ src/errors.coffee
@@ -75,6 +75,6 @@

 ##
 # Thrown by Connection.send()
-class exports.MaxStanzaSizeExceeded
+class exports.MaxStanzaSizeExceeded extends Error
     constructor: (bytes) ->
         super("Maximum stanza size exceeded (#{bytes} bytes)")


We have 1.4 on the machine.

We have 1.4 on the machine.

--- resources/assets/js/outer/versions.coffee
+++ resources/assets/js/outer/versions.coffee
@@ -162,7 +162,7 @@
     "5.6.2"
   ]

-  golang: '1.3'
+  golang: '1.4'
   erlang: 'r14b04'

   default_java_package: "oraclejdk7"


Fix FF behavior once and for all

Fix FF behavior once and for all

--- coffee/main.coffee
+++ coffee/main.coffee
@@ -23,6 +23,17 @@
       $(this).trigger('click').trigger('click')

+position = (e) ->
+  if e.offsetX?
+    {left: e.offsetX, top: e.offsetY}
+  else
+    p = $(e.delegateTarget).position()
+    {
+      left: e.pageX - p.left,
+      top: e.pageY - p.top,
+    }
+
+
 $.fn.literallycanvas = ->
   @nodoubletapzoom()

@@ -35,19 +46,24 @@
   $c.mousedown (e) =>
     e.originalEvent.preventDefault();
     document.onselectstart = -> false # disable selection while dragging
-    lc.begin(e.offsetX, e.offsetY)
+    p = position(e)
+    console.log p
+    lc.begin(p.left, p.top)

   $c.mousemove (e) =>
     e.originalEvent.preventDefault();
-    lc.continue(e.offsetX, e.offsetY)
+    p = position(e)
+    lc.continue(p.left, p.top)

   $c.mouseup (e) =>
     e.originalEvent.preventDefault();
     document.onselectstart = -> true # disable selection while dragging
-    lc.end(e.offsetX, e.offsetY)
+    p = position(e)
+    lc.end(p.left, p.top)

   $c.mouseout (e) =>
-    lc.end(e.offsetX, e.offsetY)
+    p = position(e)
+    lc.end(p.left, p.top)

   $c.bind 'touchstart', (e) ->
     e.preventDefault()


add Array#clear

add Array#clear

--- coffee/util.coffee
+++ coffee/util.coffee
@@ -13,6 +13,14 @@
   String.prototype.isBlank = () ->
     return !this? || this.trim?() is ''

+###
+ clear array.
+###
+if not ('clear' in Array.prototype)
+  Array.prototype.clear = () ->
+    while (this.length > 0) then this.pop()
+    return
+

 @util = {


Move home() to voxel-player

Move home() to voxel-player

Requires deathcap/voxel-player@95ed1faed3ba3c44b7e8d4b49dbceb1248a343b1

--- index.coffee
+++ index.coffee
@@ -95,7 +95,7 @@
     'voxel-land': {populateTrees: true}
     # note: onDemand so doesn't automatically enable
     'voxel-oculus': { distortion: 0.2, separation: 0.5, onDemand: true } # TODO: switch to voxel-oculus-vr? https://github.com/vladikoff/voxel-oculus-vr?source=c - closer matches threejs example
-    'voxel-player': {image: 'player.png'}
+    'voxel-player': {image: 'player.png', homePosition: [2,14,4], homeRotation: [0,0,0]}
     'voxel-fly': {flySpeed: 0.8, onDemand: true}
     'voxel-gamemode': {}
     'voxel-walk': {}
@@ -133,22 +133,16 @@
   game.appendTo document.body
   return game if game.notCapable()

-  avatar = plugins.get('voxel-player')
-  home(avatar)

   # load textures after all plugins loaded (since they may add their own)
   registry = plugins.get('voxel-registry')
   game.materials.load registry.getBlockPropsAll 'texture'
   global.InventoryWindow_defaultGetTexture = (itemPile) => registry.getItemPileTexture(itemPile) # TODO: cleanup

-  game.buttons.down.on 'pov', () -> avatar.toggle() # TODO: disable/re-enable voxel-walk in 1st/3rd person?
+  game.buttons.down.on 'pov', () -> plugins.get('voxel-player')?.toggle()
   game.buttons.down.on 'vr', () -> plugins.toggle 'voxel-oculus'
-  game.buttons.down.on 'home', () -> home(avatar)
+  game.buttons.down.on 'home', () -> plugins.get('voxel-player')?.home()
   game.buttons.down.on 'inventory', () -> plugins.get('voxel-inventory-dialog')?.show()

   return game

-home = (avatar) ->
-  avatar.yaw.position.set 2, 14, 4
-
-


update the counter only after a certain interval


Use different release directory

Use different release directory

--- index.coffee
+++ index.coffee
@@ -58,7 +58,7 @@
         '--releasify'
         nupkgPath
         '--releaseDir'
-        outputDirectory
+        path.join(outputDirectory, 'release')
         '--loadingGif'
         loadingGif
       ]


Cleanup and simplify checking for valid getStatus() return

--- index.coffee
+++ index.coffee
@@ -69,8 +69,7 @@
   #
   # This command *must* be passed through a formatter before its displayed
   @register 'status', (done) ->
-    status = repo?.getStatus()
-    done null, [] unless status
+    return done null, [] unless status = repo?.getStatus()

     statuses = []
     for path, code of status


Move avatar possess to voxel-player

Move avatar possess to voxel-player

Requires deathcap/voxel-player@5cadc5d8fa640073527e7c1ede3831daa8b2eb65

--- index.coffee
+++ index.coffee
@@ -134,7 +134,6 @@
   return game if game.notCapable()

   avatar = plugins.get('voxel-player')
-  avatar.possess()
   home(avatar)

   # load textures after all plugins loaded (since they may add their own)


Remove extra spaces

Remove extra spaces

--- app/assets/javascripts/activeadmin_polymorphic.js.coffee
+++ app/assets/javascripts/activeadmin_polymorphic.js.coffee
@@ -34,7 +34,6 @@

     extractAndInsertForm formPath, rapper

-
   $(document).on 'click', 'a.button.polymorphic_has_many_remove', (e)->
     e.preventDefault()
     parent    = $(@).closest '.polymorphic_has_many_container'
@@ -62,7 +61,6 @@
       parent.trigger 'polymorphic_has_many_add:after', [fieldset, parent]

   init_polymorphic_sortable()
-

   $('.polymorphic_has_many_container').on 'change', '.polymorphic_type_select', (event) ->
     fieldset = $(this).closest 'fieldset'
@@ -114,7 +112,7 @@
     if sortable_input.length
       sortable_input.val if destroy_input.is ':checked' then '' else position++

-window.extractAndInsertForm= (url, target)->
+window.extractAndInsertForm = (url, target)->
   target = $ target

   $.get url, (data)->
@@ -135,7 +133,6 @@
     $(form).on 'submit', -> return false

     $(target).replaceWith(form)
-

 window.remoteSubmit = (target, callback)->
   $(target).data('remote', true)
@@ -169,4 +166,3 @@
         $(target).remove()

       callback()
-


Do not replace the whole form on errors.

--- app/assets/javascripts/activeadmin_polymorphic.js.coffee
+++ app/assets/javascripts/activeadmin_polymorphic.js.coffee
@@ -161,10 +161,12 @@
     # duplicates method above. refactor using callbacks
     elements = $(data)
     form = $('#main_content form', elements).first()
-    $(form).find('.actions').remove()
+    fieldset = form.find('fieldset').first()
+
+    $(fieldset).find('.actions').remove()
     $(form).on 'submit', -> return false

-    $(target).replaceWith(form)
+    $(target).find('fieldset').replaceWith(fieldset)
     container = $(form).closest '.polymorphic_has_many_container'
     container.trigger "polymorphic_has_many_form:inserted", [ form ]


update backbone router

update backbone router

--- app/assets/javascripts/backbone/routers/router.js.coffee
+++ app/assets/javascripts/backbone/routers/router.js.coffee
@@ -11,8 +11,6 @@
     users = new App.Models.Users
     users.fetch()

-    collectionView = new App.Views.Users
-      collection: users
-    $("#users").html(collectionView.render().el)
+


Hide arrange functionality when user doesn't have edit permissions

--- app/assets/javascripts/components/timeline/timeline.cjsx
+++ app/assets/javascripts/components/timeline/timeline.cjsx
@@ -216,19 +216,20 @@

     )

-    if @props.reorderable
-      reorderable_controls = (
-

-
Arrange Blocks

-
Arrange blocks by ‘dragging & dropping’ into the desired location/week, or reposition the blocks using the arrows on the card.

-

-      )
-    else if @props.editable_block_ids.length == 0
-      reorderable_controls = (
-

-          <button className="button border button--block" onClick={@props.enableReorderable}>Arrange Blocks</button>
-

-      )
+    if @props.edit_permissions
+      if @props.reorderable
+        reorderable_controls = (
+

+
Arrange Blocks

+
Arrange blocks by ‘dragging & dropping’ into the desired location/week, or reposition the blocks using the arrows on the card.

+

+        )
+      else if @props.editable_block_ids.length == 0
+        reorderable_controls = (
+

+            <button className="button border button--block" onClick={@props.enableReorderable}>Arrange Blocks</button>
+

+        )

     week_nav = week_components.map (week, i) => (
       className = 'week-nav__item'


Add prompt to save when dirty link

Add prompt to save when dirty link

--- app/assets/javascripts/effective_ckeditor/init.js.coffee
+++ app/assets/javascripts/effective_ckeditor/init.js.coffee
@@ -19,7 +19,8 @@
   if ckeditors.length
     $('body').prepend("

").addClass('effective-ckeditor-editting')

-    $(window).on 'beforeunload', (event) -> promptToSaveIfDirty(event)
+    $(window).on 'beforeunload', (event) -> promptToSaveIfDirtyWindow(event)
+    $(document).on 'click', 'a', (event) -> promptToSaveIfDirtyLink(event)
     $(window).on 'unload', (event) -> $.cookie('effective_regions_editting', '', {path: '/', expires: -1})

     ckeditors.each ->
@@ -120,7 +121,7 @@
     imagesPath: CKEDITOR.getUrl( window.location.protocol + '//' + window.location.host + '/assets/effective/templates/' ),
     templates: template for template in templates

-promptToSaveIfDirty = (event) ->
+promptToSaveIfDirtyWindow = (event) ->
   dirty = false

   for name, instance of CKEDITOR.instances
@@ -132,6 +133,17 @@
     'You have unsaved changes'
   else
     event.stopPropagation()
+
+promptToSaveIfDirtyLink = (event) ->
+  dirty = false
+
+  for name, instance of CKEDITOR.instances
+    if instance.checkDirty()
+      dirty = true
+      break
+
+  if dirty && !confirm('You have unsaved changes. Really leave page?')
+    event.preventDefault()

 affixBootstrapMenu = (editor_div) ->
   dropdown_menu = editor_div.closest('.dropdown-menu')


updated to v0.0.48

updated to v0.0.48

--- test/test.coffee
+++ test/test.coffee
@@ -15,6 +15,8 @@
   $$.mkdir(source)
   $$.read(source)
   $$.remove(source)
+  $$.rm(source)
+  $$.write(source, data)

 ###

@@ -22,17 +24,20 @@

   it "$$.backup('./temp/readme.md')", co ->

+    source = './temp/readme.md'
+    target = './temp/readme.md.bak'
+
     yield $$.copy './readme.md', './temp'

-    yield $$.backup './temp/readme.md'
-
-    unless yield $$.isExisted './temp/readme.md.bak'
-      throw new Error()
-
-    sourceData = yield $$.read './temp/readme.md'
-    targetData = yield $$.read './temp/readme.md.bak'
-
-    unless sourceData.toString() == targetData.toString()
+    yield $$.backup source
+
+    unless yield $$.isExisted target
+      throw new Error()
+
+    sourceData = yield $$.read source
+    targetData = yield $$.read target
+
+    if sourceData.toString() != targetData.toString()
       throw new Error()

     # clean
@@ -56,9 +61,11 @@

   it "$$.isExisted('./temp/existed')", co ->

-    yield $$.mkdir './temp/existed'
-
-    unless yield $$.isExisted './temp/existed'
+    source = './temp/existed'
+
+    yield $$.mkdir source
+
+    unless yield $$.isExisted source
       throw new Error()

     # clean
@@ -74,9 +81,11 @@

   it "$$.isExisted('./temp/existed/existed.txt')", co ->

-    yield $$.write './temp/existed/existed.txt', 'existed'
-
-    unless yield $$.isExisted './temp/existed/existed.txt'
+    source = './temp/existed/existed.txt'
+
+    yield $$.write source, 'existed'
+
+    unless yield $$.isExisted source
       throw new Error()

     # clean
@@ -125,13 +134,14 @@

   it "$$.read('./temp/test.txt')", co ->

-    string = 'a test message'
-
-    yield $$.write './temp/test.txt', string
-
-    cont = yield $$.read './temp/test.txt'
-
-    unless cont == string
+    source = './temp/test.txt'
+    string = 'a test message'
+
+    yield $$.write source, string
+
+    cont = yield $$.read source
+
+    if cont != string
       throw new Error()

     # clean
@@ -139,14 +149,15 @@

   it "$$.read('./temp/test.json')", co ->

+    source = './temp/test.json'
     string = 'a test message'
     object = message: string

-    yield $$.write './temp/test.json', object
-
-    cont = yield $$.read './temp/test.json'
-
-    unless cont.message == string
+    yield $$.write source, object
+
+    cont = yield $$.read source
+
+    if cont.message != string
       throw new Error()

     # clean
@@ -164,4 +175,50 @@
       throw new Error()

     # clean
+    yield $$.remove './temp'
+
+describe '$$.rm(source)', ->
+
+  it '$$.rm()', ->
+
+    if $$.rm != $$.remove
+      throw new Error()
+
+describe '$$.write(source, data)', ->
+
+  it "$$.write('./temp/wr/ite.txt', 'a test message')", co ->
+
+    source = './temp/wr/ite.txt'
+    string = 'a test message'
+
+    yield $$.write source, string
+
+    unless yield $$.isExisted source
+      throw new Error()
+
+    cont = yield $$.read source
+
+    if cont != string
+      throw new Error()
+
+    # clean
+    yield $$.remove './temp'
+
+  it "$$.write('./temp/wr/ite.json', {message: 'a test message'})", co ->
+
+    source = './temp/wr/ite.json'
+    string = 'a test message'
+    object = message: string
+
+    yield $$.write source, object
+
+    unless yield $$.isExisted source
+      throw new Error()
+
+    cont = yield $$.read source
+
+    if cont.message != string
+      throw new Error()
+
+    # clean
     yield $$.remove './temp'


OK the check for the pid file should include the actual pid extension.

--- test/test.coffee
+++ test/test.coffee
@@ -13,7 +13,7 @@
 		,500
 	it 'should erase the pid file', (done)->
 		setTimeout ->
-			require('fs').exists pidfile, (exists)->
+			require('fs').exists pidfile+'.pid', (exists)->
 					assert.equal false, exists
 					done()
 		,1000


Fix DB put values test

Fix DB put values test

--- tests/db-test.coffee
+++ tests/db-test.coffee
@@ -64,7 +64,7 @@
       db.approximateSizes '0', '1'

     it 'should put values', (done) ->
-      db.put '' + i, 'Hello World!' for i in [0..999]
+      db.putSync '' + i, 'Hello World!' for i in [0..999]
       db.put '100', 'Goodbye World!', done

     it 'should close database', (done) ->


FasterKoding: made the root path redirected to /Home

--- client/Main/kodingrouter.coffee
+++ client/Main/kodingrouter.coffee
@@ -99,7 +99,7 @@
       if err or not target? then status_404()
       else status_301 target

-  getDefaultRoute:-> if KD.isLoggedIn() then '/Activity' else '/'
+  getDefaultRoute:-> if KD.isLoggedIn() then '/Activity' else '/Home'

   setPageTitle:(title="Koding")-> document.title = Encoder.htmlDecode title


AppController: remove explicit binding to context, use prototype method

--- client/ide/AppController.coffee
+++ client/ide/AppController.coffee
@@ -1922,7 +1922,7 @@
   sendPing: -> @pingTime.setText Date.now().toString()

-  forceQuitCollaboration = ->
+  forceQuitCollaboration: ->

     { Collaboration } = KD.remote.api
     Collaboration.stop @rtmFileId, @workspaceData, (err) =>
@@ -1953,7 +1953,7 @@
       # kill session if `errorTryCount`
       # limit is passed.
       if errorTryCount <= 0
-        forceQuitCollaboration.call this
+        @forceQuitCollaboration()
       # update the lastChecked at if the last ping
       # is still the same, decrease the error try count.
       else if ping is lastPing and errorTryCount > 0


AppController: Put back resurrecting the snapshot.

--- client/ide/AppController.coffee
+++ client/ide/AppController.coffee
@@ -912,7 +912,7 @@
       @listenPings()
       @rtm.isReady = yes
       @emit 'RTMIsReady'
-      # @resurrectSnapshot()
+      @resurrectSnapshot()  unless @amIHost

       unless @myWatchMap.values().length
         @listChatParticipants (accounts) =>


authorize credentials in API

authorize credentials in API

--- services/http.coffee
+++ services/http.coffee
@@ -21,7 +21,7 @@

 # enable middlewares
 addThirdPartyMiddlewares = (app) ->
-    app.use cors()
+    app.use cors credentials: true
     app.use bodyParser.urlencoded extended: true
     # extend express and routing
     router = new Router
@@ -42,7 +42,7 @@
                 as: section
             } for section in availableSections when section in sections
             return includes
-
+
         # checks if a user is authenticated
         # otherwise, throw a 403 error
         req.checkAuthentication = ->


Retina `Particles`

Retina `Particles`

--- docs/components/home/Particles.cjsx
+++ docs/components/home/Particles.cjsx
@@ -24,9 +24,12 @@
     wrapWidth = wrapNode.clientWidth
     wrapHeight = wrapNode.clientHeight

-    # Set width and height
-    canvasNode.width = wrapWidth
-    canvasNode.height = wrapHeight
+    # Set width and height 2x scaled back for retina
+    canvasNode.width = wrapWidth * 2
+    canvasNode.height = wrapHeight * 2
+    canvasNode.style.width = wrapWidth + 'px'
+    canvasNode.style.height = wrapHeight + 'px'
+    canvasContext.scale(2,2)

     canvasContext.clearRect(0, 0, wrapWidth, wrapHeight);


Adding i18nLabel sorting for settings

Adding i18nLabel sorting for settings

--- client/views/admin/admin.coffee
+++ client/views/admin/admin.coffee
@@ -6,7 +6,7 @@
 	sections: ->
 		group = FlowRouter.getParam('group')
 		group ?= Settings.findOne({ type: 'group' })?._id
-		settings = Settings.find({ group: group }, {sort: {section: 1}}).fetch()
+		settings = Settings.find({ group: group }, {sort: {section: 1, i18nLabel: 1}}).fetch()
 		sections = {}
 		for setting in settings
 			sections[setting.section or ''] ?= []


Fix for notification

Fix for notification

--- client/views/install_mod.coffee
+++ client/views/install_mod.coffee
@@ -23,7 +23,7 @@
   clients.findOne()?
 Template.installMod.destroyed = ->
   if installingNot?
-    installingNot.pnotify_remove() if(installingNot.pnotify_remove)
+    installingNot.remove() if(installingNot.remove)
   installingNot = null

 Template.installMod.events


sort by creation date, newest first

sort by creation date, newest first

--- client/views/needs/index.coffee
+++ client/views/needs/index.coffee
@@ -1,6 +1,6 @@
 Template.needs.helpers
 	needs: ->
     if Session.get('myNeeds', true)
-      Needs.find({userId: Meteor.userId()})
+      Needs.find({userId: Meteor.userId()}, sort: {createdAt: -1})
     else
-      Needs.find({completedAt: {$exists: false}})+      Needs.find({completedAt: {$exists: false}}, sort: {createdAt: -1})


Forgotten initiative in init, closes #444

--- init.coffee
+++ init.coffee
@@ -278,15 +278,20 @@
 		throw new Error("No locations found. Forgot unify data?")

 	dbConnection.query.sync(dbConnection, "TRUNCATE monsters", [])
+	prototypesFromDB = dbConnection.query.sync(dbConnection, "SELECT * FROM monster_prototypes").rows
 	for i in [0...50]
-		soul = prototypes.pickRandom()
+		soul = prototypesFromDB.pickRandom()
 		dbConnection.query.sync(
 			dbConnection
 			"INSERT INTO monsters "+
-				"(id, prototype, location, health, mana, effects, attack_chance) "+
+				"(id, prototype, location, health, mana, effects,"+
+				" attack_chance, initiative) "+
 				"VALUES "+
-				"($1, $2, $3, $4, $5, $6, $7)"
-			[i, soul[0], locs.pickRandom().id, soul[8], soul[9], null, Math.random()*25|0]
+				"($1, $2, $3, $4, $5, $6, $7, $8)"
+			[
+				i, soul.id, locs.pickRandom().id, soul.health_max, soul.mana_max, null,
+				Math.random()*25|0, soul.initiative_min + Math.random()*(soul.initiative_max-soul.initiative_min)|0
+			]
 		)

 	console.log('Done.')


Use Uglify

Use Uglify

--- cli/Gruntfile.coffee
+++ cli/Gruntfile.coffee
@@ -77,14 +77,16 @@
   ## Tasks
   ####

-  # Always call explicitly with parameter to allow easy extension in the future
   compileTasks = [
-    'clean:public'
-    'clean:tmp'
+    'clean:all'

     'copyComponentAssets'
     'copy:assets'
-    'copy:params'
+    # Copy over the app's params first, then the dev version, which takes
+    # precedence
+    'copy:paramsApp'
+    'copy:paramsDev'
+    'copy:dev'

     'compile:js'
     'compile:stylus'
@@ -103,7 +105,7 @@
     'optimize'
     'link'

-    'clean:tmp'
+    'clean:build'
   ]

   # Template-related
@@ -124,8 +126,6 @@
   # Script optimization tasks
   optimizeScriptTasks = [
     'uglify'
-    'copy:jsmin'
-    'clean:jsmin'
   ]

@@ -145,14 +145,16 @@
           livereload: true

     clean:
-      public:
-        src: 'public'
-
-      tmp:
-        src: 'tmp'
-
-      jsmin:
-        src: 'public/script.min.js'
+      all: [
+        'tmp'
+        'public'
+      ]
+
+      build: [
+        'tmp'
+        'public/**/*.json'
+        'public/template.html'
+      ]

     copy:
       assets:
@@ -177,12 +179,11 @@
         src: '**/*.js'
         dest: 'tmp/'

-      jsmin:
-        src: 'public/script.min.js'
-        dest: 'public/script.js'
-
-      params:
+      paramsApp:
         src: 'app/params.json'
+        dest: 'tmp/params.json'
+      paramsDev:
+        src: 'dev/params.json'
         dest: 'tmp/params.json'

     concat:
@@ -193,7 +194,7 @@
           'components/**/public/script.js'
           'tmp/**/*.js'
         ]
-        dest: 'public/script.js'
+        dest: 'tmp/script.js'

       css:
         src: [
@@ -339,7 +340,7 @@
       default:
         closurePath: __dirname
         js: 'public/script.js'
-        jsOutputFile: 'public/script.min.js'
+        jsOutputFile: 'public/script.js'
         options:
           compilation_level: 'ADVANCED_OPTIMIZATIONS'
           language_in: 'ECMASCRIPT5_STRICT'
@@ -350,7 +351,7 @@
       default:
         files:
           src: 'public/script.js'
-          dest: 'public/script.min.js'
+          dest: 'public/script.js'

   ####


insert new line at eof on arrow down

insert new line at eof on arrow down

(only if the last line is not empty)

--- client/editor.coffee
+++ client/editor.coffee
@@ -50,7 +50,15 @@
     fixedGutter: false, firstLineNumber: 0, lineNumberFormatter: (i) -> "[#{i}]"
     keyMap: 'dyalog', matchBrackets: true, autoCloseBrackets: {pairs: '()[]{}', explode: '{}'}
     gutters: ['breakpoints', 'CodeMirror-linenumbers']
-    extraKeys: Tab: -> c = cm.getCursor(); opts.autocomplete? cm.getLine(c.line), c.ch; return
+    extraKeys:
+      Tab: -> c = cm.getCursor(); opts.autocomplete? cm.getLine(c.line), c.ch; return
+      Down: ->
+        l = cm.getCursor().line
+        if l == cm.lineCount() - 1 && cm.getLine l
+          cm.execCommand 'goDocEnd'; cm.execCommand 'newlineAndIndent'
+        else
+          cm.execCommand 'goLineDown'
+        return
   cm.dyalogCommands =
     ED: -> opts.edit? cm.getValue(), cm.indexFromPos cm.getCursor(); return # Edit
     QT: -> opts.close?(); return # Quit (and lose changes)


analyse with constant speed

analyse with constant speed

--- coffeescript/lib/bot/bot.coffee
+++ coffeescript/lib/bot/bot.coffee
@@ -1,4 +1,4 @@
-module.exports = (winston, physics) ->
+module.exports = (winston, physics, rref) ->
   class Bot
     logOnEveryNthTick = 1
     headerLogged = no
@@ -14,6 +14,7 @@
       @maxSlipInitialized = no
       @factorMaxSlip = 0.5
       @maxSlipAngle = 0
+      @slipTick = 0

 #      if @color is 'red'
 #        @throttle = 0.7
@@ -34,6 +35,7 @@
     carPositions: (data, control) ->
       @initPhysicsParameters()
       @initMaxSlipFactor()
+      @angleStuff()

       @adjustVelocity()
       @maxSlipAngle = Math.max(@maxSlipAngle, @race.getCarAngle(@color))
@@ -88,15 +90,21 @@
     initMaxSlipFactor: ->
       return if @maxSlipInitialized or @race.getCarAngle(@color) is 0

+
       a = Math.abs @race.getCarAngle @color
       v = @race.getVelocity @color
       r = @getRadius()
       b = v / r * 180 / Math.PI
       bslip = b - a
       vslip = r * b * Math.PI / 180
-      @factorMaxSlip = 0.97 * vslip * vslip / r
-      winston.warn @logPrefix()  + ";initMaxSlipFactor;a:#{a}, v:#{v}, r:#{r}, b:#{b}, bs:#{bslip}, vs:#{vslip}, fac:#{@factorMaxSlip}"
-      @maxSlipInitialized = yes
+
+      @angleStuff()
+
+      @slipTick = @slipTick + 1
+      if @slipTick > 3
+        @maxSlipInitialized = yes
+        @factorMaxSlip = 0.97 * vslip * vslip / r
+        winston.warn @logPrefix()  + ";initMaxSlipFactor;a:#{a}, v:#{v}, r:#{r}, b:#{b}, bs:#{bslip}, vs:#{vslip}, fac:#{@factorMaxSlip}"

     setThrottle: (throttle) ->
       if throttle < 0
@@ -124,8 +132,10 @@
       angleSC = @race.getAngularSpeedChange @color

       log1 = "#{@logPrefix()};#{throttle};#{velocity};#{acceleration};"
-      log2 = "#{angle};#{angleS};#{angleSC};#{radius};#{predict?.velocity};#{predict?.acceleration}"
-      winston.info log1 + log2
+      log2 = "#{angle};#{angleS};#{angleSC};#{radius}"
+      log2a = ";#{predict?.velocity};#{predict?.acceleration}"
+      log3 = ";#{@constants?[0]};#{@constants?[1]};#{@constants?[2]};#{@constants?[3]}"
+      winston.info log1 + log2 + log3

     logPrefix: ->
       gameTick = @race.currentTick
@@ -144,6 +154,9 @@
     getRadiusOnLane: (pieceIndex) -> @race.getRadiusOnLane pieceIndex, @race.getCarLane(@color)

     adjustVelocity: ->
+      @targetVelocity = 5.4
+      return @adjustThrottle()
+
       if @race.straightToFinish @color
         @targetVelocity = 100
         return @adjustThrottle()
@@ -176,8 +189,8 @@
       @setThrottle @throttleForVelocityInDistance @targetVelocity, distance

     throttleForVelocityInDistance: (targetVelocity, distance = 0) ->
-      if distance > 0
-        distance += 20
+#      if distance > 0
+#        distance += 20
       velocity = @race.getVelocity @color
       @physics.optimalThrottleForVelocityInDistance targetVelocity, distance, velocity

@@ -191,27 +204,48 @@
 #      c0 + (angularSpeed1 * c1 + c2 * velocity) + angle2 * c2 * velocity
 #
 #
-#    angleStuff: ->
-#      return if @race.getCarAngle(@color) is 0
-#      tick = @race.currentTick
-#
+    angleStuff: ->
+      return if @race.getCarAngle(@color) is 0
+      tick = @race.currentTick
+
 #      if @angleParams?
 #        return
-#
-#      if @race.getAngularSpeedChange(@color, tick - 2) > 0
-#        aSC2 = @race.getAngularSpeedChange(@color, tick - 2)
-#        aSC1 = @race.getAngularSpeedChange(@color, tick - 1)
-#        aSC0 = @race.getAngularSpeedChange(@color, tick)
-#        aS1 = @race.getAngularSpeed(@color, tick - 1)
-#
-#        c3 = ((aSC0 - aS1 * (aSC1 / aSC2 - 1)) / aSC2) - 1
-#        c2 = c3 / @race.getVelocity(@color)
-#        c1 = aSC1 / aSC2 - 1 - c3
-#
-#        c0 = aSC0
-#
-#        @angleParams = {c0, c1, c2}
-
-
-
-
+
+      if @race.getAngularSpeedChange(@color, tick - 2) isnt 0
+        aSC2 = @race.getAngularSpeedChange(@color, tick - 2)
+        aSC1 = @race.getAngularSpeedChange(@color, tick - 1)
+        aSC0 = @race.getAngularSpeedChange(@color, tick)
+        aS3 = @race.getAngularSpeed(@color, tick - 3)
+        aS2 = @race.getAngularSpeed(@color, tick - 2)
+        aS1 = @race.getAngularSpeed(@color, tick - 1)
+        a2 = @race.getCarAngle(@color, tick - 2)
+        a3 = @race.getCarAngle(@color, tick - 3)
+        a4 = @race.getCarAngle(@color, tick - 4)
+        v2 = @race.getVelocity(@color, tick - 2)
+        v1 = @race.getVelocity(@color, tick - 1)
+        v0 = @race.getVelocity(@color, tick)
+
+        c3 = ((aSC0 - aS1 * (aSC1 / aSC2 - 1)) / aSC2) - 1
+        c2 = c3 / @race.getVelocity(@color)
+        c1 = aSC1 / aSC2 - 1 - c3
+
+        c0 = aSC0
+        r = @getRadius()
+
+        solved = rref [
+          [v2*v2/r, aS1, v2 * (aS1 + a2), aSC0]
+          [v1*v1/r, aS2, v1 * (aS2 + a3), aSC1]
+          [v0*v0/r, aS3, v0 * (aS3 + a4), aSC2]
+        ]
+        @constants = (row[-1..][0] for row in solved)
+        @constants.push @constants[0] * (v0*v0) / r
+
+
+        #winston.warn @logPrefix() + ";aSC2;aSC1;aSC0;aS1;c3;c2;c1;c0"
+        #winston.warn @logPrefix() + ";#{aSC2};#{aSC1};#{aSC0};#{aS1};#{c3};#{c2};#{c1};#{c0}"
+
+        @angleParams = {c0, c1, c2}
+
+        #winston.warn @logPrefix() + ";#{@constants?[0]};#{@constants?[1]};#{@constants?[2]}"
+
+


actually close the dialog when upload done

--- client/images.coffee
+++ client/images.coffee
@@ -119,7 +119,7 @@

   my_uploader.send upload_file, (error, downloadUrl) ->
     # This callback is called when the upload is complete (or on error).
-    upload_progress_dialog.close()
+    upload_progress_dialog.modal('hide')
     upload_progress_dialog = null

     if error?


Adding more snippets

Adding more snippets

--- snippets/verify.cson
+++ snippets/verify.cson
@@ -205,15 +205,15 @@
       'body': 'verify that the page does not contain the text alias "$1"'

     'verify76':
-      'prefix': 'verify that the page does not contain the regex "text"'
-      'body': 'verify that the page does not contain the regex "$1"'
+        'prefix': 'verify that the page does not contain the regex "text"'
+        'body': 'verify that the page does not contain the regex "$1"'
     'verify77':
-      'prefix': 'verify that the page does not contain the regex alias "text"'
-      'body': 'verify that the page does not contain the regex alias "$1"'
-
-  'verify90':
-    'prefix': 'verify that there were no HTTP errors'
-    'body': 'verify that there were no HTTP errors'
+        'prefix': 'verify that the page does not contain the regex alias "text"'
+        'body': 'verify that the page does not contain the regex alias "$1"'
+
+    'verify90':
+        'prefix': 'verify that there were no HTTP errors'
+        'body': 'verify that there were no HTTP errors'

     'verify100':
         'prefix': 'verify the element found by "identifier" is displayed'
@@ -269,22 +269,297 @@
     'verify117':
         'prefix': 'verify the element found by "identifier" is not clickable within "time" seconds ignoring timeouts'
         'body': 'verify the element found by "$1" is not clickable within "$2" seconds ignoring timeouts'
-
-     'verify120':
+
+    'verify130':
+        'prefix': 'verify the element with the ID of "identifier" is displayed'
+        'body': 'verify the element the ID of "$1" is displayed'
+    'verify131':
+        'prefix': 'verify the element the ID of "identifier" is displayed within "time" seconds'
+        'body': 'verify the element the ID of "$1" is displayed within "$2" seconds'
+    'verify132':
+        'prefix': 'verify the element the ID of "identifier" is displayed within "time" seconds ignoring timeouts'
+        'body': 'verify the element the ID of "$1" is displayed within "$2" seconds ignoring timeouts"
+    'verify133':
+        'prefix': 'verify the element the ID of "identifier" is present'
+        'body': 'verify the element the ID of "$1" is present'
+    'verify134':
+        'prefix': 'verify the element the ID of "identifier" is present within "time" seconds'
+        'body': 'verify the element the ID of "$1" is present within "$2" seconds'
+    'verify135':
+        'prefix': 'verify the element the ID of "identifier" is present within "time" seconds ignoring timeouts'
+        'body': 'verify the element the ID of "$1" is present within "$2" seconds ignoring timeouts'
+    'verify136':
+        'prefix': 'verify the element the ID of "identifier" is clickable'
+        'body': 'verify the element the ID of "$1" is clickable'
+    'verify137':
+        'prefix': 'verify the element the ID of "identifier" is clickable within "time" seconds'
+        'body': 'verify the element the ID of "$1" is clickable within "$2" seconds'
+    'verify138':
+        'prefix': 'verify the element the ID of "identifier" is clickable within "time" seconds ignoring timeouts'
+        'body': 'verify the element the ID of "$1" is clickable within "$2" seconds ignoring timeouts'
+    'verify139':
+        'prefix': 'verify the element the ID of "identifier" is not displayed'
+        'body': 'verify the element the ID of "$1" is not displayed'
+    'verify140':
+        'prefix': 'verify the element the ID of "identifier" is not displayed within "time" seconds'
+        'body': 'verify the element the ID of "$1" is not displayed within "$2" seconds'
+    'verify141':
+        'prefix': 'verify the element the ID of "identifier" is not displayed within "time" seconds ignoring timeouts'
+        'body': 'verify the element the ID of "$1" is not displayed within "$2" seconds ignoring timeouts"
+    'verify142':
+        'prefix': 'verify the element the ID of "identifier" is not present'
+        'body': 'verify the element the ID of "$1" is not present'
+    'verify143':
+        'prefix': 'verify the element the ID of "identifier" is not present within "time" seconds'
+        'body': 'verify the element the ID of "$1" is not present within "$2" seconds'
+    'verify144':
+        'prefix': 'verify the element the ID of "identifier" is not present within "time" seconds ignoring timeouts'
+        'body': 'verify the element the ID of "$1" is not present within "$2" seconds ignoring timeouts'
+    'verify145':
+        'prefix': 'verify the element the ID of "identifier" is not clickable'
+        'body': 'verify the element the ID of "$1" is not clickable'
+    'verify146':
+        'prefix': 'verify the element the ID of "identifier" is not clickable within "time" seconds'
+        'body': 'verify the element the ID of "$1" is not clickable within "$2" seconds'
+    'verify147':
+        'prefix': 'verify the element the ID of "identifier" is not clickable within "time" seconds ignoring timeouts'
+        'body': 'verify the element the ID of "$1" is not clickable within "$2" seconds ignoring timeouts'
+
+    'verify160':
+        'prefix': 'verify the element with the css selector of "identifier" is displayed'
+        'body': 'verify the element the css selector of "$1" is displayed'
+    'verify161':
+        'prefix': 'verify the element the css selector of "identifier" is displayed within "time" seconds'
+        'body': 'verify the element the css selector of "$1" is displayed within "$2" seconds'
+    'verify162':
+        'prefix': 'verify the element the css selector of "identifier" is displayed within "time" seconds ignoring timeouts'
+        'body': 'verify the element the css selector of "$1" is displayed within "$2" seconds ignoring timeouts"
+    'verify163':
+        'prefix': 'verify the element the css selector of "identifier" is present'
+        'body': 'verify the element the css selector of "$1" is present'
+    'verify164':
+        'prefix': 'verify the element the css selector of "identifier" is present within "time" seconds'
+        'body': 'verify the element the css selector of "$1" is present within "$2" seconds'
+    'verify165':
+        'prefix': 'verify the element the css selector of "identifier" is present within "time" seconds ignoring timeouts'
+        'body': 'verify the element the css selector of "$1" is present within "$2" seconds ignoring timeouts'
+    'verify166':
+        'prefix': 'verify the element the css selector of "identifier" is clickable'
+        'body': 'verify the element the css selector of "$1" is clickable'
+    'verify167':
+        'prefix': 'verify the element the css selector of "identifier" is clickable within "time" seconds'
+        'body': 'verify the element the css selector of "$1" is clickable within "$2" seconds'
+    'verify168':
+        'prefix': 'verify the element the css selector of "identifier" is clickable within "time" seconds ignoring timeouts'
+        'body': 'verify the element the css selector of "$1" is clickable within "$2" seconds ignoring timeouts'
+    'verify169':
+        'prefix': 'verify the element the css selector of "identifier" is not displayed'
+        'body': 'verify the element the css selector of "$1" is not displayed'
+    'verify170':
+        'prefix': 'verify the element the css selector of "identifier" is not displayed within "time" seconds'
+        'body': 'verify the element the css selector of "$1" is not displayed within "$2" seconds'
+    'verify171':
+        'prefix': 'verify the element the css selector of "identifier" is not displayed within "time" seconds ignoring timeouts'
+        'body': 'verify the element the css selector of "$1" is not displayed within "$2" seconds ignoring timeouts"
+    'verify172':
+        'prefix': 'verify the element the css selector of "identifier" is not present'
+        'body': 'verify the element the css selector of "$1" is not present'
+    'verify173':
+        'prefix': 'verify the element the css selector of "identifier" is not present within "time" seconds'
+        'body': 'verify the element the css selector of "$1" is not present within "$2" seconds'
+    'verify174':
+        'prefix': 'verify the element the css selector of "identifier" is not present within "time" seconds ignoring timeouts'
+        'body': 'verify the element the css selector of "$1" is not present within "$2" seconds ignoring timeouts'
+    'verify175':
+        'prefix': 'verify the element the css selector of "identifier" is not clickable'
+        'body': 'verify the element the css selector of "$1" is not clickable'
+    'verify176':
+        'prefix': 'verify the element the css selector of "identifier" is not clickable within "time" seconds'
+        'body': 'verify the element the css selector of "$1" is not clickable within "$2" seconds'
+    'verify177':
+        'prefix': 'verify the element the css selector of "identifier" is not clickable within "time" seconds ignoring timeouts'
+        'body': 'verify the element the css selector of "$1" is not clickable within "$2" seconds ignoring timeouts'
+
+    'verify190':
+        'prefix': 'verify the element with the class of "identifier" is displayed'
+        'body': 'verify the element the class of "$1" is displayed'
+    'verify191':
+        'prefix': 'verify the element the class of "identifier" is displayed within "time" seconds'
+        'body': 'verify the element the class of "$1" is displayed within "$2" seconds'
+    'verify192':
+        'prefix': 'verify the element the class of "identifier" is displayed within "time" seconds ignoring timeouts'
+        'body': 'verify the element the class of "$1" is displayed within "$2" seconds ignoring timeouts"
+    'verify193':
+        'prefix': 'verify the element the class of "identifier" is present'
+        'body': 'verify the element the class of "$1" is present'
+    'verify194':
+        'prefix': 'verify the element the class of "identifier" is present within "time" seconds'
+        'body': 'verify the element the class of "$1" is present within "$2" seconds'
+    'verify195':
+        'prefix': 'verify the element the class of "identifier" is present within "time" seconds ignoring timeouts'
+        'body': 'verify the element the class of "$1" is present within "$2" seconds ignoring timeouts'
+    'verify196':
+        'prefix': 'verify the element the class of "identifier" is clickable'
+        'body': 'verify the element the class of "$1" is clickable'
+    'verify197':
+        'prefix': 'verify the element the class of "identifier" is clickable within "time" seconds'
+        'body': 'verify the element the class of "$1" is clickable within "$2" seconds'
+    'verify198':
+        'prefix': 'verify the element the class of "identifier" is clickable within "time" seconds ignoring timeouts'
+        'body': 'verify the element the class of "$1" is clickable within "$2" seconds ignoring timeouts'
+    'verify199':
+        'prefix': 'verify the element the class of "identifier" is not displayed'
+        'body': 'verify the element the class of "$1" is not displayed'
+    'verify200':
+        'prefix': 'verify the element the class of "identifier" is not displayed within "time" seconds'
+        'body': 'verify the element the class of "$1" is not displayed within "$2" seconds'
+    'verify201':
+        'prefix': 'verify the element the class of "identifier" is not displayed within "time" seconds ignoring timeouts'
+        'body': 'verify the element the class of "$1" is not displayed within "$2" seconds ignoring timeouts"
+    'verify202':
+        'prefix': 'verify the element the class of "identifier" is not present'
+        'body': 'verify the element the class of "$1" is not present'
+    'verify203':
+        'prefix': 'verify the element the class of "identifier" is not present within "time" seconds'
+        'body': 'verify the element the class of "$1" is not present within "$2" seconds'
+    'verify204':
+        'prefix': 'verify the element the class of "identifier" is not present within "time" seconds ignoring timeouts'
+        'body': 'verify the element the class of "$1" is not present within "$2" seconds ignoring timeouts'
+    'verify205':
+        'prefix': 'verify the element the class of "identifier" is not clickable'
+        'body': 'verify the element the class of "$1" is not clickable'
+    'verify206':
+        'prefix': 'verify the element the class of "identifier" is not clickable within "time" seconds'
+        'body': 'verify the element the class of "$1" is not clickable within "$2" seconds'
+    'verify207':
+        'prefix': 'verify the element the class of "identifier" is not clickable within "time" seconds ignoring timeouts'
+        'body': 'verify the element the class of "$1" is not clickable within "$2" seconds ignoring timeouts'
+
+    'verify220':
+        'prefix': 'verify the element with the xpath of "identifier" is displayed'
+        'body': 'verify the element the xpath of "$1" is displayed'
+    'verify221':
+        'prefix': 'verify the element the xpath of "identifier" is displayed within "time" seconds'
+        'body': 'verify the element the xpath of "$1" is displayed within "$2" seconds'
+    'verify222':
+        'prefix': 'verify the element the xpath of "identifier" is displayed within "time" seconds ignoring timeouts'
+        'body': 'verify the element the xpath of "$1" is displayed within "$2" seconds ignoring timeouts"
+    'verify223':
+        'prefix': 'verify the element the xpath of "identifier" is present'
+        'body': 'verify the element the xpath of "$1" is present'
+    'verify224':
+        'prefix': 'verify the element the xpath of "identifier" is present within "time" seconds'
+        'body': 'verify the element the xpath of "$1" is present within "$2" seconds'
+    'verify225':
+        'prefix': 'verify the element the xpath of "identifier" is present within "time" seconds ignoring timeouts'
+        'body': 'verify the element the xpath of "$1" is present within "$2" seconds ignoring timeouts'
+    'verify226':
+        'prefix': 'verify the element the xpath of "identifier" is clickable'
+        'body': 'verify the element the xpath of "$1" is clickable'
+    'verify227':
+        'prefix': 'verify the element the xpath of "identifier" is clickable within "time" seconds'
+        'body': 'verify the element the xpath of "$1" is clickable within "$2" seconds'
+    'verify228':
+        'prefix': 'verify the element the xpath of "identifier" is clickable within "time" seconds ignoring timeouts'
+        'body': 'verify the element the xpath of "$1" is clickable within "$2" seconds ignoring timeouts'
+    'verify229':
+        'prefix': 'verify the element the xpath of "identifier" is not displayed'
+        'body': 'verify the element the xpath of "$1" is not displayed'
+    'verify230':
+        'prefix': 'verify the element the xpath of "identifier" is not displayed within "time" seconds'
+        'body': 'verify the element the xpath of "$1" is not displayed within "$2" seconds'
+    'verify231':
+        'prefix': 'verify the element the xpath of "identifier" is not displayed within "time" seconds ignoring timeouts'
+        'body': 'verify the element the xpath of "$1" is not displayed within "$2" seconds ignoring timeouts"
+    'verify232':
+        'prefix': 'verify the element the xpath of "identifier" is not present'
+        'body': 'verify the element the xpath of "$1" is not present'
+    'verify233':
+        'prefix': 'verify the element the xpath of "identifier" is not present within "time" seconds'
+        'body': 'verify the element the xpath of "$1" is not present within "$2" seconds'
+    'verify234':
+        'prefix': 'verify the element the xpath of "identifier" is not present within "time" seconds ignoring timeouts'
+        'body': 'verify the element the xpath of "$1" is not present within "$2" seconds ignoring timeouts'
+    'verify235':
+        'prefix': 'verify the element the xpath of "identifier" is not clickable'
+        'body': 'verify the element the xpath of "$1" is not clickable'
+    'verify236':
+        'prefix': 'verify the element the xpath of "identifier" is not clickable within "time" seconds'
+        'body': 'verify the element the xpath of "$1" is not clickable within "$2" seconds'
+    'verify237':
+        'prefix': 'verify the element the xpath of "identifier" is not clickable within "time" seconds ignoring timeouts'
+        'body': 'verify the element the xpath of "$1" is not clickable within "$2" seconds ignoring timeouts'
+
+    'verify250':
+        'prefix': 'verify the element with the name of "identifier" is displayed'
+        'body': 'verify the element the name of "$1" is displayed'
+    'verify251':
+        'prefix': 'verify the element the name of "identifier" is displayed within "time" seconds'
+        'body': 'verify the element the name of "$1" is displayed within "$2" seconds'
+    'verify252':
+        'prefix': 'verify the element the name of "identifier" is displayed within "time" seconds ignoring timeouts'
+        'body': 'verify the element the name of "$1" is displayed within "$2" seconds ignoring timeouts"
+    'verify253':
+        'prefix': 'verify the element the name of "identifier" is present'
+        'body': 'verify the element the name of "$1" is present'
+    'verify254':
+        'prefix': 'verify the element the name of "identifier" is present within "time" seconds'
+        'body': 'verify the element the name of "$1" is present within "$2" seconds'
+    'verify255':
+        'prefix': 'verify the element the name of "identifier" is present within "time" seconds ignoring timeouts'
+        'body': 'verify the element the name of "$1" is present within "$2" seconds ignoring timeouts'
+    'verify256':
+        'prefix': 'verify the element the name of "identifier" is clickable'
+        'body': 'verify the element the name of "$1" is clickable'
+    'verify257':
+        'prefix': 'verify the element the name of "identifier" is clickable within "time" seconds'
+        'body': 'verify the element the name of "$1" is clickable within "$2" seconds'
+    'verify258':
+        'prefix': 'verify the element the name of "identifier" is clickable within "time" seconds ignoring timeouts'
+        'body': 'verify the element the name of "$1" is clickable within "$2" seconds ignoring timeouts'
+    'verify259':
+        'prefix': 'verify the element the name of "identifier" is not displayed'
+        'body': 'verify the element the name of "$1" is not displayed'
+    'verify260':
+        'prefix': 'verify the element the name of "identifier" is not displayed within "time" seconds'
+        'body': 'verify the element the name of "$1" is not displayed within "$2" seconds'
+    'verify261':
+        'prefix': 'verify the element the name of "identifier" is not displayed within "time" seconds ignoring timeouts'
+        'body': 'verify the element the name of "$1" is not displayed within "$2" seconds ignoring timeouts"
+    'verify262':
+        'prefix': 'verify the element the name of "identifier" is not present'
+        'body': 'verify the element the name of "$1" is not present'
+    'verify263':
+        'prefix': 'verify the element the name of "identifier" is not present within "time" seconds'
+        'body': 'verify the element the name of "$1" is not present within "$2" seconds'
+    'verify264':
+        'prefix': 'verify the element the name of "identifier" is not present within "time" seconds ignoring timeouts'
+        'body': 'verify the element the name of "$1" is not present within "$2" seconds ignoring timeouts'
+    'verify265':
+        'prefix': 'verify the element the name of "identifier" is not clickable'
+        'body': 'verify the element the name of "$1" is not clickable'
+    'verify266':
+        'prefix': 'verify the element the name of "identifier" is not clickable within "time" seconds'
+        'body': 'verify the element the name of "$1" is not clickable within "$2" seconds'
+    'verify267':
+        'prefix': 'verify the element the name of "identifier" is not clickable within "time" seconds ignoring timeouts'
+        'body': 'verify the element the name of "$1" is not clickable within "$2" seconds ignoring timeouts'
+
+     'verify200':
          'prefix': 'verify a link with the text content of "identifier" is present'
          'body': 'verify a link with the text content of "$1" is present'
-     'verify121':
+     'verify201':
          'prefix': 'verify a link with the text content of "identifier" is present within "time" seconds'
          'body': 'verify a link with the text content of "$1" is present within "$2" seconds'
-     'verify122':
+     'verify202':
          'prefix': 'verify a link with the text content of "identifier" is present within "time" seconds ignoring timeouts'
          'body': 'verify a link with the text content of "$1" is present within "$2" seconds ignoring timeouts'
-     'verify123':
+     'verify203':
          'prefix': 'verify a link with the text content of "identifier" is not present'
          'body': 'verify a link with the text content of "$1" is present'
-     'verify124':
+     'verify204':
          'prefix': 'verify a link with the text content of "identifier" is not present within "time" seconds'
          'body': 'verify a link with the text content of "$1" is present within "$2" seconds'
-     'verify125':
+     'verify205':
          'prefix': 'verify a link with the text content of "identifier" is not present within "time" seconds ignoring timeouts'
          'body': 'verify a link with the text content of "$1" is present within "$2" seconds ignoring timeouts'


time to sleep

time to sleep

--- commands/version-control.coffee
+++ commands/version-control.coffee
@@ -16,7 +16,7 @@

 svnExport = (repo, respond) ->

-    validate repo, ->
+    validateRepo repo, ->

         options = "-q --no-auth-cache --username #{config.svn.username} --password #{config.svn.password}"
         exec "svn export #{options} svn://#{config.svn.url}/#{repo} #{config.svn.path}/#{repo}", (err, stdout, stderr) ->
@@ -28,7 +28,7 @@

 svnLog = (repo, respond) ->

-    validate repo, ->
+    validateRepo repo, ->

         options = '-l 3 --no-auth-cache --username florinda --password chespirito'
         exec "svn log #{options} svn://localhost/#{repo}", (err, stdout, stderr) ->


Fix syntax error

Fix syntax error

--- app/api/article.coffee
+++ app/api/article.coffee
@@ -88,9 +88,8 @@
       # Helpppppp
       if Array.isArray voteEntriesParam
         db.collections.voteentry.create voteEntriesParam.map (voteEntry) ->
-          return
-            name: voteEntry
-            article: article.id
+          name: voteEntry
+          article: article.id
         .then (voteEntries) ->
           article.voteEntries = voteEntries
           return article