use the new backbone way to assign id

use the new backbone way to assign id

--- vendor/assets/javascripts/ckeditor/ckeditor_actions.coffee
+++ vendor/assets/javascripts/ckeditor/ckeditor_actions.coffee
@@ -16,7 +16,7 @@
   $.each(CKEDITOR.instances, (key, editor) ->
     dataset = editor.container.$.dataset
     model = FrontendEditor.getCurrentModel(dataset.object)
-    model.id = dataset.id
+    model.set('id', dataset.id)
     model.set(dataset.attribute, editor.getData())
   )


fix logic error in code for disconnected state

--- zechat/static/network.coffee
+++ zechat/static/network.coffee
@@ -67,12 +67,12 @@
     @in_flight.reply(msg)

   send: (msg) ->
-    promise = @in_flight.wrap(msg)
-    if @ws.readyState == WebSocket.OPEN
+    if @ws and @ws.readyState == WebSocket.OPEN
+      promise = @in_flight.wrap(msg)
       @ws.send(JSON.stringify(msg))
+      return promise
     else
-      promise.reject('disconnected')
-    return promise
+      return Q.reject('disconnected')

 class zc.Receiver extends zc.Controller


more data fields from rich-core

more data fields from rich-core

--- server/richcore.coffee
+++ server/richcore.coffee
@@ -35,7 +35,11 @@
                 cmdline: g.lines[0]
         else
             switch g.name
-                when 'date' then core.date = parse_core_date g.lines[0]
+                when 'date'     then core.date = parse_core_date g.lines[0]
+                when 'ls_proc'  then core.ls_proc = g.lines
+                when 'fd'       then core.fd = g.lines
+                when 'df'       then core.df = g.lines
+                when 'ifconfig' then core.ifconfig = g.lines

     groups.on 'end', () ->
         cb? null, core


PersistantAnimator bugfix: continuous animations with ever-changing targets broke; small tweak and they work again!

--- src/art/engine/animation/persistant_animator.coffee
+++ src/art/engine/animation/persistant_animator.coffee
@@ -370,7 +370,7 @@

   @getter
     animationSeconds: -> @_currentSecond - @_startSecond
-    frameSeconds: -> @_currentSecond - @_lastSecond
+    frameSeconds: -> if @_active then @_currentSecond - @_lastSecond else 0

     ###
     returns a bound function to stop this animator
@@ -403,7 +403,7 @@
       @stop()

   _activate: ->
-    @_lastSecond = @_startSecond = @_currentSecond
+    @_lastSecond = @_startSecond = @_currentSecond - @frameSeconds
     @_startValue = @_currentValue
     @queueEvent "start"
     @_active = true


add ability to not echo to post window CmdPeriod: no echo

--- lib/repl.coffee
+++ lib/repl.coffee
@@ -41,13 +41,14 @@
     @sclang.on 'stderr', (d) =>
       @bus.push("
#{d}
")

-  eval: (expression) ->
-    if expression.length > 80
-      echo = expression.substr(0, 80) + '...'
-    else
-      echo = expression
-    # =>
-    @bus.push "
#{echo}
"
+  eval: (expression, noecho=false) ->
+    unless noecho
+      if expression.length > 80
+        echo = expression.substr(0, 80) + '...'
+      else
+        echo = expression
+      # =>
+      @bus.push "
#{echo}
"

     escaped = expression.replace(/[\n\r]/g, '__NL__')
                         .replace(/\"/g, '\\"')
@@ -60,7 +61,7 @@

   cmdPeriod: ->
     # aka panic !
-    @eval("CmdPeriod.run;")
+    @eval("CmdPeriod.run;", true)

   clearPostWindow: ->
     @postWindow.clearPostWindow()


compact controlBar

compact controlBar

--- lib/control-bar.coffee
+++ lib/control-bar.coffee
@@ -1,6 +1,5 @@
 {CompositeDisposable} = require 'atom'
 {addToolTips, suppressEvent} = require './utils'
-

 # This is NOT Panel in Atom's terminology, Just naming.
 module.exports =
@@ -32,38 +31,51 @@
     # NOTE: Avoid mousedown event propagated up to belonging narrow-editor's element
     # If propagated, button clicking cause narrow-editor's cursor move etc See #123.
     @container.addEventListener('mousedown', suppressEvent)
+    # @toolTipDisposables = new CompositeDisposable
+    keyBindingTarget = @editorElement
+    @toolTipsSpecs = []

-    elementFor = (name) => @container.getElementsByClassName(name)[0]
-    hideElement = (name) -> elementFor(name).style.display = 'none'
+    elementFor = (name, {click, hideIf, selected, tips}={}) =>
+      element = @container.getElementsByClassName(name)[0]
+      if click
+        element.addEventListener('click', click)
+      if hideIf
+        element.style.display = 'none'
+      if selected
+        element.classList.toggle('selected')
+      if tips
+        @toolTipsSpecs.push({element, commandName: tips, keyBindingTarget})
+      element

     @elements =
-      autoPreview: elementFor('auto-preview')
-      protected: elementFor('protected')
-      refresh: elementFor('refresh')
-      itemCount: elementFor('item-count')
-      selectFiles: elementFor('select-files')
-      searchIgnoreCase: elementFor('search-ignore-case')
-      searchWholeWord: elementFor('search-whole-word')
-      searchUseRegex: elementFor('search-use-regex')
-      searchRegex: elementFor('search-regex')
+      autoPreview: elementFor 'auto-preview',
+        click: @ui.toggleAutoPreview
+        tips: "narrow-ui:toggle-auto-preview"
+        selected: @ui.autoPreview
+      protected: elementFor 'protected',
+        click: @ui.toggleProtected
+        tips: "narrow-ui:protect"
+        selected: @ui.protected
+      refresh: elementFor 'refresh',
+        click: @ui.refreshManually
+        tips: "narrow:refresh"
+      itemCount: elementFor 'item-count'
+      selectFiles: elementFor 'select-files',
+        click: @ui.selectFiles,
+        hideIf: @provider.boundToSingleFile
+        tips: "narrow-ui:select-files"
+      searchIgnoreCase: elementFor 'search-ignore-case',
+        click: @ui.toggleSearchIgnoreCase
+        tips: "narrow-ui:toggle-search-ignore-case"
+      searchWholeWord: elementFor 'search-whole-word',
+        click: @ui.toggleSearchWholeWord
+        tips: "narrow-ui:toggle-search-whole-word"
+      searchUseRegex: elementFor 'search-use-regex',
+        click: @ui.toggleSearchUseRegex
+        tips: "narrow-ui:toggle-search-use-regex"
+      searchRegex: elementFor 'search-regex'

-    hideElement('select-files') if @provider.boundToSingleFile
-    hideElement('search-options') unless @showSearchOption
-    @addClickEvents()
-
-
-  addClickEvents: ->
-    clickEvents =
-      autoPreview: @ui.toggleAutoPreview
-      protected: @ui.toggleProtected
-      refresh: @ui.refreshManually
-      selectFiles: @ui.selectFiles
-      searchIgnoreCase: @ui.toggleSearchIgnoreCase
-      searchWholeWord: @ui.toggleSearchWholeWord
-      searchUseRegex: @ui.toggleSearchUseRegex
-
-    for elementName, fn of clickEvents when element = @elements[elementName]
-      element.addEventListener('click', fn)
+    elementFor('search-options', hideIf: not @showSearchOption)

   destroy: ->
     @toolTipDisposables?.dispose()
@@ -76,11 +88,10 @@
     @marker = @editor.markBufferPosition([0, 0])
     @editor.decorateMarker(@marker, type: 'block', item: @container, position: 'before')

-    @toolTipDisposables ?= @addToolTips()
-
-    @updateElements
-      autoPreview: @ui.autoPreview
-      protected: @ui.protected
+    unless @toolTipDisposables?
+      @toolTipDisposables = new CompositeDisposable
+      for toolTipsSpec in @toolTipsSpecs
+        @toolTipDisposables.add(addToolTips(toolTipsSpec))

   updateElements: (states) ->
     for elementName, value of states when element = @elements[elementName]
@@ -94,25 +105,9 @@
           else
             element.textContent = states.searchTerm
             invalid = states.searchTerm.length isnt 0
+          element.classList.toggle('invalid', invalid)

-          element.classList.toggle('invalid', invalid)
         when 'refresh'
           element.classList.toggle('running', value)
         else
           element.classList.toggle('selected', value)
-
-  addToolTips: ->
-    tooltips =
-      autoPreview: "narrow-ui:toggle-auto-preview"
-      protected: "narrow-ui:protect"
-      refresh: "narrow:refresh"
-      selectFiles: "narrow-ui:select-files"
-      searchWholeWord: "narrow-ui:toggle-search-whole-word"
-      searchIgnoreCase: "narrow-ui:toggle-search-ignore-case"
-      searchUseRegex: "narrow-ui:toggle-search-use-regex"
-
-    disposables = new CompositeDisposable
-    keyBindingTarget = @editorElement
-    for elementName, commandName of tooltips when element = @elements[elementName]
-      disposables.add(addToolTips({element, commandName, keyBindingTarget}))
-    disposables


Defer if definition doesnt have arity declared yet

--- src/js/app/compilers/teascript/compiler.coffee
+++ src/js/app/compilers/teascript/compiler.coffee
@@ -2677,9 +2677,9 @@
       type = freshInstance ctx, contextType
       nameTranslate ctx, atom, symbol, type
     # In sub-scope (function) only defer compilation for declarations in current scope
-    else if (not ctx.isCurrentlyDeclared symbol) and
-        ((ctx.isFinallyDeclared symbol) or symbol in ctx.parentDeferrableDefinitionNames()) or
-          contextType instanceof TempType
+    else if ((not ctx.isCurrentlyDeclared symbol) and (ctx.arity symbol) and
+          ((ctx.isFinallyDeclared symbol) or symbol in ctx.parentDeferrableDefinitionNames())) or
+            contextType instanceof TempType
       # Typing deferred, use an impricise type var
       type = toConstrained ctx.freshTypeVariable star
       ctx.addToDeferredNames {name: symbol, type: (mapOrigin type, atom)}
@@ -3353,11 +3353,11 @@
   "null"

-jsReturn = (arg) ->
-  {js: jsReturnTranslate, arg}
-
-jsReturnTranslate = ({arg}) ->
-  "return #{arg};"
+jsReturn = (result) ->
+  {js: jsReturnTranslate, result}
+
+jsReturnTranslate = ({result}) ->
+  "return #{result};"

 jsTernary = (cond, thenExp, elseExp) ->
@@ -6461,6 +6461,30 @@
   """
   'f', 7

+  'constraints and deferring'
+  """
+  Show (class [a]
+    show (fn [x] (: (Fn a String))))
+
+  show-string (instance (Show String)
+    show (fn [x] x))
+
+  s (fn [y]
+    (show y))
+
+  f (fn [x]
+    g)
+
+  g "2"
+
+  r (fn [y]
+    (f (s y)))
+
+  j (fn [x]
+    (r "src"))
+  """
+  '(j 2)', "2"
+

   # TODO: support matching with the same name
   #       to implement this we need the iife to take as arguments all variables


[fix] Wrong snippets.

[fix] Wrong snippets.

--- snippets/snippets.cson
+++ snippets/snippets.cson
@@ -1,543 +1,543 @@
-'.bve-map-2.02':
-  #自軌道の平面曲線
-  'curve':
-    'prefix': 'Curve'
-    'body': 'Curve'
-    'description': '自軌道の平面曲線を表すマップ要素です。'
-    'rightLabelHTML': '自軌道の平面曲線'
-  'curve.setgauge':
-    'prefix': 'SetGauge(value)'
-    'body': 'SetGauge(${1:value});${2:}'
-    'description': '現在の距離程以降の軌間を設定します。この値は、カントを角度に換算するために使用します。'
-    'leftLabelHTML': 'Curve.'
-    'rightLabelHTML': '平面曲線'
-  'curve.setcenter':
-    'prefix': 'SetCenter(x)'
-    'body': 'SetCenter(${1:x});${2:}'
-    'description': '現在の距離程以降のカントの回転中心位置を設定します。'
-    'leftLabelHTML': 'Curve.'
-    'rightLabelHTML': '平面曲線'
-  'curve.setfunction':
-    'prefix': 'SetFunction(id)'
-    'body': 'SetFunction(${1:id});${2:}'
-    'description': '現在の距離程以降の緩和曲線関数を設定します。'
-    'leftLabelHTML': 'Curve.'
-    'rightLabelHTML': '平面曲線'
-  'curve.begin1':
-    'prefix': 'Begin(radius,cant)'
-    'body': 'Begin(${1:radius},${2:cant});${3:}'
-    'description': '平面曲線の円曲線を現在の距離程から開始します。'
-    'leftLabelHTML': 'Curve.'
-    'rightLabelHTML': '平面曲線'
-  'curve.begin2':
-    'prefix': 'Begin(radius)'
-    'body': 'Begin(${1:radius});${2:}'
-    'description': '平面曲線の円曲線を現在の距離程から開始します。'
-    'leftLabelHTML': 'Curve.'
-    'rightLabelHTML': '平面曲線'
-  'curve.interpolate1':
-    'prefix': 'Interpolate(radius,cant)'
-    'body': 'Interpolate(${1:radius},${2:cant});${3:}'
-    'description': '現在の距離程における平面曲線の半径とカントを設定します。'
-    'leftLabelHTML': 'Curve.'
-    'rightLabelHTML': '平面曲線'
-  'curve.interpolate2':
-    'prefix': 'Interpolate(radius)'
-    'body': 'Interpolate(${1:radius});${2:}'
-    'description': '現在の距離程における平面曲線の半径とカントを設定します。'
-    'leftLabelHTML': 'Curve.'
-    'rightLabelHTML': '平面曲線'
-  'curve.interpolate2':
-    'prefix': 'Interpolate()'
-    'body': 'Interpolate();${1:}'
-    'description': '現在の距離程における平面曲線の半径とカントを設定します。'
-    'leftLabelHTML': 'Curve.'
-    'rightLabelHTML': '平面曲線'
-
-  #自軌道の勾配
-  'gradient':
-    'prefix': 'Gradient'
-    'body': 'Gradient'
-    'description': '自軌道の勾配を表すマップ要素です。'
-    'rightLabelHTML': '勾配'
-  'gradient.begin':
-    'prefix': 'Begin(gradient)'
-    'body': 'Begin(${1:gradient});${2:}'
-    'description': '縦曲線を現在の距離程で終了し、勾配を一定に保ちます。'
-    'leftLabelHTML': 'Gradient.'
-    'rightLabelHTML': '勾配'
-  'gradient.interpolate1':
-    'prefix': 'Interpolate(gradient)'
-    'body': 'Interpolate(${1:gradient});${2:}'
-    'description': '現在の距離程に置ける勾配を設定します。2つのInterpolate間は線形補間されます。'
-    'leftLabelHTML': 'Gradient.'
-    'rightLabelHTML': '勾配'
-  'gradient.interpolate2':
-    'prefix': 'Interpolate()'
-    'body': 'Interpolate();${1:}'
-    'description': '現在の距離程に置ける勾配を設定します。2つのInterpolate間は線形補間されます。'
-    'leftLabelHTML': 'Gradient.'
-    'rightLabelHTML': '勾配'
-
-  #他軌道
-  'track':
-    'prefix': 'Track[\'trackKey\']'
-    'body': 'Track[\'${1:trackKey}\']${2:}'
-    'description': '他軌道を表すマップ要素です。'
-    'rightLabelHTML': '他軌道'
-  'track.x.interpolate1':
-    'prefix': 'X.Interpolate(x,radius)'
-    'body': 'X.Interpolate(${1:x},${2:radius});${3:}'
-    'description': '現在に距離程における他軌道のx方向位置を設定します。2つのX.Interpolate間は線形補間されます。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.x.interpolate2':
-    'prefix': 'X.Interpolate(x)'
-    'body': 'X.Interpolate(${1:x});${2:}'
-    'description': '現在に距離程における他軌道のx方向位置を設定します。2つのX.Interpolate間は線形補間されます。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.x.interpolate3':
-    'prefix': 'X.Interpolate()'
-    'body': 'X.Interpolate();${1:}'
-    'description': '現在に距離程における他軌道のx方向位置を設定します。2つのX.Interpolate間は線形補間されます。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.y.interpolate1':
-    'prefix': 'Y.Interpolate(y,radius)'
-    'body': 'Y.Interpolate(${1:y},${2:radius});${3:}'
-    'description': '現在に距離程における他軌道のy方向位置を設定します。2つのY.Interpolate間は線形補間されます。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.y.interpolate2':
-    'prefix': 'Y.Interpolate(y)'
-    'body': 'Y.Interpolate(${1:y});${2:}'
-    'description': '現在に距離程における他軌道のy方向位置を設定します。2つのY.Interpolate間は線形補間されます。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.y.interpolate3':
-    'prefix': 'Y.Interpolate()'
-    'body': 'Y.Interpolate();${1:}'
-    'description': '現在に距離程における他軌道のy方向位置を設定します。2つのY.Interpolate間は線形補間されます。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.position1':
-    'prefix': 'Position(x,y,radiusH,radiusV)'
-    'body': 'Position(${1:x},${2:y},${3:radiusH},${4:radiusV});${5:}'
-    'description': '現在の距離程における他軌道の位置を設定します。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.position2':
-    'prefix': 'Position(x,y,radiusH)'
-    'body': 'Position(${1:x},${2:y},${3:radiusH});${4:}'
-    'description': '現在の距離程における他軌道の位置を設定します。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.position3':
-    'prefix': 'Position(x,y)'
-    'body': 'Position(${1:x},${2:y});${3:}'
-    'description': '現在の距離程における他軌道の位置を設定します。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.cant.setgauge':
-    'prefix': 'Cant.SetGauge(gauge)'
-    'body': 'Cant.setGauge(${1:gauge});${2:}'
-    'description': '現在の距離程以降の他軌道の軌間を設定します。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.cant.setcenter':
-    'prefix': 'Cant.SetCenter(x)'
-    'body': 'Cant.setCenter(${1:x});${2:}'
-    'description': '現在の距離程以降の他軌道のカントの回転中心位置を設定します。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.cant.setfunction':
-    'prefix': 'Cant.SetFunction(id)'
-    'body': 'Cant.SetFunction(${1:id});${2:}'
-    'description': '現在の距離程以降の他軌道のカント逓減関数を設定します。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.cant.begintransition':
-    'prefix': 'Cant.BeginTransition()'
-    'body': 'Cant.BeginTransition();${1:}'
-    'description': '他軌道のカントの逓減を現在の距離程から開始します。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.cant.begin':
-    'prefix': 'Cant.Begin(cant)'
-    'body': 'Cant.Begin(${1:cant});${2:}'
-    'description': '他軌道のカントの逓減を現在の距離程で終了し、カントを一定に保ちます。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.cant.end':
-    'prefix': 'Cant.End()'
-    'body': 'Cant.Begin();${1:}'
-    'description': '他軌道のカントを現在の距離程で終了します。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.cant.interpolate1':
-    'prefix': 'Cant.Interpolate(cant)'
-    'body': 'Cant.Interpolate(${1:cant});${2:}'
-    'description': '現在の距離程における他軌道のカントを設定します。2つのCant.Interpolate間のカントは補完されます。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-  'track.cant.interpolate2':
-    'prefix': 'Cant.Interpolate()'
-    'body': 'Cant.Interpolate();${1:}'
-    'description': '現在の距離程における他軌道のカントを設定します。2つのCant.Interpolate間のカントは補完されます。'
-    'leftLabelHTML': 'Track.'
-    'rightLabelHTML': '他軌道'
-
-  #ストラクチャ
-  'structure.load':
-    'prefix': 'Structure.Load(\'filePath\')'
-    'body': 'Structure.Load(\'${1:filePath}\');${2:}'
-    'description': 'ストラクチャリストファイルに基づいてストラクチャを読み込みます。'
-    'rightLabelHTML': 'ストラクチャ'
-  'structure':
-    'prefix': 'Structure[\'structureKey\']'
-    'body': 'Structure[\'${1:structureKey}\']${2:}'
-    'description': 'ストラクチャを表すマップ要素です。'
-    'rightLabelHTML': 'ストラクチャ'
-  'structure.put':
-    'prefix': 'Put(\'trackKey\',x,y,z,rx,ry,rz,tilt,span)'
-    'body': 'Put(\'${1:trackKey}\',${2:x},${3:y},${4:z},${5:rx},${6:ry},${7:rz},${8:tilt},${9:span});${10:}'
-    'description': 'ストラクチャを設置します。'
-    'leftLabelHTML': 'Structure.'
-    'rightLabelHTML': 'ストラクチャ'
-  'structure.put0':
-    'prefix': 'Put0(\'trackKey\'tilt,span)'
-    'body': 'Put(\'${1:trackKey}\',${2:tilt},${3:span});${4:}'
-    'description': 'ストラクチャを設置します。'
-    'leftLabelHTML': 'Structure.'
-    'rightLabelHTML': 'ストラクチャ'
-  'structure.putbetween1':
-    'prefix': 'PutBetWeen(\'trackKey1\',\'trackKey2\',flag)'
-    'body': 'PutBetWeen(\'${1:trackKey1}\',\'${2:trackKey2}\',${3:flag});${4:}'
-    'description': 'ストラクチャを現在の距離程の2つの軌道の間に設置します。ストラクチャは軌道間の距離に応じて変形します。'
-    'leftLabelHTML': 'Structure.'
-    'rightLabelHTML': 'ストラクチャ'
-  'structure.putbetween2':
-    'prefix': 'PutBetWeen(\'trackKey1\',\'trackKey2\')'
-    'body': 'PutBetWeen(\'${1:trackKey1}\',\'${2:trackKey2}\');${3:}'
-    'description': 'ストラクチャを現在の距離程の2つの軌道の間に設置します。ストラクチャは軌道間の距離に応じて変形します。'
-    'leftLabelHTML': 'Structure.'
-    'rightLabelHTML': 'ストラクチャ'
-
-  #連続ストラクチャ
-  'repeater':
-    'prefix': 'Repeater[\'repeaterKey\']'
-    'body': 'Repeater[\'${1:repeaterKey}\']${2:}'
-    'description': '連続ストラクチャを表すマップ要素です。'
-    'rightLabelHTML': '連続ストラクチャ'
-  'repeater.begin':
-    'prefix': 'Begin(\'trackKey\',x,y,z,rx,ry,rz,tilt,span,interval)'
-    'body': 'Begin(\'${1:trackKey}\',${2:x},${3:y},${4:z},${5:rx},${6:ry},${7:rz},${8:tilt},${9:span},${10:interval},\'${11:structureKey}\');${12:}'
-    'description': 'ストラクチャの連続配置を現在の距離程から開始します。'
-    'leftLabelHTML': 'Repeater.'
-    'rightLabelHTML': '連続ストラクチャ'
-  'repeater.begin0':
-    'prefix': 'Begin0(\'trackKey\',tilt,span,interval)'
-    'body': 'Begin0(\'${1:trackKey}\',${2:tilt},${3:span},${4:interval},\'${5:structureKey}\');${6:}'
-    'description': 'ストラクチャの連続配置を現在の距離程から開始します。'
-    'leftLabelHTML': 'Repeater.'
-    'rightLabelHTML': '連続ストラクチャ'
-  'background.change':
-    'prefix': 'Background.Change(structureKey)'
-    'body': 'Background.Change(\'${1:structureKey}\');${2:}'
-    'description': '背景を変更します。'
-    'rightLabelHTML': '連続ストラクチャ'
-
-  #停車場
-  'station.load':
-    'prefix': 'Station.Load(\'filePath\')'
-    'body': 'Station.Load(\'${1:filePath}\');${2:}'
-    'description': '停車場リストファイルに基づいて停車場を定義します。'
-    'rightLabelHTML': '停車場'
-  'station.put':
-    'prefix': 'Station[\'stationKey\'].Put(door,margin1,margin2)'
-    'body': 'Station[\'${1:stationKey}\'].Put(${2:door},${3:margin1},${4:margin2});${5:}'
-    'description': 'この列車の停止位置を現在の距離程に設定します。'
-    'rightLabelHTML': '停車場'
-
-  #閉塞
-  'section':
-    'prefix': 'Section'
-    'body': 'Section'
-    'description': '閉塞を表すマップ要素です。'
-    'rightLabelHTML': '閉塞'
-  'section.begin':
-    'prefix': 'Begin(\'singal0\',\'signal1\',...,\'signalN\')'
-    'body': 'Begin(\'${1:signal0}\',\'${2:signal1}\',\'${3:signal2}\');${4:}'
-    'description': '新しい閉塞を現在の距離程から開始します。'
-    'leftLabelHTML': 'Section.'
-    'rightLabelHTML': '閉塞'
-  'section.setspeedlimit':
-    'prefix': 'SetSpeedLimit(v0,v1,...,vN)'
-    'body': 'SetSpeedLimit(${1:v0},${2:v1},${3:v2},${4:v3},${5:v4});${6:}'
-    'description': '信号現示の許容速度を設定します。'
-    'leftLabelHTML': 'Section.'
-    'rightLabelHTML': '閉塞'
-
-  #地上信号機
-  'signal':
-    'prefix': 'Signal[\'signalAspectKey\']'
-    'body': 'Signal[\'${1:signalAspectKey}\']${2:}'
-    'description': '地上信号機を表すマップ要素です。'
-    'rightLabelHTML': '地上信号機'
-  'signal.load':
-    'prefix': 'Load(\'filePath\')'
-    'body': 'Load(\'${1:filePath}\');${2:}'
-    'description': '信号現示リストファイルに基づいて信号現示を定義します。'
-    'leftLabelHTML': 'Signal.'
-    'rightLabelHTML': '地上信号機'
-  'signal.put1':
-    'prefix': 'Put(section,\'trackKey\',x,y)'
-    'body': 'Put(${1:section},\'${2:trackKey}\',${3:x},${4:y});${5:}'
-    'description': '地上信号機を現在の距離程に設置します。'
-    'leftLabelHTML': 'Signal.'
-    'rightLabelHTML': '地上信号機'
-  'signal.put2':
-    'prefix': 'Put(section,\'trackKey\',x,y,z,rx,ry,rz,tilt,span)'
-    'body': 'Put(${1:section},\'${2:trackKey}\',${3:x},${4:y},${5:z},${6:rx},${7:ry},${8:rz},${9:tilt},${10:span});${11:}'
-    'description': '地上信号機を現在の距離程に設置します。'
-    'leftLabelHTML': 'Signal.'
-    'rightLabelHTML': '地上信号機'
-
-  #地上子
-  'beacon.put':
-    'prefix': 'Beacon.Put(type,section,sendData)'
-    'body': 'Beacon.Put(${1:type},${2:section},${3:sendData});${4:}'
-    'description': '地上子の送信イベントを現在の距離程に定義します。'
-    'rightLabelHTML': '地上子'
-
-  #速度制限
-  'speedlimit':
-    'prefix': 'SpeedLimit'
-    'body': 'SpeedLimit'
-    'description': '速度制限を表すマップ要素です。'
-    'rightLabelHTML': '速度制限'
-  'speedlimit.begin':
-    'prefix': 'Begin(v)'
-    'body': 'Begin(${1:v});${2:}'
-    'description': '速度制限を現在の距離程から開始します。'
-    'leftLabelHTML': 'SpeedLimit.'
-    'rightLabelHTML': '速度制限'
-
-  #先行列車
-  'pretrain':
-    'prefix': 'PreTrain'
-    'body': 'PreTrain'
-    'description': '先行列車を表すマップ要素です。'
-    'rightLabelHTML': '先行列車'
-  'pretrain.pass1':
-    'prefix': 'Pass(\'hh:mm:ss\')'
-    'body': 'Pass(\'${1:hh}:${2:mm}:${3:ss}\');${4:}'
-    'description': '先行列車が現在の距離程を通過する時刻を設定します。'
-    'leftLabelHTML': 'PreTrain.'
-    'rightLabelHTML': '先行列車'
-  'pretrain.pass2':
-    'prefix': 'Pass(second)'
-    'body': 'Pass(${1:second});${2:}'
-    'description': '先行列車が現在の距離程を通過する時刻を設定します。'
-    'leftLabelHTML': 'PreTrain.'
-    'rightLabelHTML': '先行列車'
-
-  #光源
-  'light':
-    'prefix': 'Light'
-    'body': 'Light'
-    'description': '光源を表すマップ要素です。'
-    'rightLabelHTML': '光源'
-  'light.ambient':
-    'prefix': 'Ambient(red,green,blue)'
-    'body': 'Ambient(${1:red},${2:green},${3:blue});${4:}'
-    'description': '環境光の色(アンビエント色)を設定します。この構文はマップファイルに1回のみ記述可能です。'
-    'leftLabelHTML': 'Light.'
-    'rightLabelHTML': '光源'
-  'light.diffuse':
-    'prefix': 'Diffuse(red,green,blue)'
-    'body': 'Diffuse(${1:red},${2:green},${3:blue});${4:}'
-    'description': '平行光の色(デフューズ色)を設定します。この構文はマップファイルに1回のみ記述可能です。'
-    'leftLabelHTML': 'Light.'
-    'rightLabelHTML': '光源'
-  'light.direction':
-    'prefix': 'Direction(pitch,yaw)'
-    'body': 'Direction(${1:pitch},${2:yaw});${3:}'
-    'description': '距離程0において、平行光がさす方向を設定します。この構文はマップファイルに1回のみ記述可能です。'
-    'leftLabelHTML': 'Light.'
-    'rightLabelHTML': '光源'
-
-  #霧効果
-  'fog':
-    'prefix': 'Fog'
-    'body': 'Fog'
-    'description': '霧効果を表すマップ要素です。'
-    'rightLabelHTML': '霧効果'
-  'fog.interpolate1':
-    'prefix': 'Interpolate(density,red,green,blue)'
-    'body': 'Interpolate(${1:density},${2:red},${3:green},${4:blue});${5:}'
-    'description': '現在の距離程における霧効果を設定します。2つのFog.Interpolate間は線形補間されます。'
-    'leftLabelHTML': 'Fog.'
-    'rightLabelHTML': '霧効果'
-  'fog.interpolate2':
-    'prefix': 'Interpolate(density)'
-    'body': 'Interpolate(${1:density});${2:}'
-    'description': '現在の距離程における霧効果を設定します。2つのFog.Interpolate間は線形補間されます。'
-    'leftLabelHTML': 'Fog.'
-    'rightLabelHTML': '霧効果'
-  'fog.interpolate3':
-    'prefix': 'Interpolate()'
-    'body': 'Interpolate();${1:}'
-    'description': '現在の距離程における霧効果を設定します。2つのFog.Interpolate間は線形補間されます。'
-    'leftLabelHTML': 'Fog.'
-    'rightLabelHTML': '霧効果'
-
-  #風景描画距離
-  'drawdistance.change':
-    'prefix': 'DrawDistance.Change(value)'
-    'body': 'DrawDistance.Change(${1:value});${2:}'
-    'description': '現在の距離程以降の風景の描画距離を設定します。'
-    'rightLabelHTML': '風景描画距離'
-
-  #運転台の明るさ
-  'cabllluminance':
-    'prefix': 'Cabllluminance'
-    'body': 'Cabllluminance'
-    'description': '運転台の明るさを表すマップ要素です。'
-    'rightLabelHTML': '運転台の明るさ'
-  'cabllluminance.interpolate1':
-    'prefix': 'Interpolate(value)'
-    'body': 'Interpolate(${1:value});${2:}'
-    'description': '現在の距離程における運転台の明るさを設定します。2つのCabllluminance.Interpolate間は線形補間されます。'
-    'leftLabelHTML': 'Cabllluminance.'
-    'rightLabelHTML': '運転台の明るさ'
-  'cabllluminance.interpolate2':
-    'prefix': 'Interpolate()'
-    'body': 'Interpolate();${1:}'
-    'description': '現在の距離程における運転台の明るさを設定します。2つのCabllluminance.Interpolate間は線形補間されます。'
-    'leftLabelHTML': 'Cabllluminance.'
-    'rightLabelHTML': '運転台の明るさ'
-
-  #軌道変位
-  'irregularity.change':
-    'prefix': 'Irregularity.Change(x,y,r,lx,ly,lr)'
-    'body': 'Irregularity.Change(${1:x},${2:y},${3:r},${4:lx},${5:ly},${6:lr});${7:}'
-    'description': '現在の距離程以降の軌道変位を設定します。'
-    'rightLabelHTML': '軌道変位'
-
-  #粘着特性
-  'adhesion':
-    'prefix': 'Adhesion'
-    'body': 'Adhesion'
-    'description': '粘着特性を表すマップ要素です。'
-    'rightLabelHTML': '粘着特性'
-  'adhesion.change1':
-    'prefix': 'Change(a)'
-    'body': 'Change(${1:a});${2:}'
-    'description': '現在の距離程以降の車輪とレール間の粘着特性を設定します。'
-    'leftLabelHTML': 'Adhesion.'
-    'rightLabelHTML': '粘着特性'
-  'adhesion.change2':
-    'prefix': 'Change(a,b,c)'
-    'body': 'Change(${1:a},${2:b},${3:c});${4:}'
-    'description': '現在の距離程以降の車輪とレール間の粘着特性を設定します。'
-    'leftLabelHTML': 'Adhesion.'
-    'rightLabelHTML': '粘着特性'
-
-  #音
-  'sound.load':
-    'prefix': 'Sound.Load(\'filePath\')'
-    'body': 'Sound.Load(\'${1:filePath}\');${2:}'
-    'description': 'サウンドリストファイルに基づいてサウンドを読み込みます。'
-    'rightLabelHTML': '音'
-  'sound.play':
-    'prefix': 'Sound[\'soundKey\'].Play()'
-    'body': 'Sound[\'${1:soundKey}\'].Play();${2:}'
-    'description': '現在の距離程を通過するときにサウンドを1回再生します。'
-    'rightLabelHTML': '音'
-
-  #固定音源
-  'sound3d.load':
-    'prefix': 'Sound3D.Load(\'filePath\')'
-    'body': 'Sound.Load(\'${1:filePath}\');${2:}'
-    'description': 'サウンドリストファイルに基づいてサウンドを読み込みます。'
-    'rightLabelHTML': '固定音源'
-  'sound3d.put':
-    'prefix': 'Sound3D[\'soundKey\'].Put(x,y)'
-    'body': 'Sound3D[\'${1:soundKey}\'].Put(${3:x},${4:y});${5:}'
-    'description': '地上に固定された音源を現在の距離程に設置します。サウンドは連続再生されます。'
-    'rightLabelHTML': '固定音源'
-
-  #走行音
-  'rollingnoise.change':
-    'prefix': 'RollingNoise.Change(index)'
-    'body': 'RollingNoise.Change(${1:index});${2:}'
-    'description': '現在の距離程以降の車輪転動音を設定します。'
-    'rightLabelHTML': '走行音'
-
-  #フランジきしり音
-  'flangenoise.change':
-    'prefix': 'FlangeNoise.Change(index)'
-    'body': 'FlangeNoise.Change(${1:index});${2:}'
-    'description': '現在の距離程以降のフランジきしり音を設定します。'
-    'rightLabelHTML': 'フランジきしり音'
-
-  #分岐器通過音
-  'jointnoise.play':
-    'prefix': 'JointNoise.Play(index)'
-    'body': 'JointNoise.Play(${1:index});${2:}'
-    'description': '現在の距離程を通過するときに分岐器通過音を走行速度に応じて再生します。'
-    'rightLabelHTML': '分岐器通過音'
-
-  #他列車
-  'train':
-    'prefix': 'Train[\'trainKey\']'
-    'body': 'Train[\'trainKey\']'
-    'description': '他列車を表すマップ要素です。'
-    'rightLabelHTML': '他列車'
-  'train.add':
-    'prefix': 'Train.Add(\'trainKey\',filePath,\'trackKey\',direction)'
-    'body': 'Train.Add(\'${1:trainKey}\',${2:filePath},\'${3:trackKey}\',${4:direction});${5:}'
-    'description': '他列車を定義します。'
-    'rightLabelHTML': '他列車'
-  'train.load':
-    'prefix': 'Load(\'filePath\',\'trackKey\',direction)'
-    'body': 'Load(\'${1:filePath}\',\'${2:trackKey}\',${3:direction});${4:}'
-    'description': '他列車を定義します。'
-    'rightLabelHTML': '他列車'
-    'leftLabelHTML': 'Train.'
-  'train.enable1':
-    'prefix': 'Enable(\'time\')'
-    'body': 'Enable(\'${1:hh}:${2:mm}:${3:ss}\');${4:}'
-    'description': '他列車が現在の距離程を通過し、かつ設定された時刻になったとき、他列車の動作を有効にします。'
-    'rightLabelHTML': '他列車'
-    'leftLabelHTML': 'Train.'
-  'train.enable2':
-    'prefix': 'Enable(second)'
-    'body': 'Enable(${1:second});${2:}'
-    'description': '他列車が現在の距離程を通過し、かつ設定された時刻になったとき、他列車の動作を有効にします。'
-    'rightLabelHTML': '他列車'
-    'leftLabelHTML': 'Train.'
-  'train.stop':
-    'prefix': 'Stop(decelerate,stopTime,accelerate,speed)'
-    'body': 'Stop(${1:decelerate},${2:stopTime},${3:accelerate},${4:speed});${5:}'
-    'description': '他列車を現在の距離程に一旦停車させます。'
-    'rightLabelHTML': '他列車'
-    'leftLabelHTML': 'Train.'
-
-  #他マップの挿入
-  'include':
-    'prefix': 'include \'submap.txt\''
-    'body': 'include \'${1:submap}.txt\';${2:}'
-    'description': '他マップファイルの内容をその位置に挿入します。'
-
-  #その他
-  'end':
-    'prefix': 'End'
-    'body': 'End();${1:}'
-    'description': '平面曲線,縦曲線,ストラクチャの連続配置,速度制限を現在の距離程から開始します。'
-  'begintransition':
-    'prefix': 'BeginTransition'
-    'body': 'BeginTransition();'
-    'description': '緩和曲線,縦曲線の遷移を現在の距離程から開始します。'
+'.bve-map-2.02':
+  #自軌道の平面曲線
+  'curve':
+    'prefix': 'Curve'
+    'body': 'Curve'
+    'description': '自軌道の平面曲線を表すマップ要素です。'
+    'rightLabelHTML': '自軌道の平面曲線'
+  'curve.setgauge':
+    'prefix': 'SetGauge(value)'
+    'body': 'SetGauge(${1:value});${2:}'
+    'description': '現在の距離程以降の軌間を設定します。この値は、カントを角度に換算するために使用します。'
+    'leftLabelHTML': 'Curve.'
+    'rightLabelHTML': '平面曲線'
+  'curve.setcenter':
+    'prefix': 'SetCenter(x)'
+    'body': 'SetCenter(${1:x});${2:}'
+    'description': '現在の距離程以降のカントの回転中心位置を設定します。'
+    'leftLabelHTML': 'Curve.'
+    'rightLabelHTML': '平面曲線'
+  'curve.setfunction':
+    'prefix': 'SetFunction(id)'
+    'body': 'SetFunction(${1:id});${2:}'
+    'description': '現在の距離程以降の緩和曲線関数を設定します。'
+    'leftLabelHTML': 'Curve.'
+    'rightLabelHTML': '平面曲線'
+  'curve.begin1':
+    'prefix': 'Begin(radius,cant)'
+    'body': 'Begin(${1:radius},${2:cant});${3:}'
+    'description': '平面曲線の円曲線を現在の距離程から開始します。'
+    'leftLabelHTML': 'Curve.'
+    'rightLabelHTML': '平面曲線'
+  'curve.begin2':
+    'prefix': 'Begin(radius)'
+    'body': 'Begin(${1:radius});${2:}'
+    'description': '平面曲線の円曲線を現在の距離程から開始します。'
+    'leftLabelHTML': 'Curve.'
+    'rightLabelHTML': '平面曲線'
+  'curve.interpolate1':
+    'prefix': 'Interpolate(radius,cant)'
+    'body': 'Interpolate(${1:radius},${2:cant});${3:}'
+    'description': '現在の距離程における平面曲線の半径とカントを設定します。'
+    'leftLabelHTML': 'Curve.'
+    'rightLabelHTML': '平面曲線'
+  'curve.interpolate2':
+    'prefix': 'Interpolate(radius)'
+    'body': 'Interpolate(${1:radius});${2:}'
+    'description': '現在の距離程における平面曲線の半径とカントを設定します。'
+    'leftLabelHTML': 'Curve.'
+    'rightLabelHTML': '平面曲線'
+  'curve.interpolate2':
+    'prefix': 'Interpolate()'
+    'body': 'Interpolate();${1:}'
+    'description': '現在の距離程における平面曲線の半径とカントを設定します。'
+    'leftLabelHTML': 'Curve.'
+    'rightLabelHTML': '平面曲線'
+
+  #自軌道の勾配
+  'gradient':
+    'prefix': 'Gradient'
+    'body': 'Gradient'
+    'description': '自軌道の勾配を表すマップ要素です。'
+    'rightLabelHTML': '勾配'
+  'gradient.begin':
+    'prefix': 'Begin(gradient)'
+    'body': 'Begin(${1:gradient});${2:}'
+    'description': '縦曲線を現在の距離程で終了し、勾配を一定に保ちます。'
+    'leftLabelHTML': 'Gradient.'
+    'rightLabelHTML': '勾配'
+  'gradient.interpolate1':
+    'prefix': 'Interpolate(gradient)'
+    'body': 'Interpolate(${1:gradient});${2:}'
+    'description': '現在の距離程に置ける勾配を設定します。2つのInterpolate間は線形補間されます。'
+    'leftLabelHTML': 'Gradient.'
+    'rightLabelHTML': '勾配'
+  'gradient.interpolate2':
+    'prefix': 'Interpolate()'
+    'body': 'Interpolate();${1:}'
+    'description': '現在の距離程に置ける勾配を設定します。2つのInterpolate間は線形補間されます。'
+    'leftLabelHTML': 'Gradient.'
+    'rightLabelHTML': '勾配'
+
+  #他軌道
+  'track':
+    'prefix': 'Track[\'trackKey\']'
+    'body': 'Track[\'${1:trackKey}\']${2:}'
+    'description': '他軌道を表すマップ要素です。'
+    'rightLabelHTML': '他軌道'
+  'track.x.interpolate1':
+    'prefix': 'X.Interpolate(x,radius)'
+    'body': 'X.Interpolate(${1:x},${2:radius});${3:}'
+    'description': '現在に距離程における他軌道のx方向位置を設定します。2つのX.Interpolate間は線形補間されます。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.x.interpolate2':
+    'prefix': 'X.Interpolate(x)'
+    'body': 'X.Interpolate(${1:x});${2:}'
+    'description': '現在に距離程における他軌道のx方向位置を設定します。2つのX.Interpolate間は線形補間されます。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.x.interpolate3':
+    'prefix': 'X.Interpolate()'
+    'body': 'X.Interpolate();${1:}'
+    'description': '現在に距離程における他軌道のx方向位置を設定します。2つのX.Interpolate間は線形補間されます。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.y.interpolate1':
+    'prefix': 'Y.Interpolate(y,radius)'
+    'body': 'Y.Interpolate(${1:y},${2:radius});${3:}'
+    'description': '現在に距離程における他軌道のy方向位置を設定します。2つのY.Interpolate間は線形補間されます。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.y.interpolate2':
+    'prefix': 'Y.Interpolate(y)'
+    'body': 'Y.Interpolate(${1:y});${2:}'
+    'description': '現在に距離程における他軌道のy方向位置を設定します。2つのY.Interpolate間は線形補間されます。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.y.interpolate3':
+    'prefix': 'Y.Interpolate()'
+    'body': 'Y.Interpolate();${1:}'
+    'description': '現在に距離程における他軌道のy方向位置を設定します。2つのY.Interpolate間は線形補間されます。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.position1':
+    'prefix': 'Position(x,y,radiusH,radiusV)'
+    'body': 'Position(${1:x},${2:y},${3:radiusH},${4:radiusV});${5:}'
+    'description': '現在の距離程における他軌道の位置を設定します。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.position2':
+    'prefix': 'Position(x,y,radiusH)'
+    'body': 'Position(${1:x},${2:y},${3:radiusH});${4:}'
+    'description': '現在の距離程における他軌道の位置を設定します。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.position3':
+    'prefix': 'Position(x,y)'
+    'body': 'Position(${1:x},${2:y});${3:}'
+    'description': '現在の距離程における他軌道の位置を設定します。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.cant.setgauge':
+    'prefix': 'Cant.SetGauge(gauge)'
+    'body': 'Cant.setGauge(${1:gauge});${2:}'
+    'description': '現在の距離程以降の他軌道の軌間を設定します。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.cant.setcenter':
+    'prefix': 'Cant.SetCenter(x)'
+    'body': 'Cant.setCenter(${1:x});${2:}'
+    'description': '現在の距離程以降の他軌道のカントの回転中心位置を設定します。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.cant.setfunction':
+    'prefix': 'Cant.SetFunction(id)'
+    'body': 'Cant.SetFunction(${1:id});${2:}'
+    'description': '現在の距離程以降の他軌道のカント逓減関数を設定します。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.cant.begintransition':
+    'prefix': 'Cant.BeginTransition()'
+    'body': 'Cant.BeginTransition();${1:}'
+    'description': '他軌道のカントの逓減を現在の距離程から開始します。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.cant.begin':
+    'prefix': 'Cant.Begin(cant)'
+    'body': 'Cant.Begin(${1:cant});${2:}'
+    'description': '他軌道のカントの逓減を現在の距離程で終了し、カントを一定に保ちます。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.cant.end':
+    'prefix': 'Cant.End()'
+    'body': 'Cant.Begin();${1:}'
+    'description': '他軌道のカントを現在の距離程で終了します。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.cant.interpolate1':
+    'prefix': 'Cant.Interpolate(cant)'
+    'body': 'Cant.Interpolate(${1:cant});${2:}'
+    'description': '現在の距離程における他軌道のカントを設定します。2つのCant.Interpolate間のカントは補完されます。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+  'track.cant.interpolate2':
+    'prefix': 'Cant.Interpolate()'
+    'body': 'Cant.Interpolate();${1:}'
+    'description': '現在の距離程における他軌道のカントを設定します。2つのCant.Interpolate間のカントは補完されます。'
+    'leftLabelHTML': 'Track.'
+    'rightLabelHTML': '他軌道'
+
+  #ストラクチャ
+  'structure.load':
+    'prefix': 'Structure.Load(\'filePath\')'
+    'body': 'Structure.Load(\'${1:filePath}\');${2:}'
+    'description': 'ストラクチャリストファイルに基づいてストラクチャを読み込みます。'
+    'rightLabelHTML': 'ストラクチャ'
+  'structure':
+    'prefix': 'Structure[\'structureKey\']'
+    'body': 'Structure[\'${1:structureKey}\']${2:}'
+    'description': 'ストラクチャを表すマップ要素です。'
+    'rightLabelHTML': 'ストラクチャ'
+  'structure.put':
+    'prefix': 'Put(\'trackKey\',x,y,z,rx,ry,rz,tilt,span)'
+    'body': 'Put(\'${1:trackKey}\',${2:x},${3:y},${4:z},${5:rx},${6:ry},${7:rz},${8:tilt},${9:span});${10:}'
+    'description': 'ストラクチャを設置します。'
+    'leftLabelHTML': 'Structure.'
+    'rightLabelHTML': 'ストラクチャ'
+  'structure.put0':
+    'prefix': 'Put0(\'trackKey\'tilt,span)'
+    'body': 'Put(\'${1:trackKey}\',${2:tilt},${3:span});${4:}'
+    'description': 'ストラクチャを設置します。'
+    'leftLabelHTML': 'Structure.'
+    'rightLabelHTML': 'ストラクチャ'
+  'structure.putbetween1':
+    'prefix': 'PutBetWeen(\'trackKey1\',\'trackKey2\',flag)'
+    'body': 'PutBetWeen(\'${1:trackKey1}\',\'${2:trackKey2}\',${3:flag});${4:}'
+    'description': 'ストラクチャを現在の距離程の2つの軌道の間に設置します。ストラクチャは軌道間の距離に応じて変形します。'
+    'leftLabelHTML': 'Structure.'
+    'rightLabelHTML': 'ストラクチャ'
+  'structure.putbetween2':
+    'prefix': 'PutBetWeen(\'trackKey1\',\'trackKey2\')'
+    'body': 'PutBetWeen(\'${1:trackKey1}\',\'${2:trackKey2}\');${3:}'
+    'description': 'ストラクチャを現在の距離程の2つの軌道の間に設置します。ストラクチャは軌道間の距離に応じて変形します。'
+    'leftLabelHTML': 'Structure.'
+    'rightLabelHTML': 'ストラクチャ'
+
+  #連続ストラクチャ
+  'repeater':
+    'prefix': 'Repeater[\'repeaterKey\']'
+    'body': 'Repeater[\'${1:repeaterKey}\']${2:}'
+    'description': '連続ストラクチャを表すマップ要素です。'
+    'rightLabelHTML': '連続ストラクチャ'
+  'repeater.begin':
+    'prefix': 'Begin(\'trackKey\',x,y,z,rx,ry,rz,tilt,span,interval)'
+    'body': 'Begin(\'${1:trackKey}\',${2:x},${3:y},${4:z},${5:rx},${6:ry},${7:rz},${8:tilt},${9:span},${10:interval},\'${11:structureKey}\');${12:}'
+    'description': 'ストラクチャの連続配置を現在の距離程から開始します。'
+    'leftLabelHTML': 'Repeater.'
+    'rightLabelHTML': '連続ストラクチャ'
+  'repeater.begin0':
+    'prefix': 'Begin0(\'trackKey\',tilt,span,interval)'
+    'body': 'Begin0(\'${1:trackKey}\',${2:tilt},${3:span},${4:interval},\'${5:structureKey}\');${6:}'
+    'description': 'ストラクチャの連続配置を現在の距離程から開始します。'
+    'leftLabelHTML': 'Repeater.'
+    'rightLabelHTML': '連続ストラクチャ'
+  'background.change':
+    'prefix': 'Background.Change(structureKey)'
+    'body': 'Background.Change(\'${1:structureKey}\');${2:}'
+    'description': '背景を変更します。'
+    'rightLabelHTML': '連続ストラクチャ'
+
+  #停車場
+  'station.load':
+    'prefix': 'Station.Load(\'filePath\')'
+    'body': 'Station.Load(\'${1:filePath}\');${2:}'
+    'description': '停車場リストファイルに基づいて停車場を定義します。'
+    'rightLabelHTML': '停車場'
+  'station.put':
+    'prefix': 'Station[\'stationKey\'].Put(door,margin1,margin2)'
+    'body': 'Station[\'${1:stationKey}\'].Put(${2:door},${3:margin1},${4:margin2});${5:}'
+    'description': 'この列車の停止位置を現在の距離程に設定します。'
+    'rightLabelHTML': '停車場'
+
+  #閉塞
+  'section':
+    'prefix': 'Section'
+    'body': 'Section'
+    'description': '閉塞を表すマップ要素です。'
+    'rightLabelHTML': '閉塞'
+  'section.begin':
+    'prefix': 'Begin(\'singal0\',\'signal1\',...,\'signalN\')'
+    'body': 'Begin(\'${1:signal0}\',\'${2:signal1}\',\'${3:signal2}\');${4:}'
+    'description': '新しい閉塞を現在の距離程から開始します。'
+    'leftLabelHTML': 'Section.'
+    'rightLabelHTML': '閉塞'
+  'section.setspeedlimit':
+    'prefix': 'SetSpeedLimit(v0,v1,...,vN)'
+    'body': 'SetSpeedLimit(${1:v0},${2:v1},${3:v2},${4:v3},${5:v4});${6:}'
+    'description': '信号現示の許容速度を設定します。'
+    'leftLabelHTML': 'Section.'
+    'rightLabelHTML': '閉塞'
+
+  #地上信号機
+  'signal':
+    'prefix': 'Signal[\'signalAspectKey\']'
+    'body': 'Signal[\'${1:signalAspectKey}\']${2:}'
+    'description': '地上信号機を表すマップ要素です。'
+    'rightLabelHTML': '地上信号機'
+  'signal.load':
+    'prefix': 'Load(\'filePath\')'
+    'body': 'Load(\'${1:filePath}\');${2:}'
+    'description': '信号現示リストファイルに基づいて信号現示を定義します。'
+    'leftLabelHTML': 'Signal.'
+    'rightLabelHTML': '地上信号機'
+  'signal.put1':
+    'prefix': 'Put(section,\'trackKey\',x,y)'
+    'body': 'Put(${1:section},\'${2:trackKey}\',${3:x},${4:y});${5:}'
+    'description': '地上信号機を現在の距離程に設置します。'
+    'leftLabelHTML': 'Signal.'
+    'rightLabelHTML': '地上信号機'
+  'signal.put2':
+    'prefix': 'Put(section,\'trackKey\',x,y,z,rx,ry,rz,tilt,span)'
+    'body': 'Put(${1:section},\'${2:trackKey}\',${3:x},${4:y},${5:z},${6:rx},${7:ry},${8:rz},${9:tilt},${10:span});${11:}'
+    'description': '地上信号機を現在の距離程に設置します。'
+    'leftLabelHTML': 'Signal.'
+    'rightLabelHTML': '地上信号機'
+
+  #地上子
+  'beacon.put':
+    'prefix': 'Beacon.Put(type,section,sendData)'
+    'body': 'Beacon.Put(${1:type},${2:section},${3:sendData});${4:}'
+    'description': '地上子の送信イベントを現在の距離程に定義します。'
+    'rightLabelHTML': '地上子'
+
+  #速度制限
+  'speedlimit':
+    'prefix': 'SpeedLimit'
+    'body': 'SpeedLimit'
+    'description': '速度制限を表すマップ要素です。'
+    'rightLabelHTML': '速度制限'
+  'speedlimit.begin':
+    'prefix': 'Begin(v)'
+    'body': 'Begin(${1:v});${2:}'
+    'description': '速度制限を現在の距離程から開始します。'
+    'leftLabelHTML': 'SpeedLimit.'
+    'rightLabelHTML': '速度制限'
+
+  #先行列車
+  'pretrain':
+    'prefix': 'PreTrain'
+    'body': 'PreTrain'
+    'description': '先行列車を表すマップ要素です。'
+    'rightLabelHTML': '先行列車'
+  'pretrain.pass1':
+    'prefix': 'Pass(\'hh:mm:ss\')'
+    'body': 'Pass(\'${1:hh}:${2:mm}:${3:ss}\');${4:}'
+    'description': '先行列車が現在の距離程を通過する時刻を設定します。'
+    'leftLabelHTML': 'PreTrain.'
+    'rightLabelHTML': '先行列車'
+  'pretrain.pass2':
+    'prefix': 'Pass(second)'
+    'body': 'Pass(${1:second});${2:}'
+    'description': '先行列車が現在の距離程を通過する時刻を設定します。'
+    'leftLabelHTML': 'PreTrain.'
+    'rightLabelHTML': '先行列車'
+
+  #光源
+  'light':
+    'prefix': 'Light'
+    'body': 'Light'
+    'description': '光源を表すマップ要素です。'
+    'rightLabelHTML': '光源'
+  'light.ambient':
+    'prefix': 'Ambient(red,green,blue)'
+    'body': 'Ambient(${1:red},${2:green},${3:blue});${4:}'
+    'description': '環境光の色(アンビエント色)を設定します。この構文はマップファイルに1回のみ記述可能です。'
+    'leftLabelHTML': 'Light.'
+    'rightLabelHTML': '光源'
+  'light.diffuse':
+    'prefix': 'Diffuse(red,green,blue)'
+    'body': 'Diffuse(${1:red},${2:green},${3:blue});${4:}'
+    'description': '平行光の色(デフューズ色)を設定します。この構文はマップファイルに1回のみ記述可能です。'
+    'leftLabelHTML': 'Light.'
+    'rightLabelHTML': '光源'
+  'light.direction':
+    'prefix': 'Direction(pitch,yaw)'
+    'body': 'Direction(${1:pitch},${2:yaw});${3:}'
+    'description': '距離程0において、平行光がさす方向を設定します。この構文はマップファイルに1回のみ記述可能です。'
+    'leftLabelHTML': 'Light.'
+    'rightLabelHTML': '光源'
+
+  #霧効果
+  'fog':
+    'prefix': 'Fog'
+    'body': 'Fog'
+    'description': '霧効果を表すマップ要素です。'
+    'rightLabelHTML': '霧効果'
+  'fog.interpolate1':
+    'prefix': 'Interpolate(density,red,green,blue)'
+    'body': 'Interpolate(${1:density},${2:red},${3:green},${4:blue});${5:}'
+    'description': '現在の距離程における霧効果を設定します。2つのFog.Interpolate間は線形補間されます。'
+    'leftLabelHTML': 'Fog.'
+    'rightLabelHTML': '霧効果'
+  'fog.interpolate2':
+    'prefix': 'Interpolate(density)'
+    'body': 'Interpolate(${1:density});${2:}'
+    'description': '現在の距離程における霧効果を設定します。2つのFog.Interpolate間は線形補間されます。'
+    'leftLabelHTML': 'Fog.'
+    'rightLabelHTML': '霧効果'
+  'fog.interpolate3':
+    'prefix': 'Interpolate()'
+    'body': 'Interpolate();${1:}'
+    'description': '現在の距離程における霧効果を設定します。2つのFog.Interpolate間は線形補間されます。'
+    'leftLabelHTML': 'Fog.'
+    'rightLabelHTML': '霧効果'
+
+  #風景描画距離
+  'drawdistance.change':
+    'prefix': 'DrawDistance.Change(value)'
+    'body': 'DrawDistance.Change(${1:value});${2:}'
+    'description': '現在の距離程以降の風景の描画距離を設定します。'
+    'rightLabelHTML': '風景描画距離'
+
+  #運転台の明るさ
+  'cabilluminance':
+    'prefix': 'cabIlluminance'
+    'body': 'CabIlluminance'
+    'description': '運転台の明るさを表すマップ要素です。'
+    'rightLabelHTML': '運転台の明るさ'
+  'cabilluminance.interpolate1':
+    'prefix': 'Interpolate(value)'
+    'body': 'Interpolate(${1:value});${2:}'
+    'description': '現在の距離程における運転台の明るさを設定します。2つのCabIlluminance.Interpolate間は線形補間されます。'
+    'leftLabelHTML': 'CabIlluminance.'
+    'rightLabelHTML': '運転台の明るさ'
+  'cabilluminance.interpolate2':
+    'prefix': 'Interpolate()'
+    'body': 'Interpolate();${1:}'
+    'description': '現在の距離程における運転台の明るさを設定します。2つのCabIlluminance.Interpolate間は線形補間されます。'
+    'leftLabelHTML': 'CabIlluminance.'
+    'rightLabelHTML': '運転台の明るさ'
+
+  #軌道変位
+  'irregularity.change':
+    'prefix': 'Irregularity.Change(x,y,r,lx,ly,lr)'
+    'body': 'Irregularity.Change(${1:x},${2:y},${3:r},${4:lx},${5:ly},${6:lr});${7:}'
+    'description': '現在の距離程以降の軌道変位を設定します。'
+    'rightLabelHTML': '軌道変位'
+
+  #粘着特性
+  'adhesion':
+    'prefix': 'Adhesion'
+    'body': 'Adhesion'
+    'description': '粘着特性を表すマップ要素です。'
+    'rightLabelHTML': '粘着特性'
+  'adhesion.change1':
+    'prefix': 'Change(a)'
+    'body': 'Change(${1:a});${2:}'
+    'description': '現在の距離程以降の車輪とレール間の粘着特性を設定します。'
+    'leftLabelHTML': 'Adhesion.'
+    'rightLabelHTML': '粘着特性'
+  'adhesion.change2':
+    'prefix': 'Change(a,b,c)'
+    'body': 'Change(${1:a},${2:b},${3:c});${4:}'
+    'description': '現在の距離程以降の車輪とレール間の粘着特性を設定します。'
+    'leftLabelHTML': 'Adhesion.'
+    'rightLabelHTML': '粘着特性'
+
+  #音
+  'sound.load':
+    'prefix': 'Sound.Load(\'filePath\')'
+    'body': 'Sound.Load(\'${1:filePath}\');${2:}'
+    'description': 'サウンドリストファイルに基づいてサウンドを読み込みます。'
+    'rightLabelHTML': '音'
+  'sound.play':
+    'prefix': 'Sound[\'soundKey\'].Play()'
+    'body': 'Sound[\'${1:soundKey}\'].Play();${2:}'
+    'description': '現在の距離程を通過するときにサウンドを1回再生します。'
+    'rightLabelHTML': '音'
+
+  #固定音源
+  'sound3d.load':
+    'prefix': 'Sound3D.Load(\'filePath\')'
+    'body': 'Sound.Load(\'${1:filePath}\');${2:}'
+    'description': 'サウンドリストファイルに基づいてサウンドを読み込みます。'
+    'rightLabelHTML': '固定音源'
+  'sound3d.put':
+    'prefix': 'Sound3D[\'soundKey\'].Put(x,y)'
+    'body': 'Sound3D[\'${1:soundKey}\'].Put(${3:x},${4:y});${5:}'
+    'description': '地上に固定された音源を現在の距離程に設置します。サウンドは連続再生されます。'
+    'rightLabelHTML': '固定音源'
+
+  #走行音
+  'rollingnoise.change':
+    'prefix': 'RollingNoise.Change(index)'
+    'body': 'RollingNoise.Change(${1:index});${2:}'
+    'description': '現在の距離程以降の車輪転動音を設定します。'
+    'rightLabelHTML': '走行音'
+
+  #フランジきしり音
+  'flangenoise.change':
+    'prefix': 'FlangeNoise.Change(index)'
+    'body': 'FlangeNoise.Change(${1:index});${2:}'
+    'description': '現在の距離程以降のフランジきしり音を設定します。'
+    'rightLabelHTML': 'フランジきしり音'
+
+  #分岐器通過音
+  'jointnoise.play':
+    'prefix': 'JointNoise.Play(index)'
+    'body': 'JointNoise.Play(${1:index});${2:}'
+    'description': '現在の距離程を通過するときに分岐器通過音を走行速度に応じて再生します。'
+    'rightLabelHTML': '分岐器通過音'
+
+  #他列車
+  'train':
+    'prefix': 'Train[\'trainKey\']'
+    'body': 'Train[\'trainKey\']'
+    'description': '他列車を表すマップ要素です。'
+    'rightLabelHTML': '他列車'
+  'train.add':
+    'prefix': 'Train.Add(\'trainKey\',filePath,\'trackKey\',direction)'
+    'body': 'Train.Add(\'${1:trainKey}\',${2:filePath},\'${3:trackKey}\',${4:direction});${5:}'
+    'description': '他列車を定義します。'
+    'rightLabelHTML': '他列車'
+  'train.load':
+    'prefix': 'Load(\'filePath\',\'trackKey\',direction)'
+    'body': 'Load(\'${1:filePath}\',\'${2:trackKey}\',${3:direction});${4:}'
+    'description': '他列車を定義します。'
+    'rightLabelHTML': '他列車'
+    'leftLabelHTML': 'Train.'
+  'train.enable1':
+    'prefix': 'Enable(\'time\')'
+    'body': 'Enable(\'${1:hh}:${2:mm}:${3:ss}\');${4:}'
+    'description': '他列車が現在の距離程を通過し、かつ設定された時刻になったとき、他列車の動作を有効にします。'
+    'rightLabelHTML': '他列車'
+    'leftLabelHTML': 'Train.'
+  'train.enable2':
+    'prefix': 'Enable(second)'
+    'body': 'Enable(${1:second});${2:}'
+    'description': '他列車が現在の距離程を通過し、かつ設定された時刻になったとき、他列車の動作を有効にします。'
+    'rightLabelHTML': '他列車'
+    'leftLabelHTML': 'Train.'
+  'train.stop':
+    'prefix': 'Stop(decelerate,stopTime,accelerate,speed)'
+    'body': 'Stop(${1:decelerate},${2:stopTime},${3:accelerate},${4:speed});${5:}'
+    'description': '他列車を現在の距離程に一旦停車させます。'
+    'rightLabelHTML': '他列車'
+    'leftLabelHTML': 'Train.'
+
+  #他マップの挿入
+  'include':
+    'prefix': 'include \'submap.txt\''
+    'body': 'include \'${1:submap}.txt\';${2:}'
+    'description': '他マップファイルの内容をその位置に挿入します。'
+
+  #その他
+  'end':
+    'prefix': 'End'
+    'body': 'End();${1:}'
+    'description': '平面曲線,縦曲線,ストラクチャの連続配置,速度制限を現在の距離程から開始します。'
+  'begintransition':
+    'prefix': 'BeginTransition'
+    'body': 'BeginTransition();'
+    'description': '緩和曲線,縦曲線の遷移を現在の距離程から開始します。'


Update filter icons to match filterset

Update filter icons to match filterset

--- app/lib/characteristics.coffee
+++ app/lib/characteristics.coffee
@@ -8,8 +8,11 @@
     label: translate 'span', 'characteristics.like'
     values: [
       new Value id: 'likeCatDog', label: translate 'span', 'characteristicValues.likeCatDog'
+      new Value id: 'likeAntelopeDeer', label: translate 'span', 'characteristicValues.likeAntelopeDeer'
+      new Value id: 'likeRabbit', label: translate 'span', 'characteristicValues.likeRabbit'
+      new Value id: 'likeBird', label: translate 'span', 'characteristicValues.likeBird'
+      new Value id: 'likeWeasel', label: translate 'span', 'characteristicValues.likeWeasel'
       new Value id: 'likeRodent', label: translate 'span', 'characteristicValues.likeRodent'
-      new Value id: 'likeManMade', label: translate 'span', 'characteristicValues.likeManMade'
       new Value id: 'likeOther', label: translate 'span', 'characteristicValues.likeOther'
     ]

@@ -17,13 +20,13 @@
     id: 'coat'
     label: translate 'span', 'characteristics.coat'
     values: [
-      new Value id: 'coatTanYellow', label: translate 'span', 'characteristicValues.coatTanYellow'
-      new Value id: 'coatRedBrown', label: translate 'span', 'characteristicValues.coatRedBrown'
-      new Value id: 'coatBrownBlack', label: translate 'span', 'characteristicValues.coatBrownBlack'
+      new Value id: 'coatTanBrown', label: translate 'span', 'characteristicValues.coatTanBrown'
+      new Value id: 'coatRed', label: translate 'span', 'characteristicValues.coatRed'
+      new Value id: 'coatWhite', label: translate 'span', 'characteristicValues.coatWhite'
       new Value id: 'coatGrayBlack', label: translate 'span', 'characteristicValues.coatGrayBlack'
-      new Value id: 'coatMottled', label: translate 'span', 'characteristicValues.coatMottled'
       new Value id: 'coatSolid', label: translate 'span', 'characteristicValues.coatSolid'
-      new Value id: 'coatOrTailStriped', label: translate 'span', 'characteristicValues.coatOrTailStriped'
+      new Value id: 'coatBandsOrStripes', label: translate 'span', 'characteristicValues.coatBandsOrStripes'
+      new Value id: 'coatSpots', label: translate 'span', 'characteristicValues.coatSpots'
     ]

   new Characteristic
@@ -33,14 +36,15 @@
       new Value id: 'tailBushy', label: translate 'span', 'characteristicValues.tailBushy'
       new Value id: 'tailSmooth', label: translate 'span', 'characteristicValues.tailSmooth'
       new Value id: 'tailLong', label: translate 'span', 'characteristicValues.tailLong'
+      new Value id: 'tailShort', label: translate 'span', 'characteristicValues.tailShort'
     ]

-  #TODO was tall build omitted by LPZ on purpose?
   new Characteristic
     id: 'build'
     label: translate 'span', 'characteristics.build'
     values: [
       new Value id: 'buildStocky', label: translate 'span', 'characteristicValues.buildStocky'
+      new Value id: 'buildTall', label: translate 'span', 'characteristicValues.buildTall'
       new Value id: 'buildLanky', label: translate 'span', 'characteristicValues.buildLanky'
       new Value id: 'buildSmall', label: translate 'span', 'characteristicValues.buildSmall'
       new Value id: 'buildLowSlung', label: translate 'span', 'characteristicValues.buildLowSlung'


Fix "check" button. Overlooked one variable when renaming.

--- resources/static/brunch/src/app/views/home_view.coffee
+++ resources/static/brunch/src/app/views/home_view.coffee
@@ -58,7 +58,7 @@
         )

     invalids = app.collections.rulesTree.any(
-      (rule) -> !rule? || !x.validate
+      (rule) -> !rule? || !rule.validate
     )

     if invalids


Activity Ticker: Decorate relationships for ticker

--- workers/social/lib/social/models/activityticker.coffee
+++ workers/social/lib/social/models/activityticker.coffee
@@ -11,19 +11,47 @@
       static      : ["fetch"]

   relationshipNames = ["follower", "like", "member", "user"]
-  constructorNames  = ["JAccount", "JApp", "JGroup", "JTag"]
+  constructorNames  = ["JAccount", "JApp", "JGroup", "JTag", "JStatusUpdate"]
+
+  JAccount = require './account'
+
+  decorateEvents = (relationship, callback) ->
+    {source, target, as, timestamp} = relationship
+
+    if as is "like"
+      # there is a flipped relationship between JAccount and JStatusUpdate
+      # source is status update
+      # target is account, we should correct it here
+      # and also we should add the origin account here
+      JAccount.one {"_id": source.originId}, (err, targetAccount)->
+        return callback err if err
+
+        modifiedEvent =
+          source    : target
+          target    : targetAccount
+          subject   : source
+          as        : as
+          timestamp : timestamp
+
+        callback null, modifiedEvent
+    else
+      callback null, {source, target, as, timestamp}
+
+

   @fetch = secure (client, options = {}, callback) ->
     {connection: {delegate}} = client

+    from = options.from or +(new Date())
     selector     =
       sourceName : "$in": constructorNames
       as         : "$in": relationshipNames
       targetName : "$in": constructorNames
+      timestamp : {"$lt" : new Date(from)}

     options      =
-      limit      : options.limit or 20
-      skip       : options.skip  or 0
+      # do not fetch more than 15 at once
+      limit      : Math.min options.limit ? 15, 15
       sort       : timestamp  : -1

     Relationship.some selector, options, (err, relationships) ->
@@ -32,9 +60,9 @@
       daisy queue = relationships.map (relationship) ->
         ->
           relationship.fetchTeaser ->
-            {source, target, as} = relationship
-            buckets.push {source, target, as}
-            queue.next()
+            decorateEvents relationship, (err, decoratedEvent)=>
+              buckets.push decoratedEvent
+              queue.next()

       queue.push ->
         callback null, buckets


Fix hipchat exception trigger

Fix hipchat exception trigger

--- plugins/hipchat/index.coffee
+++ plugins/hipchat/index.coffee
@@ -19,7 +19,7 @@
         comment: event.comment
         user: event.user

-      if details.comment.message
+      if details.comment?.message
         details.comment.message = details.comment.message.truncate(80)

     else


Pass the facility code to the Form service

--- app/scripts/controllers.coffee
+++ app/scripts/controllers.coffee
@@ -33,7 +33,7 @@
         status: 1
     , addMarkers
   .controller 'WaterpointCreateCtrl', ($scope, Waterpoint, Form) ->
-    $scope.formTemplate = Form
+    $scope.formTemplate = Form 'wpf001'
     # FIXME: Should not hardcode the facility code here
     $scope.waterpoint =
       facility_code: "wpf001"
@@ -43,7 +43,7 @@
   .controller 'WaterpointEditCtrl', ($scope, $http, $routeParams, Waterpoint, Form) ->
     Waterpoint.get id: $routeParams.id, (waterpoint) ->
       $scope.waterpoint = waterpoint
-    $scope.formTemplate = Form
+    $scope.formTemplate = Form 'wpf001'
     $scope.save = () ->
       etag = $scope.waterpoint._etag
       # We need to remove these special attributes since they are not defined


Guard against non-match of remotes pattern

--- lib/github-file.coffee
+++ lib/github-file.coffee
@@ -88,7 +88,7 @@

   # Internal
   gitUrl: ->
-    remoteOrBestGuess = @remoteName() || 'origin'
+    remoteOrBestGuess = @remoteName() or 'origin'
     @repo.getConfigValue("remote.#{remoteOrBestGuess}.url")

   # Internal
@@ -107,9 +107,7 @@
   # Internal
   remoteName: ->
     refName = @repo.getUpstreamBranch() # e.g., "refs/remotes/origin/master"
-    return null unless refName?
-
-    refName.match(/^refs\/remotes\/(.*)\/.*$/)[1]
+    refName?.match(/^refs\/remotes\/(.*)\/.*$/)?[1]

   # Internal
   branch: ->


use ajax global instead

use ajax global instead

--- lib/assets/javascripts/transponder/response.coffee
+++ lib/assets/javascripts/transponder/response.coffee
@@ -2,7 +2,7 @@
   payload: {}

   constructor: ->
-    $(document).on 'ajax:complete', (event, xhr, status) =>
+    $(document).ajaxComplete (event, xhr, status) =>
       if xhr.getResponseHeader('Content-Type') is 'application/transmission'
         @payload.raw = JSON.parse(@cleanContent(xhr.responseText))
         element    = @payload.raw[0]


hdp: select latest version unless already set

--- lib/hdp_service.coffee
+++ lib/hdp_service.coffee
@@ -36,6 +36,14 @@
           cmd: """
           code=3
           version=`hdp-select status #{options.version_name} | sed 's/.* \\(\\d*\\)/\\1/'`
+          if [ ! -d "/usr/hdp/$version" ]; then
+            version=`yum repolist | egrep HDP-[0-9] | sed 's/^HDP-\\([0-9\\.]*\\).*$/\\1/'`
+            version=`ls --format=single-column /usr/hdp | grep ${version} | tail -1`
+            if [ ! -d "/usr/hdp/$version" ]; then
+              echo 'Failed to detect the latest HDP version'
+              exit 1
+            fi
+          fi
           echo $version
           source="/etc/init.d/#{options.name}"
           target="/usr/hdp/$version/etc/rc.d/init.d/#{options.name}"


修正分页查询的bug

修正分页查询的bug

--- lib/helper/rest.coffee
+++ lib/helper/rest.coffee
@@ -36,9 +36,12 @@
   list: (Model, opt = null, allowAttrs, hook = null) ->
     (req, res, next) ->
       options = opt and req.hooks[opt] or Model.findAllOpts(req.params)
+      offset = options.offset
+      options.offset = 0
       Model.count(options).done((error, count) ->
         return next(error) if error
         if count
+          options.offset = offset
           Model.findAll(options).done((error, result) ->
             return next(error) if error
             res.header("X-Content-Record-Total", count)


servers/handler: check bongo connectivity before starting tests

--- servers/lib/server/handlers/getteammembers.test.coffee
+++ servers/lib/server/handlers/getteammembers.test.coffee
@@ -5,6 +5,7 @@
   querystring
   generateUrl
   generateRandomEmail
+  checkBongoConnectivity
   generateRandomString }                = require '../../../testhelper'
 { generateRegisterRequestParams }       = require '../../../testhelper/handler/registerhelper'
 { generateCreateTeamRequestParams
@@ -13,6 +14,9 @@
 JGroup      = require '../../../models/group'
 JInvitation = require '../../../models/invitation'

+beforeTests = -> before (done) ->
+
+  checkBongoConnectivity done

 # here we have actual tests
 runTests = -> describe 'server.handlers.getteammembers', ->


fix failing tests in getteammembers.test.coffee

--- servers/lib/server/handlers/getteammembers.test.coffee
+++ servers/lib/server/handlers/getteammembers.test.coffee
@@ -51,14 +51,14 @@
     queue = [

       ->
-        createTeamRequestParams = generateCreateTeamRequestParams
-          body    :
-            slug  : groupSlug
-
-        request.post createTeamRequestParams, (err, res, body) ->
-          expect(err)             .to.not.exist
-          expect(res.statusCode)  .to.be.equal 200
-          queue.next()
+        generateCreateTeamRequestParams {
+          body : { slug : groupSlug }
+        }, (createTeamRequestParams) ->
+
+          request.post createTeamRequestParams, (err, res, body) ->
+            expect(err)             .to.not.exist
+            expect(res.statusCode)  .to.be.equal 200
+            queue.next()

       ->
         getTeamMembersRequestParams = generateGetTeamMembersRequestParams
@@ -86,14 +86,14 @@
     queue = [

       ->
-        createTeamRequestParams = generateCreateTeamRequestParams
-          body    :
-            slug  : groupSlug
-
-        request.post createTeamRequestParams, (err, res, body) ->
-          expect(err)             .to.not.exist
-          expect(res.statusCode)  .to.be.equal 200
-          queue.next()
+        generateCreateTeamRequestParams {
+          body : { slug : groupSlug }
+        }, (createTeamRequestParams) ->
+
+          request.post createTeamRequestParams, (err, res, body) ->
+            expect(err)             .to.not.exist
+            expect(res.statusCode)  .to.be.equal 200
+            queue.next()

       ->
         getTeamMembersRequestParams = generateGetTeamMembersRequestParams
@@ -126,18 +126,20 @@

       ->
         # expecting team to be created
-        createTeamRequestParams = generateCreateTeamRequestParams
-          body              :
+        generateCreateTeamRequestParams {
+          body : {
             slug            : groupSlug
             invitees        : inviteeEmail
             username        : groupOwnerUsername
             password        : groupOwnerPassword
             passwordConfirm : groupOwnerPassword
-
-        request.post createTeamRequestParams, (err, res, body) ->
-          expect(err)             .to.not.exist
-          expect(res.statusCode)  .to.be.equal 200
-          queue.next()
+          }
+        }, (createTeamRequestParams) ->
+
+          request.post createTeamRequestParams, (err, res, body) ->
+            expect(err)             .to.not.exist
+            expect(res.statusCode)  .to.be.equal 200
+            queue.next()

       ->
         # expecting group to be crated
@@ -229,8 +231,8 @@

       ->
         # expecting team to be created
-        createTeamRequestParams = generateCreateTeamRequestParams
-          body              :
+        generateCreateTeamRequestParams {
+          body : {
             slug            : groupSlug
             email           : groupOwnerEmail
             invitees        : inviteeEmail
@@ -239,11 +241,13 @@
             alreadyMember   : 'true'
             passwordConfirm : groupOwnerPassword

-
-        request.post createTeamRequestParams, (err, res, body) ->
-          expect(err)             .to.not.exist
-          expect(res.statusCode)  .to.be.equal 200
-          queue.next()
+          }
+        }, (createTeamRequestParams) ->
+
+          request.post createTeamRequestParams, (err, res, body) ->
+            expect(err)             .to.not.exist
+            expect(res.statusCode)  .to.be.equal 200
+            queue.next()

       ->
         # expecting group to be crated


Added a comment that explains Esc suppressing logic

--- extension/packages/vim.coffee
+++ extension/packages/vim.coffee
@@ -30,6 +30,9 @@

     suppress = modes[@mode]?.onInput(@, @storage[@mode], keyStr, event)

+    # Esc key is not suppressed, and passed to the browser in `normal` mode.
+    # Here we compare against the mode that was active before the key was processed
+    # because processing the command may change the mode.
     if oldMode == 'normal' and keyStr == 'Esc'
       return false
     else


Add Firefox compatibility.

Add Firefox compatibility.

--- lib/util.coffee
+++ lib/util.coffee
@@ -10,8 +10,21 @@
       enumerable: false
       configurable: true

-if Map? # polyfill
+# polyfill
+if Map?
+
+  if not Map.prototype.items
+    Map.prototype.items = () ->
+      results = []
+      i = this.iterator();
+      size = this.size()
+      if size
+        for num in [1..size]
+          results.push(i.next())
+      results
+
   exports.Map = Map
+
 else
   class exports.Map
     constructor: ->


Make highlight pointer disappear immediately and move off screen when hidden

It causes problems in IE10 and lower, because the css property pointer-events
does not work in those browsers. So fixed that by moving the arrow out of the way.

--- app/views/core/CocoView.coffee
+++ app/views/core/CocoView.coffee
@@ -383,7 +383,7 @@
     setTimeout (=> $pointer.css transition: 'all 0.4s ease-in', transform: "rotate(#{@pointerRotation}rad) translate(-3px, #{@pointerRadialDistance}px)"), 800

   endHighlight: ->
-    @getPointer(false).css('opacity', 0.0)
+    @getPointer(false).css({'opacity': 0.0, 'transition': 'none', top: '-50px', right: '-50px'})
     clearInterval @pointerInterval
     clearTimeout @pointerDelayTimeout
     clearTimeout @pointerDurationTimeout


fix getEmptyMessage

fix getEmptyMessage

--- lib/view.coffee
+++ lib/view.coffee
@@ -4,6 +4,9 @@

 module.exports =
 class View extends FuzzyFinderView
+  getEmptyMessage: ->
+    'No files here'
+
   toggle: (items) ->
     if @panel?.isVisible()
       @cancel()


Working on getting my base repo set up.

Working on getting my base repo set up.

--- lib/linter-reek.coffee
+++ lib/linter-reek.coffee
@@ -9,7 +9,7 @@

   # A string, list, tuple or callable that returns a string, list or tuple,
   # containing the command line (with arguments) used to lint.
-  cmd: 'rubocop --format emacs'
+  cmd: 'reek -y'

   linterName: 'reek'

@@ -22,17 +22,14 @@
   constructor: (editor)->
     super(editor)

-    if editor.getGrammar().scopeName == 'source.ruby.rails'
-      @cmd += " -R"
+    config = findFile(@cwd, 'config.reek')
+    if config
+      @cmd += " -c #{config}"

-    config = findFile(@cwd, '.rubocop.yml')
-    if config
-      @cmd += " --config #{config}"
-
-    atom.config.observe 'linter-rubocop.rubocopExecutablePath', =>
-      @executablePath = atom.config.get 'linter-rubocop.rubocopExecutablePath'
+    atom.config.observe 'linter-reek.reekExecutablePath', =>
+      @executablePath = atom.config.get 'linter-reek.reekExecutablePath'

   destroy: ->
-    atom.config.unobserve 'linter-rubocop.rubocopExecutablePath'
+    atom.config.unobserve 'linter-reek.reekExecutablePath'

-module.exports = LinterRubocop
+module.exports = LinterReek


hub/test: fixing one postgres test

hub/test: fixing one postgres test

--- src/smc-hub/test/postgres/postgres-test.coffee
+++ src/smc-hub/test/postgres/postgres-test.coffee
@@ -403,7 +403,16 @@
             cb    : (err, users) ->
                 expect(users.length).toBe(1)
                 n = 0
-                expect(users[0]).toEqual("email_address": "sage0@sagemath.com", account_id:users[n].account_id, first_name: "Sage#{n}", last_name: "Math#{n}")
+                data = users[0]
+                delete data.created
+                expect(data).toEqual(
+                    email_address: "sage0@sagemath.com",
+                    account_id:users[n].account_id,
+                    first_name: "Sage#{n}",
+                    last_name: "Math#{n}",
+                    email_address_verified: null,
+                    last_active: null
+                )
                 done(err)
     it "searches for the non-existent user with email sageBLAH@sagemath.com", (done) ->
         db.user_search


Change to constant messages.

Change to constant messages.

--- app/assets/volume/slot.coffee
+++ app/assets/volume/slot.coffee
@@ -716,7 +716,7 @@
           return
         messages.clear(this)
         if !@asset.classification && value > (slot.release || 0)
-          confirmation = confirm("The highlight level you have chosen is more open then the volume.  Are you sure you want to proceed?")
+          confirmation = confirm(constants.message('classification.excerpt.warning'))
         if confirmation
           @excerpt.target.setExcerpt(value)
             .then (excerpt) =>


Change isHost to isLeader

Change isHost to isLeader

--- src/packages/collaboration/lib/collaboration.coffee
+++ src/packages/collaboration/lib/collaboration.coffee
@@ -27,7 +27,7 @@

     rootView.eachPane (pane) ->
       setTimeout ->
-        buttons = if session.isHost() then new HostStatusBar(session) else new GuestStatusBar(session)
+        buttons = if session.isLeader() then new HostStatusBar(session) else new GuestStatusBar(session)
         buttons.insertAfter(pane.find('.git-branch'))
       , 0


Ignore children with no names

Ignore children with no names

This will be elements that aren't package views

--- src/packages/settings-view/lib/package-panel.coffee
+++ src/packages/settings-view/lib/package-panel.coffee
@@ -119,7 +119,9 @@
   filterPackages: (filterString) ->
     for children in [@installedPackages.children(), @availablePackages.children()]
       for packageView in children
-        if /^\s*$/.test(filterString) or stringScore(packageView.getAttribute('name'), filterString)
+        name = packageView.getAttribute('name')
+        continue unless name
+        if /^\s*$/.test(filterString) or stringScore(name, filterString)
           $(packageView).show()
         else
           $(packageView).hide()


checking open in app and clear priority

checking open in app and clear priority

--- lib/url-handler.coffee
+++ lib/url-handler.coffee
@@ -12,6 +12,7 @@
   ipcRenderer.send('command', 'application:new-window')

 openInExistingWindow = ->
+  console.log 'm at openInExistingWindow'
   bus.emit('learn:open', {timestamp: Date.now(), slug: getLabSlug()})

 windowOpen = ->


remove references to subToolIndex in pickMany

--- app/assets/javascripts/components/core-tools/pick-many.cjsx
+++ app/assets/javascripts/components/core-tools/pick-many.cjsx
@@ -91,22 +91,7 @@
       responses: []
     onChange: NOOP

-  componentDidMount: ->
-    # @setState subToolIndex: 0
-    # @handleChange 0
-    # @setSubToolIndex @props.annotation?.subToolIndex ? 0
-
-  componentWillReceiveProps: (new_props) ->
-    console.log 'componentWillReceiveProps(): new_props = ', new_props
-    if ! new_props.annotation?.subToolIndex
-      console.log ".. set subToolIndex to 0", @state.annotation
-      # @props.onChange? @state.annotation
-
-    # @state.annotation
-    # @handleChange 0
-
   getInitialState: ->
-    subToolIndex: @props.annotation?.subToolIndex ? 0
     annotation: { responses: [] }#@props.annotation ? {}

   render: ->
@@ -139,41 +124,18 @@

     <GenericTask question={@props.task.instruction} help={@props.task.help} answers={tools} />

-  # getSubToolIndex: ->
-  #   @props.annotation?.subToolIndex ? 0
+  handleChange: (index, e) ->
+    inp = @refs["inp-#{index}"]
+    annotation = @state.annotation
+    annotation.toolName = @props.task.tool_config.tools[index].type
+    isChecked = annotation.responses.indexOf(annotation.toolName) >= 0

-  setSubToolIndex: (index) ->
-    annotation = @state.annotation
-    console.log 'ANNOTATION : ', annotation
-
-    # annotation.subToolIndex = index
-    annotation.toolName = @props.task.tool_config.tools[index].type
-
-    isAlreadyChecked = annotation.responses.indexOf(annotation.toolName) >= 0
-    if isAlreadyChecked
-      annotation.responses.splice(annotation.responses.indexOf(annotation.toolName), 1)
+    # toggle checkmark
+    if isChecked
+      annotation.responses.splice(annotation.responses.indexOf(annotation.toolName), 1) # remove entry
     else
       annotation.responses.push annotation.toolName
-    console.log 'RESPONSES: ', annotation.responses
-
-    # annotation.subToolIndex = index

     @setState
       annotation: annotation, () =>
-        console.log 'ON CHANGE!!!!!!!!!!!!!!!'
         @props.onChange? @state.annotation
-
-  handleChange: (index, e) ->
-    console.log 'PICK-ONE-MARK-ONE::handleChange(), INDEX = ', index, @refs
-    inp = @refs["inp-#{index}"]
-    # if inp.getDOMNode().checked
-    @setSubToolIndex index
-
-      # if e.target.checked
-      # @props.onChange? {
-        # subToolIndex: index,
-        # toolName: @props.task.tool_config.tools[index].type
-        # generates_subject_type: @props.task.tool_config.tools[index].generates_subject_type
-      # }
-
-      # @forceUpdate()


let's back that out

let's back that out

--- app/assets/javascripts/tenon/features/record_list.js.coffee
+++ app/assets/javascripts/tenon/features/record_list.js.coffee
@@ -68,7 +68,7 @@

   _toggleInfiniteLoader: (pagination) =>
     $loader = $(".infinite-loader[data-record-list='##{@$list.attr('id')}']")
-    if parseInt(pagination.totalPages) > 0
+    if @_currentPage < parseInt(pagination.totalPages)
       $loader.show()
     else
       $loader.hide()


fix kaltura file size error message

fix kaltura file size error message

the max file size argument is in megabytes

test plan:
 - enable the kaltura/notorious plugin
 - in the rich text editor, click the "record / upload media" button (filmstrip),
   select the "Upload Media" tab, and press the button to select a video file.
 - choose a file that is not a video file and is smaller than 500MB.
   it should tell you the file isn't an acceptable video file.
 - choose a file that is greater than 500MB in size, and it should tell you
   the file is over the file size limit of 500MB.

fixes CNVS-28315

Change-Id: I96696b94ea0e9eb02851f5aeeaf5053d6c52b58e
Reviewed-on: https://gerrit.instructure.com/75652
Tested-by: Jenkins
Reviewed-by: Felix Milea-Ciobanu <9384aa226ac9d3237ed0bc52e18ffcb251ee0bf7@instructure.com>
Reviewed-by: Joel Hough <4816dabf8db1bc6cac35b3a24cab2ff844b5b0c7@instructure.com>
QA-Review: Heath Hales <8ca81b68c7e2592ac614bd07f22fcc735ca55f93@instructure.com>
Product-Review: Jeremy Stanley <b3f594e10a9edcf5413cf1190121d45078c62290@instructure.com>

--- app/coffeescripts/media_comments/upload_view_manager.coffee
+++ app/coffeescripts/media_comments/upload_view_manager.coffee
@@ -31,8 +31,8 @@
       @uploader.removeEventListener 'K5.progress', @updateProgBar

     onFileTypeError: (error) =>
-      if (error.file.size > error.maxFileSize)
-        message = I18n.t('file_size_error', 'Size of %{file} is greater than the maximum %{max} allowed file size.',{file: error.file.name, max: error.maxFileSize})
+      if (error.file.size > error.maxFileSize * 1024 * 1024) # consistent with UiConfig#acceptable_file_size in k5uploader
+        message = I18n.t('file_size_error', 'Size of %{file} is greater than the maximum %{max} MB allowed file size.',{file: error.file.name, max: error.maxFileSize})
       else
         message = I18n.t('file_type_error', '%{file} is not an acceptable %{type} file.', {file: error.file.name, type: error.allowedMediaTypes[0]})
       @resetFileDetails()


added a test for MomentUtil

added a test for MomentUtil

--- src/scripts/daterangepicker/util/moment-util.coffee
+++ src/scripts/daterangepicker/util/moment-util.coffee
@@ -3,6 +3,7 @@
     moment.locale(moment.locale(), obj)

   @setFirstDayOfTheWeek: (dow) ->
+    dow = (dow % 7 + 7) % 7
     if moment.localeData().firstDayOfWeek() != dow
       offset = dow - moment.localeData().firstDayOfWeek()
       @patchCurrentLocale({


fix for issue #330 - transactions and balances don't show up

--- app/js/services/wallet.coffee
+++ app/js/services/wallet.coffee
@@ -239,7 +239,7 @@
                             memo: entry.memo
                             running_balances: running_balances

-                    time = @utils.toDate(val.received_time)
+                    time = @utils.toDate(val.timestamp)
                     transaction =
                         is_virtual: val.is_virtual
                         is_confirmed: val.is_confirmed


Fix tutorial steps line breaks

Fix tutorial steps line breaks

--- app/lib/tutorial_steps.coffee
+++ app/lib/tutorial_steps.coffee
@@ -3,9 +3,9 @@
 {Step} = Tutorial

 inline = (string) ->
-  string = string.replace '\n\n', '_NEWLINE_'
-  string = string.replace '\n', ' '
-  string = string.replace '_NEWLINE_', '\n'
+  string = string.replace '\n\n', '_NEWLINE_', 'g'
+  string = string.replace '\n', ' ', 'g'
+  string = string.replace '_NEWLINE_', '\n', 'g'
   string

 Step::defaultButton = translate 'classify.tutorial.continueButton'


reference media service as var config.js

--- app/scripts/directives.coffee
+++ app/scripts/directives.coffee
@@ -20,9 +20,9 @@
       $scope.$watch("url", (value) ->
           if(value)
             if(value.indexOf('http') == -1)
-              $scope.url_image = "https://media.lefresnoy.net/?url=https://api.lefresnoy.net/"+value+"&w="+$scope.width+"h="+$scope.height+"&fmt=jpg"
+              $scope.url_image = config.media_service+"?url="+config.api_url+value+"&w="+$scope.width+"h="+$scope.height+"&fmt=jpg"
             else
-              $scope.url_image = "https://media.lefresnoy.net/?url="+value+"&w="+$scope.width+"h="+$scope.height+"&fmt=jpg"
+              $scope.url_image = config.media_service+"?url="+value+"&w="+$scope.width+"h="+$scope.height+"&fmt=jpg"

             if $scope.op
               $scope.url_image += "&op=#{ scope.op }"


Update network-config.cjsx

Update network-config.cjsx

--- views/components/settings/parts/network-config.cjsx
+++ views/components/settings/parts/network-config.cjsx
@@ -141,7 +141,7 @@
         </Col>
         <Col xs={12}>
           <Alert bsStyle='danger' style={marginTop: '10px'}>
-            任何防猫都不能保证绝对安全，斟酌使用。
+            任何本地防猫都不能保证绝对安全，斟酌使用。
           </Alert>
         </Col>
       </Grid>


Update classification count stat label

Update classification count stat label

--- app/translations/en_us.coffee
+++ app/translations/en_us.coffee
@@ -28,7 +28,7 @@
     stats:
       header: "CHICAGO WILDLIFE WATCH Statistics"
       activeUsers: "Active Users"
-      crittersIdentified: "Critters Identified"
+      crittersIdentified: "Classifications"
       totalImages: "Images Total"
       complete: "Complete"


removed console.logs

removed console.logs

--- app/coffee/view/form.coffee
+++ app/coffee/view/form.coffee
@@ -61,7 +61,6 @@
 			@bindFormToModel()
 			@listenTo @formModel, 'invalid', (model, messages) ->
 				for message in messages
-					console.log 'message field', message.field
 					field = @$el.find "label.#{message.field}"
 					errors = field.addClass("error").find "small.error"
 					if !errors.length
@@ -71,9 +70,7 @@
 					errors.text message.messages

 			@listenTo @formModel, 'change', (model) ->
-				console.log 'changing...', model
 				for field, __ of model.changed
-					console.log 'changed... ', field
 					@$el
 						.find "label.#{field}"
 						.removeClass "error"


fix case of states in fluview response

fix case of states in fluview response

--- site/app.coffee
+++ site/app.coffee
@@ -257,17 +257,21 @@
   'std': 0.5 + Math.random() * 1
   'wili': 1 + Math.random() * 3

+normalizeCase = (loc) ->
+  # states should be upper case, regions should be lower case
+  return if loc.length() == 2 then loc.toUpperCase() else loc.toLowerCase()
+
 getEpidataHander = (callback) ->
   return (result, message, epidata) ->
     if result == 1
       # normalize the case of locations
       for row in epidata
-        if row.location.length() == 2
-          # states should be upper case
-          row.location = row.location.toUpperCase()
-        else
-          # regions should be lower case
-          row.location = row.location.toLowerCase()
+        if row.location?
+          # the nowcast response
+          row.location = normalizeCase(row.location)
+        if row.region?
+          # the fluview response
+          row.region = normalizeCase(row.region)
       # invoke the supplied callback
       callback(epidata)
     else


removed commented out methods

removed commented out methods

--- workers/social/lib/social/models/group/index.coffee
+++ workers/social/lib/social/models/group/index.coffee
@@ -154,8 +154,6 @@
           (signature Function)
           (signature Object, Function)
         ]
-        createRole:
-          (signature Object, Function)
         updatePermissions:
           (signature Object, Function)
         fetchAdmins: [
@@ -207,44 +205,10 @@
           (signature String, Function)
         transferOwnership:
           (signature String, Function)
-        # fetchInvitationsFromGraph:
-        #   (signature String, Object, Function)
-        # countInvitationsFromGraph:
-        #   (signature String, Object, Function)
-        # fetchMembersFromGraph:
-        #   (signature Object, Function)
         remove:
           (signature Function)
-        # bulkApprove:
-        #   (signature Number, Object, Function)
-        # fetchNewestMembers: [
-        #   (signature Function)
-        #   (signature Object, Function)
-        #   (signature Object, Object, Function)
-        # ]
         makePayment:
           (signature Object, Function)
-        # # addProduct:
-        # (signature)
-        # # deleteProduct:
-        # (signature)
-        # fetchProducts: [
-        #   (signature Function)
-        #   (signature String, Function)
-        #   (signature String, Object, Function)
-        # ]
-        # saveInviteMessage: [
-        #   (signature String, String)
-        #   (signature String, String, Function)
-        # ]
-        # redeemInvitation:
-        #   (signature String, Function)
-        # fetchPaymentMethod:
-        #   (signature Function)
-        # linkPaymentMethod:
-        #   (signature String, Function)
-        # unlinkPaymentMethod:
-        #   (signature String, Function)
         addSubscription:
           (signature String, Function)
         fetchSubscription:
@@ -826,23 +790,6 @@
       kallback()

-  createRole: permit 'grant permissions',
-    success:(client, formData, callback)->
-      JGroupRole = require './role'
-      JGroupRole.create
-        title           : formData.title
-        isConfigureable : formData.isConfigureable or no
-      , callback
-
-  # addCustomRole: permit 'grant permissions',
-  #   success:(client,formData,callback)->
-  #     @createRole client,formData, (err,role)=>
-  #       console.log err,role
-  #       unless err
-  #         @addRole role, callback
-  #       else
-  #         callback err, null
-
   createMembershipPolicy:(requestType, queue, callback)->
     [callback, queue] = [queue, callback]  unless callback
     queue ?= []
@@ -935,16 +882,6 @@
         callback clientError, no

-  # saveInviteMessage: permit 'send invitations',
-  #   success: (client, messageType, message, callback=->)->
-  #     @fetchMembershipPolicy (err, policy)=>
-  #       return callback err  if err
-  #       return callback new KodingError "No policy found"  unless policy
-  #       set = {}
-  #       set["communications.#{messageType}"] = message
-  #       policy.update $set: set, callback
-
-
   isMember: (account, callback)->
     return callback new Error "No account found!"  unless account
     selector =
@@ -955,26 +892,6 @@
       if err then callback err
       else callback null, (if count is 0 then no else yes)

-
-  # bulkApprove: permit 'send invitations',
-  #   success: (client, count, options, callback)->
-  #     selOptions =
-  #       targetOptions: {selector: status: 'pending'},
-  #       limit: count,
-  #       sort: requestedAt: 1
-  #     @fetchInvitationRequests {}, selOptions, (err, requests)->
-  #       return callback err  if err
-  #       errors = []
-  #       emails = []
-  #       queue = requests.map (request)-> ->
-  #         request.approve client, options, (err)->
-  #           if err
-  #             errors.push "#{request.email} failed!"
-  #           else
-  #             emails.push request.email
-  #           setTimeout queue.next.bind(queue), 50
-  #       queue.push -> callback (if errors.length > 0 then errors else null), emails
-  #       daisy queue

   approveMember:(member, roles, callback)->
     [callback, roles] = [roles, callback]  unless callback
@@ -1273,16 +1190,6 @@

         daisy queue

-  # addProduct: permit 'manage products',
-  #   success: (client, data, callback)->
-  #     JPaymentGroup = require '../payment/group'
-  #     JPaymentGroup.addPlan this, data, callback
-
-  # deleteProduct: permit 'manage products',
-  #   success: (client, data, callback)->
-  #     JPaymentGroup = require '../payment/group'
-  #     JPaymentGroup.deletePlan this, data, callback
-

   fetchOrCountInvitations: permit 'send invitations',
     success: (client, type, method, options, callback)->
@@ -1387,160 +1294,3 @@
         return callback err if err
         return callback null, channel.id

-  # _fetchSubscription: (callback) ->
-  #   @fetchSubscription (err, subscription) =>
-  #     return callback new KodingError "Error when fetching group's subscription: #{err}"  if err
-  #     return callback new KodingError "Group #{@slug}'s subscription is not found"  unless subscription
-  #     callback err, subscription
-
-  # debitPack: (options, callback) ->
-  #   @_fetchSubscription (err, subscription) ->
-  #     return callback err  if err
-  #     subscription.debitPack options, callback
-
-  # creditPack: (options, callback) ->
-  #   @_fetchSubscription (err, subscription) ->
-  #     return callback err  if err
-  #     subscription.creditPack options, callback
-
-  # linkPaymentMethod: permit 'manage payment methods',
-  #   success: (client, paymentMethodId, callback) ->
-  #     { delegate } = client.connection
-  #     JPaymentMethod = require '../payment/method'
-  #     JPaymentMethod.one { paymentMethodId }, (err, paymentMethod) =>
-  #       return callback err  if err
-  #       delegate.hasTarget paymentMethod, 'payment method', (err, hasTarget) =>
-  #         return callback err  if err
-  #         return callback { message: 'Access denied!' }  unless hasTarget
-  #         @addPaymentMethod paymentMethod, callback
-
-  # unlinkPaymentMethod: permit 'manage payment methods',
-  #   success: (client, paymentMethodId, callback) ->
-  #     JPaymentMethod = require '../payment/method'
-  #     JPaymentMethod.one { paymentMethodId }, (err, paymentMethod) =>
-  #       return callback err  if err
-  #       @removePaymentMethod paymentMethod, callback
-
-  # fetchPaymentMethod$: permit 'manage payment methods',
-  #   success: (client, callback) ->
-  #     JPaymentMethod = require '../payment/method'
-  #     @fetchPaymentMethod (err, paymentMethod) ->
-  #       return callback err  if err
-  #       JPaymentMethod.decoratePaymentMethods [paymentMethod], (err, paymentMethods) ->
-  #         return callback err  if err
-  #         callback null, paymentMethods[0]
-
-  # fetchProducts$: (category, options, callback) ->
-  #   [options, callback] = [callback, options]  unless callback
-  #   options ?= {}
-  #   { tag, tags } = options
-  #   tags = [tag]  if tag and not tags
-
-  #   options.targetOptions ?= {}
-  #   options.targetOptions.options ?= {}
-  #   options.targetOptions.options.sort ?= sortWeight: 1
-  #   options.targetOptions.selector =
-  #     if tags
-  #     then { tags }
-  #     else {}
-
-  #   switch category
-  #     when 'product'
-  #       @fetchProducts {}, options, callback
-  #     when 'pack'
-  #       @fetchPacks {}, options, callback
-  #     when 'plan'
-  #       @fetchPlans {}, options, callback
-
-
-  # fetchInvitationsFromGraph: permit 'send invitations',
-  #   success: (client, type, options, callback)->
-  #     @fetchOrCountInvitations client, type, 'fetch', options, (err, results)=>
-  #       return callback err  if err
-  #       ids = (res.groupOwnedNodes.data.id  for res in results)
-
-  #       require(
-  #         if type is 'InvitationRequest'
-  #         then '../invitationrequest'
-  #         else '../invitation'
-  #       ).some _id: $in: ids, {}, callback
-
-  # countInvitationsFromGraph: permit 'send invitations',
-  #   success: (client, type, options, callback)->
-  #     @fetchOrCountInvitations client, type, 'count', options, (err, result)=>
-  #       return callback err, result?[0]?.count
-
-  # fetchMembersFromGraph:(client, options, callback)->
-  #   return callback {message: "unimplemented feature"}
-
-  # fetchMembersFromGraph$: permit 'list members',
-  #   success: (client, rest...) -> @fetchMembersFromGraph client, rest...
-  #
-
-  # fetchOrCreateBundle: (callback) ->
-  #   @fetchBundle (err, bundle) =>
-  #     return callback err, bundle  if err or bundle
-
-  #     if @slug is 'koding'
-  #       @createBundle
-  #         overagePolicy: 'not allowed'
-  #         paymentPlan  : ''
-  #         allocation   : 0
-  #         sharedVM     : yes
-  #       , (err, bundle) =>
-  #         if err then return callback new KodingError 'Unable to create default group bundle'
-  #         callback null, bundle
-  #     else
-  #       callback new KodingError 'Unable to fetch group bundle'
-
-  # fetchNewestMembers$: permit 'list members',
-  #   success:(client, rest...)->
-  #     [selector, options, callback] = Module.limitEdges 10, 19, rest
-  #     selector            or= {}
-  #     selector.as         = 'member'
-  #     selector.sourceName = 'JGroup'
-  #     selector.sourceId   = @getId()
-  #     selector.targetName = 'JAccount'
-
-  #     options             or= {}
-  #     options.sort        or=
-  #       timestamp         : -1
-  #     options.limit       or= 16
-
-  #     Relationship.some selector, options, (err,members)=>
-  #       if err then callback err
-  #       else
-  #         targetIds = (member.targetId for member in members)
-  #         JAccount = require '../account'
-  #         JAccount.some
-  #           _id   :
-  #             $in : targetIds
-  #         , {}, (err,memberAccounts)=>
-  #           callback err,memberAccounts
-
-  # fetchSubscription$: secure (client, callback) ->
-  #   @fetchSubscription (err, subscription) ->
-  #     return callback err  if err
-  #     {planCode} = subscription
-  #     JPaymentPlan = require '../payment/plan'
-  #     JPaymentPlan.one {planCode}, (err, plan) ->
-  #       return callback err  if err
-  #       subscription.plan = plan
-  #       callback null, subscription
-
-  # redeemInvitation: secure (client, code, callback)->
-  #   {delegate} = client.connection
-  #   @isMember delegate, (err, isMember)=>
-  #     return callback err  if err or isMember
-  #     selector = targetOptions: selector: {code, status:$in:['active', 'sent']}
-  #     @fetchInvitations {}, selector, (err, [invite])=>
-  #       return callback err  if err
-  #       return callback new KodingError 'Invitation code is invalid!'  unless invite
-  #       delegate.fetchUser (err, user)=>
-  #         return callback err  if err
-  #         unless invite.type is 'multiuse' or user.email is invite.email
-  #           return callback new KodingError 'Are you sure invitation e-mail is for you?'
-
-  #         invite.redeem delegate, (err) =>
-  #           return callback err if err
-  #           @approveMember delegate, callback


fixed splice in a for loop, which can lead to out of range exceptions. also now I remove the whole permission if there is no permission anymore

--- workers/social/lib/social/models/group/index.coffee
+++ workers/social/lib/social/models/group/index.coffee
@@ -293,9 +293,16 @@
       # remove permissions for guest which made sense for public but not for private
       if group.privacy is 'private'
         toBeRemoved = ['read activity', 'read tags', 'list members']
-        for perm, i in permissionSet.permissions when perm.role is 'guest'
-          for permission, j in perm.permissions when permission in toBeRemoved
-            permissionSet.permissions[i].permissions.splice j, 1
+        i = permissionSet.permissions.length
+        while i--
+          if permissionSet.permissions[i].role is 'guest'
+            j = permissionSet.permissions[i].permissions.length
+            while j--
+              if permissionSet.permissions[i].permissions[j] in toBeRemoved
+                permissionSet.permissions[i].permissions.splice j, 1
+                if permissionSet.permissions[i].permissions.length <= 0
+                  permissionSet.permissions.splice i, 1
+                  break

       queue = [
         -> group.useSlug group.slug, (err, slug)->


SocialWorker: JGroup: remove MemberAdded shared instance event

--- workers/social/lib/social/models/group/index.coffee
+++ workers/social/lib/social/models/group/index.coffee
@@ -106,7 +106,6 @@
       ]
       instance      : [
         { name: 'GroupCreated' }
-        { name: 'MemberAdded',      filter: -> null }
         { name: 'MemberRemoved',    filter: -> null }
         { name: 'NewInvitationRequest' }
         { name: 'updateInstance' }


fix coffeelint error

fix coffeelint error

--- workers/social/lib/social/models/group/index.coffee
+++ workers/social/lib/social/models/group/index.coffee
@@ -1230,7 +1230,7 @@
     if @slug in ['koding', 'guests']
       return callback new KodingError "It's not allowed to leave this group"

-    @fetchMyRoles client, (err, roles) =>
+    @fetchMyRoles client, (err, roles) ->
       return callback err if err

       account.fetchUser (err, user) ->


TBCampaign: Moved campaign data to above in scriptblock.

--- workers/social/lib/social/render/scriptblock.coffee
+++ workers/social/lib/social/render/scriptblock.coffee
@@ -37,12 +37,12 @@
     <!-- MIXPANEL -->
     <script>(function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;a=e.createElement("script");a.type="text/javascript";a.async=!0;a.src=("https:"===e.location.protocol?"https:":"http:")+'//cdn.mxpnl.com/libs/mixpanel-2.2.min.js';f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f);b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!==typeof d?c=b[d]=[]:d="mixpanel";c.people=c.people||[];c.toString=function(b){var a="mixpanel";"mixpanel"!==d&&(a+="."+d);b||(a+=" (stub)");return a};c.people.toString=function(){return c.toString(1)+".people (stub)"};i="disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" ");for(g=0;g<i.length;g++)f(c,i[g]);b._i.push([a,e,d])};b.__SV=1.2}})(document,window.mixpanel||[]);mixpanel.init("#{KONFIG.mixpanel}");</script>

+    <script>KD.campaign=#{encodedCampaignData};</script>
     <script src='/a/js/kd.#{KONFIG.version}.js'></script>
     #{if intro then "<script src='/a/js/introapp.#{ KONFIG.version }.js'></script>" else ''}
     <script src='/a/js/koding.#{KONFIG.version}.js'></script>
     #{if landing then "<script src='/a/js/landingapp.#{ KONFIG.version }.js'></script>" else ''}
     <script>KD.prefetchedFeeds=#{encodedFeed};</script>
-    <script>KD.campaign=#{encodedCampaignData};</script>

     <!-- GOOGLE ANALYTICS -->


scriptblock: log errors while prefetching socialapi data

--- workers/social/lib/social/render/scriptblock.coffee
+++ workers/social/lib/social/render/scriptblock.coffee
@@ -87,6 +87,7 @@
     ->
       socialApiCacheFn = require '../cache/socialapi'
       socialApiCacheFn options, (err, data)->
+        console.error 'could not get prefetched data', err  if err
         socialapidata = data
         queue.fin()
     ->


fix disappearing wysiwyg toolbar

fix disappearing wysiwyg toolbar

--- @client/form.coffee
+++ @client/form.coffee
@@ -188,6 +188,12 @@
       # },
     ]

+    for button in toolbar_items
+      button.onClick = (e) ->
+        e.stopPropagation()
+        e.preventDefault()
+        console.log "BUTTON onclick"
+

     close_if_nothing_in_menu_focused = =>
       console.log document.activeElement, "##{id}", document.activeElement.closest("##{id}")
@@ -205,7 +211,9 @@
       toolbar_items.push
         className: 'fa fa-code'
         title: 'Directly edit HTML'
-        onClick: => @local.edit_code = true; save @local
+        onClick: =>
+          @local.edit_code = true
+          save @local

     id = @props.editor_key.replace(/\//g, '__')
     DIV
@@ -214,7 +222,7 @@
         position: 'relative'

       onClick: (ev) ->
-        console.log 'high'
+        console.log 'onclick on editor area'
         # Catch any clicks within the editor area to prevent the
         # toolbar from being hidden via the root level
         # wysiwyg_editor state
@@ -258,7 +266,7 @@
                 visibility: if wysiwyg_editor.showing != @props.editor_key then 'hidden'

               onFocus: (e) =>
-                if !@local.focused_toolbar_item && !@local.just_unfocused
+                if !@local.focused_toolbar_item

                   if @local.focused_toolbar_item in [undefined, null]
                     @local.focused_toolbar_item = 0
@@ -268,7 +276,6 @@
                   ReactDOM.findDOMNode(@refs["toolbaritem-#{@local.focused_toolbar_item}"]).focus()

               onKeyDown: (e) =>
-
                 if e.which in [37, 38, 39, 40]
                   # focus prev...
                   i = @local.focused_toolbar_item
@@ -287,7 +294,7 @@
                   e.preventDefault()

               for button, idx in toolbar_items
-                do (idx) =>
+                do (button, idx) =>
                   BUTTON
                     key: button.title or idx
                     ref: "toolbaritem-#{idx}"
@@ -306,24 +313,8 @@
                       display: if toolbar_horizontal then 'inline-block' else 'block'
                       marginBottom: 4
                     title: button.title
-                    value: if button.value then button.value
+                    value: button.value
                     onClick: button.onClick
-
-                    onFocus: (e) =>
-                      @local.focused_toolbar_item = idx;
-                      save @local
-                      e.stopPropagation()
-
-                    onBlur: (e) =>
-                      e.stopPropagation()
-                      @local.focused_toolbar_item = null
-                      @local.just_unfocused = true
-                      setTimeout =>
-                        @local.just_unfocused = false
-                      , 0
-                      save @local
-
-                      close_if_nothing_in_menu_focused()

           DIV
             style: _.defaults {}, @props.container_style,


--- @client/tabs.coffee
+++ @client/tabs.coffee
@@ -106,8 +106,18 @@

 window.get_tabs = ->
-  if customization('homepage_tabs')?.length > 0
-    fetch('/subdomain').customizations.homepage_tabs
+  if fetch('/subdomain').customizations?.homepage_tabs?.length > 0
+    console.log (t.name for t in fetch('/subdomain').customizations.homepage_tabs when t.name)
+    tabs = fetch('/subdomain').customizations.homepage_tabs
+
+    # hack to fix a bug I haven't found where a tab can have a null name
+    idx = tabs.length - 1
+    while idx >= 0
+      if tabs[idx].name == null
+        tabs.splice idx, 1
+      idx -= 1
+
+    tabs
   else
     null