diff --git a/app/lib/Buddha.coffee b/app/lib/Buddha.coffee index 33af9d742..25ac3e21e 100644 --- a/app/lib/Buddha.coffee +++ b/app/lib/Buddha.coffee @@ -72,7 +72,7 @@ class Angel return if @aborting unless serialized # We're only interested in goalStates. (Simulator) - @latestGoalStates = goalStates; + @latestGoalStates = goalStates Backbone.Mediator.publish('god:goals-calculated', goalStates: goalStates) @running = false @shared.busyAngels.pop @ @@ -95,7 +95,7 @@ class Angel @shared.goalManager?.world = world @running = false @shared.busyAngels.pop @ - @shared.firstWorld = false; + @shared.firstWorld = false @doWork() infinitelyLooped: => @@ -111,7 +111,7 @@ class Angel doWork: => #console.log "work." return if @aborted - console.log @id + " ready and looking for work. WorkQueue lenght is " + @shared.workQueue.length + console.log @id + " ready and looking for work. WorkQueue length is " + @shared.workQueue.length if @initialized and @shared.workQueue.length work = @shared.workQueue.pop() if work is Angel.cyanide # Kill all other Angels, too diff --git a/app/lib/God.coffee b/app/lib/God.coffee index 3bca0b1d8..b036b2467 100644 --- a/app/lib/God.coffee +++ b/app/lib/God.coffee @@ -92,7 +92,7 @@ module.exports = class God #console.log "UserCodeProblem:", '"' + problem.message + '"', "for", problem.userInfo.thangID, "-", problem.userInfo.methodName, 'at line', problem.ranges?[0][0][0], 'column', problem.ranges?[0][0][1] Backbone.Mediator.publish 'god:user-code-problem', problem: problem - createWorld: (spells) -> + createWorld: (@spells) -> #console.log @id + ': "Let there be light upon', @world.name + '!"' unless Worker? # profiling world simulation is easier on main thread, or we are IE9 setTimeout @simulateWorld, 1 @@ -121,7 +121,7 @@ module.exports = class God beholdWorld: (angel, serialized, goalStates) -> unless serialized # We're only interested in goalStates. - @latestGoalStates = goalStates; + @latestGoalStates = goalStates Backbone.Mediator.publish('god:goals-calculated', goalStates: goalStates, team: me.team) unless _.find @angels, 'busy' @spells = null # Don't hold onto old spells; memory leaks diff --git a/app/lib/LevelLoader.coffee b/app/lib/LevelLoader.coffee index a276d0364..ac1e77601 100644 --- a/app/lib/LevelLoader.coffee +++ b/app/lib/LevelLoader.coffee @@ -155,6 +155,7 @@ module.exports = class LevelLoader extends CocoClass # Building sprite sheets buildSpriteSheetsForThangType: (thangType) -> + return if @headless @grabThangTypeTeams() unless @thangTypeTeams for team in @thangTypeTeams[thangType.get('original')] ? [null] spriteOptions = {resolutionFactor: 4, async: false} diff --git a/app/lib/simulator/Simulator.coffee b/app/lib/simulator/Simulator.coffee index 7293c9f7f..b27266f8f 100644 --- a/app/lib/simulator/Simulator.coffee +++ b/app/lib/simulator/Simulator.coffee @@ -6,16 +6,14 @@ God = require 'lib/Buddha' module.exports = class Simulator extends CocoClass - constructor: (workerCode) -> + constructor: (@options) -> + @options ?= {} _.extend @, Backbone.Events @trigger 'statusUpdate', 'Starting simulation!' @retryDelayInSeconds = 10 @taskURL = '/queue/scoring' @simulatedByYou = 0 - if workerCode - @god = new God maxWorkerPoolSize: 1, maxAngels: 1, workerCode: workerCode # Start loading worker. - else - @god = new God maxWorkerPoolSize: 1, maxAngels: 1 + @god = new God maxWorkerPoolSize: 1, maxAngels: 1, workerCode: @options.workerCode # Start loading worker. destroy: -> @off() @@ -25,14 +23,14 @@ module.exports = class Simulator extends CocoClass fetchAndSimulateTask: => return if @destroyed - if headless + if @options.headlessClient if @dumpThisTime # The first heapdump would be useless to find leaks. console.log "Writing snapshot." - heapdump.writeSnapshot() - @dumpThisTime = true if heapdump + @options.heapdump.writeSnapshot() + @dumpThisTime = true if @options.heapdump - if testing - _.delay @setupSimulationAndLoadLevel, 0, testFile, "Testing...", status: 400 + if @options.testing + _.delay @setupSimulationAndLoadLevel, 0, @options.testFile, "Testing...", status: 400 return @trigger 'statusUpdate', 'Fetching simulation data!' @@ -116,7 +114,7 @@ module.exports = class Simulator extends CocoClass Backbone.Mediator.subscribeOnce 'god:new-world-created', @processResults, @ #Search for leaks, headless-client only. - if headless and leaktest and not @memwatch? + if @options.headlessClient and @options.leakTest and not @memwatch? leakcount = 0 maxleakcount = 0 console.log "Setting leak callbacks." @@ -134,7 +132,7 @@ module.exports = class Simulator extends CocoClass diff = @hd.end() console.warn "HeapDiff:\n" + JSON.stringify(diff) - if exitOnLeak + if @options.exitOnLeak console.warn "Exiting because of Leak." process.exit() @hd = new @memwatch.HeapDiff() @@ -153,7 +151,7 @@ module.exports = class Simulator extends CocoClass @trigger 'statusUpdate', 'Simulation completed, sending results back to server!' console.log "Sending result back to server!" - if headless and testing + if @options.headlessClient and @options.testing return @fetchAndSimulateTask() $.ajax @@ -169,7 +167,7 @@ module.exports = class Simulator extends CocoClass @trigger 'statusUpdate', 'Results were successfully sent back to server!' console.log "Simulated by you: " + @simulatedByYou @simulatedByYou++ - if not headless + unless @options.headlessClient simulatedBy = parseInt($('#simulated-by-you').text(), 10) + 1 $('#simulated-by-you').text(simulatedBy) @@ -178,8 +176,15 @@ module.exports = class Simulator extends CocoClass console.log "Task registration error: #{JSON.stringify error}" cleanupAndSimulateAnotherTask: => + @cleanupSimulation() @fetchAndSimulateTask() + cleanupSimulation: -> + @god?.destroy() + @god = null + @world = null + @level = null + formTaskResultsObject: (simulationResults) -> taskResults = taskID: @task.getTaskID() diff --git a/app/views/play/ladder/simulate_tab.coffee b/app/views/play/ladder/simulate_tab.coffee index 418838b43..645a4597a 100644 --- a/app/views/play/ladder/simulate_tab.coffee +++ b/app/views/play/ladder/simulate_tab.coffee @@ -38,7 +38,7 @@ module.exports = class SimulateTabView extends CocoView # Simulations onSimulateButtonClick: (e) -> - $("#simulate-button").prop "disabled",true + $("#simulate-button").prop "disabled", true $("#simulate-button").text "Simulating..." @simulator.fetchAndSimulateTask() diff --git a/headless_client.coffee b/headless_client.coffee index 686851893..01041a68a 100644 --- a/headless_client.coffee +++ b/headless_client.coffee @@ -3,14 +3,22 @@ This file will simulate games on node.js by emulating the browser environment. At some point, most of the code can be merged with Simulator.coffee ### -# SETTINGS -GLOBAL.debug = false # Enable logging of ajax calls mainly -GLOBAL.testing = false # Instead of simulating 'real' games, use the same one over and over again. Good for leak hunting. -GLOBAL.leaktest = false # Install callback that tries to find leaks automatically -GLOBAL.exitOnLeak = false # Exit if leak is found. Only useful if leaktest is set to true, obviously. -GLOBAL.heapdump = false # Dumps the whole heap after every pass. The heap dumps can then be viewed in Chrome browser. +bowerComponentsPath = "./bower_components/" +headlessClientPath = "./headless_client/" -server = if testing then "http://127.0.0.1:3000" else "http://codecombat.com" +# SETTINGS +options = + workerCode: require headlessClientPath + 'worker_world' + debug: false # Enable logging of ajax calls mainly + testing: true # Instead of simulating 'real' games, use the same one over and over again. Good for leak hunting. + testFile: require headlessClientPath + 'test.js' + leakTest: false # Install callback that tries to find leaks automatically + exitOnLeak: false # Exit if leak is found. Only useful if leaktest is set to true, obviously. + heapdump: false # Dumps the whole heap after every pass. The heap dumps can then be viewed in Chrome browser. + headlessClient: true + +options.heapdump = require('heapdump') if options.heapdump +server = if options.testing then "http://127.0.0.1:3000" else "http://codecombat.com" # Disabled modules disable = [ @@ -19,12 +27,8 @@ disable = [ '../locale/locale' ] -GLOBAL.bowerComponents = "./bower_components/" -GLOBAL.headlessClient = "./headless_client/" - # Start of the actual code. Setting up the enivronment to match the environment of the browser -heapdump = require('heapdump') if heapdump # the path used for the loader. __dirname is module dependent. path = __dirname @@ -45,7 +49,6 @@ JASON = require 'jason' # Global emulated stuff GLOBAL.window = GLOBAL -GLOBAL.headless = true GLOBAL.document = location: pathname: "headless_client" GLOBAL.console.debug = console.log @@ -79,20 +82,20 @@ hookedLoader = (request, parent, isMain) -> request = 'lib/Buddha' if request in disable or ~request.indexOf('templates') - console.log 'Ignored ' + request if debug + console.log 'Ignored ' + request if options.debug return class fake else if '/' in request and not (request[0] is '.') or request is 'application' request = path + '/app/' + request else if request is 'underscore' request = 'lodash' - console.log "loading " + request if debug + console.log "loading " + request if options.debug originalLoader request, parent, isMain #jQuery wrapped for compatibility purposes. Poorly. GLOBAL.$ = GLOBAL.jQuery = (input) -> - console.log 'Ignored jQuery: ' + input if debug + console.log 'Ignored jQuery: ' + input if options.debug append: (input)-> exports: ()-> cookies = request.jar() @@ -111,8 +114,8 @@ $.ajax = (options) -> #console.warn JSON.stringify data #data = JSON.stringify data - console.log "Requesting: " + JSON.stringify options if debug - console.log "URL: " + url if debug + console.log "Requesting: " + JSON.stringify options if options.debug + console.log "URL: " + url if options.debug request url: url jar: cookies @@ -120,17 +123,17 @@ $.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 options.debug and not error if responded - console.log "\t↳Already returned before." if debug + console.log "\t↳Already returned before." if options.debug return if (error) console.warn "\t↳Returned: error: #{error}" options.error(error) if options.error? else - console.log "\t↳Returned: statusCode #{response.statusCode}: #{if options.parse then JSON.stringify body else body}" if debug + console.log "\t↳Returned: statusCode #{response.statusCode}: #{if options.parse then JSON.stringify body else body}" if options.debug options.success(body, response, status: response.statusCode) if options.success? @@ -161,11 +164,11 @@ do (setupLodash = this) -> # load Backbone. Needs hooked loader to reroute underscore to lodash. hook() -GLOBAL.Backbone = require bowerComponents + 'backbone/backbone' +GLOBAL.Backbone = require bowerComponentsPath + 'backbone/backbone' unhook() Backbone.$ = $ -require bowerComponents + 'validated-backbone-mediator/backbone-mediator' +require bowerComponentsPath + 'validated-backbone-mediator/backbone-mediator' # Instead of mediator, dummy might be faster yet suffice? #Mediator = class Mediator # publish: (id, object) -> @@ -198,10 +201,6 @@ $.ajax LevelLoader = require 'lib/LevelLoader' GoalManager = require 'lib/world/GoalManager' - - - workerCode = require headlessClient + 'worker_world' - SuperModel = require 'models/SuperModel' log = require 'winston' @@ -210,8 +209,6 @@ $.ajax Simulator = require 'lib/simulator/Simulator' - GLOBAL.testFile = require headlessClient + 'test.js' + sim = new Simulator options - sim = new Simulator workerCode - - sim.fetchAndSimulateTask() \ No newline at end of file + sim.fetchAndSimulateTask()