add text to Toast in AuthenticateUser service

--- app/services/authenticate-user.coffee
+++ app/services/authenticate-user.coffee
@@ -10,7 +10,7 @@
         .then (data) ->
           if groupId = parseInt($stateParams.groupId)
             if !(_.find data.groups, (group) -> group.id == groupId)
-              Toast.show('The group you were trying to access is private')
+              Toast.show('The group you were trying to access is private, please sign in to continue')
               ipCookie.remove('initialRequestPath')
               $location.path('/')
               deferred.reject()
@@ -19,7 +19,7 @@
               userIsMemberOfBucketGroup = _.find data.groups, (group) ->
                 group.id == bucket.groupId
               if !userIsMemberOfBucketGroup
-                Toast.show('The bucket you were trying to access is private')
+                Toast.show('The bucket you were trying to access is private, please sign in to continue')
                 ipCookie.remove('initialRequestPath')
                 $location.path('/')
                 deferred.reject()


resset state of root editable to make work on subsequent activations

--- scripts/views/workspace/content/aloha-edit.coffee
+++ scripts/views/workspace/content/aloha-edit.coffee
@@ -75,6 +75,11 @@
         Aloha.ready =>
           @$el.addClass('aloha-root-editable')
           @$el.mahalo?()
+
+          # resset some of the state of our root element so aloha doesn't freak out
+          @$el.removeClass('aloha-block-blocklevel-sortable')
+          @$el.removeData()
+
           @$el.aloha()

           Aloha.bind 'aloha-smart-content-changed.updatemodel', (evt, d) =>


Always insert the first text when dragging a selected range

* More closely matches the behavior of Pages.app
* Fixes dragging images back into galleries

--- src/trix/models/document.coffee
+++ src/trix/models/document.coffee
@@ -162,19 +162,18 @@
     movingRightward = startPosition < position
     position -= document.getLength() if movingRightward

-    unless result.firstBlockInRangeIsEntirelySelected(range)
-      [firstBlock, blocks...] = document.getBlocks()
-      if blocks.length is 0
-        text = firstBlock.getTextWithoutBlockBreak()
-        position += 1 if movingRightward
-      else
-        text = firstBlock.text
-
-      result = result.insertTextAtRange(text, position)
-      return result if blocks.length is 0
-
-      document = new @constructor blocks
-      position += text.getLength()
+    [firstBlock, blocks...] = document.getBlocks()
+    if blocks.length is 0
+      text = firstBlock.getTextWithoutBlockBreak()
+      position += 1 if movingRightward
+    else
+      text = firstBlock.text
+
+    result = result.insertTextAtRange(text, position)
+    return result if blocks.length is 0
+
+    document = new @constructor blocks
+    position += text.getLength()

     result.insertDocumentAtRange(document, position)

@@ -262,19 +261,6 @@
         block.removeAttribute(lastAttributeName)
     new @constructor blockList

-  firstBlockInRangeIsEntirelySelected: (range) ->
-    [startPosition, endPosition] = range = normalizeRange(range)
-    leftLocation = @locationFromPosition(startPosition)
-    rightLocation = @locationFromPosition(endPosition)
-
-    if leftLocation.offset is 0 and leftLocation.index < rightLocation.index
-      true
-    else if leftLocation.index is rightLocation.index
-      length = @getBlockAtIndex(leftLocation.index).getLength()
-      leftLocation.offset is 0 and rightLocation.offset is length
-    else
-      false
-
   expandRangeToLineBreaksAndSplitBlocks: (range) ->
     [startPosition, endPosition] = range = normalizeRange(range)
     startLocation = @locationFromPosition(startPosition)


sv work

sv work

--- src/ubret/subject_viewer.coffee
+++ src/ubret/subject_viewer.coffee
@@ -26,19 +26,21 @@
         .attr('class', 'subject')

     subject.append('img')
-        .attr('src', (d) -> console.log d; d.image)
-        .attr('width', 300)
-        .attr('height', 300)
+        .attr('src', (d) -> d.image)

-    subject.selectAll('ul')
-      .append('ul')
+    subject.append('ul').selectAll('ul')
       .data((d) => @toArray(d)).enter()
         .append('li')
         .attr('data-key', (d) -> d[0])
-        .text((d) => "#{@formatKey(d[0])}: #{d[1]}")
+        .html((d) => "#{@formatKey(d[0])}: #{d[1]}")

     subject.select("[data-key=\"#{@selectedKey}\"]")
       .attr('class', 'selected')
+
+    header = subject.selectAll('ul')
+      .insert('li', ':first-child')
+        .attr('class', 'heading')
+        .html('Key Value')

   toArray: (data) =>
     arrayedData = new Array


Model: initialize fixes

Model: initialize fixes

* should always call super
* should always return this

--- coffee/src/model.coffee
+++ coffee/src/model.coffee
@@ -5,8 +5,10 @@
 class acorn.Model extends Backbone.Model

   initialize: =>
+    super()
     if not @acornid()
       @acornid 'new'
+    @

   defaults: =>
     shell: {shell: 'acorn.LinkShell'}


Revert "Run tests via task dependencies"

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -749,7 +749,7 @@
 		.on 'error', onError

 # Execute karma unit tests
-gulp.task 'karma', [].concat(unless runWatch then ['build'] else []), ->
+gulp.task 'karma', ->
 	sources = [].concat SCRIPTS, '**/*.html'

 	options =
@@ -1209,7 +1209,6 @@
 	# get args from parent process to pass on to child process
 	args  = ("--#{key}=#{value}" for own key, value of yargs.argv when key isnt '_' and key isnt '$0')
 	args  = ['karma'].concat args
-
 	spawn = childProcess.spawn command, args, {stdio: 'inherit'}

 # Compile TypeScript


remove reference to rjs

remove reference to rjs

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -32,7 +32,7 @@
 	pkg = JSON.stringify pkg, null, 2
 	fs.writeFileSync path.join(__dirname, "package.json"), pkg

-	# Replace version in r.js wrap files
+	# Replace version in wrap files
 	gulp.src 'build/*.template'
 	.pipe replace "{CAPACITOR_VERSION}", version
 	.pipe rename extname: ".js"


removed comment about gulp-sass

removed comment about gulp-sass

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -1,5 +1,3 @@
-# Note: Don't try to use gulp-sass. It doesn't work.
-
 browserify = require 'gulp-browserify'
 coffee = require 'gulp-coffee'
 coffeelint = require 'gulp-coffeelint'


fix woff to base64

fix woff to base64

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -95,7 +95,7 @@
     .pipe(stylus())
     .pipe(base64(
         extensions: ['woff']
-        maxImageSize: 10 * 1024 # 10 mb
+        maxImageSize: 1024 * 1024 * 10 # 10 mb
     ))
     .pipe(urlAdjuster(
         replace: ['../../img/', '../img/']
@@ -116,14 +116,14 @@
     .pipe(stylus())
     .pipe(base64(
         extensions: ['woff']
-        maxImageSize: 10 * 1024 # 10 mb
+        maxImageSize: 1024 * 1024 * 10 # 10 mb
     ))
     .pipe(urlAdjuster(
         replace: ['../../img/', '../../frontend/img/']
     ))
     .pipe(base64(
         extensions: ['png', 'svg', 'jpg']
-        maxImageSize: 10 * 1024 # 10 mb
+        maxImageSize: 1024 * 1024 # 1 mb
     ))
     .pipe(urlAdjuster(
         replace: ['../../frontend/img/','../img/']


Don't read coverage on src

Don't read coverage on src

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -92,7 +92,7 @@
     gutil.log(gutil.colors.red("coverage.json not found."))
     process.exit(1)

-  stream = gulp.src('coverage/coverage.json')
+  stream = gulp.src('coverage/coverage.json', read: false)
     .pipe(exec(
       'istanbul check-coverage --statements <%= options.coverage.statements %> --branches <%= options.coverage.branches %> --functions <%= options.coverage.functions %> --lines <%= options.coverage.lines %>',
       silent: false


Completely remove gulp-connect

Completely remove gulp-connect

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -17,7 +17,6 @@
 karma = require 'gulp-karma'
 protractor = require('gulp-protractor').protractor
 browserSync = require 'browser-sync'
-connect = require 'gulp-connect'

 # CONFIG -------------------------------------------

@@ -74,13 +73,6 @@
 ]

 # TASKS ----------------------------------------------------------------------
-
-# Allows to autoreload the page
-gulp.task 'connect', connect.server(
-  root: ['build'] # this is the directory the server will run
-  port: 1337
-  livereload: true
-)

 # Compiles SASS with libsass to a compressed output
 gulp.task 'style', ->


Disable output logger (for tests)

Disable output logger (for tests)

--- src/test/hubot-factoid_test.coffee
+++ src/test/hubot-factoid_test.coffee
@@ -66,9 +66,11 @@
   user = robot.brain.userForId '1', name: 'Shell', room: 'Shell', roles: [ "edit_factoids" ]
   robot.adapter.receive new TextMessage user, msg, 'messageId'

-[['Addressed', "#{robot.name}: "], ['Not Addressed', '']].forEach (type) ->
-  describe type[0], ()->
-    describe '#Commands', ()->
+robot.logger.info = sinon.spy()
+
+describe '#Commands', ()->
+  [['Addressed', "#{robot.name}: "], ['Not Addressed', '']].forEach (type) ->
+    describe type[0], ()->
       describe '#Randoms', ()->
         before (done) ->
           robot.brain.data.factoids = {


schema containedBy

schema containedBy

--- src/textorum/tinymce/plugin.coffee
+++ src/textorum/tinymce/plugin.coffee
@@ -37,8 +37,12 @@
     schema = data
     schema.containedBy ||= {}
     schema.defs ||= {}
+    for element, details of schema.defs
+      elementContains = {}
+      for own containedElement, v of details.contains
+        schema.containedBy[containedElement] ||= {}
+        schema.containedBy[containedElement][element] = 1

-  console.log "let's go"
   tinymce.create 'tinymce.plugins.textorum.loader', {
     init: (editor, url) =>
       console.log "editor", editor


It is obvious (?)

It is obvious (?)


bugfix in multiple preview

bugfix in multiple preview

--- app/assets/javascripts/uploadcare/widget/tabs/preview-tab-multiple.js.coffee
+++ app/assets/javascripts/uploadcare/widget/tabs/preview-tab-multiple.js.coffee
@@ -30,10 +30,10 @@

       @fileColl.onAnyProgress.add @__updateFileView

-      @fileColl.onAnyFail.add (file, error) ->
+      @fileColl.onAnyFail.add (file, error) =>
         @__fileToEl(file).addClass(CLASS_PREFIX + 'error')

-      @fileColl.onAnyDone.add (file, info) ->
+      @fileColl.onAnyDone.add (file, info) =>
         @__fileToEl(file).addClass(CLASS_PREFIX + 'uploaded')

     __find: (s, context = @container) ->


removed okay button and made dismiss button primary for request pending modal

--- client/landing/app/Applications/Home.kdapplication/Views/homeloginbar.coffee
+++ client/landing/app/Applications/Home.kdapplication/Views/homeloginbar.coffee
@@ -109,7 +109,7 @@
             height         : 'auto'
             overlay        : yes
             buttons        :
-              Okay         :
+              Dismiss      :
                 style      : 'modal-clean-green'
                 loader     :
                   color    : "#ffffff"
@@ -130,9 +130,6 @@
                     if @policy.approvalEnabled
                     then @access.show()
                     else @request.show()
-              Dismiss      :
-                style      : "modal-cancel"
-                callback   : -> modal.destroy()

     @invited      = new CustomLinkView
       tagName     : "a"


Fix bug on client disconnection

Fix bug on client disconnection

--- app/static/scripts/connections.coffee
+++ app/static/scripts/connections.coffee
@@ -111,10 +111,13 @@
             uid     : @call.peer
         @emitter.trigger 'stream.create', data

-    onClose     : () =>
-
     sendStream   : (stream) =>
         @call.answer stream
+
+    onClose     : () =>
+
+    close       : () =>
+        do @call.close

 class Connections
     constructor : (@emitter, @uid, @rid, @wsPortal, @pjsPortal) ->
@@ -150,9 +153,12 @@
     initUser : (event, data) =>
         window.Voicious.currentUser = data
         @emitter.trigger 'module.initialize', { }
-
+
     removePeer   : (peerId) =>
-        do @peers[peerId].close
+        console.log @peers[peerId]
+        do @peers[peerId].dc.close
+        if @peers[peerId].mc?
+            do @peers[peerId].mc.close
         @peers[peerId] = null
         delete @peers[peerId]

@@ -172,7 +178,7 @@
             if !@peers[do data.dc.peer]?
                 @peers[do data.dc.peer] = {}
             @peers[do data.dc.peer].dc = data.dc
-            # @sendStreamState do data.dc.peer
+            @sendStreamState do data.dc.peer
         @emitter.on 'peer.mediaconnection', (event, data) =>
             if !@peers[do data.mc.peer]?
                 @peers[do data.mc.peer] = {}
@@ -197,7 +203,7 @@
             message = { type : 'chat.message' , params : { message : data } }
         for id, peer of @peers
             @send id, message
-
+
     sendToOneName : (event, msg) =>
         message = { type : msg.type, params : msg.params }
         userId = @getIdFromUsername msg.to
@@ -239,7 +245,7 @@
             if peer.name is username
                 id = peer.id
                 break
-        id
+        id

 window.RTCSessionDescription = window.mozRTCSessionDescription or window.RTCSessionDescription
 window.RTCIceCandidate       = window.mozRTCIceCandidate       or window.RTCIceCandidate


refactoring

refactoring

--- imports/server/stateReconciler.coffee
+++ imports/server/stateReconciler.coffee
@@ -85,9 +85,8 @@
         properties = labelsToObject labels
         updateDoc =
           name: name
-          app:
-            name: properties.bigboat?.application?.name
-            version: properties.bigboat?.application?.version
+          'app.name': properties.bigboat?.application?.name
+          'app.version': properties.bigboat?.application?.version
           startedBy: properties.bigboat?.startedBy
           storageBucket: properties.bigboat?.storage?.bucket
           agent:


add debug line

add debug line

--- services/docstore/config/settings.defaults.coffee
+++ services/docstore/config/settings.defaults.coffee
@@ -27,5 +27,7 @@
 		key: process.env['AWS_ACCESS_KEY_ID']
 		secret: process.env['AWS_SECRET_ACCESS_KEY']
 		bucket: process.env['AWS_BUCKET']
+
+console.log Settings, process.env['HEALTH_CHECK_PROJECT_ID']

 module.exports = Settings


Use isPullRequest instead of eventType

Use isPullRequest instead of eventType

--- assets/scripts/app/models/repo.coffee
+++ assets/scripts/app/models/repo.coffee
@@ -34,12 +34,11 @@
     array  = Travis.ExpandableRecordArray.create
       type: Travis.Build
       content: Ember.A([])
-      store: @get('store')

     array.load(builds)

     id = @get('id')
-    array.observe(@get('allBuilds'), (build) -> build.get('isLoaded') && build.get('eventType') && build.get('repo.id') == id && !build.get('isPullRequest') )
+    array.observe(@get('allBuilds'), (build) -> build.get('isLoaded') && build.get('repo.id') == id && !build.get('isPullRequest') )

     array
   ).property()
@@ -50,12 +49,11 @@
     array  = Travis.ExpandableRecordArray.create
       type: Travis.Build
       content: Ember.A([])
-      store: @get('store')

     array.load(builds)

     id = @get('id')
-    array.observe(@get('allBuilds'), (build) -> build.get('isLoaded') && build.get('eventType') && build.get('repo.id') == id && build.get('isPullRequest') )
+    array.observe(@get('allBuilds'), (build) -> build.get('isLoaded') && build.get('repo.id') == id && build.get('isPullRequest') )

     array
   ).property()


Fix pull requests view to show PR number

--- assets/scripts/app/views/build.coffee
+++ assets/scripts/app/views/build.coffee
@@ -30,6 +30,8 @@
     buildBinding: 'context'
     commitBinding: 'build.commit'

+    isPullRequestsList: ( -> @get('parentView.isPullRequestsList') ).property('parentView.isPullRequestsList')
+
     color: (->
       Travis.Helpers.colorForState(@get('build.state'))
     ).property('build.state')


fix updating progress bar time

fix updating progress bar time

--- src/javascripts/progress_bar.coffee
+++ src/javascripts/progress_bar.coffee
@@ -40,6 +40,7 @@
     @updateLoaded()

   updateTime: (time) =>
+    return unless typeof time == 'number'
     currentTime = time || @media.currentTime
     time = if @timeMode == 'countup'
       prefix = ''
@@ -147,7 +148,8 @@

   handleDrop: (event) =>
     position = Utils.calculateCursorPosition(event, @elem[0])
-    @jumpToPosition(position)
+    if position <= @barWidth()
+      @jumpToPosition(position)

   barWidth: => @railElement.width()


fix valid values for picker fix message callbacks

--- app/assets/javascripts/hub_client.coffee
+++ app/assets/javascripts/hub_client.coffee
@@ -12,7 +12,7 @@

   openPicker: (type) ->
-    valid_types = ['entityset', 'action', 'event']
+    valid_types = ['entity_set', 'action', 'event']
     console.error("called HubApi\#openPicker(type) with type=#{type}. valid values: #{valid_types.join(', ')}.") if $.inArray(type, valid_types) == -1

     pr = new PickerResult(@)
@@ -24,8 +24,13 @@
     @url

   _message: (event) ->
+    return if $.isEmptyObject(@pickers)
     data = JSON.parse(event.data)
-    @pickers[data.target][data.message](data)
+    target = @pickers[data.target]
+    target[data.message](data) if target
+
+  _removePicker: (pr) ->
+    delete @pickers[pr.id]

 class PickerResult
   constructor: (@api) ->
@@ -73,6 +78,7 @@

   close: ->
     @container.remove()
+    @api._removePicker(@)

   then: (callback) ->
     @then = callback


avoid duplicate toast error messages #639

--- app/assets/javascripts/libs/toast.coffee
+++ app/assets/javascripts/libs/toast.coffee
@@ -38,8 +38,9 @@
       messages = messages
       @message(type, message, sticky) for message in messages

-    else
-      $messageElement = $("<div>", class : "alert alert-#{type} fade in").html(message)
+    # Avoid duplicate messages
+    else if $(".alert-#{type}[data-id='#{message}']").length == 0
+      $messageElement = $("<div>", class : "alert alert-#{type} fade in", "data-id" : message).html(message)
       $messageElement.prepend($("<button>", type : "button", class : "close", "data-dismiss" : "alert").html("×"))
       if sticky
         $messageElement.alert()


Remove TODO from public view

Remove TODO from public view

--- app/classifier/tasks/generic-editor.cjsx
+++ app/classifier/tasks/generic-editor.cjsx
@@ -104,6 +104,7 @@
                       <AutoSave resource={@props.workflow}>
                         Color{' '}
                         <select name="#{@props.taskPrefix}.#{choicesKey}.#{index}.color" value={choice.color} onChange={handleChange}>
+                          <!-- TODO Color picker instead of fixed choices -->
                           <option value="#ff0000">Red</option>
                           <option value="#ffff00">Yellow</option>
                           <option value="#00ff00">Green</option>
@@ -112,7 +113,6 @@
                           <option value="#ff00ff">Magenta</option>
                           <option value="#000000">Black</option>
                           <option value="#ffffff">White</option>
-                          <option disabled>TODO: Picker</option>
                         </select>
                       </AutoSave>
                     </div>


Fix millisSinceLastOfferHuman

Fix millisSinceLastOfferHuman

--- SingularityUI/app/models/State.coffee
+++ SingularityUI/app/models/State.coffee
@@ -7,7 +7,7 @@
     parse: (state) =>
         state.uptimeHuman = moment.duration(state.uptime).humanize()
         state.driverStatusHuman = constants.driverStates[state.driverStatus]
-        state.millisSinceLastOfferHuman = moment(state.millisSinceLastOffer).from()
+        state.millisSinceLastOfferHuman = moment(+new Date() - state.millisSinceLastOffer).from()
         state

 module.exports = State


[backport] add missing ngRoute

[backport] add missing ngRoute

--- app/plugins/humanshtml/humanshtml.coffee
+++ app/plugins/humanshtml/humanshtml.coffee
@@ -23,7 +23,7 @@
 # and add additional template.

 taiga = @.taiga
-module = angular.module("taigaPlugins")
+module = angular.module("taigaPlugins", ["ngRoute"])

 configure = ($routeProvider) ->
     $routeProvider.when("/humans.html", {"templateUrl": "/plugins/humanshtml/templates/humans.html"})


Ignore errors from child process

Ignore errors from child process

These can be ignored since the close event handler will still
invoke the callback.

--- src/apm-cli.coffee
+++ src/apm-cli.coffee
@@ -117,6 +117,7 @@
     outputChunks = []
     spawned.stderr.on 'data', (chunk) -> outputChunks.push(chunk)
     spawned.stdout.on 'data', (chunk) -> outputChunks.push(chunk)
+    spawned.on 'error', ->
     spawned.on 'close', (code) ->
       if code is 0
         [name, version] = Buffer.concat(outputChunks).toString().split(' ')
@@ -133,6 +134,7 @@
     outputChunks = []
     spawned.stderr.on 'data', (chunk) -> outputChunks.push(chunk)
     spawned.stdout.on 'data', (chunk) -> outputChunks.push(chunk)
+    spawned.on 'error', ->
     spawned.on 'close', (code) ->
       if code is 0
         [gitName, versionName, version] = Buffer.concat(outputChunks).toString().split(' ')


Clean all popovers after each spec

Clean all popovers after each spec

--- src/spec/bootstrap-tour.spec.coffee
+++ src/spec/bootstrap-tour.spec.coffee
@@ -10,6 +10,7 @@
     $.each @tour._steps, (i, s) ->
       $element = $(tour.getStep(i).element)
       $element.popover("destroy").removeData("bs.popover")
+      $element.remove()

   it "should set the tour options", ->
     @tour = new Tour
@@ -589,9 +590,12 @@
       orphan: true
     @tour.showStep(0)
     expect($(".popover").length).toBe 1
+    $(".popover").remove()

   it "should add 'orphan' class to the popover", ->
     @tour = new Tour
     @tour.addStep
       orphan: true
+    @tour.showStep(0)
     expect($(".popover").hasClass("orphan")).toBe true
+    $(".popover").remove()


Cleaned up views/ui/field_list

Cleaned up views/ui/field_list

--- src/views/ui/form/field_list.coffee
+++ src/views/ui/form/field_list.coffee
@@ -10,8 +10,10 @@

   addOne: (model) =>

-    editor = FieldFactory.build
+    key = "#{model.get 'key'}"
+
+    # console.log @options.fieldStyles, @options.fieldStyles[key]
+
+    @add FieldFactory.build
       field: model
       controller: @controller
-
-    @view.add editor.render().view


basic zoom working

basic zoom working

--- static/coffee/tools/zoomtool.coffee
+++ static/coffee/tools/zoomtool.coffee
@@ -38,7 +38,7 @@
     return @mappers

   mouse_coords : (e, x, y) ->
-    [x_, y_] = [@plot_view.viewstate.rxpos(x), @plot_view.viewstate.rypos(y)]
+    [x_, y_] = [@plot_view.view_state.device_to_sx(x), @plot_view.view_state.device_to_sy(y)]
     return [x_, y_]

   _zoom : (e) ->
@@ -48,19 +48,34 @@
     [x, y] = @mouse_coords(e, screenX, screenY)
     speed = @mget('speed')
     factor = - speed  * (delta * 50)
-    for dim, mapper in @mappers
-      if dim == 'width'
-        eventpos = x
-      else
-        eventpos = y
-      screenlow = 0
-      screenhigh = @plot_view.viewstate.get(mapper.screendim)
-      start = screenlow - (eventpos - screenlow) * factor
-      end = screenhigh + (screenhigh - eventpos) * factor
-      [start, end] = [mapper.map_data(start), mapper.map_data(end)]
-      mapper.data_range.set(
-        start : start
-        end : end)
+
+    sx_low = 0
+    sx_high = @plot_view.view_state.get('inner_width')
+    sy_low = 0
+    sy_high = @plot_view.view_state.get('inner_height')
+
+    xstart = @plot_view.xmapper.map_from_target(sx_low-(x-sx_low)*factor)
+    xend   = @plot_view.xmapper.map_from_target(sx_high+(sx_high-x)*factor)
+    ystart = @plot_view.ymapper.map_from_target(sy_low-(y-sy_low)*factor)
+    yend   = @plot_view.ymapper.map_from_target(sy_high+(sy_high-y)*factor)
+
+    @plot_view.x_range.set({start: xstart, end: xend})
+    @plot_view.y_range.set({start: ystart, end: yend})
+
+
+    # for dim, mapper in @mappers
+    #   if dim == 'width'
+    #     eventpos = x
+    #   else
+    #     eventpos = y
+    #   screenlow = 0
+    #   screenhigh = @plot_view.viewstate.get(mapper.screendim)
+    #   start = screenlow - (eventpos - screenlow) * factor
+    #   end = screenhigh + (screenhigh - eventpos) * factor
+    #   [start, end] = [mapper.map_data(start), mapper.map_data(end)]
+    #   mapper.data_range.set(
+    #     start : start
+    #     end : end)
     return null


Don't adjust project quality charts

Don't adjust project quality charts

--- static/scripts/plottings.coffee
+++ static/scripts/plottings.coffee
@@ -47,8 +47,7 @@
                                 0

         _preparePlot: (plot) ->
-            prepared = _.flatten [_.map(_.range(@limit), -> 0), [plot.reverse()]]
-            _.map (_.last prepared, @limit), (item, num) -> [num, item]
+            _.map (_.last plot, @limit), (item, num) -> [num, item]

         _checkDatasets: (datasets) ->
             datasets.length and (_.any datasets, (@item) ->


Add project context to subject comments

Add project context to subject comments

--- app/talk/quick-subject-comment-form.cjsx
+++ app/talk/quick-subject-comment-form.cjsx
@@ -88,6 +88,7 @@

Leave a note about this subject

       <CommentBox
+        project={@props.project}
         user={@props.user}
         header={null}
         validationCheck={@commentErrors}


Completed konacha test cases for Repository.Branch class.

Signed off by: Daniel Miranda <danielkza2@gmail.com>

--- spec/javascripts/repository/branch_spec.js.coffee
+++ spec/javascripts/repository/branch_spec.js.coffee
@@ -77,31 +77,51 @@

   describe '#fetch', ->
     beforeEach ->
+      @subject.names = {}
+      @address = 'https://github.com/mezuro/kalibro_processor.git'
       @subject.cancel_request = sinon.stub()
+      sinon.stub(@subject, "fill_options")
+
+      @select = {empty: sinon.stub()}
+      # $ is a global jQuery variable. That is why we don't need to declare it as @$
+      $ = sinon.stub(window, "$")
+      $.withArgs("#repository_branch").returns(@select)
+      $.withArgs("#repository_scm_type").returns({val: -> "GIT"})
+
+    afterEach ->
+      @subject.fill_options.restore()
+      $.restore()

     context 'with valid address', ->
-      beforeEach ->
-        sinon.stub(@subject, "fill_options")
-
-      afterEach ->
-        @subject.fill_options.restore()
-
-      context 'with new address', ->
+      context 'with an address that is not cached', ->
         beforeEach ->
-          @subject.names = {}
-          @address = 'https://github.com/mezuro/kalibro_processor.git'
-
-          @select = {empty: sinon.stub()}
-          $ = sinon.stub(window, "$")
-          $.withArgs("#repository_branch").returns(@select)
-          $.withArgs("#repository_scm_type").returns({val: -> "GIT"})
           $.get = sinon.stub().withArgs('/repository_branches', {'url': @address, 'scm_type': 'GIT'}).returns().yields({
             'branches': ['stable', 'dev', 'master']
           })

-        afterEach ->
-          $.restore()
-
         it 'should fetch the branches and fill the options', ->
           @subject.fetch(@address)
+          sinon.assert.calledWith(@select.empty)
           sinon.assert.calledWith(@subject.fill_options, ['stable', 'dev', 'master'], @select)
+
+      context 'with an address that is cached', ->
+        beforeEach ->
+          @subject.names[@address] = ['stable', 'dev', 'master']
+          $.get = sinon.stub()
+
+        it 'should not request the branches but fill the select with the cached values', ->
+          @subject.fetch(@address)
+          sinon.assert.calledWith(@select.empty)
+          sinon.assert.calledWith(@subject.fill_options, ['stable', 'dev', 'master'], @select)
+          sinon.assert.notCalled($.get)
+
+    context 'with an invalid address', ->
+      beforeEach ->
+        $.get = sinon.stub().withArgs('/repository_branches', {'url': @address, 'scm_type': 'GIT'}).returns().yields({
+          'errors': ['InvalidUrl']
+        })
+
+      it 'should not fill the options', ->
+        @subject.fetch(@address)
+        sinon.assert.calledWith(@select.empty)
+        sinon.assert.notCalled(@subject.fill_options)


fix priority

fix priority

--- packages/rocketchat-oembed/server/server.coffee
+++ packages/rocketchat-oembed/server/server.coffee
@@ -31,8 +31,7 @@
 	if detectedCharset
 		if detectedCharset == httpHeaderCharset
 			result = httpHeaderCharset
-
-		if detectedCharset == htmlMetaCharset
+		else if detectedCharset == htmlMetaCharset
 			result = htmlMetaCharset

 	unless result


for -> with

for -> with

--- src/trix/models/html_parser.coffee
+++ src/trix/models/html_parser.coffee
@@ -85,7 +85,7 @@
           for key, value of getImageDimensions(image)
             if value isnt attributes[key]
               textAttributes[key] = value
-        @appendAttachmentForAttributes(attributes, textAttributes)
+        @appendAttachmentWithAttributes(attributes, textAttributes)
         # We have everything we need so avoid processing inner nodes
         element.innerHTML = ""
       @processedElements.push(element)
@@ -98,7 +98,7 @@
         when "img"
           attributes = url: element.src, contentType: "image"
           attributes[key] = value for key, value of getImageDimensions(element)
-          @appendAttachmentForAttributes(attributes, getTextAttributes(element))
+          @appendAttachmentWithAttributes(attributes, getTextAttributes(element))
           @processedElements.push(element)
         when "tr"
           unless element.parentNode.firstChild is element
@@ -119,7 +119,7 @@
   appendStringWithAttributes: (string, attributes) ->
     @appendPiece(pieceForString(string, attributes))

-  appendAttachmentForAttributes: (attachment, attributes) ->
+  appendAttachmentWithAttributes: (attachment, attributes) ->
     @appendPiece(pieceForAttachment(attachment, attributes))

   appendPiece: (piece) ->


feat: twitter api -- commenting out shit people dont use

--- api/server.coffee
+++ api/server.coffee
@@ -1,6 +1,11 @@
 express = require("express")
 path = require("path")
 http = require("http")
+
+util = require("util")
+
+twitter = require("twitter")
+twit = require('./private-token')

 Firebase = require('firebase')
 app = express()
@@ -22,11 +27,14 @@
   )

 #Twitter Watchers
-pingRef = new Firebase('https://thetable.firebaseio.com/waits/')
-pingRef.on('child_added', (childSnapshot, prevChildName) ->
-  console.log childSnapshot.val()
-  console.log "someone pinged!"
-)
+# No one cares about twitter, or thetable.io anyway.
+# pingRef = new Firebase('https://thetable.firebaseio.com/waits/')
+# pingRef.on('child_added', (childSnapshot, prevChildName) ->
+#   waits = childSnapshot.val()
+#   console.log waits
+#   console.log waits.twitter
+#   console.log "someone pinged!"
+# )

 require('./routes')(app)


Added recent pro Hungarian diplomats

Added recent pro Hungarian diplomats

--- app/views/contribute/DiplomatView.coffee
+++ app/views/contribute/DiplomatView.coffee
@@ -121,7 +121,7 @@
     el: ['Stergios', 'micman', 'zsdregas']             # ελληνικά, Greek
     ro: []             # limba română, Romanian
     vi: ['An Nguyen Hoang Thien']             # Tiếng Việt, Vietnamese
-    hu: ['Anon', 'atlantisguru', 'bbeasmile', 'csuvsaregal', 'divaDseidnA', 'ferpeter', 'kinez']             # magyar, Hungarian
+    hu: ['Anon', 'atlantisguru', 'bbeasmile', 'csuvsaregal', 'divaDseidnA', 'ferpeter', 'kinez', 'adamcsillag', 'LogMeIn', 'espell.com']             # magyar, Hungarian
     th: ['Kamolchanok Jittrepit']             # ไทย, Thai
     da: ['Anon', 'Einar Rasmussen', 'Rahazan', 'Randi Hillerøe', 'Silwing', 'marc-portier', 'sorsjen', 'Zleep-Dogg']             # dansk, Danish
     ko: ['Melondonut']             # 한국어, Korean


Refactor: remove classroom-ladder levels from list of hero-ladder levels that don't allow hero configuration

--- app/views/play/menu/GameMenuModal.coffee
+++ app/views/play/menu/GameMenuModal.coffee
@@ -50,7 +50,7 @@
   showsChooseHero: ->
     return false if @level?.isType('course', 'course-ladder')
     return false if @level?.get('assessment') is 'open-ended'
-    return false if @options.levelID in ['zero-sum', 'ace-of-coders', 'elemental-wars', 'the-battle-of-sky-span', 'tesla-tesoro', 'escort-duty']
+    return false if @options.levelID in ['zero-sum', 'ace-of-coders', 'the-battle-of-sky-span']
     return true

   afterRender: ->


Cleans up

Cleans up

--- apps/articles/client/team_channel.coffee
+++ apps/articles/client/team_channel.coffee
@@ -58,7 +58,8 @@
       @$body.removeClass 'is-open'
       $('.team-channel-body').css 'transform', "translate3d(0, 0, 0)"
     else
-      height = $('.team-channel-nav__links a').length * 50
+      withHeader = if $('body.is-sticky').length > 0 then 0 else 92
+      height = $('.team-channel-nav__links a').length * 50 + withHeader
       @$body.addClass 'is-open'
       $('.team-channel-body').css 'transform', "translate3d(0, #{height}px, 0)"


fixes for last modified

fixes for last modified

--- apps/artist/client/views/overview.coffee
+++ apps/artist/client/views/overview.coffee
@@ -97,10 +97,10 @@
       mostRecentArtworkDate =
         (for artwork in artworks
           new Date(artwork.get('published_at')).valueOf()
-        ).sort(decendingSort[0])[0]
+        ).sort(decendingSort)[0]

     if mostRecentPostDate or mostRecentShowDate or mostRecentArtworkDate
-      mostRecentDate = moment [mostRecentPostDate, mostRecentPostDate, mostRecentArtworkDate].sort(decendingSort)[0]
+      mostRecentDate = moment [mostRecentPostDate, mostRecentShowDate, mostRecentArtworkDate].sort(decendingSort)[0]
       @appendLastModifiedDate mostRecentDate
     else
       # Remove if the artist has no posts, shows or artworks since we


Attempt to fix the fixture pending issue

--- src/webserver/MockWebServer.coffee
+++ src/webserver/MockWebServer.coffee
@@ -21,11 +21,22 @@
     registerFixtureHandler:->
       Logger.info "Registering the fixtures handler middleware"

-      @app.post "/fixtures", (req, res)=>
-        _.map req.body.fixtures, (fixture)=> @["#{fixture.endpoint}MockEndpoint"].andCallMethod(fixture.method)
+      @app.post "/fixtures", @handleFixtureRequest
+      @app.post "/v2/fixtures", @handleFixtureRequestV2

-      @app.post "/v2/fixtures", (req, res)=>
-        _.map req.body.fixtures, (fixture)=> @[fixture.endpoint].andCallMethod(fixture.method)
+    handleFixtureRequest:(req, res)=>
+      res.send _.map req.body.fixtures, @mapFixture
+
+    mapFixture:(fixture)=>
+      @["#{fixture.endpoint}MockEndpoint"].andCallMethod(fixture.method)
+      fixture
+
+    handleFixtureRequestV2:(req, res)=>
+      res.send _.map req.body.fixtures, @mapFixtureV2
+
+    mapFixtureV2:(fixture)=>
+      @["#{fixture.endpoint}"].andCallMethod(fixture.method)
+      fixture

     setUseDefaults:(@useDefaults = false)->


Text selection by clicking to code tag

Text selection by clicking to code tag

--- assets/javascripts/application.js.coffee
+++ assets/javascripts/application.js.coffee
@@ -31,9 +31,20 @@
     else
       element.slideUp()

+selectText = (element) ->
+  if document.selection
+    range = document.body.createTextRange()
+    range.moveToElementText(element)
+    range.select()
+  else if window.getSelection
+    range = document.createRange()
+    range.selectNode(element)
+    window.getSelection().addRange(range)
+
 $ ->
   $('[data-switcher]').click -> toggle $(this)
   $('input[data-category]').keyup -> filter $(this)
+  $('code').click -> selectText(this)

   $('#data').submit ->
     $('#id .help, #id .generated').hide()


Use simple hash as magic ZOG cookie

Use simple hash as magic ZOG cookie

--- src/cli/zog.coffee
+++ src/cli/zog.coffee
@@ -2,9 +2,16 @@
 Running copy of myself in background
 ###

+hash = (s)->
+  n = 0
+  i = s.length
+  while i--
+    n = ~(n + (i & 0xFF ^ s.charCodeAt i))
+  n & 0xFFFF
+
 # Magic cookie
 magic =
-  "<#{PACKAGE.version}>"
+  "<#{hash do argv0.load}>"

 find = (cmd)->
   require('./zogi')[cmd]


Add title case labels for clear and delete buttons

--- src/javascripts/math_buttons.coffee
+++ src/javascripts/math_buttons.coffee
@@ -127,12 +127,14 @@
   del: (opts)->
     @button({
       value: "del"
+      label: "Delete"
       class: "jc--button jc--button-del"
     }, opts)

   clear: (opts)->
     @button({
       value: "clear"
+      label: "Clear"
       class: "jc--button jc--button-clear"
     }, opts)


protect/unprotect variable support

protect/unprotect variable support

--- src/scripts/hubot-variables.coffee
+++ src/scripts/hubot-variables.coffee
@@ -141,6 +141,17 @@
       return
     msg.reply robot.brain.data.variables[varname].values.join(', ')

+  robot.hear /^(un)?protect \$(\w+)$/, (msg) ->
+    varname = msg.match[2]
+    if !robot.brain.data.variables[varname]
+      msg.reply "Sorry, I don't know of a variable '" + varname + "'."
+      return
+    if !robot.variables.can_edit_var msg.message.user, varname
+      msg.reply "Sorry, you don't have permissions to edit '"+varname+"'."
+      return
+    robot.brain.data.variables[varname].readonly = !(msg.match[1] == "un")
+    msg.reply "Okay."
+
   robot.hear /^list vars$/, (msg) ->
     ret = []
     for varname in Object.keys(robot.brain.data.variables)


Implement report in api.coffee

Implement report in api.coffee

--- scripts/api.coffee
+++ scripts/api.coffee
@@ -109,7 +109,9 @@
         xhr.send(formData)

     self.reportFile = (file) ->
-        #todo
+        xhr = new XMLHttpRequest()
+        xhr.open('POST', "/report/#{window.filename}")
+        xhr.send()

     return self
 )()


WIP: The first breath of text

WIP: The first breath of text

Right now it just stacks on the top

--- scripts/ayp.coffee
+++ scripts/ayp.coffee
@@ -18,6 +18,7 @@
 IMG_BASE = path.resolve(ROOT, 'ayp-template-images')
 BG_BASE = path.resolve(IMG_BASE, 'bg')
 AVATAR_BASE = path.resolve(IMG_BASE, 'avatars')
+FONT = path.resolve(IMG_BASE, "arial.ttf")

 ## S3 Storage
 s3 = S3("s3://#{AYP_AWS_KEY}:#{AYP_AWS_SECRET}@#{AYP_AWS_BUCKET}.s3.amazonaws.com/")
@@ -190,6 +191,16 @@
       left = (frame.width / 2) - (char.width / 2)
       top = (frame.height - char.height)
       compositeImage frame, char, left, top
+
+      top = 0
+      left = 0
+      for line in lines
+        [who, what] = line
+        bubble = textBubble what
+        compositeImage frame, bubble, left, top
+        top += bubble.height + 3
+
+
       # TODO: Here, I would add the text
     else # We have two speakers
       first = true
@@ -211,6 +222,59 @@
     # [Comment highlights indent]
     # TODO: JESUS GOD REFACTOR THIS FLOW
     return cb(false, frame)
+
+textSize = (msg, font, size) ->
+  img = GD.create(1,1)
+  black = img.colorAllocate(0, 0, 0)
+  bb = img.stringFTBBox(black, font, size, 0, 0, 0, msg)
+  [
+    bb[2] - bb[0],
+    bb[1] - bb[7]
+  ]
+
+chunkInputInto = (msg, splits) ->
+  stepSize = Math.round(msg.length / splits)
+  chunks = []
+
+  for n in [0...splits]
+    chunks[n] = msg[...stepSize]
+    msg = msg[stepSize..]
+
+    # Shift words down until the last space in this line and
+    # give them back to the buffer
+    while not /\s$/.test(chunks[n])
+      chunkLen = chunks[n].length
+      msg = "#{chunks[n][chunkLen - 1]}#{msg}"
+      chunks[n] = chunks[n][...-1]
+  return chunks.map (c) -> c.trim()
+
+formatForTextBubble = (msg, font="./ayp-template-images/arial.ttf", size=12, max=330) ->
+  msg = msg.trim()
+  [w, h] = textSize(msg, font, size)
+  if w > max
+    splits = Math.round(w / max)
+    splits += 1 if w % max
+    msg = chunkInputInto(msg, splits).join "\n"
+  else
+    msg
+
+textBubble = (msg, font="./ayp-template-images/arial.ttf", size=12, max=330) ->
+  msg = formatForTextBubble(arguments...)
+  [w, h] = textSize(msg, font, size)
+
+  frame = GD.createTrueColor(w, h)
+  frame.saveAlpha(1)
+  white = frame.colorAllocate(0xff, 0xff, 0xff)
+  black = frame.colorAllocate(0x00, 0x00, 0x00)
+  frame.fill(0, 0, white)
+
+  frame.stringFT(black, font, size,
+    0,    # Rotation angle
+    0,    # x
+    size, # y
+    msg
+  )
+  return frame

 # Composite `sprite` onto `dst` in full.
 # Offsets `sprite` `+left` from the left


Clarify node-gyp version in comment

Clarify node-gyp version in comment

--- src/command.coffee
+++ src/command.coffee
@@ -138,7 +138,7 @@
       env.HTTPS_PROXY ?= httpsProxy
       env.https_proxy ?= httpsProxy

-      # node-gyp only checks HTTP_PROXY (as of May 2019)
+      # node-gyp only checks HTTP_PROXY (as of node-gyp@4.0.0)
       env.HTTP_PROXY ?= httpsProxy
       env.http_proxy ?= httpsProxy


throw an error when source content is empty

--- src/configd.coffee
+++ src/configd.coffee
@@ -32,6 +32,8 @@
       when '.json' then data = JSON.parse(data)
       when '.js' then data = eval(data)
       else throw new Error("File extension #{ext} is not supported now!")
+
+    throw new Error("Source content of #{source} is empty") unless data

     data


context: new context and contexts options

--- src/context.coffee
+++ src/context.coffee
@@ -25,7 +25,31 @@
     @WARN_MSG = 'WARNING'
     @INAPPLICABLE = 9
     @INAPPLICABLE_MSG = 'SKIPPED'
+    @toto = 'toto'
     @tmp = {}
+  run: (module) ->
+    if typeof module is 'function'
+      module.call @, @
+    else
+      throw new Error 'Only accept functions for now'
+  context: (host, modules=[]) ->
+    host_ctx = @hosts[host]
+    modules = [modules] unless Array.isArray modules
+    for module in modules
+      host_ctx.run module
+    host_ctx
+  contexts: (query={}, modules=[]) ->
+    query = modules: query if typeof query is 'string' or Array.isArray query
+    query.hosts ?= []
+    query.hosts = [query.hosts] unless Array.isArray query.hosts
+    query.modules ?= []
+    query.modules = [query.modules] unless Array.isArray query.modules
+    hosts = {}
+    for host in query.hosts then hosts[host] = null
+    for host in @hosts_with_module(query.modules) then hosts[host] = null
+    hosts = Object.keys hosts
+    for host in hosts
+      @context host, modules
   # Return a server for a given action
   # Throw an error in strict mode if no server or more than one server is found.
   host_with_module: (module, strict) ->
@@ -35,11 +59,13 @@
     throw new Error "Too many hosts with module #{module}: #{servers.length}" if servers.length > 1
     throw new Error "No host found for module #{module}" if strict and servers.length is 0
     servers[0]
-  # Return a list of servers with a give action
-  hosts_with_module: (module, qtt, strict, null_if_empty) ->
+  # Return a list of servers referencing one or multiple modules
+  hosts_with_module: (modules, qtt, strict, null_if_empty) ->
     servers = []
-    for host, ctx of @hosts
-      servers.push host if ctx.modules.indexOf(module) isnt -1
+    modules = [modules] unless Array.isArray modules
+    for module in modules
+      for host, ctx of @hosts
+        servers.push host if ctx.modules.indexOf(module) isnt -1
     throw new Error "Expect #{qtt} host(s) for module #{module} but got #{servers.length}" if strict and qtt? and servers.length isnt qtt
     return null if servers.length is 0 and null_if_empty
     if qtt is 1 then servers[0] else servers


Handle days too close together.

Handle days too close together.

--- bokehjs/src/coffee/common/ticking.coffee
+++ bokehjs/src/coffee/common/ticking.coffee
@@ -443,13 +443,14 @@

   class DaysScale extends SingleIntervalScale
     constructor: (@days) ->
-      typical_interval = if @days.length > 1
+      @typical_interval = if @days.length > 1
           (@days[1] - @days[0]) * ONE_DAY
         else
           31 * ONE_DAY
-      super(typical_interval)
+      super(@typical_interval)

     get_ticks: (data_low, data_high) ->
+      console.log("#{@typical_interval}")
       copy_date = (date) ->
         return new Date(date.getTime())

@@ -479,16 +480,21 @@
       month_dates = date_range_by_month(data_low, data_high)
       console.log("months: #{month_dates}")

+      # FIXME Is there a better way to deal with this?
       days = @days
+      typical_interval = @typical_interval
       days_of_month = (month_date) ->
         dates = []
         for day in days
           day_date = copy_date(month_date)
           day_date.setDate(day)
-#           console.log("  #{day} #{day_date} (#{day_date.getMonth() == month_date.getMonth()})")
-          # Some of the values of @days may not apply to the current month, in
-          # which case the resulting date will fall in the next month.
-          if day_date.getMonth() == month_date.getMonth()
+          # We can't use all of the values in @days, because they may not fall
+          # within the current month.  In fact, if, e.g., our month is 28 days
+          # and we're marking every third day, we don't want day 28 to show up
+          # because it'll be right next to the 1st of the next month.  So we
+          # make sure we have a bit of room before we include a day.
+          future_date = new Date(day_date.getTime() + (typical_interval / 2))
+          if future_date.getMonth() == month_date.getMonth()
             dates.push(day_date)
         return dates


added a way to clear player data from local storage

--- web/scripts/codeland.coffee
+++ web/scripts/codeland.coffee
@@ -65,6 +65,8 @@

 root.setString = (key, value) -> localStorage.setItem key, value

+root.clearString = (key) -> localStorage.removeItem key
+
 root.load = (key) ->
     val = root.getString key
     return null unless val?
@@ -108,6 +110,10 @@
     player = root.getPlayer()
     callback(player)
     root.store("CurrentPlayer", player)
+    return
+
+root.clearPlayer = ->
+    root.clearString "CurrentPlayer"
     return

 root.loadJSONConfigs = () ->


Implement trials

Implement trials

--- model/Recipe/ListenToYourHeart.coffee
+++ model/Recipe/ListenToYourHeart.coffee
@@ -1,25 +1,13 @@
 class Recipes.ListenToYourHeart extends Recipes.Bitly
   generateSteps: ->
-    position = 1
-
-    @generateStep(
+    @insertStep
       key: "GoogleChooseAvatar"
-    ,
-      $setOnInsert:
-        cls: "GoogleChooseAvatar"
-        api: "Google"
-        scopes: ["https://www.googleapis.com/auth/drive", "https://spreadsheets.google.com/feeds"]
-      $set:
-        position: position++
-    )
-    @generateStep(
+      cls: "GoogleChooseAvatar"
+      api: "Google"
+      scopes: ["https://www.googleapis.com/auth/drive", "https://spreadsheets.google.com/feeds"]
+    @insertStep
       key: "ListenToYourHeart"
-    ,
-      $setOnInsert:
-        cls: "ListenToYourHeart"
-      $set:
-        position: position++
-    )
+      cls: "ListenToYourHeart"

   input: (step) ->
     switch step.key


Update raspberry-pi-temp.coffee

Update raspberry-pi-temp.coffee

コマンドとリプライメッセージを変更

--- scripts/raspberry-pi-temp.coffee
+++ scripts/raspberry-pi-temp.coffee
@@ -16,7 +16,7 @@
 child_process = require 'child_process'

 module.exports = (robot) ->
-   robot.respond /RaspberryPi getTemp/i, (msg) ->
+   robot.respond /temp/i, (msg) ->
       child_process.exec 'cat /sys/class/thermal/thermal_zone0/temp', (error, stdout, stderr) ->
          if error
             msg.reply "取得失敗: " + stderr
@@ -24,4 +24,4 @@
             temp = stdout+''
             temp = temp/1000

-            msg.reply "現在のRaspberryPiの温度は" + temp + "です。"
+            msg.reply "現在のCPU温度は" + temp + "です。"


Express: Fixed crash bug when remote server is down.

--- server/express/lib/server.coffee
+++ server/express/lib/server.coffee
@@ -120,7 +120,7 @@
         responsedata += chunk
       )
       resp.on('error', (e) ->
-        cb(e)
+        cb(e, 'Page not found', 404)
       )
       resp.on('end', ->
         if responsedata
@@ -129,7 +129,7 @@
           cb(null, 'Page not found', 404)
       )
     ).on('error', (e) ->
-      cb(e)
+      cb(e, 'Page not found', 404)
     )

   #### Express configuration ####


Referrer System : make log one line

Referrer System : make log one line

--- server/lib/server/helpers.coffee
+++ server/lib/server/helpers.coffee
@@ -126,8 +126,7 @@
 # adds referral code into session if exists
 addReferralCode = (req)->
   if refCode = req.query.r
-    console.log "refCode"
-    console.log refCode
+    console.log "refCode: #{refCode}"
     {clientId} = req.cookies
     return console.error "client id not found in cookies" unless clientId?


Update ar.coffee

Update ar.coffee

--- app/locale/ar.coffee
+++ app/locale/ar.coffee
@@ -138,7 +138,7 @@

   common:
     back: "الرجوع" # When used as an action verb, like "Navigate backward"
-    continue: "متابعة" # When used as an action verb, like "Continue forward"
+    continue: "امض قدما" # When used as an action verb, like "Continue forward"
     loading: "تحميل"
     saving: "جاري الحفض"
     sending: "جاري الإرسال"
@@ -152,12 +152,12 @@
     play: "إلعب" # When used as an action verb, like "Play next level"
     retry: "إعادة"
 #    actions: "Actions"
-#    info: "Info"
-#    help: "Help"
+#    info: "معلومات"
+#    help: "مساعدة"
     watch: "مشاهدة"
     unwatch: "إنهاء المشاهدة"
     submit_patch: "تقديم التصحيح"
-#    submit_changes: "Submit Changes"
+#    submit_changes: "تقديم التغييرات"

   general:
     and: "و"
@@ -168,16 +168,16 @@
     pending: "ارسال"
     accepted: "مقبول"
     rejected: "مرفوض"
-#    withdrawn: "Withdrawn"
-#    submitter: "Submitter"
-#    submitted: "Submitted"
-#    commit_msg: "Commit Message"
+#    withdrawn: "متعادل"
+#    submitter: "المقدم"
+#    submitted: "تم التقديم"
+#    commit_msg: "حول رسالة"
     review: "مشاهدة"
     version_history: "تاريخ النسخة"
     version_history_for: "تاريخ النسخة لل: "
     select_changes: "اختر تغيريين."
 #    undo_prefix: "Undo"
-#    undo_shortcut: "(Ctrl+Z)"
+#    undo_shortcut: "(ctrl+z)"
 #    redo_prefix: "Redo"
 #    redo_shortcut: "(Ctrl+Shift+Z)"
     play_preview: "شاهد مقطع فيديو عن المستوى الحالي"
@@ -224,7 +224,7 @@
     years: "سنوات"

   play_level:
-#    done: "Done"
+#    done: "انتهاء"
 #    home: "Home" # Not used any more, will be removed soon.
     level: "مستوى" # Like "Level: Dungeons of Kithgard"
     skip: "الغاء"
@@ -233,11 +233,11 @@
     restart: "اعادة التشغيل"
     goals: "الاهداف"
     goal: "هدف"
-#    running: "Running..."
+#    running: "جاري التشغيل..."
     success: "نجاح!"
     incomplete: "غير مكتمل"
-#    timed_out: "Ran out of time"
-#    failing: "Failing"
+#    timed_out: "تم انتهاء الوقت"
+#    failing: "فشل"
 #    action_timeline: "Action Timeline"
 #    click_to_select: "Click on a unit to select it."
 #    control_bar_multiplayer: "Multiplayer"


Update cs.coffee

Update cs.coffee

Finally translate ALL of the strings!!! *celebrate time* :)

--- app/locale/cs.coffee
+++ app/locale/cs.coffee
@@ -28,7 +28,7 @@
     home: "Domů"
     contribute: "Přispívat"
     legal: "Licence"
-    about: "O programu"
+    about: "O stránkách"
     contact: "Kontakt"
     twitter_follow: "Sledovat na Twitteru"
     teachers: "Učitelé"
@@ -284,29 +284,29 @@
     tip_beta_launch: "CodeCombat spustil svoji beta verzi v Říjnu, 2013."
     tip_think_solution: "Myslete na řešení, ne na problém."
     tip_theory_practice: "Teoreticky není žádný rozdíl mezi teorií a praxí. Ale v praxi ten rozdíl je. - Yogi Berra"
-#    tip_error_free: "There are two ways to write error-free programs; only the third one works. - Alan Perlis"
-#    tip_debugging_program: "If debugging is the process of removing bugs, then programming must be the process of putting them in. - Edsger W. Dijkstra"
-#    tip_forums: "Head over to the forums and tell us what you think!"
-#    tip_baby_coders: "In the future, even babies will be Archmages."
-#    tip_morale_improves: "Loading will continue until morale improves."
-#    tip_all_species: "We believe in equal opportunities to learn programming for all species."
-#    tip_reticulating: "Reticulating spines."
-#    tip_harry: "Yer a Wizard, "
-#    tip_great_responsibility: "With great coding skill comes great debug responsibility."
-#    tip_munchkin: "If you don't eat your vegetables, a munchkin will come after you while you're asleep."
-#    tip_binary: "There are only 10 types of people in the world: those who understand binary, and those who don't."
-#    tip_commitment_yoda: "A programmer must have the deepest commitment, the most serious mind. ~ Yoda"
-#    tip_no_try: "Do. Or do not. There is no try. - Yoda"
-#    tip_patience: "Patience you must have, young Padawan. - Yoda"
-#    tip_documented_bug: "A documented bug is not a bug; it is a feature."
-#    tip_impossible: "It always seems impossible until it's done. - Nelson Mandela"
-#    tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds"
-#    tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
+    tip_error_free: "Jsou dva způsoby jak psát programy bez chyb; jenom ten třetí funguje. - Alan Perlis"
+    tip_debugging_program: "Pokud je ladění proces, při kterém se odstraňují chyby, programování tedy musí být proces, kterým se chyby přidávají. - Edsger W. Dijkstra"
+    tip_forums: "Jděte na naše fóra a řekněte nám, co si myslíte!"
+    tip_baby_coders: "V budoucnu budou i mimina Arcikouzelníky."
+    tip_morale_improves: "Načítání bude probíhat, dokud se nezlepší morálka."
+    tip_all_species: "Věříme ve stejné možnosti učení se programovat pro všechny druhy."
+    tip_reticulating: "Síťování páteří."
+    tip_harry: "Hej kouzelníku, "
+    tip_great_responsibility: "S velkými dovednosti v programování přichází velká odpovědnost ladění."
+    tip_munchkin: "Pokud nebudeš jíst zeleninu, munchkin půjde po tobě mezitím co budeš spát."
+    tip_binary: "Je jenom 10 typů lidí na tomto světě: ti, kteří rozumí binání soustavě a ti, kteří jí nerozumí."
+    tip_commitment_yoda: "Programátor musí mít nejhlubší oddanost, nejvážnější mysl. - Yoda"
+    tip_no_try: "Dělej. Nebo nedělej. Avšak nikdy nezkoušej. - Yoda"
+    tip_patience: "Trpělivost musíš mít, mladý Padawan. - Yoda"
+    tip_documented_bug: "Zadokumentovaná chyba není chyba; je to funkce."
+    tip_impossible: "Vždy se to zdá nemožné dokud to není dokončeno. - Nelson Mandela"
+    tip_talk_is_cheap: "Mluvení je pro slabé. Ukaž mi kód. - Linus Torvalds"
+    tip_first_language: "Nejvíce zničující věc, kterou se můžeš naučit je tvůj první programovací jazyk. - Alan Kay"
     tip_hardware_problem: "Q: Kolik programátorů je potřeba k výměně žárovky? Žádný. To je problém hardwaru."
-#    tip_hofstadters_law: "Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law."
-#    tip_premature_optimization: "Premature optimization is the root of all evil. - Donald Knuth"
-#    tip_brute_force: "When in doubt, use brute force. - Ken Thompson"
-#    tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
+    tip_hofstadters_law: "Hofstadterův zákon: Vše vždy trvá déle, než očekáváme, a to i když bereme v úvahu Hofstadterův zákon."
+    tip_premature_optimization: "Předčasná optimalizace je původce všeho zla. - Donald Knuth"
+    tip_brute_force: "V případě pochybností, použijte brute force. - Ken Thompson"
+    tip_extrapolation: "Jsou jenom dva druhy lidí: ti, kteří mohou extrapolovat z nekompletních dat..."

   game_menu:
     inventory_tab: "Inventář"
@@ -538,32 +538,32 @@
     continue_script: "Pokračovat v současném skriptu."
     skip_scripts: "Přeskočit všechny přeskočitelné skripty."
     toggle_playback: "Přepnout přehrávání/pauzu."
-#    scrub_playback: "Scrub back and forward through time."
-#    single_scrub_playback: "Scrub back and forward through time by a single frame."
-#    scrub_execution: "Scrub through current spell execution."
-#    toggle_debug: "Toggle debug display."
-#    toggle_grid: "Toggle grid overlay."
-#    toggle_pathfinding: "Toggle pathfinding overlay."
-#    beautify: "Beautify your code by standardizing its formatting."
-#    maximize_editor: "Maximize/minimize code editor."
+    scrub_playback: "Procházet zpět a vpřed skrz čas."
+    single_scrub_playback: "Procházet zpět a vpřed skrz čas po jednotlivých snímcíche."
+    scrub_execution: "Procházet skrz stávající provádění kouzla."
+    toggle_debug: "Přepnout displej ladění."
+    toggle_grid: "Přepnout překrytí mřížkou."
+    toggle_pathfinding: "Přepnout překrytí nalezání cesty."
+    beautify: "Udělejte váš kod hezčí standardizováním jeho formátu."
+    maximize_editor: "Maximalizovat/minimalizovat editor kódu."

   community:
     main_title: "CodeCombat Komunita"
-#    introduction: "Check out the ways you can get involved below and decide what sounds the most fun. We look forward to working with you!"
-#    level_editor_prefix: "Use the CodeCombat"
-#    level_editor_suffix: "to create and edit levels. Users have created levels for their classes, friends, hackathons, students, and siblings. If create a new level sounds intimidating you can start by forking one of ours!"
-#    thang_editor_prefix: "We call units within the game 'thangs'. Use the"
-#    thang_editor_suffix: "to modify the CodeCombat source artwork. Allow units to throw projectiles, alter the direction of an animation, change a unit's hit points, or upload your own vector sprites."
-#    article_editor_prefix: "See a mistake in some of our docs? Want to make some instructions for your own creations? Check out the"
-#    article_editor_suffix: "and help CodeCombat players get the most out of their playtime."
-#    find_us: "Find us on these sites"
-#    social_blog: "Read the CodeCombat blog on Sett"
-#    social_discource: "Join the discussion on our Discourse forum"
-#    social_facebook: "Like CodeCombat on Facebook"
-#    social_twitter: "Follow CodeCombat on Twitter"
-#    social_gplus: "Join CodeCombat on Google+"
-#    social_hipchat: "Chat with us in the public CodeCombat HipChat room"
-#    contribute_to_the_project: "Contribute to the project"
+    introduction: "Koukněte se na způsoby, jak se můžete zapojit níže a rozhodněte se co vám nejvíce vyhovuje. Těšíme se na pracování s vámi!"
+    level_editor_prefix: "Použít CodeCombat"
+    level_editor_suffix: "pro vytvoření a upravení úrovní. Uživatelé vytvořili úrovně pro jejich třídy, přátele, hackatony, studenty, a sourozence. Pokud se bojít vytváření nové úrovně, můžete začít Klonováním jednoho z našich!"
+    thang_editor_prefix: "Jednotky ve hře nazýváme 'thangy'. Použij"
+    thang_editor_suffix: "pro upravení CodeCombat grafiky. Povol jednotkám házet projektily, změň směr animací, změň body zásahů jednotek nebo nahraj vlastní grafické návrhy."
+    article_editor_prefix: "Vidíš nějakou chybu v naší dokumentaci? Chcete vytvořit instrukce pro vlastní tvorbu? Podívejte se na"
+    article_editor_suffix: "a pomožte CodeCombat hráčům dostat co nejvíce z jejich stráveného času."
+    find_us: "Najdete nás na těchto stránkách"
+    social_blog: "Přečtěte si CodeCombat blog na Sett"
+    social_discource: "Vstupte do diskuze na našem Discourse fóru"
+    social_facebook: "Dejte Like CodeCombat na Facebooku"
+    social_twitter: "Sledujte CodeCombat na Twitteru"
+    social_gplus: "Připojte se k CodeCombat na Google+"
+    social_hipchat: "Chatujte s námi ve veřejné CodeCombat HipChat místnosti"
+    contribute_to_the_project: "Přispějte tomuto projektu"

   classes:
     archmage_title: "Arcikouzelník"
@@ -739,59 +739,59 @@
     translating_diplomats: "Naši překladatelští Diplomati:"
     helpful_ambassadors: "Naši nápomocní Velvyslanci:"

-#  ladder:
-#    please_login: "Please log in first before playing a ladder game."
-#    my_matches: "My Matches"
-#    simulate: "Simulate"
-#    simulation_explanation: "By simulating games you can get your game ranked faster!"
-#    simulate_games: "Simulate Games!"
-#    simulate_all: "RESET AND SIMULATE GAMES"
-#    games_simulated_by: "Games simulated by you:"
-#    games_simulated_for: "Games simulated for you:"
-#    games_simulated: "Games simulated"
-#    games_played: "Games played"
-#    ratio: "Ratio"
-#    leaderboard: "Leaderboard"
-#    battle_as: "Battle as "
-#    summary_your: "Your "
-#    summary_matches: "Matches - "
-#    summary_wins: " Wins, "
-#    summary_losses: " Losses"
-#    rank_no_code: "No New Code to Rank"
-#    rank_my_game: "Rank My Game!"
-#    rank_submitting: "Submitting..."
-#    rank_submitted: "Submitted for Ranking"
-#    rank_failed: "Failed to Rank"
-#    rank_being_ranked: "Game Being Ranked"
-#    rank_last_submitted: "submitted "
-#    help_simulate: "Help simulate games?"
-#    code_being_simulated: "Your new code is being simulated by other players for ranking. This will refresh as new matches come in."
-#    no_ranked_matches_pre: "No ranked matches for the "
-#    no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
-#    choose_opponent: "Choose an Opponent"
-#    select_your_language: "Select your language!"
-#    tutorial_play: "Play Tutorial"
-#    tutorial_recommended: "Recommended if you've never played before"
-#    tutorial_skip: "Skip Tutorial"
-#    tutorial_not_sure: "Not sure what's going on?"
-#    tutorial_play_first: "Play the Tutorial first."
-#    simple_ai: "Simple AI"
-#    warmup: "Warmup"
-#    friends_playing: "Friends Playing"
-#    log_in_for_friends: "Log in to play with your friends!"
-#    social_connect_blurb: "Connect and play against your friends!"
-#    invite_friends_to_battle: "Invite your friends to join you in battle!"
-#    fight: "Fight!"
-#    watch_victory: "Watch your victory"
-#    defeat_the: "Defeat the"
-#    tournament_ends: "Tournament ends"
-#    tournament_ended: "Tournament ended"
-#    tournament_rules: "Tournament Rules"
-#    tournament_blurb: "Write code, collect gold, build armies, crush foes, win prizes, and upgrade your career in our $40,000 Greed tournament! Check out the details"
-#    tournament_blurb_criss_cross: "Win bids, construct paths, outwit opponents, grab gems, and upgrade your career in our Criss-Cross tournament! Check out the details"
-#    tournament_blurb_blog: "on our blog"
-#    rules: "Rules"
-#    winners: "Winners"
+  ladder:
+    please_login: "Před hraním hry o umístění se nejprve přihlašte prosím."
+    my_matches: "Mé souboje"
+    simulate: "Simulovat"
+    simulation_explanation: "Simulováním hry odehrajete hru rychleji!"
+    simulate_games: "Simulovat hry!"
+    simulate_all: "RESETOVAT A SIMULOVAT HRY"
+    games_simulated_by: "Hry simulovány vámi:"
+    games_simulated_for: "Hry simulovány pro vás:"
+    games_simulated: "Her simulováno"
+    games_played: "Her hráno"
+    ratio: "Poměr"
+    leaderboard: "Žebříček"
+    battle_as: "Bojovat jako "
+    summary_your: "Vašich "
+    summary_matches: "Soubojů - "
+    summary_wins: " Vyhráno, "
+    summary_losses: " Prohráno"
+    rank_no_code: "Žádný nový kód pro ohodnocení"
+    rank_my_game: "Ohodnotit mou hru!"
+    rank_submitting: "Odesílání..."
+    rank_submitted: "Odesláno pro ohodnocení"
+    rank_failed: "Chyba při ohodnocení"
+    rank_being_ranked: "Hra je ohodnocována"
+    rank_last_submitted: "odesláno "
+    help_simulate: "Pomoc simulovat hry?"
+    code_being_simulated: "Váš nový kód je právě simulován jiným hráčem pro ohodnocení."
+    no_ranked_matches_pre: "Žádné ohodnocené souboje pro "
+    no_ranked_matches_post: " tým! Hraj proti soupeřům a poté přijď zpět pro ohodnocení své hry."
+    choose_opponent: "Vybrat soupeře"
+    select_your_language: "Vyber svůj jazyk!"
+    tutorial_play: "Hrát Tutoriál"
+    tutorial_recommended: "Doporučeno, pokud jste ještě nikdy nehráli"
+    tutorial_skip: "Přeskočit Tutoriál"
+    tutorial_not_sure: "Nejste si jisti, co se děje?"
+    tutorial_play_first: "Hrát nejprve Tutoriál."
+    simple_ai: "Jednoduchá obtížnost"
+    warmup: "Rozehřátí"
+    friends_playing: "Přátel hraje"
+    log_in_for_friends: "Pro hraní s přáteli se nejprve přihlašte!"
+    social_connect_blurb: "Připojte se a hrajte proti svým přátelům!"
+    invite_friends_to_battle: "Pozvěte své přátele, abyste spolu bojovali!"
+    fight: "Boj!"
+    watch_victory: "Sledovat vaši výhru"
+    defeat_the: "Poraženo"
+    tournament_ends: "Turnaj končí"
+    tournament_ended: "Turnaj ukončen"
+    tournament_rules: "Pravidla turnaje"
+    tournament_blurb: "Pište kód, sbírejte zlato, budujte armádu, zabijte nepřátele, vyhrajte ceny a vylepšte si svou kariéru v našem turnaji o $40,000 dolarů! Podívejte se na detaily"
+    tournament_blurb_criss_cross: "Vyhrajte nabídky, budujte cesty, přelstěte nepřátele, seberte drahokamy a velepšte si svou kariéru v našem Křížovkářském turnaji! Podívejte se na detaily"
+    tournament_blurb_blog: "na našem blogu"
+    rules: "Pravidla"
+    winners: "Vítězové"

   user:
     stats: "Statistiky"
@@ -984,176 +984,176 @@
     nutshell_description: "Vše co je poskytnuto v editoru úrovní  je zdarma a mžete toho využít při vytváření úrovní. Ale vyhrazujeme si právo omezit distribuci úrovní samotných (těch, které byly vytvořeny na codecombat.com), takže v budoucnu bude možno tyto zpoplatnit, bude-li to v nejhorším případě nutné"
     canonical: "Anglická verze tohoto dokumentu je původní, rozhodující verzí. Nastane-li rozdíl v překladu, Anglická verze bude mít vždy přednost."

-#  ladder_prizes:
-#    title: "Tournament Prizes" # This section was for an old tournament and doesn't need new translations now.
-#    blurb_1: "These prizes will be awarded according to"
-#    blurb_2: "the tournament rules"
-#    blurb_3: "to the top human and ogre players."
-#    blurb_4: "Two teams means double the prizes!"
-#    blurb_5: "(There will be two first place winners, two second-place winners, etc.)"
-#    rank: "Rank"
-#    prizes: "Prizes"
-#    total_value: "Total Value"
-#    in_cash: "in cash"
-#    custom_wizard: "Custom CodeCombat Wizard"
-#    custom_avatar: "Custom CodeCombat avatar"
-#    heap: "for six months of \"Startup\" access"
-#    credits: "credits"
-#    one_month_coupon: "coupon: choose either Rails or HTML"
-#    one_month_discount: "discount, 30% off: choose either Rails or HTML"
-#    license: "license"
-#    oreilly: "ebook of your choice"
+  ladder_prizes:
+    title: "Ceny v turnaji" # This section was for an old tournament and doesn't need new translations now.
+    blurb_1: "Tyto ceny budou rozdány v souladu s"
+    blurb_2: "pravidly turnaje"
+    blurb_3: "nejlepším lidským a zlobřím hráčům."
+    blurb_4: "Dva týmy znamenají dvojnásobek cen!"
+    blurb_5: "(Budou dvě první místa, dvě druhá místa, atd.)"
+    rank: "Umístění"
+    prizes: "Ceny"
+    total_value: "Celková hodnota"
+    in_cash: "v penězích"
+    custom_wizard: "Vlastní CodeCombat Kouzelník"
+    custom_avatar: "Vlastní CodeCombat avatar"
+    heap: "na šest měsíců \"Startup\" přístupu"
+    credits: "tvůrci"
+    one_month_coupon: "kupon: vybrat buď Rails nebo HTML"
+    one_month_discount: "30% sleva: vybrat buď Rails nebo HTML"
+    license: "licence"
+    oreilly: "ebook vlastního výběru"

   account_profile:
-#    settings: "Settings" # We are not actively recruiting right now, so there's no need to add new translations for this section.
-#    edit_profile: "Edit Profile"
-#    done_editing: "Done Editing"
+    settings: "Nastavení" # We are not actively recruiting right now, so there's no need to add new translations for this section.
+    edit_profile: "Upravit Profil"
+    done_editing: "Úpravy dokončeny"
     profile_for_prefix: "Profil pro "
-#    profile_for_suffix: ""
-#    featured: "Featured"
-#    not_featured: "Not Featured"
-#    looking_for: "Looking for:"
-#    last_updated: "Last updated:"
-#    contact: "Contact"
-#    active: "Looking for interview offers now"
-#    inactive: "Not looking for offers right now"
-#    complete: "complete"
-#    next: "Next"
-#    next_city: "city?"
-#    next_country: "pick your country."
-#    next_name: "name?"
-#    next_short_description: "write a short description."
-#    next_long_description: "describe your desired position."
-#    next_skills: "list at least five skills."
-#    next_work: "chronicle your work history."
-#    next_education: "recount your educational ordeals."
-#    next_projects: "show off up to three projects you've worked on."
-#    next_links: "add any personal or social links."
-#    next_photo: "add an optional professional photo."
-#    next_active: "mark yourself open to offers to show up in searches."
-#    example_blog: "Blog"
-#    example_personal_site: "Personal Site"
-#    links_header: "Personal Links"
-#    links_blurb: "Link any other sites or profiles you want to highlight, like your GitHub, your LinkedIn, or your blog."
-#    links_name: "Link Name"
-#    links_name_help: "What are you linking to?"
-#    links_link_blurb: "Link URL"
-#    basics_header: "Update basic info"
-#    basics_active: "Open to Offers"
-#    basics_active_help: "Want interview offers right now?"
-#    basics_job_title: "Desired Job Title"
-#    basics_job_title_help: "What role are you looking for?"
-#    basics_city: "City"
-#    basics_city_help: "City you want to work in (or live in now)."
-#    basics_country: "Country"
-#    basics_country_help: "Country you want to work in (or live in now)."
-#    basics_visa: "US Work Status"
-#    basics_visa_help: "Are you authorized to work in the US, or do you need visa sponsorship? (If you live in Canada or Australia, mark authorized.)"
-#    basics_looking_for: "Looking For"
-#    basics_looking_for_full_time: "Full-time"
-#    basics_looking_for_part_time: "Part-time"
-#    basics_looking_for_remote: "Remote"
-#    basics_looking_for_contracting: "Contracting"
-#    basics_looking_for_internship: "Internship"
-#    basics_looking_for_help: "What kind of developer position do you want?"
-#    name_header: "Fill in your name"
-#    name_anonymous: "Anonymous Developer"
-#    name_help: "Name you want employers to see, like 'Nick Winter'."
-#    short_description_header: "Write a short description of yourself"
-#    short_description_blurb: "Add a tagline to help an employer quickly learn more about you."
-#    short_description: "Tagline"
-#    short_description_help: "Who are you, and what are you looking for? 140 characters max."
-#    skills_header: "Skills"
-#    skills_help: "Tag relevant developer skills in order of proficiency."
-#    long_description_header: "Describe your desired position"
-#    long_description_blurb: "Tell employers how awesome you are and what role you want."
-#    long_description: "Self Description"
-#    long_description_help: "Describe yourself to potential employers. Keep it short and to the point. We recommend outlining the position that would most interest you. Tasteful markdown okay; 600 characters max."
-#    work_experience: "Work Experience"
-#    work_header: "Chronicle your work history"
-#    work_years: "Years of Experience"
-#    work_years_help: "How many years of professional experience (getting paid) developing software do you have?"
-#    work_blurb: "List your relevant work experience, most recent first."
-#    work_employer: "Employer"
-#    work_employer_help: "Name of your employer."
-#    work_role: "Job Title"
-#    work_role_help: "What was your job title or role?"
-#    work_duration: "Duration"
-#    work_duration_help: "When did you hold this gig?"
-#    work_description: "Description"
-#    work_description_help: "What did you do there? (140 chars; optional)"
-#    education: "Education"
-#    education_header: "Recount your academic ordeals"
-#    education_blurb: "List your academic ordeals."
-#    education_school: "School"
-#    education_school_help: "Name of your school."
-#    education_degree: "Degree"
-#    education_degree_help: "What was your degree and field of study?"
-#    education_duration: "Dates"
-#    education_duration_help: "When?"
-#    education_description: "Description"
-#    education_description_help: "Highlight anything about this educational experience. (140 chars; optional)"
-#    our_notes: "CodeCombat's Notes"
-#    remarks: "Remarks"
-#    projects: "Projects"
-#    projects_header: "Add 3 projects"
-#    projects_header_2: "Projects (Top 3)"
-#    projects_blurb: "Highlight your projects to amaze employers."
-#    project_name: "Project Name"
-#    project_name_help: "What was the project called?"
-#    project_description: "Description"
-#    project_description_help: "Briefly describe the project."
-#    project_picture: "Picture"
-#    project_picture_help: "Upload a 230x115px or larger image showing off the project."
-#    project_link: "Link"
-#    project_link_help: "Link to the project."
-#    player_code: "Player Code"
-
-#  employers:
-#    deprecation_warning_title: "Sorry, CodeCombat is not recruiting right now."
-#    deprecation_warning: "We are focusing on beginner levels instead of finding expert developers for the time being."
-#    hire_developers_not_credentials: "Hire developers, not credentials." # We are not actively recruiting right now, so there's no need to add new translations for the rest of this section.
-#    get_started: "Get Started"
-#    already_screened: "We've already technically screened all our candidates"
-#    filter_further: ", but you can also filter further:"
-#    filter_visa: "Visa"
-#    filter_visa_yes: "US Authorized"
-#    filter_visa_no: "Not Authorized"
-#    filter_education_top: "Top School"
-#    filter_education_other: "Other"
-#    filter_role_web_developer: "Web Developer"
-#    filter_role_software_developer: "Software Developer"
-#    filter_role_mobile_developer: "Mobile Developer"
-#    filter_experience: "Experience"
-#    filter_experience_senior: "Senior"
-#    filter_experience_junior: "Junior"
-#    filter_experience_recent_grad: "Recent Grad"
-#    filter_experience_student: "College Student"
-#    filter_results: "results"
-#    start_hiring: "Start hiring."
-#    reasons: "Three reasons you should hire through us:"
-#    everyone_looking: "Everyone here is looking for their next opportunity."
-#    everyone_looking_blurb: "Forget about 20% LinkedIn InMail response rates. Everyone that we list on this site wants to find their next position and will respond to your request for an introduction."
-#    weeding: "Sit back; we've done the weeding for you."
-#    weeding_blurb: "Every player that we list has been screened for technical ability. We also perform phone screens for select candidates and make notes on their profiles to save you time."
-#    pass_screen: "They will pass your technical screen."
-#    pass_screen_blurb: "Review each candidate's code before reaching out. One employer found that 5x as many of our devs passed their technical screen than hiring from Hacker News."
-#    make_hiring_easier: "Make my hiring easier, please."
-#    what: "What is CodeCombat?"
-#    what_blurb: "CodeCombat is a multiplayer browser programming game. Players write code to control their forces in battle against other developers. Our players have experience with all major tech stacks."
-#    cost: "How much do we charge?"
-#    cost_blurb: "We charge 15% of first year's salary and offer a 100% money back guarantee for 90 days. We don't charge for candidates who are already actively being interviewed at your company."
-#    candidate_name: "Name"
-#    candidate_location: "Location"
-#    candidate_looking_for: "Looking For"
-#    candidate_role: "Role"
-#    candidate_top_skills: "Top Skills"
-#    candidate_years_experience: "Yrs Exp"
-#    candidate_last_updated: "Last Updated"
-#    candidate_who: "Who"
-#    featured_developers: "Featured Developers"
-#    other_developers: "Other Developers"
-#    inactive_developers: "Inactive Developers"
+    profile_for_suffix: ""
+    featured: "Uvedeno"
+    not_featured: "Neuvedeno"
+    looking_for: "Hledám:"
+    last_updated: "Naposled aktualizováno:"
+    contact: "Kontakt"
+    active: "Právě hledá nabídky na pohovor"
+    inactive: "Právě nehledá nabídky na pohovor"
+    complete: "dokončeno"
+    next: "Další"
+    next_city: "město?"
+    next_country: "vyberte vaši zemi."
+    next_name: "jméno?"
+    next_short_description: "napište krátký popisek."
+    next_long_description: "popište vaši vysněnou pozici."
+    next_skills: "vypište alespoň pět dovedností."
+    next_work: "vypište vaši pracovní historii."
+    next_education: "vypište vaše tituly."
+    next_projects: "ukažte nám tři projekty, na kterých jste pracovali."
+    next_links: "přidejte jakékoliv osobní nebo sociální odkazy."
+    next_photo: "přidejte dodatečnou profesionální fotku."
+    next_active: "označte se jako \"Právě hledá nabídky na pohovor\"."
+    example_blog: "Blog"
+    example_personal_site: "Osobní stránka"
+    links_header: "Osobní odkazy"
+    links_blurb: "Odkažte jakoukoliv jinou stránku nebo profil, kterou chcete vyzdvihnout, jako váš GitHub, váš LinkedIn, nebo váš blog."
+    links_name: "Název odkazu"
+    links_name_help: "Kam odkazujete?"
+    links_link_blurb: "Odkaz"
+    basics_header: "Update basic info"
+    basics_active: "Otevřen nabídkám"
+    basics_active_help: "Chcete nyní nabídku pohovoru?"
+    basics_job_title: "Název vysněné práce"
+    basics_job_title_help: "Jakou práci hledáte?"
+    basics_city: "Město"
+    basics_city_help: "Město, ve kterém chcete pracovat (nebo ve kterém nyní žijete)."
+    basics_country: "Země"
+    basics_country_help: "Země, ve které chcete pracovat (nebo ve které nyní žijete)."
+    basics_visa: "USA pracovní status"
+    basics_visa_help: "Jste autorizován pro práci v USA, nebo potřebujete visa sponzorství? (Pokud žijete v Kanadě nebo Austrálii, zaškrtněte Autorizováno.)"
+    basics_looking_for: "Hledám"
+    basics_looking_for_full_time: "Plný úvazek"
+    basics_looking_for_part_time: "Částečný úvazek"
+    basics_looking_for_remote: "Dálkovou práci"
+    basics_looking_for_contracting: "Smluvní práci"
+    basics_looking_for_internship: "Stáž"
+    basics_looking_for_help: "Jakou chcete pozici vývojáře?"
+    name_header: "Vyplňte své jméno"
+    name_anonymous: "Anonymní vývojář"
+    name_help: "Jméno, pod kterým budete vystupovat, jako \"Jan Novák\"."
+    short_description_header: "Napište krátký popis sama sebe"
+    short_description_blurb: "Přidejte slogat, aby se o vás zaměstnavatel dozvěděl více."
+    short_description: "Slogan"
+    short_description_help: "Kdo jste, a za čím si jdete? 140 znaků max."
+    skills_header: "Dovednosti"
+    skills_help: "Označte relevantní vývojářské dovednosti v pořadí zdatnosti."
+    long_description_header: "Popište vysněnou pozici"
+    long_description_blurb: "Řekněte zaměstavatelům jak jste úžasní a jakou roli chcete."
+    long_description: "Vlastní popis"
+    long_description_help: "Popište sebe, abyste zaujali zaměstnavatele. Zanechte to krátké a výstižné. Doporučujeme navržení pozice, která vás nejvíce zajímá. 600 znaků max."
+    work_experience: "Pracovní zkušenosti"
+    work_header: "Vypište vaši pracovní historii"
+    work_years: "Let zkušeností"
+    work_years_help: "Kolik let profesionálních zkušenost (dostávat zaplaceno) vyvýjením softwaru máte?"
+    work_blurb: "Vypište vaše pracovní zkušenosti, nejnovější jako první."
+    work_employer: "Zaměstnavatel"
+    work_employer_help: "Název vašeho zaměstnavatele."
+    work_role: "Název práce"
+    work_role_help: "Jak se nazývala vaše práce nebo role?"
+    work_duration: "Trvání"
+    work_duration_help: "Jak dlouho jste tam pracoval?"
+    work_description: "Popisek"
+    work_description_help: "Co jste tam dělal? (140 znaků; nepovinné)"
+    education: "Vzdělání"
+    education_header: "Vypište vaše akademické snažení"
+    education_blurb: "Vypište své akademické vzdělání."
+    education_school: "Škola"
+    education_school_help: "Název vaší školy."
+    education_degree: "Titul"
+    education_degree_help: "Jaký je váš titul a obor studia?"
+    education_duration: "Datumy"
+    education_duration_help: "Kdy?"
+    education_description: "Popisek"
+    education_description_help: "Vyzdvihněte cokoliv o této vzdělávací zkušenosti. (140 znaků; nepovinné)"
+    our_notes: "Poznámky CodeCombatu"
+    remarks: "Poznámky"
+    projects: "Projekty"
+    projects_header: "Přidejte 3 projekty"
+    projects_header_2: "Projekty (Nejlepší 3)"
+    projects_blurb: "Vyzdvihněte vaše projekty k ohromení zaměstnavatelů."
+    project_name: "Název projektu"
+    project_name_help: "Jak se projekt jmenoval?"
+    project_description: "Popisek"
+    project_description_help: "Krátce popište projekt."
+    project_picture: "Obrázek"
+    project_picture_help: "Nahrajte 230x115px nebo větší obrázek ukazující projekt."
+    project_link: "Odkaz"
+    project_link_help: "Odkaz na projekt."
+    player_code: "Kód hráče"
+
+  employers:
+    deprecation_warning_title: "Omlouváme se, CodeCombat právě nepřijímá další žadatele."
+    deprecation_warning: "Zaměřujeme se na začátečnickou úroveň, místo toho, abychom nalézali vývojářské experty."
+    hire_developers_not_credentials: "Najímejte vývojáře, ne jen ty s tituly." # We are not actively recruiting right now, so there's no need to add new translations for the rest of this section.
+    get_started: "Začnětě"
+    already_screened: "Již jsme si technicky prověřili všechny naše kandidáty"
+    filter_further: ", ale můžete si také zapnout filtry:"
+    filter_visa: "Visa"
+    filter_visa_yes: "USA autorizováno"
+    filter_visa_no: "Neautorizováno"
+    filter_education_top: "Nejlepší škola"
+    filter_education_other: "Jiné"
+    filter_role_web_developer: "Webový vývojář"
+    filter_role_software_developer: "Softwarový vývojářr"
+    filter_role_mobile_developer: "Mobilní vývojář"
+    filter_experience: "Zkušený"
+    filter_experience_senior: "Senior"
+    filter_experience_junior: "Junior"
+    filter_experience_recent_grad: "Čerstvý absolvent"
+    filter_experience_student: "Vysokoškolák"
+    filter_results: "výsledky"
+    start_hiring: "Začít přijímat."
+    reasons: "Tři důvody, pro byste měli přijímat přes nás:"
+    everyone_looking: "Každý zde hledá svou další příležitost."
+    everyone_looking_blurb: "Zapomeňte na 20% LinkedIn InMail míru odezvy. Každý, který je uveden na této stránce chce najít svou další pozici a odpoví na váš požadavek na představení se."
+    weeding: "Opřete se; odstranili jsme všechny mouchy za vás."
+    weeding_blurb: "Každý hráč, který je uveden byl prověřen o svých technických dovednostech. Kandidáti také uvádí poznámky na svých profilech, aby vám ušetřili čas."
+    pass_screen: "Projdou vašimi technickými prověrkami."
+    pass_screen_blurb: "Prohlédněte si kód každého kandidáta. Takto zjistíte, jestli se vám kandidát bude hodit či nikoliv."
+    make_hiring_easier: "Ulehčete mi přijímání zaměstananců, prosím."
+    what: "Co je CodeCombat?"
+    what_blurb: "CodeCombat je multiplayerová prohlížečová programovací hra. Hráči píší köd, kterým ovládají jejich jednotky v boji proti jiným vývojářům. Naši hráči mají dobré zkušenosti s technikou."
+    cost: "Kolik si účtujeme?"
+    cost_blurb: "Účtujeme si 15% z platu po dobu prvního roku a nabízíme 100% záruku vrácení peněz po dobu 90 dní. Neúčtujeme si za kandidáty, se kterými se již aktivně vede pohovor ve vaší společnosti."
+    candidate_name: "Jméno"
+    candidate_location: "Umístění"
+    candidate_looking_for: "Hledá"
+    candidate_role: "Role"
+    candidate_top_skills: "Nejlepší dovednosti"
+    candidate_years_experience: "Roků zkušeností"
+    candidate_last_updated: "Naposled aktualizováno"
+    candidate_who: "Kdo"
+    featured_developers: "Uvedení vývojáři"
+    other_developers: "Jiní vývojáři"
+    inactive_developers: "Neaktivní vývojáři"

   admin:
     av_espionage: "Špionáž" # Really not important to translate /admin controls.


Update subscribe modal level counts

Update subscribe modal level counts

--- app/locale/en.coffee
+++ app/locale/en.coffee
@@ -495,9 +495,9 @@

   subscribe:
     comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
-    feature1: "110+ basic levels across 4 worlds"
+    feature1: "125+ basic levels across 4 worlds" # {change}
     feature2: "10 powerful new heroes with unique skills!"
-    feature3: "80+ bonus levels"
+    feature3: "85+ bonus levels" # {change}
     feature4: "{{gems}} bonus gems every month!"
     feature5: "Video tutorials"
     feature6: "Premium email support"