This commit is contained in:
Nick Winter 2014-08-30 13:43:56 -07:00
parent 5f11a5ecca
commit 85a9a558ef
7 changed files with 64 additions and 79 deletions

View file

@ -0,0 +1,48 @@
Aether.addGlobal 'Vector', require 'lib/world/vector'
Aether.addGlobal '_', _
module.exports.createAetherOptions = (options) ->
throw new Error 'Specify a function name to create an Aether instance' unless options.functionName
throw new Error 'Specify a code language to create an Aether instance' unless options.codeLanguage
aetherOptions =
functionName: options.functionName
protectAPI: not options.skipProtectAPI
includeFlow: false
yieldConditionally: options.functionName is 'plan'
globals: ['Vector', '_']
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
aether_MissingThis: {level: 'error'}
#functionParameters: # TODOOOOO
executionLimit: 1 * 1000 * 1000
language: options.codeLanguage
parameters = functionParameters[options.functionName]
unless parameters
console.warn "Unknown method #{options.functionName}: please add function parameters to lib/aether_utils.coffee."
parameters = []
if options.functionParameters and not _.isEqual options.functionParameters, parameters
console.error "Update lib/aether_utils.coffee with the right function parameters for #{options.functionName} (had: #{parameters} but this gave #{options.functionParameters}."
parameters = options.functionParameters
aetherOptions.functionParameters = parameters.slice()
#console.log 'creating aether with options', aetherOptions
return aetherOptions
# TODO: figure out some way of saving this info dynamically so that we don't have to hard-code it: #1329
functionParameters =
hear: ['speaker', 'message', 'data']
makeBid: ['tileGroupLetter']
findCentroids: ['centroids']
isFriend: ['name']
evaluateBoard: ['board', 'player']
getPossibleMoves: ['board']
minimax_alphaBeta: ['board', 'player', 'depth', 'alpha', 'beta']
chooseAction: []
plan: []
initializeCentroids: []

View file

@ -3,9 +3,7 @@ CocoClass = require 'lib/CocoClass'
LevelLoader = require 'lib/LevelLoader' LevelLoader = require 'lib/LevelLoader'
GoalManager = require 'lib/world/GoalManager' GoalManager = require 'lib/world/GoalManager'
God = require 'lib/God' God = require 'lib/God'
{createAetherOptions} = require 'lib/aether_utils'
Aether.addGlobal 'Vector', require 'lib/world/vector'
Aether.addGlobal '_', _
module.exports = class Simulator extends CocoClass module.exports = class Simulator extends CocoClass
constructor: (@options) -> constructor: (@options) ->
@ -400,23 +398,7 @@ module.exports = class Simulator extends CocoClass
aether.transpile '' aether.transpile ''
createAether: (methodName, method, useProtectAPI, codeLanguage) -> createAether: (methodName, method, useProtectAPI, codeLanguage) ->
aetherOptions = aetherOptions = createAetherOptions functionName: methodName, codeLanguage: codeLanguage, skipProtectAPI: not useProtectAPI
functionName: methodName
protectAPI: useProtectAPI
includeFlow: false
yieldConditionally: methodName is 'plan'
globals: ['Vector', '_']
problems:
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
return new Aether aetherOptions return new Aether aetherOptions
class SimulationTask class SimulationTask

View file

@ -62,7 +62,7 @@ module.exports = class ThangType extends CocoModel
options options
buildSpriteSheet: (options) -> buildSpriteSheet: (options) ->
return false unless @isFullyLoaded() return false unless @isFullyLoaded() and @get 'raw'
@options = @fillOptions options @options = @fillOptions options
key = @spriteSheetKey(@options) key = @spriteSheetKey(@options)
if ss = @spriteSheets[key] then return ss if ss = @spriteSheets[key] then return ss

View file

@ -122,7 +122,7 @@ _.extend LevelSessionSchema.properties,
type: 'object' type: 'object'
additionalProperties: additionalProperties:
type: 'string' type: 'string'
format: 'javascript' format: 'code'
codeLanguage: codeLanguage:
type: 'string' type: 'string'
@ -165,6 +165,7 @@ _.extend LevelSessionSchema.properties,
type: 'object' type: 'object'
additionalProperties: additionalProperties:
type: 'string' type: 'string'
format: 'code'
submittedCodeLanguage: submittedCodeLanguage:
type: 'string' type: 'string'
@ -175,6 +176,7 @@ _.extend LevelSessionSchema.properties,
type: 'object' type: 'object'
additionalProperties: additionalProperties:
type: 'string' type: 'string'
format: 'code'
isRanking: isRanking:
type: 'boolean' type: 'boolean'

View file

@ -1,5 +1,6 @@
CocoView = require 'views/kinds/CocoView' CocoView = require 'views/kinds/CocoView'
template = require 'templates/play/common/ladder_submission' template = require 'templates/play/common/ladder_submission'
{createAetherOptions} = require 'lib/aether_utils'
module.exports = class LadderSubmissionView extends CocoView module.exports = class LadderSubmissionView extends CocoView
className: 'ladder-submission-view' className: 'ladder-submission-view'
@ -72,29 +73,15 @@ module.exports = class LadderSubmissionView extends CocoView
transpileSession: -> transpileSession: ->
submittedCode = @session.get('code') submittedCode = @session.get('code')
language = @session.get('codeLanguage') or 'javascript' codeLanguage = @session.get('codeLanguage') or 'javascript'
@session.set('submittedCodeLanguage', language) @session.set('submittedCodeLanguage', codeLanguage)
@session.save() # TODO: maybe actually use a callback to make sure this works? @session.save() # TODO: maybe actually use a callback to make sure this works?
transpiledCode = {} transpiledCode = {}
for thang, spells of submittedCode for thang, spells of submittedCode
transpiledCode[thang] = {} transpiledCode[thang] = {}
for spellID, spell of spells 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 = createAetherOptions functionName: spellID, codeLanguage: codeLanguage
aetherOptions =
problems: {}
language: language
functionName: spellID
functionParameters: []
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']
aether = new Aether aetherOptions aether = new Aether aetherOptions
transpiledCode[thang][spellID] = aether.transpile spell transpiledCode[thang][spellID] = aether.transpile spell
transpiledCode transpiledCode

View file

@ -1,9 +1,7 @@
SpellView = require './SpellView' SpellView = require './SpellView'
SpellListTabEntryView = require './SpellListTabEntryView' SpellListTabEntryView = require './SpellListTabEntryView'
{me} = require 'lib/auth' {me} = require 'lib/auth'
{createAetherOptions} = require 'lib/aether_utils'
Aether.addGlobal 'Vector', require 'lib/world/vector'
Aether.addGlobal '_', _
module.exports = class Spell module.exports = class Spell
loaded: false loaded: false
@ -125,25 +123,8 @@ module.exports = class Spell
createAether: (thang) -> createAether: (thang) ->
aceConfig = me.get('aceConfig') ? {} aceConfig = me.get('aceConfig') ? {}
writable = @permissions.readwrite.length > 0 writable = @permissions.readwrite.length > 0
aetherOptions = skipProtectAPI = @skipProtectAPI or not writable
problems: aetherOptions = createAetherOptions functionName: @name, codeLanguage: @language, functionParameters: @parameters, skipProtectAPI: skipProtectAPI
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
functionParameters: @parameters
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.
includeFlow: false
executionLimit: 1 * 1000 * 1000
#console.log 'creating aether with options', aetherOptions
aether = new Aether aetherOptions aether = new Aether aetherOptions
workerMessage = workerMessage =
function: 'createAether' function: 'createAether'

View file

@ -8,9 +8,8 @@ async = require 'async'
serverSetup = require '../server_setup' serverSetup = require '../server_setup'
Level = require '../server/levels/Level' Level = require '../server/levels/Level'
LevelSession = require '../server/levels/sessions/LevelSession' LevelSession = require '../server/levels/sessions/LevelSession'
{createAetherOptions} = require '../app/lib/aether_utils'
Aether.addGlobal 'Vector', require '../app/lib/world/vector'
Aether.addGlobal '_', _
i = 0 i = 0
transpileLevelSession = (sessionID, cb) -> 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()
@ -27,23 +26,9 @@ transpileLevelSession = (sessionID, cb) ->
transpiledCode[thang] = {} transpiledCode[thang] = {}
for spellID, spell of spells for spellID, spell of spells
spellName = thang + '/' + spellID spellName = thang + '/' + spellID
continue if session.teamSpells and not (spellName in session.teamSpells[session.team])
if session.teamSpells and not (spellName in session.teamSpells[session.team]) then continue
#console.log "Transpiling spell #{spellName}" #console.log "Transpiling spell #{spellName}"
aetherOptions = aetherOptions = createAetherOptions functionName: spellID, codeLanguage: session.submittedCodeLanguage
problems: {}
language: session.submittedCodeLanguage
functionName: spellID
functionParameters: []
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']
aether = new Aether aetherOptions aether = new Aether aetherOptions
transpiledCode[thang][spellID] = aether.transpile spell transpiledCode[thang][spellID] = aether.transpile spell
conditions = conditions =