add comments to reset routes procedure that occurs on starting

--- config/initializers/resetproxy.coffee
+++ config/initializers/resetproxy.coffee
@@ -1,14 +1,11 @@
 Client = require('request-json').JsonClient

 client = new Client 'http://localhost:9104/'
-haibu = require('haibu-api')
-haibuClient = haibu.createClient
-    host: 'localhost'
-    port: 9002
-
-
 haibuClient =  new Client 'http://localhost:9002/'

+# Grab all application informations listed in the database and compare
+# them to informations stored inside haibu. If port is different
+# application port is updated in data system.
 resetRoutes = ->
     Application.all (err, installedApps) ->
         appDict = {}
@@ -17,8 +14,11 @@
                 appDict[installedApp.name] = installedApp

         haibuClient.get 'drones/running', (err, res, apps) ->
-            updateApps(apps, appDict, resetProxy)
+            updateApps apps, appDict, resetProxy

+# Recursive function that compare haibu port to port stored for each
+# application. If port is different, the application port is updated with the
+# one given by haibu.
 updateApps = (apps, appDict, callback) ->
     if apps? and apps.length > 0
         app = apps.pop()
@@ -32,6 +32,7 @@
     else
         callback()

+# Ask to proxy for synchronization between home and proxy.
 resetProxy = ->
     client.get 'routes/reset/', (err, res, body) ->
         if res? and res.statusCode is 200
@@ -41,4 +42,3 @@

 if process.env.NODE_ENV != "test"
     resetRoutes()
-


toggle class for quote

toggle class for quote

--- assets/coffeescript/pupil_store.coffee
+++ assets/coffeescript/pupil_store.coffee
@@ -468,7 +468,6 @@
           $('#payment-text').text(paymentText + creditCardQuote)
       else
         # this is an order request
-        $(button).toggleClass('checkmark--active')
         $(input).val('order')
         submitTxt = "Submit Order Request"
         $('label[for="form-submit"]').text(submitTxt)
@@ -483,6 +482,8 @@
   eventToggleQuoteType: ->
     $("#q-checkbox").click (event)=>
       event.preventDefault()
+      button = $(event.target)
+      $(button).toggleClass('checkmark--active')
       @updateOrderTypePaymentText()

   eventTogglePaymentType: ->


fix deprecation

fix deprecation

--- app/assets/javascripts/socializer/activities.js.coffee
+++ app/assets/javascripts/socializer/activities.js.coffee
@@ -12,7 +12,7 @@
       datetime = $(this).attr('datetime')
       locale   = $('body').data('locale')

-      moment.lang locale
+      moment.locale locale

       $(this).text moment(datetime).fromNow()


minor

minor

--- lib/bindings.coffee
+++ lib/bindings.coffee
@@ -5,7 +5,7 @@

 addBinding
   name: 'default'
-  bind: (bindArg, event) ->
+  bind: (bindArg) ->
     bindArg.element.on bindArg.bindName, (event) ->
       bindArg.setVmValue(event)
       return


Assign commands in Atom environment constructor

--- src/atom.coffee
+++ src/atom.coffee
@@ -174,6 +174,9 @@
     TooltipManager = require './tooltip-manager'
     @tooltips = new TooltipManager(keymapManager: @keymaps)

+    CommandRegistry = require './command-registry'
+    @commands = new CommandRegistry
+
   reset: ->
     @config.reset()

@@ -211,7 +214,6 @@
     @loadTime = null

     ViewRegistry = require './view-registry'
-    CommandRegistry = require './command-registry'
     PackageManager = require './package-manager'
     Clipboard = require './clipboard'
     GrammarRegistry = require './grammar-registry'
@@ -232,7 +234,7 @@
     process.env.NODE_ENV ?= 'production' unless devMode

     @keymaps.subscribeToFileReadFailure()
-    @commands = new CommandRegistry
+
     @views = new ViewRegistry
     @registerViewProviders()
     @packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode})


Use resolvable path to bootstrap stylesheet

--- src/atom.coffee
+++ src/atom.coffee
@@ -141,7 +141,7 @@
       null

   loadBaseStylesheets: ->
-    requireStylesheet('bootstrap')
+    requireStylesheet('bootstrap/less/bootstrap')
     @reloadBaseStylesheets()

   reloadBaseStylesheets: ->


Move deprecated methods to the bottom of the file

--- src/atom.coffee
+++ src/atom.coffee
@@ -205,18 +205,6 @@
     Editor = require './editor'

     @windowEventHandler = new WindowEventHandler
-
-  # Deprecated: Callers should be converted to use atom.deserializers
-  registerRepresentationClass: ->
-    deprecate("Callers should be converted to use atom.deserializers")
-
-  # Deprecated: Callers should be converted to use atom.deserializers
-  registerRepresentationClasses: ->
-    deprecate("Callers should be converted to use atom.deserializers")
-
-  setBodyPlatformClass: ->
-    document.body.classList.add("platform-#{process.platform}")
-

   ###
   Section: Managing The Atom Window
@@ -381,6 +369,10 @@
     dimensions = @getWindowDimensions()
     @state.windowDimensions = dimensions if @isValidDimensions(dimensions)

+
+
+
+
   # Public: Get the load settings for the current window.
   #
   # Returns an {Object} containing all the load setting key/value pairs.
@@ -662,3 +654,14 @@
         delete window[key]
       else
         window[key] = value
+
+  # Deprecated: Callers should be converted to use atom.deserializers
+  registerRepresentationClass: ->
+    deprecate("Callers should be converted to use atom.deserializers")
+
+  # Deprecated: Callers should be converted to use atom.deserializers
+  registerRepresentationClasses: ->
+    deprecate("Callers should be converted to use atom.deserializers")
+
+  setBodyPlatformClass: ->
+    document.body.classList.add("platform-#{process.platform}")


Don't load ~/.atom/init.coffee in safe mode

This ensures the code from the init script isn't causing issues
when trying to reproduce something in safe mode.

Refs #2772

--- src/atom.coffee
+++ src/atom.coffee
@@ -321,8 +321,9 @@

   # Call this method when establishing a real application window.
   startEditorWindow: ->
+    {resourcePath, safeMode} = @getLoadSettings()
+
     CommandInstaller = require './command-installer'
-    resourcePath = atom.getLoadSettings().resourcePath
     CommandInstaller.installAtomCommand resourcePath, false, (error) ->
       console.warn error.message if error?
     CommandInstaller.installApmCommand resourcePath, false, (error) ->
@@ -341,7 +342,7 @@

     @packages.activate()
     @keymaps.loadUserKeymap()
-    @requireUserInitScript()
+    @requireUserInitScript() unless safeMode
     @menu.update()

     maximize = dimensions?.maximized and process.platform isnt 'darwin'


fix apparently permanent bug in thinking this was testing truthiness and not existence

--- lib/cli/main.coffee
+++ lib/cli/main.coffee
@@ -103,7 +103,7 @@
   commander.parse(process.argv)

 invokeGrunt = (config = {}) ->
-  done = new RunsNextCommand(commander, config.name).run if config.chainable?
+  done = new RunsNextCommand(commander, config.name).run if config.chainable
   grunt.cli(config.options || {}, done)

 noCommandWasGiven = -> _.isEmpty(process.argv[2])


Text: Typo in text module.

Text: Typo in text module.

--- src/core/ui/text.coffee
+++ src/core/ui/text.coffee
@@ -169,7 +169,7 @@

             else
                 editProperties.width  = layer.sizeCurrent.width
-                editProperties.height = layer.sizeCurrent.lineHeight
+                editProperties.height = layer.sizeCurrent.height

             $textEdit.css editProperties


:bug: Fix a typo in commands

:bug: Fix a typo in commands

--- lib/commands.coffee
+++ lib/commands.coffee
@@ -23,7 +23,7 @@
     return unless activeEditor
     editorLinter = @linter.getEditorLinter(activeEditor)
     if editorLinter
-      editorLinter.deactivate()
+      editorLinter.destroy()
     else
       @linter.createEditorLinter(editorLinter)


Support for powershell scripts with whitespaces in path

--- lib/grammars.coffee
+++ lib/grammars.coffee
@@ -203,7 +203,7 @@
   PowerShell:
     "File Based":
       command: "powershell"
-      args: (context) -> [context.filepath]
+      args: (context) -> [context.filepath.replace /\ /g, "` "]

   Python:
     "Selection Based":


Alphabetize grammars.

Alphabetize grammars.

--- lib/grammars.coffee
+++ lib/grammars.coffee
@@ -35,6 +35,11 @@
     "File Based":
       command: "fsharpi"
       args: (filename) -> ['--exec', filename]
+
+  Gherkin:
+    "File Based":
+      command: "cucumber"
+      args: (filename) -> [filename]

   Go:
     "File Based":
@@ -79,6 +84,14 @@
       args: (code)  -> ['-e', code]
     "File Based":
       command: "lua"
+      args: (filename) -> [filename]
+
+  newLISP:
+    "Selection Based":
+      command: "newlisp"
+      args: (code) -> ['-e', code]
+    "File Based":
+      command: "newlisp"
       args: (filename) -> [filename]

   PHP:
@@ -136,16 +149,3 @@
     "File Based":
       command: "scala"
       args: (filename) -> [filename]
-
-  newLISP:
-    "Selection Based":
-      command: "newlisp"
-      args: (code) -> ['-e', code]
-    "File Based":
-      command: "newlisp"
-      args: (filename) -> [filename]
-
-  Gherkin:
-    "File Based":
-      command: "cucumber"
-      args: (filename) -> [filename]


fixed command delimiters

fixed command delimiters

--- src/mist-ninja-builder.coffee
+++ src/mist-ninja-builder.coffee
@@ -24,7 +24,11 @@
     @commandDict = @compileCommandDict()
     @commandDictRefs = {}
     for k, v of @commandDict
-      @commandDictRefs[k] = "${#{k}}"
+      console.log k
+      console.log v
+      @commandDictRefs[k] = ["${#{v[0]}}"]
+
+    console.log @commandDictRefs

   setRootDir: (@rootDir)->
   setDir: (@mistDir)->
@@ -58,7 +62,7 @@
     return dict

   delimitCommand: (cmd)->
-    (@delimitDict cmd, @commandDict)[0]
+    (@delimitDict cmd, @commandDictRefs)[0]

   delimitAll: (arr, dict = {})->
     arr


Refactored collision nodes in hash map code.

--- lib/hash_map.coffee
+++ lib/hash_map.coffee
@@ -115,16 +115,19 @@
   get:  (shift, hash, key) -> @value if util.equal(key, @key)

   with: (shift, hash, leaf) ->
+    this.baseForAdditionOf(shift, hash, leaf).with(shift, hash, leaf)
+
+  without: (shift, hash, key) -> null
+
+  toString: -> "LeaveNode(#{@key}, #{@value})"
+
+  baseForAdditionOf: (shift, hash, leaf) ->
     if util.equal(@key, leaf.key)
-      leaf
+      EmptyNode
     else if hash == @hash
-      new CollisionNode(hash, [[@key, @value], [leaf.key, leaf.value]])
-    else
-      new BitmapIndexedNode().with(shift, @hash, this).with(shift, hash, leaf)
-
-  without: (shift, hash, key) -> null
-
-  toString: -> "LeaveNode(#{@key}, #{@value})"
+      new CollisionNode(hash).with(shift, @hash, this)
+    else
+      new BitmapIndexedNode().with(shift, @hash, this)

 # A collision node contains several key-value pairs in which all keys
@@ -132,6 +135,7 @@
 # stored in an array @bucket.
 class CollisionNode
   constructor: (@hash, @bucket) ->
+    @bucket = [] unless @bucket?
     @size = @bucket.length

   each: (func) ->


Text in CSS now displays whitespaces

Text in CSS now displays whitespaces

--- impl/css/level0/text.coffee
+++ impl/css/level0/text.coffee
@@ -56,7 +56,7 @@
 		if not updatePending
 			{textElement} = @_impl
 			auto = @_impl.autoWidth = @width is 0
-			textElement.style.whiteSpace = if auto then 'nowrap' else 'normal'
+			textElement.style.whiteSpace = if auto then 'pre' else 'pre-wrap'
 			textElement.style.width = if auto then 'auto' else '100%'
 			if auto
 				updateSize @
@@ -86,7 +86,7 @@
 		{style} = textElement
 		style.width = 'auto'
 		style.height = 'auto'
-		style.whiteSpace = 'nowrap'
+		style.whiteSpace = 'pre'
 		style.fontSize = '14px'
 		style.fontFamily = 'sans-serif'
 		if isFirefox


Removed:  is defined in the application router class

--- client/app/libs/PanelRouter.coffee
+++ client/app/libs/PanelRouter.coffee
@@ -230,20 +230,3 @@
             return filledPattern
         else
             return ''
-
-    # Determines and gets the default parameters regarding a specific action
-    _getDefaultParameters: (action) ->
-        defaultParameters = null
-        switch action
-            when 'mailbox.emails', 'mailbox.config'
-                defaultMailbox = MailboxStore.getDefault()
-                defaultParameters = [defaultMailbox.id] if defaultMailbox
-            when 'mailbox.imap.emails'
-                defaultMailbox = MailboxStore.getDefault().id
-                if defaultMailbox
-                    defaultImapFolder = 'lala'
-                    defaultParameters = [defaultMailbox, defaultImapFolder]
-            else
-                defaultParameters = null
-
-        return defaultParameters


Fix Action Controller

Fix Action Controller

--- client/src/ActionController.coffee
+++ client/src/ActionController.coffee
@@ -50,9 +50,8 @@

         console.log "Parsing gestures.."
         #console.log "model: ", model
-
-        handModel = model[0]
-        for handModel in model
+
+        for handModel in model.hands
             console.log "handModel: ", handModel

             # Demo mouse clicking


Only include halo 1-3 quotes in chief plugin

--- plugins/chief/masterchief.cson
+++ plugins/chief/masterchief.cson
@@ -1,193 +1,79 @@
 quotes: [
+  "Captain Keyes."
   "No thanks to your driving, yes."
+  "I understand."
   "Don't get any funny ideas."
   "Punch it."
   "We'll be fine."
   "You all right?"
+  "So… what sort of weapon is it?"
   "Let's stay focused. Halo... how do we use it against the Covenant?"
   "Slow down. You're losing me."
   "Something buried? Where?"
-  "I don't understan-"
+  "No, nothing."
   "Hold on now, he's a friend."
-  "Yes... Activate Halo's defenses, and destroy the Flood, which is why we brought the Index to the Control Center."
+  "Yes… activate Halo's defenses, and destroy the Flood, which is why we brought the Index to the Control Center."
   "Enough! The Flood is spreading. If we activate Halo's defenses, we can wipe them out."
   "Is it true?"
   "That's not going to happen."
-  "Let's find a ride and get to the Captain."
-  "You have a better idea?"
+  "Let's find a ride, and get to the Captain."
   "Something tells me I'm not gonna like this."
+  "It'll hold."
   "We'll make it."
   "How much firepower would you need to crack one of the engine's shields?"
   "Here we go."
+  "Did anyone else make it?"
   "No. I think we're just getting started."
-  "Tell that to the Covenant"
+  "Tell that to the Covenant."
   "You told me there wouldn't be any cameras."
-  "I need a weapon."
-  "Sir, permission to leave the station"
+  "Thanks."
+  "Yes sir, I need a weapon."
+  "How much time was left?"
+  "Sir. Permission to leave the station."
   "To give the Covenant back their bomb."
+  "So, stay here."
   "I won't."
+  "Understood."
+  "Are you sure?"
+  "Commander, we've got a problem."
   "Relax. I'd rather not piss this thing off."
   "This thing is right. Halo is a weapon. Your Prophets are making a big mistake."
-  "Boo..."
+  "Boo."
   "Your pal. Where's he going?"
   "That Brute has the Index. And Miranda and Johnson. He can activate the ring."
-  "After I'm through with Truth—"
+  "After I'm through with Truth..."
+  "This is Spartan-117, can anyone hear me? Over."
   "Sir, finishing this fight."
-  "Aboard Forerunner vessel. Destination Earth- Minimum one Prophet Hierarch on board. No estimate for remaining crew... More to follow."
   "Yeah. You're not."
   "She stayed behind."
+  "Likewise, ma'am."
+  "What about Halo?"
   "The rings will kill us all."
+  "Green. Sir."
   "Does he usually mention me?"
   "Worse."
-  "Wait, leave her alone"
+  "Wait. Leave her alone."
   "On Halo, you tried to kill Cortana. You tried to kill me."
   "It's just a message."
   "I'll find Cortana's solution. And I'll bring it back."
+  "That's...our galaxy. We're beyond the rim."
+  "What is this place?"
+  "This is the Ark?"
+  "That's a first."
+  "Can you tell me where we are exactly?"
+  "And Truth?"
+  "Spark, move."
+  "Commander."
   "Not close enough."
+  "When did you know?"
   "Light it."
   "You know me. When I make a promise..."
   "Lucky me. Do you still have it?"
-  "Thought I'd try shooting my way out — mix things up a little."
+  "Thought I'd try shooting my way out—mix things up a little."
   "We'll head for the Portal. And we'll all go home."
   "I'm getting you out of here."
   "We'll make it."
+  "What happened?"
+  "It's finished."
   "Wake me... When you need me."
-  "We make our own luck, but I'll always be there when you need me."
-  "Not lucky enough, we lost two Spartans today: Solomon and Arthur. And that Elite we encountered... he was strong. I have to be stronger."
-  "What are you lookin' at?"
-  "You need a weapon?"
-  "Did you miss me?"
-  "Finish this Fight!"
-  "Time to give the Covenant back their bombs."
-  "Trust me, I can stick it."
-  "I won't...miss."
-  "I'm just getting started."
-  "Headshot, great."
-  "Tango down."
-  "Headshot."
-  "I'm in."
-  "It's dead."
-  "Frag out."
-  "Cover me, I'm reloading."
-  "Reloading."
-  "He won't be gettin' up."
-  "Hostile eliminated."
-  "Ha!"
-  "Not bad, shot's on target."
-  "This is bad."
-  "Get behind me."
-  "Plasma Launcher, ready."
-  "Spartan-117, locked and loaded."
-  "Rockets, ready."
-  "Let's finish this fight."
-  "Let's mix things up a little."
-  "This ends here!"
-  "Quick and painless."
-  "Anti-vehicle, up."
-  "Spartan Laser, ready."
-  "Point me in the right direction."
-  "Master Chief Laser. Online."
-  "You want me to talk? I won't."
-  "Heretic THAT."
-  "You hear that voice in your head too?"
-  "You know, I remember my gear being a lot cleaner than this."
-  "The voice in my head... sounds HOT."
-  "Maybe I AM a demon."
-  "Fuel Rod ready."
-  "Stay Sharp."
-  "Let's try to stay focused now."
-  "Permission to speak... you know what, forget it."
-  "Trust me, you really don't want to piss me off."
-  "This fight...is...finished."
-  "Ready to get back to work?"
-  "How long was I out?"
-  "I thought we had a truce with the Covenant."
-  "Maybe they haven't recognized us."
-  "These Covenant seem more fanatical than the ones we fought before."
-  "The Covenant weren't the one's scanning us."
-  "Something was wrong before we left the Dawn."
-  "If we could just get back to Earth, and find Halsey, she could fix this."
-  "It sounds like the Covenant were here looking for something."
-  "They've been waiting outside the planet for three years?"
-  "Asking's not my strong suit."
-  "Requiem. At least we know where we are now."
-  "That can't be right. Scan again."
-  "You mean the planet's hollow?"
-  "What do you know about Infinity?"
-  "Humanity... That's got to be Infinity. Can you get us to those coordinates?"
-  "What were those things?"
-  "The beacon was pulled into Requiem with us. If they try to follow it..."
-  "I'll handle them; you just find us that control node."
-  "How soon 'til Infinity hits the gravity well?"
-  "We don't have time!"
-  "Infinity! This is Sierra-117 of the UNSC Forward Unto Dawn. Do you copy?"
-  "Same place we are."
-  "Something tells me that's only because the Didact wanted it that way."
-  "This is Sierra-117 of the UNSC Forward Unto Dawn. We're on station, ready to assist."
-  "Light up their friend-or-foe tags; we're gonna need something to zero in on."
-  "Sir, Infinity drove the Didact back. He's vulnerable!"
-  "Captain, what's Force Recon's assessment of the terrain?"
-  "We'll make it work."
-  "You know I won't let that happen."
-  "Sir, I can move faster alone."
-  "This could be a trap."
-  "Who are you?"
-  "The Prometheans... they're human."
-  "Planning for what?"
-  "Can I defeat the Didact without it?"
-  "It's a long story, but I know what the Didact's after."
-  "Sierra One One Seven to Infinity, what's our status?"
-  "Does Infinity have a shot on the gravity well?"
-  "Sir, we've seen what the Didact is capable of. If we let him leave this world, humanity will be at risk."
-  "With all due respect Sir, I know what I saw."
-  "The Didact has to be stopped. If you won't do that... I will."
-  "No, Sir."
-  "Get word to Earth that trouble is coming. Cortana and I will do what we can back here."
-  "Infinity's tracked the Didact's vessel to a docking structure southeast of here. We'll jump ship as Infinity exits the roof."
-  "Cortana, where's this coming from?"
-  "He's there. Keep trying."
-  "Cortana, are you hearing him?"
-  "What are you doing?"
-  "His ship's online! They're leaving!"
-  "Track those Liches. We can go across them to get to the Didact's ship."
-  "This is UNSC Master Chief to base. Do you read?"
-  "They're after a Forerunner artifact you took from a Halo ring."
-  "Doctor, I need you to protect that artifact until we arrived. Send whatever-"
-  "Doctor, listen to me. You have to issue the order to evacuate the station."
-  "Send me your coordinates. I'll see what I can do about clearing an evac route on my way to you."
-  "What can we do to keep the Covenant out?"
-  "The device you recovered was a Forerunner weapon. The commander of that ship wants it back."
-  "We don't have any choice, doctor."
-  "If we can't move the Composer, we have to make sure the Didact can't either."
-  "I'm sorry, doctor. Keep routing your people to the evac centers. Once we take care of the Composer, you won't have much time."
-  "Doctor Tillson, the Composer's location's been compromised. You've got to get the nuke down here!"
-  "Ready or not, I need it now!"
-  "Cortana, see if you can raise Tillson. Get me a status on the rest of the station."
-  "Cortana, I need that info! (sigh) Look... don't think about the Didact. Don't think about the Composer. Only focus on finding me Tillson."
-  "Didact's taken the Composer. Get these people to the evac centers!"
-  "Cortana. It's not over. Not yet."
-  "The Didact's got the Composer. We're in a Broadsword carrying a HAVOK-grade payload, on approach to deliver it."
-  "Commander, direct all your ships to the Composer."
-  "Infinity, the Didact just closed off our entrance to the Composer."
-  "Clean hit. We're proceeding to insertion."
-  "Plan B."
-  "We'll have to deploy the warhead manually. How and where?"
-  "Keep scanning for the Composer. We'll figure it out along the way."
-  "Cortana? Cortana, do you read? Cortana, come in."
-  "How...?"
-  "So how do we get out of here?"
-  "... what?"
-  "No. That's not-! We go together."
-  "I am not leaving you here!"
-  "It was my job to take care of you."
-  "Cortana- please..."
-  "Wait."
-  "Our duty as soldiers, is to protect Humanity, whatever the cost."
-  "She said that to me once. About being a machine"
-  "You're on."
-  "Not yet."
-  "I don't need medals or awards, Cortana."
-  "Service and the respect of my fellow soldiers is all the reward I ask."
-  "I-I'll need a tux."
-  "Thanks."
 ]


Fixed: missing dependency

Fixed: missing dependency

--- client/src/stores/TaskStore.coffee
+++ client/src/stores/TaskStore.coffee
@@ -1,3 +1,4 @@
+_ = require 'underscore'
 Store = require '../libs/flux/store/Store'
 TaskUtils = require '../utils/TaskUtil'


tableverse/avatar: Draw label using current ui colors.

--- Oghma/tableverse/avatar.coffee
+++ Oghma/tableverse/avatar.coffee
@@ -50,8 +50,8 @@
       @__k.label.setAttrs(
         text:     attrs.name + ''
         y:        25
-        fill:     'black'
-        stroke:   'black'
+        fill:     O.ui_colors.value().primary
+        stroke:   O.ui_colors.value().primary
         fontSize: 16
       )

@@ -94,4 +94,10 @@
         attrs
       )
   )
+
+  O.ui_colors.on_set( ->
+    O.tableverse.avatar.each( ( avatar ) ->
+      avatar.redraw()
+    )
+  )
 )


artik10.coffee: Set initial versioning and change to 1
the partition holding config.json

Signed-off-by: Florin Sarbu <3a837a37a2ac9072a088641ec330e0e5d5b86f4e@resin.io>

--- artik10.coffee
+++ artik10.coffee
@@ -15,6 +15,7 @@
 ]

 module.exports =
+	version: 1
 	slug: 'artik10'
 	aliases: [ 'artik10' ]
 	name: 'Samsung Artik 10'
@@ -52,8 +53,7 @@
 	configuration:
 		config:
 			partition:
-				primary: 4
-				logical: 1
+				primary: 1
 			path: '/config.json'

 	initialization: commonImg.initialization


added mitch.coffee to rollout mitch hedburg quotes when the user types where is mitch

--- src/scripts/google-images.coffee
+++ src/scripts/google-images.coffee
@@ -1,12 +1,10 @@
 # A way to interact with the Google Images API.
 #
-# image me <query>    - The Original. Queries Google Images for <query> and
-#                       returns a random top result.
-# animate me <query>  - The same thing as `image me`, except adds a few
-#                       parameters to try to return an animated GIF instead.
+# image me <query>    - The Original. Queries Google Images for <query> and returns a random top result.
+# animate me <query>  - The same thing as `image me`, except adds a few parameters to try to return an animated GIF instead.
 # mustache me <url>   - Adds a mustache to the specified URL.
-# mustache me <query> - Searches Google Images for the specified query and
-#                       mustaches it.
+# mustache me <query> - Searches Google Images for the specified query and mustaches it.
+#
 module.exports = (robot) ->
   robot.respond /(image|img)( me)? (.*)/i, (msg) ->
     imageMe msg, msg.match[3], (url) ->


If site is in slower 50% of sites, use "slower than 80%" rather than "faster than 20%" for clarity.

--- src/scripts/pingdom-tools.coffee
+++ src/scripts/pingdom-tools.coffee
@@ -38,7 +38,11 @@
                             "/#{msg.match[1]}"
                           replies.push "Full page report: #{url}"
                         if result.pagespeed_score and result.load_time_percentile
-                          replies.push "Pagespeed score #{result.pagespeed_score}, faster than #{result.load_time_percentile}% of sites."
+                          if result.load_time_percentile >= 50
+                            replies.push "Pagespeed score #{result.pagespeed_score}, faster than #{result.load_time_percentile}% of sites."
+                          else
+                            slower_than = -result.load_time_percentile + 100
+                            replies.push "Pagespeed score #{result.pagespeed_score}, slower than #{slower_than}% of sites."
                         if result.page_bytes and result.page_load_time
                           replies.push "#{result.page_bytes} bytes in #{result.page_load_time} ms."
                         if replies.length


rename NetworkManager inputId to clientInputId

--- src/shared/NetworkManager.coffee
+++ src/shared/NetworkManager.coffee
@@ -5,7 +5,7 @@

   # Uses socket.io for networking
   #
-  # TODO: inputId in base36 (maybe)
+  # TODO: clientInputId in base36 (maybe)
   #
   # @example
   #   nm = NetworkManager.get()
@@ -16,7 +16,7 @@
   #     console.log data
   class Singleton.NetworkManager
     socket: undefined
-    inputId: 0
+    clientInputId: 0

     # Connect to a namespace
     connect: (namespace = '/') ->
@@ -51,8 +51,8 @@
     # @nodoc
     _prepareData: (data={}) ->
       data.timestamp = new Date().getTime()
-      data.inputId = @inputId
-      @inputId += 1
+      data.clientInputId = @clientInputId
+      @clientInputId += 1
       data

     # Emit an event


Activity: socialapicontroller consistent api method for reviving channel added

--- client/Main/socialapicontroller.coffee
+++ client/Main/socialapicontroller.coffee
@@ -409,3 +409,5 @@
     updateLastSeenTime   : channelRequesterFn
       fnName             : 'updateLastSeenTime'
       validateOptionsWith: ["channelId"]
+
+    revive               : mapChannel


SocialApiController: Add payload.link_url existence before adding embedly data

--- client/Main/socialapicontroller.coffee
+++ client/Main/socialapicontroller.coffee
@@ -75,7 +75,7 @@
         actorsPreview : []
         isInteracted  : no

-    if payload
+    if payload?.link_url
       m.link       =
         link_url   : payload.link_url
         link_embed :


SyncController: add callback to return results on queue and use file object to save and fetch contents

--- client/Main/synclocalcontroller.coffee
+++ client/Main/synclocalcontroller.coffee
@@ -47,10 +47,14 @@
         if content and not err
           newContent = @getPatchedContent content, localContent
           if newContent
-            @writeToFile vmName, fileName, newContent[0], (err, res)=>
-              return KD.showError err if err
-              @removeFromSaveArray fileName
-              @emit "LocalContentSynced", fileName
+            file.save newContent[0], (err, res)=>
+              return cb err if err
+              @removeFromSaveArray file
+              @emit "LocalContentSynced", file
+              cb null, file
+          else
+            @removeFromSaveArray file
+            cb null, file

   getPatchedContent: (originalContent, localContent)->
     dmp = new diff_match_patch


Activity: separated private message styles added

--- client/Social/Activity/includes.coffee
+++ client/Social/Activity/includes.coffee
@@ -130,5 +130,6 @@
   "views/buymachinemodal.coffee"

   "styl/activity.styl"
+  "styl/activity.pm.styl"
   "styl/activity.responsive.styl"
 ]


code cleanup

code cleanup

disambiguate var names; whitespace

--- client/app/MainApp/kodingrouter.coffee
+++ client/app/MainApp/kodingrouter.coffee
@@ -52,9 +52,9 @@

   stripTemplate =(str, konstructor)->
     {slugTemplate} = konstructor
-    slugRe = /^(.+)?(#\{slug\})(.+)?$/
-    re = RegExp slugTemplate.replace slugRe, (tmp, begin, slug, end)->
-      "^#{begin ? ''}(.*)#{end ? ''}$"
+    slugStripPattern = /^(.+)?(#\{slug\})(.+)?$/
+    re = RegExp slugTemplate.replace slugStripPattern,
+      (tmp, begin, slug, end)-> "^#{begin ? ''}(.*)#{end ? ''}$"
     str.match(re)?[1]

   handleNotFound:(route)->
@@ -130,12 +130,12 @@
   getRoutes =->
     mainController = KD.getSingleton 'mainController'

-    goToContent = createLinks(
+    nouns = createLinks(
       'Activity Apps Groups Members Topics'
       (sec)=> @createContentDisplayHandler sec
     )

-    goToSection = createLinks(
+    content = createLinks(
       'Account Activity Apps Groups Members StartTab Topics'
       (sec)-> ({params:{name}, query})-> @go sec, name, query
     )
@@ -153,18 +153,18 @@
       '/:name?/Recover'   : ({params:{name}})-> mainController.doRecover name

       # nouns
-      '/:name?/Groups'                  : goToSection.Groups
-      '/:name?/Activity'                : goToSection.Activity
-      '/:name?/Members'                 : goToSection.Members
-      '/:name?/Topics'                  : goToSection.Topics
-      '/:name?/Develop'                 : goToSection.StartTab
-      '/:name?/Apps'                    : goToSection.Apps
-      '/:name?/Account'                 : goToSection.Account
+      '/:name?/Groups'                  : nouns.Groups
+      '/:name?/Activity'                : nouns.Activity
+      '/:name?/Members'                 : nouns.Members
+      '/:name?/Topics'                  : nouns.Topics
+      '/:name?/Develop'                 : nouns.StartTab
+      '/:name?/Apps'                    : nouns.Apps
+      '/:name?/Account'                 : nouns.Account

       # content displays:
-      '/:name?/Topics/:topicSlug'       : goToContent.Topics
-      '/:name?/Activity/:activitySlug'  : goToContent.Activity
-      '/:name?/Apps/:appSlug'           : goToContent.Apps
+      '/:name?/Topics/:topicSlug'       : content.Topics
+      '/:name?/Activity/:activitySlug'  : content.Activity
+      '/:name?/Apps/:appSlug'           : content.Apps

       '/recover/:recoveryToken': ({params:{recoveryToken}})->
         mainController.appReady =>


Move anims: some refactoring

Move anims: some refactoring

--- client/app/js/views/battle_view.coffee
+++ client/app/js/views/battle_view.coffee
@@ -306,13 +306,7 @@
     else if moveData['power'] > 0
       # Non-contact attacking move
       # Projectile
-      $projectile = $('<div/>').addClass('projectile')
-      $projectile.addClass(moveData['type'].toLowerCase())
-      $projectile.appendTo(@$(".battle_pane"))
-      $projectile.css(
-        top: a.top + (($attacker.height() - $projectile.height()) >> 1)
-        left: a.left + (($attacker.width() - $projectile.width()) >> 1)
-      )
+      $projectile = @$projectile($attacker, moveData)
       [transX, transY] = [(d.left - a.left), (d.top - a.top)]
       $projectile
         .transition(x: transX / 2, y: transY / 2, scale: (scale + 1) / 2, 200, 'easeOutCubic')
@@ -325,13 +319,7 @@
     else if player != targetPlayer || slot != targetSlot
       # This is a non-attacking move that affects another pokemon
       # S-shaped movement
-      $projectile = $('<div/>').addClass('projectile')
-      $projectile.addClass(moveData['type'].toLowerCase())
-      $projectile.appendTo(@$(".battle_pane"))
-      $projectile.css(
-        top: a.top + (($attacker.height() - $projectile.height()) >> 1)
-        left: a.left + (($attacker.width() - $projectile.width()) >> 1)
-      )
+      $projectile = @$projectile($attacker, moveData)
       [transX, transY] = [(d.left - a.left), (d.top - a.top)]
       $projectile
         .transition(x: transX * 2 / 3, y: transY / 3, 150, 'easeInOutSine')
@@ -814,6 +802,16 @@
   $sprite: (player, slot) =>
     @$pokemon(player, slot).find('.sprite')

+  $projectile: ($pokemon, moveData) =>
+    $projectile = $('<div/>').addClass('projectile')
+    $projectile.addClass(moveData['type'].toLowerCase())
+    $projectile.appendTo(@$(".battle_pane"))
+    $projectile.css(
+      top: a.top + (($pokemon.height() - $projectile.height()) >> 1)
+      left: a.left + (($pokemon.width() - $projectile.width()) >> 1)
+    )
+    $projectile
+
   isFront: (player) =>
     @model.index != player


Added primitive islandPriority to the basicAI

--- basicAI.coffee
+++ basicAI.coffee
@@ -489,6 +489,24 @@
       "Copper,0"
     ]

+  # islandPriority chooses which card to set aside with Island. At present this
+  # list is incomplete, but covers just about everything that we would want to set aside
+  # with an Island.
+  islandPriority: (state, my) ->
+  [
+    "Colony"
+    "Province"
+    "Fairgrounds"
+    "Duchy"
+    "Duke"
+    "Gardens"
+    "Vineyard"
+    "Estate"
+    "Copper"
+    "Curse"
+    "Island"
+  ]
+
   # Taking into account gain priorities, gain values, trash priorities, and
   # trash values, how much do we like having this card in our deck overall?
   cardInDeckValue: (state, card, my) ->


Update sqs-queue-parallel.coffee

Update sqs-queue-parallel.coffee

--- src/sqs-queue-parallel.coffee
+++ src/sqs-queue-parallel.coffee
@@ -45,7 +45,7 @@
 					async.eachSeries queue.Messages, (message, next) ->
 						self.emit "message",
 							type: 'message'
-							data: message.Body
+							data: if message.body.indexOf('<?xml') < 0 then JSON.parse(message.body) else JSON.parse(message.body) or message.body
 							message: message
 							metadata: queue.ResponseMetadata
 							url: self.url


Remove alert.

Remove alert.

--- js/routers/AppRouter.coffee
+++ js/routers/AppRouter.coffee
@@ -10,8 +10,6 @@
     collection = new app.Collections.ActivityCollection
     @view = new app.Views.Activity collection : collection
     flight.goTo "#activity"
-    $('#main-menu').click ->
-      alert('clicked')

   goToPanel: (id) ->
     @view = new app.Views["Panel_" + id]


activity_scores: fix off-by-one error in binning

Signed-off-by: Imre Deak <fbd5edba1988036c8923f0cca0cce6ac4811db29@intel.com>

--- static/js/activity_scores.coffee
+++ static/js/activity_scores.coffee
@@ -60,14 +60,13 @@
             score = act.score

             while data_idx + 1 < score_list.length
-                data_idx += 1
-
-                act = score_list[data_idx].attributes
+                act = score_list[data_idx + 1].attributes

                 if act.time != time
                     break

                 score += act.score
+                data_idx += 1

             time = new Date(time).getTime()
             column = [ time, score ]


fix 'secret' argument to cookieParser

fix 'secret' argument to cookieParser

--- platform.coffee
+++ platform.coffee
@@ -237,8 +237,7 @@
 					fn = ->
 						@use express.methodOverride() if cfg.server.method_override

-						@use express.cookieParser({
-							secret: cfg.app.cookies?.secret,
+						@use express.cookieParser(cfg.app.cookies?.secret, {
 							secure: cfg.app.cookies?.secure
 						}) if cfg.app.cookies?.enabled


make keys more VS like

make keys more VS like

--- keymaps/omnisharp-atom.cson
+++ keymaps/omnisharp-atom.cson
@@ -16,14 +16,18 @@
   'ctrl-shift-b': 'omnisharp-atom:build'

 'atom-text-editor:not([mini])[data-grammar~="cs"], atom-text-editor:not([mini])[data-grammar~="csx"]':
-  'alt-F12': 'omnisharp-atom:go-to-definition'
-  'shift-F12': 'omnisharp-atom:find-usages'
+  'f12': 'omnisharp-atom:go-to-definition'
+  'shift-f12': 'omnisharp-atom:find-usages'
   'ctrl-alt-u': 'omnisharp-atom:fix-usings'
-  'ctrl-alt-m': 'omnisharp-atom:code-format'
+  'ctrl-k ctrl-d': 'omnisharp-atom:code-format'
+  'ctrl-k ctrl-c': 'editor:toggle-line-comments'
+  'ctrl-k ctrl-u': 'editor:toggle-line-comments'
   ';': 'omnisharp-atom:code-format-on-semicolon'
   '}': 'omnisharp-atom:code-format-on-curly-brace'
   'alt-r': 'omnisharp-atom:rename'
-  'ctrl-F12': 'omnisharp-atom:go-to-implementation'
+  'f2': 'omnisharp-atom:rename'
+  'ctrl-r ctrl-r': 'omnisharp-atom:rename'
+  'ctrl-f12': 'omnisharp-atom:go-to-implementation'
   'f1': 'omnisharp-atom:type-lookup'

 '.autocomplete-active:not([mini])[data-grammar~="cs"], .autocomplete-active:not([mini])[data-grammar~="csx"]':


Tests: helpers: Fixed open file test.

Tests: helpers: Fixed open file test.

--- client/test/lib/helpers/helpers.coffee
+++ client/test/lib/helpers/helpers.coffee
@@ -291,6 +291,7 @@
     webSelector   = "span[title='" + webPath + "']"

     browser
+      .pause                   5000 # wait for filetree load
       .waitForElementVisible   '.vm-header', 50000
       .click                   '.vm-header .buttons'
       .waitForElementPresent   '.context-list-wrapper', 50000


sagews2html: image aspect ratio for scaling; removing bottom lines; input/output styling

--- src/smc-webapp/printing.coffee
+++ src/smc-webapp/printing.coffee
@@ -177,15 +177,21 @@
                         @media print {
                           body { width: 100%; margin: 1rem .2rem; font-size: 12pt; }
                         }
-
+                        pre { margin: 0; }
+                        div.output + pre.input { margin-top: 1rem; }
                         div.output {
                             border-left: .2rem solid #33a;
-                            padding: 0 0 0 .3rem;
+                            padding: .3rem;
                             margin-left: -.5rem;
-                        }
-                        div.output img { width: 70%; }
+                            line-height: 1.5;
+                        }
+                        div.output img {
+                            max-width: 70%;
+                            width: auto;
+                            height: auto;
+                        }
                         div.output.stdout, div.output.stderr { font-family: monospace; white-space: pre-wrap; }
-                        div.output.stderr { color: red; border-color: #a33; }
+                        div.output.stderr { color: #F00; border-color: #F33; }

                         span.sagews-output-image > img,
                         span.sagews-output-html > img
@@ -208,18 +214,19 @@
                             min-width: 2rem;
                             text-align: right;
                         }
+                        /* numbering output, disabled because it doesn't look good */
+                        /*
                         div.output:before {
                             margin-left: -3rem;
                             counter-increment: line;
                             content: counter(line);
                             display: inline-block;
-                            padding: 0 .5rem 0 0;
-                            margin-right: .5rem;
                             color: #888;
                             min-width: 2rem;
                             text-align: right;
                             font-family: monospace;
                         }
+                        */
                         footer {
                             margin-top: 1rem;
                             border-top: .1rem solid #888;
@@ -388,7 +395,15 @@
             CodeMirror.runMode(line, mode, code)
             return code.outerHTML

-        input_lines_process = =>
+        input_lines_process = (final = false) =>
+            # final: if true, filter out the empty lines at the bottom
+            while final and input_lines.length > 0
+                line = input_lines[input_lines.length - 1]
+                console.log("last line:", line)
+                if line.length == 0
+                    input_lines.pop()
+                else
+                    break
             if input_lines.length > 0
                 input_lines = input_lines.map(process_line).join('') # no \n linebreaks!
                 #@_html.push("<div class='mode'>#{input_lines_mode ? input_lines_default_mode} mode")
@@ -446,7 +461,7 @@
                 cb(null, line, x)
             ,
             (err, line, x) ->
-                input_lines_process()
+                input_lines_process(final = true)
                 if err
                     msg = "error processing line #{line}: '#{x}'"
                     console.error(msg)


Get entire icon CSS class from file icon service

--- lib/tab-view.coffee
+++ lib/tab-view.coffee
@@ -190,6 +190,8 @@
       @itemTitle.classList.remove('icon', "icon-#{@iconName}")

     if @iconName = @item.getIconName?() or @path? and @iconName = FileIcons.getService().iconClassForPath(@path)
+      # File icons service will return an entire CSS class
+      @iconName = @iconName.replace('icon-', '')
       @itemTitle.classList.add('icon', "icon-#{@iconName}")

   getTabs: ->


sidebar: improve message listing limits

sidebar: improve message listing limits

because of the collaborative message filtering

--- client/Social/Activity/sidebar/activitysideview.coffee
+++ client/Social/Activity/sidebar/activitysideview.coffee
@@ -97,13 +97,28 @@

   renderItems: (err, items = []) ->
+
     {limit} = @getOptions()

     @listController.hideLazyLoader()

     return  if err

-    @listController.addItem itemData for itemData, i in items when i < limit
+    regularItemCount = 0
+    index = 0
+
+    loop
+
+      break  if index is items.length
+
+      itemData = items[index]
+      index   += 1
+
+      break     if regularItemCount >= limit
+      continue  if KD.utils.isChannelCollaborative itemData
+
+      @listController.addItem itemData
+      regularItemCount += 1

   pistachio: ->


AdminModal: Existence check for group.defaultChannels.

--- client/admin/lib/views/groupgeneralsettingsview.coffee
+++ client/admin/lib/views/groupgeneralsettingsview.coffee
@@ -111,7 +111,7 @@
       description  : 'Your new members will automatically join to <b>#general</b> channel. Here you can specify more channels for new team members to join automatically.'
       name         : 'channels'
       placeholder  : 'product, design, ux, random etc'
-      defaultValue : Encoder.htmlDecode group.defaultChannels.join(', ') ? ''
+      defaultValue : Encoder.htmlDecode group.defaultChannels?.join(', ') ? ''
       nextElement  : new KDCustomHTMLView
         cssClass   : 'warning-text'
         tagName    : 'span'


Pass file type as folder

Pass file type as folder

--- client/landing/app/MainApp/kodingappscontroller.coffee
+++ client/landing/app/MainApp/kodingappscontroller.coffee
@@ -57,8 +57,8 @@

   fetchAppsFromFs:(callback)->

-    path = "/home/#{KD.whoami().profile.nickname}/Applications"
-    appDir = FSHelper.createFileFromPath path
+    path   = "/home/#{KD.whoami().profile.nickname}/Applications"
+    appDir = FSHelper.createFileFromPath path, 'folder'
     appDir.fetchContents KD.utils.getTimedOutCallback (files)=>
       if not Array.isArray files or files.length is 0
         @putAppsToAppStorage {}


removed opacity transition when moving between pages, i think translateY is enough

--- app/_src/pjaxnavigation.coffee
+++ app/_src/pjaxnavigation.coffee
@@ -99,12 +99,12 @@
         # short transition when moving between pages
         TweenLite.fromTo(@$content[0], 0.5, {
           y: @yTo/3,
-          opacity: 0,
+          #opacity: 0,
           display: 'block'
         },
         {
           y: 0,
-          opacity: 1,
+          #opacity: 1,
           delay: 0.1,
           ease: Circ.easeOut,
           clearProps: 'all'


:fire: Remove the modifiesBuffer attribute

--- lib/validate.coffee
+++ lib/validate.coffee
@@ -4,8 +4,6 @@
 module.exports = Validate =

   linter: (linter) ->
-    # set undefined to false for backward compatibility
-    linter.modifiesBuffer = Boolean(linter.modifiesBuffer)
     unless linter.grammarScopes instanceof Array
       throw new Error("grammarScopes is not an Array. Got: #{linter.grammarScopes}")
     if linter.lint


reset state on turbolinks navigation

reset state on turbolinks navigation

--- resources/assets/coffee/_classes/user-card.coffee
+++ resources/assets/coffee/_classes/user-card.coffee
@@ -25,6 +25,7 @@
     $(document).on 'keydown', @onKeyDown
     $(document).on 'mouseenter', '.js-react--user-card-tooltip', @onMouseEnter
     $(document).on 'mouseleave', '.js-react--user-card-tooltip', @onMouseLeave
+    $(document).on 'turbolinks:before-cache', @onBeforeCache

   createTooltip: (el) =>
@@ -72,6 +73,11 @@
     $(el).qtip options

+  onBeforeCache: =>
+    @inCard = false
+    window.tooltipWithActiveMenu = null
+
+
   onKeyDown: (e) =>
     $('.qtip--user-card').qtip('hide') if e.keyCode == 27 && !@inCard


Builds dynamic IGV link with "origin" in query string

--- app/controllers/variant.coffee
+++ app/controllers/variant.coffee
@@ -218,7 +218,7 @@
   ).property 'omim.OMIM_ID'

   igvLink: (->
-    return "https://clinical-db.scilifelab.se:8081/api/v1/variants/#{@get('id')}/igv.xml"
+    return "#{location.origin}/api/v1/variants/#{@get('id')}/igv.xml?host=#{location.origin}"
   ).property 'id'

   hgmdLink: (->


goods_full_tree: Remove the examples counts from "Done".

Because it makes no sense to have example images on this.
This line for "Done" now matches the same one in sloan_tree.coffee.

See https://github.com/zooniverse/Galaxy-Zoo/issues/190

--- app/lib/goods_full_tree.coffee
+++ app/lib/goods_full_tree.coffee
@@ -114,7 +114,7 @@
     @checkbox 'Other', icon: 'other', examples: 2
     @checkbox 'Merger', icon: 'merger', examples: 2
     @checkbox 'Dust lane', icon: 'dustlane', examples: 3
-    @answer 'Done', leadsTo: 'Would you like to discuss this object?', icon: 'yes', examples: 2
+    @answer 'Done', leadsTo: 'Would you like to discuss this object?', icon: 'yes'

 module.exports = GoodsTree


Added a system for viewing pathfinding.

Added a system for viewing pathfinding.

--- app/lib/surface/Surface.coffee
+++ app/lib/surface/Surface.coffee
@@ -65,6 +65,7 @@
   shortcuts:
     '\\': 'onToggleDebug'
     'g': 'onToggleGrid'
+    'w': 'onTogglePathFinding'

   # external functions

@@ -100,6 +101,61 @@
       @surfaceTextLayer.addChild new CoordinateDisplay camera: @camera
     @onFrameChanged()
     Backbone.Mediator.publish 'surface:world-set-up'
+
+  onTogglePathFinding: ->
+    @hidePathFinding()
+    @showingPathFinding = not @showingPathFinding
+    if @showingPathFinding then @showPathFinding() else @hidePathFinding()
+
+  hidePathFinding: ->
+    @surfaceLayer.removeChild @navRectangles if @navRectangles
+    @surfaceLayer.removeChild @navPaths if @navPaths
+    @navRectangles = @navPaths = null
+
+  showPathFinding: ->
+    @hidePathFinding()
+    mesh = _.values(@world.navMeshes or {})[0]
+    return unless mesh
+    @navRectangles = new createjs.Container()
+    @navRectangles.layerPriority = -1
+    @addMeshRectanglesToContainer mesh, @navRectangles
+    @surfaceLayer.addChild @navRectangles
+    @surfaceLayer.updateLayerOrder()
+    return @surfaceLayer.updateLayerOrder() unless @world.graph
+    @navPaths = new createjs.Container()
+    @navPaths.layerPriority = -1
+    @addNavPathsToContainer @world.graph, @navPaths
+    @surfaceLayer.addChild @navPaths
+    @surfaceLayer.updateLayerOrder()
+
+  addMeshRectanglesToContainer: (mesh, container) ->
+    for rect in mesh
+      shape = new createjs.Shape()
+      pos = @camera.worldToSurface {x:rect.x, y:rect.y}
+      dim = @camera.worldToSurface {x:rect.width, y:rect.height}
+      shape.graphics
+        .setStrokeStyle(3)
+        .beginFill('rgba(0, 0, 128, 0.3)')
+        .beginStroke('rgba(0, 0, 128, 0.7)')
+        .drawRect(pos.x - dim.x/2, pos.y - dim.y/2, dim.x, dim.y)
+      container.addChild shape
+
+  addNavPathsToContainer: (graph, container) ->
+    for node in _.values graph
+      for edgeVertex in node.edges
+        @drawLine node.vertex, edgeVertex, container
+
+  drawLine: (v1, v2, container) ->
+    shape = new createjs.Shape()
+    v1 = @camera.worldToSurface v1
+    v2 = @camera.worldToSurface v2
+    shape.graphics
+      .setStrokeStyle(1)
+      .moveTo(v1.x, v1.y)
+      .beginStroke('rgba(128, 0, 0, 0.4)')
+      .lineTo(v2.x, v2.y)
+      .endStroke()
+    container.addChild shape

   setProgress: (progress, scrubDuration=500) ->
     progress = Math.max(Math.min(progress, 0.99), 0.0)


Remove some unused code

Remove some unused code


Changed App.Ajax and App.Auth object/method mode.

--- app/assets/javascripts/app/index.js.coffee
+++ app/assets/javascripts/app/index.js.coffee
@@ -54,7 +54,17 @@
 console.log '1112222', Config2.get( 'a')
 ###

-class App.Ajax
+class App.Com
+  _instance = undefined # Must be declared here to force the closure on the class
+  @ajax: (args) -> # Must be a static method
+    if _instance == undefined
+      _instance ?= new _Singleton
+
+    _instance.ajax(args)
+    _instance
+
+# The actual Singleton class
+class _Singleton
   defaults:
     contentType: 'application/json'
     dataType: 'json'
@@ -63,16 +73,27 @@
     cache: false
     async: true

+  queue_list: {}
+  pending: false
+
+  constructor: (@args) ->
+
   ajax: (params, defaults) ->
-    $.ajax($.extend({}, @defaults, defaults, params))
-
-class App.Auth extends App.Ajax
-  constructor: ->
-    console.log 'auth'
-
-  login: (params) ->
+    if params['id']
+      if @queue_list[ params['id'] ]
+        @queue_list[ params['id'] ].abort()
+      @queue_list[ params['id'] ] = $.ajax($.extend({}, @defaults, defaults, params))
+    else
+      $.ajax($.extend({}, @defaults, defaults, params))
+
+    console.log('AJAX', params['url'] )
+
+class App.Auth
+
+  @login: (params) ->
     console.log 'login(...)', params
-    @ajax(
+    App.Com.ajax(
+      id:     'login',
 #      params,
       type:   'POST',
       url:     '/signin',
@@ -81,9 +102,10 @@
       error:   params.error,
     )

-  loginCheck: ->
+  @loginCheck: ->
     console.log 'loginCheck(...)'
-    @ajax(
+    App.Com.ajax(
+      id:    'login_check',
       async: false,
       type:  'GET',
       url:   '/signshow',
@@ -133,18 +155,17 @@

         # empty session
         window.Session = {}
-
-    )
-
-  logout: ->
+    )
+
+  @logout: ->
     console.log 'logout(...)'
-    @ajax(
+    App.Com.ajax(
+      id:   'logout',
       type: 'DELETE',
       url:  '/signout',
     )

-class App.i18n extends App.Ajax
-#  @include App.Ajax
+class App.i18n

   constructor: ->
     @locale = 'de'
@@ -200,7 +221,8 @@

   set: (locale) =>
     @map = {}
-    @ajax(
+    App.Com.ajax(
+      id:    'i18n-set-' + locale,
       type:   'GET',
       url:    '/translations/lang/' + locale,
       async:  false,
@@ -276,8 +298,7 @@
     new App.Navigation( el: @el.find('#navigation') );

     # check if session already exists/try to get session data from server
-    auth = new App.Auth
-    auth.loginCheck()
+    App.Auth.loginCheck()

     # start notify controller
     new App.Notify( el: @el.find('#notify') );


old sorting way now

old sorting way now

--- app/assets/javascripts/verticals.js.coffee
+++ app/assets/javascripts/verticals.js.coffee
@@ -11,48 +11,48 @@
     currentURL = window.location.href

     # find all active verticals
-    $activeVerticals = $('.vertical-link.active a')
+    # $activeVerticals = $('.vertical-link.active a')

-    # verticals previously selected
-    if $activeVerticals.length > 0
-      wasActive = false
+    # # verticals previously selected
+    # if $activeVerticals.length > 0
+    #   wasActive = false

-      verticalSlugs = currentURL.split('/').
-                        pop().
-                        replace('posts#', '').
-                        split('+')
+    #   verticalSlugs = currentURL.split('/').
+    #                     pop().
+    #                     replace('posts#', '').
+    #                     split('+')

-      for vertical in $activeVerticals
-        if vertical = $vertical[0]
-          $verticalWrapper.removeClass('active')
-          verticalSlugs = verticalSlugs.filter (slug) -> slug isnt verticalSlug
-          wasActive = true
+    #   for vertical in $activeVerticals
+    #     if vertical = $vertical[0]
+    #       $verticalWrapper.removeClass('active')
+    #       verticalSlugs = verticalSlugs.filter (slug) -> slug isnt verticalSlug
+    #       wasActive = true

-      # if wasActive
-      #   # it was not the last vertical active
-      #   if verticalSlugs.length
-      #     url = '/posts/vertical/' + verticalSlugs.join('+')
-      #   # it WAS the last vertical active
-      #   else
-      #     # TODO: make this less sucky
-      #     window.location.href = '/posts'
-      # else
-      #   verticalSlugs.push(verticalSlug)
-      #   url = '/posts/vertical/' + verticalSlugs.join('+')
+    #   # if wasActive
+    #   #   # it was not the last vertical active
+    #   #   if verticalSlugs.length
+    #   #     url = '/posts/vertical/' + verticalSlugs.join('+')
+    #   #   # it WAS the last vertical active
+    #   #   else
+    #   #     # TODO: make this less sucky
+    #   #     window.location.href = '/posts'
+    #   # else
+    #   #   verticalSlugs.push(verticalSlug)
+    #   #   url = '/posts/vertical/' + verticalSlugs.join('+')

-      if wasActive and verticalSlugs.length <= 0
-        window.location.href = '/posts'
-      else
-        verticalSlugs.push(verticalSlug) if not wasActive
+    #   if wasActive and verticalSlugs.length <= 0
+    #     window.location.href = '/posts'
+    #   else
+    #     verticalSlugs.push(verticalSlug) if not wasActive

-        url = '/posts/vertical/' + verticalSlugs.join('+')
+    #     url = '/posts/vertical/' + verticalSlugs.join('+')

-    # no verticals previously selected
-    else
-      url = '/posts/vertical/' + verticalSlug
+    # # no verticals previously selected
+    # else
+    url = '/posts/vertical/' + verticalSlug

-      $('.pagination').remove()
-      $.getScript url, ->
-        $('.vertical-link').removeClass('active')
-        $('.' + verticalSlug).addClass('active')
-        history.pushState(null, '', url)+    $('.pagination').remove()
+    $.getScript url, ->
+      $('.vertical-link').removeClass('active')
+      $('.' + verticalSlug).addClass('active')
+      history.pushState(null, '', url)


simplify code

simplify code

--- src/game.coffee
+++ src/game.coffee
@@ -43,8 +43,7 @@
       game.gameOver(casePosition)
       return

-    game.safe++
-    if game.safe is game.board.nbHorizontalCases * game.board.nbVerticalCases - game.nbMines
+    if ++game.safe is game.board.nbHorizontalCases * game.board.nbVerticalCases - game.nbMines
       console.log "WIN"
       return


Fix obscure edge case with JS parser hackery (this. at end of lines that aren't standalone, like in comments)

--- app/lib/aether/languages/javascript.coffee
+++ app/lib/aether/languages/javascript.coffee
@@ -131,8 +131,8 @@
   # Hacky McHack step for things we can't easily change via AST transforms (which preserve statement ranges).
   # TODO: Should probably refactor and get rid of this soon.
   hackCommonMistakes: (code, aether) ->
-    # Stop this.\n from failing on the next weird line
-    code = code.replace /this\.\s*?\n/g, "this.IncompleteThisReference;"
+    # Stop standalone this.\n from failing on the next weird line
+    code = code.replace /\n\s*this\.\s*?\n/g, "\nthis.IncompleteThisReference;"
     # If we wanted to do it just when it would hit the ending } but allow multiline this refs:
     #code = code.replace /this.(\s+})$/, "this.IncompleteThisReference;$1"
     code


Rearrange code slightly.

Rearrange code slightly.

--- core/app/backbone/controllers/client_controller.coffee
+++ core/app/backbone/controllers/client_controller.coffee
@@ -1,6 +1,7 @@
 window.ClientController =
   showFact: (fact_id) ->
     fact = new Fact id: fact_id
+
     fact.on 'destroy', ->
       parent.remote.hide()
       parent.remote.stopHighlightingFactlink fact_id
@@ -8,10 +9,8 @@
     fact.fetch success: ->
       newClientModal = new DiscussionModalContainer
       FactlinkApp.discussionModalRegion.show newClientModal
-
       view = new DiscussionView model: fact
       view.on 'render', parent.onModalReady
-
       newClientModal.mainRegion.show view

   showNewFact: (params={}) ->
@@ -21,12 +20,9 @@

     clientModal = new DiscussionModalContainer
     FactlinkApp.discussionModalRegion.show clientModal
-
     FactlinkApp.guided = params.guided == 'true'
-
     if params.fact
       mp_track("Modal: Open prepare")
-
     factsNewView = new FactsNewView
       layout: 'client'
       fact_text: params.fact
@@ -34,11 +30,7 @@
       url: params.url
       csrf_token: params.csrf_token
       guided: FactlinkApp.guided
-
     factsNewView.on 'render', parent.onModalReady
-
-    factsNewView.on 'factCreated', (fact) ->
-      parent.highlightLastCreatedFactlink(fact.id, params.fact)
-
+    factsNewView.on 'factCreated', (fact) ->  parent.highlightLastCreatedFactlink(fact.id, params.fact)
     clientModal.mainRegion.show factsNewView


Fix load_spinner module to work with jQuery 1.9+

The load_spinner uses the global Ajax events to show the spinner.  We
were applying the load_spinner widget to the body tag, which resulting
in attaching the events to the tag.  For jQuery 1.9+, these events must
be attached to the document only,

Signed-off-by: Steven Chan <e44f0ea69ce310c26f3dae7dc40dfba581c2c7de@sitka.bclibraries.ca>

--- src/load_spinner.coffee
+++ src/load_spinner.coffee
@@ -3,23 +3,21 @@

 	# The module defines a jQuery plugin to show or hide a spinner graphic.
 	# It is actually a wrapper to use jQuery Mobile's 'page loading message' as the graphic.
-	$.fn.load_spinner = () ->
+	$.fn.load_spinner = ->
+
+		show = -> $.mobile.showPageLoadingMsg()
+
+		hide = -> $.mobile.hidePageLoadingMsg()
+
+		# We show the spinner upon an ajax start event, and hide it upon an
+		# ajax stop or an ajax error event.
+		$(document)
+			.ajaxStart(show)
+			.ajaxStop(hide)
+			.ajaxError(hide)

 		@plugin('load_spinner')
-
-		# We show the spinner upon an ajax start event,
-		.ajaxStart ->
-			$.mobile.showPageLoadingMsg()
-			return false
-
-		.refresh refresh = ->
-			$.mobile.hidePageLoadingMsg()
-			return false
-
-		# and hide the spinner upon an ajax stop
-		.ajaxStop(refresh)
-		# or an ajax error event.
-		.ajaxError(refresh)
+			.refresh(hide)

 	# > FIXME: if the user presses the esc key to force loading to stop,
 	# we ought to hide the spinner.


QUALITY: Remove debugging messages from tasks list

--- src/app/units/states/feedback/tasks-list/tasks-list.coffee
+++ src/app/units/states/feedback/tasks-list/tasks-list.coffee
@@ -28,12 +28,9 @@
     $scope.tutorialScopeOptions = $scope.unit.tutorials
     $scope.updateStatusCheck = (toggleStatus) ->
       if _.includes($scope.filters.statuses, toggleStatus)
-        console.log("removing", toggleStatus)
         $scope.filters.statuses = _.without($scope.filters.statuses, toggleStatus)
       else
-        console.log("adding", toggleStatus)
         $scope.filters.statuses.push(toggleStatus)
-      console.log($scope.filters.statuses)
     $scope.$watch 'filters.tutorialIdSelected', (tutorialId) ->
       return unless _.isString(tutorialId)
       if tutorialId == 'mine'
@@ -43,9 +40,6 @@
       else
         $scope.filters.tutorials = [$scope.unit.tutorialFromId(tutorialId)]
       $scope.filters.tutorials = _.map $scope.filters.tutorials, 'id'
-      console.log("$scope.filters.tutorials", $scope.filters.tutorials)
-    $scope.$watch 'filters.taskDefinition.id', (td) ->
-      console.log("$scope.filters.taskDefinition", $scope.filters.taskDefinition)
     # Tasks for feedback
     $scope.$watch 'unit.id', (newUnitId) ->
       return unless newUnitId?


Add CourseInstance ID to back-to-ladder link

--- app/views/play/level/ControlBarView.coffee
+++ app/views/play/level/ControlBarView.coffee
@@ -89,10 +89,10 @@
       @homeViewClass = "views/courses/TeacherCoursesView"
     else if @level.isType('ladder', 'ladder-tutorial', 'hero-ladder', 'course-ladder')
       levelID = @level.get('slug')?.replace(/\-tutorial$/, '') or @level.id
-      @homeLink = '/play/ladder/' + levelID
+      @homeLink = "/play/ladder/#{levelID}"
       @homeViewClass = 'views/ladder/LadderView'
       @homeViewArgs.push levelID
-      if leagueID = @getQueryVariable 'league'
+      if leagueID = @getQueryVariable('league') or @getQueryVariable('course-instance')
         leagueType = if @level.isType('course-ladder') then 'course' else 'clan'
         @homeViewArgs.push leagueType
         @homeViewArgs.push leagueID


Fix bug when retrieving neighbors

Fix bug when retrieving neighbors

--- src/grid.coffee
+++ src/grid.coffee
@@ -29,7 +29,7 @@
     result = []
     neighbors = [[1,0],[1,-1],[0,-1],[-1,0],[-1,1],[0,1]]
     for neighbor in neighbors
-      result.push { q: q+neighbor[0], r: neighbor[1] }
+      result.push { q: q+neighbor[0], r: r+neighbor[1] }
     result

   getCenterXY: (q, r) ->


GameObject.Effect

GameObject.Effect


Highlight User rows

Highlight User rows

--- lib/keybinding-panel.coffee
+++ lib/keybinding-panel.coffee
@@ -56,7 +56,8 @@
     {selector, keystroke, command, source} = keyBinding
     source = @determineSource(source)
     $$$ ->
-      @tr =>
+      rowClasses = if source is 'User' then 'success' else ''
+      @tr class: rowClasses, =>
         @td class: 'keystroke', keystroke
         @td class: 'command', command
         @td class: 'source', source


add is_my_account

add is_my_account

--- app/js/services/wallet.coffee
+++ app/js/services/wallet.coffee
@@ -20,8 +20,7 @@
                         @balances[name][symbol] = @utils.newAsset(amount, symbol, asset_record.precision)

     # turn raw rpc return value into nice object
-    #TODO add "has_private_key" as field on RPC return obj so we don't need to pass bool
-    populate_account: (val) ->
+    populate_account: (val, is_mine) ->
         if not @balances[val.name]
             @balances[val.name] =
                 "XTS": @utils.newAsset(0, "XTS", 1000000) #TODO move to utils/config
@@ -31,6 +30,7 @@
             active_key: val.active_key_history[val.active_key_history.length - 1][1]
             active_key_history: val.active_key_history
             registered_date: @utils.toDate(val.registration_date)
+            is_my_accout: is_mine
         }
         @accounts[acct.name] = acct
         return acct
@@ -42,11 +42,11 @@
     refresh_accounts: ->
         @wallet_api.list_receive_accounts().then (result) =>
             angular.forEach result, (val) =>
-                @populate_account(val)
+                @populate_account(val, true)
             @refresh_balances()
         @wallet_api.list_contact_accounts().then (result) =>
             angular.forEach result, (val) =>
-                @populate_account(val)
+                @populate_account(val, false)
             @refresh_balances()


Implement beforeRemove instead of overriding unsubscribe

--- lib/misspelling-view.coffee
+++ lib/misspelling-view.coffee
@@ -40,8 +40,7 @@
     {SpellChecker} = require 'spellchecker'
     corrections = SpellChecker.getCorrectionsForMisspelling(misspelling)

-  unsubscribe: ->
-    super
+  beforeRemove: ->
     @marker.destroy()

   containsCursor: ->


Fix some tutorial steps

Fix some tutorial steps

--- app/lib/tutorial-steps.coffee
+++ app/lib/tutorial-steps.coffee
@@ -2,8 +2,6 @@
 GhostMouse = require 'ghost-mouse'

 ghostMouse = new GhostMouse events: false
-
-clicks = 0

 module.exports =
   welcome: new Step
@@ -58,8 +56,8 @@
     next: 'click button[name="load-next-step"]': 'measureFirstLobule'

   measureFirstLobule: new Step
-    details: 'Now we need to draw crosses to measure the major and minor axes of the lobules.'
-    instruction: 'Drag from the top to the bottom of the lobule at the top-right of the image. Then drag a perpendicular line across the width of the lobule, forming a cross.'
+    details: 'Now we need to draw crosses to measure the major and minor axes of each of the lobules.'
+    instruction: 'Drag from the top to the bottom of the lobule at the top-left of the image.'
     attachment: 'left middle .subject-container 0.4 0.4'

     demo: (callback) ->
@@ -73,7 +71,7 @@

   measureSecondAxis: new Step
     details: 'Now the minor axis.'
-    instruction: 'Drag perpendicular the previous line to complete the cross.'
+    instruction: 'Now drag a line out perpendicular to the previous line to complete the cross.'
     attachment: 'left middle .subject-container 0.4 0.4'

     demo: (callback) ->
@@ -89,16 +87,36 @@
     details: 'Great! There\'s one more lobule in this image.'
     instruction: 'Mark the axes of the other lobule.'
     attachment: 'right middle .marking-surface center middle'
+
+    onEnter: ->
+      @markCreatedOnStep = false
+      $(document).one 'create-mark', =>
+        @markCreatedOnStep = true
+
+      @mousesUp = 0
+
+    demo: (callback) ->
+      ghostMouse.run ->
+        @move '.marking-surface', 0.15963855421686746, 0.10503951362941576
+        @drag '.marking-surface', 0.23313253012048193, 0.6781620432736846
+        @move '.marking-surface', 0.05602409638554217, 0.4172924780562932
+        @drag '.marking-surface', 0.33313253012048194, 0.3224308179772418
+        @do 0, -> callback()
+
     next:
       'mouseup .marking-surface': ->
-        @mousesUp ?= 0
-
-        @mousesUp += 1
+        @mousesUp += 1 if @markCreatedOnStep

         if @mousesUp is 2
+          console.log 'To finish'
           'finish'
         else
+          console.log 'Dont change steps'
           'oneMore'
+
+    onExit: ->
+      delete @mousesUp
+      delete @markCreatedOnStep

   finish: new Step
     details: 'Now that we\'ve marked the stem and all the lobules, move on to the next image.'


fixes first click credentials input bug (key was being passed back wrong from API)

--- api/v0/controllers/keys.coffee
+++ api/v0/controllers/keys.coffee
@@ -29,7 +29,8 @@
 									if err
 										@responses.internalError res, "Your key didn't exist, so we tried to create a new one.  We got an error.  It probably wasn't your fault."
 									else
-										@responses.respond res, keyObj
+										@responses.respond res,
+											key: keyObj

 					else
 						#Woot woot!  Key already exists!


hotfix: triggering EVENT_ANIMATION_SHOWN event even when skipping animation on history navigation

--- app/_src/pjaxnavigation.coffee
+++ app/_src/pjaxnavigation.coffee
@@ -125,6 +125,11 @@
     isPoppingHistory = options?.push isnt true

     @cancelSpinner( =>
+
+      # trigger callback first since some components
+      # bind to the EVENT_ANIMATION_SHOWN event
+      @onEndCallback() if @onEndCallback
+
       # transition in content for all pages except home
       unless @getPageIdFromUrl(options.url) is @HOMEPAGE_ID
         if @currentPageId is @HOMEPAGE_ID
@@ -133,8 +138,8 @@
         else
           # fast transition between other pages
           @showContent(isPoppingHistory)
+
       @updateBodyPageId(options)
-      @onEndCallback() if @onEndCallback
     )

@@ -146,7 +151,6 @@
       @currentPageId = pageId
     else
       @currentPageId = @HOMEPAGE_ID
-

     @$body.addClass('page-' + @currentPageId)

@@ -251,6 +255,8 @@
       TweenLite.set(@$content[0], {
         display: 'block'
       })
+      @$body.trigger @constructor.EVENT_ANIMATION_SHOWN
+
     else
       TweenLite.set(@$content[0], {
         display: 'block'


route level transitions to load

route level transitions to load

--- app/routes/application.coffee
+++ app/routes/application.coffee
@@ -1,29 +1,16 @@
 `import TurnOrder from '../models/turn-order'`

 ApplicationRoute = Ember.Route.extend
-    model: ->
-        return TurnOrder.create
-            participants: [
-                {
-                    name: "Charizzle"
-                    type: "charizard"
-                    battleStats: {
-                        speed: 100
-                    }
-                    images: {
-                        icon: "/pokemon/charizard/icon.png"
-                    }
-                }
-                {
-                    name: "Squirtle"
-                    type: "squirtle"
-                    battleStats: {
-                        speed: 43
-                    }
-                    images: {
-                        icon: "/pokemon/squirtle/icon.png"
-                    }
-                }
-            ]
+    beforeModel: ->
+        if not @game.active
+            @transitionTo 'load'
+
+    actions:
+        willTransition: ->
+            if not @game.active
+                @transitionTo 'load'
+
+        gameLoaded: ->
+            @transitionTo 'index'

 `export default ApplicationRoute`


WORKING PROTOTYPE, BIATCH! 🎉

WORKING PROTOTYPE, BIATCH! 🎉

--- src/main.coffee
+++ src/main.coffee
@@ -16,7 +16,7 @@
 		@size = new P.Size P.view.size.width, .7 * P.view.size.height

 	# The rectangle used for the cutout of the pieces
-	rectangle = new P.Rectangle 0, 0, P.view.size.width / 4, .7 * P.view.size.height / 4
+	rectangle = new P.Rectangle 0, 0, P.view.size.width / 3, .7 * P.view.size.height / 3

 	###
 	Top row
@@ -25,26 +25,55 @@
 	pieceEdges = [{
 		left: 0
 		right: 1,
+		top: 0,
+		bottom: 1
+	}, {
+		left: -1,
+		right: -1,
+		top: 0,
+		bottom: 1
+	}, {
+		left: 1,
+		right: 0,
+		top: 0,
+		bottom: 1
+	}, {
+		left: 0,
+		right: 1,
+		top: -1,
+		bottom: 1
+	}, {
+		left: -1,
+		right: -1,
+		top: -1,
+		bottom: 1
+	}, {
+		left: 1,
+		right: 0,
+		top: -1,
 		bottom: -1
 	}, {
-		left: -1,
-		right: -1,
-		bottom: 1
-	}, {
-		left: 1,
-		right: -1,
-		bottom: -1
+		left: 0,
+		right: -1,
+		top: -1,
+		bottom: 0
+	}, {
+		left: 1,
+		right: -1,
+		top: -1,
+		bottom: 0
 	}, {
 		left: 1,
 		right: 0,
-		bottom: -1
+		top: 1,
+		bottom: 0
 	}]

 	dropZoneLayer = new P.Layer()
 	piecesLayer = new P.Layer()
 	pieces = []

-	for i in [0..3]
+	for i in [0..8]

 		# An actual puzzle piece shape
 		W = rectangle.width
@@ -59,6 +88,26 @@
 		puzzle.moveTo 0, 0

 		# Top edge
+		zero = (rectangle.width - rectangle.height) / 2
+		one = zero + rectangle.height
+		half = rectangle.height / 2
+
+		if pieceEdges[i].top is 1
+
+			# Outwards
+			puzzle.lineTo new P.Point zero + 3 * E, 0
+			puzzle.quadraticCurveTo new P.Point(zero + half, 0), new P.Point(zero + 3 * E, -E)
+			puzzle.cubicCurveTo new P.Point(zero + 2 * E, -2 * E), new P.Point(one - 2 * E, -2 * E), new P.Point(one - 3 * E, -E)
+			puzzle.quadraticCurveTo new P.Point(one - half, 0), new P.Point(one - 3 * E, 0)
+
+		else if pieceEdges[i].top is -1
+
+			# Inwards
+			puzzle.lineTo new P.Point zero + 3 * E, 0
+			puzzle.quadraticCurveTo new P.Point(zero + half, 0), new P.Point(zero + 3 * E, E)
+			puzzle.cubicCurveTo new P.Point(zero + 2 * E, 2 * E), new P.Point(one - 2 * E, 2 * E), new P.Point(one - 3 * E, E)
+			puzzle.quadraticCurveTo new P.Point(one - half, 0), new P.Point(one - 3 * E, 0)
+
 		puzzle.lineTo new P.Point W, 0

 		# Right edge
@@ -82,11 +131,6 @@
 		puzzle.lineTo new P.Point W, H

 		# Bottom edge
-		zero = (rectangle.width - rectangle.height) / 2
-		one = zero + rectangle.height
-		half = rectangle.height / 2
-		quarter = rectangle.height / 4
-
 		if pieceEdges[i].bottom is 1

 			# Outwards
@@ -97,7 +141,7 @@

 		else if pieceEdges[i].bottom is -1

-			# Outwards
+			# Inwards
 			puzzle.lineTo new P.Point one - 3 * E, H
 			puzzle.quadraticCurveTo new P.Point(one - half, H), new P.Point(one - 3 * E, H - E)
 			puzzle.cubicCurveTo new P.Point(one - 2 * E, H - 2 * E), new P.Point(zero + 2 * E, H - 2 * E), new P.Point(zero + 3 * E, H - E)
@@ -128,24 +172,28 @@

 		# The dropzone for the piece
 		dropZone = puzzle.clone()
-		dropZone.point = new P.Point 0, 0
 		dropZone.fillColor = 'white'
 		dropZone.opacity = 0.5
 		dropZoneLayer.addChild dropZone

-		difference = puzzle.bounds.width - rectangle.width
-		difference /= 2 if pieceEdges[i].left is 1 and pieceEdges[i].right is 1
+		differenceHorizontally = puzzle.bounds.width - rectangle.width
+		differenceHorizontally /= 2 if pieceEdges[i].left is 1 and pieceEdges[i].right is 1
+
+		differenceVertically = puzzle.bounds.height - rectangle.height
+		differenceVertically /= 2 if pieceEdges[i].left is 1 and pieceEdges[i].right is 1

 		# Set correct top left
-		dropZone.bounds.x = i * rectangle.width
-		dropZone.bounds.x -= difference if pieceEdges[i].left > 0
+		dropZone.bounds.x = (i % 3) * rectangle.width
+		dropZone.bounds.x -= differenceHorizontally if pieceEdges[i].left > 0
+		dropZone.bounds.y = Math.floor(i / 3) * rectangle.height
+		dropZone.bounds.y -= differenceVertically if pieceEdges[i].top > 0

 		# The edge will serve as the mask for the piece
 		pieceEdge = puzzle.clone()

 		pieceBackground = new P.Raster
 			source: '//hufkens.net/wp-content/uploads/2012/10/bumba-win8.png'
-			position: new P.Point P.view.center.x - i * rectangle.width, .7 * P.view.center.y
+			position: new P.Point P.view.center.x - (i % 3) * rectangle.width, .7 * P.view.center.y - Math.floor(i / 3) * rectangle.height

 		pieceBackground.onLoad = () ->
 			@size = new P.Size P.view.size.width, .7 * P.view.size.height
@@ -153,8 +201,10 @@
 		# Create a Group using the mask and the background
 		pieceGroup = new P.Group pieceEdge, pieceBackground, pieceEdge.clone()
 		pieceGroup.clipped = true
-		pieceGroup.bounds.x = i * rectangle.width
-		pieceGroup.bounds.x -= difference if pieceEdges[i].left > 0
+		pieceGroup.bounds.x = (i % 3) * rectangle.width
+		pieceGroup.bounds.x -= differenceHorizontally if pieceEdges[i].left > 0
+		pieceGroup.bounds.y = Math.floor(i / 3) * rectangle.height
+		pieceGroup.bounds.y -= differenceVertically if pieceEdges[i].top > 0
 		pieceGroup.strokeColor = 'black'
 		piecesLayer.addChild pieceGroup


Remove unused Phaser states

Remove unused Phaser states

--- src/main.coffee
+++ src/main.coffee
@@ -49,12 +49,6 @@
       cell.reset(cell.x, cell.y)
       cell.toBeReset = false

-update = ->
-
-render = ->
-
 game = new Phaser.Game 800, 600, Phaser.AUTO, '',
   preload: preload
   create: create
-  update: update
-  render: render


main: fix defaultConfig stuff

main: fix defaultConfig stuff

--- src/main.coffee
+++ src/main.coffee
@@ -1,28 +1,26 @@
 cli = require('cli')
 path = require('path')
 async = require('async')
-default_config = require(path.join(process.cwd(),"..","..","config"))
+defaultConfigPath = path.join(__dirname,"..","..","config")
+config = require(defaultConfigPath)

-cli.parse
+cli.parse cli_args =
     host: ['b', "xmpp server listen address"
-        'host', process.env.HOST or default_config.xmpp.host]
+        'host', process.env.HOST or config.xmpp.host]
     port: ['p', "xmpp server listen port"
-        'number', parseInt(process.env.PORT) or default_config.xmpp.port]
-    config: ['c', "load config file", 'path', path.join(process.cwd(),"..","..","config.js")]
+        'number', parseInt(process.env.PORT) or config.xmpp.port]
+    config: ['c', "load config file", 'path', defaultConfigPath]
     debug: [off, "enable debug mode"]
     nobuild: [off, "[INTERNAL] disable build"]

 cli.main (args, opts) ->
-    unless opts.config is "#{process.cwd()}/../../config"
-        config = require(opts.config)
-    else
-        config = default_config
+    config = require(opts.config)

-    unless opts.host is (process.env.HOST or default_config.xmpp.host)
+    unless opts.host is cli_args.host[3]
         config.xmpp.host = opts.host

-    unless opts.host is (process.env.PORT or default_config.xmpp.port)
-        config.xmpp.host = opts.host
+    unless opts.port is cli_args.port[3]
+        config.xmpp.port = opts.port

     if opts.debug
         process.on 'uncaughtException', (err) ->


Add upper and lower bound inclusive filters.

--- app/javascripts/filters.coffee
+++ app/javascripts/filters.coffee
@@ -132,6 +132,32 @@
         if value? then value.toString().concat('%') else value

+    filters.filter 'lowerBoundInclusive', ->
+      # Returns the string representation of the given input value as follows:
+      # * true => '≥'
+      # * false => '>'
+      # * null or undefined => 'Not Specified'
+      #
+      # @param value the boolean or null input
+      # @returns the string representation
+      # @throws TypeError if the value is not boolean, null or undefined
+      (value) ->
+        booleanFilter(value, '≥', '>')
+
+
+    filters.filter 'upperBoundInclusive', ->
+      # Returns the string representation of the given input value as follows:
+      # * true => '≤'
+      # * false => '<'
+      # * null or undefined => 'Not Specified'
+      #
+      # @param value the boolean or null input
+      # @returns the string representation
+      # @throws TypeError if the value is not boolean, null or undefined
+      (value) ->
+        booleanFilter(value, '≤', '<')
+
+
     filters.filter 'visitDates', ->
       (sessions) ->
         sess.date() for sess in sessions


Logging in on hitting Enter

Logging in on hitting Enter

--- lib/views/login-view.coffee
+++ lib/views/login-view.coffee
@@ -33,9 +33,9 @@
     SettingsHelper = require '../utils/settings-helper'

     @panel = atom.workspace.addModalPanel(item: this, visible: false)
+    @workspaceElement = atom.views.getView(atom.workspace)

     @disposables = new CompositeDisposable
-    @workspaceElement = atom.views.getView(atom.workspace)
     @disposables.add atom.commands.add 'atom-workspace',
       'core:cancel', =>
         atom.commands.dispatch @workspaceElement, 'spark-dev:cancel-login'
@@ -47,7 +47,6 @@

     @emailModel = @emailEditor.editor.getModel()
     @passwordModel = @passwordEditor.editor.getModel()
-
     passwordElement = $(@passwordEditor.editor.element.rootElement)
     passwordElement.find('div.lines').addClass('password-lines')
     @passwordModel.onDidChange =>
@@ -57,6 +56,9 @@

       passwordElement.find('#password-style').remove()
       passwordElement.append('<style id="password-style">.password-lines .line span.text:before {content:"' + string + '";}</style>')
+    @disposables.add atom.commands.add @passwordEditor.editor.element,
+      'core:confirm': =>
+        @login()

   # Returns an object that can be retrieved when package is activated
   serialize: ->


Translate to zh-Hant (#5609)

Translate to zh-Hant (#5609)


Render locations properly in the data table

--- app/scripts/dcplotsctrl.coffee
+++ app/scripts/dcplotsctrl.coffee
@@ -549,6 +549,11 @@
             mRender: (obj) ->
               y = obj.getFullYear()
               if y == YEAR_ZERO then "unknown" else y
+          else if x == "location"
+            mData: x
+            sDefaultContent: ""
+            mRender: (obj) ->
+              y = String(obj.coordinates)
           else
             {mData: x, sDefaultContent: ""})


Replace @current_signature with _current_signature()

--- src/mock.coffee
+++ src/mock.coffee
@@ -21,14 +21,13 @@
   # TODO: add description
   constructor: ->
     @signatures = []
-    @current_signature = undefined    # TODO: not needed; use a method instead that returns: @signatures[0] ? undefined
     @state = undefined

   # TODO: add description
   expects: (method_name) ->
     @_check_expects_usage(method_name)
-    @current_signature = new MethodSignature(method_name)
-    @signatures.push(@current_signature)
+    @signatures.unshift(new MethodSignature(method_name))
+    # TODO: use ?=, not =
     @[ method_name ] = @_define_expected_method(method_name)
     @_set_state("expects")
     @
@@ -36,15 +35,15 @@
   # TODO: add description
   args: (args...) ->
     @_check_args_usage(args...)
-    @_check_if_duplicate_signature(@current_signature.method_name, args...)
-    @current_signature.args = args
+    @_check_if_duplicate_signature(@_current_signature().method_name, args...)
+    @_current_signature().args = args
     @_set_state("args")
     @

   # TODO: add description
   returns: (value) ->
     @_check_returns_usage(value)
-    @current_signature.returns = value
+    @_current_signature().returns = value
     @_set_state("returns")
     @

@@ -57,6 +56,9 @@
   # private

   # TODO: re-order methods below
+
+  _current_signature: ->
+    @signatures[0]

   _find_signature: (method_name, args...) ->
     for signature in @signatures when signature.matches(method_name, args...)


mqtt: Debug on failed parsing of discovery message

--- src/mqtt.coffee
+++ src/mqtt.coffee
@@ -100,6 +100,7 @@
     try
       msg = JSON.parse message.toString()
     catch e
+      debug 'failed to parse discovery message', e
       msg = message.toString()
     handlers = @subscribers[topic]


Working a bit more now

Working a bit more now

--- src/msgc.coffee
+++ src/msgc.coffee
@@ -12,11 +12,12 @@

   constructor: (robot) ->
     super robot
-    @robot.logger.info "Constructed!"

   send: (envelope, strings...) ->
     console.log("**** send ****")
-    @robot.logger.info("**** send ****")
+    console.log(envelope)
+    console.log(strings)
+    console.log("**** send ****")
     @wss.clients.forEach (client) =>
       client.send(JSON.stringify(strings))

@@ -27,22 +28,26 @@

   reply: (envelope, strings...) ->
     console.log("**** reply ****")
-    @robot.logger.info("**** reply ****")
+    console.log(envelope)
+    console.log(strings)
+    console.log("**** reply ****")
     strings = strings.map (s) -> "#{envelope.user.name}: #{s}"
     @send envelope, strings...

-  on_message: (e) =>
-    console.log("**** on_message ****")
-    @robot.logger.info("**** on_message #{e} ****")
-    e = JSON.parse e
-    @robot.logger.info("**** on_message now e = #{e} ****")
-    @robot.logger.info("**** on_message now e.message = #{e.message} ****")
-    user = @robot.brain.userForId(e.user, {name: e.user, room: e.room})
-    @receive new TextMessage(user, e.message, 'messageId')
+  _on_text_message: (user, text) =>
+    @robot.logger.debug("Received text message from #{user.name} => #{text}")
+    @receive new TextMessage(user, text)
+
+  on_message: (message) =>
+    @robot.logger.debug("Received message #{message}")
+    message = JSON.parse message
+    user = @robot.brain.userForId(message.username)
+    switch message.type
+        when "text" then @_on_text_message(user, message.text)
+        else @robot.logger.error("Unexpected message type #{message.type}")

   on_heartbeat: (e) =>
-    console.log("**** on_heartbeat ****")
-    @robot.logger.info("**** on_heartbeat ****")
+    @robot.logger.debug("heartbeat")

   run: ->
     # Hack robot to inject proxy settings
@@ -51,13 +56,11 @@

     @wss = new WebSocketServer {port: 4773}
     @wss.on 'connection', (ws) =>
-      console.log("**** connected ****")
-      @robot.logger.info("**** connected ****")
+      @robot.logger.info("Websocket connection opened")
       ws.on 'message', @on_message
       ws.on 'heartbeat', @on_heartbeat

-    console.log("**** Woohoo ****")
-    @robot.logger.info("**** Woohoo ****")
+    @robot.logger.info("Connected to hubot")
     @emit "connected"

 exports.use = (robot) ->


Don't highlight WIPs

Don't highlight WIPs

--- prviewer.coffee
+++ prviewer.coffee
@@ -180,25 +180,25 @@
               else
                 reviewers[name] = true

+          # Is this pull a proposal?
+          if 'proposal' of reviewers
+            pull.class = 'info'
+            pull.title = "PROPOSAL: #{ pull.title }"
+            delete reviewers.proposal
+
+          # Check for my username in submitter or reviewers.
+          if username == pull.user.login or username of reviewers
+            pull.class = 'warning'
+
+          # Check for my username in any comments.
+          if username in (c.user.login for c in comments)
+            pull.class = 'warning'
+
           # Is this pull a Work In Progress?
           if 'wip' of reviewers
             pull.class = 'ignore'
             pull.title = "WIP: #{ pull.title }"
             delete reviewers.wip
-
-          # Is this pull a proposal?
-          if 'proposal' of reviewers
-            pull.class = 'info'
-            pull.title = "PROPOSAL: #{ pull.title }"
-            delete reviewers.proposal
-
-          # Check for my username in submitter or reviewers.
-          if username == pull.user.login or username of reviewers
-            pull.class = 'warning'
-
-          # Check for my username in any comments.
-          if username in (c.user.login for c in comments)
-            pull.class = 'warning'

           # Check for GLHF in last few comments.
           if comments.length


add localStorage catch

add localStorage catch

--- src/models/score.coffee
+++ src/models/score.coffee
@@ -3,9 +3,12 @@
 class Score
   constructor: ->
     @last = 0
-    @best = if localStorage[BEST_KEY] then \
-              parseInt(localStorage[BEST_KEY]) \
-            else 0
+    try
+      @best = if localStorage[BEST_KEY] then \
+                parseInt(localStorage[BEST_KEY]) \
+              else 0
+    catch e
+      console.log e

   save: (score) =>
     @last = score
@@ -18,7 +21,10 @@

   setBest: (score) ->
     @best = score
-    localStorage[BEST_KEY] = score
+    try
+      localStorage[BEST_KEY] = score
+    catch e
+      console.log e

   getBest: ->
     @best


fixed regex bug

fixed regex bug

--- src/poll.coffee
+++ src/poll.coffee
@@ -53,7 +53,7 @@
 			msg.send error
 			@robot.logger.error error

-	robot.respond /vote\s+(\d)/i, (msg) ->
+	robot.respond /vote\s+(\d+)/i, (msg) ->
 		try
 			vote = msg.match[1]
 			user = msg.envelope.user['name']


Removed chunk debug message

Removed chunk debug message

--- app/scripts/client/webgl.coffee
+++ app/scripts/client/webgl.coffee
@@ -123,7 +123,7 @@
         if position
             chunkPos = @world._chunkPositionForWorldPosition(position)
             chunkCoord = @world._worldPositionInChunk(position)
-            console.log('chunk: ' + chunkPos.x, chunkPos.y)
+            # console.log('chunk: ' + chunkPos.x, chunkPos.y)
             # console.log('position inside chunk: ' + chunkCoord.x, chunkCoord.y)
         if not @mouseDown or not position
             return


added first destructuring test - faling

added first destructuring test - faling

--- test/tests/CaffeineScript/Parser/Working/Assignment.coffee
+++ test/tests/CaffeineScript/Parser/Working/Assignment.coffee
@@ -44,5 +44,5 @@
       "f\n  .foo = 1":     "f.foo = 1;"
       "f\n  || foo = 1":   "let foo; f || (foo = 1);"

-  # destructuring: ->
-  #   pa
+  destructuring:
+    "{a} = b": "let a; ({a} = b);"


[About #30707449] must be - with another three digits less, at least

--- test/mocha/ephemeris.spec.coffee
+++ test/mocha/ephemeris.spec.coffee
@@ -10,7 +10,7 @@

 # Floating point numbers fixed to precision,
 # suitable for testing across architectures.
-precision = 14
+precision = 11
 fixFloats = (obj, digits = precision) ->
   traverse(obj).forEach (val) ->
     if typeof val is 'number' and val % 1 isnt 0


(refactor) UID is neverchanging so use this in session.

--- src/rest.coffee
+++ src/rest.coffee
@@ -6,16 +6,15 @@
     get: (rest) ->
       (app, config) ->
         app.get rest.path, (req,res) ->
-          console.log req.session
           promisedCallback rest.dataCall(), res, config
     getByParam: (rest) ->
       (app, config) ->
         app.get rest.path, (req,res) ->
           promisedCallback rest.dataCall(req.params[rest.param]), res, config
-    getBySessionPseudo: (rest) ->
+    getBySessionUID: (rest) ->
       (app, config) ->
         app.get rest.path, (req,res) ->
-          promisedCallback rest.dataCall(req.session.pseudonym), res, config
+          promisedCallback rest.dataCall(req.session.uid), res, config
     postByBodyParam: (rest) ->
       (app, config) ->
         app.post rest.path, (req, res) ->
@@ -24,16 +23,16 @@
       (app, config) ->
         app.put rest.path, (req, res) ->
           promisedCallback rest.dataCall(req.body[rest.param]), res, config
-    putBySessionPseudoAndParam: (rest) ->
+    putBySessionUIDAndParam: (rest) ->
       (app, config) ->
         app.put rest.path, (req, res) ->
-          promisedCallback rest.dataCall(req.session.pseudonym, req.body[rest.param]), res, config
-    postBySessionPseudoAndParam: (rest) ->
+          promisedCallback rest.dataCall(req.session.uid, req.body[rest.param]), res, config
+    postBySessionUIDAndParam: (rest) ->
       (app, config) ->
         app.post rest.path, (req, res) ->
-          promisedCallback rest.dataCall(req.session.pseudonym, req.body[rest.param]), res, config
-    deleteBySessionPseudo: (rest) ->
+          promisedCallback rest.dataCall(req.session.uid, req.body[rest.param]), res, config
+    deleteBySessionUID: (rest) ->
       (app, config) ->
         app.delete rest.path, (req,res) ->
-          promisedCallback rest.dataCall(req.session.pseudonym), res, config
+          promisedCallback rest.dataCall(req.session.uid), res, config
   }


fix another test

fix another test

--- test/unit/model/serv_tool.coffee
+++ test/unit/model/serv_tool.coffee
@@ -130,10 +130,10 @@
         tool.updateInstances done

     it 'has updated the dataset boxes', ->
-      pulledInDSBox = @requestStub.calledWithMatch
+      pulledInDSBox = @requestStub.calledWith
         uri: sinon.match /2416349265/
         form:
-          apikey: sinon.match new RegExp(process.env.COTEST_USER_API_KEY)
+          apikey: 'zarino'
           cmd: sinon.match /git pull/
       pulledInDSBox.should.be.true


PrivateMessage: Fix user receives messages even after she is kicked from private channel bug [fixes #75280346]

--- workers/social/lib/social/models/socialapi/requests.coffee
+++ workers/social/lib/social/models/socialapi/requests.coffee
@@ -166,7 +166,35 @@

 removeParticipants = (data, callback)->
   url = "/channel/#{data.channelId}/participants/remove"
-  doChannelParticipantOperation data, url, callback
+  doChannelParticipantOperation data, url, (err, response) ->
+    return callback err if err
+    cycleChannelHelper data, response
+    callback null, response
+
+cycleChannelHelper = (data, removeResult)->
+  return unless removeResult?.length
+
+  isUserRemoved = (removeResult) ->
+    for accountResult in removeResult
+      return yes  if accountResult.statusConstant is 'left'
+
+    return no
+
+  return unless isUserRemoved removeResult
+
+  {channelId, accountId} = data
+  channelById {id: channelId, accountId}, (err, channel) ->
+    return console.error err if err
+    return console.error 'Channel not found' unless channel?.channel
+    {channel} = channel
+    options =
+      groupSlug     : channel.groupName
+      apiChannelType: channel.typeConstant
+      apiChannelName: channel.name
+    SocialChannel = require './channel'
+    SocialChannel.cycleChannel options, (err) ->
+      return console.error err if err
+

 doChannelParticipantOperation = (data, url, callback)->
   return callback { message: "Request is not valid" } unless data.channelId


Expose marked in pages

Expose marked in pages

--- src/plugins/page.coffee
+++ src/plugins/page.coffee
@@ -3,6 +3,7 @@
 async = require 'async'
 underscore = require 'underscore'
 moment = require 'moment'
+marked = require 'marked'

 {ContentPlugin} = require './../content'
 {stripExtension, extend} = require './../common'
@@ -49,6 +50,7 @@
           contents: contents
           _: underscore
           moment: moment
+          marked: marked
         extend ctx, locals
         template.render ctx, callback
     ], callback


Update help.coffee to use robot.alias if it's defined

Previously, if you specifed an alias like '/', it wouldn't be reflected in `/help`'s
output, instead just showing the robot name.

--- src/scripts/help.coffee
+++ src/scripts/help.coffee
@@ -53,18 +53,21 @@
 module.exports = (robot) ->
   robot.respond /help\s*(.*)?$/i, (msg) ->
     cmds = robot.helpCommands()
+    filter = msg.match[1]

-    if msg.match[1]
+    if filter
       cmds = cmds.filter (cmd) ->
-        cmd.match new RegExp(msg.match[1], 'i')
+        cmd.match new RegExp(filter, 'i')
+      if cmds.length == 0
+        msg.send "No available commands match #{filter}"
+        return

-      if cmds.length == 0
-        msg.send "No available commands match #{msg.match[1]}"
-        return
+    prefix = robot.alias or "#{robot.name} "
+    cmds = cmds.map (cmd) ->
+      cmd = cmd.replace /^hubot /, prefix
+      cmd.replace /hubot/ig, robot.name
+
     emit = cmds.join "\n"
-
-    unless robot.name.toLowerCase() is 'hubot'
-      emit = emit.replace /hubot/ig, robot.name

     msg.send emit


small changes

small changes

--- src/scriptscript.coffee
+++ src/scriptscript.coffee
@@ -26,7 +26,7 @@
 #################################### utils ####################################

 print_error = (err, debug, prefix="") ->
-  perr red(prefix +
+  perr red.bold(prefix +
     if debug
     then err.stack
     else err.stack.split('\n')[...2].join('\n') + "\n    <You can see full stack trace in debug mode (-d option or :d in the REPL)>"
@@ -42,7 +42,7 @@
     catch eval_err
       print_error eval_err, a.d
   if a.p or !a.e
-    p res
+    puts res

 ##################################### REPL ####################################

@@ -106,7 +106,7 @@
         continue
     ### !pragma coverage-skip-block ###
     if a.p
-      p res
+      puts res
     if a.e and typeof a.e == "boolean" or !a.s and !a.p and !a.c and !a.o and !a.i
       try
         geval res


Fixed another path bug in server.coffee.  browsercloud works now.

--- src/server/index.coffee
+++ src/server/index.coffee
@@ -64,7 +64,7 @@
             server.use(express.bodyParser())
             server.use(express.cookieParser())
             server.use(express.session({secret: 'change me please'}))
-            server.set('views', Path.join(__dirname, '..', 'views'))
+            server.set('views', Path.join(__dirname, '..', '..', 'views'))
             server.set('view options', {layout: false})

         # This Path should be configurable, so they can host multiple apps


Fix completion key generation.

Fix completion key generation.

--- background_scripts/main.coffee
+++ background_scripts/main.coffee
@@ -143,9 +143,9 @@
 #
 # Returns the keys that can complete a valid command given the current key queue.
 #
-getCompletionKeysRequest = (request) ->
+getCompletionKeysRequest = (request, keysToCheck = "") ->
   name: "refreshCompletionKeys"
-  completionKeys: generateCompletionKeys()
+  completionKeys: generateCompletionKeys(keysToCheck)
   validFirstKeys: validFirstKeys

 #
@@ -472,7 +472,7 @@
   # If we haven't sent the completion keys piggybacked on executePageCommand,
   # send them by themselves.
   unless refreshedCompletionKeys
-    chrome.tabs.sendRequest(tabId, getCompletionKeysRequest(), null)
+    chrome.tabs.sendRequest(tabId, getCompletionKeysRequest(null, newKeyQueue), null)

   newKeyQueue


Update context menu system

Update context menu system

--- menus/find-and-replace.cson
+++ menus/find-and-replace.cson
@@ -19,5 +19,6 @@
 ]

 'context-menu':
-  '.tree-view > li.directory':
-    'Search in Directory': 'project-find:show-in-current-directory'
+  '.tree-view > li.directory': [
+    { 'label': 'Search in Directory', 'command': 'project-find:show-in-current-directory' }
+  ]


fix typo, american english is not used in XAPI julien-f ;)

--- src/spec.coffee
+++ src/spec.coffee
@@ -468,7 +468,7 @@
           # TODO: determine whether or not tags are required for a VDI.
           #tags: -> retrieveTags @value.UUID

-          usage: get('physical_utilization')
+          usage: get('physical_utilisation')

           size: get('virtual_size')


Add a test for "link rel='next'" kind of link.

While this is not strictly valid, we don't put the link markup into
`<head>` to avoid adding more code just for those two new tests.

--- tests/dom_tests/dom_tests.coffee
+++ tests/dom_tests/dom_tests.coffee
@@ -215,6 +215,21 @@
     goNext()
     assert.equal '#second', window.location.hash

+  should "find link relation in header", ->
+    document.getElementById("test-div").innerHTML = """
+    <link rel='next' href='#first'>
+    """
+    goNext()
+    assert.equal '#first', window.location.hash
+
+  should "favor link relation to text matching", ->
+    document.getElementById("test-div").innerHTML = """
+    <link rel='next' href='#first'>
+    next
+    """
+    goNext()
+    assert.equal '#first', window.location.hash
+
 createLinks = (n) ->
   for i in [0...n] by 1
     link = document.createElement("a")


use Direction class variable to replace direction magic numbers

--- src/tank.coffee
+++ src/tank.coffee
@@ -1,7 +1,7 @@
 class Direction
   @UP: 0
   @DOWN: 180
-  @LEFT: 90
+  @LEFT: 270
   @RIGHT: 90
   @all: () -> [@UP, @DOWN, @LEFT, @RIGHT]

@@ -386,13 +386,13 @@
   _offset_by_direction: (offset) ->
     offset = parseInt(offset)
     switch (@direction)
-      when 0
+      when Direction.UP
         [0, - _.min([offset, @area.y1])]
-      when 90
+      when Direction.RIGHT
         [_.min([offset, @map.max_x - @area.x2]), 0]
-      when 180
+      when Direction.DOWN
         [0, _.min([offset, @map.max_y - @area.y2])]
-      when 270
+      when Direction.LEFT
         [- _.min([offset, @area.x1]), 0]

 class Terrain extends MapUnit2D
@@ -778,28 +778,28 @@
     @destroy() if @energy <= 0
   destroy_area: ->
     switch @direction
-      when 0
+      when Direction.UP
         new MapArea2D(
           @area.x1 - @default_width/4,
           @area.y1 - @default_height/4,
           @area.x2 + @default_width/4,
           @area.y1
         )
-      when 90
+      when Direction.RIGHT
         new MapArea2D(
           @area.x2,
           @area.y1 - @default_height/4,
           @area.x2 + @default_width/4,
           @area.y2 + @default_height/4
         )
-      when 180
+      when Direction.DOWN
         new MapArea2D(
           @area.x1 - @default_width/4,
           @area.y2,
           @area.x2 + @default_width/4,
           @area.y2 + @default_height/4
         )
-      when 270
+      when Direction.LEFT
         new MapArea2D(
           @area.x1 - @default_width/4,
           @area.y1 - @default_height/4,
@@ -819,10 +819,10 @@
     @direction = @map_unit.direction
     @commands = []
   direction_action_map: {
-    up: 0,
-    down: 180,
-    left: 270,
-    right: 90
+    up: Direction.UP,
+    down: Direction.DOWN,
+    left: Direction.LEFT,
+    right: Direction.RIGHT
   }
   # calculate next commands
   next: () ->