 
   getSessions: -> @rawData.sessions
 
-  getSpellKeyToTeamMap: -> @spellKeyToTeamMap
-
-  getPlayerTeams: -> _.pluck @rawData.sessions, 'team'
-
   setWorld: (@world) ->
-
-  generateSpellKeyToSourceMap: ->
-    # TODO: we always now only have hero-placeholder/plan vs. hero-placeholder-1/plan on humans vs. ogres, always just have to retranspile for Esper, and never need to transpile for NPCs or other methods, so we can get rid of almost all of this stuff.
-    playerTeams = _.pluck @rawData.sessions, 'team'
-    spellKeyToSourceMap = {}
-    for session in @rawData.sessions
-      teamSpells = session.teamSpells[session.team]
-      allTeams = _.keys session.teamSpells
-      for team in allTeams
-        for spell in session.teamSpells[team]
-          @spellKeyToTeamMap[spell] = team
-      teamCode = {}
-
-      for thangName, thangSpells of session.submittedCode
-        for spellName, spell of thangSpells
-          fullSpellName = [thangName, spellName].join '/'
-          if _.contains(teamSpells, fullSpellName)
-            teamCode[fullSpellName] = LZString.decompressFromUTF16 spell
-
-      _.merge spellKeyToSourceMap, teamCode
-
-    spellKeyToSourceMap

      return 1

  generateSpellsObject: ->
    @currentUserCodeMap = @task.generateSpellKeyToSourceMap()
    @spells = {}
    for thang in @level.attributes.thangs
      continue if @thangIsATemplate thang
      @generateSpellKeyToSourceMapPropertiesFromThang thang
    @spells

  thangIsATemplate: (thang) ->
    for component in thang.components
      continue unless @componentHasProgrammableMethods component
      for methodName, method of component.config.programmableMethods
        return true if @methodBelongsToTemplateThang method

    return false

  componentHasProgrammableMethods: (component) -> component.config? and _.has component.config, 'programmableMethods'

  methodBelongsToTemplateThang: (method) -> typeof method is 'string'

  generateSpellKeyToSourceMapPropertiesFromThang: (thang) =>
    for component in thang.components
      continue unless @componentHasProgrammableMethods component
      for methodName, method of component.config.programmableMethods
        spellKey = @generateSpellKeyFromThangIDAndMethodName thang.id, methodName

        @createSpellAndAssignName spellKey, methodName
        @createSpellThang thang, method, spellKey
        @transpileSpell thang, spellKey, methodName

  generateSpellKeyFromThangIDAndMethodName: (thang, methodName) ->
    spellKeyComponents = [thang, methodName]
    spellKeyComponents[0] = _.string.slugify spellKeyComponents[0]
    spellKey = spellKeyComponents.join '/'
    spellKey

  createSpellAndAssignName: (spellKey, spellName) ->
    @spells[spellKey] ?= {}
    @spells[spellKey].name = spellName

  createSpellThang: (thang, method, spellKey) ->
    @spells[spellKey].thangs ?= {}
    @spells[spellKey].thangs[thang.id] ?= {}
    spellTeam = @task.getSpellKeyToTeamMap()[spellKey]
    playerTeams = @task.getPlayerTeams()
    useProtectAPI = true
    if spellTeam not in playerTeams
      useProtectAPI = false
    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
    @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] ? ''
    aether = @spells[spellKey].thangs[thang.id].aether
    #unless _.contains(@task.spellKeysToTranspile, generatedSpellKey)
    try
      aether.transpile source
    catch e
      console.log "Couldn't transpile #{spellKey}:\n#{source}\n", e
      aether.transpile ''

  createAether: (methodName, method, useProtectAPI, codeLanguage) ->
    aetherOptions = createAetherOptions functionName: methodName, codeLanguage: codeLanguage, skipProtectAPI: not useProtectAPI
    return new Aether aetherOptions

class SimulationTask
  constructor: (@rawData) ->
    @spellKeyToTeamMap = {}

  getLevelName: ->
    levelName = @rawData.sessions?[0]?.levelID

    catch error
      console.log "Failed to form task results:", error
      return @cleanupAndSimulateAnotherTask()
    humanSessionRank = taskResults.sessions[0].metrics.rank
    ogreSessionRank = taskResults.sessions[1].metrics.rank
    if @options.headlessClient and @options.simulateOnlyOneGame
