diff --git a/app/application.coffee b/app/application.coffee index 8486b876b..8d71a3249 100644 --- a/app/application.coffee +++ b/app/application.coffee @@ -27,7 +27,7 @@ elementAcceptsKeystrokes = (el) -> type = el.type?.toLowerCase() textInputTypes = ['text', 'password', 'file', 'number', 'search', 'url', 'tel', 'email', 'date', 'month', 'week', 'time', 'datetimelocal'] # not radio, checkbox, range, or color - return (tag is 'textarea' or (tag is 'input' and type in textInputTypes) or el.contentEditable in ["", "true"]) and not (el.readOnly or el.disabled) + return (tag is 'textarea' or (tag is 'input' and type in textInputTypes) or el.contentEditable in ['', 'true']) and not (el.readOnly or el.disabled) COMMON_FILES = ['/images/pages/base/modal_background.png', '/images/level/code_palette_background.png', '/images/level/popover_background.png', '/images/level/code_editor_background.png'] preload = (arrayOfImages) -> @@ -49,7 +49,7 @@ Application = initialize: -> resStore: locale #debug: true #sendMissing: true - #sendMissingTo: "current" + #sendMissingTo: 'current' #resPostPath: '/languages/add/__lng__/__ns__' }, (t) => @router = new Router() diff --git a/app/collections/DocumentFiles.coffee b/app/collections/DocumentFiles.coffee index b4ab7559d..a91ee0bbd 100644 --- a/app/collections/DocumentFiles.coffee +++ b/app/collections/DocumentFiles.coffee @@ -3,9 +3,9 @@ File = require 'models/File' module.exports = class ModelFiles extends CocoCollection model: File - + constructor: (model) -> super() url = model.constructor.prototype.urlRoot url += "/#{model.get('original') or model.id}/files" - @url = url \ No newline at end of file + @url = url diff --git a/app/collections/PatchesCollection.coffee b/app/collections/PatchesCollection.coffee index f3f1a6d8e..cb03c3486 100644 --- a/app/collections/PatchesCollection.coffee +++ b/app/collections/PatchesCollection.coffee @@ -3,8 +3,7 @@ CocoCollection = require 'collections/CocoCollection' module.exports = class PatchesCollection extends CocoCollection model: PatchModel - + initialize: (models, options, forModel, @status='pending') -> super(arguments...) @url = "#{forModel.urlRoot}/#{forModel.get('original')}/patches?status=#{@status}" - diff --git a/app/collections/ThangNamesCollection.coffee b/app/collections/ThangNamesCollection.coffee index 414628d84..3e98fb02e 100644 --- a/app/collections/ThangNamesCollection.coffee +++ b/app/collections/ThangNamesCollection.coffee @@ -7,7 +7,7 @@ module.exports = class ThangNamesCollection extends CocoCollection isCachable: false constructor: (@ids) -> super() - + fetch: (options) -> options ?= {} _.extend options, {type:'POST', data:{ids:@ids}} diff --git a/app/initialize.coffee b/app/initialize.coffee index 2e76c6de4..5462242f4 100644 --- a/app/initialize.coffee +++ b/app/initialize.coffee @@ -22,7 +22,7 @@ init = -> testing = path.startsWith '/test' demoing = path.startsWith '/demo' initializeServices() unless testing or demoing - + # Set up Backbone.Mediator schemas setUpDefinitions() setUpChannels() @@ -35,10 +35,10 @@ init = -> treemaExt.setup() $ -> init() - + handleNormalUrls = -> # http://artsy.github.com/blog/2012/06/25/replacing-hashbang-routes-with-pushstate/ - $(document).on "click", "a[href^='/']", (event) -> + $(document).on 'click', "a[href^='/']", (event) -> href = $(event.currentTarget).attr('href') diff --git a/app/lib/Angel.coffee b/app/lib/Angel.coffee index 74208df30..5c079d3b3 100644 --- a/app/lib/Angel.coffee +++ b/app/lib/Angel.coffee @@ -15,7 +15,7 @@ module.exports = class Angel extends CocoClass constructor: (@shared) -> super() @say 'Got my wings.' - if window.navigator and (window.navigator.userAgent.search("MSIE") isnt -1 or window.navigator.appName is 'Microsoft Internet Explorer') + if window.navigator and (window.navigator.userAgent.search('MSIE') isnt -1 or window.navigator.appName is 'Microsoft Internet Explorer') @infiniteLoopIntervalDuration *= 10 # since it's so slow to serialize without transferable objects, we can't trust it @infiniteLoopTimeoutDuration *= 10 @abortTimeoutDuration *= 10 @@ -40,7 +40,7 @@ module.exports = class Angel extends CocoClass return if @destroyed clearTimeout @condemnTimeout @condemnTimeout = _.delay @infinitelyLooped, @infiniteLoopTimeoutDuration - @say "Let's give it", @infiniteLoopTimeoutDuration, "to not loop." + @say 'Let\'s give it', @infiniteLoopTimeoutDuration, 'to not loop.' @worker.postMessage func: 'reportIn' onWorkerMessage: (event) => @@ -58,7 +58,7 @@ module.exports = class Angel extends CocoClass when 'start-load-frames' clearTimeout @condemnTimeout when 'report-in' - @say "Worker reported in." + @say 'Worker reported in.' clearTimeout @condemnTimeout when 'end-load-frames' clearTimeout @condemnTimeout @@ -84,7 +84,7 @@ module.exports = class Angel extends CocoClass when 'new-world' @beholdWorld event.data.serialized, event.data.goalStates when 'abort' - @say "Aborted.", event.data + @say 'Aborted.', event.data clearTimeout @abortTimeout @aborting = false @running = false @@ -92,7 +92,7 @@ module.exports = class Angel extends CocoClass @doWork() else - @log "Received unsupported message:", event.data + @log 'Received unsupported message:', event.data beholdGoalStates: (goalStates) -> return if @aborting @@ -125,37 +125,37 @@ module.exports = class Angel extends CocoClass @doWork() finalizePreload: -> - @say "Finalize preload." + @say 'Finalize preload.' @worker.postMessage func: 'finalizePreload' infinitelyLooped: => - @say "On infinitely looped! Aborting?", @aborting + @say 'On infinitely looped! Aborting?', @aborting return if @aborting - problem = type: "runtime", level: "error", id: "runtime_InfiniteLoop", message: "Code never finished. It's either really slow or has an infinite loop." + problem = type: 'runtime', level: 'error', id: 'runtime_InfiniteLoop', message: 'Code never finished. It\'s either really slow or has an infinite loop.' Backbone.Mediator.publish 'god:user-code-problem', problem: problem Backbone.Mediator.publish 'god:infinite-loop', firstWorld: @shared.firstWorld @fireWorker() doWork: -> return if @aborting - return @say "Not initialized for work yet." unless @initialized + return @say 'Not initialized for work yet.' unless @initialized if @shared.workQueue.length @work = @shared.workQueue.shift() return _.defer @simulateSync, @work if @work.synchronous - @say "Running world..." + @say 'Running world...' @running = true @shared.busyAngels.push @ @worker.postMessage func: 'runWorld', args: @work clearTimeout @purgatoryTimer - @say "Infinite loop timer started at interval of", @infiniteLoopIntervalDuration + @say 'Infinite loop timer started at interval of', @infiniteLoopIntervalDuration @purgatoryTimer = setInterval @testWorker, @infiniteLoopIntervalDuration else - @say "No work to do." + @say 'No work to do.' @hireWorker() abort: -> return unless @worker and @running - @say "Aborting..." + @say 'Aborting...' @running = false @work = null _.remove @shared.busyAngels, @ @@ -172,14 +172,14 @@ module.exports = class Angel extends CocoClass @worker = null clearTimeout @condemnTimeout clearInterval @purgatoryTimer - @say "Fired worker." + @say 'Fired worker.' @initialized = false @work = null @hireWorker() if rehire hireWorker: -> return if @worker - @say "Hiring worker." + @say 'Hiring worker.' @worker = new Worker @shared.workerCode @worker.addEventListener 'message', @onWorkerMessage @worker.creationTime = new Date() @@ -199,7 +199,7 @@ module.exports = class Angel extends CocoClass testWorld.setGoalManager testGM @doSimulateWorld work console?.profileEnd?() if imitateIE9? - console.log "Construction:", (work.t1 - work.t0).toFixed(0), "ms. Simulation:", (work.t2 - work.t1).toFixed(0), "ms --", ((work.t2 - work.t1) / testWorld.frames.length).toFixed(3), "ms per frame, profiled." + console.log 'Construction:', (work.t1 - work.t0).toFixed(0), 'ms. Simulation:', (work.t2 - work.t1).toFixed(0), 'ms --', ((work.t2 - work.t1) / testWorld.frames.length).toFixed(3), 'ms per frame, profiled.' # If performance was really a priority in IE9, we would rework things to be able to skip this step. goalStates = testGM?.getGoalStates() @@ -212,7 +212,7 @@ module.exports = class Angel extends CocoClass doSimulateWorld: (work) -> work.t1 = now() Math.random = work.testWorld.rand.randf # so user code is predictable - Aether.replaceBuiltin("Math", Math) + Aether.replaceBuiltin('Math', Math) i = 0 while i < work.testWorld.totalFrames frame = work.testWorld.getFrame i++ diff --git a/app/lib/AsyncCloner.coffee b/app/lib/AsyncCloner.coffee index 7050d3452..9af166286 100644 --- a/app/lib/AsyncCloner.coffee +++ b/app/lib/AsyncCloner.coffee @@ -6,17 +6,17 @@ # super() # @indexLists = [] # @initClone() -# +# # initClone: () -> # @target = AsyncCloner.cloneToDepth(@source, @depth) # @indexLists = [_.keys(@target)] if _.isObject @target -# +# # @cloneToDepth: (value, depth) -> # value = _.clone(value) # return value unless depth and _.isObject value # value[key] = @cloneToDepth(value[key], depth-1) for key in _.keys value # value -# +# # clone: -> # while @indexLists.length # #console.log 'Clone loop:', JSON.stringify @indexLists @@ -25,7 +25,7 @@ # @cloneOne() # @moveIndexForwardOne() # break if @done() or @timeToSleep() -# +# # moveIndexForward: -> # while @indexLists.length # nextValue = @getNextValue() @@ -34,7 +34,7 @@ # # push a new list if it's a collection # @indexLists.push _.keys(nextValue) # continue -# else +# else # break # we done, the next value needs to be deep cloned # #console.log 'Skipping:', @getNextPath() # @moveIndexForwardOne() # move past this value otherwise @@ -44,15 +44,15 @@ # value = @target # value = value[indexList[0]] for indexList in @indexLists # value -# +# # getNextParent: -> # parent = @target # parent = parent[indexList[0]] for indexList in @indexLists[...-1] # parent -# +# # getNextPath: -> # (indexList[0] for indexList in @indexLists when indexList.length).join '.' -# +# # moveIndexForwardOne: -> # @indexLists[@indexLists.length-1].shift() # move the index forward one # # if we reached the end of an index list, trim down through all finished lists @@ -69,7 +69,7 @@ # #console.log 'Deep Cloned:', @getNextPath() # # done: -> not @indexLists.length -# +# # timeToSleep: -> false @@ -79,4 +79,4 @@ Clone that one, popping it off the list. If the last list is now empty, pop that list and every subsequent list if needed. Check for doneness, or timeout. -### \ No newline at end of file +### diff --git a/app/lib/AudioPlayer.coffee b/app/lib/AudioPlayer.coffee index 40b07974d..3c6c73992 100644 --- a/app/lib/AudioPlayer.coffee +++ b/app/lib/AudioPlayer.coffee @@ -1,11 +1,11 @@ CocoClass = require 'lib/CocoClass' cache = {} -{me} = require('lib/auth') +{me} = require 'lib/auth' # Top 20 obscene words (plus 'fiddlesticks') will trigger swearing Simlish with *beeps*. # Didn't like leaving so much profanity lying around in the source, so rot13'd. -rot13 = (s) -> s.replace /[A-z]/g, (c) -> String.fromCharCode c.charCodeAt(0) + (if c.toUpperCase() <= "M" then 13 else -13) -swears = (rot13 s for s in ["nefrubyr", "nffubyr", "onfgneq", "ovgpu", "oybbql", "obyybpxf", "ohttre", "pbpx", "penc", "phag", "qnza", "qnea", "qvpx", "qbhpur", "snt", "shpx", "cvff", "chffl", "fuvg", "fyhg", "svqqyrfgvpxf"]) +rot13 = (s) -> s.replace /[A-z]/g, (c) -> String.fromCharCode c.charCodeAt(0) + (if c.toUpperCase() <= 'M' then 13 else -13) +swears = (rot13 s for s in ['nefrubyr', 'nffubyr', 'onfgneq', 'ovgpu', 'oybbql', 'obyybpxf', 'ohttre', 'pbpx', 'penc', 'phag', 'qnza', 'qnea', 'qvpx', 'qbhpur', 'snt', 'shpx', 'cvff', 'chffl', 'fuvg', 'fyhg', 'svqqyrfgvpxf']) createjs.Sound.registerPlugins([createjs.WebAudioPlugin, createjs.FlashPlugin, createjs.HTMLAudioPlugin]) @@ -129,7 +129,7 @@ class AudioPlayer extends CocoClass console.error 'Could not load sound', e notifyProgressChanged: -> - Backbone.Mediator.publish('audio-player:loaded', {sender:@}) + Backbone.Mediator.publish('audio-player:loaded', {sender: @}) getStatus: (src) -> return cache[src] or null diff --git a/app/lib/Bus.coffee b/app/lib/Bus.coffee index 63caba7f0..a79f6a67c 100644 --- a/app/lib/Bus.coffee +++ b/app/lib/Bus.coffee @@ -26,9 +26,9 @@ module.exports = Bus = class Bus extends CocoClass @notifyStateChanges() connect: -> - Backbone.Mediator.publish 'bus:connecting', {bus:@} + Backbone.Mediator.publish 'bus:connecting', {bus: @} Firebase.goOnline() - @fireRef = new Firebase(Bus.fireHost + "/" + @docName) + @fireRef = new Firebase(Bus.fireHost + '/' + @docName) @fireRef.once 'value', @onFireOpen onFireOpen: (snapshot) => @@ -36,7 +36,7 @@ module.exports = Bus = class Bus extends CocoClass console.log("Leaving '#{@docName}' because class has been destroyed.") return @init() - Backbone.Mediator.publish 'bus:connected', {bus:@} + Backbone.Mediator.publish 'bus:connected', {bus: @} disconnect: -> Firebase.goOffline() @@ -49,7 +49,7 @@ module.exports = Bus = class Bus extends CocoClass @myConnection?.off() @myConnection = null @joined = false - Backbone.Mediator.publish 'bus:disconnected', {bus:@} + Backbone.Mediator.publish 'bus:disconnected', {bus: @} init: -> """ @@ -59,7 +59,7 @@ module.exports = Bus = class Bus extends CocoClass @firePlayersRef = @fireRef.child('players') @join() @listenForChanges() - @sendMessage("/me joined.", true) + @sendMessage('/me joined.', true) join: -> @joined = true @@ -75,13 +75,13 @@ module.exports = Bus = class Bus extends CocoClass @firePlayersRef.on 'child_changed', @onPlayerChanged onChatAdded: (snapshot) => - Backbone.Mediator.publish('bus:new-message', {message:snapshot.val(), bus:@}) + Backbone.Mediator.publish('bus:new-message', {message: snapshot.val(), bus: @}) onPlayerJoined: (snapshot) => player = snapshot.val() return unless player.connected @players[player.id] = player - Backbone.Mediator.publish('bus:player-joined', {player:player, bus:@}) + Backbone.Mediator.publish('bus:player-joined', {player: player, bus: @}) onPlayerLeft: (snapshot) => val = snapshot.val() @@ -89,7 +89,7 @@ module.exports = Bus = class Bus extends CocoClass player = @players[val.id] return unless player delete @players[player.id] - Backbone.Mediator.publish('bus:player-left', {player:player, bus:@}) + Backbone.Mediator.publish('bus:player-left', {player: player, bus: @}) onPlayerChanged: (snapshot) => player = snapshot.val() @@ -97,7 +97,7 @@ module.exports = Bus = class Bus extends CocoClass @players[player.id] = player @onPlayerLeft(snapshot) if wasConnected and not player.connected @onPlayerJoined(snapshot) if player.connected and not wasConnected - Backbone.Mediator.publish('bus:player-states-changed', {states:@players, bus:@}) + Backbone.Mediator.publish('bus:player-states-changed', {states: @players, bus: @}) onMeSynced: => @myConnection?.child('name').set(me.get('name')) @@ -118,9 +118,9 @@ module.exports = Bus = class Bus extends CocoClass sendMessage: (content, system=false) -> MAX_MESSAGE_LENGTH = 400 message = - content:content[... MAX_MESSAGE_LENGTH] - authorName:me.displayName() - authorID:me.id + content: content[... MAX_MESSAGE_LENGTH] + authorName: me.displayName() + authorID: me.id dateMade: new Date() message.system = system if system @fireChatRef.push(message) @@ -128,7 +128,7 @@ module.exports = Bus = class Bus extends CocoClass # TEARDOWN destroy: -> - @sendMessage("/me left.", true) if @joined + @sendMessage('/me left.', true) if @joined delete Bus.activeBuses[@docName] if @docName of Bus.activeBuses @disconnect() super() diff --git a/app/lib/CocoClass.coffee b/app/lib/CocoClass.coffee index e29298b18..4922f9e5e 100644 --- a/app/lib/CocoClass.coffee +++ b/app/lib/CocoClass.coffee @@ -9,7 +9,7 @@ module.exports = class CocoClass @nicksUsed: {} @remainingNicks: [] @nextNick: -> - return (@name or "CocoClass") + " " + classCount unless @nicks.length + return (@name or 'CocoClass') + ' ' + classCount unless @nicks.length @remainingNicks = if @remainingNicks.length then @remainingNicks else @nicks.slice() baseNick = @remainingNicks.splice(Math.floor(Math.random() * @remainingNicks.length), 1)[0] i = 0 diff --git a/app/lib/FacebookHandler.coffee b/app/lib/FacebookHandler.coffee index e9bf6aadc..61553d946 100644 --- a/app/lib/FacebookHandler.coffee +++ b/app/lib/FacebookHandler.coffee @@ -44,7 +44,7 @@ module.exports = FacebookHandler = class FacebookHandler extends CocoClass me.set('gender', r.gender) if r.gender me.set('email', r.email) if r.email me.set('facebookID', r.id) if r.id - + Backbone.Mediator.publish('logging-in-with-facebook') window.tracker?.trackEvent 'Facebook Login' window.tracker?.identify() diff --git a/app/lib/GPlusHandler.coffee b/app/lib/GPlusHandler.coffee index 4b8637b8c..997a25ab4 100644 --- a/app/lib/GPlusHandler.coffee +++ b/app/lib/GPlusHandler.coffee @@ -14,8 +14,8 @@ userPropsToSave = fieldsToFetch = 'displayName,gender,image,name(familyName,givenName),id' plusURL = '/plus/v1/people/me?fields='+fieldsToFetch revokeUrl = 'https://accounts.google.com/o/oauth2/revoke?token=' -clientID = "800329290710-j9sivplv2gpcdgkrsis9rff3o417mlfa.apps.googleusercontent.com" -scope = "https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email" +clientID = '800329290710-j9sivplv2gpcdgkrsis9rff3o417mlfa.apps.googleusercontent.com' +scope = 'https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email' module.exports = GPlusHandler = class GPlusHandler extends CocoClass constructor: -> @@ -32,7 +32,7 @@ module.exports = GPlusHandler = class GPlusHandler extends CocoClass # We need to check the current state, given our access token gapi.auth.setToken 'token', @accessToken session_state = @accessToken.session_state - gapi.auth.checkSessionState({client_id:clientID, session_state:session_state}, @onCheckedSessionState) + gapi.auth.checkSessionState({client_id: clientID, session_state: session_state}, @onCheckedSessionState) else # If we ran checkSessionState, it might return true, that the user is logged into Google, but has not authorized us @loggedIn = false @@ -57,7 +57,7 @@ module.exports = GPlusHandler = class GPlusHandler extends CocoClass # email and profile data loaded separately @responsesComplete = 0 - gapi.client.request(path:plusURL, callback:@onPersonEntityReceived) + gapi.client.request(path: plusURL, callback: @onPersonEntityReceived) gapi.client.load('oauth2', 'v2', => gapi.client.oauth2.userinfo.get().execute(@onEmailReceived)) @@ -108,7 +108,7 @@ module.exports = GPlusHandler = class GPlusHandler extends CocoClass loadFriends: (friendsCallback) -> return friendsCallback() unless @loggedIn expiresIn = if @accessToken then parseInt(@accessToken.expires_at) - new Date().getTime()/1000 else -1 - onReauthorized = => gapi.client.request({path:'/plus/v1/people/me/people/visible', callback: friendsCallback}) + onReauthorized = => gapi.client.request({path: '/plus/v1/people/me/people/visible', callback: friendsCallback}) if expiresIn < 0 # TODO: this tries to open a popup window, which might not ever finish or work, so the callback may never be called. @reauthorize() diff --git a/app/lib/God.coffee b/app/lib/God.coffee index 017c1263d..ffe2ad726 100644 --- a/app/lib/God.coffee +++ b/app/lib/God.coffee @@ -8,7 +8,7 @@ CocoClass = require 'lib/CocoClass' Angel = require 'lib/Angel' module.exports = class God extends CocoClass - @nicks: ['Athena', 'Baldr', 'Crom', 'Dagr', 'Eris', 'Freyja', 'Great Gish', 'Hades', 'Ishtar', 'Janus', 'Khronos', 'Loki', 'Marduk', 'Negafook', 'Odin', 'Poseidon', 'Quetzalcoatl', 'Ra', 'Shiva', 'Thor', 'Umvelinqangi', 'Týr', 'Vishnu', 'Wepwawet', 'Xipe Totec', 'Yahweh', 'Zeus', '上帝', 'Tiamat', '盘古', 'Phoebe', 'Artemis', 'Osiris', "嫦娥", 'Anhur', 'Teshub', 'Enlil', 'Perkele', 'Chaos', 'Hera', 'Iris', 'Theia', 'Uranus', 'Stribog', 'Sabazios', 'Izanagi', 'Ao', 'Tāwhirimātea', 'Tengri', 'Inmar', 'Torngarsuk', 'Centzonhuitznahua', 'Hunab Ku', 'Apollo', 'Helios', 'Thoth', 'Hyperion', 'Alectrona', 'Eos', 'Mitra', 'Saranyu', 'Freyr', 'Koyash', 'Atropos', 'Clotho', 'Lachesis', 'Tyche', 'Skuld', 'Urðr', 'Verðandi', 'Camaxtli', 'Huhetotl', 'Set', 'Anu', 'Allah', 'Anshar', 'Hermes', 'Lugh', 'Brigit', 'Manannan Mac Lir', 'Persephone', 'Mercury', 'Venus', 'Mars', 'Azrael', 'He-Man', 'Anansi', 'Issek', 'Mog', 'Kos', 'Amaterasu Omikami', 'Raijin', 'Susanowo', 'Blind Io', 'The Lady', 'Offler', 'Ptah', 'Anubis', 'Ereshkigal', 'Nergal', 'Thanatos', 'Macaria', 'Angelos', 'Erebus', 'Hecate', 'Hel', 'Orcus', 'Ishtar-Deela Nakh', 'Prometheus', 'Hephaestos', 'Sekhmet', 'Ares', 'Enyo', 'Otrera', 'Pele', 'Hadúr', 'Hachiman', 'Dayisun Tngri', 'Ullr', 'Lua', 'Minerva'] + @nicks: ['Athena', 'Baldr', 'Crom', 'Dagr', 'Eris', 'Freyja', 'Great Gish', 'Hades', 'Ishtar', 'Janus', 'Khronos', 'Loki', 'Marduk', 'Negafook', 'Odin', 'Poseidon', 'Quetzalcoatl', 'Ra', 'Shiva', 'Thor', 'Umvelinqangi', 'Týr', 'Vishnu', 'Wepwawet', 'Xipe Totec', 'Yahweh', 'Zeus', '上帝', 'Tiamat', '盘古', 'Phoebe', 'Artemis', 'Osiris', '嫦娥', 'Anhur', 'Teshub', 'Enlil', 'Perkele', 'Chaos', 'Hera', 'Iris', 'Theia', 'Uranus', 'Stribog', 'Sabazios', 'Izanagi', 'Ao', 'Tāwhirimātea', 'Tengri', 'Inmar', 'Torngarsuk', 'Centzonhuitznahua', 'Hunab Ku', 'Apollo', 'Helios', 'Thoth', 'Hyperion', 'Alectrona', 'Eos', 'Mitra', 'Saranyu', 'Freyr', 'Koyash', 'Atropos', 'Clotho', 'Lachesis', 'Tyche', 'Skuld', 'Urðr', 'Verðandi', 'Camaxtli', 'Huhetotl', 'Set', 'Anu', 'Allah', 'Anshar', 'Hermes', 'Lugh', 'Brigit', 'Manannan Mac Lir', 'Persephone', 'Mercury', 'Venus', 'Mars', 'Azrael', 'He-Man', 'Anansi', 'Issek', 'Mog', 'Kos', 'Amaterasu Omikami', 'Raijin', 'Susanowo', 'Blind Io', 'The Lady', 'Offler', 'Ptah', 'Anubis', 'Ereshkigal', 'Nergal', 'Thanatos', 'Macaria', 'Angelos', 'Erebus', 'Hecate', 'Hel', 'Orcus', 'Ishtar-Deela Nakh', 'Prometheus', 'Hephaestos', 'Sekhmet', 'Ares', 'Enyo', 'Otrera', 'Pele', 'Hadúr', 'Hachiman', 'Dayisun Tngri', 'Ullr', 'Lua', 'Minerva'] subscriptions: 'tome:cast-spells': 'onTomeCast' @@ -98,7 +98,7 @@ module.exports = class God extends CocoClass retrieveValueFromFrame: (args) => return if @destroyed return unless args.thangID and args.spellID and args.variableChain - return console.error "Tried to retrieve debug value with no currentUserCodeMap" unless @currentUserCodeMap + return console.error 'Tried to retrieve debug value with no currentUserCodeMap' unless @currentUserCodeMap @debugWorker ?= @createDebugWorker() args.frame ?= @angelsShare.world.age / @angelsShare.world.dt @debugWorker.postMessage diff --git a/app/lib/LevelBus.coffee b/app/lib/LevelBus.coffee index 810038242..845020c8d 100644 --- a/app/lib/LevelBus.coffee +++ b/app/lib/LevelBus.coffee @@ -43,7 +43,7 @@ module.exports = class LevelBus extends Bus incrementSessionPlaytime: => if @playerIsIdle then return @changedSessionProperties.playtime = true - @session.set("playtime",@session.get("playtime") + 1) + @session.set('playtime', @session.get('playtime') + 1) onPoint: -> return true unless @session?.get('multiplayer') @@ -123,7 +123,7 @@ module.exports = class LevelBus extends Bus @changedSessionProperties.teamSpells = true @session.set({'teamSpells': @teamSpellMap}) @saveSession() - if spellTeam is me.team or spellTeam is "common" + if spellTeam is me.team or spellTeam is 'common' @onSpellChanged e # Save the new spell to the session, too. onScriptStateChanged: (e) -> @@ -233,7 +233,7 @@ module.exports = class LevelBus extends Bus # since updates are coming fast and loose for session objects # don't let what the server returns overwrite changes since the save began - tempSession = new LevelSession _id:@session.id + tempSession = new LevelSession _id: @session.id tempSession.save(patch, {patch: true}) destroy: -> diff --git a/app/lib/LevelLoader.coffee b/app/lib/LevelLoader.coffee index 2c0b98fff..59332b64e 100644 --- a/app/lib/LevelLoader.coffee +++ b/app/lib/LevelLoader.coffee @@ -48,7 +48,7 @@ module.exports = class LevelLoader extends CocoClass # Apparently the jingle, when it tries to play immediately during all this loading, you can't hear it. # Add the timeout to fix this weird behavior. f = -> - jingles = ["ident_1", "ident_2"] + jingles = ['ident_1', 'ident_2'] AudioPlayer.playInterfaceSound jingles[Math.floor Math.random() * jingles.length] setTimeout f, 500 @@ -63,7 +63,7 @@ module.exports = class LevelLoader extends CocoClass url += "?team=#{@team}" if @team session = new LevelSession().setURL url - @sessionResource = @supermodel.loadModel(session, 'level_session', {cache:false}) + @sessionResource = @supermodel.loadModel(session, 'level_session', {cache: false}) @session = @sessionResource.model @session.once 'sync', -> @url = -> '/db/level.session/' + @id @@ -151,7 +151,7 @@ module.exports = class LevelLoader extends CocoClass continue if thangType.isFullyLoaded() thangType.fetch() thangType = @supermodel.loadModel(thangType, 'thang').model - res = @supermodel.addSomethingResource "sprite_sheet", 5 + res = @supermodel.addSomethingResource 'sprite_sheet', 5 res.thangType = thangType res.markLoading() @spriteSheetsToBuild.push res @@ -246,7 +246,7 @@ module.exports = class LevelLoader extends CocoClass break unless @teamConfigs # Hack: pulled from Alliance System code. TODO: put in just one place. - @teamConfigs = {"humans":{"superteam":"humans","color":{"hue":0,"saturation":0.75,"lightness":0.5},"playable":true},"ogres":{"superteam":"ogres","color":{"hue":0.66,"saturation":0.75,"lightness":0.5},"playable":false},"neutral":{"superteam":"neutral","color":{"hue":0.33,"saturation":0.75,"lightness":0.5}}} + @teamConfigs = {'humans': {'superteam': 'humans', 'color': {'hue': 0, 'saturation': 0.75, 'lightness': 0.5}, 'playable': true}, 'ogres': {'superteam': 'ogres', 'color': {'hue': 0.66, 'saturation': 0.75, 'lightness': 0.5}, 'playable': false}, 'neutral': {'superteam': 'neutral', 'color': {'hue': 0.33, 'saturation': 0.75, 'lightness': 0.5}}} @teamConfigs buildSpriteSheet: (thangType, options) -> @@ -263,13 +263,13 @@ module.exports = class LevelLoader extends CocoClass @world.levelSessionIDs = if @opponentSessionID then [@sessionID, @opponentSessionID] else [@sessionID] serializedLevel = @level.serialize(@supermodel) @world.loadFromLevel serializedLevel, false - console.log "World has been initialized from level loader." + console.log 'World has been initialized from level loader.' # Initial Sound Loading loadAudio: -> return if @headless - AudioPlayer.preloadInterfaceSounds ["victory"] + AudioPlayer.preloadInterfaceSounds ['victory'] loadLevelSounds: -> return if @headless diff --git a/app/lib/LinkedInHandler.coffee b/app/lib/LinkedInHandler.coffee index a19090391..ed322f2c2 100644 --- a/app/lib/LinkedInHandler.coffee +++ b/app/lib/LinkedInHandler.coffee @@ -12,20 +12,20 @@ module.exports = LinkedInHandler = class LinkedInHandler extends CocoClass 'linkedin-loaded': 'onLinkedInLoaded' onLinkedInLoaded: (e) -> - IN.Event.on IN, "auth", @onLinkedInAuth + IN.Event.on IN, 'auth', @onLinkedInAuth - onLinkedInAuth: (e) => console.log "Authorized with LinkedIn" + onLinkedInAuth: (e) => console.log 'Authorized with LinkedIn' constructEmployerAgreementObject: (cb) => - IN.API.Profile("me") - .fields(["positions","public-profile-url","id","first-name","last-name","email-address"]) + IN.API.Profile('me') + .fields(['positions', 'public-profile-url', 'id', 'first-name', 'last-name', 'email-address']) .error(cb) .result (profiles) => cb null, profiles.values[0] - + getProfileData: (cb) => - IN.API.Profile("me") - .fields(["formatted-name","educations","skills","headline","summary","positions","public-profile-url"]) + IN.API.Profile('me') + .fields(['formatted-name', 'educations', 'skills', 'headline', 'summary', 'positions', 'public-profile-url']) .error(cb) .result (profiles) => cb null, profiles.values[0] diff --git a/app/lib/NameLoader.coffee b/app/lib/NameLoader.coffee index f4ca48b8f..122becf7e 100644 --- a/app/lib/NameLoader.coffee +++ b/app/lib/NameLoader.coffee @@ -7,9 +7,9 @@ class NameLoader extends CocoClass toLoad = _.uniq (id for id in ids when not namesCache[id]) return false unless toLoad.length jqxhrOptions = { - url: '/db/user/x/names', - type:'POST', - data:{ids:toLoad}, + url: '/db/user/x/names', + type: 'POST', + data: {ids: toLoad}, success: @loadedNames } @@ -17,7 +17,7 @@ class NameLoader extends CocoClass loadedNames: (newNames) => _.extend namesCache, newNames - + getName: (id) -> namesCache[id]?.name or id module.exports = new NameLoader() diff --git a/app/lib/Router.coffee b/app/lib/Router.coffee index d7ac1a1cc..357c56ddc 100644 --- a/app/lib/Router.coffee +++ b/app/lib/Router.coffee @@ -1,4 +1,4 @@ -gplusClientID = "800329290710-j9sivplv2gpcdgkrsis9rff3o417mlfa.apps.googleusercontent.com" +gplusClientID = '800329290710-j9sivplv2gpcdgkrsis9rff3o417mlfa.apps.googleusercontent.com' go = (path) -> -> @routeDirectly path, arguments @@ -75,16 +75,16 @@ module.exports = class CocoRouter extends Backbone.Router gapi.plusone.go?() # Handles +1 button for gplusButton in $('.gplus-login-button') params = { - callback:"signinCallback", - clientid:gplusClientID, - cookiepolicy:"single_host_origin", - scope:"https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email", - height: "short", + callback: 'signinCallback', + clientid: gplusClientID, + cookiepolicy: 'single_host_origin', + scope: 'https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email', + height: 'short', } if gapi.signin?.render gapi.signin.render(gplusButton, params) else - console.warn "Didn't have gapi.signin to render G+ login button. (DoNotTrackMe extension?)" + console.warn 'Didn\'t have gapi.signin to render G+ login button. (DoNotTrackMe extension?)' getViewFromCache: (route) -> if route of @cache @@ -106,7 +106,7 @@ module.exports = class CocoRouter extends Backbone.Router getView: (route, suffix='_view') -> # iteratively breaks down the url pieces looking for the view - # passing the broken off pieces as args. This way views like "resource/14394893" + # passing the broken off pieces as args. This way views like 'resource/14394893' # will get passed to the resource view with arg '14394893' pieces = _.string.words(route, '/') split = Math.max(1, pieces.length-1) diff --git a/app/lib/SystemNameLoader.coffee b/app/lib/SystemNameLoader.coffee index f23dbe491..c25abb914 100644 --- a/app/lib/SystemNameLoader.coffee +++ b/app/lib/SystemNameLoader.coffee @@ -5,6 +5,6 @@ namesCache = {} class SystemNameLoader extends CocoClass getName: (id) -> namesCache[id]?.name - setName: (system) -> namesCache[system.get('original')] = {name:system.get('name')} + setName: (system) -> namesCache[system.get('original')] = {name: system.get('name')} module.exports = new SystemNameLoader() diff --git a/app/lib/Tracker.coffee b/app/lib/Tracker.coffee index a21a7820c..fd51ecead 100644 --- a/app/lib/Tracker.coffee +++ b/app/lib/Tracker.coffee @@ -5,14 +5,14 @@ debugAnalytics = false module.exports = class Tracker constructor: -> if window.tracker - console.error "Overwrote our Tracker!", window.tracker + console.error 'Overwrote our Tracker!', window.tracker window.tracker = @ - @isProduction = document.location.href.search("codecombat.com") isnt -1 + @isProduction = document.location.href.search('codecombat.com') isnt -1 @identify() @updateOlark() identify: (traits) -> - console.log "Would identify", traits if debugAnalytics + console.log 'Would identify', traits if debugAnalytics return unless me and @isProduction and analytics? # https://segment.io/docs/methods/identify traits ?= {} @@ -23,8 +23,8 @@ module.exports = class Tracker updateOlark: -> return unless me and olark? olark 'api.chat.updateVisitorStatus', snippet: ["User ID: #{me.id}"] - return if me.get("anonymous") - olark 'api.visitor.updateEmailAddress', emailAddress: me.get("email") if me.get('email') + return if me.get('anonymous') + olark 'api.visitor.updateEmailAddress', emailAddress: me.get('email') if me.get('email') olark 'api.chat.updateVisitorNickname', snippet: me.displayName() updatePlayState: (level, session) -> @@ -41,13 +41,13 @@ module.exports = class Tracker trackPageView: -> return unless @isProduction and analytics? url = Backbone.history.getFragment() - console.log "Going to track visit for", "/#{url}" if debugAnalytics + console.log 'Going to track visit for', "/#{url}" if debugAnalytics analytics.pageview "/#{url}" trackEvent: (event, properties, includeProviders=null) => - console.log "Would track analytics event:", event, properties if debugAnalytics + console.log 'Would track analytics event:', event, properties if debugAnalytics return unless me and @isProduction and analytics? - console.log "Going to track analytics event:", event, properties if debugAnalytics + console.log 'Going to track analytics event:', event, properties if debugAnalytics properties = properties or {} context = {} if includeProviders @@ -60,5 +60,5 @@ module.exports = class Tracker trackTiming: (duration, category, variable, label, samplePercentage=5) -> # https://developers.google.com/analytics/devguides/collection/gajs/gaTrackingTiming return console.warn "Duration #{duration} invalid for trackTiming call." unless duration >= 0 and duration < 60 * 60 * 1000 - console.log "Would track timing event:", arguments if debugAnalytics + console.log 'Would track timing event:', arguments if debugAnalytics window._gaq?.push ['_trackTiming', category, variable, duration, label, samplePercentage] diff --git a/app/lib/auth.coffee b/app/lib/auth.coffee index 310727b65..b19fbc668 100644 --- a/app/lib/auth.coffee +++ b/app/lib/auth.coffee @@ -12,13 +12,13 @@ init = -> me.set 'testGroupNumber', Math.floor(Math.random() * 256) me.patch() - Backbone.listenTo(me, 'sync', Backbone.Mediator.publish('me:synced', {me:me})) + Backbone.listenTo(me, 'sync', Backbone.Mediator.publish('me:synced', {me: me})) module.exports.createUser = (userObject, failure=backboneFailure, nextURL=null) -> user = new User(userObject) user.notyErrors = false user.save({}, { - error: (model,jqxhr,options) -> + error: (model, jqxhr, options) -> error = parseServerError(jqxhr.responseText) property = error.property if error.property if jqxhr.status is 409 and property is 'name' @@ -34,14 +34,14 @@ module.exports.createUserWithoutReload = (userObject, failure=backboneFailure) - user.save({}, { error: failure success: -> - Backbone.Mediator.publish("created-user-without-reload") + Backbone.Mediator.publish('created-user-without-reload') }) module.exports.loginUser = (userObject, failure=genericFailure) -> jqxhr = $.post('/auth/login', { - username:userObject.email, - password:userObject.password + username: userObject.email, + password: userObject.password }, (model) -> window.location.reload() ) diff --git a/app/lib/contact.coffee b/app/lib/contact.coffee index ade94f2e9..4e1422b59 100644 --- a/app/lib/contact.coffee +++ b/app/lib/contact.coffee @@ -2,8 +2,8 @@ module.exports.sendContactMessage = (contactMessageObject, modal) -> modal.find('.sending-indicator').show() jqxhr = $.post '/contact', contactMessageObject, (response) -> modal.find('.sending-indicator').hide() - modal.find('#contact-message').val("Thanks!") + modal.find('#contact-message').val('Thanks!') _.delay -> - modal.find('#contact-message').val("") + modal.find('#contact-message').val('') modal.modal 'hide' , 1000 diff --git a/app/lib/deltas.coffee b/app/lib/deltas.coffee index 4ec639532..48ea32cfa 100644 --- a/app/lib/deltas.coffee +++ b/app/lib/deltas.coffee @@ -1,23 +1,23 @@ SystemNameLoader = require 'lib/SystemNameLoader' -### +### Good-to-knows: dataPath: an array of keys that walks you up a JSON object that's being patched ex: ['scripts', 0, 'description'] deltaPath: an array of keys that walks you up a JSON Diff Patch object. ex: ['scripts', '_0', 'description'] ### - + module.exports.expandDelta = (delta, left, schema) -> flattenedDeltas = flattenDelta(delta) (expandFlattenedDelta(fd, left, schema) for fd in flattenedDeltas) - + flattenDelta = (delta, dataPath=null, deltaPath=null) -> # takes a single jsondiffpatch delta and returns an array of objects with return [] unless delta dataPath ?= [] deltaPath ?= [] - return [{dataPath:dataPath, deltaPath: deltaPath, o:delta}] if _.isArray delta + return [{dataPath: dataPath, deltaPath: deltaPath, o: delta}] if _.isArray delta results = [] affectingArray = delta._t is 'a' @@ -27,12 +27,12 @@ flattenDelta = (delta, dataPath=null, deltaPath=null) -> results = results.concat flattenDelta( childDelta, dataPath.concat([dataIndex]), deltaPath.concat([deltaIndex])) results - + expandFlattenedDelta = (delta, left, schema) -> # takes a single flattened delta and converts into an object that can be # easily formatted into something human readable. - + delta.action = '???' o = delta.o # the raw jsondiffpatch delta @@ -80,58 +80,72 @@ expandFlattenedDelta = (delta, left, schema) -> humanPath.push humanKey parentLeft = childLeft parentSchema = childSchema - + delta.humanPath = humanPath.join(' :: ') delta.schema = childSchema delta.left = childLeft delta.right = jsondiffpatch.patch childLeft, delta.o unless delta.action is 'moved-index' - + delta - + module.exports.makeJSONDiffer = -> hasher = (obj) -> obj.name || obj.id || obj._id || JSON.stringify(_.keys(obj)) - jsondiffpatch.create({objectHash:hasher}) - + jsondiffpatch.create({objectHash: hasher}) + module.exports.getConflicts = (headDeltas, pendingDeltas) -> - # headDeltas and pendingDeltas should be lists of deltas returned by interpretDelta + # headDeltas and pendingDeltas should be lists of deltas returned by expandDelta # Returns a list of conflict objects with properties: # headDelta # pendingDelta # The deltas that have conflicts also have conflict properties pointing to one another. - + headPathMap = groupDeltasByAffectingPaths(headDeltas) pendingPathMap = groupDeltasByAffectingPaths(pendingDeltas) paths = _.keys(headPathMap).concat(_.keys(pendingPathMap)) - + # Here's my thinking: conflicts happen when one delta path is a substring of another delta path # So, sort paths from both deltas together, which will naturally make conflicts adjacent, - # and if one is identified, one path is from the headDeltas, the other is from pendingDeltas + # and if one is identified AND one path is from the headDeltas AND the other is from pendingDeltas # This is all to avoid an O(nm) brute force search. - + conflicts = [] paths.sort() for path, i in paths - continue if i + 1 is paths.length - nextPath = paths[i+1] - if nextPath.startsWith path - headDelta = (headPathMap[path] or headPathMap[nextPath])[0].delta - pendingDelta = (pendingPathMap[path] or pendingPathMap[nextPath])[0].delta - conflicts.push({headDelta:headDelta, pendingDelta:pendingDelta}) - pendingDelta.conflict = headDelta - headDelta.conflict = pendingDelta + offset = 1 + while i + offset < paths.length + # Look at the neighbor + nextPath = paths[i+offset] + offset += 1 + + # these stop being substrings of each other? Then conflict DNE + if not (nextPath.startsWith path) then break + + # check if these two are from the same group, but we still need to check for more beyond + unless headPathMap[path] or headPathMap[nextPath] then continue + unless pendingPathMap[path] or pendingPathMap[nextPath] then continue + + # Okay, we found two deltas from different groups which conflict + for headMetaDelta in (headPathMap[path] or headPathMap[nextPath]) + headDelta = headMetaDelta.delta + for pendingMetaDelta in (pendingPathMap[path] or pendingPathMap[nextPath]) + pendingDelta = pendingMetaDelta.delta + conflicts.push({headDelta: headDelta, pendingDelta: pendingDelta}) + pendingDelta.conflict = headDelta + headDelta.conflict = pendingDelta return conflicts if conflicts.length - + groupDeltasByAffectingPaths = (deltas) -> metaDeltas = [] for delta in deltas conflictPaths = [] + # We're being fairly liberal with what's a conflict, because the alternative is worse if delta.action is 'moved-index' - # every other action affects just the data path, but moved indexes affect a swath - indices = [delta.originalIndex, delta.destinationIndex] - indices.sort() - for index in _.range(indices[0], indices[1]+1) - conflictPaths.push delta.dataPath.slice(0, delta.dataPath.length-1).concat(index) + # If you moved items around in an array, mark the whole array as a gonner + conflictPaths.push delta.dataPath.slice(0, delta.dataPath.length-1) + else if delta.action in ['deleted', 'added'] and _.isNumber(delta.dataPath[delta.dataPath.length-1]) + # If you remove or add items in an array, mark the whole thing as a gonner + conflictPaths.push delta.dataPath.slice(0, delta.dataPath.length-1) else conflictPaths.push delta.dataPath for path in conflictPaths @@ -139,39 +153,21 @@ groupDeltasByAffectingPaths = (deltas) -> delta: delta path: (item.toString() for item in path).join('/') } - + map = _.groupBy metaDeltas, 'path' + return map - # Turns out there are cases where a single delta can include paths - # that 'conflict' with each other, ie one is a substring of the other - # because of moved indices. To handle this case, go through and prune - # out all deeper paths that conflict with more shallow paths, so - # getConflicts path checking works properly. - - paths = _.keys(map) - return map unless paths.length - paths.sort() - prunedMap = {} - previousPath = paths[0] - for path, i in paths - continue if i is 0 - continue if path.startsWith previousPath - prunedMap[path] = map[path] - previousPath = path - - prunedMap - module.exports.pruneConflictsFromDelta = (delta, conflicts) -> expandedDeltas = (conflict.pendingDelta for conflict in conflicts) module.exports.pruneExpandedDeltasFromDelta delta, expandedDeltas - + module.exports.pruneExpandedDeltasFromDelta = (delta, expandedDeltas) -> # the jsondiffpatch delta mustn't include any dangling nodes, # or else things will get removed which shouldn't be, or errors will occur for expandedDelta in expandedDeltas prunePath delta, expandedDelta.deltaPath if _.isEmpty delta then undefined else delta - + prunePath = (delta, path) -> if path.length is 1 delete delta[path] diff --git a/app/lib/errors.coffee b/app/lib/errors.coffee index 8e7fe4203..04a0c8fd5 100644 --- a/app/lib/errors.coffee +++ b/app/lib/errors.coffee @@ -1,16 +1,16 @@ -errorModalTemplate = require('templates/modal/error') -{applyErrorsToForm} = require('lib/forms') +errorModalTemplate = require 'templates/modal/error' +{applyErrorsToForm} = require 'lib/forms' module.exports.parseServerError = (text) -> try - error = JSON.parse(text) or {message:"Unknown error."} + error = JSON.parse(text) or {message: 'Unknown error.'} catch SyntaxError - error = {message:text or "Unknown error."} + error = {message: text or 'Unknown error.'} error = error[0] if _.isArray(error) error module.exports.genericFailure = (jqxhr) -> - Backbone.Mediator.publish('server-error', {response:jqxhr}) + Backbone.Mediator.publish('server-error', {response: jqxhr}) return connectionFailure() if not jqxhr.status error = module.exports.parseServerError(jqxhr.responseText) @@ -24,8 +24,8 @@ module.exports.genericFailure = (jqxhr) -> existingForm.append($('
').text(error.message)) else res = errorModalTemplate( - status:jqxhr.status - statusText:jqxhr.statusText + status: jqxhr.status + statusText: jqxhr.statusText message: message ) showErrorModal(res) @@ -36,7 +36,7 @@ module.exports.backboneFailure = (model, jqxhr, options) -> module.exports.connectionFailure = connectionFailure = -> html = errorModalTemplate( status: 0 - statusText:'Connection Gone' + statusText: 'Connection Gone' message: 'No response from the CoCo servers, captain.' ) showErrorModal(html) diff --git a/app/lib/forms.coffee b/app/lib/forms.coffee index 73e419698..cd8eb7e13 100644 --- a/app/lib/forms.coffee +++ b/app/lib/forms.coffee @@ -16,13 +16,13 @@ module.exports.applyErrorsToForm = (el, errors) -> if error.dataPath prop = error.dataPath[1..] message = error.message - + else message = "#{error.property} #{error.message}." message = message[0].toUpperCase() + message[1..] message = error.message if error.formatted prop = error.property - + input = $("[name='#{prop}']", el) if not input.length missingErrors.push(error) @@ -35,4 +35,4 @@ module.exports.applyErrorsToForm = (el, errors) -> module.exports.clearFormAlerts = (el) -> $('.has-error', el).removeClass('has-error') $('.alert.alert-danger', el).remove() - el.find('.help-block.error-help-block').remove() \ No newline at end of file + el.find('.help-block.error-help-block').remove() diff --git a/app/lib/image_filter.coffee b/app/lib/image_filter.coffee index 4c1a5f93e..11bf70d76 100644 --- a/app/lib/image_filter.coffee +++ b/app/lib/image_filter.coffee @@ -6,9 +6,9 @@ Filters.getPixels = (img) -> c = @getCanvas(img.naturalWidth, img.naturalHeight) ctx = c.getContext('2d') ctx.drawImage(img, 0, 0) - return ctx.getImageData(0,0,c.width,c.height) + return ctx.getImageData(0, 0, c.width, c.height) -Filters.getCanvas = (w,h) -> +Filters.getCanvas = (w, h) -> c = document.createElement('canvas') c.width = w c.height = h @@ -34,7 +34,7 @@ module.exports.darkenImage = darkenImage = (img, pct=0.5) -> return img.src = cachedValue if cachedValue jqimg.data('original', img.src) unless jqimg.data('original') if not (img.naturalWidth > 0 and img.naturalHeight > 0) - console.warn "Tried to darken image", img, "but it has natural dimensions", img.naturalWidth, img.naturalHeight + console.warn 'Tried to darken image', img, 'but it has natural dimensions', img.naturalWidth, img.naturalHeight return img imageData = Filters.filterImage(Filters.brightness, img, pct) c = Filters.getCanvas(img.naturalWidth, img.naturalHeight) diff --git a/app/lib/requireUtils.coffee b/app/lib/requireUtils.coffee index a79fe790c..66940517a 100644 --- a/app/lib/requireUtils.coffee +++ b/app/lib/requireUtils.coffee @@ -9,7 +9,7 @@ module.exports.getParentFolders = (subPath, urlPrefix='/test/') -> url: urlPrefix + parts.join('/') } paths - + module.exports.parseImmediateChildren = (allChildren, subPath, baseRequirePath='test/app/', urlPrefix='/test/') -> return [] unless allChildren folders = {} @@ -34,14 +34,14 @@ module.exports.parseImmediateChildren = (allChildren, subPath, baseRequirePath=' for name in _.keys(folders) children.push { - type:'folder', + type: 'folder', url: urlPrefix+name name: name+'/' size: folders[name] } for name in _.keys(files) children.push { - type:'file', + type: 'file', url: urlPrefix+name name: name } diff --git a/app/lib/scripts/DOMScriptModule.coffee b/app/lib/scripts/DOMScriptModule.coffee index a74af6930..041dbcc7c 100644 --- a/app/lib/scripts/DOMScriptModule.coffee +++ b/app/lib/scripts/DOMScriptModule.coffee @@ -15,8 +15,8 @@ module.exports = class DOMScriptModule extends ScriptModule endNotes: -> notes = [] - notes.push({ 'channel': 'end-level-highlight-dom' }) if @noteGroup.dom.highlight? - notes.push({ 'channel': 'level-enable-controls' }) if @noteGroup.dom.lock? + notes.push({'channel': 'end-level-highlight-dom'}) if @noteGroup.dom.highlight? + notes.push({'channel': 'level-enable-controls'}) if @noteGroup.dom.lock? return notes skipNotes: -> @@ -60,7 +60,7 @@ module.exports = class DOMScriptModule extends ScriptModule lock = @noteGroup.dom.lock event.controls = lock if _.isArray lock # array: subset of controls channel = if lock then 'level-disable-controls' else 'level-enable-controls' - return { channel: channel, event: event } + return {channel: channel, event: event} letterboxNote: -> - return { channel: 'level-set-letterbox', event: { on: @noteGroup.dom.letterbox } } \ No newline at end of file + return {channel: 'level-set-letterbox', event: {on: @noteGroup.dom.letterbox}} diff --git a/app/lib/scripts/ScriptManager.coffee b/app/lib/scripts/ScriptManager.coffee index ce0d5d583..0ba6ae9bd 100644 --- a/app/lib/scripts/ScriptManager.coffee +++ b/app/lib/scripts/ScriptManager.coffee @@ -76,10 +76,10 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass script.id = (idNum++).toString() unless script.id callback = makeCallback(script.channel) # curry in the channel argument @addNewSubscription(script.channel, callback) - + beginTicking: -> @tickInterval = setInterval @tick, 5000 - + tick: => scriptStates = {} now = new Date() @@ -87,7 +87,7 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass scriptStates[script.id] = timeSinceLastEnded: (if script.lastEnded then now - script.lastEnded else 0) / 1000 timeSinceLastTriggered: (if script.lastTriggered then now - script.lastTriggered else 0) / 1000 - + stateEvent = scriptRunning: @currentNoteGroup?.scriptID or '' noteGroupRunning: @currentNoteGroup?.name or '' @@ -123,7 +123,7 @@ module.exports = ScriptManager = class ScriptManager extends CocoClass for scriptID in scriptsToSkip script = _.find @scripts, {id: scriptID} unless script - console.warn "Couldn't find script for", scriptID, "from scripts", @scripts, "when restoring session scripts." + console.warn 'Couldn\'t find script for', scriptID, 'from scripts', @scripts, 'when restoring session scripts.' continue continue if script.repeats # repeating scripts are not 'rerun' @triggered.push(scriptID) diff --git a/app/lib/scripts/ScriptModule.coffee b/app/lib/scripts/ScriptModule.coffee index 52c4aab22..466e0ebc7 100644 --- a/app/lib/scripts/ScriptModule.coffee +++ b/app/lib/scripts/ScriptModule.coffee @@ -1,31 +1,31 @@ CocoClass = require 'lib/CocoClass' module.exports = class ScriptModule extends CocoClass - + scrubbingTime = 0 movementTime = 0 - + constructor: (@noteGroup) -> super() if not @noteGroup.prepared @analyzeNoteGroup(noteGroup) @noteGroup.notes ?= [] @noteGroup.prepared = true - + # subclass should overwrite these - + @neededFor: -> false startNotes: -> [] endNotes: -> [] skipNotes: -> @endNotes() - + # common logic - + analyzeNoteGroup: -> # some notes need to happen after others. Calculate the delays @movementTime = @calculateMovementMax(@noteGroup) @scrubbingTime = @noteGroup.playback?.scrub?.duration or 0 - + calculateMovementMax: -> sums = {} for sprite in @noteGroup.sprites @@ -36,4 +36,4 @@ module.exports = class ScriptModule extends CocoClass Math.max(0, sums...) maybeApplyDelayToNote: (note) -> - note.delay = (@scrubbingTime + @movementTime) or 0 \ No newline at end of file + note.delay = (@scrubbingTime + @movementTime) or 0 diff --git a/app/lib/scripts/SoundScriptModule.coffee b/app/lib/scripts/SoundScriptModule.coffee index 4c9282c2a..616c07f88 100644 --- a/app/lib/scripts/SoundScriptModule.coffee +++ b/app/lib/scripts/SoundScriptModule.coffee @@ -26,7 +26,7 @@ module.exports = class SoundScriptModule extends ScriptModule channel: 'level-suppress-selection-sounds' event: {suppress: @noteGroup.sound.suppressSelectionSounds} return note - + addMusicNote: -> note = channel: 'level-play-music' diff --git a/app/lib/scripts/SpriteScriptModule.coffee b/app/lib/scripts/SpriteScriptModule.coffee index 84585e0f3..bff0d3c28 100644 --- a/app/lib/scripts/SpriteScriptModule.coffee +++ b/app/lib/scripts/SpriteScriptModule.coffee @@ -45,7 +45,7 @@ module.exports = class SpritesScriptModule extends ScriptModule event: message: text blurb: blurb - mood: sprite.say.mood or "explain" + mood: sprite.say.mood or 'explain' responses: responses spriteID: sprite.id sound: sound diff --git a/app/lib/services/facebook.coffee b/app/lib/services/facebook.coffee index bc4834c0b..e4e08d52d 100644 --- a/app/lib/services/facebook.coffee +++ b/app/lib/services/facebook.coffee @@ -1,42 +1,42 @@ module.exports = initializeFacebook = -> # Additional JS functions here window.fbAsyncInit = -> - Backbone.Mediator.publish "fbapi-loaded" FB.init - appId: (if document.location.origin is "http://localhost:3000" then "607435142676437" else "148832601965463") # App ID - channelUrl: document.location.origin + "/channel.html" # Channel File + appId: (if document.location.origin is 'http://localhost:3000' then '607435142676437' else '148832601965463') # App ID + channelUrl: document.location.origin + '/channel.html' # Channel File status: true # check login status cookie: true # enable cookies to allow the server to access the session xfbml: true # parse XFBML - + Backbone.Mediator.publish 'fbapi-loaded' + # This is fired for any auth related change, such as login, logout or session refresh. - FB.Event.subscribe "auth.authResponseChange", (response) -> - - # Here we specify what we do with the response anytime this event occurs. - if response.status is "connected" - + FB.Event.subscribe 'auth.authResponseChange', (response) -> + + # Here we specify what we do with the response anytime this event occurs. + if response.status is 'connected' + # They have logged in to the app. - Backbone.Mediator.publish "facebook-logged-in", + Backbone.Mediator.publish 'facebook-logged-in', response: response - else if response.status is "not_authorized" + else if response.status is 'not_authorized' # else - # + # # Load the SDK asynchronously ((d) -> js = undefined - id = "facebook-jssdk" - ref = d.getElementsByTagName("script")[0] + id = 'facebook-jssdk' + ref = d.getElementsByTagName('script')[0] return if d.getElementById(id) - js = d.createElement("script") + js = d.createElement('script') js.id = id js.async = true - js.src = "//connect.facebook.net/en_US/all.js" - - #js.src = "//connect.facebook.net/en_US/all/debug.js"; + js.src = '//connect.facebook.net/en_US/all.js' + + #js.src = '//connect.facebook.net/en_US/all/debug.js' ref.parentNode.insertBefore js, ref return ) document diff --git a/app/lib/services/filepicker.coffee b/app/lib/services/filepicker.coffee index 2c16b48bd..d3b0f6c9b 100644 --- a/app/lib/services/filepicker.coffee +++ b/app/lib/services/filepicker.coffee @@ -1,15 +1,15 @@ module.exports = initializeFilepicker = -> ((a) -> - return if window.filepicker - b = a.createElement("script") - b.type = "text/javascript" + return if window.filepicker + b = a.createElement('script') + b.type = 'text/javascript' b.async = not 0 - b.src = ((if "https:" is a.location.protocol then "https:" else "http:")) + "//api.filepicker.io/v1/filepicker.js" - c = a.getElementsByTagName("script")[0] + b.src = ((if 'https:' is a.location.protocol then 'https:' else 'http:')) + '//api.filepicker.io/v1/filepicker.js' + c = a.getElementsByTagName('script')[0] c.parentNode.insertBefore b, c d = {} d._queue = [] - e = "pick,pickMultiple,pickAndStore,read,write,writeUrl,export,convert,store,storeUrl,remove,stat,setKey,constructWidget,makeDropPane".split(",") + e = 'pick,pickMultiple,pickAndStore,read,write,writeUrl,export,convert,store,storeUrl,remove,stat,setKey,constructWidget,makeDropPane'.split(',') f = (a, b) -> -> b.push [ diff --git a/app/lib/services/google.coffee b/app/lib/services/google.coffee index cf8e14af0..0e470a375 100644 --- a/app/lib/services/google.coffee +++ b/app/lib/services/google.coffee @@ -1,16 +1,16 @@ module.exports = initializeGoogle = -> window.onGPlusLoaded = -> - Backbone.Mediator.publish "gapi-loaded" + Backbone.Mediator.publish 'gapi-loaded' return window.signinCallback = (authResult) -> - Backbone.Mediator.publish "gplus-logged-in", authResult if authResult["access_token"] + Backbone.Mediator.publish 'gplus-logged-in', authResult if authResult['access_token'] return (-> - po = document.createElement("script") - po.type = "text/javascript" + po = document.createElement('script') + po.type = 'text/javascript' po.async = true - po.src = "https://apis.google.com/js/client:plusone.js?onload=onGPlusLoaded" - s = document.getElementsByTagName("script")[0] + po.src = 'https://apis.google.com/js/client:plusone.js?onload=onGPlusLoaded' + s = document.getElementsByTagName('script')[0] s.parentNode.insertBefore po, s return )() diff --git a/app/lib/services/linkedin.coffee b/app/lib/services/linkedin.coffee index 094f8eedb..9a6f0b37f 100644 --- a/app/lib/services/linkedin.coffee +++ b/app/lib/services/linkedin.coffee @@ -1,6 +1,6 @@ module.exports = initializeLinkedIn = -> window.linkedInAsyncInit = -> - console.log "Linkedin async init success!" + console.log 'Linkedin async init success!' Backbone.Mediator.publish 'linkedin-loaded' linkedInSnippet = diff --git a/app/lib/services/olark.coffee b/app/lib/services/olark.coffee index e0189da1c..c91f3a89f 100644 --- a/app/lib/services/olark.coffee +++ b/app/lib/services/olark.coffee @@ -2,9 +2,9 @@ module.exports = initializeOlark = -> window.olark or ((c) -> # s = -> a.P r @@ -19,7 +19,7 @@ module.exports = initializeOlark = -> while q-- ((n) -> f[z][n] = -> - f[z] "call", n, arguments + f[z] 'call', n, arguments return return @@ -31,67 +31,67 @@ module.exports = initializeOlark = -> a.p[u] = new Date - a.p[0] return - (if f.addEventListener then f.addEventListener(r, s, false) else f.attachEvent("on" + r, s)) + (if f.addEventListener then f.addEventListener(r, s, false) else f.attachEvent('on' + r, s)) ld = -> p = (hd) -> - hd = "head" + hd = 'head' [ - "<" + '<' hd - "><" + '><' i - " onl" + "oad=\"var d=" + ' onl' + 'oad=\"var d=' g ";d.getElementsByTagName('head')[0]." j - "(d." + '(d.' h "('script'))." k "='" l - "//" + '//' a.l "'" - "\"" - ">" - ].join "" - i = "body" + '>' + ].join '' + i = 'body' m = d[i] return setTimeout(ld, 100) unless m a.P 1 - j = "appendChild" - h = "createElement" - k = "src" - n = d[h]("div") + j = 'appendChild' + h = 'createElement' + k = 'src' + n = d[h]('div') v = n[j](d[h](z)) - b = d[h]("iframe") - g = "document" - e = "domain" + b = d[h]('iframe') + g = 'document' + e = 'domain' o = undefined - n.style.display = "none" + n.style.display = 'none' m.insertBefore(n, m.firstChild).id = z - b.frameBorder = "0" - b.id = z + "-loader" - b.src = "javascript:false" if /MSIE[ ]+6/.test(navigator.userAgent) - b.allowTransparency = "true" + b.frameBorder = '0' + b.id = z + '-loader' + b.src = 'javascript:false' if /MSIE[ ]+6/.test(navigator.userAgent) + b.allowTransparency = 'true' v[j] b try b.contentWindow[g].open() catch w c[e] = d[e] - o = "javascript:var d=" + g + ".open();d.domain='" + d.domain + "';" - b[k] = o + "void(0);" + o = 'javascript:var d=' + g + ".open();d.domain='" + d.domain + "';" + b[k] = o + 'void(0);' try t = b.contentWindow[g] t.write p() t.close() catch x - b[k] = o + "d.write(\"" + p().replace(/"/g, String.fromCharCode(92) + "\"") + "\");d.close();" + b[k] = o + 'd.write(\"' + p().replace(/"/g, String.fromCharCode(92) + '\"') + '\");d.close();' a.P 2 return @@ -101,16 +101,15 @@ module.exports = initializeOlark = -> nt() return )( - loader: "static.olark.com/jsclient/loader0.js" - name: "olark" + loader: 'static.olark.com/jsclient/loader0.js' + name: 'olark' methods: [ - "configure" - "extend" - "declare" - "identify" + 'configure' + 'extend' + 'declare' + 'identify' ] ) - # custom configuration goes here (www.olark.com/documentation) - olark.identify "1451-787-10-5544" #]]> - + # custom configuration goes here (www.olark.com/documentation) + olark.identify '1451-787-10-5544' #]]> diff --git a/app/lib/services/segmentio.coffee b/app/lib/services/segmentio.coffee index afb156245..565959690 100644 --- a/app/lib/services/segmentio.coffee +++ b/app/lib/services/segmentio.coffee @@ -2,18 +2,18 @@ module.exports = initializeSegmentio = -> analytics = analytics or [] (-> e = [ - "identify" - "track" - "trackLink" - "trackForm" - "trackClick" - "trackSubmit" - "page" - "pageview" - "ab" - "alias" - "ready" - "group" + 'identify' + 'track' + 'trackLink' + 'trackForm' + 'trackClick' + 'trackSubmit' + 'page' + 'pageview' + 'ab' + 'alias' + 'ready' + 'group' ] t = (e) -> -> @@ -28,14 +28,13 @@ module.exports = initializeSegmentio = -> return )() analytics.load = (e) -> - t = document.createElement("script") - t.type = "text/javascript" + t = document.createElement('script') + t.type = 'text/javascript' t.async = not 0 - t.src = ((if "https:" is document.location.protocol then "https://" else "http://")) + "d2dq2ahtl5zl1z.cloudfront.net/analytics.js/v1/" + e + "/analytics.min.js" + t.src = ((if 'https:' is document.location.protocol then 'https://' else 'http://')) + 'd2dq2ahtl5zl1z.cloudfront.net/analytics.js/v1/' + e + '/analytics.min.js' - n = document.getElementsByTagName("script")[0] + n = document.getElementsByTagName('script')[0] n.parentNode.insertBefore t, n return - - analytics.load "jsjzx9n4d2" + analytics.load 'jsjzx9n4d2' diff --git a/app/lib/services/twitter.coffee b/app/lib/services/twitter.coffee index eaba1f36f..a78c9e748 100644 --- a/app/lib/services/twitter.coffee +++ b/app/lib/services/twitter.coffee @@ -2,11 +2,11 @@ module.exports = initializeTwitter = -> ((d, s, id) -> js = undefined fjs = d.getElementsByTagName(s)[0] - p = (if /^http:/.test(d.location) then "http" else "https") + p = (if /^http:/.test(d.location) then 'http' else 'https') unless d.getElementById(id) js = d.createElement(s) js.id = id - js.src = p + "://platform.twitter.com/widgets.js" + js.src = p + '://platform.twitter.com/widgets.js' fjs.parentNode.insertBefore js, fjs return - ) document, "script", "twitter-wjs" + ) document, 'script', 'twitter-wjs' diff --git a/app/lib/simulator/Simulator.coffee b/app/lib/simulator/Simulator.coffee index 6579a004a..fbc235d02 100644 --- a/app/lib/simulator/Simulator.coffee +++ b/app/lib/simulator/Simulator.coffee @@ -8,7 +8,6 @@ Aether.addGlobal 'Vector', require 'lib/world/vector' Aether.addGlobal '_', _ module.exports = class Simulator extends CocoClass - constructor: (@options) -> @options ?= {} _.extend @, Backbone.Events @@ -27,12 +26,12 @@ module.exports = class Simulator extends CocoClass fetchAndSimulateOneGame: (humanGameID, ogresGameID) => return if @destroyed $.ajax - url: "/queue/scoring/getTwoGames" - type: "POST" + url: '/queue/scoring/getTwoGames' + type: 'POST' parse: true data: - "humansGameID": humanGameID - "ogresGameID": ogresGameID + 'humansGameID': humanGameID + 'ogresGameID': ogresGameID error: (errorData) -> console.warn "There was an error fetching two games! #{JSON.stringify errorData}" success: (taskData) => @@ -71,31 +70,31 @@ module.exports = class Simulator extends CocoClass @god.createWorld @generateSpellsObject() handleSingleSimulationError: (error) -> - console.error "There was an error simulating a single game!", error + console.error 'There was an error simulating a single game!', error if @options.headlessClient and @options.simulateOnlyOneGame - console.log "GAMERESULT:tie" + console.log 'GAMERESULT:tie' process.exit(0) @cleanupAndSimulateAnotherTask() handleSingleSimulationInfiniteLoop: -> - console.log "There was an infinite loop in the single game!" + console.log 'There was an infinite loop in the single game!' if @options.headlessClient and @options.simulateOnlyOneGame - console.log "GAMERESULT:tie" + console.log 'GAMERESULT:tie' process.exit(0) @cleanupAndSimulateAnotherTask() processSingleGameResults: (simulationResults) -> taskResults = @formTaskResultsObject simulationResults - console.log "Processing results:", taskResults + console.log 'Processing results:', taskResults humanSessionRank = taskResults.sessions[0].metrics.rank ogreSessionRank = taskResults.sessions[1].metrics.rank if @options.headlessClient and @options.simulateOnlyOneGame if humanSessionRank is ogreSessionRank - console.log "GAMERESULT:tie" + console.log 'GAMERESULT:tie' else if humanSessionRank < ogreSessionRank - console.log "GAMERESULT:humans" + console.log 'GAMERESULT:humans' else if ogreSessionRank < humanSessionRank - console.log "GAMERESULT:ogres" + console.log 'GAMERESULT:ogres' process.exit(0) else @sendSingleGameBackToServer(taskResults) @@ -104,32 +103,31 @@ module.exports = class Simulator extends CocoClass @trigger 'statusUpdate', 'Simulation completed, sending results back to server!' $.ajax - url: "/queue/scoring/recordTwoGames" + url: '/queue/scoring/recordTwoGames' data: results - type: "PUT" + type: 'PUT' parse: true success: @handleTaskResultsTransferSuccess error: @handleTaskResultsTransferError complete: @cleanupAndSimulateAnotherTask - fetchAndSimulateTask: => return if @destroyed if @options.headlessClient if @dumpThisTime # The first heapdump would be useless to find leaks. - console.log "Writing snapshot." + console.log 'Writing snapshot.' @options.heapdump.writeSnapshot() @dumpThisTime = true if @options.heapdump if @options.testing - _.delay @setupSimulationAndLoadLevel, 0, @options.testFile, "Testing...", status: 400 + _.delay @setupSimulationAndLoadLevel, 0, @options.testFile, 'Testing...', status: 400 return @trigger 'statusUpdate', 'Fetching simulation data!' $.ajax url: @taskURL - type: "GET" + type: 'GET' parse: true error: @handleFetchTaskError success: @setupSimulationAndLoadLevel @@ -139,13 +137,12 @@ module.exports = class Simulator extends CocoClass @trigger 'statusUpdate', 'There was an error fetching games to simulate. Retrying in 10 seconds.' @simulateAnotherTaskAfterDelay() - handleNoGamesResponse: -> info = 'Finding game to simulate...' console.log info @trigger 'statusUpdate', info @fetchAndSimulateOneGame() - application.tracker?.trackEvent 'Simulator Result', label: "No Games", ['Google Analytics'] + application.tracker?.trackEvent 'Simulator Result', label: 'No Games', ['Google Analytics'] simulateAnotherTaskAfterDelay: => console.log "Retrying in #{@retryDelayInSeconds}" @@ -184,7 +181,7 @@ module.exports = class Simulator extends CocoClass try @commenceSimulationAndSetupCallback() catch err - console.error "There was an error in simulation:", err, "-- trying again in #{@retryDelayInSeconds} seconds" + console.error 'There was an error in simulation:', err, "-- trying again in #{@retryDelayInSeconds} seconds" @simulateAnotherTaskAfterDelay() assignWorldAndLevelFromLevelLoaderAndDestroyIt: -> @@ -205,11 +202,11 @@ module.exports = class Simulator extends CocoClass Backbone.Mediator.subscribeOnce 'god:goals-calculated', @processResults, @ @god.createWorld @generateSpellsObject() - #Search for leaks, headless-client only. + # Search for leaks, headless-client only. if @options.headlessClient and @options.leakTest and not @memwatch? leakcount = 0 maxleakcount = 0 - console.log "Setting leak callbacks." + console.log 'Setting leak callbacks.' @memwatch = require 'memwatch' @memwatch.on 'leak', (info) => @@ -220,17 +217,17 @@ module.exports = class Simulator extends CocoClass @hd = new @memwatch.HeapDiff() @memwatch.on 'stats', (stats) => - console.warn "stats callback: " + stats + console.warn 'stats callback: ' + stats diff = @hd.end() console.warn "HeapDiff:\n" + JSON.stringify(diff) if @options.exitOnLeak - console.warn "Exiting because of Leak." + console.warn 'Exiting because of Leak.' process.exit() @hd = new @memwatch.HeapDiff() onInfiniteLoop: -> - console.warn "Skipping infinitely looping game." + console.warn 'Skipping infinitely looping game.' @trigger 'statusUpdate', "Infinite loop detected; grabbing a new game in #{@retryDelayInSeconds} seconds." _.delay @cleanupAndSimulateAnotherTask, @retryDelayInSeconds * 1000 @@ -244,16 +241,16 @@ module.exports = class Simulator extends CocoClass sendResultsBackToServer: (results) -> @trigger 'statusUpdate', 'Simulation completed, sending results back to server!' - console.log "Sending result back to server:" + console.log 'Sending result back to server:' console.log JSON.stringify results if @options.headlessClient and @options.testing return @fetchAndSimulateTask() $.ajax - url: "/queue/scoring" + url: '/queue/scoring' data: results - type: "PUT" + type: 'PUT' parse: true success: @handleTaskResultsTransferSuccess error: @handleTaskResultsTransferError @@ -263,12 +260,12 @@ module.exports = class Simulator extends CocoClass return if @destroyed console.log "Task registration result: #{JSON.stringify result}" @trigger 'statusUpdate', 'Results were successfully sent back to server!' - console.log "Simulated by you:", @simulatedByYou + console.log 'Simulated by you:', @simulatedByYou @simulatedByYou++ unless @options.headlessClient simulatedBy = parseInt($('#simulated-by-you').text(), 10) + 1 $('#simulated-by-you').text(simulatedBy) - application.tracker?.trackEvent 'Simulator Result', label: "Success", ['Google Analytics'] + application.tracker?.trackEvent 'Simulator Result', label: 'Success', ['Google Analytics'] handleTaskResultsTransferError: (error) => return if @destroyed @@ -316,11 +313,11 @@ module.exports = class Simulator extends CocoClass humansWon = _.all humanGoals, {status: 'success'} if ogresWon is humansWon return 0 - else if ogresWon and teamSessionMap["ogres"] is sessionID + else if ogresWon and teamSessionMap['ogres'] is sessionID return 0 - else if ogresWon and teamSessionMap["ogres"] isnt sessionID + else if ogresWon and teamSessionMap['ogres'] isnt sessionID return 1 - else if humansWon and teamSessionMap["humans"] is sessionID + else if humansWon and teamSessionMap['humans'] is sessionID return 0 else return 1 @@ -376,14 +373,13 @@ module.exports = class Simulator extends CocoClass else spellSession = _.filter(@task.getSessions(), {team: spellTeam})[0] unless codeLanguage = spellSession?.submittedCodeLanguage - console.warn "Session", spellSession.creatorName, spellSession.team, "didn't have submittedCodeLanguage, just:", spellSession + console.warn 'Session', spellSession.creatorName, spellSession.team, 'didn\'t have submittedCodeLanguage, just:', spellSession @spells[spellKey].thangs[thang.id].aether = @createAether @spells[spellKey].name, method, useProtectAPI, codeLanguage ? 'javascript' - transpileSpell: (thang, spellKey, methodName) -> slugifiedThangID = _.string.slugify thang.id generatedSpellKey = [slugifiedThangID,methodName].join '/' - source = @currentUserCodeMap[generatedSpellKey] ? "" + source = @currentUserCodeMap[generatedSpellKey] ? '' aether = @spells[spellKey].thangs[thang.id].aether unless _.contains(@task.spellKeysToTranspile, generatedSpellKey) aether.pure = source @@ -399,22 +395,21 @@ module.exports = class Simulator extends CocoClass functionName: methodName protectAPI: useProtectAPI includeFlow: false - yieldConditionally: methodName is "plan" + yieldConditionally: methodName is 'plan' globals: ['Vector', '_'] problems: - jshint_W040: {level: "ignore"} - jshint_W030: {level: "ignore"} # aether_NoEffect instead + jshint_W040: {level: 'ignore'} + jshint_W030: {level: 'ignore'} # aether_NoEffect instead aether_MissingThis: {level: 'error'} #functionParameters: # TODOOOOO executionLimit: 1 * 1000 * 1000 language: codeLanguage if methodName is 'hear' then aetherOptions.functionParameters = ['speaker', 'message', 'data'] if methodName is 'makeBid' then aetherOptions.functionParameters = ['tileGroupLetter'] - if methodName is "findCentroids" then aetherOptions.functionParameters = ["centroids"] - #console.log "creating aether with options", aetherOptions + if methodName is 'findCentroids' then aetherOptions.functionParameters = ['centroids'] + #console.log 'creating aether with options', aetherOptions return new Aether aetherOptions - class SimulationTask constructor: (@rawData) -> @spellKeyToTeamMap = {} @@ -423,12 +418,12 @@ class SimulationTask getLevelName: -> levelName = @rawData.sessions?[0]?.levelID return levelName if levelName? - @throwMalformedTaskError "The level name couldn't be deduced from the task." + @throwMalformedTaskError 'The level name couldn\'t be deduced from the task.' generateTeamToSessionMap: -> teamSessionMap = {} for session in @rawData.sessions - @throwMalformedTaskError "Two players share the same team" if teamSessionMap[session.team]? + @throwMalformedTaskError 'Two players share the same team' if teamSessionMap[session.team]? teamSessionMap[session.team] = session.sessionID teamSessionMap @@ -450,7 +445,6 @@ class SimulationTask setWorld: (@world) -> - generateSpellKeyToSourceMap: -> playerTeams = _.pluck @rawData.sessions, 'team' spellKeyToSourceMap = {} @@ -469,7 +463,7 @@ class SimulationTask for thangName, thangSpells of session.transpiledCode for spellName, spell of thangSpells - fullSpellName = [thangName,spellName].join '/' + fullSpellName = [thangName, spellName].join '/' if _.contains(teamSpells, fullSpellName) teamCode[fullSpellName]=spell diff --git a/app/lib/sprites/SpriteBuilder.coffee b/app/lib/sprites/SpriteBuilder.coffee index d0e73f17d..88639fe0d 100644 --- a/app/lib/sprites/SpriteBuilder.coffee +++ b/app/lib/sprites/SpriteBuilder.coffee @@ -14,7 +14,7 @@ module.exports = class SpriteBuilder buildMovieClip: (animationName, movieClipArgs...) -> animData = @animationStore[animationName] unless animData - console.error "couldn't find animData from", @animationStore, "for", animationName + console.error 'couldn\'t find animData from', @animationStore, 'for', animationName return null locals = {} _.extend locals, @buildMovieClipShapes(animData.shapes) @@ -111,7 +111,7 @@ module.exports = class SpriteBuilder shape buildContainerFromStore: (containerKey) -> - console.error "Yo we don't have no", containerKey unless containerKey + console.error 'Yo we don\'t have no', containerKey unless containerKey contData = @containerStore[containerKey] cont = new createjs.Container() cont.initialize() @@ -182,5 +182,4 @@ module.exports = class SpriteBuilder continue if (not shape.fc?) or not(colors[shape.fc]) @colorMap[shapeKey] = hslToHex(colors[shape.fc]) - sum = (nums) -> _.reduce(nums, (s, num) -> s + num) diff --git a/app/lib/sprites/SpriteParser.coffee b/app/lib/sprites/SpriteParser.coffee index 0de48c013..ad6d74cb5 100644 --- a/app/lib/sprites/SpriteParser.coffee +++ b/app/lib/sprites/SpriteParser.coffee @@ -29,8 +29,8 @@ module.exports = class SpriteParser parse: (source) -> # Grab the library properties' width/height so we can subtract half of each from frame bounds properties = source.match(/.*lib\.properties = \{\n.*?width: (\d+),\n.*?height: (\d+)/im) - @width = parseInt(properties?[1] ? "0", 10) - @height = parseInt(properties?[2] ? "0", 10) + @width = parseInt(properties?[1] ? '0', 10) + @height = parseInt(properties?[2] ? '0', 10) options = {loc: false, range: true} ast = esprima.parse source, options @@ -60,7 +60,7 @@ module.exports = class SpriteParser continue if gotIt for c in localContainers if c.bn is bn - instructions.push { t: c.t, gn: c.gn } + instructions.push {t: c.t, gn: c.gn} break @addContainer {c: instructions, b: container.bounds}, container.name for movieClip in movieClips @@ -101,7 +101,7 @@ module.exports = class SpriteParser if not shortKey? shortKey = name if @thangType.containers[shortKey]? - shortKey = @animationName + ":" + name + shortKey = @animationName + ':' + name @thangType.containers[shortKey] = container @containerLongKeys[longKey] = shortKey @containerRenamings[name] = shortKey @@ -115,7 +115,7 @@ module.exports = class SpriteParser else shortKey = name if @thangType.animations[shortKey]? - shortKey = @animationName + ":" + name + shortKey = @animationName + ':' + name @thangType.animations[shortKey] = animation @animationLongKeys[longKey] = shortKey @animationRenamings[name] = shortKey @@ -173,7 +173,7 @@ module.exports = class SpriteParser frameBoundsRange = frameBoundsStatement.expression.right.range frameBoundsSource = @subSourceFromRange frameBoundsRange, source if frameBoundsSource.search(/\[rect/) is -1 # some other statement; we don't have multiframe bounds - console.log "Didn't have multiframe bounds for this movie clip." + console.log 'Didn\'t have multiframe bounds for this movie clip.' frameBounds = [nominalBounds] else lastRect = nominalBounds @@ -204,10 +204,10 @@ module.exports = class SpriteParser functionExpressions ### - this.shape_1.graphics.f("#605E4A").s().p("AAOD/IgOgaIAEhkIgmgdIgMgBIgPgFIgVgJQA1h9g8jXQAQAHAOASQAQAUAKAeQARAuAJBJQAHA/gBA5IAAADIACAfIAFARIACAGIAEAHIAHAHQAVAXAQAUQAUAaANAUIABACIgsgdIgggXIAAAnIABAwIgBgBg"); + this.shape_1.graphics.f('#605E4A').s().p('AAOD/IgOgaIAEhkIgmgdIgMgBIgPgFIgVgJQA1h9g8jXQAQAHAOASQAQAUAKAeQARAuAJBJQAHA/gBA5IAAADIACAfIAFARIACAGIAEAHIAHAHQAVAXAQAUQAUAaANAUIABACIgsgdIgggXIAAAnIABAwIgBgBg'); this.shape_1.sett(23.2,30.1); - this.shape.graphics.f().s("#000000").ss(0.1,1,1).p("AAAAAQAAAAAAAA"); + this.shape.graphics.f().s('#000000').ss(0.1,1,1).p('AAAAAQAAAAAAAA'); this.shape.sett(3.8,22.4); ### @@ -218,7 +218,7 @@ module.exports = class SpriteParser return unless node.type is 'NewExpression' and node.callee.property.name is 'Graphics' blockName = node.parent.parent.parent.id.name graphicsString = node.parent.parent.arguments[0].value - localGraphics.push({p:graphicsString, bn:blockName}) + localGraphics.push {p:graphicsString, bn:blockName} @walk block, null, gatherShapeDefinitions return localGraphics @@ -233,7 +233,7 @@ module.exports = class SpriteParser if not name name = node.parent?.parent?.id?.name return unless name and name.indexOf('mask') is 0 and node.property?.name is 'Shape' - shape = { bn: name, im: true } + shape = {bn: name, im: true} localShapes.push shape return return unless name.search('shape') is 0 and node.object.property?.name is 'graphics' @@ -243,14 +243,14 @@ module.exports = class SpriteParser linearGradientFill = @grabFunctionArguments linearGradientFillSource.replace(/.*?lf\(/, 'lf('), true else fillColor = fillCall.arguments[0]?.value ? null - console.error "What is this?! Not a fill!" unless fillCall.callee.property.name is 'f' + console.error 'What is this?! Not a fill!' unless fillCall.callee.property.name is 'f' strokeCall = node.parent.parent.parent.parent if strokeCall.object.callee.property.name is 'ls' linearGradientStrokeSource = @subSourceFromRange strokeCall.parent.range, source linearGradientStroke = @grabFunctionArguments linearGradientStrokeSource.replace(/.*?ls\(/, 'ls(').replace(/\).ss\(.*/, ')'), true else strokeColor = strokeCall.object.arguments?[0]?.value ? null - console.error "What is this?! Not a stroke!" unless strokeCall.object.callee.property.name is 's' + console.error 'What is this?! Not a stroke!' unless strokeCall.object.callee.property.name is 's' strokeStyle = null graphicsStatement = strokeCall.parent if strokeColor or linearGradientStroke @@ -264,7 +264,7 @@ module.exports = class SpriteParser drawEllipse = @grabFunctionArguments drawEllipseSource.replace(/.*?de\(/, 'de('), true else path = graphicsStatement.arguments?[0]?.value ? null - console.error "What is this?! Not a path!" unless graphicsStatement.callee.property.name is 'p' + console.error 'What is this?! Not a path!' unless graphicsStatement.callee.property.name is 'p' body = graphicsStatement.parent.parent.body graphicsStatementIndex = _.indexOf body, graphicsStatement.parent t = body[graphicsStatementIndex + 1].expression @@ -295,8 +295,8 @@ module.exports = class SpriteParser shape.fc = fillColor if fillColor shape.lf = linearGradientFill if linearGradientFill shape.ls = linearGradientStroke if linearGradientStroke - if name.search('shape') isnt -1 and shape.fc is "rgba(0,0,0,0.451)" and not shape.ss and not shape.sc - console.log "Skipping a shadow", name, shape, "because we're doing shadows separately now." + if name.search('shape') isnt -1 and shape.fc is 'rgba(0,0,0,0.451)' and not shape.ss and not shape.sc + console.log 'Skipping a shadow', name, shape, 'because we\'re doing shadows separately now.' return shapeKeys.push shapeKey = @addShape shape localShape = {bn: name, gn: shapeKey} @@ -372,17 +372,17 @@ module.exports = class SpriteParser return if name is 'get' and callExpressions.length # avoid Ease calls in the tweens flattenedRanges = _.flatten [a.range for a in node.arguments] range = [_.min(flattenedRanges), _.max(flattenedRanges)] - # Replace "this." references with just the "name" + # Replace 'this.' references with just the 'name' argsSource = @subSourceFromRange(range, source) argsSource = argsSource.replace(/mask/g, 'this.mask') # so the mask thing will be handled correctly as a blockName in the next line - argsSource = argsSource.replace(/this\.([a-z_0-9]+)/ig, '"$1"') # turns this.shape literal to "shape" string + argsSource = argsSource.replace(/this\.([a-z_0-9]+)/ig, '"$1"') # turns this.shape literal to 'shape' string argsSource = argsSource.replace(/cjs(.+)\)/, '"createjs$1)"') # turns cjs.Ease.get(0.5) args = eval "[#{argsSource}]" shadowTween = args[0]?.search?('shape') is 0 and not _.find(localShapes, bn: args[0]) - shadowTween = shadowTween or args[0]?.state?[0]?.t?.search?("shape") is 0 and not _.find(localShapes, bn: args[0].state[0].t) + shadowTween = shadowTween or args[0]?.state?[0]?.t?.search?('shape') is 0 and not _.find(localShapes, bn: args[0].state[0].t) if shadowTween - console.log "Skipping tween", name, argsSource, args, "from localShapes", localShapes, "presumably because it's a shadow we skipped." + console.log 'Skipping tween', name, argsSource, args, 'from localShapes', localShapes, 'presumably because it\'s a shadow we skipped.' return callExpressions.push {n: name, a: args} @walk node.parent.parent, null, gatherCallExpressions @@ -395,7 +395,7 @@ module.exports = class SpriteParser block = block.expression.object.right.body localArgs = [] gatherAddChildCalls = (node) => - return unless node.type is "Identifier" and node.name is "addChild" + return unless node.type is 'Identifier' and node.name is 'addChild' args = node.parent.parent.arguments args = (arg.property.name for arg in args) localArgs.push arg for arg in args @@ -427,18 +427,18 @@ var p; // shortcut to reference prototypes // Layer 7 this.shape = new cjs.Shape(); - this.shape.graphics.f("#4F6877").s().p("AgsAxQgSgVgB"); + this.shape.graphics.f('#4F6877').s().p('AgsAxQgSgVgB'); this.shape.setTransform(283.1,146.1); // Layer 7 2 this.shape_1 = new cjs.Shape(); - this.shape_1.graphics.f("rgba(255,255,255,0.4)").s().p("ArTs0QSMB7EbVGQhsBhiGBHQjg1IvVkhg"); + this.shape_1.graphics.f('rgba(255,255,255,0.4)').s().p('ArTs0QSMB7EbVGQhsBhiGBHQjg1IvVkhg'); this.shape_1.setTransform(400.2,185.5); this.timeline.addTween(cjs.Tween.get({}).to({state:[]}).to({state:[{t:this.shape}]},7).to({state:[]},2).wait(6)); // Wing - this.instance_9 = new lib.Wing_Animation("synched",0); + this.instance_9 = new lib.Wing_Animation('synched',0); this.instance_9.setTransform(313.9,145.6,1,1,0,0,0,49,-83.5); this.timeline.addTween(cjs.Tween.get(this.instance_9).to({y:128,startPosition:7},7).wait(1)); @@ -455,11 +455,11 @@ p.nominalBounds = new cjs.Rectangle(7.1,48.9,528.7,431.1); // Isolation Mode this.shape = new cjs.Shape(); - this.shape.graphics.f("#1D2226").s().p("AgVAwQgUgdgN"); + this.shape.graphics.f('#1D2226').s().p('AgVAwQgUgdgN'); this.shape.setTransform(75,25.8); this.shape_1 = new cjs.Shape(); - this.shape_1.graphics.f("#1D2226").s().p("AgnBXQACABAF"); + this.shape_1.graphics.f('#1D2226').s().p('AgnBXQACABAF'); this.shape_1.setTransform(80.8,22); this.addChild(this.shape_1,this.shape); @@ -471,15 +471,15 @@ p.nominalBounds = new cjs.Rectangle(5.8,0,87.9,85); // Layer 1 this.shape = new cjs.Shape(); - this.shape.graphics.f("#DBDDBC").s().p("Ag3BeQgCgRA"); + this.shape.graphics.f('#DBDDBC').s().p('Ag3BeQgCgRA'); this.shape.setTransform(10.6,19.7,1.081,1.081); this.shape_1 = new cjs.Shape(); - this.shape_1.graphics.f("#1D2226").s().p("AB4CDQgGg"); + this.shape_1.graphics.f('#1D2226').s().p('AB4CDQgGg'); this.shape_1.setTransform(19.9,17.6,1.081,1.081); this.shape_2 = new cjs.Shape(); - this.shape_2.graphics.f("#605E4A").s().p("AiECbQgRg"); + this.shape_2.graphics.f('#605E4A').s().p('AiECbQgRg'); this.shape_2.setTransform(19.5,18.4,1.081,1.081); this.addChild(this.shape_2,this.shape_1,this.shape); diff --git a/app/lib/surface/Camera.coffee b/app/lib/surface/Camera.coffee index cfbea59fb..4a65f52db 100644 --- a/app/lib/surface/Camera.coffee +++ b/app/lib/surface/Camera.coffee @@ -8,7 +8,7 @@ d2r = (degrees) -> degrees / 180 * Math.PI MAX_ZOOM = 8 MIN_ZOOM = 0.1 DEFAULT_ZOOM = 2.0 -DEFAULT_TARGET = {x:0, y:0} +DEFAULT_TARGET = {x: 0, y: 0} DEFAULT_TIME = 1000 STANDARD_ZOOM_WIDTH = 924 STANDARD_ZOOM_HEIGHT = 589 @@ -78,7 +78,7 @@ module.exports = class Camera extends CocoClass console.log "Restricted given horizontal field of view to #{r2d(hFOV)} to #{r2d(@hFOV)}." @vFOV = 2 * Math.atan(Math.tan(@hFOV / 2) * @canvasHeight / @canvasWidth) if @vFOV > Math.PI - console.log "Vertical field of view problem: expected canvas not to be taller than it is wide with high field of view." + console.log 'Vertical field of view problem: expected canvas not to be taller than it is wide with high field of view.' @vFOV = Math.PI - epsilon calculateAxisConversionFactors: -> @@ -210,9 +210,9 @@ module.exports = class Camera extends CocoClass right = Math.max(worldBounds[0].x, worldBounds[1].x) bottom -= 1 if top is bottom right += 1 if left is right - p1 = @worldToSurface({x:left, y:top}) - p2 = @worldToSurface({x:right, y:bottom}) - {x:p1.x, y:p1.y, width:p2.x-p1.x, height:p2.y-p1.y} + p1 = @worldToSurface({x: left, y: top}) + p2 = @worldToSurface({x: right, y: bottom}) + {x: p1.x, y: p1.y, width: p2.x-p1.x, height: p2.y-p1.y} calculateMinMaxZoom: -> # Zoom targets are always done in Surface coordinates. @@ -314,6 +314,7 @@ module.exports = class Camera extends CocoClass lock: -> @target = @currentTarget @locked = true + unlock: -> @locked = false diff --git a/app/lib/surface/CameraBorder.coffee b/app/lib/surface/CameraBorder.coffee index e315a25d8..16e7fbfe0 100644 --- a/app/lib/surface/CameraBorder.coffee +++ b/app/lib/surface/CameraBorder.coffee @@ -25,6 +25,6 @@ module.exports = class CameraBorder extends createjs.Container i = width while i opacity = 3 * (1 - (i/width)) / width - @border.graphics.setStrokeStyle(i,"round").beginStroke("rgba(0,0,0,#{opacity})").drawRect(bounds.x, bounds.y, bounds.width, bounds.height) + @border.graphics.setStrokeStyle(i, 'round').beginStroke("rgba(0,0,0,#{opacity})").drawRect(bounds.x, bounds.y, bounds.width, bounds.height) i -= 1 @border.cache bounds.x, bounds.y, bounds.width, bounds.height diff --git a/app/lib/surface/CastingScreen.coffee b/app/lib/surface/CastingScreen.coffee index be4ac1f79..63eea858e 100644 --- a/app/lib/surface/CastingScreen.coffee +++ b/app/lib/surface/CastingScreen.coffee @@ -11,21 +11,21 @@ module.exports = class CastingScreen extends CocoClass options ?= {} @camera = options.camera @layer = options.layer - console.error @toString(), "needs a camera." unless @camera - console.error @toString(), "needs a layer." unless @layer + console.error @toString(), 'needs a camera.' unless @camera + console.error @toString(), 'needs a layer.' unless @layer @build() onCastingBegins: (e) -> @show() unless e.preload onCastingEnds: (e) -> @hide() - toString: -> "" + toString: -> '' build: -> @dimLayer = new createjs.Container() @dimLayer.mouseEnabled = @dimLayer.mouseChildren = false @dimLayer.layerIndex = -11 @dimLayer.addChild @dimScreen = new createjs.Shape() - @dimScreen.graphics.beginFill("rgba(0,0,0,0.5)").rect 0, 0, @camera.canvasWidth, @camera.canvasHeight + @dimScreen.graphics.beginFill('rgba(0,0,0,0.5)').rect 0, 0, @camera.canvasWidth, @camera.canvasHeight @dimLayer.alpha = 0 @layer.addChild @dimLayer @dimLayer.addChild @makeProgressBar() @@ -34,7 +34,7 @@ module.exports = class CastingScreen extends CocoClass onWorldLoadProgressChanged: (e) -> if new Date().getTime() - @t0 > 500 createjs.Tween.removeTweens @progressBar - createjs.Tween.get(@progressBar).to({scaleX:e.progress}, 200) + createjs.Tween.get(@progressBar).to({scaleX: e.progress}, 200) makeProgressBar: -> BAR_PIXEL_HEIGHT = 3 @@ -44,8 +44,8 @@ module.exports = class CastingScreen extends CocoClass barY = 3 * (@camera.canvasHeight / 5) g = new createjs.Graphics() - g.beginFill(createjs.Graphics.getRGB(255,255, 255)) - g.drawRoundRect(0,0,pixelWidth, BAR_PIXEL_HEIGHT, 3) + g.beginFill(createjs.Graphics.getRGB(255, 255, 255)) + g.drawRoundRect(0, 0, pixelWidth, BAR_PIXEL_HEIGHT, 3) @progressBar = new createjs.Shape(g) @progressBar.x = pixelMargin @progressBar.y = barY @@ -54,7 +54,7 @@ module.exports = class CastingScreen extends CocoClass makeCastingText: -> size = @camera.canvasHeight / 15 - text = new createjs.Text("Casting", "#{size}px cursive", "#aaaaaa") + text = new createjs.Text('Casting', "#{size}px cursive", '#aaaaaa') text.regX = text.getMeasuredWidth() / 2 text.regY = text.getMeasuredHeight() / 2 text.x = @camera.canvasWidth / 2 @@ -70,7 +70,7 @@ module.exports = class CastingScreen extends CocoClass @progressBar.scaleX = 0 @dimLayer.alpha = 0 createjs.Tween.removeTweens @dimLayer - createjs.Tween.get(@dimLayer).to({alpha:1}, 500) + createjs.Tween.get(@dimLayer).to({alpha: 1}, 500) hide: -> return unless @showing @@ -78,4 +78,4 @@ module.exports = class CastingScreen extends CocoClass createjs.Tween.removeTweens @progressBar createjs.Tween.removeTweens @dimLayer - createjs.Tween.get(@dimLayer).to({alpha:0}, 500) + createjs.Tween.get(@dimLayer).to({alpha: 0}, 500) diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee index 4dc818a6d..1f18a4f6b 100644 --- a/app/lib/surface/CocoSprite.coffee +++ b/app/lib/surface/CocoSprite.coffee @@ -65,7 +65,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass super() @options = _.extend($.extend(true, {}, @options), options) @setThang @options.thang - console.error @toString(), "has no ThangType!" unless @thangType + console.error @toString(), 'has no ThangType!' unless @thangType # this is a stub, use @setImageObject to swap it out for something else later @imageObject = new createjs.Container @@ -94,7 +94,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass else result = @buildSpriteSheet() if _.isString result # async build - @listenToOnce @thangType, 'build-complete', @setupSprite + @listenToOnce @thangType, 'build-complete', @setupSprite else @stillLoading = false @actions = @thangType.getActions() @@ -171,7 +171,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass onSurfaceTicked: (e) -> @age += e.dt playNextAction: => - @playAction(@actionQueue.splice(0,1)[0]) if @actionQueue.length + @playAction(@actionQueue.splice(0, 1)[0]) if @actionQueue.length playAction: (action) -> return if @isRaster @@ -180,7 +180,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass @show() @updateBaseScale() return @updateActionDirection() unless action.animation or action.container - m = if action.container then "gotoAndStop" else "gotoAndPlay" + m = if action.container then 'gotoAndStop' else 'gotoAndPlay' @imageObject.framerate = action.framerate or 20 @imageObject[m] action.name reg = @getOffset 'registration' @@ -235,7 +235,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass @handledDisplayEvents[event] = true args = JSON.parse(event[4...]) - pos = @options.camera.worldToSurface {x:args[0], y:args[1]} + pos = @options.camera.worldToSurface {x: args[0], y: args[1]} circle = new createjs.Shape() circle.graphics.beginFill(args[3]).drawCircle(0, 0, args[2]*Camera.PPM) circle.x = pos.x @@ -270,18 +270,17 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass window.labels.push label label.alpha = 0 createjs.Tween.get(label) - .to({y:label.y-2, alpha:1}, 200, createjs.Ease.linear) - .to({y:label.y-12}, 1000, createjs.Ease.linear) - .to({y:label.y-22, alpha:0}, 1000, createjs.Ease.linear) + .to({y: label.y-2, alpha: 1}, 200, createjs.Ease.linear) + .to({y: label.y-12}, 1000, createjs.Ease.linear) + .to({y: label.y-22, alpha: 0}, 1000, createjs.Ease.linear) .call => return if @destroyed @options.floatingLayer.removeChild label - cache: -> bounds = @imageObject.getBounds() @imageObject.cache 0, 0, bounds.width, bounds.height - #console.log "just cached", @thang.id, "which was at", @imageObject.x, @imageObject.y, bounds.width, bounds.height, "with scale", Math.max(@imageObject.scaleX, @imageObject.scaleY) + #console.log 'just cached', @thang.id, 'which was at', @imageObject.x, @imageObject.y, bounds.width, bounds.height, 'with scale', Math.max(@imageObject.scaleX, @imageObject.scaleY) getBobOffset: -> return 0 unless @thang.bobHeight @@ -351,14 +350,14 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass angle = 180 - angle if angle > 90 scaleX = 0.5 + 0.5 * (90 - angle) / 90 -# console.error "No thang for", @ unless @thang +# console.error 'No thang for', @ unless @thang # TODO: support using scaleFactorX/Y from the thang object @imageObject.scaleX = @baseScaleX * @scaleFactor * scaleX @imageObject.scaleY = @baseScaleY * @scaleFactor * scaleY if @thang and (@thang.scaleFactor or 1) isnt @targetScaleFactor createjs.Tween.removeTweens(@) - createjs.Tween.get(@).to({scaleFactor:@thang.scaleFactor or 1}, 2000, createjs.Ease.elasticOut) + createjs.Tween.get(@).to({scaleFactor: @thang.scaleFactor or 1}, 2000, createjs.Ease.elasticOut) @targetScaleFactor = @thang.scaleFactor or 1 updateAlpha: -> @@ -410,7 +409,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass action = @determineAction() isDifferent = action isnt @currentRootAction or action is null if not action and @thang?.actionActivated and not @stopLogging - console.error "action is", action, "for", @thang?.id, "from", @currentRootAction, @thang.action, @thang.getActionName?() + console.error 'action is', action, 'for', @thang?.id, 'from', @currentRootAction, @thang.action, @thang.getActionName?() @stopLogging = true @queueAction(action) if action and (isDifferent or (@thang?.actionActivated and action.name isnt 'move')) @updateActionDirection() @@ -439,7 +438,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass rootAction ?= @currentRootAction return null unless relatedActions = rootAction?.relatedActions ? {} rotation = @getRotation() - if relatedActions["111111111111"] # has grid-surrounding-wall-based actions + if relatedActions['111111111111'] # has grid-surrounding-wall-based actions if @wallGrid action = '' tileSize = 4 @@ -452,25 +451,25 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass wallThangs = ['outside of the map yo'] if wallThangs.length is 0 if y is gy and x is gx - action += "1" # the center wall we're placing + action += '1' # the center wall we're placing else - action += "0" + action += '0' else if wallThangs.length is 1 - action += "1" + action += '1' else - console.error "Overlapping walls at", x, y, "...", wallThangs - action += "1" + console.error 'Overlapping walls at', x, y, '...', wallThangs + action += '1' matchedAction = '111111111111' for relatedAction of relatedActions if action.match(relatedAction.replace(/\?/g, '.')) matchedAction = relatedAction break - #console.log "returning", matchedAction, "for", @thang.id, "at", gx, gy + #console.log 'returning', matchedAction, 'for', @thang.id, 'at', gx, gy return relatedActions[matchedAction] else keys = _.keys relatedActions index = Math.max 0, Math.floor((179 + rotation) / 360 * keys.length) - #console.log "Showing", relatedActions[keys[index]] + #console.log 'Showing', relatedActions[keys[index]] return relatedActions[keys[index]] value = Math.abs(rotation) direction = null @@ -510,8 +509,8 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass Backbone.Mediator.publish ourEventName, newEvent addHealthBar: -> - return unless @thang?.health? and "health" in (@thang?.hudProperties ? []) and @options.floatingLayer - healthColor = healthColors[@thang?.team] ? healthColors["neutral"] + return unless @thang?.health? and 'health' in (@thang?.hudProperties ? []) and @options.floatingLayer + healthColor = healthColors[@thang?.team] ? healthColors['neutral'] healthOffset = @getOffset 'aboveHead' bar = @healthBar = createProgressBar(healthColor, healthOffset) bar.name = 'health bar' @@ -660,7 +659,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass sound = e.sound ? AudioPlayer.soundForDialogue e.message, @thangType.get 'soundTriggers' @instance?.stop() if @instance = @playSound sound, false - @instance.addEventListener "complete", -> Backbone.Mediator.publish 'dialogue-sound-completed' + @instance.addEventListener 'complete', -> Backbone.Mediator.publish 'dialogue-sound-completed' @notifySpeechUpdated e onClearDialogue: (e) -> @@ -714,7 +713,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass delay = if withDelay and sound.delay then 1000 * sound.delay / createjs.Ticker.getFPS() else 0 name = AudioPlayer.nameForSoundReference sound instance = AudioPlayer.playSound name, volume, delay, @getWorldPosition() - #console.log @thang?.id, "played sound", name, "with delay", delay, "volume", volume, "and got sound instance", instance + #console.log @thang?.id, 'played sound', name, 'with delay', delay, 'volume', volume, 'and got sound instance', instance instance onMove: (e) -> @@ -723,7 +722,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass if _.isArray pos pos = new Vector pos... else if _.isString pos - return console.warn "Couldn't find target sprite", pos, "from", @options.sprites unless pos of @options.sprites + return console.warn 'Couldn\'t find target sprite', pos, 'from', @options.sprites unless pos of @options.sprites target = @options.sprites[pos].thang heading = Vector.subtract(target.pos, @thang.pos).normalize() distance = @thang.pos.distance target.pos @@ -766,7 +765,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass @lastTween = createjs.Tween .get(@shadow.pos) - .to({x:pos.x, y:pos.y}, duration, ease) + .to({x: pos.x, y: pos.y}, duration, ease) .call(endFunc) pointToward: (pos) -> diff --git a/app/lib/surface/CoordinateDisplay.coffee b/app/lib/surface/CoordinateDisplay.coffee index 032574983..448671ce3 100644 --- a/app/lib/surface/CoordinateDisplay.coffee +++ b/app/lib/surface/CoordinateDisplay.coffee @@ -11,7 +11,7 @@ module.exports = class CoordinateDisplay extends createjs.Container super() @initialize() @camera = options.camera - console.error "CoordinateDisplay needs camera." unless @camera + console.error 'CoordinateDisplay needs camera.' unless @camera @build() @show = _.debounce @show, 125 Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions @@ -24,10 +24,10 @@ module.exports = class CoordinateDisplay extends createjs.Container build: -> @mouseEnabled = @mouseChildren = false @addChild @background = new createjs.Shape() - @addChild @label = new createjs.Text("", "bold 16px Arial", "#FFFFFF") + @addChild @label = new createjs.Text('', 'bold 16px Arial', '#FFFFFF') @label.name = 'Coordinate Display Text' - @label.shadow = new createjs.Shadow("#000000", 1, 1, 0) - @background.name = "Coordinate Display Background" + @label.shadow = new createjs.Shadow('#000000', 1, 1, 0) + @background.name = 'Coordinate Display Background' onMouseOver: (e) -> @mouseInBounds = true onMouseOut: (e) -> @mouseInBounds = false @@ -71,8 +71,8 @@ module.exports = class CoordinateDisplay extends createjs.Container @label.regY = @background.regY = height / 2 - margin @background.graphics .clear() - .beginFill("rgba(0, 0, 0, 0.4)") - .beginStroke("rgba(0, 0, 0, 0.6)") + .beginFill('rgba(0,0,0,0.4)') + .beginStroke('rgba(0,0,0,0.6)') .setStrokeStyle(1) .drawRoundRect(0, 0, width, height, radius) .endFill() diff --git a/app/lib/surface/DebugDisplay.coffee b/app/lib/surface/DebugDisplay.coffee index a53059bf4..da287e6ed 100644 --- a/app/lib/surface/DebugDisplay.coffee +++ b/app/lib/surface/DebugDisplay.coffee @@ -8,7 +8,7 @@ module.exports = class DebugDisplay extends createjs.Container @initialize() @canvasWidth = options.canvasWidth @canvasHeight = options.canvasHeight - console.error "DebugDisplay needs canvasWidth/Height." unless @canvasWidth and @canvasHeight + console.error 'DebugDisplay needs canvasWidth/Height.' unless @canvasWidth and @canvasHeight @build() @onSetDebug debug: true Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions @@ -25,7 +25,7 @@ module.exports = class DebugDisplay extends createjs.Container build: -> @mouseEnabled = @mouseChildren = false - @addChild @frameText = new createjs.Text "...", "20px Arial", "#FFF" + @addChild @frameText = new createjs.Text '...', '20px Arial', '#FFF' @frameText.name = 'frame text' @frameText.x = @canvasWidth - 50 @frameText.y = @canvasHeight - 25 @@ -41,5 +41,5 @@ module.exports = class DebugDisplay extends createjs.Container @lastFrameSecondStart = time @framesRenderedThisSecond = 0 - @frameText.text = Math.round(currentFrame) + (if @fps? then " - " + @fps + ' fps' else '') + @frameText.text = Math.round(currentFrame) + (if @fps? then ' - ' + @fps + ' fps' else '') @frameText.x = @canvasWidth - @frameText.getMeasuredWidth() - 10 diff --git a/app/lib/surface/Dimmer.coffee b/app/lib/surface/Dimmer.coffee index 566df7af4..a34740468 100644 --- a/app/lib/surface/Dimmer.coffee +++ b/app/lib/surface/Dimmer.coffee @@ -14,14 +14,14 @@ module.exports = class Dimmer extends CocoClass options ?= {} @camera = options.camera @layer = options.layer - console.error @toString(), "needs a camera." unless @camera - console.error @toString(), "needs a layer." unless @layer + console.error @toString(), 'needs a camera.' unless @camera + console.error @toString(), 'needs a layer.' unless @layer @build() @updateDimMask = _.throttle @updateDimMask, 10 @highlightedThangIDs = [] @sprites = {} - toString: -> "" + toString: -> '' build: -> @dimLayer = new createjs.Container() @@ -29,7 +29,7 @@ module.exports = class Dimmer extends CocoClass @dimLayer.layerIndex = -10 @dimLayer.addChild @dimScreen = new createjs.Shape() @dimLayer.addChild @dimMask = new createjs.Shape() - @dimScreen.graphics.beginFill("rgba(0,0,0,0.5)").rect 0, 0, @camera.canvasWidth, @camera.canvasHeight + @dimScreen.graphics.beginFill('rgba(0,0,0,0.5)').rect 0, 0, @camera.canvasWidth, @camera.canvasHeight @dimMask.compositeOperation = 'destination-out' @dimLayer.cache 0, 0, @camera.canvasWidth, @camera.canvasHeight @@ -70,6 +70,6 @@ module.exports = class Dimmer extends CocoClass sup = x: sprite.imageObject.x, y: sprite.imageObject.y cap = @camera.surfaceToCanvas sup r = 50 * @camera.zoom # TODO: find better way to get the radius based on the sprite's size - @dimMask.graphics.beginRadialGradientFill(["rgba(0,0,0,1)", "rgba(0,0,0,0)"], [0.5, 1], cap.x, cap.y, 0, cap.x, cap.y, r).drawCircle(cap.x, cap.y, r) + @dimMask.graphics.beginRadialGradientFill(['rgba(0,0,0,1)', 'rgba(0,0,0,0)'], [0.5, 1], cap.x, cap.y, 0, cap.x, cap.y, r).drawCircle(cap.x, cap.y, r) @dimLayer.updateCache 0, 0, @camera.canvasWidth, @camera.canvasHeight diff --git a/app/lib/surface/Dropper.coffee b/app/lib/surface/Dropper.coffee index 3dae5b7db..e7ea3c6cd 100644 --- a/app/lib/surface/Dropper.coffee +++ b/app/lib/surface/Dropper.coffee @@ -25,5 +25,4 @@ Dropper = class Dropper drop: -> return @drop_counter > 0 - module.exports = new Dropper() diff --git a/app/lib/surface/Label.coffee b/app/lib/surface/Label.coffee index 92e19c140..959c92c13 100644 --- a/app/lib/surface/Label.coffee +++ b/app/lib/surface/Label.coffee @@ -1,9 +1,9 @@ CocoClass = require 'lib/CocoClass' module.exports = class Label extends CocoClass - @STYLE_DIALOGUE = "dialogue" # A speech bubble from a script - @STYLE_SAY = "say" # A piece of text generated from the world - @STYLE_NAME = "name" # A name like Scott set up for the Wizard + @STYLE_DIALOGUE = 'dialogue' # A speech bubble from a script + @STYLE_SAY = 'say' # A piece of text generated from the world + @STYLE_NAME = 'name' # A name like Scott set up for the Wizard # We might want to combine 'say' and 'name'; they're very similar # Nick designed 'say' based off of Scott's 'name' back when they were using two systems @@ -16,9 +16,9 @@ module.exports = class Label extends CocoClass @camera = options.camera @layer = options.layer @style = options.style ? Label.STYLE_SAY - console.error @toString(), "needs a sprite." unless @sprite - console.error @toString(), "needs a camera." unless @camera - console.error @toString(), "needs a layer." unless @layer + console.error @toString(), 'needs a sprite.' unless @sprite + console.error @toString(), 'needs a camera.' unless @camera + console.error @toString(), 'needs a layer.' unless @layer @setText options.text if options.text destroy: -> @@ -58,15 +58,15 @@ module.exports = class Label extends CocoClass st = {dialogue: 'D', say: 'S', name: 'N'}[@style] o.marginX = {D: 5, S: 6, N: 3}[st] o.marginY = {D: 6, S: 4, N: 3}[st] - o.fontWeight = {D: "bold", S: "bold", N: "bold"}[st] + o.fontWeight = {D: 'bold', S: 'bold', N: 'bold'}[st] o.shadow = {D: false, S: true, N: true}[st] - o.shadowColor = {D: "#FFF", S: "#000", N: "#FFF"}[st] + o.shadowColor = {D: '#FFF', S: '#000', N: '#FFF'}[st] o.fontSize = {D: 25, S: 12, N: 12}[st] - fontFamily = {D: "Arial", S: "Arial", N: "Arial"}[st] + fontFamily = {D: 'Arial', S: 'Arial', N: 'Arial'}[st] o.fontDescriptor = "#{o.fontWeight} #{o.fontSize}px #{fontFamily}" - o.fontColor = {D: "#000", S: "#FFF", N: "#00a"}[st] - o.backgroundFillColor = {D: "white", S: "rgba(0, 0, 0, 0.4)", N: "rgba(255, 255, 255, 0.5)"}[st] - o.backgroundStrokeColor = {D: "black", S: "rgba(0, 0, 0, .6)", N: "rgba(0, 0, 0, 0.0)"}[st] + o.fontColor = {D: '#000', S: '#FFF', N: '#00a'}[st] + o.backgroundFillColor = {D: 'white', S: 'rgba(0,0,0,0.4)', N: 'rgba(255,255,255,0.5)'}[st] + o.backgroundStrokeColor = {D: 'black', S: 'rgba(0,0,0,0.6)', N: 'rgba(0,0,0,0)'}[st] o.backgroundStrokeStyle = {D: 2, S: 1, N: 1}[st] o.backgroundBorderRadius = {D: 10, S: 3, N: 3}[st] o.layerPriority = {D: 10, S: 5, N: 5}[st] @@ -169,7 +169,7 @@ module.exports = class Label extends CocoClass textWidth = 0 for word in words row.push(word) - text = new createjs.Text(_.string.join(' ', row...), fontDescriptor, "#000") + text = new createjs.Text(_.string.join(' ', row...), fontDescriptor, '#000') width = text.getMeasuredWidth() if width > maxWidth if row.length is 1 # one long word, truncate it @@ -186,5 +186,5 @@ module.exports = class Label extends CocoClass textWidth = Math.max(textWidth, width) rows.push(row) if row.length for row, i in rows - rows[i] = _.string.join(" ", row...) + rows[i] = _.string.join(' ', row...) text: _.string.join("\n", rows...), textWidth: textWidth diff --git a/app/lib/surface/Layer.coffee b/app/lib/surface/Layer.coffee index 1e438a2ea..b148be49c 100644 --- a/app/lib/surface/Layer.coffee +++ b/app/lib/surface/Layer.coffee @@ -18,10 +18,10 @@ ### module.exports = class Layer extends createjs.Container - @TRANSFORM_CHILD = "child" # Layer transform is managed by its parents - @TRANSFORM_SURFACE = "surface" # Layer moves/scales/zooms with the Surface of the World - @TRANSFORM_SURFACE_TEXT = "surface_text" # Layer moves with the Surface but is size-independent - @TRANSFORM_SCREEN = "screen" # Layer stays fixed to the screen (different from child?) + @TRANSFORM_CHILD = 'child' # Layer transform is managed by its parents + @TRANSFORM_SURFACE = 'surface' # Layer moves/scales/zooms with the Surface of the World + @TRANSFORM_SURFACE_TEXT = 'surface_text' # Layer moves with the Surface but is size-independent + @TRANSFORM_SCREEN = 'screen' # Layer stays fixed to the screen (different from child?) subscriptions: 'camera:zoom-updated': 'onZoomUpdated' @@ -30,11 +30,11 @@ module.exports = class Layer extends createjs.Container super() @initialize() options ?= {} - @name = options.name ? "Unnamed" + @name = options.name ? 'Unnamed' @layerPriority = options.layerPriority ? 0 @transformStyle = options.transform ? Layer.TRANSFORM_CHILD @camera = options.camera - console.error @toString(), "needs a camera." unless @camera + console.error @toString(), 'needs a camera.' unless @camera @updateLayerOrder = _.throttle @updateLayerOrder, 1000 / 30 # Don't call multiple times in one frame; 30 FPS is probably good enough Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions @@ -60,7 +60,7 @@ module.exports = class Layer extends createjs.Container child.scaleY *= @scaleY updateLayerOrder: => - #console.log @, @toString(), "sorting children", _.clone @children if @name is 'Default' + #console.log @, @toString(), 'sorting children', _.clone @children if @name is 'Default' @sortChildren @layerOrderComparator layerOrderComparator: (a, b) -> diff --git a/app/lib/surface/Letterbox.coffee b/app/lib/surface/Letterbox.coffee index c5d2f86b7..1e829d3df 100644 --- a/app/lib/surface/Letterbox.coffee +++ b/app/lib/surface/Letterbox.coffee @@ -1,5 +1,4 @@ module.exports = class Letterbox extends createjs.Container - subscriptions: 'level-set-letterbox': 'onSetLetterbox' @@ -8,7 +7,7 @@ module.exports = class Letterbox extends createjs.Container @initialize() @canvasWidth = options.canvasWidth @canvasHeight = options.canvasHeight - console.error "Letterbox needs canvasWidth/Height." unless @canvasWidth and @canvasHeight + console.error 'Letterbox needs canvasWidth/Height.' unless @canvasWidth and @canvasHeight @build() Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions @@ -16,7 +15,7 @@ module.exports = class Letterbox extends createjs.Container @mouseEnabled = @mouseChildren = false @matteHeight = 0.10 * @canvasHeight @upperMatte = new createjs.Shape() - @upperMatte.graphics.beginFill("black").rect(0, 0, @canvasWidth, @matteHeight) + @upperMatte.graphics.beginFill('black').rect(0, 0, @canvasWidth, @matteHeight) @lowerMatte = @upperMatte.clone() @upperMatte.x = @lowerMatte.x = 0 @upperMatte.y = -@matteHeight diff --git a/app/lib/surface/Mark.coffee b/app/lib/surface/Mark.coffee index f5e640154..54853f506 100644 --- a/app/lib/surface/Mark.coffee +++ b/app/lib/surface/Mark.coffee @@ -15,9 +15,9 @@ module.exports = class Mark extends CocoClass @camera = options.camera @layer = options.layer @thangType = options.thangType - console.error @toString(), "needs a name." unless @name - console.error @toString(), "needs a camera." unless @camera - console.error @toString(), "needs a layer." unless @layer + console.error @toString(), 'needs a name.' unless @name + console.error @toString(), 'needs a camera.' unless @camera + console.error @toString(), 'needs a layer.' unless @layer @build() destroy: -> @@ -58,7 +58,7 @@ module.exports = class Mark extends CocoClass else if @name is 'debug' then @buildDebug() else if @name.match(/.+(Range|Distance|Radius)$/) then @buildRadius(@name) else if @thangType then @buildSprite() - else console.error "Don't know how to build mark for", @name + else console.error 'Don\'t know how to build mark for', @name @mark?.mouseEnabled = false @ @@ -77,7 +77,7 @@ module.exports = class Mark extends CocoClass shape.graphics.setStrokeStyle 5 shape.graphics.beginStroke color shape.graphics.beginFill color.replace('0.5', '0.25') - if @sprite.thang.shape in ["ellipsoid", "disc"] + if @sprite.thang.shape in ['ellipsoid', 'disc'] shape.drawEllipse 0, 0, w, h else shape.graphics.drawRect -w / 2, -h / 2, w, h @@ -86,20 +86,20 @@ module.exports = class Mark extends CocoClass @mark.addChild shape if @sprite.thang.drawsBoundsStyle is 'border-text' - text = new createjs.Text "" + @drawsBoundsIndex, "20px Arial", color.replace('0.5', '1') + text = new createjs.Text '' + @drawsBoundsIndex, '20px Arial', color.replace('0.5', '1') text.regX = text.getMeasuredWidth() / 2 text.regY = text.getMeasuredHeight() / 2 - text.shadow = new createjs.Shadow("#000000", 1, 1, 0) + text.shadow = new createjs.Shadow('#000000', 1, 1, 0) @mark.addChild text else if @sprite.thang.drawsBoundsStyle is 'corner-text' return if @sprite.thang.world.age is 0 - letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[@drawsBoundsIndex % 26] - text = new createjs.Text letter, "14px Arial", "#333333" # color.replace('0.5', '1') + letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[@drawsBoundsIndex % 26] + text = new createjs.Text letter, '14px Arial', '#333333' # color.replace('0.5', '1') text.x = -w / 2 + 2 text.y = -h / 2 + 2 @mark.addChild text else - console.warn @sprite.thang.id, "didn't know how to draw bounds style:", @sprite.thang.drawsBoundsStyle + console.warn @sprite.thang.id, 'didn\'t know how to draw bounds style:', @sprite.thang.drawsBoundsStyle if w > 0 and h > 0 @mark.cache -w / 2, -h / 2, w, h, 2 @@ -118,7 +118,7 @@ module.exports = class Mark extends CocoClass height *= Camera.PPM * @camera.y2x # TODO: doesn't work with rotation @mark = new createjs.Shape() @mark.mouseEnabled = false - @mark.graphics.beginFill "rgba(0, 0, 0, #{alpha})" + @mark.graphics.beginFill "rgba(0,0,0,#{alpha})" if @sprite.thang.shape in ['ellipsoid', 'disc'] @mark.graphics.drawEllipse 0, 0, width, height else @@ -132,16 +132,16 @@ module.exports = class Mark extends CocoClass buildRadius: (range) -> alpha = 0.15 colors = - voiceRange: "rgba(0, 145, 0, #{alpha})" - visualRange: "rgba(0, 0, 145, #{alpha})" - attackRange: "rgba(145, 0, 0, #{alpha})" + voiceRange: "rgba(0,145,0,#{alpha})" + visualRange: "rgba(0,0,145,#{alpha})" + attackRange: "rgba(145,0,0,#{alpha})" # Fallback colors which work on both dungeon and grass tiles extraColors = [ - "rgba(145, 0, 145, #{alpha})" - "rgba(0, 145, 145, #{alpha})" - "rgba(145, 105, 0, #{alpha})" - "rgba(225, 125, 0, #{alpha})" + "rgba(145,0,145,#{alpha})" + "rgba(0,145,145,#{alpha})" + "rgba(145,105,0,#{alpha})" + "rgba(225,125,0,#{alpha})" ] # Find the index of this range, to find the next-smallest radius @@ -179,7 +179,7 @@ module.exports = class Mark extends CocoClass [w, h] = [Math.max(PX, @sprite.thang.width * Camera.PPM), Math.max(PX, @sprite.thang.height * Camera.PPM) * @camera.y2x] @mark.alpha = 0.5 @mark.graphics.beginFill '#abcdef' - if @sprite.thang.shape in ["ellipsoid", "disc"] + if @sprite.thang.shape in ['ellipsoid', 'disc'] [w, h] = [Math.max(PX, w, h), Math.max(PX, w, h)] @mark.graphics.drawCircle 0, 0, w / 2 else @@ -248,11 +248,11 @@ module.exports = class Mark extends CocoClass if @name is 'shadow' worldZ = @sprite.thang.pos.z - @sprite.thang.depth / 2 + @sprite.getBobOffset() @mark.alpha = @alpha * 0.451 / Math.sqrt(worldZ / 2 + 1) - else if @name isnt "bounds" + else if @name isnt 'bounds' @mark.alpha = @alpha updateRotation: -> - if @name is 'debug' or (@name is 'shadow' and @sprite.thang?.shape in ["rectangle", "box"]) + if @name is 'debug' or (@name is 'shadow' and @sprite.thang?.shape in ['rectangle', 'box']) @mark.rotation = @sprite.thang.rotation * 180 / Math.PI updateScale: -> @@ -271,7 +271,7 @@ module.exports = class Mark extends CocoClass @mark.scaleX = thang.scaleFactor ? thang.scaleFactorX ? 1 @mark.scaleY = thang.scaleFactor ? thang.scaleFactorY ? 1 - return unless @name in ["selection", "target", "repair", "highlight"] + return unless @name in ['selection', 'target', 'repair', 'highlight'] # scale these marks to 10m (100px). Adjust based on sprite size. factor = 0.3 # default size: 3m width, most commonly for target when pointing to a location diff --git a/app/lib/surface/MusicPlayer.coffee b/app/lib/surface/MusicPlayer.coffee index ac31992c7..e01f32372 100644 --- a/app/lib/surface/MusicPlayer.coffee +++ b/app/lib/surface/MusicPlayer.coffee @@ -25,7 +25,7 @@ module.exports = class MusicPlayer extends CocoClass if (not e.file) or src is @currentMusic?.src if e.play then @restartCurrentMusic() else @fadeOutCurrentMusic() return - + media = AudioPlayer.getStatus(src) if not media?.loaded AudioPlayer.preloadSound(src) @@ -35,23 +35,23 @@ module.exports = class MusicPlayer extends CocoClass @standingBy = null @fadeOutCurrentMusic() @startNewMusic(src) if e.play - + restartCurrentMusic: -> return unless @currentMusic @currentMusic.play('none', 0, 0, -1, 0.3) @updateMusicVolume() - + fadeOutCurrentMusic: -> return unless @currentMusic f = -> @stop() - createjs.Tween.get(@currentMusic).to({volume:0.0}, CROSSFADE_LENGTH).call(f) - + createjs.Tween.get(@currentMusic).to({volume: 0.0}, CROSSFADE_LENGTH).call(f) + startNewMusic: (src) -> @currentMusic = createjs.Sound.play(src, 'none', 0, 0, -1, 0.3) if src return unless @currentMusic @currentMusic.volume = 0.0 if me.get('music') - createjs.Tween.get(@currentMusic).to({volume:1.0}, CROSSFADE_LENGTH) + createjs.Tween.get(@currentMusic).to({volume: 1.0}, CROSSFADE_LENGTH) onMusicSettingChanged: -> @updateMusicVolume() @@ -64,4 +64,3 @@ module.exports = class MusicPlayer extends CocoClass destroy: -> me.off 'change:music', @onMusicSettingChanged, @ super() - \ No newline at end of file diff --git a/app/lib/surface/PlaybackOverScreen.coffee b/app/lib/surface/PlaybackOverScreen.coffee index dba87def5..9bf05fe7b 100644 --- a/app/lib/surface/PlaybackOverScreen.coffee +++ b/app/lib/surface/PlaybackOverScreen.coffee @@ -6,18 +6,18 @@ module.exports = class PlaybackOverScreen extends CocoClass options ?= {} @camera = options.camera @layer = options.layer - console.error @toString(), "needs a camera." unless @camera - console.error @toString(), "needs a layer." unless @layer + console.error @toString(), 'needs a camera.' unless @camera + console.error @toString(), 'needs a layer.' unless @layer @build() - toString: -> "" + toString: -> '' build: -> @dimLayer = new createjs.Container() @dimLayer.mouseEnabled = @dimLayer.mouseChildren = false @dimLayer.layerIndex = -12 @dimLayer.addChild @dimScreen = new createjs.Shape() - @dimScreen.graphics.beginFill("rgba(0,0,0,0.4)").rect 0, 0, @camera.canvasWidth, @camera.canvasHeight + @dimScreen.graphics.beginFill('rgba(0,0,0,0.4)').rect 0, 0, @camera.canvasWidth, @camera.canvasHeight @dimLayer.cache 0, 0, @camera.canvasWidth, @camera.canvasHeight @dimLayer.alpha = 0 @layer.addChild @dimLayer @@ -28,11 +28,11 @@ module.exports = class PlaybackOverScreen extends CocoClass @dimLayer.alpha = 0 createjs.Tween.removeTweens @dimLayer - createjs.Tween.get(@dimLayer).to({alpha:1}, 500) + createjs.Tween.get(@dimLayer).to({alpha: 1}, 500) hide: -> return unless @showing @showing = false createjs.Tween.removeTweens @dimLayer - createjs.Tween.get(@dimLayer).to({alpha:0}, 500) + createjs.Tween.get(@dimLayer).to({alpha: 0}, 500) diff --git a/app/lib/surface/PointChooser.coffee b/app/lib/surface/PointChooser.coffee index 2c8e598e5..88c61db98 100644 --- a/app/lib/surface/PointChooser.coffee +++ b/app/lib/surface/PointChooser.coffee @@ -19,12 +19,12 @@ module.exports = class PointChooser extends CocoClass @shape = new createjs.Shape() @shape.alpha = 0.9 @shape.mouseEnabled = false - @shape.graphics.setStrokeStyle(1, "round").beginStroke("#000000").beginFill('#fedcba') + @shape.graphics.setStrokeStyle(1, 'round').beginStroke('#000000').beginFill('#fedcba') @shape.graphics.drawCircle(0, 0, 4).endFill() @shape.layerIndex = 100 onMouseDown: (e) => - console.log "got stagemousedown", e, key.shift + console.log 'got stagemousedown', e, key.shift return unless key.shift @setPoint @options.camera.screenToWorld {x: e.stageX, y: e.stageY} Backbone.Mediator.publish 'choose-point', point: @point diff --git a/app/lib/surface/SpriteBoss.coffee b/app/lib/surface/SpriteBoss.coffee index bdf4d5005..1483481a7 100644 --- a/app/lib/surface/SpriteBoss.coffee +++ b/app/lib/surface/SpriteBoss.coffee @@ -51,12 +51,12 @@ module.exports = class SpriteBoss extends CocoClass createLayers: -> @spriteLayers = {} for [name, priority] in [ - ["Land", -40] - ["Ground", -30] - ["Obstacle", -20] - ["Path", -10] - ["Default", 0] - ["Floating", 10] + ['Land', -40] + ['Ground', -30] + ['Obstacle', -20] + ['Path', -10] + ['Default', 0] + ['Floating', 10] ] @spriteLayers[name] = new Layer name: name, layerPriority: priority, transform: Layer.TRANSFORM_CHILD, camera: @camera @surfaceLayer.addChild _.values(@spriteLayers)... @@ -66,36 +66,36 @@ module.exports = class SpriteBoss extends CocoClass # TODO: make better system child.layerPriority = 0 if sprite?.thang?.isSelectable child.layerPriority = -40 if sprite?.thang?.isLand - return @spriteLayers["Default"] unless child.layerPriority + return @spriteLayers['Default'] unless child.layerPriority layer = _.findLast @spriteLayers, (layer, name) -> layer.layerPriority <= child.layerPriority - #console.log "layer for", child, "is", (layer ? @spriteLayers["Default"]) - layer ? @spriteLayers["Default"] + #console.log 'layer for', child, 'is', (layer ? @spriteLayers['Default']) + layer ? @spriteLayers['Default'] addSprite: (sprite, id=null, layer=null) -> id ?= sprite.thang.id - console.error "Sprite collision! Already have:", id if @sprites[id] + console.error 'Sprite collision! Already have:', id if @sprites[id] @sprites[id] = sprite @spriteArray.push sprite - layer ?= @spriteLayers["Obstacle"] if sprite.thang?.spriteName.search(/(dungeon|indoor).wall/i) isnt -1 + layer ?= @spriteLayers['Obstacle'] if sprite.thang?.spriteName.search(/(dungeon|indoor).wall/i) isnt -1 layer ?= @layerForChild sprite.imageObject, sprite layer.addChild sprite.imageObject layer.updateLayerOrder() sprite createMarks: -> - @targetMark = new Mark name: 'target', camera: @camera, layer: @spriteLayers["Ground"], thangType: 'target' - @selectionMark = new Mark name: 'selection', camera: @camera, layer: @spriteLayers["Ground"], thangType: 'selection' + @targetMark = new Mark name: 'target', camera: @camera, layer: @spriteLayers['Ground'], thangType: 'target' + @selectionMark = new Mark name: 'selection', camera: @camera, layer: @spriteLayers['Ground'], thangType: 'selection' createSpriteOptions: (options) -> - _.extend options, camera: @camera, resolutionFactor: 4, groundLayer: @spriteLayers["Ground"], textLayer: @surfaceTextLayer, floatingLayer: @spriteLayers["Floating"], spriteSheetCache: @spriteSheetCache, showInvisible: @options.showInvisible + _.extend options, camera: @camera, resolutionFactor: 4, groundLayer: @spriteLayers['Ground'], textLayer: @surfaceTextLayer, floatingLayer: @spriteLayers['Floating'], spriteSheetCache: @spriteSheetCache, showInvisible: @options.showInvisible createIndieSprites: (indieSprites, withWizards) -> unless @indieSprites @indieSprites = [] @indieSprites = (@createIndieSprite indieSprite for indieSprite in indieSprites) if indieSprites if withWizards and not @selfWizardSprite - @selfWizardSprite = @createWizardSprite thangID: "My Wizard", isSelf: true, sprites: @sprites + @selfWizardSprite = @createWizardSprite thangID: 'My Wizard', isSelf: true, sprites: @sprites createIndieSprite: (indieSprite) -> unless thangType = @thangTypeFor indieSprite.thangType @@ -107,16 +107,16 @@ module.exports = class SpriteBoss extends CocoClass createOpponentWizard: (opponent) -> # TODO: colorize name and cloud by team, colorize wizard by user's color config, level-specific wizard spawn points sprite = @createWizardSprite thangID: opponent.id, name: opponent.name - if not opponent.levelSlug or opponent.levelSlug is "brawlwood" + if not opponent.levelSlug or opponent.levelSlug is 'brawlwood' sprite.targetPos = if opponent.team is 'ogres' then {x: 52, y: 52} else {x: 28, y: 28} - else if opponent.levelSlug is "dungeon-arena" - sprite.targetPos = if opponent.team is 'ogres' then {x:72, y: 39} else {x: 9, y:39} + else if opponent.levelSlug is 'dungeon-arena' + sprite.targetPos = if opponent.team is 'ogres' then {x: 72, y: 39} else {x: 9, y: 39} else - sprite.targetPos = if opponent.team is 'ogres' then {x:52, y: 28} else {x: 20, y:28} + sprite.targetPos = if opponent.team is 'ogres' then {x: 52, y: 28} else {x: 20, y: 28} createWizardSprite: (options) -> - sprite = new WizardSprite @thangTypeFor("Wizard"), @createSpriteOptions(options) - @addSprite sprite, sprite.thang.id, @spriteLayers["Floating"] + sprite = new WizardSprite @thangTypeFor('Wizard'), @createSpriteOptions(options) + @addSprite sprite, sprite.thang.id, @spriteLayers['Floating'] onPlayerJoined: (e) -> # Create another WizardSprite, unless this player is just me @@ -172,7 +172,7 @@ module.exports = class SpriteBoss extends CocoClass @adjustSpriteExistence() if frameChanged sprite.update frameChanged for sprite in @spriteArray @updateSelection() - @spriteLayers["Default"].updateLayerOrder() + @spriteLayers['Default'].updateLayerOrder() @cache() adjustSpriteExistence: -> @@ -184,11 +184,11 @@ module.exports = class SpriteBoss extends CocoClass else sprite = @addThangToSprites(thang) Backbone.Mediator.publish 'surface:new-thang-added', thang:thang, sprite:sprite - updateCache = updateCache or sprite.imageObject.parent is @spriteLayers["Obstacle"] + updateCache = updateCache or sprite.imageObject.parent is @spriteLayers['Obstacle'] sprite.playSounds() for thangID, sprite of @sprites missing = not (sprite.notOfThisWorld or @world.thangMap[thangID]?.exists) - isObstacle = sprite.imageObject.parent is @spriteLayers["Obstacle"] + isObstacle = sprite.imageObject.parent is @spriteLayers['Obstacle'] updateCache = updateCache or (isObstacle and (missing or sprite.hasMoved)) sprite.hasMoved = false @removeSprite sprite if missing @@ -210,11 +210,11 @@ module.exports = class SpriteBoss extends CocoClass wallSprite.updateScale() wallSprite.updatePosition() #console.log @wallGrid.toString() - @spriteLayers["Obstacle"].uncache() if @spriteLayers["Obstacle"].cacheID # might have changed sizes - @spriteLayers["Obstacle"].cache() + @spriteLayers['Obstacle'].uncache() if @spriteLayers['Obstacle'].cacheID # might have changed sizes + @spriteLayers['Obstacle'].cache() # test performance of doing land layer, too, to see if it's faster -# @spriteLayers["Land"].uncache() if @spriteLayers["Land"].cacheID # might have changed sizes -# @spriteLayers["Land"].cache() +# @spriteLayers['Land'].uncache() if @spriteLayers['Land'].cacheID # might have changed sizes +# @spriteLayers['Land'].cache() # I don't notice much difference - Scott @cached = true @@ -291,7 +291,6 @@ module.exports = class SpriteBoss extends CocoClass instance.addEventListener 'complete', -> Backbone.Mediator.publish 'thang-finished-talking', thang: sprite?.thang - # Marks updateSelection: -> diff --git a/app/lib/surface/Surface.coffee b/app/lib/surface/Surface.coffee index 75fd686a9..fd745d8ec 100644 --- a/app/lib/surface/Surface.coffee +++ b/app/lib/surface/Surface.coffee @@ -90,7 +90,7 @@ module.exports = Surface = class Surface extends CocoClass destroy: -> @dead = true @camera?.destroy() - createjs.Ticker.removeEventListener("tick", @tick) + createjs.Ticker.removeEventListener('tick', @tick) createjs.Sound.stop() layer.destroy() for layer in @layers @spriteBoss.destroy() @@ -160,12 +160,12 @@ module.exports = Surface = class Surface extends CocoClass addMeshRectanglesToContainer: (mesh, container) -> for rect in mesh shape = new createjs.Shape() - pos = @camera.worldToSurface {x:rect.x, y:rect.y} - dim = @camera.worldToSurface {x:rect.width, y:rect.height} + pos = @camera.worldToSurface {x: rect.x, y: rect.y} + dim = @camera.worldToSurface {x: rect.width, y: rect.height} shape.graphics .setStrokeStyle(3) - .beginFill('rgba(0, 0, 128, 0.3)') - .beginStroke('rgba(0, 0, 128, 0.7)') + .beginFill('rgba(0,0,128,0.3)') + .beginStroke('rgba(0,0,128,0.7)') .drawRect(pos.x - dim.x/2, pos.y - dim.y/2, dim.x, dim.y) container.addChild shape @@ -181,7 +181,7 @@ module.exports = Surface = class Surface extends CocoClass shape.graphics .setStrokeStyle(1) .moveTo(v1.x, v1.y) - .beginStroke('rgba(128, 0, 0, 0.4)') + .beginStroke('rgba(128,0,0,0.4)') .lineTo(v2.x, v2.y) .endStroke() container.addChild shape @@ -206,7 +206,7 @@ module.exports = Surface = class Surface extends CocoClass if scrubDuration t = createjs.Tween .get(@) - .to({currentFrame:@scrubbingTo}, scrubDuration, createjs.Ease.sineInOut) + .to({currentFrame: @scrubbingTo}, scrubDuration, createjs.Ease.sineInOut) .call(onTweenEnd) t.addEventListener('change', @onFramesScrubbed) else @@ -309,7 +309,7 @@ module.exports = Surface = class Surface extends CocoClass return if @currentFrame is @lastFrame and not force progress = @getProgress() Backbone.Mediator.publish('surface:frame-changed', - type: "frame-changed" + type: 'frame-changed' selectedThang: @spriteBoss.selectedSprite?.thang progress: progress frame: @currentFrame @@ -353,7 +353,7 @@ module.exports = Surface = class Surface extends CocoClass @setPaused false if @ended @casting = true @wasPlayingWhenCastingBegan = @playing - Backbone.Mediator.publish 'level-set-playing', { playing: false } + Backbone.Mediator.publish 'level-set-playing', {playing: false} @setPlayingCalled = false # don't overwrite playing settings if they changed by, say, scripts if @coordinateDisplay? @@ -361,7 +361,7 @@ module.exports = Surface = class Surface extends CocoClass @coordinateDisplay.destroy() createjs.Tween.removeTweens(@surfaceLayer) - createjs.Tween.get(@surfaceLayer).to({alpha:0.9}, 1000, createjs.Ease.getPowOut(4.0)) + createjs.Tween.get(@surfaceLayer).to({alpha: 0.9}, 1000, createjs.Ease.getPowOut(4.0)) onNewWorld: (event) -> return unless event.world.name is @world.name @@ -373,7 +373,7 @@ module.exports = Surface = class Surface extends CocoClass # This has a tendency to break scripts that are waiting for playback to change when the level is loaded # so only run it after the first world is created. - Backbone.Mediator.publish 'level-set-playing', { playing: @wasPlayingWhenCastingBegan } unless event.firstWorld or @setPlayingCalled + Backbone.Mediator.publish 'level-set-playing', {playing: @wasPlayingWhenCastingBegan} unless event.firstWorld or @setPlayingCalled fastForwardTo = null if @playing @@ -391,9 +391,9 @@ module.exports = Surface = class Surface extends CocoClass @setProgress fastForwardToRatio, 1000 * fastForwardToTime / fastForwardSpeed @fastForwarding = true createjs.Tween.get(@surfaceLayer) - .to({alpha:0.0}, 50) + .to({alpha: 0.0}, 50) .call(f) - .to({alpha:1.0}, 2000, createjs.Ease.getPowOut(2.0)) + .to({alpha: 1.0}, 2000, createjs.Ease.getPowOut(2.0)) # initialization @@ -405,9 +405,9 @@ module.exports = Surface = class Surface extends CocoClass @camera?.destroy() @camera = new Camera @canvas AudioPlayer.camera = @camera - @layers.push @surfaceLayer = new Layer name: "Surface", layerPriority: 0, transform: Layer.TRANSFORM_SURFACE, camera: @camera - @layers.push @surfaceTextLayer = new Layer name: "Surface Text", layerPriority: 1, transform: Layer.TRANSFORM_SURFACE_TEXT, camera: @camera - @layers.push @screenLayer = new Layer name: "Screen", layerPriority: 2, transform: Layer.TRANSFORM_SCREEN, camera: @camera + @layers.push @surfaceLayer = new Layer name: 'Surface', layerPriority: 0, transform: Layer.TRANSFORM_SURFACE, camera: @camera + @layers.push @surfaceTextLayer = new Layer name: 'Surface Text', layerPriority: 1, transform: Layer.TRANSFORM_SURFACE_TEXT, camera: @camera + @layers.push @screenLayer = new Layer name: 'Screen', layerPriority: 2, transform: Layer.TRANSFORM_SCREEN, camera: @camera @stage.addChild @layers... @surfaceLayer.addChild @cameraBorder = new CameraBorder bounds: @camera.bounds @screenLayer.addChild new Letterbox canvasWidth: canvasWidth, canvasHeight: canvasHeight @@ -449,7 +449,7 @@ module.exports = Surface = class Surface extends CocoClass @updateState true @drawCurrentFrame() @showGrid() if @options.grid # TODO: pay attention to world grid setting (which we only know when world simulates) - createjs.Ticker.addEventListener "tick", @tick + createjs.Ticker.addEventListener 'tick', @tick Backbone.Mediator.publish 'level:started' createOpponentWizard: (opponent) -> @@ -469,10 +469,10 @@ module.exports = Surface = class Surface extends CocoClass @gridLayer.z = 90019001 @gridLayer.mouseEnabled = false @gridShape.alpha = 0.125 - @gridShape.graphics.beginStroke "blue" + @gridShape.graphics.beginStroke 'blue' gridSize = Math.round(@world.size()[0] / 20) unless gridSize > 0.1 - return console.error "Grid size is", gridSize, "so we can't draw a grid." + return console.error 'Grid size is', gridSize, 'so we can\'t draw a grid.' wopStart = x: 0, y: 0 wopEnd = x: @world.size()[0], y: @world.size()[1] supStart = @camera.worldToSurface wopStart @@ -481,7 +481,7 @@ module.exports = Surface = class Surface extends CocoClass while wop.x < wopEnd.x sup = @camera.worldToSurface wop @gridShape.graphics.mt(sup.x, supStart.y).lt(sup.x, supEnd.y) - t = new createjs.Text(wop.x.toFixed(0), "16px Arial", "blue") + t = new createjs.Text(wop.x.toFixed(0), '16px Arial', 'blue') t.x = sup.x - t.getMeasuredWidth() / 2 t.y = supStart.y - 10 - t.getMeasuredHeight() / 2 t.alpha = 0.75 @@ -490,7 +490,7 @@ module.exports = Surface = class Surface extends CocoClass while wop.y < wopEnd.y sup = @camera.worldToSurface wop @gridShape.graphics.mt(supStart.x, sup.y).lt(supEnd.x, sup.y) - t = new createjs.Text(wop.y.toFixed(0), "16px Arial", "blue") + t = new createjs.Text(wop.y.toFixed(0), '16px Arial', 'blue') t.x = 10 - t.getMeasuredWidth() / 2 t.y = sup.y - t.getMeasuredHeight() / 2 t.alpha = 0.75 @@ -596,7 +596,7 @@ module.exports = Surface = class Surface extends CocoClass Backbone.Mediator.publish('surface:ticked', {dt: 1 / @options.frameRate}) mib = @stage.mouseInBounds if @mouseInBounds isnt mib - Backbone.Mediator.publish('surface:mouse-' + (if mib then "over" else "out"), {}) + Backbone.Mediator.publish('surface:mouse-' + (if mib then 'over' else 'out'), {}) @mouseInBounds = mib restoreWorldState: -> @@ -631,10 +631,10 @@ module.exports = Surface = class Surface extends CocoClass return if @world.showPaths is 'paused' and @playing return if @world.showPaths is 'selected' and not selectedThang @trailmaster ?= new path.Trailmaster @camera - selectedOnly = @playing and @world.showPaths is "selected" + selectedOnly = @playing and @world.showPaths is 'selected' @paths = @trailmaster.generatePaths @world, @getCurrentFrame(), selectedThang, @spriteBoss.sprites, selectedOnly @paths.name = 'paths' - @spriteBoss.spriteLayers["Path"].addChild @paths + @spriteBoss.spriteLayers['Path'].addChild @paths hidePaths: -> return if not @paths @@ -647,8 +647,8 @@ module.exports = Surface = class Surface extends CocoClass margin = (1 - 1 / zoom) / 2 @stage.cache margin * w, margin * h, w / zoom, h / zoom, scale * zoom imageData = @stage.cacheCanvas.toDataURL(format, quality) - #console.log "Screenshot with scale", scale, "format", format, "quality", quality, "was", Math.floor(imageData.length / 1024), "kB" - screenshot = document.createElement("img") + #console.log 'Screenshot with scale', scale, 'format', format, 'quality', quality, 'was', Math.floor(imageData.length / 1024), 'kB' + screenshot = document.createElement('img') screenshot.src = imageData @stage.uncache() imageData diff --git a/app/lib/surface/WizardSprite.coffee b/app/lib/surface/WizardSprite.coffee index b502cce4c..9c25c0c7f 100644 --- a/app/lib/surface/WizardSprite.coffee +++ b/app/lib/surface/WizardSprite.coffee @@ -63,7 +63,7 @@ module.exports = class WizardSprite extends IndieSprite continue unless state.wizard? @setColorHue state.wizard.wizardColor1 if targetID = state.wizard.targetSprite - return console.warn "Wizard Sprite couldn't find target sprite", targetID unless targetID of @options.sprites + return console.warn 'Wizard Sprite couldn\'t find target sprite', targetID unless targetID of @options.sprites @setTarget @options.sprites[targetID] else @setTarget state.wizard.targetPos @@ -129,7 +129,7 @@ module.exports = class WizardSprite extends IndieSprite @targetPos = @boundWizard targetPos @beginMoveTween(duration, isLinear) @shoveOtherWizards() - Backbone.Mediator.publish('self-wizard:target-changed', {sender:@}) if @isSelf + Backbone.Mediator.publish('self-wizard:target-changed', {sender: @}) if @isSelf boundWizard: (target) -> # Passed an {x, y} in world coordinates, returns {x, y} within world bounds @@ -168,7 +168,7 @@ module.exports = class WizardSprite extends IndieSprite createjs.Tween .get(@) - .to({tweenPercentage:0.0}, duration, ease) + .to({tweenPercentage: 0.0}, duration, ease) .call(@endMoveTween) @reachedTarget = false @update true @@ -176,7 +176,7 @@ module.exports = class WizardSprite extends IndieSprite shoveOtherWizards: (removeMe) -> return unless @targetSprite allWizards = [] - Backbone.Mediator.publish('echo-all-wizard-sprites', {payload:allWizards}) + Backbone.Mediator.publish('echo-all-wizard-sprites', {payload: allWizards}) allOfUs = (wizard for wizard in allWizards when wizard.targetSprite is @targetSprite) allOfUs = (wizard for wizard in allOfUs when wizard isnt @) if removeMe diff --git a/app/lib/surface/path.coffee b/app/lib/surface/path.coffee index d289faeed..05654f906 100644 --- a/app/lib/surface/path.coffee +++ b/app/lib/surface/path.coffee @@ -121,12 +121,12 @@ module.exports.Trailmaster = class Trailmaster return unless thang.allTargets g = new createjs.Graphics() g.setStrokeStyle(0.5) - g.beginStroke(createjs.Graphics.getRGB(0,0,0)) + g.beginStroke(createjs.Graphics.getRGB(0, 0, 0)) color = colorForThang(thang.team) i = 0 while i < thang.allTargets.length - g.beginStroke(createjs.Graphics.getRGB(0,0,0)) + g.beginStroke(createjs.Graphics.getRGB(0, 0, 0)) g.beginFill(createjs.Graphics.getRGB(color...)) sup = @camera.worldToSurface x: thang.allTargets[i], y: thang.allTargets[i + 1] g.drawEllipse(sup.x - 5, sup.y - 3, 10, 6) @@ -168,7 +168,7 @@ module.exports.Trailmaster = class Trailmaster clone.scaleY *= CLONE_SCALE if sprite.expandActions # old Sprite sprite.updateRotation(clone, sprite.data) - animActions = sprite.expandActions(if thang.acts then thang.getActionName() else "idle") + animActions = sprite.expandActions(if thang.acts then thang.getActionName() else 'idle') sprite.applyActionsToSprites(animActions, [clone], true) animation = clone.spriteSheet.getAnimation(clone.currentAnimation) clone.currentAnimationFrame = Math.min(@clock % (animation.frames.length * 3), animation.frames.length - 1) @@ -186,9 +186,6 @@ module.exports.Trailmaster = class Trailmaster @world.frames[@currentFrame].restoreStateForThang(thang) sprites - - - createPath = (points, options={}, g=null) -> options = options or {} tailColor = options.tailColor ? options.headColor @@ -290,5 +287,3 @@ colorForThang = (team, brightness=100, alpha=1.0) => return color module.exports.createPath = createPath - - diff --git a/app/lib/utils.coffee b/app/lib/utils.coffee index 8dbae8cc2..a63a1274d 100644 --- a/app/lib/utils.coffee +++ b/app/lib/utils.coffee @@ -1,5 +1,5 @@ module.exports.clone = (obj) -> - return obj if obj is null or typeof (obj) isnt "object" + return obj if obj is null or typeof (obj) isnt 'object' temp = obj.constructor() for key of obj temp[key] = module.exports.clone(obj[key]) @@ -25,7 +25,7 @@ module.exports.normalizeFunc = (func_thing, object) -> if _.isString(func_thing) func = object[func_thing] if not func - console.error("Could not find method", func_thing, 'in object', @) + console.error "Could not find method #{func_thing} in object #{@}" return => null # always return a func, or Mediator will go boom func_thing = func return func_thing @@ -36,7 +36,7 @@ module.exports.hexToHSL = (hex) -> hexToR = (h) -> parseInt (cutHex(h)).substring(0, 2), 16 hexToG = (h) -> parseInt (cutHex(h)).substring(2, 4), 16 hexToB = (h) -> parseInt (cutHex(h)).substring(4, 6), 16 -cutHex = (h) -> (if (h.charAt(0) is "#") then h.substring(1, 7) else h) +cutHex = (h) -> (if (h.charAt(0) is '#') then h.substring(1, 7) else h) module.exports.hslToHex = (hsl) -> '#' + (toHex(n) for n in hslToRgb(hsl...)).join('') @@ -57,10 +57,10 @@ module.exports.i18n = (say, target, language=me.lang(), fallback='en') -> if target of locale result = locale[target] else continue - return result if localeName == language - generalResult = result if localeName == generalName - fallbackResult = result if localeName == fallback - fallforwardResult = result if localeName.indexOf(language) == 0 and not fallforwardResult? + return result if localeName is language + generalResult = result if localeName is generalName + fallbackResult = result if localeName is fallback + fallforwardResult = result if localeName.indexOf(language) is 0 and not fallforwardResult? return generalResult if generalResult? return fallforwardResult if fallforwardResult? diff --git a/app/lib/world/GoalManager.coffee b/app/lib/world/GoalManager.coffee index b729ece4b..a758d9fc7 100644 --- a/app/lib/world/GoalManager.coffee +++ b/app/lib/world/GoalManager.coffee @@ -14,7 +14,7 @@ module.exports = class GoalManager extends CocoClass # If you want weird goals or hybrid goals, make a custom goal. nextGoalID: 0 - nicks: ["GoalManager"] + nicks: ['GoalManager'] constructor: (@world, @initialGoals, @team) -> super() @@ -134,9 +134,9 @@ module.exports = class GoalManager extends CocoClass } @initGoalState(state, [goal.killThangs, goal.saveThangs], 'killed') for getTo in goal.getAllToLocations ? [] - @initGoalState(state,[ getTo.getToLocation?.who , [] ], 'arrived') + @initGoalState(state, [getTo.getToLocation?.who, []], 'arrived') for keepFrom in goal.keepAllFromLocations ? [] - @initGoalState(state,[ [] , keepFrom.keepFromLocation?.who], 'arrived') + @initGoalState(state, [[], keepFrom.keepFromLocation?.who], 'arrived') @initGoalState(state, [goal.getToLocations?.who, goal.keepFromLocations?.who], 'arrived') @initGoalState(state, [goal.leaveOffSides?.who, goal.keepFromLeavingOffSides?.who], 'left') @initGoalState(state, [goal.collectThangs?.who, goal.keepFromCollectingThangs?.who], 'collected') @@ -229,8 +229,8 @@ module.exports = class GoalManager extends CocoClass if overallStatus = @checkOverallStatus true matchedGoals = (_.find(@goals, {id: goalID}) for goalID, goalState of @goalStates when goalState.status is overallStatus) mostEagerGoal = _.min matchedGoals, 'worldEndsAfter' - victory = overallStatus is "success" - tentative = overallStatus is "success" + victory = overallStatus is 'success' + tentative = overallStatus is 'success' @world.endWorld victory, mostEagerGoal.worldEndsAfter, tentative if mostEagerGoal isnt Infinity updateGoalState: (goalID, thangID, progressObjectName, frameNumber) -> @@ -244,20 +244,20 @@ module.exports = class GoalManager extends CocoClass if success numNeeded = goal.howMany ? Math.max(1, _.size stateThangs) else - # saveThangs: by default we would want to save all the Thangs, which means that we would want none of them to be "done" + # saveThangs: by default we would want to save all the Thangs, which means that we would want none of them to be 'done' numNeeded = _.size(stateThangs) - Math.max((goal.howMany ? 1), _.size stateThangs) + 1 numDone = _.filter(stateThangs).length - #console.log "needed", numNeeded, "done", numDone, "of total", _.size(stateThangs), "with how many", goal.howMany, "and stateThangs", stateThangs + #console.log 'needed', numNeeded, 'done', numDone, 'of total', _.size(stateThangs), 'with how many', goal.howMany, 'and stateThangs', stateThangs return unless numDone >= numNeeded return if state.status and not success # already failed it; don't wipe keyframe - state.status = if success then "success" else "failure" + state.status = if success then 'success' else 'failure' state.keyFrame = frameNumber - #console.log goalID, "became", success, "on frame", frameNumber, "with overallStatus", @checkOverallStatus true + #console.log goalID, 'became', success, 'on frame', frameNumber, 'with overallStatus', @checkOverallStatus true if overallStatus = @checkOverallStatus true matchedGoals = (_.find(@goals, {id: goalID}) for goalID, goalState of @goalStates when goalState.status is overallStatus) mostEagerGoal = _.min matchedGoals, 'worldEndsAfter' - victory = overallStatus is "success" - tentative = overallStatus is "success" + victory = overallStatus is 'success' + tentative = overallStatus is 'success' @world.endWorld victory, mostEagerGoal.worldEndsAfter, tentative if mostEagerGoal isnt Infinity goalIsPositive: (goalID) -> diff --git a/app/lib/world/Grid.coffee b/app/lib/world/Grid.coffee index cdf85547e..edd383bfc 100644 --- a/app/lib/world/Grid.coffee +++ b/app/lib/world/Grid.coffee @@ -31,7 +31,7 @@ module.exports = class Grid for y in @columns gy - height / 2, gy + height / 2 for x in @rows gx - width / 2, gx + width / 2 for thang in @grid[y][x] - thangs.push thang if thang.collides and not (thang in thangs) and thang.id isnt "Add Thang Phantom" + thangs.push thang if thang.collides and not (thang in thangs) and thang.id isnt 'Add Thang Phantom' thangs clampColumn: (y) -> @@ -51,4 +51,4 @@ module.exports = class Grid toString: -> upsideDown = _.clone @grid upsideDown.reverse() - (((if thangs.length then ("" + thangs.length) else " ") for thangs in row).join(" ") for row in upsideDown).join("\n") + (((if thangs.length then ('' + thangs.length) else ' ') for thangs in row).join(' ') for row in upsideDown).join("\n") diff --git a/app/lib/world/component.coffee b/app/lib/world/component.coffee index bbf0aa399..e0639b57b 100644 --- a/app/lib/world/component.coffee +++ b/app/lib/world/component.coffee @@ -1,7 +1,7 @@ componentKeywords = ['attach', 'constructor', 'validateArguments', 'toString', 'isComponent'] # Array is faster than object module.exports = class Component - @className: "Component" + @className: 'Component' isComponent: true constructor: (config) -> for key, value of config @@ -9,7 +9,7 @@ module.exports = class Component attach: (thang) -> # Optimize; this is much of the World constructor time - for key, value of @ when key not in componentKeywords and key[0] isnt "_" + for key, value of @ when key not in componentKeywords and key[0] isnt '_' oldValue = thang[key] if typeof oldValue is 'function' thang.appendMethod key, value diff --git a/app/lib/world/errors.coffee b/app/lib/world/errors.coffee index 32a5bc129..920db3251 100644 --- a/app/lib/world/errors.coffee +++ b/app/lib/world/errors.coffee @@ -1,23 +1,23 @@ Vector = require './vector' module.exports.ArgumentError = class ArgumentError extends Error - @className: "ArgumentError" + @className: 'ArgumentError' constructor: (@message, @functionName, @argumentName, @intendedType, @actualValue, @numArguments) -> super message - @name = "ArgumentError" + @name = 'ArgumentError' if Error.captureStackTrace? Error.captureStackTrace @, @constructor toString: -> s = "#{@functionName}" - if @argumentName is "return" + if @argumentName is 'return' s += "'s return value" - else if @argumentName is "_excess" + else if @argumentName is '_excess' s += " takes only #{@numArguments} argument#{if @numArguments > 1 then 's' else ''}." else if @argumentName s += "'s argument #{@argumentName}" else - s += " takes no arguments." + s += ' takes no arguments.' actualType = typeof @actualValue if not @actualValue? @@ -26,12 +26,12 @@ module.exports.ArgumentError = class ArgumentError extends Error actualType = 'array' typeMismatch = @intendedType and not @intendedType.match actualType if typeMismatch - v = "" + v = '' if actualType is 'string' v = "\"#{@actualValue}\"" - else if actualType is "number" + else if actualType is 'number' if Math.round(@actualValue) is @actualValue then @actualValue else @actualValue.toFixed(2) - else if actualType is "boolean" + else if actualType is 'boolean' v = "#{@actualValue}" else if (@actualValue? and @actualValue.id and @actualValue.trackedPropertiesKeys) # (Don't import Thang, but determine whether it is Thang.) @@ -40,7 +40,7 @@ module.exports.ArgumentError = class ArgumentError extends Error v = @actualValue.toString() showValue = showValue or @actualValue instanceof Vector s += " should have type #{@intendedType}, but got #{actualType}#{if v then ': ' + v else ''}." - else if @argumentName and @argumentName isnt "_excess" - s += " has a problem." + else if @argumentName and @argumentName isnt '_excess' + s += ' has a problem.' s += '\n' + @message if @message s diff --git a/app/lib/world/names.coffee b/app/lib/world/names.coffee index f8bb3a6b3..8cfa1a449 100644 --- a/app/lib/world/names.coffee +++ b/app/lib/world/names.coffee @@ -1,375 +1,375 @@ module.exports.thangNames = thangNames = - "Soldier M": [ - "Duke" - "William" - "Lucas" - "Marcus" - "Robert" - "Gordon" - "Kirin" - "Theo" - "Roger" - "Roderick" - "Samson" - "Silas" - "Richard" - "Max" - "Jax" - "Dax" - "Mischa" - "Ronald" - "Tyrone" - "Thelonious" - "Miles" - "Bill" - "Kumar" - "Ricardo" - "Maxwell" - "Jonah" - "Leopold" - "Phineas" - "Ferb" - "Felix" - "Ezra" - "Lucian" - "Augustus" - "Ronan" - "Pierce" - "Harry" - "Hirium" - "Hugo" - "Cecil" - "Barron" - "Huburt" - "Sterling" - "Alistair" - "Cid" - "Remy" - "Stormy" - "Halle" - "Sage" - "Ryan" - "Bond" + 'Soldier M': [ + 'Duke' + 'William' + 'Lucas' + 'Marcus' + 'Robert' + 'Gordon' + 'Kirin' + 'Theo' + 'Roger' + 'Roderick' + 'Samson' + 'Silas' + 'Richard' + 'Max' + 'Jax' + 'Dax' + 'Mischa' + 'Ronald' + 'Tyrone' + 'Thelonious' + 'Miles' + 'Bill' + 'Kumar' + 'Ricardo' + 'Maxwell' + 'Jonah' + 'Leopold' + 'Phineas' + 'Ferb' + 'Felix' + 'Ezra' + 'Lucian' + 'Augustus' + 'Ronan' + 'Pierce' + 'Harry' + 'Hirium' + 'Hugo' + 'Cecil' + 'Barron' + 'Huburt' + 'Sterling' + 'Alistair' + 'Cid' + 'Remy' + 'Stormy' + 'Halle' + 'Sage' + 'Ryan' + 'Bond' ] - "Soldier F": [ - "Sarah" - "Alexandra" - "Holly" - "Trinity" - "Nikita" - "Alana" - "Lana" - "Joan" - "Helga" - "Annie" - "Lukaz" - "Gorgin" - "Coco" - "Buffy" - "Allankrita" - "Kay" + 'Soldier F': [ + 'Sarah' + 'Alexandra' + 'Holly' + 'Trinity' + 'Nikita' + 'Alana' + 'Lana' + 'Joan' + 'Helga' + 'Annie' + 'Lukaz' + 'Gorgin' + 'Coco' + 'Buffy' + 'Allankrita' + 'Kay' ] - "Peasant M": [ - "Yorik" - "Hector" - "Thad" - "Victor" - "Lyle" - "Charles" - "Yusef" - "Hingle" - "Azgot" - "Piers" - "Carlton" - "Hershell" - "Gawain" - "Durfkor" - "Paps" - "Hodor" + 'Peasant M': [ + 'Yorik' + 'Hector' + 'Thad' + 'Victor' + 'Lyle' + 'Charles' + 'Yusef' + 'Hingle' + 'Azgot' + 'Piers' + 'Carlton' + 'Hershell' + 'Gawain' + 'Durfkor' + 'Paps' + 'Hodor' ] - "Peasant F": [ - "Hilda" - "Icey" - "Matilda" - "Mertia" - "Mary" - "Brandy" - "Gwendolin" - "Tabitha" - "Regan" - "Giselle" - "Bernadette" + 'Peasant F': [ + 'Hilda' + 'Icey' + 'Matilda' + 'Mertia' + 'Mary' + 'Brandy' + 'Gwendolin' + 'Tabitha' + 'Regan' + 'Giselle' + 'Bernadette' ] - "Archer F": [ - "Phoebe" - "Mira" - "Agapi" - "Cecily" - "Tansy" - "Ivy" - "Gemma" - "Keturah" - "Korra" - "Kim" - "Odette" - "Orly" - "Mercedes" - "Rosaline" - "Vesper" - "Beverly" - "Natalie" - "Clare" - "Rowan" - "Omar" - "Alden" - "Cairn" - "Jensen" - "Yilitha" - "Mirana" - "Lina" - "Luna" - "Alleria" - "Vereesa" - "Beatrice" + 'Archer F': [ + 'Phoebe' + 'Mira' + 'Agapi' + 'Cecily' + 'Tansy' + 'Ivy' + 'Gemma' + 'Keturah' + 'Korra' + 'Kim' + 'Odette' + 'Orly' + 'Mercedes' + 'Rosaline' + 'Vesper' + 'Beverly' + 'Natalie' + 'Clare' + 'Rowan' + 'Omar' + 'Alden' + 'Cairn' + 'Jensen' + 'Yilitha' + 'Mirana' + 'Lina' + 'Luna' + 'Alleria' + 'Vereesa' + 'Beatrice' ] - "Archer M": [ - "Brian" - "Cole" - "Roman" - "Hunter" - "Simon" - "Robin" - "Quinn" - "Arty" - "Gimsley" - "Fidsdale" - "Slyvos" - "Logos" - "Denin" - "Lycan" - "Loco" - "Vican" - "Mars" - "Dev" - "Oliver" + 'Archer M': [ + 'Brian' + 'Cole' + 'Roman' + 'Hunter' + 'Simon' + 'Robin' + 'Quinn' + 'Arty' + 'Gimsley' + 'Fidsdale' + 'Slyvos' + 'Logos' + 'Denin' + 'Lycan' + 'Loco' + 'Vican' + 'Mars' + 'Dev' + 'Oliver' ] - "Ogre Munchkin M": [ - "Brack" - "Gort" - "Weeb" - "Nerph" - "Kratt" - "Smerk" - "Raack" - "Dobo" - "Draff" - "Zozo" - "Kogpole" - "Leerer" - "Skoggen" - "Treg" - "Goreball" - "Gert" - "Thabt" - "Snortt" - "Kog" - "Ursa" - "Ragtime" + 'Ogre Munchkin M': [ + 'Brack' + 'Gort' + 'Weeb' + 'Nerph' + 'Kratt' + 'Smerk' + 'Raack' + 'Dobo' + 'Draff' + 'Zozo' + 'Kogpole' + 'Leerer' + 'Skoggen' + 'Treg' + 'Goreball' + 'Gert' + 'Thabt' + 'Snortt' + 'Kog' + 'Ursa' + 'Ragtime' ] - "Ogre Munchkin F": [ - "Iyert" - "Palt" - "Shmeal" - "Gurzunn" - "Yugark" - "Dosha" - "Inski" - "Lacos" - "Upfish" + 'Ogre Munchkin F': [ + 'Iyert' + 'Palt' + 'Shmeal' + 'Gurzunn' + 'Yugark' + 'Dosha' + 'Inski' + 'Lacos' + 'Upfish' ] - "Ogre Peon M": [ - "Durbo" - "Kurger" - "Mudwich" - "Ba Bo" - "Zugger" - "Toe Pod" + 'Ogre Peon M': [ + 'Durbo' + 'Kurger' + 'Mudwich' + 'Ba Bo' + 'Zugger' + 'Toe Pod' ] - "Ogre Peon F": [ - "Iblet" - "Lorba" - "Zzoya" - "Yamra" - "Greeke" - "Vapa" + 'Ogre Peon F': [ + 'Iblet' + 'Lorba' + 'Zzoya' + 'Yamra' + 'Greeke' + 'Vapa' ] - "Ogre M": [ - "Krogg" - "Dronck" - "Trogdor" - "Kulgor" - "Skrungt" - "Mak Fod" - "Trung" - "Axe Ox" - "Vargutt" - "Grumus" - "Gug" - "Tarlok" - "Gurulax" - "Mokrul" - "Polifemo" - "Muthyala" - "Saltporker" + 'Ogre M': [ + 'Krogg' + 'Dronck' + 'Trogdor' + 'Kulgor' + 'Skrungt' + 'Mak Fod' + 'Trung' + 'Axe Ox' + 'Vargutt' + 'Grumus' + 'Gug' + 'Tarlok' + 'Gurulax' + 'Mokrul' + 'Polifemo' + 'Muthyala' + 'Saltporker' ] - "Ogre F": [ - "Nareng" - "Morthrug" - "Glonc" - "Marghurk" - "Martha" - "Holkam" - "Alkaz" - "Gar'ah" - "Mak'rah" - "Marnag" + 'Ogre F': [ + 'Nareng' + 'Morthrug' + 'Glonc' + 'Marghurk' + 'Martha' + 'Holkam' + 'Alkaz' + 'Gar\'ah' + 'Mak\'rah' + 'Marnag' ] - "Ogre Brawler": [ - "Grul'thock" - "Boz" - "Trod" - "Muul" - "Grumoll" - "Burobb" - "Arelt" - "Zagurk" - "Zeredd" - "Borgag" - "Grognar" - "Ironjaw" - "Tuguro" - "York" - "Ork'han" - "Roast Beefy" - "Haggar" + 'Ogre Brawler': [ + 'Grul\'thock' + 'Boz' + 'Trod' + 'Muul' + 'Grumoll' + 'Burobb' + 'Arelt' + 'Zagurk' + 'Zeredd' + 'Borgag' + 'Grognar' + 'Ironjaw' + 'Tuguro' + 'York' + 'Ork\'han' + 'Roast Beefy' + 'Haggar' ] - "Ogre Fangrider": [ - "Dreek" - "Flarsho" - "Mizzy" - "Secka" - "Arizard" - "Secka" - "Arizard" - "Morzgret" - "Doralt" - "Geggret" - "Gurzthrot" - "Murgark" - "Muttin" - "Bortrok" + 'Ogre Fangrider': [ + 'Dreek' + 'Flarsho' + 'Mizzy' + 'Secka' + 'Arizard' + 'Secka' + 'Arizard' + 'Morzgret' + 'Doralt' + 'Geggret' + 'Gurzthrot' + 'Murgark' + 'Muttin' + 'Bortrok' ] - "Ogre Shaman": [ - "Sham'uk" - "Il'Du'duka" - "Ahst'durante" - "Poult" - "Aolian'Tak" - "Tuzell" - "Yamizeb" - "Yerong" - "Tuzang" - "Varreth" - "Yugargen" - "Turann" - "Ugoki" - "Zulabar" - "Zo'Goroth" - "Mogadishu" - "Nazgareth" - "Gror" - "Grek" - "Gom" - "Gogg" - "Ghuk" - "Makas" - "Drun" + 'Ogre Shaman': [ + 'Sham\'uk' + 'Il\'Du\'duka' + 'Ahst\'durante' + 'Poult' + 'Aolian\'Tak' + 'Tuzell' + 'Yamizeb' + 'Yerong' + 'Tuzang' + 'Varreth' + 'Yugargen' + 'Turann' + 'Ugoki' + 'Zulabar' + 'Zo\'Goroth' + 'Mogadishu' + 'Nazgareth' + 'Gror' + 'Grek' + 'Gom' + 'Gogg' + 'Ghuk' + 'Makas' + 'Drun' ] - "Ogre Thrower": [ - "Kyrgg" - "Durnath" - "Kraggan" - "Rasha" - "Moza" - "Vujii" - "Esha" - "Zara" - "Hamedi" - "Jinjin" - "Yetu" - "Makas" - "Rakash" - "Drumbaa" - "Pinakin" + 'Ogre Thrower': [ + 'Kyrgg' + 'Durnath' + 'Kraggan' + 'Rasha' + 'Moza' + 'Vujii' + 'Esha' + 'Zara' + 'Hamedi' + 'Jinjin' + 'Yetu' + 'Makas' + 'Rakash' + 'Drumbaa' + 'Pinakin' ] - "Burl": [ - "Borlit" - "Burlosh" - "Dorf" + 'Burl': [ + 'Borlit' + 'Burlosh' + 'Dorf' ] - "Griffin Rider": [ - "Aeoldan" - "Bestarius" + 'Griffin Rider': [ + 'Aeoldan' + 'Bestarius' ] - "Potion Master": [ - "Snake" - "Amaranth" - "Zander" - "Arora" - "Curie" - "Clause" - "Vanders" + 'Potion Master': [ + 'Snake' + 'Amaranth' + 'Zander' + 'Arora' + 'Curie' + 'Clause' + 'Vanders' ] - "Librarian": [ - "Hushbaum" - "Matilda" - "Agnes" - "Agathe" - "Satish" + 'Librarian': [ + 'Hushbaum' + 'Matilda' + 'Agnes' + 'Agathe' + 'Satish' ] - "Equestrian": [ - "Reynaldo" - "Ryder" - "Thoron" - "Mirial" - "Neely" + 'Equestrian': [ + 'Reynaldo' + 'Ryder' + 'Thoron' + 'Mirial' + 'Neely' ] - "Knight": [ - "Tharin" - "Arthur" - "Galahad" - "Mace" - "Drake" - "Duran" - "Almeric" - "Hunfray" - "Hank" - "Jeph" - "Neville" - "Alphonse" - "Edward" + 'Knight': [ + 'Tharin' + 'Arthur' + 'Galahad' + 'Mace' + 'Drake' + 'Duran' + 'Almeric' + 'Hunfray' + 'Hank' + 'Jeph' + 'Neville' + 'Alphonse' + 'Edward' ] - "Captain": [ - "Anya" - "Brigette" - "Sarre" - "Katana" - "Lily" - "Isa" - "Dimia" - "Jane" - "Lia" - "Hardcastle" - "Leona" + 'Captain': [ + 'Anya' + 'Brigette' + 'Sarre' + 'Katana' + 'Lily' + 'Isa' + 'Dimia' + 'Jane' + 'Lia' + 'Hardcastle' + 'Leona' ] diff --git a/app/lib/world/rand.coffee b/app/lib/world/rand.coffee index 515019611..aa83a9b02 100644 --- a/app/lib/world/rand.coffee +++ b/app/lib/world/rand.coffee @@ -1,6 +1,6 @@ # http://coffeescriptcookbook.com/chapters/math/generating-predictable-random-numbers class Rand - @className: "Rand" + @className: 'Rand' # If created without a seed, uses current time as seed. constructor: (@seed) -> # Knuth and Lewis' improvements to Park and Miller's LCPRNG diff --git a/app/lib/world/rectangle.coffee b/app/lib/world/rectangle.coffee index f4f5400a4..e3fec8d76 100644 --- a/app/lib/world/rectangle.coffee +++ b/app/lib/world/rectangle.coffee @@ -1,7 +1,7 @@ Vector = require './vector' class Rectangle - @className: "Rectangle" + @className: 'Rectangle' # Class methods for nondestructively operating for name in ['add', 'subtract', 'multiply', 'divide'] do (name) -> diff --git a/app/lib/world/system.coffee b/app/lib/world/system.coffee index 458366b21..74b26e7d8 100644 --- a/app/lib/world/system.coffee +++ b/app/lib/world/system.coffee @@ -3,7 +3,7 @@ # Other Systems might be things like Attraction, EdgeBounce, EdgeWrap, and non-physics ones, too, like Rendering, Animation, ... module.exports = class System - @className: "System" + @className: 'System' constructor: (@world, config) -> # Unlike with Component, we don't automatically copy all our properties onto the World. # Subclasses can copy select properties here if they like. diff --git a/app/lib/world/systems/collision.coffee b/app/lib/world/systems/collision.coffee index efceab106..45b2bbeeb 100644 --- a/app/lib/world/systems/collision.coffee +++ b/app/lib/world/systems/collision.coffee @@ -1,16 +1,16 @@ # http://codingowl.com/readblog.php?blogid=124 module.exports.CollisionCategory = class CollisionCategory - @className: "CollisionCategory" + @className: 'CollisionCategory' constructor: (name, @superteamIndex=null, @collisionSystem) -> - # @superteamIndex is null for "none", "obstacles", and "dead". - # It's 0 for "ground", "air", and "ground_and_air" units with no superteams. + # @superteamIndex is null for 'none', 'obstacles', and 'dead'. + # It's 0 for 'ground', 'air', and 'ground_and_air' units with no superteams. # It's 1, 2, or 3 for the superteams it gets after that. We can only have 16 collision categories. - @ground = name.search("ground") isnt -1 - @air = name.search("air") isnt -1 + @ground = name.search('ground') isnt -1 + @air = name.search('air') isnt -1 @name = CollisionCategory.nameFor name, @superteamIndex @superteamIndex ?= 0 if @ground or @air @number = 1 << @collisionSystem.totalCategories++ - if @collisionSystem.totalCategories > 16 then console.log "There should only be 16 collision categories!" + if @collisionSystem.totalCategories > 16 then console.log 'There should only be 16 collision categories!' @mask = 0 @collisionSystem.allCategories[@name] = @ for otherCatName, otherCat of @collisionSystem.allCategories @@ -19,32 +19,32 @@ module.exports.CollisionCategory = class CollisionCategory otherCat.mask = otherCat.mask | @number collidesWith: (cat) -> - # "none" collides with nothing - return false if @name is "none" or cat.name is "none" + # 'none' collides with nothing + return false if @name is 'none' or cat.name is 'none' - # "obstacles" collides with everything; could also try letting air units (but not ground_and_air) fly over these - return true if cat.name is "obstacles" or @name is "obstacles" + # 'obstacles' collides with everything; could also try letting air units (but not ground_and_air) fly over these + return true if cat.name is 'obstacles' or @name is 'obstacles' - # "dead" collides only with obstacles - return cat.name is "obstacles" if @name is "dead" - return @name is "obstacles" if cat.name is "dead" + # 'dead' collides only with obstacles + return cat.name is 'obstacles' if @name is 'dead' + return @name is 'obstacles' if cat.name is 'dead' - # "ground_and_air_" units don't hit ground or air units on their team (so missiles don't hit same team) + # 'ground_and_air_' units don't hit ground or air units on their team (so missiles don't hit same team) sameTeam = @superteamIndex and cat.superteamIndex is @superteamIndex return false if sameTeam and @ground and @air - # actually, "ground_and_air" units don't hit any ground_and_air units (temp missile collision fix) + # actually, 'ground_and_air' units don't hit any ground_and_air units (temp missile collision fix) return false if @ground and @air and cat.ground and cat.air - # "ground" collides with "ground" + # 'ground' collides with 'ground' return true if cat.ground and @ground - # "air" collides with "air" + # 'air' collides with 'air' return true if cat.air and @air - # doesn't collide (probably "ground" and "air") + # doesn't collide (probably 'ground' and 'air') false @nameFor: (name, superteamIndex=null) -> - return name unless name.match("ground") or name.match("air") - name + "_" + (superteamIndex or 0) + return name unless name.match('ground') or name.match('air') + name + '_' + (superteamIndex or 0) diff --git a/app/lib/world/thang.coffee b/app/lib/world/thang.coffee index 248f30e60..63d544b1e 100644 --- a/app/lib/world/thang.coffee +++ b/app/lib/world/thang.coffee @@ -131,7 +131,7 @@ module.exports = class Thang source.original = chain.original.toString() source.user = chain.user?.toString() else - source.original = @[methodName]?.toString() ? "" + source.original = @[methodName]?.toString() ? '' source.original = Aether.getFunctionBody source.original source diff --git a/app/lib/world/thang_state.coffee b/app/lib/world/thang_state.coffee index f7c3b1f23..c4a1a540b 100644 --- a/app/lib/world/thang_state.coffee +++ b/app/lib/world/thang_state.coffee @@ -8,15 +8,15 @@ else bytesPerFloat = 4 module.exports = class ThangState - @className: "ThangState" + @className: 'ThangState' @trackedPropertyTypes: [ - "boolean" - "number" - "string" - "array" # will turn everything into strings - "object" # grrr - "Vector" - "Thang" # serialized as ids, like strings + 'boolean' + 'number' + 'string' + 'array' # will turn everything into strings + 'object' # grrr + 'Vector' + 'Thang' # serialized as ids, like strings ] hasRestored: false @@ -40,7 +40,7 @@ module.exports = class ThangState unless type type = @trackedPropertyTypes[propIndex] storage = @trackedPropertyValues[propIndex] - if type is "Vector" + if type is 'Vector' value = new Vector storage[3 * @frameIndex], storage[3 * @frameIndex + 1], storage[3 * @frameIndex + 2] else if type is 'string' specialKey = storage[@frameIndex] @@ -78,7 +78,7 @@ module.exports = class ThangState type = @trackedPropertyTypes[propIndex] storage = @trackedPropertyValues[propIndex] props.push(@thang[prop] = @getStoredProp propIndex, type, storage) - #console.log @frameIndex, @thang.id, prop, propIndex, type, storage, "got", @thang[prop] + #console.log @frameIndex, @thang.id, prop, propIndex, type, storage, 'got', @thang[prop] @props = props @trackedPropertyTypes = @trackedPropertyValues = @specialKeysToValues = null # leave @trackedPropertyKeys for indexing @hasRestored = true @@ -90,14 +90,14 @@ module.exports = class ThangState restorePartial: (ratio) -> inverse = 1 - ratio - for prop, propIndex in @trackedPropertyKeys when prop is "pos" or prop is "rotation" + for prop, propIndex in @trackedPropertyKeys when prop is 'pos' or prop is 'rotation' if @hasRestored value = @props[propIndex] else type = @trackedPropertyTypes[propIndex] storage = @trackedPropertyValues[propIndex] value = @getStoredProp propIndex, type, storage - if prop is "pos" + if prop is 'pos' if @thang.teleport and @thang.pos.distanceSquared(value) > 900 # Don't interpolate; it was probably a teleport. https://github.com/codecombat/codecombat/issues/738 @thang.pos = value @@ -106,7 +106,7 @@ module.exports = class ThangState @thang.pos.x = inverse * @thang.pos.x + ratio * value.x @thang.pos.y = inverse * @thang.pos.y + ratio * value.y @thang.pos.z = inverse * @thang.pos.z + ratio * value.z - else if prop is "rotation" + else if prop is 'rotation' @thang.rotation = inverse * @thang.rotation + ratio * value @thang.partialState = true @ @@ -119,7 +119,7 @@ module.exports = class ThangState value = @props[originalPropIndex] if value # undefined, null, false, 0 won't trigger in this serialization code scheme anyway, so we can't differentiate between them when deserializing - if type is "Vector" + if type is 'Vector' storage[3 * frameIndex] = value.x storage[3 * frameIndex + 1] = value.y storage[3 * frameIndex + 2] = value.z @@ -157,7 +157,7 @@ module.exports = class ThangState storage[frameIndex] = specialKey else storage[frameIndex] = value - #console.log @thang.id, "assigned prop", originalPropIndex, newPropIndex, value, type, "at", frameIndex, "to", storage[frameIndex] + #console.log @thang.id, 'assigned prop', originalPropIndex, newPropIndex, value, type, 'at', frameIndex, 'to', storage[frameIndex] null @deserialize: (world, frameIndex, thang, trackedPropertyKeys, trackedPropertyTypes, trackedPropertyValues, specialKeysToValues) -> @@ -173,12 +173,12 @@ module.exports = class ThangState @transferableBytesNeededForType: (type, nFrames) -> bytes = switch type - when "boolean" then 1 - when "number" then bytesPerFloat - when "Vector" then bytesPerFloat * 3 - when "string" then 4 - when "Thang" then 4 # turn them into strings of their ids - when "array" then 4 # turn them into strings and hope it doesn't explode? + when 'boolean' then 1 + when 'number' then bytesPerFloat + when 'Vector' then bytesPerFloat * 3 + when 'string' then 4 + when 'Thang' then 4 # turn them into strings of their ids + when 'array' then 4 # turn them into strings and hope it doesn't explode? else 0 # We need to be a multiple of bytesPerFloat otherwise bigger-byte array (Float64Array, etc.) offsets won't work # http://www.kirupa.com/forum/showthread.php?378737-Typed-Arrays-Y-U-No-offset-at-values-other-than-multiples-of-element-size @@ -187,17 +187,17 @@ module.exports = class ThangState @createArrayForType: (type, nFrames, buffer, offset) -> bytes = @transferableBytesNeededForType type, nFrames storage = switch type - when "boolean" + when 'boolean' new Uint8Array(buffer, offset, nFrames) - when "number" + when 'number' new FloatArrayType(buffer, offset, nFrames) - when "Vector" + when 'Vector' new FloatArrayType(buffer, offset, nFrames * 3) - when "string" + when 'string' new Uint32Array(buffer, offset, nFrames) - when "Thang" + when 'Thang' new Uint32Array(buffer, offset, nFrames) - when "array" + when 'array' new Uint32Array(buffer, offset, nFrames) else [] diff --git a/app/lib/world/vector.coffee b/app/lib/world/vector.coffee index 90805f2e0..a17e5d077 100644 --- a/app/lib/world/vector.coffee +++ b/app/lib/world/vector.coffee @@ -1,6 +1,6 @@ # https://github.com/hornairs/blog/blob/master/assets/coffeescripts/flocking/vector.coffee class Vector - @className: "Vector" + @className: 'Vector' # Class methods for nondestructively operating for name in ['add', 'subtract', 'multiply', 'divide', 'limit', 'normalize'] do (name) -> diff --git a/app/lib/world/world.coffee b/app/lib/world/world.coffee index 9492c2e01..3e929ef77 100644 --- a/app/lib/world/world.coffee +++ b/app/lib/world/world.coffee @@ -12,7 +12,7 @@ PROGRESS_UPDATE_INTERVAL = 200 DESERIALIZATION_INTERVAL = 20 module.exports = class World - @className: "World" + @className: 'World' age: 0 ended: false preloading: false # Whether we are just preloading a world in case we soon cast it @@ -63,12 +63,12 @@ module.exports = class World @thangMap[thang.id] = thang thangDialogueSounds: -> - if @frames.length < @totalFrames then throw new Error("World should be over before grabbing dialogue") + if @frames.length < @totalFrames then throw new Error('World should be over before grabbing dialogue') [sounds, seen] = [[], {}] for frame in @frames for thangID, state of frame.thangStateMap - continue unless state.thang.say and sayMessage = state.getStateForProp "sayMessage" - soundKey = state.thang.spriteName + ":" + sayMessage + continue unless state.thang.say and sayMessage = state.getStateForProp 'sayMessage' + soundKey = state.thang.spriteName + ':' + sayMessage unless seen[soundKey] sounds.push [state.thang.spriteName, sayMessage] seen[soundKey] = true @@ -83,7 +83,7 @@ module.exports = class World loadFrames: (loadedCallback, errorCallback, loadProgressCallback, skipDeferredLoading, loadUntilFrame) -> return if @aborted unless @thangs.length - console.log "Warning: loadFrames called on empty World (no thangs)." + console.log 'Warning: loadFrames called on empty World (no thangs).' t1 = now() @t0 ?= t1 if loadUntilFrame @@ -113,7 +113,7 @@ module.exports = class World loadProgressCallback? i / @totalFrames unless @preloading t1 = t2 if t2 - @t0 > 1000 - console.log(' Loaded', i, 'of', @totalFrames, "(+" + (t2 - @t0).toFixed(0) + "ms)") + console.log ' Loaded', i, 'of', @totalFrames, '(+' + (t2 - @t0).toFixed(0) + 'ms)' @t0 = t2 continueFn = => return if @destroyed @@ -155,7 +155,7 @@ module.exports = class World for levelSystem in level.systems systemModel = levelSystem.model config = levelSystem.config - systemClass = @loadClassFromCode systemModel.js, systemModel.name, "system" + systemClass = @loadClassFromCode systemModel.js, systemModel.name, 'system' #console.log "using db system class ---\n", systemClass, "\n--- from code ---n", systemModel.js, "\n---" system = new systemClass @, config @addSystems system @@ -169,15 +169,15 @@ module.exports = class World # Load new Thangs toAdd = [] for d in level.thangs - continue if d.thangType is "Interface" # ignore old Interface Thangs until we've migrated away + continue if d.thangType is 'Interface' # ignore old Interface Thangs until we've migrated away components = [] for component in d.components componentModel = _.find level.levelComponents, (c) -> c.original is component.original and c.version.major is (component.majorVersion ? 0) - #console.log "found model", componentModel, "from", component, "for", d.id, "from existing components", level.levelComponents - componentClass = @loadClassFromCode componentModel.js, componentModel.name, "component" + #console.log 'found model', componentModel, 'from', component, 'for', d.id, 'from existing components', level.levelComponents + componentClass = @loadClassFromCode componentModel.js, componentModel.name, 'component' components.push [componentClass, component.config] - #console.log "---", d.id, "using db component class ---\n", componentClass, "\n--- from code ---\n", componentModel.js, '\n---' - #console.log "(found", componentModel, "for id", component.original, "from", level.levelComponents, ")" + #console.log '---', d.id, "using db component class ---\n", componentClass, "\n--- from code ---\n", componentModel.js, '\n---' + #console.log '(found', componentModel, 'for id', component.original, 'from', level.levelComponents, ')' thangType = d.thangType thangTypeModel = _.find level.thangTypes, (t) -> t.original is thangType thangType = thangTypeModel.name if thangTypeModel @@ -185,7 +185,7 @@ module.exports = class World try thang.addComponents components... catch e - console.error "couldn't load components for", d.thangType, d.id, "because", e, e.stack, e.stackTrace + console.error 'couldn\'t load components for', d.thangType, d.id, 'because', e, e.stack, e.stackTrace toAdd.push thang @extraneousThangs = consolidateThangs toAdd if willSimulate # combine walls, for example; serialize the leftovers later for thang in toAdd @@ -200,11 +200,11 @@ module.exports = class World @scripts = [] @addScripts level.scripts... - loadClassFromCode: (js, name, kind="component") -> + loadClassFromCode: (js, name, kind='component') -> # Cache them based on source code so we don't have to worry about extra compilations @componentCodeClassMap ?= {} @systemCodeClassMap ?= {} - map = if kind is "component" then @componentCodeClassMap else @systemCodeClassMap + map = if kind is 'component' then @componentCodeClassMap else @systemCodeClassMap c = map[js] return c if c c = map[js] = eval js @@ -285,7 +285,7 @@ module.exports = class World serialize: -> # Code hotspot; optimize it - if @frames.length < @totalFrames then throw new Error("World Should Be Over Before Serialization") + if @frames.length < @totalFrames then throw new Error('World Should Be Over Before Serialization') [transferableObjects, nontransferableObjects] = [0, 0] o = {totalFrames: @totalFrames, maxTotalFrames: @maxTotalFrames, frameRate: @frameRate, dt: @dt, victory: @victory, userCodeMap: {}, trackedProperties: {}} o.trackedProperties[prop] = @[prop] for prop in @trackedProperties or [] @@ -364,20 +364,20 @@ module.exports = class World flattened.push value o.storageBuffer = flattened - #console.log "Allocating memory:", (t1 - t0).toFixed(0), "ms; assigning values:", (t2 - t1).toFixed(0), "ms, so", ((t2 - t1) / @frames.length).toFixed(3), "ms per frame" - #console.log "Got", transferableObjects, "transferable objects and", nontransferableObjects, "nontransferable; stored", transferableStorageBytesNeeded, "bytes transferably" + #console.log 'Allocating memory:', (t1 - t0).toFixed(0), 'ms; assigning values:', (t2 - t1).toFixed(0), 'ms, so', ((t2 - t1) / @frames.length).toFixed(3), 'ms per frame' + #console.log 'Got', transferableObjects, 'transferable objects and', nontransferableObjects, 'nontransferable; stored', transferableStorageBytesNeeded, 'bytes transferably' o.thangs = (t.serialize() for t in @thangs.concat(@extraneousThangs ? [])) o.scriptNotes = (sn.serialize() for sn in @scriptNotes) if o.scriptNotes.length > 200 - console.log "Whoa, serializing a lot of WorldScriptNotes here:", o.scriptNotes.length + console.log 'Whoa, serializing a lot of WorldScriptNotes here:', o.scriptNotes.length {serializedWorld: o, transferableObjects: [o.storageBuffer]} @deserialize: (o, classMap, oldSerializedWorldFrames, finishedWorldCallback) -> # Code hotspot; optimize it - #console.log "Deserializing", o, "length", JSON.stringify(o).length + #console.log 'Deserializing', o, 'length', JSON.stringify(o).length #console.log JSON.stringify(o) - #console.log "Got special keys and values:", o.specialValuesToKeys, o.specialKeysToValues + #console.log 'Got special keys and values:', o.specialValuesToKeys, o.specialKeysToValues perf = {} perf.t0 = now() w = new World o.userCodeMap, classMap @@ -424,13 +424,13 @@ module.exports = class World w.ended = true w.getFrame(w.totalFrames - 1).restoreState() perf.t5 = now() - console.log "Deserialization:", (perf.t5 - perf.t0).toFixed(0) + "ms (" + ((perf.t5 - perf.t0) / w.frames.length).toFixed(3) + "ms per frame).", perf.batches, "batches." + console.log 'Deserialization:', (perf.t5 - perf.t0).toFixed(0) + 'ms (' + ((perf.t5 - perf.t0) / w.frames.length).toFixed(3) + 'ms per frame).', perf.batches, 'batches.' if false - console.log " Deserializing--constructing new World:", (perf.t1 - perf.t0).toFixed(2) + "ms" - console.log " Deserializing--Thangs and ScriptNotes:", (perf.t2 - perf.t1).toFixed(2) + "ms" - console.log " Deserializing--reallocating memory:", (perf.t3 - perf.t2).toFixed(2) + "ms" - console.log " Deserializing--WorldFrames:", (perf.t4 - perf.t3).toFixed(2) + "ms" - console.log " Deserializing--restoring last WorldFrame:", (perf.t5 - perf.t4).toFixed(2) + "ms" + console.log ' Deserializing--constructing new World:', (perf.t1 - perf.t0).toFixed(2) + 'ms' + console.log ' Deserializing--Thangs and ScriptNotes:', (perf.t2 - perf.t1).toFixed(2) + 'ms' + console.log ' Deserializing--reallocating memory:', (perf.t3 - perf.t2).toFixed(2) + 'ms' + console.log ' Deserializing--WorldFrames:', (perf.t4 - perf.t3).toFixed(2) + 'ms' + console.log ' Deserializing--restoring last WorldFrame:', (perf.t5 - perf.t4).toFixed(2) + 'ms' finishedWorldCallback w findFirstChangedFrame: (oldWorld) -> @@ -440,9 +440,9 @@ module.exports = class World break unless oldFrame and newFrame.hash is oldFrame.hash @firstChangedFrame = i if @frames[i] - console.log "First changed frame is", @firstChangedFrame, "with hash", @frames[i].hash, "compared to", oldWorld.frames[i]?.hash + console.log 'First changed frame is', @firstChangedFrame, 'with hash', @frames[i].hash, 'compared to', oldWorld.frames[i]?.hash else - console.log "No frames were changed out of all", @frames.length + console.log 'No frames were changed out of all', @frames.length @firstChangedFrame pointsForThang: (thangID, frameStart=0, frameEnd=null, camera=null, resolution=4) -> @@ -478,7 +478,7 @@ module.exports = class World actionsForThang: (thangID, keepIdle=false) -> # Optimized @actionsForThangCache ?= {} - cacheKey = thangID + "_" + Boolean(keepIdle) + cacheKey = thangID + '_' + Boolean(keepIdle) cached = @actionsForThangCache[cacheKey] return cached if cached states = (frame.thangStateMap[thangID] for frame in @frames) diff --git a/app/lib/world/world_frame.coffee b/app/lib/world/world_frame.coffee index fc21546e2..2ab99f153 100644 --- a/app/lib/world/world_frame.coffee +++ b/app/lib/world/world_frame.coffee @@ -1,10 +1,12 @@ ThangState = require './thang_state' module.exports = class WorldFrame - @className: "WorldFrame" + @className: 'WorldFrame' + constructor: (@world, @time=0) -> @thangStateMap = {} @setState() if @world + getNextFrame: -> # Optimized. Must be called while thangs are current at this frame. nextTime = @time + @world.dt @@ -22,7 +24,7 @@ module.exports = class WorldFrame thangState.restore() for thangID, thangState of @thangStateMap for thang in @world.thangs if not @thangStateMap[thang.id] and not thang.stateless - #console.log "Frame", @time, "restoring state for", thang.id, "and saying it don't exist" + #console.log 'Frame', @time, 'restoring state for', thang.id, 'and saying it don\'t exist' thang.exists = false restorePartialState: (ratio) -> @@ -33,22 +35,22 @@ module.exports = class WorldFrame if not thangState if not thang.stateless thang.exists = false - #console.log "Frame", @time, "restoring state for", thang.id, "in particular and saying it don't exist" + #console.log 'Frame', @time, 'restoring state for', thang.id, 'in particular and saying it don\'t exist' return thangState.restore() - + clearEvents: -> thang.currentEvents = [] for thang in @world.thangs toString: -> map = ((' ' for x in [0 .. @world.width]) \ for y in [0 .. @world.height]) - symbols = ".ox@dfga[]/D" + symbols = '.ox@dfga[]/D' for thang, i in @world.thangs when thang.rectangle rect = thang.rectangle().axisAlignedBoundingBox() for y in [Math.floor(rect.y - rect.height / 2) ... Math.ceil(rect.y + rect.height / 2)] for x in [Math.floor(rect.x - rect.width / 2) ... Math.ceil(rect.x + rect.width / 2)] map[y][x] = symbols[i % symbols.length] if 0 <= y < @world.height and 0 <= x < @world.width - @time + "\n" + (xs.join(' ') for xs in map).join('\n') + '\n' + @time + '\n' + (xs.join(' ') for xs in map).join('\n') + '\n' serialize: (frameIndex, trackedPropertiesThangIDs, trackedPropertiesPerThangIndices, trackedPropertiesPerThangTypes, trackedPropertiesPerThangValues, specialValuesToKeys, specialKeysToValues) -> # Optimize diff --git a/app/lib/world/world_script_note.coffee b/app/lib/world/world_script_note.coffee index 2786cee49..be342cee7 100644 --- a/app/lib/world/world_script_note.coffee +++ b/app/lib/world/world_script_note.coffee @@ -2,7 +2,7 @@ {scriptMatchesEventPrereqs} = require './script_event_prereqs' module.exports = class WorldScriptNote - @className: "WorldScriptNote" + @className: 'WorldScriptNote' constructor: (script, @event, world) -> return unless script? @invalid = true diff --git a/app/lib/world/world_utils.coffee b/app/lib/world/world_utils.coffee index f38a55d74..d6d5c1171 100644 --- a/app/lib/world/world_utils.coffee +++ b/app/lib/world/world_utils.coffee @@ -78,17 +78,17 @@ module.exports.consolidateThangs = consolidateThangs = (thangs) -> topmost = _.max structural, (t) -> t.pos.y + t.height / 2 leftmost = _.min structural, (t) -> t.pos.x - t.width / 2 bottommost = _.min structural, (t) -> t.pos.y - t.height / 2 - console.log "got rightmost", rightmost.id, "topmost", topmost.id, "lefmostmost", leftmost.id, "bottommost", bottommost.id, "out of", structural.length, "structural thangs" if debug + console.log 'got rightmost', rightmost.id, 'topmost', topmost.id, 'lefmostmost', leftmost.id, 'bottommost', bottommost.id, 'out of', structural.length, 'structural thangs' if debug left = Math.min 0, leftmost.pos.x - leftmost.width / 2 bottom = Math.min 0, bottommost.pos.y - bottommost.height / 2 if (left < 0) or (bottom < 0) - console.error "Negative structural Thangs aren't supported, sorry!" # TODO: largestRectangle, AI System, and anything else that accesses grid directly need updating to finish this + console.error 'Negative structural Thangs aren\'t supported, sorry!' # TODO: largestRectangle, AI System, and anything else that accesses grid directly need updating to finish this left = 0 bottom = 0 width = rightmost.pos.x + rightmost.width / 2 - left height = topmost.pos.y + topmost.height / 2 - bottom padding = 0 - console.log "got max width", width, "height", height, "left", left, "bottom", bottom, "of thangs", thangs.length, "structural", structural.length if debug + console.log 'got max width', width, 'height', height, 'left', left, 'bottom', bottom, 'of thangs', thangs.length, 'structural', structural.length if debug grid = new Grid structural, width, height, padding, left, bottom console.log grid.toString() if debug @@ -107,14 +107,14 @@ module.exports.consolidateThangs = consolidateThangs = (thangs) -> grid.grid[y2][x2] = [] console.log grid.toString() if debug thang = structural[dissection.length] # grab one we already know is configured properly - console.error "Hmm, our dissection has more Thangs than the original structural Thangs?", dissection.length unless thang + console.error 'Hmm, our dissection has more Thangs than the original structural Thangs?', dissection.length unless thang thang.width = rect.width thang.height = rect.height thang.pos.x = rect.x thang.pos.y = rect.y thang.createBodyDef() dissection.push thang - console.log "Turned", structural.length, "structural Thangs into", dissection.length, "dissecting Thangs." + console.log 'Turned', structural.length, 'structural Thangs into', dissection.length, 'dissecting Thangs.' thangs.push dissection... structural[dissection.length ... structural.length] @@ -133,7 +133,7 @@ module.exports.largestRectangle = largestRectangle = (grid, bottomY, leftX, want break unless coveredRow coveredRows.push coveredRow shortestCoveredRow = Math.min(shortestCoveredRow, coveredRow) - console.log "largestRectangle() for", bottomY, leftX, "got coveredRows", coveredRows if debug + console.log 'largestRectangle() for', bottomY, leftX, 'got coveredRows', coveredRows if debug [maxArea, maxAreaRows, maxAreaRowLength, shortestRow] = [0, 0, 0, 0] for rowLength, rowIndex in coveredRows shortestRow ||= rowLength @@ -143,7 +143,7 @@ module.exports.largestRectangle = largestRectangle = (grid, bottomY, leftX, want maxAreaRowLength = shortestRow maxArea = area shortestRow = Math.min(rowLength, shortestRow) - console.log "So largest rect has area", maxArea, "with", maxAreaRows, "rows of length", maxAreaRowLength if debug + console.log 'So largest rect has area', maxArea, 'with', maxAreaRows, 'rows of length', maxAreaRowLength if debug rect = new Rectangle leftX + maxAreaRowLength / 2, bottomY + maxAreaRows / 2, maxAreaRowLength, maxAreaRows - console.log "That corresponds to a rectangle", rect.toString() if debug + console.log 'That corresponds to a rectangle', rect.toString() if debug rect diff --git a/app/locale/de-CH.coffee b/app/locale/de-CH.coffee index 18da78f62..87347663e 100644 --- a/app/locale/de-CH.coffee +++ b/app/locale/de-CH.coffee @@ -101,40 +101,40 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge multiplayer: "Multiplayer" for_developers: "Für Entwickler" -# play: -# choose_your_level: "Choose Your Level" -# adventurer_prefix: "You can jump to any level below, or discuss the levels on " -# adventurer_forum: "the Adventurer forum" + play: + choose_your_level: "Wähl dis Level us" + adventurer_prefix: "Du chasch zu de untere Level zrugg goh oder die kommende Level diskutiere " + adventurer_forum: "s Abentürer-Forum" # adventurer_suffix: "." -# campaign_beginner: "Beginner Campaign" -# campaign_beginner_description: "... in which you learn the wizardry of programming." -# campaign_dev: "Random Harder Levels" -# campaign_dev_description: "... in which you learn the interface while doing something a little harder." -# campaign_multiplayer: "Multiplayer Arenas" -# campaign_multiplayer_description: "... in which you code head-to-head against other players." + campaign_beginner: "Afängerkampagne" + campaign_beginner_description: "... i dere du d Zauberkunst vom Programmiere lernsch." + campaign_dev: "Zuefälligi schwierigeri Level" + campaign_dev_description: "... i dene du s Interface kenne lernsch, während du öppis chli Schwierigers machsch." + campaign_multiplayer: "Multiplayer Arenas" + campaign_multiplayer_description: "... i dene du Chopf a Chopf geg anderi Spieler spielsch." # campaign_player_created: "Player-Created" # campaign_player_created_description: "... in which you battle against the creativity of your fellow Artisan Wizards." -# level_difficulty: "Difficulty: " -# play_as: "Play As" -# spectate: "Spectate" + level_difficulty: "Schwierigkeit: " + play_as: "Spiel als" + spectate: "Zueluege" -# contact: -# contact_us: "Contact CodeCombat" -# welcome: "Good to hear from you! Use this form to send us email. " -# contribute_prefix: "If you're interested in contributing, check out our " -# contribute_page: "contribute page" + contact: + contact_us: "CodeCombat kontaktiere" + welcome: "Mir ghöred gern vo dir! Benutz das Formular zum üs e E-Mail schicke." + contribute_prefix: "Wenn du dra interessiert bisch, mitzhelfe denn lueg doch mol verbii uf üsere" + contribute_page: "Contribute Page" # contribute_suffix: "!" -# forum_prefix: "For anything public, please try " -# forum_page: "our forum" -# forum_suffix: " instead." -# send: "Send Feedback" + forum_prefix: "Für öffentlichi Sache versuechs mol bi" + forum_page: "üsem Forum" + forum_suffix: " stattdesse." + send: "Feedback schicke" # contact_candidate: "Contact Candidate" # recruitment_reminder: "Use this form to reach out to candidates you are interested in interviewing. Remember that CodeCombat charges 15% of first-year salary. The fee is due upon hiring the employee and is refundable for 90 days if the employee does not remain employed. Part time, remote, and contract employees are free, as are interns." diplomat_suggestion: title: "Hilf, CodeCombat z übersetze!" sub_heading: "Mir bruuched dini Sprochfähigkeite." - pitch_body: "We develop CodeCombat in English, but we already have players all over the world. Many of them want to play in Swiss German but don't speak English, so if you can speak both, please consider signing up to be a Diplomat and help translate both the CodeCombat website and all the levels into Swiss German." + pitch_body: "Mir entwickled CodeCombat in Englisch, aber mir hend scho Spieler uf de ganze Welt. Vieli devo würed gern uf Schwiizerdütsch spiele, aber chönd kei Englisch. Wenn du beides chasch, denk doch mol drüber noh, dich bi üs als Diplomat izträge und z helfe, d CodeCombat Websiite und alli Level uf Schwiizerdütsch z übersetze." missing_translations: "Until we can translate everything into Swiss German, you'll see generic German or English when Swiss German isn't available." learn_more: "Lern meh drüber, en Diplomat zsii" subscribe_as_diplomat: "Abonnier als en Diplomat" @@ -142,18 +142,18 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge wizard_settings: title: "Zaubereristellige" customize_avatar: "Pass din Avatar ah" -# active: "Active" + active: "Aktiv" color: "Farb" group: "Gruppe" clothes: "Chleider" -# trim: "Trim" + trim: "Zueschniide" cloud: "Wolke" team: "Team" spell: "Zauberspruch" boots: "Stiefel" -# hue: "Hue" + hue: "Färbig" saturation: "Sättigung" -# lightness: "Lightness" + lightness: "Helligkeit" account_settings: title: "Account Istellige" @@ -166,16 +166,16 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge password_tab: "Passwort" emails_tab: "E-Mails" admin: "Admin" -# wizard_color: "Wizard Clothes Color" + wizard_color: "Zaubererchleid Farb" new_password: "Neus Passwort" new_password_verify: "Bestätige" email_subscriptions: "E-Mail Abos" email_announcements: "Akündigunge" email_announcements_description: "Bechum Mails mit Neuigkeite und de neuste Entwicklige bi CodeCombat." email_notifications: "Benachrichtigunge" -# email_notifications_summary: "Controls for personalized, automatic email notifications related to your CodeCombat activity." -# email_any_notes: "Any Notifications" -# email_any_notes_description: "Disable to stop all activity notification emails." + email_notifications_summary: "Istellige für personalisierti, automatischi E-Mail Notifikatione im Zemehang mit dine CodeCombat Aktivitäte" + email_any_notes: "Alli Notifikatione" + email_any_notes_description: "Deaktiviere zum kei Aktivitäts-Notifikatione meh per E-Mail becho." # email_recruit_notes: "Job Opportunities" # email_recruit_notes_description: "If you play really well, we may contact you about getting you a (better) job." # contributor_emails: "Contributor Class Emails" @@ -192,36 +192,35 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge # sample_profile: "See a sample profile" # view_profile: "View Your Profile" -# account_profile: -# settings: "Settings" -# edit_profile: "Edit Profile" -# done_editing: "Done Editing" -# profile_for_prefix: "Profile for " -# profile_for_suffix: "" + account_profile: + settings: "Istellige" + edit_profile: "Profil bearbeite" + done_editing: "Fertig mit bearbeite" + profile_for_prefix: "Profil für " +# profile_for_suffix: "" # featured: "Featured" # not_featured: "Not Featured" # looking_for: "Looking for:" -# last_updated: "Last updated:" -# contact: "Contact" + last_updated: "S letzte Update:" + contact: "Kontakt" # 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." + complete: "komplett" + next: "Nögst" + next_city: "Stadt?" + next_country: "wähl dis Land." + next_name: "Name?" + next_short_description: "schriibe e churzi Beschriibig." + next_long_description: "beschriib dini Wunschstell." # 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_projects: "Zeig üs bis zu drü Projekt a dene du scho gschaffet hesch." + next_links: "füeg persönlichi oder Social Media Links ih." # 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" + example_blog: "Blog" + example_personal_site: "Eigeni Websiite" + links_header: "Eigeni 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?" @@ -324,39 +323,39 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge # other_developers: "Other Developers" # inactive_developers: "Inactive Developers" -# play_level: -# done: "Done" -# grid: "Grid" -# customize_wizard: "Customize Wizard" -# home: "Home" -# guide: "Guide" -# multiplayer: "Multiplayer" -# restart: "Restart" -# goals: "Goals" -# success: "Success!" -# incomplete: "Incomplete" -# timed_out: "Ran out of time" -# failing: "Failing" -# action_timeline: "Action Timeline" -# click_to_select: "Click on a unit to select it." -# reload_title: "Reload All Code?" -# reload_really: "Are you sure you want to reload this level back to the beginning?" -# reload_confirm: "Reload All" + play_level: + done: "Fertig" + grid: "Gitter" + customize_wizard: "Zauberer apasse" + home: "Home" + guide: "Aleitig" + multiplayer: "Multiplayer" + restart: "Neu starte" + goals: "Ziel" + success: "Erfolg!" + incomplete: "Unvollständig" + timed_out: "Ziit abglaufe" + failing: "Fehler" + action_timeline: "Aktionsziitleiste" + click_to_select: "Klick uf e Einheit zum sie uswähle." + reload_title: "De ganze Code neu lade?" + reload_really: "Bisch sicher du willsch level neu lade bis zrugg zum Afang?" + reload_confirm: "Alles neu lade" # victory_title_prefix: "" -# victory_title_suffix: " Complete" -# victory_sign_up: "Sign Up to Save Progress" -# victory_sign_up_poke: "Want to save your code? Create a free account!" -# victory_rate_the_level: "Rate the level: " -# victory_return_to_ladder: "Return to Ladder" -# victory_play_next_level: "Play Next Level" + victory_title_suffix: " Vollständig" + victory_sign_up: "Meld dich ah zum din Fortschritt speichere" + victory_sign_up_poke: "Wötsch din Code speichere? Erstell gratis en Account!" + victory_rate_the_level: "Bewerte das Level: " + victory_return_to_ladder: "Zrugg zum letzte Level" + victory_play_next_level: "Spiel s nögste Level" # victory_go_home: "Go Home" -# victory_review: "Tell us more!" -# victory_hour_of_code_done: "Are You Done?" -# victory_hour_of_code_done_yes: "Yes, I'm finished with my Hour of Code™!" -# multiplayer_title: "Multiplayer Settings" -# multiplayer_link_description: "Give this link to anyone to have them join you." -# multiplayer_hint_label: "Hint:" -# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link." + victory_review: "Verzell üs meh!" + victory_hour_of_code_done: "Bisch fertig?" + victory_hour_of_code_done_yes: "Jo, ich bin fertig mit mim Hour of Code™!" + multiplayer_title: "Multiplayer Istellige" + multiplayer_link_description: "Gib de Link jedem, wo mit dir will spiele." + multiplayer_hint_label: "Hiiwis:" + multiplayer_hint: " Klick uf de Link zum alles uswähle und druck ⌘-C or Ctrl-C zum de Link kopiere" # multiplayer_coming_soon: "More multiplayer features to come!" # multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard." # guide_title: "Guide" diff --git a/app/models/Article.coffee b/app/models/Article.coffee index e93c6102a..02e7fe80f 100644 --- a/app/models/Article.coffee +++ b/app/models/Article.coffee @@ -1,7 +1,7 @@ -CocoModel = require('./CocoModel') +CocoModel = require './CocoModel' module.exports = class Article extends CocoModel - @className: "Article" + @className: 'Article' @schema: require 'schemas/models/article' - urlRoot: "/db/article" + urlRoot: '/db/article' saveBackups: true diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee index 7c4a2f1a1..0d2846359 100644 --- a/app/models/CocoModel.coffee +++ b/app/models/CocoModel.coffee @@ -4,7 +4,7 @@ deltasLib = require 'lib/deltas' NewAchievementCollection = require '../collections/NewAchievementCollection' class CocoModel extends Backbone.Model - idAttribute: "_id" + idAttribute: '_id' loaded: false loading: false saveBackups: false @@ -55,10 +55,12 @@ class CocoModel extends Backbone.Model return unless @saveBackups existing = storage.load @id if existing - @set(existing, {silent:true}) + @set(existing, {silent: true}) CocoModel.backedUp[@id] = @ - saveBackup: -> + saveBackup: -> @saveBackupNow() + + saveBackupNow: -> storage.save(@id, @attributes) CocoModel.backedUp[@id] = @ @@ -74,7 +76,7 @@ class CocoModel extends Backbone.Model if errors?.length console.debug "Validation failed for #{@constructor.className}: '#{@get('name') or @}'." for error in errors - console.debug "\t", error.dataPath, ":", error.message + console.debug "\t", error.dataPath, ':', error.message return errors save: (attrs, options) -> @@ -84,7 +86,7 @@ class CocoModel extends Backbone.Model success = options.success error = options.error options.success = (model, res) => - @trigger "save:success", @ + @trigger 'save:success', @ success(@, res) if success @markToRevert() if @_revertAttributes @clearBackup() @@ -95,7 +97,7 @@ class CocoModel extends Backbone.Model errorMessage = "Error saving #{@get('name') ? @type()}" console.error errorMessage, res.responseJSON noty text: "#{errorMessage}: #{res.status} #{res.statusText}", layout: 'topCenter', type: 'error', killer: false, timeout: 10000 - @trigger "save", @ + @trigger 'save', @ return super attrs, options patch: (options) -> @@ -137,7 +139,6 @@ class CocoModel extends Backbone.Model cloneNewMinorVersion: -> newData = _.clone @attributes - clone = new @constructor(newData) clone @@ -152,20 +153,20 @@ class CocoModel extends Backbone.Model false publish: -> - if @isPublished() then throw new Error("Can't publish what's already-published. Can't kill what's already dead.") - @set "permissions", (@get("permissions") or []).concat({access: 'read', target: 'public'}) + if @isPublished() then throw new Error('Can\'t publish what\'s already-published. Can\'t kill what\'s already dead.') + @set 'permissions', (@get('permissions') or []).concat({access: 'read', target: 'public'}) addSchemaDefaults: -> return if @addedSchemaDefaults @addedSchemaDefaults = true for prop, defaultValue of @constructor.schema.default or {} continue if @get(prop)? - #console.log "setting", prop, "to", defaultValue, "from attributes.default" + #console.log 'setting', prop, 'to', defaultValue, 'from attributes.default' @set prop, defaultValue for prop, sch of @constructor.schema.properties or {} continue if @get(prop)? continue if prop is 'emails' # hack, defaults are handled through User.coffee's email-specific methods. - #console.log "setting", prop, "to", sch.default, "from sch.default" if sch.default? + #console.log 'setting', prop, 'to', sch.default, 'from sch.default' if sch.default? @set prop, sch.default if sch.default? if @loaded @loadFromBackup() @@ -210,7 +211,7 @@ class CocoModel extends Backbone.Model try jsondiffpatch.patch newAttributes, delta catch error - console.error "Error applying delta", delta, "to attributes", newAttributes, error + console.error 'Error applying delta\n', JSON.stringify(delta, null, '\t'), '\n\nto attributes\n\n', newAttributes return false @set newAttributes return true @@ -224,7 +225,7 @@ class CocoModel extends Backbone.Model deltasLib.expandDelta(delta, @attributes, @schema()) watch: (doWatch=true) -> - $.ajax("#{@urlRoot}/#{@id}/watch", {type:'PUT', data:{on:doWatch}}) + $.ajax("#{@urlRoot}/#{@id}/watch", {type: 'PUT', data: {on: doWatch}}) @watching = -> doWatch watching: -> @@ -254,9 +255,9 @@ class CocoModel extends Backbone.Model @getReferencedModel: (data, schema) -> return null unless schema.links? - linkObject = _.find schema.links, rel: "db" + linkObject = _.find schema.links, rel: 'db' return null unless linkObject - return null if linkObject.href.match("thang.type") and not @isObjectID(data) # Skip loading hardcoded Thang Types for now (TODO) + return null if linkObject.href.match('thang.type') and not @isObjectID(data) # Skip loading hardcoded Thang Types for now (TODO) # not fully extensible, but we can worry about that later link = linkObject.href @@ -296,7 +297,6 @@ class CocoModel extends Backbone.Model me.fetch (success: -> Backbone.Mediator.publish('achievements:new', collection)) unless _.isEmpty(collection.models) ) - CocoModel.pollAchievements = _.debounce CocoModel.pollAchievements, 500 module.exports = CocoModel diff --git a/app/models/File.coffee b/app/models/File.coffee index e2fe10446..b4ac0079f 100644 --- a/app/models/File.coffee +++ b/app/models/File.coffee @@ -1,6 +1,6 @@ -CocoModel = require('./CocoModel') +CocoModel = require './CocoModel' module.exports = class File extends CocoModel - @className: "File" + @className: 'File' @schema: {} - urlRoot: "/db/file" + urlRoot: '/db/file' diff --git a/app/models/Level.coffee b/app/models/Level.coffee index 0a56ccc09..6ae47f25e 100644 --- a/app/models/Level.coffee +++ b/app/models/Level.coffee @@ -4,10 +4,10 @@ LevelSystem = require './LevelSystem' ThangType = require './ThangType' module.exports = class Level extends CocoModel - @className: "Level" + @className: 'Level' @schema: require 'schemas/models/level' - urlRoot: "/db/level" - + urlRoot: '/db/level' + serialize: (supermodel) -> # o = _.cloneDeep @attributes # slow in level editor when there are hundreds of Thangs o = $.extend true, {}, @attributes @@ -23,7 +23,6 @@ module.exports = class Level extends CocoModel @fillInDefaultSystemConfiguration o.systems o.thangTypes = (original: tt.get('original'), name: tt.get('name') for tt in supermodel.getModels ThangType) - o sortSystems: (levelSystems, systemModels) -> @@ -31,11 +30,11 @@ module.exports = class Level extends CocoModel visit = (system) -> return if system.original of originalsSeen systemModel = _.find systemModels, {original: system.original} - console.error "Couldn't find model for original", system.original, "from", systemModels unless systemModel + console.error 'Couldn\'t find model for original', system.original, 'from', systemModels unless systemModel for d in systemModel.dependencies or [] system2 = _.find levelSystems, {original: d.original} visit system2 - #console.log "sorted systems adding", systemModel.name + #console.log 'sorted systems adding', systemModel.name sorted.push {model: systemModel, config: _.cloneDeep system.config} originalsSeen[system.original] = true visit system for system in levelSystems @@ -54,21 +53,21 @@ module.exports = class Level extends CocoModel visit = (c) -> return if c in sorted lc = _.find levelComponents, {original: c.original} - console.error thang.id, "couldn't find lc for", c unless lc - if lc.name is "Programmable" + console.error thang.id, 'couldn\'t find lc for', c unless lc + if lc.name is 'Programmable' # Programmable always comes last visit c2 for c2 in _.without thang.components, c else for d in lc.dependencies or [] c2 = _.find thang.components, {original: d.original} - console.error thang.id, "couldn't find dependent Component", d.original, "from", lc.name unless c2 + console.error thang.id, 'couldn\'t find dependent Component', d.original, 'from', lc.name unless c2 visit c2 - if lc.name is "Collides" - allied = _.find levelComponents, {name: "Allied"} + if lc.name is 'Collides' + allied = _.find levelComponents, {name: 'Allied'} if allied collides = _.find(thang.components, {original: allied.original}) visit collides if collides - #console.log thang.id, "sorted comps adding", lc.name + #console.log thang.id, 'sorted comps adding', lc.name sorted.push c for comp in thang.components visit comp @@ -90,7 +89,7 @@ module.exports = class Level extends CocoModel return unless properties for prop, schema of properties if schema.default? and config[prop] is undefined - #console.log "Setting default of", config, "for", prop, "to", schema.default + #console.log 'Setting default of', config, 'for', prop, 'to', schema.default config[prop] = schema.default if schema.type is 'object' and config[prop] @walkDefaults config[prop], schema.properties @@ -107,4 +106,4 @@ module.exports = class Level extends CocoModel continue unless c? width = c.width if c.width? and c.width > width height = c.height if c.height? and c.height > height - return {width:width, height:height} + return {width: width, height: height} diff --git a/app/models/LevelComponent.coffee b/app/models/LevelComponent.coffee index 3f6ef20b6..0e261482d 100644 --- a/app/models/LevelComponent.coffee +++ b/app/models/LevelComponent.coffee @@ -1,9 +1,9 @@ -CocoModel = require('./CocoModel') +CocoModel = require './CocoModel' module.exports = class LevelComponent extends CocoModel - @className: "LevelComponent" + @className: 'LevelComponent' @schema: require 'schemas/models/level_component' - urlRoot: "/db/level.component" + urlRoot: '/db/level.component' set: (key, val, options) -> if _.isObject key @@ -20,11 +20,11 @@ module.exports = class LevelComponent extends CocoModel compile: (code) -> if @get('codeLanguage') and @get('codeLanguage') isnt 'coffeescript' - return console.error("Can't compile", @get('codeLanguage'), "-- only CoffeeScript.", @) + return console.error('Can\'t compile', @get('codeLanguage'), '-- only CoffeeScript.', @) try js = CoffeeScript.compile(code, bare: true) catch e - #console.log "couldn't compile", code, "for", @get('name'), "because", e + #console.log 'couldn\'t compile', code, 'for', @get('name'), 'because', e js = @get 'js' js diff --git a/app/models/LevelFeedback.coffee b/app/models/LevelFeedback.coffee index a4bc1f3a9..1206934d9 100644 --- a/app/models/LevelFeedback.coffee +++ b/app/models/LevelFeedback.coffee @@ -1,6 +1,6 @@ -CocoModel = require('./CocoModel') +CocoModel = require './CocoModel' module.exports = class LevelFeedback extends CocoModel - @className: "LevelFeedback" + @className: 'LevelFeedback' @schema: require 'schemas/models/level_feedback' - urlRoot: "/db/level.feedback" + urlRoot: '/db/level.feedback' diff --git a/app/models/LevelSession.coffee b/app/models/LevelSession.coffee index b686fa149..b98cac66e 100644 --- a/app/models/LevelSession.coffee +++ b/app/models/LevelSession.coffee @@ -1,9 +1,9 @@ -CocoModel = require('./CocoModel') +CocoModel = require './CocoModel' module.exports = class LevelSession extends CocoModel - @className: "LevelSession" + @className: 'LevelSession' @schema: require 'schemas/models/level_session' - urlRoot: "/db/level.session" + urlRoot: '/db/level.session' initialize: -> super() @@ -16,7 +16,7 @@ module.exports = class LevelSession extends CocoModel permissions = @get 'permissions' permissions = (p for p in permissions when p.target isnt 'public') if @get('multiplayer') - permissions.push {target:'public', access:'write'} + permissions.push {target: 'public', access: 'write'} @set 'permissions', permissions getSourceFor: (spellKey) -> @@ -30,7 +30,7 @@ module.exports = class LevelSession extends CocoModel return false unless c1 = @get('code') return false unless team = @get('team') return true unless c2 = @get('submittedCode') - thangSpellArr = (s.split("/") for s in @get('teamSpells')[team]) + thangSpellArr = (s.split('/') for s in @get('teamSpells')[team]) for item in thangSpellArr thang = item[0] spell = item[1] diff --git a/app/models/LevelSystem.coffee b/app/models/LevelSystem.coffee index 8ba7bb264..04da10e8e 100644 --- a/app/models/LevelSystem.coffee +++ b/app/models/LevelSystem.coffee @@ -1,10 +1,10 @@ -CocoModel = require('./CocoModel') -SystemNameLoader = require('lib/SystemNameLoader') +CocoModel = require './CocoModel' +SystemNameLoader = require 'lib/SystemNameLoader' module.exports = class LevelSystem extends CocoModel - @className: "LevelSystem" + @className: 'LevelSystem' @schema: require 'schemas/models/level_system' - urlRoot: "/db/level.system" + urlRoot: '/db/level.system' set: (key, val, options) -> if _.isObject key @@ -22,11 +22,11 @@ module.exports = class LevelSystem extends CocoModel compile: (code) -> if @get('codeLanguage') and @get('codeLanguage') isnt 'coffeescript' - return console.error("Can't compile", @get('codeLanguage'), "-- only CoffeeScript.", @) + return console.error('Can\'t compile', @get('codeLanguage'), '-- only CoffeeScript.', @) try js = CoffeeScript.compile(code, bare: true) catch e - #console.log "couldn't compile", code, "for", @get('name'), "because", e + #console.log 'couldn\'t compile', code, 'for', @get('name'), 'because', e js = @get 'js' js diff --git a/app/models/Patch.coffee b/app/models/Patch.coffee index 3416ee44d..f77354638 100644 --- a/app/models/Patch.coffee +++ b/app/models/Patch.coffee @@ -1,12 +1,12 @@ -CocoModel = require('./CocoModel') +CocoModel = require './CocoModel' module.exports = class PatchModel extends CocoModel - @className: "Patch" + @className: 'Patch' @schema: require 'schemas/models/patch' - urlRoot: "/db/patch" + urlRoot: '/db/patch' setStatus: (status) -> PatchModel.setStatus @id, status @setStatus: (id, status) -> - $.ajax("/db/patch/#{id}/status", {type:"PUT", data: {status:status}}) + $.ajax("/db/patch/#{id}/status", {type: 'PUT', data: {status: status}}) diff --git a/app/models/SuperModel.coffee b/app/models/SuperModel.coffee index 7fd98ded5..c366d8285 100644 --- a/app/models/SuperModel.coffee +++ b/app/models/SuperModel.coffee @@ -19,11 +19,11 @@ module.exports = class SuperModel extends Backbone.Model report: -> # Useful for debugging why a SuperModel never finishes loading. - console.info "SuperModel report ------------------------" + console.info 'SuperModel report ------------------------' console.info "#{_.values(@resources).length} resources." unfinished = [] for resource in _.values(@resources) when resource - console.info '\t', resource.name, "loaded", resource.isLoaded + console.info "\t", resource.name, 'loaded', resource.isLoaded unfinished.push resource unless resource.isLoaded unfinished @@ -38,7 +38,6 @@ module.exports = class SuperModel extends Backbone.Model res = @addModelResource(cachedModel, name, fetchOptions, value) res.markLoading() return res - else @registerModel(model) res = @addModelResource(model, name, fetchOptions, value) @@ -57,7 +56,6 @@ module.exports = class SuperModel extends Backbone.Model res = @addModelResource(cachedCollection, name, fetchOptions, value) res.markLoading() return res - else @addCollection collection @listenToOnce collection, 'sync', (c) -> @@ -196,8 +194,6 @@ module.exports = class SuperModel extends Backbone.Model getResource: (rid) -> return @resources[rid] - - class Resource extends Backbone.Model constructor: (name, value=1) -> @name = name @@ -230,8 +226,6 @@ class Resource extends Backbone.Model load: -> @ - - class ModelResource extends Resource constructor: (modelOrCollection, name, fetchOptions, value)-> super(name, value) @@ -253,7 +247,6 @@ class ModelResource extends Resource @jqxhr = null @model.jqxhr = null - class RequestResource extends Resource constructor: (name, jqxhrOptions, value) -> super(name, value) @@ -267,6 +260,4 @@ class RequestResource extends Resource @jqxhr.fail => _.defer => @markFailed() @ - - class SomethingResource extends Resource diff --git a/app/models/ThangType.coffee b/app/models/ThangType.coffee index b236ba9cd..76bffd5a0 100644 --- a/app/models/ThangType.coffee +++ b/app/models/ThangType.coffee @@ -1,12 +1,12 @@ -CocoModel = require('./CocoModel') +CocoModel = require './CocoModel' SpriteBuilder = require 'lib/sprites/SpriteBuilder' buildQueue = [] module.exports = class ThangType extends CocoModel - @className: "ThangType" + @className: 'ThangType' @schema: require 'schemas/models/thang_type' - urlRoot: "/db/thang.type" + urlRoot: '/db/thang.type' building: {} initialize: -> @@ -27,7 +27,7 @@ module.exports = class ThangType extends CocoModel @resetRawData() unless @get('raw') resetRawData: -> - @set('raw', {shapes:{}, containers:{}, animations:{}}) + @set('raw', {shapes: {}, containers: {}, animations: {}}) resetSpriteSheetCache: -> @buildActions() @@ -48,7 +48,7 @@ module.exports = class ThangType extends CocoModel for name, action of @actions action.name = name for relatedName, relatedAction of action.relatedActions ? {} - relatedAction.name = action.name + "_" + relatedName + relatedAction.name = action.name + '_' + relatedName @actions[relatedAction.name] = relatedAction @actions @@ -114,12 +114,12 @@ module.exports = class ThangType extends CocoModel mc = @vectorParser.buildMovieClip name continue unless mc @builder.addMovieClip mc, null, animation.scale * @options.resolutionFactor - framesMap[animation.scale + "_" + name] = @builder._animations[name].frames + framesMap[animation.scale + '_' + name] = @builder._animations[name].frames for name, action of @actions when action.animation continue if name is 'portrait' scale = action.scale ? @get('scale') ? 1 - frames = framesMap[scale + "_" + action.animation] + frames = framesMap[scale + '_' + action.animation] continue unless frames frames = @mapFrames(action.frames, frames[0]) if action.frames? next = true @@ -179,7 +179,7 @@ module.exports = class ThangType extends CocoModel buildQueue[0]?.buildAsync() @spriteSheets[key] = e.target.spriteSheet @building[key] = false - @trigger 'build-complete', {key:key, thangType:@} + @trigger 'build-complete', {key: key, thangType: @} @vectorParser = null logBuild: (startTime, async, portrait) -> @@ -249,14 +249,14 @@ module.exports = class ThangType extends CocoModel path: "db/thang.type/#{@get('original')}" b64png: src force: 'true' - $.ajax('/file', { type: 'POST', data: body, success: callback or @onFileUploaded }) + $.ajax('/file', {type: 'POST', data: body, success: callback or @onFileUploaded}) onFileUploaded: => console.log 'Image uploaded' @loadUniversalWizard: -> return @wizardType if @wizardType - wizOriginal = "52a00d55cf1818f2be00000b" + wizOriginal = '52a00d55cf1818f2be00000b' url = "/db/thang.type/#{wizOriginal}/version" @wizardType = new module.exports() @wizardType.url = -> url diff --git a/app/models/User.coffee b/app/models/User.coffee index f224c85c9..9766a85aa 100644 --- a/app/models/User.coffee +++ b/app/models/User.coffee @@ -1,11 +1,11 @@ GRAVATAR_URL = 'https://www.gravatar.com/' cache = {} -CocoModel = require('./CocoModel') +CocoModel = require './CocoModel' module.exports = class User extends CocoModel - @className: "User" + @className: 'User' @schema: require 'schemas/models/user' - urlRoot: "/db/user" + urlRoot: '/db/user' initialize: -> super() @@ -16,24 +16,24 @@ module.exports = class User extends CocoModel return 'admin' in permissions displayName: -> - @get('name') or "Anoner" + @get('name') or 'Anoner' lang: -> - @get('preferredLanguage') or "en-US" + @get('preferredLanguage') or 'en-US' getPhotoURL: (size=80, useJobProfilePhoto=false) -> photoURL = if useJobProfilePhoto then @get('jobProfile')?.photoURL else null photoURL ||= @get('photoURL') if photoURL - prefix = if photoURL.search(/\?/) is -1 then "?" else "&" + prefix = if photoURL.search(/\?/) is -1 then '?' else '&' return "#{photoURL}#{prefix}s=#{size}" if photoURL.search('http') isnt -1 # legacy return "/file/#{photoURL}#{prefix}s=#{size}" return "/db/user/#{@id}/avatar?s=#{size}" @getByID = (id, properties, force) -> - {me} = require('lib/auth') + {me} = require 'lib/auth' return me if me.id is id - user = cache[id] or new module.exports({_id:id}) + user = cache[id] or new module.exports({_id: id}) if force or not cache[id] user.loading = true user.fetch( @@ -44,18 +44,18 @@ module.exports = class User extends CocoModel ) cache[id] = user user - + getEnabledEmails: -> @migrateEmails() emails = _.clone(@get('emails')) or {} emails = _.defaults emails, @schema().properties.emails.default (emailName for emailName, emailDoc of emails when emailDoc.enabled) - + setEmailSubscription: (name, enabled) -> newSubs = _.clone(@get('emails')) or {} (newSubs[name] ?= {}).enabled = enabled @set 'emails', newSubs - + emailMap: announcement: 'generalNews' developer: 'archmageNews' @@ -70,9 +70,9 @@ module.exports = class User extends CocoModel return if @attributes.emails or not @attributes.emailSubscriptions oldSubs = @get('emailSubscriptions') or [] newSubs = {} - newSubs[newSubName] = { enabled: oldSubName in oldSubs } for oldSubName, newSubName of @emailMap + newSubs[newSubName] = {enabled: oldSubName in oldSubs} for oldSubName, newSubName of @emailMap @set('emails', newSubs) - + isEmailSubscriptionEnabled: (name) -> (@get('emails') or {})[name]?.enabled a = 5 diff --git a/app/models/UserRemark.coffee b/app/models/UserRemark.coffee index 2bb37f42d..73db3ecf3 100644 --- a/app/models/UserRemark.coffee +++ b/app/models/UserRemark.coffee @@ -1,6 +1,6 @@ -CocoModel = require('./CocoModel') +CocoModel = require './CocoModel' module.exports = class UserRemark extends CocoModel - @className: "UserRemark" + @className: 'UserRemark' @schema: require 'schemas/models/user_remark' - urlRoot: "/db/user.remark" + urlRoot: '/db/user.remark' diff --git a/app/schemas/definitions/bus.coffee b/app/schemas/definitions/bus.coffee index bdec6248f..a552d16a8 100644 --- a/app/schemas/definitions/bus.coffee +++ b/app/schemas/definitions/bus.coffee @@ -1,14 +1,14 @@ module.exports = bus: - title: "Bus" - id: "bus" - $schema: "http://json-schema.org/draft-04/schema#" - description: "Bus" # TODO - type: "object" + title: 'Bus' + id: 'bus' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'Bus' # TODO + type: 'object' properties: # TODO joined: - type: ["boolean", "null"] + type: ['boolean', 'null'] players: - type: "object" - required: ["joined", "players"] + type: 'object' + required: ['joined', 'players'] additionalProperties: true diff --git a/app/schemas/definitions/misc.coffee b/app/schemas/definitions/misc.coffee index bbf9f5c02..79ce47b11 100644 --- a/app/schemas/definitions/misc.coffee +++ b/app/schemas/definitions/misc.coffee @@ -1,12 +1,12 @@ module.exports = jQueryEvent: - title: "jQuery Event" - id: "jQueryEvent" - $schema: "http://json-schema.org/draft-04/schema#" - description: "A standard jQuery Event" - type: "object" + title: 'jQuery Event' + id: 'jQueryEvent' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'A standard jQuery Event' + type: 'object' properties: # TODO schema complete altKey: - type: "boolean" + type: 'boolean' required: [] additionalProperties: true diff --git a/app/schemas/i18n_schema.coffee b/app/schemas/i18n_schema.coffee index 2a2aaf816..20053d47e 100644 --- a/app/schemas/i18n_schema.coffee +++ b/app/schemas/i18n_schema.coffee @@ -3,26 +3,24 @@ c = require './schemas' languageCodeArrayRegex = c.generateLanguageCodeArrayRegex() - ExampleSchema = { - title: "Example Schema", - description:"An example schema", - type: "object", + title: 'Example Schema', + description: 'An example schema', + type: 'object', properties: { text: { - title: "Text", - description: "A short message to display in the dialogue area. Markdown okay.", - type: "string", + title: 'Text', + description: 'A short message to display in the dialogue area. Markdown okay.', + type: 'string', maxLength: 400 }, - i18n: {"$ref": "#/definitions/i18n"} + i18n: {'$ref': '#/definitions/i18n'} }, - definitions: { i18n: { - title: "i18n", - description: "The internationalization object", - type: "object", + title: 'i18n', + description: 'The internationalization object', + type: 'object', patternProperties: { languageCodeArrayRegex: { additionalProperties: false, @@ -30,19 +28,18 @@ ExampleSchema = { #put the translatable properties here #if it is possible to not include i18n with a reference # to #/properties, you could just do - properties: {"$ref":"#/properties"} - # text: {"$ref": "#/properties/text"} + properties: {'$ref': '#/properties'} + # text: {'$ref': '#/properties/text'} } default: { - title: "LanguageCode", - description: "LanguageDescription" + title: 'LanguageCode', + description: 'LanguageDescription' } } } } - }, - + } } #define a i18n object type for each schema, then have the i18n have it's oneOf check against -#translatable schemas of that object \ No newline at end of file +#translatable schemas of that object diff --git a/app/schemas/metaschema.coffee b/app/schemas/metaschema.coffee index 4d9d7c0d8..163e87d98 100644 --- a/app/schemas/metaschema.coffee +++ b/app/schemas/metaschema.coffee @@ -1,132 +1,132 @@ # The JSON Schema Core/Validation Meta-Schema, but with titles and descriptions added to make it easier to edit in Treema, and in CoffeeScript module.exports = - id: "metaschema" - displayProperty: "title" - $schema: "http://json-schema.org/draft-04/schema#" - title: "Schema" - description: "Core schema meta-schema" + id: 'metaschema' + displayProperty: 'title' + $schema: 'http://json-schema.org/draft-04/schema#' + title: 'Schema' + description: 'Core schema meta-schema' definitions: schemaArray: - type: "array" + type: 'array' minItems: 1 - items: { $ref: "#" } - title: "Array of Schemas" - "default": [{}] + items: {$ref: '#'} + title: 'Array of Schemas' + 'default': [{}] positiveInteger: - type: "integer" + type: 'integer' minimum: 0 - title: "Positive Integer" + title: 'Positive Integer' positiveIntegerDefault0: - allOf: [ { $ref: "#/definitions/positiveInteger" }, { "default": 0 } ] + allOf: [{$ref: '#/definitions/positiveInteger'}, {'default': 0}] simpleTypes: - title: "Single Type" - "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ] + title: 'Single Type' + 'enum': ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] stringArray: - type: "array" - items: { type: "string" } + type: 'array' + items: {type: 'string'} minItems: 1 uniqueItems: true - title: "String Array" - "default": [''] - type: "object" + title: 'String Array' + 'default': [''] + type: 'object' properties: id: - type: "string" - format: "uri" + type: 'string' + format: 'uri' $schema: - type: "string" - format: "uri" - "default": "http://json-schema.org/draft-04/schema#" + type: 'string' + format: 'uri' + 'default': 'http://json-schema.org/draft-04/schema#' title: - type: "string" + type: 'string' description: - type: "string" - "default": {} + type: 'string' + 'default': {} multipleOf: - type: "number" + type: 'number' minimum: 0 exclusiveMinimum: true maximum: - type: "number" + type: 'number' exclusiveMaximum: - type: "boolean" - "default": false + type: 'boolean' + 'default': false minimum: - type: "number" + type: 'number' exclusiveMinimum: - type: "boolean" - "default": false - maxLength: { $ref: "#/definitions/positiveInteger" } - minLength: { $ref: "#/definitions/positiveIntegerDefault0" } + type: 'boolean' + 'default': false + maxLength: {$ref: '#/definitions/positiveInteger'} + minLength: {$ref: '#/definitions/positiveIntegerDefault0'} pattern: - type: "string" - format: "regex" + type: 'string' + format: 'regex' additionalItems: anyOf: [ - { type: "boolean", "default": false } - { $ref: "#" } + {type: 'boolean', 'default': false} + {$ref: '#'} ] items: anyOf: [ - { $ref: "#" } - { $ref: "#/definitions/schemaArray" } + {$ref: '#'} + {$ref: '#/definitions/schemaArray'} ] - "default": {} - maxItems: { $ref: "#/definitions/positiveInteger" } - minItems: { $ref: "#/definitions/positiveIntegerDefault0" } + 'default': {} + maxItems: {$ref: '#/definitions/positiveInteger'} + minItems: {$ref: '#/definitions/positiveIntegerDefault0'} uniqueItems: - type: "boolean" - "default": false - maxProperties: { $ref: "#/definitions/positiveInteger" } - minProperties: { $ref: "#/definitions/positiveIntegerDefault0" } - required: { $ref: "#/definitions/stringArray" } + type: 'boolean' + 'default': false + maxProperties: {$ref: '#/definitions/positiveInteger'} + minProperties: {$ref: '#/definitions/positiveIntegerDefault0'} + required: {$ref: '#/definitions/stringArray'} additionalProperties: anyOf: [ - { type: "boolean", "default": true } - { $ref: "#" } + {type: 'boolean', 'default': true} + {$ref: '#'} ] - "default": {} + 'default': {} definitions: - type: "object" - additionalProperties: { $ref: "#" } - "default": {} + type: 'object' + additionalProperties: {$ref: '#'} + 'default': {} properties: - type: "object" - additionalProperties: { $ref: "#" } - "default": {} + type: 'object' + additionalProperties: {$ref: '#'} + 'default': {} patternProperties: - type: "object" - additionalProperties: { $ref: "#" } - "default": {} + type: 'object' + additionalProperties: {$ref: '#'} + 'default': {} dependencies: - type: "object" + type: 'object' additionalProperties: anyOf: [ - { $ref: "#" } - { $ref: "#/definitions/stringArray" } + {$ref: '#'} + {$ref: '#/definitions/stringArray'} ] - "enum": - type: "array" + 'enum': + type: 'array' minItems: 1 uniqueItems: true - "default": [''] + 'default': [''] type: anyOf: [ - { $ref: "#/definitions/simpleTypes" } + {$ref: '#/definitions/simpleTypes'} { - type: "array" - items: { $ref: "#/definitions/simpleTypes" } + type: 'array' + items: {$ref: '#/definitions/simpleTypes'} minItems: 1 uniqueItems: true - title: "Array of Types" - "default": ['string'] + title: 'Array of Types' + 'default': ['string'] }] - allOf: { $ref: "#/definitions/schemaArray" } - anyOf: { $ref: "#/definitions/schemaArray" } - oneOf: { $ref: "#/definitions/schemaArray" } - not: { $ref: "#" } + allOf: {$ref: '#/definitions/schemaArray'} + anyOf: {$ref: '#/definitions/schemaArray'} + oneOf: {$ref: '#/definitions/schemaArray'} + not: {$ref: '#'} dependencies: - exclusiveMaximum: [ "maximum" ] - exclusiveMinimum: [ "minimum" ] - "default": {} + exclusiveMaximum: ['maximum'] + exclusiveMinimum: ['minimum'] + 'default': {} diff --git a/app/schemas/models/achievement.coffee b/app/schemas/models/achievement.coffee index d02e9c8fd..196c81974 100644 --- a/app/schemas/models/achievement.coffee +++ b/app/schemas/models/achievement.coffee @@ -11,7 +11,7 @@ MongoQueryOperatorSchema = '$in': type: 'array' '$lt': type: 'number' '$lte': type: 'number' - '$ne': type: [ 'number', 'string' ] + '$ne': type: ['number', 'string'] '$nin': type: 'array' additionalProperties: true # TODO set to false when the schema's done @@ -23,9 +23,9 @@ MongoFindQuerySchema = #'^[-a-zA-Z0-9_]*$': '^[-a-zA-Z0-9\.]*$': oneOf: [ - #{ $ref: '#/definitions/' + MongoQueryOperatorSchema.id}, - { type: 'string' } - { type: 'object' } + #{$ref: '#/definitions/' + MongoQueryOperatorSchema.id}, + {type: 'string'}, + {type: 'object'} ] additionalProperties: true # TODO make Treema accept new pattern matched keys definitions: {} @@ -41,12 +41,12 @@ _.extend(AchievementSchema.properties, query: #type:'object' $ref: '#/definitions/' + MongoFindQuerySchema.id - worth: { type: 'number' } - collection: { type: 'string' } - description: { type: 'string' } - userField: { type: 'string' } + worth: {type: 'number'} + collection: {type: 'string'} + description: {type: 'string'} + userField: {type: 'string'} related: c.objectId(description: 'Related entity') - icon: { type: 'string', format: 'image-file', title: 'Icon' } + icon: {type: 'string', format: 'image-file', title: 'Icon'} proportionalTo: type: 'string' description: 'For repeatables only. Denotes the field a repeatable achievement needs for its calculations' diff --git a/app/schemas/models/article.coffee b/app/schemas/models/article.coffee index 60f65640f..eccab57b3 100644 --- a/app/schemas/models/article.coffee +++ b/app/schemas/models/article.coffee @@ -3,8 +3,8 @@ c = require './../schemas' ArticleSchema = c.object() c.extendNamedProperties ArticleSchema # name first -ArticleSchema.properties.body = { type: 'string', title: 'Content', format: 'markdown' } -ArticleSchema.properties.i18n = { type: 'object', title: 'i18n', format: 'i18n', props: ['name', 'body'] } +ArticleSchema.properties.body = {type: 'string', title: 'Content', format: 'markdown'} +ArticleSchema.properties.i18n = {type: 'object', title: 'i18n', format: 'i18n', props: ['name', 'body']} c.extendBasicProperties ArticleSchema, 'article' c.extendSearchableProperties ArticleSchema diff --git a/app/schemas/models/earned_achievement.coffee b/app/schemas/models/earned_achievement.coffee index e250834d4..12451ceac 100644 --- a/app/schemas/models/earned_achievement.coffee +++ b/app/schemas/models/earned_achievement.coffee @@ -9,7 +9,7 @@ module.exports = [ { rel: 'extra' - href: "/db/user/{($)}" + href: '/db/user/{($)}' } ] achievement: c.objectId diff --git a/app/schemas/models/level.coffee b/app/schemas/models/level.coffee index 302e5e5e9..eba42f599 100644 --- a/app/schemas/models/level.coffee +++ b/app/schemas/models/level.coffee @@ -3,242 +3,242 @@ ThangComponentSchema = require './thang_component' SpecificArticleSchema = c.object() c.extendNamedProperties SpecificArticleSchema # name first -SpecificArticleSchema.properties.body = { type: 'string', title: 'Content', description: "The body content of the article, in Markdown.", format: 'markdown' } -SpecificArticleSchema.properties.i18n = {type: "object", format: 'i18n', props: ['name', 'body'], description: "Help translate this article"} +SpecificArticleSchema.properties.body = {type: 'string', title: 'Content', description: 'The body content of the article, in Markdown.', format: 'markdown'} +SpecificArticleSchema.properties.i18n = {type: 'object', format: 'i18n', props: ['name', 'body'], description: 'Help translate this article'} SpecificArticleSchema.displayProperty = 'name' -side = {title: "Side", description: "A side.", type: 'string', 'enum': ['left', 'right', 'top', 'bottom']} -thang = {title: "Thang", description: "The name of a Thang.", type: 'string', maxLength: 30, format:'thang'} +side = {title: 'Side', description: 'A side.', type: 'string', 'enum': ['left', 'right', 'top', 'bottom']} +thang = {title: 'Thang', description: 'The name of a Thang.', type: 'string', maxLength: 30, format: 'thang'} -eventPrereqValueTypes = ["boolean", "integer", "number", "null", "string"] # not "object" or "array" -EventPrereqSchema = c.object {title: "Event Prerequisite", format: 'event-prereq', description: "Script requires that the value of some property on the event triggering it to meet some prerequisite.", "default": {eventProps: []}, required: ["eventProps"]}, - eventProps: c.array {'default': ["thang"], format:'event-value-chain', maxItems: 10, title: "Event Property", description: 'A chain of keys in the event, like "thang.pos.x" to access event.thang.pos.x.'}, c.shortString(title: "Property", description: "A key in the event property key chain.") - equalTo: c.object {type: eventPrereqValueTypes, title: "==", description: "Script requires the event's property chain value to be equal to this value."} - notEqualTo: c.object {type: eventPrereqValueTypes, title: "!=", description: "Script requires the event's property chain value to *not* be equal to this value."} - greaterThan: {type: 'number', title: ">", description: "Script requires the event's property chain value to be greater than this value."} - greaterThanOrEqualTo: {type: 'number', title: ">=", description: "Script requires the event's property chain value to be greater or equal to this value."} - lessThan: {type: 'number', title: "<", description: "Script requires the event's property chain value to be less than this value."} - lessThanOrEqualTo: {type: 'number', title: "<=", description: "Script requires the event's property chain value to be less than or equal to this value."} - containingString: c.shortString(title: "Contains", description: "Script requires the event's property chain value to be a string containing this string.") - notContainingString: c.shortString(title: "Does not contain", description: "Script requires the event's property chain value to *not* be a string containing this string.") - containingRegexp: c.shortString(title: "Contains Regexp", description: "Script requires the event's property chain value to be a string containing this regular expression.") - notContainingRegexp: c.shortString(title: "Does not contain regexp", description: "Script requires the event's property chain value to *not* be a string containing this regular expression.") +eventPrereqValueTypes = ['boolean', 'integer', 'number', 'null', 'string'] # not 'object' or 'array' +EventPrereqSchema = c.object {title: 'Event Prerequisite', format: 'event-prereq', description: 'Script requires that the value of some property on the event triggering it to meet some prerequisite.', 'default': {eventProps: []}, required: ['eventProps']}, + eventProps: c.array {'default': ['thang'], format: 'event-value-chain', maxItems: 10, title: 'Event Property', description: 'A chain of keys in the event, like "thang.pos.x" to access event.thang.pos.x.'}, c.shortString(title: 'Property', description: 'A key in the event property key chain.') + equalTo: c.object {type: eventPrereqValueTypes, title: '==', description: 'Script requires the event\'s property chain value to be equal to this value.'} + notEqualTo: c.object {type: eventPrereqValueTypes, title: '!=', description: 'Script requires the event\'s property chain value to *not* be equal to this value.'} + greaterThan: {type: 'number', title: '>', description: 'Script requires the event\'s property chain value to be greater than this value.'} + greaterThanOrEqualTo: {type: 'number', title: '>=', description: 'Script requires the event\'s property chain value to be greater or equal to this value.'} + lessThan: {type: 'number', title: '<', description: 'Script requires the event\'s property chain value to be less than this value.'} + lessThanOrEqualTo: {type: 'number', title: '<=', description: 'Script requires the event\'s property chain value to be less than or equal to this value.'} + containingString: c.shortString(title: 'Contains', description: 'Script requires the event\'s property chain value to be a string containing this string.') + notContainingString: c.shortString(title: 'Does not contain', description: 'Script requires the event\'s property chain value to *not* be a string containing this string.') + containingRegexp: c.shortString(title: 'Contains Regexp', description: 'Script requires the event\'s property chain value to be a string containing this regular expression.') + notContainingRegexp: c.shortString(title: 'Does not contain regexp', description: 'Script requires the event\'s property chain value to *not* be a string containing this regular expression.') -GoalSchema = c.object {title: "Goal", description: "A goal that the player can accomplish.", required: ["name", "id"]}, - name: c.shortString(title: "Name", description: "Name of the goal that the player will see, like \"Defeat eighteen dragons\".") - i18n: {type: "object", format: 'i18n', props: ['name'], description: "Help translate this goal"} - id: c.shortString(title: "ID", description: "Unique identifier for this goal, like \"defeat-dragons\".") # unique somehow? - worldEndsAfter: {title: 'World Ends After', description: "When included, ends the world this many seconds after this goal succeeds or fails.", type: 'number', minimum: 0, exclusiveMinimum: true, maximum: 300, default: 3} - howMany: {title: "How Many", description: "When included, require only this many of the listed goal targets instead of all of them.", type: 'integer', minimum: 1} - hiddenGoal: {title: "Hidden", description: "Hidden goals don't show up in the goals area for the player until they're failed. (Usually they're obvious, like 'don't die'.)", 'type': 'boolean', default: false} +GoalSchema = c.object {title: 'Goal', description: 'A goal that the player can accomplish.', required: ['name', 'id']}, + name: c.shortString(title: 'Name', description: 'Name of the goal that the player will see, like \"Defeat eighteen dragons\".') + i18n: {type: 'object', format: 'i18n', props: ['name'], description: 'Help translate this goal'} + id: c.shortString(title: 'ID', description: 'Unique identifier for this goal, like \"defeat-dragons\".') # unique somehow? + worldEndsAfter: {title: 'World Ends After', description: 'When included, ends the world this many seconds after this goal succeeds or fails.', type: 'number', minimum: 0, exclusiveMinimum: true, maximum: 300, default: 3} + howMany: {title: 'How Many', description: 'When included, require only this many of the listed goal targets instead of all of them.', type: 'integer', minimum: 1} + hiddenGoal: {title: 'Hidden', description: 'Hidden goals don\'t show up in the goals area for the player until they\'re failed. (Usually they\'re obvious, like "don\'t die".)', 'type': 'boolean', default: false} team: c.shortString(title: 'Team', description: 'Name of the team this goal is for, if it is not for all of the playable teams.') - killThangs: c.array {title: "Kill Thangs", description: "A list of Thang IDs the player should kill, or team names.", uniqueItems: true, minItems: 1, "default": ["ogres"]}, thang - saveThangs: c.array {title: "Save Thangs", description: "A list of Thang IDs the player should save, or team names", uniqueItems: true, minItems: 1, "default": ["humans"]}, thang - getToLocations: c.object {title: "Get To Locations", description: "Will be set off when any of the \"who\" touch any of the \"targets\" ", required: ["who", "targets"]}, - who: c.array {title: "Who", description: "The Thangs who must get to the target locations.", minItems: 1}, thang - targets: c.array {title: "Targets", description: "The target locations to which the Thangs must get.", minItems: 1}, thang - getAllToLocations: c.array {title: "Get all to locations", description: "Similar to getToLocations but now a specific \"who\" can have a specific \"target\", also must be used with the HowMany property for desired effect",required: ["getToLocation"]}, - c.object {title: "", description: ""}, - getToLocation: c.object {title: "Get To Locations", description: "TODO: explain", required: ["who", "targets"]}, - who: c.array {title: "Who", description: "The Thangs who must get to the target locations.", minItems: 1}, thang - targets: c.array {title: "Targets", description: "The target locations to which the Thangs must get.", minItems: 1}, thang - keepFromLocations: c.object {title: "Keep From Locations", description: "TODO: explain", required: ["who", "targets"]}, - who: c.array {title: "Who", description: "The Thangs who must not get to the target locations.", minItems: 1}, thang - targets: c.array {title: "Targets", description: "The target locations to which the Thangs must not get.", minItems: 1}, thang - keepAllFromLocations: c.array {title: "Keep ALL From Locations", description: "Similar to keepFromLocations but now a specific \"who\" can have a specific \"target\", also must be used with the HowMany property for desired effect", required: ["keepFromLocation"]}, - c.object {title: "", description: ""}, - keepFromLocation: c.object {title: "Keep From Locations", description: "TODO: explain", required: ["who", "targets"]}, - who: c.array {title: "Who", description: "The Thangs who must not get to the target locations.", minItems: 1}, thang - targets: c.array {title: "Targets", description: "The target locations to which the Thangs must not get.", minItems: 1}, thang - leaveOffSides: c.object {title: "Leave Off Sides", description: "Sides of the level to get some Thangs to leave across.", required: ["who", "sides"]}, - who: c.array {title: "Who", description: "The Thangs which must leave off the sides of the level.", minItems: 1}, thang - sides: c.array {title: "Sides", description: "The sides off which the Thangs must leave.", minItems: 1}, side - keepFromLeavingOffSides: c.object {title: "Keep From Leaving Off Sides", description: "Sides of the level to keep some Thangs from leaving across.", required: ["who", "sides"]}, - who: c.array {title: "Who", description: "The Thangs which must not leave off the sides of the level.", minItems: 1}, thang - sides: side, {title: "Sides", description: "The sides off which the Thangs must not leave.", minItems: 1}, side - collectThangs: c.object {title: "Collect", description: "Thangs that other Thangs must collect.", required: ["who", "targets"]}, - who: c.array {title: "Who", description: "The Thangs which must collect the target items.", minItems: 1}, thang - targets: c.array {title: "Targets", description: "The target items which the Thangs must collect.", minItems: 1}, thang - keepFromCollectingThangs: c.object {title: "Keep From Collecting", description: "Thangs that the player must prevent other Thangs from collecting.", required: ["who", "targets"]}, - who: c.array {title: "Who", description: "The Thangs which must not collect the target items.", minItems: 1}, thang - targets: c.array {title: "Targets", description: "The target items which the Thangs must not collect.", minItems: 1}, thang + killThangs: c.array {title: 'Kill Thangs', description: 'A list of Thang IDs the player should kill, or team names.', uniqueItems: true, minItems: 1, 'default': ['ogres']}, thang + saveThangs: c.array {title: 'Save Thangs', description: 'A list of Thang IDs the player should save, or team names', uniqueItems: true, minItems: 1, 'default': ['humans']}, thang + getToLocations: c.object {title: 'Get To Locations', description: 'Will be set off when any of the \"who\" touch any of the \"targets\"', required: ['who', 'targets']}, + who: c.array {title: 'Who', description: 'The Thangs who must get to the target locations.', minItems: 1}, thang + targets: c.array {title: 'Targets', description: 'The target locations to which the Thangs must get.', minItems: 1}, thang + getAllToLocations: c.array {title: 'Get all to locations', description: 'Similar to getToLocations but now a specific \"who\" can have a specific \"target\", also must be used with the HowMany property for desired effect', required: ['getToLocation']}, + c.object {title: '', description: ''}, + getToLocation: c.object {title: 'Get To Locations', description: 'TODO: explain', required: ['who', 'targets']}, + who: c.array {title: 'Who', description: 'The Thangs who must get to the target locations.', minItems: 1}, thang + targets: c.array {title: 'Targets', description: 'The target locations to which the Thangs must get.', minItems: 1}, thang + keepFromLocations: c.object {title: 'Keep From Locations', description: 'TODO: explain', required: ['who', 'targets']}, + who: c.array {title: 'Who', description: 'The Thangs who must not get to the target locations.', minItems: 1}, thang + targets: c.array {title: 'Targets', description: 'The target locations to which the Thangs must not get.', minItems: 1}, thang + keepAllFromLocations: c.array {title: 'Keep ALL From Locations', description: 'Similar to keepFromLocations but now a specific \"who\" can have a specific \"target\", also must be used with the HowMany property for desired effect', required: ['keepFromLocation']}, + c.object {title: '', description: ''}, + keepFromLocation: c.object {title: 'Keep From Locations', description: 'TODO: explain', required: ['who', 'targets']}, + who: c.array {title: 'Who', description: 'The Thangs who must not get to the target locations.', minItems: 1}, thang + targets: c.array {title: 'Targets', description: 'The target locations to which the Thangs must not get.', minItems: 1}, thang + leaveOffSides: c.object {title: 'Leave Off Sides', description: 'Sides of the level to get some Thangs to leave across.', required: ['who', 'sides']}, + who: c.array {title: 'Who', description: 'The Thangs which must leave off the sides of the level.', minItems: 1}, thang + sides: c.array {title: 'Sides', description: 'The sides off which the Thangs must leave.', minItems: 1}, side + keepFromLeavingOffSides: c.object {title: 'Keep From Leaving Off Sides', description: 'Sides of the level to keep some Thangs from leaving across.', required: ['who', 'sides']}, + who: c.array {title: 'Who', description: 'The Thangs which must not leave off the sides of the level.', minItems: 1}, thang + sides: side, {title: 'Sides', description: 'The sides off which the Thangs must not leave.', minItems: 1}, side + collectThangs: c.object {title: 'Collect', description: 'Thangs that other Thangs must collect.', required: ['who', 'targets']}, + who: c.array {title: 'Who', description: 'The Thangs which must collect the target items.', minItems: 1}, thang + targets: c.array {title: 'Targets', description: 'The target items which the Thangs must collect.', minItems: 1}, thang + keepFromCollectingThangs: c.object {title: 'Keep From Collecting', description: 'Thangs that the player must prevent other Thangs from collecting.', required: ['who', 'targets']}, + who: c.array {title: 'Who', description: 'The Thangs which must not collect the target items.', minItems: 1}, thang + targets: c.array {title: 'Targets', description: 'The target items which the Thangs must not collect.', minItems: 1}, thang -ResponseSchema = c.object {title: "Dialogue Button", description: "A button to be shown to the user with the dialogue.", required: ["text"]}, - text: {title: "Title", description: "The text that will be on the button", "default": "Okay", type: 'string', maxLength: 30} - channel: c.shortString(title: "Channel", format: 'event-channel', description: 'Channel that this event will be broadcast over, like "level-set-playing".') - event: {type: 'object', title: "Event", description: "Event that will be broadcast when this button is pressed, like {playing: true}."} - buttonClass: c.shortString(title: "Button Class", description: 'CSS class that will be added to the button, like "btn-primary".') - i18n: {type: "object", format: 'i18n', props: ['text'], description: "Help translate this button"} +ResponseSchema = c.object {title: 'Dialogue Button', description: 'A button to be shown to the user with the dialogue.', required: ['text']}, + text: {title: 'Title', description: 'The text that will be on the button', 'default': 'Okay', type: 'string', maxLength: 30} + channel: c.shortString(title: 'Channel', format: 'event-channel', description: 'Channel that this event will be broadcast over, like "level-set-playing".') + event: {type: 'object', title: 'Event', description: 'Event that will be broadcast when this button is pressed, like {playing: true}.'} + buttonClass: c.shortString(title: 'Button Class', description: 'CSS class that will be added to the button, like "btn-primary".') + i18n: {type: 'object', format: 'i18n', props: ['text'], description: 'Help translate this button'} -PointSchema = c.object {title: "Point", description: "An {x, y} coordinate point.", format: "point2d", required: ["x", "y"]}, - x: {title: "x", description: "The x coordinate.", type: "number", "default": 15} - y: {title: "y", description: "The y coordinate.", type: "number", "default": 20} +PointSchema = c.object {title: 'Point', description: 'An {x, y} coordinate point.', format: 'point2d', required: ['x', 'y']}, + x: {title: 'x', description: 'The x coordinate.', type: 'number', 'default': 15} + y: {title: 'y', description: 'The y coordinate.', type: 'number', 'default': 20} -SpriteCommandSchema = c.object {title: "Thang Command", description: "Make a target Thang move or say something, or select/deselect it.", required: ["id"], default: {id: "Captain Anya"}}, +SpriteCommandSchema = c.object {title: 'Thang Command', description: 'Make a target Thang move or say something, or select/deselect it.', required: ['id'], default: {id: 'Captain Anya'}}, id: thang - select: {title: "Select", description: "Select or deselect this Thang.", type: 'boolean'} - say: c.object {title: "Say", description: "Make this Thang say a message.", required: ["text"]}, - blurb: c.shortString(title: "Blurb", description: "A very short message to display above this Thang's head. Plain text.", maxLength: 50) - mood: c.shortString(title: "Mood", description: "The mood with which the Thang speaks.", "enum": ["explain", "debrief", "congrats", "attack", "joke", "tip", "alarm"], "default": "explain") - text: {title: "Text", description: "A short message to display in the dialogue area. Markdown okay.", type: "string", maxLength: 400} - sound: c.object {title: "Sound", description: "A dialogue sound file to accompany the message.", required: ["mp3", "ogg"]}, - mp3: c.shortString(title: "MP3", format: 'sound-file') - ogg: c.shortString(title: "OGG", format: 'sound-file') - preload: {title: "Preload", description: "Whether to load this sound file before the level can begin (typically for the first dialogue of a level).", type: 'boolean', "default": false} - responses: c.array {title: "Buttons", description: "An array of buttons to include with the dialogue, with which the user can respond."}, ResponseSchema - i18n: {type: "object", format: 'i18n', props: ['blurb', 'text'], description: "Help translate this message"} - move: c.object {title: "Move", description: "Tell the Thang to move.", required: ['target'], default: {target: {x: 20, y: 20}, duration: 500}}, + select: {title: 'Select', description: 'Select or deselect this Thang.', type: 'boolean'} + say: c.object {title: 'Say', description: 'Make this Thang say a message.', required: ['text']}, + blurb: c.shortString(title: 'Blurb', description: 'A very short message to display above this Thang\'s head. Plain text.', maxLength: 50) + mood: c.shortString(title: 'Mood', description: 'The mood with which the Thang speaks.', 'enum': ['explain', 'debrief', 'congrats', 'attack', 'joke', 'tip', 'alarm'], 'default': 'explain') + text: {title: 'Text', description: 'A short message to display in the dialogue area. Markdown okay.', type: 'string', maxLength: 400} + sound: c.object {title: 'Sound', description: 'A dialogue sound file to accompany the message.', required: ['mp3', 'ogg']}, + mp3: c.shortString(title: 'MP3', format: 'sound-file') + ogg: c.shortString(title: 'OGG', format: 'sound-file') + preload: {title: 'Preload', description: 'Whether to load this sound file before the level can begin (typically for the first dialogue of a level).', type: 'boolean', 'default': false} + responses: c.array {title: 'Buttons', description: 'An array of buttons to include with the dialogue, with which the user can respond.'}, ResponseSchema + i18n: {type: 'object', format: 'i18n', props: ['blurb', 'text'], description: 'Help translate this message'} + move: c.object {title: 'Move', description: 'Tell the Thang to move.', required: ['target'], default: {target: {x: 20, y: 20}, duration: 500}}, target: _.extend _.cloneDeep(PointSchema), {title: 'Target', description: 'Target point to which the Thang will move.'} - duration: {title: "Duration", description: "Number of milliseconds over which to move, or 0 for an instant move.", type: 'integer', minimum: 0, default: 500, format: 'milliseconds'} + duration: {title: 'Duration', description: 'Number of milliseconds over which to move, or 0 for an instant move.', type: 'integer', minimum: 0, default: 500, format: 'milliseconds'} -NoteGroupSchema = c.object {title: "Note Group", description: "A group of notes that should be sent out as a result of this script triggering.", displayProperty: "name"}, - name: {title: "Name", description: "Short name describing the script, like \"Anya greets the player\", for your convenience.", type: "string"} - dom: c.object {title: "DOM", description: "Manipulate things in the play area DOM, outside of the level area canvas."}, - focus: c.shortString(title: "Focus", description: "Set the window focus to this DOM selector string.") +NoteGroupSchema = c.object {title: 'Note Group', description: 'A group of notes that should be sent out as a result of this script triggering.', displayProperty: 'name'}, + name: {title: 'Name', description: 'Short name describing the script, like \"Anya greets the player\", for your convenience.', type: 'string'} + dom: c.object {title: 'DOM', description: 'Manipulate things in the play area DOM, outside of the level area canvas.'}, + focus: c.shortString(title: 'Focus', description: 'Set the window focus to this DOM selector string.') showVictory: { - title: "Show Victory", - description: "Show the done button and maybe also the victory modal.", + title: 'Show Victory', + description: 'Show the done button and maybe also the victory modal.', enum: [true, 'Done Button', 'Done Button And Modal'] # deprecate true, same as 'done_button_and_modal' } - highlight: c.object {title: "Highlight", description: "Highlight the target DOM selector string with a big arrow."}, - target: c.shortString(title: "Target", description: "Target highlight element DOM selector string.") - delay: {type: 'integer', minimum: 0, title: "Delay", description: "Show the highlight after this many milliseconds. Doesn't affect the dim shade cutout highlight method."} + highlight: c.object {title: 'Highlight', description: 'Highlight the target DOM selector string with a big arrow.'}, + target: c.shortString(title: 'Target', description: 'Target highlight element DOM selector string.') + delay: {type: 'integer', minimum: 0, title: 'Delay', description: 'Show the highlight after this many milliseconds. Doesn\'t affect the dim shade cutout highlight method.'} offset: _.extend _.cloneDeep(PointSchema), {title: 'Offset', description: 'Pointing arrow tip offset in pixels from the default target.', format: null} - rotation: {type: 'number', minimum: 0, title: "Rotation", description: "Rotation of the pointing arrow, in radians. PI / 2 points left, PI points up, etc."} - sides: c.array {title: "Sides", description: "Which sides of the target element to point at."}, {type: 'string', 'enum': ['left', 'right', 'top', 'bottom'], title: "Side", description: "A side of the target element to point at."} - lock: {title: "Lock", description: "Whether the interface should be locked so that the player's focus is on the script, or specific areas to lock.", type: ['boolean', 'array'], items: {type: 'string', enum: ['surface', 'editor', 'palette', 'hud', 'playback', 'playback-hover', 'level']}} - letterbox: {type: 'boolean', title: 'Letterbox', description:'Turn letterbox mode on or off. Disables surface and playback controls.'} + rotation: {type: 'number', minimum: 0, title: 'Rotation', description: 'Rotation of the pointing arrow, in radians. PI / 2 points left, PI points up, etc.'} + sides: c.array {title: 'Sides', description: 'Which sides of the target element to point at.'}, {type: 'string', 'enum': ['left', 'right', 'top', 'bottom'], title: 'Side', description: 'A side of the target element to point at.'} + lock: {title: 'Lock', description: 'Whether the interface should be locked so that the player\'s focus is on the script, or specific areas to lock.', type: ['boolean', 'array'], items: {type: 'string', enum: ['surface', 'editor', 'palette', 'hud', 'playback', 'playback-hover', 'level']}} + letterbox: {type: 'boolean', title: 'Letterbox', description: 'Turn letterbox mode on or off. Disables surface and playback controls.'} - goals: c.object {title: "Goals (Old)", description: "Deprecated. Goals added here have no effect. Add goals in the level settings instead."}, - add: c.array {title: "Add", description: "Deprecated. Goals added here have no effect. Add goals in the level settings instead."}, GoalSchema - remove: c.array {title: "Remove", description: "Deprecated. Goals removed here have no effect. Adjust goals in the level settings instead."}, GoalSchema + goals: c.object {title: 'Goals (Old)', description: 'Deprecated. Goals added here have no effect. Add goals in the level settings instead.'}, + add: c.array {title: 'Add', description: 'Deprecated. Goals added here have no effect. Add goals in the level settings instead.'}, GoalSchema + remove: c.array {title: 'Remove', description: 'Deprecated. Goals removed here have no effect. Adjust goals in the level settings instead.'}, GoalSchema - playback: c.object {title: "Playback", description: "Control the playback of the level."}, - playing: {type: 'boolean', title: "Set Playing", description: "Set whether playback is playing or paused."} - scrub: c.object {title: "Scrub", description: "Scrub the level playback time to a certain point.", default: {offset: 2, duration: 1000, toRatio: 0.5}}, - offset: {type: 'integer', title: "Offset", description: "Number of frames by which to adjust the scrub target time.", default: 2} - duration: {type: 'integer', title: "Duration", description: "Number of milliseconds over which to scrub time.", minimum: 0, format: 'milliseconds'} - toRatio: {type: 'number', title: "To Progress Ratio", description: "Set playback time to a target playback progress ratio.", minimum: 0, maximum: 1} - toTime: {type: 'number', title: "To Time", description: "Set playback time to a target playback point, in seconds.", minimum: 0} - toGoal: c.shortString(title: "To Goal", description: "Set playback time to when this goal was achieved. (TODO: not implemented.)") + playback: c.object {title: 'Playback', description: 'Control the playback of the level.'}, + playing: {type: 'boolean', title: 'Set Playing', description: 'Set whether playback is playing or paused.'} + scrub: c.object {title: 'Scrub', description: 'Scrub the level playback time to a certain point.', default: {offset: 2, duration: 1000, toRatio: 0.5}}, + offset: {type: 'integer', title: 'Offset', description: 'Number of frames by which to adjust the scrub target time.', default: 2} + duration: {type: 'integer', title: 'Duration', description: 'Number of milliseconds over which to scrub time.', minimum: 0, format: 'milliseconds'} + toRatio: {type: 'number', title: 'To Progress Ratio', description: 'Set playback time to a target playback progress ratio.', minimum: 0, maximum: 1} + toTime: {type: 'number', title: 'To Time', description: 'Set playback time to a target playback point, in seconds.', minimum: 0} + toGoal: c.shortString(title: 'To Goal', description: 'Set playback time to when this goal was achieved. (TODO: not implemented.)') - script: c.object {title: "Script", description: "Extra configuration for this action group."}, - duration: {type: 'integer', minimum: 0, title: "Duration", description: "How long this script should last in milliseconds. 0 for indefinite.", format: 'milliseconds'} - skippable: {type: 'boolean', title: "Skippable", description: "Whether this script shouldn't bother firing when the player skips past all current scripts."} - beforeLoad: {type: 'boolean', title: "Before Load", description: "Whether this script should fire before the level is finished loading."} + script: c.object {title: 'Script', description: 'Extra configuration for this action group.'}, + duration: {type: 'integer', minimum: 0, title: 'Duration', description: 'How long this script should last in milliseconds. 0 for indefinite.', format: 'milliseconds'} + skippable: {type: 'boolean', title: 'Skippable', description: 'Whether this script shouldn\'t bother firing when the player skips past all current scripts.'} + beforeLoad: {type: 'boolean', title: 'Before Load', description: 'Whether this script should fire before the level is finished loading.'} - sprites: c.array {title: "Sprites", description: "Commands to issue to Sprites on the Surface."}, SpriteCommandSchema + sprites: c.array {title: 'Sprites', description: 'Commands to issue to Sprites on the Surface.'}, SpriteCommandSchema - surface: c.object {title: "Surface", description: "Commands to issue to the Surface itself."}, - focus: c.object {title: "Camera", description: "Focus the camera on a specific point on the Surface.", format:'viewport'}, - target: {anyOf: [PointSchema, thang, {type: 'null'}], title: "Target", description: "Where to center the camera view.", default: {x:0, y:0}} - zoom: {type: 'number', minimum: 0, exclusiveMinimum: true, maximum: 64, title: "Zoom", description: "What zoom level to use."} - duration: {type:'number', minimum: 0, title: "Duration", description: "in ms"} - bounds: c.array {title:'Boundary', maxItems: 2, minItems: 2, default:[{x:0,y:0}, {x:46, y:39}], format: 'bounds'}, PointSchema - isNewDefault: {type:'boolean', format: 'hidden', title: "New Default", description: 'Set this as new default zoom once scripts end.'} # deprecated - highlight: c.object {title: "Highlight", description: "Highlight specific Sprites on the Surface."}, - targets: c.array {title: "Targets", description: "Thang IDs of target Sprites to highlight."}, thang - delay: {type: 'integer', minimum: 0, title: "Delay", description: "Delay in milliseconds before the highlight appears."} - lockSelect: {type: 'boolean', title: "Lock Select", description: "Whether to lock Sprite selection so that the player can't select/deselect anything."} + surface: c.object {title: 'Surface', description: 'Commands to issue to the Surface itself.'}, + focus: c.object {title: 'Camera', description: 'Focus the camera on a specific point on the Surface.', format: 'viewport'}, + target: {anyOf: [PointSchema, thang, {type: 'null'}], title: 'Target', description: 'Where to center the camera view.', default: {x: 0, y: 0}} + zoom: {type: 'number', minimum: 0, exclusiveMinimum: true, maximum: 64, title: 'Zoom', description: 'What zoom level to use.'} + duration: {type: 'number', minimum: 0, title: 'Duration', description: 'in ms'} + bounds: c.array {title: 'Boundary', maxItems: 2, minItems: 2, default: [{x: 0, y: 0}, {x: 46, y: 39}], format: 'bounds'}, PointSchema + isNewDefault: {type: 'boolean', format: 'hidden', title: 'New Default', description: 'Set this as new default zoom once scripts end.'} # deprecated + highlight: c.object {title: 'Highlight', description: 'Highlight specific Sprites on the Surface.'}, + targets: c.array {title: 'Targets', description: 'Thang IDs of target Sprites to highlight.'}, thang + delay: {type: 'integer', minimum: 0, title: 'Delay', description: 'Delay in milliseconds before the highlight appears.'} + lockSelect: {type: 'boolean', title: 'Lock Select', description: 'Whether to lock Sprite selection so that the player can\'t select/deselect anything.'} - sound: c.object {title: "Sound", description: "Commands to control sound playback."}, - suppressSelectionSounds: {type: "boolean", title: "Suppress Selection Sounds", description: "Whether to suppress selection sounds made from clicking on Thangs."} - music: c.object { title: "Music", description: "Control music playing"}, - play: { title: "Play", type: "boolean" } - file: c.shortString(title: "File", enum:['/music/music_level_1','/music/music_level_2','/music/music_level_3','/music/music_level_4','/music/music_level_5']) + sound: c.object {title: 'Sound', description: 'Commands to control sound playback.'}, + suppressSelectionSounds: {type: 'boolean', title: 'Suppress Selection Sounds', description: 'Whether to suppress selection sounds made from clicking on Thangs.'} + music: c.object {title: 'Music', description: 'Control music playing'}, + play: {title: 'Play', type: 'boolean'} + file: c.shortString(title: 'File', enum: ['/music/music_level_1', '/music/music_level_2', '/music/music_level_3', '/music/music_level_4', '/music/music_level_5']) ScriptSchema = c.object { - title: "Script" + title: 'Script' description: 'A script fires off a chain of notes to interact with the game when a certain event triggers it.' - required: ["channel"] - 'default': {channel: "world:won", noteChain: []} + required: ['channel'] + 'default': {channel: 'world:won', noteChain: []} }, - id: c.shortString(title: "ID", description: "A unique ID that other scripts can rely on in their Happens After prereqs, for sequencing.") # uniqueness? - channel: c.shortString(title: "Event", format: 'event-channel', description: 'Event channel this script might trigger for, like "world:won".') - eventPrereqs: c.array {title: "Event Checks", description: "Logical checks on the event for this script to trigger.", format:'event-prereqs'}, EventPrereqSchema - repeats: {title: "Repeats", description: "Whether this script can trigger more than once during a level.", enum: [true, false, 'session'], "default": false} - scriptPrereqs: c.array {title: "Happens After", description: "Scripts that need to fire first."}, - c.shortString(title: "ID", description: "A unique ID of a script.") - notAfter: c.array {title: "Not After", description: "Do not run this script if any of these scripts have run."}, - c.shortString(title: "ID", description: "A unique ID of a script.") - noteChain: c.array {title: "Actions", description: "A list of things that happen when this script triggers."}, NoteGroupSchema + id: c.shortString(title: 'ID', description: 'A unique ID that other scripts can rely on in their Happens After prereqs, for sequencing.') # uniqueness? + channel: c.shortString(title: 'Event', format: 'event-channel', description: 'Event channel this script might trigger for, like "world:won".') + eventPrereqs: c.array {title: 'Event Checks', description: 'Logical checks on the event for this script to trigger.', format: 'event-prereqs'}, EventPrereqSchema + repeats: {title: 'Repeats', description: 'Whether this script can trigger more than once during a level.', enum: [true, false, 'session'], 'default': false} + scriptPrereqs: c.array {title: 'Happens After', description: 'Scripts that need to fire first.'}, + c.shortString(title: 'ID', description: 'A unique ID of a script.') + notAfter: c.array {title: 'Not After', description: 'Do not run this script if any of these scripts have run.'}, + c.shortString(title: 'ID', description: 'A unique ID of a script.') + noteChain: c.array {title: 'Actions', description: 'A list of things that happen when this script triggers.'}, NoteGroupSchema LevelThangSchema = c.object { - title: "Thang", - description: "Thangs are any units, doodads, or abstract things that you use to build the level. (\"Thing\" was too confusing to say.)", - format: "thang" - required: ["id", "thangType", "components"] + title: 'Thang', + description: 'Thangs are any units, doodads, or abstract things that you use to build the level. (\"Thing\" was too confusing to say.)', + format: 'thang' + required: ['id', 'thangType', 'components'] 'default': - id: "Boris" - thangType: "Soldier" + id: 'Boris' + thangType: 'Soldier' components: [] }, id: thang # TODO: figure out if we can make this unique and how to set dynamic defaults - # TODO: split thangType into "original" and "majorVersion" like the rest for consistency - thangType: c.objectId(links: [{rel: "db", href: "/db/thang.type/{($)}/version"}], title: "Thang Type", description: "A reference to the original Thang template being configured.", format: 'thang-type') - components: c.array {title: "Components", description: "Thangs are configured by changing the Components attached to them.", uniqueItems: true, format: 'thang-components-array'}, ThangComponentSchema # TODO: uniqueness should be based on "original", not whole thing + # TODO: split thangType into 'original' and 'majorVersion' like the rest for consistency + thangType: c.objectId(links: [{rel: 'db', href: '/db/thang.type/{($)}/version'}], title: 'Thang Type', description: 'A reference to the original Thang template being configured.', format: 'thang-type') + components: c.array {title: 'Components', description: 'Thangs are configured by changing the Components attached to them.', uniqueItems: true, format: 'thang-components-array'}, ThangComponentSchema # TODO: uniqueness should be based on 'original', not whole thing LevelSystemSchema = c.object { - title: "System" - description: "Configuration for a System that this Level uses." + title: 'System' + description: 'Configuration for a System that this Level uses.' format: 'level-system' required: ['original', 'majorVersion'] 'default': majorVersion: 0 config: {} - links: [{rel: "db", href: "/db/level.system/{(original)}/version/{(majorVersion)}"}] + links: [{rel: 'db', href: '/db/level.system/{(original)}/version/{(majorVersion)}'}] }, - original: c.objectId(title: "Original", description: "A reference to the original System being configured.", format: "hidden") - config: c.object {title: "Configuration", description: "System-specific configuration properties.", additionalProperties: true, format: 'level-system-configuration'} - majorVersion: {title: "Major Version", description: "Which major version of the System is being used.", type: 'integer', minimum: 0, default: 0, format: "hidden"} + original: c.objectId(title: 'Original', description: 'A reference to the original System being configured.', format: 'hidden') + config: c.object {title: 'Configuration', description: 'System-specific configuration properties.', additionalProperties: true, format: 'level-system-configuration'} + majorVersion: {title: 'Major Version', description: 'Which major version of the System is being used.', type: 'integer', minimum: 0, default: 0, format: 'hidden'} GeneralArticleSchema = c.object { - title: "Article" - description: "Reference to a general documentation article." + title: 'Article' + description: 'Reference to a general documentation article.' required: ['original'] format: 'latest-version-reference' 'default': original: null majorVersion: 0 - links: [{rel: "db", href: "/db/article/{(original)}/version/{(majorVersion)}"}] + links: [{rel: 'db', href: '/db/article/{(original)}/version/{(majorVersion)}'}] }, - original: c.objectId(title: "Original", description: "A reference to the original Article.")#, format: "hidden") # hidden? - majorVersion: {title: "Major Version", description: "Which major version of the Article is being used.", type: 'integer', minimum: 0}#, format: "hidden"} # hidden? + original: c.objectId(title: 'Original', description: 'A reference to the original Article.')#, format: 'hidden') # hidden? + majorVersion: {title: 'Major Version', description: 'Which major version of the Article is being used.', type: 'integer', minimum: 0}#, format: 'hidden'} # hidden? LevelSchema = c.object { - title: "Level" - description: "A spectacular level which will delight and educate its stalwart players with the sorcery of coding." - required: ["name", "description", "scripts", "thangs", "documentation"] + title: 'Level' + description: 'A spectacular level which will delight and educate its stalwart players with the sorcery of coding.' + required: ['name', 'description', 'scripts', 'thangs', 'documentation'] 'default': - name: "Ineffable Wizardry" - description: "This level is indescribably flarmy." + name: 'Ineffable Wizardry' + description: 'This level is indescribably flarmy.' documentation: {specificArticles: [], generalArticles: []} scripts: [] thangs: [] } c.extendNamedProperties LevelSchema # let's have the name be the first property _.extend LevelSchema.properties, - description: {title: "Description", description: "A short explanation of what this level is about.", type: "string", maxLength: 65536, "default": "This level is indescribably flarmy!", format: 'markdown'} - documentation: c.object {title: "Documentation", description: "Documentation articles relating to this level.", required: ["specificArticles", "generalArticles"], 'default': {specificArticles: [], generalArticles: []}}, - specificArticles: c.array {title: "Specific Articles", description: "Specific documentation articles that live only in this level.", uniqueItems: true, "default": []}, SpecificArticleSchema - generalArticles: c.array {title: "General Articles", description: "General documentation articles that can be linked from multiple levels.", uniqueItems: true, "default": []}, GeneralArticleSchema + description: {title: 'Description', description: 'A short explanation of what this level is about.', type: 'string', maxLength: 65536, 'default': 'This level is indescribably flarmy!', format: 'markdown'} + documentation: c.object {title: 'Documentation', description: 'Documentation articles relating to this level.', required: ['specificArticles', 'generalArticles'], 'default': {specificArticles: [], generalArticles: []}}, + specificArticles: c.array {title: 'Specific Articles', description: 'Specific documentation articles that live only in this level.', uniqueItems: true, 'default': []}, SpecificArticleSchema + generalArticles: c.array {title: 'General Articles', description: 'General documentation articles that can be linked from multiple levels.', uniqueItems: true, 'default': []}, GeneralArticleSchema background: c.objectId({format: 'hidden'}) nextLevel: { - type:'object', - links: [{rel: "extra", href: "/db/level/{($)}"}, {rel:'db', href: "/db/level/{(original)}/version/{(majorVersion)}"}], + type: 'object', + links: [{rel: 'extra', href: '/db/level/{($)}'}, {rel: 'db', href: '/db/level/{(original)}/version/{(majorVersion)}'}], format: 'latest-version-reference', - title: "Next Level", - description: "Reference to the next level players will play after beating this one." + title: 'Next Level', + description: 'Reference to the next level players will play after beating this one.' } - scripts: c.array {title: "Scripts", description: "An array of scripts that trigger based on what the player does and affect things outside of the core level simulation.", "default": []}, ScriptSchema - thangs: c.array {title: "Thangs", description: "An array of Thangs that make up the level.", "default": []}, LevelThangSchema - systems: c.array {title: "Systems", description: "Levels are configured by changing the Systems attached to them.", uniqueItems: true, default: []}, LevelSystemSchema # TODO: uniqueness should be based on "original", not whole thing - victory: c.object {title: "Victory Screen", default: {}, properties: {'body': {type: 'string', format: 'markdown', title: 'Body Text', description: 'Inserted into the Victory Modal once this level is complete. Tell the player they did a good job and what they accomplished!'}, i18n: {type: "object", format: 'i18n', props: ['body'], description: "Help translate this victory message"}}} - i18n: {type: "object", format: 'i18n', props: ['name', 'description'], description: "Help translate this level"} - icon: { type: 'string', format: 'image-file', title: 'Icon' } + scripts: c.array {title: 'Scripts', description: 'An array of scripts that trigger based on what the player does and affect things outside of the core level simulation.', 'default': []}, ScriptSchema + thangs: c.array {title: 'Thangs', description: 'An array of Thangs that make up the level.', 'default': []}, LevelThangSchema + systems: c.array {title: 'Systems', description: 'Levels are configured by changing the Systems attached to them.', uniqueItems: true, default: []}, LevelSystemSchema # TODO: uniqueness should be based on 'original', not whole thing + victory: c.object {title: 'Victory Screen', default: {}, properties: {'body': {type: 'string', format: 'markdown', title: 'Body Text', description: 'Inserted into the Victory Modal once this level is complete. Tell the player they did a good job and what they accomplished!'}, i18n: {type: 'object', format: 'i18n', props: ['body'], description: 'Help translate this victory message'}}} + i18n: {type: 'object', format: 'i18n', props: ['name', 'description'], description: 'Help translate this level'} + icon: {type: 'string', format: 'image-file', title: 'Icon'} goals: c.array {title: 'Goals', description: 'An array of goals which are visible to the player and can trigger scripts.'}, GoalSchema - type: c.shortString(title: "Type", description: "What kind of level this is.", "enum": ['campaign', 'ladder', 'ladder-tutorial']) - showsGuide: c.shortString(title: "Shows Guide", description: "If the guide is shown at the beginning of the level.", "enum": ['first-time', 'always']) + type: c.shortString(title: 'Type', description: 'What kind of level this is.', 'enum': ['campaign', 'ladder', 'ladder-tutorial']) + showsGuide: c.shortString(title: 'Shows Guide', description: 'If the guide is shown at the beginning of the level.', 'enum': ['first-time', 'always']) c.extendBasicProperties LevelSchema, 'level' c.extendSearchableProperties LevelSchema diff --git a/app/schemas/models/level_component.coffee b/app/schemas/models/level_component.coffee index 5eb519144..b97cb7d1e 100644 --- a/app/schemas/models/level_component.coffee +++ b/app/schemas/models/level_component.coffee @@ -3,54 +3,53 @@ metaschema = require './../metaschema' attackSelfCode = """ class AttacksSelf extends Component - @className: "AttacksSelf" + @className: 'AttacksSelf' chooseAction: -> @attack @ """ systems = [ - 'action', 'ai', 'alliance', 'collision', 'combat', 'display', 'event', 'existence', 'hearing' + 'action', 'ai', 'alliance', 'collision', 'combat', 'display', 'event', 'existence', 'hearing', 'inventory', 'movement', 'programming', 'targeting', 'ui', 'vision', 'misc', 'physics', 'effect', 'magic' ] PropertyDocumentationSchema = c.object { - title: "Property Documentation" - description: "Documentation entry for a property this Component will add to its Thang which other Components might - want to also use." - "default": - name: "foo" - type: "object" + title: 'Property Documentation' + description: 'Documentation entry for a property this Component will add to its Thang which other Components might want to also use.' + 'default': + name: 'foo' + type: 'object' description: 'The `foo` property can satisfy all the #{spriteName}\'s foobar needs. Use it wisely.' required: ['name', 'type', 'description'] }, - name: {type: 'string', title: "Name", description: "Name of the property."} + name: {type: 'string', title: 'Name', description: 'Name of the property.'} # not actual JS types, just whatever they describe... - type: c.shortString(title: "Type", description: "Intended type of the property.") + type: c.shortString(title: 'Type', description: 'Intended type of the property.') description: oneOf: [ - {title: "Description", type: 'string', description: "Description of the property.", maxLength: 1000, format: 'markdown'} + {title: 'Description', type: 'string', description: 'Description of the property.', maxLength: 1000, format: 'markdown'} { type: 'object', - title: "Language Descriptions", - description: "Property descriptions by code language.", - additionalProperties: {type: 'string', description: "Description of the property.", maxLength: 1000, format: 'markdown'} + title: 'Language Descriptions', + description: 'Property descriptions by code language.', + additionalProperties: {type: 'string', description: 'Description of the property.', maxLength: 1000, format: 'markdown'} } ] - args: c.array {title: "Arguments", description: "If this property has type 'function', then provide documentation for any function arguments."}, c.FunctionArgumentSchema - owner: {title: "Owner", type: 'string', description: 'Owner of the property, like "this" or "Math".'} + args: c.array {title: 'Arguments', description: 'If this property has type "function", then provide documentation for any function arguments.'}, c.FunctionArgumentSchema + owner: {title: 'Owner', type: 'string', description: 'Owner of the property, like "this" or "Math".'} example: oneOf: [ - {title: "Example", type: 'string', description: 'An optional example code block.', format: 'javascript'} + {title: 'Example', type: 'string', description: 'An optional example code block.', format: 'javascript'} { type: 'object', - title: "Language Examples", - description: "Examples by code language.", + title: 'Language Examples', + description: 'Examples by code language.', additionalProperties: {type: 'string', description: 'An example code block.', format: 'javascript'} # TODO: not JS } ] snippets: c.object { - title: "Snippets", - description: "List of snippets for the respective programming languages" + title: 'Snippets', + description: 'List of snippets for the respective programming languages' }, javascript: c.object {title: 'JavaScript'}, c.codeSnippet 'javascript' coffeescript: c.object {title: 'CoffeeScript'}, c.codeSnippet 'coffee' @@ -59,60 +58,60 @@ PropertyDocumentationSchema = c.object { lua: c.object {title: 'Lua'}, c.codeSnippet 'lua' io: c.object {title: 'IO'}, c.codeSnippet 'io' returns: c.object { - title: "Return Value" + title: 'Return Value' description: 'Optional documentation of any return value.' required: ['type'] default: {type: 'null'} }, - type: c.shortString(title: "Type", description: "Type of the return value") + type: c.shortString(title: 'Type', description: 'Type of the return value') example: oneOf: [ - c.shortString(title: "Example", description: "Example return value") + c.shortString(title: 'Example', description: 'Example return value') { type: 'object', - title: "Language Examples", - description: "Example return values by code language.", + title: 'Language Examples', + description: 'Example return values by code language.', additionalProperties: c.shortString(description: 'Example return value.', format: 'javascript') # TODO: not JS } ] description: oneOf: [ - {title: "Description", type: 'string', description: "Description of the return value.", maxLength: 1000} + {title: 'Description', type: 'string', description: 'Description of the return value.', maxLength: 1000} { type: 'object', - title: "Language Descriptions", - description: "Example return values by code language.", - additionalProperties: {type: 'string', description: "Description of the return value.", maxLength: 1000} + title: 'Language Descriptions', + description: 'Example return values by code language.', + additionalProperties: {type: 'string', description: 'Description of the return value.', maxLength: 1000} } ] DependencySchema = c.object { - title: "Component Dependency" - description: "A Component upon which this Component depends." - "default": + title: 'Component Dependency' + description: 'A Component upon which this Component depends.' + 'default': #original: ? majorVersion: 0 - required: ["original", "majorVersion"] + required: ['original', 'majorVersion'] format: 'latest-version-reference' - links: [{rel: "db", href: "/db/level.component/{(original)}/version/{(majorVersion)}"}] + links: [{rel: 'db', href: '/db/level.component/{(original)}/version/{(majorVersion)}'}] }, - original: c.objectId(title: "Original", description: "A reference to another Component upon which this Component depends.") + original: c.objectId(title: 'Original', description: 'A reference to another Component upon which this Component depends.') majorVersion: - title: "Major Version" - description: "Which major version of the Component this Component needs." + title: 'Major Version' + description: 'Which major version of the Component this Component needs.' type: 'integer' minimum: 0 LevelComponentSchema = c.object { - title: "Component" - description: "A Component which can affect Thang behavior." - required: ["system", "name", "description", "code", "dependencies", "propertyDocumentation", "codeLanguage"] - "default": - system: "ai" - name: "AttacksSelf" - description: "This Component makes the Thang attack itself." + title: 'Component' + description: 'A Component which can affect Thang behavior.' + required: ['system', 'name', 'description', 'code', 'dependencies', 'propertyDocumentation', 'codeLanguage'] + 'default': + system: 'ai' + name: 'AttacksSelf' + description: 'This Component makes the Thang attack itself.' code: attackSelfCode - codeLanguage: "coffeescript" + codeLanguage: 'coffeescript' dependencies: [] # TODO: should depend on something by default propertyDocumentation: [] } @@ -120,42 +119,41 @@ c.extendNamedProperties LevelComponentSchema # let's have the name be the first LevelComponentSchema.properties.name.pattern = c.classNamePattern _.extend LevelComponentSchema.properties, system: - title: "System" - description: "The short name of the System this Component belongs to, like \"ai\"." - type: "string" - "enum": systems - "default": "ai" + title: 'System' + description: 'The short name of the System this Component belongs to, like \"ai\".' + type: 'string' + 'enum': systems + 'default': 'ai' description: - title: "Description" - description: "A short explanation of what this Component does." - type: "string" + title: 'Description' + description: 'A short explanation of what this Component does.' + type: 'string' maxLength: 2000 - "default": "This Component makes the Thang attack itself." + 'default': 'This Component makes the Thang attack itself.' codeLanguage: - type: "string" - title: "Language" - description: "Which programming language this Component is written in." - "enum": ["coffeescript"] + type: 'string' + title: 'Language' + description: 'Which programming language this Component is written in.' + 'enum': ['coffeescript'] code: - title: "Code" - description: "The code for this Component, as a CoffeeScript class. TODO: add link to documentation for - how to write these." - "default": attackSelfCode - type: "string" - format: "coffee" + title: 'Code' + description: 'The code for this Component, as a CoffeeScript class. TODO: add link to documentation for how to write these.' + 'default': attackSelfCode + type: 'string' + format: 'coffee' js: - title: "JavaScript" - description: "The transpiled JavaScript code for this Component" - type: "string" - format: "hidden" - dependencies: c.array {title: "Dependencies", description: "An array of Components upon which this Component depends.", "default": [], uniqueItems: true}, DependencySchema - propertyDocumentation: c.array {title: "Property Documentation", description: "An array of documentation entries for each notable property this Component will add to its Thang which other Components might want to also use.", "default": []}, PropertyDocumentationSchema - configSchema: _.extend metaschema, {title: "Configuration Schema", description: "A schema for validating the arguments that can be passed to this Component as configuration.", default: {type: 'object', additionalProperties: false}} + title: 'JavaScript' + description: 'The transpiled JavaScript code for this Component' + type: 'string' + format: 'hidden' + dependencies: c.array {title: 'Dependencies', description: 'An array of Components upon which this Component depends.', 'default': [], uniqueItems: true}, DependencySchema + propertyDocumentation: c.array {title: 'Property Documentation', description: 'An array of documentation entries for each notable property this Component will add to its Thang which other Components might want to also use.', 'default': []}, PropertyDocumentationSchema + configSchema: _.extend metaschema, {title: 'Configuration Schema', description: 'A schema for validating the arguments that can be passed to this Component as configuration.', default: {type: 'object', additionalProperties: false}} official: - type: "boolean" - title: "Official" - description: "Whether this is an official CodeCombat Component." - "default": false + type: 'boolean' + title: 'Official' + description: 'Whether this is an official CodeCombat Component.' + 'default': false c.extendBasicProperties LevelComponentSchema, 'level.component' c.extendSearchableProperties LevelComponentSchema diff --git a/app/schemas/models/level_feedback.coffee b/app/schemas/models/level_feedback.coffee index f8bb6a73c..ce0374d8b 100644 --- a/app/schemas/models/level_feedback.coffee +++ b/app/schemas/models/level_feedback.coffee @@ -5,22 +5,22 @@ LevelFeedbackLevelSchema = c.object {required: ['original', 'majorVersion']}, { majorVersion: {type: 'integer', minimum: 0, default: 0}} LevelFeedbackSchema = c.object { - title: "Feedback" - description: "Feedback on a level." + title: 'Feedback' + description: 'Feedback on a level.' } _.extend LevelFeedbackSchema.properties, # denormalization - creatorName: { type: 'string' } - levelName: { type: 'string' } - levelID: { type: 'string' } + creatorName: {type: 'string'} + levelName: {type: 'string'} + levelID: {type: 'string'} + + creator: c.objectId(links: [{rel: 'extra', href: '/db/user/{($)}'}]) + created: c.date({title: 'Created', readOnly: true}) - creator: c.objectId(links: [{rel: 'extra', href: "/db/user/{($)}"}]) - created: c.date( { title: 'Created', readOnly: true }) - level: LevelFeedbackLevelSchema - rating: { type: 'number', minimum: 1, maximum: 5 } - review: { type: 'string' } + rating: {type: 'number', minimum: 1, maximum: 5} + review: {type: 'string'} c.extendBasicProperties LevelFeedbackSchema, 'level.feedback' diff --git a/app/schemas/models/level_session.coffee b/app/schemas/models/level_session.coffee index a37c98aaf..a4e655ded 100644 --- a/app/schemas/models/level_session.coffee +++ b/app/schemas/models/level_session.coffee @@ -5,7 +5,7 @@ LevelSessionPlayerSchema = c.object links: [ { rel: 'extra' - href: "/db/user/{($)}" + href: '/db/user/{($)}' } ] time: @@ -13,7 +13,6 @@ LevelSessionPlayerSchema = c.object changes: type: 'Number' - LevelSessionLevelSchema = c.object {required: ['original', 'majorVersion']}, original: c.objectId({}) majorVersion: @@ -21,11 +20,9 @@ LevelSessionLevelSchema = c.object {required: ['original', 'majorVersion']}, minimum: 0 default: 0 - LevelSessionSchema = c.object - title: "Session" - description: "A single session for a given level." - + title: 'Session' + description: 'A single session for a given level.' _.extend LevelSessionSchema.properties, # denormalization @@ -42,7 +39,7 @@ _.extend LevelSessionSchema.properties, [ { rel: 'extra' - href: "/db/user/{($)}" + href: '/db/user/{($)}' } ] created: c.date @@ -108,17 +105,17 @@ _.extend LevelSessionSchema.properties, additionalProperties: type: 'string' format: 'javascript' - + codeLanguage: type: 'string' default: 'javascript' - + playtime: type: 'number' title: 'Playtime' default: 0 description: 'The total playtime on this session' - + teamSpells: type: 'object' additionalProperties: @@ -134,7 +131,7 @@ _.extend LevelSessionSchema.properties, type: 'number' standardDeviation: - type:'number' + type: 'number' minimum: 0 totalScore: @@ -156,7 +153,7 @@ _.extend LevelSessionSchema.properties, submittedCodeLanguage: type: 'string' default: 'javascript' - + transpiledCode: type: 'object' additionalProperties: @@ -203,7 +200,6 @@ _.extend LevelSessionSchema.properties, title: 'Playtime so far' description: 'The total seconds of playtime on this session when the match was computed.' type: 'number' - metrics: type: 'object' title: 'Metrics' @@ -223,19 +219,19 @@ _.extend LevelSessionSchema.properties, sessionID: title: 'Opponent Session ID' description: 'The session ID of an opponent.' - type: ['object', 'string','null'] + type: ['object', 'string', 'null'] userID: title: 'Opponent User ID' description: 'The user ID of an opponent' - type: ['object','string','null'] + type: ['object', 'string', 'null'] name: title: 'Opponent name' description: 'The name of the opponent' - type: ['string','null'] + type: ['string', 'null'] totalScore: title: 'Opponent total score' description: 'The totalScore of a user when the match was computed' - type: ['number','string', 'null'] + type: ['number', 'string', 'null'] metrics: type: 'object' properties: @@ -244,11 +240,6 @@ _.extend LevelSessionSchema.properties, description: 'The opponent\'s ranking in a given match' type: 'number' - - - - - c.extendBasicProperties LevelSessionSchema, 'level.session' c.extendPermissionsProperties LevelSessionSchema, 'level.session' diff --git a/app/schemas/models/level_system.coffee b/app/schemas/models/level_system.coffee index 63c12919b..13f97e545 100644 --- a/app/schemas/models/level_system.coffee +++ b/app/schemas/models/level_system.coffee @@ -19,47 +19,46 @@ class Jitter extends System """ PropertyDocumentationSchema = c.object { - title: "Property Documentation" - description: "Documentation entry for a property this System will add to its Thang which other Systems - might want to also use." - "default": - name: "foo" - type: "object" - description: "This System provides a 'foo' property to satisfy all one's foobar needs. Use it wisely." + title: 'Property Documentation' + description: 'Documentation entry for a property this System will add to its Thang which other Systems might want to also use.' + 'default': + name: 'foo' + type: 'object' + description: 'This System provides a "foo" property to satisfy all one\'s foobar needs. Use it wisely.' required: ['name', 'type', 'description'] }, - name: {type: 'string', pattern: c.identifierPattern, title: "Name", description: "Name of the property."} + name: {type: 'string', pattern: c.identifierPattern, title: 'Name', description: 'Name of the property.'} # not actual JS types, just whatever they describe... - type: c.shortString(title: "Type", description: "Intended type of the property.") - description: {type: 'string', description: "Description of the property.", maxLength: 1000} - args: c.array {title: "Arguments", description: "If this property has type 'function', then provide documentation for any function arguments."}, c.FunctionArgumentSchema + type: c.shortString(title: 'Type', description: 'Intended type of the property.') + description: {type: 'string', description: 'Description of the property.', maxLength: 1000} + args: c.array {title: 'Arguments', description: 'If this property has type "function", then provide documentation for any function arguments.'}, c.FunctionArgumentSchema DependencySchema = c.object { - title: "System Dependency" - description: "A System upon which this System depends." - "default": + title: 'System Dependency' + description: 'A System upon which this System depends.' + 'default': #original: ? majorVersion: 0 - required: ["original", "majorVersion"] + required: ['original', 'majorVersion'] format: 'latest-version-reference' - links: [{rel: "db", href: "/db/level.system/{(original)}/version/{(majorVersion)}"}] + links: [{rel: 'db', href: '/db/level.system/{(original)}/version/{(majorVersion)}'}] }, - original: c.objectId(title: "Original", description: "A reference to another System upon which this System depends.") + original: c.objectId(title: 'Original', description: 'A reference to another System upon which this System depends.') majorVersion: - title: "Major Version" - description: "Which major version of the System this System needs." + title: 'Major Version' + description: 'Which major version of the System this System needs.' type: 'integer' minimum: 0 LevelSystemSchema = c.object { - title: "System" - description: "A System which can affect Level behavior." - required: ["name", "description", "code", "dependencies", "propertyDocumentation", "codeLanguage"] - "default": - name: "JitterSystem" - description: "This System makes all idle, movable Thangs jitter around." + title: 'System' + description: 'A System which can affect Level behavior.' + required: ['name', 'description', 'code', 'dependencies', 'propertyDocumentation', 'codeLanguage'] + 'default': + name: 'JitterSystem' + description: 'This System makes all idle, movable Thangs jitter around.' code: jitterSystemCode - codeLanguage: "coffeescript" + codeLanguage: 'coffeescript' dependencies: [] # TODO: should depend on something by default propertyDocumentation: [] } @@ -67,36 +66,35 @@ c.extendNamedProperties LevelSystemSchema # let's have the name be the first pr LevelSystemSchema.properties.name.pattern = c.classNamePattern _.extend LevelSystemSchema.properties, description: - title: "Description" - description: "A short explanation of what this System does." - type: "string" + title: 'Description' + description: 'A short explanation of what this System does.' + type: 'string' maxLength: 2000 - "default": "This System doesn't do anything yet." + 'default': 'This System doesn\'t do anything yet.' codeLanguage: - type: "string" - title: "Language" - description: "Which programming language this System is written in." - "enum": ["coffeescript"] + type: 'string' + title: 'Language' + description: 'Which programming language this System is written in.' + 'enum': ['coffeescript'] code: - title: "Code" - description: "The code for this System, as a CoffeeScript class. TODO: add link to documentation - for how to write these." - "default": jitterSystemCode - type: "string" - format: "coffee" + title: 'Code' + description: 'The code for this System, as a CoffeeScript class. TODO: add link to documentation for how to write these.' + 'default': jitterSystemCode + type: 'string' + format: 'coffee' js: - title: "JavaScript" - description: "The transpiled JavaScript code for this System" - type: "string" - format: "hidden" - dependencies: c.array {title: "Dependencies", description: "An array of Systems upon which this System depends.", "default": [], uniqueItems: true}, DependencySchema - propertyDocumentation: c.array {title: "Property Documentation", description: "An array of documentation entries for each notable property this System will add to its Level which other Systems might want to also use.", "default": []}, PropertyDocumentationSchema - configSchema: _.extend metaschema, {title: "Configuration Schema", description: "A schema for validating the arguments that can be passed to this System as configuration.", default: {type: 'object', additionalProperties: false}} + title: 'JavaScript' + description: 'The transpiled JavaScript code for this System' + type: 'string' + format: 'hidden' + dependencies: c.array {title: 'Dependencies', description: 'An array of Systems upon which this System depends.', 'default': [], uniqueItems: true}, DependencySchema + propertyDocumentation: c.array {title: 'Property Documentation', description: 'An array of documentation entries for each notable property this System will add to its Level which other Systems might want to also use.', 'default': []}, PropertyDocumentationSchema + configSchema: _.extend metaschema, {title: 'Configuration Schema', description: 'A schema for validating the arguments that can be passed to this System as configuration.', default: {type: 'object', additionalProperties: false}} official: - type: "boolean" - title: "Official" - description: "Whether this is an official CodeCombat System." - "default": false + type: 'boolean' + title: 'Official' + description: 'Whether this is an official CodeCombat System.' + 'default': false c.extendBasicProperties LevelSystemSchema, 'level.system' c.extendSearchableProperties LevelSystemSchema diff --git a/app/schemas/models/patch.coffee b/app/schemas/models/patch.coffee index e14423371..6af348725 100644 --- a/app/schemas/models/patch.coffee +++ b/app/schemas/models/patch.coffee @@ -1,24 +1,24 @@ c = require './../schemas' patchables = ['level', 'thang_type', 'level_system', 'level_component', 'article'] - -PatchSchema = c.object({title:'Patch', required:['target', 'delta', 'commitMessage']}, { - delta: { title: 'Delta', type:['array', 'object'] } + +PatchSchema = c.object({title: 'Patch', required: ['target', 'delta', 'commitMessage']}, { + delta: {title: 'Delta', type: ['array', 'object']} commitMessage: c.shortString({maxLength: 500, minLength: 1}) - creator: c.objectId(links: [{rel: 'extra', href: "/db/user/{($)}"}]) - created: c.date( { title: 'Created', readOnly: true }) - status: { enum: ['pending', 'accepted', 'rejected', 'withdrawn']} - - target: c.object({title: 'Target', required:['collection', 'id']}, { - collection: { enum: patchables } + creator: c.objectId(links: [{rel: 'extra', href: '/db/user/{($)}'}]) + created: c.date({title: 'Created', readOnly: true}) + status: {enum: ['pending', 'accepted', 'rejected', 'withdrawn']} + + target: c.object({title: 'Target', required: ['collection', 'id']}, { + collection: {enum: patchables} id: c.objectId(title: 'Target ID') # search by this if not versioned # if target is versioned, want to know that info too original: c.objectId(title: 'Target Original') # search by this if versioned version: properties: - major: { type: 'number', minimum: 0 } - minor: { type: 'number', minimum: 0 } + major: {type: 'number', minimum: 0} + minor: {type: 'number', minimum: 0} }) }) diff --git a/app/schemas/models/thang_component.coffee b/app/schemas/models/thang_component.coffee index eebcf155b..a8b6b5b74 100644 --- a/app/schemas/models/thang_component.coffee +++ b/app/schemas/models/thang_component.coffee @@ -1,21 +1,21 @@ c = require './../schemas' module.exports = ThangComponentSchema = c.object { - title: "Component" - description: "Configuration for a Component that this Thang uses." + title: 'Component' + description: 'Configuration for a Component that this Thang uses.' format: 'thang-component' required: ['original', 'majorVersion'] 'default': majorVersion: 0 config: {} - links: [{rel: "db", href: "/db/level.component/{(original)}/version/{(majorVersion)}"}] + links: [{rel: 'db', href: '/db/level.component/{(original)}/version/{(majorVersion)}'}] }, - original: c.objectId(title: "Original", description: "A reference to the original Component being configured.", format: "hidden") - config: c.object {title: "Configuration", description: "Component-specific configuration properties.", additionalProperties: true, format: 'thang-component-configuration'} + original: c.objectId(title: 'Original', description: 'A reference to the original Component being configured.', format: 'hidden') + config: c.object {title: 'Configuration', description: 'Component-specific configuration properties.', additionalProperties: true, format: 'thang-component-configuration'} majorVersion: - title: "Major Version" - description: "Which major version of the Component is being used." + title: 'Major Version' + description: 'Which major version of the Component is being used.' type: 'integer' minimum: 0 default: 0 - format: "hidden" + format: 'hidden' diff --git a/app/schemas/models/thang_type.coffee b/app/schemas/models/thang_type.coffee index 37624c180..0203287af 100644 --- a/app/schemas/models/thang_type.coffee +++ b/app/schemas/models/thang_type.coffee @@ -4,144 +4,144 @@ ThangComponentSchema = require './thang_component' ThangTypeSchema = c.object() c.extendNamedProperties ThangTypeSchema # name first -ShapeObjectSchema = c.object { title: 'Shape' }, - fc: { type: 'string', title: 'Fill Color' } - lf: { type: 'array', title: 'Linear Gradient Fill' } - ls: { type: 'array', title: 'Linear Gradient Stroke' } - p: { type: 'string', title: 'Path' } - de: { type: 'array', title: 'Draw Ellipse' } - sc: { type: 'string', title: 'Stroke Color' } - ss: { type: 'array', title: 'Stroke Style' } - t: c.array {}, { type: 'number', title: 'Transform' } - m: { type: 'string', title: 'Mask' } +ShapeObjectSchema = c.object {title: 'Shape'}, + fc: {type: 'string', title: 'Fill Color'} + lf: {type: 'array', title: 'Linear Gradient Fill'} + ls: {type: 'array', title: 'Linear Gradient Stroke'} + p: {type: 'string', title: 'Path'} + de: {type: 'array', title: 'Draw Ellipse'} + sc: {type: 'string', title: 'Stroke Color'} + ss: {type: 'array', title: 'Stroke Style'} + t: c.array {}, {type: 'number', title: 'Transform'} + m: {type: 'string', title: 'Mask'} -ContainerObjectSchema = c.object { format: 'container' }, - b: c.array { title: 'Bounds' }, { type: 'number' } - c: c.array { title: 'Children' }, { anyOf: [ - { type: 'string', title: 'Shape Child' }, - c.object { title: 'Container Child' } - gn: { type: 'string', title: 'Global Name' } - t: c.array {}, { type: 'number' } +ContainerObjectSchema = c.object {format: 'container'}, + b: c.array {title: 'Bounds'}, {type: 'number'} + c: c.array {title: 'Children'}, {anyOf: [ + {type: 'string', title: 'Shape Child'}, + c.object {title: 'Container Child'} + gn: {type: 'string', title: 'Global Name'} + t: c.array {}, {type: 'number'} ]} RawAnimationObjectSchema = c.object {}, - bounds: c.array { title: 'Bounds' }, { type: 'number' } - frameBounds: c.array { title: 'Frame Bounds' }, c.array { title: 'Bounds' }, { type: 'number' } + bounds: c.array {title: 'Bounds'}, {type: 'number'} + frameBounds: c.array {title: 'Frame Bounds'}, c.array {title: 'Bounds'}, {type: 'number'} shapes: c.array {}, - bn: { type: 'string', title: 'Block Name' } - gn: { type: 'string', title: 'Global Name' } - im : { type: 'boolean', title: 'Is Mask' } - m: { type: 'string', title: 'Uses Mask' } + bn: {type: 'string', title: 'Block Name'} + gn: {type: 'string', title: 'Global Name'} + im : {type: 'boolean', title: 'Is Mask'} + m: {type: 'string', title: 'Uses Mask'} containers: c.array {}, - bn: { type: 'string', title: 'Block Name' } - gn: { type: 'string', title: 'Global Name' } - t: c.array {}, { type: 'number' } - o: { type: 'boolean', title: 'Starts Hidden (_off)'} - al: { type: 'number', title: 'Alpha'} + bn: {type: 'string', title: 'Block Name'} + gn: {type: 'string', title: 'Global Name'} + t: c.array {}, {type: 'number'} + o: {type: 'boolean', title: 'Starts Hidden (_off)'} + al: {type: 'number', title: 'Alpha'} animations: c.array {}, - bn: { type: 'string', title: 'Block Name' } - gn: { type: 'string', title: 'Global Name' } - t: c.array {}, { type: 'number', title: 'Transform' } - a: c.array { title: 'Arguments' } + bn: {type: 'string', title: 'Block Name'} + gn: {type: 'string', title: 'Global Name'} + t: c.array {}, {type: 'number', title: 'Transform'} + a: c.array {title: 'Arguments'} tweens: c.array {}, - c.array { title: 'Function Chain', }, - c.object { title: 'Function Call' }, - n: { type: 'string', title: 'Name' } - a: c.array { title: 'Arguments' } + c.array {title: 'Function Chain'}, + c.object {title: 'Function Call'}, + n: {type: 'string', title: 'Name'} + a: c.array {title: 'Arguments'} graphics: c.array {}, - bn: { type: 'string', title: 'Block Name' } - p: { type: 'string', title: 'Path' } + bn: {type: 'string', title: 'Block Name'} + p: {type: 'string', title: 'Path'} -PositionsSchema = c.object { title: 'Positions', description: 'Customize position offsets.' }, - registration: c.point2d { title: 'Registration Point', description: "Action-specific registration point override." } - torso: c.point2d { title: 'Torso Offset', description: "Action-specific torso offset override." } - mouth: c.point2d { title: 'Mouth Offset', description: "Action-specific mouth offset override." } - aboveHead: c.point2d { title: 'Above Head Offset', description: "Action-specific above-head offset override." } +PositionsSchema = c.object {title: 'Positions', description: 'Customize position offsets.'}, + registration: c.point2d {title: 'Registration Point', description: 'Action-specific registration point override.'} + torso: c.point2d {title: 'Torso Offset', description: 'Action-specific torso offset override.'} + mouth: c.point2d {title: 'Mouth Offset', description: 'Action-specific mouth offset override.'} + aboveHead: c.point2d {title: 'Above Head Offset', description: 'Action-specific above-head offset override.'} ActionSchema = c.object {}, - animation: { type: 'string', description: 'Raw animation being sourced', format: 'raw-animation' } - container: { type: 'string', description: 'Name of the container to show' } - relatedActions: c.object { }, - begin: { $ref: '#/definitions/action' } - end: { $ref: '#/definitions/action' } - main: { $ref: '#/definitions/action' } - fore: { $ref: '#/definitions/action' } - back: { $ref: '#/definitions/action' } - side: { $ref: '#/definitions/action' } + animation: {type: 'string', description: 'Raw animation being sourced', format: 'raw-animation'} + container: {type: 'string', description: 'Name of the container to show'} + relatedActions: c.object {}, + begin: {$ref: '#/definitions/action'} + end: {$ref: '#/definitions/action'} + main: {$ref: '#/definitions/action'} + fore: {$ref: '#/definitions/action'} + back: {$ref: '#/definitions/action'} + side: {$ref: '#/definitions/action'} - "?0?011?11?11": { $ref: '#/definitions/action', title: "NW corner" } - "?0?11011?11?": { $ref: '#/definitions/action', title: "NE corner, flipped" } - "?0?111111111": { $ref: '#/definitions/action', title: "N face" } - "?11011011?0?": { $ref: '#/definitions/action', title: "SW corner, top" } - "11?11?110?0?": { $ref: '#/definitions/action', title: "SE corner, top, flipped" } - "?11011?0????": { $ref: '#/definitions/action', title: "SW corner, bottom" } - "11?110?0????": { $ref: '#/definitions/action', title: "SE corner, bottom, flipped" } - "?11011?11?11": { $ref: '#/definitions/action', title: "W face" } - "11?11011?11?": { $ref: '#/definitions/action', title: "E face, flipped" } - "011111111111": { $ref: '#/definitions/action', title: "NW elbow" } - "110111111111": { $ref: '#/definitions/action', title: "NE elbow, flipped" } - "111111111?0?": { $ref: '#/definitions/action', title: "S face, top" } - "111111?0????": { $ref: '#/definitions/action', title: "S face, bottom" } - "111111111011": { $ref: '#/definitions/action', title: "SW elbow, top" } - "111111111110": { $ref: '#/definitions/action', title: "SE elbow, top, flipped" } - "111111011?11": { $ref: '#/definitions/action', title: "SW elbow, bottom" } - "11111111011?": { $ref: '#/definitions/action', title: "SE elbow, bottom, flipped" } - "111111111111": { $ref: '#/definitions/action', title: "Middle" } + '?0?011?11?11': {$ref: '#/definitions/action', title: 'NW corner'} + '?0?11011?11?': {$ref: '#/definitions/action', title: 'NE corner, flipped'} + '?0?111111111': {$ref: '#/definitions/action', title: 'N face'} + '?11011011?0?': {$ref: '#/definitions/action', title: 'SW corner, top'} + '11?11?110?0?': {$ref: '#/definitions/action', title: 'SE corner, top, flipped'} + '?11011?0????': {$ref: '#/definitions/action', title: 'SW corner, bottom'} + '11?110?0????': {$ref: '#/definitions/action', title: 'SE corner, bottom, flipped'} + '?11011?11?11': {$ref: '#/definitions/action', title: 'W face'} + '11?11011?11?': {$ref: '#/definitions/action', title: 'E face, flipped'} + '011111111111': {$ref: '#/definitions/action', title: 'NW elbow'} + '110111111111': {$ref: '#/definitions/action', title: 'NE elbow, flipped'} + '111111111?0?': {$ref: '#/definitions/action', title: 'S face, top'} + '111111?0????': {$ref: '#/definitions/action', title: 'S face, bottom'} + '111111111011': {$ref: '#/definitions/action', title: 'SW elbow, top'} + '111111111110': {$ref: '#/definitions/action', title: 'SE elbow, top, flipped'} + '111111011?11': {$ref: '#/definitions/action', title: 'SW elbow, bottom'} + '11111111011?': {$ref: '#/definitions/action', title: 'SE elbow, bottom, flipped'} + '111111111111': {$ref: '#/definitions/action', title: 'Middle'} - loops: { type: 'boolean' } - speed: { type: 'number' } - goesTo: { type: 'string', description: 'Action (animation?) to which we switch after this animation.' } - frames: { type: 'string', pattern:'^[0-9,]+$', description: 'Manually way to specify frames.' } - framerate: { type: 'number', description: 'Get this from the HTML output.' } + loops: {type: 'boolean'} + speed: {type: 'number'} + goesTo: {type: 'string', description: 'Action (animation?) to which we switch after this animation.'} + frames: {type: 'string', pattern: '^[0-9,]+$', description: 'Manually way to specify frames.'} + framerate: {type: 'number', description: 'Get this from the HTML output.'} positions: PositionsSchema - scale: { title: 'Scale', type: 'number' } - flipX: { title: "Flip X", type: 'boolean', description: "Flip this animation horizontally?" } - flipY: { title: "Flip Y", type: 'boolean', description: "Flip this animation vertically?" } + scale: {title: 'Scale', type: 'number'} + flipX: {title: 'Flip X', type: 'boolean', description: 'Flip this animation horizontally?'} + flipY: {title: 'Flip Y', type: 'boolean', description: 'Flip this animation vertically?'} -SoundSchema = c.sound({delay: { type: 'number' }}) +SoundSchema = c.sound({delay: {type: 'number'}}) _.extend ThangTypeSchema.properties, raw: c.object {title: 'Raw Vector Data'}, shapes: c.object {title: 'Shapes', additionalProperties: ShapeObjectSchema} containers: c.object {title: 'Containers', additionalProperties: ContainerObjectSchema} animations: c.object {title: 'Animations', additionalProperties: RawAnimationObjectSchema} - kind: c.shortString { enum: ['Unit', 'Floor', 'Wall', 'Doodad', 'Misc', 'Mark'], default: 'Misc', title: 'Kind' } + kind: c.shortString {enum: ['Unit', 'Floor', 'Wall', 'Doodad', 'Misc', 'Mark'], default: 'Misc', title: 'Kind'} - actions: c.object { title: 'Actions', additionalProperties: { $ref: '#/definitions/action' } } - soundTriggers: c.object { title: "Sound Triggers", additionalProperties: c.array({}, { $ref: '#/definitions/sound' }) }, - say: c.object { format: 'slug-props', additionalProperties: { $ref: '#/definitions/sound' } }, - defaultSimlish: c.array({}, { $ref: '#/definitions/sound' }) - swearingSimlish: c.array({}, { $ref: '#/definitions/sound' }) - rotationType: { title: 'Rotation', type: 'string', enum: ['isometric', 'fixed']} - matchWorldDimensions: { title: 'Match World Dimensions', type: 'boolean' } - shadow: { title: 'Shadow Diameter', type: 'number', format: 'meters', description: "Shadow diameter in meters" } + actions: c.object {title: 'Actions', additionalProperties: {$ref: '#/definitions/action'}} + soundTriggers: c.object {title: 'Sound Triggers', additionalProperties: c.array({}, {$ref: '#/definitions/sound'})}, + say: c.object {format: 'slug-props', additionalProperties: {$ref: '#/definitions/sound'}}, + defaultSimlish: c.array({}, {$ref: '#/definitions/sound'}) + swearingSimlish: c.array({}, {$ref: '#/definitions/sound'}) + rotationType: {title: 'Rotation', type: 'string', enum: ['isometric', 'fixed']} + matchWorldDimensions: {title: 'Match World Dimensions', type: 'boolean'} + shadow: {title: 'Shadow Diameter', type: 'number', format: 'meters', description: 'Shadow diameter in meters'} layerPriority: title: 'Layer Priority' type: 'integer' - description: "Within its layer, sprites are sorted by layer priority, then y, then z." + description: 'Within its layer, sprites are sorted by layer priority, then y, then z.' scale: title: 'Scale' type: 'number' positions: PositionsSchema - raster: { type: 'string', format: 'image-file', title: 'Raster Image' } + raster: {type: 'string', format: 'image-file', title: 'Raster Image'} colorGroups: c.object title: 'Color Groups' additionalProperties: - type:'array' + type: 'array' format: 'thang-color-group' - items: {type:'string'} - snap: c.object { title: "Snap", description: "In the level editor, snap positioning to these intervals.", required: ['x', 'y'] }, + items: {type: 'string'} + snap: c.object {title: 'Snap', description: 'In the level editor, snap positioning to these intervals.', required: ['x', 'y']}, x: - title: "Snap X" + title: 'Snap X' type: 'number' - description: "Snap to this many meters in the x-direction." + description: 'Snap to this many meters in the x-direction.' default: 4 y: - title: "Snap Y" + title: 'Snap Y' type: 'number' - description: "Snap to this many meters in the y-direction." + description: 'Snap to this many meters in the y-direction.' default: 4 - components: c.array {title: "Components", description: "Thangs are configured by changing the Components attached to them.", uniqueItems: true, format: 'thang-components-array'}, ThangComponentSchema # TODO: uniqueness should be based on "original", not whole thing + components: c.array {title: 'Components', description: 'Thangs are configured by changing the Components attached to them.', uniqueItems: true, format: 'thang-components-array'}, ThangComponentSchema # TODO: uniqueness should be based on 'original', not whole thing ThangTypeSchema.definitions = action: ActionSchema diff --git a/app/schemas/models/user.coffee b/app/schemas/models/user.coffee index 74e9c7dd3..08401b03b 100644 --- a/app/schemas/models/user.coffee +++ b/app/schemas/models/user.coffee @@ -2,12 +2,12 @@ c = require './../schemas' emailSubscriptions = ['announcement', 'tester', 'level_creator', 'developer', 'article_editor', 'translator', 'support', 'notification'] UserSchema = c.object {}, - name: c.shortString({title: 'Display Name', default:''}) + name: c.shortString({title: 'Display Name', default: ''}) email: c.shortString({title: 'Email', format: 'email'}) firstName: c.shortString({title: 'First Name'}) lastName: c.shortString({title: 'Last Name'}) gender: {type: 'string', 'enum': ['male', 'female']} - password: {type: 'string', maxLength: 256, minLength: 2, title:'Password'} + password: {type: 'string', maxLength: 256, minLength: 2, title: 'Password'} passwordReset: {type: 'string'} photoURL: {type: 'string', format: 'image-file', title: 'Profile Picture', description: 'Upload a 256x256px or larger image to serve as your profile picture.'} @@ -17,24 +17,24 @@ UserSchema = c.object {}, wizardColor1: c.pct({title: 'Wizard Clothes Color'}) volume: c.pct({title: 'Volume'}) music: {type: 'boolean', default: true} - autocastDelay: {type: 'integer', 'default': 5000 } - lastLevel: { type: 'string' } + autocastDelay: {type: 'integer', 'default': 5000} + lastLevel: {type: 'string'} emailSubscriptions: c.array {uniqueItems: true}, {'enum': emailSubscriptions} - emails: c.object {title: "Email Settings", default: {generalNews: {enabled:true}, anyNotes: {enabled:true}, recruitNotes: {enabled:true}}}, + emails: c.object {title: 'Email Settings', default: {generalNews: {enabled: true}, anyNotes: {enabled: true}, recruitNotes: {enabled: true}}}, # newsletters - generalNews: { $ref: '#/definitions/emailSubscription' } - adventurerNews: { $ref: '#/definitions/emailSubscription' } - ambassadorNews: { $ref: '#/definitions/emailSubscription' } - archmageNews: { $ref: '#/definitions/emailSubscription' } - artisanNews: { $ref: '#/definitions/emailSubscription' } - diplomatNews: { $ref: '#/definitions/emailSubscription' } - scribeNews: { $ref: '#/definitions/emailSubscription' } + generalNews: {$ref: '#/definitions/emailSubscription'} + adventurerNews: {$ref: '#/definitions/emailSubscription'} + ambassadorNews: {$ref: '#/definitions/emailSubscription'} + archmageNews: {$ref: '#/definitions/emailSubscription'} + artisanNews: {$ref: '#/definitions/emailSubscription'} + diplomatNews: {$ref: '#/definitions/emailSubscription'} + scribeNews: {$ref: '#/definitions/emailSubscription'} # notifications - anyNotes: { $ref: '#/definitions/emailSubscription' } # overrides any other notifications settings - recruitNotes: { $ref: '#/definitions/emailSubscription' } - employerNotes: { $ref: '#/definitions/emailSubscription' } + anyNotes: {$ref: '#/definitions/emailSubscription'} # overrides any other notifications settings + recruitNotes: {$ref: '#/definitions/emailSubscription'} + employerNotes: {$ref: '#/definitions/emailSubscription'} # server controlled permissions: c.array {'default': []}, c.shortString() @@ -78,7 +78,7 @@ UserSchema = c.object {}, name: c.shortString {title: 'Name', description: 'Name you want employers to see, like "Nick Winter".'} city: c.shortString {title: 'City', description: 'City you want to work in (or live in now), like "San Francisco" or "Lubbock, TX".', default: 'Defaultsville, CA', format: 'city'} country: c.shortString {title: 'Country', description: 'Country you want to work in (or live in now), like "USA" or "France".', default: 'USA', format: 'country'} - skills: c.array {title: 'Skills', description: 'Tag relevant developer skills in order of proficiency.', default: ['javascript'], minItems: 1, maxItems: 40, uniqueItems: true}, + skills: c.array {title: 'Skills', description: 'Tag relevant developer skills in order of proficiency.', default: ['javascript'], minItems: 1, maxItems: 30, uniqueItems: true}, {type: 'string', minLength: 1, maxLength: 50, description: 'Ex.: "objective-c", "mongodb", "rails", "android", "javascript"', format: 'skill'} experience: {type: 'integer', title: 'Years of Experience', minimum: 0, description: 'How many years of professional experience (getting paid) developing software do you have?'} shortDescription: {type: 'string', maxLength: 140, title: 'Short Description', description: 'Who are you, and what are you looking for? 140 characters max.', default: 'Programmer seeking to build great software.'} @@ -152,17 +152,15 @@ UserSchema = c.object {}, type: 'string' enum: ['College Student', 'Recent Grad', 'Junior', 'Senior', 'Management'] jobProfileApproved: {title: 'Job Profile Approved', type: 'boolean', description: 'Whether your profile has been approved by CodeCombat.'} - jobProfileNotes: {type: 'string', maxLength: 1000, title: 'Our Notes', description: "CodeCombat's notes on the candidate.", format: 'markdown', default: ''} - employerAt: c.shortString {description: "If given employer permissions to view job candidates, for which employer?"} + jobProfileNotes: {type: 'string', maxLength: 1000, title: 'Our Notes', description: 'CodeCombat\'s notes on the candidate.', format: 'markdown', default: ''} + employerAt: c.shortString {description: 'If given employer permissions to view job candidates, for which employer?'} signedEmployerAgreement: c.object {}, - linkedinID: c.shortString {title:"LinkedInID", description: "The user's LinkedIn ID when they signed the contract."} - date: c.date {title: "Date signed employer agreement"} - data: c.object {description: "Cached LinkedIn data slurped from profile.", additionalProperties: true} - points: {type:'number'} + linkedinID: c.shortString {title: 'LinkedInID', description: 'The user\'s LinkedIn ID when they signed the contract.'} + date: c.date {title: 'Date signed employer agreement'} + data: c.object {description: 'Cached LinkedIn data slurped from profile.', additionalProperties: true} + points: {type: 'number'} activity: {type: 'object', description: 'Summary statistics about user activity', additionalProperties: c.activity} - - c.extendBasicProperties UserSchema, 'user' c.definitions = diff --git a/app/schemas/models/user_remark.coffee b/app/schemas/models/user_remark.coffee index cd351c4a4..839ce1380 100644 --- a/app/schemas/models/user_remark.coffee +++ b/app/schemas/models/user_remark.coffee @@ -1,13 +1,13 @@ c = require './../schemas' UserRemarkSchema = c.object { - title: "Remark" - description: "Remarks on a user, point of contact, tasks." + title: 'Remark' + description: 'Remarks on a user, point of contact, tasks.' } _.extend UserRemarkSchema.properties, - user: c.objectId links: [{rel: 'extra', href: "/db/user/{($)}"}] - contact: c.objectId links: [{rel: 'extra', href: "/db/user/{($)}"}] + user: c.objectId links: [{rel: 'extra', href: '/db/user/{($)}'}] + contact: c.objectId links: [{rel: 'extra', href: '/db/user/{($)}'}] created: c.date title: 'Created', readOnly: true history: c.array {title: 'History', description: 'Records of our interactions with the user.'}, c.object {title: 'Record'}, {date: c.date(title: 'Date'), content: {title: 'Content', type: 'string', format: 'markdown'}} @@ -15,9 +15,8 @@ _.extend UserRemarkSchema.properties, c.object {title: 'Task'}, {date: c.date(title: 'Date'), action: {title: 'Action', type: 'string'}} # denormalization - userName: { title: "Player Name", type: 'string' } - contactName: { title: "Contact Name", type: 'string' } # Not actually our usernames - + userName: {title: 'Player Name', type: 'string'} + contactName: {title: 'Contact Name', type: 'string'} # Not actually our usernames c.extendBasicProperties UserRemarkSchema, 'user.remark' diff --git a/app/schemas/schemas.coffee b/app/schemas/schemas.coffee index 8d8559aeb..8474a9be0 100644 --- a/app/schemas/schemas.coffee +++ b/app/schemas/schemas.coffee @@ -11,34 +11,34 @@ combine = (base, ext) -> urlPattern = '^(ht|f)tp(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&%\$#_=]*)?$' # Common schema properties -me.object = (ext, props) -> combine {type: 'object', additionalProperties: false, properties: props or {}}, ext -me.array = (ext, items) -> combine {type: 'array', items: items or {}}, ext +me.object = (ext, props) -> combine({type: 'object', additionalProperties: false, properties: props or {}}, ext) +me.array = (ext, items) -> combine({type: 'array', items: items or {}}, ext) me.shortString = (ext) -> combine({type: 'string', maxLength: 100}, ext) me.pct = (ext) -> combine({type: 'number', maximum: 1.0, minimum: 0.0}, ext) me.date = (ext) -> combine({type: ['object', 'string'], format: 'date-time'}, ext) # should just be string (Mongo ID), but sometimes mongoose turns them into objects representing those, so we are lenient -me.objectId = (ext) -> schema = combine({type: ['object', 'string'] }, ext) +me.objectId = (ext) -> schema = combine({type: ['object', 'string']}, ext) me.url = (ext) -> combine({type: 'string', format: 'url', pattern: urlPattern}, ext) -PointSchema = me.object {title: "Point", description: "An {x, y} coordinate point.", format: "point2d", required: ["x", "y"]}, - x: {title: "x", description: "The x coordinate.", type: "number", "default": 15} - y: {title: "y", description: "The y coordinate.", type: "number", "default": 20} +PointSchema = me.object {title: 'Point', description: 'An {x, y} coordinate point.', format: 'point2d', required: ['x', 'y']}, + x: {title: 'x', description: 'The x coordinate.', type: 'number', 'default': 15} + y: {title: 'y', description: 'The y coordinate.', type: 'number', 'default': 20} me.point2d = (ext) -> combine(_.cloneDeep(PointSchema), ext) -SoundSchema = me.object { format: 'sound' }, - mp3: { type: 'string', format: 'sound-file' } - ogg: { type: 'string', format: 'sound-file' } +SoundSchema = me.object {format: 'sound'}, + mp3: {type: 'string', format: 'sound-file'} + ogg: {type: 'string', format: 'sound-file'} me.sound = (props) -> obj = _.cloneDeep(SoundSchema) obj.properties[prop] = props[prop] for prop of props obj -ColorConfigSchema = me.object { format: 'color-sound' }, - hue: { format: 'range', type: 'number', minimum: 0, maximum: 1 } - saturation: { format: 'range', type: 'number', minimum: 0, maximum: 1 } - lightness: { format: 'range', type: 'number', minimum: 0, maximum: 1 } +ColorConfigSchema = me.object {format: 'color-sound'}, + hue: {format: 'range', type: 'number', minimum: 0, maximum: 1} + saturation: {format: 'range', type: 'number', minimum: 0, maximum: 1} + lightness: {format: 'range', type: 'number', minimum: 0, maximum: 1} me.colorConfig = (props) -> obj = _.cloneDeep(ColorConfigSchema) @@ -48,8 +48,8 @@ me.colorConfig = (props) -> # BASICS basicProps = (linkFragment) -> - _id: me.objectId(links: [{rel: 'self', href: "/db/#{linkFragment}/{($)}"}], format:"hidden") - __v: { title: 'Mongoose Version', format: 'hidden' } + _id: me.objectId(links: [{rel: 'self', href: "/db/#{linkFragment}/{($)}"}], format: 'hidden') + __v: {title: 'Mongoose Version', format: 'hidden'} me.extendBasicProperties = (schema, linkFragment) -> schema.properties = {} unless schema.properties? @@ -59,12 +59,12 @@ me.extendBasicProperties = (schema, linkFragment) -> patchableProps = -> patches: me.array({title:'Patches'}, { - _id: me.objectId(links: [{rel: "db", href: "/db/patch/{($)}"}], title: "Patch ID", description: "A reference to the patch.") - status: { enum: ['pending', 'accepted', 'rejected', 'cancelled']} + _id: me.objectId(links: [{rel: 'db', href: '/db/patch/{($)}'}], title: 'Patch ID', description: 'A reference to the patch.') + status: {enum: ['pending', 'accepted', 'rejected', 'cancelled']} }) - allowPatches: { type: 'boolean' } - watchers: me.array({title:'Watchers'}, - me.objectId(links: [{rel: 'extra', href: "/db/user/{($)}"}])) + allowPatches: {type: 'boolean'} + watchers: me.array({title: 'Watchers'}, + me.objectId(links: [{rel: 'extra', href: '/db/user/{($)}'}])) me.extendPatchableProperties = (schema) -> schema.properties = {} unless schema.properties? @@ -80,44 +80,41 @@ me.extendNamedProperties = (schema) -> schema.properties = {} unless schema.properties? _.extend(schema.properties, namedProps()) - # VERSIONED versionedProps = (linkFragment) -> version: - 'default': { minor: 0, major: 0, isLatestMajor: true, isLatestMinor: true } + 'default': {minor: 0, major: 0, isLatestMajor: true, isLatestMinor: true} format: 'version' title: 'Version' type: 'object' readOnly: true additionalProperties: false properties: - major: { type: 'number', minimum: 0 } - minor: { type: 'number', minimum: 0 } - isLatestMajor: { type: 'boolean' } - isLatestMinor: { type: 'boolean' } + major: {type: 'number', minimum: 0} + minor: {type: 'number', minimum: 0} + isLatestMajor: {type: 'boolean'} + isLatestMinor: {type: 'boolean'} # TODO: figure out useful 'rel' values here original: me.objectId(links: [{rel: 'extra', href: "/db/#{linkFragment}/{($)}"}], format: 'hidden') parent: me.objectId(links: [{rel: 'extra', href: "/db/#{linkFragment}/{($)}"}], format: 'hidden') - creator: me.objectId(links: [{rel: 'extra', href: "/db/user/{($)}"}], format: 'hidden') - created: me.date( { title: 'Created', readOnly: true }) - commitMessage: { type: 'string', maxLength: 500, title: 'Commit Message', readOnly: true } + creator: me.objectId(links: [{rel: 'extra', href: '/db/user/{($)}'}], format: 'hidden') + created: me.date({title: 'Created', readOnly: true}) + commitMessage: {type: 'string', maxLength: 500, title: 'Commit Message', readOnly: true} me.extendVersionedProperties = (schema, linkFragment) -> schema.properties = {} unless schema.properties? _.extend(schema.properties, versionedProps(linkFragment)) - # SEARCHABLE searchableProps = -> - index: { format: 'hidden' } + index: {format: 'hidden'} me.extendSearchableProperties = (schema) -> schema.properties = {} unless schema.properties? _.extend(schema.properties, searchableProps()) - # PERMISSIONED permissionsProps = -> @@ -129,7 +126,7 @@ permissionsProps = -> properties: target: {} access: {type: 'string', 'enum': ['read', 'write', 'owner']} - format: "hidden" + format: 'hidden' me.extendPermissionsProperties = (schema) -> schema.properties = {} unless schema.properties? @@ -137,7 +134,7 @@ me.extendPermissionsProperties = (schema) -> # TRANSLATABLE -me.generateLanguageCodeArrayRegex = -> "^(" + Language.languageCodes.join("|") + ")$" +me.generateLanguageCodeArrayRegex = -> '^(' + Language.languageCodes.join('|') + ')$' me.getLanguageCodeArray = -> return Language.languageCodes @@ -146,57 +143,56 @@ me.getLanguagesObject = -> return Language # OTHER -me.classNamePattern = "^[A-Z][A-Za-z0-9]*$" # starts with capital letter; just letters and numbers -me.identifierPattern = "^[a-z][A-Za-z0-9]*$" # starts with lowercase letter; just letters and numbers -me.constantPattern = "^[A-Z0-9_]+$" # just uppercase letters, underscores, and numbers -me.identifierOrConstantPattern = "^([a-z][A-Za-z0-9]*|[A-Z0-9_]+)$" +me.classNamePattern = '^[A-Z][A-Za-z0-9]*$' # starts with capital letter; just letters and numbers +me.identifierPattern = '^[a-z][A-Za-z0-9]*$' # starts with lowercase letter; just letters and numbers +me.constantPattern = '^[A-Z0-9_]+$' # just uppercase letters, underscores, and numbers +me.identifierOrConstantPattern = '^([a-z][A-Za-z0-9]*|[A-Z0-9_]+)$' me.FunctionArgumentSchema = me.object { - title: "Function Argument", - description: "Documentation entry for a function argument." - "default": - name: "target" - type: "object" - example: "this.getNearestEnemy()" - description: "The target of this function." + title: 'Function Argument', + description: 'Documentation entry for a function argument.' + 'default': + name: 'target' + type: 'object' + example: 'this.getNearestEnemy()' + description: 'The target of this function.' required: ['name', 'type', 'example', 'description'] }, - name: {type: 'string', pattern: me.identifierPattern, title: "Name", description: "Name of the function argument."} + name: {type: 'string', pattern: me.identifierPattern, title: 'Name', description: 'Name of the function argument.'} # not actual JS types, just whatever they describe... - type: me.shortString(title: "Type", description: "Intended type of the argument.") + type: me.shortString(title: 'Type', description: 'Intended type of the argument.') example: oneOf: [ - me.shortString(title: "Example", description: "Example value for the argument.") + me.shortString(title: 'Example', description: 'Example value for the argument.') { type: 'object', - title: "Language Examples", - description: "Examples by code language.", + title: 'Language Examples', + description: 'Examples by code language.', additionalProperties: me.shortString(description: 'Example value for the argument.') } ] description: oneOf: [ - {title: "Description", type: 'string', description: "Description of the argument.", maxLength: 1000} + {title: 'Description', type: 'string', description: 'Description of the argument.', maxLength: 1000} { type: 'object', - title: "Language Descriptions", - description: "Example argument descriptions by code language.", - additionalProperties: {type: 'string', description: "Description of the argument.", maxLength: 1000} + title: 'Language Descriptions', + description: 'Example argument descriptions by code language.', + additionalProperties: {type: 'string', description: 'Description of the argument.', maxLength: 1000} } ] - "default": - title: "Default" - description: "Default value of the argument. (Your code should set this.)" - "default": null + 'default': + title: 'Default' + description: 'Default value of the argument. (Your code should set this.)' + 'default': null me.codeSnippet = (mode) -> - return snippet = + return snippet = code: {type: 'string', title: 'Snippet', default: '', description: 'Code snippet. Use ${1:defaultValue} syntax to add flexible arguments'} # code: {type: 'string', format: 'ace', aceMode: 'ace/mode/'+mode, title: 'Snippet', default: '', description: 'Code snippet. Use ${1:defaultValue} syntax to add flexible arguments'} tab: {type: 'string', title: 'Tab Trigger', description: 'Tab completion text. Will be expanded to the snippet if typed and hit tab.'} -me.activity = me.object {description: "Stats on an activity"}, +me.activity = me.object {description: 'Stats on an activity'}, first: me.date() last: me.date() count: {type: 'integer', minimum: 0} - diff --git a/app/schemas/subscriptions/app.coffee b/app/schemas/subscriptions/app.coffee index 14e7c33b0..f107935c4 100644 --- a/app/schemas/subscriptions/app.coffee +++ b/app/schemas/subscriptions/app.coffee @@ -1,45 +1,45 @@ module.exports = - "application:idle-changed": + 'application: idle-changed': {} # TODO schema - "fbapi-loaded": + 'fbapi-loaded': {} # TODO schema - "logging-in-with-facebook": + 'logging-in-with-facebook': {} # TODO schema - "facebook-logged-in": - title: "Facebook logged in" - $schema: "http://json-schema.org/draft-04/schema#" - description: "Published when you successfully logged in with facebook" - type: "object" + 'facebook-logged-in': + title: 'Facebook logged in' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'Published when you successfully logged in with facebook' + type: 'object' properties: response: - type: "object" + type: 'object' properties: - status: { type: "string" } + status: {type: 'string'} authResponse: - type: "object" + type: 'object' properties: - accessToken: { type: "string" } - expiresIn: { type: "number" } - signedRequest: { type: "string" } - userID: { type: "string" } - required: ["response"] - - "facebook-logged-out": {} - - "linkedin-loaded": {} + accessToken: {type: 'string'} + expiresIn: {type: 'number'} + signedRequest: {type: 'string'} + userID: {type: 'string'} + required: ['response'] - "gapi-loaded": + 'facebook-logged-out': {} + + 'linkedin-loaded': {} + + 'gapi-loaded': {} # TODO schema - "logging-in-with-gplus": + 'logging-in-with-gplus': {} # TODO schema - "gplus-logged-in": - title: "G+ logged in" - $schema: "http://json-schema.org/draft-04/schema#" - description: "Published when you successfully logged in with G+" - type: "object" - required: ["access_token"] + 'gplus-logged-in': + title: 'G+ logged in' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'Published when you successfully logged in with G+' + type: 'object' + required: ['access_token'] diff --git a/app/schemas/subscriptions/bus.coffee b/app/schemas/subscriptions/bus.coffee index 3e4702cfd..72bdd6b07 100644 --- a/app/schemas/subscriptions/bus.coffee +++ b/app/schemas/subscriptions/bus.coffee @@ -1,71 +1,71 @@ module.exports = - "bus:connecting": - title: "Bus Connecting" - $schema: "http://json-schema.org/draft-04/schema#" - description: "Published when a Bus starts connecting" - type: "object" + 'bus:connecting': + title: 'Bus Connecting' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'Published when a Bus starts connecting' + type: 'object' properties: bus: - $ref: "bus" + $ref: 'bus' - "bus:connected": - title: "Bus Connected" - $schema: "http://json-schema.org/draft-04/schema#" - description: "Published when a Bus has connected" - type: "object" + 'bus:connected': + title: 'Bus Connected' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'Published when a Bus has connected' + type: 'object' properties: bus: - $ref: "bus" + $ref: 'bus' - "bus:disconnected": - title: "Bus Disconnected" - $schema: "http://json-schema.org/draft-04/schema#" - description: "Published when a Bus has disconnected" - type: "object" + 'bus:disconnected': + title: 'Bus Disconnected' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'Published when a Bus has disconnected' + type: 'object' properties: bus: - $ref: "bus" + $ref: 'bus' - "bus:new-message": - title: "Message sent" - $schema: "http://json-schema.org/draft-04/schema#" - description: "A new message was sent" - type: "object" + 'bus:new-message': + title: 'Message sent' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'A new message was sent' + type: 'object' properties: message: - type: "object" + type: 'object' bus: - $ref: "bus" + $ref: 'bus' - "bus:player-joined": - title: "Player joined" - $schema: "http://json-schema.org/draft-04/schema#" - description: "A new player has joined" - type: "object" + 'bus:player-joined': + title: 'Player joined' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'A new player has joined' + type: 'object' properties: player: - type: "object" + type: 'object' bus: - $ref: "bus" + $ref: 'bus' - "bus:player-left": - title: "Player left" - $schema: "http://json-schema.org/draft-04/schema#" - description: "A player has left" - type: "object" + 'bus:player-left': + title: 'Player left' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'A player has left' + type: 'object' properties: player: - type: "object" + type: 'object' bus: - $ref: "bus" + $ref: 'bus' - "bus:player-states-changed": - title: "Player state changes" - $schema: "http://json-schema.org/draft-04/schema#" - description: "State of the players has changed" - type: "object" + 'bus:player-states-changed': + title: 'Player state changes' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'State of the players has changed' + type: 'object' properties: player: - type: "array" + type: 'array' bus: - $ref: "bus" + $ref: 'bus' diff --git a/app/schemas/subscriptions/editor.coffee b/app/schemas/subscriptions/editor.coffee index eba61f772..b75649c9e 100644 --- a/app/schemas/subscriptions/editor.coffee +++ b/app/schemas/subscriptions/editor.coffee @@ -1,78 +1,78 @@ module.exports = - "save-new-version": - title: "Save New Version" - $schema: "http://json-schema.org/draft-04/schema#" - description: "Published when a version gets saved" - type: "object" + 'save-new-version': + title: 'Save New Version' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'Published when a version gets saved' + type: 'object' properties: major: - type: "boolean" + type: 'boolean' commitMessage: - type: "string" - required: ["major", "commitMessage"] + type: 'string' + required: ['major', 'commitMessage'] additionalProperties: false # TODO all these events starting with 'level:' should have 'editor' in their name # to avoid confusion with level play events - "level:view-switched": - title: "Level View Switched" - $schema: "http://json-schema.org/draft-04/schema#" - description: "Published whenever the view switches" - $ref: "jQueryEvent" + 'level:view-switched': + title: 'Level View Switched' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'Published whenever the view switches' + $ref: 'jQueryEvent' - "level-components-changed": + 'level-components-changed': {} # TODO schema - "edit-level-component": + 'edit-level-component': {} # TODO schema - "level-component-edited": + 'level-component-edited': {} # TODO schema - "level-component-editing-ended": + 'level-component-editing-ended': {} # TODO schema - "level-systems-changed": + 'level-systems-changed': {} # TODO schema - "edit-level-system": + 'edit-level-system': {} # TODO schema - "level-system-added": + 'level-system-added': {} # TODO schema - "level-system-edited": + 'level-system-edited': {} # TODO schema - "level-system-editing-ended": + 'level-system-editing-ended': {} # TODO schema - "level-thangs-changed": - title: "Level Thangs Changed" - $schema: "http://json-schema.org/draft-04/schema#" - description: "Published when a Thang changes" - type: "object" + 'level-thangs-changed': + title: 'Level Thangs Changed' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'Published when a Thang changes' + type: 'object' properties: thangsData: - type: "array" - required: ["thangsData"] + type: 'array' + required: ['thangsData'] additionalProperties: false - "edit-level-thang": + 'edit-level-thang': {} # TODO schema - "level-thang-edited": + 'level-thang-edited': {} # TODO schema - "level-thang-done-editing": + 'level-thang-done-editing': {} # TODO schema - "level-loaded": + 'level-loaded': {} # TODO schema - "level-reload-from-data": + 'level-reload-from-data': {} # TODO schema - "save-new-version": + 'save-new-version': {} # TODO schema diff --git a/app/schemas/subscriptions/errors.coffee b/app/schemas/subscriptions/errors.coffee index 4fa0e33ef..598dfc6d9 100644 --- a/app/schemas/subscriptions/errors.coffee +++ b/app/schemas/subscriptions/errors.coffee @@ -1,5 +1,4 @@ module.exports = # app/lib/errors - "server-error": + 'server-error': {} # TODO schema - diff --git a/app/schemas/subscriptions/misc.coffee b/app/schemas/subscriptions/misc.coffee index 5834aaff8..87ff86cac 100644 --- a/app/schemas/subscriptions/misc.coffee +++ b/app/schemas/subscriptions/misc.coffee @@ -1,20 +1,20 @@ module.exports = - "audio-played:loaded": + 'audio-played:loaded': {} # TODO schema # TODO location is debatable - "note-group-started": + 'note-group-started': {} # TODO schema - "note-group-ended": + 'note-group-ended': {} # TODO schema - "modal-closed": + 'modal-closed': {} # TODO schema # TODO I propose prepending 'modal:' - "save-new-version": + 'save-new-version': {} # TODO schema - "router:navigate": + 'router:navigate': {} # TODO schema diff --git a/app/schemas/subscriptions/play.coffee b/app/schemas/subscriptions/play.coffee index 0db11f30d..cfb9cffd4 100644 --- a/app/schemas/subscriptions/play.coffee +++ b/app/schemas/subscriptions/play.coffee @@ -2,88 +2,88 @@ module.exports = # TODO There should be a better way to divide these channels into smaller ones # TODO location is debatable - "echo-self-wizard-sprite": + 'echo-self-wizard-sprite': {} # TODO schema - "level:session-will-save": + 'level:session-will-save': {} # TODO schema - "level-loader:progress-changed": + 'level-loader:progress-changed': {} # TODO schema - "level:shift-space-pressed": + 'level:shift-space-pressed': {} # TODO schema - "level:escape-pressed": + 'level:escape-pressed': {} # TODO schema - "level-enable-controls": + 'level-enable-controls': {} # TODO schema - "level-set-letterbox": + 'level-set-letterbox': {} # TODO schema - "level:started": + 'level:started': {} # TODO schema - "level-set-debug": + 'level-set-debug': {} # TODO schema - "level-set-grid": + 'level-set-grid': {} # TODO schema - "tome:cast-spell": + 'tome:cast-spell': {} # TODO schema - "level:restarted": + 'level:restarted': {} # TODO schema - "level-set-volume": + 'level-set-volume': {} # TODO schema - "level-set-time": + 'level-set-time': {} # TODO schema - "level-select-sprite": + 'level-select-sprite': {} # TODO schema - "level-set-playing": + 'level-set-playing': {} # TODO schema - "level:team-set": + 'level:team-set': {} # TODO schema - "level:docs-shown": {} + 'level:docs-shown': {} - "level:docs-hidden": {} + 'level:docs-hidden': {} - "level:victory-hidden": + 'level:victory-hidden': {} # TODO schema - "next-game-pressed": + 'next-game-pressed': {} # TODO schema - "end-current-script": + 'end-current-script': {} # TODO schema - "script:reset": + 'script:reset': {} # TODO schema - "script:ended": + 'script:ended': {} # TODO schema - "end-all-scripts": {} + 'end-all-scripts': {} - "script:state-changed": + 'script:state-changed': {} # TODO schema 'script-manager:tick': type: 'object' additionalProperties: false properties: - scriptRunning: { type: 'string' } - noteGroupRunning: { type: 'string' } - timeSinceLastScriptEnded: { type: 'number' } + scriptRunning: {type: 'string'} + noteGroupRunning: {type: 'string'} + timeSinceLastScriptEnded: {type: 'number'} scriptStates: type: 'object' additionalProperties: @@ -98,58 +98,58 @@ module.exports = type: 'number' description: 'seconds since this script was triggered last' - "play-sound": + 'play-sound': {} # TODO schema # TODO refactor name - "onLoadingViewUnveiled": + 'onLoadingViewUnveiled': {} # TODO schema - "playback:manually-scrubbed": + 'playback:manually-scrubbed': {} # TODO schema - "change:editor-config": + 'change:editor-config': {} # TODO schema - "restart-level": + 'restart-level': {} # TODO schema - "play-next-level": + 'play-next-level': {} # TODO schema - "level-select-sprite": + 'level-select-sprite': {} # TODO schema - "level-toggle-grid": + 'level-toggle-grid': {} # TODO schema - "level-toggle-debug": + 'level-toggle-debug': {} # TODO schema - "level-toggle-pathfinding": + 'level-toggle-pathfinding': {} # TODO schema - "level-scrub-forward": + 'level-scrub-forward': {} # TODO schema - "level-scrub-back": + 'level-scrub-back': {} # TODO schema - "level-show-victory": + 'level-show-victory': type: 'object' additionalProperties: false properties: - showModal: { type: 'boolean' } + showModal: {type: 'boolean'} - "level-highlight-dom": + 'level-highlight-dom': type: 'object' additionalProperties: false properties: - selector: { type: 'string' } - delay: { type: 'number' } - sides: { type: 'array', items: { 'enum': ['left', 'right', 'top', 'bottom'] }} - offset: { type: 'object' } - rotation: { type: 'number' } + selector: {type: 'string'} + delay: {type: 'number'} + sides: {type: 'array', items: {'enum': ['left', 'right', 'top', 'bottom']}} + offset: {type: 'object'} + rotation: {type: 'number'} - "goal-manager:new-goal-states": + 'goal-manager:new-goal-states': {} # TODO schema diff --git a/app/schemas/subscriptions/surface.coffee b/app/schemas/subscriptions/surface.coffee index 6fa5f2415..0c7413248 100644 --- a/app/schemas/subscriptions/surface.coffee +++ b/app/schemas/subscriptions/surface.coffee @@ -1,96 +1,96 @@ module.exports = # /app/lib/surface - "camera-dragged": + 'camera-dragged': {} # TODO schema - "camera-zoom-in": + 'camera-zoom-in': {} # TODO schema - "camera-zoom-out": + 'camera-zoom-out': {} # TODO schema - "camera-zoom-to": + 'camera-zoom-to': {} # TODO schema - "camera:zoom-updated": + 'camera:zoom-updated': {} # TODO schema - "sprite:speech-updated": + 'sprite:speech-updated': {} # TODO schema - "dialogue-sound-completed": + 'dialogue-sound-completed': {} # TODO schema - "surface:gold-changed": + 'surface:gold-changed': {} # TODO schema - "surface:coordinate-selected": + 'surface:coordinate-selected': {} # TODO schema - "surface:coordinates-shown": + 'surface:coordinates-shown': {} # TODO schema - "level-sprite-clear-dialogue": + 'level-sprite-clear-dialogue': {} # TODO schema - "sprite:loaded": + 'sprite:loaded': {} # TODO schema - "choose-point": + 'choose-point': {} # TODO schema - "choose-region": + 'choose-region': {} # TODO schema - "surface:new-thang-added": + 'surface:new-thang-added': {} # TODO schema - "surface:sprite-selected": + 'surface:sprite-selected': {} # TODO schema - "thang-began-talking": + 'thang-began-talking': {} # TODO schema - "thang-finished-talking": + 'thang-finished-talking': {} # TODO schema - "surface:world-set-up": + 'surface:world-set-up': {} # TODO schema - "surface:frame-changed": + 'surface:frame-changed': {} # TODO schema - "surface:playback-ended": + 'surface:playback-ended': {} # TODO schema - "surface:playback-restarted": + 'surface:playback-restarted': {} # TODO schema - "level-set-playing": + 'level-set-playing': {} # TODO schema - "registrar-echo-states": + 'registrar-echo-states': {} # TODO schema - "surface:mouse-moved": + 'surface:mouse-moved': {} # TODO schema - "surface:stage-mouse-down": + 'surface:stage-mouse-down': {} # TODO schema - "surface:mouse-scrolled": + 'surface:mouse-scrolled': {} # TODO schema - "surface:ticked": + 'surface:ticked': {} # TODO schema - "surface:mouse-over": + 'surface:mouse-over': {} # TODO schema - "surface:mouse-out": + 'surface:mouse-out': {} # TODO schema - "self-wizard:target-changed": + 'self-wizard:target-changed': {} # TODO schema - "echo-all-wizard-sprites": + 'echo-all-wizard-sprites': {} # TODO schema diff --git a/app/schemas/subscriptions/tome.coffee b/app/schemas/subscriptions/tome.coffee index 3f73c188f..f19203d0a 100644 --- a/app/schemas/subscriptions/tome.coffee +++ b/app/schemas/subscriptions/tome.coffee @@ -1,95 +1,95 @@ module.exports = - "tome:cast-spell": + 'tome:cast-spell': {} # TODO schema # TODO do we really need both 'cast-spell' and 'cast-spells'? - "tome:cast-spells": + 'tome:cast-spells': {} # TODO schema - "tome:manual-cast": + 'tome:manual-cast': {} # TODO schema - "tome:spell-created": + 'tome:spell-created': {} # TODO schema - "tome:spell-debug-property-hovered": + 'tome:spell-debug-property-hovered': {} # TODO schema - "tome:toggle-spell-list": + 'tome:toggle-spell-list': {} # TODO schema - "tome:reload-code": + 'tome:reload-code': {} # TODO schema - "tome:palette-hovered": + 'tome:palette-hovered': {} # TODO schema - "tome:palette-pin-toggled": + 'tome:palette-pin-toggled': {} # TODO schema - "tome:palette-clicked": + 'tome:palette-clicked': {} # TODO schema - "tome:spell-statement-index-updated": + 'tome:spell-statement-index-updated': {} # TODO schema # TODO proposition: refactor 'tome' into spell events - "spell-beautify": + 'spell-beautify': {} # TODO schema - "spell-step-forward": + 'spell-step-forward': {} # TODO schema - "spell-step-backward": + 'spell-step-backward': {} # TODO schema - "tome:spell-loaded": + 'tome:spell-loaded': {} # TODO schema - "tome:cast-spell": + 'tome:cast-spell': {} # TODO schema - "tome:spell-changed": + 'tome:spell-changed': {} # TODO schema - "tome:editing-ended": + 'tome:editing-ended': {} # TODO schema - "tome:editing-began": + 'tome:editing-began': {} # TODO schema - "tome:problems-updated": + 'tome:problems-updated': {} # TODO schema - "tome:thang-list-entry-popover-shown": + 'tome:thang-list-entry-popover-shown': {} # TODO schema - "tome:spell-shown": + 'tome:spell-shown': {} # TODO schema - "tome:focus-editor": + 'tome:focus-editor': {} # TODO schema - "tome:change-language": - title: "Tome Change Language" - $schema: "http://json-schema.org/draft-04/schema#" - description: "Published when the Tome should update its programming language." - type: "object" + 'tome:change-language': + title: 'Tome Change Language' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'Published when the Tome should update its programming language.' + type: 'object' additionalProperties: false properties: language: - type: "string" - required: ["language"] + type: 'string' + required: ['language'] - "tome:spell-changed-language": - title: "Spell Changed Language" - $schema: "http://json-schema.org/draft-04/schema#" - description: "Published when an individual spell has updated its code language." - type: "object" + 'tome:spell-changed-language': + title: 'Spell Changed Language' + $schema: 'http://json-schema.org/draft-04/schema#' + description: 'Published when an individual spell has updated its code language.' + type: 'object' additionalProperties: false properties: spell: - type: "object" + type: 'object' language: - type: "string" - required: ["spell"] + type: 'string' + required: ['spell'] diff --git a/app/schemas/subscriptions/user.coffee b/app/schemas/subscriptions/user.coffee index 44e713777..b9ae1e4c0 100644 --- a/app/schemas/subscriptions/user.coffee +++ b/app/schemas/subscriptions/user.coffee @@ -1,9 +1,9 @@ module.exports = - "me:synced": + 'me:synced': {} # TODO schema - "user-fetched": + 'user-fetched': {} # TODO schema - "edit-wizard-settings": + 'edit-wizard-settings': {} # TODO schema diff --git a/app/schemas/subscriptions/world.coffee b/app/schemas/subscriptions/world.coffee index d5e953de4..9cb7487f0 100644 --- a/app/schemas/subscriptions/world.coffee +++ b/app/schemas/subscriptions/world.coffee @@ -1,15 +1,15 @@ module.exports = - "god:user-code-problem": + 'god:user-code-problem': {} # TODO schema - "god:infinite-loop": + 'god:infinite-loop': {} # TODO schema - "god:user-code-problem": + 'god:user-code-problem': {} # TODO schema - "god:new-world-created": + 'god:new-world-created': {} # TODO schema - "god:world-load-progress-changed": - {} # TODO schema \ No newline at end of file + 'god:world-load-progress-changed': + {} # TODO schema diff --git a/app/styles/employers.sass b/app/styles/employers.sass index 1e11323fa..c9f519ce8 100644 --- a/app/styles/employers.sass +++ b/app/styles/employers.sass @@ -67,7 +67,7 @@ .reasons height: 275px margin-bottom: 25px - width: 100% + width: 100% .information_row height: 150px @@ -79,6 +79,7 @@ padding-left: 3% height: 150px display: inline-block + vertical-align: top .employer_icon width: 125px margin: 0px auto diff --git a/app/templates/modal/employer_signup_modal.jade b/app/templates/modal/employer_signup_modal.jade index 82854fcc1..d6a627ddf 100644 --- a/app/templates/modal/employer_signup_modal.jade +++ b/app/templates/modal/employer_signup_modal.jade @@ -49,7 +49,7 @@ block modal-body-content br br b Placement fee: - | If you hire our any of our players, you agree to pay us 15% of the candidate's first year annualized starting base salary. The fee is due on the first day that the candidate is employed and is 100% refundable for up to 90 day if the candidate doesn't remain employed at the company for any reason. + | If you hire any of our players, you agree to pay us 15% of the candidate's first year annualized starting base salary. The fee is due on the first day that the candidate is employed and is 100% refundable for up to 90 day if the candidate doesn't remain employed at the company for any reason. br br b Interns are free: @@ -69,4 +69,4 @@ block modal-footer button.btn.btn-primary(id="contract-agreement-button") I agree else .modal-footer.linkedin - | Thanks! You've already agreed to the contract. \ No newline at end of file + | Thanks! You've already agreed to the contract. diff --git a/app/treema-ext.coffee b/app/treema-ext.coffee index dcfd4dbed..0bb6772e6 100644 --- a/app/treema-ext.coffee +++ b/app/treema-ext.coffee @@ -18,7 +18,7 @@ class LiveEditingMarkup extends TreemaNode.nodeMap.ace constructor: -> super(arguments...) - @schema.aceMode = "ace/mode/markdown" + @schema.aceMode = 'ace/mode/markdown' buildValueForEditing: (valEl) -> super(valEl) @@ -200,7 +200,7 @@ class ImageFileTreema extends TreemaNode.nodeMap.string class CoffeeTreema extends TreemaNode.nodeMap.ace constructor: -> super(arguments...) - @schema.aceMode = "ace/mode/coffee" + @schema.aceMode = 'ace/mode/coffee' @schema.aceTabSize = 2 buildValueForEditing: (valEl) -> @@ -216,7 +216,7 @@ class CoffeeTreema extends TreemaNode.nodeMap.ace class JavaScriptTreema extends CoffeeTreema constructor: -> super(arguments...) - @schema.aceMode = "ace/mode/javascript" + @schema.aceMode = 'ace/mode/javascript' @schema.aceTabSize = 4 KB = 1024 @@ -232,13 +232,13 @@ class InternationalizationNode extends TreemaNode.nodeMap.object i18nChildSchema = { title: @findLanguageName(key) - type: "object" + type: 'object' properties: {} } return i18nChildSchema unless @parent unless @schema.props? - console.warn "i18n props array is empty! Filling with all parent properties by default" - @schema.props = (prop for prop,_ of @parent.schema.properties when prop isnt "i18n") + console.warn 'i18n props array is empty! Filling with all parent properties by default' + @schema.props = (prop for prop,_ of @parent.schema.properties when prop isnt 'i18n') for i18nProperty in @schema.props i18nChildSchema.properties[i18nProperty] = @parent.schema.properties[i18nProperty] diff --git a/app/views/DemoView.coffee b/app/views/DemoView.coffee index 00def8100..a3b65c781 100644 --- a/app/views/DemoView.coffee +++ b/app/views/DemoView.coffee @@ -7,7 +7,7 @@ DEMO_URL_PREFIX = '/demo/' ### What are demo files? - + They could be a function which returns an element to insert into the demo page. But what about demoing achievements? They'll get put into the main html. Or modals. Well, I was thinking that a single folder would show all demos at the same time, line them up. @@ -16,15 +16,15 @@ DEMO_URL_PREFIX = '/demo/' It could work like Jasmine, where it modifies the path and so when you select to run them, they all run with page reloads. I think for now, I'll just say: have it be a function which we can run anytime. It may or may not return an element to be inserted into the main area. - + Another idea. Do we want root views to just take over the full view? Or should they just go into the central part? Probably should take over the full view, and if you want to get out of the demo, you navigate back. - + ### module.exports = DemoView = class DemoView extends CocoView - id: "demo-view" + id: 'demo-view' template: template # INITIALIZE diff --git a/app/views/TestView.coffee b/app/views/TestView.coffee index ef1d02fbf..dceff7b36 100644 --- a/app/views/TestView.coffee +++ b/app/views/TestView.coffee @@ -6,10 +6,10 @@ TEST_REQUIRE_PREFIX = 'test/app/' TEST_URL_PREFIX = '/test/' module.exports = TestView = class TestView extends CocoView - id: "test-view" + id: 'test-view' template: template reloadOnClose: true - + # INITIALIZE constructor: (options, @subPath='') -> @@ -25,15 +25,15 @@ module.exports = TestView = class TestView extends CocoView src: "/javascripts/#{f}.js" type: createjs.LoadQueue.JAVASCRIPT }) - + scriptsLoaded: -> @initSpecFiles() @render() TestView.runTests(@specFiles) window.runJasmine() - + # RENDER DATA - + getRenderData: -> c = super(arguments...) c.parentFolders = requireUtils.getParentFolders(@subPath, TEST_URL_PREFIX) @@ -41,9 +41,9 @@ module.exports = TestView = class TestView extends CocoView parts = @subPath.split('/') c.currentFolder = parts[parts.length-1] or parts[parts.length-2] or 'All' c - + # RUNNING TESTS - + initSpecFiles: -> @specFiles = TestView.getAllSpecFiles() if @subPath @@ -62,11 +62,11 @@ module.exports = TestView = class TestView extends CocoView # * document.location # * firebase # * all the services that load in main.html - + afterEach -> # TODO Clean up more things # * Events - + require f for f in specFiles # runs the tests @getAllSpecFiles = -> @@ -76,4 +76,4 @@ module.exports = TestView = class TestView extends CocoView destroy: -> # hack to get jasmine tests to properly run again on clicking links, and make sure if you # leave this page (say, back to the main site) that test stuff doesn't follow you. - document.location.reload() \ No newline at end of file + document.location.reload() diff --git a/app/views/about_view.coffee b/app/views/about_view.coffee index af77a43b9..76988aba8 100644 --- a/app/views/about_view.coffee +++ b/app/views/about_view.coffee @@ -2,5 +2,5 @@ View = require 'views/kinds/RootView' template = require 'templates/about' module.exports = class AboutView extends View - id: "about-view" + id: 'about-view' template: template diff --git a/app/views/account/job_profile_view.coffee b/app/views/account/job_profile_view.coffee index 97b2371e4..bd4472d23 100644 --- a/app/views/account/job_profile_view.coffee +++ b/app/views/account/job_profile_view.coffee @@ -1,6 +1,6 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/account/job_profile' -{me} = require('lib/auth') +{me} = require 'lib/auth' module.exports = class JobProfileView extends CocoView id: 'job-profile-view' @@ -60,7 +60,7 @@ module.exports = class JobProfileView extends CocoView progress = Math.round 100 * completed / totalWeight bar = @$el.find('.profile-completion-progress .progress-bar') bar.css 'width', "#{progress}%" - text = "" + text = '' if progress > 19 text = "#{progress}% complete" else if progress > 5 @@ -77,26 +77,25 @@ module.exports = class JobProfileView extends CocoView modified = (field) -> -> jobProfile[field] and jobProfile[field] isnt schema.properties[field].default listStarted = (field, subfields) -> -> jobProfile[field]?.length and _.every subfields, (subfield) -> jobProfile[field][0][subfield] @progressMetrics = [ - {name: "Mark yourself open to offers to show up in searches.", weight: 1, fn: modified 'active'} - {name: "Specify your desired job title.", weight: 0, fn: exists 'jobTitle'} - {name: "Provide your name.", weight: 1, fn: modified 'name'} - {name: "Choose your city.", weight: 1, fn: modified 'city'} - {name: "Pick your country.", weight: 0, fn: exists 'country'} - {name: "List at least five skills.", weight: 2, fn: -> jobProfile.skills.length >= 5} - {name: "Write a short description to summarize yourself at a glance.", weight: 2, fn: modified 'shortDescription'} - {name: "Fill in your main description to sell yourself and describe the work you're looking for.", weight: 3, fn: modified 'longDescription'} - {name: "List your work experience.", weight: 3, fn: listStarted 'work', ['role', 'employer']} - {name: "Recount your educational ordeals.", weight: 3, fn: listStarted 'education', ['degree', 'school']} - {name: "Show off up to three projects you've worked on.", weight: 3, fn: listStarted 'projects', ['name']} - {name: "Add any personal or social links.", weight: 2, fn: listStarted 'links', ['link', 'name']} - {name: "Add an optional professional photo.", weight: 2, fn: modified 'photoURL'} + {name: 'Mark yourself open to offers to show up in searches.', weight: 1, fn: modified 'active'} + {name: 'Specify your desired job title.', weight: 0, fn: exists 'jobTitle'} + {name: 'Provide your name.', weight: 1, fn: modified 'name'} + {name: 'Choose your city.', weight: 1, fn: modified 'city'} + {name: 'Pick your country.', weight: 0, fn: exists 'country'} + {name: 'List at least five skills.', weight: 2, fn: -> jobProfile.skills.length >= 5} + {name: 'Write a short description to summarize yourself at a glance.', weight: 2, fn: modified 'shortDescription'} + {name: 'Fill in your main description to sell yourself and describe the work you\'re looking for.', weight: 3, fn: modified 'longDescription'} + {name: 'List your work experience.', weight: 3, fn: listStarted 'work', ['role', 'employer']} + {name: 'Recount your educational ordeals.', weight: 3, fn: listStarted 'education', ['degree', 'school']} + {name: 'Show off up to three projects you\'ve worked on.', weight: 3, fn: listStarted 'projects', ['name']} + {name: 'Add any personal or social links.', weight: 2, fn: listStarted 'links', ['link', 'name']} + {name: 'Add an optional professional photo.', weight: 2, fn: modified 'photoURL'} ] getData: -> return {} unless me.get('jobProfile') or @hasEditedProfile _.pick @jobProfileTreema.data, (value, key) => key in @editableSettings - JobProfileView.commonSkills = commonSkills = ['c#', 'java', 'javascript', 'php', 'android', 'jquery', 'python', 'c++', 'html', 'mysql', 'ios', 'asp.net', 'css', 'sql', 'iphone', '.net', 'objective-c', 'ruby-on-rails', 'c', 'ruby', 'sql-server', 'ajax', 'wpf', 'linux', 'database', 'django', 'vb.net', 'windows', 'facebook', 'r', 'html5', 'multithreading', 'ruby-on-rails-3', 'wordpress', 'winforms', 'node.js', 'spring', 'osx', 'performance', 'visual-studio-2010', 'oracle', 'swing', 'algorithm', 'git', 'linq', 'apache', 'web-services', 'perl', 'wcf', 'entity-framework', 'bash', 'visual-studio', 'sql-server-2008', 'hibernate', 'actionscript-3', 'angularjs', 'matlab', 'qt', 'ipad', 'sqlite', 'cocoa-touch', 'cocoa', 'flash', 'mongodb', 'codeigniter', 'jquery-ui', 'css3', 'tsql', 'google-maps', 'silverlight', 'security', 'delphi', 'vba', 'postgresql', 'jsp', 'shell', 'internet-explorer', 'google-app-engine', 'sockets', 'validation', 'scala', 'oop', 'unit-testing', 'xaml', 'parsing', 'twitter-bootstrap', 'google-chrome', 'http', 'magento', 'email', 'android-layout', 'flex', 'rest', 'maven', 'jsf', 'listview', 'date', 'winapi', 'windows-phone-7', 'facebook-graph-api', 'unix', 'url', 'c#-4.0', 'jquery-ajax', 'svn', 'symfony2', 'table', 'cakephp', 'firefox', 'ms-access', 'java-ee', 'jquery-mobile', 'python-2.7', 'tomcat', 'zend-framework', 'opencv', 'visual-c++', 'opengl', 'spring-mvc', 'sql-server-2005', 'authentication', 'search', 'xslt', 'servlets', 'pdf', 'animation', 'math', 'batch-file', 'excel-vba', 'iis', 'mod-rewrite', 'sharepoint', 'gwt', 'powershell', 'visual-studio-2012', 'haskell', 'grails', 'ubuntu', 'networking', 'nhibernate', 'design-patterns', 'testing', 'jpa', 'visual-studio-2008', 'core-data', 'user-interface', 'audio', 'backbone.js', 'gcc', 'mobile', 'design', 'activerecord', 'extjs', 'video', 'stored-procedures', 'optimization', 'drupal', 'image-processing', 'android-intent', 'logging', 'web-applications', 'razor', 'database-design', 'azure', 'vim', 'memory-management', 'model-view-controller', 'cordova', 'c++11', 'selenium', 'ssl', 'assembly', 'soap', 'boost', 'canvas', 'google-maps-api-3', 'netbeans', 'heroku', 'jsf-2', 'encryption', 'hadoop', 'linq-to-sql', 'dll', 'xpath', 'data-binding', 'windows-phone-8', 'phonegap', 'jdbc', 'python-3.x', 'twitter', 'mvvm', 'gui', 'web', 'jquery-plugins', 'numpy', 'deployment', 'ios7', 'emacs', 'knockout.js', 'graphics', 'joomla', 'unicode', 'windows-8', 'android-fragments', 'ant', 'command-line', 'version-control', 'yii', 'github', 'amazon-web-services', 'macros', 'ember.js', 'svg', 'opengl-es', 'django-models', 'solr', 'orm', 'blackberry', 'windows-7', 'ruby-on-rails-4', 'compiler', 'tcp', 'pdo', 'architecture', 'groovy', 'nginx', 'concurrency', 'paypal', 'iis-7', 'express', 'vbscript', 'google-chrome-extension', 'memory-leaks', 'rspec', 'actionscript', 'interface', 'fonts', 'oauth', 'ssh', 'tfs', 'junit', 'struts2', 'd3.js', 'coldfusion', '.net-4.0', 'jqgrid', 'asp-classic', 'https', 'plsql', 'stl', 'sharepoint-2010', 'asp.net-web-api', 'mysqli', 'sed', 'awk', 'internet-explorer-8', 'jboss', 'charts', 'scripting', 'matplotlib', 'laravel', 'clojure', 'entity-framework-4', 'intellij-idea', 'xml-parsing', 'sqlite3', '3d', 'io', 'mfc', 'devise', 'playframework', 'youtube', 'amazon-ec2', 'localization', 'cuda', 'jenkins', 'ssis', 'safari', 'doctrine2', 'vb6', 'amazon-s3', 'dojo', 'air', 'eclipse-plugin', 'android-asynctask', 'crystal-reports', 'cocos2d-iphone', 'dns', 'highcharts', 'ruby-on-rails-3.2', 'ado.net', 'sql-server-2008-r2', 'android-emulator', 'spring-security', 'cross-browser', 'oracle11g', 'bluetooth', 'f#', 'msbuild', 'drupal-7', 'google-apps-script', 'mercurial', 'xna', 'google-analytics', 'lua', 'parallel-processing', 'internationalization', 'java-me', 'mono', 'monotouch', 'android-ndk', 'lucene', 'kendo-ui', 'linux-kernel', 'terminal', 'phpmyadmin', 'makefile', 'ffmpeg', 'applet', 'active-directory', 'coffeescript', 'pandas', 'responsive-design', 'xhtml', 'silverlight-4.0', '.net-3.5', 'jaxb', 'ruby-on-rails-3.1', 'gps', 'geolocation', 'network-programming', 'windows-services', 'laravel-4', 'ggplot2', 'rss', 'webkit', 'functional-programming', 'wsdl', 'telerik', 'maven-2', 'cron', 'mapreduce', 'websocket', 'automation', 'windows-runtime', 'django-forms', 'tkinter', 'android-widget', 'android-activity', 'rubygems', 'content-management-system', 'doctrine', 'django-templates', 'gem', 'fluent-nhibernate', 'seo', 'meteor', 'serial-port', 'glassfish', 'documentation', 'cryptography', 'ef-code-first', 'extjs4', 'x86', 'wordpress-plugin', 'go', 'wix', 'linq-to-entities', 'oracle10g', 'cocos2d', 'selenium-webdriver', 'open-source', 'jtable', 'qt4', 'smtp', 'redis', 'jvm', 'openssl', 'timezone', 'nosql', 'erlang', 'playframework-2.0', 'machine-learning', 'mocking', 'unity3d', 'thread-safety', 'android-actionbar', 'jni', 'udp', 'jasper-reports', 'zend-framework2', 'apache2', 'internet-explorer-7', 'sqlalchemy', 'neo4j', 'ldap', 'jframe', 'youtube-api', 'filesystems', 'make', 'flask', 'gdb', 'cassandra', 'sms', 'g++', 'django-admin', 'push-notification', 'statistics', 'tinymce', 'locking', 'javafx', 'firefox-addon', 'fancybox', 'windows-phone', 'log4j', 'uikit', 'prolog', 'socket.io', 'icons', 'oauth-2.0', 'refactoring', 'sencha-touch', 'elasticsearch', 'symfony1', 'google-api', 'webserver', 'wpf-controls', 'microsoft-metro', 'gtk', 'flex4', 'three.js', 'gradle', 'centos', 'angularjs-directive', 'internet-explorer-9', 'sass', 'html5-canvas', 'interface-builder', 'programming-languages', 'gmail', 'jersey', 'twitter-bootstrap-3', 'arduino', 'requirejs', 'cmake', 'web-development', 'software-engineering', 'startups', 'entrepreneurship', 'social-media-marketing', 'writing', 'marketing', 'web-design', 'graphic-design', 'game-development', 'game-design', 'photoshop', 'illustrator', 'robotics', 'aws', 'devops', 'mathematica', 'bioinformatics', 'data-vis', 'ui', 'embedded-systems', 'codecombat'] JobProfileView.commonLinkNames = commonLinkNames = ['GitHub', 'Facebook', 'Twitter', 'G+', 'LinkedIn', 'Personal Website', 'Blog'] diff --git a/app/views/account/profile_view.coffee b/app/views/account/profile_view.coffee index ca3329595..8c88b2a39 100644 --- a/app/views/account/profile_view.coffee +++ b/app/views/account/profile_view.coffee @@ -17,16 +17,16 @@ class LevelSessionsCollection extends CocoCollection super() adminContacts = [ - {id: "", name: "Assign a Contact"} - {id: "512ef4805a67a8c507000001", name: "Nick"} - {id: "5162fab9c92b4c751e000274", name: "Scott"} - {id: "51eb2714fa058cb20d0006ef", name: "Michael"} - {id: "51538fdb812dd9af02000001", name: "George"} - {id: "52a57252a89409700d0000d9", name: "Ignore"} + {id: '', name: 'Assign a Contact'} + {id: '512ef4805a67a8c507000001', name: 'Nick'} + {id: '5162fab9c92b4c751e000274', name: 'Scott'} + {id: '51eb2714fa058cb20d0006ef', name: 'Michael'} + {id: '51538fdb812dd9af02000001', name: 'George'} + {id: '52a57252a89409700d0000d9', name: 'Ignore'} ] module.exports = class ProfileView extends View - id: "profile-view" + id: 'profile-view' template: template subscriptions: 'linkedin-loaded': 'onLinkedInLoaded' @@ -74,10 +74,10 @@ module.exports = class ProfileView extends View @highlightedContainers = [] if @userID is me.id @user = me - else if me.isAdmin() or "employer" in me.get('permissions') + else if me.isAdmin() or 'employer' in me.get('permissions') @user = User.getByID(@userID) @user.fetch() - @listenTo @user, "sync", => + @listenTo @user, 'sync', => @render() $.post "/db/user/#{me.id}/track/view_candidate" $.post "/db/user/#{@userID}/track/viewed_by_employer" unless me.isAdmin() @@ -112,7 +112,7 @@ module.exports = class ProfileView extends View afterInsert: -> super() - linkedInButtonParentElement = document.getElementById("linkedInAuthButton") + linkedInButtonParentElement = document.getElementById('linkedInAuthButton') if linkedInButtonParentElement if @linkedinLoaded @renderLinkedInButton() @@ -120,10 +120,11 @@ module.exports = class ProfileView extends View @waitingForLinkedIn = true importLinkedIn: => - overwriteConfirm = confirm("Importing LinkedIn data will overwrite your current work experience, skills, name, descriptions, and education. Continue?") + overwriteConfirm = confirm('Importing LinkedIn data will overwrite your current work experience, skills, name, descriptions, and education. Continue?') unless overwriteConfirm then return application.linkedinHandler.getProfileData (err, profileData) => @processLinkedInProfileData profileData + jobProfileSchema: -> @user.schema().properties.jobProfile.properties processLinkedInProfileData: (p) -> @@ -132,96 +133,95 @@ module.exports = class ProfileView extends View oldJobProfile = _.cloneDeep(currentJobProfile) jobProfileSchema = @user.schema().properties.jobProfile.properties - if p["formattedName"]? and p["formattedName"] isnt "private" + if p['formattedName']? and p['formattedName'] isnt 'private' nameMaxLength = jobProfileSchema.name.maxLength - currentJobProfile.name = p["formattedName"].slice(0,nameMaxLength) - if p["skills"]?["values"].length + currentJobProfile.name = p['formattedName'].slice(0, nameMaxLength) + if p['skills']?['values'].length skillNames = [] skillMaxLength = jobProfileSchema.skills.items.maxLength for skill in p.skills.values - skillNames.push skill.skill.name.slice(0,skillMaxLength) + skillNames.push skill.skill.name.slice(0, skillMaxLength) currentJobProfile.skills = skillNames - if p["headline"] + if p['headline'] shortDescriptionMaxLength = jobProfileSchema.shortDescription.maxLength - currentJobProfile.shortDescription = p["headline"].slice(0,shortDescriptionMaxLength) - if p["summary"] + currentJobProfile.shortDescription = p['headline'].slice(0, shortDescriptionMaxLength) + if p['summary'] longDescriptionMaxLength = jobProfileSchema.longDescription.maxLength - currentJobProfile.longDescription = p.summary.slice(0,longDescriptionMaxLength) - if p["positions"]?["values"]?.length + currentJobProfile.longDescription = p.summary.slice(0, longDescriptionMaxLength) + if p['positions']?['values']?.length newWorks = [] workSchema = jobProfileSchema.work.items.properties - for position in p["positions"]["values"] + for position in p['positions']['values'] workObj = {} descriptionMaxLength = workSchema.description.maxLength - workObj.description = position.summary?.slice(0,descriptionMaxLength) - workObj.description ?= "" + workObj.description = position.summary?.slice(0, descriptionMaxLength) + workObj.description ?= '' if position.startDate?.year? workObj.duration = "#{position.startDate.year} - " if (not position.endDate?.year) or (position.endDate?.year and position.endDate?.year > (new Date().getFullYear())) - workObj.duration += "present" + workObj.duration += 'present' else workObj.duration += position.endDate.year else - workObj.duration = "" + workObj.duration = '' durationMaxLength = workSchema.duration.maxLength - workObj.duration = workObj.duration.slice(0,durationMaxLength) + workObj.duration = workObj.duration.slice(0, durationMaxLength) employerMaxLength = workSchema.employer.maxLength - workObj.employer = position.company?.name ? "" - workObj.employer = workObj.employer.slice(0,employerMaxLength) - workObj.role = position.title ? "" + workObj.employer = position.company?.name ? '' + workObj.employer = workObj.employer.slice(0, employerMaxLength) + workObj.role = position.title ? '' roleMaxLength = workSchema.role.maxLength - workObj.role = workObj.role.slice(0,roleMaxLength) + workObj.role = workObj.role.slice(0, roleMaxLength) newWorks.push workObj currentJobProfile.work = newWorks - - if p["educations"]?["values"]?.length + if p['educations']?['values']?.length newEducation = [] eduSchema = jobProfileSchema.education.items.properties - for education in p["educations"]["values"] + for education in p['educations']['values'] educationObject = {} - educationObject.degree = education.degree ? "Studied" + educationObject.degree = education.degree ? 'Studied' if education.startDate?.year? educationObject.duration = "#{education.startDate.year} - " if (not education.endDate?.year) or (education.endDate?.year and education.endDate?.year > (new Date().getFullYear())) - educationObject.duration += "present" - if educationObject.degree is "Studied" - educationObject.degree = "Studying" + educationObject.duration += 'present' + if educationObject.degree is 'Studied' + educationObject.degree = 'Studying' else educationObject.duration += education.endDate.year else - educationObject.duration = "" + educationObject.duration = '' if education.fieldOfStudy - if educationObject.degree is "Studied" or educationObject.degree is "Studying" + if educationObject.degree is 'Studied' or educationObject.degree is 'Studying' educationObject.degree += " #{education.fieldOfStudy}" else educationObject.degree += " in #{education.fieldOfStudy}" - educationObject.degree = educationObject.degree.slice(0,eduSchema.degree.maxLength) - educationObject.duration = educationObject.duration.slice(0,eduSchema.duration.maxLength) - educationObject.school = education.schoolName ? "" - educationObject.school = educationObject.school.slice(0,eduSchema.school.maxLength) - educationObject.description = "" + educationObject.degree = educationObject.degree.slice(0, eduSchema.degree.maxLength) + educationObject.duration = educationObject.duration.slice(0, eduSchema.duration.maxLength) + educationObject.school = education.schoolName ? '' + educationObject.school = educationObject.school.slice(0, eduSchema.school.maxLength) + educationObject.description = '' newEducation.push educationObject currentJobProfile.education = newEducation - if p["publicProfileUrl"] + if p['publicProfileUrl'] #search for linkedin link links = currentJobProfile.links alreadyHasLinkedIn = false for link in links - if link.link.toLowerCase().indexOf("linkedin") > -1 + if link.link.toLowerCase().indexOf('linkedin') > -1 alreadyHasLinkedIn = true break unless alreadyHasLinkedIn newLink = - link: p["publicProfileUrl"] - name: "LinkedIn" + link: p['publicProfileUrl'] + name: 'LinkedIn' currentJobProfile.links.push newLink - @user.set('jobProfile',currentJobProfile) + @user.set('jobProfile', currentJobProfile) validationErrors = @user.validate() if validationErrors - @user.set('jobProfile',oldJobProfile) + @user.set('jobProfile', oldJobProfile) return alert("Please notify team@codecombat.com! There were validation errors from the LinkedIn import: #{JSON.stringify validationErrors}") else @render() @@ -242,7 +242,7 @@ module.exports = class ProfileView extends View context.profile = jobProfile context.user = @user context.myProfile = @user?.id is context.me.id - context.allowedToViewJobProfile = @user and (me.isAdmin() or "employer" in me.get('permissions') or (context.myProfile && !me.get('anonymous'))) + context.allowedToViewJobProfile = @user and (me.isAdmin() or 'employer' in me.get('permissions') or (context.myProfile && !me.get('anonymous'))) context.allowedToEditJobProfile = @user and (me.isAdmin() or (context.myProfile && !me.get('anonymous'))) context.profileApproved = @user?.get 'jobProfileApproved' context.progress = @progress ? @updateProgress() @@ -276,11 +276,11 @@ module.exports = class ProfileView extends View @$el.find('.editable-display').attr('title', '') @initializeAutocomplete() highlightNext = @highlightNext ? true - justSavedSection = @$el.find('#' + @justSavedSectionID).addClass "just-saved" + justSavedSection = @$el.find('#' + @justSavedSectionID).addClass 'just-saved' _.defer => @progress = @updateProgress highlightNext _.delay -> - justSavedSection.removeClass "just-saved", duration: 1500, easing: 'easeOutQuad' + justSavedSection.removeClass 'just-saved', duration: 1500, easing: 'easeOutQuad' , 500 if me.isAdmin() visibleSettings = ['history', 'tasks'] @@ -330,14 +330,14 @@ module.exports = class ProfileView extends View @user.get('jobProfile').active = active @saveEdits() if active and not (me.isAdmin() or @stackLed) - $.post "/stacklead" + $.post '/stacklead' @stackLed = true enterEspionageMode: -> postData = emailLower: @user.get('email').toLowerCase(), usernameLower: @user.get('name').toLowerCase() $.ajax - type: "POST", - url: "/auth/spy" + type: 'POST', + url: '/auth/spy' data: postData success: @espionageSuccess @@ -348,7 +348,7 @@ module.exports = class ProfileView extends View @openModalView new ModelModal models: [@user] onJobProfileNotesChanged: (e) => - notes = @$el.find("#job-profile-notes").val() + notes = @$el.find('#job-profile-notes').val() @user.set 'jobProfileNotes', notes @user.save {jobProfileNotes: notes}, {patch: true} @@ -371,7 +371,7 @@ module.exports = class ProfileView extends View showErrors: (errors) -> section = @$el.find '.saving' - console.error "Couldn't save because of validation errors:", errors + console.error 'Couldn\'t save because of validation errors:', errors section.removeClass 'saving' forms.clearFormAlerts section # This is pretty lame, since we don't easily match which field had the error like forms.applyErrorsToForm can. @@ -477,7 +477,7 @@ module.exports = class ProfileView extends View @saveEdits true extractFieldKeyChain: (key) -> - # "root[projects][0][name]" -> ["projects", "0", "name"] + # 'root[projects][0][name]' -> ['projects', '0', 'name'] key.replace(/^root/, '').replace(/\[(.*?)\]/g, '.$1').replace(/^\./, '').split(/\./) extractFieldValue: (key, value) -> @@ -527,14 +527,14 @@ module.exports = class ProfileView extends View @remark.set 'user', @user.id @remark.set 'userName', @user.get('name') if errors = @remark.validate() - return console.error "UserRemark", @remark, "failed validation with errors:", errors + return console.error 'UserRemark', @remark, 'failed validation with errors:', errors res = @remark.save() res.error => return if @destroyed - console.error "UserRemark", @remark, "failed to save with error:", res.responseText + console.error 'UserRemark', @remark, 'failed to save with error:', res.responseText res.success (model, response, options) => return if @destroyed - console.log "Saved UserRemark", @remark, "with response", response + console.log 'Saved UserRemark', @remark, 'with response', response updateProgress: (highlightNext) -> return unless @user @@ -550,7 +550,7 @@ module.exports = class ProfileView extends View bar = @$el.find('.profile-completion-progress .progress-bar') bar.css 'width', "#{progress}%" if next - text = "" + text = '' t = $.i18n.t text = "#{progress}% #{t 'account_profile.complete'}. #{t 'account_profile.next'}: #{next.name}" bar.parent().show().find('.progress-text').text text diff --git a/app/views/account/settings_view.coffee b/app/views/account/settings_view.coffee index 377c590eb..7c49e2eb5 100644 --- a/app/views/account/settings_view.coffee +++ b/app/views/account/settings_view.coffee @@ -1,8 +1,8 @@ View = require 'views/kinds/RootView' template = require 'templates/account/settings' -{me} = require('lib/auth') -forms = require('lib/forms') -User = require('models/User') +{me} = require 'lib/auth' +forms = require 'lib/forms' +User = require 'models/User' AuthModalView = require 'views/modal/auth_modal' WizardSettingsView = require './wizard_settings_view' @@ -35,7 +35,7 @@ module.exports = class SettingsView extends View forms.clearFormAlerts($('#password-pane', @$el)) ) - @chooseTab(location.hash.replace('#','')) + @chooseTab(location.hash.replace('#', '')) wizardSettingsView = new WizardSettingsView() @listenTo wizardSettingsView, 'change', @save @@ -107,7 +107,7 @@ module.exports = class SettingsView extends View @grabData() res = me.validate() if res? - console.error "Couldn't save because of validation errors:", res + console.error 'Couldn\'t save because of validation errors:', res forms.applyErrorsToForm(@$el, res) return @@ -135,7 +135,7 @@ module.exports = class SettingsView extends View bothThere = Boolean(password1) and Boolean(password2) if bothThere and password1 isnt password2 message = $.i18n.t('account_settings.password_mismatch', defaultValue: 'Password does not match.') - err = [message:message, property:'password2', formatted:true] + err = [message: message, property: 'password2', formatted: true] forms.applyErrorsToForm(@$el, err) return if bothThere diff --git a/app/views/account/unsubscribe_view.coffee b/app/views/account/unsubscribe_view.coffee index 9c951abb0..e75ae7f4b 100644 --- a/app/views/account/unsubscribe_view.coffee +++ b/app/views/account/unsubscribe_view.coffee @@ -3,7 +3,7 @@ template = require 'templates/account/unsubscribe' {me} = require 'lib/auth' module.exports = class UnsubscribeView extends RootView - id: "unsubscribe-view" + id: 'unsubscribe-view' template: template events: diff --git a/app/views/account/wizard_settings_view.coffee b/app/views/account/wizard_settings_view.coffee index 1458f78de..6e441654f 100644 --- a/app/views/account/wizard_settings_view.coffee +++ b/app/views/account/wizard_settings_view.coffee @@ -1,6 +1,6 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/account/wizard_settings' -{me} = require('lib/auth') +{me} = require 'lib/auth' ThangType = require 'models/ThangType' SpriteBuilder = require 'lib/sprites/SpriteBuilder' {hslToHex, hexToHSL} = require 'lib/utils' @@ -77,7 +77,7 @@ module.exports = class WizardSettingsView extends CocoView input = colorGroup.find('.minicolors-input') hex = input.val() hsl = hexToHSL(hex) - config = {hue: hsl[0], saturation:hsl[1], lightness:hsl[2]} + config = {hue: hsl[0], saturation: hsl[1], lightness: hsl[2]} wizardSettings.colorConfig[colorName] = config else delete wizardSettings.colorConfig[colorName] diff --git a/app/views/admin/base_view.coffee b/app/views/admin/base_view.coffee index 5db653086..ca58690c0 100644 --- a/app/views/admin/base_view.coffee +++ b/app/views/admin/base_view.coffee @@ -2,5 +2,5 @@ RootView = require 'views/kinds/RootView' template = require 'templates/base' module.exports = class BaseView extends RootView - id: "base-view" + id: 'base-view' template: template diff --git a/app/views/admin/clas_view.coffee b/app/views/admin/clas_view.coffee index e099b4d10..96828e23e 100644 --- a/app/views/admin/clas_view.coffee +++ b/app/views/admin/clas_view.coffee @@ -2,7 +2,7 @@ View = require 'views/kinds/RootView' template = require 'templates/admin/clas' module.exports = class CLAsView extends View - id: "admin-clas-view" + id: 'admin-clas-view' template: template startsLoading: true diff --git a/app/views/admin/employer_list_view.coffee b/app/views/admin/employer_list_view.coffee index fc7d2f2af..b2ec64d77 100644 --- a/app/views/admin/employer_list_view.coffee +++ b/app/views/admin/employer_list_view.coffee @@ -11,7 +11,7 @@ class EmployersCollection extends CocoCollection model: User module.exports = class EmployersView extends View - id: "employers-view" + id: 'employers-view' template: template events: @@ -42,21 +42,20 @@ module.exports = class EmployersView extends View $.extend $.tablesorter.themes.bootstrap, # these classes are added to the table. To see other table classes available, # look here: http://twitter.github.com/bootstrap/base-css.html#tables - table: "table table-bordered" - caption: "caption" - header: "bootstrap-header" # give the header a gradient background - footerRow: "" - footerCells: "" - icons: "" # add "icon-white" to make them white; this icon class is added to the in the header - sortNone: "bootstrap-icon-unsorted" - sortAsc: "icon-chevron-up" # glyphicon glyphicon-chevron-up" # we are still using v2 icons - sortDesc: "icon-chevron-down" # glyphicon-chevron-down" # we are still using v2 icons - active: "" # applied when column is sorted - hover: "" # use custom css here - bootstrap class may not override it - filterRow: "" # filter row class - even: "" # odd row zebra striping - odd: "" # even row zebra striping - + table: 'table table-bordered' + caption: 'caption' + header: 'bootstrap-header' # give the header a gradient background + footerRow: '' + footerCells: '' + icons: '' # add 'icon-white' to make them white; this icon class is added to the in the header + sortNone: 'bootstrap-icon-unsorted' + sortAsc: 'icon-chevron-up' # glyphicon glyphicon-chevron-up' # we are still using v2 icons + sortDesc: 'icon-chevron-down' # glyphicon-chevron-down' # we are still using v2 icons + active: '' # applied when column is sorted + hover: '' # use custom css here - bootstrap class may not override it + filterRow: '' # filter row class + even: '' # odd row zebra striping + odd: '' # even row zebra striping # e = exact text from cell # n = normalized value returned by the column parser @@ -66,10 +65,10 @@ module.exports = class EmployersView extends View filterSelectExactMatch = (e, n, f, i, $r) -> e is f # call the tablesorter plugin and apply the uitheme widget - @$el.find(".tablesorter").tablesorter - theme: "bootstrap" + @$el.find('.tablesorter').tablesorter + theme: 'bootstrap' widthFixed: true - headerTemplate: "{content} {icon}" + headerTemplate: '{content} {icon}' textSorter: 6: (a, b, direction, column, table) -> days = [] @@ -95,16 +94,16 @@ module.exports = class EmployersView extends View sortList: [[6, 0]] # widget code contained in the jquery.tablesorter.widgets.js file # use the zebra stripe widget if you plan on hiding any rows (filter widget) - widgets: ["uitheme", "zebra", "filter"] + widgets: ['uitheme', 'zebra', 'filter'] widgetOptions: # using the default zebra striping class name, so it actually isn't included in the theme variable above # this is ONLY needed for bootstrap theming if you are using the filter widget, because rows are hidden - zebra: ["even", "odd"] + zebra: ['even', 'odd'] # extra css class applied to the table row containing the filters & the inputs within that row - filter_cssFilter: "" + filter_cssFilter: '' - # If there are child rows in the table (rows with class name from "cssChildRow" option) + # If there are child rows in the table (rows with class name from 'cssChildRow' option) # and this option is true and a match is found anywhere in the child row, then it will make that row # visible; default is false filter_childRows: false @@ -117,7 +116,7 @@ module.exports = class EmployersView extends View filter_ignoreCase: true # jQuery selector string of an element used to reset the filters - filter_reset: ".reset" + filter_reset: '.reset' # Use the $.tablesorter.storage utility to save the most recent filters filter_saveFilters: true @@ -127,30 +126,30 @@ module.exports = class EmployersView extends View filter_searchDelay: 150 # Set this option to true to use the filter to find text from the start of the column - # So typing in "a" will find "albert" but not "frank", both have a's; default is false + # So typing in 'a' will find 'albert' but not 'frank', both have a's; default is false filter_startsWith: false filter_functions: 3: - "0-1": (e, n, f, i, $r) -> parseInt(e) <= 1 - "2-5": (e, n, f, i, $r) -> 2 <= parseInt(e) <= 5 - "6+": (e, n, f, i, $r) -> 6 <= parseInt(e) + '0-1': (e, n, f, i, $r) -> parseInt(e) <= 1 + '2-5': (e, n, f, i, $r) -> 2 <= parseInt(e) <= 5 + '6+': (e, n, f, i, $r) -> 6 <= parseInt(e) 4: - "0-1": (e, n, f, i, $r) -> parseInt(e) <= 1 - "2-5": (e, n, f, i, $r) -> 2 <= parseInt(e) <= 5 - "6+": (e, n, f, i, $r) -> 6 <= parseInt(e) + '0-1': (e, n, f, i, $r) -> parseInt(e) <= 1 + '2-5': (e, n, f, i, $r) -> 2 <= parseInt(e) <= 5 + '6+': (e, n, f, i, $r) -> 6 <= parseInt(e) 5: - "0-1": (e, n, f, i, $r) -> parseInt(e) <= 1 - "2-5": (e, n, f, i, $r) -> 2 <= parseInt(e) <= 5 - "6+": (e, n, f, i, $r) -> 6 <= parseInt(e) + '0-1': (e, n, f, i, $r) -> parseInt(e) <= 1 + '2-5': (e, n, f, i, $r) -> 2 <= parseInt(e) <= 5 + '6+': (e, n, f, i, $r) -> 6 <= parseInt(e) 6: - "Last day": (e, n, f, i, $r) -> + 'Last day': (e, n, f, i, $r) -> days = parseFloat $($r.find('td')[i]).data('employer-age') days <= 1 - "Last week": (e, n, f, i, $r) -> + 'Last week': (e, n, f, i, $r) -> days = parseFloat $($r.find('td')[i]).data('employer-age') days <= 7 - "Last 4 weeks": (e, n, f, i, $r) -> + 'Last 4 weeks': (e, n, f, i, $r) -> days = parseFloat $($r.find('td')[i]).data('employer-age') days <= 28 diff --git a/app/views/admin/files_view.coffee b/app/views/admin/files_view.coffee index 9df6deb10..f444bd91a 100644 --- a/app/views/admin/files_view.coffee +++ b/app/views/admin/files_view.coffee @@ -3,17 +3,17 @@ template = require 'templates/admin/files' tableTemplate = require 'templates/admin/files_table' module.exports = class FilesView extends RootView - id: "admin-files-view" + id: 'admin-files-view' template: template - + events: 'click #upload-button': -> filepicker.pick {mimetypes:'audio/*'}, @onFileChosen 'change #folder-select': 'loadFiles' - + afterRender: -> super() @loadFiles() - + onFileChosen: (InkBlob) => body = url: InkBlob.url @@ -25,18 +25,18 @@ module.exports = class FilesView extends RootView # Automatically overwrite if the same path was put in here before # body.force = true # if InkBlob.filename is @data @uploadingPath = [@currentFolder(), InkBlob.filename].join('/') - $.ajax('/file', { type: 'POST', data: body, success: @onFileUploaded }) + $.ajax('/file', {type: 'POST', data: body, success: @onFileUploaded}) onFileUploaded: (e) => @loadFiles() - + currentFolder: -> @$el.find('#folder-select').val() loadFiles: -> $.ajax url: "/file/#{@currentFolder()}/" success: @onLoadedFiles - + onLoadedFiles: (res) => table = tableTemplate({files:res}) - @$el.find('#file-table').replaceWith(table) \ No newline at end of file + @$el.find('#file-table').replaceWith(table) diff --git a/app/views/admin/level_sessions_view.coffee b/app/views/admin/level_sessions_view.coffee index c00fcc2fe..cca854cc3 100644 --- a/app/views/admin/level_sessions_view.coffee +++ b/app/views/admin/level_sessions_view.coffee @@ -8,7 +8,7 @@ class LevelSessionCollection extends Backbone.Collection model: LevelSession module.exports = class LevelSessionsView extends View - id: "admin-level-sessions-view" + id: 'admin-level-sessions-view' template: template constructor: (options) -> diff --git a/app/views/admin/users_view.coffee b/app/views/admin/users_view.coffee index acc9a8152..fa4aa1ba9 100644 --- a/app/views/admin/users_view.coffee +++ b/app/views/admin/users_view.coffee @@ -5,7 +5,7 @@ User = require 'models/User' module.exports = class UsersView extends View # TODO: Pagination, choosing filters on the page itself. - id: "admin-users-view" + id: 'admin-users-view' template: template constructor: (options) -> @@ -41,4 +41,4 @@ module.exports = class UsersView extends View getRenderData: -> c = super() c.users = (user.attributes for user in @users.models) - c \ No newline at end of file + c diff --git a/app/views/admin_view.coffee b/app/views/admin_view.coffee index eab1bbc42..6b0aadcc9 100644 --- a/app/views/admin_view.coffee +++ b/app/views/admin_view.coffee @@ -3,7 +3,7 @@ View = require 'views/kinds/RootView' template = require 'templates/admin' module.exports = class AdminView extends View - id: "admin-view" + id: 'admin-view' template: template events: @@ -11,16 +11,16 @@ module.exports = class AdminView extends View 'click #increment-button': 'incrementUserAttribute' enterEspionageMode: -> - userEmail = $("#user-email").val().toLowerCase() - username = $("#user-username").val().toLowerCase() + userEmail = $('#user-email').val().toLowerCase() + username = $('#user-username').val().toLowerCase() postData = usernameLower: username emailLower: userEmail $.ajax - type: "POST", - url: "/auth/spy" + type: 'POST', + url: '/auth/spy' data: postData success: @espionageSuccess error: @espionageFailure diff --git a/app/views/cla_view.coffee b/app/views/cla_view.coffee index 70269eaed..93f03aa56 100644 --- a/app/views/cla_view.coffee +++ b/app/views/cla_view.coffee @@ -3,7 +3,7 @@ template = require 'templates/cla' {me} = require 'lib/auth' module.exports = class CLAView extends View - id: "cla-view" + id: 'cla-view' template: template events: @@ -17,8 +17,8 @@ module.exports = class CLAView extends View onAgree: -> @$el.find('#agreement-button').prop('disabled', true).text('Saving') $.ajax({ - url: "/db/user/me/agreeToCLA" - data: { 'githubUsername': @$el.find('#github-username').val() } + url: '/db/user/me/agreeToCLA' + data: {'githubUsername': @$el.find('#github-username').val()} method: 'POST' success: @onAgreeSucceeded error: @onAgreeFailed diff --git a/app/views/community_view.coffee b/app/views/community_view.coffee index e31b09f33..69a140269 100644 --- a/app/views/community_view.coffee +++ b/app/views/community_view.coffee @@ -2,5 +2,5 @@ View = require 'views/kinds/RootView' template = require 'templates/community' module.exports = class CommunityView extends View - id: "community-view" + id: 'community-view' template: template diff --git a/app/views/contribute/adventurer_view.coffee b/app/views/contribute/adventurer_view.coffee index 9428a8624..deda5add5 100644 --- a/app/views/contribute/adventurer_view.coffee +++ b/app/views/contribute/adventurer_view.coffee @@ -1,8 +1,8 @@ ContributeClassView = require 'views/contribute/contribute_class_view' template = require 'templates/contribute/adventurer' -{me} = require('lib/auth') +{me} = require 'lib/auth' module.exports = class AdventurerView extends ContributeClassView - id: "adventurer-view" + id: 'adventurer-view' template: template contributorClassName: 'adventurer' diff --git a/app/views/contribute/ambassador_view.coffee b/app/views/contribute/ambassador_view.coffee index 6ea7a68cd..73c35bf96 100644 --- a/app/views/contribute/ambassador_view.coffee +++ b/app/views/contribute/ambassador_view.coffee @@ -1,8 +1,8 @@ ContributeClassView = require 'views/contribute/contribute_class_view' template = require 'templates/contribute/ambassador' -{me} = require('lib/auth') +{me} = require 'lib/auth' module.exports = class AmbassadorView extends ContributeClassView - id: "ambassador-view" + id: 'ambassador-view' template: template contributorClassName: 'ambassador' diff --git a/app/views/contribute/archmage_view.coffee b/app/views/contribute/archmage_view.coffee index 7ac7508ca..e29a9be5c 100644 --- a/app/views/contribute/archmage_view.coffee +++ b/app/views/contribute/archmage_view.coffee @@ -2,32 +2,32 @@ ContributeClassView = require 'views/contribute/contribute_class_view' template = require 'templates/contribute/archmage' module.exports = class ArchmageView extends ContributeClassView - id: "archmage-view" + id: 'archmage-view' template: template contributorClassName: 'archmage' contributors: [ - {id: "52bfc3ecb7ec628868001297", name: "Tom Steinbrecher", github: "TomSteinbrecher"} - {id: "5272806093680c5817033f73", name: "Sébastien Moratinos", github: "smoratinos"} - {name: "deepak1556", avatar: "deepak", github: "deepak1556"} - {name: "Ronnie Cheng", avatar: "ronald", github: "rhc2104"} - {name: "Chloe Fan", avatar: "chloe", github: "chloester"} - {name: "Rachel Xiang", avatar: "rachel", github: "rdxiang"} - {name: "Dan Ristic", avatar: "dan", github: "dristic"} - {name: "Brad Dickason", avatar: "brad", github: "bdickason"} - {name: "Rebecca Saines", avatar: "becca"} - {name: "Laura Watiker", avatar: "laura", github: "lwatiker"} - {name: "Shiying Zheng", avatar: "shiying", github: "shiyingzheng"} - {name: "Mischa Lewis-Norelle", avatar: "mischa", github: "mlewisno"} - {name: "Paul Buser", avatar: "paul"} - {name: "Benjamin Stern", avatar: "ben"} - {name: "Alex Cotsarelis", avatar: "alex"} - {name: "Ken Stanley", avatar: "ken"} - {name: "devast8a", avatar: "", github: "devast8a"} - {name: "phansch", avatar: "", github: "phansch"} - {name: "Zach Martin", avatar: "", github: "zachster01"} - {name: "David Golds", avatar: ""} - {name: "gabceb", avatar: "", github: "gabceb"} - {name: "MDP66", avatar: "", github: "MDP66"} - {name: "Alexandru Caciulescu", avatar: "", github: "Darredevil"} + {id: '52bfc3ecb7ec628868001297', name: 'Tom Steinbrecher', github: 'TomSteinbrecher'} + {id: '5272806093680c5817033f73', name: 'Sébastien Moratinos', github: 'smoratinos'} + {name: 'deepak1556', avatar: 'deepak', github: 'deepak1556'} + {name: 'Ronnie Cheng', avatar: 'ronald', github: 'rhc2104'} + {name: 'Chloe Fan', avatar: 'chloe', github: 'chloester'} + {name: 'Rachel Xiang', avatar: 'rachel', github: 'rdxiang'} + {name: 'Dan Ristic', avatar: 'dan', github: 'dristic'} + {name: 'Brad Dickason', avatar: 'brad', github: 'bdickason'} + {name: 'Rebecca Saines', avatar: 'becca'} + {name: 'Laura Watiker', avatar: 'laura', github: 'lwatiker'} + {name: 'Shiying Zheng', avatar: 'shiying', github: 'shiyingzheng'} + {name: 'Mischa Lewis-Norelle', avatar: 'mischa', github: 'mlewisno'} + {name: 'Paul Buser', avatar: 'paul'} + {name: 'Benjamin Stern', avatar: 'ben'} + {name: 'Alex Cotsarelis', avatar: 'alex'} + {name: 'Ken Stanley', avatar: 'ken'} + {name: 'devast8a', avatar: '', github: 'devast8a'} + {name: 'phansch', avatar: '', github: 'phansch'} + {name: 'Zach Martin', avatar: '', github: 'zachster01'} + {name: 'David Golds', avatar: ''} + {name: 'gabceb', avatar: '', github: 'gabceb'} + {name: 'MDP66', avatar: '', github: 'MDP66'} + {name: 'Alexandru Caciulescu', avatar: '', github: 'Darredevil'} ] diff --git a/app/views/contribute/artisan_view.coffee b/app/views/contribute/artisan_view.coffee index dbad64902..7094dba98 100644 --- a/app/views/contribute/artisan_view.coffee +++ b/app/views/contribute/artisan_view.coffee @@ -1,25 +1,25 @@ ContributeClassView = require 'views/contribute/contribute_class_view' template = require 'templates/contribute/artisan' -{me} = require('lib/auth') +{me} = require 'lib/auth' module.exports = class ArtisanView extends ContributeClassView - id: "artisan-view" + id: 'artisan-view' template: template contributorClassName: 'artisan' contributors: [ - {name: "Sootn", avatar: ""} - {name: "Zach Martin", avatar: "", github: "zachster01"} - {name: "Aftermath", avatar: ""} - {name: "mcdavid1991", avatar: ""} - {name: "dwhittaker", avatar: ""} - {name: "Zacharias Fisches", avatar: ""} - {name: "Tom Setliff", avatar: ""} - {name: "Robert Moreton", avatar: "rob"} - {name: "Andrew Witcher", avatar: "andrew"} - {name: "Axandre Oge", avatar: "axandre"} - {name: "Katharine Chan", avatar: "katharine"} - {name: "Derek Wong", avatar: "derek"} - {name: "Alexandru Caciulescu", avatar: "", github: "Darredevil"} - {name: "Prabh Simran Singh Baweja", avatar: "", github: "prabh27"} + {name: 'Sootn', avatar: ''} + {name: 'Zach Martin', avatar: '', github: 'zachster01'} + {name: 'Aftermath', avatar: ''} + {name: 'mcdavid1991', avatar: ''} + {name: 'dwhittaker', avatar: ''} + {name: 'Zacharias Fisches', avatar: ''} + {name: 'Tom Setliff', avatar: ''} + {name: 'Robert Moreton', avatar: 'rob'} + {name: 'Andrew Witcher', avatar: 'andrew'} + {name: 'Axandre Oge', avatar: 'axandre'} + {name: 'Katharine Chan', avatar: 'katharine'} + {name: 'Derek Wong', avatar: 'derek'} + {name: 'Alexandru Caciulescu', avatar: '', github: 'Darredevil'} + {name: 'Prabh Simran Singh Baweja', avatar: '', github: 'prabh27'} ] diff --git a/app/views/contribute/contribute_class_view.coffee b/app/views/contribute/contribute_class_view.coffee index ae6fd59af..3da551ffb 100644 --- a/app/views/contribute/contribute_class_view.coffee +++ b/app/views/contribute/contribute_class_view.coffee @@ -1,6 +1,6 @@ SignupModalView = require 'views/modal/signup_modal' View = require 'views/kinds/RootView' -{me} = require('lib/auth') +{me} = require 'lib/auth' contributorSignupAnonymousTemplate = require 'templates/contribute/contributor_signup_anonymous' contributorSignupTemplate = require 'templates/contribute/contributor_signup' contributorListTemplate = require 'templates/contribute/contributor_list' @@ -34,7 +34,7 @@ module.exports = class ContributeClassView extends View el = $(e.target) checked = el.prop('checked') subscription = el.attr('name') - + me.setEmailSubscription subscription+'News', checked me.patch() @openModalView new SignupModalView() if me.get 'anonymous' diff --git a/app/views/contribute/counselor_view.coffee b/app/views/contribute/counselor_view.coffee new file mode 100644 index 000000000..c2a8e4faf --- /dev/null +++ b/app/views/contribute/counselor_view.coffee @@ -0,0 +1,8 @@ +ContributeClassView = require 'views/contribute/contribute_class_view' +template = require 'templates/contribute/counselor' +{me} = require 'lib/auth' + +module.exports = class CounselorView extends ContributeClassView + id: 'counselor-view' + template: template + contributorClassName: 'counselor' diff --git a/app/views/contribute/diplomat_view.coffee b/app/views/contribute/diplomat_view.coffee index 0769af517..00b3dd7a7 100644 --- a/app/views/contribute/diplomat_view.coffee +++ b/app/views/contribute/diplomat_view.coffee @@ -1,8 +1,8 @@ ContributeClassView = require 'views/contribute/contribute_class_view' template = require 'templates/contribute/diplomat' -{me} = require('lib/auth') +{me} = require 'lib/auth' module.exports = class DiplomatView extends ContributeClassView - id: "diplomat-view" + id: 'diplomat-view' template: template contributorClassName: 'diplomat' diff --git a/app/views/contribute/scribe_view.coffee b/app/views/contribute/scribe_view.coffee index 7f87a3275..d52d0106b 100644 --- a/app/views/contribute/scribe_view.coffee +++ b/app/views/contribute/scribe_view.coffee @@ -1,18 +1,18 @@ ContributeClassView = require 'views/contribute/contribute_class_view' template = require 'templates/contribute/scribe' -{me} = require('lib/auth') +{me} = require 'lib/auth' module.exports = class ScribeView extends ContributeClassView - id: "scribe-view" + id: 'scribe-view' template: template contributorClassName: 'scribe' contributors: [ - {name: "Ryan Faidley"} - {name: "Mischa Lewis-Norelle", github: "mlewisno"} - {name: "Tavio"} - {name: "Ronnie Cheng", github: "rhc2104"} - {name: "engstrom"} - {name: "Dman19993"} - {name: "mattinsler"} + {name: 'Ryan Faidley'} + {name: 'Mischa Lewis-Norelle', github: 'mlewisno'} + {name: 'Tavio'} + {name: 'Ronnie Cheng', github: 'rhc2104'} + {name: 'engstrom'} + {name: 'Dman19993'} + {name: 'mattinsler'} ] diff --git a/app/views/contribute_view.coffee b/app/views/contribute_view.coffee index 12a35c71f..fa772c75a 100644 --- a/app/views/contribute_view.coffee +++ b/app/views/contribute_view.coffee @@ -2,7 +2,7 @@ ContributeClassView = require 'views/contribute/contribute_class_view' template = require 'templates/contribute/contribute' module.exports = class ContributeView extends ContributeClassView - id: "contribute-view" + id: 'contribute-view' template: template navPrefix: '' diff --git a/app/views/editor/achievement/edit.coffee b/app/views/editor/achievement/edit.coffee index 76988a586..ce65446dd 100644 --- a/app/views/editor/achievement/edit.coffee +++ b/app/views/editor/achievement/edit.coffee @@ -4,7 +4,7 @@ Achievement = require 'models/Achievement' ConfirmModal = require 'views/modal/confirm' module.exports = class AchievementEditView extends View - id: "editor-achievement-edit-view" + id: 'editor-achievement-edit-view' template: template startsLoading: true @@ -77,10 +77,10 @@ module.exports = class AchievementEditView extends View confirmRecalculation: (e) -> renderData = - 'confirmTitle': "Are you really sure?" - 'confirmBody': "This will trigger recalculation of the achievement for all users. Are you really sure you want to go down this path?" - 'confirmDecline': "Not really" - 'confirmConfirm': "Definitely" + 'confirmTitle': 'Are you really sure?' + 'confirmBody': 'This will trigger recalculation of the achievement for all users. Are you really sure you want to go down this path?' + 'confirmDecline': 'Not really' + 'confirmConfirm': 'Definitely' confirmModal = new ConfirmModal(renderData) confirmModal.onConfirm @recalculateAchievement diff --git a/app/views/editor/achievement/home.coffee b/app/views/editor/achievement/home.coffee index 37bcb2795..4f6a21b29 100644 --- a/app/views/editor/achievement/home.coffee +++ b/app/views/editor/achievement/home.coffee @@ -1,8 +1,8 @@ SearchView = require 'views/kinds/SearchView' module.exports = class AchievementSearchView extends SearchView - id: "editor-achievement-home-view" - modelLabel: "Achievement" + id: 'editor-achievement-home-view' + modelLabel: 'Achievement' model: require 'models/Achievement' modelURL: '/db/achievement' tableTemplate: require 'templates/editor/achievement/table' diff --git a/app/views/editor/article/edit.coffee b/app/views/editor/article/edit.coffee index 5a319bd06..1511ba155 100644 --- a/app/views/editor/article/edit.coffee +++ b/app/views/editor/article/edit.coffee @@ -6,7 +6,7 @@ Article = require 'models/Article' SaveVersionModal = require 'views/modal/save_version_modal' module.exports = class ArticleEditView extends View - id: "editor-article-edit-view" + id: 'editor-article-edit-view' template: template startsLoading: true @@ -107,6 +107,6 @@ module.exports = class ArticleEditView extends View document.location.href = url showVersionHistory: (e) -> - versionHistoryView = new VersionHistoryView article:@article, @articleID + versionHistoryView = new VersionHistoryView article: @article, @articleID @openModalView versionHistoryView Backbone.Mediator.publish 'level:view-switched', e diff --git a/app/views/editor/article/home.coffee b/app/views/editor/article/home.coffee index c34640d55..4f8fdab05 100644 --- a/app/views/editor/article/home.coffee +++ b/app/views/editor/article/home.coffee @@ -1,7 +1,7 @@ SearchView = require 'views/kinds/SearchView' module.exports = class ThangTypeHomeView extends SearchView - id: "editor-article-home-view" + id: 'editor-article-home-view' modelLabel: 'Article' model: require 'models/Article' modelURL: '/db/article' diff --git a/app/views/editor/article/preview.coffee b/app/views/editor/article/preview.coffee index 74851e1c2..ef4d3455b 100644 --- a/app/views/editor/article/preview.coffee +++ b/app/views/editor/article/preview.coffee @@ -2,5 +2,5 @@ View = require 'views/kinds/RootView' template = require 'templates/editor/article/preview' module.exports = class PreviewView extends View - id: "editor-article-preview-view" + id: 'editor-article-preview-view' template: template diff --git a/app/views/editor/article/versions_view.coffee b/app/views/editor/article/versions_view.coffee index 63b040366..98d9f1c63 100644 --- a/app/views/editor/article/versions_view.coffee +++ b/app/views/editor/article/versions_view.coffee @@ -1,9 +1,9 @@ VersionsModalView = require 'views/modal/versions_modal' module.exports = class ArticleVersionsView extends VersionsModalView - id: "editor-article-versions-view" - url: "/db/article/" - page: "article" + id: 'editor-article-versions-view' + url: '/db/article/' + page: 'article' constructor: (options, @ID) -> - super options, ID, require 'models/Article' \ No newline at end of file + super options, ID, require 'models/Article' diff --git a/app/views/editor/component/versions_view.coffee b/app/views/editor/component/versions_view.coffee index 1edaad280..409dc8553 100755 --- a/app/views/editor/component/versions_view.coffee +++ b/app/views/editor/component/versions_view.coffee @@ -1,9 +1,9 @@ VersionsModalView = require 'views/modal/versions_modal' module.exports = class ComponentVersionsView extends VersionsModalView - id: "editor-component-versions-view" - url: "/db/level.component/" - page: "component" + id: 'editor-component-versions-view' + url: '/db/level.component/' + page: 'component' constructor: (options, @ID) -> - super options, ID, require 'models/LevelComponent' \ No newline at end of file + super options, ID, require 'models/LevelComponent' diff --git a/app/views/editor/components/config.coffee b/app/views/editor/components/config.coffee index 7b605a5a1..7fb37b3ab 100644 --- a/app/views/editor/components/config.coffee +++ b/app/views/editor/components/config.coffee @@ -6,7 +6,7 @@ LevelComponent = require 'models/LevelComponent' nodes = require '../level/treema_nodes' module.exports = class ComponentConfigView extends CocoView - id: "component-config-column-view" + id: 'component-config-column-view' template: template className: 'column' changed: false @@ -29,7 +29,7 @@ module.exports = class ComponentConfigView extends CocoView afterRender: -> super() @buildTreema() - + buildTreema: -> thangs = if @level? then @level.get('thangs') else [] thangIDs = _.filter(_.pluck(thangs, 'id')) @@ -68,5 +68,5 @@ module.exports = class ComponentConfigView extends CocoView onConfigEdited: => @changed = true @callback?(@data()) - + data: -> @editThangTreema.data diff --git a/app/views/editor/components/main.coffee b/app/views/editor/components/main.coffee index e8040f231..234608a44 100644 --- a/app/views/editor/components/main.coffee +++ b/app/views/editor/components/main.coffee @@ -8,7 +8,7 @@ ComponentsCollection = require 'collections/ComponentsCollection' ComponentConfigView = require './config' module.exports = class ThangComponentEditView extends CocoView - id: "thang-components-edit-view" + id: 'thang-components-edit-view' template: template constructor: (options) -> @@ -18,7 +18,7 @@ module.exports = class ThangComponentEditView extends CocoView @level = options.level @callback = options.callback @componentCollection = @supermodel.loadCollection(new ComponentsCollection(), 'components').model - + afterRender: -> super() return unless @supermodel.finished() @@ -31,7 +31,7 @@ module.exports = class ThangComponentEditView extends CocoView supermodel: @supermodel schema: level.schema().properties.thangs.items.properties.components data: _.cloneDeep @components - callbacks: {select: @onSelectExtantComponent, change:@onChangeExtantComponents} + callbacks: {select: @onSelectExtantComponent, change: @onChangeExtantComponents} noSortable: true nodeClasses: 'thang-components-array': ThangComponentsArrayNode @@ -49,13 +49,13 @@ module.exports = class ThangComponentEditView extends CocoView components = (m.attributes for m in @componentCollection.models) _.remove components, (comp) => _.find extantComponents, {original: comp.original} # already have this one added - components = _.sortBy components, (comp) -> comp.system + "." + comp.name + components = _.sortBy components, (comp) -> comp.system + '.' + comp.name treemaOptions = supermodel: @supermodel - schema: { type: 'array', items: LevelComponent.schema } + schema: {type: 'array', items: LevelComponent.schema} data: ($.extend(true, {}, c) for c in components) - callbacks: {select: @onSelectAddableComponent, enter: @onAddComponentEnterPressed } + callbacks: {select: @onSelectAddableComponent, enter: @onAddComponentEnterPressed} readOnly: true noSortable: true nodeClasses: @@ -162,7 +162,7 @@ module.exports = class ThangComponentEditView extends CocoView id = node.data._id comp = _.find @componentCollection.models, id: id unless comp - return console.error "Couldn't find component for id", id, "out of", @components.models + return console.error 'Couldn\'t find component for id', id, 'out of', @components.models # Add all dependencies, recursively, unless we already have them toAdd = comp.getDependencies(@componentCollection.models) _.remove toAdd, (c1) => @@ -181,7 +181,6 @@ module.exports = class ThangComponentEditView extends CocoView treema.select() return - reportChanges: -> @callback?($.extend(true, [], @extantComponentsTreema.data)) @@ -210,11 +209,11 @@ class ThangComponentNode extends TreemaObjectNode grabDBComponent: -> @component = @settings.supermodel.getModelByOriginalAndMajorVersion LevelComponent, @data.original, @data.majorVersion - console.error "Couldn't find comp for", @data.original, @data.majorVersion, "from models", @settings.supermodel.models unless @component + console.error 'Couldn\'t find comp for', @data.original, @data.majorVersion, 'from models', @settings.supermodel.models unless @component buildValueForDisplay: (valEl) -> return super valEl unless @data.original and @component - s = @component.get('system') + "." + @component.get('name') + s = @component.get('system') + '.' + @component.get('name') @buildValueForDisplaySimply valEl, s class ComponentArrayNode extends TreemaArrayNode @@ -234,7 +233,7 @@ class ComponentNode extends TreemaObjectNode collection: false buildValueForDisplay: (valEl) -> - s = @data.system + "." + @data.name + s = @data.system + '.' + @data.name @buildValueForDisplaySimply valEl, s onEnterPressed: (args...) -> diff --git a/app/views/editor/delta.coffee b/app/views/editor/delta.coffee index 91a8f6dba..fe0f875da 100644 --- a/app/views/editor/delta.coffee +++ b/app/views/editor/delta.coffee @@ -21,7 +21,7 @@ module.exports = class DeltaView extends CocoView ### @deltaCounter: 0 - className: "delta-view" + className: 'delta-view' template: template constructor: (options) -> @@ -30,8 +30,7 @@ module.exports = class DeltaView extends CocoView @skipPaths = options.skipPaths for modelName in ['model', 'headModel', 'comparisonModel'] - continue unless m = options[modelName] - @[modelName] = @supermodel.loadModel(m, 'document').model + @[modelName] = options[modelName] @buildDeltas() if @supermodel.finished() @@ -112,4 +111,4 @@ module.exports = class DeltaView extends CocoView delta = @model.getDelta() delta = deltasLib.pruneConflictsFromDelta delta, @conflicts if @conflicts delta = deltasLib.pruneExpandedDeltasFromDelta delta, @skippedDeltas if @skippedDeltas - delta \ No newline at end of file + delta diff --git a/app/views/editor/level/add_thangs_view.coffee b/app/views/editor/level/add_thangs_view.coffee index 2a635b2c9..7a7070b17 100644 --- a/app/views/editor/level/add_thangs_view.coffee +++ b/app/views/editor/level/add_thangs_view.coffee @@ -11,7 +11,7 @@ class ThangTypeSearchCollection extends CocoCollection @url += "&term=#{term}" if term module.exports = class AddThangsView extends View - id: "add-thangs-column" + id: 'add-thangs-column' className: 'add-thangs-palette thangs-column' template: add_thangs_template startsLoading: false @@ -72,5 +72,5 @@ module.exports = class AddThangsView extends View @lastSearch = term onEscapePressed: -> - @$el.find('input#thang-search').val("") + @$el.find('input#thang-search').val('') @runSearch diff --git a/app/views/editor/level/component/edit.coffee b/app/views/editor/level/component/edit.coffee index c3908f277..a7bc51149 100644 --- a/app/views/editor/level/component/edit.coffee +++ b/app/views/editor/level/component/edit.coffee @@ -6,7 +6,7 @@ PatchesView = require 'views/editor/patches_view' SaveVersionModal = require 'views/modal/save_version_modal' module.exports = class LevelComponentEditView extends View - id: "editor-level-component-edit-view" + id: 'editor-level-component-edit-view' template: template editableSettings: ['name', 'description', 'system', 'codeLanguage', 'dependencies', 'propertyDocumentation', 'i18n'] @@ -24,7 +24,7 @@ module.exports = class LevelComponentEditView extends View constructor: (options) -> super options @levelComponent = @supermodel.getModelByOriginalAndMajorVersion LevelComponent, options.original, options.majorVersion or 0 - console.log "Couldn't get levelComponent for", options, "from", @supermodel.models unless @levelComponent + console.log 'Couldn\'t get levelComponent for', options, 'from', @supermodel.models unless @levelComponent @onEditorChange = _.debounce @onEditorChange, 1000 getRenderData: (context={}) -> @@ -34,6 +34,7 @@ module.exports = class LevelComponentEditView extends View context onLoaded: -> @render() + afterRender: -> super() @buildSettingsTreema() @@ -44,6 +45,7 @@ module.exports = class LevelComponentEditView extends View buildSettingsTreema: -> data = _.pick @levelComponent.attributes, (value, key) => key in @editableSettings + data = $.extend(true, {}, data) schema = _.cloneDeep LevelComponent.schema schema.properties = _.pick schema.properties, (value, key) => key in @editableSettings schema.required = _.intersection schema.required, @editableSettings @@ -111,7 +113,7 @@ module.exports = class LevelComponentEditView extends View Backbone.Mediator.publish 'level:view-switched', e startPatchingComponent: (e) -> - @openModalView new SaveVersionModal({model:@levelComponent}) + @openModalView new SaveVersionModal({model: @levelComponent}) Backbone.Mediator.publish 'level:view-switched', e toggleWatchComponent: -> diff --git a/app/views/editor/level/component/new.coffee b/app/views/editor/level/component/new.coffee index 88b7761b8..072a69df6 100644 --- a/app/views/editor/level/component/new.coffee +++ b/app/views/editor/level/component/new.coffee @@ -4,9 +4,8 @@ LevelComponent = require 'models/LevelComponent' forms = require 'lib/forms' {me} = require 'lib/auth' - module.exports = class LevelComponentNewView extends View - id: "editor-level-component-new-modal" + id: 'editor-level-component-new-modal' template: template instant: false modalWidthPercent: 60 @@ -30,7 +29,7 @@ module.exports = class LevelComponentNewView extends View @showLoading() res.error => @hideLoading() - console.log "Got errors:", JSON.parse(res.responseText) + console.log 'Got errors:', JSON.parse(res.responseText) forms.applyErrorsToForm(@$el, JSON.parse(res.responseText)) res.success => @supermodel.registerModel component diff --git a/app/views/editor/level/components_tab_view.coffee b/app/views/editor/level/components_tab_view.coffee index 0ae4a3873..27f91ae87 100644 --- a/app/views/editor/level/components_tab_view.coffee +++ b/app/views/editor/level/components_tab_view.coffee @@ -9,7 +9,7 @@ class LevelComponentCollection extends Backbone.Collection model: LevelComponent module.exports = class ComponentsTabView extends View - id: "editor-level-components-tab-view" + id: 'editor-level-components-tab-view' template: template className: 'tab-pane' @@ -82,9 +82,9 @@ class LevelComponentNode extends TreemaObjectNode valueClass: 'treema-level-component' collection: false buildValueForDisplay: (valEl) -> - count = if @data.count is 1 then @data.thangs[0] else ((if @data.count >= 100 then "100+" else @data.count) + " Thangs") - if @data.original.match ":" - name = "Old: " + @data.original.replace('systems/', '') + count = if @data.count is 1 then @data.thangs[0] else ((if @data.count >= 100 then '100+' else @data.count) + ' Thangs') + if @data.original.match ':' + name = 'Old: ' + @data.original.replace('systems/', '') else comp = _.find @settings.supermodel.getModels(LevelComponent), (m) => m.get('original') is @data.original and m.get('version').major is @data.majorVersion diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/edit.coffee index 1b19e68b2..c81e7f708 100644 --- a/app/views/editor/level/edit.coffee +++ b/app/views/editor/level/edit.coffee @@ -19,7 +19,7 @@ VersionHistoryView = require './versions_view' ErrorView = require '../../error_view' module.exports = class EditorLevelView extends View - id: "editor-level-view" + id: 'editor-level-view' template: template cache: false @@ -34,7 +34,7 @@ module.exports = class EditorLevelView extends View 'click #level-watch-button': 'toggleWatchLevel' 'click #pop-level-i18n-button': -> @level.populateI18N() 'mouseup .nav-tabs > li a': 'toggleTab' - + constructor: (options, @levelID) -> super options @supermodel.shouldSaveBackups = (model) -> @@ -73,7 +73,7 @@ module.exports = class EditorLevelView extends View Backbone.Mediator.publish 'level-loaded', level: @level @showReadOnly() if me.get('anonymous') @patchesView = @insertSubView(new PatchesView(@level), @$el.find('.patches-view')) - @listenTo @patchesView, 'accepted-patch', -> setTimeout "location.reload()", 400 + @listenTo @patchesView, 'accepted-patch', -> location.reload() @$el.find('#level-watch-button').find('> span').toggleClass('secret') if @level.watching() onPlayLevel: (e) -> @@ -84,15 +84,15 @@ module.exports = class EditorLevelView extends View sendLevel() else # Create a new Window with a blank LevelView - scratchLevelID = @level.get('slug') + "?dev=true" + scratchLevelID = @level.get('slug') + '?dev=true' @childWindow = window.open("/play/level/#{scratchLevelID}", 'child_window', 'width=1024,height=560,left=10,top=10,location=0,menubar=0,scrollbars=0,status=0,titlebar=0,toolbar=0', true) @childWindow.onPlayLevelViewLoaded = (e) => sendLevel() # still a hack @childWindow.focus() startPatchingLevel: (e) -> - @openModalView new SaveVersionModal({model:@level}) + @openModalView new SaveVersionModal({model: @level}) Backbone.Mediator.publish 'level:view-switched', e - + startCommittingLevel: (e) -> @openModalView new LevelSaveView level: @level, supermodel: @supermodel Backbone.Mediator.publish 'level:view-switched', e @@ -103,7 +103,7 @@ module.exports = class EditorLevelView extends View Backbone.Mediator.publish 'level:view-switched', e showVersionHistory: (e) -> - versionHistoryView = new VersionHistoryView level:@level, @levelID + versionHistoryView = new VersionHistoryView level: @level, @levelID @openModalView versionHistoryView Backbone.Mediator.publish 'level:view-switched', e @@ -111,7 +111,7 @@ module.exports = class EditorLevelView extends View button = @$el.find('#level-watch-button') @level.watch(button.find('.watch').is(':visible')) button.find('> span').toggleClass('secret') - + toggleTab: (e) -> @renderScrollbar() return unless $(document).width() <= 800 diff --git a/app/views/editor/level/fork_view.coffee b/app/views/editor/level/fork_view.coffee index 9f8ffb229..522a21b1c 100644 --- a/app/views/editor/level/fork_view.coffee +++ b/app/views/editor/level/fork_view.coffee @@ -4,7 +4,7 @@ forms = require 'lib/forms' Level = require 'models/Level' module.exports = class LevelForkView extends View - id: "editor-level-fork-modal" + id: 'editor-level-fork-modal' template: template instant: false modalWidthPercent: 60 diff --git a/app/views/editor/level/home.coffee b/app/views/editor/level/home.coffee index ae31fd6e8..f5db556e6 100644 --- a/app/views/editor/level/home.coffee +++ b/app/views/editor/level/home.coffee @@ -1,7 +1,7 @@ SearchView = require 'views/kinds/SearchView' module.exports = class EditorSearchView extends SearchView - id: "editor-level-home-view" + id: 'editor-level-home-view' modelLabel: 'Level' model: require 'models/Level' modelURL: '/db/level' diff --git a/app/views/editor/level/modal/world_select.coffee b/app/views/editor/level/modal/world_select.coffee index 05cef5e38..adbbd11d3 100644 --- a/app/views/editor/level/modal/world_select.coffee +++ b/app/views/editor/level/modal/world_select.coffee @@ -57,7 +57,7 @@ module.exports = class WorldSelectModal extends View window.s = @surface @surface.playing = false @surface.setWorld @world - @surface.camera.zoomTo({x:262, y:-164}, 1.66, 0) + @surface.camera.zoomTo({x: 262, y: -164}, 1.66, 0) @showDefaults() showDefaults: -> diff --git a/app/views/editor/level/save_view.coffee b/app/views/editor/level/save_view.coffee index 6f0f6f18e..3d95ee2f4 100644 --- a/app/views/editor/level/save_view.coffee +++ b/app/views/editor/level/save_view.coffee @@ -39,10 +39,10 @@ module.exports = class LevelSaveView extends SaveVersionModal for changeEl, i in changeEls model = models[i] try - deltaView = new DeltaView({model:model}) + deltaView = new DeltaView({model: model}) @insertSubView(deltaView, $(changeEl)) catch e - console.error "Couldn't create delta view:", e + console.error 'Couldn\'t create delta view:', e shouldSaveEntity: (m) -> return false unless m.hasWriteAccess() @@ -58,14 +58,14 @@ module.exports = class LevelSaveView extends SaveVersionModal # Level form is first, then LevelComponents' forms, then LevelSystems' forms fields = {} for field in $(form).serializeArray() - fields[field.name] = if field.value is "on" then true else field.value + fields[field.name] = if field.value is 'on' then true else field.value isLevelForm = $(form).attr('id') is 'save-level-form' if isLevelForm model = @level else [kind, klass] = if $(form).hasClass 'component-form' then ['component', LevelComponent] else ['system', LevelSystem] model = @supermodel.getModelByOriginalAndMajorVersion klass, fields["#{kind}-original"], parseInt(fields["#{kind}-parent-major-version"], 10) - console.log "Couldn't find model for", kind, fields, "from", @supermodel.models unless model + console.log 'Couldn\'t find model for', kind, fields, 'from', @supermodel.models unless model newModel = if fields.major then model.cloneNewMajorVersion() else model.cloneNewMinorVersion() newModel.set 'commitMessage', fields['commit-message'] modelsToSave.push newModel @@ -92,7 +92,7 @@ module.exports = class LevelSaveView extends SaveVersionModal do (newModel, form) => res.error => @hideLoading() - console.log "Got errors:", JSON.parse(res.responseText) + console.log 'Got errors:', JSON.parse(res.responseText) forms.applyErrorsToForm($(form), JSON.parse(res.responseText)) res.success => modelsToSave = _.without modelsToSave, newModel diff --git a/app/views/editor/level/scripts_tab_view.coffee b/app/views/editor/level/scripts_tab_view.coffee index f9ad725a4..7a3e96c65 100644 --- a/app/views/editor/level/scripts_tab_view.coffee +++ b/app/views/editor/level/scripts_tab_view.coffee @@ -5,7 +5,7 @@ Surface = require 'lib/surface/Surface' nodes = require './treema_nodes' module.exports = class ScriptsTabView extends View - id: "editor-level-scripts-tab-view" + id: 'editor-level-scripts-tab-view' template: template className: 'tab-pane' @@ -16,7 +16,7 @@ module.exports = class ScriptsTabView extends View super options @world = options.world @files = options.files - + onLoaded: -> onLevelLoaded: (e) -> @level = e.level @@ -86,7 +86,6 @@ module.exports = class ScriptsTabView extends View onScriptChanged: => @scriptsTreema.set(@selectedScriptPath, @scriptTreema.data) - class ScriptNode extends TreemaObjectNode valueClass: 'treema-script' collection: false @@ -109,7 +108,6 @@ class ScriptNode extends TreemaObjectNode return unless firstRow? firstRow.select() - class EventPropsNode extends TreemaNode.nodeMap.string valueClass: 'treema-event-props' diff --git a/app/views/editor/level/system/add.coffee b/app/views/editor/level/system/add.coffee index fb42a866b..28a362809 100644 --- a/app/views/editor/level/system/add.coffee +++ b/app/views/editor/level/system/add.coffee @@ -9,7 +9,7 @@ class LevelSystemSearchCollection extends CocoCollection model: LevelSystem module.exports = class LevelSystemAddView extends View - id: "editor-level-system-add-modal" + id: 'editor-level-system-add-modal' template: template instant: true @@ -52,7 +52,7 @@ module.exports = class LevelSystemAddView extends View id = $(e.currentTarget).data('system-id') system = _.find @systems.models, id: id unless system - return console.error "Couldn't find system for id", id, "out of", @systems.models + return console.error 'Couldn\'t find system for id', id, 'out of', @systems.models # Add all dependencies, recursively, unless we already have them toAdd = system.getDependencies(@systems.models) _.remove toAdd, (s1) => diff --git a/app/views/editor/level/system/edit.coffee b/app/views/editor/level/system/edit.coffee index 6560bafa7..f9e9646db 100644 --- a/app/views/editor/level/system/edit.coffee +++ b/app/views/editor/level/system/edit.coffee @@ -6,7 +6,7 @@ PatchesView = require 'views/editor/patches_view' SaveVersionModal = require 'views/modal/save_version_modal' module.exports = class LevelSystemEditView extends View - id: "editor-level-system-edit-view" + id: 'editor-level-system-edit-view' template: template editableSettings: ['name', 'description', 'codeLanguage', 'dependencies', 'propertyDocumentation', 'i18n'] @@ -24,7 +24,7 @@ module.exports = class LevelSystemEditView extends View constructor: (options) -> super options @levelSystem = @supermodel.getModelByOriginalAndMajorVersion LevelSystem, options.original, options.majorVersion or 0 - console.log "Couldn't get levelSystem for", options, "from", @supermodel.models unless @levelSystem + console.log 'Couldn\'t get levelSystem for', options, 'from', @supermodel.models unless @levelSystem getRenderData: (context={}) -> context = super(context) @@ -106,7 +106,7 @@ module.exports = class LevelSystemEditView extends View Backbone.Mediator.publish 'level:view-switched', e startPatchingSystem: (e) -> - @openModalView new SaveVersionModal({model:@levelSystem}) + @openModalView new SaveVersionModal({model: @levelSystem}) Backbone.Mediator.publish 'level:view-switched', e toggleWatchSystem: -> diff --git a/app/views/editor/level/system/new.coffee b/app/views/editor/level/system/new.coffee index 4b91a7df6..1ddd8d158 100644 --- a/app/views/editor/level/system/new.coffee +++ b/app/views/editor/level/system/new.coffee @@ -4,9 +4,8 @@ LevelSystem = require 'models/LevelSystem' forms = require 'lib/forms' {me} = require 'lib/auth' - module.exports = class LevelSystemNewView extends View - id: "editor-level-system-new-modal" + id: 'editor-level-system-new-modal' template: template instant: false modalWidthPercent: 60 @@ -29,7 +28,7 @@ module.exports = class LevelSystemNewView extends View @showLoading() res.error => @hideLoading() - console.log "Got errors:", JSON.parse(res.responseText) + console.log 'Got errors:', JSON.parse(res.responseText) forms.applyErrorsToForm(@$el, JSON.parse(res.responseText)) res.success => @supermodel.registerModel system diff --git a/app/views/editor/level/systems_tab_view.coffee b/app/views/editor/level/systems_tab_view.coffee index 4d3ed88c6..a3b6df3f2 100644 --- a/app/views/editor/level/systems_tab_view.coffee +++ b/app/views/editor/level/systems_tab_view.coffee @@ -8,7 +8,7 @@ LevelSystemAddView = require './system/add' {ThangTypeNode} = require './treema_nodes' module.exports = class SystemsTabView extends View - id: "editor-level-systems-tab-view" + id: 'editor-level-systems-tab-view' template: template className: 'tab-pane' @@ -33,10 +33,10 @@ module.exports = class SystemsTabView extends View afterRender: -> @buildSystemsTreema() - + onLoaded: -> super() - + onLevelLoaded: (e) -> @level = e.level @buildSystemsTreema() @@ -109,21 +109,21 @@ module.exports = class SystemsTabView extends View buildDefaultSystems: -> [ - {original: "528112c00268d018e3000008", majorVersion: 0} # Event - {original: "5280f83b8ae1581b66000001", majorVersion: 0, config: {lifespan: 60}} # Existence - {original: "5281146f0268d018e3000014", majorVersion: 0} # Programming - {original: "528110f30268d018e3000001", majorVersion: 0} # AI - {original: "52810ffa33e01a6e86000012", majorVersion: 0} # Action - {original: "528114b20268d018e3000017", majorVersion: 0} # Targeting - {original: "528105f833e01a6e86000007", majorVersion: 0} # Collision - {original: "528113240268d018e300000c", majorVersion: 0, config: {gravity: 9.81}} # Movement - {original: "528112530268d018e3000007", majorVersion: 0} # Combat - {original: "52810f4933e01a6e8600000c", majorVersion: 0} # Hearing - {original: "528115040268d018e300001b", majorVersion: 0} # Vision - {original: "5280dc4d251616c907000001", majorVersion: 0} # Inventory - {original: "528111b30268d018e3000004", majorVersion: 0} # Alliance - {original: "528114e60268d018e300001a", majorVersion: 0} # UI - {original: "528114040268d018e3000011", majorVersion: 0} # Physics + {original: '528112c00268d018e3000008', majorVersion: 0} # Event + {original: '5280f83b8ae1581b66000001', majorVersion: 0, config: {lifespan: 60}} # Existence + {original: '5281146f0268d018e3000014', majorVersion: 0} # Programming + {original: '528110f30268d018e3000001', majorVersion: 0} # AI + {original: '52810ffa33e01a6e86000012', majorVersion: 0} # Action + {original: '528114b20268d018e3000017', majorVersion: 0} # Targeting + {original: '528105f833e01a6e86000007', majorVersion: 0} # Collision + {original: '528113240268d018e300000c', majorVersion: 0, config: {gravity: 9.81}} # Movement + {original: '528112530268d018e3000007', majorVersion: 0} # Combat + {original: '52810f4933e01a6e8600000c', majorVersion: 0} # Hearing + {original: '528115040268d018e300001b', majorVersion: 0} # Vision + {original: '5280dc4d251616c907000001', majorVersion: 0} # Inventory + {original: '528111b30268d018e3000004', majorVersion: 0} # Alliance + {original: '528114e60268d018e300001a', majorVersion: 0} # UI + {original: '528114040268d018e3000011', majorVersion: 0} # Physics ] class LevelSystemNode extends TreemaObjectNode @@ -137,7 +137,7 @@ class LevelSystemNode extends TreemaObjectNode unless _.isString @data.original return alert('Press the "Add System" button at the bottom instead of the "+". Sorry.') @system = @settings.supermodel.getModelByOriginalAndMajorVersion(LevelSystem, @data.original, @data.majorVersion) - console.error "Couldn't find system for", @data.original, @data.majorVersion, "from models", @settings.supermodel.models unless @system + console.error 'Couldn\'t find system for', @data.original, @data.majorVersion, 'from models', @settings.supermodel.models unless @system getChildSchema: (key) -> return @system.attributes.configSchema if key is 'config' diff --git a/app/views/editor/level/thang/edit.coffee b/app/views/editor/level/thang/edit.coffee index d749eea10..01eb9c1d1 100644 --- a/app/views/editor/level/thang/edit.coffee +++ b/app/views/editor/level/thang/edit.coffee @@ -10,7 +10,7 @@ module.exports = class LevelThangEditView extends View ThangType editor view. ### - id: "editor-level-thang-edit" + id: 'editor-level-thang-edit' template: template events: diff --git a/app/views/editor/level/thangs_tab_view.coffee b/app/views/editor/level/thangs_tab_view.coffee index 8e62c8f5d..8e905654a 100644 --- a/app/views/editor/level/thangs_tab_view.coffee +++ b/app/views/editor/level/thangs_tab_view.coffee @@ -17,15 +17,15 @@ MOVE_SPEED = 13 # Essential component original ids componentOriginals = - "existence.Exists" : "524b4150ff92f1f4f8000024" - "physics.Physical" : "524b75ad7fc0f6d519000001" + 'existence.Exists': '524b4150ff92f1f4f8000024' + 'physics.Physical': '524b75ad7fc0f6d519000001' class ThangTypeSearchCollection extends CocoCollection url: '/db/thang.type?project=original,name,version,slug,kind,components' model: ThangType module.exports = class ThangsTabView extends View - id: "editor-level-thangs-tab-view" + id: 'editor-level-thangs-tab-view' className: 'tab-pane active' template: thangs_template startsLoading: true @@ -166,7 +166,7 @@ module.exports = class ThangsTabView extends View } @surface.playing = false @surface.setWorld @world - @surface.camera.zoomTo({x:262, y:-164}, 1.66, 0) + @surface.camera.zoomTo({x: 262, y: -164}, 1.66, 0) destroy: -> @selectAddThangType null @@ -211,7 +211,7 @@ module.exports = class ThangsTabView extends View @surface.camera.dragDisabled = false return unless @selectedExtantThang and e.thang?.id is @selectedExtantThang?.id pos = @selectedExtantThang.pos - physicalOriginal = componentOriginals["physics.Physical"] + physicalOriginal = componentOriginals['physics.Physical'] path = "id=#{@selectedExtantThang.id}/components/original=#{physicalOriginal}" # TODO: hack physical = @thangsTreema.get path return if not physical or (physical.config.pos.x is pos.x and physical.config.pos.y is pos.y) @@ -229,7 +229,7 @@ module.exports = class ThangsTabView extends View if e.thang and (key.alt or key.meta) # We alt-clicked, so create a clone addThang @selectAddThangType e.thang.spriteName, @selectedExtantThang - else if e.thang and not (@addThangSprite and @addThangType is "Blood Torch Test") # TODO: figure out which Thangs can be placed on other Thangs + else if e.thang and not (@addThangSprite and @addThangType is 'Blood Torch Test') # TODO: figure out which Thangs can be placed on other Thangs # We clicked on a Thang (or its Treema), so select the Thang @selectAddThang null @selectedExtantThangClickTime = new Date() @@ -273,13 +273,13 @@ module.exports = class ThangsTabView extends View selectAddThangType: (type, @cloneSourceThang) -> if _.isString type - type = _.find @supermodel.getModels(ThangType), (m) -> m.get("name") is type + type = _.find @supermodel.getModels(ThangType), (m) -> m.get('name') is type pos = @addThangSprite?.thang.pos # Maintain old sprite's pos if we have it @surface.spriteBoss.removeSprite @addThangSprite if @addThangSprite @addThangType = type if @addThangType thang = @createAddThang() - @addThangSprite = @surface.spriteBoss.addThangToSprites thang, @surface.spriteBoss.spriteLayers["Floating"] + @addThangSprite = @surface.spriteBoss.addThangToSprites thang, @surface.spriteBoss.spriteLayers['Floating'] @addThangSprite.notOfThisWorld = true @addThangSprite.imageObject.alpha = 0.75 @addThangSprite.playSound? 'selected' @@ -290,8 +290,8 @@ module.exports = class ThangsTabView extends View createEssentialComponents: -> [ - {original: componentOriginals["existence.Exists"], majorVersion: 0, config: {}} - {original: componentOriginals["physics.Physical"], majorVersion: 0, config: {pos: {x: 10, y: 10, z: 1}, width: 2, height: 2, depth: 2, shape: "box"}} + {original: componentOriginals['existence.Exists'], majorVersion: 0, config: {}} + {original: componentOriginals['physics.Physical'], majorVersion: 0, config: {pos: {x: 10, y: 10, z: 1}, width: 2, height: 2, depth: 2, shape: 'box'}} ] createAddThang: -> @@ -304,9 +304,9 @@ module.exports = class ThangsTabView extends View for raw in mockThang.components comp = _.find allComponents, {original: raw.original} continue if comp.name in ['Selectable', 'Attackable'] # Don't draw health bars or intercept clicks - componentClass = @world.loadClassFromCode comp.js, comp.name, "component" + componentClass = @world.loadClassFromCode comp.js, comp.name, 'component' components.push [componentClass, raw.config] - thang = new Thang @world, @addThangType.get('name'), "Add Thang Phantom" + thang = new Thang @world, @addThangType.get('name'), 'Add Thang Phantom' thang.addComponents components... thang @@ -356,7 +356,7 @@ module.exports = class ThangsTabView extends View moveSide: => return unless @speed c = @surface.camera - p = {x:c.target.x + @moveLatitude * @speed / c.zoom, y:c.target.y + @moveLongitude * @speed / c.zoom} + p = {x: c.target.x + @moveLatitude * @speed / c.zoom, y: c.target.y + @moveLongitude * @speed / c.zoom} c.zoomTo(p, c.zoom, 0) deleteSelectedExtantThang: (e) => @@ -450,7 +450,6 @@ module.exports = class ThangsTabView extends View $('#add-thangs-column').toggle() @onWindowResize e - class ThangsNode extends TreemaNode.nodeMap.array valueClass: 'treema-array-replacement' getChildren: -> @@ -474,11 +473,11 @@ class ThangNode extends TreemaObjectNode kind = ThangNode.thangKindMap[s] @$el.addClass "treema-#{kind}" s = name - s += " - " + @data.id if @data.id isnt s + s += ' - ' + @data.id if @data.id isnt s if pos s += " (#{Math.round(pos.x)}, #{Math.round(pos.y)})" else - s += " (non-physical)" + s += ' (non-physical)' @buildValueForDisplaySimply valEl, s onEnterPressed: -> diff --git a/app/views/editor/level/treema_nodes.coffee b/app/views/editor/level/treema_nodes.coffee index 01e1362a2..f06654698 100644 --- a/app/views/editor/level/treema_nodes.coffee +++ b/app/views/editor/level/treema_nodes.coffee @@ -62,7 +62,7 @@ class WorldRegionNode extends TreemaNode.nodeMap.object callback: (e) => x = Math.min e.points[0].x, e.points[1].x y = Math.min e.points[0].y, e.points[1].y - @data.pos = {x:x, y:y, z:0} + @data.pos = {x: x, y: y, z: 0} @data.width = Math.abs e.points[0].x - e.points[1].x @data.height = Math.min e.points[0].y - e.points[1].y @refreshDisplay() @@ -70,7 +70,6 @@ class WorldRegionNode extends TreemaNode.nodeMap.object createWorldBounds: -> # not yet written - module.exports.WorldViewportNode = class WorldViewportNode extends TreemaNode.nodeMap.object # selecting ratio'd dimensions in the world, ie the camera in level scripts constructor: (args...) -> @@ -132,15 +131,15 @@ module.exports.WorldBoundsNode = class WorldBoundsNode extends TreemaNode.nodeMa if btn.length then @openMap() else super(arguments...) openMap: -> - bounds = @data or [{x:0, y:0}, {x:100, y: 80}] + bounds = @data or [{x: 0, y: 0}, {x: 100, y: 80}] modal = new WorldSelectModal(world: @settings.world, dataType: 'region', default: bounds, supermodel: @settings.supermodel) modal.callback = @callback @settings.view.openModalView modal callback: (e) => return unless e - @set '/0', { x: shorten(e.points[0].x), y: shorten(e.points[0].y) } - @set '/1', { x: shorten(e.points[1].x), y: shorten(e.points[1].y) } + @set '/0', {x: shorten(e.points[0].x), y: shorten(e.points[0].y)} + @set '/1', {x: shorten(e.points[1].x), y: shorten(e.points[1].y)} module.exports.ThangNode = class ThangNode extends TreemaNode.nodeMap.string buildValueForEditing: (valEl) -> @@ -201,7 +200,7 @@ module.exports.ThangTypeNode = class ThangTypeNode extends TreemaNode.nodeMap.st constructor: (args...) -> super args... @thangType = _.find @settings.supermodel.getModels(ThangType), (m) => m.get('original') is @data if @data - console.log "ThangTypeNode found ThangType", @thangType, "for data", @data + console.log 'ThangTypeNode found ThangType', @thangType, 'for data', @data buildValueForDisplay: (valEl) -> @buildValueForDisplaySimply(valEl, @thangType?.get('name') or 'None') diff --git a/app/views/editor/level/versions_view.coffee b/app/views/editor/level/versions_view.coffee index 09aa5925e..38375ead8 100644 --- a/app/views/editor/level/versions_view.coffee +++ b/app/views/editor/level/versions_view.coffee @@ -1,9 +1,9 @@ VersionsModalView = require 'views/modal/versions_modal' module.exports = class LevelVersionsView extends VersionsModalView - id: "editor-level-versions-view" - url: "/db/level/" - page: "level" + id: 'editor-level-versions-view' + url: '/db/level/' + page: 'level' constructor: (options, @ID) -> - super options, ID, require 'models/Level' \ No newline at end of file + super options, ID, require 'models/Level' diff --git a/app/views/editor/patch_modal.coffee b/app/views/editor/patch_modal.coffee index debd20231..37361e129 100644 --- a/app/views/editor/patch_modal.coffee +++ b/app/views/editor/patch_modal.coffee @@ -4,7 +4,7 @@ DeltaView = require 'views/editor/delta' auth = require 'lib/auth' module.exports = class PatchModal extends ModalView - id: "patch-modal" + id: 'patch-modal' template: template plain: true modalWidthPercent: 60 @@ -23,8 +23,8 @@ module.exports = class PatchModal extends ModalView else @originalSource = new @targetModel.constructor({_id:targetID}) @supermodel.loadModel @originalSource, 'source_document' - - onLoaded: -> + + applyDelta: -> @headModel = null if @targetModel.hasWriteAccess() @headModel = @originalSource.clone(false) @@ -36,6 +36,9 @@ module.exports = class PatchModal extends ModalView @pendingModel.markToRevert true @deltaWorked = @pendingModel.applyDelta(@patch.get('delta')) @pendingModel.loaded = true + + render: -> + @applyDelta() if @supermodel.finished() super() getRenderData: -> @@ -57,6 +60,7 @@ module.exports = class PatchModal extends ModalView acceptPatch: -> delta = @deltaView.getApplicableDelta() @targetModel.applyDelta(delta) + @targetModel.saveBackupNow() @patch.setStatus('accepted') @trigger 'accepted-patch' @hide() diff --git a/app/views/editor/patches_view.coffee b/app/views/editor/patches_view.coffee index a75e1e36d..751ec837c 100644 --- a/app/views/editor/patches_view.coffee +++ b/app/views/editor/patches_view.coffee @@ -51,8 +51,8 @@ module.exports = class PatchesView extends CocoView @render() openPatchModal: (e) -> - console.log "open patch modal" - patch = _.find @patches.models, {id:$(e.target).data('patch-id')} + console.log 'open patch modal' + patch = _.find @patches.models, {id: $(e.target).data('patch-id')} modal = new PatchModal(patch, @model) @openModalView(modal) @listenTo modal, 'accepted-patch', -> @trigger 'accepted-patch' diff --git a/app/views/editor/system/versions_view.coffee b/app/views/editor/system/versions_view.coffee index 562d134ad..6c0fe3e59 100755 --- a/app/views/editor/system/versions_view.coffee +++ b/app/views/editor/system/versions_view.coffee @@ -1,9 +1,9 @@ VersionsModalView = require 'views/modal/versions_modal' module.exports = class SystemVersionsView extends VersionsModalView - id: "editor-system-versions-view" - url: "/db/level.system/" - page: "system" + id: 'editor-system-versions-view' + url: '/db/level.system/' + page: 'system' constructor: (options, @ID) -> - super options, ID, require 'models/LevelSystem' \ No newline at end of file + super options, ID, require 'models/LevelSystem' diff --git a/app/views/editor/thang/colors_tab_view.coffee b/app/views/editor/thang/colors_tab_view.coffee index 00ba6b16c..b4a60e017 100644 --- a/app/views/editor/thang/colors_tab_view.coffee +++ b/app/views/editor/thang/colors_tab_view.coffee @@ -13,7 +13,7 @@ module.exports = class ColorsTabView extends CocoView constructor: (@thangType, options) -> @listenToOnce(@thangType, 'sync', @tryToBuild) # @listenToOnce(@thangType.schema(), 'sync', @tryToBuild) - @colorConfig = { hue: 0, saturation: 0.5, lightness: 0.5 } + @colorConfig = {hue: 0, saturation: 0.5, lightness: 0.5} @spriteBuilder = new SpriteBuilder(@thangType) f = => @offset++ @@ -24,7 +24,7 @@ module.exports = class ColorsTabView extends CocoView destroy: -> clearInterval @interval super() - + onLoaded: -> @render() afterRender: -> super() @@ -36,9 +36,9 @@ module.exports = class ColorsTabView extends CocoView # sliders initSliders: -> - @hueSlider = @initSlider $("#hue-slider", @$el), 0, @makeSliderCallback 'hue' - @saturationSlider = @initSlider $("#saturation-slider", @$el), 50, @makeSliderCallback 'saturation' - @lightnessSlider = @initSlider $("#lightness-slider", @$el), 50, @makeSliderCallback 'lightness' + @hueSlider = @initSlider $('#hue-slider', @$el), 0, @makeSliderCallback 'hue' + @saturationSlider = @initSlider $('#saturation-slider', @$el), 50, @makeSliderCallback 'saturation' + @lightnessSlider = @initSlider $('#lightness-slider', @$el), 50, @makeSliderCallback 'lightness' makeSliderCallback: (property) -> (e, result) => @@ -51,7 +51,7 @@ module.exports = class ColorsTabView extends CocoView canvas = @$el.find('#tinting-display') @stage = new createjs.Stage(canvas[0]) createjs.Ticker.setFPS 20 - createjs.Ticker.addEventListener("tick", @stage) + createjs.Ticker.addEventListener('tick', @stage) @updateMovieClip() updateMovieClip: -> diff --git a/app/views/editor/thang/edit.coffee b/app/views/editor/thang/edit.coffee index 0880fbff4..39fe787ba 100644 --- a/app/views/editor/thang/edit.coffee +++ b/app/views/editor/thang/edit.coffee @@ -14,10 +14,10 @@ SaveVersionModal = require 'views/modal/save_version_modal' ErrorView = require '../../error_view' template = require 'templates/editor/thang/edit' -CENTER = {x:200, y:300} +CENTER = {x: 200, y: 300} module.exports = class ThangTypeEditView extends View - id: "editor-thang-type-edit-view" + id: 'editor-thang-type-edit-view' template: template startsLoading: true resolution: 4 @@ -112,7 +112,7 @@ module.exports = class ThangTypeEditView extends View @refreshAnimation() createjs.Ticker.setFPS(30) - createjs.Ticker.addEventListener("tick", @stage) + createjs.Ticker.addEventListener('tick', @stage) toggleDots: -> @showDots = not @showDots @@ -234,7 +234,7 @@ module.exports = class ThangTypeEditView extends View movieClip.regY = -reg.y @showImageObject(movieClip) - getSpriteOptions: -> { resolutionFactor: @resolution, thang: @mockThang} + getSpriteOptions: -> {resolutionFactor: @resolution, thang: @mockThang} showSprite: (actionName) -> options = @getSpriteOptions() @@ -266,7 +266,7 @@ module.exports = class ThangTypeEditView extends View # sliders initSliders: -> - @rotationSlider = @initSlider $("#rotation-slider", @$el), 50, @updateRotation + @rotationSlider = @initSlider $('#rotation-slider', @$el), 50, @updateRotation @scaleSlider = @initSlider $('#scale-slider', @$el), 29, @updateScale @resolutionSlider = @initSlider $('#resolution-slider', @$el), 39, @updateResolution @healthSlider = @initSlider $('#health-slider', @$el), 100, @updateHealth @@ -401,7 +401,7 @@ module.exports = class ThangTypeEditView extends View @showingSelectedNode = false showVersionHistory: (e) -> - versionHistoryView = new VersionHistoryView thangType:@thangType, @thangTypeID + versionHistoryView = new VersionHistoryView thangType: @thangType, @thangTypeID @openModalView versionHistoryView Backbone.Mediator.publish 'level:view-switched', e @@ -413,12 +413,12 @@ module.exports = class ThangTypeEditView extends View super() imageToPortrait = (img) -> - canvas = document.createElement("canvas") + canvas = document.createElement('canvas') canvas.width = 100 canvas.height = 100 - ctx = canvas.getContext("2d") + ctx = canvas.getContext('2d') scaleX = 100 / img.width scaleY = 100 / img.height ctx.scale scaleX, scaleY ctx.drawImage img, 0, 0 - canvas.toDataURL("image/png") + canvas.toDataURL('image/png') diff --git a/app/views/editor/thang/home.coffee b/app/views/editor/thang/home.coffee index 1f585b2ab..b14f1b9c4 100644 --- a/app/views/editor/thang/home.coffee +++ b/app/views/editor/thang/home.coffee @@ -18,6 +18,6 @@ module.exports = class ThangTypeHomeView extends SearchView onSearchChange: => super() - @$el.find("img").error(-> $(this).hide()) + @$el.find('img').error(-> $(this).hide()) # TODO: do the new thing on click, not just enter diff --git a/app/views/editor/thang/versions_view.coffee b/app/views/editor/thang/versions_view.coffee index 889d9c902..08344ce48 100755 --- a/app/views/editor/thang/versions_view.coffee +++ b/app/views/editor/thang/versions_view.coffee @@ -1,9 +1,9 @@ VersionsModalView = require 'views/modal/versions_modal' module.exports = class ComponentVersionsView extends VersionsModalView - id: "editor-thang-versions-view" - url: "/db/thang.type/" - page: "thang" + id: 'editor-thang-versions-view' + url: '/db/thang.type/' + page: 'thang' constructor: (options, @ID) -> - super options, ID, require 'models/ThangType' \ No newline at end of file + super options, ID, require 'models/ThangType' diff --git a/app/views/editor_view.coffee b/app/views/editor_view.coffee index f07d0af0f..aafe00eb1 100644 --- a/app/views/editor_view.coffee +++ b/app/views/editor_view.coffee @@ -2,5 +2,5 @@ View = require 'views/kinds/RootView' template = require 'templates/editor' module.exports = class EditorView extends View - id: "editor-nav-view" - template: template \ No newline at end of file + id: 'editor-nav-view' + template: template diff --git a/app/views/employers_view.coffee b/app/views/employers_view.coffee index 788a2d584..5b7bd2710 100644 --- a/app/views/employers_view.coffee +++ b/app/views/employers_view.coffee @@ -16,7 +16,7 @@ class UserRemarksCollection extends CocoCollection model: UserRemark module.exports = class EmployersView extends View - id: "employers-view" + id: 'employers-view' template: template events: @@ -33,8 +33,8 @@ module.exports = class EmployersView extends View super options @getCandidates() @setFilterDefaults() - - + + afterRender: -> super() @sortTable() if @candidates.models.length @@ -43,52 +43,52 @@ module.exports = class EmployersView extends View super() _.delay @checkForEmployerSignupHash, 500 #fairly hacky, change this in the future - @originalBackgroundColor = $("body").css 'background-color' - $("body").css 'background-color', '#B4B4B4' - + @originalBackgroundColor = $('body').css 'background-color' + $('body').css 'background-color', '#B4B4B4' + restoreBodyColor: -> - $("body").css 'background-color', @originalBackgroundColor - + $('body').css 'background-color', @originalBackgroundColor + swapFolderIcon: -> - $("#folder-icon").toggleClass("glyphicon-folder-close").toggleClass("glyphicon-folder-open") + $('#folder-icon').toggleClass('glyphicon-folder-close').toggleClass('glyphicon-folder-open') onFilterChanged: -> @resetFilters() that = @ - $("#filters :input").each -> + $('#filters :input').each -> input = $(this) checked = input.prop 'checked' name = input.attr 'name' value = input.val() - if name is "phoneScreenFilter" + if name is 'phoneScreenFilter' value = JSON.parse(input.prop 'value') if checked that.filters[name] = _.union that.filters[name], [value] else that.filters[name] = _.difference that.filters[name], [value] - + for filterName, filterValues of @filters if filterValues.length is 0 @filters[filterName] = @defaultFilters[filterName] - + openSignupModal: -> @openModalView new EmployerSignupView handleSelectAllChange: (e) -> checkedState = e.currentTarget.checked - $("#filters :input").each -> + $('#filters :input').each -> $(this).prop 'checked', checkedState @onFilterChanged() - + resetFilters: -> for filterName, filterValues of @filters @filters[filterName] = [] - + applyFilters: -> candidateList = _.sortBy @candidates.models, (c) -> c.get('jobProfile').updated candidateList = _.filter candidateList, (c) -> c.get('jobProfileApproved') - + filteredCandidates = candidateList for filterName, filterValues of @filters - if filterName is "visa" + if filterName is 'visa' filteredCandidates = _.difference filteredCandidates, _.filter(filteredCandidates, (c) -> fieldValue = c.get('jobProfile').visa return not (_.contains filterValues, fieldValue) @@ -100,15 +100,15 @@ module.exports = class EmployersView extends View return not (_.contains filterValues, fieldValue) ) candidateIDsToShow = _.pluck filteredCandidates, 'id' - $("#candidate-table tr").each -> $(this).hide() + $('#candidate-table tr').each -> $(this).hide() candidateIDsToShow.forEach (id) -> $("[data-candidate-id=#{id}]").show() - $("#results").text(candidateIDsToShow.length + " results") - - + $('#results').text(candidateIDsToShow.length + ' results') + + return filteredCandidates setFilterDefaults: -> - @filters = + @filters = phoneScreenFilter: [true, false] visa: ['Authorized to work in the US', 'Need visa sponsorship'] schoolFilter: ['Top 20 Eng.', 'Other US', 'Other Intl.'] @@ -116,8 +116,8 @@ module.exports = class EmployersView extends View roleFilter: ['Web Developer', 'Software Developer', 'iOS Developer', 'Android Developer', 'Project Manager'] seniorityFilter: ['College Student', 'Recent Grad', 'Junior', 'Senior', 'Management'] @defaultFilters = _.cloneDeep @filters - - + + getRenderData: -> ctx = super() ctx.isEmployer = @isEmployer() @@ -138,7 +138,7 @@ module.exports = class EmployersView extends View isEmployer: -> userPermissions = me.get('permissions') ? [] - _.contains userPermissions, "employer" + _.contains userPermissions, 'employer' getCandidates: -> @candidates = new CandidatesCollection() @@ -151,37 +151,36 @@ module.exports = class EmployersView extends View renderCandidatesAndSetupScrolling: => @render() - $(".nano").nanoScroller() + $('.nano').nanoScroller() #if window.history?.state?.lastViewedCandidateID - # $(".nano").nanoScroller({scrollTo:$("#" + window.history.state.lastViewedCandidateID)}) + # $('.nano').nanoScroller({scrollTo: $('#' + window.history.state.lastViewedCandidateID)}) #else if window.location.hash.length is 25 - # $(".nano").nanoScroller({scrollTo:$(window.location.hash)}) + # $('.nano').nanoScroller({scrollTo: $(window.location.hash)}) checkForEmployerSignupHash: => - if window.location.hash is "#employerSignupLoggingIn" and not ("employer" in me.get("permissions")) - @openModalView application.router.getView("modal/employer_signup","_modal") - window.location.hash = "" + if window.location.hash is '#employerSignupLoggingIn' and not ('employer' in me.get('permissions')) + @openModalView application.router.getView('modal/employer_signup', '_modal') + window.location.hash = '' sortTable: -> # http://mottie.github.io/tablesorter/docs/example-widget-bootstrap-theme.html $.extend $.tablesorter.themes.bootstrap, # these classes are added to the table. To see other table classes available, # look here: http://twitter.github.com/bootstrap/base-css.html#tables - table: "table table-bordered" - caption: "caption" - header: "bootstrap-header" # give the header a gradient background - footerRow: "" - footerCells: "" - icons: "" # add "icon-white" to make them white; this icon class is added to the in the header - sortNone: "bootstrap-icon-unsorted" - sortAsc: "icon-chevron-up" # glyphicon glyphicon-chevron-up" # we are still using v2 icons - sortDesc: "icon-chevron-down" # glyphicon-chevron-down" # we are still using v2 icons - active: "" # applied when column is sorted - hover: "" # use custom css here - bootstrap class may not override it - filterRow: "" # filter row class - even: "" # odd row zebra striping - odd: "" # even row zebra striping - + table: 'table table-bordered' + caption: 'caption' + header: 'bootstrap-header' # give the header a gradient background + footerRow: '' + footerCells: '' + icons: '' # add 'icon-white' to make them white; this icon class is added to the in the header + sortNone: 'bootstrap-icon-unsorted' + sortAsc: 'icon-chevron-up' # glyphicon glyphicon-chevron-up' # we are still using v2 icons + sortDesc: 'icon-chevron-down' # glyphicon-chevron-down' # we are still using v2 icons + active: '' # applied when column is sorted + hover: '' # use custom css here - bootstrap class may not override it + filterRow: '' # filter row class + even: '' # odd row zebra striping + odd: '' # even row zebra striping # e = exact text from cell # n = normalized value returned by the column parser @@ -191,10 +190,10 @@ module.exports = class EmployersView extends View filterSelectExactMatch = (e, n, f, i, $r) -> e is f # call the tablesorter plugin and apply the uitheme widget - @$el.find(".tablesorter").tablesorter - theme: "bootstrap" + @$el.find('.tablesorter').tablesorter + theme: 'bootstrap' widthFixed: true - headerTemplate: "{content} {icon}" + headerTemplate: '{content} {icon}' textSorter: 6: (a, b, direction, column, table) -> days = [] @@ -203,9 +202,9 @@ module.exports = class EmployersView extends View n = 0 unless _.isNumber n n = 1 if /^a/.test s for [duration, factor] in [ - [/second/i, 1 / (86400 * 1000)] - [/minute/i, 1 / 1440] - [/hour/i, 1 / 24] + [/second/i, 1/(86400*1000)] + [/minute/i, 1/1440] + [/hour/i, 1/24] [/week/i, 7] [/month/i, 30.42] [/year/i, 365.2425] @@ -220,16 +219,16 @@ module.exports = class EmployersView extends View sortList: if @isEmployer() or me.isAdmin() then [[6, 0]] else [[0, 1]] # widget code contained in the jquery.tablesorter.widgets.js file # use the zebra stripe widget if you plan on hiding any rows (filter widget) - widgets: ["uitheme", "zebra", "filter"] + widgets: ['uitheme', 'zebra', 'filter'] widgetOptions: # using the default zebra striping class name, so it actually isn't included in the theme variable above # this is ONLY needed for bootstrap theming if you are using the filter widget, because rows are hidden - zebra: ["even", "odd"] + zebra: ['even', 'odd'] # extra css class applied to the table row containing the filters & the inputs within that row - filter_cssFilter: "" + filter_cssFilter: '' - # If there are child rows in the table (rows with class name from "cssChildRow" option) + # If there are child rows in the table (rows with class name from 'cssChildRow' option) # and this option is true and a match is found anywhere in the child row, then it will make that row # visible; default is false filter_childRows: false @@ -242,7 +241,7 @@ module.exports = class EmployersView extends View filter_ignoreCase: true # jQuery selector string of an element used to reset the filters - filter_reset: ".reset" + filter_reset: '.reset' # Use the $.tablesorter.storage utility to save the most recent filters filter_saveFilters: true @@ -252,44 +251,44 @@ module.exports = class EmployersView extends View filter_searchDelay: 150 # Set this option to true to use the filter to find text from the start of the column - # So typing in "a" will find "albert" but not "frank", both have a's; default is false + # So typing in 'a' will find 'albert' but not 'frank', both have a's; default is false filter_startsWith: false filter_functions: 2: - "Full-time": filterSelectExactMatch - "Part-time": filterSelectExactMatch - "Contracting": filterSelectExactMatch - "Remote": filterSelectExactMatch - "Internship": filterSelectExactMatch + 'Full-time': filterSelectExactMatch + 'Part-time': filterSelectExactMatch + 'Contracting': filterSelectExactMatch + 'Remote': filterSelectExactMatch + 'Internship': filterSelectExactMatch 5: - "0-1": (e, n, f, i, $r) -> n <= 1 - "2-5": (e, n, f, i, $r) -> 2 <= n <= 5 - "6+": (e, n, f, i, $r) -> 6 <= n + '0-1': (e, n, f, i, $r) -> n <= 1 + '2-5': (e, n, f, i, $r) -> 2 <= n <= 5 + '6+': (e, n, f, i, $r) -> 6 <= n 6: - "Last day": (e, n, f, i, $r) -> + 'Last day': (e, n, f, i, $r) -> days = parseFloat $($r.find('td')[i]).data('profile-age') days <= 1 - "Last week": (e, n, f, i, $r) -> + 'Last week': (e, n, f, i, $r) -> days = parseFloat $($r.find('td')[i]).data('profile-age') days <= 7 - "Last 4 weeks": (e, n, f, i, $r) -> + 'Last 4 weeks': (e, n, f, i, $r) -> days = parseFloat $($r.find('td')[i]).data('profile-age') days <= 28 8: - "✓": filterSelectExactMatch - "✗": filterSelectExactMatch + '✓': filterSelectExactMatch + '✗': filterSelectExactMatch onCandidateClicked: (e) -> id = $(e.target).closest('tr').data('candidate-id') if id and (@isEmployer() or me.isAdmin()) if window.history oldState = _.cloneDeep window.history.state ? {} - oldState["lastViewedCandidateID"] = id - window.history.replaceState(oldState,"") + oldState['lastViewedCandidateID'] = id + window.history.replaceState(oldState, '') else window.location.hash = id url = "/account/profile/#{id}" - window.open url,"_blank" + window.open url, '_blank' else @openModalView new EmployerSignupView diff --git a/app/views/error_view.coffee b/app/views/error_view.coffee index 03ee44f92..3ed6db5fd 100644 --- a/app/views/error_view.coffee +++ b/app/views/error_view.coffee @@ -2,5 +2,5 @@ View = require 'views/kinds/RootView' template = require 'templates/error' module.exports = class ErrorView extends View - id: "error-view" - template: template \ No newline at end of file + id: 'error-view' + template: template diff --git a/app/views/home_view.coffee b/app/views/home_view.coffee index 7899d7bf4..40eb72e88 100644 --- a/app/views/home_view.coffee +++ b/app/views/home_view.coffee @@ -36,16 +36,16 @@ module.exports = class HomeView extends View @$el.find('.modal').on 'shown.bs.modal', -> $('input:visible:first', @).focus() - # Try to find latest level and set "Play" link to go to that level - lastLevel = me.get("lastLevel") - lastLevel ?= localStorage?["lastLevel"] # Temp, until it's migrated to user property + # Try to find latest level and set 'Play' link to go to that level + lastLevel = me.get('lastLevel') + lastLevel ?= localStorage?['lastLevel'] # Temp, until it's migrated to user property if lastLevel - playLink = @$el.find("#beginner-campaign") + playLink = @$el.find('#beginner-campaign') if playLink[0]? - href = playLink.attr("href").split("/") + href = playLink.attr('href').split('/') href[href.length-1] = lastLevel if href.length isnt 0 - href = href.join("/") - playLink.attr("href", href) + href = href.join('/') + playLink.attr('href', href) codeLanguage = (me.get('aceConfig') ? {}).language or 'javascript' @$el.find(".code-language[data-code-language=#{codeLanguage}]").addClass 'selected-language' diff --git a/app/views/kinds/CocoView.coffee b/app/views/kinds/CocoView.coffee index 22e00f40e..541d02657 100644 --- a/app/views/kinds/CocoView.coffee +++ b/app/views/kinds/CocoView.coffee @@ -103,7 +103,7 @@ module.exports = class CocoView extends Backbone.View context ?= {} context.isProduction = document.location.href.search(/codecombat.com/) isnt -1 context.me = me - context.pathname = document.location.pathname # like "/play/level" + context.pathname = document.location.pathname # like '/play/level' context.fbRef = context.pathname.replace(/[^a-zA-Z0-9+/=\-.:_]/g, '').slice(0, 40) or 'home' context.isMobile = @isMobile() context.isIE = @isIE() @@ -146,7 +146,7 @@ module.exports = class CocoView extends Backbone.View $(e.target).closest('.loading-error-alert').remove() # Modals - + @lastToggleModalCall = 0 toggleModal: (e) -> @@ -205,7 +205,7 @@ module.exports = class CocoView extends Backbone.View showReadOnly: -> return if me.isAdmin() - warning = $.i18n.t 'editor.read_only_warning2', defaultValue: "Note: you can't save any edits here, because you're not logged in." + warning = $.i18n.t 'editor.read_only_warning2', defaultValue: 'Note: you can\'t save any edits here, because you\'re not logged in.' noty text: warning, layout: 'center', type: 'information', killer: true, timeout: 5000 # Loading ModalViews @@ -267,9 +267,9 @@ module.exports = class CocoView extends Backbone.View getQueryVariable: (param, defaultValue) -> CocoView.getQueryVariable(param, defaultValue) @getQueryVariable: (param, defaultValue) -> query = document.location.search.substring 1 - pairs = (pair.split("=") for pair in query.split "&") + pairs = (pair.split('=') for pair in query.split '&') for pair in pairs when pair[0] is param - return {"true": true, "false": false}[pair[1]] ? decodeURIComponent(pair[1]) + return {'true': true, 'false': false}[pair[1]] ? decodeURIComponent(pair[1]) defaultValue getRootView: -> @@ -283,16 +283,16 @@ module.exports = class CocoView extends Backbone.View isIE: -> ua = navigator.userAgent or navigator.vendor or window.opera - return ua.search("MSIE") != -1 + return ua.search('MSIE') != -1 isMac: -> navigator.platform.toUpperCase().indexOf('MAC') isnt -1 initSlider: ($el, startValue, changeCallback) -> - slider = $el.slider({ animate: "fast" }) + slider = $el.slider({animate: 'fast'}) slider.slider('value', startValue) - slider.on('slide',changeCallback) - slider.on('slidechange',changeCallback) + slider.on('slide', changeCallback) + slider.on('slidechange', changeCallback) slider diff --git a/app/views/kinds/ModalView.coffee b/app/views/kinds/ModalView.coffee index a5e3e49ed..ad25b3c09 100644 --- a/app/views/kinds/ModalView.coffee +++ b/app/views/kinds/ModalView.coffee @@ -1,12 +1,12 @@ CocoView = require './CocoView' module.exports = class ModalView extends CocoView - className: "modal fade" + className: 'modal fade' closeButton: true closesOnClickOutside: true modalWidthPercent: null plain: false - + events: 'click a': 'toggleModal' 'click button': 'toggleModal' @@ -17,7 +17,7 @@ module.exports = class ModalView extends CocoView constructor: (options) -> options ?= {} - @className = @className.replace " fade", "" if options.instant + @className = @className.replace ' fade', '' if options.instant @closeButton = options.closeButton if options.closeButton? @modalWidthPercent = options.modalWidthPercent if options.modalWidthPercent super options @@ -51,7 +51,7 @@ module.exports = class ModalView extends CocoView hide: -> @trigger 'hide' - @$el.removeClass('fade').modal "hide" + @$el.removeClass('fade').modal 'hide' onHidden: -> @trigger 'hidden' diff --git a/app/views/kinds/RootView.coffee b/app/views/kinds/RootView.coffee index 899c0aaa7..aac5dc64f 100644 --- a/app/views/kinds/RootView.coffee +++ b/app/views/kinds/RootView.coffee @@ -18,7 +18,7 @@ filterKeyboardEvents = (allowedEvents, func) -> module.exports = class RootView extends CocoView events: - "click #logout-button": "logoutAccount" + 'click #logout-button': 'logoutAccount' 'change .language-dropdown': 'onLanguageChanged' 'click .toggle-fullscreen': 'toggleFullscreen' 'click .auth-button': 'onClickAuthbutton' @@ -29,7 +29,6 @@ module.exports = class RootView extends CocoView subscriptions: 'achievements:new': 'handleNewAchievements' - showNewAchievement: (achievement, earnedAchievement) -> currentLevel = me.level() nextLevel = currentLevel + 1 @@ -115,7 +114,7 @@ module.exports = class RootView extends CocoView afterRender: -> super(arguments...) - @chooseTab(location.hash.replace('#','')) if location.hash + @chooseTab(location.hash.replace('#', '')) if location.hash @buildLanguages() $('body').removeClass('is-playing') @@ -125,10 +124,10 @@ module.exports = class RootView extends CocoView # TODO: automate tabs to put in hashes when they are clicked buildLanguages: -> - $select = @$el.find(".language-dropdown").empty() - if $select.hasClass("fancified") + $select = @$el.find('.language-dropdown').empty() + if $select.hasClass('fancified') $select.parent().find('.options, .trigger').remove() - $select.unwrap().removeClass("fancified") + $select.unwrap().removeClass('fancified') preferred = me.lang() codes = _.keys(locale) genericCodes = _.filter codes, (code) -> @@ -136,17 +135,17 @@ module.exports = class RootView extends CocoView code2 isnt code and code2.split('-')[0] is code) for code, localeInfo of locale when not (code in genericCodes) or code is preferred $select.append( - $("").val(code).text(localeInfo.nativeDescription)) + $('').val(code).text(localeInfo.nativeDescription)) $select.val(preferred).fancySelect().parent().find('.trigger').addClass('header-font') $('body').attr('lang', preferred) onLanguageChanged: -> - newLang = $(".language-dropdown").val() + newLang = $('.language-dropdown').val() $.i18n.setLng(newLang, {}) @saveLanguage(newLang) @render() - unless newLang.split('-')[0] is "en" - @openModalView(application.router.getView("modal/diplomat_suggestion", "_modal")) + unless newLang.split('-')[0] is 'en' + @openModalView(application.router.getView('modal/diplomat_suggestion', '_modal')) saveLanguage: (newLang) -> me.set('preferredLanguage', newLang) @@ -154,9 +153,9 @@ module.exports = class RootView extends CocoView return unless res res.error -> errors = JSON.parse(res.responseText) - console.warn "Error saving language:", errors + console.warn 'Error saving language:', errors res.success (model, response, options) -> - #console.log "Saved language:", newLang + #console.log 'Saved language:', newLang toggleFullscreen: (e) -> # https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode?redirectlocale=en-US&redirectslug=Web/Guide/DOM/Using_full_screen_mode diff --git a/app/views/kinds/SearchView.coffee b/app/views/kinds/SearchView.coffee index 8f7a17420..91b04d4d5 100644 --- a/app/views/kinds/SearchView.coffee +++ b/app/views/kinds/SearchView.coffee @@ -1,7 +1,7 @@ View = require 'views/kinds/RootView' template = require 'templates/kinds/search' -forms = require('lib/forms') -app = require('application') +forms = require 'lib/forms' +app = require 'application' class SearchCollection extends Backbone.Collection initialize: (modelURL, @model, @term, @projection) -> @@ -9,7 +9,7 @@ class SearchCollection extends Backbone.Collection if @projection? and not (@projection == []) @url += projection[0] @url += ',' + projected for projected in projection[1..] - else @url += "true" + else @url += 'true' @url += "&term=#{term}" if @term module.exports = class SearchView extends View @@ -31,7 +31,6 @@ module.exports = class SearchView extends View 'shown.bs.modal #new-model-modal': 'focusOnName' 'hidden.bs.modal #new-model-modal': 'onModalHidden' - constructor: (options) -> @runSearch = _.debounce(@runSearch, 500) super options @@ -46,6 +45,7 @@ module.exports = class SearchView extends View searchInput.focus() runSearch: => + return if @destroyed term = @$el.find('input#search').val() return if @sameSearch(term) @removeOldSearch() @@ -59,7 +59,7 @@ module.exports = class SearchView extends View @collection.fetch() updateHash: (term) -> - newPath = document.location.pathname + (if term then "#" + term else "") + newPath = document.location.pathname + (if term then '#' + term else '') currentPath = document.location.pathname + document.location.hash app.router.navigate(newPath) if newPath isnt currentPath @@ -103,7 +103,7 @@ module.exports = class SearchView extends View onModalHidden: -> # Can only redirect after the modal hidden event has triggered base = document.location.pathname[1..] + '/' - app.router.navigate(base + (@model.get('slug') or @model.id), {trigger:true}) + app.router.navigate(base + (@model.get('slug') or @model.id), {trigger: true}) focusOnName: -> @$el.find('#name').focus() diff --git a/app/views/legal_view.coffee b/app/views/legal_view.coffee index 92aedb97e..09ae6f2c3 100644 --- a/app/views/legal_view.coffee +++ b/app/views/legal_view.coffee @@ -2,5 +2,5 @@ View = require 'views/kinds/RootView' template = require 'templates/legal' module.exports = class LegalView extends View - id: "legal-view" + id: 'legal-view' template: template diff --git a/app/views/modal/auth_modal.coffee b/app/views/modal/auth_modal.coffee index 43a2e23be..81edc7dd4 100644 --- a/app/views/modal/auth_modal.coffee +++ b/app/views/modal/auth_modal.coffee @@ -6,25 +6,25 @@ User = require 'models/User' application = require 'application' module.exports = class AuthModalView extends View - id: "auth-modal" + id: 'auth-modal' template: template mode: 'login' # or 'signup' - + events: # login buttons - "click #switch-to-signup-button": "onSignupInstead" - "click #signup-confirm-age": "checkAge" + 'click #switch-to-signup-button': 'onSignupInstead' + 'click #signup-confirm-age': 'checkAge' 'submit': 'onSubmitForm' # handles both submit buttons subscriptions: 'server-error': 'onServerError' 'logging-in-with-facebook': 'onLoggingInWithFacebook' - + getRenderData: -> c = super() c.showRequiredError = @options.showRequiredError - c.title = {0: "short", 1: "long"}[me.get('testGroupNumber') % 2] - c.descriptionOn = {0: "yes", 1: "no"}[Math.floor(me.get('testGroupNumber')/2) % 2] + c.title = {0: 'short', 1: 'long'}[me.get('testGroupNumber') % 2] + c.descriptionOn = {0: 'yes', 1: 'no'}[Math.floor(me.get('testGroupNumber')/2) % 2] if @mode is 'signup' application.tracker.identify authModalTitle: c.title application.tracker.trackEvent 'Started Signup', authModalTitle: c.title, descriptionOn: c.descriptionOn @@ -35,20 +35,20 @@ module.exports = class AuthModalView extends View afterInsert: -> super() _.delay application.router.renderLoginButtons, 500 - + onSignupInstead: (e) -> @mode = 'signup' @previousFormInputs = forms.formToObject @$el @render() _.delay application.router.renderLoginButtons, 500 - + onSubmitForm: (e) -> e.preventDefault() if @mode is 'login' then @loginAccount() else @createAccount() false checkAge: (e) -> - $("#signup-button", @$el).prop 'disabled', not $(e.target).prop('checked') + $('#signup-button', @$el).prop 'disabled', not $(e.target).prop('checked') loginAccount: -> forms.clearFormAlerts(@$el) @@ -62,8 +62,8 @@ module.exports = class AuthModalView extends View forms.clearFormAlerts(@$el) userObject = forms.formToObject @$el delete userObject.subscribe - delete userObject["confirm-age"] - for key, val of me.attributes when key in ["preferredLanguage", "testGroupNumber", "dateCreated", "wizardColor1", "name", "music", "volume", "emails"] + delete userObject['confirm-age'] + for key, val of me.attributes when key in ['preferredLanguage', 'testGroupNumber', 'dateCreated', 'wizardColor1', 'name', 'music', 'volume', 'emails'] userObject[key] ?= val subscribe = @$el.find('#signup-subscribe').prop('checked') userObject.emails ?= {} @@ -80,4 +80,4 @@ module.exports = class AuthModalView extends View @enableModalInProgress(modal) # TODO: part of forms onServerError: (e) -> # TODO: work error handling into a separate forms system - @disableModalInProgress(@$el) \ No newline at end of file + @disableModalInProgress(@$el) diff --git a/app/views/modal/confirm.coffee b/app/views/modal/confirm.coffee index 18ded9ed6..4749fc913 100644 --- a/app/views/modal/confirm.coffee +++ b/app/views/modal/confirm.coffee @@ -2,7 +2,7 @@ ModalView = require '../kinds/ModalView' template = require 'templates/modal/confirm' module.exports = class ConfirmModal extends ModalView - id: "confirm-modal" + id: 'confirm-modal' template: template closeButton: true closeOnConfirm: true diff --git a/app/views/modal/contact_modal.coffee b/app/views/modal/contact_modal.coffee index 3c4af7a83..0851c9ee9 100644 --- a/app/views/modal/contact_modal.coffee +++ b/app/views/modal/contact_modal.coffee @@ -19,12 +19,12 @@ contactSchema = minLength: 1 module.exports = class ContactView extends View - id: "contact-modal" + id: 'contact-modal' template: template closeButton: true events: - "click #contact-submit-button": "contact" + 'click #contact-submit-button': 'contact' contact: -> forms.clearFormAlerts @$el diff --git a/app/views/modal/diplomat_suggestion_modal.coffee b/app/views/modal/diplomat_suggestion_modal.coffee index bd735f995..48312ad36 100644 --- a/app/views/modal/diplomat_suggestion_modal.coffee +++ b/app/views/modal/diplomat_suggestion_modal.coffee @@ -1,18 +1,18 @@ View = require 'views/kinds/ModalView' template = require 'templates/modal/diplomat_suggestion' -{me} = require('lib/auth') -forms = require('lib/forms') +{me} = require 'lib/auth' +forms = require 'lib/forms' module.exports = class DiplomatSuggestionView extends View - id: "diplomat-suggestion-modal" + id: 'diplomat-suggestion-modal' template: template events: - "click #subscribe-button": "subscribeAsDiplomat" + 'click #subscribe-button': 'subscribeAsDiplomat' subscribeAsDiplomat: -> me.setEmailSubscription 'diplomatNews', true me.patch() - $("#email_translator").prop("checked", 1) + $('#email_translator').prop('checked', 1) @hide() return diff --git a/app/views/modal/employer_signup_modal.coffee b/app/views/modal/employer_signup_modal.coffee index 5aa2a8cde..5355e26c9 100644 --- a/app/views/modal/employer_signup_modal.coffee +++ b/app/views/modal/employer_signup_modal.coffee @@ -1,28 +1,26 @@ View = require 'views/kinds/ModalView' template = require 'templates/modal/employer_signup_modal' -forms = require('lib/forms') +forms = require 'lib/forms' User = require 'models/User' -auth = require('lib/auth') +auth = require 'lib/auth' me = auth.me module.exports = class EmployerSignupView extends View - id: "employer-signup" + id: 'employer-signup' template: template closeButton: true - subscriptions: - "server-error": "onServerError" + 'server-error': 'onServerError' 'linkedin-loaded': 'onLinkedInLoaded' - "created-user-without-reload": 'createdAccount' + 'created-user-without-reload': 'createdAccount' events: - "click #contract-agreement-button": "agreeToContract" - "click #create-account-button": "createAccount" - "click #more-info-button": "submitMoreInfoEmail" - "click .login-link": "setHashToOpenModalAutomatically" - "keydown": "checkForFormSubmissionEnterPress" - + 'click #contract-agreement-button': 'agreeToContract' + 'click #create-account-button': 'createAccount' + 'click #more-info-button': 'submitMoreInfoEmail' + 'click .login-link': 'setHashToOpenModalAutomatically' + 'keydown': 'checkForFormSubmissionEnterPress' constructor: (options) -> super(options) @@ -49,7 +47,7 @@ module.exports = class EmployerSignupView extends View afterInsert: -> super() - linkedInButtonParentElement = document.getElementById("linkedInAuthButton") + linkedInButtonParentElement = document.getElementById('linkedInAuthButton') if linkedInButtonParentElement if @linkedinLoaded @renderLinkedInButton() @@ -59,7 +57,7 @@ module.exports = class EmployerSignupView extends View getRenderData: -> context = super() context.userIsAuthorized = @authorizedWithLinkedIn - context.userHasSignedContract = "employer" in me.get("permissions") + context.userHasSignedContract = 'employer' in me.get('permissions') context.userIsAnonymous = context.me.get('anonymous') context.sentMoreInfoEmail = @sentMoreInfoEmail context @@ -70,7 +68,7 @@ module.exports = class EmployerSignupView extends View $.ajax url: "/db/user/#{me.id}/agreeToEmployerAgreement" data: profileData - type: "POST" + type: 'POST' success: @handleAgreementSuccess error: @handleAgreementFailure @@ -84,19 +82,19 @@ module.exports = class EmployerSignupView extends View checkForFormSubmissionEnterPress: (e) -> if e.which is 13 - if $("#signup-email").val() isnt '' and $("#signup-password").val() isnt '' + if $('#signup-email').val() isnt '' and $('#signup-password').val() isnt '' @createAccount(e) - else if $("#more-info-email").val() isnt '' + else if $('#more-info-email').val() isnt '' @submitMoreInfoEmail e createAccount: (e) => window.tracker?.trackEvent 'Finished Employer Signup' - el = $("#signup-form") + el = $('#signup-form') e.stopPropagation() forms.clearFormAlerts(el) userObject = forms.formToObject el delete userObject.subscribe - for key, val of me.attributes when key in ["preferredLanguage", "testGroupNumber", "dateCreated", "wizardColor1", "name", "music", "volume", "emails"] + for key, val of me.attributes when key in ['preferredLanguage', 'testGroupNumber', 'dateCreated', 'wizardColor1', 'name', 'music', 'volume', 'emails'] userObject[key] ?= val userObject.emails ?= {} userObject.emails.employerNotes = {enabled: true} @@ -106,29 +104,29 @@ module.exports = class EmployerSignupView extends View auth.createUserWithoutReload userObject, null submitMoreInfoEmail: (e) => - emailAddress = $("#more-info-email").val() + emailAddress = $('#more-info-email').val() window.tracker?.trackEvent 'Employer requested more information.' successFunc = => @sentMoreInfoEmail = true @render() errorFunc = => - alert("Something went wrong! Please contact team@codecombat.com for more information and inform them of this error.") + alert('Something went wrong! Please contact team@codecombat.com for more information and inform them of this error.') $.ajax - type: "POST" - url: "/contact" + type: 'POST' + url: '/contact' data: email: emailAddress message: "THIS IS AN AUTOMATED MESSAGE FROM THE EMPLOYER SIGNUP FORM \n Please send me more info about hiring CodeCombat players." success: successFunc error: errorFunc - $.post "/stacklead", email: emailAddress + $.post '/stacklead', email: emailAddress setHashToOpenModalAutomatically: (e) -> - window.location.hash = "employerSignupLoggingIn" + window.location.hash = 'employerSignupLoggingIn' createdAccount: -> @reloadWhenClosed = true - @listenTo me,"sync", => + @listenTo me, 'sync', => @render() IN.parse() me.fetch() diff --git a/app/views/modal/job_profile_contact_modal.coffee b/app/views/modal/job_profile_contact_modal.coffee index d0b39d702..0a933fe48 100644 --- a/app/views/modal/job_profile_contact_modal.coffee +++ b/app/views/modal/job_profile_contact_modal.coffee @@ -27,7 +27,7 @@ contactSchema = minLength: 1 module.exports = class JobProfileContactView extends ContactView - id: "job-profile-contact-modal" + id: 'job-profile-contact-modal' template: template contact: -> diff --git a/app/views/modal/model_modal.coffee b/app/views/modal/model_modal.coffee index 52c18b78d..50b0cdd8a 100644 --- a/app/views/modal/model_modal.coffee +++ b/app/views/modal/model_modal.coffee @@ -55,17 +55,17 @@ module.exports = class ModelModal extends View model = _.find @models, id: container.data('model-id') treema = @modelTreemas[model.id] for key, val of treema.data when not _.isEqual val, model.get key - console.log "Updating", key, "from", model.get(key), "to", val + console.log 'Updating', key, 'from', model.get(key), 'to', val model.set key, val for key, val of model.attributes when treema.get(key) is undefined and not _.string.startsWith key, '_' - console.log "Deleting", key, "which was", val, "but man, that ain't going to work, now is it?" + console.log 'Deleting', key, 'which was', val, 'but man, that ain\'t going to work, now is it?' model.unset key if errors = model.validate() - return console.warn model, "failed validation with errors:", errors + return console.warn model, 'failed validation with errors:', errors return unless res = model.patch() res.error => return if @destroyed - console.error model, "failed to save with error:", res.responseText + console.error model, 'failed to save with error:', res.responseText res.success (model, response, options) => return if @destroyed @hide() diff --git a/app/views/modal/recover_modal.coffee b/app/views/modal/recover_modal.coffee index c77017e82..c65fc1f8a 100644 --- a/app/views/modal/recover_modal.coffee +++ b/app/views/modal/recover_modal.coffee @@ -1,6 +1,6 @@ View = require 'views/kinds/ModalView' template = require 'templates/modal/recover' -forms = require('lib/forms') +forms = require 'lib/forms' {genericFailure} = require 'lib/errors' filterKeyboardEvents = (allowedEvents, func) -> @@ -10,12 +10,12 @@ filterKeyboardEvents = (allowedEvents, func) -> return func(splat...) module.exports = class RecoverModalView extends View - id: "recover-modal" + id: 'recover-modal' template: template - + events: - "click #recover-button": "recoverAccount" - "keydown input": "recoverAccount" + 'click #recover-button': 'recoverAccount' + 'keydown input': 'recoverAccount' subscriptions: 'server-error': 'onServerError' @@ -31,10 +31,10 @@ module.exports = class RecoverModalView extends View forms.clearFormAlerts(@$el) email = (forms.formToObject @$el).email return unless email - res = $.post '/auth/reset', {email:email}, @successfullyRecovered + res = $.post '/auth/reset', {email: email}, @successfullyRecovered res.fail(genericFailure) @enableModalInProgress(@$el) - + successfullyRecovered: => @disableModalInProgress(@$el) @$el.find('.modal-body:visible').text('Recovery email sent.') diff --git a/app/views/modal/save_version_modal.coffee b/app/views/modal/save_version_modal.coffee index 94cdee854..9edaaf859 100644 --- a/app/views/modal/save_version_modal.coffee +++ b/app/views/modal/save_version_modal.coffee @@ -34,10 +34,10 @@ module.exports = class SaveVersionModal extends ModalView changeEl = @$el.find('.changes-stub') if insertDeltaView try - deltaView = new DeltaView({model:@model}) + deltaView = new DeltaView({model: @model}) @insertSubView(deltaView, changeEl) catch e - console.error "Couldn't create delta view:", e + console.error 'Couldn\'t create delta view:', e @$el.find('.commit-message input').attr('placeholder', $.i18n.t('general.commit_msg')) onClickSaveButton: -> @@ -73,7 +73,7 @@ module.exports = class SaveVersionModal extends ModalView onAgreedToCLA: -> @$el.find('#agreement-button').text('Saving').prop('disabled', true) $.ajax({ - url: "/db/user/me/agreeToCLA" + url: '/db/user/me/agreeToCLA' method: 'POST' success: @onAgreeSucceeded error: @onAgreeFailed diff --git a/app/views/modal/signup_modal.coffee b/app/views/modal/signup_modal.coffee index e368034cf..7c34cd6fe 100644 --- a/app/views/modal/signup_modal.coffee +++ b/app/views/modal/signup_modal.coffee @@ -1,4 +1,4 @@ AuthModal = require 'views/modal/auth_modal' module.exports = class SignupModalView extends AuthModal - mode: 'signup' \ No newline at end of file + mode: 'signup' diff --git a/app/views/modal/versions_modal.coffee b/app/views/modal/versions_modal.coffee index 8f2b94fa4..f00cbe29d 100755 --- a/app/views/modal/versions_modal.coffee +++ b/app/views/modal/versions_modal.coffee @@ -7,7 +7,7 @@ nameLoader = require 'lib/NameLoader' CocoCollection = require 'collections/CocoCollection' class VersionsViewCollection extends CocoCollection - url: "" + url: '' model: null initialize: (@url, @levelID, @model) -> @@ -22,10 +22,10 @@ module.exports = class VersionsModalView extends ModalView modalWidthPercent: 80 # needs to be overwritten by child - id: "" - url: "" - page: "" - + id: '' + url: '' + page: '' + events: 'change input.select': 'onSelectionChanged' @@ -50,11 +50,11 @@ module.exports = class VersionsModalView extends ModalView deltaEl = @$el.find '.delta-view' @removeSubView(@deltaView) if @deltaView @deltaView = null - if rows.length isnt 2 then return - - laterVersion = new @model(_id:$(rows[0]).val()) - earlierVersion = new @model(_id:$(rows[1]).val()) - @deltaView = new DeltaView({model:earlierVersion, comparisonModel:laterVersion, skipPaths:PatchModal.DOC_SKIP_PATHS}) + if rows.length isnt 2 then return + + laterVersion = new @model(_id: $(rows[0]).val()) + earlierVersion = new @model(_id: $(rows[1]).val()) + @deltaView = new DeltaView({model: earlierVersion, comparisonModel: laterVersion, skipPaths: PatchModal.DOC_SKIP_PATHS}) @insertSubView(@deltaView, deltaEl) getRenderData: (context={}) -> diff --git a/app/views/modal/wizard_settings_modal.coffee b/app/views/modal/wizard_settings_modal.coffee index c099a4fba..1f7d5bc8f 100644 --- a/app/views/modal/wizard_settings_modal.coffee +++ b/app/views/modal/wizard_settings_modal.coffee @@ -3,10 +3,10 @@ template = require 'templates/modal/wizard_settings' WizardSprite = require 'lib/surface/WizardSprite' ThangType = require 'models/ThangType' {me} = require 'lib/auth' -forms = require('lib/forms') +forms = require 'lib/forms' module.exports = class WizardSettingsModal extends View - id: "wizard-settings-modal" + id: 'wizard-settings-modal' template: template closesOnClickOutside: false @@ -29,7 +29,7 @@ module.exports = class WizardSettingsModal extends View name = $('#wizard-settings-name').val() success = (id) => forms.clearFormAlerts(@$el) - forms.applyErrorsToForm(@$el, {property:'name', message:'is already taken'}) if id and id isnt me.id + forms.applyErrorsToForm(@$el, {property: 'name', message: 'is already taken'}) if id and id isnt me.id $.ajax("/db/user/#{name}/nameToID", {success: success}) onWizardSettingsDone: -> @@ -47,7 +47,7 @@ module.exports = class WizardSettingsModal extends View res.error => errors = JSON.parse(res.responseText) - console.warn "Got errors saving user:", errors + console.warn 'Got errors saving user:', errors forms.applyErrorsToForm(@$el, errors) @disableModalInProgress(@$el) diff --git a/app/views/multiplayer_view.coffee b/app/views/multiplayer_view.coffee index cf0fdd64b..acfaefe15 100644 --- a/app/views/multiplayer_view.coffee +++ b/app/views/multiplayer_view.coffee @@ -9,7 +9,7 @@ module.exports = class MultiplayerLaunchView extends HomeView class MultiplayerLaunchModal extends ModalView template: modalTemplate - id: "multiplayer-launch-modal" + id: 'multiplayer-launch-modal' hide: -> $('#multiplayer-video').attr('src','') @@ -17,4 +17,4 @@ class MultiplayerLaunchModal extends ModalView onHidden: -> $('#multiplayer-video').attr('src','') - super() \ No newline at end of file + super() diff --git a/app/views/not_found.coffee b/app/views/not_found.coffee index 6febc5ef0..95e94921b 100644 --- a/app/views/not_found.coffee +++ b/app/views/not_found.coffee @@ -2,5 +2,5 @@ View = require 'views/kinds/RootView' template = require 'templates/not_found' module.exports = class NotFoundView extends View - id: "not-found-view" + id: 'not-found-view' template: template diff --git a/app/views/play/common/ladder_submission_view.coffee b/app/views/play/common/ladder_submission_view.coffee index 42196bb96..4cf4b7e29 100644 --- a/app/views/play/common/ladder_submission_view.coffee +++ b/app/views/play/common/ladder_submission_view.coffee @@ -2,7 +2,7 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/common/ladder_submission' module.exports = class LadderSubmissionView extends CocoView - className: "ladder-submission-view" + className: 'ladder-submission-view' template: template events: @@ -79,21 +79,21 @@ module.exports = class LadderSubmissionView extends CocoView for thang, spells of submittedCode transpiledCode[thang] = {} for spellID, spell of spells - unless _.contains(@session.get('teamSpells')[@session.get('team')], thang + "/" + spellID) then continue + unless _.contains(@session.get('teamSpells')[@session.get('team')], thang + '/' + spellID) then continue #DRY this aetherOptions = problems: {} language: language functionName: spellID functionParameters: [] - yieldConditionally: spellID is "plan" + yieldConditionally: spellID is 'plan' globals: ['Vector', '_'] protectAPI: true includeFlow: false executionLimit: 1 * 1000 * 1000 - if spellID is "hear" then aetherOptions.functionParameters = ["speaker","message","data"] - if spellID is "makeBid" then aetherOptions.functionParameters = ["tileGroupLetter"] - if spellID is "findCentroids" then aetherOptions.functionParameters = ["centroids"] + if spellID is 'hear' then aetherOptions.functionParameters = ['speaker', 'message', 'data'] + if spellID is 'makeBid' then aetherOptions.functionParameters = ['tileGroupLetter'] + if spellID is 'findCentroids' then aetherOptions.functionParameters = ['centroids'] aether = new Aether aetherOptions transpiledCode[thang][spellID] = aether.transpile spell diff --git a/app/views/play/ladder/ladder_tab.coffee b/app/views/play/ladder/ladder_tab.coffee index 416cdaf2d..d0a7ff2a5 100644 --- a/app/views/play/ladder/ladder_tab.coffee +++ b/app/views/play/ladder/ladder_tab.coffee @@ -31,16 +31,16 @@ module.exports = class LadderTabView extends CocoView @teams = teamDataFromLevel @level @leaderboards = {} @refreshLadder() - @socialNetworkRes = @supermodel.addSomethingResource("social_network_apis", 0) + @socialNetworkRes = @supermodel.addSomethingResource('social_network_apis', 0) @checkFriends() checkFriends: -> return if @checked or (not window.FB) or (not window.gapi) @checked = true - # @addSomethingToLoad("facebook_status") + # @addSomethingToLoad('facebook_status') - @fbStatusRes = @supermodel.addSomethingResource("facebook_status", 0) + @fbStatusRes = @supermodel.addSomethingResource('facebook_status', 0) @fbStatusRes.load() FB.getLoginStatus (response) => @@ -65,9 +65,9 @@ module.exports = class LadderTabView extends CocoView onConnectedWithFacebook: -> location.reload() if @connecting loadFacebookFriends: -> - # @addSomethingToLoad("facebook_friends") + # @addSomethingToLoad('facebook_friends') - @fbFriendRes = @supermodel.addSomethingResource("facebook_friends", 0) + @fbFriendRes = @supermodel.addSomethingResource('facebook_friends', 0) @fbFriendRes.load() FB.api '/me/friends', @onFacebookFriendsLoaded @@ -97,6 +97,7 @@ module.exports = class LadderTabView extends CocoView friend.otherTeam = if friend.team is 'humans' then 'ogres' else 'humans' friend.imageSource = "http://graph.facebook.com/#{friend.facebookID}/picture" @facebookFriendSessions = result + @render() # because the ladder tab renders before waiting for fb to finish # GOOGLE PLUS @@ -109,8 +110,8 @@ module.exports = class LadderTabView extends CocoView gplusSessionStateLoaded: -> if application.gplusHandler.loggedIn - #@addSomethingToLoad("gplus_friends") - @gpFriendRes = @supermodel.addSomethingResource("gplus_friends", 0) + #@addSomethingToLoad('gplus_friends') + @gpFriendRes = @supermodel.addSomethingResource('gplus_friends', 0) @gpFriendRes.load() application.gplusHandler.loadFriends @gplusFriendsLoaded @@ -139,6 +140,7 @@ module.exports = class LadderTabView extends CocoView friend.otherTeam = if friend.team is 'humans' then 'ogres' else 'humans' friend.imageSource = friendsMap[friend.gplusID].image.url @gplusFriendSessions = result + @render() # because the ladder tab renders before waiting for gplus to finish # LADDER LOADING @@ -180,7 +182,7 @@ module.exports = class LadderTabView extends CocoView generateHistogram: (histogramElement, histogramData, teamName) -> #renders twice, hack fix - if $("#"+histogramElement.attr("id")).has("svg").length then return + if $('#' + histogramElement.attr('id')).has('svg').length then return histogramData = histogramData.map (d) -> d*100 margin = @@ -192,72 +194,71 @@ module.exports = class LadderTabView extends CocoView width = 300 - margin.left - margin.right height = 125 - margin.top - margin.bottom - formatCount = d3.format(",.0") + formatCount = d3.format(',.0') - x = d3.scale.linear().domain([-3000,6000]).range([0,width]) + x = d3.scale.linear().domain([-3000, 6000]).range([0, width]) data = d3.layout.histogram().bins(x.ticks(20))(histogramData) - y = d3.scale.linear().domain([0,d3.max(data, (d) -> d.y)]).range([height,10]) + y = d3.scale.linear().domain([0, d3.max(data, (d) -> d.y)]).range([height, 10]) #create the x axis - xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(5).outerTickSize(0) + xAxis = d3.svg.axis().scale(x).orient('bottom').ticks(5).outerTickSize(0) - svg = d3.select("#"+histogramElement.attr("id")).append("svg") - .attr("width", width + margin.left + margin.right) - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("transform","translate(#{margin.left},#{margin.top})") - barClass = "bar" - if teamName.toLowerCase() is "ogres" then barClass = "ogres-bar" - if teamName.toLowerCase() is "humans" then barClass = "humans-bar" + svg = d3.select('#' + histogramElement.attr('id')).append('svg') + .attr('width', width + margin.left + margin.right) + .attr('height', height + margin.top + margin.bottom) + .append('g') + .attr('transform', "translate(#{margin.left}, #{margin.top})") + barClass = 'bar' + if teamName.toLowerCase() is 'ogres' then barClass = 'ogres-bar' + if teamName.toLowerCase() is 'humans' then barClass = 'humans-bar' - bar = svg.selectAll(".bar") + bar = svg.selectAll('.bar') .data(data) - .enter().append("g") - .attr("class",barClass) - .attr("transform", (d) -> "translate(#{x(d.x)},#{y(d.y)})") + .enter().append('g') + .attr('class', barClass) + .attr('transform', (d) -> "translate(#{x(d.x)}, #{y(d.y)})") - bar.append("rect") - .attr("x",1) - .attr("width",width/20) - .attr("height", (d) -> height - y(d.y)) + bar.append('rect') + .attr('x', 1) + .attr('width', width/20) + .attr('height', (d) -> height - y(d.y)) if @leaderboards[teamName].session? playerScore = @leaderboards[teamName].session.get('totalScore') * 100 - scorebar = svg.selectAll(".specialbar") + scorebar = svg.selectAll('.specialbar') .data([playerScore]) - .enter().append("g") - .attr("class","specialbar") - .attr("transform", "translate(#{x(playerScore)},#{y(9001)})") + .enter().append('g') + .attr('class', 'specialbar') + .attr('transform', "translate(#{x(playerScore)}, #{y(9001)})") - scorebar.append("rect") - .attr("x",1) - .attr("width",3) - .attr("height",height - y(9001)) - rankClass = "rank-text" - if teamName.toLowerCase() is "ogres" then rankClass = "rank-text ogres-rank-text" - if teamName.toLowerCase() is "humans" then rankClass = "rank-text humans-rank-text" + scorebar.append('rect') + .attr('x', 1) + .attr('width', 3) + .attr('height', height - y(9001)) + rankClass = 'rank-text' + if teamName.toLowerCase() is 'ogres' then rankClass = 'rank-text ogres-rank-text' + if teamName.toLowerCase() is 'humans' then rankClass = 'rank-text humans-rank-text' message = "#{histogramData.length} players" if @leaderboards[teamName].session? if @leaderboards[teamName].myRank <= histogramData.length message="##{@leaderboards[teamName].myRank} of #{histogramData.length}" else - message="Rank your session!" - svg.append("g") - .append("text") - .attr("class",rankClass) - .attr("y",0) - .attr("text-anchor","end") - .attr("x",width) + message='Rank your session!' + svg.append('g') + .append('text') + .attr('class', rankClass) + .attr('y', 0) + .attr('text-anchor', 'end') + .attr('x', width) .text(message) #Translate the x-axis up - svg.append("g") - .attr("class", "x axis") - .attr("transform","translate(0," + height + ")") + svg.append('g') + .attr('class', 'x axis') + .attr('transform', 'translate(0, ' + height + ')') .call(xAxis) - consolidateFriends: -> allFriendSessions = (@facebookFriendSessions or []).concat(@gplusFriendSessions or []) sessions = _.uniq allFriendSessions, false, (session) -> session._id @@ -288,15 +289,15 @@ module.exports.LeaderboardData = LeaderboardData = class LeaderboardData extends fetch: -> console.warn 'Already have top players on', @ if @topPlayers - @topPlayers = new LeaderboardCollection(@level, {order:-1, scoreOffset: HIGHEST_SCORE, team: @team, limit: @limit}) + @topPlayers = new LeaderboardCollection(@level, {order: -1, scoreOffset: HIGHEST_SCORE, team: @team, limit: @limit}) promises = [] promises.push @topPlayers.fetch() if @session score = @session.get('totalScore') or 10 - @playersAbove = new LeaderboardCollection(@level, {order:1, scoreOffset: score, limit: 4, team: @team}) + @playersAbove = new LeaderboardCollection(@level, {order: 1, scoreOffset: score, limit: 4, team: @team}) promises.push @playersAbove.fetch() - @playersBelow = new LeaderboardCollection(@level, {order:-1, scoreOffset: score, limit: 4, team: @team}) + @playersBelow = new LeaderboardCollection(@level, {order: -1, scoreOffset: score, limit: 4, team: @team}) promises.push @playersBelow.fetch() level = "#{@level.get('original')}.#{@level.get('version').major}" success = (@myRank) => diff --git a/app/views/play/ladder/ladder_view.coffee b/app/views/play/ladder/ladder_view.coffee index 414d1dad4..2fef77845 100644 --- a/app/views/play/ladder/ladder_view.coffee +++ b/app/views/play/ladder/ladder_view.coffee @@ -12,7 +12,6 @@ SimulateTabView = require './simulate_tab' LadderPlayModal = require './play_modal' CocoClass = require 'lib/CocoClass' - HIGHEST_SCORE = 1000000 class LevelSessionsCollection extends CocoCollection @@ -36,7 +35,7 @@ module.exports = class LadderView extends RootView constructor: (options, @levelID) -> super(options) - @level = @supermodel.loadModel(new Level(_id:@levelID), 'level').model + @level = @supermodel.loadModel(new Level(_id: @levelID), 'level').model @sessions = @supermodel.loadCollection(new LevelSessionsCollection(levelID), 'your_sessions').model @teams = [] @@ -71,7 +70,7 @@ module.exports = class LadderView extends RootView fetchSessionsAndRefreshViews: -> return if @destroyed or application.userIsIdle or (new Date() - 2000 < @lastRefreshTime) or not @supermodel.finished() - @sessions.fetch({"success": @refreshViews}) + @sessions.fetch({'success': @refreshViews}) refreshViews: => return if @destroyed or application.userIsIdle @@ -94,7 +93,7 @@ module.exports = class LadderView extends RootView showApologeticSignupModal: -> SignupModal = require 'views/modal/auth_modal' - @openModalView(new SignupModal({showRequiredError:true})) + @openModalView(new SignupModal({showRequiredError: true})) onClickedLink: (e) -> link = $(e.target).closest('a').attr('href') diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee index 3dfe87cbd..458b3c441 100644 --- a/app/views/play/ladder/my_matches_tab.coffee +++ b/app/views/play/ladder/my_matches_tab.coffee @@ -27,7 +27,7 @@ module.exports = class MyMatchesTabView extends CocoView for match in (session.get('matches') or []) id = match.opponents[0].userID unless id - console.error "Found bad opponent ID in malformed match:", match, "from session", session + console.error 'Found bad opponent ID in malformed match:', match, 'from session', session continue ids.push id unless @nameMap[id] @@ -38,7 +38,7 @@ module.exports = class MyMatchesTabView extends CocoView for session in @sessions.models for match in session.get('matches') or [] opponent = match.opponents[0] - @nameMap[opponent.userID] ?= nameMap[opponent.userID]?.name ? "" + @nameMap[opponent.userID] ?= nameMap[opponent.userID]?.name ? '' @finishRendering() $.ajax('/db/user/-/names', { @@ -112,7 +112,7 @@ module.exports = class MyMatchesTabView extends CocoView @$el.find('tr.fresh').removeClass('fresh', 5000) - generateScoreLineChart: (wrapperID, scoreHistory,teamName) => + generateScoreLineChart: (wrapperID, scoreHistory, teamName) => margin = top: 20 right: 20 @@ -121,20 +121,20 @@ module.exports = class MyMatchesTabView extends CocoView width = 450 - margin.left - margin.right height = 125 - x = d3.time.scale().range([0,width]) - y = d3.scale.linear().range([height,0]) + x = d3.time.scale().range([0, width]) + y = d3.scale.linear().range([height, 0]) - xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(4).outerTickSize(0) - yAxis = d3.svg.axis().scale(y).orient("left").ticks(4).outerTickSize(0) + xAxis = d3.svg.axis().scale(x).orient('bottom').ticks(4).outerTickSize(0) + yAxis = d3.svg.axis().scale(y).orient('left').ticks(4).outerTickSize(0) line = d3.svg.line().x(((d) -> x(d.date))).y((d) -> y(d.close)) - selector = "#" + wrapperID + selector = '#' + wrapperID - svg = d3.select(selector).append("svg") - .attr("width", width + margin.left + margin.right) - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("transform","translate(#{margin.left},#{margin.top})") + svg = d3.select(selector).append('svg') + .attr('width', width + margin.left + margin.right) + .attr('height', height + margin.top + margin.bottom) + .append('g') + .attr('transform', "translate(#{margin.left}, #{margin.top})") time = 0 data = scoreHistory.map (d) -> time +=1 @@ -146,19 +146,19 @@ module.exports = class MyMatchesTabView extends CocoView x.domain(d3.extent(data, (d) -> d.date)) y.domain(d3.extent(data, (d) -> d.close)) - svg.append("g") - .attr("class", "y axis") + svg.append('g') + .attr('class', 'y axis') .call(yAxis) - .append("text") - .attr("transform", "rotate(-90)") - .attr("y",4) - .attr("dy", ".75em") - .style("text-anchor","end") - .text("Score") - lineClass = "line" - if teamName.toLowerCase() is "ogres" then lineClass = "ogres-line" - if teamName.toLowerCase() is "humans" then lineClass = "humans-line" - svg.append("path") + .append('text') + .attr('transform', 'rotate(-90)') + .attr('y', 4) + .attr('dy', '.75em') + .style('text-anchor', 'end') + .text('Score') + lineClass = 'line' + if teamName.toLowerCase() is 'ogres' then lineClass = 'ogres-line' + if teamName.toLowerCase() is 'humans' then lineClass = 'humans-line' + svg.append('path') .datum(data) - .attr("class",lineClass) - .attr("d",line) + .attr('class', lineClass) + .attr('d', line) diff --git a/app/views/play/ladder/play_modal.coffee b/app/views/play/ladder/play_modal.coffee index 7cfd850b8..e54e79a18 100644 --- a/app/views/play/ladder/play_modal.coffee +++ b/app/views/play/ladder/play_modal.coffee @@ -6,7 +6,7 @@ LeaderboardCollection = require 'collections/LeaderboardCollection' {teamDataFromLevel} = require './utils' module.exports = class LadderPlayModal extends View - id: "ladder-play-modal" + id: 'ladder-play-modal' template: template closeButton: true startsLoading: true @@ -115,7 +115,7 @@ module.exports = class LadderPlayModal extends View success = => cb true failure = => cb false $.ajax - type: "GET" + type: 'GET' url: "/db/level/#{tutorialLevelID}/exists" success: success error: failure @@ -166,18 +166,17 @@ module.exports = class LadderPlayModal extends View opponentID: opponent.userID } - class ChallengersData constructor: (@level, @team, @otherTeam, @session) -> _.extend @, Backbone.Events score = @session?.get('totalScore') or 25 - @easyPlayer = new LeaderboardCollection(@level, {order:1, scoreOffset: score - 5, limit: 1, team: @otherTeam}) + @easyPlayer = new LeaderboardCollection(@level, {order: 1, scoreOffset: score - 5, limit: 1, team: @otherTeam}) @easyPlayer.fetch() @listenToOnce(@easyPlayer, 'sync', @challengerLoaded) - @mediumPlayer = new LeaderboardCollection(@level, {order:1, scoreOffset: score, limit: 1, team: @otherTeam}) + @mediumPlayer = new LeaderboardCollection(@level, {order: 1, scoreOffset: score, limit: 1, team: @otherTeam}) @mediumPlayer.fetch() @listenToOnce(@mediumPlayer, 'sync', @challengerLoaded) - @hardPlayer = new LeaderboardCollection(@level, {order:-1, scoreOffset: score + 5, limit: 1, team: @otherTeam}) + @hardPlayer = new LeaderboardCollection(@level, {order: -1, scoreOffset: score + 5, limit: 1, team: @otherTeam}) @hardPlayer.fetch() @listenToOnce(@hardPlayer, 'sync', @challengerLoaded) diff --git a/app/views/play/ladder/simulate_tab.coffee b/app/views/play/ladder/simulate_tab.coffee index e73a4807a..ddb28030c 100644 --- a/app/views/play/ladder/simulate_tab.coffee +++ b/app/views/play/ladder/simulate_tab.coffee @@ -40,15 +40,15 @@ module.exports = class SimulateTabView extends CocoView onSimulateButtonClick: (e) -> application.tracker?.trackEvent 'Simulate Button Click', {} - $("#simulate-button").prop "disabled", true - $("#simulate-button").text "Simulating..." + $('#simulate-button').prop 'disabled', true + $('#simulate-button').text 'Simulating...' @simulator.fetchAndSimulateTask() refresh: -> success = (numberOfGamesInQueue) -> - $("#games-in-queue").text numberOfGamesInQueue - $.ajax "/queue/messagesInQueueCount", {success} + $('#games-in-queue').text numberOfGamesInQueue + $.ajax '/queue/messagesInQueueCount', {success} updateSimulationStatus: (simulationStatus, sessions) -> @simulationStatus = simulationStatus @@ -56,15 +56,15 @@ module.exports = class SimulateTabView extends CocoView if sessions? #TODO: Fetch names from Redis, the creatorName is denormalized creatorNames = (session.creatorName for session in sessions) - @simulationStatus = "Simulating game between " + @simulationStatus = 'Simulating game between ' for index in [0...creatorNames.length] unless creatorNames[index] - creatorNames[index] = "Anonymous" - @simulationStatus += (if index != 0 then " and " else "") + creatorNames[index] - @simulationStatus += "..." + creatorNames[index] = 'Anonymous' + @simulationStatus += (if index != 0 then ' and ' else '') + creatorNames[index] + @simulationStatus += '...' catch e console.log "There was a problem with the named simulation status: #{e}" - $("#simulation-status-text").text @simulationStatus + $('#simulation-status-text').text @simulationStatus resimulateAllSessions: -> postData = @@ -93,17 +93,17 @@ class SimulatorsLeaderboardData extends CocoClass super() fetch: -> - @topSimulators = new SimulatorsLeaderboardCollection({order:-1, scoreOffset: -1, limit: 20}) + @topSimulators = new SimulatorsLeaderboardCollection({order: -1, scoreOffset: -1, limit: 20}) promises = [] promises.push @topSimulators.fetch() unless @me.get('anonymous') score = @me.get('simulatedBy') or 0 queueSuccess = (@numberOfGamesInQueue) => - promises.push $.ajax "/queue/messagesInQueueCount", {success: queueSuccess} - @playersAbove = new SimulatorsLeaderboardCollection({order:1, scoreOffset: score, limit: 4}) + promises.push $.ajax '/queue/messagesInQueueCount', {success: queueSuccess} + @playersAbove = new SimulatorsLeaderboardCollection({order: 1, scoreOffset: score, limit: 4}) promises.push @playersAbove.fetch() if score - @playersBelow = new SimulatorsLeaderboardCollection({order:-1, scoreOffset: score, limit: 4}) + @playersBelow = new SimulatorsLeaderboardCollection({order: -1, scoreOffset: score, limit: 4}) promises.push @playersBelow.fetch() success = (@myRank) => diff --git a/app/views/play/ladder/tournament_results.coffee b/app/views/play/ladder/tournament_results.coffee index fc52d8a9f..3cbe60305 100644 --- a/app/views/play/ladder/tournament_results.coffee +++ b/app/views/play/ladder/tournament_results.coffee @@ -1,552 +1,552 @@ module.exports = results = greed: {} results.greed.humans = [ - {team: "humans", rank: 1, sessionID: "5381e3537585483905a829c1", name: "Wizard Dude", playtime: 63184, wins: 363, losses: 0, score: 363} - {team: "humans", rank: 2, sessionID: "537cf76184c54c6e05c05415", name: "Vettax", playtime: 96757, wins: 365, losses: 9, score: 356} - {team: "humans", rank: 3, sessionID: "53836824c85c223a05f4a1dd", name: "HighSea", playtime: 98996, wins: 354, losses: 7, score: 347} - {team: "humans", rank: 4, sessionID: "537c5cf614aaabe80c69fc8d", name: "BubbleDragon", playtime: 136876, wins: 352, losses: 12, score: 340} - {team: "humans", rank: 5, sessionID: "537bad0cb0d477e005347fb5", name: "Bakanio", playtime: 103933, wins: 348, losses: 11, score: 337} - {team: "humans", rank: 6, sessionID: "537cbf86264b3a7d12eb9d55", name: "zero_degrees", playtime: 4236, wins: 346, losses: 17, score: 329} - {team: "humans", rank: 7, sessionID: "538915d2d06c503805fe40d2", name: "Transistor", playtime: 742, wins: 347, losses: 19, score: 328} - {team: "humans", rank: 8, sessionID: "537bbc56831db4ca0526ced3", name: "Chrc", playtime: 2105, wins: 339, losses: 15, score: 324} - {team: "humans", rank: 9, sessionID: "5381d7f87585483905a825fc", name: "nemoyatpeace", playtime: 121202, wins: 344, losses: 20, score: 324} - {team: "humans", rank: 10, sessionID: "53928ff24ca25c6205e290c0", name: "Catalina", playtime: 239, wins: 342, losses: 27, score: 315} - {team: "humans", rank: 11, sessionID: "5383f8162757353805a97454", name: "Zzadded", playtime: 53485, wins: 334, losses: 28, score: 306} - {team: "humans", rank: 12, sessionID: "537d047084c54c6e05c05ab9", name: "Moojo", playtime: 83687, wins: 331, losses: 27, score: 304} - {team: "humans", rank: 13, sessionID: "537bab02f5b6a9d405ec5107", name: "Pentiado", playtime: 70424, wins: 336, losses: 33, score: 303} - {team: "humans", rank: 14, sessionID: "537d11947e1e10b705bbc4a6", name: "Banadux", playtime: 141292, wins: 333, losses: 32, score: 301} - {team: "humans", rank: 15, sessionID: "538181fd7585483905a801e1", name: "chadnickbok", playtime: 922, wins: 334, losses: 33, score: 301} - {team: "humans", rank: 16, sessionID: "537bc4990de0a02c07e8799a", name: "Mepath", playtime: 94421, wins: 315, losses: 28, score: 287} - {team: "humans", rank: 17, sessionID: "53826025c85c223a05f42c5c", name: "Frederick the Great", playtime: 24696, wins: 325, losses: 42, score: 283} - {team: "humans", rank: 18, sessionID: "5387d070b924da39051331a5", name: "NoMan", playtime: 279296, wins: 320, losses: 46, score: 274} - {team: "humans", rank: 19, sessionID: "535e50c1ba35914a07a308c9", name: "Patogeno", playtime: 69601, wins: 318, losses: 44, score: 274} - {team: "humans", rank: 20, sessionID: "537b9b023803a287057583dd", name: "avv", playtime: 85418, wins: 316, losses: 50, score: 266} - {team: "humans", rank: 21, sessionID: "537c89d814aaabe80c6a1139", name: "Foosvald", playtime: 3197, wins: 307, losses: 41, score: 266} - {team: "humans", rank: 22, sessionID: "538350c778171d3d057eb1e4", name: "Ticaj", playtime: 29249, wins: 316, losses: 52, score: 264} - {team: "humans", rank: 23, sessionID: "537b7d9a5bc02238050d1450", name: "DrMonky", playtime: 14815, wins: 315, losses: 55, score: 260} - {team: "humans", rank: 24, sessionID: "537c7d8526529de30cca4310", name: "imkat", playtime: 14870, wins: 292, losses: 38, score: 254} - {team: "humans", rank: 25, sessionID: "5392283b2446a44105387cbb", name: "AKA", playtime: 134724, wins: 312, losses: 58, score: 254} - {team: "humans", rank: 26, sessionID: "537b7ff9e91b4d3b05525db2", name: "UltraNagog", playtime: 113091, wins: 296, losses: 46, score: 250} - {team: "humans", rank: 27, sessionID: "537c1b0e0ff88b2c06288354", name: "Master J", playtime: 32859, wins: 305, losses: 57, score: 248} - {team: "humans", rank: 28, sessionID: "537c551814aaabe80c69f8e9", name: "texastoast", playtime: 75930, wins: 300, losses: 54, score: 246} - {team: "humans", rank: 29, sessionID: "537b9f2551e98aa705b60500", name: "Otsix", playtime: 2270, wins: 302, losses: 58, score: 244} - {team: "humans", rank: 30, sessionID: "537bb4b88698e13805226bb9", name: "asselinpaul", playtime: 22992, wins: 306, losses: 64, score: 242} - {team: "humans", rank: 31, sessionID: "537b87c6e91b4d3b0552600f", name: "tedshot", playtime: 22872, wins: 306, losses: 65, score: 241} - {team: "humans", rank: 32, sessionID: "537bae76ec57a3e805cbf5b3", name: "Aeter", playtime: 18224, wins: 307, losses: 66, score: 241} - {team: "humans", rank: 33, sessionID: "537b9e8a51e98aa705b604ab", name: "bxp", playtime: 17385, wins: 304, losses: 67, score: 237} - {team: "humans", rank: 34, sessionID: "537bdbe4a41b6b3a059befd0", name: "princeben", playtime: 52246, wins: 290, losses: 56, score: 234} - {team: "humans", rank: 35, sessionID: "537bdf1d375835400576a207", name: "Mal Keshar", playtime: 985, wins: 295, losses: 68, score: 227} - {team: "humans", rank: 36, sessionID: "5383f2ea2757353805a972d3", name: "Mergen", playtime: 37792, wins: 297, losses: 71, score: 226} - {team: "humans", rank: 37, sessionID: "537cec6a9cce053a05c04385", name: "Simulatorboy", playtime: 15925, wins: 295, losses: 75, score: 220} - {team: "humans", rank: 38, sessionID: "537b977d556db17605be76a2", name: "shoebane", playtime: 89060, wins: 287, losses: 68, score: 219} - {team: "humans", rank: 39, sessionID: "538757328ca8b1120b8c0bb5", name: "ProvençalLeGaulois", playtime: 183850, wins: 289, losses: 71, score: 218} - {team: "humans", rank: 40, sessionID: "5384b9803e0daa3905188225", name: "Rincewind the Wizard", playtime: 49014, wins: 280, losses: 64, score: 216} - {team: "humans", rank: 41, sessionID: "53805c227585483905a77c38", name: "guuuuuuuuuuu", playtime: 40835, wins: 290, losses: 76, score: 214} - {team: "humans", rank: 42, sessionID: "537bc0060b070d6b0691fd47", name: "toothpaste", playtime: 116438, wins: 289, losses: 78, score: 211} - {team: "humans", rank: 43, sessionID: "538bc7d05572d43b0520ede9", name: "MaxF", playtime: 16012, wins: 271, losses: 62, score: 209} - {team: "humans", rank: 44, sessionID: "537ca06126529de30cca58a1", name: "firemanphil", playtime: 58857, wins: 287, losses: 81, score: 206} - {team: "humans", rank: 45, sessionID: "537b895ee91b4d3b0552606a", name: "Supaku", playtime: 23623, wins: 281, losses: 79, score: 202} - {team: "humans", rank: 46, sessionID: "537ba1d7903fd2b805155298", name: "Greediest", playtime: 32390, wins: 286, losses: 87, score: 199} - {team: "humans", rank: 47, sessionID: "537ba398903fd2b805155376", name: "RapTorS", playtime: 30828, wins: 280, losses: 83, score: 197} - {team: "humans", rank: 48, sessionID: "537bbb371aaa69c405267714", name: "PIptastic", playtime: 14165, wins: 282, losses: 85, score: 197} - {team: "humans", rank: 49, sessionID: "537fd2f62a5a5acd08dbbe90", name: "aldezar", playtime: 55511, wins: 260, losses: 64, score: 196} - {team: "humans", rank: 50, sessionID: "537c0f440ff88b2c06287c31", name: "yes", playtime: 42677, wins: 251, losses: 55, score: 196} - {team: "humans", rank: 51, sessionID: "537fb985c1a6b99109171054", name: "IamTesting", playtime: 242, wins: 280, losses: 90, score: 190} - {team: "humans", rank: 52, sessionID: "537cdd63665bde1b13ffdede", name: "wiggles", playtime: 9574, wins: 278, losses: 94, score: 184} - {team: "humans", rank: 53, sessionID: "537cda44665bde1b13ffdcb2", name: "Nullable", playtime: 21602, wins: 275, losses: 93, score: 182} - {team: "humans", rank: 54, sessionID: "537bf012b72b2bbe053c9173", name: "hyn", playtime: 5688, wins: 278, losses: 97, score: 181} - {team: "humans", rank: 55, sessionID: "537bda813dd7d35105f5fec2", name: "Rinomon", playtime: 19811, wins: 272, losses: 96, score: 176} - {team: "humans", rank: 56, sessionID: "537b9e7251e98aa705b604a2", name: "stuntman_fx", playtime: 12496, wins: 258, losses: 86, score: 172} - {team: "humans", rank: 57, sessionID: "537d1def7e1e10b705bbcbc4", name: "WizBit", playtime: 35790, wins: 270, losses: 98, score: 172} - {team: "humans", rank: 58, sessionID: "537b8a93e91b4d3b055260f3", name: "Korla March", playtime: 13093, wins: 265, losses: 94, score: 171} - {team: "humans", rank: 59, sessionID: "53873bc17d99a7390561afd2", name: "VicksC", playtime: 65582, wins: 262, losses: 93, score: 169} - {team: "humans", rank: 60, sessionID: "537b907d5bc02238050d1b22", name: "Jonanin", playtime: 60888, wins: 272, losses: 103, score: 169} - {team: "humans", rank: 61, sessionID: "537b9345c74f237005ecc475", name: "AdrianoKF", playtime: 8880, wins: 267, losses: 100, score: 167} - {team: "humans", rank: 62, sessionID: "537ba08651e98aa705b605a8", name: "frickinjason", playtime: 311295, wins: 266, losses: 99, score: 167} - {team: "humans", rank: 63, sessionID: "536076104c5ed51d05284aeb", name: "会打电脑的狼", playtime: 180932, wins: 262, losses: 96, score: 166} - {team: "humans", rank: 64, sessionID: "537fb41bc1a6b99109170daf", name: "avatar652", playtime: 23943, wins: 260, losses: 95, score: 165} - {team: "humans", rank: 65, sessionID: "537bb34a8698e13805226ae1", name: "Superice", playtime: 8561, wins: 267, losses: 103, score: 164} - {team: "humans", rank: 66, sessionID: "537b8f285bc02238050d1a91", name: "renner96", playtime: 8962, wins: 265, losses: 103, score: 162} - {team: "humans", rank: 67, sessionID: "537b97ba556db17605be76bc", name: "howsiwei", playtime: 37865, wins: 249, losses: 90, score: 159} - {team: "humans", rank: 68, sessionID: "537d6e997e6f2dba0510649c", name: "Brainoutoforder", playtime: 79551, wins: 263, losses: 104, score: 159} - {team: "humans", rank: 69, sessionID: "537bbe24d9644630065c90f4", name: "cc", playtime: 27244, wins: 247, losses: 94, score: 153} - {team: "humans", rank: 70, sessionID: "538f055b7558763705258211", name: "Klee", playtime: 29269, wins: 264, losses: 111, score: 153} - {team: "humans", rank: 71, sessionID: "537c3a51e8ea6e790a7cceb2", name: "NovaHorizon", playtime: 72951, wins: 254, losses: 103, score: 151} - {team: "humans", rank: 72, sessionID: "537c3e0dd08a96e40a64f01c", name: "Arnfrid", playtime: 13133, wins: 261, losses: 111, score: 150} - {team: "humans", rank: 73, sessionID: "537b7cf65bc02238050d141f", name: "rawpower", playtime: 60808, wins: 256, losses: 110, score: 146} - {team: "humans", rank: 74, sessionID: "537bcc75c57303a5070c2e9a", name: "dhimdis", playtime: 43092, wins: 256, losses: 111, score: 145} - {team: "humans", rank: 75, sessionID: "538bc1a15572d43b0520e8ae", name: "rednek", playtime: 38220, wins: 250, losses: 106, score: 144} - {team: "humans", rank: 76, sessionID: "5380c8ed7585483905a7ad55", name: "Kungfury", playtime: 628, wins: 254, losses: 113, score: 141} - {team: "humans", rank: 77, sessionID: "537c37dff1d9cfe4096ba9c9", name: "Auralien", playtime: 24844, wins: 255, losses: 115, score: 140} - {team: "humans", rank: 78, sessionID: "539234c52446a441053881ad", name: "Szalami", playtime: 45304, wins: 243, losses: 108, score: 135} - {team: "humans", rank: 79, sessionID: "537c15910ff88b2c06287fd5", name: "Ahrimen", playtime: 24541, wins: 253, losses: 120, score: 133} - {team: "humans", rank: 80, sessionID: "537ff34f4cd8023705770b31", name: "ColtYolo", playtime: 18704, wins: 244, losses: 115, score: 129} - {team: "humans", rank: 81, sessionID: "538ceadc56c3613905300df1", name: "Teshynil", playtime: 59986, wins: 233, losses: 105, score: 128} - {team: "humans", rank: 82, sessionID: "538f174df3691038051651f1", name: "Leas", playtime: 11670, wins: 251, losses: 126, score: 125} - {team: "humans", rank: 83, sessionID: "537d8cae13add33a051be70c", name: "Jamar", playtime: 9358, wins: 245, losses: 123, score: 122} - {team: "humans", rank: 84, sessionID: "53877f428ca8b1120b8c2ba8", name: "madcoder", playtime: 58824, wins: 241, losses: 120, score: 121} - {team: "humans", rank: 85, sessionID: "5391f1f282f0bc4705242218", name: "RedRudeBoy", playtime: 13356, wins: 230, losses: 110, score: 120} - {team: "humans", rank: 86, sessionID: "537bdb1c6b018e5505b9d5ae", name: "Ralkarin", playtime: 16137, wins: 245, losses: 128, score: 117} - {team: "humans", rank: 87, sessionID: "537bc9efa968548907de6dc5", name: "scrumlock", playtime: 43716, wins: 238, losses: 122, score: 116} - {team: "humans", rank: 88, sessionID: "53973dc02546283905a3d603", name: "Olivier_A", playtime: 5903, wins: 246, losses: 131, score: 115} - {team: "humans", rank: 89, sessionID: "537d3fffe20e956205f0da0c", name: "Lecky", playtime: 28974, wins: 242, losses: 127, score: 115} - {team: "humans", rank: 90, sessionID: "537b9edc7c89ec9805f4de89", name: "Cemiv", playtime: 5632, wins: 241, losses: 134, score: 107} - {team: "humans", rank: 91, sessionID: "537b8bede91b4d3b05526151", name: "Witchy", playtime: 29809, wins: 214, losses: 110, score: 104} - {team: "humans", rank: 92, sessionID: "535d728c30f061020b8f9893", name: "ZeoNFrosT", playtime: 0, wins: 233, losses: 130, score: 103} - {team: "humans", rank: 93, sessionID: "537b9c4b16613c8405155abd", name: "JD557", playtime: 17456, wins: 236, losses: 134, score: 102} - {team: "humans", rank: 94, sessionID: "537bdb396b018e5505b9d5ba", name: "devast8a", playtime: 89013, wins: 233, losses: 133, score: 100} - {team: "humans", rank: 95, sessionID: "537b7fbc5bc02238050d14ee", name: "jojman272", playtime: 859, wins: 232, losses: 132, score: 100} - {team: "humans", rank: 96, sessionID: "537cc552e4523d0113ba4eb2", name: "Sir Coward", playtime: 26839, wins: 235, losses: 135, score: 100} - {team: "humans", rank: 97, sessionID: "537b8abde91b4d3b05526103", name: "Jef", playtime: 10311, wins: 236, losses: 139, score: 97} - {team: "humans", rank: 98, sessionID: "537ed4db14bb1d38053b5b72", name: "ModernBarbershop", playtime: 33894, wins: 221, losses: 129, score: 92} - {team: "humans", rank: 99, sessionID: "537b8ba6e91b4d3b0552613c", name: "Wiz", playtime: 1655, wins: 227, losses: 137, score: 90} - {team: "humans", rank: 100, sessionID: "537bad3396ee90f605f2b0f9", name: "Rnq", playtime: 14853, wins: 226, losses: 138, score: 88} - {team: "humans", rank: 101, sessionID: "537f9d5ba7d2578f083d69b4", name: "BLACKORP", playtime: 2869, wins: 225, losses: 138, score: 87} - {team: "humans", rank: 102, sessionID: "537ba00e7c89ec9805f4defc", name: "xoko814", playtime: 869, wins: 225, losses: 139, score: 86} - {team: "humans", rank: 103, sessionID: "5391f83082f0bc47052424c7", name: "tarasiu", playtime: 228, wins: 225, losses: 139, score: 86} - {team: "humans", rank: 104, sessionID: "537d26d77e1e10b705bbd0d5", name: "Traitor", playtime: 8900, wins: 222, losses: 137, score: 85} - {team: "humans", rank: 105, sessionID: "537bbb0a1aaa69c4052676f5", name: "TROGDOR BURNINATE", playtime: 6630, wins: 231, losses: 146, score: 85} - {team: "humans", rank: 106, sessionID: "5387a8a3d06c503805fda60d", name: "masanorinyo", playtime: 68753, wins: 226, losses: 142, score: 84} - {team: "humans", rank: 107, sessionID: "538e8593f369103805160d76", name: "Aggar", playtime: 12492, wins: 228, losses: 144, score: 84} - {team: "humans", rank: 108, sessionID: "537e7eac63734c630505be27", name: "TheRealThrall", playtime: 587, wins: 224, losses: 141, score: 83} - {team: "humans", rank: 109, sessionID: "537c8dfa26529de30cca4c43", name: "xeno", playtime: 15394, wins: 222, losses: 142, score: 80} - {team: "humans", rank: 110, sessionID: "537bef0b8c297aa0055d1184", name: "Floogle", playtime: 36828, wins: 224, losses: 145, score: 79} - {team: "humans", rank: 111, sessionID: "537c666826529de30cca38c2", name: "Jerson Otzoy", playtime: 46519, wins: 201, losses: 122, score: 79} - {team: "humans", rank: 112, sessionID: "537cb6b2a3cb63ea103c8000", name: "phisixersai", playtime: 8170, wins: 224, losses: 146, score: 78} - {team: "humans", rank: 113, sessionID: "537b9ba716613c8405155a73", name: "Beerdroid", playtime: 2547, wins: 226, losses: 150, score: 76} - {team: "humans", rank: 114, sessionID: "537c9bcd26529de30cca54e0", name: "Dood", playtime: 1121, wins: 219, losses: 145, score: 74} - {team: "humans", rank: 115, sessionID: "537c5b7c26529de30cca3439", name: "Markoth", playtime: 787, wins: 220, losses: 147, score: 73} - {team: "humans", rank: 116, sessionID: "537d1c297e1e10b705bbca7d", name: "chotic", playtime: 1292, wins: 218, losses: 146, score: 72} - {team: "humans", rank: 117, sessionID: "538484a53e0daa39051863e4", name: "Drago", playtime: 465, wins: 217, losses: 147, score: 70} - {team: "humans", rank: 118, sessionID: "537baaab03ff8dc005b8436c", name: "Petteri", playtime: 15235, wins: 219, losses: 149, score: 70} - {team: "humans", rank: 119, sessionID: "537ca0aa26529de30cca58c8", name: "3ng3l", playtime: 1703, wins: 217, losses: 147, score: 70} - {team: "humans", rank: 120, sessionID: "537b897f5bc02238050d181c", name: "Jremz", playtime: 8386, wins: 221, losses: 152, score: 69} - {team: "humans", rank: 121, sessionID: "537ba85554a7b1d5053bb366", name: "Taters", playtime: 9664, wins: 193, losses: 126, score: 67} - {team: "humans", rank: 122, sessionID: "537b9220e91b4d3b055263ea", name: "Listr", playtime: 34000, wins: 202, losses: 136, score: 66} - {team: "humans", rank: 123, sessionID: "537cadbd2f6e3aee0ed581f0", name: "satefa", playtime: 10106, wins: 220, losses: 156, score: 64} - {team: "humans", rank: 124, sessionID: "537d0a8c84c54c6e05c05db7", name: "redWizzard", playtime: 53180, wins: 183, losses: 120, score: 63} - {team: "humans", rank: 125, sessionID: "536c6d1c68b5258d0c4b7da8", name: "Tober", playtime: 452, wins: 216, losses: 153, score: 63} - {team: "humans", rank: 126, sessionID: "535ee1e023f09c2c0836a2a7", name: "(ノಠ益ಠ)ノ彡┻━┻", playtime: 3229, wins: 218, losses: 158, score: 60} - {team: "humans", rank: 127, sessionID: "5371626351ce9b3a05d95d5c", name: "Perrekus", playtime: 9047, wins: 215, losses: 158, score: 57} - {team: "humans", rank: 128, sessionID: "53968372e1b8fd0c08c693d5", name: "leoTest", playtime: 10739, wins: 215, losses: 158, score: 57} - {team: "humans", rank: 129, sessionID: "537cfcd69cce053a05c04ce1", name: "Soulnai", playtime: 22641, wins: 210, losses: 154, score: 56} - {team: "humans", rank: 130, sessionID: "537bf57795356a43065f7403", name: "Mordecai", playtime: 11262, wins: 215, losses: 159, score: 56} - {team: "humans", rank: 131, sessionID: "5377aabf05e1483905cb99d5", name: "Umaris", playtime: 23418, wins: 211, losses: 156, score: 55} - {team: "humans", rank: 132, sessionID: "537c93ce26529de30cca5029", name: "Willybe", playtime: 4772, wins: 212, losses: 158, score: 54} - {team: "humans", rank: 133, sessionID: "537babf403838cf0050ace06", name: "Brian Humphrey", playtime: 7300, wins: 212, losses: 158, score: 54} - {team: "humans", rank: 134, sessionID: "537e19e30efa6a37059e0b4f", name: "Aqrrc", playtime: 5003, wins: 210, losses: 163, score: 47} - {team: "humans", rank: 135, sessionID: "5395d19622ca0e39054ea5b1", name: "anykey", playtime: 29278, wins: 201, losses: 155, score: 46} - {team: "humans", rank: 136, sessionID: "537b7fd6e91b4d3b05525da3", name: "Gily", playtime: 17673, wins: 205, losses: 163, score: 42} - {team: "humans", rank: 137, sessionID: "537bbbcb3dc5f3c3055c3040", name: "roseaboveit", playtime: 12398, wins: 205, losses: 168, score: 37} - {team: "humans", rank: 138, sessionID: "538757897d99a7390561bb7f", name: "Jeremy", playtime: 6842, wins: 199, losses: 166, score: 33} - {team: "humans", rank: 139, sessionID: "537b8b845bc02238050d18e8", name: "Abel Soares Siqueira", playtime: 4945, wins: 204, losses: 171, score: 33} - {team: "humans", rank: 140, sessionID: "537b8a37e91b4d3b055260c9", name: "mattmatt", playtime: 77241, wins: 198, losses: 166, score: 32} - {team: "humans", rank: 141, sessionID: "537fc26d2a5a5acd08dbb0a5", name: "Melrakal", playtime: 2393, wins: 200, losses: 173, score: 27} - {team: "humans", rank: 142, sessionID: "537bd8a73dd7d35105f5fd6a", name: "drakiac", playtime: 14601, wins: 196, losses: 169, score: 27} - {team: "humans", rank: 143, sessionID: "537cea3d9cce053a05c04226", name: "CNKLC", playtime: 11663, wins: 200, losses: 175, score: 25} - {team: "humans", rank: 144, sessionID: "537bf9c20ff88b2c06286e7c", name: "Jotipalo", playtime: 4124, wins: 199, losses: 176, score: 23} - {team: "humans", rank: 145, sessionID: "53807d9405e52a3305de99f5", name: "Booya", playtime: 118149, wins: 173, losses: 152, score: 21} - {team: "humans", rank: 146, sessionID: "537bf291d3443b2b068c1056", name: "Penguin", playtime: 7688, wins: 196, losses: 176, score: 20} - {team: "humans", rank: 147, sessionID: "5380b82005e52a3305deb679", name: "TheWrightDev", playtime: 26967, wins: 194, losses: 176, score: 18} - {team: "humans", rank: 148, sessionID: "537cf2aa98a1be440545d878", name: "Kipernicus", playtime: 11906, wins: 189, losses: 181, score: 8} - {team: "humans", rank: 149, sessionID: "535e1f1187ab8481075b8d95", name: "freek", playtime: 0, wins: 190, losses: 183, score: 7} - {team: "humans", rank: 150, sessionID: "535f0911d42bda62085e40fc", name: "heated", playtime: 65, wins: 188, losses: 182, score: 6} - {team: "humans", rank: 151, sessionID: "539120d882f0bc470523cd6f", name: "Fitbos", playtime: 1622, wins: 0, losses: 0, score: 0} - {team: "humans", rank: 152, sessionID: "539875130599fa3a05ca7293", name: "jeimmy", playtime: 663, wins: 0, losses: 0, score: 0} - {team: "humans", rank: 153, sessionID: "537b7ccce91b4d3b05525cdc", name: "Bart2121", playtime: 4177, wins: 184, losses: 187, score: -3} - {team: "humans", rank: 154, sessionID: "53866ed58ca8b1120b8b816d", name: "Nikolai", playtime: 26320, wins: 184, losses: 187, score: -3} - {team: "humans", rank: 155, sessionID: "5385610f3e0daa390518e2f6", name: "Stravinsky", playtime: 8870, wins: 182, losses: 185, score: -3} - {team: "humans", rank: 156, sessionID: "537b94956c13497e05de816e", name: "Maix", playtime: 3163, wins: 183, losses: 186, score: -3} - {team: "humans", rank: 157, sessionID: "537187dcce8e453b05c9d21c", name: "NasytToast", playtime: 0, wins: 183, losses: 188, score: -5} - {team: "humans", rank: 158, sessionID: "537bb696dd932f6b05d370fd", name: "HandmadeMercury", playtime: 5539, wins: 169, losses: 175, score: -6} - {team: "humans", rank: 159, sessionID: "537b7f605bc02238050d14c9", name: "Jaden", playtime: 10547, wins: 182, losses: 192, score: -10} - {team: "humans", rank: 160, sessionID: "537c489314aaabe80c69f413", name: "HiddEnigma", playtime: 5850, wins: 181, losses: 191, score: -10} - {team: "humans", rank: 161, sessionID: "537bb7cd1e8dd17a054c1044", name: "Alexander the Grape", playtime: 30398, wins: 178, losses: 189, score: -11} - {team: "humans", rank: 162, sessionID: "538eada37558763705255a0c", name: "Evran", playtime: 22253, wins: 179, losses: 192, score: -13} - {team: "humans", rank: 163, sessionID: "5386aedf7d99a7390561802a", name: "Reclusiarch", playtime: 3281, wins: 178, losses: 192, score: -14} - {team: "humans", rank: 164, sessionID: "538b7202b924da3905157e07", name: "Mlatic", playtime: 723, wins: 176, losses: 190, score: -14} - {team: "humans", rank: 165, sessionID: "537c4411c209bbd60c16a3d8", name: "liorst1", playtime: 14571, wins: 178, losses: 193, score: -15} - {team: "humans", rank: 166, sessionID: "537fcaee2a5a5acd08dbb79c", name: "Booya2nd", playtime: 9598, wins: 153, losses: 168, score: -15} - {team: "humans", rank: 167, sessionID: "538ae84fb924da3905154172", name: "WAAW", playtime: 3668, wins: 177, losses: 194, score: -17} - {team: "humans", rank: 168, sessionID: "538751b78ca8b1120b8c0792", name: "DZC", playtime: 5512, wins: 170, losses: 188, score: -18} - {team: "humans", rank: 169, sessionID: "537c0ab50ff88b2c0628792e", name: "maxily", playtime: 18792, wins: 174, losses: 192, score: -18} - {team: "humans", rank: 170, sessionID: "537ba1347c89ec9805f4df76", name: "qkhhly", playtime: 9518, wins: 176, losses: 196, score: -20} - {team: "humans", rank: 171, sessionID: "538b4bbdd06c503805ff3b8a", name: "iamcodewar", playtime: 10939, wins: 178, losses: 198, score: -20} - {team: "humans", rank: 172, sessionID: "537f14e18fe881f1055df20a", name: "Alanor", playtime: 20437, wins: 150, losses: 174, score: -24} - {team: "humans", rank: 173, sessionID: "537f57ff3282d7a507695039", name: "Navi' Dendi", playtime: 4382, wins: 172, losses: 197, score: -25} - {team: "humans", rank: 174, sessionID: "537c14950ff88b2c06287f22", name: "lolka", playtime: 3820, wins: 172, losses: 200, score: -28} - {team: "humans", rank: 175, sessionID: "53570b7a1bfa9bba14b5e045", name: "Scott", playtime: 6228, wins: 173, losses: 202, score: -29} - {team: "humans", rank: 176, sessionID: "537bbd0f3cd816fa05a48401", name: "DonutBaron", playtime: 9716, wins: 165, losses: 195, score: -30} - {team: "humans", rank: 177, sessionID: "5381726d7585483905a7f978", name: "armlol", playtime: 5149, wins: 171, losses: 204, score: -33} - {team: "humans", rank: 178, sessionID: "538c0bfb56c36139052fa076", name: "Aura Temple Network", playtime: 7489, wins: 169, losses: 205, score: -36} - {team: "humans", rank: 179, sessionID: "538ec77af3691038051629c3", name: "BI", playtime: 3870, wins: 164, losses: 200, score: -36} - {team: "humans", rank: 180, sessionID: "537b889fe91b4d3b0552603e", name: "McDerp", playtime: 3415, wins: 161, losses: 203, score: -42} - {team: "humans", rank: 181, sessionID: "537d169a7e1e10b705bbc736", name: "Nitor", playtime: 7036, wins: 159, losses: 205, score: -46} - {team: "humans", rank: 182, sessionID: "53837eee6f3bea3a05faf5fb", name: "HeadCrusher", playtime: 22806, wins: 133, losses: 182, score: -49} - {team: "humans", rank: 183, sessionID: "537ba4887c89ec9805f4e10d", name: "Geralt", playtime: 2353, wins: 158, losses: 208, score: -50} - {team: "humans", rank: 184, sessionID: "53802aab05e52a3305de797e", name: "micblayo", playtime: 14726, wins: 159, losses: 209, score: -50} - {team: "humans", rank: 185, sessionID: "538b60bdb924da39051576e2", name: "mydoom", playtime: 9270, wins: 159, losses: 209, score: -50} - {team: "humans", rank: 186, sessionID: "5380f3917585483905a7c0b3", name: "Lalaland1125", playtime: 689, wins: 160, losses: 211, score: -51} - {team: "humans", rank: 187, sessionID: "537b8125e91b4d3b05525e1e", name: "Garrett", playtime: 1833, wins: 157, losses: 212, score: -55} - {team: "humans", rank: 188, sessionID: "537b8c60e91b4d3b05526181", name: "Usopp", playtime: 8340, wins: 156, losses: 217, score: -61} - {team: "humans", rank: 189, sessionID: "537b9b4116613c8405155a41", name: "Y0DA", playtime: 5351, wins: 154, losses: 216, score: -62} - {team: "humans", rank: 190, sessionID: "5387f127d06c503805fdcd97", name: "Hexadecimage", playtime: 89476, wins: 151, losses: 222, score: -71} - {team: "humans", rank: 191, sessionID: "539265012446a44105389a8c", name: "odeakihumi", playtime: 23819, wins: 143, losses: 219, score: -76} - {team: "humans", rank: 192, sessionID: "537ba73a980cfcba051f19c5", name: "Torg", playtime: 7045, wins: 145, losses: 221, score: -76} - {team: "humans", rank: 193, sessionID: "5392bbc0e04ba13805ed4c0f", name: "iownspace", playtime: 51659, wins: 146, losses: 223, score: -77} - {team: "humans", rank: 194, sessionID: "537bf14bf8b46fbd0544fc18", name: "danshou", playtime: 22590, wins: 148, losses: 226, score: -78} - {team: "humans", rank: 195, sessionID: "537b212dfe0ec03905fcd712", name: "ThunderClan", playtime: 766, wins: 144, losses: 228, score: -84} - {team: "humans", rank: 196, sessionID: "536540d51415c79e648b1de5", name: "Nick04 Bubonic", playtime: 12, wins: 138, losses: 222, score: -84} - {team: "humans", rank: 197, sessionID: "537fb0792a5a5acd08dba76f", name: "Slackus", playtime: 49736, wins: 141, losses: 226, score: -85} - {team: "humans", rank: 198, sessionID: "537d44911333605305550411", name: "tehowner", playtime: 2969, wins: 138, losses: 223, score: -85} - {team: "humans", rank: 199, sessionID: "537df429933d99860613ab2d", name: "Farafonoff", playtime: 4315, wins: 142, losses: 228, score: -86} - {team: "humans", rank: 200, sessionID: "538501137d99a7390560db54", name: "Joodoc", playtime: 6042, wins: 144, losses: 231, score: -87} - {team: "humans", rank: 201, sessionID: "537b8a58e91b4d3b055260d8", name: "Terebijoke", playtime: 85680, wins: 122, losses: 210, score: -88} - {team: "humans", rank: 202, sessionID: "537c110195356a43065f8450", name: "Chen Yu LIu", playtime: 843, wins: 140, losses: 232, score: -92} - {team: "humans", rank: 203, sessionID: "537dba4613add33a051bf680", name: "Bobbybaby", playtime: 1509, wins: 140, losses: 232, score: -92} - {team: "humans", rank: 204, sessionID: "537b9003e91b4d3b05526329", name: "Coreth", playtime: 11677, wins: 131, losses: 224, score: -93} - {team: "humans", rank: 205, sessionID: "538b618bd06c503805ff4210", name: "robat", playtime: 5776, wins: 138, losses: 234, score: -96} - {team: "humans", rank: 206, sessionID: "5383b7196f3bea3a05fb1472", name: "lilos", playtime: 2464, wins: 135, losses: 232, score: -97} - {team: "humans", rank: 207, sessionID: "537f8672d409ac270861c842", name: "ThatOtherPerson", playtime: 2018, wins: 137, losses: 236, score: -99} - {team: "humans", rank: 208, sessionID: "53809c2c7585483905a795f1", name: "都比", playtime: 28855, wins: 136, losses: 235, score: -99} - {team: "humans", rank: 209, sessionID: "537c866f14aaabe80c6a0f90", name: "Energy", playtime: 1276, wins: 130, losses: 229, score: -99} - {team: "humans", rank: 210, sessionID: "538e4af0755876370525291c", name: "commando Tech", playtime: 3725, wins: 136, losses: 236, score: -100} - {team: "humans", rank: 211, sessionID: "537b9da67c89ec9805f4de0b", name: "tembelu", playtime: 9298, wins: 129, losses: 230, score: -101} - {team: "humans", rank: 212, sessionID: "53972a5f2546283905a3bdc5", name: "holyKoT", playtime: 2171, wins: 131, losses: 241, score: -110} - {team: "humans", rank: 213, sessionID: "537ba6dd980cfcba051f199d", name: "Aaron1011", playtime: 3449, wins: 130, losses: 240, score: -110} - {team: "humans", rank: 214, sessionID: "537c68bf26529de30cca39cb", name: "ESWAT", playtime: 893, wins: 128, losses: 239, score: -111} - {team: "humans", rank: 215, sessionID: "537d5fdb3dcf67c40571fb13", name: "JustTurrable", playtime: 264, wins: 125, losses: 240, score: -115} - {team: "humans", rank: 216, sessionID: "537e4268e1489fe206667e26", name: "EvanK", playtime: 668, wins: 125, losses: 245, score: -120} - {team: "humans", rank: 217, sessionID: "537be834a3b60b390500e0a3", name: "gilxa1226", playtime: 394, wins: 125, losses: 245, score: -120} - {team: "humans", rank: 218, sessionID: "537bbcfd9e1bf5f905926ebf", name: "Qin Shi Huang", playtime: 4691, wins: 125, losses: 246, score: -121} - {team: "humans", rank: 219, sessionID: "537b9bd016613c8405155a8b", name: "WaffleFries", playtime: 2944, wins: 121, losses: 246, score: -125} - {team: "humans", rank: 220, sessionID: "537b8a65e91b4d3b055260e0", name: "Gurra", playtime: 6295, wins: 107, losses: 233, score: -126} - {team: "humans", rank: 221, sessionID: "537e2025933d99860613c614", name: "Encosia", playtime: 2025, wins: 118, losses: 250, score: -132} - {team: "humans", rank: 222, sessionID: "537bb694dd932f6b05d370fc", name: "Kaboomm", playtime: 4333, wins: 116, losses: 253, score: -137} - {team: "humans", rank: 223, sessionID: "538001aebf8ae33a0501b98e", name: "taichi_kunnn", playtime: 3524, wins: 112, losses: 254, score: -142} - {team: "humans", rank: 224, sessionID: "53630b6573bdb4f7045a772c", name: "Lonib", playtime: 0, wins: 113, losses: 257, score: -144} - {team: "humans", rank: 225, sessionID: "5360f83b67c29a0609ddceb4", name: "Readper", playtime: 0, wins: 109, losses: 264, score: -155} - {team: "humans", rank: 226, sessionID: "53717f4551ce9b3a05d96043", name: "cpkenn09y", playtime: 0, wins: 106, losses: 263, score: -157} - {team: "humans", rank: 227, sessionID: "537b9b9416613c8405155a6b", name: "Rubini", playtime: 6763, wins: 103, losses: 271, score: -168} - {team: "humans", rank: 228, sessionID: "53902ad775587637052615d9", name: "Loxk", playtime: 32690, wins: 89, losses: 265, score: -176} - {team: "humans", rank: 229, sessionID: "537b93886c13497e05de80a6", name: "Klomnar", playtime: 405, wins: 98, losses: 274, score: -176} - {team: "humans", rank: 230, sessionID: "537b9c7c16613c8405155ae0", name: "dpen2000", playtime: 4313, wins: 93, losses: 273, score: -180} - {team: "humans", rank: 231, sessionID: "53692c2d84e82a3a0553305e", name: "rnprdk", playtime: 0, wins: 94, losses: 278, score: -184} - {team: "humans", rank: 232, sessionID: "537be99f20a501380564e764", name: "rizend", playtime: 3017, wins: 92, losses: 279, score: -187} - {team: "humans", rank: 233, sessionID: "537ba94d54a7b1d5053bb426", name: "Rokner", playtime: 3911, wins: 90, losses: 282, score: -192} - {team: "humans", rank: 234, sessionID: "537b949e556db17605be74ff", name: "baldeagle", playtime: 7698, wins: 91, losses: 284, score: -193} - {team: "humans", rank: 235, sessionID: "535f0cdfc2e83ad9048faef0", name: "Mobius", playtime: 0, wins: 87, losses: 288, score: -201} - {team: "humans", rank: 236, sessionID: "537bbe446d5f9f2f06e0c674", name: "Lakk", playtime: 12072, wins: 76, losses: 296, score: -220} - {team: "humans", rank: 237, sessionID: "535ac395d83daa1a052494c1", name: "Michael S.", playtime: 304, wins: 68, losses: 304, score: -236} - {team: "humans", rank: 238, sessionID: "53718c6cce8e453b05c9d298", name: "Blitz", playtime: 0, wins: 68, losses: 306, score: -238} - {team: "humans", rank: 239, sessionID: "536310848e22980605aa58c3", name: "sjarvie", playtime: 0, wins: 66, losses: 308, score: -242} - {team: "humans", rank: 240, sessionID: "537ba10e51e98aa705b605df", name: "Deleu", playtime: 7241, wins: 61, losses: 307, score: -246} - {team: "humans", rank: 241, sessionID: "537b92765bc02238050d1bf0", name: "Deneim", playtime: 13791, wins: 62, losses: 312, score: -250} - {team: "humans", rank: 242, sessionID: "538e609af36910380515f8d6", name: "Volgax", playtime: 6774, wins: 59, losses: 310, score: -251} - {team: "humans", rank: 243, sessionID: "537ba62557494fc405a6faac", name: "Zandrasco", playtime: 4193, wins: 60, losses: 315, score: -255} - {team: "humans", rank: 244, sessionID: "537ecf5414bb1d38053b58bb", name: "Sir Mouse", playtime: 16021, wins: 52, losses: 321, score: -269} - {team: "humans", rank: 245, sessionID: "538c8faf5572d43b05214e3b", name: "AceWizard", playtime: 54, wins: 45, losses: 315, score: -270} - {team: "humans", rank: 246, sessionID: "537deb820efa6a37059df268", name: "MadMan30", playtime: 316, wins: 46, losses: 319, score: -273} - {team: "humans", rank: 247, sessionID: "537bf38495356a43065f7291", name: "NicRio", playtime: 130, wins: 43, losses: 316, score: -273} - {team: "humans", rank: 248, sessionID: "537cd876665bde1b13ffdad4", name: "Is_G", playtime: 776, wins: 44, losses: 319, score: -275} - {team: "humans", rank: 249, sessionID: "537bb14b4f81f53805b6366a", name: "jeromeASF", playtime: 335, wins: 41, losses: 318, score: -277} - {team: "humans", rank: 250, sessionID: "5381745005e52a3305df1c23", name: "El Psy Congr00", playtime: 1032, wins: 41, losses: 319, score: -278} - {team: "humans", rank: 251, sessionID: "538451183e0daa39051845a0", name: "loquele", playtime: 549, wins: 43, losses: 322, score: -279} - {team: "humans", rank: 252, sessionID: "537b606a2daeeb3905a9292f", name: "DeathStalker", playtime: 166, wins: 38, losses: 319, score: -281} - {team: "humans", rank: 253, sessionID: "537bd56ab0d1766d05243002", name: "thelion", playtime: 338, wins: 40, losses: 323, score: -283} - {team: "humans", rank: 254, sessionID: "537d15d37e1e10b705bbc6ef", name: "Diegobrp", playtime: 2132, wins: 37, losses: 321, score: -284} - {team: "humans", rank: 255, sessionID: "537caa102f6e3aee0ed57f84", name: "Sakares Saengkaew", playtime: 34, wins: 37, losses: 321, score: -284} - {team: "humans", rank: 256, sessionID: "53627e2fca5c6f3c11ebc9b1", name: "Animex", playtime: 0, wins: 38, losses: 324, score: -286} - {team: "humans", rank: 257, sessionID: "537bc0ad1c8dfa820699fcb9", name: "Black Mage Wizard Guy", playtime: 691, wins: 37, losses: 323, score: -286} - {team: "humans", rank: 258, sessionID: "535f07d39894af8f7fd84e85", name: "Maksym", playtime: 0, wins: 38, losses: 327, score: -289} - {team: "humans", rank: 259, sessionID: "537b98e33803a287057582a8", name: "Angeland", playtime: 1758, wins: 41, losses: 330, score: -289} - {team: "humans", rank: 260, sessionID: "537c63f426529de30cca37ba", name: "Dmitry", playtime: 181, wins: 35, losses: 325, score: -290} - {team: "humans", rank: 261, sessionID: "537ceb1798a1be440545d40e", name: "jaba", playtime: 572, wins: 35, losses: 325, score: -290} - {team: "humans", rank: 262, sessionID: "537c0f3f0ff88b2c06287c2b", name: "Quan Pham", playtime: 4353, wins: 40, losses: 332, score: -292} - {team: "humans", rank: 263, sessionID: "537d60467e6f2dba051060b6", name: "rhall", playtime: 67548, wins: 11, losses: 316, score: -305} - {team: "humans", rank: 264, sessionID: "5384c9de7d99a7390560bfd7", name: "Secathor", playtime: 16404, wins: 28, losses: 345, score: -317} - {team: "humans", rank: 265, sessionID: "538a08bed06c503805feb6b0", name: "Nemoy", playtime: 1643, wins: 0, losses: 319, score: -319} - {team: "humans", rank: 266, sessionID: "537c3806f1d9cfe4096ba9d8", name: "Hannofcart", playtime: 17397, wins: 0, losses: 323, score: -323} - {team: "humans", rank: 267, sessionID: "537c4d5f26529de30cca2e68", name: "Morphumax", playtime: 58395, wins: 0, losses: 323, score: -323} - {team: "humans", rank: 268, sessionID: "53864aa37d99a73905615dda", name: "shoetest", playtime: 14876, wins: 0, losses: 324, score: -324} - {team: "humans", rank: 269, sessionID: "537b97cd556db17605be76c3", name: "domrein", playtime: 12339, wins: 0, losses: 324, score: -324} - {team: "humans", rank: 270, sessionID: "53835f1fc85c223a05f49ddb", name: "hace", playtime: 9175, wins: 0, losses: 325, score: -325} - {team: "humans", rank: 271, sessionID: "53666cc75af8b2c71dc017e8", name: "Bonesdog", playtime: 0, wins: 0, losses: 326, score: -326} - {team: "humans", rank: 272, sessionID: "537be26d20a501380564e359", name: "Cinnamon Scrolls", playtime: 6619, wins: 0, losses: 330, score: -330} - {team: "humans", rank: 273, sessionID: "537b8f3ce91b4d3b055262d7", name: "asdasd", playtime: 242330, wins: 0, losses: 335, score: -335} - {team: "humans", rank: 274, sessionID: "5383551cc85c223a05f49992", name: "marthyi", playtime: 30008, wins: 325, losses: 43, score: 282} - {team: "humans", rank: 275, sessionID: "538f5334f369103805167613", name: "Leshka", playtime: 10409, wins: 93, losses: 282, score: -189} + {team: 'humans', rank: 1, sessionID: '5381e3537585483905a829c1', name: 'Wizard Dude', playtime: 63184, wins: 363, losses: 0, score: 363} + {team: 'humans', rank: 2, sessionID: '537cf76184c54c6e05c05415', name: 'Vettax', playtime: 96757, wins: 365, losses: 9, score: 356} + {team: 'humans', rank: 3, sessionID: '53836824c85c223a05f4a1dd', name: 'HighSea', playtime: 98996, wins: 354, losses: 7, score: 347} + {team: 'humans', rank: 4, sessionID: '537c5cf614aaabe80c69fc8d', name: 'BubbleDragon', playtime: 136876, wins: 352, losses: 12, score: 340} + {team: 'humans', rank: 5, sessionID: '537bad0cb0d477e005347fb5', name: 'Bakanio', playtime: 103933, wins: 348, losses: 11, score: 337} + {team: 'humans', rank: 6, sessionID: '537cbf86264b3a7d12eb9d55', name: 'zero_degrees', playtime: 4236, wins: 346, losses: 17, score: 329} + {team: 'humans', rank: 7, sessionID: '538915d2d06c503805fe40d2', name: 'Transistor', playtime: 742, wins: 347, losses: 19, score: 328} + {team: 'humans', rank: 8, sessionID: '537bbc56831db4ca0526ced3', name: 'Chrc', playtime: 2105, wins: 339, losses: 15, score: 324} + {team: 'humans', rank: 9, sessionID: '5381d7f87585483905a825fc', name: 'nemoyatpeace', playtime: 121202, wins: 344, losses: 20, score: 324} + {team: 'humans', rank: 10, sessionID: '53928ff24ca25c6205e290c0', name: 'Catalina', playtime: 239, wins: 342, losses: 27, score: 315} + {team: 'humans', rank: 11, sessionID: '5383f8162757353805a97454', name: 'Zzadded', playtime: 53485, wins: 334, losses: 28, score: 306} + {team: 'humans', rank: 12, sessionID: '537d047084c54c6e05c05ab9', name: 'Moojo', playtime: 83687, wins: 331, losses: 27, score: 304} + {team: 'humans', rank: 13, sessionID: '537bab02f5b6a9d405ec5107', name: 'Pentiado', playtime: 70424, wins: 336, losses: 33, score: 303} + {team: 'humans', rank: 14, sessionID: '537d11947e1e10b705bbc4a6', name: 'Banadux', playtime: 141292, wins: 333, losses: 32, score: 301} + {team: 'humans', rank: 15, sessionID: '538181fd7585483905a801e1', name: 'chadnickbok', playtime: 922, wins: 334, losses: 33, score: 301} + {team: 'humans', rank: 16, sessionID: '537bc4990de0a02c07e8799a', name: 'Mepath', playtime: 94421, wins: 315, losses: 28, score: 287} + {team: 'humans', rank: 17, sessionID: '53826025c85c223a05f42c5c', name: 'Frederick the Great', playtime: 24696, wins: 325, losses: 42, score: 283} + {team: 'humans', rank: 18, sessionID: '5387d070b924da39051331a5', name: 'NoMan', playtime: 279296, wins: 320, losses: 46, score: 274} + {team: 'humans', rank: 19, sessionID: '535e50c1ba35914a07a308c9', name: 'Patogeno', playtime: 69601, wins: 318, losses: 44, score: 274} + {team: 'humans', rank: 20, sessionID: '537b9b023803a287057583dd', name: 'avv', playtime: 85418, wins: 316, losses: 50, score: 266} + {team: 'humans', rank: 21, sessionID: '537c89d814aaabe80c6a1139', name: 'Foosvald', playtime: 3197, wins: 307, losses: 41, score: 266} + {team: 'humans', rank: 22, sessionID: '538350c778171d3d057eb1e4', name: 'Ticaj', playtime: 29249, wins: 316, losses: 52, score: 264} + {team: 'humans', rank: 23, sessionID: '537b7d9a5bc02238050d1450', name: 'DrMonky', playtime: 14815, wins: 315, losses: 55, score: 260} + {team: 'humans', rank: 24, sessionID: '537c7d8526529de30cca4310', name: 'imkat', playtime: 14870, wins: 292, losses: 38, score: 254} + {team: 'humans', rank: 25, sessionID: '5392283b2446a44105387cbb', name: 'AKA', playtime: 134724, wins: 312, losses: 58, score: 254} + {team: 'humans', rank: 26, sessionID: '537b7ff9e91b4d3b05525db2', name: 'UltraNagog', playtime: 113091, wins: 296, losses: 46, score: 250} + {team: 'humans', rank: 27, sessionID: '537c1b0e0ff88b2c06288354', name: 'Master J', playtime: 32859, wins: 305, losses: 57, score: 248} + {team: 'humans', rank: 28, sessionID: '537c551814aaabe80c69f8e9', name: 'texastoast', playtime: 75930, wins: 300, losses: 54, score: 246} + {team: 'humans', rank: 29, sessionID: '537b9f2551e98aa705b60500', name: 'Otsix', playtime: 2270, wins: 302, losses: 58, score: 244} + {team: 'humans', rank: 30, sessionID: '537bb4b88698e13805226bb9', name: 'asselinpaul', playtime: 22992, wins: 306, losses: 64, score: 242} + {team: 'humans', rank: 31, sessionID: '537b87c6e91b4d3b0552600f', name: 'tedshot', playtime: 22872, wins: 306, losses: 65, score: 241} + {team: 'humans', rank: 32, sessionID: '537bae76ec57a3e805cbf5b3', name: 'Aeter', playtime: 18224, wins: 307, losses: 66, score: 241} + {team: 'humans', rank: 33, sessionID: '537b9e8a51e98aa705b604ab', name: 'bxp', playtime: 17385, wins: 304, losses: 67, score: 237} + {team: 'humans', rank: 34, sessionID: '537bdbe4a41b6b3a059befd0', name: 'princeben', playtime: 52246, wins: 290, losses: 56, score: 234} + {team: 'humans', rank: 35, sessionID: '537bdf1d375835400576a207', name: 'Mal Keshar', playtime: 985, wins: 295, losses: 68, score: 227} + {team: 'humans', rank: 36, sessionID: '5383f2ea2757353805a972d3', name: 'Mergen', playtime: 37792, wins: 297, losses: 71, score: 226} + {team: 'humans', rank: 37, sessionID: '537cec6a9cce053a05c04385', name: 'Simulatorboy', playtime: 15925, wins: 295, losses: 75, score: 220} + {team: 'humans', rank: 38, sessionID: '537b977d556db17605be76a2', name: 'shoebane', playtime: 89060, wins: 287, losses: 68, score: 219} + {team: 'humans', rank: 39, sessionID: '538757328ca8b1120b8c0bb5', name: 'ProvençalLeGaulois', playtime: 183850, wins: 289, losses: 71, score: 218} + {team: 'humans', rank: 40, sessionID: '5384b9803e0daa3905188225', name: 'Rincewind the Wizard', playtime: 49014, wins: 280, losses: 64, score: 216} + {team: 'humans', rank: 41, sessionID: '53805c227585483905a77c38', name: 'guuuuuuuuuuu', playtime: 40835, wins: 290, losses: 76, score: 214} + {team: 'humans', rank: 42, sessionID: '537bc0060b070d6b0691fd47', name: 'toothpaste', playtime: 116438, wins: 289, losses: 78, score: 211} + {team: 'humans', rank: 43, sessionID: '538bc7d05572d43b0520ede9', name: 'MaxF', playtime: 16012, wins: 271, losses: 62, score: 209} + {team: 'humans', rank: 44, sessionID: '537ca06126529de30cca58a1', name: 'firemanphil', playtime: 58857, wins: 287, losses: 81, score: 206} + {team: 'humans', rank: 45, sessionID: '537b895ee91b4d3b0552606a', name: 'Supaku', playtime: 23623, wins: 281, losses: 79, score: 202} + {team: 'humans', rank: 46, sessionID: '537ba1d7903fd2b805155298', name: 'Greediest', playtime: 32390, wins: 286, losses: 87, score: 199} + {team: 'humans', rank: 47, sessionID: '537ba398903fd2b805155376', name: 'RapTorS', playtime: 30828, wins: 280, losses: 83, score: 197} + {team: 'humans', rank: 48, sessionID: '537bbb371aaa69c405267714', name: 'PIptastic', playtime: 14165, wins: 282, losses: 85, score: 197} + {team: 'humans', rank: 49, sessionID: '537fd2f62a5a5acd08dbbe90', name: 'aldezar', playtime: 55511, wins: 260, losses: 64, score: 196} + {team: 'humans', rank: 50, sessionID: '537c0f440ff88b2c06287c31', name: 'yes', playtime: 42677, wins: 251, losses: 55, score: 196} + {team: 'humans', rank: 51, sessionID: '537fb985c1a6b99109171054', name: 'IamTesting', playtime: 242, wins: 280, losses: 90, score: 190} + {team: 'humans', rank: 52, sessionID: '537cdd63665bde1b13ffdede', name: 'wiggles', playtime: 9574, wins: 278, losses: 94, score: 184} + {team: 'humans', rank: 53, sessionID: '537cda44665bde1b13ffdcb2', name: 'Nullable', playtime: 21602, wins: 275, losses: 93, score: 182} + {team: 'humans', rank: 54, sessionID: '537bf012b72b2bbe053c9173', name: 'hyn', playtime: 5688, wins: 278, losses: 97, score: 181} + {team: 'humans', rank: 55, sessionID: '537bda813dd7d35105f5fec2', name: 'Rinomon', playtime: 19811, wins: 272, losses: 96, score: 176} + {team: 'humans', rank: 56, sessionID: '537b9e7251e98aa705b604a2', name: 'stuntman_fx', playtime: 12496, wins: 258, losses: 86, score: 172} + {team: 'humans', rank: 57, sessionID: '537d1def7e1e10b705bbcbc4', name: 'WizBit', playtime: 35790, wins: 270, losses: 98, score: 172} + {team: 'humans', rank: 58, sessionID: '537b8a93e91b4d3b055260f3', name: 'Korla March', playtime: 13093, wins: 265, losses: 94, score: 171} + {team: 'humans', rank: 59, sessionID: '53873bc17d99a7390561afd2', name: 'VicksC', playtime: 65582, wins: 262, losses: 93, score: 169} + {team: 'humans', rank: 60, sessionID: '537b907d5bc02238050d1b22', name: 'Jonanin', playtime: 60888, wins: 272, losses: 103, score: 169} + {team: 'humans', rank: 61, sessionID: '537b9345c74f237005ecc475', name: 'AdrianoKF', playtime: 8880, wins: 267, losses: 100, score: 167} + {team: 'humans', rank: 62, sessionID: '537ba08651e98aa705b605a8', name: 'frickinjason', playtime: 311295, wins: 266, losses: 99, score: 167} + {team: 'humans', rank: 63, sessionID: '536076104c5ed51d05284aeb', name: '会打电脑的狼', playtime: 180932, wins: 262, losses: 96, score: 166} + {team: 'humans', rank: 64, sessionID: '537fb41bc1a6b99109170daf', name: 'avatar652', playtime: 23943, wins: 260, losses: 95, score: 165} + {team: 'humans', rank: 65, sessionID: '537bb34a8698e13805226ae1', name: 'Superice', playtime: 8561, wins: 267, losses: 103, score: 164} + {team: 'humans', rank: 66, sessionID: '537b8f285bc02238050d1a91', name: 'renner96', playtime: 8962, wins: 265, losses: 103, score: 162} + {team: 'humans', rank: 67, sessionID: '537b97ba556db17605be76bc', name: 'howsiwei', playtime: 37865, wins: 249, losses: 90, score: 159} + {team: 'humans', rank: 68, sessionID: '537d6e997e6f2dba0510649c', name: 'Brainoutoforder', playtime: 79551, wins: 263, losses: 104, score: 159} + {team: 'humans', rank: 69, sessionID: '537bbe24d9644630065c90f4', name: 'cc', playtime: 27244, wins: 247, losses: 94, score: 153} + {team: 'humans', rank: 70, sessionID: '538f055b7558763705258211', name: 'Klee', playtime: 29269, wins: 264, losses: 111, score: 153} + {team: 'humans', rank: 71, sessionID: '537c3a51e8ea6e790a7cceb2', name: 'NovaHorizon', playtime: 72951, wins: 254, losses: 103, score: 151} + {team: 'humans', rank: 72, sessionID: '537c3e0dd08a96e40a64f01c', name: 'Arnfrid', playtime: 13133, wins: 261, losses: 111, score: 150} + {team: 'humans', rank: 73, sessionID: '537b7cf65bc02238050d141f', name: 'rawpower', playtime: 60808, wins: 256, losses: 110, score: 146} + {team: 'humans', rank: 74, sessionID: '537bcc75c57303a5070c2e9a', name: 'dhimdis', playtime: 43092, wins: 256, losses: 111, score: 145} + {team: 'humans', rank: 75, sessionID: '538bc1a15572d43b0520e8ae', name: 'rednek', playtime: 38220, wins: 250, losses: 106, score: 144} + {team: 'humans', rank: 76, sessionID: '5380c8ed7585483905a7ad55', name: 'Kungfury', playtime: 628, wins: 254, losses: 113, score: 141} + {team: 'humans', rank: 77, sessionID: '537c37dff1d9cfe4096ba9c9', name: 'Auralien', playtime: 24844, wins: 255, losses: 115, score: 140} + {team: 'humans', rank: 78, sessionID: '539234c52446a441053881ad', name: 'Szalami', playtime: 45304, wins: 243, losses: 108, score: 135} + {team: 'humans', rank: 79, sessionID: '537c15910ff88b2c06287fd5', name: 'Ahrimen', playtime: 24541, wins: 253, losses: 120, score: 133} + {team: 'humans', rank: 80, sessionID: '537ff34f4cd8023705770b31', name: 'ColtYolo', playtime: 18704, wins: 244, losses: 115, score: 129} + {team: 'humans', rank: 81, sessionID: '538ceadc56c3613905300df1', name: 'Teshynil', playtime: 59986, wins: 233, losses: 105, score: 128} + {team: 'humans', rank: 82, sessionID: '538f174df3691038051651f1', name: 'Leas', playtime: 11670, wins: 251, losses: 126, score: 125} + {team: 'humans', rank: 83, sessionID: '537d8cae13add33a051be70c', name: 'Jamar', playtime: 9358, wins: 245, losses: 123, score: 122} + {team: 'humans', rank: 84, sessionID: '53877f428ca8b1120b8c2ba8', name: 'madcoder', playtime: 58824, wins: 241, losses: 120, score: 121} + {team: 'humans', rank: 85, sessionID: '5391f1f282f0bc4705242218', name: 'RedRudeBoy', playtime: 13356, wins: 230, losses: 110, score: 120} + {team: 'humans', rank: 86, sessionID: '537bdb1c6b018e5505b9d5ae', name: 'Ralkarin', playtime: 16137, wins: 245, losses: 128, score: 117} + {team: 'humans', rank: 87, sessionID: '537bc9efa968548907de6dc5', name: 'scrumlock', playtime: 43716, wins: 238, losses: 122, score: 116} + {team: 'humans', rank: 88, sessionID: '53973dc02546283905a3d603', name: 'Olivier_A', playtime: 5903, wins: 246, losses: 131, score: 115} + {team: 'humans', rank: 89, sessionID: '537d3fffe20e956205f0da0c', name: 'Lecky', playtime: 28974, wins: 242, losses: 127, score: 115} + {team: 'humans', rank: 90, sessionID: '537b9edc7c89ec9805f4de89', name: 'Cemiv', playtime: 5632, wins: 241, losses: 134, score: 107} + {team: 'humans', rank: 91, sessionID: '537b8bede91b4d3b05526151', name: 'Witchy', playtime: 29809, wins: 214, losses: 110, score: 104} + {team: 'humans', rank: 92, sessionID: '535d728c30f061020b8f9893', name: 'ZeoNFrosT', playtime: 0, wins: 233, losses: 130, score: 103} + {team: 'humans', rank: 93, sessionID: '537b9c4b16613c8405155abd', name: 'JD557', playtime: 17456, wins: 236, losses: 134, score: 102} + {team: 'humans', rank: 94, sessionID: '537bdb396b018e5505b9d5ba', name: 'devast8a', playtime: 89013, wins: 233, losses: 133, score: 100} + {team: 'humans', rank: 95, sessionID: '537b7fbc5bc02238050d14ee', name: 'jojman272', playtime: 859, wins: 232, losses: 132, score: 100} + {team: 'humans', rank: 96, sessionID: '537cc552e4523d0113ba4eb2', name: 'Sir Coward', playtime: 26839, wins: 235, losses: 135, score: 100} + {team: 'humans', rank: 97, sessionID: '537b8abde91b4d3b05526103', name: 'Jef', playtime: 10311, wins: 236, losses: 139, score: 97} + {team: 'humans', rank: 98, sessionID: '537ed4db14bb1d38053b5b72', name: 'ModernBarbershop', playtime: 33894, wins: 221, losses: 129, score: 92} + {team: 'humans', rank: 99, sessionID: '537b8ba6e91b4d3b0552613c', name: 'Wiz', playtime: 1655, wins: 227, losses: 137, score: 90} + {team: 'humans', rank: 100, sessionID: '537bad3396ee90f605f2b0f9', name: 'Rnq', playtime: 14853, wins: 226, losses: 138, score: 88} + {team: 'humans', rank: 101, sessionID: '537f9d5ba7d2578f083d69b4', name: 'BLACKORP', playtime: 2869, wins: 225, losses: 138, score: 87} + {team: 'humans', rank: 102, sessionID: '537ba00e7c89ec9805f4defc', name: 'xoko814', playtime: 869, wins: 225, losses: 139, score: 86} + {team: 'humans', rank: 103, sessionID: '5391f83082f0bc47052424c7', name: 'tarasiu', playtime: 228, wins: 225, losses: 139, score: 86} + {team: 'humans', rank: 104, sessionID: '537d26d77e1e10b705bbd0d5', name: 'Traitor', playtime: 8900, wins: 222, losses: 137, score: 85} + {team: 'humans', rank: 105, sessionID: '537bbb0a1aaa69c4052676f5', name: 'TROGDOR BURNINATE', playtime: 6630, wins: 231, losses: 146, score: 85} + {team: 'humans', rank: 106, sessionID: '5387a8a3d06c503805fda60d', name: 'masanorinyo', playtime: 68753, wins: 226, losses: 142, score: 84} + {team: 'humans', rank: 107, sessionID: '538e8593f369103805160d76', name: 'Aggar', playtime: 12492, wins: 228, losses: 144, score: 84} + {team: 'humans', rank: 108, sessionID: '537e7eac63734c630505be27', name: 'TheRealThrall', playtime: 587, wins: 224, losses: 141, score: 83} + {team: 'humans', rank: 109, sessionID: '537c8dfa26529de30cca4c43', name: 'xeno', playtime: 15394, wins: 222, losses: 142, score: 80} + {team: 'humans', rank: 110, sessionID: '537bef0b8c297aa0055d1184', name: 'Floogle', playtime: 36828, wins: 224, losses: 145, score: 79} + {team: 'humans', rank: 111, sessionID: '537c666826529de30cca38c2', name: 'Jerson Otzoy', playtime: 46519, wins: 201, losses: 122, score: 79} + {team: 'humans', rank: 112, sessionID: '537cb6b2a3cb63ea103c8000', name: 'phisixersai', playtime: 8170, wins: 224, losses: 146, score: 78} + {team: 'humans', rank: 113, sessionID: '537b9ba716613c8405155a73', name: 'Beerdroid', playtime: 2547, wins: 226, losses: 150, score: 76} + {team: 'humans', rank: 114, sessionID: '537c9bcd26529de30cca54e0', name: 'Dood', playtime: 1121, wins: 219, losses: 145, score: 74} + {team: 'humans', rank: 115, sessionID: '537c5b7c26529de30cca3439', name: 'Markoth', playtime: 787, wins: 220, losses: 147, score: 73} + {team: 'humans', rank: 116, sessionID: '537d1c297e1e10b705bbca7d', name: 'chotic', playtime: 1292, wins: 218, losses: 146, score: 72} + {team: 'humans', rank: 117, sessionID: '538484a53e0daa39051863e4', name: 'Drago', playtime: 465, wins: 217, losses: 147, score: 70} + {team: 'humans', rank: 118, sessionID: '537baaab03ff8dc005b8436c', name: 'Petteri', playtime: 15235, wins: 219, losses: 149, score: 70} + {team: 'humans', rank: 119, sessionID: '537ca0aa26529de30cca58c8', name: '3ng3l', playtime: 1703, wins: 217, losses: 147, score: 70} + {team: 'humans', rank: 120, sessionID: '537b897f5bc02238050d181c', name: 'Jremz', playtime: 8386, wins: 221, losses: 152, score: 69} + {team: 'humans', rank: 121, sessionID: '537ba85554a7b1d5053bb366', name: 'Taters', playtime: 9664, wins: 193, losses: 126, score: 67} + {team: 'humans', rank: 122, sessionID: '537b9220e91b4d3b055263ea', name: 'Listr', playtime: 34000, wins: 202, losses: 136, score: 66} + {team: 'humans', rank: 123, sessionID: '537cadbd2f6e3aee0ed581f0', name: 'satefa', playtime: 10106, wins: 220, losses: 156, score: 64} + {team: 'humans', rank: 124, sessionID: '537d0a8c84c54c6e05c05db7', name: 'redWizzard', playtime: 53180, wins: 183, losses: 120, score: 63} + {team: 'humans', rank: 125, sessionID: '536c6d1c68b5258d0c4b7da8', name: 'Tober', playtime: 452, wins: 216, losses: 153, score: 63} + {team: 'humans', rank: 126, sessionID: '535ee1e023f09c2c0836a2a7', name: '(ノಠ益ಠ)ノ彡┻━┻', playtime: 3229, wins: 218, losses: 158, score: 60} + {team: 'humans', rank: 127, sessionID: '5371626351ce9b3a05d95d5c', name: 'Perrekus', playtime: 9047, wins: 215, losses: 158, score: 57} + {team: 'humans', rank: 128, sessionID: '53968372e1b8fd0c08c693d5', name: 'leoTest', playtime: 10739, wins: 215, losses: 158, score: 57} + {team: 'humans', rank: 129, sessionID: '537cfcd69cce053a05c04ce1', name: 'Soulnai', playtime: 22641, wins: 210, losses: 154, score: 56} + {team: 'humans', rank: 130, sessionID: '537bf57795356a43065f7403', name: 'Mordecai', playtime: 11262, wins: 215, losses: 159, score: 56} + {team: 'humans', rank: 131, sessionID: '5377aabf05e1483905cb99d5', name: 'Umaris', playtime: 23418, wins: 211, losses: 156, score: 55} + {team: 'humans', rank: 132, sessionID: '537c93ce26529de30cca5029', name: 'Willybe', playtime: 4772, wins: 212, losses: 158, score: 54} + {team: 'humans', rank: 133, sessionID: '537babf403838cf0050ace06', name: 'Brian Humphrey', playtime: 7300, wins: 212, losses: 158, score: 54} + {team: 'humans', rank: 134, sessionID: '537e19e30efa6a37059e0b4f', name: 'Aqrrc', playtime: 5003, wins: 210, losses: 163, score: 47} + {team: 'humans', rank: 135, sessionID: '5395d19622ca0e39054ea5b1', name: 'anykey', playtime: 29278, wins: 201, losses: 155, score: 46} + {team: 'humans', rank: 136, sessionID: '537b7fd6e91b4d3b05525da3', name: 'Gily', playtime: 17673, wins: 205, losses: 163, score: 42} + {team: 'humans', rank: 137, sessionID: '537bbbcb3dc5f3c3055c3040', name: 'roseaboveit', playtime: 12398, wins: 205, losses: 168, score: 37} + {team: 'humans', rank: 138, sessionID: '538757897d99a7390561bb7f', name: 'Jeremy', playtime: 6842, wins: 199, losses: 166, score: 33} + {team: 'humans', rank: 139, sessionID: '537b8b845bc02238050d18e8', name: 'Abel Soares Siqueira', playtime: 4945, wins: 204, losses: 171, score: 33} + {team: 'humans', rank: 140, sessionID: '537b8a37e91b4d3b055260c9', name: 'mattmatt', playtime: 77241, wins: 198, losses: 166, score: 32} + {team: 'humans', rank: 141, sessionID: '537fc26d2a5a5acd08dbb0a5', name: 'Melrakal', playtime: 2393, wins: 200, losses: 173, score: 27} + {team: 'humans', rank: 142, sessionID: '537bd8a73dd7d35105f5fd6a', name: 'drakiac', playtime: 14601, wins: 196, losses: 169, score: 27} + {team: 'humans', rank: 143, sessionID: '537cea3d9cce053a05c04226', name: 'CNKLC', playtime: 11663, wins: 200, losses: 175, score: 25} + {team: 'humans', rank: 144, sessionID: '537bf9c20ff88b2c06286e7c', name: 'Jotipalo', playtime: 4124, wins: 199, losses: 176, score: 23} + {team: 'humans', rank: 145, sessionID: '53807d9405e52a3305de99f5', name: 'Booya', playtime: 118149, wins: 173, losses: 152, score: 21} + {team: 'humans', rank: 146, sessionID: '537bf291d3443b2b068c1056', name: 'Penguin', playtime: 7688, wins: 196, losses: 176, score: 20} + {team: 'humans', rank: 147, sessionID: '5380b82005e52a3305deb679', name: 'TheWrightDev', playtime: 26967, wins: 194, losses: 176, score: 18} + {team: 'humans', rank: 148, sessionID: '537cf2aa98a1be440545d878', name: 'Kipernicus', playtime: 11906, wins: 189, losses: 181, score: 8} + {team: 'humans', rank: 149, sessionID: '535e1f1187ab8481075b8d95', name: 'freek', playtime: 0, wins: 190, losses: 183, score: 7} + {team: 'humans', rank: 150, sessionID: '535f0911d42bda62085e40fc', name: 'heated', playtime: 65, wins: 188, losses: 182, score: 6} + {team: 'humans', rank: 151, sessionID: '539120d882f0bc470523cd6f', name: 'Fitbos', playtime: 1622, wins: 0, losses: 0, score: 0} + {team: 'humans', rank: 152, sessionID: '539875130599fa3a05ca7293', name: 'jeimmy', playtime: 663, wins: 0, losses: 0, score: 0} + {team: 'humans', rank: 153, sessionID: '537b7ccce91b4d3b05525cdc', name: 'Bart2121', playtime: 4177, wins: 184, losses: 187, score: -3} + {team: 'humans', rank: 154, sessionID: '53866ed58ca8b1120b8b816d', name: 'Nikolai', playtime: 26320, wins: 184, losses: 187, score: -3} + {team: 'humans', rank: 155, sessionID: '5385610f3e0daa390518e2f6', name: 'Stravinsky', playtime: 8870, wins: 182, losses: 185, score: -3} + {team: 'humans', rank: 156, sessionID: '537b94956c13497e05de816e', name: 'Maix', playtime: 3163, wins: 183, losses: 186, score: -3} + {team: 'humans', rank: 157, sessionID: '537187dcce8e453b05c9d21c', name: 'NasytToast', playtime: 0, wins: 183, losses: 188, score: -5} + {team: 'humans', rank: 158, sessionID: '537bb696dd932f6b05d370fd', name: 'HandmadeMercury', playtime: 5539, wins: 169, losses: 175, score: -6} + {team: 'humans', rank: 159, sessionID: '537b7f605bc02238050d14c9', name: 'Jaden', playtime: 10547, wins: 182, losses: 192, score: -10} + {team: 'humans', rank: 160, sessionID: '537c489314aaabe80c69f413', name: 'HiddEnigma', playtime: 5850, wins: 181, losses: 191, score: -10} + {team: 'humans', rank: 161, sessionID: '537bb7cd1e8dd17a054c1044', name: 'Alexander the Grape', playtime: 30398, wins: 178, losses: 189, score: -11} + {team: 'humans', rank: 162, sessionID: '538eada37558763705255a0c', name: 'Evran', playtime: 22253, wins: 179, losses: 192, score: -13} + {team: 'humans', rank: 163, sessionID: '5386aedf7d99a7390561802a', name: 'Reclusiarch', playtime: 3281, wins: 178, losses: 192, score: -14} + {team: 'humans', rank: 164, sessionID: '538b7202b924da3905157e07', name: 'Mlatic', playtime: 723, wins: 176, losses: 190, score: -14} + {team: 'humans', rank: 165, sessionID: '537c4411c209bbd60c16a3d8', name: 'liorst1', playtime: 14571, wins: 178, losses: 193, score: -15} + {team: 'humans', rank: 166, sessionID: '537fcaee2a5a5acd08dbb79c', name: 'Booya2nd', playtime: 9598, wins: 153, losses: 168, score: -15} + {team: 'humans', rank: 167, sessionID: '538ae84fb924da3905154172', name: 'WAAW', playtime: 3668, wins: 177, losses: 194, score: -17} + {team: 'humans', rank: 168, sessionID: '538751b78ca8b1120b8c0792', name: 'DZC', playtime: 5512, wins: 170, losses: 188, score: -18} + {team: 'humans', rank: 169, sessionID: '537c0ab50ff88b2c0628792e', name: 'maxily', playtime: 18792, wins: 174, losses: 192, score: -18} + {team: 'humans', rank: 170, sessionID: '537ba1347c89ec9805f4df76', name: 'qkhhly', playtime: 9518, wins: 176, losses: 196, score: -20} + {team: 'humans', rank: 171, sessionID: '538b4bbdd06c503805ff3b8a', name: 'iamcodewar', playtime: 10939, wins: 178, losses: 198, score: -20} + {team: 'humans', rank: 172, sessionID: '537f14e18fe881f1055df20a', name: 'Alanor', playtime: 20437, wins: 150, losses: 174, score: -24} + {team: 'humans', rank: 173, sessionID: '537f57ff3282d7a507695039', name: 'Navi\' Dendi', playtime: 4382, wins: 172, losses: 197, score: -25} + {team: 'humans', rank: 174, sessionID: '537c14950ff88b2c06287f22', name: 'lolka', playtime: 3820, wins: 172, losses: 200, score: -28} + {team: 'humans', rank: 175, sessionID: '53570b7a1bfa9bba14b5e045', name: 'Scott', playtime: 6228, wins: 173, losses: 202, score: -29} + {team: 'humans', rank: 176, sessionID: '537bbd0f3cd816fa05a48401', name: 'DonutBaron', playtime: 9716, wins: 165, losses: 195, score: -30} + {team: 'humans', rank: 177, sessionID: '5381726d7585483905a7f978', name: 'armlol', playtime: 5149, wins: 171, losses: 204, score: -33} + {team: 'humans', rank: 178, sessionID: '538c0bfb56c36139052fa076', name: 'Aura Temple Network', playtime: 7489, wins: 169, losses: 205, score: -36} + {team: 'humans', rank: 179, sessionID: '538ec77af3691038051629c3', name: 'BI', playtime: 3870, wins: 164, losses: 200, score: -36} + {team: 'humans', rank: 180, sessionID: '537b889fe91b4d3b0552603e', name: 'McDerp', playtime: 3415, wins: 161, losses: 203, score: -42} + {team: 'humans', rank: 181, sessionID: '537d169a7e1e10b705bbc736', name: 'Nitor', playtime: 7036, wins: 159, losses: 205, score: -46} + {team: 'humans', rank: 182, sessionID: '53837eee6f3bea3a05faf5fb', name: 'HeadCrusher', playtime: 22806, wins: 133, losses: 182, score: -49} + {team: 'humans', rank: 183, sessionID: '537ba4887c89ec9805f4e10d', name: 'Geralt', playtime: 2353, wins: 158, losses: 208, score: -50} + {team: 'humans', rank: 184, sessionID: '53802aab05e52a3305de797e', name: 'micblayo', playtime: 14726, wins: 159, losses: 209, score: -50} + {team: 'humans', rank: 185, sessionID: '538b60bdb924da39051576e2', name: 'mydoom', playtime: 9270, wins: 159, losses: 209, score: -50} + {team: 'humans', rank: 186, sessionID: '5380f3917585483905a7c0b3', name: 'Lalaland1125', playtime: 689, wins: 160, losses: 211, score: -51} + {team: 'humans', rank: 187, sessionID: '537b8125e91b4d3b05525e1e', name: 'Garrett', playtime: 1833, wins: 157, losses: 212, score: -55} + {team: 'humans', rank: 188, sessionID: '537b8c60e91b4d3b05526181', name: 'Usopp', playtime: 8340, wins: 156, losses: 217, score: -61} + {team: 'humans', rank: 189, sessionID: '537b9b4116613c8405155a41', name: 'Y0DA', playtime: 5351, wins: 154, losses: 216, score: -62} + {team: 'humans', rank: 190, sessionID: '5387f127d06c503805fdcd97', name: 'Hexadecimage', playtime: 89476, wins: 151, losses: 222, score: -71} + {team: 'humans', rank: 191, sessionID: '539265012446a44105389a8c', name: 'odeakihumi', playtime: 23819, wins: 143, losses: 219, score: -76} + {team: 'humans', rank: 192, sessionID: '537ba73a980cfcba051f19c5', name: 'Torg', playtime: 7045, wins: 145, losses: 221, score: -76} + {team: 'humans', rank: 193, sessionID: '5392bbc0e04ba13805ed4c0f', name: 'iownspace', playtime: 51659, wins: 146, losses: 223, score: -77} + {team: 'humans', rank: 194, sessionID: '537bf14bf8b46fbd0544fc18', name: 'danshou', playtime: 22590, wins: 148, losses: 226, score: -78} + {team: 'humans', rank: 195, sessionID: '537b212dfe0ec03905fcd712', name: 'ThunderClan', playtime: 766, wins: 144, losses: 228, score: -84} + {team: 'humans', rank: 196, sessionID: '536540d51415c79e648b1de5', name: 'Nick04 Bubonic', playtime: 12, wins: 138, losses: 222, score: -84} + {team: 'humans', rank: 197, sessionID: '537fb0792a5a5acd08dba76f', name: 'Slackus', playtime: 49736, wins: 141, losses: 226, score: -85} + {team: 'humans', rank: 198, sessionID: '537d44911333605305550411', name: 'tehowner', playtime: 2969, wins: 138, losses: 223, score: -85} + {team: 'humans', rank: 199, sessionID: '537df429933d99860613ab2d', name: 'Farafonoff', playtime: 4315, wins: 142, losses: 228, score: -86} + {team: 'humans', rank: 200, sessionID: '538501137d99a7390560db54', name: 'Joodoc', playtime: 6042, wins: 144, losses: 231, score: -87} + {team: 'humans', rank: 201, sessionID: '537b8a58e91b4d3b055260d8', name: 'Terebijoke', playtime: 85680, wins: 122, losses: 210, score: -88} + {team: 'humans', rank: 202, sessionID: '537c110195356a43065f8450', name: 'Chen Yu LIu', playtime: 843, wins: 140, losses: 232, score: -92} + {team: 'humans', rank: 203, sessionID: '537dba4613add33a051bf680', name: 'Bobbybaby', playtime: 1509, wins: 140, losses: 232, score: -92} + {team: 'humans', rank: 204, sessionID: '537b9003e91b4d3b05526329', name: 'Coreth', playtime: 11677, wins: 131, losses: 224, score: -93} + {team: 'humans', rank: 205, sessionID: '538b618bd06c503805ff4210', name: 'robat', playtime: 5776, wins: 138, losses: 234, score: -96} + {team: 'humans', rank: 206, sessionID: '5383b7196f3bea3a05fb1472', name: 'lilos', playtime: 2464, wins: 135, losses: 232, score: -97} + {team: 'humans', rank: 207, sessionID: '537f8672d409ac270861c842', name: 'ThatOtherPerson', playtime: 2018, wins: 137, losses: 236, score: -99} + {team: 'humans', rank: 208, sessionID: '53809c2c7585483905a795f1', name: '都比', playtime: 28855, wins: 136, losses: 235, score: -99} + {team: 'humans', rank: 209, sessionID: '537c866f14aaabe80c6a0f90', name: 'Energy', playtime: 1276, wins: 130, losses: 229, score: -99} + {team: 'humans', rank: 210, sessionID: '538e4af0755876370525291c', name: 'commando Tech', playtime: 3725, wins: 136, losses: 236, score: -100} + {team: 'humans', rank: 211, sessionID: '537b9da67c89ec9805f4de0b', name: 'tembelu', playtime: 9298, wins: 129, losses: 230, score: -101} + {team: 'humans', rank: 212, sessionID: '53972a5f2546283905a3bdc5', name: 'holyKoT', playtime: 2171, wins: 131, losses: 241, score: -110} + {team: 'humans', rank: 213, sessionID: '537ba6dd980cfcba051f199d', name: 'Aaron1011', playtime: 3449, wins: 130, losses: 240, score: -110} + {team: 'humans', rank: 214, sessionID: '537c68bf26529de30cca39cb', name: 'ESWAT', playtime: 893, wins: 128, losses: 239, score: -111} + {team: 'humans', rank: 215, sessionID: '537d5fdb3dcf67c40571fb13', name: 'JustTurrable', playtime: 264, wins: 125, losses: 240, score: -115} + {team: 'humans', rank: 216, sessionID: '537e4268e1489fe206667e26', name: 'EvanK', playtime: 668, wins: 125, losses: 245, score: -120} + {team: 'humans', rank: 217, sessionID: '537be834a3b60b390500e0a3', name: 'gilxa1226', playtime: 394, wins: 125, losses: 245, score: -120} + {team: 'humans', rank: 218, sessionID: '537bbcfd9e1bf5f905926ebf', name: 'Qin Shi Huang', playtime: 4691, wins: 125, losses: 246, score: -121} + {team: 'humans', rank: 219, sessionID: '537b9bd016613c8405155a8b', name: 'WaffleFries', playtime: 2944, wins: 121, losses: 246, score: -125} + {team: 'humans', rank: 220, sessionID: '537b8a65e91b4d3b055260e0', name: 'Gurra', playtime: 6295, wins: 107, losses: 233, score: -126} + {team: 'humans', rank: 221, sessionID: '537e2025933d99860613c614', name: 'Encosia', playtime: 2025, wins: 118, losses: 250, score: -132} + {team: 'humans', rank: 222, sessionID: '537bb694dd932f6b05d370fc', name: 'Kaboomm', playtime: 4333, wins: 116, losses: 253, score: -137} + {team: 'humans', rank: 223, sessionID: '538001aebf8ae33a0501b98e', name: 'taichi_kunnn', playtime: 3524, wins: 112, losses: 254, score: -142} + {team: 'humans', rank: 224, sessionID: '53630b6573bdb4f7045a772c', name: 'Lonib', playtime: 0, wins: 113, losses: 257, score: -144} + {team: 'humans', rank: 225, sessionID: '5360f83b67c29a0609ddceb4', name: 'Readper', playtime: 0, wins: 109, losses: 264, score: -155} + {team: 'humans', rank: 226, sessionID: '53717f4551ce9b3a05d96043', name: 'cpkenn09y', playtime: 0, wins: 106, losses: 263, score: -157} + {team: 'humans', rank: 227, sessionID: '537b9b9416613c8405155a6b', name: 'Rubini', playtime: 6763, wins: 103, losses: 271, score: -168} + {team: 'humans', rank: 228, sessionID: '53902ad775587637052615d9', name: 'Loxk', playtime: 32690, wins: 89, losses: 265, score: -176} + {team: 'humans', rank: 229, sessionID: '537b93886c13497e05de80a6', name: 'Klomnar', playtime: 405, wins: 98, losses: 274, score: -176} + {team: 'humans', rank: 230, sessionID: '537b9c7c16613c8405155ae0', name: 'dpen2000', playtime: 4313, wins: 93, losses: 273, score: -180} + {team: 'humans', rank: 231, sessionID: '53692c2d84e82a3a0553305e', name: 'rnprdk', playtime: 0, wins: 94, losses: 278, score: -184} + {team: 'humans', rank: 232, sessionID: '537be99f20a501380564e764', name: 'rizend', playtime: 3017, wins: 92, losses: 279, score: -187} + {team: 'humans', rank: 233, sessionID: '537ba94d54a7b1d5053bb426', name: 'Rokner', playtime: 3911, wins: 90, losses: 282, score: -192} + {team: 'humans', rank: 234, sessionID: '537b949e556db17605be74ff', name: 'baldeagle', playtime: 7698, wins: 91, losses: 284, score: -193} + {team: 'humans', rank: 235, sessionID: '535f0cdfc2e83ad9048faef0', name: 'Mobius', playtime: 0, wins: 87, losses: 288, score: -201} + {team: 'humans', rank: 236, sessionID: '537bbe446d5f9f2f06e0c674', name: 'Lakk', playtime: 12072, wins: 76, losses: 296, score: -220} + {team: 'humans', rank: 237, sessionID: '535ac395d83daa1a052494c1', name: 'Michael S.', playtime: 304, wins: 68, losses: 304, score: -236} + {team: 'humans', rank: 238, sessionID: '53718c6cce8e453b05c9d298', name: 'Blitz', playtime: 0, wins: 68, losses: 306, score: -238} + {team: 'humans', rank: 239, sessionID: '536310848e22980605aa58c3', name: 'sjarvie', playtime: 0, wins: 66, losses: 308, score: -242} + {team: 'humans', rank: 240, sessionID: '537ba10e51e98aa705b605df', name: 'Deleu', playtime: 7241, wins: 61, losses: 307, score: -246} + {team: 'humans', rank: 241, sessionID: '537b92765bc02238050d1bf0', name: 'Deneim', playtime: 13791, wins: 62, losses: 312, score: -250} + {team: 'humans', rank: 242, sessionID: '538e609af36910380515f8d6', name: 'Volgax', playtime: 6774, wins: 59, losses: 310, score: -251} + {team: 'humans', rank: 243, sessionID: '537ba62557494fc405a6faac', name: 'Zandrasco', playtime: 4193, wins: 60, losses: 315, score: -255} + {team: 'humans', rank: 244, sessionID: '537ecf5414bb1d38053b58bb', name: 'Sir Mouse', playtime: 16021, wins: 52, losses: 321, score: -269} + {team: 'humans', rank: 245, sessionID: '538c8faf5572d43b05214e3b', name: 'AceWizard', playtime: 54, wins: 45, losses: 315, score: -270} + {team: 'humans', rank: 246, sessionID: '537deb820efa6a37059df268', name: 'MadMan30', playtime: 316, wins: 46, losses: 319, score: -273} + {team: 'humans', rank: 247, sessionID: '537bf38495356a43065f7291', name: 'NicRio', playtime: 130, wins: 43, losses: 316, score: -273} + {team: 'humans', rank: 248, sessionID: '537cd876665bde1b13ffdad4', name: 'Is_G', playtime: 776, wins: 44, losses: 319, score: -275} + {team: 'humans', rank: 249, sessionID: '537bb14b4f81f53805b6366a', name: 'jeromeASF', playtime: 335, wins: 41, losses: 318, score: -277} + {team: 'humans', rank: 250, sessionID: '5381745005e52a3305df1c23', name: 'El Psy Congr00', playtime: 1032, wins: 41, losses: 319, score: -278} + {team: 'humans', rank: 251, sessionID: '538451183e0daa39051845a0', name: 'loquele', playtime: 549, wins: 43, losses: 322, score: -279} + {team: 'humans', rank: 252, sessionID: '537b606a2daeeb3905a9292f', name: 'DeathStalker', playtime: 166, wins: 38, losses: 319, score: -281} + {team: 'humans', rank: 253, sessionID: '537bd56ab0d1766d05243002', name: 'thelion', playtime: 338, wins: 40, losses: 323, score: -283} + {team: 'humans', rank: 254, sessionID: '537d15d37e1e10b705bbc6ef', name: 'Diegobrp', playtime: 2132, wins: 37, losses: 321, score: -284} + {team: 'humans', rank: 255, sessionID: '537caa102f6e3aee0ed57f84', name: 'Sakares Saengkaew', playtime: 34, wins: 37, losses: 321, score: -284} + {team: 'humans', rank: 256, sessionID: '53627e2fca5c6f3c11ebc9b1', name: 'Animex', playtime: 0, wins: 38, losses: 324, score: -286} + {team: 'humans', rank: 257, sessionID: '537bc0ad1c8dfa820699fcb9', name: 'Black Mage Wizard Guy', playtime: 691, wins: 37, losses: 323, score: -286} + {team: 'humans', rank: 258, sessionID: '535f07d39894af8f7fd84e85', name: 'Maksym', playtime: 0, wins: 38, losses: 327, score: -289} + {team: 'humans', rank: 259, sessionID: '537b98e33803a287057582a8', name: 'Angeland', playtime: 1758, wins: 41, losses: 330, score: -289} + {team: 'humans', rank: 260, sessionID: '537c63f426529de30cca37ba', name: 'Dmitry', playtime: 181, wins: 35, losses: 325, score: -290} + {team: 'humans', rank: 261, sessionID: '537ceb1798a1be440545d40e', name: 'jaba', playtime: 572, wins: 35, losses: 325, score: -290} + {team: 'humans', rank: 262, sessionID: '537c0f3f0ff88b2c06287c2b', name: 'Quan Pham', playtime: 4353, wins: 40, losses: 332, score: -292} + {team: 'humans', rank: 263, sessionID: '537d60467e6f2dba051060b6', name: 'rhall', playtime: 67548, wins: 11, losses: 316, score: -305} + {team: 'humans', rank: 264, sessionID: '5384c9de7d99a7390560bfd7', name: 'Secathor', playtime: 16404, wins: 28, losses: 345, score: -317} + {team: 'humans', rank: 265, sessionID: '538a08bed06c503805feb6b0', name: 'Nemoy', playtime: 1643, wins: 0, losses: 319, score: -319} + {team: 'humans', rank: 266, sessionID: '537c3806f1d9cfe4096ba9d8', name: 'Hannofcart', playtime: 17397, wins: 0, losses: 323, score: -323} + {team: 'humans', rank: 267, sessionID: '537c4d5f26529de30cca2e68', name: 'Morphumax', playtime: 58395, wins: 0, losses: 323, score: -323} + {team: 'humans', rank: 268, sessionID: '53864aa37d99a73905615dda', name: 'shoetest', playtime: 14876, wins: 0, losses: 324, score: -324} + {team: 'humans', rank: 269, sessionID: '537b97cd556db17605be76c3', name: 'domrein', playtime: 12339, wins: 0, losses: 324, score: -324} + {team: 'humans', rank: 270, sessionID: '53835f1fc85c223a05f49ddb', name: 'hace', playtime: 9175, wins: 0, losses: 325, score: -325} + {team: 'humans', rank: 271, sessionID: '53666cc75af8b2c71dc017e8', name: 'Bonesdog', playtime: 0, wins: 0, losses: 326, score: -326} + {team: 'humans', rank: 272, sessionID: '537be26d20a501380564e359', name: 'Cinnamon Scrolls', playtime: 6619, wins: 0, losses: 330, score: -330} + {team: 'humans', rank: 273, sessionID: '537b8f3ce91b4d3b055262d7', name: 'asdasd', playtime: 242330, wins: 0, losses: 335, score: -335} + {team: 'humans', rank: 274, sessionID: '5383551cc85c223a05f49992', name: 'marthyi', playtime: 30008, wins: 325, losses: 43, score: 282} + {team: 'humans', rank: 275, sessionID: '538f5334f369103805167613', name: 'Leshka', playtime: 10409, wins: 93, losses: 282, score: -189} ] results.greed.ogres = [ - {team: "ogres", rank: 1, sessionID: "537b958e6c13497e05de81f2", name: "Bellardia", playtime: 189111, wins: 387, losses: 7, score: 380} - {team: "ogres", rank: 2, sessionID: "537c11df95356a43065f84c9", name: "blinkingTore", playtime: 38360, wins: 381, losses: 9, score: 372} - {team: "ogres", rank: 3, sessionID: "537c09ee95356a43065f801c", name: "Eye", playtime: 172960, wins: 370, losses: 18, score: 352} - {team: "ogres", rank: 4, sessionID: "537b7d475bc02238050d1439", name: "Cripi", playtime: 61966, wins: 373, losses: 23, score: 350} - {team: "ogres", rank: 5, sessionID: "537e317450d1673a054b7dd2", name: "Pop-up", playtime: 39939, wins: 369, losses: 26, score: 343} - {team: "ogres", rank: 6, sessionID: "537e364a50d1673a054b8322", name: "Ravenclaw", playtime: 4579, wins: 367, losses: 24, score: 343} - {team: "ogres", rank: 7, sessionID: "537cb51fa0d7a5cc10992b11", name: "JerryP", playtime: 52872, wins: 368, losses: 33, score: 335} - {team: "ogres", rank: 8, sessionID: "537bd37888a86e67053f9d61", name: "Mickydtron", playtime: 38533, wins: 368, losses: 35, score: 333} - {team: "ogres", rank: 9, sessionID: "5384a3f63e0daa390518765d", name: "ProfBoesch", playtime: 10366, wins: 365, losses: 34, score: 331} - {team: "ogres", rank: 10, sessionID: "538064d27585483905a77f9f", name: "KaosWalking", playtime: 88663, wins: 359, losses: 35, score: 324} - {team: "ogres", rank: 11, sessionID: "53892a98d06c503805fe522b", name: "Urdaris", playtime: 87750, wins: 353, losses: 32, score: 321} - {team: "ogres", rank: 12, sessionID: "53668d64c6ab10ef1ea9a10d", name: "no_login_found", playtime: 11313, wins: 355, losses: 46, score: 309} - {team: "ogres", rank: 13, sessionID: "537f68bc14f08dec07950945", name: "Take it easy", playtime: 2839, wins: 348, losses: 47, score: 301} - {team: "ogres", rank: 14, sessionID: "537bac56b0d477e005347f67", name: "gosunero", playtime: 41429, wins: 346, losses: 54, score: 292} - {team: "ogres", rank: 15, sessionID: "536d258f68b5258d0c4b96ed", name: "Jex", playtime: 4910, wins: 337, losses: 48, score: 289} - {team: "ogres", rank: 16, sessionID: "537bcba8a797656f07c93db5", name: "Durbination", playtime: 13465, wins: 337, losses: 49, score: 288} - {team: "ogres", rank: 17, sessionID: "5381e48a7585483905a82a2d", name: "Edoardo Morandi", playtime: 96844, wins: 330, losses: 49, score: 281} - {team: "ogres", rank: 18, sessionID: "538471737d99a73905608fb4", name: "Artraxus", playtime: 61114, wins: 336, losses: 60, score: 276} - {team: "ogres", rank: 19, sessionID: "537ba9a154a7b1d5053bb45a", name: "skeltoac", playtime: 39087, wins: 330, losses: 55, score: 275} - {team: "ogres", rank: 20, sessionID: "537be145a3b60b390500dcc3", name: "ReyO", playtime: 204112, wins: 328, losses: 55, score: 273} - {team: "ogres", rank: 21, sessionID: "537cc939665bde1b13ffd197", name: "Orson Peters", playtime: 24821, wins: 333, losses: 60, score: 273} - {team: "ogres", rank: 22, sessionID: "5395cf0b7362c439054f7c3a", name: "nino48", playtime: 33541, wins: 327, losses: 62, score: 265} - {team: "ogres", rank: 23, sessionID: "537d541e3dcf67c40571f792", name: "pbd", playtime: 4062, wins: 319, losses: 84, score: 235} - {team: "ogres", rank: 24, sessionID: "537e284650d1673a054b7602", name: "Tech", playtime: 13208, wins: 306, losses: 71, score: 235} - {team: "ogres", rank: 25, sessionID: "537d025184c54c6e05c059b7", name: "Storm0x2a", playtime: 1026, wins: 306, losses: 71, score: 235} - {team: "ogres", rank: 26, sessionID: "537bed83f575b482052f03a0", name: "Blindfold", playtime: 45865, wins: 303, losses: 69, score: 234} - {team: "ogres", rank: 27, sessionID: "537bc4750de0a02c07e8797f", name: "Walter Danilo Galante", playtime: 24476, wins: 313, losses: 84, score: 229} - {team: "ogres", rank: 28, sessionID: "538d0a4356c3613905301e50", name: "Fedux", playtime: 1862, wins: 300, losses: 79, score: 221} - {team: "ogres", rank: 29, sessionID: "537b8cbee91b4d3b0552619e", name: "Nazywam", playtime: 6395, wins: 303, losses: 83, score: 220} - {team: "ogres", rank: 30, sessionID: "5382502a7585483905a85e42", name: "vlizard", playtime: 803, wins: 308, losses: 89, score: 219} - {team: "ogres", rank: 31, sessionID: "5385d1cf3e0daa3905191e57", name: "olu", playtime: 65635, wins: 301, losses: 86, score: 215} - {team: "ogres", rank: 32, sessionID: "537babd003838cf0050acdf2", name: "Pentar", playtime: 36006, wins: 309, losses: 95, score: 214} - {team: "ogres", rank: 33, sessionID: "537c31112b08c344082e22de", name: "Agathanar", playtime: 41371, wins: 308, losses: 94, score: 214} - {team: "ogres", rank: 34, sessionID: "537cd98ae4523d0113ba5ac7", name: "Tehvudgaw", playtime: 81681, wins: 298, losses: 94, score: 204} - {team: "ogres", rank: 35, sessionID: "537b803ae91b4d3b05525dc7", name: "Forsaken", playtime: 50237, wins: 294, losses: 91, score: 203} - {team: "ogres", rank: 36, sessionID: "537b7e44e91b4d3b05525d38", name: "COGSMITH", playtime: 284674, wins: 300, losses: 98, score: 202} - {team: "ogres", rank: 37, sessionID: "537ba3e0903fd2b80515539d", name: "Statik", playtime: 64062, wins: 294, losses: 98, score: 196} - {team: "ogres", rank: 38, sessionID: "537b85e15bc02238050d16d4", name: "Cuef", playtime: 81666, wins: 286, losses: 90, score: 196} - {team: "ogres", rank: 39, sessionID: "5392f7b1304ab93805efa3d2", name: "Cracker", playtime: 2576, wins: 282, losses: 90, score: 192} - {team: "ogres", rank: 40, sessionID: "537b9c42ffeaa29e051b2657", name: "JamesJNadeau.com", playtime: 28164, wins: 295, losses: 110, score: 185} - {team: "ogres", rank: 41, sessionID: "537ce37be9c4e97c05e3ea66", name: "Quasar", playtime: 21773, wins: 287, losses: 104, score: 183} - {team: "ogres", rank: 42, sessionID: "537baa2403ff8dc005b8433e", name: "Almatia", playtime: 15387, wins: 291, losses: 109, score: 182} - {team: "ogres", rank: 43, sessionID: "537b87f55bc02238050d1786", name: "mordonne", playtime: 71830, wins: 277, losses: 103, score: 174} - {team: "ogres", rank: 44, sessionID: "537e56129008f87b0541cd03", name: "O'Connor", playtime: 55869, wins: 281, losses: 109, score: 172} - {team: "ogres", rank: 45, sessionID: "537ba9e57b9ffadb05476784", name: "timmox", playtime: 13280, wins: 256, losses: 86, score: 170} - {team: "ogres", rank: 46, sessionID: "537b86e75bc02238050d1721", name: "Tomas", playtime: 21845, wins: 275, losses: 106, score: 169} - {team: "ogres", rank: 47, sessionID: "537bebbea3b60b390500e280", name: "Buge", playtime: 3506, wins: 281, losses: 118, score: 163} - {team: "ogres", rank: 48, sessionID: "53854c0b7d99a7390560f9f4", name: "MatBot", playtime: 15049, wins: 281, losses: 119, score: 162} - {team: "ogres", rank: 49, sessionID: "5380a9bb7585483905a79dff", name: "salesman", playtime: 60290, wins: 277, losses: 118, score: 159} - {team: "ogres", rank: 50, sessionID: "53949f635009fe5b075bb584", name: "Dematerial", playtime: 4661, wins: 273, losses: 116, score: 157} - {team: "ogres", rank: 51, sessionID: "53832a3ec85c223a05f48736", name: "Popey", playtime: 37593, wins: 256, losses: 104, score: 152} - {team: "ogres", rank: 52, sessionID: "537b89a2e91b4d3b05526082", name: "Ryemane", playtime: 20671, wins: 276, losses: 125, score: 151} - {team: "ogres", rank: 53, sessionID: "537cd542e4523d0113ba5782", name: "schups", playtime: 20886, wins: 277, losses: 127, score: 150} - {team: "ogres", rank: 54, sessionID: "537be1cca3b60b390500dd24", name: "ohsnap", playtime: 3574, wins: 273, losses: 127, score: 146} - {team: "ogres", rank: 55, sessionID: "538bef7356c36139052f8c80", name: "Hephaestian", playtime: 9626, wins: 272, losses: 131, score: 141} - {team: "ogres", rank: 56, sessionID: "537c527026529de30cca302f", name: "Jinrai", playtime: 23726, wins: 269, losses: 129, score: 140} - {team: "ogres", rank: 57, sessionID: "538471087d99a73905608f84", name: "Basque", playtime: 37986, wins: 269, losses: 130, score: 139} - {team: "ogres", rank: 58, sessionID: "537cd3c3665bde1b13ffd74c", name: "Stormaggedon Dark Lord of All", playtime: 27471, wins: 261, losses: 123, score: 138} - {team: "ogres", rank: 59, sessionID: "537b984f3803a2870575824f", name: "Cody", playtime: 85426, wins: 259, losses: 138, score: 121} - {team: "ogres", rank: 60, sessionID: "5383ead92757353805a96ff4", name: "hotdogeater", playtime: 55657, wins: 258, losses: 137, score: 121} - {team: "ogres", rank: 61, sessionID: "537d2a397e1e10b705bbd2c8", name: "PatchworkKnight", playtime: 23663, wins: 257, losses: 138, score: 119} - {team: "ogres", rank: 62, sessionID: "537b8185e91b4d3b05525e3c", name: "FlameFrost", playtime: 29939, wins: 251, losses: 142, score: 109} - {team: "ogres", rank: 63, sessionID: "537bb4168623bc410575f208", name: "NitrousDave", playtime: 29420, wins: 252, losses: 143, score: 109} - {team: "ogres", rank: 64, sessionID: "537f4fa1c3067a7b07ba7786", name: "Zodd", playtime: 8820, wins: 248, losses: 140, score: 108} - {team: "ogres", rank: 65, sessionID: "538358b978171d3d057eb471", name: "Lololala", playtime: 39892, wins: 252, losses: 144, score: 108} - {team: "ogres", rank: 66, sessionID: "537f224c8fe881f1055dfb7e", name: "Artoemius", playtime: 1470, wins: 251, losses: 150, score: 101} - {team: "ogres", rank: 67, sessionID: "537b7b25e91b4d3b05525b61", name: "Makaze", playtime: 21714, wins: 248, losses: 149, score: 99} - {team: "ogres", rank: 68, sessionID: "537cf18c9cce053a05c0467f", name: "CodeBane", playtime: 39749, wins: 233, losses: 137, score: 96} - {team: "ogres", rank: 69, sessionID: "537baac910c8a6e405b9cf92", name: "cooler", playtime: 49558, wins: 229, losses: 134, score: 95} - {team: "ogres", rank: 70, sessionID: "5380d0a405e52a3305dec328", name: "DoctorTacoPhD", playtime: 9723, wins: 249, losses: 155, score: 94} - {team: "ogres", rank: 71, sessionID: "53948cfc5009fe5b075ba92d", name: "zeus1200", playtime: 236, wins: 246, losses: 152, score: 94} - {team: "ogres", rank: 72, sessionID: "537c66d114aaabe80c6a0072", name: "Vratislav", playtime: 21203, wins: 237, losses: 144, score: 93} - {team: "ogres", rank: 73, sessionID: "537b996016613c8405155922", name: "Dafe", playtime: 701, wins: 232, losses: 140, score: 92} - {team: "ogres", rank: 74, sessionID: "537b8271e91b4d3b05525e8e", name: "@billyvg", playtime: 20844, wins: 243, losses: 154, score: 89} - {team: "ogres", rank: 75, sessionID: "537caafc2f6e3aee0ed58007", name: "Sakares", playtime: 1257, wins: 237, losses: 151, score: 86} - {team: "ogres", rank: 76, sessionID: "538142de05e52a3305df037d", name: "Meowth", playtime: 12054, wins: 241, losses: 155, score: 86} - {team: "ogres", rank: 77, sessionID: "537155a1ee35af3905987a87", name: "Lanner", playtime: 3658, wins: 236, losses: 152, score: 84} - {team: "ogres", rank: 78, sessionID: "537b99573803a287057582e3", name: "DavyWong", playtime: 16467, wins: 242, losses: 161, score: 81} - {team: "ogres", rank: 79, sessionID: "537be8fda3b60b390500e105", name: "BeAsT MoDe", playtime: 2097, wins: 234, losses: 153, score: 81} - {team: "ogres", rank: 80, sessionID: "537b96696c13497e05de8271", name: "vkeg", playtime: 1883, wins: 236, losses: 157, score: 79} - {team: "ogres", rank: 81, sessionID: "537ca60cb128a1850e083077", name: "SPAMR", playtime: 19978, wins: 233, losses: 154, score: 79} - {team: "ogres", rank: 82, sessionID: "537b5662fe0ec03905fcdcd4", name: "pages", playtime: 22679, wins: 231, losses: 155, score: 76} - {team: "ogres", rank: 83, sessionID: "537bf90295356a43065f7640", name: "", playtime: 167, wins: 218, losses: 144, score: 74} - {team: "ogres", rank: 84, sessionID: "535de130c969efa7053345ab", name: "Racksickle", playtime: 319, wins: 231, losses: 157, score: 74} - {team: "ogres", rank: 85, sessionID: "537c2facf67b6b1c08af376f", name: "greyworm", playtime: 22755, wins: 234, losses: 160, score: 74} - {team: "ogres", rank: 86, sessionID: "537eef8c8fe881f1055dddb6", name: "huang123", playtime: 2590, wins: 234, losses: 161, score: 73} - {team: "ogres", rank: 87, sessionID: "53934430304ab93805efcf4f", name: "LilDooda", playtime: 16603, wins: 229, losses: 156, score: 73} - {team: "ogres", rank: 88, sessionID: "5389c83fb924da39051485d2", name: "nineties", playtime: 58607, wins: 183, losses: 113, score: 70} - {team: "ogres", rank: 89, sessionID: "537b760f1ed81a3b05c4fbfe", name: "Xavion", playtime: 3593, wins: 229, losses: 159, score: 70} - {team: "ogres", rank: 90, sessionID: "5383ec74087dc139054d8658", name: "cattycat", playtime: 384, wins: 228, losses: 160, score: 68} - {team: "ogres", rank: 91, sessionID: "538375bb78171d3d057ebdb6", name: "Johnwg7", playtime: 65297, wins: 233, losses: 165, score: 68} - {team: "ogres", rank: 92, sessionID: "537b99063803a287057582c1", name: "Simba", playtime: 16847, wins: 230, losses: 163, score: 67} - {team: "ogres", rank: 93, sessionID: "53929b482446a4410538b59d", name: "Buh", playtime: 28766, wins: 230, losses: 165, score: 65} - {team: "ogres", rank: 94, sessionID: "537bf9410ff88b2c06286e43", name: "Ulfberht", playtime: 26046, wins: 232, losses: 171, score: 61} - {team: "ogres", rank: 95, sessionID: "537bc6e24add491607deaaa1", name: "Victor Hugo", playtime: 31094, wins: 221, losses: 163, score: 58} - {team: "ogres", rank: 96, sessionID: "53809a807585483905a79529", name: "stderr", playtime: 20568, wins: 229, losses: 173, score: 56} - {team: "ogres", rank: 97, sessionID: "537b8643e91b4d3b05525f83", name: "Austinh100", playtime: 12405, wins: 225, losses: 176, score: 49} - {team: "ogres", rank: 98, sessionID: "537c7fad26529de30cca440d", name: "efraglebagga", playtime: 22417, wins: 219, losses: 172, score: 47} - {team: "ogres", rank: 99, sessionID: "537dde5d933d99860613a256", name: "Meojifo", playtime: 50047, wins: 222, losses: 177, score: 45} - {team: "ogres", rank: 100, sessionID: "537bc0eb467df184064bb865", name: "Diginaut", playtime: 8029, wins: 225, losses: 180, score: 45} - {team: "ogres", rank: 101, sessionID: "538390336f3bea3a05faff49", name: "Ghostly_Cookie", playtime: 5804, wins: 221, losses: 177, score: 44} - {team: "ogres", rank: 102, sessionID: "537f2cb8fdacc2fa050231bf", name: "crazydiv", playtime: 12170, wins: 212, losses: 170, score: 42} - {team: "ogres", rank: 103, sessionID: "537ef0e78fe881f1055dde46", name: "Æ", playtime: 97439, wins: 204, losses: 163, score: 41} - {team: "ogres", rank: 104, sessionID: "537b96f216613c84051557f1", name: "mda", playtime: 11544, wins: 222, losses: 181, score: 41} - {team: "ogres", rank: 105, sessionID: "537b8231e91b4d3b05525e7e", name: "BobFranz", playtime: 632, wins: 222, losses: 184, score: 38} - {team: "ogres", rank: 106, sessionID: "537b9a1d3803a2870575835f", name: "pvande", playtime: 39177, wins: 216, losses: 179, score: 37} - {team: "ogres", rank: 107, sessionID: "537c23fffa0d80a106b10eb4", name: "Nylan", playtime: 1236, wins: 204, losses: 174, score: 30} - {team: "ogres", rank: 108, sessionID: "537b91795bc02238050d1b80", name: "Orange!", playtime: 22940, wins: 210, losses: 181, score: 29} - {team: "ogres", rank: 109, sessionID: "537b8cfde91b4d3b055261b6", name: "Thumb", playtime: 22271, wins: 212, losses: 185, score: 27} - {team: "ogres", rank: 110, sessionID: "53978487888ab73905184003", name: "Nick2", playtime: 5539, wins: 197, losses: 173, score: 24} - {team: "ogres", rank: 111, sessionID: "5386313f8ca8b1120b8b58a3", name: "fudgy", playtime: 2744, wins: 213, losses: 193, score: 20} - {team: "ogres", rank: 112, sessionID: "537cbcc062dea6b811f109c7", name: "Kirstin", playtime: 23151, wins: 211, losses: 192, score: 19} - {team: "ogres", rank: 113, sessionID: "53814d4605e52a3305df086c", name: "jsut", playtime: 21961, wins: 208, losses: 189, score: 19} - {team: "ogres", rank: 114, sessionID: "5384c51f7d99a7390560bce1", name: "Xhuy", playtime: 4562, wins: 204, losses: 188, score: 16} - {team: "ogres", rank: 115, sessionID: "536259c5fc1acf300b2ebcb7", name: "DarthNato", playtime: 26611, wins: 206, losses: 193, score: 13} - {team: "ogres", rank: 116, sessionID: "538db7f65572d43b0521cf9c", name: "rehashed", playtime: 12008, wins: 201, losses: 188, score: 13} - {team: "ogres", rank: 117, sessionID: "5361946c801ef0010d3a3369", name: "DeathScythe", playtime: 0, wins: 209, losses: 197, score: 12} - {team: "ogres", rank: 118, sessionID: "537f5d073282d7a5076952e6", name: "kraxor", playtime: 14420, wins: 191, losses: 179, score: 12} - {team: "ogres", rank: 119, sessionID: "537bc98ba968548907de6dad", name: "Huragok", playtime: 325, wins: 207, losses: 197, score: 10} - {team: "ogres", rank: 120, sessionID: "53718545d0d9b1370555448b", name: "SuchNoob", playtime: 0, wins: 196, losses: 188, score: 8} - {team: "ogres", rank: 121, sessionID: "538a1888b924da390514c2d6", name: "Lomidrevo", playtime: 9470, wins: 207, losses: 199, score: 8} - {team: "ogres", rank: 122, sessionID: "537b92265bc02238050d1bc3", name: "Drew", playtime: 21829, wins: 199, losses: 192, score: 7} - {team: "ogres", rank: 123, sessionID: "537b976e556db17605be769e", name: "Drak", playtime: 9554, wins: 202, losses: 197, score: 5} - {team: "ogres", rank: 124, sessionID: "5380b07205e52a3305deb2ea", name: "LinaLin", playtime: 1852, wins: 204, losses: 199, score: 5} - {team: "ogres", rank: 125, sessionID: "537b84de5bc02238050d1699", name: "WoLfulus", playtime: 9762, wins: 204, losses: 200, score: 4} - {team: "ogres", rank: 126, sessionID: "537b7f945bc02238050d14d8", name: "Shack", playtime: 16108, wins: 199, losses: 197, score: 2} - {team: "ogres", rank: 127, sessionID: "537badf8ec57a3e805cbf577", name: "borreltijd", playtime: 29749, wins: 202, losses: 203, score: -1} - {team: "ogres", rank: 128, sessionID: "537f8306ead05fd3075d1d39", name: "icoderz", playtime: 5382, wins: 202, losses: 204, score: -2} - {team: "ogres", rank: 129, sessionID: "537b92b55bc02238050d1c18", name: "Bullcity", playtime: 7478, wins: 197, losses: 204, score: -7} - {team: "ogres", rank: 130, sessionID: "537ba0937c89ec9805f4df2f", name: "Pavlov", playtime: 15761, wins: 198, losses: 205, score: -7} - {team: "ogres", rank: 131, sessionID: "537b85055bc02238050d16a6", name: "Drunk McLovin", playtime: 10225, wins: 194, losses: 204, score: -10} - {team: "ogres", rank: 132, sessionID: "537cbb38a0d7a5cc10992ee9", name: "Aion Crane", playtime: 9616, wins: 195, losses: 206, score: -11} - {team: "ogres", rank: 133, sessionID: "537be31fa3b60b390500ddc5", name: "antkim003", playtime: 19059, wins: 195, losses: 206, score: -11} - {team: "ogres", rank: 134, sessionID: "537d20d97e1e10b705bbcd58", name: "Tain", playtime: 28374, wins: 173, losses: 189, score: -16} - {team: "ogres", rank: 135, sessionID: "537bb6d6386abb6e05a3facf", name: "RTN", playtime: 4108, wins: 194, losses: 211, score: -17} - {team: "ogres", rank: 136, sessionID: "537b86b95bc02238050d1706", name: "Luogbelnu", playtime: 24526, wins: 191, losses: 208, score: -17} - {team: "ogres", rank: 137, sessionID: "537338f73108bc3905f7528d", name: "chess", playtime: 321, wins: 192, losses: 213, score: -21} - {team: "ogres", rank: 138, sessionID: "537df0950efa6a37059df463", name: "Rury", playtime: 14371, wins: 187, losses: 215, score: -28} - {team: "ogres", rank: 139, sessionID: "537c11290ff88b2c06287d29", name: "Crustopher", playtime: 15401, wins: 167, losses: 195, score: -28} - {team: "ogres", rank: 140, sessionID: "537df96a0efa6a37059df853", name: "HuangSY", playtime: 34229, wins: 178, losses: 209, score: -31} - {team: "ogres", rank: 141, sessionID: "537b909f5bc02238050d1b32", name: "ArthurDent", playtime: 63903, wins: 173, losses: 204, score: -31} - {team: "ogres", rank: 142, sessionID: "537e901b9008f87b0541fc83", name: "Mawox", playtime: 15961, wins: 186, losses: 218, score: -32} - {team: "ogres", rank: 143, sessionID: "537fa33bf56c5874086896cc", name: "Urg", playtime: 1760, wins: 182, losses: 218, score: -36} - {team: "ogres", rank: 144, sessionID: "53854e7d7d99a7390560fadd", name: "Dodrithard", playtime: 4087, wins: 160, losses: 196, score: -36} - {team: "ogres", rank: 145, sessionID: "537bfa3395356a43065f76bd", name: "Cicir", playtime: 7369, wins: 183, losses: 221, score: -38} - {team: "ogres", rank: 146, sessionID: "537ba4f3d60bb0b405d852b2", name: "Dubastot", playtime: 17312, wins: 160, losses: 201, score: -41} - {team: "ogres", rank: 147, sessionID: "537b8dbbe91b4d3b05526226", name: "Raetsel", playtime: 11005, wins: 180, losses: 223, score: -43} - {team: "ogres", rank: 148, sessionID: "537bc0b31c8dfa820699fcc2", name: "Source Error", playtime: 1731, wins: 171, losses: 214, score: -43} - {team: "ogres", rank: 149, sessionID: "537b92dde91b4d3b05526442", name: "Script Pimpkin", playtime: 18711, wins: 180, losses: 225, score: -45} - {team: "ogres", rank: 150, sessionID: "538f33d0755876370525988f", name: "Rigamortis", playtime: 23232, wins: 176, losses: 221, score: -45} - {team: "ogres", rank: 151, sessionID: "537c8bb826529de30cca4b02", name: "Static", playtime: 673, wins: 167, losses: 216, score: -49} - {team: "ogres", rank: 152, sessionID: "537bdd5ed3f3bb3305bd997a", name: "Tuna", playtime: 4854, wins: 177, losses: 226, score: -49} - {team: "ogres", rank: 153, sessionID: "537b945d556db17605be74d0", name: "Dino", playtime: 5413, wins: 177, losses: 227, score: -50} - {team: "ogres", rank: 154, sessionID: "537bcda2c57303a5070c2f3a", name: "LaughingMan", playtime: 52476, wins: 170, losses: 222, score: -52} - {team: "ogres", rank: 155, sessionID: "53825ebf78171d3d057e4e48", name: "Lord Azrael", playtime: 25968, wins: 175, losses: 227, score: -52} - {team: "ogres", rank: 156, sessionID: "537d19307e1e10b705bbc877", name: "Naoki", playtime: 7851, wins: 172, losses: 226, score: -54} - {team: "ogres", rank: 157, sessionID: "537b95526c13497e05de81d2", name: "Gromliqk", playtime: 15566, wins: 174, losses: 230, score: -56} - {team: "ogres", rank: 158, sessionID: "537bacbc03838cf0050ace6f", name: "cameltoe", playtime: 53128, wins: 171, losses: 230, score: -59} - {team: "ogres", rank: 159, sessionID: "537b82d75bc02238050d160d", name: "Kithid", playtime: 14756, wins: 169, losses: 229, score: -60} - {team: "ogres", rank: 160, sessionID: "537d4e5d3dcf67c40571f5c3", name: "bonnnie", playtime: 25945, wins: 173, losses: 233, score: -60} - {team: "ogres", rank: 161, sessionID: "537e4d7a63734c6305059374", name: "kotowlos", playtime: 6498, wins: 172, losses: 233, score: -61} - {team: "ogres", rank: 162, sessionID: "537b80425bc02238050d152c", name: "mdz", playtime: 12720, wins: 167, losses: 229, score: -62} - {team: "ogres", rank: 163, sessionID: "537bb50218bd7f4705b9d459", name: "Claros", playtime: 1250, wins: 170, losses: 236, score: -66} - {team: "ogres", rank: 164, sessionID: "537c8a5626529de30cca4a2f", name: "nulo", playtime: 5264, wins: 168, losses: 236, score: -68} - {team: "ogres", rank: 165, sessionID: "537bb4598698e13805226b77", name: "JojoTheGreat", playtime: 1733, wins: 162, losses: 235, score: -73} - {team: "ogres", rank: 166, sessionID: "537bab9b89a8aeea05970d0b", name: "gameloop.io", playtime: 2823, wins: 163, losses: 237, score: -74} - {team: "ogres", rank: 167, sessionID: "5382411905e52a3305df893b", name: "Richard Adleta", playtime: 3272, wins: 162, losses: 240, score: -78} - {team: "ogres", rank: 168, sessionID: "537c4408a56c78cb0cb4f353", name: "lichens", playtime: 59782, wins: 163, losses: 241, score: -78} - {team: "ogres", rank: 169, sessionID: "537e1ab60efa6a37059e0bf0", name: "Scnoobi", playtime: 3430, wins: 159, losses: 239, score: -80} - {team: "ogres", rank: 170, sessionID: "537f6adc14f08dec07950ab2", name: "Ralphy282", playtime: 42208, wins: 155, losses: 235, score: -80} - {team: "ogres", rank: 171, sessionID: "537be8d820a501380564e6e7", name: "gandalfStormcrow", playtime: 435, wins: 162, losses: 242, score: -80} - {team: "ogres", rank: 172, sessionID: "537bc4b10de0a02c07e879a8", name: "", playtime: 872, wins: 161, losses: 242, score: -81} - {team: "ogres", rank: 173, sessionID: "537e581863734c6305059a53", name: "taz", playtime: 24420, wins: 160, losses: 242, score: -82} - {team: "ogres", rank: 174, sessionID: "537ce331e9c4e97c05e3ea34", name: "bb", playtime: 391, wins: 159, losses: 245, score: -86} - {team: "ogres", rank: 175, sessionID: "537c5f4f14aaabe80c69fd70", name: "@ESWAT", playtime: 13389, wins: 152, losses: 239, score: -87} - {team: "ogres", rank: 176, sessionID: "537b8a515bc02238050d1873", name: "joshuacarley", playtime: 23663, wins: 156, losses: 244, score: -88} - {team: "ogres", rank: 177, sessionID: "537d550d3dcf67c40571f7dc", name: "J'Son", playtime: 5290, wins: 156, losses: 246, score: -90} - {team: "ogres", rank: 178, sessionID: "537c05ef95356a43065f7e1c", name: "Cerbi", playtime: 9095, wins: 151, losses: 250, score: -99} - {team: "ogres", rank: 179, sessionID: "537c532126529de30cca3067", name: "warrned", playtime: 3870, wins: 149, losses: 254, score: -105} - {team: "ogres", rank: 180, sessionID: "537fc780c1a6b99109171791", name: "OWalerys", playtime: 18624, wins: 146, losses: 251, score: -105} - {team: "ogres", rank: 181, sessionID: "537efa7e8fe881f1055de25e", name: "Smaug", playtime: 14526, wins: 146, losses: 253, score: -107} - {team: "ogres", rank: 182, sessionID: "537bf37d95356a43065f7286", name: "cokaroach", playtime: 47117, wins: 124, losses: 237, score: -113} - {team: "ogres", rank: 183, sessionID: "537e304e64659f3a0577248a", name: "Plak87", playtime: 5459, wins: 144, losses: 259, score: -115} - {team: "ogres", rank: 184, sessionID: "537cfe4d9cce053a05c04dc2", name: "xzores", playtime: 9686, wins: 145, losses: 260, score: -115} - {team: "ogres", rank: 185, sessionID: "537bb0ad2323353a05bd57ef", name: "Wicked", playtime: 4520, wins: 140, losses: 258, score: -118} - {team: "ogres", rank: 186, sessionID: "537cd1c4665bde1b13ffd635", name: "Delforas", playtime: 3970, wins: 138, losses: 258, score: -120} - {team: "ogres", rank: 187, sessionID: "53806a8405e52a3305de92fa", name: "Pabelo", playtime: 4629, wins: 141, losses: 262, score: -121} - {team: "ogres", rank: 188, sessionID: "537fcc57c1a6b99109171ced", name: "jhoie", playtime: 1045, wins: 137, losses: 259, score: -122} - {team: "ogres", rank: 189, sessionID: "5395d1ba7362c439054f7e6e", name: "JenJen", playtime: 151, wins: 137, losses: 259, score: -122} - {team: "ogres", rank: 190, sessionID: "537b9dc4ffeaa29e051b2738", name: "Kevin", playtime: 9970, wins: 136, losses: 263, score: -127} - {team: "ogres", rank: 191, sessionID: "537b9c09ffeaa29e051b2637", name: "Tuefekci", playtime: 10790, wins: 131, losses: 259, score: -128} - {team: "ogres", rank: 192, sessionID: "537c5b3526529de30cca340c", name: "patchnotes", playtime: 31167, wins: 119, losses: 252, score: -133} - {team: "ogres", rank: 193, sessionID: "5380fdb47585483905a7c753", name: "null0pointer", playtime: 9524, wins: 131, losses: 266, score: -135} - {team: "ogres", rank: 194, sessionID: "537b9f4751e98aa705b60515", name: "Sawyer", playtime: 9450, wins: 136, losses: 271, score: -135} - {team: "ogres", rank: 195, sessionID: "5380bd747585483905a7a707", name: "Lobo", playtime: 5280, wins: 132, losses: 269, score: -137} - {team: "ogres", rank: 196, sessionID: "5382593bc85c223a05f429d9", name: "squidlarkin", playtime: 2036, wins: 130, losses: 267, score: -137} - {team: "ogres", rank: 197, sessionID: "537cd5fee4523d0113ba57ea", name: "Borlak", playtime: 14470, wins: 133, losses: 271, score: -138} - {team: "ogres", rank: 198, sessionID: "537bbb201aaa69c4052676fd", name: "jMerliN", playtime: 3292, wins: 129, losses: 270, score: -141} - {team: "ogres", rank: 199, sessionID: "537be3c7a3b60b390500de0e", name: "Dragon DM", playtime: 17848, wins: 131, losses: 274, score: -143} - {team: "ogres", rank: 200, sessionID: "537b90295bc02238050d1af5", name: "octopushugs", playtime: 706, wins: 125, losses: 270, score: -145} - {team: "ogres", rank: 201, sessionID: "5380d5be7585483905a7b1e1", name: "Quaritch", playtime: 12711, wins: 128, losses: 274, score: -146} - {team: "ogres", rank: 202, sessionID: "5397732542cf7d3905ed7233", name: "BloodJohn", playtime: 5178, wins: 127, losses: 276, score: -149} - {team: "ogres", rank: 203, sessionID: "537cab3d0e905d000fbfad57", name: "Xor", playtime: 19480, wins: 126, losses: 278, score: -152} - {team: "ogres", rank: 204, sessionID: "537b88f85bc02238050d17e2", name: "Jojas", playtime: 9328, wins: 126, losses: 278, score: -152} - {team: "ogres", rank: 205, sessionID: "539436745009fe5b075b70a7", name: "Vhr", playtime: 3065, wins: 122, losses: 274, score: -152} - {team: "ogres", rank: 206, sessionID: "535f0c4b11c0ebd2049d1664", name: "Jebso", playtime: 0, wins: 125, losses: 278, score: -153} - {team: "ogres", rank: 207, sessionID: "537b9d3cffeaa29e051b26eb", name: "", playtime: 784, wins: 125, losses: 278, score: -153} - {team: "ogres", rank: 208, sessionID: "537c3bdb54bc23770a21e166", name: "seaclair", playtime: 385, wins: 122, losses: 279, score: -157} - {team: "ogres", rank: 209, sessionID: "537bf147f8b46fbd0544fc15", name: "", playtime: 16376, wins: 109, losses: 269, score: -160} - {team: "ogres", rank: 210, sessionID: "537bd2e0be90aa5605fb2ebd", name: "educavalcanti", playtime: 50086, wins: 121, losses: 282, score: -161} - {team: "ogres", rank: 211, sessionID: "537cd0e0665bde1b13ffd5ca", name: "itsbth", playtime: 1299, wins: 104, losses: 265, score: -161} - {team: "ogres", rank: 212, sessionID: "537b8e1ee91b4d3b05526274", name: "Jorge", playtime: 4728, wins: 118, losses: 280, score: -162} - {team: "ogres", rank: 213, sessionID: "537b88f6e91b4d3b05526048", name: "CzonI", playtime: 3033, wins: 120, losses: 283, score: -163} - {team: "ogres", rank: 214, sessionID: "537b7c26e91b4d3b05525c6a", name: "TTSS", playtime: 1132, wins: 120, losses: 283, score: -163} - {team: "ogres", rank: 215, sessionID: "5389d73bb924da3905149015", name: "oli-f", playtime: 10824, wins: 101, losses: 266, score: -165} - {team: "ogres", rank: 216, sessionID: "537b8c21e91b4d3b0552616d", name: "Luke Young", playtime: 10713, wins: 117, losses: 285, score: -168} - {team: "ogres", rank: 217, sessionID: "537b84e15bc02238050d169c", name: "", playtime: 359, wins: 116, losses: 284, score: -168} - {team: "ogres", rank: 218, sessionID: "537b845fe91b4d3b05525f03", name: "walesmd", playtime: 1630, wins: 116, losses: 285, score: -169} - {team: "ogres", rank: 219, sessionID: "538515a73e0daa390518ba45", name: "Azerroth", playtime: 19862, wins: 114, losses: 285, score: -171} - {team: "ogres", rank: 220, sessionID: "537bd660142ee637052420e3", name: "tkl", playtime: 8276, wins: 102, losses: 278, score: -176} - {team: "ogres", rank: 221, sessionID: "538a9449b924da3905151926", name: "cdaaar", playtime: 14955, wins: 45, losses: 222, score: -177} - {team: "ogres", rank: 222, sessionID: "538345b078171d3d057eae61", name: "Ikrus", playtime: 13687, wins: 111, losses: 295, score: -184} - {team: "ogres", rank: 223, sessionID: "537b8e26e91b4d3b05526277", name: "Zairja", playtime: 10077, wins: 101, losses: 293, score: -192} - {team: "ogres", rank: 224, sessionID: "537b97f53803a28705758218", name: "kookieblues", playtime: 2400, wins: 104, losses: 303, score: -199} - {team: "ogres", rank: 225, sessionID: "537d06bd7e1e10b705bbbe83", name: "llcossette", playtime: 2648, wins: 95, losses: 302, score: -207} - {team: "ogres", rank: 226, sessionID: "537b800de91b4d3b05525db8", name: "Merlin Gough", playtime: 8942, wins: 90, losses: 303, score: -213} - {team: "ogres", rank: 227, sessionID: "538382db86de19c31c1ce893", name: "Nick05 Testinator", playtime: 1454, wins: 90, losses: 311, score: -221} - {team: "ogres", rank: 228, sessionID: "537bcd7ec57303a5070c2f1e", name: "hedint", playtime: 8881, wins: 92, losses: 314, score: -222} - {team: "ogres", rank: 229, sessionID: "537cc425665bde1b13ffce89", name: "dotnetjohn", playtime: 1304, wins: 87, losses: 315, score: -228} - {team: "ogres", rank: 230, sessionID: "537c3c1454bc23770a21e187", name: "Prelude", playtime: 2351, wins: 85, losses: 313, score: -228} - {team: "ogres", rank: 231, sessionID: "538925b4d06c503805fe4ff7", name: "Perenolder", playtime: 21235, wins: 79, losses: 322, score: -243} - {team: "ogres", rank: 232, sessionID: "538a26cdd06c503805fec706", name: "the-k-man", playtime: 10321, wins: 78, losses: 327, score: -249} - {team: "ogres", rank: 233, sessionID: "537c531d26529de30cca3065", name: "masashi", playtime: 17871, wins: 75, losses: 330, score: -255} - {team: "ogres", rank: 234, sessionID: "5371861fd4491339051c3b11", name: "asdlk;fj asd fas", playtime: 0, wins: 65, losses: 333, score: -268} - {team: "ogres", rank: 235, sessionID: "537b8429e91b4d3b05525ef5", name: "Missblit", playtime: 28639, wins: 59, losses: 346, score: -287} - {team: "ogres", rank: 236, sessionID: "538b1322d06c503805ff299f", name: "judar1o", playtime: 5891, wins: 59, losses: 347, score: -288} - {team: "ogres", rank: 237, sessionID: "53583ab57962157d05b398f8", name: "makertech81", playtime: 170, wins: 55, losses: 344, score: -289} - {team: "ogres", rank: 238, sessionID: "539723388376eb3805dc2d4e", name: "immersion", playtime: 6471, wins: 54, losses: 348, score: -294} - {team: "ogres", rank: 239, sessionID: "537c99aa14aaabe80c6a1a44", name: "werewolf", playtime: 167, wins: 46, losses: 343, score: -297} - {team: "ogres", rank: 240, sessionID: "539085aaf369103805172236", name: "Kabbi", playtime: 6873, wins: 43, losses: 344, score: -301} - {team: "ogres", rank: 241, sessionID: "537bd587b0d1766d05243016", name: "Casey", playtime: 1229, wins: 44, losses: 346, score: -302} - {team: "ogres", rank: 242, sessionID: "537e2bd864659f3a05772075", name: "", playtime: 322, wins: 42, losses: 349, score: -307} - {team: "ogres", rank: 243, sessionID: "5385c7503e0daa39051919db", name: "Zack", playtime: 66, wins: 40, losses: 348, score: -308} - {team: "ogres", rank: 244, sessionID: "537ba0a551e98aa705b605b2", name: "", playtime: 232, wins: 39, losses: 349, score: -310} - {team: "ogres", rank: 245, sessionID: "535fdebe5c7324a80702cb3b", name: "mich55", playtime: 0, wins: 38, losses: 349, score: -311} - {team: "ogres", rank: 246, sessionID: "5390823e7558763705263cc8", name: "Duchess", playtime: 460, wins: 37, losses: 349, score: -312} - {team: "ogres", rank: 247, sessionID: "5360a43d9859fefb0673aefa", name: "daruba", playtime: 0, wins: 34, losses: 351, score: -317} - {team: "ogres", rank: 248, sessionID: "537bab4f6e54cbda057ee565", name: "Pajamas", playtime: 27043, wins: 14, losses: 338, score: -324} - {team: "ogres", rank: 249, sessionID: "537bf053f8b46fbd0544fb8c", name: "Fusspawn", playtime: 9524, wins: 37, losses: 368, score: -331} - {team: "ogres", rank: 250, sessionID: "5382f069c85c223a05f47200", name: "ferrak", playtime: 7015, wins: 33, losses: 373, score: -340} - {team: "ogres", rank: 251, sessionID: "5380a3737585483905a799e1", name: "Dark Pikachu", playtime: 1373, wins: 29, losses: 377, score: -348} - {team: "ogres", rank: 252, sessionID: "538711898ca8b1120b8bdb3f", name: "A", playtime: 4272, wins: 24, losses: 380, score: -356} - {team: "ogres", rank: 253, sessionID: "5384af823e0daa3905187cb1", name: "Macguffin", playtime: 837, wins: 18, losses: 384, score: -366} - {team: "ogres", rank: 254, sessionID: "537db76b13add33a051bf575", name: "Luyalve", playtime: 1404, wins: 3, losses: 372, score: -369} - {team: "ogres", rank: 255, sessionID: "537b9bac16613c8405155a79", name: "solarian", playtime: 24889, wins: 0, losses: 371, score: -371} - {team: "ogres", rank: 256, sessionID: "537ba09951e98aa705b605ae", name: "Potato", playtime: 61777, wins: 0, losses: 371, score: -371} - {team: "ogres", rank: 257, sessionID: "537d24db84c54c6e05c06ac4", name: "terriblesarcasm", playtime: 39553, wins: 0, losses: 371, score: -371} - {team: "ogres", rank: 258, sessionID: "537c2abc224747bb0761634f", name: "chicones", playtime: 9831, wins: 0, losses: 371, score: -371} - {team: "ogres", rank: 259, sessionID: "538381a5c83e563705a06fdb", name: "diddly-dum", playtime: 8077, wins: 0, losses: 372, score: -372} - {team: "ogres", rank: 260, sessionID: "5388a785b924da3905139f46", name: "AWESOMEHACKER", playtime: 564, wins: 0, losses: 372, score: -372} - {team: "ogres", rank: 261, sessionID: "537bb6d2386abb6e05a3facc", name: "chrm", playtime: 213307, wins: 0, losses: 375, score: -375} - {team: "ogres", rank: 262, sessionID: "537bc26e8fe668b406d4c019", name: "Sapid", playtime: 11917, wins: 0, losses: 376, score: -376} - {team: "ogres", rank: 263, sessionID: "5357127a1bfa9bba14b5e048", name: "dcm", playtime: 5380, wins: 0, losses: 376, score: -376} - {team: "ogres", rank: 264, sessionID: "537aee4cfb4c173805cf26f7", name: "basicer", playtime: 10407, wins: 0, losses: 376, score: -376} - {team: "ogres", rank: 265, sessionID: "5382cbb078171d3d057e804f", name: "vvv", playtime: 719, wins: 0, losses: 376, score: -376} - {team: "ogres", rank: 266, sessionID: "537ba40a903fd2b8051553b0", name: "ElderTale", playtime: 13984, wins: 0, losses: 376, score: -376} - {team: "ogres", rank: 267, sessionID: "53839e256f3bea3a05fb09b3", name: "Gondolfs", playtime: 29985, wins: 0, losses: 378, score: -378} - {team: "ogres", rank: 268, sessionID: "537a73a6e488a7380545affd", name: "Galvan", playtime: 514, wins: 0, losses: 378, score: -378} - {team: "ogres", rank: 269, sessionID: "537b96b16c13497e05de82a8", name: "Krris", playtime: 2618, wins: 0, losses: 379, score: -379} - {team: "ogres", rank: 270, sessionID: "537bc1b81db8c8ac063a3b7b", name: "jpiasetz", playtime: 14565, wins: 0, losses: 380, score: -380} + {team: 'ogres', rank: 1, sessionID: '537b958e6c13497e05de81f2', name: 'Bellardia', playtime: 189111, wins: 387, losses: 7, score: 380} + {team: 'ogres', rank: 2, sessionID: '537c11df95356a43065f84c9', name: 'blinkingTore', playtime: 38360, wins: 381, losses: 9, score: 372} + {team: 'ogres', rank: 3, sessionID: '537c09ee95356a43065f801c', name: 'Eye', playtime: 172960, wins: 370, losses: 18, score: 352} + {team: 'ogres', rank: 4, sessionID: '537b7d475bc02238050d1439', name: 'Cripi', playtime: 61966, wins: 373, losses: 23, score: 350} + {team: 'ogres', rank: 5, sessionID: '537e317450d1673a054b7dd2', name: 'Pop-up', playtime: 39939, wins: 369, losses: 26, score: 343} + {team: 'ogres', rank: 6, sessionID: '537e364a50d1673a054b8322', name: 'Ravenclaw', playtime: 4579, wins: 367, losses: 24, score: 343} + {team: 'ogres', rank: 7, sessionID: '537cb51fa0d7a5cc10992b11', name: 'JerryP', playtime: 52872, wins: 368, losses: 33, score: 335} + {team: 'ogres', rank: 8, sessionID: '537bd37888a86e67053f9d61', name: 'Mickydtron', playtime: 38533, wins: 368, losses: 35, score: 333} + {team: 'ogres', rank: 9, sessionID: '5384a3f63e0daa390518765d', name: 'ProfBoesch', playtime: 10366, wins: 365, losses: 34, score: 331} + {team: 'ogres', rank: 10, sessionID: '538064d27585483905a77f9f', name: 'KaosWalking', playtime: 88663, wins: 359, losses: 35, score: 324} + {team: 'ogres', rank: 11, sessionID: '53892a98d06c503805fe522b', name: 'Urdaris', playtime: 87750, wins: 353, losses: 32, score: 321} + {team: 'ogres', rank: 12, sessionID: '53668d64c6ab10ef1ea9a10d', name: 'no_login_found', playtime: 11313, wins: 355, losses: 46, score: 309} + {team: 'ogres', rank: 13, sessionID: '537f68bc14f08dec07950945', name: 'Take it easy', playtime: 2839, wins: 348, losses: 47, score: 301} + {team: 'ogres', rank: 14, sessionID: '537bac56b0d477e005347f67', name: 'gosunero', playtime: 41429, wins: 346, losses: 54, score: 292} + {team: 'ogres', rank: 15, sessionID: '536d258f68b5258d0c4b96ed', name: 'Jex', playtime: 4910, wins: 337, losses: 48, score: 289} + {team: 'ogres', rank: 16, sessionID: '537bcba8a797656f07c93db5', name: 'Durbination', playtime: 13465, wins: 337, losses: 49, score: 288} + {team: 'ogres', rank: 17, sessionID: '5381e48a7585483905a82a2d', name: 'Edoardo Morandi', playtime: 96844, wins: 330, losses: 49, score: 281} + {team: 'ogres', rank: 18, sessionID: '538471737d99a73905608fb4', name: 'Artraxus', playtime: 61114, wins: 336, losses: 60, score: 276} + {team: 'ogres', rank: 19, sessionID: '537ba9a154a7b1d5053bb45a', name: 'skeltoac', playtime: 39087, wins: 330, losses: 55, score: 275} + {team: 'ogres', rank: 20, sessionID: '537be145a3b60b390500dcc3', name: 'ReyO', playtime: 204112, wins: 328, losses: 55, score: 273} + {team: 'ogres', rank: 21, sessionID: '537cc939665bde1b13ffd197', name: 'Orson Peters', playtime: 24821, wins: 333, losses: 60, score: 273} + {team: 'ogres', rank: 22, sessionID: '5395cf0b7362c439054f7c3a', name: 'nino48', playtime: 33541, wins: 327, losses: 62, score: 265} + {team: 'ogres', rank: 23, sessionID: '537d541e3dcf67c40571f792', name: 'pbd', playtime: 4062, wins: 319, losses: 84, score: 235} + {team: 'ogres', rank: 24, sessionID: '537e284650d1673a054b7602', name: 'Tech', playtime: 13208, wins: 306, losses: 71, score: 235} + {team: 'ogres', rank: 25, sessionID: '537d025184c54c6e05c059b7', name: 'Storm0x2a', playtime: 1026, wins: 306, losses: 71, score: 235} + {team: 'ogres', rank: 26, sessionID: '537bed83f575b482052f03a0', name: 'Blindfold', playtime: 45865, wins: 303, losses: 69, score: 234} + {team: 'ogres', rank: 27, sessionID: '537bc4750de0a02c07e8797f', name: 'Walter Danilo Galante', playtime: 24476, wins: 313, losses: 84, score: 229} + {team: 'ogres', rank: 28, sessionID: '538d0a4356c3613905301e50', name: 'Fedux', playtime: 1862, wins: 300, losses: 79, score: 221} + {team: 'ogres', rank: 29, sessionID: '537b8cbee91b4d3b0552619e', name: 'Nazywam', playtime: 6395, wins: 303, losses: 83, score: 220} + {team: 'ogres', rank: 30, sessionID: '5382502a7585483905a85e42', name: 'vlizard', playtime: 803, wins: 308, losses: 89, score: 219} + {team: 'ogres', rank: 31, sessionID: '5385d1cf3e0daa3905191e57', name: 'olu', playtime: 65635, wins: 301, losses: 86, score: 215} + {team: 'ogres', rank: 32, sessionID: '537babd003838cf0050acdf2', name: 'Pentar', playtime: 36006, wins: 309, losses: 95, score: 214} + {team: 'ogres', rank: 33, sessionID: '537c31112b08c344082e22de', name: 'Agathanar', playtime: 41371, wins: 308, losses: 94, score: 214} + {team: 'ogres', rank: 34, sessionID: '537cd98ae4523d0113ba5ac7', name: 'Tehvudgaw', playtime: 81681, wins: 298, losses: 94, score: 204} + {team: 'ogres', rank: 35, sessionID: '537b803ae91b4d3b05525dc7', name: 'Forsaken', playtime: 50237, wins: 294, losses: 91, score: 203} + {team: 'ogres', rank: 36, sessionID: '537b7e44e91b4d3b05525d38', name: 'COGSMITH', playtime: 284674, wins: 300, losses: 98, score: 202} + {team: 'ogres', rank: 37, sessionID: '537ba3e0903fd2b80515539d', name: 'Statik', playtime: 64062, wins: 294, losses: 98, score: 196} + {team: 'ogres', rank: 38, sessionID: '537b85e15bc02238050d16d4', name: 'Cuef', playtime: 81666, wins: 286, losses: 90, score: 196} + {team: 'ogres', rank: 39, sessionID: '5392f7b1304ab93805efa3d2', name: 'Cracker', playtime: 2576, wins: 282, losses: 90, score: 192} + {team: 'ogres', rank: 40, sessionID: '537b9c42ffeaa29e051b2657', name: 'JamesJNadeau.com', playtime: 28164, wins: 295, losses: 110, score: 185} + {team: 'ogres', rank: 41, sessionID: '537ce37be9c4e97c05e3ea66', name: 'Quasar', playtime: 21773, wins: 287, losses: 104, score: 183} + {team: 'ogres', rank: 42, sessionID: '537baa2403ff8dc005b8433e', name: 'Almatia', playtime: 15387, wins: 291, losses: 109, score: 182} + {team: 'ogres', rank: 43, sessionID: '537b87f55bc02238050d1786', name: 'mordonne', playtime: 71830, wins: 277, losses: 103, score: 174} + {team: 'ogres', rank: 44, sessionID: '537e56129008f87b0541cd03', name: 'O\'Connor', playtime: 55869, wins: 281, losses: 109, score: 172} + {team: 'ogres', rank: 45, sessionID: '537ba9e57b9ffadb05476784', name: 'timmox', playtime: 13280, wins: 256, losses: 86, score: 170} + {team: 'ogres', rank: 46, sessionID: '537b86e75bc02238050d1721', name: 'Tomas', playtime: 21845, wins: 275, losses: 106, score: 169} + {team: 'ogres', rank: 47, sessionID: '537bebbea3b60b390500e280', name: 'Buge', playtime: 3506, wins: 281, losses: 118, score: 163} + {team: 'ogres', rank: 48, sessionID: '53854c0b7d99a7390560f9f4', name: 'MatBot', playtime: 15049, wins: 281, losses: 119, score: 162} + {team: 'ogres', rank: 49, sessionID: '5380a9bb7585483905a79dff', name: 'salesman', playtime: 60290, wins: 277, losses: 118, score: 159} + {team: 'ogres', rank: 50, sessionID: '53949f635009fe5b075bb584', name: 'Dematerial', playtime: 4661, wins: 273, losses: 116, score: 157} + {team: 'ogres', rank: 51, sessionID: '53832a3ec85c223a05f48736', name: 'Popey', playtime: 37593, wins: 256, losses: 104, score: 152} + {team: 'ogres', rank: 52, sessionID: '537b89a2e91b4d3b05526082', name: 'Ryemane', playtime: 20671, wins: 276, losses: 125, score: 151} + {team: 'ogres', rank: 53, sessionID: '537cd542e4523d0113ba5782', name: 'schups', playtime: 20886, wins: 277, losses: 127, score: 150} + {team: 'ogres', rank: 54, sessionID: '537be1cca3b60b390500dd24', name: 'ohsnap', playtime: 3574, wins: 273, losses: 127, score: 146} + {team: 'ogres', rank: 55, sessionID: '538bef7356c36139052f8c80', name: 'Hephaestian', playtime: 9626, wins: 272, losses: 131, score: 141} + {team: 'ogres', rank: 56, sessionID: '537c527026529de30cca302f', name: 'Jinrai', playtime: 23726, wins: 269, losses: 129, score: 140} + {team: 'ogres', rank: 57, sessionID: '538471087d99a73905608f84', name: 'Basque', playtime: 37986, wins: 269, losses: 130, score: 139} + {team: 'ogres', rank: 58, sessionID: '537cd3c3665bde1b13ffd74c', name: 'Stormaggedon Dark Lord of All', playtime: 27471, wins: 261, losses: 123, score: 138} + {team: 'ogres', rank: 59, sessionID: '537b984f3803a2870575824f', name: 'Cody', playtime: 85426, wins: 259, losses: 138, score: 121} + {team: 'ogres', rank: 60, sessionID: '5383ead92757353805a96ff4', name: 'hotdogeater', playtime: 55657, wins: 258, losses: 137, score: 121} + {team: 'ogres', rank: 61, sessionID: '537d2a397e1e10b705bbd2c8', name: 'PatchworkKnight', playtime: 23663, wins: 257, losses: 138, score: 119} + {team: 'ogres', rank: 62, sessionID: '537b8185e91b4d3b05525e3c', name: 'FlameFrost', playtime: 29939, wins: 251, losses: 142, score: 109} + {team: 'ogres', rank: 63, sessionID: '537bb4168623bc410575f208', name: 'NitrousDave', playtime: 29420, wins: 252, losses: 143, score: 109} + {team: 'ogres', rank: 64, sessionID: '537f4fa1c3067a7b07ba7786', name: 'Zodd', playtime: 8820, wins: 248, losses: 140, score: 108} + {team: 'ogres', rank: 65, sessionID: '538358b978171d3d057eb471', name: 'Lololala', playtime: 39892, wins: 252, losses: 144, score: 108} + {team: 'ogres', rank: 66, sessionID: '537f224c8fe881f1055dfb7e', name: 'Artoemius', playtime: 1470, wins: 251, losses: 150, score: 101} + {team: 'ogres', rank: 67, sessionID: '537b7b25e91b4d3b05525b61', name: 'Makaze', playtime: 21714, wins: 248, losses: 149, score: 99} + {team: 'ogres', rank: 68, sessionID: '537cf18c9cce053a05c0467f', name: 'CodeBane', playtime: 39749, wins: 233, losses: 137, score: 96} + {team: 'ogres', rank: 69, sessionID: '537baac910c8a6e405b9cf92', name: 'cooler', playtime: 49558, wins: 229, losses: 134, score: 95} + {team: 'ogres', rank: 70, sessionID: '5380d0a405e52a3305dec328', name: 'DoctorTacoPhD', playtime: 9723, wins: 249, losses: 155, score: 94} + {team: 'ogres', rank: 71, sessionID: '53948cfc5009fe5b075ba92d', name: 'zeus1200', playtime: 236, wins: 246, losses: 152, score: 94} + {team: 'ogres', rank: 72, sessionID: '537c66d114aaabe80c6a0072', name: 'Vratislav', playtime: 21203, wins: 237, losses: 144, score: 93} + {team: 'ogres', rank: 73, sessionID: '537b996016613c8405155922', name: 'Dafe', playtime: 701, wins: 232, losses: 140, score: 92} + {team: 'ogres', rank: 74, sessionID: '537b8271e91b4d3b05525e8e', name: '@billyvg', playtime: 20844, wins: 243, losses: 154, score: 89} + {team: 'ogres', rank: 75, sessionID: '537caafc2f6e3aee0ed58007', name: 'Sakares', playtime: 1257, wins: 237, losses: 151, score: 86} + {team: 'ogres', rank: 76, sessionID: '538142de05e52a3305df037d', name: 'Meowth', playtime: 12054, wins: 241, losses: 155, score: 86} + {team: 'ogres', rank: 77, sessionID: '537155a1ee35af3905987a87', name: 'Lanner', playtime: 3658, wins: 236, losses: 152, score: 84} + {team: 'ogres', rank: 78, sessionID: '537b99573803a287057582e3', name: 'DavyWong', playtime: 16467, wins: 242, losses: 161, score: 81} + {team: 'ogres', rank: 79, sessionID: '537be8fda3b60b390500e105', name: 'BeAsT MoDe', playtime: 2097, wins: 234, losses: 153, score: 81} + {team: 'ogres', rank: 80, sessionID: '537b96696c13497e05de8271', name: 'vkeg', playtime: 1883, wins: 236, losses: 157, score: 79} + {team: 'ogres', rank: 81, sessionID: '537ca60cb128a1850e083077', name: 'SPAMR', playtime: 19978, wins: 233, losses: 154, score: 79} + {team: 'ogres', rank: 82, sessionID: '537b5662fe0ec03905fcdcd4', name: 'pages', playtime: 22679, wins: 231, losses: 155, score: 76} + {team: 'ogres', rank: 83, sessionID: '537bf90295356a43065f7640', name: '', playtime: 167, wins: 218, losses: 144, score: 74} + {team: 'ogres', rank: 84, sessionID: '535de130c969efa7053345ab', name: 'Racksickle', playtime: 319, wins: 231, losses: 157, score: 74} + {team: 'ogres', rank: 85, sessionID: '537c2facf67b6b1c08af376f', name: 'greyworm', playtime: 22755, wins: 234, losses: 160, score: 74} + {team: 'ogres', rank: 86, sessionID: '537eef8c8fe881f1055dddb6', name: 'huang123', playtime: 2590, wins: 234, losses: 161, score: 73} + {team: 'ogres', rank: 87, sessionID: '53934430304ab93805efcf4f', name: 'LilDooda', playtime: 16603, wins: 229, losses: 156, score: 73} + {team: 'ogres', rank: 88, sessionID: '5389c83fb924da39051485d2', name: 'nineties', playtime: 58607, wins: 183, losses: 113, score: 70} + {team: 'ogres', rank: 89, sessionID: '537b760f1ed81a3b05c4fbfe', name: 'Xavion', playtime: 3593, wins: 229, losses: 159, score: 70} + {team: 'ogres', rank: 90, sessionID: '5383ec74087dc139054d8658', name: 'cattycat', playtime: 384, wins: 228, losses: 160, score: 68} + {team: 'ogres', rank: 91, sessionID: '538375bb78171d3d057ebdb6', name: 'Johnwg7', playtime: 65297, wins: 233, losses: 165, score: 68} + {team: 'ogres', rank: 92, sessionID: '537b99063803a287057582c1', name: 'Simba', playtime: 16847, wins: 230, losses: 163, score: 67} + {team: 'ogres', rank: 93, sessionID: '53929b482446a4410538b59d', name: 'Buh', playtime: 28766, wins: 230, losses: 165, score: 65} + {team: 'ogres', rank: 94, sessionID: '537bf9410ff88b2c06286e43', name: 'Ulfberht', playtime: 26046, wins: 232, losses: 171, score: 61} + {team: 'ogres', rank: 95, sessionID: '537bc6e24add491607deaaa1', name: 'Victor Hugo', playtime: 31094, wins: 221, losses: 163, score: 58} + {team: 'ogres', rank: 96, sessionID: '53809a807585483905a79529', name: 'stderr', playtime: 20568, wins: 229, losses: 173, score: 56} + {team: 'ogres', rank: 97, sessionID: '537b8643e91b4d3b05525f83', name: 'Austinh100', playtime: 12405, wins: 225, losses: 176, score: 49} + {team: 'ogres', rank: 98, sessionID: '537c7fad26529de30cca440d', name: 'efraglebagga', playtime: 22417, wins: 219, losses: 172, score: 47} + {team: 'ogres', rank: 99, sessionID: '537dde5d933d99860613a256', name: 'Meojifo', playtime: 50047, wins: 222, losses: 177, score: 45} + {team: 'ogres', rank: 100, sessionID: '537bc0eb467df184064bb865', name: 'Diginaut', playtime: 8029, wins: 225, losses: 180, score: 45} + {team: 'ogres', rank: 101, sessionID: '538390336f3bea3a05faff49', name: 'Ghostly_Cookie', playtime: 5804, wins: 221, losses: 177, score: 44} + {team: 'ogres', rank: 102, sessionID: '537f2cb8fdacc2fa050231bf', name: 'crazydiv', playtime: 12170, wins: 212, losses: 170, score: 42} + {team: 'ogres', rank: 103, sessionID: '537ef0e78fe881f1055dde46', name: 'Æ', playtime: 97439, wins: 204, losses: 163, score: 41} + {team: 'ogres', rank: 104, sessionID: '537b96f216613c84051557f1', name: 'mda', playtime: 11544, wins: 222, losses: 181, score: 41} + {team: 'ogres', rank: 105, sessionID: '537b8231e91b4d3b05525e7e', name: 'BobFranz', playtime: 632, wins: 222, losses: 184, score: 38} + {team: 'ogres', rank: 106, sessionID: '537b9a1d3803a2870575835f', name: 'pvande', playtime: 39177, wins: 216, losses: 179, score: 37} + {team: 'ogres', rank: 107, sessionID: '537c23fffa0d80a106b10eb4', name: 'Nylan', playtime: 1236, wins: 204, losses: 174, score: 30} + {team: 'ogres', rank: 108, sessionID: '537b91795bc02238050d1b80', name: 'Orange!', playtime: 22940, wins: 210, losses: 181, score: 29} + {team: 'ogres', rank: 109, sessionID: '537b8cfde91b4d3b055261b6', name: 'Thumb', playtime: 22271, wins: 212, losses: 185, score: 27} + {team: 'ogres', rank: 110, sessionID: '53978487888ab73905184003', name: 'Nick2', playtime: 5539, wins: 197, losses: 173, score: 24} + {team: 'ogres', rank: 111, sessionID: '5386313f8ca8b1120b8b58a3', name: 'fudgy', playtime: 2744, wins: 213, losses: 193, score: 20} + {team: 'ogres', rank: 112, sessionID: '537cbcc062dea6b811f109c7', name: 'Kirstin', playtime: 23151, wins: 211, losses: 192, score: 19} + {team: 'ogres', rank: 113, sessionID: '53814d4605e52a3305df086c', name: 'jsut', playtime: 21961, wins: 208, losses: 189, score: 19} + {team: 'ogres', rank: 114, sessionID: '5384c51f7d99a7390560bce1', name: 'Xhuy', playtime: 4562, wins: 204, losses: 188, score: 16} + {team: 'ogres', rank: 115, sessionID: '536259c5fc1acf300b2ebcb7', name: 'DarthNato', playtime: 26611, wins: 206, losses: 193, score: 13} + {team: 'ogres', rank: 116, sessionID: '538db7f65572d43b0521cf9c', name: 'rehashed', playtime: 12008, wins: 201, losses: 188, score: 13} + {team: 'ogres', rank: 117, sessionID: '5361946c801ef0010d3a3369', name: 'DeathScythe', playtime: 0, wins: 209, losses: 197, score: 12} + {team: 'ogres', rank: 118, sessionID: '537f5d073282d7a5076952e6', name: 'kraxor', playtime: 14420, wins: 191, losses: 179, score: 12} + {team: 'ogres', rank: 119, sessionID: '537bc98ba968548907de6dad', name: 'Huragok', playtime: 325, wins: 207, losses: 197, score: 10} + {team: 'ogres', rank: 120, sessionID: '53718545d0d9b1370555448b', name: 'SuchNoob', playtime: 0, wins: 196, losses: 188, score: 8} + {team: 'ogres', rank: 121, sessionID: '538a1888b924da390514c2d6', name: 'Lomidrevo', playtime: 9470, wins: 207, losses: 199, score: 8} + {team: 'ogres', rank: 122, sessionID: '537b92265bc02238050d1bc3', name: 'Drew', playtime: 21829, wins: 199, losses: 192, score: 7} + {team: 'ogres', rank: 123, sessionID: '537b976e556db17605be769e', name: 'Drak', playtime: 9554, wins: 202, losses: 197, score: 5} + {team: 'ogres', rank: 124, sessionID: '5380b07205e52a3305deb2ea', name: 'LinaLin', playtime: 1852, wins: 204, losses: 199, score: 5} + {team: 'ogres', rank: 125, sessionID: '537b84de5bc02238050d1699', name: 'WoLfulus', playtime: 9762, wins: 204, losses: 200, score: 4} + {team: 'ogres', rank: 126, sessionID: '537b7f945bc02238050d14d8', name: 'Shack', playtime: 16108, wins: 199, losses: 197, score: 2} + {team: 'ogres', rank: 127, sessionID: '537badf8ec57a3e805cbf577', name: 'borreltijd', playtime: 29749, wins: 202, losses: 203, score: -1} + {team: 'ogres', rank: 128, sessionID: '537f8306ead05fd3075d1d39', name: 'icoderz', playtime: 5382, wins: 202, losses: 204, score: -2} + {team: 'ogres', rank: 129, sessionID: '537b92b55bc02238050d1c18', name: 'Bullcity', playtime: 7478, wins: 197, losses: 204, score: -7} + {team: 'ogres', rank: 130, sessionID: '537ba0937c89ec9805f4df2f', name: 'Pavlov', playtime: 15761, wins: 198, losses: 205, score: -7} + {team: 'ogres', rank: 131, sessionID: '537b85055bc02238050d16a6', name: 'Drunk McLovin', playtime: 10225, wins: 194, losses: 204, score: -10} + {team: 'ogres', rank: 132, sessionID: '537cbb38a0d7a5cc10992ee9', name: 'Aion Crane', playtime: 9616, wins: 195, losses: 206, score: -11} + {team: 'ogres', rank: 133, sessionID: '537be31fa3b60b390500ddc5', name: 'antkim003', playtime: 19059, wins: 195, losses: 206, score: -11} + {team: 'ogres', rank: 134, sessionID: '537d20d97e1e10b705bbcd58', name: 'Tain', playtime: 28374, wins: 173, losses: 189, score: -16} + {team: 'ogres', rank: 135, sessionID: '537bb6d6386abb6e05a3facf', name: 'RTN', playtime: 4108, wins: 194, losses: 211, score: -17} + {team: 'ogres', rank: 136, sessionID: '537b86b95bc02238050d1706', name: 'Luogbelnu', playtime: 24526, wins: 191, losses: 208, score: -17} + {team: 'ogres', rank: 137, sessionID: '537338f73108bc3905f7528d', name: 'chess', playtime: 321, wins: 192, losses: 213, score: -21} + {team: 'ogres', rank: 138, sessionID: '537df0950efa6a37059df463', name: 'Rury', playtime: 14371, wins: 187, losses: 215, score: -28} + {team: 'ogres', rank: 139, sessionID: '537c11290ff88b2c06287d29', name: 'Crustopher', playtime: 15401, wins: 167, losses: 195, score: -28} + {team: 'ogres', rank: 140, sessionID: '537df96a0efa6a37059df853', name: 'HuangSY', playtime: 34229, wins: 178, losses: 209, score: -31} + {team: 'ogres', rank: 141, sessionID: '537b909f5bc02238050d1b32', name: 'ArthurDent', playtime: 63903, wins: 173, losses: 204, score: -31} + {team: 'ogres', rank: 142, sessionID: '537e901b9008f87b0541fc83', name: 'Mawox', playtime: 15961, wins: 186, losses: 218, score: -32} + {team: 'ogres', rank: 143, sessionID: '537fa33bf56c5874086896cc', name: 'Urg', playtime: 1760, wins: 182, losses: 218, score: -36} + {team: 'ogres', rank: 144, sessionID: '53854e7d7d99a7390560fadd', name: 'Dodrithard', playtime: 4087, wins: 160, losses: 196, score: -36} + {team: 'ogres', rank: 145, sessionID: '537bfa3395356a43065f76bd', name: 'Cicir', playtime: 7369, wins: 183, losses: 221, score: -38} + {team: 'ogres', rank: 146, sessionID: '537ba4f3d60bb0b405d852b2', name: 'Dubastot', playtime: 17312, wins: 160, losses: 201, score: -41} + {team: 'ogres', rank: 147, sessionID: '537b8dbbe91b4d3b05526226', name: 'Raetsel', playtime: 11005, wins: 180, losses: 223, score: -43} + {team: 'ogres', rank: 148, sessionID: '537bc0b31c8dfa820699fcc2', name: 'Source Error', playtime: 1731, wins: 171, losses: 214, score: -43} + {team: 'ogres', rank: 149, sessionID: '537b92dde91b4d3b05526442', name: 'Script Pimpkin', playtime: 18711, wins: 180, losses: 225, score: -45} + {team: 'ogres', rank: 150, sessionID: '538f33d0755876370525988f', name: 'Rigamortis', playtime: 23232, wins: 176, losses: 221, score: -45} + {team: 'ogres', rank: 151, sessionID: '537c8bb826529de30cca4b02', name: 'Static', playtime: 673, wins: 167, losses: 216, score: -49} + {team: 'ogres', rank: 152, sessionID: '537bdd5ed3f3bb3305bd997a', name: 'Tuna', playtime: 4854, wins: 177, losses: 226, score: -49} + {team: 'ogres', rank: 153, sessionID: '537b945d556db17605be74d0', name: 'Dino', playtime: 5413, wins: 177, losses: 227, score: -50} + {team: 'ogres', rank: 154, sessionID: '537bcda2c57303a5070c2f3a', name: 'LaughingMan', playtime: 52476, wins: 170, losses: 222, score: -52} + {team: 'ogres', rank: 155, sessionID: '53825ebf78171d3d057e4e48', name: 'Lord Azrael', playtime: 25968, wins: 175, losses: 227, score: -52} + {team: 'ogres', rank: 156, sessionID: '537d19307e1e10b705bbc877', name: 'Naoki', playtime: 7851, wins: 172, losses: 226, score: -54} + {team: 'ogres', rank: 157, sessionID: '537b95526c13497e05de81d2', name: 'Gromliqk', playtime: 15566, wins: 174, losses: 230, score: -56} + {team: 'ogres', rank: 158, sessionID: '537bacbc03838cf0050ace6f', name: 'cameltoe', playtime: 53128, wins: 171, losses: 230, score: -59} + {team: 'ogres', rank: 159, sessionID: '537b82d75bc02238050d160d', name: 'Kithid', playtime: 14756, wins: 169, losses: 229, score: -60} + {team: 'ogres', rank: 160, sessionID: '537d4e5d3dcf67c40571f5c3', name: 'bonnnie', playtime: 25945, wins: 173, losses: 233, score: -60} + {team: 'ogres', rank: 161, sessionID: '537e4d7a63734c6305059374', name: 'kotowlos', playtime: 6498, wins: 172, losses: 233, score: -61} + {team: 'ogres', rank: 162, sessionID: '537b80425bc02238050d152c', name: 'mdz', playtime: 12720, wins: 167, losses: 229, score: -62} + {team: 'ogres', rank: 163, sessionID: '537bb50218bd7f4705b9d459', name: 'Claros', playtime: 1250, wins: 170, losses: 236, score: -66} + {team: 'ogres', rank: 164, sessionID: '537c8a5626529de30cca4a2f', name: 'nulo', playtime: 5264, wins: 168, losses: 236, score: -68} + {team: 'ogres', rank: 165, sessionID: '537bb4598698e13805226b77', name: 'JojoTheGreat', playtime: 1733, wins: 162, losses: 235, score: -73} + {team: 'ogres', rank: 166, sessionID: '537bab9b89a8aeea05970d0b', name: 'gameloop.io', playtime: 2823, wins: 163, losses: 237, score: -74} + {team: 'ogres', rank: 167, sessionID: '5382411905e52a3305df893b', name: 'Richard Adleta', playtime: 3272, wins: 162, losses: 240, score: -78} + {team: 'ogres', rank: 168, sessionID: '537c4408a56c78cb0cb4f353', name: 'lichens', playtime: 59782, wins: 163, losses: 241, score: -78} + {team: 'ogres', rank: 169, sessionID: '537e1ab60efa6a37059e0bf0', name: 'Scnoobi', playtime: 3430, wins: 159, losses: 239, score: -80} + {team: 'ogres', rank: 170, sessionID: '537f6adc14f08dec07950ab2', name: 'Ralphy282', playtime: 42208, wins: 155, losses: 235, score: -80} + {team: 'ogres', rank: 171, sessionID: '537be8d820a501380564e6e7', name: 'gandalfStormcrow', playtime: 435, wins: 162, losses: 242, score: -80} + {team: 'ogres', rank: 172, sessionID: '537bc4b10de0a02c07e879a8', name: '', playtime: 872, wins: 161, losses: 242, score: -81} + {team: 'ogres', rank: 173, sessionID: '537e581863734c6305059a53', name: 'taz', playtime: 24420, wins: 160, losses: 242, score: -82} + {team: 'ogres', rank: 174, sessionID: '537ce331e9c4e97c05e3ea34', name: 'bb', playtime: 391, wins: 159, losses: 245, score: -86} + {team: 'ogres', rank: 175, sessionID: '537c5f4f14aaabe80c69fd70', name: '@ESWAT', playtime: 13389, wins: 152, losses: 239, score: -87} + {team: 'ogres', rank: 176, sessionID: '537b8a515bc02238050d1873', name: 'joshuacarley', playtime: 23663, wins: 156, losses: 244, score: -88} + {team: 'ogres', rank: 177, sessionID: '537d550d3dcf67c40571f7dc', name: 'J\'Son', playtime: 5290, wins: 156, losses: 246, score: -90} + {team: 'ogres', rank: 178, sessionID: '537c05ef95356a43065f7e1c', name: 'Cerbi', playtime: 9095, wins: 151, losses: 250, score: -99} + {team: 'ogres', rank: 179, sessionID: '537c532126529de30cca3067', name: 'warrned', playtime: 3870, wins: 149, losses: 254, score: -105} + {team: 'ogres', rank: 180, sessionID: '537fc780c1a6b99109171791', name: 'OWalerys', playtime: 18624, wins: 146, losses: 251, score: -105} + {team: 'ogres', rank: 181, sessionID: '537efa7e8fe881f1055de25e', name: 'Smaug', playtime: 14526, wins: 146, losses: 253, score: -107} + {team: 'ogres', rank: 182, sessionID: '537bf37d95356a43065f7286', name: 'cokaroach', playtime: 47117, wins: 124, losses: 237, score: -113} + {team: 'ogres', rank: 183, sessionID: '537e304e64659f3a0577248a', name: 'Plak87', playtime: 5459, wins: 144, losses: 259, score: -115} + {team: 'ogres', rank: 184, sessionID: '537cfe4d9cce053a05c04dc2', name: 'xzores', playtime: 9686, wins: 145, losses: 260, score: -115} + {team: 'ogres', rank: 185, sessionID: '537bb0ad2323353a05bd57ef', name: 'Wicked', playtime: 4520, wins: 140, losses: 258, score: -118} + {team: 'ogres', rank: 186, sessionID: '537cd1c4665bde1b13ffd635', name: 'Delforas', playtime: 3970, wins: 138, losses: 258, score: -120} + {team: 'ogres', rank: 187, sessionID: '53806a8405e52a3305de92fa', name: 'Pabelo', playtime: 4629, wins: 141, losses: 262, score: -121} + {team: 'ogres', rank: 188, sessionID: '537fcc57c1a6b99109171ced', name: 'jhoie', playtime: 1045, wins: 137, losses: 259, score: -122} + {team: 'ogres', rank: 189, sessionID: '5395d1ba7362c439054f7e6e', name: 'JenJen', playtime: 151, wins: 137, losses: 259, score: -122} + {team: 'ogres', rank: 190, sessionID: '537b9dc4ffeaa29e051b2738', name: 'Kevin', playtime: 9970, wins: 136, losses: 263, score: -127} + {team: 'ogres', rank: 191, sessionID: '537b9c09ffeaa29e051b2637', name: 'Tuefekci', playtime: 10790, wins: 131, losses: 259, score: -128} + {team: 'ogres', rank: 192, sessionID: '537c5b3526529de30cca340c', name: 'patchnotes', playtime: 31167, wins: 119, losses: 252, score: -133} + {team: 'ogres', rank: 193, sessionID: '5380fdb47585483905a7c753', name: 'null0pointer', playtime: 9524, wins: 131, losses: 266, score: -135} + {team: 'ogres', rank: 194, sessionID: '537b9f4751e98aa705b60515', name: 'Sawyer', playtime: 9450, wins: 136, losses: 271, score: -135} + {team: 'ogres', rank: 195, sessionID: '5380bd747585483905a7a707', name: 'Lobo', playtime: 5280, wins: 132, losses: 269, score: -137} + {team: 'ogres', rank: 196, sessionID: '5382593bc85c223a05f429d9', name: 'squidlarkin', playtime: 2036, wins: 130, losses: 267, score: -137} + {team: 'ogres', rank: 197, sessionID: '537cd5fee4523d0113ba57ea', name: 'Borlak', playtime: 14470, wins: 133, losses: 271, score: -138} + {team: 'ogres', rank: 198, sessionID: '537bbb201aaa69c4052676fd', name: 'jMerliN', playtime: 3292, wins: 129, losses: 270, score: -141} + {team: 'ogres', rank: 199, sessionID: '537be3c7a3b60b390500de0e', name: 'Dragon DM', playtime: 17848, wins: 131, losses: 274, score: -143} + {team: 'ogres', rank: 200, sessionID: '537b90295bc02238050d1af5', name: 'octopushugs', playtime: 706, wins: 125, losses: 270, score: -145} + {team: 'ogres', rank: 201, sessionID: '5380d5be7585483905a7b1e1', name: 'Quaritch', playtime: 12711, wins: 128, losses: 274, score: -146} + {team: 'ogres', rank: 202, sessionID: '5397732542cf7d3905ed7233', name: 'BloodJohn', playtime: 5178, wins: 127, losses: 276, score: -149} + {team: 'ogres', rank: 203, sessionID: '537cab3d0e905d000fbfad57', name: 'Xor', playtime: 19480, wins: 126, losses: 278, score: -152} + {team: 'ogres', rank: 204, sessionID: '537b88f85bc02238050d17e2', name: 'Jojas', playtime: 9328, wins: 126, losses: 278, score: -152} + {team: 'ogres', rank: 205, sessionID: '539436745009fe5b075b70a7', name: 'Vhr', playtime: 3065, wins: 122, losses: 274, score: -152} + {team: 'ogres', rank: 206, sessionID: '535f0c4b11c0ebd2049d1664', name: 'Jebso', playtime: 0, wins: 125, losses: 278, score: -153} + {team: 'ogres', rank: 207, sessionID: '537b9d3cffeaa29e051b26eb', name: '', playtime: 784, wins: 125, losses: 278, score: -153} + {team: 'ogres', rank: 208, sessionID: '537c3bdb54bc23770a21e166', name: 'seaclair', playtime: 385, wins: 122, losses: 279, score: -157} + {team: 'ogres', rank: 209, sessionID: '537bf147f8b46fbd0544fc15', name: '', playtime: 16376, wins: 109, losses: 269, score: -160} + {team: 'ogres', rank: 210, sessionID: '537bd2e0be90aa5605fb2ebd', name: 'educavalcanti', playtime: 50086, wins: 121, losses: 282, score: -161} + {team: 'ogres', rank: 211, sessionID: '537cd0e0665bde1b13ffd5ca', name: 'itsbth', playtime: 1299, wins: 104, losses: 265, score: -161} + {team: 'ogres', rank: 212, sessionID: '537b8e1ee91b4d3b05526274', name: 'Jorge', playtime: 4728, wins: 118, losses: 280, score: -162} + {team: 'ogres', rank: 213, sessionID: '537b88f6e91b4d3b05526048', name: 'CzonI', playtime: 3033, wins: 120, losses: 283, score: -163} + {team: 'ogres', rank: 214, sessionID: '537b7c26e91b4d3b05525c6a', name: 'TTSS', playtime: 1132, wins: 120, losses: 283, score: -163} + {team: 'ogres', rank: 215, sessionID: '5389d73bb924da3905149015', name: 'oli-f', playtime: 10824, wins: 101, losses: 266, score: -165} + {team: 'ogres', rank: 216, sessionID: '537b8c21e91b4d3b0552616d', name: 'Luke Young', playtime: 10713, wins: 117, losses: 285, score: -168} + {team: 'ogres', rank: 217, sessionID: '537b84e15bc02238050d169c', name: '', playtime: 359, wins: 116, losses: 284, score: -168} + {team: 'ogres', rank: 218, sessionID: '537b845fe91b4d3b05525f03', name: 'walesmd', playtime: 1630, wins: 116, losses: 285, score: -169} + {team: 'ogres', rank: 219, sessionID: '538515a73e0daa390518ba45', name: 'Azerroth', playtime: 19862, wins: 114, losses: 285, score: -171} + {team: 'ogres', rank: 220, sessionID: '537bd660142ee637052420e3', name: 'tkl', playtime: 8276, wins: 102, losses: 278, score: -176} + {team: 'ogres', rank: 221, sessionID: '538a9449b924da3905151926', name: 'cdaaar', playtime: 14955, wins: 45, losses: 222, score: -177} + {team: 'ogres', rank: 222, sessionID: '538345b078171d3d057eae61', name: 'Ikrus', playtime: 13687, wins: 111, losses: 295, score: -184} + {team: 'ogres', rank: 223, sessionID: '537b8e26e91b4d3b05526277', name: 'Zairja', playtime: 10077, wins: 101, losses: 293, score: -192} + {team: 'ogres', rank: 224, sessionID: '537b97f53803a28705758218', name: 'kookieblues', playtime: 2400, wins: 104, losses: 303, score: -199} + {team: 'ogres', rank: 225, sessionID: '537d06bd7e1e10b705bbbe83', name: 'llcossette', playtime: 2648, wins: 95, losses: 302, score: -207} + {team: 'ogres', rank: 226, sessionID: '537b800de91b4d3b05525db8', name: 'Merlin Gough', playtime: 8942, wins: 90, losses: 303, score: -213} + {team: 'ogres', rank: 227, sessionID: '538382db86de19c31c1ce893', name: 'Nick05 Testinator', playtime: 1454, wins: 90, losses: 311, score: -221} + {team: 'ogres', rank: 228, sessionID: '537bcd7ec57303a5070c2f1e', name: 'hedint', playtime: 8881, wins: 92, losses: 314, score: -222} + {team: 'ogres', rank: 229, sessionID: '537cc425665bde1b13ffce89', name: 'dotnetjohn', playtime: 1304, wins: 87, losses: 315, score: -228} + {team: 'ogres', rank: 230, sessionID: '537c3c1454bc23770a21e187', name: 'Prelude', playtime: 2351, wins: 85, losses: 313, score: -228} + {team: 'ogres', rank: 231, sessionID: '538925b4d06c503805fe4ff7', name: 'Perenolder', playtime: 21235, wins: 79, losses: 322, score: -243} + {team: 'ogres', rank: 232, sessionID: '538a26cdd06c503805fec706', name: 'the-k-man', playtime: 10321, wins: 78, losses: 327, score: -249} + {team: 'ogres', rank: 233, sessionID: '537c531d26529de30cca3065', name: 'masashi', playtime: 17871, wins: 75, losses: 330, score: -255} + {team: 'ogres', rank: 234, sessionID: '5371861fd4491339051c3b11', name: 'asdlk;fj asd fas', playtime: 0, wins: 65, losses: 333, score: -268} + {team: 'ogres', rank: 235, sessionID: '537b8429e91b4d3b05525ef5', name: 'Missblit', playtime: 28639, wins: 59, losses: 346, score: -287} + {team: 'ogres', rank: 236, sessionID: '538b1322d06c503805ff299f', name: 'judar1o', playtime: 5891, wins: 59, losses: 347, score: -288} + {team: 'ogres', rank: 237, sessionID: '53583ab57962157d05b398f8', name: 'makertech81', playtime: 170, wins: 55, losses: 344, score: -289} + {team: 'ogres', rank: 238, sessionID: '539723388376eb3805dc2d4e', name: 'immersion', playtime: 6471, wins: 54, losses: 348, score: -294} + {team: 'ogres', rank: 239, sessionID: '537c99aa14aaabe80c6a1a44', name: 'werewolf', playtime: 167, wins: 46, losses: 343, score: -297} + {team: 'ogres', rank: 240, sessionID: '539085aaf369103805172236', name: 'Kabbi', playtime: 6873, wins: 43, losses: 344, score: -301} + {team: 'ogres', rank: 241, sessionID: '537bd587b0d1766d05243016', name: 'Casey', playtime: 1229, wins: 44, losses: 346, score: -302} + {team: 'ogres', rank: 242, sessionID: '537e2bd864659f3a05772075', name: '', playtime: 322, wins: 42, losses: 349, score: -307} + {team: 'ogres', rank: 243, sessionID: '5385c7503e0daa39051919db', name: 'Zack', playtime: 66, wins: 40, losses: 348, score: -308} + {team: 'ogres', rank: 244, sessionID: '537ba0a551e98aa705b605b2', name: '', playtime: 232, wins: 39, losses: 349, score: -310} + {team: 'ogres', rank: 245, sessionID: '535fdebe5c7324a80702cb3b', name: 'mich55', playtime: 0, wins: 38, losses: 349, score: -311} + {team: 'ogres', rank: 246, sessionID: '5390823e7558763705263cc8', name: 'Duchess', playtime: 460, wins: 37, losses: 349, score: -312} + {team: 'ogres', rank: 247, sessionID: '5360a43d9859fefb0673aefa', name: 'daruba', playtime: 0, wins: 34, losses: 351, score: -317} + {team: 'ogres', rank: 248, sessionID: '537bab4f6e54cbda057ee565', name: 'Pajamas', playtime: 27043, wins: 14, losses: 338, score: -324} + {team: 'ogres', rank: 249, sessionID: '537bf053f8b46fbd0544fb8c', name: 'Fusspawn', playtime: 9524, wins: 37, losses: 368, score: -331} + {team: 'ogres', rank: 250, sessionID: '5382f069c85c223a05f47200', name: 'ferrak', playtime: 7015, wins: 33, losses: 373, score: -340} + {team: 'ogres', rank: 251, sessionID: '5380a3737585483905a799e1', name: 'Dark Pikachu', playtime: 1373, wins: 29, losses: 377, score: -348} + {team: 'ogres', rank: 252, sessionID: '538711898ca8b1120b8bdb3f', name: 'A', playtime: 4272, wins: 24, losses: 380, score: -356} + {team: 'ogres', rank: 253, sessionID: '5384af823e0daa3905187cb1', name: 'Macguffin', playtime: 837, wins: 18, losses: 384, score: -366} + {team: 'ogres', rank: 254, sessionID: '537db76b13add33a051bf575', name: 'Luyalve', playtime: 1404, wins: 3, losses: 372, score: -369} + {team: 'ogres', rank: 255, sessionID: '537b9bac16613c8405155a79', name: 'solarian', playtime: 24889, wins: 0, losses: 371, score: -371} + {team: 'ogres', rank: 256, sessionID: '537ba09951e98aa705b605ae', name: 'Potato', playtime: 61777, wins: 0, losses: 371, score: -371} + {team: 'ogres', rank: 257, sessionID: '537d24db84c54c6e05c06ac4', name: 'terriblesarcasm', playtime: 39553, wins: 0, losses: 371, score: -371} + {team: 'ogres', rank: 258, sessionID: '537c2abc224747bb0761634f', name: 'chicones', playtime: 9831, wins: 0, losses: 371, score: -371} + {team: 'ogres', rank: 259, sessionID: '538381a5c83e563705a06fdb', name: 'diddly-dum', playtime: 8077, wins: 0, losses: 372, score: -372} + {team: 'ogres', rank: 260, sessionID: '5388a785b924da3905139f46', name: 'AWESOMEHACKER', playtime: 564, wins: 0, losses: 372, score: -372} + {team: 'ogres', rank: 261, sessionID: '537bb6d2386abb6e05a3facc', name: 'chrm', playtime: 213307, wins: 0, losses: 375, score: -375} + {team: 'ogres', rank: 262, sessionID: '537bc26e8fe668b406d4c019', name: 'Sapid', playtime: 11917, wins: 0, losses: 376, score: -376} + {team: 'ogres', rank: 263, sessionID: '5357127a1bfa9bba14b5e048', name: 'dcm', playtime: 5380, wins: 0, losses: 376, score: -376} + {team: 'ogres', rank: 264, sessionID: '537aee4cfb4c173805cf26f7', name: 'basicer', playtime: 10407, wins: 0, losses: 376, score: -376} + {team: 'ogres', rank: 265, sessionID: '5382cbb078171d3d057e804f', name: 'vvv', playtime: 719, wins: 0, losses: 376, score: -376} + {team: 'ogres', rank: 266, sessionID: '537ba40a903fd2b8051553b0', name: 'ElderTale', playtime: 13984, wins: 0, losses: 376, score: -376} + {team: 'ogres', rank: 267, sessionID: '53839e256f3bea3a05fb09b3', name: 'Gondolfs', playtime: 29985, wins: 0, losses: 378, score: -378} + {team: 'ogres', rank: 268, sessionID: '537a73a6e488a7380545affd', name: 'Galvan', playtime: 514, wins: 0, losses: 378, score: -378} + {team: 'ogres', rank: 269, sessionID: '537b96b16c13497e05de82a8', name: 'Krris', playtime: 2618, wins: 0, losses: 379, score: -379} + {team: 'ogres', rank: 270, sessionID: '537bc1b81db8c8ac063a3b7b', name: 'jpiasetz', playtime: 14565, wins: 0, losses: 380, score: -380} ] diff --git a/app/views/play/ladder/utils.coffee b/app/views/play/ladder/utils.coffee index 10f088093..ffa340ac3 100644 --- a/app/views/play/ladder/utils.coffee +++ b/app/views/play/ladder/utils.coffee @@ -19,4 +19,4 @@ module.exports.teamDataFromLevel = (level) -> primaryColor: primaryColor }) - teams \ No newline at end of file + teams diff --git a/app/views/play/ladder_home.coffee b/app/views/play/ladder_home.coffee index 0150b2284..1508697c9 100644 --- a/app/views/play/ladder_home.coffee +++ b/app/views/play/ladder_home.coffee @@ -12,7 +12,7 @@ class LevelSessionsCollection extends CocoCollection @url = "/db/user/#{me.id}/level.sessions?project=state.complete,levelID" module.exports = class LadderHomeView extends View - id: "ladder-home-view" + id: 'ladder-home-view' template: template constructor: (options) -> @@ -35,33 +35,33 @@ module.exports = class LadderHomeView extends View difficulty: 4 id: 'greed' image: '/file/db/level/53558b5a9914f5a90d7ccddb/greed_banner.jpg' - description: "Liked Dungeon Arena and Gold Rush? Put them together in this economic arena!" + description: 'Liked Dungeon Arena and Gold Rush? Put them together in this economic arena!' } { name: 'Dungeon Arena' difficulty: 3 id: 'dungeon-arena' image: '/file/db/level/53173f76c269d400000543c2/Level%20Banner%20Dungeon%20Arena.jpg' - description: "Play head-to-head against fellow Wizards in a dungeon melee!" + description: 'Play head-to-head against fellow Wizards in a dungeon melee!' } { name: 'Gold Rush' difficulty: 3 id: 'gold-rush' image: '/file/db/level/533353722a61b7ca6832840c/Gold-Rush.png' - description: "Prove you are better at collecting gold than your opponent!" + description: 'Prove you are better at collecting gold than your opponent!' } { name: 'Brawlwood' difficulty: 4 id: 'brawlwood' image: '/file/db/level/52d97ecd32362bc86e004e87/Level%20Banner%20Brawlwood.jpg' - description: "Combat the armies of other Wizards in a strategic forest arena! (Fast computer required.)" + description: 'Combat the armies of other Wizards in a strategic forest arena! (Fast computer required.)' } ] context.campaigns = [ - {id: "multiplayer", name: "Multiplayer Arenas", description: "... in which you code head-to-head against other players.", levels: arenas} + {id: 'multiplayer', name: 'Multiplayer Arenas', description: '... in which you code head-to-head against other players.', levels: arenas} ] context.levelStatusMap = @levelStatusMap context diff --git a/app/views/play/level/control_bar_view.coffee b/app/views/play/level/control_bar_view.coffee index d5102c60b..7a1dd58ec 100644 --- a/app/views/play/level/control_bar_view.coffee +++ b/app/views/play/level/control_bar_view.coffee @@ -6,7 +6,7 @@ MultiplayerModal = require './modal/multiplayer_modal' ReloadModal = require './modal/reload_modal' module.exports = class ControlBarView extends View - id: "control-bar-view" + id: 'control-bar-view' template: template subscriptions: diff --git a/app/views/play/level/dialogue_animator.coffee b/app/views/play/level/dialogue_animator.coffee index dee5ca48c..2edae3662 100644 --- a/app/views/play/level/dialogue_animator.coffee +++ b/app/views/play/level/dialogue_animator.coffee @@ -3,24 +3,24 @@ module.exports = class DialogueAnimator childrenToAdd: null charsToAdd: null childAnimator: null - + constructor: (html, @jqueryElement) -> d = $('
').html(html) @childrenToAdd = _.map(d[0].childNodes, (e) -> return e) - + tick: -> if not @charsToAdd and not @childAnimator @addNextElement() - + if @charsToAdd @addSingleChar() return - + if @childAnimator @childAnimator.tick() if @childAnimator.done() @childAnimator = null - + addNextElement: -> return unless @childrenToAdd.length nextElem = @childrenToAdd[0] @@ -33,13 +33,13 @@ module.exports = class DialogueAnimator @jqueryElement.append(newElem) if value @childAnimator = new DialogueAnimator(value, newElem) - + addSingleChar: -> @jqueryElement.html(@jqueryElement.html() + @charsToAdd[0]) @charsToAdd = @charsToAdd[1..] if @charsToAdd.length is 0 @charsToAdd = null - + done: -> return false if @childrenToAdd.length > 0 return false if @charsToAdd diff --git a/app/views/play/level/goals_view.coffee b/app/views/play/level/goals_view.coffee index 21e27e29d..e55d881b8 100644 --- a/app/views/play/level/goals_view.coffee +++ b/app/views/play/level/goals_view.coffee @@ -9,7 +9,7 @@ stateIconMap = failure: 'icon-remove' module.exports = class GoalsView extends View - id: "goals-view" + id: 'goals-view' template: template subscriptions: @@ -22,7 +22,7 @@ module.exports = class GoalsView extends View 'mouseenter': -> @mouseEntered = true @updatePlacement() - + 'mouseleave': -> @mouseEntered = false @updatePlacement() @@ -38,7 +38,7 @@ module.exports = class GoalsView extends View classToShow ?= 'timed-out' if e.timedOut classToShow ?= 'incomplete' @$el.find('.goal-status.'+classToShow).removeClass 'secret' - + list = $('#primary-goals-list', @$el) list.empty() goals = [] @@ -78,11 +78,11 @@ module.exports = class GoalsView extends View render: -> super() @$el.addClass('secret').addClass('expanded') - + afterRender: -> super() @updatePlacement() - + updatePlacement: -> if @playbackEnded or @mouseEntered # expand diff --git a/app/views/play/level/gold_view.coffee b/app/views/play/level/gold_view.coffee index 01cde9f21..f7168b386 100644 --- a/app/views/play/level/gold_view.coffee +++ b/app/views/play/level/gold_view.coffee @@ -3,7 +3,7 @@ template = require 'templates/play/level/gold' teamTemplate = require 'templates/play/level/team_gold' module.exports = class GoldView extends View - id: "gold-view" + id: 'gold-view' template: template subscriptions: diff --git a/app/views/play/level/hud_view.coffee b/app/views/play/level/hud_view.coffee index 612dcae41..75bc68346 100644 --- a/app/views/play/level/hud_view.coffee +++ b/app/views/play/level/hud_view.coffee @@ -143,7 +143,7 @@ module.exports = class HUDView extends View createProperties: -> props = @$el.find('.thang-props') - props.find(":not(.thang-name)").remove() + props.find(':not(.thang-name)').remove() props.find('.thang-name').text(if @thang.type then "#{@thang.id} - #{@thang.type}" else @thang.id) propNames = _.without @thang.hudProperties ? [], 'action' nColumns = Math.ceil propNames.length / 5 @@ -187,8 +187,8 @@ module.exports = class HUDView extends View group.append(button) response.button = $('button:last', group) else - s = $.i18n.t('play_level.hud_continue', defaultValue: "Continue (shift+space)") - sk = $.i18n.t('play_level.skip_tutorial', defaultValue: "skip: esc") + s = $.i18n.t('play_level.hud_continue', defaultValue: 'Continue (shift+space)') + sk = $.i18n.t('play_level.skip_tutorial', defaultValue: 'skip: esc') if not @escapePressed group.append('' + sk + '') group.append($('')) @@ -201,7 +201,7 @@ module.exports = class HUDView extends View if @animator.done() clearInterval(@messageInterval) @messageInterval = null - $('.enter', @bubble).removeClass("secret").css('opacity', 0.0).delay(500).animate({opacity:1.0}, 500, @animateEnterButton) + $('.enter', @bubble).removeClass('secret').css('opacity', 0.0).delay(500).animate({opacity: 1.0}, 500, @animateEnterButton) if @lastResponses buttons = $('.enter button') for response, i in @lastResponses @@ -228,7 +228,7 @@ module.exports = class HUDView extends View return unless @bubble button = $('.enter', @bubble) dot = $('.dot', button) - dot.animate({opacity:0.2}, 300).animate({opacity:1.9}, 600, @animateEnterButton) + dot.animate({opacity: 0.2}, 300).animate({opacity: 1.9}, 600, @animateEnterButton) switchToDialogueElements: -> @dialogueMode = true @@ -236,11 +236,11 @@ module.exports = class HUDView extends View @$el.find('.thang-canvas-wrapper').removeClass('secret') $('.dialogue-area', @$el) .removeClass('secret') - .animate({opacity:1.0}, 200) + .animate({opacity: 1.0}, 200) $('.dialogue-bubble', @$el) .css('opacity', 0.0) .delay(200) - .animate({opacity:1.0}, 200) + .animate({opacity: 1.0}, 200) clearTimeout @hintNextSelectionTimeout switchToThangElements: -> @@ -257,26 +257,26 @@ module.exports = class HUDView extends View @updateActions() createPropElement: (prop) -> - if prop in ["maxHealth"] + if prop in ['maxHealth'] return null # included in the bar context = prop: prop - hasIcon: prop in ["health", "pos", "target", "inventory", "gold", "bountyGold", "visualRange", "attackDamage", "attackRange", "maxSpeed"] - hasBar: prop in ["health"] + hasIcon: prop in ['health', 'pos', 'target', 'inventory', 'gold', 'bountyGold', 'visualRange', 'attackDamage', 'attackRange', 'maxSpeed'] + hasBar: prop in ['health'] $(prop_template(context)) updatePropElement: (prop, val) -> pel = @$el.find '.thang-props *[name=' + prop + ']' - if prop in ["maxHealth"] + if prop in ['maxHealth'] return # Don't show maxes--they're built into bar labels. - if prop in ["health"] - max = @thang["max" + prop.charAt(0).toUpperCase() + prop.slice(1)] - regen = @thang[prop + "ReplenishRate"] + if prop in ['health'] + max = @thang['max' + prop.charAt(0).toUpperCase() + prop.slice(1)] + regen = @thang[prop + 'ReplenishRate'] percent = Math.round 100 * val / max - pel.find('.bar').css 'width', percent + "%" - labelText = prop + ": " + @formatValue(prop, val) + " / " + @formatValue(prop, max) + pel.find('.bar').css 'width', percent + '%' + labelText = prop + ': ' + @formatValue(prop, val) + ' / ' + @formatValue(prop, max) if regen - labelText += " (+" + @formatValue(prop, regen) + "/s)" + labelText += ' (+' + @formatValue(prop, regen) + '/s)' pel.find('.bar-prop-value').text(Math.round(max)) if max else s = @formatValue(prop, val) @@ -290,11 +290,11 @@ module.exports = class HUDView extends View pel formatValue: (prop, val) -> - if prop is "target" and not val - val = @thang["targetPos"] + if prop is 'target' and not val + val = @thang['targetPos'] val = null if val?.isZero() - if prop is "rotation" - return (val * 180 / Math.PI).toFixed(0) + "˚" + if prop is 'rotation' + return (val * 180 / Math.PI).toFixed(0) + '˚' if prop.search(/Range$/) isnt -1 return val + 'm' if typeof val is 'number' @@ -302,14 +302,14 @@ module.exports = class HUDView extends View if -10 < val < 10 then return val.toFixed(2) if -100 < val < 100 then return val.toFixed(1) return val.toFixed(0) - if val and typeof val is "object" + if val and typeof val is 'object' if val.id return val.id else if val.x and val.y return "x: #{val.x.toFixed(0)} y: #{val.y.toFixed(0)}" #return "x: #{val.x.toFixed(0)} y: #{val.y.toFixed(0)}, z: #{val.z.toFixed(0)}" # Debugging: include z else if not val? - return "No " + prop + return 'No ' + prop return val updateActions: -> diff --git a/app/views/play/level/level_chat_view.coffee b/app/views/play/level/level_chat_view.coffee index 09936ae65..c581563da 100644 --- a/app/views/play/level/level_chat_view.coffee +++ b/app/views/play/level/level_chat_view.coffee @@ -51,14 +51,14 @@ module.exports = class LevelChatView extends View @playNoise() if e.message.authorID isnt me.id playNoise: -> - Backbone.Mediator.publish 'play-sound', trigger: "chat_received" + Backbone.Mediator.publish 'play-sound', trigger: 'chat_received' messageObjectToJQuery: (message) -> td = $('') content = message.content content = _.string.escapeHTML(content) - content = content.replace(/\n/g, "
") - content = content.replace(RegExp(' ', 'g'), "  ") # coffeescript can't compile "/ /g" + content = content.replace(/\n/g, '
') + content = content.replace(RegExp(' ', 'g'), '  ') # coffeescript can't compile '/ /g' if _.string.startsWith(content, '/me') content = message.authorName + content.slice(3) diff --git a/app/views/play/level/level_loading_view.coffee b/app/views/play/level/level_loading_view.coffee index 217b4bc9b..2ed460796 100644 --- a/app/views/play/level/level_loading_view.coffee +++ b/app/views/play/level/level_loading_view.coffee @@ -1,9 +1,8 @@ View = require 'views/kinds/CocoView' template = require 'templates/play/level/level_loading' - module.exports = class LevelLoadingView extends View - id: "level-loading-view" + id: 'level-loading-view' template: template onLoaded: -> diff --git a/app/views/play/level/modal/docs_modal.coffee b/app/views/play/level/modal/docs_modal.coffee index 1df8975c0..72aa6b8d0 100644 --- a/app/views/play/level/modal/docs_modal.coffee +++ b/app/views/play/level/modal/docs_modal.coffee @@ -50,7 +50,7 @@ module.exports = class DocsModal extends View clickTab: (e) => @$el.find('li.active').removeClass('active') - + afterInsert: -> super() Backbone.Mediator.publish 'level:docs-shown' diff --git a/app/views/play/level/modal/editor_config_modal.coffee b/app/views/play/level/modal/editor_config_modal.coffee index ba2e3b7f0..5f8fd878f 100644 --- a/app/views/play/level/modal/editor_config_modal.coffee +++ b/app/views/play/level/modal/editor_config_modal.coffee @@ -1,6 +1,6 @@ View = require 'views/kinds/ModalView' template = require 'templates/play/level/modal/editor_config' -{me} = require('lib/auth') +{me} = require 'lib/auth' module.exports = class EditorConfigModal extends View id: 'level-editor-config-modal' diff --git a/app/views/play/level/modal/victory_modal.coffee b/app/views/play/level/modal/victory_modal.coffee index 954ab63ef..6ee9cabef 100644 --- a/app/views/play/level/modal/victory_modal.coffee +++ b/app/views/play/level/modal/victory_modal.coffee @@ -54,7 +54,7 @@ module.exports = class VictoryModal extends View @feedback = new LevelFeedback() @feedback.set('levelID', @level.get('slug') or @level.id) @feedback.set('levelName', @level.get('name') or '') - @feedback.set('level', {majorVersion: @level.get('version').major, original:@level.get('original')}) + @feedback.set('level', {majorVersion: @level.get('version').major, original: @level.get('original')}) @showStars() onPlayNextLevel: -> @@ -79,7 +79,7 @@ module.exports = class VictoryModal extends View elapsed = (new Date() - new Date(me.get('dateCreated'))) enough = not c.hasNextLevel or elapsed >= 30 * 60 * 1000 if enough and not me.get('hourOfCodeComplete') - $('body').append($("")) + $('body').append($('')) me.set 'hourOfCodeComplete', true me.patch() window.tracker?.trackEvent 'Hour of Code Finish', {} @@ -95,7 +95,7 @@ module.exports = class VictoryModal extends View afterInsert: -> super() - Backbone.Mediator.publish 'play-sound', trigger: "victory" + Backbone.Mediator.publish 'play-sound', trigger: 'victory' gapi?.plusone?.go? @$el[0] FB?.XFBML?.parse? @$el[0] twttr?.widgets?.load?() diff --git a/app/views/play/level/playback_view.coffee b/app/views/play/level/playback_view.coffee index fb0ba5fd7..4ae415729 100644 --- a/app/views/play/level/playback_view.coffee +++ b/app/views/play/level/playback_view.coffee @@ -6,7 +6,7 @@ EditorConfigModal = require './modal/editor_config_modal' KeyboardShortcutsModal = require './modal/keyboard_shortcuts_modal' module.exports = class PlaybackView extends View - id: "playback-view" + id: 'playback-view' template: template subscriptions: @@ -48,14 +48,13 @@ module.exports = class PlaybackView extends View '⌘+], ctrl+]': 'onScrubForward' '⌘+⇧+], ctrl+⇧+]': 'onSingleScrubForward' - # popover that shows at the current mouse position on the progressbar, using the bootstrap popover. # Could make this into a jQuery plugins itself theoretically. class HoverPopup extends $.fn.popover.Constructor constructor: () -> @enabled = true @shown = false - @type = "HoverPopup" + @type = 'HoverPopup' @options = placement: 'top' container: 'body' @@ -66,7 +65,7 @@ module.exports = class PlaybackView extends View @$element = $('#timeProgress') @$tip = $('#timePopover') - @content = "" + @content = '' getContent: -> @content @@ -122,7 +121,7 @@ module.exports = class PlaybackView extends View # These functions could go to some helper class pad2: (num) -> - if not num? or num is 0 then "00" else ((if num < 10 then "0" else "") + num) + if not num? or num is 0 then '00' else ((if num < 10 then '0' else '') + num) formatTime: (text, time) => "#{text}\t#{@timeToString time}" @@ -131,9 +130,9 @@ module.exports = class PlaybackView extends View mins = Math.floor(time / 60) secs = (time - mins * 60).toFixed(1) if withUnits - ret = "" - ret = (mins + " " + (if mins is 1 then @minute else @minutes)) if (mins > 0) - ret = (ret + " " + secs + " " + (if secs is 1 then @second else @seconds)) if (secs > 0 or mins is 0) + ret = '' + ret = (mins + ' ' + (if mins is 1 then @minute else @minutes)) if (mins > 0) + ret = (ret + ' ' + secs + ' ' + (if secs is 1 then @second else @seconds)) if (secs > 0 or mins is 0) else "#{mins}:#{@pad2 secs}" @@ -302,7 +301,7 @@ module.exports = class PlaybackView extends View @clickingSlider = false # whether the mouse has been pressed down without moving @$progressScrubber.slider( max: @sliderIncrements - animate: "slow" + animate: 'slow' slide: (event, ui) => @scrubTo ui.value / @sliderIncrements @slideCount += 1 diff --git a/app/views/play/level/thang_avatar_view.coffee b/app/views/play/level/thang_avatar_view.coffee index fe9babf5b..054fb0d1a 100644 --- a/app/views/play/level/thang_avatar_view.coffee +++ b/app/views/play/level/thang_avatar_view.coffee @@ -7,7 +7,7 @@ module.exports = class ThangAvatarView extends View template: template subscriptions: - 'tome:problems-updated': "onProblemsUpdated" + 'tome:problems-updated': 'onProblemsUpdated' 'god:new-world-created': 'onNewWorld' constructor: (options) -> @@ -18,10 +18,10 @@ module.exports = class ThangAvatarView extends View if not @thangType console.error 'Thang avatar view expected a thang type to be provided.' return - + unless @thangType.isFullyLoaded() or @thangType.loading @thangType.fetch() - + # couldn't get the level view to load properly through the supermodel # so just doing it manually this time. @listenTo @thangType, 'sync', @render @@ -73,4 +73,4 @@ module.exports = class ThangAvatarView extends View @options.thang = @thang = e.world.thangMap[@thang.id] if @thang destroy: -> - super() \ No newline at end of file + super() diff --git a/app/views/play/level/tome/cast_button_view.coffee b/app/views/play/level/tome/cast_button_view.coffee index 7454c3cd4..1eb85c79f 100644 --- a/app/views/play/level/tome/cast_button_view.coffee +++ b/app/views/play/level/tome/cast_button_view.coffee @@ -11,7 +11,7 @@ module.exports = class CastButtonView extends View 'click .autocast-delays a': 'onCastOptionsClick' subscriptions: - 'tome:spell-changed': "onSpellChanged" + 'tome:spell-changed': 'onSpellChanged' 'tome:cast-spells': 'onCastSpells' 'god:world-load-progress-changed': 'onWorldLoadProgressChanged' 'god:new-world-created': 'onNewWorld' @@ -20,8 +20,8 @@ module.exports = class CastButtonView extends View super options @spells = options.spells @levelID = options.levelID - @castShortcut = "⇧↵" - @castShortcutVerbose = "Shift+Enter" + @castShortcut = '⇧↵' + @castShortcutVerbose = 'Shift+Enter' getRenderData: (context={}) -> context = super context @@ -84,16 +84,16 @@ module.exports = class CastButtonView extends View Backbone.Mediator.publish 'tome:spell-has-changed-significantly-calculation', hasChangedSignificantly: castable @castButtonGroup.toggleClass('castable', castable).toggleClass('casting', @casting) if @casting - s = $.i18n.t("play_level.tome_cast_button_casting", defaultValue: "Casting") + s = $.i18n.t('play_level.tome_cast_button_casting', defaultValue: 'Casting') else if castable - s = $.i18n.t("play_level.tome_cast_button_castable", defaultValue: "Cast Spell") + " " + @castShortcut + s = $.i18n.t('play_level.tome_cast_button_castable', defaultValue: 'Cast Spell') + ' ' + @castShortcut else - s = $.i18n.t("play_level.tome_cast_button_cast", defaultValue: "Spell Cast") + s = $.i18n.t('play_level.tome_cast_button_cast', defaultValue: 'Spell Cast') @castButton.text s @castButton.prop 'disabled', not castable setAutocastDelay: (delay) -> - #console.log "Set autocast delay to", delay + #console.log 'Set autocast delay to', delay return unless delay @autocastDelay = delay = parseInt delay me.set('autocastDelay', delay) diff --git a/app/views/play/level/tome/doc_formatter.coffee b/app/views/play/level/tome/doc_formatter.coffee index 20923916a..2d256c3ad 100644 --- a/app/views/play/level/tome/doc_formatter.coffee +++ b/app/views/play/level/tome/doc_formatter.coffee @@ -7,18 +7,18 @@ safeJSONStringify = (input, maxDepth) -> output = {} pPath = undefined refIdx = undefined - path = path or "" + path = path or '' depth = depth or 0 depth++ - return "{depth over " + maxDepth + "}" if maxDepth and depth > maxDepth + return '{depth over ' + maxDepth + '}' if maxDepth and depth > maxDepth for p of input - pPath = ((if path then (path + ".") else "")) + p - if typeof input[p] is "function" - output[p] = "{function}" - else if typeof input[p] is "object" + pPath = ((if path then (path + '.') else '')) + p + if typeof input[p] is 'function' + output[p] = '{function}' + else if typeof input[p] is 'object' refIdx = refs.indexOf(input[p]) if -1 isnt refIdx - output[p] = "{reference to " + refsPaths[refIdx] + "}" + output[p] = '{reference to ' + refsPaths[refIdx] + '}' else refs.push input[p] refsPaths.push pPath @@ -29,7 +29,7 @@ safeJSONStringify = (input, maxDepth) -> refs = [] refsPaths = [] maxDepth = maxDepth or 5 - if typeof input is "object" + if typeof input is 'object' output = recursion(input) else output = input diff --git a/app/views/play/level/tome/problem.coffee b/app/views/play/level/tome/problem.coffee index 9dc6db442..13fb7cede 100644 --- a/app/views/play/level/tome/problem.coffee +++ b/app/views/play/level/tome/problem.coffee @@ -1,5 +1,5 @@ ProblemAlertView = require './problem_alert_view' -Range = ace.require("ace/range").Range +Range = ace.require('ace/range').Range module.exports = class Problem annotation: null @@ -25,7 +25,7 @@ module.exports = class Problem column: start.col, raw: text, text: text, - type: @aetherProblem.level ? "error" + type: @aetherProblem.level ? 'error' buildAlertView: -> @alertView = new ProblemAlertView problem: @ @@ -39,7 +39,7 @@ module.exports = class Problem @markerRange = new Range start.row, start.col, end.row, end.col @markerRange.start = @ace.getSession().getDocument().createAnchor @markerRange.start @markerRange.end = @ace.getSession().getDocument().createAnchor @markerRange.end - @markerRange.id = @ace.getSession().addMarker @markerRange, clazz, "text" + @markerRange.id = @ace.getSession().addMarker @markerRange, clazz, 'text' removeMarkerRange: -> return unless @markerRange diff --git a/app/views/play/level/tome/problem_alert_view.coffee b/app/views/play/level/tome/problem_alert_view.coffee index f17648e67..2a77e1632 100644 --- a/app/views/play/level/tome/problem_alert_view.coffee +++ b/app/views/play/level/tome/problem_alert_view.coffee @@ -9,7 +9,7 @@ module.exports = class ProblemAlertView extends View subscriptions: {} events: - "click .close": "onRemoveClicked" + 'click .close': 'onRemoveClicked' constructor: (options) -> super options diff --git a/app/views/play/level/tome/spell.coffee b/app/views/play/level/tome/spell.coffee index 523d8451b..0572542b3 100644 --- a/app/views/play/level/tome/spell.coffee +++ b/app/views/play/level/tome/spell.coffee @@ -32,7 +32,7 @@ module.exports = class Spell else @setLanguage 'javascript' @useTranspiledCode = @shouldUseTranspiledCode() - console.log "Spell", @spellKey, "is using transpiled code (should only happen if it's an enemy/spectate writable method)." if @useTranspiledCode + console.log 'Spell', @spellKey, 'is using transpiled code (should only happen if it\'s an enemy/spectate writable method).' if @useTranspiledCode @source = @originalSource @parameters = p.parameters @@ -43,7 +43,7 @@ module.exports = class Spell @view.render() # Get it ready and code loaded in advance @tabView = new SpellListTabEntryView spell: @, supermodel: @supermodel, language: @language @tabView.render() - @team = @permissions.readwrite[0] ? "common" + @team = @permissions.readwrite[0] ? 'common' Backbone.Mediator.publish 'tome:spell-created', spell: @ destroy: -> @@ -88,11 +88,11 @@ module.exports = class Spell else pure = spellThang.aether.transpile source problems = spellThang.aether.problems - #console.log "aether transpiled", source.length, "to", spellThang.aether.pure.length, "for", thangID, @spellKey + #console.log 'aether transpiled', source.length, 'to', spellThang.aether.pure.length, 'for', thangID, @spellKey else spellThang.aether.pure = pure spellThang.aether.problems = problems - #console.log "aether reused transpilation for", thangID, @spellKey + #console.log 'aether reused transpilation for', thangID, @spellKey null hasChanged: (newSource=null, currentSource=null) -> @@ -103,19 +103,19 @@ module.exports = class Spell aether = spellThang.aether break unless aether - console.error @toString(), "couldn't find a spellThang with aether of", @thangs + console.error @toString(), 'couldn\'t find a spellThang with aether of', @thangs cb false workerMessage = - function: "hasChangedSignificantly" + function: 'hasChangedSignificantly' a: (newSource ? @originalSource) spellKey: @spellKey b: (currentSource ? @source) careAboutLineNumbers: true careAboutLint: true - @worker.addEventListener "message", (e) => + @worker.addEventListener 'message', (e) => workerData = JSON.parse e.data - if workerData.function is "hasChangedSignificantly" and workerData.spellKey is @spellKey - @worker.removeEventListener "message", arguments.callee, false + if workerData.function is 'hasChangedSignificantly' and workerData.spellKey is @spellKey + @worker.removeEventListener 'message', arguments.callee, false cb(workerData.hasChanged) @worker.postMessage JSON.stringify(workerMessage) @@ -124,12 +124,12 @@ module.exports = class Spell writable = @permissions.readwrite.length > 0 aetherOptions = problems: - jshint_W040: {level: "ignore"} - jshint_W030: {level: "ignore"} # aether_NoEffect instead - jshint_W038: {level: "ignore"} # eliminates hoisting problems - jshint_W091: {level: "ignore"} # eliminates more hoisting problems - jshint_E043: {level: "ignore"} # https://github.com/codecombat/codecombat/issues/813 -- since we can't actually tell JSHint to really ignore things - jshint_Unknown: {level: "ignore"} # E043 also triggers Unknown, so ignore that, too + jshint_W040: {level: 'ignore'} + jshint_W030: {level: 'ignore'} # aether_NoEffect instead + jshint_W038: {level: 'ignore'} # eliminates hoisting problems + jshint_W091: {level: 'ignore'} # eliminates more hoisting problems + jshint_E043: {level: 'ignore'} # https://github.com/codecombat/codecombat/issues/813 -- since we can't actually tell JSHint to really ignore things + jshint_Unknown: {level: 'ignore'} # E043 also triggers Unknown, so ignore that, too aether_MissingThis: {level: 'error'} language: @language functionName: @name @@ -137,13 +137,13 @@ module.exports = class Spell yieldConditionally: thang.plan? globals: ['Vector', '_'] # TODO: Gridmancer doesn't currently work with protectAPI, so hack it off - protectAPI: not (@skipProtectAPI or window.currentView?.level.get('name').match("Gridmancer")) and writable # If anyone can write to this method, we must protect it. + protectAPI: not (@skipProtectAPI or window.currentView?.level.get('name').match('Gridmancer')) and writable # If anyone can write to this method, we must protect it. includeFlow: false executionLimit: 1 * 1000 * 1000 - #console.log "creating aether with options", aetherOptions + #console.log 'creating aether with options', aetherOptions aether = new Aether aetherOptions workerMessage = - function: "createAether" + function: 'createAether' spellKey: @spellKey options: aetherOptions @worker.postMessage JSON.stringify workerMessage @@ -155,7 +155,7 @@ module.exports = class Spell spellThang.castAether = null Backbone.Mediator.publish 'tome:spell-changed-language', spell: @, language: @language workerMessage = - function: "updateLanguageAether" + function: 'updateLanguageAether' newLanguage: @language @worker.postMessage JSON.stringify workerMessage @transpile() diff --git a/app/views/play/level/tome/spell_debug_view.coffee b/app/views/play/level/tome/spell_debug_view.coffee index 2fb4584f9..8d08dca71 100644 --- a/app/views/play/level/tome/spell_debug_view.coffee +++ b/app/views/play/level/tome/spell_debug_view.coffee @@ -1,11 +1,11 @@ View = require 'views/kinds/CocoView' template = require 'templates/play/level/tome/spell_debug' -Range = ace.require("ace/range").Range -TokenIterator = ace.require("ace/token_iterator").TokenIterator +Range = ace.require('ace/range').Range +TokenIterator = ace.require('ace/token_iterator').TokenIterator serializedClasses = - Thang: require "lib/world/thang" - Vector: require "lib/world/vector" - Rectangle: require "lib/world/rectangle" + Thang: require 'lib/world/thang' + Vector: require 'lib/world/vector' + Rectangle: require 'lib/world/rectangle' module.exports = class DebugView extends View className: 'spell-debug-view' @@ -39,11 +39,9 @@ module.exports = class DebugView extends View @workerIsSimulating = false @spellHasChanged = false @debouncedTooltipUpdate = _.debounce @updateTooltipProgress, 100 - - pad2: (num) -> - if not num? or num is 0 then "00" else ((if num < 10 then "0" else "") + num) + if not num? or num is 0 then '00' else ((if num < 10 then '0' else '') + num) calculateCurrentTimeString: => time = @currentFrame / @frameRate @@ -51,45 +49,44 @@ module.exports = class DebugView extends View secs = (time - mins * 60).toFixed(1) "#{mins}:#{@pad2 secs}" - setTooltipKeyAndValue: (key, value) => @hideProgressBarAndShowText() message = "Time: #{@calculateCurrentTimeString()}\n#{key}: #{value}" - @$el.find("code").text message + @$el.find('code').text message @$el.show().css(@pos) setTooltipText: (text) => #perhaps changing styling here in the future @hideProgressBarAndShowText() - @$el.find("code").text text + @$el.find('code').text text @$el.show().css(@pos) - + setTooltipProgress: (progress) => @showProgressBarAndHideText() - @$el.find(".progress-bar").css('width',progress + '%').attr 'aria-valuenow', progress + @$el.find('.progress-bar').css('width', progress + '%').attr 'aria-valuenow', progress @$el.show().css(@pos) - + showProgressBarAndHideText: -> - @$el.find("pre").css("display","none") - @$el.find(".progress").css("display","block") - + @$el.find('pre').css('display', 'none') + @$el.find('.progress').css('display', 'block') + hideProgressBarAndShowText: -> - @$el.find("pre").css("display","block") - @$el.find(".progress").css("display","none") - + @$el.find('pre').css('display', 'block') + @$el.find('.progress').css('display', 'none') + onTomeCast: -> @invalidateCache() invalidateCache: -> @cache = {} - retrieveValueFromCache: (thangID,spellID,variableChain,frame) -> + retrieveValueFromCache: (thangID, spellID, variableChain, frame) -> joinedVariableChain = variableChain.join() value = @cache[frame]?[thangID]?[spellID]?[joinedVariableChain] return value ? undefined updateCache: (thangID, spellID, variableChain, frame, value) -> currentObject = @cache - keys = [frame,thangID,spellID,variableChain.join()] + keys = [frame, thangID, spellID, variableChain.join()] for keyIndex in [0...(keys.length - 1)] key = keys[keyIndex] unless key of currentObject @@ -97,7 +94,6 @@ module.exports = class DebugView extends View currentObject = currentObject[key] currentObject[keys[keys.length - 1]] = value - changeCurrentThangAndSpell: (thangAndSpellObject) -> @thang = thangAndSpellObject.thang @spell = thangAndSpellObject.spell @@ -105,16 +101,16 @@ module.exports = class DebugView extends View handleDebugValue: (returnObject) -> @workerIsSimulating = false {key, value} = returnObject - @updateCache(@thang.id,@spell.name,key.split("."),@lastFrameRequested,value) - if @variableChain and not key is @variableChain.join(".") then return - @setTooltipKeyAndValue(key,value) + @updateCache(@thang.id, @spell.name, key.split('.'), @lastFrameRequested, value) + if @variableChain and not key is @variableChain.join('.') then return + @setTooltipKeyAndValue(key, value) handleWorldLoadProgressChanged: (data) -> @progress = data.progress - + afterRender: -> super() - @ace.on "mousemove", @onMouseMove + @ace.on 'mousemove', @onMouseMove setVariableStates: (@variableStates) -> @update() @@ -131,13 +127,13 @@ module.exports = class DebugView extends View break if endOfLine or not token # Don't iterate beyond end or beginning of line it.stepBackward() if @isIdentifier token - # This could be a property access, like "enemy.target.pos" or "this.spawnedRectangles". + # This could be a property access, like 'enemy.target.pos' or 'this.spawnedRectangles'. # We have to realize this and dig into the nesting of the objects. start = it.getCurrentTokenColumn() [chain, start, end] = [[token.value], start, start + token.value.length] while it.getCurrentTokenRow() is pos.row it.stepBackward() - break unless it.getCurrentToken()?.value is "." + break unless it.getCurrentToken()?.value is '.' it.stepBackward() token = null # If we're doing a complex access like this.getEnemies().length, then length isn't a valid var. break unless @isIdentifier(prev = it.getCurrentToken()) @@ -145,7 +141,7 @@ module.exports = class DebugView extends View start = it.getCurrentTokenColumn() chain.unshift token.value #Highlight all tokens, so true overrides all other conditions TODO: Refactor this later - if token and (true or token.value of @variableStates or token.value is "this" or @globals[token.value]) + if token and (true or token.value of @variableStates or token.value is 'this' or @globals[token.value]) @variableChain = chain offsetX = e.domEvent.offsetX ? e.clientX - $(e.domEvent.target).offset().left offsetY = e.domEvent.offsetY ? e.clientY - $(e.domEvent.target).offset().top @@ -160,12 +156,12 @@ module.exports = class DebugView extends View onMouseOut: (e) -> @variableChain = @markerRange = null @update() - + updateTooltipProgress: => if @variableChain and @progress < 1 @setTooltipProgress(@progress * 100) _.delay @updateTooltipProgress, 100 - + onNewWorld: (e) -> @thang = @options.thang = e.world.thangMap[@thang.id] if @thang @frameRate = e.world.frameRate @@ -173,22 +169,22 @@ module.exports = class DebugView extends View onFrameChanged: (data) -> @currentFrame = data.frame @frameRate = data.world.frameRate - + onSpellChangedCalculation: (data) -> @spellHasChanged = data.hasChangedSignificantly - + update: -> if @variableChain if @spellHasChanged - @setTooltipText("You've changed this spell! \nPlease recast to use the hover debugger.") - else if @variableChain.length is 2 and @variableChain[0] is "this" - @setTooltipKeyAndValue(@variableChain.join("."),@stringifyValue(@thang[@variableChain[1]],0)) + @setTooltipText('You\'ve changed this spell! \nPlease recast to use the hover debugger.') + else if @variableChain.length is 2 and @variableChain[0] is 'this' + @setTooltipKeyAndValue(@variableChain.join('.'), @stringifyValue(@thang[@variableChain[1]], 0)) else if @variableChain.length is 1 and Aether.globals[@variableChain[0]] - @setTooltipKeyAndValue(@variableChain.join("."),@stringifyValue(Aether.globals[@variableChain[0]],0)) + @setTooltipKeyAndValue(@variableChain.join('.'), @stringifyValue(Aether.globals[@variableChain[0]], 0)) else if @workerIsSimulating and @progress < 1 @debouncedTooltipUpdate() else if @currentFrame is @lastFrameRequested and (cacheValue = @retrieveValueFromCache(@thang.id, @spell.name, @variableChain, @currentFrame)) - @setTooltipKeyAndValue(@variableChain.join("."),cacheValue) + @setTooltipKeyAndValue(@variableChain.join('.'), cacheValue) else Backbone.Mediator.publish 'tome:spell-debug-value-request', thangID: @thang.id @@ -211,10 +207,10 @@ module.exports = class DebugView extends View stringifyValue: (value, depth) -> return value if not value or _.isString value if _.isFunction value - return if depth is 2 then undefined else "" + return if depth is 2 then undefined else '' return "" if value is @thang and depth if depth is 2 - if value.constructor?.className is "Thang" + if value.constructor?.className is 'Thang' value = "<#{value.type or value.spriteName} - #{value.id}, #{if value.pos then value.pos.toString() else 'non-physical'}>" else value = value.toString() @@ -223,23 +219,23 @@ module.exports = class DebugView extends View isArray = _.isArray value isObject = _.isObject value return value.toString() unless isArray or isObject - brackets = if isArray then ["[", "]"] else ["{", "}"] + brackets = if isArray then ['[', ']'] else ['{', '}'] size = _.size value - return brackets.join "" unless size + return brackets.join '' unless size values = [] if isArray for v in value s = @stringifyValue(v, depth + 1) - values.push "" + s unless s is undefined + values.push '' + s unless s is undefined else for key in value.apiProperties ? _.keys value s = @stringifyValue(value[key], depth + 1) - values.push key + ": " + s unless s is undefined - sep = '\n' + (" " for i in [0 ... depth]).join('') + values.push key + ': ' + s unless s is undefined + sep = '\n' + (' ' for i in [0 ... depth]).join('') prefix = value.constructor?.className - prefix ?= "Array" if isArray - prefix ?= "Object" if isObject - prefix = if prefix then prefix + " " else "" + prefix ?= 'Array' if isArray + prefix ?= 'Object' if isObject + prefix = if prefix then prefix + ' ' else '' return "#{prefix}#{brackets[0]}#{sep} #{values.join(sep + ' ')}#{sep}#{brackets[1]}" notifyPropertyHovered: => clearTimeout @hoveredPropertyTimeout if @hoveredPropertyTimeout @@ -254,9 +250,9 @@ module.exports = class DebugView extends View @ace.getSession().removeMarker @marker @marker = null if @markerRange - @marker = @ace.getSession().addMarker @markerRange, "ace_bracket", "text" + @marker = @ace.getSession().addMarker @markerRange, 'ace_bracket', 'text' destroy: -> - @ace?.removeEventListener "mousemove", @onMouseMove + @ace?.removeEventListener 'mousemove', @onMouseMove super() diff --git a/app/views/play/level/tome/spell_list_entry_thangs_view.coffee b/app/views/play/level/tome/spell_list_entry_thangs_view.coffee index c7a545a65..43f54f2cd 100644 --- a/app/views/play/level/tome/spell_list_entry_thangs_view.coffee +++ b/app/views/play/level/tome/spell_list_entry_thangs_view.coffee @@ -30,10 +30,10 @@ module.exports = class SpellListEntryThangsView extends View avatar.render() avatar.setSelected thang is @thang avatar.$el.data('thang-id', thang.id).click (e) -> - Backbone.Mediator.publish "level-select-sprite", thangID: $(@).data('thang-id'), spellName: spellName + Backbone.Mediator.publish 'level-select-sprite', thangID: $(@).data('thang-id'), spellName: spellName avatar.onProblemsUpdated spell: @spell @avatars.push avatar - + destroy: -> avatar.destroy() for avatar in @avatars super() diff --git a/app/views/play/level/tome/spell_list_entry_view.coffee b/app/views/play/level/tome/spell_list_entry_view.coffee index 76354fe84..cd39559a8 100644 --- a/app/views/play/level/tome/spell_list_entry_view.coffee +++ b/app/views/play/level/tome/spell_list_entry_view.coffee @@ -12,7 +12,7 @@ module.exports = class SpellListEntryView extends View controlsEnabled: true subscriptions: - 'tome:problems-updated': "onProblemsUpdated" + 'tome:problems-updated': 'onProblemsUpdated' 'tome:spell-changed-language': 'onSpellChangedLanguage' 'level-disable-controls': 'onDisableControls' 'level-enable-controls': 'onEnableControls' @@ -32,7 +32,7 @@ module.exports = class SpellListEntryView extends View context = super context context.spell = @spell context.methodSignature = @createMethodSignature() - context.thangNames = (thangID for thangID, spellThang of @spell.thangs when spellThang.thang.exists).join(', ') # + ", Marcus, Robert, Phoebe, Will Smith, Zap Brannigan, You, Gandaaaaalf" + context.thangNames = (thangID for thangID, spellThang of @spell.thangs when spellThang.thang.exists).join(', ') # + ', Marcus, Robert, Phoebe, Will Smith, Zap Brannigan, You, Gandaaaaalf' context.showTopDivider = @showTopDivider context @@ -88,7 +88,7 @@ module.exports = class SpellListEntryView extends View onClick: (e) -> spellThang = @getPrimarySpellThang() - Backbone.Mediator.publish "level-select-sprite", thangID: spellThang.thang.id, spellName: @spell.name + Backbone.Mediator.publish 'level-select-sprite', thangID: spellThang.thang.id, spellName: @spell.name onMouseEnterAvatar: (e) -> return unless @controlsEnabled and _.size(@spell.thangs) > 1 @@ -118,7 +118,7 @@ module.exports = class SpellListEntryView extends View onProblemsUpdated: (e) -> return unless e.spell is @spell - @$el.toggleClass "user-code-problem", e.problems.length + @$el.toggleClass 'user-code-problem', e.problems.length onSpellChangedLanguage: (e) -> return unless e.spell is @spell diff --git a/app/views/play/level/tome/spell_list_tab_entry_view.coffee b/app/views/play/level/tome/spell_list_tab_entry_view.coffee index df5710d2b..1938cc1e4 100644 --- a/app/views/play/level/tome/spell_list_tab_entry_view.coffee +++ b/app/views/play/level/tome/spell_list_tab_entry_view.coffee @@ -9,8 +9,8 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView id: 'spell-list-tab-entry-view' subscriptions: - 'tome:spell-loaded': "onSpellLoaded" - 'tome:spell-changed': "onSpellChanged" + 'tome:spell-loaded': 'onSpellLoaded' + 'tome:spell-changed': 'onSpellChanged' 'god:new-world-created': 'onNewWorld' 'tome:spell-changed-language': 'onSpellChangedLanguage' @@ -80,11 +80,11 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView onCodeReload: -> return unless @controlsEnabled - Backbone.Mediator.publish "tome:reload-code", spell: @spell + Backbone.Mediator.publish 'tome:reload-code', spell: @spell onBeautifyClick: -> return unless @controlsEnabled - Backbone.Mediator.publish "spell-beautify", spell: @spell + Backbone.Mediator.publish 'spell-beautify', spell: @spell updateReloadButton: -> changed = @spell.hasChanged null, @spell.getSource() diff --git a/app/views/play/level/tome/spell_list_view.coffee b/app/views/play/level/tome/spell_list_view.coffee index d4ab72157..f18eacb9b 100644 --- a/app/views/play/level/tome/spell_list_view.coffee +++ b/app/views/play/level/tome/spell_list_view.coffee @@ -26,7 +26,7 @@ module.exports = class SpellListView extends View # Keep only spells for which we have permissions spells = _.filter @options.spells, (s) -> s.canRead() @spells = _.sortBy spells, @sortScoreForSpell - #console.log "Kept sorted spells", @spells + #console.log 'Kept sorted spells', @spells sortScoreForSpell: (s) => # Sort by most spells per fewest Thangs @@ -66,7 +66,7 @@ module.exports = class SpellListView extends View for entry in newEntries @$el.append entry.el entry.render() # Render after appending so that we can access parent container for popover - + rerenderEntries: -> entry.render() for entry in @entries @@ -93,4 +93,4 @@ module.exports = class SpellListView extends View destroy: -> entry.destroy() for entry in @entries - super() \ No newline at end of file + super() diff --git a/app/views/play/level/tome/spell_palette_entry_view.coffee b/app/views/play/level/tome/spell_palette_entry_view.coffee index fe8e0cab0..1996b1972 100644 --- a/app/views/play/level/tome/spell_palette_entry_view.coffee +++ b/app/views/play/level/tome/spell_palette_entry_view.coffee @@ -11,9 +11,9 @@ module.exports = class SpellPaletteEntryView extends View popoverPinned: false subscriptions: - 'surface:frame-changed': "onFrameChanged" - 'tome:palette-hovered': "onPaletteHovered" - 'tome:palette-pin-toggled': "onPalettePinToggled" + 'surface:frame-changed': 'onFrameChanged' + 'tome:palette-hovered': 'onPaletteHovered' + 'tome:palette-pin-toggled': 'onPalettePinToggled' 'tome:spell-debug-property-hovered': 'onSpellDebugPropertyHovered' events: diff --git a/app/views/play/level/tome/spell_palette_view.coffee b/app/views/play/level/tome/spell_palette_view.coffee index 3057838e3..1924258e8 100644 --- a/app/views/play/level/tome/spell_palette_view.coffee +++ b/app/views/play/level/tome/spell_palette_view.coffee @@ -16,7 +16,7 @@ module.exports = class SpellPaletteView extends View subscriptions: 'level-disable-controls': 'onDisableControls' 'level-enable-controls': 'onEnableControls' - 'surface:frame-changed': "onFrameChanged" + 'surface:frame-changed': 'onFrameChanged' 'tome:change-language': 'onTomeChangedLanguage' events: @@ -114,7 +114,7 @@ module.exports = class SpellPaletteView extends View if tabbify and _.find @entries, ((entry) -> entry.doc.owner isnt 'this') @entryGroups = _.groupBy @entries, groupForEntry else - defaultGroup = $.i18n.t("play_level.tome_available_spells", defaultValue: "Available Spells") + defaultGroup = $.i18n.t('play_level.tome_available_spells', defaultValue: 'Available Spells') @entryGroups = {} @entryGroups[defaultGroup] = @entries @defaultGroupSlug = _.string.slugify defaultGroup diff --git a/app/views/play/level/tome/spell_toolbar_view.coffee b/app/views/play/level/tome/spell_toolbar_view.coffee index 2abd5460d..6ac432e17 100644 --- a/app/views/play/level/tome/spell_toolbar_view.coffee +++ b/app/views/play/level/tome/spell_toolbar_view.coffee @@ -24,7 +24,7 @@ module.exports = class SpellToolbarView extends View super() toggleFlow: (to) -> - @$el.find(".flow").toggle to + @$el.find('.flow').toggle to setStatementIndex: (statementIndex) -> return unless total = @callState?.statementsExecuted @@ -55,8 +55,8 @@ module.exports = class SpellToolbarView extends View $metrics.find('.statements-executed-total').text " (#{@metrics.statementsExecuted})" titleSuffix = " (#{@metrics.statementsExecuted} statements total)" else - $metrics.find('.statements-executed-total').text "" - titleSuffix = "" + $metrics.find('.statements-executed-total').text '' + titleSuffix = '' $metrics.find('.statements-metric').show().attr('title', "Statement #{@statementIndex + 1} of #{statementsExecuted} this call#{titleSuffix}") else $metrics.find('.statements-metric').hide() diff --git a/app/views/play/level/tome/spell_view.coffee b/app/views/play/level/tome/spell_view.coffee index adfd5146f..7c3114f59 100644 --- a/app/views/play/level/tome/spell_view.coffee +++ b/app/views/play/level/tome/spell_view.coffee @@ -2,7 +2,7 @@ View = require 'views/kinds/CocoView' template = require 'templates/play/level/tome/spell' {me} = require 'lib/auth' filters = require 'lib/image_filter' -Range = ace.require("ace/range").Range +Range = ace.require('ace/range').Range Problem = require './problem' SpellDebugView = require './spell_debug_view' SpellToolbarView = require './spell_toolbar_view' @@ -83,7 +83,7 @@ module.exports = class SpellView extends View @aceSession.setMode @editModes[@spell.language] @aceSession.setWrapLimitRange null @aceSession.setUseWrapMode true - @aceSession.setNewLineMode "unix" + @aceSession.setNewLineMode 'unix' @aceSession.setUseSoftTabs true @ace.setTheme 'ace/theme/textmate' @ace.setDisplayIndentGuides aceConfig.indentGuides @@ -304,7 +304,7 @@ module.exports = class SpellView extends View try @ace.resize true # hack: @ace may not have updated its text properly, so we force it to refresh catch error - console.warn "Error resizing ACE after an update:", error + console.warn 'Error resizing ACE after an update:', error # Called from CastButtonView initially and whenever the delay is changed setAutocastDelay: (@autocastDelay) -> @@ -375,14 +375,14 @@ module.exports = class SpellView extends View @clearAetherDisplay() if codeHasChangedSignificantly and not codeIsAsCast workerMessage = - function: "transpile" + function: 'transpile' spellKey: @spell.spellKey source: source - @worker.addEventListener "message", (e) => + @worker.addEventListener 'message', (e) => workerData = JSON.parse e.data - if workerData.function is "transpile" and workerData.spellKey is @spell.spellKey - @worker.removeEventListener "message", arguments.callee, false + if workerData.function is 'transpile' and workerData.spellKey is @spell.spellKey + @worker.removeEventListener 'message', arguments.callee, false aether.problems = workerData.problems aether.raw = source finishUpdatingAether(aether) @@ -433,7 +433,7 @@ module.exports = class SpellView extends View currentLine = _.string.rtrim(@aceDoc.$lines[cursorPosition.row].replace(/[ \t]*\/\/[^"']*/g, '')) # trim // unless inside " endOfLine = cursorPosition.column >= currentLine.length # just typed a semicolon or brace, for example beginningOfLine = not currentLine.substr(0, cursorPosition.column).trim().length # uncommenting code, for example - #console.log "finished?", valid, endOfLine, beginningOfLine, cursorPosition, currentLine.length, aether, new Date() - 0, currentLine + #console.log 'finished?', valid, endOfLine, beginningOfLine, cursorPosition, currentLine.length, aether, new Date() - 0, currentLine if valid and (endOfLine or beginningOfLine) if @autocastDelay > 60000 @preload() @@ -465,7 +465,7 @@ module.exports = class SpellView extends View @spellHasChanged = false onUserCodeProblem: (e) -> - return @onInfiniteLoop e if e.problem.id is "runtime_InfiniteLoop" + return @onInfiniteLoop e if e.problem.id is 'runtime_InfiniteLoop' return unless e.problem.userInfo.methodName is @spell.name return unless spellThang = _.find @spell.thangs, (spellThang, thangID) -> thangID is e.problem.userInfo.thangID @spell.hasChangedSignificantly @getSource(), null, (hasChanged) => @@ -496,7 +496,7 @@ module.exports = class SpellView extends View aether = e.world.userCodeMap[thangID]?[@spell.name] # Might not be there if this is a new Programmable Thang. spellThang.castAether = aether spellThang.aether = @spell.createAether thang - #console.log thangID, @spell.spellKey, "ran", aether.metrics.callsExecuted, "times over", aether.metrics.statementsExecuted, "statements, with max recursion depth", aether.metrics.maxDepth, "and full flow/metrics", aether.metrics, aether.flow + #console.log thangID, @spell.spellKey, 'ran', aether.metrics.callsExecuted, 'times over', aether.metrics.statementsExecuted, 'statements, with max recursion depth', aether.metrics.maxDepth, 'and full flow/metrics', aether.metrics, aether.flow @spell.transpile() @updateAether false, false @@ -549,7 +549,7 @@ module.exports = class SpellView extends View executedRows[state.range[0].row] = true #state.executing = true if state.userInfo?.time is @thang.world.age # no work currentCallIndex ?= callNumber - 1 - #console.log "got call index", currentCallIndex, "for time", @thang.world.age, "out of", states.length + #console.log 'got call index', currentCallIndex, 'for time', @thang.world.age, 'out of', states.length @decoratedGutter = @decoratedGutter || {} @@ -564,7 +564,7 @@ module.exports = class SpellView extends View @aceSession.removeGutterDecoration row, 'executing' @aceSession.removeGutterDecoration row, 'executed' @decoratedGutter[row] = '' - if not executed.length or (@spell.name is "plan" and @spellThang.castAether.metrics.statementsExecuted < 20) + if not executed.length or (@spell.name is 'plan' and @spellThang.castAether.metrics.statementsExecuted < 20) @toolbarView?.toggleFlow false @debugView.setVariableStates {} return @@ -581,11 +581,11 @@ module.exports = class SpellView extends View if clazz is 'executed' continue if marked[start.row] marked[start.row] = true - markerType = "fullLine" + markerType = 'fullLine' else @debugView.setVariableStates state.variables gotVariableStates = true - markerType = "text" + markerType = 'text' markerRange = new Range start.row, start.col, end.row, end.col markerRange.start = @aceDoc.createAnchor markerRange.start markerRange.end = @aceDoc.createAnchor markerRange.end @@ -626,7 +626,7 @@ module.exports = class SpellView extends View disabled = not enabled $('body').focus() if disabled and $(document.activeElement).is('.ace_text-input') @ace.setReadOnly disabled - @ace[if disabled then "setStyle" else "unsetStyle"] "disabled" + @ace[if disabled then 'setStyle' else 'unsetStyle'] 'disabled' @toggleBackground() toggleBackground: => diff --git a/app/views/play/level/tome/thang_list_entry_view.coffee b/app/views/play/level/tome/thang_list_entry_view.coffee index 388a5d10f..79d9bfa27 100644 --- a/app/views/play/level/tome/thang_list_entry_view.coffee +++ b/app/views/play/level/tome/thang_list_entry_view.coffee @@ -15,10 +15,10 @@ module.exports = class ThangListEntryView extends View reasonsToBeDisabled: {} subscriptions: - 'tome:problems-updated': "onProblemsUpdated" + 'tome:problems-updated': 'onProblemsUpdated' 'level-disable-controls': 'onDisableControls' 'level-enable-controls': 'onEnableControls' - 'surface:frame-changed': "onFrameChanged" + 'surface:frame-changed': 'onFrameChanged' 'level-set-letterbox': 'onSetLetterbox' 'tome:thang-list-entry-popover-shown': 'onThangListEntryPopoverShown' 'surface:coordinates-shown': 'onSurfaceCoordinatesShown' @@ -83,7 +83,7 @@ module.exports = class ThangListEntryView extends View onClick: (e) -> return unless @controlsEnabled @sortSpells() - Backbone.Mediator.publish "level-select-sprite", thangID: @thang.id, spellName: @spells[0]?.name + Backbone.Mediator.publish 'level-select-sprite', thangID: @thang.id, spellName: @spells[0]?.name onMouseEnter: (e) -> return unless @controlsEnabled and @spells.length @@ -122,7 +122,7 @@ module.exports = class ThangListEntryView extends View @popover.mouseleave (e) => @hideSpells() thangID = @thang.id @popover.find('code').click (e) -> - Backbone.Mediator.publish "level-select-sprite", thangID: thangID, spellName: $(@).data 'spell-name' + Backbone.Mediator.publish 'level-select-sprite', thangID: thangID, spellName: $(@).data 'spell-name' Backbone.Mediator.publish 'tome:thang-list-entry-popover-shown', entry: @ hideSpells: => diff --git a/app/views/play/level/tome/thang_list_view.coffee b/app/views/play/level/tome/thang_list_view.coffee index a2271f146..a931e06e7 100644 --- a/app/views/play/level/tome/thang_list_view.coffee +++ b/app/views/play/level/tome/thang_list_view.coffee @@ -55,9 +55,9 @@ module.exports = class ThangListView extends View addThangListEntries: -> @entries = [] for [thangs, section, permission] in [ - [@readwriteThangs, "#readwrite-thangs", "readwrite"] # Your Minions - [@readThangs, "#read-thangs", "read"] # Read-Only - [@muggleThangs, "#muggle-thangs", null] # Non-Castable + [@readwriteThangs, '#readwrite-thangs', 'readwrite'] # Your Minions + [@readThangs, '#read-thangs', 'read'] # Read-Only + [@muggleThangs, '#muggle-thangs', null] # Non-Castable ] section = @$el.find(section).toggle thangs.length > 0 for thang in thangs @@ -84,4 +84,3 @@ module.exports = class ThangListView extends View destroy: -> entry.destroy() for entry in @entries super() - diff --git a/app/views/play/level/tome/tome_view.coffee b/app/views/play/level/tome/tome_view.coffee index 7fbe51475..d709797e7 100644 --- a/app/views/play/level/tome/tome_view.coffee +++ b/app/views/play/level/tome/tome_view.coffee @@ -45,8 +45,8 @@ module.exports = class TomeView extends View cache: false subscriptions: - 'tome:spell-loaded': "onSpellLoaded" - 'tome:cast-spell': "onCastSpell" + 'tome:spell-loaded': 'onSpellLoaded' + 'tome:cast-spell': 'onCastSpell' 'tome:toggle-spell-list': 'onToggleSpellList' 'tome:change-language': 'updateLanguageForAllSpells' 'surface:sprite-selected': 'onSpriteSelected' @@ -69,7 +69,7 @@ module.exports = class TomeView extends View @teamSpellMap = @generateTeamSpellMap(@spells) else @cast() - console.warn "Warning: There are no Programmable Thangs in this level, which makes it unplayable." + console.warn 'Warning: There are no Programmable Thangs in this level, which makes it unplayable.' delete @options.thangs onNewWorld: (e) -> @@ -81,14 +81,14 @@ module.exports = class TomeView extends View onCommentMyCode: (e) -> for spellKey, spell of @spells when spell.canWrite() - console.log "Commenting out", spellKey + console.log 'Commenting out', spellKey commentedSource = 'return; // Commented out to stop infinite loop.\n' + spell.getSource() spell.view.updateACEText commentedSource spell.view.recompile false @cast() createWorker: -> - return new Worker("/javascripts/workers/aether_worker.js") + return new Worker('/javascripts/workers/aether_worker.js') generateTeamSpellMap: (spellObject) -> teamSpellMap = {} @@ -120,7 +120,7 @@ module.exports = class TomeView extends View spellKey = pathComponents.join '/' @thangSpells[thang.id].push spellKey unless method.cloneOf - skipProtectAPI = @getQueryVariable "skip_protect_api", (@options.levelID in ['gridmancer']) + skipProtectAPI = @getQueryVariable 'skip_protect_api', (@options.levelID in ['gridmancer']) spell = @spells[spellKey] = new Spell programmableMethod: method spellKey: spellKey @@ -216,7 +216,7 @@ module.exports = class TomeView extends View spell reloadAllCode: -> - spell.view.reloadCode false for spellKey, spell of @spells when spell.team is me.team or (spell.team in ["common", "neutral", null]) + spell.view.reloadCode false for spellKey, spell of @spells when spell.team is me.team or (spell.team in ['common', 'neutral', null]) Backbone.Mediator.publish 'tome:cast-spells', spells: @spells, preload: false updateLanguageForAllSpells: (e) -> diff --git a/app/views/play/level_view.coffee b/app/views/play/level_view.coffee index 70f5d7e47..88b6955e6 100644 --- a/app/views/play/level_view.coffee +++ b/app/views/play/level_view.coffee @@ -1,6 +1,6 @@ View = require 'views/kinds/RootView' template = require 'templates/play/level' -{me} = require('lib/auth') +{me} = require 'lib/auth' ThangType = require 'models/ThangType' utils = require 'lib/utils' @@ -74,7 +74,7 @@ module.exports = class PlayLevelView extends View constructor: (options, @levelID) -> console.profile?() if PROFILE_ME super options - if not me.get('hourOfCode') and @getQueryVariable "hour_of_code" + if not me.get('hourOfCode') and @getQueryVariable 'hour_of_code' @setUpHourOfCode() @isEditorPreview = @getQueryVariable 'dev' @@ -94,7 +94,7 @@ module.exports = class PlayLevelView extends View setUpHourOfCode: -> me.set 'hourOfCode', true me.patch() - $('body').append($("")) + $('body').append($('')) application.tracker?.trackEvent 'Hour of Code Begin', {} setLevel: (@level, givenSupermodel) -> @@ -112,7 +112,7 @@ module.exports = class PlayLevelView extends View load: -> @loadStartTime = new Date() @god = new God debugWorker: true - @levelLoader = new LevelLoader supermodel: @supermodel, levelID: @levelID, sessionID: @sessionID, opponentSessionID: @getQueryVariable('opponent'), team: @getQueryVariable("team") + @levelLoader = new LevelLoader supermodel: @supermodel, levelID: @levelID, sessionID: @sessionID, opponentSessionID: @getQueryVariable('opponent'), team: @getQueryVariable('team') @listenToOnce @levelLoader, 'world-necessities-loaded', @onWorldNecessitiesLoaded # CocoView overridden methods ############################################### @@ -166,7 +166,7 @@ module.exports = class PlayLevelView extends View onWorldNecessitiesLoaded: -> # Called when we have enough to build the world, but not everything is loaded @grabLevelLoaderData() - team = @getQueryVariable("team") ? @world.teamForPlayer(0) + team = @getQueryVariable('team') ? @world.teamForPlayer(0) @loadOpponentTeam(team) @setupGod() @setTeam team @@ -191,7 +191,7 @@ module.exports = class PlayLevelView extends View continue if spellTeam is myTeam or not myTeam opponentSpells = opponentSpells.concat spells if (not @session.get('teamSpells')) and @otherSession?.get('teamSpells') - @session.set('teamSpells',@otherSession.get('teamSpells')) + @session.set('teamSpells', @otherSession.get('teamSpells')) opponentCode = @otherSession?.get('transpiledCode') or {} myCode = @session.get('code') or {} for spell in opponentSpells @@ -237,7 +237,7 @@ module.exports = class PlayLevelView extends View Backbone.Mediator.publish 'level-set-volume', volume: volume initScriptManager: -> - @scriptManager = new ScriptManager({scripts: @world.scripts or [], view:@, session: @session}) + @scriptManager = new ScriptManager({scripts: @world.scripts or [], view: @, session: @session}) @scriptManager.loadFromSession() register: -> @@ -267,9 +267,9 @@ module.exports = class PlayLevelView extends View surfaceCanvas = $('canvas#surface', @$el) @surface = new Surface(@world, surfaceCanvas, thangTypes: @supermodel.getModels(ThangType), playJingle: not @isEditorPreview) worldBounds = @world.getBounds() - bounds = [{x:worldBounds.left, y:worldBounds.top}, {x:worldBounds.right, y:worldBounds.bottom}] + bounds = [{x: worldBounds.left, y: worldBounds.top}, {x: worldBounds.right, y: worldBounds.bottom}] @surface.camera.setBounds(bounds) - @surface.camera.zoomTo({x:0, y:0}, 0.1, 0) + @surface.camera.zoomTo({x: 0, y: 0}, 0.1, 0) # Once Surface is Loaded #################################################### @@ -370,7 +370,7 @@ module.exports = class PlayLevelView extends View Backbone.Mediator.publish 'router:navigate', { route: nextLevelURL, viewClass: PlayLevelView, - viewArgs: [{supermodel:@supermodel}, nextLevelID]} + viewArgs: [{supermodel: @supermodel}, nextLevelID]} getNextLevel: -> return null unless nextLevelOriginal = @level.get('nextLevel')?.original @@ -439,7 +439,6 @@ module.exports = class PlayLevelView extends View @pointerInterval = setInterval(@animatePointer, 1200) , 1) - animatePointer: => pointer = $('#pointer') pointer.css('transition', 'all 0.6s ease-out') diff --git a/app/views/play/spectate_view.coffee b/app/views/play/spectate_view.coffee index 76e5430ca..340978693 100644 --- a/app/views/play/spectate_view.coffee +++ b/app/views/play/spectate_view.coffee @@ -1,6 +1,6 @@ View = require 'views/kinds/RootView' template = require 'templates/play/spectate' -{me} = require('lib/auth') +{me} = require 'lib/auth' ThangType = require 'models/ThangType' utils = require 'lib/utils' @@ -104,7 +104,7 @@ module.exports = class SpectateLevelView extends View sessionID: @sessionOne opponentSessionID: @sessionTwo spectateMode: true - team: @getQueryVariable("team") + team: @getQueryVariable('team') @listenToOnce(@levelLoader, 'loaded-all', @onLevelLoaderLoaded) @god = new God maxAngels: 1 @@ -203,7 +203,7 @@ module.exports = class SpectateLevelView extends View c = opponentCode[thang]?[spell] myCode[thang] ?= {} if c then myCode[thang][spell] = c else delete myCode[thang][spell] - + @session.set('code', myCode) if @session.get('multiplayer') and @otherSession? # For now, ladderGame will disallow multiplayer, because session code combining doesn't play nice yet. @@ -227,7 +227,7 @@ module.exports = class SpectateLevelView extends View @modelsLoaded ?= 0 canvas = @$el.find('#surface')[0] ctx = canvas.getContext('2d') - ctx.font="20px Georgia" + ctx.font='20px Georgia' ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.fillText("Loaded #{@modelsLoaded} thingies",50,50) @@ -349,7 +349,6 @@ module.exports = class SpectateLevelView extends View @pointerInterval = setInterval(@animatePointer, 1200) ), 1) - animatePointer: -> pointer = $('#pointer') pointer.css('transition', 'all 0.6s ease-out') @@ -394,9 +393,9 @@ module.exports = class SpectateLevelView extends View initScriptManager: -> if @world.scripts nonVictoryPlaybackScripts = _.reject @world.scripts, (script) -> - script.id.indexOf("Set Camera Boundaries and Goals") == -1 + script.id.indexOf('Set Camera Boundaries and Goals') == -1 else - console.log "World scripts don't exist!" + console.log 'World scripts don\'t exist!' nonVictoryPlaybackScripts = [] console.log nonVictoryPlaybackScripts @scriptManager = new ScriptManager({scripts: nonVictoryPlaybackScripts, view:@, session: @session}) @@ -418,7 +417,7 @@ module.exports = class SpectateLevelView extends View onSessionWillSave: (e) -> # Something interesting has happened, so (at a lower frequency), we'll save a screenshot. - console.log "Session is saving but shouldn't save!!!!!!!" + console.log 'Session is saving but shouldn\'t save!!!!!!!' # Throttled saveScreenshot: (session) => @@ -443,7 +442,7 @@ module.exports = class SpectateLevelView extends View AudioPlayer.preloadSoundReference sound onNextGamePressed: (e) -> - console.log "You want to see the next game!" + console.log 'You want to see the next game!' @fetchRandomSessionPair (err, data) => if err? then return console.log "There was an error fetching the random session pair: #{data}" @sessionOne = data[0]._id @@ -457,19 +456,20 @@ module.exports = class SpectateLevelView extends View spectateSessions: {sessionOne: @sessionOne, sessionTwo: @sessionTwo} supermodel: @supermodel } - @levelID ] - } - history?.pushState? {}, "", url # Backbone won't update the URL if just query parameters change + @levelID + ] + } + history?.pushState? {}, '', url # Backbone won't update the URL if just query parameters change fetchRandomSessionPair: (cb) -> - console.log "Fetching random session pair!" + console.log 'Fetching random session pair!' randomSessionPairURL = "/db/level/#{@levelID}/random_session_pair" $.ajax url: randomSessionPairURL - type: "GET" + type: 'GET' complete: (jqxhr, textStatus) -> - if textStatus isnt "success" - cb("error", jqxhr.statusText) + if textStatus isnt 'success' + cb('error', jqxhr.statusText) else cb(null, $.parseJSON(jqxhr.responseText)) diff --git a/app/views/play_view.coffee b/app/views/play_view.coffee index 6fcc8d51a..4db520f00 100644 --- a/app/views/play_view.coffee +++ b/app/views/play_view.coffee @@ -12,7 +12,7 @@ class LevelSessionsCollection extends CocoCollection @url = "/db/user/#{me.id}/level.sessions?project=state.complete,levelID" module.exports = class PlayView extends View - id: "play-view" + id: 'play-view' template: template constructor: (options) -> @@ -37,70 +37,70 @@ module.exports = class PlayView extends View difficulty: 1 id: 'rescue-mission' image: '/file/db/level/52740644904ac0411700067c/rescue_mission_icon.png' - description: "Tharin has been captured!" + description: 'Tharin has been captured!' } { name: 'Grab the Mushroom' difficulty: 1 id: 'grab-the-mushroom' image: '/file/db/level/529662dfe0df8f0000000007/grab_the_mushroom_icon.png' - description: "Grab a powerup and smash a big ogre." + description: 'Grab a powerup and smash a big ogre.' } { name: 'Drink Me' difficulty: 1 id: 'drink-me' image: '/file/db/level/525dc5589a0765e496000006/drink_me_icon.png' - description: "Drink up and slay two munchkins." + description: 'Drink up and slay two munchkins.' } { name: 'Taunt the Guards' difficulty: 1 id: 'taunt-the-guards' image: '/file/db/level/5276c9bdcf83207a2801ff8f/taunt_icon.png' - description: "Tharin, if clever, can escape with Phoebe." + description: 'Tharin, if clever, can escape with Phoebe.' } { - name: "It's a Trap" + name: 'It\'s a Trap' difficulty: 1 id: 'its-a-trap' image: '/file/db/level/528aea2d7f37fc4e0700016b/its_a_trap_icon.png' - description: "Organize a dungeon ambush with archers." + description: 'Organize a dungeon ambush with archers.' } { name: 'Break the Prison' difficulty: 1 id: 'break-the-prison' image: '/file/db/level/5275272c69abdcb12401216e/break_the_prison_icon.png' - description: "More comrades are imprisoned!" + description: 'More comrades are imprisoned!' } { name: 'Taunt' difficulty: 1 id: 'taunt' image: '/file/db/level/525f150306e1ab0962000018/taunt_icon.png' - description: "Taunt the ogre to claim victory." + description: 'Taunt the ogre to claim victory.' } { name: 'Cowardly Taunt' difficulty: 1 id: 'cowardly-taunt' image: '/file/db/level/525abfd9b12777d78e000009/cowardly_taunt_icon.png' - description: "Lure infuriated ogres to their doom." + description: 'Lure infuriated ogres to their doom.' } { name: 'Commanding Followers' difficulty: 1 id: 'commanding-followers' image: '/file/db/level/525ef8ef06e1ab0962000003/commanding_followers_icon.png' - description: "Lead allied soldiers into battle." + description: 'Lead allied soldiers into battle.' } { name: 'Mobile Artillery' difficulty: 1 id: 'mobile-artillery' image: '/file/db/level/525085419851b83f4b000001/mobile_artillery_icon.png' - description: "Blow ogres up!" + description: 'Blow ogres up!' } ] @@ -110,35 +110,35 @@ module.exports = class PlayView extends View difficulty: 2 id: 'hunter-triplets' image: '/file/db/level/526711d9add4f8965f000002/hunter_triplets_icon.png' - description: "Three soldiers go ogre hunting." + description: 'Three soldiers go ogre hunting.' } { name: 'Emphasis on Aim' difficulty: 2 id: 'emphasis-on-aim' image: '/file/db/level/525f384d96cd77000000000f/munchkin_masher_icon.png' - description: "Chose your targets carefully." + description: 'Chose your targets carefully.' } { name: 'Zone of Danger' difficulty: 3 id: 'zone-of-danger' image: '/file/db/level/526ae95c1e5cd30000000008/zone_of_danger_icon.png' - description: "Target the ogres swarming into arrow range." + description: 'Target the ogres swarming into arrow range.' } { name: 'Molotov Medic' difficulty: 2 id: 'molotov-medic' image: '/file/db/level/52602ecb026e8481e7000001/generic_1.png' - description: "Tharin must play support in this dungeon battle." + description: 'Tharin must play support in this dungeon battle.' } { name: 'Gridmancer' difficulty: 5 id: 'gridmancer' image: '/file/db/level/52ae2460ef42c52f13000008/gridmancer_icon.png' - description: "Super algorithm challenge level!" + description: 'Super algorithm challenge level!' } ] @@ -148,7 +148,7 @@ module.exports = class PlayView extends View difficulty: 4 id: 'greed' image: '/file/db/level/526fd3043c637ece50001bb2/the_herd_icon.png' - description: "Liked Dungeon Arena and Gold Rush? Put them together in this economic arena!" + description: 'Liked Dungeon Arena and Gold Rush? Put them together in this economic arena!' levelPath: 'ladder' } { @@ -156,7 +156,7 @@ module.exports = class PlayView extends View difficulty: 3 id: 'dungeon-arena' image: '/file/db/level/526ae95c1e5cd30000000008/zone_of_danger_icon.png' - description: "Play head-to-head against fellow Wizards in a dungeon melee!" + description: 'Play head-to-head against fellow Wizards in a dungeon melee!' levelPath: 'ladder' } { @@ -164,7 +164,7 @@ module.exports = class PlayView extends View difficulty: 3 id: 'gold-rush' image: '/file/db/level/52602ecb026e8481e7000001/generic_1.png' - description: "Prove you are better at collecting gold than your opponent!" + description: 'Prove you are better at collecting gold than your opponent!' levelPath: 'ladder' } { @@ -172,7 +172,7 @@ module.exports = class PlayView extends View difficulty: 4 id: 'brawlwood' image: '/file/db/level/525ef8ef06e1ab0962000003/commanding_followers_icon.png' - description: "Combat the armies of other Wizards in a strategic forest arena! (Fast computer required.)" + description: 'Combat the armies of other Wizards in a strategic forest arena! (Fast computer required.)' levelPath: 'ladder' } ] @@ -183,14 +183,14 @@ module.exports = class PlayView extends View difficulty: 2 id: 'extra-extrapolation' image: '/file/db/level/526bda3fe79aefde2a003e36/mobile_artillery_icon.png' - description: "Predict your target's position for deadly aim. - by Sootn" + description: 'Predict your target\'s position for deadly aim. - by Sootn' } { name: 'The Right Route' difficulty: 1 id: 'the-right-route' image: '/file/db/level/526fd3043c637ece50001bb2/the_herd_icon.png' - description: "Strike at the weak point in an array of enemies. - by Aftermath" + description: 'Strike at the weak point in an array of enemies. - by Aftermath' } { name: 'Sword Loop' @@ -211,50 +211,50 @@ module.exports = class PlayView extends View difficulty: 3 id: 'bubble-sort-bootcamp-battle' image: '/file/db/level/525ef8ef06e1ab0962000003/commanding_followers_icon.png' - description: "Write a bubble sort to organize your soldiers. - by Alexandru Caciulescu" + description: 'Write a bubble sort to organize your soldiers. - by Alexandru Caciulescu' } { name: 'Ogres of Hanoi' difficulty: 3 id: 'ogres-of-hanoi' image: '/file/db/level/526fd3043c637ece50001bb2/the_herd_icon.png' - description: "Transfer a stack of ogres while preserving their honor. - by Alexandru Caciulescu" + description: 'Transfer a stack of ogres while preserving their honor. - by Alexandru Caciulescu' } { name: 'Danger! Minefield' difficulty: 3 id: 'danger-minefield' image: '/file/db/level/526bda3fe79aefde2a003e36/mobile_artillery_icon.png' - description: "Learn how to find prime numbers while defusing mines! - by Alexandru Caciulescu" + description: 'Learn how to find prime numbers while defusing mines! - by Alexandru Caciulescu' } { name: 'K-means++ Cluster Wars' difficulty: 4 id: 'k-means-cluster-wars' image: '/file/db/level/525ef8ef06e1ab0962000003/commanding_followers_icon.png' - description: "Learn cluster analysis while leading armies into battle! - by Alexandru Caciulescu" + description: 'Learn cluster analysis while leading armies into battle! - by Alexandru Caciulescu' } { name: 'Find the Spy' difficulty: 2 id: 'find-the-spy' image: '/file/db/level/526ae95c1e5cd30000000008/zone_of_danger_icon.png' - description: "Identify the spies hidden among your soldiers - by Nathan Gossett" + description: 'Identify the spies hidden among your soldiers - by Nathan Gossett' } { name: 'Harvest Time' difficulty: 2 id: 'harvest-time' image: '/file/db/level/529662dfe0df8f0000000007/grab_the_mushroom_icon.png' - description: "Collect a hundred mushrooms in just five lines of code - by Nathan Gossett" + description: 'Collect a hundred mushrooms in just five lines of code - by Nathan Gossett' } ] context.campaigns = [ - {id: "beginner", name: "Beginner Campaign", description: "... in which you learn the wizardry of programming.", levels: tutorials} - {id: "multiplayer", name: "Multiplayer Arenas", description: "... in which you code head-to-head against other players.", levels: arenas} - {id: "dev", name: "Random Harder Levels", description: "... in which you learn the interface while doing something a little harder.", levels: experienced} - {id: "player_created", name: "Player-Created", description: "... in which you battle against the creativity of your fellow Artisan Wizards.", levels: playerCreated} + {id: 'beginner', name: 'Beginner Campaign', description: '... in which you learn the wizardry of programming.', levels: tutorials} + {id: 'multiplayer', name: 'Multiplayer Arenas', description: '... in which you code head-to-head against other players.', levels: arenas} + {id: 'dev', name: 'Random Harder Levels', description: '... in which you learn the interface while doing something a little harder.', levels: experienced} + {id: 'player_created', name: 'Player-Created', description: '... in which you battle against the creativity of your fellow Artisan Wizards.', levels: playerCreated} ] context.levelStatusMap = @levelStatusMap context diff --git a/app/views/sprite_parser_test_view.coffee b/app/views/sprite_parser_test_view.coffee index a4fb5fbf1..ece70743e 100644 --- a/app/views/sprite_parser_test_view.coffee +++ b/app/views/sprite_parser_test_view.coffee @@ -6,7 +6,7 @@ samples = require 'lib/sprites/parser_samples_artillery' ThangType = require 'models/ThangType' module.exports = class SpriteParserTestView extends View - id: "sprite-parser-test-view" + id: 'sprite-parser-test-view' template: template afterRender: -> @@ -17,6 +17,6 @@ module.exports = class SpriteParserTestView extends View for sample in _.shuffle samples parser = new SpriteParser(thangType) parser.parse(sample) - console.log "thang type is now", thangType + console.log 'thang type is now', thangType console.log JSON.stringify(thangType).length -# console.log JSON.stringify(thangType.attributes.raw.animations.tharin_defend.tweens) \ No newline at end of file +# console.log JSON.stringify(thangType.attributes.raw.animations.tharin_defend.tweens) diff --git a/app/views/teachers_view.coffee b/app/views/teachers_view.coffee index b3fbc77ba..783f1391e 100644 --- a/app/views/teachers_view.coffee +++ b/app/views/teachers_view.coffee @@ -2,5 +2,5 @@ View = require 'views/kinds/RootView' template = require 'templates/teachers' module.exports = class TeachersView extends View - id: "teachers-view" + id: 'teachers-view' template: template diff --git a/bower.json b/bower.json index 62304bd97..beb943ad0 100644 --- a/bower.json +++ b/bower.json @@ -40,7 +40,7 @@ "jsondiffpatch": "~0.1.5", "nanoscroller": "~0.8.0", "jquery.tablesorter": "~2.15.13", - "treema": "~0.0.8", + "treema": "~0.0.9", "bootstrap": "~3.1.1", "validated-backbone-mediator": "~0.1.3", "jquery.browser": "~0.0.6", diff --git a/config.coffee b/config.coffee index 1c9ff8cc6..697a621de 100644 --- a/config.coffee +++ b/config.coffee @@ -36,7 +36,7 @@ exports.config = )/// 'javascripts/test-app.js': /^test[\/\\]app/ 'javascripts/demo-app.js': /^test[\/\\]demo/ - + order: before: [ 'bower_components/jquery/dist/jquery.js' @@ -73,19 +73,19 @@ exports.config = plugins: autoReload: - delay: 300 + delay: 300 coffeelint: pattern: /^app\/.*\.coffee$/ options: line_endings: - value: "unix" - level: "error" + value: 'unix' + level: 'error' max_line_length: - level: "ignore" + level: 'ignore' no_trailing_whitespace: - level: "ignore" # PyCharm can't just autostrip for .coffee, needed for .jade + level: 'ignore' # PyCharm can't just autostrip for .coffee, needed for .jade no_unnecessary_fat_arrows: - level: "ignore" + level: 'ignore' uglify: output: semicolons: false diff --git a/headless_client.coffee b/headless_client.coffee index a9dfe48b1..04fdc109a 100644 --- a/headless_client.coffee +++ b/headless_client.coffee @@ -2,12 +2,12 @@ This file will simulate games on node.js by emulating the browser environment. ### simulateOneGame = false -if process.argv[2] is "one-game" +if process.argv[2] is 'one-game' #calculate result of one game here simulateOneGame = true console.log "Simulating #{process.argv[3]} vs #{process.argv[4]}" -bowerComponentsPath = "./bower_components/" -headlessClientPath = "./headless_client/" +bowerComponentsPath = './bower_components/' +headlessClientPath = './headless_client/' # SETTINGS options = @@ -22,7 +22,7 @@ options = simulateOnlyOneGame: simulateOneGame options.heapdump = require('heapdump') if options.heapdump -server = if options.testing then "http://127.0.0.1:3000" else "https://codecombat.com" +server = if options.testing then 'http://127.0.0.1:3000' else 'https://codecombat.com' # Disabled modules disable = [ @@ -35,7 +35,7 @@ disable = [ # Global emulated stuff GLOBAL.window = GLOBAL -GLOBAL.document = location: pathname: "headless_client" +GLOBAL.document = location: pathname: 'headless_client' GLOBAL.console.debug = console.log GLOBAL.Worker = require('webworker-threads').Worker Worker::removeEventListener = (what) -> @@ -65,7 +65,7 @@ hookedLoader = (request, parent, isMain) -> request = path + '/app/' + request else if request is 'underscore' request = 'lodash' - console.log "loading " + request if options.debug + console.log 'loading ' + request if options.debug originalLoader request, parent, isMain unhook = () -> m._load = originalLoader @@ -98,14 +98,14 @@ login = require './login.coffee' #should contain an object containing they keys #Login user and start the code. $.ajax url: '/auth/login' - type: "POST" + type: 'POST' data: login parse: true - error: (error) -> "Bad Error. Can't connect to server or something. " + error + error: (error) -> 'Bad Error. Can\'t connect to server or something. ' + error success: (response, textStatus, jqXHR) -> - console.log "User: ", response if options.debug + console.log 'User: ', response if options.debug unless jqXHR.status is 200 - console.log "User not authenticated. Status code: ", jqXHR.status + console.log 'User not authenticated. Status code: ', jqXHR.status return GLOBAL.window.userObject = response # JSON.parse response Simulator = require 'lib/simulator/Simulator' diff --git a/headless_client/jQlone.coffee b/headless_client/jQlone.coffee index a5abf26dd..12f806bf1 100644 --- a/headless_client/jQlone.coffee +++ b/headless_client/jQlone.coffee @@ -2,14 +2,14 @@ #Leaves out all the dome stuff but allows ajax. _ = require 'lodash' request = require 'request' -Deferred = require "JQDeferred" +Deferred = require 'JQDeferred' module.exports = $ = (input) -> console.log 'Ignored jQuery: ', input if $._debug append: (input)-> exports: ()-> # Non-standard jQuery stuff. Don't use outside of server. $._debug = false -$._server = "https://codecombat.com" +$._server = 'https://codecombat.com' $._cookies = request.jar() $.when = Deferred.when @@ -21,8 +21,8 @@ $.ajax = (options) -> url = $._server + url data = options.data - console.log "Requesting: " + JSON.stringify options if $._debug - console.log "URL: " + url if $._debug + console.log 'Requesting: ' + JSON.stringify options if $._debug + console.log 'URL: ' + url if $._debug deferred = Deferred() request url: url @@ -31,9 +31,9 @@ $.ajax = (options) -> method: options.type body: data , (error, response, body) -> - console.log "HTTP Request:" + JSON.stringify options if $._debug and not error + console.log 'HTTP Request:' + JSON.stringify options if $._debug and not error if responded - console.log "\t↳Already returned before." if $._debug + console.log '\t↳Already returned before.' if $._debug return if (error) console.warn "\t↳Returned: error: #{error}" diff --git a/headless_client/worker_world.coffee b/headless_client/worker_world.coffee index 41d09210e..c683c4f1d 100644 --- a/headless_client/worker_world.coffee +++ b/headless_client/worker_world.coffee @@ -17,8 +17,8 @@ betterConsole = () -> self.console = log: -> if self.logsLogged++ is self.logLimit self.postMessage - type: "console-log" - args: ["Log limit " + self.logLimit + " reached; shutting up."] + type: 'console-log' + args: ['Log limit ' + self.logLimit + ' reached; shutting up.'] id: self.workerID else if self.logsLogged < self.logLimit @@ -26,19 +26,19 @@ betterConsole = () -> i = 0 while i < args.length - args[i] = args[i].toString() if args[i].constructor.className is "Thang" or args[i].isComponent if args[i] and args[i].constructor + args[i] = args[i].toString() if args[i].constructor.className is 'Thang' or args[i].isComponent if args[i] and args[i].constructor ++i try self.postMessage - type: "console-log" + type: 'console-log' args: args id: self.workerID catch error self.postMessage - type: "console-log" + type: 'console-log' args: [ - "Could not post log: " + args + 'Could not post log: ' + args error.toString() error.stack error.stackTrace @@ -50,9 +50,8 @@ betterConsole = () -> GLOBAL.console = console = self.console self.console - work = () -> - console.log "starting..." + console.log 'starting...' console.log = -> @@ -70,7 +69,7 @@ work = () -> self.logsLogged = 0 self.runWorld = (args) -> - console.log "Running world inside worker." + console.log 'Running world inside worker.' self.postedErrors = {} self.t0 = new Date() self.postedErrors = false @@ -79,7 +78,7 @@ work = () -> try self.world = new World(args.userCodeMap) self.world.levelSessionIDs = args.levelSessionIDs - self.world.loadFromLevel args.level, true if args.level + self.world.loadFromLevel args.level, true if args.level self.world.headless = args.headless self.goalManager = new GoalManager(self.world) self.goalManager.setGoals args.goals @@ -87,23 +86,21 @@ work = () -> self.goalManager.worldGenerationWillBegin() self.world.setGoalManager self.goalManager catch error - console.log "There has been an error inside the worker." + console.log 'There has been an error inside the worker.' self.onWorldError error return Math.random = self.world.rand.randf # so user code is predictable - Aether.replaceBuiltin("Math", Math) - console.log "Loading frames." - - self.postMessage type: "start-load-frames" + Aether.replaceBuiltin('Math', Math) + console.log 'Loading frames.' + self.postMessage type: 'start-load-frames' self.world.loadFrames self.onWorldLoaded, self.onWorldError, self.onWorldLoadProgress, true - self.onWorldLoaded = onWorldLoaded = -> self.goalManager.worldGenerationEnded() goalStates = self.goalManager.getGoalStates() - self.postMessage type: "end-load-frames", goalStates: goalStates + self.postMessage type: 'end-load-frames', goalStates: goalStates t1 = new Date() diff = t1 - self.t0 @@ -115,13 +112,13 @@ work = () -> serialized = serializedWorld: self.world.serialize() transferableSupported = false catch error - console.log "World serialization error:", error.toString() + "\n" + error.stack or error.stackTrace + console.log 'World serialization error:', error.toString() + "\n" + error.stack or error.stackTrace t2 = new Date() - # console.log("About to transfer", serialized.serializedWorld.trackedPropertiesPerThangValues, serialized.transferableObjects); + # console.log('About to transfer', serialized.serializedWorld.trackedPropertiesPerThangValues, serialized.transferableObjects); try message = - type: "new-world" + type: 'new-world' serialized: serialized.serializedWorld goalStates: goalStates if transferableSupported @@ -130,9 +127,9 @@ work = () -> self.postMessage message catch error - console.log "World delivery error:", error.toString() + "\n" + error.stack or error.stackTrace + console.log 'World delivery error:', error.toString() + "\n" + error.stack or error.stackTrace t3 = new Date() - console.log "And it was so: (" + (diff / self.world.totalFrames).toFixed(3) + "ms per frame,", self.world.totalFrames, "frames)\nSimulation :", diff + "ms \nSerialization:", (t2 - t1) + "ms\nDelivery :", (t3 - t2) + "ms" + console.log 'And it was so: (' + (diff / self.world.totalFrames).toFixed(3) + 'ms per frame,', self.world.totalFrames, "frames)\nSimulation :", diff + "ms \nSerialization:", (t2 - t1) + "ms\nDelivery :", (t3 - t2) + 'ms' self.cleanUp() @@ -141,42 +138,42 @@ work = () -> errorKey = error.userInfo.key if not errorKey or not self.postedErrors[errorKey] self.postMessage - type: "user-code-problem" + type: 'user-code-problem' problem: error self.postedErrors[errorKey] = error else - console.log "Non-UserCodeError:", error.toString() + "\n" + error.stack or error.stackTrace + console.log 'Non-UserCodeError:', error.toString() + "\n" + error.stack or error.stackTrace self.cleanUp() return true self.onWorldLoadProgress = onWorldLoadProgress = (progress) -> - #console.log "Worker onWorldLoadProgress" + #console.log 'Worker onWorldLoadProgress' self.postMessage - type: "world-load-progress-changed" + type: 'world-load-progress-changed' progress: progress self.abort = abort = -> - #console.log "Abort called for worker." + #console.log 'Abort called for worker.' if self.world - #console.log "About to abort:", self.world.name, typeof self.world.abort + #console.log 'About to abort:', self.world.name, typeof self.world.abort self.world.abort() self.world = null - self.postMessage type: "abort" + self.postMessage type: 'abort' self.cleanUp() self.reportIn = reportIn = -> - console.log "Reporting in." - self.postMessage type: "report-in" + console.log 'Reporting in.' + self.postMessage type: 'report-in' - self.addEventListener "message", (event) -> + self.addEventListener 'message', (event) -> #console.log JSON.stringify event self[event.data.func] event.data.args - self.postMessage type: "worker-initialized" + self.postMessage type: 'worker-initialized' -worldCode = fs.readFileSync "./public/javascripts/world.js", 'utf8' -lodashCode = fs.readFileSync "./public/javascripts/lodash.js", 'utf8' -aetherCode = fs.readFileSync "./public/javascripts/aether.js", 'utf8' +worldCode = fs.readFileSync './public/javascripts/world.js', 'utf8' +lodashCode = fs.readFileSync './public/javascripts/lodash.js', 'utf8' +aetherCode = fs.readFileSync './public/javascripts/aether.js', 'utf8' #window.BOX2D_ENABLED = true; @@ -187,7 +184,7 @@ ret = """ GLOBAL = root = window = self; GLOBAL.window = window; - self.workerID = "Worker"; + self.workerID = 'Worker'; console = #{JASON.stringify betterConsole}(); @@ -203,17 +200,15 @@ ret = """ // the actual function #{JASON.stringify work}(); - }catch (error) { - self.postMessage({"type": "console-log", args: ["An unhandled error occured: ", error.toString(), error.stack], id: -1}); + } catch (error) { + self.postMessage({'type': 'console-log', args: ['An unhandled error occured: ', error.toString(), error.stack], id: -1}); } """ - #console = #{JASON.stringify createConsole}(); # # console.error = console.info = console.log; #self.console = console; #GLOBAL.console = console; - module.exports = new Function(ret) diff --git a/scripts/copy-i18n-tags.coffee b/scripts/copy-i18n-tags.coffee index 9e125ace0..c7f49b975 100644 --- a/scripts/copy-i18n-tags.coffee +++ b/scripts/copy-i18n-tags.coffee @@ -9,7 +9,7 @@ for file in dir when not (file in ['locale.coffee', 'en.coffee']) for enCat, enTags of en catMissing = not categories[enCat] cat = (categories[enCat] ?= {}) - lines.push "" unless first # blank lines between categories + lines.push '' unless first # blank lines between categories lines.push "#{if catMissing then '#' else ''} #{enCat}:" first = false for enTag, enString of enTags diff --git a/scripts/mail.coffee b/scripts/mail.coffee index dc2c82c8a..dbc81a790 100644 --- a/scripts/mail.coffee +++ b/scripts/mail.coffee @@ -18,21 +18,21 @@ DEBUGGING = true sendInitialRecruitingEmail = -> leaderboards = [ - {slug: 'brawlwood', team: 'humans', limit: 55, name: "Brawlwood", original: "52d97ecd32362bc86e004e87", majorVersion: 0} - {slug: 'brawlwood', team: 'ogres', limit: 40, name: "Brawlwood", original: "52d97ecd32362bc86e004e87", majorVersion: 0} - {slug: 'dungeon-arena', team: 'humans', limit: 300, name: "Dungeon Arena", original: "53173f76c269d400000543c2", majorVersion: 0} - {slug: 'dungeon-arena', team: 'ogres', limit: 250, name: "Dungeon Arena", original: "53173f76c269d400000543c2", majorVersion: 0} - {slug: 'greed', team: 'humans', limit: 465, name: "Greed", original: "53558b5a9914f5a90d7ccddb", majorVersion: 0} - {slug: 'greed', team: 'ogres', limit: 371, name: "Greed", original: "53558b5a9914f5a90d7ccddb", majorVersion: 0} - {slug: 'gold-rush', team: 'humans', limit: 253, name: "Gold Rush", original: "533353722a61b7ca6832840c", majorVersion: 0} - {slug: 'gold-rush', team: 'ogres', limit: 203, name: "Gold Rush", original: "533353722a61b7ca6832840c", majorVersion: 0} + {slug: 'brawlwood', team: 'humans', limit: 55, name: 'Brawlwood', original: '52d97ecd32362bc86e004e87', majorVersion: 0} + {slug: 'brawlwood', team: 'ogres', limit: 40, name: 'Brawlwood', original: '52d97ecd32362bc86e004e87', majorVersion: 0} + {slug: 'dungeon-arena', team: 'humans', limit: 300, name: 'Dungeon Arena', original: '53173f76c269d400000543c2', majorVersion: 0} + {slug: 'dungeon-arena', team: 'ogres', limit: 250, name: 'Dungeon Arena', original: '53173f76c269d400000543c2', majorVersion: 0} + {slug: 'greed', team: 'humans', limit: 465, name: 'Greed', original: '53558b5a9914f5a90d7ccddb', majorVersion: 0} + {slug: 'greed', team: 'ogres', limit: 371, name: 'Greed', original: '53558b5a9914f5a90d7ccddb', majorVersion: 0} + {slug: 'gold-rush', team: 'humans', limit: 253, name: 'Gold Rush', original: '533353722a61b7ca6832840c', majorVersion: 0} + {slug: 'gold-rush', team: 'ogres', limit: 203, name: 'Gold Rush', original: '533353722a61b7ca6832840c', majorVersion: 0} ] async.waterfall [ (callback) -> async.map leaderboards, grabSessions, callback (sessionLists, callback) -> async.map collapseSessions(sessionLists), grabUser, callback (users, callback) -> async.map users, emailUserInitialRecruiting, callback ], (err, results) -> - return console.log "Error:", err if err + return console.log 'Error:', err if err console.log "Looked at sending to #{results.length} users; sent to #{_.filter(results).length}." console.log "Sent to: ['#{(user.email for user in results when user).join('\', \'')}']" @@ -81,13 +81,13 @@ grabUser = (session, callback) -> totalEmailsSent = 0 emailUserInitialRecruiting = (user, callback) -> - #return callback null, false if user.emails?.anyNotes?.enabled is false # TODO: later, uncomment to obey also "anyNotes" when that's untangled + #return callback null, false if user.emails?.anyNotes?.enabled is false # TODO: later, uncomment to obey also 'anyNotes' when that's untangled return callback null, false if user.emails?.recruitNotes?.enabled is false return callback null, false if user.email in alreadyEmailed return callback null, false if DEBUGGING and (totalEmailsSent > 1 or Math.random() > 0.05) ++totalEmailsSent name = if user.firstName and user.lastName then "#{user.firstName}" else user.name - name = "Wizard" if not name or name is "Anoner" + name = 'Wizard' if not name or name is 'Anoner' team = user.session.levelInfo.team team = team.substr(0, team.length - 1) context = @@ -98,14 +98,13 @@ emailUserInitialRecruiting = (user, callback) -> email_data: name: name level_name: user.session.levelInfo.name - place: "##{user.session.rank}" # like "#31" + place: "##{user.session.rank}" # like '#31' level_race: team ladder_link: "http://codecombat.com/play/ladder/#{user.session.levelInfo.slug}" sendwithus.api.send context, (err, result) -> return callback err if err callback null, user - sendTournamentResultsEmail = -> winners = tournamentResults.greed.humans.concat tournamentResults.greed.ogres async.waterfall [ @@ -113,7 +112,7 @@ sendTournamentResultsEmail = -> (winners, callback) -> async.map winners, grabEmail, callback (winners, callback) -> async.map winners, emailUserTournamentResults, callback ], (err, results) -> - return console.log "Error:", err if err + return console.log 'Error:', err if err console.log "Looked at sending to #{results.length} users; sent to #{_.filter(results).length}." console.log "Sent to: ['#{(user.email for user in results when user).join('\', \'')}']" @@ -142,13 +141,13 @@ emailUserTournamentResults = (winner, callback) -> email_data: userID: winner.userID name: name - level_name: "Greed" + level_name: 'Greed' wins: winner.wins ties: {humans: 377, ogres: 407}[winner.team] - winner.wins - winner.losses losses: winner.losses rank: winner.rank team_name: team - ladder_url: "http://codecombat.com/play/ladder/greed#winners" + ladder_url: 'http://codecombat.com/play/ladder/greed#winners' top3: winner.rank <= 3 top5: winner.rank <= 5 top10: winner.rank <= 10 @@ -158,7 +157,6 @@ emailUserTournamentResults = (winner, callback) -> return callback err if err callback null, winner - serverSetup.connectToDatabase() fn = process.argv[2] diff --git a/scripts/runAfterGit.coffee b/scripts/runAfterGit.coffee index 3fedb8d7c..cc08f1ff7 100644 --- a/scripts/runAfterGit.coffee +++ b/scripts/runAfterGit.coffee @@ -1,4 +1,3 @@ - # This is written in coffeescript. Run this using coffee, not node. (Line to yield nice warnings on node. :)) return console.log '------------------------------------------------- \n @@ -41,22 +40,22 @@ mongopath += 'mongodb' # mongodb is in path. run = (proc, args) -> deferred = Deferred() spawned = spawn proc, args - spawned.stdout.on "data", (data) -> process.stdout.write data - spawned.stderr.on "data", (data) -> process.stderr.write data - spawned.on "exit", (code) -> - console.log proc + " exited with code " + code + spawned.stdout.on 'data', (data) -> process.stdout.write data + spawned.stderr.on 'data', (data) -> process.stderr.write data + spawned.on 'exit', (code) -> + console.log proc + ' exited with code ' + code # unless code is null doesn't seem to work # deferred.reject() deferred.resolve code - spawned.on "error", (code, error) -> - console.error proc + " failed!" + spawned.on 'error', (code, error) -> + console.error proc + ' failed!' deferred.reject() deferred.promise() removeDir = (path) -> if fs.existsSync(path) fs.readdirSync(path).forEach (file) -> - current = path + "/" + file + current = path + '/' + file if fs.lstatSync(current).isDirectory() # recurse removeDir current else # delete file @@ -65,12 +64,12 @@ removeDir = (path) -> resetDB = -> deferred = Deferred() - console.log "Dropping Database" - mongodrop = run "mongo", ["coco", "--eval", "db.dropDatabase()"] - mongodrop.fail -> console.error "Error occurred while dropping mongo. Make sure CoCo's MongoDB is running." + console.log 'Dropping Database' + mongodrop = run 'mongo', ['coco', '--eval', 'db.dropDatabase()'] + mongodrop.fail -> console.error 'Error occurred while dropping mongo. Make sure CoCo\'s MongoDB is running.' mongodrop.done -> - console.log "Restoring from dump." - mongorestore = run "mongorestore", [dbLocalPath] + console.log 'Restoring from dump.' + mongorestore = run 'mongorestore', [dbLocalPath] mongorestore.always = deferred.resolve() deferred.promise() @@ -78,7 +77,7 @@ downloadDB = -> deferred = Deferred() #mongoose = require 'mongoose' # TODO: What if mongo is not running? - console.log "Downloading Database dump. It's big. This may take a while..." + console.log 'Downloading Database dump. It\'s big. This may take a while...' request = http.get dbDump, (response)-> unzip = response.pipe(zlib.createGunzip()).pipe(tar.Extract(path: dbLocalPath)) # Log download @@ -88,17 +87,17 @@ downloadDB = -> total = len / 1048576 #1048576 - bytes in 1Megabyte response.on 'data', (chunk) -> cur += chunk.length - console.log 'DB dump download received chunk ' + currentChunk++ + ", " + (100.0 * cur / len).toFixed(2) + "% finished of " + total.toFixed(0) + " mb" - unzip.on('data', -> console.log "Unpacking zip...") - unzip.on('error', (err) -> console.log "An error occurred while downloading DB Dump: " + err) + console.log 'DB dump download received chunk ' + currentChunk++ + ', ' + (100.0 * cur / len).toFixed(2) + '% finished of ' + total.toFixed(0) + ' mb' + unzip.on('data', -> console.log 'Unpacking zip...') + unzip.on('error', (err) -> console.log 'An error occurred while downloading DB Dump: ' + err) unzip.on 'end', -> - console.log "Finished downloading." + console.log 'Finished downloading.' deferred.resolve() deferred.promise() installUpdates = -> deferred = Deferred() - npm = if process.platform is "win32" then "npm.cmd" else "npm" + npm = if process.platform is 'win32' then 'npm.cmd' else 'npm' npminstall = run npm, ['update'] npminstall.done -> bowerinstall = run 'bower', ['update'] @@ -123,4 +122,3 @@ else if '--dldb' in process.argv downloadDB() # TODO: Could advice to start SCOCODE.bat et al. here - diff --git a/scripts/simulate.coffee b/scripts/simulate.coffee index 01eccb5f9..cd8e62e59 100644 --- a/scripts/simulate.coffee +++ b/scripts/simulate.coffee @@ -1,13 +1,13 @@ -spawn = require("child_process").spawn +spawn = require('child_process').spawn -[sessionOne, sessionTwo] = [process.argv[2],process.argv[3]] +[sessionOne, sessionTwo] = [process.argv[2], process.argv[3]] homeDirectory = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE unless sessionOne and sessionTwo and sessionOne.length is 24 and sessionTwo.length is 24 - console.log "Not enough games to continue!" + console.log 'Not enough games to continue!' process.exit(1) run = (cb) -> - command = spawn("coffee",["headless_client.coffee","one-game",sessionOne,sessionTwo],{cwd: homeDirectory + "/codecombat/"}) - result = "" + command = spawn('coffee', ['headless_client.coffee', 'one-game', sessionOne, sessionTwo], {cwd: homeDirectory + '/codecombat/'}) + result = '' command.stdout.on 'data', (data) -> result += data.toString() command.stdout.on 'close', -> @@ -15,9 +15,7 @@ run = (cb) -> run (result) -> lines = result.split("\n") for line in lines - if line.slice(0, 10) is "GAMERESULT" + if line.slice(0, 10) is 'GAMERESULT' process.stdout.write line.slice(11) process.exit(0) process.exit(0) - - \ No newline at end of file diff --git a/scripts/transpile.coffee b/scripts/transpile.coffee index f8563e64f..5c39b414b 100644 --- a/scripts/transpile.coffee +++ b/scripts/transpile.coffee @@ -2,7 +2,7 @@ do (setupLodash = this) -> GLOBAL._ = require 'lodash' _.str = require 'underscore.string' _.mixin _.str.exports() -Aether = require "aether" +Aether = require 'aether' async = require 'async' serverSetup = require '../server_setup' @@ -13,12 +13,12 @@ Aether.addGlobal 'Vector', require '../app/lib/world/vector' Aether.addGlobal '_', _ i = 0 transpileLevelSession = (sessionID, cb) -> - query = LevelSession.findOne("_id": sessionID).select("team teamSpells submittedCode submittedCodeLanguage").lean() + query = LevelSession.findOne('_id': sessionID).select('team teamSpells submittedCode submittedCodeLanguage').lean() query.exec (err, session) -> if err then return cb err submittedCode = session.submittedCode unless session.submittedCodeLanguage - throw "SUBMITTED CODE LANGUAGE DOESN'T EXIST" + throw 'SUBMITTED CODE LANGUAGE DOESN\'T EXIST' else console.log "Transpiling code for session #{i++} #{session._id} in language #{session.submittedCodeLanguage}" transpiledCode = {} @@ -26,7 +26,7 @@ transpileLevelSession = (sessionID, cb) -> for thang, spells of submittedCode transpiledCode[thang] = {} for spellID, spell of spells - spellName = thang + "/" + spellID + spellName = thang + '/' + spellID if session.teamSpells and not (spellName in session.teamSpells[session.team]) then continue #console.log "Transpiling spell #{spellName}" @@ -35,36 +35,36 @@ transpileLevelSession = (sessionID, cb) -> language: session.submittedCodeLanguage functionName: spellID functionParameters: [] - yieldConditionally: spellID is "plan" + yieldConditionally: spellID is 'plan' globals: ['Vector', '_'] protectAPI: true includeFlow: false executionLimit: 1 * 1000 * 1000 - if spellID is "hear" then aetherOptions.functionParameters = ["speaker","message","data"] - if spellID is "makeBid" then aetherOptions.functionParameters = ["tileGroupLetter"] - if spellID is "findCentroids" then aetherOptions.functionParameters = ["centroids"] + if spellID is 'hear' then aetherOptions.functionParameters = ['speaker', 'message', 'data'] + if spellID is 'makeBid' then aetherOptions.functionParameters = ['tileGroupLetter'] + if spellID is 'findCentroids' then aetherOptions.functionParameters = ['centroids'] aether = new Aether aetherOptions transpiledCode[thang][spellID] = aether.transpile spell conditions = - "_id": sessionID + '_id': sessionID update = - "transpiledCode": transpiledCode - query = LevelSession.update(conditions,update) + 'transpiledCode': transpiledCode + query = LevelSession.update(conditions, update) query.exec (err, numUpdated) -> cb err findLadderLevelSessions = (levelID, cb) -> queryParameters = - "level.original": levelID + "" + 'level.original': levelID + '' submitted: true - selectString = "_id" + selectString = '_id' query = LevelSession.find(queryParameters).select(selectString).lean() query.exec (err, levelSessions) -> if err then return cb err - levelSessionIDs = _.pluck levelSessions, "_id" + levelSessionIDs = _.pluck levelSessions, '_id' async.eachSeries levelSessionIDs, transpileLevelSession, (err) -> if err then return cb err return cb null @@ -72,15 +72,15 @@ findLadderLevelSessions = (levelID, cb) -> transpileLadderSessions = -> queryParameters = - type: "ladder" - "version.isLatestMajor": true - "version.isLatestMinor": true - selectString = "original" + type: 'ladder' + 'version.isLatestMajor': true + 'version.isLatestMinor': true + selectString = 'original' query = Level.find(queryParameters).select(selectString).lean() query.exec (err, ladderLevels) -> throw err if err - ladderLevels = _.pluck ladderLevels, "original" + ladderLevels = _.pluck ladderLevels, 'original' async.eachSeries ladderLevels, findLadderLevelSessions, (err) -> throw err if err diff --git a/server.coffee b/server.coffee index 6021f2865..9b3df86ac 100644 --- a/server.coffee +++ b/server.coffee @@ -11,7 +11,7 @@ serverSetup = require './server_setup' module.exports.startServer = -> app = createAndConfigureApp() http.createServer(app).listen(app.get('port')) - log.info("Express SSL server listening on port " + app.get('port')) + log.info('Express SSL server listening on port ' + app.get('port')) return app createAndConfigureApp = -> diff --git a/server/achievements/Achievement.coffee b/server/achievements/Achievement.coffee index 83562018e..fed2cfa5b 100644 --- a/server/achievements/Achievement.coffee +++ b/server/achievements/Achievement.coffee @@ -1,8 +1,8 @@ -mongoose = require('mongoose') -jsonschema = require('../../app/schemas/models/achievement') +mongoose = require 'mongoose' +jsonschema = require '../../app/schemas/models/achievement' log = require 'winston' util = require '../../app/lib/utils' -plugins = require('../plugins/plugins') +plugins = require '../plugins/plugins' # `pre` and `post` are not called for update operations executed directly on the database, # including `Model.update`,`.findByIdAndUpdate`,`.findOneAndUpdate`, `.findOneAndRemove`,and `.findByIdAndRemove`.order @@ -15,13 +15,13 @@ AchievementSchema = new mongoose.Schema({ AchievementSchema.methods.objectifyQuery = -> try - @set('query', JSON.parse(@get('query'))) if typeof @get('query') == "string" + @set('query', JSON.parse(@get('query'))) if typeof @get('query') == 'string' catch error log.error "Couldn't convert query string to object because of #{error}" @set('query', {}) AchievementSchema.methods.stringifyQuery = -> - @set('query', JSON.stringify(@get('query'))) if typeof @get('query') != "string" + @set('query', JSON.stringify(@get('query'))) if typeof @get('query') != 'string' getExpFunction: -> kind = @get('function')?.kind or jsonschema.function.default.kind diff --git a/server/achievements/EarnedAchievement.coffee b/server/achievements/EarnedAchievement.coffee index 16738ae78..685a502c6 100644 --- a/server/achievements/EarnedAchievement.coffee +++ b/server/achievements/EarnedAchievement.coffee @@ -20,8 +20,4 @@ EarnedAchievementSchema.pre 'save', (next) -> EarnedAchievementSchema.index({user: 1, achievement: 1}, {unique: true, name: 'earned achievement index'}) EarnedAchievementSchema.index({user: 1, changed: -1}, {name: 'latest '}) - module.exports = EarnedAchievement = mongoose.model('EarnedAchievement', EarnedAchievementSchema) - - - diff --git a/server/achievements/achievement_handler.coffee b/server/achievements/achievement_handler.coffee index 998c7694c..989a8b955 100644 --- a/server/achievements/achievement_handler.coffee +++ b/server/achievements/achievement_handler.coffee @@ -11,5 +11,4 @@ class AchievementHandler extends Handler hasAccess: (req) -> req.method is 'GET' or req.user?.isAdmin() - module.exports = new AchievementHandler() diff --git a/server/achievements/earned_achievement_handler.coffee b/server/achievements/earned_achievement_handler.coffee index 24615054d..11f40cc54 100644 --- a/server/achievements/earned_achievement_handler.coffee +++ b/server/achievements/earned_achievement_handler.coffee @@ -15,7 +15,7 @@ class EarnedAchievementHandler extends Handler req.method is 'GET' # or req.user.isAdmin() recalculate: (req, res) -> - onSuccess = (data) => log.debug "Finished recalculating achievements" + onSuccess = (data) => log.debug 'Finished recalculating achievements' if 'achievements' of req.body # Support both slugs and IDs separated by commas achievementSlugsOrIDs = req.body.achievements EarnedAchievementHandler.recalculate achievementSlugsOrIDs, onSuccess @@ -91,7 +91,7 @@ class EarnedAchievementHandler extends Handler earned.earnedPoints = newPoints newTotalPoints += newPoints - EarnedAchievement.update {achievement:earned.achievement, user:earned.user}, earned, {upsert: true}, (err) -> + EarnedAchievement.update {achievement: earned.achievement, user: earned.user}, earned, {upsert: true}, (err) -> log.error err if err? callback() @@ -111,5 +111,4 @@ class EarnedAchievementHandler extends Handler # We need to have all these database updates chained so we know the final score async.series earnedAchievementSavers - module.exports = new EarnedAchievementHandler() diff --git a/server/articles/Article.coffee b/server/articles/Article.coffee index 626fc779c..1645b15b6 100644 --- a/server/articles/Article.coffee +++ b/server/articles/Article.coffee @@ -1,7 +1,7 @@ -mongoose = require('mongoose') -plugins = require('../plugins/plugins') +mongoose = require 'mongoose' +plugins = require '../plugins/plugins' -ArticleSchema = new mongoose.Schema(body: String, {strict:false}) +ArticleSchema = new mongoose.Schema(body: String, {strict: false}) ArticleSchema.plugin(plugins.NamedPlugin) ArticleSchema.plugin(plugins.VersionedPlugin) diff --git a/server/articles/article_handler.coffee b/server/articles/article_handler.coffee index 8aa2d26dc..d0d500904 100644 --- a/server/articles/article_handler.coffee +++ b/server/articles/article_handler.coffee @@ -1,5 +1,5 @@ -Article = require('./Article') -Handler = require('../commons/Handler') +Article = require './Article' +Handler = require '../commons/Handler' ArticleHandler = class ArticleHandler extends Handler modelClass: Article diff --git a/server/commons/Handler.coffee b/server/commons/Handler.coffee index ee4c312de..a796b705e 100644 --- a/server/commons/Handler.coffee +++ b/server/commons/Handler.coffee @@ -1,5 +1,5 @@ async = require 'async' -mongoose = require('mongoose') +mongoose = require 'mongoose' Grid = require 'gridfs-stream' errors = require './errors' log = require 'winston' @@ -7,7 +7,7 @@ Patch = require '../patches/Patch' User = require '../users/User' sendwithus = require '../sendwithus' -PROJECT = {original:1, name:1, version:1, description: 1, slug:1, kind: 1} +PROJECT = {original: 1, name: 1, version: 1, description: 1, slug: 1, kind: 1} FETCH_LIMIT = 200 module.exports = class Handler @@ -81,7 +81,7 @@ module.exports = class Handler else if req.query.project if @modelClass.className is 'User' projection = PROJECT - log.warn "Whoa, we haven't yet thought about public properties for User projection yet." + log.warn 'Whoa, we haven\'t yet thought about public properties for User projection yet.' else projection = {} projection[field] = 1 for field in req.query.project.split(',') @@ -130,7 +130,6 @@ module.exports = class Handler else return @sendUnauthorizedError(res) - getById: (req, res, id) -> # return @sendNotFoundError(res) # for testing return @sendUnauthorizedError(res) unless @hasAccess(req) @@ -152,7 +151,7 @@ module.exports = class Handler ids = req.query.ids or req.body.ids if @modelClass.schema.uses_coco_versions return @getNamesByOriginals(req, res) - @getPropertiesFromMultipleDocuments res, User, "name", ids + @getPropertiesFromMultipleDocuments res, User, 'name', ids getNamesByOriginals: (req, res) -> ids = req.query.ids or req.body.ids @@ -385,7 +384,6 @@ module.exports = class Handler @modelClass.findOne {slug: idOrSlug}, (err, document) -> done(err, document) - doWaterfallChecks: (req, document, done) -> return done(null, document) unless @waterfallFunctions.length @@ -430,6 +428,6 @@ module.exports = class Handler res.send dict res.end() - delete: (req, res) -> @sendMethodNotAllowed res, @allowedMethods, "DELETE not allowed." + delete: (req, res) -> @sendMethodNotAllowed res, @allowedMethods, 'DELETE not allowed.' - head: (req, res) -> @sendMethodNotAllowed res, @allowedMethods, "HEAD not allowed." + head: (req, res) -> @sendMethodNotAllowed res, @allowedMethods, 'HEAD not allowed.' diff --git a/server/commons/database.coffee b/server/commons/database.coffee index d664725c0..c0656562c 100644 --- a/server/commons/database.coffee +++ b/server/commons/database.coffee @@ -20,9 +20,9 @@ module.exports.generateMongoConnectionString = -> else dbName = config.mongo.db dbName += '_unittest' if testing - address = config.mongo.host + ":" + config.mongo.port + address = config.mongo.host + ':' + config.mongo.port if config.mongo.username and config.mongo.password - address = config.mongo.username + ":" + config.mongo.password + "@" + address + address = config.mongo.username + ':' + config.mongo.password + '@' + address address = "mongodb://#{address}/#{dbName}" return address diff --git a/server/commons/errors.coffee b/server/commons/errors.coffee index 74c50a1f8..819cb87a8 100644 --- a/server/commons/errors.coffee +++ b/server/commons/errors.coffee @@ -1,5 +1,3 @@ - - module.exports.custom = (res, code=500, message='Internal Server Error') -> res.send code, message res.end() @@ -35,10 +33,10 @@ module.exports.serverError = (res, message='Internal Server Error') -> res.send 500, message res.end() -module.exports.gatewayTimeoutError = (res, message="Gateway timeout") -> +module.exports.gatewayTimeoutError = (res, message='Gateway timeout') -> res.send 504, message res.end() -module.exports.clientTimeout = (res, message="The server did not receive the client response in a timely manner") -> +module.exports.clientTimeout = (res, message='The server did not receive the client response in a timely manner') -> res.send 408, message res.end() diff --git a/server/commons/logging.coffee b/server/commons/logging.coffee index 37c6b5668..537e045e0 100644 --- a/server/commons/logging.coffee +++ b/server/commons/logging.coffee @@ -1,4 +1,4 @@ -winston = require('winston') +winston = require 'winston' module.exports.setup = -> winston.remove(winston.transports.Console) diff --git a/server/commons/mail.coffee b/server/commons/mail.coffee index 96bb56e2d..e270bb2cd 100644 --- a/server/commons/mail.coffee +++ b/server/commons/mail.coffee @@ -8,8 +8,8 @@ module.exports.MAILCHIMP_GROUPS = ['Announcements', 'Adventurers', 'Artisans', ' module.exports.NEWS_GROUPS = ['generalNews', 'adventurerNews', 'artisanNews', 'archmageNews', 'scribeNews', 'diplomatNews', 'ambassadorNews'] nodemailer = require 'nodemailer' -module.exports.transport = nodemailer.createTransport "SMTP", +module.exports.transport = nodemailer.createTransport 'SMTP', service: config.mail.service user: config.mail.username pass: config.mail.password - authMethod: "LOGIN" + authMethod: 'LOGIN' diff --git a/server/commons/queue.coffee b/server/commons/queue.coffee index 0703427d4..312f60a6e 100644 --- a/server/commons/queue.coffee +++ b/server/commons/queue.coffee @@ -13,13 +13,11 @@ module.exports.queueClient = undefined defaultMessageVisibilityTimeoutInSeconds = 500 defaultMessageReceiptTimeout = 10 - module.exports.initializeQueueClient = (cb) -> module.exports.queueClient = generateQueueClient() unless queueClient? cb?() - generateQueueClient = -> #if config.queue.accessKeyId if false #TODO: Change this in production @@ -27,49 +25,40 @@ generateQueueClient = -> else queueClient = new MongoQueueClient() - class SQSQueueClient registerQueue: (queueName, options, callback) -> queueCreationOptions = QueueName: queueName - @sqs.createQueue queueCreationOptions, (err,data) => + @sqs.createQueue queueCreationOptions, (err, data) => @_logAndThrowFatalException "There was an error creating a new SQS queue, reason: #{JSON.stringify err}" if err? newQueue = new SQSQueue queueName, data.QueueUrl, @sqs callback? err, newQueue - constructor: -> @_configure() @sqs = @_generateSQSInstance() - _configure: -> aws.config.update accessKeyId: config.queue.accessKeyId secretAccessKey: config.queue.secretAccessKey region: config.queue.region - _generateSQSInstance: -> new aws.SQS() - _logAndThrowFatalException: (errorMessage) -> log.error errorMessage throw new Error errorMessage - - class SQSQueue extends events.EventEmitter constructor: (@queueName, @queueUrl, @sqs) -> - subscribe: (eventName, callback) -> @on eventName, callback unsubscribe: (eventName, callback) -> @removeListener eventName, callback - receiveMessage: (callback) -> queueReceiveOptions = QueueUrl: @queueUrl @@ -77,14 +66,13 @@ class SQSQueue extends events.EventEmitter @sqs.receiveMessage queueReceiveOptions, (err, data) => if err? - @emit 'error',err,originalData + @emit 'error', err, originalData else originalData = data data = new SQSMessage originalData, this - @emit 'message',err,data - - callback? err,data + @emit 'message', err, data + callback? err, data deleteMessage: (receiptHandle, callback) -> queueDeletionOptions = @@ -92,10 +80,9 @@ class SQSQueue extends events.EventEmitter ReceiptHandle: receiptHandle @sqs.deleteMessage queueDeletionOptions, (err, data) => - if err? then @emit 'error',err,data else @emit 'message',err,data - - callback? err,data + if err? then @emit 'error', err, data else @emit 'message', err, data + callback? err, data changeMessageVisibilityTimeout: (secondsFromNow, receiptHandle, callback) -> messageVisibilityTimeoutOptions = @@ -104,10 +91,9 @@ class SQSQueue extends events.EventEmitter VisibilityTimeout: secondsFromNow @sqs.changeMessageVisibility messageVisibilityTimeoutOptions, (err, data) => - if err? then @emit 'error',err,data else @emit 'edited',err,data - - callback? err,data + if err? then @emit 'error', err, data else @emit 'edited', err, data + callback? err, data sendMessage: (messageBody, delaySeconds, callback) -> queueSendingOptions = @@ -116,14 +102,12 @@ class SQSQueue extends events.EventEmitter DelaySeconds: delaySeconds @sqs.sendMessage queueSendingOptions, (err, data) => - if err? then @emit 'error',err,data else @emit 'sent',err, data - - callback? err,data + if err? then @emit 'error', err, data else @emit 'sent', err, data + callback? err, data listenForever: => async.forever (asyncCallback) => @receiveMessage (err, data) -> asyncCallback(null) - class SQSMessage constructor: (@originalMessage, @parentQueue) -> @@ -138,55 +122,46 @@ class SQSMessage requeue: (callback) -> @parentQueue.changeMessageVisibilityTimeout 0, @getReceiptHandle(), callback changeMessageVisibilityTimeout: (secondsFromFunctionCall, callback) -> - @parentQueue.changeMessageVisibilityTimeout secondsFromFunctionCall,@getReceiptHandle(), callback + @parentQueue.changeMessageVisibilityTimeout secondsFromFunctionCall, @getReceiptHandle(), callback getReceiptHandle: -> @originalMessage.Messages[0].ReceiptHandle - - - class MongoQueueClient registerQueue: (queueName, options, callback) -> - newQueue = new MongoQueue queueName,options,@messageModel + newQueue = new MongoQueue queueName, options, @messageModel callback(null, newQueue) - constructor: -> @_configure() @_createMongoConnection() @messageModel = @_generateMessageModel() - _configure: -> @databaseAddress = db.generateMongoConnectionString() - _createMongoConnection: -> @mongooseConnection = mongoose.createConnection @databaseAddress - @mongooseConnection.on 'error', -> log.error "There was an error connecting to the queue in MongoDB" - @mongooseConnection.once 'open', -> log.info "Successfully connected to MongoDB queue!" - + @mongooseConnection.on 'error', -> log.error 'There was an error connecting to the queue in MongoDB' + @mongooseConnection.once 'open', -> log.info 'Successfully connected to MongoDB queue!' _generateMessageModel: -> schema = new mongoose.Schema messageBody: Object, - queue: {type: String, index:true} + queue: {type: String, index: true} scheduledVisibilityTime: {type: Date, index: true} receiptHandle: {type: String, index: true} - @mongooseConnection.model 'messageQueue',schema - + @mongooseConnection.model 'messageQueue', schema class MongoQueue extends events.EventEmitter constructor: (queueName, options, messageModel) -> @Message = messageModel @queueName = queueName - subscribe: (eventName, callback) -> @on eventName, callback unsubscribe: (eventName, callback) -> @removeListener eventName, callback totalMessagesInQueue: (callback) -> @Message.count {}, callback - + receiveMessage: (callback) -> conditions = queue: @queueName @@ -202,13 +177,12 @@ class MongoQueue extends events.EventEmitter scheduledVisibilityTime: @_constructDefaultVisibilityTimeoutDate() @Message.findOneAndUpdate conditions, update, (err, data) => - return @emit 'error',err,data if err? + return @emit 'error', err, data if err? originalData = data data = new MongoMessage originalData, this - @emit 'message',err,data - callback? err,data - + @emit 'message', err, data + callback? err, data deleteMessage: (receiptHandle, callback) -> conditions = @@ -218,10 +192,9 @@ class MongoQueue extends events.EventEmitter $gte: new Date() @Message.findOneAndRemove conditions, {}, (err, data) => - if err? then @emit 'error',err,data else @emit 'delete',err,data - - callback? err,data + if err? then @emit 'error', err, data else @emit 'delete', err, data + callback? err, data sendMessage: (messageBody, delaySeconds, callback) -> messageToSend = new @Message @@ -229,9 +202,9 @@ class MongoQueue extends events.EventEmitter queue: @queueName scheduledVisibilityTime: @_constructDefaultVisibilityTimeoutDate delaySeconds - messageToSend.save (err,data) => - if err? then @emit 'error',err,data else @emit 'sent',err, data - callback? err,data + messageToSend.save (err, data) => + if err? then @emit 'error', err, data else @emit 'sent', err, data + callback? err, data changeMessageVisibilityTimeout: (secondsFromNow, receiptHandle, callback) -> conditions = @@ -247,17 +220,15 @@ class MongoQueue extends events.EventEmitter @Message.findOneAndUpdate conditions, update, (err, data) => if err? log.error "There was a problem updating the message visibility timeout:#{err}" - @emit 'error',err,data + @emit 'error', err, data else - @emit 'update',err,data - #log.info "The message visibility time was updated" + @emit 'update', err, data + #log.info 'The message visibility time was updated' callback? err, data - listenForever: => async.forever (asyncCallback) => @recieveMessage (err, data) -> asyncCallback(null) - _constructDefaultVisibilityTimeoutDate: (timeoutSeconds) -> timeoutSeconds ?= defaultMessageVisibilityTimeoutInSeconds newDate = new Date() @@ -265,11 +236,8 @@ class MongoQueue extends events.EventEmitter newDate - _generateRandomReceiptHandle: -> crypto.randomBytes(20).toString('hex') - - class MongoMessage constructor: (@originalMessage, @parentQueue) -> @@ -284,6 +252,6 @@ class MongoMessage requeue: (callback) -> @parentQueue.changeMessageVisibilityTimeout 0, @getReceiptHandle(), callback changeMessageVisibilityTimeout: (secondsFromFunctionCall, callback) -> - @parentQueue.changeMessageVisibilityTimeout secondsFromFunctionCall,@getReceiptHandle(), callback + @parentQueue.changeMessageVisibilityTimeout secondsFromFunctionCall, @getReceiptHandle(), callback getReceiptHandle: -> @originalMessage.receiptHandle diff --git a/server/levels/Level.coffee b/server/levels/Level.coffee index 9cadeac7b..05cbdeb8f 100644 --- a/server/levels/Level.coffee +++ b/server/levels/Level.coffee @@ -1,6 +1,6 @@ -mongoose = require('mongoose') -plugins = require('../plugins/plugins') -jsonschema = require('../../app/schemas/models/level') +mongoose = require 'mongoose' +plugins = require '../plugins/plugins' +jsonschema = require '../../app/schemas/models/level' LevelSchema = new mongoose.Schema({ description: String @@ -17,7 +17,7 @@ LevelSchema.pre 'init', (next) -> for prop, sch of jsonschema.properties @set(prop, _.cloneDeep(sch.default)) if sch.default? next() - + LevelSchema.post 'init', (doc) -> if _.isString(doc.get('nextLevel')) doc.set('nextLevel', undefined) diff --git a/server/levels/components/LevelComponent.coffee b/server/levels/components/LevelComponent.coffee index 6c1a58370..6fb467908 100644 --- a/server/levels/components/LevelComponent.coffee +++ b/server/levels/components/LevelComponent.coffee @@ -1,6 +1,6 @@ -mongoose = require('mongoose') -plugins = require('../../plugins/plugins') -jsonschema = require('../../../app/schemas/models/level_component') +mongoose = require 'mongoose' +plugins = require '../../plugins/plugins' +jsonschema = require '../../../app/schemas/models/level_component' LevelComponentSchema = new mongoose.Schema { description: String diff --git a/server/levels/components/level_component_handler.coffee b/server/levels/components/level_component_handler.coffee index 98844ddbc..810fa3e86 100644 --- a/server/levels/components/level_component_handler.coffee +++ b/server/levels/components/level_component_handler.coffee @@ -1,5 +1,5 @@ -LevelComponent = require('./LevelComponent') -Handler = require('../../commons/Handler') +LevelComponent = require './LevelComponent' +Handler = require '../../commons/Handler' LevelComponentHandler = class LevelComponentHandler extends Handler modelClass: LevelComponent diff --git a/server/levels/feedbacks/LevelFeedback.coffee b/server/levels/feedbacks/LevelFeedback.coffee index 5fef6a567..523bf9120 100644 --- a/server/levels/feedbacks/LevelFeedback.coffee +++ b/server/levels/feedbacks/LevelFeedback.coffee @@ -1,8 +1,8 @@ # TODO: not updated since rename from level_instance, or since we redid how all models are done; probably busted -mongoose = require('mongoose') -plugins = require('../../plugins/plugins') -jsonschema = require('../../../app/schemas/models/level_feedback') +mongoose = require 'mongoose' +plugins = require '../../plugins/plugins' +jsonschema = require '../../../app/schemas/models/level_feedback' LevelFeedbackSchema = new mongoose.Schema({ created: @@ -10,4 +10,4 @@ LevelFeedbackSchema = new mongoose.Schema({ 'default': Date.now }, {strict: false}) -module.exports = LevelFeedback = mongoose.model('level.feedback', LevelFeedbackSchema) \ No newline at end of file +module.exports = LevelFeedback = mongoose.model('level.feedback', LevelFeedbackSchema) diff --git a/server/levels/feedbacks/level_feedback_handler.coffee b/server/levels/feedbacks/level_feedback_handler.coffee index 58d268db1..4226b1d07 100644 --- a/server/levels/feedbacks/level_feedback_handler.coffee +++ b/server/levels/feedbacks/level_feedback_handler.coffee @@ -1,5 +1,5 @@ -LevelFeedback = require('./LevelFeedback') -Handler = require('../../commons/Handler') +LevelFeedback = require './LevelFeedback' +Handler = require '../../commons/Handler' class LevelFeedbackHandler extends Handler modelClass: LevelFeedback diff --git a/server/levels/level_handler.coffee b/server/levels/level_handler.coffee index 27c5f0042..0843b0ffc 100644 --- a/server/levels/level_handler.coffee +++ b/server/levels/level_handler.coffee @@ -1,11 +1,12 @@ -Level = require('./Level') -Session = require('./sessions/LevelSession') +Level = require './Level' +Session = require './sessions/LevelSession' User = require '../users/User' -SessionHandler = require('./sessions/level_session_handler') -Feedback = require('./feedbacks/LevelFeedback') -Handler = require('../commons/Handler') -mongoose = require('mongoose') +SessionHandler = require './sessions/level_session_handler' +Feedback = require './feedbacks/LevelFeedback' +Handler = require '../commons/Handler' +mongoose = require 'mongoose' async = require 'async' + LevelHandler = class LevelHandler extends Handler modelClass: Level jsonSchema: require '../../app/schemas/models/level' @@ -34,7 +35,7 @@ LevelHandler = class LevelHandler extends Handler return @getMyLeaderboardRank(req, res, args[0]) if args[1] is 'leaderboard_rank' return @getMySessions(req, res, args[0]) if args[1] is 'my_sessions' return @getFeedback(req, res, args[0]) if args[1] is 'feedback' - return @getRandomSessionPair(req,res,args[0]) if args[1] is 'random_session_pair' + return @getRandomSessionPair(req, res, args[0]) if args[1] is 'random_session_pair' return @getLeaderboardFacebookFriends(req, res, args[0]) if args[1] is 'leaderboard_facebook_friends' return @getLeaderboardGPlusFriends(req, res, args[0]) if args[1] is 'leaderboard_gplus_friends' return @getHistogramData(req, res, args[0]) if args[1] is 'histogram_data' @@ -69,23 +70,22 @@ LevelHandler = class LevelHandler extends Handler return @sendSuccess(res, doc) if doc? @createAndSaveNewSession sessionQuery, req, res - createAndSaveNewSession: (sessionQuery, req, res) => initVals = sessionQuery initVals.state = - complete:false + complete: false scripts: - currentScript:null # will not save empty objects + currentScript: null # will not save empty objects initVals.permissions = [ { - target:req.user.id - access:'owner' + target: req.user.id + access: 'owner' } { - target:'public' - access:'write' + target: 'public' + access: 'write' } ] initVals.codeLanguage = req.user.get('aceConfig')?.language ? 'javascript' @@ -101,9 +101,9 @@ LevelHandler = class LevelHandler extends Handler getMySessions: (req, res, slugOrID) -> findParameters = {} if Handler.isID slugOrID - findParameters["_id"] = slugOrID + findParameters['_id'] = slugOrID else - findParameters["slug"] = slugOrID + findParameters['slug'] = slugOrID selectString = 'original version.major permissions' query = Level.findOne(findParameters) .select(selectString) @@ -122,23 +122,23 @@ LevelHandler = class LevelHandler extends Handler query.exec (err, results) => if err then @sendDatabaseError(res, err) else @sendSuccess res, results - getHistogramData: (req, res,slug) -> + getHistogramData: (req, res, slug) -> query = Session.aggregate [ - {$match: {"levelID":slug, "submitted": true, "team":req.query.team}} + {$match: {'levelID': slug, 'submitted': true, 'team': req.query.team}} {$project: {totalScore: 1, _id: 0}} ] query.exec (err, data) => if err? then return @sendDatabaseError res, err - valueArray = _.pluck data, "totalScore" + valueArray = _.pluck data, 'totalScore' @sendSuccess res, valueArray checkExistence: (req, res, slugOrID) -> findParameters = {} if Handler.isID slugOrID - findParameters["_id"] = slugOrID + findParameters['_id'] = slugOrID else - findParameters["slug"] = slugOrID + findParameters['slug'] = slugOrID selectString = 'original version.major permissions' query = Level.findOne(findParameters) .select(selectString) @@ -147,14 +147,14 @@ LevelHandler = class LevelHandler extends Handler query.exec (err, level) => return @sendDatabaseError(res, err) if err return @sendNotFoundError(res) unless level? - res.send({"exists":true}) + res.send({'exists': true}) res.end() getLeaderboard: (req, res, id) -> sessionsQueryParameters = @makeLeaderboardQueryParameters(req, id) sortParameters = - "totalScore": req.query.order + 'totalScore': req.query.order selectProperties = ['totalScore', 'creatorName', 'creator'] query = Session @@ -180,7 +180,7 @@ LevelHandler = class LevelHandler extends Handler [original, version] = id.split '.' version = parseInt(version) ? 0 scoreQuery = {} - scoreQuery[if req.query.order is 1 then "$gt" else "$lt"] = req.query.scoreOffset + scoreQuery[if req.query.order is 1 then '$gt' else '$lt'] = req.query.scoreOffset query = level: original: original @@ -203,14 +203,14 @@ LevelHandler = class LevelHandler extends Handler return res.send([]) unless friendIDs.length q = {} - q[serviceProperty] = {$in:friendIDs} + q[serviceProperty] = {$in: friendIDs} query = User.find(q).select("#{serviceProperty} name").lean() query.exec (err, userResults) -> return res.send([]) unless userResults.length [id, version] = id.split('.') userIDs = (r._id+'' for r in userResults) - q = {'level.original':id, 'level.majorVersion': parseInt(version), creator: {$in:userIDs}, totalScore:{$exists:true}} + q = {'level.original': id, 'level.majorVersion': parseInt(version), creator: {$in: userIDs}, totalScore: {$exists: true}} query = Session.find(q) .select('creator creatorName totalScore team') .lean() @@ -225,9 +225,9 @@ LevelHandler = class LevelHandler extends Handler getRandomSessionPair: (req, res, slugOrID) -> findParameters = {} if Handler.isID slugOrID - findParameters["_id"] = slugOrID + findParameters['_id'] = slugOrID else - findParameters["slug"] = slugOrID + findParameters['slug'] = slugOrID selectString = 'original version' query = Level.findOne(findParameters) .select(selectString) @@ -241,17 +241,17 @@ LevelHandler = class LevelHandler extends Handler level: original: level.original.toString() majorVersion: level.version.major - submitted:true + submitted: true - query = Session.find(sessionsQueryParameters).distinct("team") + query = Session.find(sessionsQueryParameters).distinct('team') query.exec (err, teams) => return @sendDatabaseError res, err if err? or not teams findTop20Players = (sessionQueryParams, team, cb) -> - sessionQueryParams["team"] = team + sessionQueryParams['team'] = team Session.aggregate [ {$match: sessionQueryParams} - {$project: {"totalScore":1}} - {$sort: {"totalScore":-1}} + {$project: {'totalScore': 1}} + {$sort: {'totalScore': -1}} {$limit: 20} ], cb @@ -260,10 +260,9 @@ LevelHandler = class LevelHandler extends Handler sessions = [] for mapItem in map sessions.push _.sample(mapItem) - if map.length != 2 then return @sendDatabaseError res, "There aren't sessions of 2 teams, so cannot choose random opponents!" + if map.length != 2 then return @sendDatabaseError res, 'There aren\'t sessions of 2 teams, so cannot choose random opponents!' @sendSuccess res, sessions - getFeedback: (req, res, id) -> return @sendNotFoundError(res) unless req.user @fetchLevelByIDAndHandleErrors id, req, res, (err, level) => diff --git a/server/levels/sessions/LevelSession.coffee b/server/levels/sessions/LevelSession.coffee index 122789183..4873e40a5 100644 --- a/server/levels/sessions/LevelSession.coffee +++ b/server/levels/sessions/LevelSession.coffee @@ -1,9 +1,9 @@ # TODO: not updated since rename from level_instance, or since we redid how all models are done; probably busted -mongoose = require('mongoose') -plugins = require('../../plugins/plugins') +mongoose = require 'mongoose' +plugins = require '../../plugins/plugins' AchievablePlugin = require '../../plugins/achievements' -jsonschema = require('../../../app/schemas/models/level_session') +jsonschema = require '../../../app/schemas/models/level_session' LevelSessionSchema = new mongoose.Schema({ created: @@ -24,4 +24,4 @@ LevelSessionSchema.pre 'save', (next) -> @set('changed', new Date()) next() -module.exports = LevelSession = mongoose.model('level.session', LevelSessionSchema) \ No newline at end of file +module.exports = LevelSession = mongoose.model('level.session', LevelSessionSchema) diff --git a/server/levels/sessions/level_session_handler.coffee b/server/levels/sessions/level_session_handler.coffee index b43f0a26f..b1179acf8 100644 --- a/server/levels/sessions/level_session_handler.coffee +++ b/server/levels/sessions/level_session_handler.coffee @@ -1,5 +1,5 @@ -LevelSession = require('./LevelSession') -Handler = require('../../commons/Handler') +LevelSession = require './LevelSession' +Handler = require '../../commons/Handler' log = require 'winston' TIMEOUT = 1000 * 30 # no activity for 30 seconds means it's not active diff --git a/server/levels/systems/LevelSystem.coffee b/server/levels/systems/LevelSystem.coffee index f945aaa95..b553cdd89 100644 --- a/server/levels/systems/LevelSystem.coffee +++ b/server/levels/systems/LevelSystem.coffee @@ -1,6 +1,6 @@ -mongoose = require('mongoose') -plugins = require('../../plugins/plugins') -jsonschema = require('../../../app/schemas/models/level_system') +mongoose = require 'mongoose' +plugins = require '../../plugins/plugins' +jsonschema = require '../../../app/schemas/models/level_system' LevelSystemSchema = new mongoose.Schema { description: String diff --git a/server/levels/systems/level_system_handler.coffee b/server/levels/systems/level_system_handler.coffee index e19dd43bd..ef9dd5d2b 100644 --- a/server/levels/systems/level_system_handler.coffee +++ b/server/levels/systems/level_system_handler.coffee @@ -1,5 +1,5 @@ -LevelSystem = require('./LevelSystem') -Handler = require('../../commons/Handler') +LevelSystem = require './LevelSystem' +Handler = require '../../commons/Handler' LevelSystemHandler = class LevelSystemHandler extends Handler modelClass: LevelSystem diff --git a/server/levels/thangs/LevelThangType.coffee b/server/levels/thangs/LevelThangType.coffee index 98d89c4b3..264ef5348 100644 --- a/server/levels/thangs/LevelThangType.coffee +++ b/server/levels/thangs/LevelThangType.coffee @@ -1,5 +1,5 @@ -mongoose = require('mongoose') -plugins = require('../../plugins/plugins') +mongoose = require 'mongoose' +plugins = require '../../plugins/plugins' LevelComponentSchema = new mongoose.Schema( original: {type: mongoose.Schema.ObjectId, ref: 'level.session'} diff --git a/server/levels/thangs/ThangType.coffee b/server/levels/thangs/ThangType.coffee index 292597719..78ee66180 100644 --- a/server/levels/thangs/ThangType.coffee +++ b/server/levels/thangs/ThangType.coffee @@ -1,5 +1,5 @@ -mongoose = require('mongoose') -plugins = require('../../plugins/plugins') +mongoose = require 'mongoose' +plugins = require '../../plugins/plugins' ThangTypeSchema = new mongoose.Schema({ body: String, diff --git a/server/levels/thangs/thang_type_handler.coffee b/server/levels/thangs/thang_type_handler.coffee index a8d5c05e7..9e51a80f3 100644 --- a/server/levels/thangs/thang_type_handler.coffee +++ b/server/levels/thangs/thang_type_handler.coffee @@ -1,5 +1,5 @@ -ThangType = require('./ThangType') -Handler = require('../../commons/Handler') +ThangType = require './ThangType' +Handler = require '../../commons/Handler' ThangTypeHandler = class ThangTypeHandler extends Handler modelClass: ThangType diff --git a/server/patches/Patch.coffee b/server/patches/Patch.coffee index 3e12638cf..05227e7f6 100644 --- a/server/patches/Patch.coffee +++ b/server/patches/Patch.coffee @@ -1,4 +1,4 @@ -mongoose = require('mongoose') +mongoose = require 'mongoose' {handlers} = require '../commons/mapping' PatchSchema = new mongoose.Schema({}, {strict: false}) @@ -10,22 +10,22 @@ PatchSchema.pre 'save', (next) -> Handler = require '../commons/Handler' if not Handler.isID(targetID) err = new Error('Invalid input.') - err.response = {message:"isn't a MongoDB id.", property:'target.id'} + err.response = {message: 'isn\'t a MongoDB id.', property: 'target.id'} err.code = 422 return next(err) - + collection = target.collection handler = require('../' + handlers[collection]) handler.getDocumentForIdOrSlug targetID, (err, document) => if err err = new Error('Server error.') - err.response = {message:'', property:'target.id'} + err.response = {message: '', property: 'target.id'} err.code = 500 return next(err) if not document err = new Error('Target of patch not found.') - err.response = {message:'was not found.', property:'target.id'} + err.response = {message: 'was not found.', property: 'target.id'} err.code = 404 return next(err) @@ -37,7 +37,7 @@ PatchSchema.pre 'save', (next) -> @set('target', target) else target.original = targetID - + patches = document.get('patches') or [] patches = _.clone patches patches.push @_id diff --git a/server/patches/patch_handler.coffee b/server/patches/patch_handler.coffee index 7d30ce353..f9c3a2224 100644 --- a/server/patches/patch_handler.coffee +++ b/server/patches/patch_handler.coffee @@ -1,9 +1,9 @@ -Patch = require('./Patch') +Patch = require './Patch' User = require '../users/User' -Handler = require('../commons/Handler') +Handler = require '../commons/Handler' schema = require '../../app/schemas/models/patch' {handlers} = require '../commons/mapping' -mongoose = require('mongoose') +mongoose = require 'mongoose' log = require 'winston' sendwithus = require '../sendwithus' @@ -23,12 +23,12 @@ PatchHandler = class PatchHandler extends Handler getByRelationship: (req, res, args...) -> return @setStatus(req, res, args[0]) if req.route.method is 'put' and args[1] is 'status' super(arguments...) - + setStatus: (req, res, id) -> newStatus = req.body.status unless newStatus in ['rejected', 'accepted', 'withdrawn'] - return @sendBadInputError(res, "Status must be 'rejected', 'accepted', or 'withdrawn'") - + return @sendBadInputError(res, 'Status must be "rejected", "accepted", or "withdrawn"') + @getDocumentForIdOrSlug id, (err, patch) => return @sendDatabaseError(res, err) if err return @sendNotFoundError(res) unless patch? @@ -45,25 +45,25 @@ PatchHandler = class PatchHandler extends Handler if newStatus in ['rejected', 'accepted'] return @sendUnauthorizedError(res) unless targetHandler.hasAccessToDocument(req, target, 'put') - + if newStatus is 'withdrawn' return @sendUnauthorizedError(res) unless req.user.get('_id').equals patch.get('creator') - + # these require callbacks - patch.update {$set:{status:newStatus}}, {}, -> - target.update {$pull:{patches:patch.get('_id')}}, {}, -> + patch.update {$set: {status: newStatus}}, {}, -> + target.update {$pull: {patches: patch.get('_id')}}, {}, -> @sendSuccess(res, null) onPostSuccess: (req, doc) -> - log.error "Error sending patch created: could not find the loaded target on the patch object." unless doc.targetLoaded + log.error 'Error sending patch created: could not find the loaded target on the patch object.' unless doc.targetLoaded return unless doc.targetLoaded watchers = doc.targetLoaded.get('watchers') or [] watchers = (w for w in watchers when not w.equals(req.user.get('_id'))) return unless watchers?.length - User.find({_id:{$in:watchers}}).select({email:1, name:1}).exec (err, watchers) => + User.find({_id: {$in: watchers}}).select({email: 1, name: 1}).exec (err, watchers) => for watcher in watchers @sendPatchCreatedEmail req.user, watcher, doc, doc.targetLoaded, req.body.editPath - + sendPatchCreatedEmail: (patchCreator, watcher, patch, target, editPath) -> # return if watcher._id is patchCreator._id context = diff --git a/server/plugins/achievements.coffee b/server/plugins/achievements.coffee index a3f0096af..0e4d448c0 100644 --- a/server/plugins/achievements.coffee +++ b/server/plugins/achievements.coffee @@ -1,4 +1,4 @@ -mongoose = require('mongoose') +mongoose = require 'mongoose' EarnedAchievement = require '../achievements/EarnedAchievement' LocalMongo = require '../../app/lib/LocalMongo' util = require '../../app/lib/utils' @@ -65,7 +65,7 @@ module.exports = AchievablePlugin = (schema, options) -> earned.achievedAmount = newAmount earned.earnedPoints = (expFunction(newAmount) - expFunction(originalAmount)) * worth earned.previouslyAchievedAmount = originalAmount - EarnedAchievement.update {achievement:earned.achievement, user:earned.user}, earned, {upsert: true}, (err) -> + EarnedAchievement.update {achievement: earned.achievement, user: earned.user}, earned, {upsert: true}, (err) -> return log.debug err if err? earnedPoints = earned.earnedPoints diff --git a/server/plugins/plugins.coffee b/server/plugins/plugins.coffee index 25674f688..e36bb16de 100644 --- a/server/plugins/plugins.coffee +++ b/server/plugins/plugins.coffee @@ -1,5 +1,5 @@ -mongoose = require('mongoose') -textSearch = require('mongoose-text-search') +mongoose = require 'mongoose' +textSearch = require 'mongoose-text-search' module.exports.MigrationPlugin = (schema, migrations) -> # Property name migrations made EZ @@ -8,7 +8,7 @@ module.exports.MigrationPlugin = (schema, migrations) -> # 1. Change the schema and the client/server logic to use the new name # 2. Add this plugin to the target models, passing in a dictionary of old/new names. # 3. Check that tests still run, deploy to production. - # 4. Run db..update({}, { $rename: {'':''} }, { multi: true }) on the server + # 4. Run db..update({}, {$rename: {'': ''}}, {multi: true}) on the server # 5. Remove the names you added to the migrations dictionaries for the next deploy schema.post 'init', -> @@ -21,8 +21,8 @@ module.exports.MigrationPlugin = (schema, migrations) -> module.exports.PatchablePlugin = (schema) -> schema.is_patchable = true - schema.index({'target.original':1, 'status':'1', 'created':-1}) - + schema.index({'target.original': 1, 'status': '1', 'created': -1}) + RESERVED_NAMES = ['names'] module.exports.NamedPlugin = (schema) -> @@ -38,7 +38,7 @@ module.exports.NamedPlugin = (schema) -> newSlug = _.str.slugify(@get('name')) if newSlug in RESERVED_NAMES err = new Error('Reserved name.') - err.response = {message:' is a reserved name', property: 'name'} + err.response = {message: ' is a reserved name', property: 'name'} err.code = 422 return next(err) if newSlug isnt @get('slug') @@ -57,29 +57,27 @@ module.exports.NamedPlugin = (schema) -> err.code = 422 done(err) - query = { slug:slug } + query = {slug: slug} if @get('original') - query.original = {'$ne':@original} + query.original = {'$ne': @original} else if @_id - query._id = {'$ne':@_id} + query._id = {'$ne': @_id} @model(@constructor.modelName).count query, (err, count) -> if count err = new Error('Slug conflict.') - err.response = {message:'is already in use', property:'name'} + err.response = {message: 'is already in use', property: 'name'} err.code = 409 done(err) done() - - module.exports.PermissionsPlugin = (schema) -> schema.uses_coco_permissions = true PermissionSchema = new mongoose.Schema target: mongoose.Schema.Types.Mixed - access: {type: String, 'enum':['read', 'write', 'owner']} + access: {type: String, 'enum': ['read', 'write', 'owner']} , {id: false, _id: false} schema.add(permissions: [PermissionSchema]) @@ -87,7 +85,7 @@ module.exports.PermissionsPlugin = (schema) -> schema.pre 'save', (next) -> return next() if @getOwner() err = new Error('Permissions needs an owner.') - err.response = {message:'needs an owner.', property:'permissions'} + err.response = {message: 'needs an owner.', property: 'permissions'} err.code = 409 next(err) @@ -143,7 +141,7 @@ module.exports.VersionedPlugin = (schema) -> original: {type: mongoose.Schema.ObjectId, ref: @modelName} parent: {type: mongoose.Schema.ObjectId, ref: @modelName} creator: {type: mongoose.Schema.ObjectId, ref: 'User'} - created: { type: Date, 'default': Date.now } + created: {type: Date, 'default': Date.now} commitMessage: {type: String} ) @@ -153,15 +151,15 @@ module.exports.VersionedPlugin = (schema) -> schema.statics.getLatestMajorVersion = (original, options, done) -> options = options or {} - query = @findOne({original:original, 'version.isLatestMajor':true}) + query = @findOne({original: original, 'version.isLatestMajor': true}) query.select(options.select) if options.select query.exec((err, latest) => return done(err) if err return done(null, latest) if latest # handle the case where no version is marked as the latest - q = @find({original:original}) - q.sort({'version.major':-1, 'version.minor':-1}) + q = @find({original: original}) + q.sort({'version.major': -1, 'version.minor': -1}) q.select(options.select) if options.select q.limit(1) q.exec((err, latest) => @@ -181,13 +179,13 @@ module.exports.VersionedPlugin = (schema) -> schema.statics.getLatestMinorVersion = (original, majorVersion, options, done) -> options = options or {} - query = @findOne({original:original, 'version.isLatestMinor':true, 'version.major':majorVersion}) + query = @findOne({original: original, 'version.isLatestMinor': true, 'version.major': majorVersion}) query.select(options.select) if options.select query.exec((err, latest) => return done(err) if err return done(null, latest) if latest - q = @find({original:original, 'version.major':majorVersion}) - q.sort({'version.minor':-1}) + q = @find({original: original, 'version.major': majorVersion}) + q.sort({'version.minor': -1}) q.select(options.select) if options.select q.limit(1) q.exec((err, latest) -> @@ -207,17 +205,17 @@ module.exports.VersionedPlugin = (schema) -> schema.methods.makeNewMajorVersion = (newObject, done) -> Model = @model(@constructor.modelName) - latest = Model.getLatestMajorVersion(@original, {select:'version'}, (err, latest) => + latest = Model.getLatestMajorVersion(@original, {select: 'version'}, (err, latest) => return done(err) if err updatedObject = _.cloneDeep latestObject # unmark the current latest major version in the database latestObject = latest.toObject() latestObject.version.isLatestMajor = false - Model.update({_id: latest._id}, {version: latestObject.version, $unset: {index:1, slug: 1} }, {}, (err) => + Model.update({_id: latest._id}, {version: latestObject.version, $unset: {index: 1, slug: 1}}, {}, (err) => return done(err) if err - newObject['version'] = { major: latest.version.major + 1 } + newObject['version'] = {major: latest.version.major + 1} newObject.index = true newObject.parent = @_id delete newObject['_id'] @@ -229,7 +227,7 @@ module.exports.VersionedPlugin = (schema) -> schema.methods.makeNewMinorVersion = (newObject, majorVersion, done) -> Model = @model(@constructor.modelName) - latest = Model.getLatestMinorVersion(@original, majorVersion, {select:'version'}, (err, latest) => + latest = Model.getLatestMinorVersion(@original, majorVersion, {select: 'version'}, (err, latest) => return done(err) if err # unmark the current latest major version in the database @@ -237,7 +235,7 @@ module.exports.VersionedPlugin = (schema) -> wasLatestMajor = latestObject.version.isLatestMajor latestObject.version.isLatestMajor = false latestObject.version.isLatestMinor = false - Model.update({_id: latest._id}, {version: latestObject.version, $unset: {index:1, slug: 1}}, {}, (err) => + Model.update({_id: latest._id}, {version: latestObject.version, $unset: {index: 1, slug: 1}}, {}, (err) => return done(err) if err newObject['version'] = @@ -256,7 +254,6 @@ module.exports.VersionedPlugin = (schema) -> ) ) - module.exports.SearchablePlugin = (schema, options) -> # this plugin must be added only after the others (specifically Versioned and Permissions) # have been added, as how it builds the text search index depends on which of those are used. @@ -274,9 +271,9 @@ module.exports.SearchablePlugin = (schema, options) -> index[prop] = 'text' for prop in searchable - # should now have something like {'index': 1, name:'text', body:'text'} + # should now have something like {'index': 1, name: 'text', body: 'text'} schema.plugin(textSearch) - schema.index(index, { sparse: true, name: 'search index', language_override: 'searchLanguage' }) + schema.index(index, {sparse: true, name: 'search index', language_override: 'searchLanguage'}) schema.pre 'save', (next) -> # never index old versions, index plugin handles un-indexing old versions diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee index 632c4a76c..4a57234c1 100644 --- a/server/queues/scoring.coffee +++ b/server/queues/scoring.coffee @@ -16,15 +16,14 @@ bayes = new (require 'bayesian-battle')() scoringTaskQueue = undefined scoringTaskTimeoutInSeconds = 240 - module.exports.setup = (app) -> connectToScoringQueue() connectToScoringQueue = -> queues.initializeQueueClient -> - queues.queueClient.registerQueue "scoring", {}, (error,data) -> + queues.queueClient.registerQueue 'scoring', {}, (error, data) -> if error? then throw new Error "There was an error registering the scoring queue: #{error}" scoringTaskQueue = data - log.info "Connected to scoring task queue!" + log.info 'Connected to scoring task queue!' module.exports.messagesInQueueCount = (req, res) -> scoringTaskQueue.totalMessagesInQueue (err, count) -> @@ -33,18 +32,16 @@ module.exports.messagesInQueueCount = (req, res) -> res.send(response) res.end() - module.exports.addPairwiseTaskToQueueFromRequest = (req, res) -> taskPair = req.body.sessions addPairwiseTaskToQueue req.body.sessions, (err, success) -> if err? then return errors.serverError res, "There was an error adding pairwise tasks: #{err}" - sendResponseObject req, res, {"message":"All task pairs were succesfully sent to the queue"} - + sendResponseObject req, res, {'message': 'All task pairs were succesfully sent to the queue'} addPairwiseTaskToQueue = (taskPair, cb) -> - LevelSession.findOne(_id:taskPair[0]).lean().exec (err, firstSession) => + LevelSession.findOne(_id: taskPair[0]).lean().exec (err, firstSession) => if err? then return cb err - LevelSession.find(_id:taskPair[1]).exec (err, secondSession) => + LevelSession.find(_id: taskPair[1]).exec (err, secondSession) => if err? then return cb err try taskPairs = generateTaskPairs(secondSession, firstSession) @@ -57,7 +54,7 @@ addPairwiseTaskToQueue = (taskPair, cb) -> # We should rip these out, probably module.exports.resimulateAllSessions = (req, res) -> - unless isUserAdmin req then return errors.unauthorized res, "Unauthorized. Even if you are authorized, you shouldn't do this" + unless isUserAdmin req then return errors.unauthorized res, 'Unauthorized. Even if you are authorized, you shouldn\'t do this' originalLevelID = req.body.originalLevelID levelMajorVersion = parseInt(req.body.levelMajorVersion) @@ -75,9 +72,9 @@ module.exports.resimulateAllSessions = (req, res) -> query.exec (err, result) -> if err? then return errors.serverError res, err result = _.sample result, 10 - async.each result, resimulateSession.bind(@,originalLevelID,levelMajorVersion), (err) -> + async.each result, resimulateSession.bind(@, originalLevelID, levelMajorVersion), (err) -> if err? then return errors.serverError res, err - sendResponseObject req, res, {"message":"All task pairs were succesfully sent to the queue"} + sendResponseObject req, res, {'message': 'All task pairs were succesfully sent to the queue'} resimulateSession = (originalLevelID, levelMajorVersion, session, cb) => sessionUpdateObject = @@ -109,7 +106,7 @@ selectRandomSkipIndex = (numberOfSessions) -> numberWeights[index] = lambda*Math.exp(-1*lambda*number) + lambda/(numberOfSessions/15) sum = numberWeights.reduce (a, b) -> a + b - for number,index in numberWeights + for number, index in numberWeights numberWeights[index] /= sum rand = (min, max) -> Math.random() * (max - min) + min @@ -125,31 +122,31 @@ selectRandomSkipIndex = (numberOfSessions) -> return numbers[i] module.exports.getTwoGames = (req, res) -> - #if userIsAnonymous req then return errors.unauthorized(res, "You need to be logged in to get games.") + #if userIsAnonymous req then return errors.unauthorized(res, 'You need to be logged in to get games.') humansGameID = req.body.humansGameID ogresGameID = req.body.ogresGameID unless ogresGameID and humansGameID #fetch random games here queryParams = - "levelID":"greed" - "submitted":true - "team":"humans" - selection = "team totalScore transpiledCode submittedCodeLanguage teamSpells levelID creatorName creator submitDate" + 'levelID': 'greed' + 'submitted': true + 'team': 'humans' + selection = 'team totalScore transpiledCode submittedCodeLanguage teamSpells levelID creatorName creator submitDate' LevelSession.count queryParams, (err, numberOfHumans) => - if err? then return errors.serverError(res, "Couldn't get the number of human games") + if err? then return errors.serverError(res, 'Couldn\'t get the number of human games') unless numberOfHumans - res.send(204, "No games to score.") + res.send(204, 'No games to score.') return res.end() humanSkipCount = Math.floor(Math.random() * numberOfHumans) ogreCountParams = - "levelID": "greed" - "submitted":true - "team":"ogres" + 'levelID': 'greed' + 'submitted': true + 'team': 'ogres' LevelSession.count ogreCountParams, (err, numberOfOgres) => - if err? then return errors.serverError(res, "Couldnt' get the number of ogre games") + if err? then return errors.serverError(res, 'Couldn\'t get the number of ogre games') unless numberOfOgres - res.send(204, "No games to score.") + res.send(204, 'No games to score.') return res.end() ogresSkipCount = Math.floor(Math.random() * numberOfOgres) @@ -157,70 +154,70 @@ module.exports.getTwoGames = (req, res) -> .aggregate() .match(queryParams) .project(selection) - .sort({"submitDate": -1}) + .sort({'submitDate': -1}) .skip(humanSkipCount) .limit(1) query.exec (err, randomSession) => if err? then return errors.serverError(res, "Couldn't select a random session! #{err}") randomSession = randomSession[0] queryParams = - "levelID":"greed" - "submitted":true - "team": "ogres" + 'levelID': 'greed' + 'submitted': true + 'team': 'ogres' query = LevelSession .aggregate() .match(queryParams) .project(selection) - .sort({"submitDate": -1}) + .sort({'submitDate': -1}) .skip(ogresSkipCount) .limit(1) query.exec (err, otherSession) => - if err? then return errors.serverError(res, "Couldnt' select the other random session!") + if err? then return errors.serverError(res, 'Couldn\'t select the other random session!') otherSession = otherSession[0] taskObject = - "messageGenerated": Date.now() - "sessions": [] + 'messageGenerated': Date.now() + 'sessions': [] for session in [randomSession, otherSession] sessionInformation = - "sessionID": session._id - "team": session.team ? "No team" - "transpiledCode": session.transpiledCode - "submittedCodeLanguage": session.submittedCodeLanguage - "teamSpells": session.teamSpells ? {} - "levelID": session.levelID - "creatorName": session.creatorName - "creator": session.creator - "totalScore": session.totalScore + 'sessionID': session._id + 'team': session.team ? 'No team' + 'transpiledCode': session.transpiledCode + 'submittedCodeLanguage': session.submittedCodeLanguage + 'teamSpells': session.teamSpells ? {} + 'levelID': session.levelID + 'creatorName': session.creatorName + 'creator': session.creator + 'totalScore': session.totalScore taskObject.sessions.push sessionInformation - console.log "Dispatching random game between", taskObject.sessions[0].creatorName, "and", taskObject.sessions[1].creatorName + console.log 'Dispatching random game between', taskObject.sessions[0].creatorName, 'and', taskObject.sessions[1].creatorName sendResponseObject req, res, taskObject else console.log "Directly simulating #{humansGameID} vs. #{ogresGameID}." LevelSession.findOne(_id: humansGameID).select(selection).lean().exec (err, humanSession) => - if err? then return errors.serverError(res, "Couldn't find the human game") + if err? then return errors.serverError(res, 'Couldn\'t find the human game') LevelSession.findOne(_id: ogresGameID).select(selection).lean().exec (err, ogreSession) => - if err? then return errors.serverError(res, "Couldn't find the ogre game") + if err? then return errors.serverError(res, 'Couldn\'t find the ogre game') taskObject = - "messageGenerated": Date.now() - "sessions": [] + 'messageGenerated': Date.now() + 'sessions': [] for session in [humanSession, ogreSession] sessionInformation = - "sessionID": session._id - "team": session.team ? "No team" - "transpiledCode": session.transpiledCode - "submittedCodeLanguage": session.submittedCodeLanguage - "teamSpells": session.teamSpells ? {} - "levelID": session.levelID - "creatorName": session.creatorName - "creator": session.creator - "totalScore": session.totalScore + 'sessionID': session._id + 'team': session.team ? 'No team' + 'transpiledCode': session.transpiledCode + 'submittedCodeLanguage': session.submittedCodeLanguage + 'teamSpells': session.teamSpells ? {} + 'levelID': session.levelID + 'creatorName': session.creatorName + 'creator': session.creator + 'totalScore': session.totalScore taskObject.sessions.push sessionInformation sendResponseObject req, res, taskObject module.exports.recordTwoGames = (req, res) -> sessions = req.body.sessions - console.log "Recording non-chained result of", sessions?[0]?.name, sessions[0]?.metrics?.rank, "and", sessions?[1]?.name, sessions?[1]?.metrics?.rank + console.log 'Recording non-chained result of', sessions?[0]?.name, sessions[0]?.metrics?.rank, 'and', sessions?[1]?.name, sessions?[1]?.metrics?.rank yetiGuru = clientResponseObject: req.body, isRandomMatch: true async.waterfall [ @@ -231,9 +228,7 @@ module.exports.recordTwoGames = (req, res) -> updateUserSimulationCounts.bind(yetiGuru, req.user._id) ], (err, successMessageObject) -> if err? then return errors.serverError res, "There was an error recording the single game:#{err}" - sendResponseObject req, res, {"message":"The single game was submitted successfully!"} - - + sendResponseObject req, res, {'message': 'The single game was submitted successfully!'} module.exports.createNewTask = (req, res) -> requestSessionID = req.body.session @@ -244,8 +239,8 @@ module.exports.createNewTask = (req, res) -> yetiGuru = {} async.waterfall [ - validatePermissions.bind(yetiGuru,req,requestSessionID) - fetchAndVerifyLevelType.bind(yetiGuru,currentLevelID) + validatePermissions.bind(yetiGuru, req, requestSessionID) + fetchAndVerifyLevelType.bind(yetiGuru, currentLevelID) fetchSessionObjectToSubmit.bind(yetiGuru, requestSessionID) updateSessionToSubmit.bind(yetiGuru, transpiledCode) fetchInitialSessionsToRankAgainst.bind(yetiGuru, requestLevelMajorVersion, originalLevelID) @@ -254,9 +249,8 @@ module.exports.createNewTask = (req, res) -> if err? then return errors.serverError res, "There was an error submitting the game to the queue:#{err}" sendResponseObject req, res, successMessageObject - -validatePermissions = (req,sessionID, callback) -> - if isUserAnonymous req then return callback "You are unauthorized to submit that game to the simulator" +validatePermissions = (req, sessionID, callback) -> + if isUserAnonymous req then return callback 'You are unauthorized to submit that game to the simulator' if isUserAdmin req then return callback null findParameters = @@ -271,7 +265,7 @@ validatePermissions = (req,sessionID, callback) -> if err? then return callback err userHasPermissionToSubmitCode = retrievedSession.creator is req.user?.id and not _.isEqual(retrievedSession.code, retrievedSession.submittedCode) - unless userHasPermissionToSubmitCode then return callback "You are unauthorized to submit that game to the simulator" + unless userHasPermissionToSubmitCode then return callback 'You are unauthorized to submit that game to the simulator' callback null fetchAndVerifyLevelType = (levelID, cb) -> @@ -285,7 +279,7 @@ fetchAndVerifyLevelType = (levelID, cb) -> .lean() query.exec (err, levelWithType) -> if err? then return cb err - if not levelWithType.type or levelWithType.type isnt "ladder" then return cb "Level isn't of type 'ladder'" + if not levelWithType.type or levelWithType.type isnt 'ladder' then return cb 'Level isn\'t of type "ladder"' cb null fetchSessionObjectToSubmit = (sessionID, callback) -> @@ -319,8 +313,8 @@ fetchInitialSessionsToRankAgainst = (levelMajorVersion, levelID, submittedSessio opposingTeam = calculateOpposingTeam(submittedSession.team) findParameters = - "level.original": levelID - "level.majorVersion": levelMajorVersion + 'level.original': levelID + 'level.majorVersion': levelMajorVersion submitted: true submittedCode: $exists: true @@ -339,20 +333,18 @@ fetchInitialSessionsToRankAgainst = (levelMajorVersion, levelID, submittedSessio query.exec (err, sessionToRankAgainst) -> callback err, sessionToRankAgainst, submittedSession - -generateAndSendTaskPairsToTheQueue = (sessionToRankAgainst,submittedSession, callback) -> +generateAndSendTaskPairsToTheQueue = (sessionToRankAgainst, submittedSession, callback) -> taskPairs = generateTaskPairs(sessionToRankAgainst, submittedSession) sendEachTaskPairToTheQueue taskPairs, (taskPairError) -> if taskPairError? then return callback taskPairError - #console.log "Sent task pairs to the queue!" + #console.log 'Sent task pairs to the queue!' #console.log taskPairs - callback null, {"message": "All task pairs were succesfully sent to the queue"} - + callback null, {'message': 'All task pairs were succesfully sent to the queue'} module.exports.dispatchTaskToConsumer = (req, res) -> yetiGuru = {} async.waterfall [ - checkSimulationPermissions.bind(yetiGuru,req) + checkSimulationPermissions.bind(yetiGuru, req) receiveMessageFromSimulationQueue changeMessageVisibilityTimeout parseTaskQueueMessage @@ -361,33 +353,31 @@ module.exports.dispatchTaskToConsumer = (req, res) -> processTaskObject ], (err, taskObjectToSend) -> if err? - if typeof err is "string" and err.indexOf "No more games in the queue" isnt -1 - res.send(204, "No games to score.") + if typeof err is 'string' and err.indexOf 'No more games in the queue' isnt -1 + res.send(204, 'No games to score.') return res.end() else return errors.serverError res, "There was an error dispatching the task: #{err}" sendResponseObject req, res, taskObjectToSend - - checkSimulationPermissions = (req, cb) -> if isUserAnonymous req - cb "You need to be logged in to simulate games" + cb 'You need to be logged in to simulate games' else cb null receiveMessageFromSimulationQueue = (cb) -> scoringTaskQueue.receiveMessage (err, message) -> if err? then return cb "No more games in the queue, error:#{err}" - if messageIsInvalid(message) then return cb "Message received from queue is invalid" + if messageIsInvalid(message) then return cb 'Message received from queue is invalid' cb null, message changeMessageVisibilityTimeout = (message, cb) -> message.changeMessageVisibilityTimeout scoringTaskTimeoutInSeconds, (err) -> cb err, message -parseTaskQueueMessage = (message,cb) -> +parseTaskQueueMessage = (message, cb) -> try - if typeof message.getBody() is "object" + if typeof message.getBody() is 'object' messageBody = message.getBody() else messageBody = JSON.parse message.getBody() @@ -400,34 +390,34 @@ constructTaskObject = (taskMessageBody, message, callback) -> if err? then return callback err taskObject = - "messageGenerated": Date.now() - "sessions": [] + 'messageGenerated': Date.now() + 'sessions': [] for session in sessions sessionInformation = - "sessionID": session._id - "submitDate": session.submitDate - "team": session.team ? "No team" - "transpiledCode": session.transpiledCode - "submittedCodeLanguage": session.submittedCodeLanguage - "teamSpells": session.teamSpells ? {} - "levelID": session.levelID - "creator": session.creator - "creatorName":session.creatorName - "totalScore": session.totalScore + 'sessionID': session._id + 'submitDate': session.submitDate + 'team': session.team ? 'No team' + 'transpiledCode': session.transpiledCode + 'submittedCodeLanguage': session.submittedCodeLanguage + 'teamSpells': session.teamSpells ? {} + 'levelID': session.levelID + 'creator': session.creator + 'creatorName': session.creatorName + 'totalScore': session.totalScore taskObject.sessions.push sessionInformation callback null, taskObject, message constructTaskLogObject = (calculatorUserID, taskObject, message, callback) -> taskLogObject = new TaskLog - "createdAt": new Date() - "calculator":calculatorUserID - "sentDate": Date.now() - "messageIdentifierString":message.getReceiptHandle() + 'createdAt': new Date() + 'calculator': calculatorUserID + 'sentDate': Date.now() + 'messageIdentifierString': message.getReceiptHandle() taskLogObject.save (err) -> callback err, taskObject, taskLogObject, message -processTaskObject = (taskObject,taskLogObject, message, cb) -> +processTaskObject = (taskObject, taskLogObject, message, cb) -> taskObject.taskID = taskLogObject._id taskObject.receiptHandle = message.getReceiptHandle() cb null, taskObject @@ -442,16 +432,15 @@ getSessionInformation = (sessionIDString, callback) -> .lean() query.exec (err, session) -> - if err? then return callback err, {"error":"There was an error retrieving the session."} + if err? then return callback err, {'error': 'There was an error retrieving the session.'} callback null, session - module.exports.processTaskResult = (req, res) -> originalSessionID = req.body?.originalSessionID yetiGuru = {} try async.waterfall [ - verifyClientResponse.bind(yetiGuru,req.body) + verifyClientResponse.bind(yetiGuru, req.body) fetchTaskLog.bind(yetiGuru) checkTaskLog.bind(yetiGuru) deleteQueueMessage.bind(yetiGuru) @@ -466,29 +455,29 @@ module.exports.processTaskResult = (req, res) -> findNearestBetterSessionID.bind(yetiGuru) addNewSessionsToQueue.bind(yetiGuru) ], (err, results) -> - if err is "shouldn't continue" + if err is 'shouldn\'t continue' markSessionAsDoneRanking originalSessionID, (err) -> - if err? then return sendResponseObject req, res, {"error":"There was an error marking the session as done ranking"} - sendResponseObject req, res, {"message":"The scores were updated successfully, person lost so no more games are being inserted!"} - else if err is "no session was found" + if err? then return sendResponseObject req, res, {'error': 'There was an error marking the session as done ranking'} + sendResponseObject req, res, {'message': 'The scores were updated successfully, person lost so no more games are being inserted!'} + else if err is 'no session was found' markSessionAsDoneRanking originalSessionID, (err) -> - if err? then return sendResponseObject req, res, {"error":"There was an error marking the session as done ranking"} - sendResponseObject req, res, {"message":"There were no more games to rank (game is at top)!"} + if err? then return sendResponseObject req, res, {'error': 'There was an error marking the session as done ranking'} + sendResponseObject req, res, {'message': 'There were no more games to rank (game is at top)!'} else if err? errors.serverError res, "There was an error:#{err}" else - sendResponseObject req, res, {"message":"The scores were updated successfully and more games were sent to the queue!"} + sendResponseObject req, res, {'message': 'The scores were updated successfully and more games were sent to the queue!'} catch e - errors.serverError res, "There was an error processing the task result!" + errors.serverError res, 'There was an error processing the task result!' verifyClientResponse = (responseObject, callback) -> #TODO: better verification - if typeof responseObject isnt "object" or responseObject?.originalSessionID?.length isnt 24 - callback "The response to that query is required to be a JSON object." + if typeof responseObject isnt 'object' or responseObject?.originalSessionID?.length isnt 24 + callback 'The response to that query is required to be a JSON object.' else @clientResponseObject = responseObject - #log.info "Verified client response!" + #log.info 'Verified client response!' callback null, responseObject fetchTaskLog = (responseObject, callback) -> @@ -496,18 +485,18 @@ fetchTaskLog = (responseObject, callback) -> query.exec (err, taskLog) => return callback new Error("Couldn't find TaskLog for _id #{responseObject.taskID}!") unless taskLog @taskLog = taskLog - #log.info "Fetched task log!" + #log.info 'Fetched task log!' callback err, taskLog.toObject() checkTaskLog = (taskLog, callback) -> - if taskLog.calculationTimeMS then return callback "That computational task has already been performed" - if hasTaskTimedOut taskLog.sentDate then return callback "The task has timed out" - #log.info "Checked task log" + if taskLog.calculationTimeMS then return callback 'That computational task has already been performed' + if hasTaskTimedOut taskLog.sentDate then return callback 'The task has timed out' + #log.info 'Checked task log' callback null deleteQueueMessage = (callback) -> scoringTaskQueue.deleteMessage @clientResponseObject.receiptHandle, (err) -> - #log.info "Deleted queue message" + #log.info 'Deleted queue message' callback err fetchLevelSession = (callback) -> @@ -519,32 +508,31 @@ fetchLevelSession = (callback) -> .lean() query.exec (err, session) => @levelSession = session - #log.info "Fetched level session" + #log.info 'Fetched level session' callback err - checkSubmissionDate = (callback) -> supposedSubmissionDate = new Date(@clientResponseObject.sessions[0].submitDate) if Number(supposedSubmissionDate) isnt Number(@levelSession.submitDate) - callback "The game has been resubmitted. Removing from queue..." + callback 'The game has been resubmitted. Removing from queue...' else - #log.info "Checked submission date" + #log.info 'Checked submission date' callback null logTaskComputation = (callback) -> - @taskLog.set('calculationTimeMS',@clientResponseObject.calculationTimeMS) + @taskLog.set('calculationTimeMS', @clientResponseObject.calculationTimeMS) @taskLog.set('sessions') @taskLog.calculationTimeMS = @clientResponseObject.calculationTimeMS @taskLog.sessions = @clientResponseObject.sessions @taskLog.save (err, saved) -> - #log.info "Logged task computation" + #log.info 'Logged task computation' callback err updateSessions = (callback) -> sessionIDs = _.pluck @clientResponseObject.sessions, 'sessionID' async.map sessionIDs, retrieveOldSessionData, (err, oldScores) => - if err? then callback err, {"error": "There was an error retrieving the old scores"} + if err? then callback err, {'error': 'There was an error retrieving the old scores'} try oldScoreArray = _.toArray putRankingFromMetricsIntoScoreObject @clientResponseObject, oldScores newScoreArray = bayes.updatePlayerSkills oldScoreArray @@ -554,12 +542,12 @@ updateSessions = (callback) -> saveNewScoresToDatabase = (newScoreArray, callback) -> async.eachSeries newScoreArray, updateScoreInSession, (err) -> - #log.info "Saved new scores to database" - callback err,newScoreArray + #log.info 'Saved new scores to database' + callback err, newScoreArray -updateScoreInSession = (scoreObject,callback) -> - LevelSession.findOne {"_id": scoreObject.id}, (err, session) -> +updateScoreInSession = (scoreObject, callback) -> + LevelSession.findOne {'_id': scoreObject.id}, (err, session) -> if err? then return callback err, null session = session.toObject() @@ -571,7 +559,7 @@ updateScoreInSession = (scoreObject,callback) -> totalScore: newTotalScore $push: {scoreHistory: {$each: [scoreHistoryAddition], $slice: -1000}} - LevelSession.update {"_id": scoreObject.id}, updateObject, callback + LevelSession.update {'_id': scoreObject.id}, updateObject, callback #log.info "New total score for session #{scoreObject.id} is #{updateObject.totalScore}" indexNewScoreArray = (newScoreArray, callback) -> @@ -594,10 +582,10 @@ addMatchToSessions = (newScoreObject, callback) -> matchObject.opponents[sessionID].metrics.rank = Number(newScoreObject[sessionID]?.gameRanking ? 0) #log.info "Match object computed, result: #{matchObject}" - #log.info "Writing match object to database..." + #log.info 'Writing match object to database...' #use bind with async to do the writes sessionIDs = _.pluck @clientResponseObject.sessions, 'sessionID' - async.each sessionIDs, updateMatchesInSession.bind(@,matchObject), (err) -> + async.each sessionIDs, updateMatchesInSession.bind(@, matchObject), (err) -> callback err updateMatchesInSession = (matchObject, sessionID, callback) -> @@ -608,18 +596,18 @@ updateMatchesInSession = (matchObject, sessionID, callback) -> opponentsClone = _.omit opponentsClone, sessionID opponentsArray = _.toArray opponentsClone currentMatchObject.opponents = opponentsArray - LevelSession.findOne {"_id": sessionID}, (err, session) -> + LevelSession.findOne {'_id': sessionID}, (err, session) -> session = session.toObject() currentMatchObject.playtime = session.playtime ? 0 sessionUpdateObject = $push: {matches: {$each: [currentMatchObject], $slice: -200}} #log.info "Updating session #{sessionID}" - LevelSession.update {"_id":sessionID}, sessionUpdateObject, callback + LevelSession.update {'_id': sessionID}, sessionUpdateObject, callback -updateUserSimulationCounts = (reqUserID,callback) -> +updateUserSimulationCounts = (reqUserID, callback) -> incrementUserSimulationCount reqUserID, 'simulatedBy', (err) => if err? then return callback err - console.log "Incremented user simulation count!" + console.log 'Incremented user simulation count!' unless @isRandomMatch incrementUserSimulationCount @levelSession.creator, 'simulatedFor', callback else @@ -640,31 +628,30 @@ determineIfSessionShouldContinueAndUpdateLog = (cb) -> _id: sessionID updateParameters = - "$inc": {} + '$inc': {} if sessionRank is 0 - updateParameters["$inc"] = {numberOfWinsAndTies: 1} + updateParameters['$inc'] = {numberOfWinsAndTies: 1} else - updateParameters["$inc"] = {numberOfLosses: 1} + updateParameters['$inc'] = {numberOfLosses: 1} - LevelSession.findOneAndUpdate queryParameters, updateParameters,{select: 'numberOfWinsAndTies numberOfLosses'}, (err, updatedSession) -> + LevelSession.findOneAndUpdate queryParameters, updateParameters, {select: 'numberOfWinsAndTies numberOfLosses'}, (err, updatedSession) -> if err? then return cb err, updatedSession updatedSession = updatedSession.toObject() totalNumberOfGamesPlayed = updatedSession.numberOfWinsAndTies + updatedSession.numberOfLosses if totalNumberOfGamesPlayed < 10 - #console.log "Number of games played is less than 10, continuing..." + #console.log 'Number of games played is less than 10, continuing...' cb null else ratio = (updatedSession.numberOfLosses) / (totalNumberOfGamesPlayed) if ratio > 0.33 - cb "shouldn't continue" + cb 'shouldn\'t continue' console.log "Ratio(#{ratio}) is bad, ending simulation" else #console.log "Ratio(#{ratio}) is good, so continuing simulations" cb null - findNearestBetterSessionID = (cb) -> try levelOriginalID = @levelSession.level.original @@ -685,8 +672,8 @@ findNearestBetterSessionID = (cb) -> $gt: opponentSessionTotalScore _id: $nin: opponentSessionIDs - "level.original": levelOriginalID - "level.majorVersion": levelMajorVersion + 'level.original': levelOriginalID + 'level.majorVersion': levelMajorVersion submitted: true submittedCode: $exists: true @@ -695,7 +682,7 @@ findNearestBetterSessionID = (cb) -> if opponentSessionTotalScore < 30 # Don't play a ton of matches at low scores--skip some in proportion to how close to 30 we are. # TODO: this could be made a lot more flexible. - queryParameters["totalScore"]["$gt"] = opponentSessionTotalScore + 2 * (30 - opponentSessionTotalScore) / 20 + queryParameters['totalScore']['$gt'] = opponentSessionTotalScore + 2 * (30 - opponentSessionTotalScore) / 20 limitNumber = 1 @@ -713,13 +700,12 @@ findNearestBetterSessionID = (cb) -> #console.log "Finding session with score near #{opponentSessionTotalScore}" query.exec (err, session) -> if err? then return cb err, session - unless session then return cb "no session was found" + unless session then return cb 'no session was found' #console.log "Found session with score #{session.totalScore}" cb err, session._id - retrieveAllOpponentSessionIDs = (sessionID, cb) -> - query = LevelSession.findOne({"_id":sessionID}) + query = LevelSession.findOne({'_id': sessionID}) .select('matches.opponents.sessionID matches.date submitDate') .lean() query.exec (err, session) -> @@ -727,13 +713,11 @@ retrieveAllOpponentSessionIDs = (sessionID, cb) -> opponentSessionIDs = (match.opponents[0].sessionID for match in session.matches when match.date > session.submitDate) cb err, opponentSessionIDs - calculateOpposingTeam = (sessionTeam) -> - teams = ['ogres','humans'] + teams = ['ogres', 'humans'] opposingTeams = _.pull teams, sessionTeam return opposingTeams[0] - addNewSessionsToQueue = (sessionID, callback) -> sessions = [@clientResponseObject.originalSessionID, sessionID] addPairwiseTaskToQueue sessions, callback @@ -747,15 +731,15 @@ generateTaskPairs = (submittedSessions, sessionToScore) -> for session in submittedSessions if session.toObject? session = session.toObject() - teams = ['ogres','humans'] + teams = ['ogres', 'humans'] opposingTeams = _.pull teams, sessionToScore.team if String(session._id) isnt String(sessionToScore._id) and session.team in opposingTeams - #console.log "Adding game to taskPairs!" - taskPairs.push [sessionToScore._id,String session._id] + #console.log 'Adding game to taskPairs!' + taskPairs.push [sessionToScore._id, String session._id] return taskPairs sendTaskPairToQueue = (taskPair, callback) -> - scoringTaskQueue.sendMessage {sessions: taskPair}, 5, (err,data) -> callback? err,data + scoringTaskQueue.sendMessage {sessions: taskPair}, 5, (err, data) -> callback? err, data getUserIDFromRequest = (req) -> if req.user? then return req.user._id else return null @@ -763,14 +747,14 @@ isUserAnonymous = (req) -> if req.user? then return req.user.get('anonymous') el isUserAdmin = (req) -> return Boolean(req.user?.isAdmin()) -sendResponseObject = (req,res,object) -> +sendResponseObject = (req, res, object) -> res.setHeader('Content-Type', 'application/json') res.send(object) res.end() hasTaskTimedOut = (taskSentTimestamp) -> taskSentTimestamp + scoringTaskTimeoutInSeconds * 1000 < Date.now() -handleTimedOutTask = (req, res, taskBody) -> errors.clientTimeout res, "The results weren't provided within the timeout" +handleTimedOutTask = (req, res, taskBody) -> errors.clientTimeout res, 'The results weren\'t provided within the timeout' putRankingFromMetricsIntoScoreObject = (taskObject, scoreObject) -> scoreObject = _.indexBy scoreObject, 'id' @@ -778,17 +762,17 @@ putRankingFromMetricsIntoScoreObject = (taskObject, scoreObject) -> return scoreObject retrieveOldSessionData = (sessionID, callback) -> - LevelSession.findOne {"_id":sessionID}, (err, session) -> - return callback err, {"error":"There was an error retrieving the session."} if err? + LevelSession.findOne {'_id': sessionID}, (err, session) -> + return callback err, {'error': 'There was an error retrieving the session.'} if err? session = session.toObject() oldScoreObject = - "standardDeviation":session.standardDeviation ? 25/3 - "meanStrength":session.meanStrength ? 25 - "totalScore":session.totalScore ? (25 - 1.8*(25/3)) - "id": sessionID + 'standardDeviation': session.standardDeviation ? 25/3 + 'meanStrength': session.meanStrength ? 25 + 'totalScore': session.totalScore ? (25 - 1.8*(25/3)) + 'id': sessionID callback err, oldScoreObject markSessionAsDoneRanking = (sessionID, cb) -> - #console.log "Marking session as done ranking..." - LevelSession.update {"_id":sessionID}, {"isRanking":false}, cb + #console.log 'Marking session as done ranking...' + LevelSession.update {'_id': sessionID}, {'isRanking': false}, cb diff --git a/server/queues/task/ScoringTask.coffee b/server/queues/task/ScoringTask.coffee index c5147bbef..b6dcf27d9 100644 --- a/server/queues/task/ScoringTask.coffee +++ b/server/queues/task/ScoringTask.coffee @@ -1,8 +1,8 @@ -mongoose = require('mongoose') +mongoose = require 'mongoose' ScoringTaskSchema = new mongoose.Schema( createdAt: {type: Date, expires: 3600} #expire document 1 hour after they are created - calculator: {type:mongoose.Schema.Types.ObjectId} + calculator: {type: mongoose.Schema.Types.ObjectId} sentDate: {type: Number} messageIdentifierString: {type: String} calculationTimeMS: {type: Number, default: 0} diff --git a/server/routes/admin.coffee b/server/routes/admin.coffee index c2ae7612a..c15b3cc05 100644 --- a/server/routes/admin.coffee +++ b/server/routes/admin.coffee @@ -2,7 +2,7 @@ log = require 'winston' errors = require '../commons/errors' handlers = require('../commons/mapping').handlers -mongoose = require('mongoose') +mongoose = require 'mongoose' module.exports.setup = (app) -> app.post '/admin/*', (req, res) -> diff --git a/server/routes/auth.coffee b/server/routes/auth.coffee index 8e99682be..5c3298f44 100644 --- a/server/routes/auth.coffee +++ b/server/routes/auth.coffee @@ -1,7 +1,7 @@ -authentication = require('passport') +authentication = require 'passport' LocalStrategy = require('passport-local').Strategy -User = require('../users/User') -UserHandler = require('../users/user_handler') +User = require '../users/User' +UserHandler = require '../users/user_handler' LevelSession = require '../levels/sessions/LevelSession' config = require '../../server_config' errors = require '../commons/errors' @@ -15,9 +15,9 @@ module.exports.setup = (app) -> authentication.use(new LocalStrategy( (username, password, done) -> - User.findOne({emailLower:username.toLowerCase()}).exec((err, user) -> + User.findOne({emailLower: username.toLowerCase()}).exec((err, user) -> return done(err) if err - return done(null, false, {message:'not found', property:'email'}) if not user + return done(null, false, {message: 'not found', property: 'email'}) if not user passwordReset = (user.get('passwordReset') or '').toLowerCase() if passwordReset and password.toLowerCase() is passwordReset User.update {_id: user.get('_id')}, {passwordReset: ''}, {}, -> @@ -25,39 +25,40 @@ module.exports.setup = (app) -> hash = User.hashPassword(password) unless user.get('passwordHash') is hash - return done(null, false, {message:'is wrong.', property:'password'}) + return done(null, false, {message: 'is wrong.', property: 'password'}) return done(null, user) ) )) + app.post '/auth/spy', (req, res, next) -> if req?.user?.isAdmin() username = req.body.usernameLower emailLower = req.body.emailLower if emailLower - query = {"emailLower":emailLower} + query = {'emailLower': emailLower} else if username - query = {"nameLower":username} + query = {'nameLower': username} else - return errors.badInput res, "You need to supply one of emailLower or username" + return errors.badInput res, 'You need to supply one of emailLower or username' User.findOne query, (err, user) -> - if err? then return errors.serverError res, "There was an error finding the specified user" + if err? then return errors.serverError res, 'There was an error finding the specified user' - unless user then return errors.badInput res, "The specified user couldn't be found" + unless user then return errors.badInput res, 'The specified user couldn\'t be found' req.logIn user, (err) -> - if err? then return errors.serverError res, "There was an error logging in with the specified" + if err? then return errors.serverError res, 'There was an error logging in with the specified' res.send(UserHandler.formatEntity(req, user)) return res.end() else - return errors.unauthorized res, "You must be an admin to enter espionage mode" + return errors.unauthorized res, 'You must be an admin to enter espionage mode' app.post('/auth/login', (req, res, next) -> authentication.authenticate('local', (err, user, info) -> return next(err) if err if not user - return errors.unauthorized(res, [{message:info.message, property:info.property}]) + return errors.unauthorized(res, [{message: info.message, property: info.property}]) req.logIn(user, (err) -> return next(err) if (err) @@ -92,13 +93,13 @@ module.exports.setup = (app) -> app.post('/auth/reset', (req, res) -> unless req.body.email - return errors.badInput(res, [{message:'Need an email specified.', property:'email'}]) + return errors.badInput(res, [{message: 'Need an email specified.', property: 'email'}]) - User.findOne({emailLower:req.body.email.toLowerCase()}).exec((err, user) -> + User.findOne({emailLower: req.body.email.toLowerCase()}).exec((err, user) -> if not user - return errors.notFound(res, [{message:'not found.', property:'email'}]) + return errors.notFound(res, [{message: 'not found.', property: 'email'}]) - user.set('passwordReset', Math.random().toString(36).slice(2,7).toUpperCase()) + user.set('passwordReset', Math.random().toString(36).slice(2, 7).toUpperCase()) user.save (err) => return errors.serverError(res) if err if config.isProduction @@ -131,7 +132,7 @@ module.exports.setup = (app) -> res.send "Unsubscribed #{req.query.email} from CodeCombat emails for #{session.levelName} #{session.team} ladder updates. Sorry to see you go!

Ladder preferences

" res.end() - User.findOne({emailLower:req.query.email.toLowerCase()}).exec (err, user) -> + User.findOne({emailLower: req.query.email.toLowerCase()}).exec (err, user) -> if not user return errors.notFound res, "No user found with email '#{req.query.email}'" @@ -153,7 +154,7 @@ module.exports.setup = (app) -> user.update {$set: {emails: emails}}, {}, => return errors.serverError res, 'Database failure.' if err - res.send msg + "

Account settings

" + res.send msg + '

Account settings

' res.end() module.exports.loginUser = loginUser = (req, res, user, send=true, next=null) -> @@ -172,7 +173,7 @@ module.exports.loginUser = loginUser = (req, res, user, send=true, next=null) -> ) module.exports.makeNewUser = makeNewUser = (req) -> - user = new User({anonymous:true}) + user = new User({anonymous: true}) user.set 'testGroupNumber', Math.floor(Math.random() * 256) # also in app/lib/auth user.set 'preferredLanguage', languages.languageCodeFromAcceptedLanguages req.acceptedLanguages @@ -182,5 +183,5 @@ createMailOptions = (receiver, password) -> from: config.mail.username to: receiver replyTo: config.mail.username - subject: "[CodeCombat] Password Reset" + subject: '[CodeCombat] Password Reset' text: "You can log into your account with: #{password}" diff --git a/server/routes/base.coffee b/server/routes/base.coffee index 5c7dd9f54..0881a7f83 100644 --- a/server/routes/base.coffee +++ b/server/routes/base.coffee @@ -6,4 +6,4 @@ module.exports.setup = (app) -> do (route) -> module = require('../'+route) module.setup app - log.debug "route module #{route} setup" \ No newline at end of file + log.debug "route module #{route} setup" diff --git a/server/routes/contact.coffee b/server/routes/contact.coffee index ec2a76325..7f4991e19 100644 --- a/server/routes/contact.coffee +++ b/server/routes/contact.coffee @@ -35,4 +35,4 @@ createMailOptions = (sender, message, user, recipientID, subject, done) -> options.to = document.get('email') done options else - done options \ No newline at end of file + done options diff --git a/server/routes/db.coffee b/server/routes/db.coffee index cddc70592..5b4ae3b17 100644 --- a/server/routes/db.coffee +++ b/server/routes/db.coffee @@ -6,7 +6,7 @@ mongoose = require 'mongoose' module.exports.setup = (app) -> # This is hacky and should probably get moved somewhere else, I dunno app.get '/db/cla.submissions', (req, res) -> - return errors.unauthorized(res, "You must be an admin to view that information") unless req.user?.isAdmin() + return errors.unauthorized(res, 'You must be an admin to view that information') unless req.user?.isAdmin() res.setHeader('Content-Type', 'application/json') collection = mongoose.connection.db.collection 'cla.submissions', (err, collection) -> return log.error "Couldn't fetch CLA submissions because #{err}" if err diff --git a/server/routes/file.coffee b/server/routes/file.coffee index 8406dd462..681c7715b 100644 --- a/server/routes/file.coffee +++ b/server/routes/file.coffee @@ -1,7 +1,7 @@ Grid = require 'gridfs-stream' fs = require 'fs' request = require 'request' -mongoose = require('mongoose') +mongoose = require 'mongoose' errors = require '../commons/errors' config = require '../../server_config' @@ -11,7 +11,6 @@ module.exports.setup = (app) -> return filePost(req, res) if req.route.method is 'post' return errors.badMethod(res, ['GET', 'POST']) - fileGet = (req, res) -> path = req.path[6..] path = decodeURI path @@ -39,7 +38,7 @@ fileGet = (req, res) -> else Grid.gfs.collection('media').findOne query, (err, filedata) => return errors.notFound(res) if not filedata - readstream = Grid.gfs.createReadStream({_id: filedata._id, root:'media'}) + readstream = Grid.gfs.createReadStream({_id: filedata._id, root: 'media'}) if req.headers['if-modified-since'] is filedata.uploadDate res.status(304) return res.end() @@ -107,11 +106,11 @@ savePNG = (req, res) -> writestream = Grid.gfs.createWriteStream(options) img = new Buffer(req.body.b64png, 'base64') streamBuffers = require 'stream-buffers' - myReadableStreamBuffer = new streamBuffers.ReadableStreamBuffer({frequency: 10,chunkSize: 2048}) + myReadableStreamBuffer = new streamBuffers.ReadableStreamBuffer({frequency: 10, chunkSize: 2048}) myReadableStreamBuffer.put(img) myReadableStreamBuffer.pipe(writestream) handleStreamEnd(res, writestream) - + userCanEditFile = (user=null, file=null) -> # no user means 'anyone'. No file means 'any file' return false unless user @@ -128,7 +127,7 @@ checkExistence = (options, req, res, force, done) -> Grid.gfs.collection('media').find(q).toArray (err, files) -> file = files[0] if file and ((not userCanEditFile(req.user, file) or (not force))) - errors.conflict(res, {canForce:userCanEditFile(req.user, file)}) + errors.conflict(res, {canForce: userCanEditFile(req.user, file)}) done(true) else if file fullPath = "/file/#{options.metadata.path}/#{options.filename}" @@ -185,7 +184,7 @@ clearCloudFlareCacheForFile = (path='/file') -> r = request.post 'https://www.cloudflare.com/api_json.html', (err, httpResponse, body) -> if (err) console.error('CloudFlare file cache clear failed:', body) - + form = r.form() form.append 'tkn', config.cloudflare.token form.append 'email', 'scott@codecombat.com' diff --git a/server/routes/folder.coffee b/server/routes/folder.coffee index d63701605..f30d2e49f 100644 --- a/server/routes/folder.coffee +++ b/server/routes/folder.coffee @@ -1,4 +1,4 @@ -mongoose = require('mongoose') +mongoose = require 'mongoose' errors = require '../commons/errors' module.exports.setup = (app) -> @@ -11,7 +11,7 @@ folderGet = (req, res) -> userfolder = "/user-#{req.user.id}/" folder = userfolder if folder is '/me/' return errors.forbidden(res) unless (folder is userfolder) or (req.user.isAdmin()) - + mongoose.connection.db.collection 'media.files', (errors, collection) -> collection.find({'metadata.path': folder}).toArray (err, results) -> res.send(results) diff --git a/server/routes/mail.coffee b/server/routes/mail.coffee index 48ae46660..f5885a38a 100644 --- a/server/routes/mail.coffee +++ b/server/routes/mail.coffee @@ -22,13 +22,13 @@ getAllLadderScores = (next) -> .lean() query.exec (err, levels) -> if err - log.error "Couldn't fetch ladder levels. Error: ", err + log.error 'Couldn\'t fetch ladder levels. Error: ', err return next [] for level in levels for team in ['humans', 'ogres'] 'I ... am not doing this.' # Query to get sessions to make histogram - # db.level.sessions.find({"submitted":true,"levelID":"brawlwood",team:"ogres"},{"_id":0,"totalScore":1}) + # db.level.sessions.find({'submitted': true, 'levelID': 'brawlwood', team: 'ogres'}, {'_id': 0, 'totalScore': 1}) DEBUGGING = false LADDER_PREGAME_INTERVAL = 2 * 3600 * 1000 # Send emails two hours before players last submitted. @@ -36,17 +36,17 @@ getTimeFromDaysAgo = (now, daysAgo) -> t = now - 86400 * 1000 * daysAgo - LADDER_PREGAME_INTERVAL isRequestFromDesignatedCronHandler = (req, res) -> - requestIP = req.headers['x-forwarded-for']?.replace(" ","").split(",")[0] + requestIP = req.headers['x-forwarded-for']?.replace(' ', '').split(',')[0] if requestIP isnt config.mail.cronHandlerPublicIP and requestIP isnt config.mail.cronHandlerPrivateIP console.log "RECEIVED REQUEST FROM IP #{requestIP}(headers indicate #{req.headers['x-forwarded-for']}" - console.log "UNAUTHORIZED ATTEMPT TO SEND TRANSACTIONAL LADDER EMAIL THROUGH CRON MAIL HANDLER" - res.send("You aren't authorized to perform that action. Only the specified Cron handler may perform that action.") + console.log 'UNAUTHORIZED ATTEMPT TO SEND TRANSACTIONAL LADDER EMAIL THROUGH CRON MAIL HANDLER' + res.send('You aren\'t authorized to perform that action. Only the specified Cron handler may perform that action.') res.end() return false return true handleLadderUpdate = (req, res) -> - log.info("Going to see about sending ladder update emails.") + log.info('Going to see about sending ladder update emails.') requestIsFromDesignatedCronHandler = isRequestFromDesignatedCronHandler req, res return unless requestIsFromDesignatedCronHandler or DEBUGGING @@ -63,7 +63,7 @@ handleLadderUpdate = (req, res) -> endTime = startTime + 15 * 60 * 1000 # Debugging: make sure there's something to send findParameters = {submitted: true, submitDate: {$gt: new Date(startTime), $lte: new Date(endTime)}} # TODO: think about putting screenshots in the email - selectString = "creator team levelName levelID totalScore matches submitted submitDate scoreHistory" + selectString = 'creator team levelName levelID totalScore matches submitted submitDate scoreHistory' query = LevelSession.find(findParameters) .select(selectString) .lean() @@ -76,7 +76,7 @@ handleLadderUpdate = (req, res) -> sendLadderUpdateEmail result, now, daysAgo for result in results sendLadderUpdateEmail = (session, now, daysAgo) -> - User.findOne({_id: session.creator}).select("name email firstName lastName emailSubscriptions emails preferredLanguage").exec (err, user) -> + User.findOne({_id: session.creator}).select('name email firstName lastName emailSubscriptions emails preferredLanguage').exec (err, user) -> if err log.error "Couldn't find user for #{session.creator} from session #{session._id}" return @@ -88,7 +88,7 @@ sendLadderUpdateEmail = (session, now, daysAgo) -> log.info "Not sending email to #{user.get('email')} #{user.get('name')} because the session had no levelName in it." return name = if user.get('firstName') and user.get('lastName') then "#{user.get('firstName')}" else user.get('name') - name = "Wizard" if not name or name is "Anoner" + name = 'Wizard' if not name or name is 'Anoner' # Fetch the most recent defeat and victory, if there are any. # (We could look at strongest/weakest, but we'd have to fetch everyone, or denormalize more.) @@ -135,22 +135,22 @@ sendLadderUpdateEmail = (session, now, daysAgo) -> if err log.error "Couldn't find defeateded opponent: #{err}" defeatedOpponent = null - victoryContext = {opponent_name: defeatedOpponent?.name ? "Anoner", url: urlForMatch(victory)} if victory + victoryContext = {opponent_name: defeatedOpponent?.name ? 'Anoner', url: urlForMatch(victory)} if victory onFetchedVictoriousOpponent = (err, victoriousOpponent) -> if err log.error "Couldn't find victorious opponent: #{err}" victoriousOpponent = null - defeatContext = {opponent_name: victoriousOpponent?.name ? "Anoner", url: urlForMatch(defeat)} if defeat + defeatContext = {opponent_name: victoriousOpponent?.name ? 'Anoner', url: urlForMatch(defeat)} if defeat sendEmail defeatContext, victoryContext if defeat - User.findOne({_id: defeat.opponents[0].userID}).select("name").lean().exec onFetchedVictoriousOpponent + User.findOne({_id: defeat.opponents[0].userID}).select('name').lean().exec onFetchedVictoriousOpponent else onFetchedVictoriousOpponent null, null if victory - User.findOne({_id: victory.opponents[0].userID}).select("name").lean().exec onFetchedDefeatedOpponent + User.findOne({_id: victory.opponents[0].userID}).select('name').lean().exec onFetchedDefeatedOpponent else onFetchedDefeatedOpponent null, null @@ -184,7 +184,7 @@ handleMailchimpWebHook = (req, res) -> res.send 'No email provided' return res.end() - query = {'mailChimp.leid':post.data.web_id} + query = {'mailChimp.leid': post.data.web_id} User.findOne query, (err, user) -> return errors.serverError(res) if err if not user diff --git a/server/routes/queue.coffee b/server/routes/queue.coffee index e69ae720e..169b71371 100644 --- a/server/routes/queue.coffee +++ b/server/routes/queue.coffee @@ -2,30 +2,29 @@ log = require 'winston' errors = require '../commons/errors' scoringQueue = require '../queues/scoring' - module.exports.setup = (app) -> scoringQueue.setup() #app.post '/queue/scoring/pairwise', (req, res) -> # handler = loadQueueHandler 'scoring' # handler.addPairwiseTaskToQueue req, res - + app.get '/queue/messagesInQueueCount', (req, res) -> handler = loadQueueHandler 'scoring' handler.messagesInQueueCount req, res - + app.post '/queue/scoring/resimulateAllSessions', (req, res) -> handler = loadQueueHandler 'scoring' handler.resimulateAllSessions req, res - + app.post '/queue/scoring/getTwoGames', (req, res) -> handler = loadQueueHandler 'scoring' - handler.getTwoGames req, res - + handler.getTwoGames req, res + app.put '/queue/scoring/recordTwoGames', (req, res) -> handler = loadQueueHandler 'scoring' handler.recordTwoGames req, res - + app.all '/queue/*', (req, res) -> setResponseHeaderToJSONContentType res @@ -33,9 +32,9 @@ module.exports.setup = (app) -> try handler = loadQueueHandler queueName if isHTTPMethodGet req - handler.dispatchTaskToConsumer req,res + handler.dispatchTaskToConsumer req, res else if isHTTPMethodPut req - handler.processTaskResult req,res + handler.processTaskResult req, res else if isHTTPMethodPost req handler.createNewTask req, res #TODO: do not use this in production else @@ -43,7 +42,6 @@ module.exports.setup = (app) -> catch error log.error error sendQueueError req, res, error - setResponseHeaderToJSONContentType = (res) -> res.setHeader('Content-Type', 'application/json') @@ -56,16 +54,12 @@ getQueueNameFromPath = (path) -> loadQueueHandler = (queueName) -> require ('../queues/' + queueName) - isHTTPMethodGet = (req) -> return req.route.method is 'get' isHTTPMethodPost = (req) -> return req.route.method is 'post' isHTTPMethodPut = (req) -> return req.route.method is 'put' +sendMethodNotSupportedError = (req, res) -> errors.badMethod(res, ['GET', 'POST', 'PUT'], 'Queues do not support the HTTP method used.' ) -sendMethodNotSupportedError = (req, res) -> errors.badMethod(res, ['GET', 'POST', 'PUT'], "Queues do not support the HTTP method used." ) - -sendQueueError = (req,res, error) -> errors.serverError(res, "Route #{req.path} had a problem: #{error}") - - +sendQueueError = (req, res, error) -> errors.serverError(res, "Route #{req.path} had a problem: #{error}") diff --git a/server/routes/stacklead.coffee b/server/routes/stacklead.coffee index ffa5f3617..705a7bf7d 100644 --- a/server/routes/stacklead.coffee +++ b/server/routes/stacklead.coffee @@ -28,5 +28,5 @@ module.exports.sendStackLead = sendStackLead = (email, user) -> form.last_name = data.lastName if data.lastName form.linkedin = data.publicProfileUrl if data.publicProfileUrl data.company = company if company = data.positions?.values?[0]?.company?.name - request.post {uri: "https://stacklead.com/api/leads", form: form}, (err, res, body) -> - return log.error "Error sending StackLead request:", err or body if err or /error/.test body + request.post {uri: 'https://stacklead.com/api/leads', form: form}, (err, res, body) -> + return log.error 'Error sending StackLead request:', err or body if err or /error/.test body diff --git a/server/users/User.coffee b/server/users/User.coffee index 40d662913..421335a21 100644 --- a/server/users/User.coffee +++ b/server/users/User.coffee @@ -1,7 +1,7 @@ -mongoose = require('mongoose') -jsonschema = require('../../app/schemas/models/user') -crypto = require('crypto') -{salt, isProduction} = require('../../server_config') +mongoose = require 'mongoose' +jsonschema = require '../../app/schemas/models/user' +crypto = require 'crypto' +{salt, isProduction} = require '../../server_config' mail = require '../commons/mail' log = require 'winston' @@ -90,8 +90,8 @@ UserSchema.statics.updateMailChimp = (doc, callback) -> params = {} params.id = mail.MAILCHIMP_LIST_ID - params.email = if existingProps then {leid:existingProps.leid} else {email:doc.get('email')} - params.merge_vars = { groupings: [ {id: mail.MAILCHIMP_GROUP_ID, groups: newGroups} ] } + params.email = if existingProps then {leid: existingProps.leid} else {email: doc.get('email')} + params.merge_vars = {groupings: [{id: mail.MAILCHIMP_GROUP_ID, groups: newGroups}]} params.update_existing = true params.double_optin = false @@ -108,7 +108,6 @@ UserSchema.statics.updateMailChimp = (doc, callback) -> mc?.lists.subscribe params, onSuccess, onFailure - UserSchema.pre('save', (next) -> @set('emailLower', @get('email')?.toLowerCase()) @set('nameLower', @get('name')?.toLowerCase()) diff --git a/server/users/remarks/UserRemark.coffee b/server/users/remarks/UserRemark.coffee index 974bc05f3..445340c0b 100644 --- a/server/users/remarks/UserRemark.coffee +++ b/server/users/remarks/UserRemark.coffee @@ -1,6 +1,6 @@ -mongoose = require('mongoose') -plugins = require('../../plugins/plugins') -jsonschema = require('../../../app/schemas/models/user_remark') +mongoose = require 'mongoose' +plugins = require '../../plugins/plugins' +jsonschema = require '../../../app/schemas/models/user_remark' UserRemarkSchema = new mongoose.Schema({ created: diff --git a/server/users/remarks/user_remark_handler.coffee b/server/users/remarks/user_remark_handler.coffee index 8d89b7873..9cc7ff90b 100644 --- a/server/users/remarks/user_remark_handler.coffee +++ b/server/users/remarks/user_remark_handler.coffee @@ -1,5 +1,5 @@ -UserRemark = require('./UserRemark') -Handler = require('../../commons/Handler') +UserRemark = require './UserRemark' +Handler = require '../../commons/Handler' class UserRemarkHandler extends Handler modelClass: UserRemark diff --git a/server/users/user_handler.coffee b/server/users/user_handler.coffee index 0ed4f6a51..ac43fda1c 100644 --- a/server/users/user_handler.coffee +++ b/server/users/user_handler.coffee @@ -8,7 +8,7 @@ config = require '../../server_config' errors = require '../commons/errors' async = require 'async' log = require 'winston' -LevelSession = require('../levels/sessions/LevelSession') +LevelSession = require '../levels/sessions/LevelSession' LevelSessionHandler = require '../levels/sessions/level_session_handler' EarnedAchievement = require '../achievements/EarnedAchievement' UserRemark = require './remarks/UserRemark' @@ -61,7 +61,7 @@ UserHandler = class UserHandler extends Handler log.warn "Error grabbing FB token: #{err}" if err body = JSON.parse(body) emailsMatch = req.body.email is body.email - return callback(res:'Invalid Facebook Access Token.', code:422) unless emailsMatch + return callback(res: 'Invalid Facebook Access Token.', code: 422) unless emailsMatch callback(null, req, user) ) @@ -75,7 +75,7 @@ UserHandler = class UserHandler extends Handler log.warn "Error grabbing G+ token: #{err}" if err body = JSON.parse(body) emailsMatch = req.body.email is body.email - return callback(res:'Invalid G+ Access Token.', code:422) unless emailsMatch + return callback(res: 'Invalid G+ Access Token.', code: 422) unless emailsMatch callback(null, req, user) ) @@ -84,18 +84,18 @@ UserHandler = class UserHandler extends Handler return callback(null, req, user) unless req.body.email? emailLower = req.body.email.toLowerCase() return callback(null, req, user) if emailLower is user.get('emailLower') - User.findOne({emailLower:emailLower}).exec (err, otherUser) -> + User.findOne({emailLower: emailLower}).exec (err, otherUser) -> log.error "Database error setting user email: #{err}" if err - return callback(res:'Database error.', code:500) if err + return callback(res: 'Database error.', code: 500) if err if (req.query.gplusID or req.query.facebookID) and otherUser # special case, log in as that user return req.logIn(otherUser, (err) -> - return callback(res:'Facebook user login error.', code:500) if err + return callback(res: 'Facebook user login error.', code: 500) if err return callback(null, req, otherUser) ) - r = {message:'is already used by another account', property:'email'} - return callback({res:r, code:409}) if otherUser + r = {message: 'is already used by another account', property: 'email'} + return callback({res: r, code: 409}) if otherUser user.set('email', req.body.email) callback(null, req, user) @@ -105,12 +105,12 @@ UserHandler = class UserHandler extends Handler nameLower = req.body.name?.toLowerCase() return callback(null, req, user) unless nameLower return callback(null, req, user) if nameLower is user.get('nameLower') and not user.get('anonymous') - User.findOne({nameLower:nameLower,anonymous:false}).exec (err, otherUser) -> + User.findOne({nameLower: nameLower, anonymous: false}).exec (err, otherUser) -> log.error "Database error setting user name: #{err}" if err - return callback(res:'Database error.', code:500) if err - r = {message:'is already used by another account', property:'name'} + return callback(res: 'Database error.', code: 500) if err + r = {message: 'is already used by another account', property: 'name'} console.log 'Another user exists' if otherUser - return callback({res:r, code:409}) if otherUser + return callback({res: r, code: 409}) if otherUser user.set('name', req.body.name) callback(null, req, user) ] @@ -123,17 +123,17 @@ UserHandler = class UserHandler extends Handler getNamesByIDs: (req, res) -> ids = req.query.ids or req.body.ids returnWizard = req.query.wizard or req.body.wizard - properties = if returnWizard then "name wizard" else "name" + properties = if returnWizard then 'name wizard' else 'name' @getPropertiesFromMultipleDocuments res, User, properties, ids nameToID: (req, res, name) -> - User.findOne({nameLower:unescape(name).toLowerCase(),anonymous:false}).exec (err, otherUser) -> + User.findOne({nameLower: unescape(name).toLowerCase(), anonymous: false}).exec (err, otherUser) -> res.send(if otherUser then otherUser._id else JSON.stringify('')) res.end() getSimulatorLeaderboard: (req, res) -> queryParameters = @getSimulatorLeaderboardQueryParameters(req) - leaderboardQuery = User.find(queryParameters.query).select("name simulatedBy simulatedFor").sort({"simulatedBy":queryParameters.sortOrder}).limit(queryParameters.limit) + leaderboardQuery = User.find(queryParameters.query).select('name simulatedBy simulatedFor').sort({'simulatedBy': queryParameters.sortOrder}).limit(queryParameters.limit) leaderboardQuery.exec (err, otherUsers) -> otherUsers = _.reject otherUsers, _id: req.user._id if req.query.scoreOffset isnt -1 otherUsers ?= [] @@ -155,11 +155,11 @@ UserHandler = class UserHandler extends Handler limit = if req.query.limit > 30 then 30 else req.query.limit if req.query.scoreOffset isnt -1 simulatedByQuery = {} - simulatedByQuery[if req.query.order is 1 then "$gt" else "$lte"] = req.query.scoreOffset + simulatedByQuery[if req.query.order is 1 then '$gt' else '$lte'] = req.query.scoreOffset query.simulatedBy = simulatedByQuery sortOrder = 1 if req.query.order is 1 else - query.simulatedBy = {"$exists": true} + query.simulatedBy = {'$exists': true} {query: query, sortOrder: sortOrder, limit: limit} validateSimulateLeaderboardRequestParameters: (req) -> @@ -182,7 +182,7 @@ UserHandler = class UserHandler extends Handler getByRelationship: (req, res, args...) -> return @agreeToCLA(req, res) if args[1] is 'agreeToCLA' - return @agreeToEmployerAgreement(req,res) if args[1] is 'agreeToEmployerAgreement' + return @agreeToEmployerAgreement(req, res) if args[1] is 'agreeToEmployerAgreement' return @avatar(req, res, args[0]) if args[1] is 'avatar' return @getNamesByIDs(req, res) if args[1] is 'names' return @nameToID(req, res, args[0]) if args[1] is 'nameToID' @@ -213,7 +213,7 @@ UserHandler = class UserHandler extends Handler req.user.set('signedCLA', doc.created) req.user.save (err) => return @sendDatabaseError(res, err) if err - @sendSuccess(res, {result:'success'}) + @sendSuccess(res, {result: 'success'}) avatar: (req, res, id) -> @modelClass.findById(id).exec (err, document) => @@ -282,28 +282,28 @@ UserHandler = class UserHandler extends Handler agreeToEmployerAgreement: (req, res) -> userIsAnonymous = req.user?.get('anonymous') - if userIsAnonymous then return errors.unauthorized(res, "You need to be logged in to agree to the employer agreeement.") + if userIsAnonymous then return errors.unauthorized(res, 'You need to be logged in to agree to the employer agreeement.') profileData = req.body #TODO: refactor this bit to make it more elegant if not profileData.id or not profileData.positions or not profileData.emailAddress or not profileData.firstName or not profileData.lastName - return errors.badInput(res, "You need to have a more complete profile to sign up for this service.") + return errors.badInput(res, 'You need to have a more complete profile to sign up for this service.') @modelClass.findById(req.user.id).exec (err, user) => - if user.get('employerAt') or user.get('signedEmployerAgreement') or "employer" in user.get('permissions') - return errors.conflict(res, "You already have signed the agreement!") + if user.get('employerAt') or user.get('signedEmployerAgreement') or 'employer' in user.get('permissions') + return errors.conflict(res, 'You already have signed the agreement!') #TODO: Search for the current position - employerAt = _.filter(profileData.positions.values,"isCurrent")[0]?.company.name ? "Not available" + employerAt = _.filter(profileData.positions.values, 'isCurrent')[0]?.company.name ? 'Not available' signedEmployerAgreement = linkedinID: profileData.id date: new Date() data: profileData updateObject = - "employerAt": employerAt - "signedEmployerAgreement": signedEmployerAgreement - $push: "permissions":'employer' + 'employerAt': employerAt + 'signedEmployerAgreement': signedEmployerAgreement + $push: 'permissions': 'employer' - User.update {"_id": req.user.id}, updateObject, (err, result) => + User.update {'_id': req.user.id}, updateObject, (err, result) => if err? then return errors.serverError(res, "There was an issue updating the user object to reflect employer status: #{err}") - res.send({"message": "The agreement was successful."}) + res.send({'message': 'The agreement was successful.'}) res.end() getCandidates: (req, res) -> @@ -350,7 +350,7 @@ UserHandler = class UserHandler extends Handler buildGravatarURL: (user, size, fallback) -> emailHash = @buildEmailHash user - fallback ?= "http://codecombat.com/file/db/thang.type/52a00d55cf1818f2be00000b/portrait.png" + fallback ?= 'http://codecombat.com/file/db/thang.type/52a00d55cf1818f2be00000b/portrait.png' fallback = "http://codecombat.com#{fallback}" unless /^http/.test fallback "https://www.gravatar.com/avatar/#{emailHash}?s=#{size}&default=#{fallback}" @@ -375,5 +375,4 @@ UserHandler = class UserHandler extends Handler return @sendNotFoundError res unless remark? @sendSuccess res, remark - module.exports = new UserHandler() diff --git a/server_config.coffee b/server_config.coffee index 7741825cf..6018bf84f 100644 --- a/server_config.coffee +++ b/server_config.coffee @@ -1,6 +1,6 @@ config = {} -config.unittest = process.argv.indexOf("--unittest") > -1 +config.unittest = process.argv.indexOf('--unittest') > -1 config.port = process.env.COCO_PORT or process.env.COCO_NODE_PORT or 3000 config.ssl_port = process.env.COCO_SSL_PORT or process.env.COCO_SSL_NODE_PORT or 3443 @@ -9,42 +9,42 @@ config.cloudflare = config.mongo = port: process.env.COCO_MONGO_PORT or 27017 - host: process.env.COCO_MONGO_HOST or "localhost" - db: process.env.COCO_MONGO_DATABASE_NAME or "coco" - mongoose_replica_string: process.env.COCO_MONGO_MONGOOSE_REPLICA_STRING or "" + host: process.env.COCO_MONGO_HOST or 'localhost' + db: process.env.COCO_MONGO_DATABASE_NAME or 'coco' + mongoose_replica_string: process.env.COCO_MONGO_MONGOOSE_REPLICA_STRING or '' if config.unittest config.port += 1 config.ssl_port += 1 - config.mongo.host = "localhost" + config.mongo.host = 'localhost' else - config.mongo.username = process.env.COCO_MONGO_USERNAME or "" - config.mongo.password = process.env.COCO_MONGO_PASSWORD or "" + config.mongo.username = process.env.COCO_MONGO_USERNAME or '' + config.mongo.password = process.env.COCO_MONGO_PASSWORD or '' config.mail = - service: process.env.COCO_MAIL_SERVICE_NAME or "Zoho" - username: process.env.COCO_MAIL_SERVICE_USERNAME or "" - password: process.env.COCO_MAIL_SERVICE_PASSWORD or "" - mailchimpAPIKey: process.env.COCO_MAILCHIMP_API_KEY or "" - mailchimpWebhook: process.env.COCO_MAILCHIMP_WEBHOOK or "/mail/webhook" - sendwithusAPIKey: process.env.COCO_SENDWITHUS_API_KEY or "" - stackleadAPIKey: process.env.COCO_STACKLEAD_API_KEY or "" - cronHandlerPublicIP: process.env.COCO_CRON_PUBLIC_IP or "" - cronHandlerPrivateIP: process.env.COCO_CRON_PRIVATE_IP or "" + service: process.env.COCO_MAIL_SERVICE_NAME or 'Zoho' + username: process.env.COCO_MAIL_SERVICE_USERNAME or '' + password: process.env.COCO_MAIL_SERVICE_PASSWORD or '' + mailchimpAPIKey: process.env.COCO_MAILCHIMP_API_KEY or '' + mailchimpWebhook: process.env.COCO_MAILCHIMP_WEBHOOK or '/mail/webhook' + sendwithusAPIKey: process.env.COCO_SENDWITHUS_API_KEY or '' + stackleadAPIKey: process.env.COCO_STACKLEAD_API_KEY or '' + cronHandlerPublicIP: process.env.COCO_CRON_PUBLIC_IP or '' + cronHandlerPrivateIP: process.env.COCO_CRON_PRIVATE_IP or '' config.queue = - accessKeyId: process.env.COCO_AWS_ACCESS_KEY_ID or "" - secretAccessKey: process.env.COCO_AWS_SECRET_ACCESS_KEY or "" - region: "us-east-1" - simulationQueueName: "simulationQueue" + accessKeyId: process.env.COCO_AWS_ACCESS_KEY_ID or '' + secretAccessKey: process.env.COCO_AWS_SECRET_ACCESS_KEY or '' + region: 'us-east-1' + simulationQueueName: 'simulationQueue' config.mongoQueue = - queueDatabaseName: "coco_queue" + queueDatabaseName: 'coco_queue' -config.salt = process.env.COCO_SALT or "pepper" -config.cookie_secret = process.env.COCO_COOKIE_SECRET or "chips ahoy" +config.salt = process.env.COCO_SALT or 'pepper' +config.cookie_secret = process.env.COCO_COOKIE_SECRET or 'chips ahoy' -config.isProduction = config.mongo.host isnt "localhost" +config.isProduction = config.mongo.host isnt 'localhost' if not config.unittest and not config.isProduction # change artificially slow down non-static requests for testing diff --git a/server_setup.coffee b/server_setup.coffee index 11454a29e..7f2b11ce6 100644 --- a/server_setup.coffee +++ b/server_setup.coffee @@ -57,7 +57,7 @@ setupMiddlewareToSendOldBrowserWarningWhenPlayersViewLevelDirectly = (app) -> # https://github.com/biggora/express-useragent/blob/master/lib/express-useragent.js return false unless ua = req.useragent return true if ua.isiPad or ua.isiPod or ua.isiPhone or ua.isOpera - return false unless ua and ua.Browser in ["Chrome", "Safari", "Firefox", "IE"] and ua.Version + return false unless ua and ua.Browser in ['Chrome', 'Safari', 'Firefox', 'IE'] and ua.Version b = ua.Browser v = parseInt ua.Version.split('.')[0], 10 return true if b is 'Chrome' and v < 17 @@ -93,9 +93,9 @@ sendMain = (req, res) -> log.error "Error modifying main.html: #{err}" if err # insert the user object directly into the html so the application can have it immediately. Sanitize data = data.replace('"userObjectTag"', JSON.stringify(UserHandler.formatEntity(req, req.user)).replace(/\//g, '\\/')) - res.header "Cache-Control", "no-cache, no-store, must-revalidate" - res.header "Pragma", "no-cache" - res.header "Expires", 0 + res.header 'Cache-Control', 'no-cache, no-store, must-revalidate' + res.header 'Pragma', 'no-cache' + res.header 'Expires', 0 res.send 200, data setupFacebookCrossDomainCommunicationRoute = (app) -> diff --git a/test/app/fixtures/levels.coffee b/test/app/fixtures/levels.coffee index 573fd5128..46383fc10 100644 --- a/test/app/fixtures/levels.coffee +++ b/test/app/fixtures/levels.coffee @@ -5,4 +5,4 @@ module.exports.LadderLevel = major: 1 minor: 2 isLatestMajor: true - isLatestMinor: true \ No newline at end of file + isLatestMinor: true diff --git a/test/app/lib/FacebookHandler.spec.coffee b/test/app/lib/FacebookHandler.spec.coffee index 662475893..49766391e 100644 --- a/test/app/lib/FacebookHandler.spec.coffee +++ b/test/app/lib/FacebookHandler.spec.coffee @@ -1,69 +1,69 @@ FacebookHandler = require 'lib/FacebookHandler' -mockAuthEvent = +mockAuthEvent = response: authResponse: - accessToken: "aksdhjflkqjrj245234b52k345q344le4j4k5l45j45s4dkljvdaskl" - userID: "4301938" + accessToken: 'aksdhjflkqjrj245234b52k345q344le4j4k5l45j45s4dkljvdaskl' + userID: '4301938' expiresIn: 5138 - signedRequest: "akjsdhfjkhea.3423nkfkdsejnfkd" - status: "connected" + signedRequest: 'akjsdhfjkhea.3423nkfkdsejnfkd' + status: 'connected' # Whatev, it's all public info anyway mockMe = - id: "4301938" - email: "scott@codecombat.com" - first_name: "Scott" - gender: "male" - last_name: "Erickson" - link: "https://www.facebook.com/scott.erickson.779" - locale: "en_US" - name: "Scott Erickson" + id: '4301938' + email: 'scott@codecombat.com' + first_name: 'Scott' + gender: 'male' + last_name: 'Erickson' + link: 'https://www.facebook.com/scott.erickson.779' + locale: 'en_US' + name: 'Scott Erickson' timezone: -7 - updated_time: "2014-05-21T04:58:06+0000" - username: "scott.erickson.779" + updated_time: '2014-05-21T04:58:06+0000' + username: 'scott.erickson.779' verified: true work: [ { employer: - id: "167559910060759" - name: "CodeCombat" + id: '167559910060759' + name: 'CodeCombat' location: - id: "114952118516947" - name: "San Francisco, California" + id: '114952118516947' + name: 'San Francisco, California' - start_date: "2013-02-28" + start_date: '2013-02-28' } { - end_date: "2013-01-31" + end_date: '2013-01-31' employer: - id: "39198748555" - name: "Skritter" + id: '39198748555' + name: 'Skritter' location: - id: "106109576086811" - name: "Oberlin, Ohio" + id: '106109576086811' + name: 'Oberlin, Ohio' - start_date: "2008-06-01" + start_date: '2008-06-01' } ] - -window.FB ?= { + +window.FB ?= { api: -> } - + describe 'lib/FacebookHandler.coffee', -> it 'on facebook-logged-in, gets data from FB and sends a patch to the server', -> - me.clear({silent:true}) + me.clear({silent: true}) me.markToRevert() me.set({_id: '12345'}) - + spyOn FB, 'api' - + new FacebookHandler() Backbone.Mediator.publish 'facebook-logged-in', mockAuthEvent - + expect(FB.api).toHaveBeenCalled() apiArgs = FB.api.calls.argsFor(0) expect(apiArgs[0]).toBe('/me') diff --git a/test/app/lib/ScriptManager.spec.coffee b/test/app/lib/ScriptManager.spec.coffee index 2313ca648..1bf82b168 100644 --- a/test/app/lib/ScriptManager.spec.coffee +++ b/test/app/lib/ScriptManager.spec.coffee @@ -1,7 +1,7 @@ describe('ScriptManager', -> ScriptManager = require 'lib/scripts/ScriptManager' xit('broadcasts note with event upon hearing from channel', -> - note = {channel: 'cnn', event: {1:1}} + note = {channel: 'cnn', event: {1: 1}} noteGroup = {duration: 0, notes: [note]} script = {channel: 'pbs', noteChain: [noteGroup]} @@ -19,7 +19,7 @@ describe('ScriptManager', -> ) xit('is silent when script event do not match', -> - note = {channel: 'cnn', event: {1:1}} + note = {channel: 'cnn', event: {1: 1}} noteGroup = {duration: 0, notes: [note]} script = channel: 'pbs' @@ -38,18 +38,18 @@ describe('ScriptManager', -> Backbone.Mediator.subscribe('cnn', f, @) # bunch of mismatches - Backbone.Mediator.publish('pbs', {foo:'rad'}) + Backbone.Mediator.publish('pbs', {foo: 'rad'}) expect(gotEvent).toBeNull() Backbone.Mediator.publish('pbs', 'bar') Backbone.Mediator.publish('pbs') - Backbone.Mediator.publish('pbs', {foo:'bar'}) + Backbone.Mediator.publish('pbs', {foo: 'bar'}) expect(gotEvent[1]).toBe(note.event[1]) sm.destroy() Backbone.Mediator.unsubscribe('cnn', f, @) ) xit('makes no subscriptions when something is invalid', -> - note = {event: {1:1}} # channel is required + note = {event: {1: 1}} # channel is required noteGroup = {notes: [note]} script = {channel: 'pbs', noteChain: [noteGroup]} sm = new ScriptManager([script]) @@ -58,11 +58,11 @@ describe('ScriptManager', -> ) xit('fills out lots of notes based on note group properties', -> - note = {channel: 'cnn', event: {1:1}} + note = {channel: 'cnn', event: {1: 1}} noteGroup = duration: 0 - botPos: [1,2] + botPos: [1, 2] botMessage: 'testers' domHighlight: '#code-area' surfaceHighlights: ['Guy0', 'Guy1'] @@ -88,12 +88,12 @@ describe('ScriptManager', -> ) xit('releases notes based on user confirmation', -> - note1 = {channel: 'cnn', event: {1:1}} - note2 = {channel: 'cbs', event: {2:2}} + note1 = {channel: 'cnn', event: {1: 1}} + note2 = {channel: 'cbs', event: {2: 2}} noteGroup1 = {duration: 0, notes: [note1]} noteGroup2 = {duration: 0, notes: [note2]} script = {channel: 'pbs', noteChain: [noteGroup1, noteGroup2]} - sm = new ScriptManager({scripts:[script]}) + sm = new ScriptManager({scripts: [script]}) sm.paused = false gotCnnEvent = null @@ -110,7 +110,7 @@ describe('ScriptManager', -> expect(sm.scriptInProgress).toBe(true) runs(-> Backbone.Mediator.publish('end-current-script')) f = -> gotCbsEvent? - waitsFor(f, "The next event should have been published", 20) + waitsFor(f, 'The next event should have been published', 20) f = -> expect(gotCnnEvent[1]).toBe(1) expect(gotCbsEvent[2]).toBe(2) @@ -125,8 +125,8 @@ describe('ScriptManager', -> xit('ignores triggers for scripts waiting for other scripts to fire', -> # channel2 won't fire the cbs notification until channel1 does its thing - note1 = {channel: 'cnn', event: {1:1}} - note2 = {channel: 'cbs', event: {2:2}} + note1 = {channel: 'cnn', event: {1: 1}} + note2 = {channel: 'cbs', event: {2: 2}} noteGroup1 = {duration: 0, notes: [note1]} noteGroup2 = {duration: 0, notes: [note2]} script1 = {channel: 'channel1', id: 'channel1Script', noteChain: [noteGroup1]} diff --git a/test/app/lib/deltas.spec.coffee b/test/app/lib/deltas.spec.coffee new file mode 100644 index 000000000..e658f3869 --- /dev/null +++ b/test/app/lib/deltas.spec.coffee @@ -0,0 +1,18 @@ +deltas = require 'lib/deltas' + +describe 'deltas lib', -> + + describe 'getConflicts', -> + + it 'handles conflicts where one change conflicts with several changes', -> + originalData = {list:[1,2,3]} + forkA = {list:['1', 2, '3']} + forkB = {noList: '...'} + differ = deltas.makeJSONDiffer() + + expandedDeltaA = deltas.expandDelta(differ.diff originalData, forkA) + expandedDeltaB = deltas.expandDelta(differ.diff originalData, forkB) + deltas.getConflicts(expandedDeltaA, expandedDeltaB) + for delta in expandedDeltaA + expect(delta.conflict).toBeDefined() + \ No newline at end of file diff --git a/test/app/lib/goal_manager.spec.coffee b/test/app/lib/goal_manager.spec.coffee index b5eb25367..df1d2ef02 100644 --- a/test/app/lib/goal_manager.spec.coffee +++ b/test/app/lib/goal_manager.spec.coffee @@ -1,20 +1,20 @@ xdescribe 'GoalManager', -> - GoalManager = require('lib/world/GoalManager') + GoalManager = require 'lib/world/GoalManager' liveState = stateMap: - '1':{health:10} - '2':{health:5} + '1': {health: 10} + '2': {health: 5} halfLiveState = stateMap: - '1':{health:0} - '2':{health:5} + '1': {health: 0} + '2': {health: 5} deadState = stateMap: - '1':{health:0} - '2':{health:-5} + '1': {health: 0} + '2': {health: -5} it 'can tell when everyone is dead', -> @@ -22,10 +22,10 @@ xdescribe 'GoalManager', -> world = frames: [liveState, liveState, liveState] gm.setWorld(world) - - goal = { id: 'die', name: 'Kill Everyone', killGuy: ['1','2'] } + + goal = {id: 'die', name: 'Kill Everyone', killGuy: ['1', '2']} gm.addGoal goal - + expect(gm.goalStates['die'].complete).toBe(false) world.frames.push(deadState) @@ -39,10 +39,10 @@ xdescribe 'GoalManager', -> world = frames: [liveState, liveState, liveState, deadState, deadState] gm.setWorld(world) - - goal = { id: 'live', name: 'Save guy 2', saveGuy: '2' } + + goal = {id: 'live', name: 'Save guy 2', saveGuy: '2'} gm.addGoal goal - + expect(gm.goalStates['live'].complete).toBe(false) world = frames: [liveState, liveState, liveState, liveState, liveState] @@ -53,4 +53,4 @@ xdescribe 'GoalManager', -> # world.frames.push(deadState) # gm.setWorld(world) # expect(gm.goalStates['live'].complete).toBe(true) -# expect(gm.goalStates['live'].frameCompleted).toBe(3) \ No newline at end of file +# expect(gm.goalStates['live'].frameCompleted).toBe(3) diff --git a/test/app/lib/local_mongo.spec.coffee b/test/app/lib/local_mongo.spec.coffee index f3719021e..4aa2dc76e 100644 --- a/test/app/lib/local_mongo.spec.coffee +++ b/test/app/lib/local_mongo.spec.coffee @@ -14,16 +14,16 @@ describe 'Local Mongo queries', -> it 'regular match of a property', -> expect(LocalMongo.matchesQuery(@fixture1, 'gender': 'unicorn')).toBeFalsy() - expect(LocalMongo.matchesQuery(@fixture1, 'type':'unicorn')).toBeTruthy() - expect(LocalMongo.matchesQuery(@fixture1, 'type':'zebra')).toBeFalsy() - expect(LocalMongo.matchesQuery(@fixture1, 'type':'unicorn', 'id':'somestring')).toBeTruthy() + expect(LocalMongo.matchesQuery(@fixture1, 'type': 'unicorn')).toBeTruthy() + expect(LocalMongo.matchesQuery(@fixture1, 'type': 'zebra')).toBeFalsy() + expect(LocalMongo.matchesQuery(@fixture1, 'type': 'unicorn', 'id': 'somestring')).toBeTruthy() it 'array match of a property', -> - expect(LocalMongo.matchesQuery(@fixture1, 'likes':'poptarts')).toBeTruthy() - expect(LocalMongo.matchesQuery(@fixture1, 'likes':'walks on the beach')).toBeFalsy() + expect(LocalMongo.matchesQuery(@fixture1, 'likes': 'poptarts')).toBeTruthy() + expect(LocalMongo.matchesQuery(@fixture1, 'likes': 'walks on the beach')).toBeFalsy() it 'nested match', -> - expect(LocalMongo.matchesQuery(@fixture2, 'this.is.so':'deep')).toBeTruthy() + expect(LocalMongo.matchesQuery(@fixture2, 'this.is.so': 'deep')).toBeTruthy() it '$gt selector', -> expect(LocalMongo.matchesQuery(@fixture1, 'value': '$gt': 8000)).toBeTruthy() @@ -67,15 +67,14 @@ describe 'Local Mongo queries', -> expect(LocalMongo.matchesQuery(@fixture1, 'likes': '$nin': ['popcorn', 'chicken'])).toBeFalsy() it '$or operator', -> - expect(LocalMongo.matchesQuery(@fixture1, $or: [{value:9000}, {type:'zebra'}])).toBeTruthy() - expect(LocalMongo.matchesQuery(@fixture1, $or: [{value:9001}, {worth:$lt:10}])).toBeTruthy() + expect(LocalMongo.matchesQuery(@fixture1, $or: [{value: 9000}, {type: 'zebra'}])).toBeTruthy() + expect(LocalMongo.matchesQuery(@fixture1, $or: [{value: 9001}, {worth: '$lt': 10}])).toBeTruthy() it '$and operator', -> - expect(LocalMongo.matchesQuery(@fixture1, $and: [{value:9000}, {type:'zebra'}])).toBeFalsy() - expect(LocalMongo.matchesQuery(@fixture1, $and: [{value:9000}, {type:'unicorn'}])).toBeTruthy() - expect(LocalMongo.matchesQuery(@fixture1, $and: [{value:$gte:9000}, {worth:$lt:10}])).toBeTruthy() + expect(LocalMongo.matchesQuery(@fixture1, $and: [{value: 9000}, {type: 'zebra'}])).toBeFalsy() + expect(LocalMongo.matchesQuery(@fixture1, $and: [{value: 9000}, {type: 'unicorn'}])).toBeTruthy() + expect(LocalMongo.matchesQuery(@fixture1, $and: [{value: '$gte': 9000}, {worth: '$lt': 10}])).toBeTruthy() it '$exists operator', -> expect(LocalMongo.matchesQuery(@fixture1, type: $exists: true)).toBeTruthy() expect(LocalMongo.matchesQuery(@fixture1, interesting: $exists: false)).toBeTruthy() - diff --git a/test/app/lib/surface/camera.spec.coffee b/test/app/lib/surface/camera.spec.coffee index 8019cd38f..f875a1135 100644 --- a/test/app/lib/surface/camera.spec.coffee +++ b/test/app/lib/surface/camera.spec.coffee @@ -20,7 +20,6 @@ describe 'Camera (Surface point of view)', -> expect(cap.x).toBeCloseTo (sup.x - cam.surfaceViewport.x) * cam.zoom expect(cap.y).toBeCloseTo (sup.y - cam.surfaceViewport.y) * cam.zoom - scp = cam.worldToScreen wop # If we ever want to use screen conversion, then make it and add this test #expect(scp.x).toBeCloseTo cap.x * @someCanvasToScreenXScaleFactor @@ -52,7 +51,7 @@ describe 'Camera (Surface point of view)', -> x: cam.worldViewport.cx y: cam.worldViewport.cy - camDist * cam.y2x * cam.z2y z: camDist * cam.z2x * cam.y2z - #console.log "botFOV", botFOV * 180 / Math.PI, "botDist", botDist, "camDist", camDist, "target pos", targetPos, "actual pos", cam.cameraWorldPos() + #console.log 'botFOV', botFOV * 180 / Math.PI, 'botDist', botDist, 'camDist', camDist, 'target pos', targetPos, 'actual pos', cam.cameraWorldPos() expectPositionsEqual cam.cameraWorldPos(), targetPos if wop @@ -98,25 +97,25 @@ describe 'Camera (Surface point of view)', -> checkCameraPos cam, wop it 'works at 90 degrees', -> - cam = new Camera { attr: (x) -> 100 }, 100 * Camera.MPP, 100 * Camera.MPP + cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP expect(cam.x2y).toBeCloseTo 1 expect(cam.x2z).toBeGreaterThan 9001 expect(cam.z2y).toBeCloseTo 0 it 'works at 0 degrees', -> - cam = new Camera { attr: (x) -> 100 }, 100 * Camera.MPP, 100 * Camera.MPP + cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP expect(cam.x2z).toBeGreaterThan 9001 expect(cam.x2y).toBeCloseTo 1 expect(cam.z2y).toBeCloseTo 0 it 'works at 45 degrees', -> - cam = new Camera { attr: (x) -> 100 }, 100 * Camera.MPP, 100 * Camera.MPP + cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP expect(cam.x2y).toBeCloseTo 1 expect(cam.x2z).toBeGreaterThan 9001 expect(cam.z2y).toBeCloseTo 0 xit 'works at default angle of asin(0.75) ~= 48.9 degrees', -> - cam = new Camera { attr: (x) -> 100 }, 100 * Camera.MPP, 100 * Camera.MPP + cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP angle = 1 / Math.cos angle expect(cam.angle).toBeCloseTo angle expect(cam.x2y).toBeCloseTo 1 @@ -124,7 +123,7 @@ describe 'Camera (Surface point of view)', -> expect(cam.z2y).toBeCloseTo 0 xit 'works at 2x zoom, 90 degrees', -> - cam = new Camera { attr: (x) -> 100 }, 100 * Camera.MPP, 100 * Camera.MPP + cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP checkCameraPos cam wop = x: 5, y: 2.5, z: 7 cap = cam.worldToCanvas wop @@ -144,7 +143,7 @@ describe 'Camera (Surface point of view)', -> expectPositionsEqual cap, {x: 0, y: 50} xit 'works at 2x zoom, 30 degrees', -> - cam = new Camera { attr: (x) -> 100 }, 100 * Camera.MPP, 2 * 100 * Camera.MPP + cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 2 * 100 * Camera.MPP expect(cam.x2y).toBeCloseTo 1 expect(cam.x2z).toBeGreaterThan 9001 checkCameraPos cam @@ -165,15 +164,15 @@ describe 'Camera (Surface point of view)', -> expectPositionsEqual cap, {x: 50, y: -100} it 'works at 2x zoom, 60 degree hFOV', -> - cam = new Camera { attr: (x) -> 100 }, 100 * Camera.MPP, 100 * Camera.MPP + cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP checkCameraPos cam xit 'works at 2x zoom, 60 degree hFOV, 40 degree hFOV', -> - cam = new Camera { attr: (x) -> x is 'height' ? 63.041494 : 100 }, 100 * Camera.MPP, 63.041494 * Camera.MPP + cam = new Camera {attr: (x) -> x is 'height' ? 63.041494 : 100}, 100 * Camera.MPP, 63.041494 * Camera.MPP checkCameraPos cam xit 'works on a surface wider than it is tall, 30 degrees, default viewing upper left corner', -> - cam = new Camera { attr: (x) -> 100 }, 200 * Camera.MPP, 2 * 50 * Camera.MPP + cam = new Camera {attr: (x) -> 100}, 200 * Camera.MPP, 2 * 50 * Camera.MPP checkCameraPos cam expect(cam.zoom).toBeCloseTo 2 wop = x: 5, y: 4, z: 6 * cam.y2z # like x: 5, y: 10 out of world width: 20, height: 10 diff --git a/test/app/lib/utils.spec.coffee b/test/app/lib/utils.spec.coffee index 925bc8e54..061a9aa71 100644 --- a/test/app/lib/utils.spec.coffee +++ b/test/app/lib/utils.spec.coffee @@ -3,26 +3,25 @@ describe 'utils library', -> beforeEach -> this.fixture1 = - "text": "G'day, Wizard! Come to practice? Well, let's get started..." - "blurb": "G'day" - "i18n": - "es-419": - "text": "¡Buenas, Hechicero! ¿Vienes a practicar? Bueno, empecemos..." - "es-ES": - "text": "¡Buenas Mago! ¿Vienes a practicar? Bien, empecemos..." - "es": - "text": "¡Buenas Mago! ¿Vienes a practicar? Muy bien, empecemos..." - "fr": - "text": "S'lut, Magicien! Venu pratiquer? Ok, bien débutons..." - "pt-BR": - "text": "Bom dia, feiticeiro! Veio praticar? Então vamos começar..." - "en": - "text": "Ohai Magician!" - "de": - "text": "'N Tach auch, Zauberer! Kommst Du zum Üben? Dann lass uns anfangen..." - "sv": - "text": "Godagens, trollkarl! Kommit för att öva? Nå, låt oss börja..." - + 'text': 'G\'day, Wizard! Come to practice? Well, let\'s get started...' + 'blurb': 'G\'day' + 'i18n': + 'es-419': + 'text': '¡Buenas, Hechicero! ¿Vienes a practicar? Bueno, empecemos...' + 'es-ES': + 'text': '¡Buenas Mago! ¿Vienes a practicar? Bien, empecemos...' + 'es': + 'text': '¡Buenas Mago! ¿Vienes a practicar? Muy bien, empecemos...' + 'fr': + 'text': 'S\'lut, Magicien! Venu pratiquer? Ok, bien débutons...' + 'pt-BR': + 'text': 'Bom dia, feiticeiro! Veio praticar? Então vamos começar...' + 'en': + 'text': 'Ohai Magician!' + 'de': + 'text': '\'N Tach auch, Zauberer! Kommst Du zum Üben? Dann lass uns anfangen...' + 'sv': + 'text': 'Godagens, trollkarl! Kommit för att öva? Nå, låt oss börja...' it 'i18n should find a valid target string', -> expect(util.i18n(this.fixture1, 'text', 'sv')).toEqual(this.fixture1.i18n['sv'].text) diff --git a/test/app/lib/world/GoalManager.spec.coffee b/test/app/lib/world/GoalManager.spec.coffee index 9641e2d55..d17cc193a 100644 --- a/test/app/lib/world/GoalManager.spec.coffee +++ b/test/app/lib/world/GoalManager.spec.coffee @@ -1,19 +1,19 @@ describe('GoalManager', -> GoalManager = require 'lib/world/GoalManager' - killGoal = { name: 'Kill Guy', killThangs: ['Guy1', 'Guy2'], id:'killguy'} - saveGoal = { name: 'Save Guy', saveThangs: ['Guy1', 'Guy2'], id:'saveguy'} - getToLocGoal = { name: 'Go there', getToLocation: {target:'Frying Pan', who:'Potato'}, id:'id'} - keepFromLocGoal = { name: 'Go there', keepFromLocation: {target:'Frying Pan', who:'Potato'}, id:'id'} - leaveMapGoal = { name: 'Go away', leaveOffSide: {who:'Yall'}, id:'id'} - stayMapGoal = { name: 'Stay here', keepFromLeavingOffSide: {who:'Yall'}, id:'id'} - getItemGoal = { name: 'Mine', getItem: {who:'Grabby', itemID:'Sandwich'}, id:'id'} - keepItemGoal = { name: 'Not Yours', keepFromGettingItem: {who:'Grabby', itemID:'Sandwich'}, id:'id'} + killGoal = {name: 'Kill Guy', killThangs: ['Guy1', 'Guy2'], id: 'killguy'} + saveGoal = {name: 'Save Guy', saveThangs: ['Guy1', 'Guy2'], id: 'saveguy'} + getToLocGoal = {name: 'Go there', getToLocation: {target: 'Frying Pan', who: 'Potato'}, id: 'id'} + keepFromLocGoal = {name: 'Go there', keepFromLocation: {target: 'Frying Pan', who: 'Potato'}, id: 'id'} + leaveMapGoal = {name: 'Go away', leaveOffSide: {who: 'Yall'}, id: 'id'} + stayMapGoal = {name: 'Stay here', keepFromLeavingOffSide: {who: 'Yall'}, id: 'id'} + getItemGoal = {name: 'Mine', getItem: {who: 'Grabby', itemID: 'Sandwich'}, id: 'id'} + keepItemGoal = {name: 'Not Yours', keepFromGettingItem: {who: 'Grabby', itemID: 'Sandwich'}, id: 'id'} it('handles kill goal', -> gm = new GoalManager() gm.setGoals([killGoal]) gm.worldGenerationWillBegin() - gm.submitWorldGenerationEvent('world:thang-died', {thang:{id:'Guy1'}}, 10) + gm.submitWorldGenerationEvent('world:thang-died', {thang: {id: 'Guy1'}}, 10) gm.worldGenerationEnded() goalStates = gm.getGoalStates() expect(goalStates.killguy.status).toBe('incomplete') @@ -21,7 +21,7 @@ describe('GoalManager', -> expect(goalStates.killguy.killed.Guy2).toBe(false) expect(goalStates.killguy.keyFrame).toBe(0) - gm.submitWorldGenerationEvent('world:thang-died', {thang:{id:'Guy2'}}, 20) + gm.submitWorldGenerationEvent('world:thang-died', {thang: {id: 'Guy2'}}, 20) goalStates = gm.getGoalStates() expect(goalStates.killguy.status).toBe('success') expect(goalStates.killguy.killed.Guy1).toBe(true) @@ -33,7 +33,7 @@ describe('GoalManager', -> gm = new GoalManager() gm.setGoals([saveGoal]) gm.worldGenerationWillBegin() - gm.submitWorldGenerationEvent('world:thang-died', {thang:{id:'Guy1'}}, 10) + gm.submitWorldGenerationEvent('world:thang-died', {thang: {id: 'Guy1'}}, 10) gm.worldGenerationEnded() goalStates = gm.getGoalStates() expect(goalStates.saveguy.status).toBe('failure') @@ -65,7 +65,7 @@ describe('GoalManager', -> gm = new GoalManager() gm.setGoals([getToLocGoal]) gm.worldGenerationWillBegin() - gm.submitWorldGenerationEvent('world:thang-touched-goal', {actor:{id:'Potato'}, touched:{id:'Frying Pan'}}, 10) + gm.submitWorldGenerationEvent('world:thang-touched-goal', {actor: {id: 'Potato'}, touched: {id: 'Frying Pan'}}, 10) gm.worldGenerationEnded() goalStates = gm.getGoalStates() expect(goalStates.id.status).toBe('success') @@ -76,7 +76,7 @@ describe('GoalManager', -> gm = new GoalManager() gm.setGoals([keepFromLocGoal]) gm.worldGenerationWillBegin() - gm.submitWorldGenerationEvent('world:thang-touched-goal', {actor:{id:'Potato'}, touched:{id:'Frying Pan'}}, 10) + gm.submitWorldGenerationEvent('world:thang-touched-goal', {actor: {id: 'Potato'}, touched: {id: 'Frying Pan'}}, 10) gm.worldGenerationEnded() goalStates = gm.getGoalStates() expect(goalStates.id.status).toBe('failure') @@ -105,7 +105,7 @@ describe('GoalManager', -> gm = new GoalManager() gm.setGoals([leaveMapGoal]) gm.worldGenerationWillBegin() - gm.submitWorldGenerationEvent('world:thang-left-map', {thang:{id:'Yall'}}, 10) + gm.submitWorldGenerationEvent('world:thang-left-map', {thang: {id: 'Yall'}}, 10) gm.worldGenerationEnded() goalStates = gm.getGoalStates() expect(goalStates.id.status).toBe('success') @@ -116,7 +116,7 @@ describe('GoalManager', -> gm = new GoalManager() gm.setGoals([stayMapGoal]) gm.worldGenerationWillBegin() - gm.submitWorldGenerationEvent('world:thang-left-map', {thang:{id:'Yall'}}, 10) + gm.submitWorldGenerationEvent('world:thang-left-map', {thang: {id: 'Yall'}}, 10) gm.worldGenerationEnded() goalStates = gm.getGoalStates() expect(goalStates.id.status).toBe('failure') @@ -145,7 +145,7 @@ describe('GoalManager', -> gm = new GoalManager() gm.setGoals([getItemGoal]) gm.worldGenerationWillBegin() - gm.submitWorldGenerationEvent('world:thang-collected-item', {actor:{id:'Grabby'}, item:{id:'Sandwich'}}, 10) + gm.submitWorldGenerationEvent('world:thang-collected-item', {actor: {id: 'Grabby'}, item: {id: 'Sandwich'}}, 10) gm.worldGenerationEnded() goalStates = gm.getGoalStates() expect(goalStates.id.status).toBe('success') @@ -156,7 +156,7 @@ describe('GoalManager', -> gm = new GoalManager() gm.setGoals([keepItemGoal]) gm.worldGenerationWillBegin() - gm.submitWorldGenerationEvent('world:thang-collected-item', {actor:{id:'Grabby'}, item:{id:'Sandwich'}}, 10) + gm.submitWorldGenerationEvent('world:thang-collected-item', {actor: {id: 'Grabby'}, item: {id: 'Sandwich'}}, 10) gm.worldGenerationEnded() goalStates = gm.getGoalStates() expect(goalStates.id.status).toBe('failure') diff --git a/test/app/lib/world/rectangle.spec.coffee b/test/app/lib/world/rectangle.spec.coffee index 1f674a8a8..76b13e0d3 100644 --- a/test/app/lib/world/rectangle.spec.coffee +++ b/test/app/lib/world/rectangle.spec.coffee @@ -71,11 +71,11 @@ describe 'Rectangle', -> it 'is its own AABB when not rotated', -> rect = new Rectangle 10, 20, 30, 40 aabb = rect.axisAlignedBoundingBox() - for prop in ["x", "y", "width", "height"] + for prop in ['x', 'y', 'width', 'height'] expect(rect[prop]).toBe aabb[prop] it 'is its own AABB when rotated 180', -> rect = new Rectangle 10, 20, 30, 40, Math.PI aabb = rect.axisAlignedBoundingBox() - for prop in ["x", "y", "width", "height"] + for prop in ['x', 'y', 'width', 'height'] expect(rect[prop]).toBe aabb[prop] diff --git a/test/app/models/CocoModel.spec.coffee b/test/app/models/CocoModel.spec.coffee index f7703b851..67e019c9a 100644 --- a/test/app/models/CocoModel.spec.coffee +++ b/test/app/models/CocoModel.spec.coffee @@ -12,10 +12,10 @@ class BlandClass extends CocoModel _id: {type: 'string'} } urlRoot: '/db/bland' - + describe 'CocoModel', -> describe 'save', -> - + it 'saves to db/', -> b = new BlandClass({}) res = b.save() @@ -23,14 +23,14 @@ describe 'CocoModel', -> expect(res).toBeDefined() expect(request.url).toBe(b.urlRoot) expect(request.method).toBe('POST') - + it 'does not save if the data is invalid based on the schema', -> b = new BlandClass({number: 'NaN'}) res = b.save() expect(res).toBe(false) request = jasmine.Ajax.requests.mostRecent() expect(request).toBeUndefined() - + it 'uses PUT when _id is included', -> b = new BlandClass({_id: 'test'}) b.save() @@ -39,7 +39,7 @@ describe 'CocoModel', -> describe 'patch', -> it 'PATCHes only properties that have changed', -> - b = new BlandClass({_id: 'test', number:1}) + b = new BlandClass({_id: 'test', number: 1}) b.loaded = true b.set('string', 'string') b.patch() @@ -47,12 +47,12 @@ describe 'CocoModel', -> params = JSON.parse request.params expect(params.string).toBeDefined() expect(params.number).toBeUndefined() - + it 'collates all changes made over several sets', -> - b = new BlandClass({_id: 'test', number:1}) + b = new BlandClass({_id: 'test', number: 1}) b.loaded = true b.set('string', 'string') - b.set('object', {4:5}) + b.set('object', {4: 5}) b.patch() request = jasmine.Ajax.requests.mostRecent() params = JSON.parse request.params @@ -61,22 +61,22 @@ describe 'CocoModel', -> expect(params.number).toBeUndefined() it 'does not include data from previous patches', -> - b = new BlandClass({_id: 'test', number:1}) + b = new BlandClass({_id: 'test', number: 1}) b.loaded = true - b.set('object', {1:2}) + b.set('object', {1: 2}) b.patch() request = jasmine.Ajax.requests.mostRecent() attrs = JSON.stringify(b.attributes) # server responds with all request.response({status: 200, responseText: attrs}) - + b.set('number', 3) b.patch() request = jasmine.Ajax.requests.mostRecent() params = JSON.parse request.params expect(params.object).toBeUndefined() - + it 'does nothing when there\'s nothing to patch', -> - b = new BlandClass({_id: 'test', number:1}) + b = new BlandClass({_id: 'test', number: 1}) b.loaded = true b.set('number', 1) b.patch() diff --git a/test/app/models/SuperModel.spec.coffee b/test/app/models/SuperModel.spec.coffee index 7e69a394d..1e64d8d14 100644 --- a/test/app/models/SuperModel.spec.coffee +++ b/test/app/models/SuperModel.spec.coffee @@ -7,14 +7,14 @@ describe 'SuperModel', -> it 'is finished by default', -> s = new SuperModel() expect(s.finished()).toBeTruthy() - + it 'is based on resource completion and value', (done) -> s = new SuperModel() r1 = s.addSomethingResource('???', 2) r2 = s.addSomethingResource('???', 3) expect(s.progress).toBe(0) r1.markLoaded() - + # progress updates are deferred so defer more _.defer -> expect(s.progress).toBe(0.4) @@ -22,26 +22,26 @@ describe 'SuperModel', -> _.defer -> expect(s.progress).toBe(1) done() - + describe 'loadModel (function)', -> it 'starts loading the model if it isn\'t already loading', -> s = new SuperModel() - m = new User({_id:'12345'}) + m = new User({_id: '12345'}) s.loadModel(m, 'user') request = jasmine.Ajax.requests.mostRecent() expect(request).toBeDefined() - + it 'also loads collections', -> s = new SuperModel() c = new ComponentsCollection() s.loadModel(c, 'collection') request = jasmine.Ajax.requests.mostRecent() expect(request).toBeDefined() - + describe 'events', -> it 'triggers "loaded-all" when finished', (done) -> s = new SuperModel() - m = new User({_id:'12345'}) + m = new User({_id: '12345'}) triggered = false s.once 'loaded-all', -> triggered = true s.loadModel(m, 'user') @@ -49,4 +49,4 @@ describe 'SuperModel', -> request.response({status: 200, responseText: '{}'}) _.defer -> expect(triggered).toBe(true) - done() \ No newline at end of file + done() diff --git a/test/app/views/editor/level/EditorLevelView.spec.coffee b/test/app/views/editor/level/EditorLevelView.spec.coffee index 860fa826c..47b32700f 100644 --- a/test/app/views/editor/level/EditorLevelView.spec.coffee +++ b/test/app/views/editor/level/EditorLevelView.spec.coffee @@ -1,14 +1,14 @@ EditorLevelView = require 'views/editor/level/edit' -emptyLevel = {"_id":"53a0a1e2d9048dbc3a793c81","name":"Emptiness","description":"Tis nothing..","documentation":{"generalArticles":[],"specificArticles":[]},"scripts":[],"thangs":[],"systems":[],"victory":{},"version":{"minor":0,"major":0,"isLatestMajor":true,"isLatestMinor":true},"index":"5388f9ac9a904d0000d94f87","slug":"emptiness","creator":"5388f9ac9a904d0000d94f87","original":"53a0a1e2d9048dbc3a793c81","watchers":["5388f9ac9a904d0000d94f87"],"__v":0,"created":"2014-06-17T20:15:30.207Z","permissions":[{"access":"owner","target":"5388f9ac9a904d0000d94f87"}]} +emptyLevel = {'_id': '53a0a1e2d9048dbc3a793c81', 'name': 'Emptiness', 'description': 'Tis nothing..', 'documentation': {'generalArticles': [], 'specificArticles': []}, 'scripts': [], 'thangs': [], 'systems': [], 'victory': {}, 'version': {'minor': 0, 'major': 0, 'isLatestMajor': true, 'isLatestMinor': true}, 'index': '5388f9ac9a904d0000d94f87', 'slug': 'emptiness', 'creator': '5388f9ac9a904d0000d94f87', 'original': '53a0a1e2d9048dbc3a793c81', 'watchers': ['5388f9ac9a904d0000d94f87'], '__v': 0, 'created': '2014-06-17T20:15:30.207Z', 'permissions': [{'access': 'owner', 'target': '5388f9ac9a904d0000d94f87'}]} describe 'EditorLevelView', -> describe 'revert button', -> it 'opens just one modal when you click it', -> view = new EditorLevelView({}, 'something') request = jasmine.Ajax.requests.first() - request.response {status:200, responseText: JSON.stringify(emptyLevel)} + request.response {status: 200, responseText: JSON.stringify(emptyLevel)} view.render() spyOn(view, 'openModalView') view.$el.find('#revert-button').click() - expect(view.openModalView.calls.count()).toBe(1) \ No newline at end of file + expect(view.openModalView.calls.count()).toBe(1) diff --git a/test/app/views/modal/AuthModalView.spec.coffee b/test/app/views/modal/AuthModalView.spec.coffee index 4cddd2a9e..01bd1b98e 100644 --- a/test/app/views/modal/AuthModalView.spec.coffee +++ b/test/app/views/modal/AuthModalView.spec.coffee @@ -9,4 +9,4 @@ describe 'AuthModalView', -> m.$el.find('#link-to-recover').click() expect(m.openModalView.calls.count()).toEqual(1) args = m.openModalView.calls.argsFor(0) - expect(args[0] instanceof RecoverModalView).toBeTruthy() \ No newline at end of file + expect(args[0] instanceof RecoverModalView).toBeTruthy() diff --git a/test/app/views/play/ladder/ladder_tab.spec.coffee b/test/app/views/play/ladder/ladder_tab.spec.coffee index b809ebb31..0f74b341b 100644 --- a/test/app/views/play/ladder/ladder_tab.spec.coffee +++ b/test/app/views/play/ladder/ladder_tab.spec.coffee @@ -7,12 +7,12 @@ describe 'LeaderboardData', -> level = new Level(fixtures.LadderLevel) leaderboard = new LadderTabView.LeaderboardData(level, 'humans', null, 4) leaderboard.fetch() - + # no session passed in, so only one request expect(jasmine.Ajax.requests.count()).toBe(1) - + request = jasmine.Ajax.requests.mostRecent() triggered = false leaderboard.once 'sync', -> triggered = true request.response({status: 200, responseText: '{}'}) - expect(triggered).toBe(true) \ No newline at end of file + expect(triggered).toBe(true) diff --git a/test/demo/views/editor/PatchesView.demo.coffee b/test/demo/views/editor/PatchesView.demo.coffee index a06da6631..cf2ee2480 100644 --- a/test/demo/views/editor/PatchesView.demo.coffee +++ b/test/demo/views/editor/PatchesView.demo.coffee @@ -14,9 +14,8 @@ class BlandModel extends CocoModel } urlRoot: '/db/bland' - module.exports = -> - model = new BlandModel({_id:'12345', name:'name', original:'original'}) + model = new BlandModel({_id: '12345', name: 'name', original: 'original'}) v = new PatchesView(model) v.load() @@ -27,17 +26,16 @@ module.exports = -> delta: null commitMessage: 'Demo message' creator: '12345' - created: "2014-01-01T12:00:00.000Z" + created: '2014-01-01T12:00:00.000Z' status: 'pending' } ] - r.response({ status:200, responseText: JSON.stringify patches }) - + r.response({status: 200, responseText: JSON.stringify patches}) + # Respond to request for user ids -> names r = jasmine.Ajax.requests.mostRecent() - names = { '12345': { name: 'Patchman' } } - r.response({ status:200, responseText: JSON.stringify names }) - + names = {'12345': {name: 'Patchman'}} + r.response({status: 200, responseText: JSON.stringify names}) + v.render() v - diff --git a/test/server/common.coffee b/test/server/common.coffee index c098650ca..fa1b04f4c 100644 --- a/test/server/common.coffee +++ b/test/server/common.coffee @@ -3,7 +3,7 @@ console.log 'IT BEGINS' -require('jasmine-spec-reporter') +require 'jasmine-spec-reporter' jasmine.getEnv().reporter.subReporters_ = [] jasmine.getEnv().addReporter(new jasmine.SpecReporter({ displaySuccessfulSpec: true, @@ -13,12 +13,12 @@ jasmine.getEnv().addReporter(new jasmine.SpecReporter({ rep = new jasmine.JsApiReporter() jasmine.getEnv().addReporter(rep) -GLOBAL._ = require('lodash') -_.str = require('underscore.string') +GLOBAL._ = require 'lodash' +_.str = require 'underscore.string' _.mixin(_.str.exports()) GLOBAL.mongoose = require 'mongoose' mongoose.connect('mongodb://localhost/coco_unittest') -path = require('path') +path = require 'path' GLOBAL.testing = true models_path = [ @@ -67,7 +67,7 @@ GLOBAL.saveModels = (models, done) -> async.parallel funcs, (err, results) -> done(err) -GLOBAL.simplePermissions = [target:'public', access:'owner'] +GLOBAL.simplePermissions = [target: 'public', access: 'owner'] GLOBAL.ObjectId = mongoose.Types.ObjectId GLOBAL.request = require 'request' @@ -90,8 +90,8 @@ unittest.getUser = (name, email, password, done, force) -> request.get getURL('/auth/whoami'), -> req = request.post(getURL('/db/user'), (err, response, body) -> throw err if err - User.findOne({email:email}).exec((err, user) -> - user.set('permissions', if password is '80yqxpb38j' then [ 'admin' ] else []) + User.findOne({email: email}).exec((err, user) -> + user.set('permissions', if password is '80yqxpb38j' then ['admin'] else []) user.set('name', name) user.save (err) -> wrapUpGetUser(email, user, done) @@ -164,4 +164,4 @@ tick = -> mongoose.disconnect() clearTimeout tickInterval -tickInterval = setInterval tick, 1000 +tickInterval = setInterval tick, 1000 diff --git a/test/server/functional/achievement.spec.coffee b/test/server/functional/achievement.spec.coffee index 793248758..e91538fd8 100644 --- a/test/server/functional/achievement.spec.coffee +++ b/test/server/functional/achievement.spec.coffee @@ -5,7 +5,7 @@ unlockable = description: 'Started playing Dungeon Arena.' worth: 3 collection: 'level.session' - query: "{\"level.original\":\"dungeon-arena\"}" + query: "{\"level.original\": \"dungeon-arena\"}" userField: 'creator' repeatable = @@ -13,7 +13,7 @@ repeatable = description: 'Simulated Games.' worth: 1 collection: 'User' - query: "{\"simulatedBy\":{\"$gt\":\"0\"}}" + query: "{\"simulatedBy\": {\"$gt\": \"0\"}}" userField: '_id' proportionalTo: 'simulatedBy' @@ -35,7 +35,7 @@ describe 'Achievement', -> it 'can\'t be updated by ordinary users', (done) -> loginJoe -> - request.put {uri: url, json:unlockable}, (err, res, body) -> + request.put {uri: url, json: unlockable}, (err, res, body) -> expect(res.statusCode).toBe(403) request {method: 'patch', uri: url, json: unlockable}, (err, res, body) -> @@ -82,13 +82,12 @@ describe 'Achievement', -> done() it 'get schema', (done) -> - request.get {uri:url + '/schema'}, (err, res, body) -> + request.get {uri: url + '/schema'}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body.type).toBeDefined() done() - describe 'Achieving Achievements', -> it 'allows users to unlock one-time Achievements', (done) -> @@ -97,14 +96,11 @@ describe 'Achieving Achievements', -> creator: joe._id level: original: 'dungeon-arena' - request.post {uri:getURL('/db/level.session'), json:levelSession}, (session) -> + request.post {uri: getURL('/db/level.session'), json: levelSession}, (session) -> done() - xit 'cleaning up test: deleting all Achievements and relates', (done) -> clearModels [Achievement, EarnedAchievement, LevelSession], (err) -> expect(err).toBeNull() done() - - diff --git a/test/server/functional/article.spec.coffee b/test/server/functional/article.spec.coffee index b96df0f4c..e17f241ea 100644 --- a/test/server/functional/article.spec.coffee +++ b/test/server/functional/article.spec.coffee @@ -7,21 +7,21 @@ describe '/db/article', -> throw err if err done() - article = {name: 'Yo', body:'yo ma'} - article2 = {name: 'Original', body:'yo daddy'} + article = {name: 'Yo', body: 'yo ma'} + article2 = {name: 'Original', body: 'yo daddy'} url = getURL('/db/article') articles = {} it 'does not allow non-admins to create Articles.', (done) -> loginJoe -> - request.post {uri:url, json:article}, (err, res, body) -> + request.post {uri: url, json: article}, (err, res, body) -> expect(res.statusCode).toBe(403) done() it 'allows admins to create Articles', (done) -> loginAdmin -> - request.post {uri:url, json:article}, (err, res, body) -> + request.post {uri: url, json: article}, (err, res, body) -> expect(res.statusCode).toBe(200) expect(body.slug).toBeDefined() expect(body.body).toBeDefined() @@ -31,7 +31,7 @@ describe '/db/article', -> articles[0] = body # Having two articles allow for testing article search and such - request.post {uri:url, json:article2}, (err, res, body) -> + request.post {uri: url, json: article2}, (err, res, body) -> expect(res.statusCode).toBe(200) expect(body.slug).toBeDefined() expect(body.body).toBeDefined() @@ -45,7 +45,7 @@ describe '/db/article', -> it 'allows admins to make new minor versions', (done) -> new_article = _.clone(articles[0]) new_article.body = 'yo daddy' - request.post {uri:url, json:new_article}, (err, res, body) -> + request.post {uri: url, json: new_article}, (err, res, body) -> expect(res.statusCode).toBe(200) expect(body.version.major).toBe(0) expect(body.version.minor).toBe(1) @@ -58,7 +58,7 @@ describe '/db/article', -> it 'allows admins to make new major versions', (done) -> new_article = _.clone(articles[1]) delete new_article.version - request.post {uri:url, json:new_article}, (err, res, body) -> + request.post {uri: url, json: new_article}, (err, res, body) -> expect(res.statusCode).toBe(200) expect(body.version.major).toBe(1) expect(body.version.minor).toBe(0) @@ -69,29 +69,29 @@ describe '/db/article', -> it 'grants access for regular users', (done) -> loginJoe -> - request.get {uri:url+'/'+articles[0]._id}, (err, res, body) -> + request.get {uri: url+'/'+articles[0]._id}, (err, res, body) -> body = JSON.parse(body) expect(res.statusCode).toBe(200) expect(body.body).toBe(articles[0].body) done() - + it 'does not allow regular users to make new versions', (done) -> new_article = _.clone(articles[2]) - request.post {uri:url, json:new_article}, (err, res, body) -> + request.post {uri: url, json: new_article}, (err, res, body) -> expect(res.statusCode).toBe(403) done() it 'allows name changes from one version to the next', (done) -> loginAdmin -> new_article = _.clone(articles[0]) - new_article.name = "Yo mama now is the larger" - request.post {uri:url, json:new_article}, (err, res, body) -> + new_article.name = 'Yo mama now is the larger' + request.post {uri: url, json: new_article}, (err, res, body) -> expect(res.statusCode).toBe(200) expect(body.name).toBe(new_article.name) done() it 'get schema', (done) -> - request.get {uri:url+'/schema'}, (err, res, body) -> + request.get {uri: url+'/schema'}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body.type).toBeDefined() @@ -99,14 +99,14 @@ describe '/db/article', -> it 'does not allow naming an article a reserved word', (done) -> loginAdmin -> - new_article = {name: 'Names', body:'is a reserved word'} - request.post {uri:url, json:new_article}, (err, res, body) -> + new_article = {name: 'Names', body: 'is a reserved word'} + request.post {uri: url, json: new_article}, (err, res, body) -> expect(res.statusCode).toBe(422) done() - + it 'allows regular users to get all articles', (done) -> loginJoe -> - request.get {uri:url, json:{}}, (err, res, body) -> + request.get {uri: url, json: {}}, (err, res, body) -> expect(res.statusCode).toBe(200) expect(body.length).toBe(2) done() @@ -114,14 +114,14 @@ describe '/db/article', -> it 'allows regular users to get articles and use projection', (done) -> loginJoe -> # default projection - request.get {uri:url + '?project=true', json:{}}, (err, res, body) -> + request.get {uri: url + '?project=true', json: {}}, (err, res, body) -> expect(res.statusCode).toBe(200) expect(body.length).toBe(2) expect(body[0].created).toBeUndefined() expect(body[0].version).toBeDefined() # custom projection - request.get {uri:url + '?project=original', json:{}}, (err, res, body) -> + request.get {uri: url + '?project=original', json: {}}, (err, res, body) -> expect(res.statusCode).toBe(200) expect(body.length).toBe(2) expect(Object.keys(body[0]).length).toBe(2) @@ -130,10 +130,9 @@ describe '/db/article', -> it 'allows regular users to perform a text search', (done) -> loginJoe -> - request.get {uri:url + '?term="daddy"', json:{}}, (err, res, body) -> + request.get {uri: url + '?term="daddy"', json: {}}, (err, res, body) -> expect(res.statusCode).toBe(200) expect(body.length).toBe(1) expect(body[0].name).toBe(article2.name) expect(body[0].body).toBe(article2.body) done() - diff --git a/test/server/functional/auth.spec.coffee b/test/server/functional/auth.spec.coffee index 35bd0660f..b5ef55878 100644 --- a/test/server/functional/auth.spec.coffee +++ b/test/server/functional/auth.spec.coffee @@ -56,7 +56,7 @@ describe '/auth/login', -> it 'rejects wrong passwords', (done) -> req = request.post(urlLogin, (error, response) -> expect(response.statusCode).toBe(401) - expect(response.body.indexOf("wrong")).toBeGreaterThan(-1) + expect(response.body.indexOf('wrong')).toBeGreaterThan(-1) done() ) form = req.form() @@ -72,7 +72,6 @@ describe '/auth/login', -> form.append('username', 'scoTT@gmaIL.com') form.append('password', 'NaDa') - describe '/auth/reset', -> passwordReset = '' @@ -143,7 +142,7 @@ describe '/auth/unsubscribe', -> request.get getURL('/auth/whoami'), -> throw err if err done() - + it 'removes just recruitment emails if you include ?recruitNotes=1', (done) -> loginJoe (joe) -> url = getURL('/auth/unsubscribe?recruitNotes=1&email='+joe.get('email')) diff --git a/test/server/functional/db-id-version.spec.coffee b/test/server/functional/db-id-version.spec.coffee index 81433f4b5..564715841 100644 --- a/test/server/functional/db-id-version.spec.coffee +++ b/test/server/functional/db-id-version.spec.coffee @@ -7,27 +7,27 @@ describe '/db//version', -> throw err if err done() - article = {name: 'Yo', body:'yo ma'} + article = {name: 'Yo', body: 'yo ma'} url = getURL('/db/article') articles = {} it 'sets up', (done) -> loginAdmin -> - request.post {uri:url, json:article}, (err, res, body) -> + request.post {uri: url, json: article}, (err, res, body) -> expect(res.statusCode).toBe(200) articles[0] = body new_article = _.clone(articles[0]) new_article.body = '...' - request.post {uri:url, json:new_article}, (err, res, body) -> + request.post {uri: url, json: new_article}, (err, res, body) -> expect(res.statusCode).toBe(200) articles[1] = body new_article = _.clone(articles[1]) delete new_article.version - request.post {uri:url, json:new_article}, (err, res, body) -> + request.post {uri: url, json: new_article}, (err, res, body) -> expect(res.statusCode).toBe(200) articles[2] = body done() - + createVersionUrl = (versionString=null) -> original = articles[0]._id url = getURL("/db/article/#{original}/version") @@ -36,7 +36,7 @@ describe '/db//version', -> it 'can fetch the latest absolute version', (done) -> baseUrl = createVersionUrl() - request.get {uri:baseUrl}, (err, res, body) -> + request.get {uri: baseUrl}, (err, res, body) -> body = JSON.parse(body) expect(res.statusCode).toBe(200) expect(body.version.major).toBe(1) @@ -45,7 +45,7 @@ describe '/db//version', -> it 'can fetch the latest major version', (done) -> baseUrl = createVersionUrl('0') - request.get {uri:baseUrl}, (err, res, body) -> + request.get {uri: baseUrl}, (err, res, body) -> body = JSON.parse(body) expect(res.statusCode).toBe(200) expect(body.version.major).toBe(0) @@ -54,15 +54,15 @@ describe '/db//version', -> it 'can fetch a particular version', (done) -> baseUrl = createVersionUrl('0.0') - request.get {uri:baseUrl}, (err, res, body) -> + request.get {uri: baseUrl}, (err, res, body) -> body = JSON.parse(body) expect(res.statusCode).toBe(200) expect(body.version.major).toBe(0) expect(body.version.minor).toBe(0) done() - + it 'returns 404 when no doc is found', (done) -> baseUrl = createVersionUrl('3.14') - request.get {uri:baseUrl}, (err, res, body) -> + request.get {uri: baseUrl}, (err, res, body) -> expect(res.statusCode).toBe(404) done() diff --git a/test/server/functional/file.spec.coffee b/test/server/functional/file.spec.coffee index eba3d24e4..e7ad50702 100644 --- a/test/server/functional/file.spec.coffee +++ b/test/server/functional/file.spec.coffee @@ -7,7 +7,7 @@ xdescribe '/file', -> url = getURL('/file') files = [] options = { - uri:url + uri: url json: { # url: 'http://scotterickson.info/images/where-are-you.jpg' url: 'http://fc07.deviantart.net/fs37/f/2008/283/5/1/Chu_Chu_Pikachu_by_angelishi.gif' @@ -63,25 +63,25 @@ xdescribe '/file', -> request.post(options, func) it 'can be read by an admin.', (done) -> - request.get {uri:url+'/'+files[0]._id}, (err, res) -> + request.get {uri: url+'/'+files[0]._id}, (err, res) -> expect(res.statusCode).toBe(200) expect(res.headers['content-type']).toBe(files[0].contentType) done() it 'returns 404 for missing files', (done) -> id = '000000000000000000000000' - request.get {uri:url+'/'+id}, (err, res) -> + request.get {uri: url+'/'+id}, (err, res) -> expect(res.statusCode).toBe(404) done() it 'returns 404 for invalid ids', (done) -> - request.get {uri:url+'/thiswillnotwork'}, (err, res) -> + request.get {uri: url+'/thiswillnotwork'}, (err, res) -> expect(res.statusCode).toBe(404) done() it 'can be created directly with form parameters', (done) -> options2 = { - uri:url + uri: url } func = (err, res, body) -> @@ -112,7 +112,7 @@ xdescribe '/file', -> form.append('my_buffer', request(jsonOptions.my_buffer_url)) it 'created directly, can be read', (done) -> - request.get {uri:url+'/'+files[1]._id}, (err, res) -> + request.get {uri: url+'/'+files[1]._id}, (err, res) -> expect(res.statusCode).toBe(200) expect(res.headers['content-type']).toBe(files[1].contentType) done() @@ -133,7 +133,7 @@ xdescribe '/file', -> request.post(options, func) it 'does overwrite existing files if force is true', (done) -> - options.json.force = "true" # TODO ask why it's a string and not a boolean ? + options.json.force = 'true' # TODO ask why it's a string and not a boolean ? func = (err, res, body) -> expect(res.statusCode).toBe(200) @@ -150,25 +150,25 @@ xdescribe '/file', -> request.post(options, func) it ' can\'t be requested with HTTP PATCH method', (done) -> - request {method: 'patch', uri:url}, (err, res) -> + request {method: 'patch', uri: url}, (err, res) -> expect(res.statusCode).toBe(405) expect(res.headers.allow).toBe(allowHeader) done() it ' can\'t be requested with HTTP PUT method', (done) -> - request.put {uri:url}, (err, res) -> + request.put {uri: url}, (err, res) -> expect(res.statusCode).toBe(405) expect(res.headers.allow).toBe(allowHeader) done() it ' can\'t be requested with HTTP HEAD method', (done) -> - request.head {uri:url}, (err, res) -> + request.head {uri: url}, (err, res) -> expect(res.statusCode).toBe(405) expect(res.headers.allow).toBe(allowHeader) done() it ' can\'t be requested with HTTP DEL method', (done) -> - request.del {uri:url}, (err, res) -> + request.del {uri: url}, (err, res) -> expect(res.statusCode).toBe(405) expect(res.headers.allow).toBe(allowHeader) done() diff --git a/test/server/functional/folder.spec.coffee b/test/server/functional/folder.spec.coffee index e79ef6d63..e8ee823b2 100644 --- a/test/server/functional/folder.spec.coffee +++ b/test/server/functional/folder.spec.coffee @@ -17,7 +17,7 @@ describe 'folder', -> done() it 'can\'t be requested with HTTP PATCH method', (done) -> - request {method:'patch', uri: url}, (err, res, body) -> + request {method: 'patch', uri: url}, (err, res, body) -> expect(res.statusCode).toBe(405) expect(res.headers.allow).toBe(allowHeader) done() diff --git a/test/server/functional/languages.spec.coffee b/test/server/functional/languages.spec.coffee index f8ccba0df..a42f71722 100644 --- a/test/server/functional/languages.spec.coffee +++ b/test/server/functional/languages.spec.coffee @@ -17,7 +17,7 @@ describe 'languages', -> done() it 'can\'t be requested with HTTP PATCH method', (done) -> - request {method:'patch', uri: url}, (err, res, body) -> + request {method: 'patch', uri: url}, (err, res, body) -> expect(res.statusCode).toBe(405) expect(res.headers.allow).toBe(allowHeader) done() diff --git a/test/server/functional/level.spec.coffee b/test/server/functional/level.spec.coffee index edd163d0d..41d394aae 100644 --- a/test/server/functional/level.spec.coffee +++ b/test/server/functional/level.spec.coffee @@ -3,12 +3,12 @@ require '../common' describe 'Level', -> level = - name: "King's Peak 3" + name: 'King\'s Peak 3' description: 'Climb a mountain.' permissions: simplePermissions scripts: [] thangs: [] - documentation: {specificArticles:[], generalArticles:[]} + documentation: {specificArticles: [], generalArticles: []} urlLevel = '/db/level' @@ -19,12 +19,12 @@ describe 'Level', -> it 'can make a Level.', (done) -> loginJoe -> - request.post {uri:getURL(urlLevel), json:level}, (err, res, body) -> + request.post {uri: getURL(urlLevel), json: level}, (err, res, body) -> expect(res.statusCode).toBe(200) done() it 'get schema', (done) -> - request.get {uri:getURL(urlLevel+'/schema')}, (err, res, body) -> + request.get {uri: getURL(urlLevel+'/schema')}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body.type).toBeDefined() diff --git a/test/server/functional/level_component.spec.coffee b/test/server/functional/level_component.spec.coffee index e185657ba..d34ec82cb 100644 --- a/test/server/functional/level_component.spec.coffee +++ b/test/server/functional/level_component.spec.coffee @@ -3,11 +3,11 @@ require '../common' describe 'LevelComponent', -> component = - name:'BashesEverything' - description:'Makes the unit uncontrollably bash anything bashable, using the bash system.' + name: 'BashesEverything' + description: 'Makes the unit uncontrollably bash anything bashable, using the bash system.' code: 'bash();' codeLanguage: 'coffeescript' - permissions:simplePermissions + permissions: simplePermissions propertyDocumentation: [] system: 'ai' dependencies: [] @@ -23,13 +23,13 @@ describe 'LevelComponent', -> it 'can\'t be created by ordinary users.', (done) -> loginJoe -> - request.post {uri:url, json:component}, (err, res, body) -> + request.post {uri: url, json: component}, (err, res, body) -> expect(res.statusCode).toBe(403) done() it 'can be created by an admin.', (done) -> loginAdmin -> - request.post {uri:url, json:component}, (err, res, body) -> + request.post {uri: url, json: component}, (err, res, body) -> expect(res.statusCode).toBe(200) expect(body._id).toBeDefined() expect(body.name).toBe(component.name) @@ -47,13 +47,13 @@ describe 'LevelComponent', -> it 'have a unique name.', (done) -> loginAdmin -> - request.post {uri:url, json:component}, (err, res, body) -> + request.post {uri: url, json: component}, (err, res, body) -> expect(res.statusCode).toBe(409) done() it 'can be read by an admin.', (done) -> loginAdmin -> - request.get {uri:url+'/'+components[0]._id}, (err, res, body) -> + request.get {uri: url+'/'+components[0]._id}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body._id).toBe(components[0]._id) @@ -61,7 +61,7 @@ describe 'LevelComponent', -> it 'can be read by ordinary users.', (done) -> loginJoe -> - request.get {uri:url+'/'+components[0]._id}, (err, res, body) -> + request.get {uri: url+'/'+components[0]._id}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body._id).toBe(components[0]._id) @@ -85,7 +85,7 @@ describe 'LevelComponent', -> it 'is unofficial by default', (done) -> loginJoe -> - request.get {uri:url+'/'+components[0]._id}, (err, res, body) -> + request.get {uri: url+'/'+components[0]._id}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body._id).toBe(components[0]._id) @@ -94,24 +94,24 @@ describe 'LevelComponent', -> it 'has system ai by default', (done) -> loginJoe -> - request.get {uri:url+'/'+components[0]._id}, (err, res, body) -> + request.get {uri: url+'/'+components[0]._id}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body._id).toBe(components[0]._id) - expect(body.system).toBe("ai") + expect(body.system).toBe('ai') done() it 'official property isn\'t editable by an ordinary user.', (done) -> components[0].official = true loginJoe -> - request.post {uri:url, json:components[0]}, (err, res, body) -> + request.post {uri: url, json: components[0]}, (err, res, body) -> expect(res.statusCode).toBe(403) done() it 'official property is editable by an admin.', (done) -> components[0].official = true loginAdmin -> - request.post {uri:url, json:components[0]}, (err, res, body) -> + request.post {uri: url, json: components[0]}, (err, res, body) -> expect(res.statusCode).toBe(200) expect(body.official).toBe(true) expect(body.original).toBe(components[0].original) @@ -119,7 +119,7 @@ describe 'LevelComponent', -> expect(body.version.isLatestMajor).toBe(true) components[1] = body - request.get {uri:url+'/'+components[0]._id}, (err, res, body) -> + request.get {uri: url+'/'+components[0]._id}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body._id).toBe(components[0]._id) @@ -129,22 +129,22 @@ describe 'LevelComponent', -> done() xit ' can\'t be requested with HTTP PUT method', (done) -> - request.put {uri:url+'/'+components[0]._id}, (err, res) -> + request.put {uri: url+'/'+components[0]._id}, (err, res) -> expect(res.statusCode).toBe(405) done() it ' can\'t be requested with HTTP HEAD method', (done) -> - request.head {uri:url+'/'+components[0]._id}, (err, res) -> + request.head {uri: url+'/'+components[0]._id}, (err, res) -> expect(res.statusCode).toBe(405) done() it ' can\'t be requested with HTTP DEL method', (done) -> - request.del {uri:url+'/'+components[0]._id}, (err, res) -> + request.del {uri: url+'/'+components[0]._id}, (err, res) -> expect(res.statusCode).toBe(405) done() it 'get schema', (done) -> - request.get {uri:url+'/schema'}, (err, res, body) -> + request.get {uri: url+'/schema'}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body.type).toBeDefined() diff --git a/test/server/functional/level_feedback.spec.coffee b/test/server/functional/level_feedback.spec.coffee index 95f4b6eb0..4cd0da0de 100644 --- a/test/server/functional/level_feedback.spec.coffee +++ b/test/server/functional/level_feedback.spec.coffee @@ -5,7 +5,7 @@ describe 'LevelFeedback', -> url = getURL('/db/level.feedback') it 'get schema', (done) -> - request.get {uri:url+'/schema'}, (err, res, body) -> + request.get {uri: url+'/schema'}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body.type).toBeDefined() diff --git a/test/server/functional/level_session.spec.coffee b/test/server/functional/level_session.spec.coffee index aa8d99c7b..ba0265cf0 100644 --- a/test/server/functional/level_session.spec.coffee +++ b/test/server/functional/level_session.spec.coffee @@ -5,7 +5,7 @@ describe 'LevelFeedback', -> url = getURL('/db/level.session') it 'get schema', (done) -> - request.get {uri:url+'/schema'}, (err, res, body) -> + request.get {uri: url+'/schema'}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body.type).toBeDefined() diff --git a/test/server/functional/level_system.spec.coffee b/test/server/functional/level_system.spec.coffee index a84c75308..7d5c1e488 100644 --- a/test/server/functional/level_system.spec.coffee +++ b/test/server/functional/level_system.spec.coffee @@ -3,14 +3,14 @@ require '../common' describe 'LevelSystem', -> system = - name:'Bashing' - description:'Performs Thang bashing updates for Bashes Thangs.' + name: 'Bashing' + description: 'Performs Thang bashing updates for Bashes Thangs.' code: """class Bashing extends System constructor: (world) -> super world """ codeLanguage: 'coffeescript' - permissions:simplePermissions + permissions: simplePermissions dependencies: [] propertyDocumentation: [] @@ -25,13 +25,13 @@ describe 'LevelSystem', -> it 'can\'t be created by ordinary users.', (done) -> loginJoe -> - request.post {uri:url, json:system}, (err, res, body) -> + request.post {uri: url, json: system}, (err, res, body) -> expect(res.statusCode).toBe(403) done() it 'can be created by an admin.', (done) -> loginAdmin -> - request.post {uri:url, json:system}, (err, res, body) -> + request.post {uri: url, json: system}, (err, res, body) -> expect(res.statusCode).toBe(200) expect(body._id).toBeDefined() expect(body.name).toBe(system.name) @@ -49,13 +49,13 @@ describe 'LevelSystem', -> it 'have a unique name.', (done) -> loginAdmin -> - request.post {uri:url, json:system}, (err, res, body) -> + request.post {uri: url, json: system}, (err, res, body) -> expect(res.statusCode).toBe(409) done() it 'can be read by an admin.', (done) -> loginAdmin -> - request.get {uri:url+'/'+systems[0]._id}, (err, res, body) -> + request.get {uri: url+'/'+systems[0]._id}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body._id).toBe(systems[0]._id) @@ -63,7 +63,7 @@ describe 'LevelSystem', -> it 'can be read by ordinary users.', (done) -> loginJoe -> - request.get {uri:url+'/'+systems[0]._id}, (err, res, body) -> + request.get {uri: url+'/'+systems[0]._id}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body._id).toBe(systems[0]._id) @@ -87,7 +87,7 @@ describe 'LevelSystem', -> it 'is unofficial by default', (done) -> loginJoe -> - request.get {uri:url+'/'+systems[0]._id}, (err, res, body) -> + request.get {uri: url+'/'+systems[0]._id}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body._id).toBe(systems[0]._id) @@ -97,14 +97,14 @@ describe 'LevelSystem', -> it 'official property isn\'t editable by an ordinary user.', (done) -> systems[0].official = true loginJoe -> - request.post {uri:url, json:systems[0]}, (err, res, body) -> + request.post {uri: url, json: systems[0]}, (err, res, body) -> expect(res.statusCode).toBe(403) done() it 'official property is editable by an admin.', (done) -> systems[0].official = true loginAdmin -> - request.post {uri:url, json:systems[0]}, (err, res, body) -> + request.post {uri: url, json: systems[0]}, (err, res, body) -> expect(res.statusCode).toBe(200) expect(body.official).toBe(true) expect(body.original).toBe(systems[0].original) @@ -112,7 +112,7 @@ describe 'LevelSystem', -> expect(body.version.isLatestMajor).toBe(true) systems[1] = body - request.get {uri:url+'/'+systems[0]._id}, (err, res, body) -> + request.get {uri: url+'/'+systems[0]._id}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body._id).toBe(systems[0]._id) @@ -122,17 +122,17 @@ describe 'LevelSystem', -> done() it ' can\'t be requested with HTTP HEAD method', (done) -> - request.head {uri:url+'/'+systems[0]._id}, (err, res) -> + request.head {uri: url+'/'+systems[0]._id}, (err, res) -> expect(res.statusCode).toBe(405) done() it ' can\'t be requested with HTTP DEL method', (done) -> - request.del {uri:url+'/'+systems[0]._id}, (err, res) -> + request.del {uri: url+'/'+systems[0]._id}, (err, res) -> expect(res.statusCode).toBe(405) done() it 'get schema', (done) -> - request.get {uri:url+'/schema'}, (err, res, body) -> + request.get {uri: url+'/schema'}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body.type).toBeDefined() diff --git a/test/server/functional/level_thang_component.spec.coffee b/test/server/functional/level_thang_component.spec.coffee index 75e334a7a..d3d7e46b4 100644 --- a/test/server/functional/level_thang_component.spec.coffee +++ b/test/server/functional/level_thang_component.spec.coffee @@ -5,7 +5,7 @@ describe 'Level Thang Component', -> url = getURL('/db/thang.component') it 'get schema', (done) -> - request.get {uri:url+'/schema'}, (err, res, body) -> + request.get {uri: url+'/schema'}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body.type).toBeDefined() diff --git a/test/server/functional/level_thang_type.spec.coffee b/test/server/functional/level_thang_type.spec.coffee index 152514951..7d31d8747 100644 --- a/test/server/functional/level_thang_type.spec.coffee +++ b/test/server/functional/level_thang_type.spec.coffee @@ -5,7 +5,7 @@ describe 'Level Thang Type', -> url = getURL('/db/thang.type') it 'get schema', (done) -> - request.get {uri:url+'/schema'}, (err, res, body) -> + request.get {uri: url+'/schema'}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body.type).toBeDefined() diff --git a/test/server/functional/mail.spec.coffee b/test/server/functional/mail.spec.coffee index 0910aab6f..87127865b 100644 --- a/test/server/functional/mail.spec.coffee +++ b/test/server/functional/mail.spec.coffee @@ -23,10 +23,10 @@ describe 'handleProfileUpdate', -> expect(u.isEmailSubscriptionEnabled('ambassadorNews')).toBeTruthy() expect(u.isEmailSubscriptionEnabled('artisanNews')).toBeTruthy() done() - + describe 'handleUnsubscribe', -> it 'turns off all news and notifications', (done) -> - u = new User({generalNews: {enabled:true}, archmageNews: {enabled:true}, anyNotes: {enabled:true}}) + u = new User({generalNews: {enabled: true}, archmageNews: {enabled: true}, anyNotes: {enabled: true}}) mail.handleUnsubscribe(u) expect(u.isEmailSubscriptionEnabled('generalNews')).toBeFalsy() expect(u.isEmailSubscriptionEnabled('adventurerNews')).toBeFalsy() diff --git a/test/server/functional/patch.spec.coffee b/test/server/functional/patch.spec.coffee index 9d0f4265d..d75c3d2cf 100644 --- a/test/server/functional/patch.spec.coffee +++ b/test/server/functional/patch.spec.coffee @@ -7,7 +7,7 @@ describe '/db/patch', -> throw err if err done() - article = {name: 'Yo', body:'yo ma'} + article = {name: 'Yo', body: 'yo ma'} articleURL = getURL('/db/article') articles = {} @@ -15,20 +15,20 @@ describe '/db/patch', -> patches = {} patch = commitMessage: 'Accept this patch!' - delta: {name:['test']} + delta: {name: ['test']} editPath: '/who/knows/yes' target: - id:null + id: null collection: 'article' it 'creates an Article to patch', (done) -> loginAdmin -> - request.post {uri:articleURL, json:article}, (err, res, body) -> + request.post {uri: articleURL, json: article}, (err, res, body) -> articles[0] = body patch.target.id = articles[0]._id done() - it "allows someone to submit a patch to something they don't control", (done) -> + it 'allows someone to submit a patch to something they don\'t control', (done) -> loginJoe (joe) -> request.post {uri: patchURL, json: patch}, (err, res, body) -> expect(res.statusCode).toBe(200) @@ -40,23 +40,23 @@ describe '/db/patch', -> expect(body.creator).toBe(joe.id) patches[0] = body done() - + it 'adds a patch to the target document', (done) -> Article.findOne({}).exec (err, article) -> expect(article.toObject().patches[0]).toBeDefined() done() - + it 'shows up in patch requests', (done) -> patchesURL = getURL("/db/article/#{articles[0]._id}/patches") request.get {uri: patchesURL}, (err, res, body) -> body = JSON.parse(body) expect(res.statusCode).toBe(200) expect(body.length).toBe(1) - done() - + done() + it 'allows you to set yourself as watching', (done) -> watchingURL = getURL("/db/article/#{articles[0]._id}/watch") - request.put {uri: watchingURL, json: {on:true}}, (err, res, body) -> + request.put {uri: watchingURL, json: {on: true}}, (err, res, body) -> expect(body.watchers[1]).toBeDefined() done() @@ -67,44 +67,44 @@ describe '/db/patch', -> it 'does not add duplicate watchers', (done) -> watchingURL = getURL("/db/article/#{articles[0]._id}/watch") - request.put {uri: watchingURL, json: {on:true}}, (err, res, body) -> + request.put {uri: watchingURL, json: {on: true}}, (err, res, body) -> expect(body.watchers.length).toBe(2) done() - + it 'allows removing yourself', (done) -> watchingURL = getURL("/db/article/#{articles[0]._id}/watch") - request.put {uri: watchingURL, json: {on:false}}, (err, res, body) -> + request.put {uri: watchingURL, json: {on: false}}, (err, res, body) -> expect(body.watchers.length).toBe(1) done() - + it 'allows the submitter to withdraw the pull request', (done) -> statusURL = getURL("/db/patch/#{patches[0]._id}/status") - request.put {uri: statusURL, json: {status:'withdrawn'}}, (err, res, body) -> + request.put {uri: statusURL, json: {status: 'withdrawn'}}, (err, res, body) -> expect(res.statusCode).toBe(200) Patch.findOne({}).exec (err, article) -> expect(article.get('status')).toBe 'withdrawn' Article.findOne({}).exec (err, article) -> expect(article.toObject().patches.length).toBe(0) done() - + it 'does not allow the submitter to reject or accept the pull request', (done) -> statusURL = getURL("/db/patch/#{patches[0]._id}/status") - request.put {uri: statusURL, json: {status:'rejected'}}, (err, res, body) -> + request.put {uri: statusURL, json: {status: 'rejected'}}, (err, res, body) -> expect(res.statusCode).toBe(403) - request.put {uri: statusURL, json: {status:'accepted'}}, (err, res, body) -> + request.put {uri: statusURL, json: {status: 'accepted'}}, (err, res, body) -> expect(res.statusCode).toBe(403) Patch.findOne({}).exec (err, article) -> expect(article.get('status')).toBe 'withdrawn' done() - + it 'allows the recipient to accept or reject the pull request', (done) -> statusURL = getURL("/db/patch/#{patches[0]._id}/status") loginAdmin -> - request.put {uri: statusURL, json: {status:'rejected'}}, (err, res, body) -> + request.put {uri: statusURL, json: {status: 'rejected'}}, (err, res, body) -> expect(res.statusCode).toBe(200) Patch.findOne({}).exec (err, article) -> expect(article.get('status')).toBe 'rejected' - request.put {uri: statusURL, json: {status:'accepted'}}, (err, res, body) -> + request.put {uri: statusURL, json: {status: 'accepted'}}, (err, res, body) -> expect(res.statusCode).toBe(200) Patch.findOne({}).exec (err, article) -> expect(article.get('status')).toBe 'accepted' @@ -112,8 +112,8 @@ describe '/db/patch', -> it 'does not allow the recipient to withdraw the pull request', (done) -> statusURL = getURL("/db/patch/#{patches[0]._id}/status") - request.put {uri: statusURL, json: {status:'withdrawn'}}, (err, res, body) -> + request.put {uri: statusURL, json: {status: 'withdrawn'}}, (err, res, body) -> expect(res.statusCode).toBe(403) Patch.findOne({}).exec (err, article) -> expect(article.get('status')).toBe 'accepted' - done() \ No newline at end of file + done() diff --git a/test/server/functional/queue.spec.coffee b/test/server/functional/queue.spec.coffee index c59ff409b..a290168fa 100644 --- a/test/server/functional/queue.spec.coffee +++ b/test/server/functional/queue.spec.coffee @@ -5,7 +5,7 @@ describe 'queue', -> allowHeader = 'GET, POST, PUT' xit 'can\'t be requested with HTTP PATCH method', (done) -> - request {method:'patch', uri: someURL}, (err, res, body) -> + request {method: 'patch', uri: someURL}, (err, res, body) -> expect(res.statusCode).toBe(405) expect(res.headers.allow).toBe(allowHeader) done() @@ -21,5 +21,3 @@ describe 'queue', -> expect(res.statusCode).toBe(405) expect(res.headers.allow).toBe(allowHeader) done() - - diff --git a/test/server/functional/user.spec.coffee b/test/server/functional/user.spec.coffee index 03a88242d..5395566a4 100644 --- a/test/server/functional/user.spec.coffee +++ b/test/server/functional/user.spec.coffee @@ -5,7 +5,7 @@ User = require '../../../server/users/User' urlUser = '/db/user' describe 'Server user object', -> - + it 'uses the schema defaults to fill in email preferences', (done) -> user = new User() expect(user.isEmailSubscriptionEnabled('generalNews')).toBeTruthy() @@ -25,9 +25,9 @@ describe 'Server user object', -> user = new User() user.set 'emailSubscriptions', ['tester'] user.setEmailSubscription('artisanNews', true) - expect(JSON.stringify(user.get('emailSubscriptions'))).toBe(JSON.stringify(['tester','level_creator'])) + expect(JSON.stringify(user.get('emailSubscriptions'))).toBe(JSON.stringify(['tester', 'level_creator'])) done() - + describe 'User.updateMailChimp', -> makeMC = (callback) -> GLOBAL.mc = @@ -39,7 +39,7 @@ describe 'User.updateMailChimp', -> expect(JSON.stringify(params.merge_vars.groupings[0].groups)).toBe(JSON.stringify(['Announcements'])) done() - user = new User({emailSubscriptions:['announcement'], email:'tester@gmail.com'}) + user = new User({emailSubscriptions: ['announcement'], email: 'tester@gmail.com'}) User.updateMailChimp(user) describe 'POST /db/user', -> @@ -53,7 +53,7 @@ describe 'POST /db/user', -> res = JSON.parse(response.body) expect(res.anonymous).toBeTruthy() expect(res.name).toEqual('Jim') - done() + done() ) form = req.form() form.append('name', 'Jim') @@ -118,12 +118,12 @@ describe 'POST /db/user', -> request.get getURL('/auth/whoami'), -> req = request.post(getURL('/db/user'), (err, response) -> expect(response.statusCode).toBe(409) - done() + done() ) form = req.form() form.append('name', 'Jim') - req = request.post(getURL('/db/user'), (err,response,body) -> + req = request.post(getURL('/db/user'), (err, response, body) -> expect(response.statusCode).toBe(200) request.get getURL('/auth/whoami'), (request, response, body) -> res = JSON.parse(response.body) @@ -134,7 +134,6 @@ describe 'POST /db/user', -> form.append('email', 'new@user.com') form.append('password', 'new') - describe 'PUT /db/user', -> it 'logs in as normal joe', (done) -> @@ -165,8 +164,8 @@ describe 'PUT /db/user', -> done() form = req.form() form.append('_id', joe.id) - form.append('email', "farghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlar -ghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghl") + form.append('email', 'farghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlar +ghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghl') it 'logs in as admin', (done) -> loginAdmin -> done() @@ -178,7 +177,7 @@ ghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghl done() form = req.form() form.append('_id', '513108d4cb8b610000000004') - form.append('email', "perfectly@good.com") + form.append('email', 'perfectly@good.com') it 'denies if the email being changed is already taken', (done) -> unittest.getNormalJoe (joe) -> @@ -226,7 +225,7 @@ describe 'GET /db/user', -> form.append('password', '80yqxpb38j') it 'get schema', (done) -> - request.get {uri:getURL(urlUser+'/schema')}, (err, res, body) -> + request.get {uri: getURL(urlUser+'/schema')}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body.type).toBeDefined() diff --git a/test/server/integration/models/Level.spec.coffee b/test/server/integration/models/Level.spec.coffee index e74daaccb..1067da955 100644 --- a/test/server/integration/models/Level.spec.coffee +++ b/test/server/integration/models/Level.spec.coffee @@ -3,7 +3,7 @@ require '../../common' describe 'Level', -> level = new Level( - name: "King's Peak" + name: 'King\'s Peak' description: 'Climb a mountain!!!' permissions: simplePermissions original: new ObjectId() diff --git a/test/server/integration/models/LevelComponent.spec.coffee b/test/server/integration/models/LevelComponent.spec.coffee index 6936fa86f..782721cd5 100644 --- a/test/server/integration/models/LevelComponent.spec.coffee +++ b/test/server/integration/models/LevelComponent.spec.coffee @@ -3,12 +3,12 @@ require '../../common' describe 'LevelComponent', -> raw = - name:'Bashes Everything' - description:'Makes the unit uncontrollably bash anything bashable, using the bash system.' + name: 'Bashes Everything' + description: 'Makes the unit uncontrollably bash anything bashable, using the bash system.' code: 'bash();' codeLanguage: 'javascript' official: true - permissions:simplePermissions + permissions: simplePermissions comp = new LevelComponent(raw) @@ -21,4 +21,3 @@ describe 'LevelComponent', -> comp.save (err) -> expect(err).toBeNull() done() - diff --git a/test/server/integration/models/LevelSession.spec.coffee b/test/server/integration/models/LevelSession.spec.coffee index ecfeefd32..1b3f6afd9 100644 --- a/test/server/integration/models/LevelSession.spec.coffee +++ b/test/server/integration/models/LevelSession.spec.coffee @@ -15,5 +15,3 @@ describe 'LevelSession', -> session.save (err) -> throw err if err done() - - diff --git a/test/server/integration/models/LevelSystem.spec.coffee b/test/server/integration/models/LevelSystem.spec.coffee index d61cd98e0..15cbbe474 100644 --- a/test/server/integration/models/LevelSystem.spec.coffee +++ b/test/server/integration/models/LevelSystem.spec.coffee @@ -3,15 +3,15 @@ require '../../common' describe 'LevelSystem', -> raw = - name:'Bashing' - description:'Performs Thang bashing updates for Bashes Thangs.' + name: 'Bashing' + description: 'Performs Thang bashing updates for Bashes Thangs.' code: """class Bashing extends System constructor: (world) -> super world """ codeLanguage: 'coffeescript' official: true - permissions:simplePermissions + permissions: simplePermissions comp = new LevelSystem(raw) diff --git a/test/server/integration/models/article.spec.coffee b/test/server/integration/models/article.spec.coffee index 51ba6e423..6ce3fb047 100644 --- a/test/server/integration/models/article.spec.coffee +++ b/test/server/integration/models/article.spec.coffee @@ -8,6 +8,6 @@ describe 'Article', -> done() it 'can be saved', (done) -> - article = new Article(name:'List Comprehension', body:"A programmer's best friend.") + article = new Article(name: 'List Comprehension', body: "A programmer's best friend.") article.save (err) -> - done() \ No newline at end of file + done() diff --git a/test/server/integration/models/plugins.spec.coffee b/test/server/integration/models/plugins.spec.coffee index b01c74ef5..e7921fba7 100644 --- a/test/server/integration/models/plugins.spec.coffee +++ b/test/server/integration/models/plugins.spec.coffee @@ -3,7 +3,7 @@ require '../../common' describe 'NamePlugin', -> article = new Article( - name: "Alpha" + name: 'Alpha' body: 'What does it mean?' ) @@ -19,17 +19,17 @@ describe 'NamePlugin', -> it 'does not allow name conflicts', (done) -> c2 = new Article( - name: "Alpha" + name: 'Alpha' body: 'The misunderstood Greek character.' ) c2.save (err) -> expect(err.code).toBe(409) done() - + it 'prevents slugs from being valid ObjectIds', (done) -> c2 = new Article( - name: "522e0f149aaa330000000002" + name: '522e0f149aaa330000000002' body: '... fish.' ) @@ -37,7 +37,6 @@ describe 'NamePlugin', -> expect(err.code).toBe(422) done() - describe 'VersionedPlugin', -> it 'clears things first', (done) -> clearModels [Article], (err) -> @@ -45,43 +44,43 @@ describe 'VersionedPlugin', -> done() it 'can create new major versions', (done) -> - firstArticle = new Article(name:'List Comp1', body:"A programmer's best friend.") + firstArticle = new Article(name: 'List Comp1', body: "A programmer's best friend.") firstArticle.original = firstArticle._id - + firstArticle.save (err) -> throw err if err - + secondObject = firstArticle.toObject() - secondObject['body'] = "Not as good as lambda." - + secondObject['body'] = 'Not as good as lambda.' + firstArticle.makeNewMajorVersion secondObject, (err, secondArticle) -> throw err if err - + secondArticle.save (err) -> throw err if err - + thirdObject = secondArticle.toObject() - thirdObject['body'] = "..." - + thirdObject['body'] = '...' + secondArticle.makeNewMajorVersion thirdObject, (err, thirdArticle) -> throw err if err - + thirdArticle.save -> - - Article.find {original:firstArticle.original}, (err, results) -> + + Article.find {original: firstArticle.original}, (err, results) -> expect(results.length).toBe(3) expect(results[0].version.major).toBe(2) expect(results[1].version.major).toBe(1) expect(results[2].version.major).toBe(0) - + expect(results[0].version.minor).toBe(0) expect(results[1].version.minor).toBe(0) expect(results[2].version.minor).toBe(0) - + expect(results[2].version.isLatestMajor).toBe(false) expect(results[1].version.isLatestMajor).toBe(false) expect(results[0].version.isLatestMajor).toBe(true) - + expect(results[2].version.isLatestMinor).toBe(true) expect(results[1].version.isLatestMinor).toBe(true) expect(results[0].version.isLatestMinor).toBe(true) @@ -91,63 +90,63 @@ describe 'VersionedPlugin', -> expect(results[0].index).toBe(true) done() - + it 'works if you do not successfully save the new major version', (done) -> - firstArticle = new Article(name:'List Comp2', body:"A programmer's best friend.") + firstArticle = new Article(name: 'List Comp2', body: "A programmer's best friend.") firstArticle.original = firstArticle._id - + firstArticle.save (err) -> throw err if err - + secondObject = firstArticle.toObject() - secondObject['body'] = "Not as good as lambda." - + secondObject['body'] = 'Not as good as lambda.' + firstArticle.makeNewMajorVersion secondObject, (err, forgottenSecondArticle) -> throw err if err - + firstArticle.makeNewMajorVersion secondObject, (err, realSecondArticle) -> throw err if err expect(realSecondArticle.version.major).toBe(1) done() - + it 'can create new minor versions', (done) -> - firstArticle = new Article(name:'List Comp3', body:"A programmer's best friend.") + firstArticle = new Article(name: 'List Comp3', body: "A programmer's best friend.") firstArticle.original = firstArticle._id - + firstArticle.save (err) -> throw err if err - + secondObject = firstArticle.toObject() - secondObject['body'] = "Not as good as lambda." - + secondObject['body'] = 'Not as good as lambda.' + firstArticle.makeNewMinorVersion secondObject, 0, (err, secondArticle) -> throw err if err - + secondArticle.save (err) -> throw err if err - + thirdObject = secondArticle.toObject() - thirdObject['body'] = "..." - + thirdObject['body'] = '...' + secondArticle.makeNewMinorVersion thirdObject, 0, (err, thirdArticle) -> throw err if err - + thirdArticle.save -> - - Article.find {original:firstArticle.original}, (err, results) -> + + Article.find {original: firstArticle.original}, (err, results) -> expect(results.length).toBe(3) expect(results[0].version.major).toBe(0) expect(results[1].version.major).toBe(0) expect(results[2].version.major).toBe(0) - + expect(results[2].version.minor).toBe(0) expect(results[1].version.minor).toBe(1) expect(results[0].version.minor).toBe(2) - + expect(results[2].version.isLatestMajor).toBe(false) expect(results[1].version.isLatestMajor).toBe(false) expect(results[0].version.isLatestMajor).toBe(true) - + expect(results[2].version.isLatestMinor).toBe(false) expect(results[1].version.isLatestMinor).toBe(false) expect(results[0].version.isLatestMinor).toBe(true) @@ -157,38 +156,38 @@ describe 'VersionedPlugin', -> expect(results[0].index).toBe(true) done() - + it 'works if you do not successfully save the new minor version', (done) -> firstArticle = new Article( - name:'List Comp4', - body:"A programmer's best friend." + name: 'List Comp4', + body: "A programmer's best friend." index: true ) firstArticle.original = firstArticle._id - + firstArticle.save (err) -> throw err if err - + secondObject = firstArticle.toObject() - secondObject['body'] = "Not as good as lambda." - + secondObject['body'] = 'Not as good as lambda.' + firstArticle.makeNewMinorVersion secondObject, 0, (err, forgottenSecondArticle) -> throw err if err - + firstArticle.makeNewMinorVersion secondObject, 0, (err, realSecondArticle) -> throw err if err expect(realSecondArticle.version.minor).toBe(1) done() it 'works if you add a new minor version for an old major version', (done) -> - firstArticle = new Article(name:'List Comp4.5', body:"A programmer's best friend.") + firstArticle = new Article(name: 'List Comp4.5', body: "A programmer's best friend.") firstArticle.original = firstArticle._id firstArticle.save (err) -> throw err if err secondObject = firstArticle.toObject() - secondObject['body'] = "Not as good as lambda." + secondObject['body'] = 'Not as good as lambda.' firstArticle.makeNewMajorVersion secondObject, (err, secondArticle) -> throw err if err @@ -197,47 +196,47 @@ describe 'VersionedPlugin', -> throw err if err thirdObject = secondArticle.toObject() - thirdObject['body'] = "..." - + thirdObject['body'] = '...' + Article.findOne {_id: firstArticle._id}, (err, firstArticle) -> - + firstArticle.makeNewMinorVersion thirdObject, 0, (err, thirdArticle) -> throw err if err - + thirdArticle.save -> - - Article.find {original:firstArticle.original}, (err, results) -> + + Article.find {original: firstArticle.original}, (err, results) -> expect(results.length).toBe(3) expect(results[2].version.major).toBe(0) expect(results[1].version.major).toBe(0) expect(results[0].version.major).toBe(1) - + expect(results[2].version.minor).toBe(0) expect(results[1].version.minor).toBe(1) expect(results[0].version.minor).toBe(0) - + expect(results[2].version.isLatestMajor).toBe(false) expect(results[1].version.isLatestMajor).toBe(false) expect(results[0].version.isLatestMajor).toBe(true) - + expect(results[2].version.isLatestMinor).toBe(false) expect(results[1].version.isLatestMinor).toBe(true) expect(results[0].version.isLatestMinor).toBe(true) - + expect(results[2].index).toBeUndefined() expect(results[1].index).toBeUndefined() expect(results[0].index).toBe(true) done() - + it 'only keeps slugs for the absolute latest versions', (done) -> - firstArticle = new Article(name:'List Comp4.6', body:"A programmer's best friend.") + firstArticle = new Article(name: 'List Comp4.6', body: "A programmer's best friend.") firstArticle.original = firstArticle._id firstArticle.save (err) -> throw err if err secondObject = firstArticle.toObject() - secondObject['body'] = "Not as good as lambda." + secondObject['body'] = 'Not as good as lambda.' firstArticle.makeNewMajorVersion secondObject, (err, secondArticle) -> throw err if err @@ -246,7 +245,7 @@ describe 'VersionedPlugin', -> throw err if err thirdObject = secondArticle.toObject() - thirdObject['body'] = "..." + thirdObject['body'] = '...' Article.findOne {_id: firstArticle._id}, (err, firstArticle) -> @@ -255,7 +254,7 @@ describe 'VersionedPlugin', -> thirdArticle.save -> - Article.find {original:firstArticle.original}, (err, results) -> + Article.find {original: firstArticle.original}, (err, results) -> expect(results.length).toBe(3) expect(results[2].slug).toBeUndefined() expect(results[1].slug).toBeUndefined() @@ -272,16 +271,16 @@ describe 'SearchablePlugin', -> it 'can do a text search', (done) -> # absolutely does not work at all if you don't save an article first firstArticle = new Article( - name:'List Comp5', - body:"A programmer's best friend.", - index:true + name: 'List Comp5', + body: "A programmer's best friend.", + index: true ) firstArticle.original = firstArticle._id firstArticle.save (err) -> throw err if err - Article.textSearch 'best', {filter:{ index: true}}, (err, results) -> + Article.textSearch 'best', {filter: {index: true}}, (err, results) -> expect(err).toBeNull() if results expect(results.results.length).toBeGreaterThan(0) @@ -289,16 +288,15 @@ describe 'SearchablePlugin', -> console.log('ERROR:', err) done() - it 'keeps the index property up to date', (done) -> - firstArticle = new Article(name:'List Comp6', body:"A programmer's best friend.") + firstArticle = new Article(name: 'List Comp6', body: "A programmer's best friend.") firstArticle.original = firstArticle._id firstArticle.save (err) -> throw err if err secondObject = firstArticle.toObject() - secondObject['body'] = "Not as good as lambda." + secondObject['body'] = 'Not as good as lambda.' firstArticle.makeNewMinorVersion secondObject, 0, (err, secondArticle) -> throw err if err @@ -307,7 +305,7 @@ describe 'SearchablePlugin', -> throw err if err thirdObject = secondArticle.toObject() - thirdObject['body'] = "..." + thirdObject['body'] = '...' secondArticle.makeNewMajorVersion thirdObject, (err, thirdArticle) -> throw err if err @@ -315,16 +313,16 @@ describe 'SearchablePlugin', -> thirdArticle.save -> throw err if err - Article.find {original:firstArticle.original}, (err, results) -> + Article.find {original: firstArticle.original}, (err, results) -> expect(results[2].index).toBeUndefined() expect(results[1].index).toBeUndefined() expect(results[0].index).toBe(true) done() raw = - name:'Battlefield 1942' - description:'Vacation all over the world!' - permissions:[ - target:'not_the_public' - access:'owner' + name: 'Battlefield 1942' + description: 'Vacation all over the world!' + permissions: [ + target: 'not_the_public' + access: 'owner' ] diff --git a/test/server/unit/user.spec.coffee b/test/server/unit/user.spec.coffee index 00e1cba17..e5173146d 100644 --- a/test/server/unit/user.spec.coffee +++ b/test/server/unit/user.spec.coffee @@ -1,4 +1,4 @@ -GLOBAL._ = require('lodash') +GLOBAL._ = require 'lodash' User = require '../../../server/users/User' @@ -21,4 +21,3 @@ describe 'user', -> classicUser.set('permissions', ['user']) expect(classicUser.isAdmin()).toBeFalsy() done() - diff --git a/test/vendor/example.coffee b/test/vendor/example.coffee index d055d440e..d08284dc1 100644 --- a/test/vendor/example.coffee +++ b/test/vendor/example.coffee @@ -1 +1 @@ -massivelyUsefulTestExample = "test..." +massivelyUsefulTestExample = 'test...'