2016-05-10 18:20:16 -04:00
utils = require ' core/utils '
2016-04-07 22:06:57 -04:00
RootView = require ' views/core/RootView '
template = require ' templates/editor/verifier/verifier-view '
VerifierTest = require ' ./VerifierTest '
2016-05-03 22:14:40 -04:00
SuperModel = require ' models/SuperModel '
2016-05-30 16:51:09 -04:00
Campaigns = require ' collections/Campaigns '
Level = require ' models/Level '
2016-04-07 22:06:57 -04:00
module.exports = class VerifierView extends RootView
className: ' style-flat '
template: template
id: ' verifier-view '
2016-05-30 16:51:09 -04:00
events:
' click # go-button ' : ' onClickGoButton '
2016-04-07 22:06:57 -04:00
constructor: (options, @levelID) ->
super options
# TODO: sort tests by unexpected result first
2016-05-03 14:46:10 -04:00
@passed = 0
@failed = 0
2016-05-03 22:14:40 -04:00
@problem = 0
2016-05-30 16:51:09 -04:00
@testCount = 0
2016-06-21 14:48:28 -04:00
defaultCores = 2
@cores = Math . max ( window . navigator . hardwareConcurrency , defaultCores )
@careAboutFrames = true
2016-05-30 16:51:09 -04:00
if @ levelID
@levelIDs = [ @ levelID ]
@testLanguages = [ ' python ' , ' javascript ' , ' java ' , ' lua ' , ' coffeescript ' ]
2016-06-29 19:16:46 -04:00
@cores = 1
2016-05-30 16:51:09 -04:00
@ startTestingLevels ( )
else
@campaigns = new Campaigns ( )
@ supermodel . trackRequest @ campaigns . fetch ( data: { project: ' slug,type,levels ' } )
@campaigns.comparator = (m) ->
[ ' intro ' , ' course-2 ' , ' course-3 ' , ' course-4 ' , ' course-5 ' , ' course-6 ' , ' course-8 ' ,
' dungeon ' , ' forest ' , ' desert ' , ' mountain ' , ' glacier ' , ' volcano ' ] . indexOf ( m . get ( ' slug ' ) )
onLoaded: ->
super ( )
return if @ levelID
@ filterCampaigns ( )
@ filterCodeLanguages ( )
@ render ( )
filterCampaigns: ->
@levelsByCampaign = { }
for campaign in @ campaigns . models when campaign . get ( ' type ' ) in [ ' course ' , ' hero ' ] and campaign . get ( ' slug ' ) isnt ' picoctf '
@ levelsByCampaign [ campaign . get ( ' slug ' ) ] ? = { levels: [ ] , checked: true }
campaignInfo = @ levelsByCampaign [ campaign . get ( ' slug ' ) ]
2016-07-14 12:38:45 -04:00
for levelID , level of campaign . get ( ' levels ' ) when level . type not in [ ' hero-ladder ' , ' course-ladder ' , ' game-dev ' , ' web-dev ' ] # Would use isType, but it's not a Level model
2016-05-30 16:51:09 -04:00
campaignInfo . levels . push level . slug
filterCodeLanguages: ->
defaultLanguages = utils . getQueryVariable ( ' languages ' , ' python,javascript ' ) . split ( /, ?/ )
@ codeLanguages ? = ( { id: c , checked: c in defaultLanguages } for c in [ ' python ' , ' javascript ' , ' java ' , ' lua ' , ' coffeescript ' ] )
2016-05-03 22:14:40 -04:00
2016-05-30 16:51:09 -04:00
onClickGoButton: (e) ->
@ filterCampaigns ( )
@levelIDs = [ ]
2016-06-21 14:48:28 -04:00
@careAboutFrames = @ $ ( " # careAboutFrames " ) . is ( ' :checked ' )
@cores = @ $ ( " # cores " ) . val ( ) | 0
2016-05-30 16:51:09 -04:00
for campaign , campaignInfo of @ levelsByCampaign
if @ $ ( " # campaign- #{ campaign } -checkbox " ) . is ( ' :checked ' )
for level in campaignInfo . levels
@ levelIDs . push level unless level in @ levelIDs
else
campaignInfo.checked = false
@testLanguages = [ ]
for codeLanguage in @ codeLanguages
if @ $ ( " # code-language- #{ codeLanguage . id } -checkbox " ) . is ( ' :checked ' )
codeLanguage.checked = true
@ testLanguages . push codeLanguage . id
else
codeLanguage.checked = false
@ startTestingLevels ( )
2016-05-03 22:14:40 -04:00
2016-05-30 16:51:09 -04:00
startTestingLevels: ->
@levelsToLoad = @initialLevelsToLoad = @ levelIDs . length
for levelID in @ levelIDs
level = @ supermodel . getModel ( Level , levelID ) or new Level _id: levelID
if level . loaded
@ onLevelLoaded ( )
else
@ listenToOnce @ supermodel . loadModel ( level ) . model , ' sync ' , @ onLevelLoaded
2016-05-05 19:56:58 -04:00
2016-05-30 16:51:09 -04:00
onLevelLoaded: (level) ->
if - - @ levelsToLoad is 0
@ onTestLevelsLoaded ( )
else
@ render ( )
2016-05-03 15:14:51 -04:00
2016-05-30 16:51:09 -04:00
onTestLevelsLoaded: ->
2016-05-03 22:14:40 -04:00
2016-05-03 15:14:51 -04:00
@linksQueryString = window . location . search
2016-04-07 22:06:57 -04:00
#supermodel = if @levelID then @supermodel else undefined
@tests = [ ]
2016-05-30 16:51:09 -04:00
@tasksList = [ ]
for levelID in @ levelIDs
level = @ supermodel . getModel ( Level , levelID )
solutions = level ? . getSolutions ( )
for codeLanguage in @ testLanguages
if not solutions or _ . find ( solutions , language: codeLanguage )
@ tasksList . push level: levelID , language: codeLanguage
2016-05-03 22:14:40 -04:00
@testCount = @ tasksList . length
2016-06-21 14:48:28 -04:00
console . log ( " Starting in " , @ cores , " cores... " )
chunks = _ . groupBy @ tasksList , (v,i) => i % @ cores
2016-05-03 22:14:40 -04:00
supermodels = [ @ supermodel ]
2016-05-05 19:56:58 -04:00
_ . forEach chunks , (chunk, i) =>
2016-05-03 22:14:40 -04:00
_ . delay =>
parentSuperModel = supermodels [ supermodels . length - 1 ]
chunkSupermodel = new SuperModel ( )
chunkSupermodel.models = _ . clone parentSuperModel . models
chunkSupermodel.collections = _ . clone parentSuperModel . collections
supermodels . push chunkSupermodel
async . eachSeries chunk , (task, next) =>
test = new VerifierTest task . level , (e) =>
@ update ( e )
2016-05-05 19:56:58 -04:00
if e . state in [ ' complete ' , ' error ' , ' no-solution ' ]
2016-05-03 22:14:40 -04:00
if e . state is ' complete '
2016-05-05 19:56:58 -04:00
if test . isSuccessful ( )
2016-05-03 22:14:40 -04:00
++ @ passed
else
++ @ failed
2016-05-05 19:56:58 -04:00
else if e . state is ' no-solution '
- - @ testCount
else
2016-05-03 22:14:40 -04:00
++ @ problem
next ( )
2016-06-21 14:48:28 -04:00
, chunkSupermodel , task . language , { dontCareAboutFrames: not @ careAboutFrames }
2016-05-03 22:14:40 -04:00
@ tests . unshift test
@ render ( )
, => @ render ( )
, if i > 0 then 5000 + i * 1000 else 0
2016-04-07 22:06:57 -04:00
update: (event) =>
2016-05-05 19:56:58 -04:00
@ render ( )