mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-23 23:58:02 -05:00
No more transpiledCode
This commit is contained in:
parent
93f940e196
commit
e4c904463c
12 changed files with 38 additions and 74 deletions
|
@ -113,6 +113,7 @@ module.exports = class God extends CocoClass
|
||||||
for thangID, spellThang of spell.thangs
|
for thangID, spellThang of spell.thangs
|
||||||
continue if spellThang.thang?.programmableMethods[spell.name].cloneOf
|
continue if spellThang.thang?.programmableMethods[spell.name].cloneOf
|
||||||
(userCodeMap[thangID] ?= {})[spell.name] = spellThang.aether.serialize()
|
(userCodeMap[thangID] ?= {})[spell.name] = spellThang.aether.serialize()
|
||||||
|
console.log 'got UCM', userCodeMap
|
||||||
userCodeMap
|
userCodeMap
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,7 @@ module.exports = class LevelLoader extends CocoClass
|
||||||
|
|
||||||
if @sessionID
|
if @sessionID
|
||||||
url = "/db/level.session/#{@sessionID}"
|
url = "/db/level.session/#{@sessionID}"
|
||||||
|
url += "?interpret=true" if @spectateMode or utils.getQueryVariable 'esper'
|
||||||
else
|
else
|
||||||
url = "/db/level/#{@levelID}/session"
|
url = "/db/level/#{@levelID}/session"
|
||||||
url += "?team=#{@team}" if @team
|
url += "?team=#{@team}" if @team
|
||||||
|
@ -126,7 +127,7 @@ module.exports = class LevelLoader extends CocoClass
|
||||||
@session = @sessionResource.model
|
@session = @sessionResource.model
|
||||||
if @opponentSessionID
|
if @opponentSessionID
|
||||||
opponentURL = "/db/level.session/#{@opponentSessionID}"
|
opponentURL = "/db/level.session/#{@opponentSessionID}"
|
||||||
opponentURL += "?interpret=true" if utils.getQueryVariable 'esper'
|
opponentURL += "?interpret=true" if @spectateMode or utils.getQueryVariable 'esper'
|
||||||
opponentSession = new LevelSession().setURL opponentURL
|
opponentSession = new LevelSession().setURL opponentURL
|
||||||
opponentSession.project = session.project if @headless
|
opponentSession.project = session.project if @headless
|
||||||
@opponentSessionResource = @supermodel.loadModel(opponentSession, 'opponent_session', {cache: false})
|
@opponentSessionResource = @supermodel.loadModel(opponentSession, 'opponent_session', {cache: false})
|
||||||
|
|
|
@ -29,7 +29,7 @@ module.exports.createAetherOptions = (options) ->
|
||||||
#functionParameters: # TODOOOOO
|
#functionParameters: # TODOOOOO
|
||||||
executionLimit: 3 * 1000 * 1000
|
executionLimit: 3 * 1000 * 1000
|
||||||
language: options.codeLanguage
|
language: options.codeLanguage
|
||||||
useInterpreter: !!utils.getQueryVariable('esper')
|
useInterpreter: options.useInterpreter ? !!utils.getQueryVariable('esper')
|
||||||
parameters = functionParameters[options.functionName]
|
parameters = functionParameters[options.functionName]
|
||||||
unless parameters
|
unless parameters
|
||||||
console.warn "Unknown method #{options.functionName}: please add function parameters to lib/aether_utils.coffee."
|
console.warn "Unknown method #{options.functionName}: please add function parameters to lib/aether_utils.coffee."
|
||||||
|
|
|
@ -5,7 +5,7 @@ GoalManager = require 'lib/world/GoalManager'
|
||||||
God = require 'lib/God'
|
God = require 'lib/God'
|
||||||
{createAetherOptions} = require 'lib/aether_utils'
|
{createAetherOptions} = require 'lib/aether_utils'
|
||||||
|
|
||||||
SIMULATOR_VERSION = 3
|
SIMULATOR_VERSION = 4
|
||||||
|
|
||||||
simulatorInfo = {}
|
simulatorInfo = {}
|
||||||
if $.browser
|
if $.browser
|
||||||
|
@ -435,23 +435,20 @@ module.exports = class Simulator extends CocoClass
|
||||||
generatedSpellKey = [slugifiedThangID,methodName].join '/'
|
generatedSpellKey = [slugifiedThangID,methodName].join '/'
|
||||||
source = @currentUserCodeMap[generatedSpellKey] ? ''
|
source = @currentUserCodeMap[generatedSpellKey] ? ''
|
||||||
aether = @spells[spellKey].thangs[thang.id].aether
|
aether = @spells[spellKey].thangs[thang.id].aether
|
||||||
unless _.contains(@task.spellKeysToTranspile, generatedSpellKey)
|
#unless _.contains(@task.spellKeysToTranspile, generatedSpellKey)
|
||||||
aether.pure = source
|
try
|
||||||
else
|
aether.transpile source
|
||||||
try
|
catch e
|
||||||
aether.transpile source
|
console.log "Couldn't transpile #{spellKey}:\n#{source}\n", e
|
||||||
catch e
|
aether.transpile ''
|
||||||
console.log "Couldn't transpile #{spellKey}:\n#{source}\n", e
|
|
||||||
aether.transpile ''
|
|
||||||
|
|
||||||
createAether: (methodName, method, useProtectAPI, codeLanguage) ->
|
createAether: (methodName, method, useProtectAPI, codeLanguage) ->
|
||||||
aetherOptions = createAetherOptions functionName: methodName, codeLanguage: codeLanguage, skipProtectAPI: not useProtectAPI
|
aetherOptions = createAetherOptions functionName: methodName, codeLanguage: codeLanguage, skipProtectAPI: not useProtectAPI, useInterpreter: true
|
||||||
return new Aether aetherOptions
|
return new Aether aetherOptions
|
||||||
|
|
||||||
class SimulationTask
|
class SimulationTask
|
||||||
constructor: (@rawData) ->
|
constructor: (@rawData) ->
|
||||||
@spellKeyToTeamMap = {}
|
@spellKeyToTeamMap = {}
|
||||||
@spellKeysToTranspile = []
|
|
||||||
|
|
||||||
getLevelName: ->
|
getLevelName: ->
|
||||||
levelName = @rawData.sessions?[0]?.levelID
|
levelName = @rawData.sessions?[0]?.levelID
|
||||||
|
@ -486,45 +483,23 @@ class SimulationTask
|
||||||
setWorld: (@world) ->
|
setWorld: (@world) ->
|
||||||
|
|
||||||
generateSpellKeyToSourceMap: ->
|
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'
|
playerTeams = _.pluck @rawData.sessions, 'team'
|
||||||
spellKeyToSourceMap = {}
|
spellKeyToSourceMap = {}
|
||||||
for session in @rawData.sessions
|
for session in @rawData.sessions
|
||||||
teamSpells = session.teamSpells[session.team]
|
teamSpells = session.teamSpells[session.team]
|
||||||
allTeams = _.keys session.teamSpells
|
allTeams = _.keys session.teamSpells
|
||||||
nonPlayerTeams = _.difference allTeams, playerTeams
|
|
||||||
for team in allTeams
|
for team in allTeams
|
||||||
for spell in session.teamSpells[team]
|
for spell in session.teamSpells[team]
|
||||||
@spellKeyToTeamMap[spell] = team
|
@spellKeyToTeamMap[spell] = team
|
||||||
for nonPlayerTeam in nonPlayerTeams
|
|
||||||
for spell in session.teamSpells[nonPlayerTeam]
|
|
||||||
spellKeyToSourceMap[spell] ?= @getWorldProgrammableSource(spell, @world)
|
|
||||||
@spellKeysToTranspile.push spell
|
|
||||||
teamCode = {}
|
teamCode = {}
|
||||||
|
|
||||||
for thangName, thangSpells of session.transpiledCode
|
for thangName, thangSpells of session.submittedCode
|
||||||
for spellName, spell of thangSpells
|
for spellName, spell of thangSpells
|
||||||
fullSpellName = [thangName, spellName].join '/'
|
fullSpellName = [thangName, spellName].join '/'
|
||||||
if _.contains(teamSpells, fullSpellName)
|
if _.contains(teamSpells, fullSpellName)
|
||||||
teamCode[fullSpellName]=spell
|
teamCode[fullSpellName] = LZString.decompressFromUTF16 spell
|
||||||
|
|
||||||
_.merge spellKeyToSourceMap, teamCode
|
_.merge spellKeyToSourceMap, teamCode
|
||||||
|
|
||||||
spellKeyToSourceMap
|
spellKeyToSourceMap
|
||||||
|
|
||||||
getWorldProgrammableSource: (desiredSpellKey ,world) ->
|
|
||||||
programmableThangs = _.filter world.thangs, 'isProgrammable'
|
|
||||||
@spells ?= {}
|
|
||||||
@thangSpells ?= {}
|
|
||||||
for thang in programmableThangs
|
|
||||||
continue if @thangSpells[thang.id]?
|
|
||||||
@thangSpells[thang.id] = []
|
|
||||||
for methodName, method of thang.programmableMethods
|
|
||||||
pathComponents = [thang.id, methodName]
|
|
||||||
if method.cloneOf
|
|
||||||
pathComponents[0] = method.cloneOf # referencing another Thang's method
|
|
||||||
pathComponents[0] = _.string.slugify pathComponents[0]
|
|
||||||
spellKey = pathComponents.join '/'
|
|
||||||
@thangSpells[thang.id].push spellKey
|
|
||||||
if not method.cloneOf and spellKey is desiredSpellKey
|
|
||||||
#console.log "Setting #{desiredSpellKey} from world!"
|
|
||||||
return method.source
|
|
||||||
|
|
|
@ -135,8 +135,8 @@ module.exports = class SpectateLevelView extends RootView
|
||||||
continue if spellTeam is myTeam or not myTeam
|
continue if spellTeam is myTeam or not myTeam
|
||||||
opponentSpells = opponentSpells.concat spells
|
opponentSpells = opponentSpells.concat spells
|
||||||
|
|
||||||
opponentCode = @otherSession?.get('transpiledCode') or {}
|
opponentCode = @otherSession?.get('code') or {}
|
||||||
myCode = @session.get('transpiledCode') or {}
|
myCode = @session.get('code') or {}
|
||||||
for spell in opponentSpells
|
for spell in opponentSpells
|
||||||
[thang, spell] = spell.split '/'
|
[thang, spell] = spell.split '/'
|
||||||
c = opponentCode[thang]?[spell]
|
c = opponentCode[thang]?[spell]
|
||||||
|
|
|
@ -63,13 +63,12 @@ module.exports = class LadderSubmissionView extends CocoView
|
||||||
failure = (jqxhr, textStatus, errorThrown) =>
|
failure = (jqxhr, textStatus, errorThrown) =>
|
||||||
console.log jqxhr.responseText
|
console.log jqxhr.responseText
|
||||||
@setRankingButtonText 'failed' unless @destroyed
|
@setRankingButtonText 'failed' unless @destroyed
|
||||||
@transpileSession (transpiledCode) =>
|
@session.save null, success: =>
|
||||||
ajaxData =
|
ajaxData =
|
||||||
session: @session.id
|
session: @session.id
|
||||||
levelID: @level.id
|
levelID: @level.id
|
||||||
originalLevelID: @level.get('original')
|
originalLevelID: @level.get('original')
|
||||||
levelMajorVersion: @level.get('version').major
|
levelMajorVersion: @level.get('version').major
|
||||||
transpiledCode: transpiledCode
|
|
||||||
ajaxOptions =
|
ajaxOptions =
|
||||||
type: 'POST'
|
type: 'POST'
|
||||||
data: ajaxData
|
data: ajaxData
|
||||||
|
@ -81,35 +80,19 @@ module.exports = class LadderSubmissionView extends CocoView
|
||||||
mirrorAjaxData.session = @mirrorSession.id
|
mirrorAjaxData.session = @mirrorSession.id
|
||||||
mirrorCode = @mirrorSession.get('code')
|
mirrorCode = @mirrorSession.get('code')
|
||||||
if @session.get('team') is 'humans'
|
if @session.get('team') is 'humans'
|
||||||
mirrorAjaxData.transpiledCode = 'hero-placeholder-1': transpiledCode['hero-placeholder']
|
|
||||||
mirrorCode['hero-placeholder-1'] = @session.get('code')['hero-placeholder']
|
mirrorCode['hero-placeholder-1'] = @session.get('code')['hero-placeholder']
|
||||||
else
|
else
|
||||||
mirrorAjaxData.transpiledCode = 'hero-placeholder': transpiledCode['hero-placeholder-1']
|
|
||||||
mirrorCode['hero-placeholder'] = @session.get('code')['hero-placeholder-1']
|
mirrorCode['hero-placeholder'] = @session.get('code')['hero-placeholder-1']
|
||||||
mirrorAjaxOptions = _.clone ajaxOptions
|
mirrorAjaxOptions = _.clone ajaxOptions
|
||||||
mirrorAjaxOptions.data = mirrorAjaxData
|
mirrorAjaxOptions.data = mirrorAjaxData
|
||||||
ajaxOptions.success = =>
|
ajaxOptions.success = =>
|
||||||
patch = code: mirrorCode, codeLanguage: @session.get('codeLanguage'), submittedCodeLanguage: @session.get('submittedCodeLanguage')
|
patch = code: mirrorCode, codeLanguage: @session.get('codeLanguage')
|
||||||
tempSession = new LevelSession _id: @mirrorSession.id
|
tempSession = new LevelSession _id: @mirrorSession.id
|
||||||
tempSession.save patch, patch: true, type: 'PUT', success: ->
|
tempSession.save patch, patch: true, type: 'PUT', success: ->
|
||||||
$.ajax '/queue/scoring', mirrorAjaxOptions
|
$.ajax '/queue/scoring', mirrorAjaxOptions
|
||||||
|
|
||||||
$.ajax '/queue/scoring', ajaxOptions
|
$.ajax '/queue/scoring', ajaxOptions
|
||||||
|
|
||||||
transpileSession: (callback) ->
|
|
||||||
submittedCode = @session.get('code')
|
|
||||||
codeLanguage = @session.get('codeLanguage') or 'javascript'
|
|
||||||
@session.set('submittedCodeLanguage', codeLanguage)
|
|
||||||
transpiledCode = {}
|
|
||||||
for thang, spells of submittedCode
|
|
||||||
transpiledCode[thang] = {}
|
|
||||||
for spellID, spell of spells
|
|
||||||
unless _.contains(@session.get('teamSpells')[@session.get('team')], thang + '/' + spellID) then continue
|
|
||||||
aetherOptions = createAetherOptions functionName: spellID, codeLanguage: codeLanguage
|
|
||||||
aether = new Aether aetherOptions
|
|
||||||
transpiledCode[thang][spellID] = aether.transpile spell
|
|
||||||
@session.save null, success: -> callback transpiledCode
|
|
||||||
|
|
||||||
onHelpSimulate: ->
|
onHelpSimulate: ->
|
||||||
@playSound 'menu-button-click'
|
@playSound 'menu-button-click'
|
||||||
$('a[href="#simulate"]').tab('show')
|
$('a[href="#simulate"]').tab('show')
|
||||||
|
|
|
@ -182,6 +182,7 @@ module.exports = class Spell
|
||||||
skipProtectAPI: skipProtectAPI
|
skipProtectAPI: skipProtectAPI
|
||||||
includeFlow: includeFlow
|
includeFlow: includeFlow
|
||||||
problemContext: problemContext
|
problemContext: problemContext
|
||||||
|
useInterpreter: if @spectateView then true else undefined
|
||||||
aether = new Aether aetherOptions
|
aether = new Aether aetherOptions
|
||||||
if @worker
|
if @worker
|
||||||
workerMessage =
|
workerMessage =
|
||||||
|
@ -215,8 +216,7 @@ module.exports = class Spell
|
||||||
|
|
||||||
shouldUseTranspiledCode: ->
|
shouldUseTranspiledCode: ->
|
||||||
# Determine whether this code has already been transpiled, or whether it's raw source needing transpilation.
|
# Determine whether this code has already been transpiled, or whether it's raw source needing transpilation.
|
||||||
return false if utils.getQueryVariable 'esper' # Don't use transpiled code with interpreter
|
return false if @spectateView or utils.getQueryVariable 'esper' # Don't use transpiled code with interpreter
|
||||||
return true if @spectateView # Use transpiled code for both teams if we're just spectating.
|
|
||||||
return true if @isEnemySpell() # Use transpiled for enemy spells.
|
return true if @isEnemySpell() # Use transpiled for enemy spells.
|
||||||
# Players without permissions can't view the raw code.
|
# Players without permissions can't view the raw code.
|
||||||
return false if @observing and @levelType in ['hero', 'course']
|
return false if @observing and @levelType in ['hero', 'course']
|
||||||
|
|
|
@ -9,7 +9,6 @@ module.exports = createNewTask = (req, res) ->
|
||||||
requestSessionID = req.body.session
|
requestSessionID = req.body.session
|
||||||
originalLevelID = req.body.originalLevelID
|
originalLevelID = req.body.originalLevelID
|
||||||
currentLevelID = req.body.levelID
|
currentLevelID = req.body.levelID
|
||||||
transpiledCode = req.body.transpiledCode
|
|
||||||
requestLevelMajorVersion = parseInt(req.body.levelMajorVersion)
|
requestLevelMajorVersion = parseInt(req.body.levelMajorVersion)
|
||||||
|
|
||||||
yetiGuru = {}
|
yetiGuru = {}
|
||||||
|
@ -17,7 +16,7 @@ module.exports = createNewTask = (req, res) ->
|
||||||
validatePermissions.bind(yetiGuru, req, requestSessionID)
|
validatePermissions.bind(yetiGuru, req, requestSessionID)
|
||||||
fetchAndVerifyLevelType.bind(yetiGuru, currentLevelID)
|
fetchAndVerifyLevelType.bind(yetiGuru, currentLevelID)
|
||||||
fetchSessionObjectToSubmit.bind(yetiGuru, requestSessionID)
|
fetchSessionObjectToSubmit.bind(yetiGuru, requestSessionID)
|
||||||
updateSessionToSubmit.bind(yetiGuru, transpiledCode, req.user)
|
updateSessionToSubmit.bind(yetiGuru, req.user)
|
||||||
# Because there's some bug where the chained rankings don't work, and this is super slow, let's just not do this until we fix it.
|
# Because there's some bug where the chained rankings don't work, and this is super slow, let's just not do this until we fix it.
|
||||||
#fetchInitialSessionsToRankAgainst.bind(yetiGuru, requestLevelMajorVersion, originalLevelID)
|
#fetchInitialSessionsToRankAgainst.bind(yetiGuru, requestLevelMajorVersion, originalLevelID)
|
||||||
#generateAndSendTaskPairsToTheQueue
|
#generateAndSendTaskPairsToTheQueue
|
||||||
|
@ -49,14 +48,14 @@ fetchAndVerifyLevelType = (levelID, cb) ->
|
||||||
cb null
|
cb null
|
||||||
|
|
||||||
fetchSessionObjectToSubmit = (sessionID, callback) ->
|
fetchSessionObjectToSubmit = (sessionID, callback) ->
|
||||||
LevelSession.findOne({_id: sessionID}).select('team code leagues').exec (err, session) ->
|
LevelSession.findOne({_id: sessionID}).select('team code leagues codeLanguage').exec (err, session) ->
|
||||||
callback err, session?.toObject()
|
callback err, session?.toObject()
|
||||||
|
|
||||||
updateSessionToSubmit = (transpiledCode, user, sessionToUpdate, callback) ->
|
updateSessionToSubmit = (user, sessionToUpdate, callback) ->
|
||||||
sessionUpdateObject =
|
sessionUpdateObject =
|
||||||
submitted: true
|
submitted: true
|
||||||
submittedCode: sessionToUpdate.code
|
submittedCode: sessionToUpdate.code
|
||||||
transpiledCode: transpiledCode
|
submittedCodeLanguage: sessionToUpdate.codeLanguage or 'python'
|
||||||
submitDate: new Date()
|
submitDate: new Date()
|
||||||
#meanStrength: 25 # Let's try not resetting the score on resubmission
|
#meanStrength: 25 # Let's try not resetting the score on resubmission
|
||||||
standardDeviation: 25 / 3
|
standardDeviation: 25 / 3
|
||||||
|
|
|
@ -57,10 +57,10 @@ constructTaskObject = (taskMessageBody, message, callback) ->
|
||||||
callback null, taskObject, message
|
callback null, taskObject, message
|
||||||
|
|
||||||
getSessionInformation = (sessionIDString, callback) ->
|
getSessionInformation = (sessionIDString, callback) ->
|
||||||
selectString = 'submitDate team submittedCode teamSpells levelID creator creatorName transpiledCode submittedCodeLanguage totalScore'
|
selectString = 'submitDate team submittedCode teamSpells levelID creator creatorName submittedCodeLanguage totalScore'
|
||||||
LevelSession.findOne(_id: sessionIDString).select(selectString).lean().exec (err, session) ->
|
LevelSession.findOne(_id: sessionIDString).select(selectString).lean().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
|
callback null, scoringUtils.formatSessionInformation session
|
||||||
|
|
||||||
constructTaskLogObject = (calculatorUserID, taskObject, message, callback) ->
|
constructTaskLogObject = (calculatorUserID, taskObject, message, callback) ->
|
||||||
taskLogObject = new TaskLog
|
taskLogObject = new TaskLog
|
||||||
|
|
|
@ -21,7 +21,7 @@ module.exports = getTwoGames = (req, res) ->
|
||||||
leagueID: req.body.leagueID
|
leagueID: req.body.leagueID
|
||||||
getRandomSessions req.user, options, sendSessionsResponse(res)
|
getRandomSessions req.user, options, sendSessionsResponse(res)
|
||||||
|
|
||||||
sessionSelectionString = 'team totalScore transpiledCode submittedCodeLanguage teamSpells levelID creatorName creator submitDate leagues'
|
sessionSelectionString = 'team totalScore submittedCode submittedCodeLanguage teamSpells levelID creatorName creator submitDate leagues'
|
||||||
|
|
||||||
sendSessionsResponse = (res) ->
|
sendSessionsResponse = (res) ->
|
||||||
(err, sessions) ->
|
(err, sessions) ->
|
||||||
|
|
|
@ -89,7 +89,7 @@ logTaskComputation = (callback) ->
|
||||||
callback err
|
callback err
|
||||||
|
|
||||||
determineIfSessionShouldContinueAndUpdateLog = (cb) ->
|
determineIfSessionShouldContinueAndUpdateLog = (cb) ->
|
||||||
sessionID = @clientResponseObject.originalSessionID
|
sessionID = @clientResponseObject.originalSessionIDx
|
||||||
sessionRank = parseInt @clientResponseObject.originalSessionRank
|
sessionRank = parseInt @clientResponseObject.originalSessionRank
|
||||||
update = '$inc': {}
|
update = '$inc': {}
|
||||||
if sessionRank is 0
|
if sessionRank is 0
|
||||||
|
|
|
@ -4,6 +4,7 @@ bayes = new (require 'bayesian-battle')()
|
||||||
LevelSession = require '../../models/LevelSession'
|
LevelSession = require '../../models/LevelSession'
|
||||||
User = require '../../models/User'
|
User = require '../../models/User'
|
||||||
perfmon = require '../../commons/perfmon'
|
perfmon = require '../../commons/perfmon'
|
||||||
|
LZString = require 'lz-string'
|
||||||
|
|
||||||
SIMULATOR_VERSION = 3
|
SIMULATOR_VERSION = 3
|
||||||
|
|
||||||
|
@ -26,11 +27,15 @@ module.exports.sendResponseObject = (res, object) ->
|
||||||
res.send(object)
|
res.send(object)
|
||||||
res.end()
|
res.end()
|
||||||
|
|
||||||
|
|
||||||
module.exports.formatSessionInformation = (session) ->
|
module.exports.formatSessionInformation = (session) ->
|
||||||
|
heroID = if session.team is 'ogres' then 'hero-placeholder-1' else 'hero-placeholder'
|
||||||
|
submittedCode = {}
|
||||||
|
submittedCode[heroID] = plan: LZString.compressToUTF16 session.submittedCode[heroID].plan
|
||||||
|
|
||||||
|
_id: session._id
|
||||||
sessionID: session._id
|
sessionID: session._id
|
||||||
team: session.team ? 'No team'
|
team: session.team ? 'No team'
|
||||||
transpiledCode: session.transpiledCode
|
submittedCode: submittedCode
|
||||||
submittedCodeLanguage: session.submittedCodeLanguage
|
submittedCodeLanguage: session.submittedCodeLanguage
|
||||||
teamSpells: session.teamSpells ? {}
|
teamSpells: session.teamSpells ? {}
|
||||||
levelID: session.levelID
|
levelID: session.levelID
|
||||||
|
|
Loading…
Reference in a new issue