From 514fce349a8f58388e1275cc6406c42fdf5ad78a Mon Sep 17 00:00:00 2001 From: Scott Erickson Date: Fri, 17 Jun 2016 15:15:13 -0700 Subject: [PATCH] Include ladder levels in level stats in teacher views, clean client test logs --- app/lib/LevelLoader.coffee | 14 +++--- app/lib/coursesHelper.coffee | 49 +++++++++---------- app/models/CocoModel.coffee | 10 ++-- app/models/LevelSession.coffee | 2 +- app/templates/account/payments-view.jade | 1 - app/templates/courses/teacher-class-view.jade | 4 +- server/middleware/classrooms.coffee | 6 +-- test/app/lib/CoursesHelper.spec.coffee | 1 - 8 files changed, 43 insertions(+), 44 deletions(-) diff --git a/app/lib/LevelLoader.coffee b/app/lib/LevelLoader.coffee index b4b03df8c..cbf7bc450 100644 --- a/app/lib/LevelLoader.coffee +++ b/app/lib/LevelLoader.coffee @@ -12,6 +12,8 @@ app = require 'core/application' World = require 'lib/world/world' utils = require 'core/utils' +LOG = false + # This is an initial stab at unifying loading and setup into a single place which can # monitor everything and keep a LoadingScreen visible overall progress. # @@ -147,7 +149,7 @@ module.exports = class LevelLoader extends CocoClass @listenToOnce @opponentSession, 'sync', @loadDependenciesForSession loadDependenciesForSession: (session) -> - console.log "Loading dependencies for session: ", session + console.log "Loading dependencies for session: ", session if LOG if me.id isnt session.get 'creator' session.patch = session.save = -> console.error "Not saving session, since we didn't create it." else if codeLanguage = utils.getQueryVariable 'codeLanguage' @@ -172,11 +174,11 @@ module.exports = class LevelLoader extends CocoClass @consolidateFlagHistory() if @session.loaded if @level.get('type', true) in ['course'] # course-ladder is hard to handle because there's 2 sessions heroConfig = me.get('heroConfig') - console.log "Course mode, loading custom hero: ", heroConfig + console.log "Course mode, loading custom hero: ", heroConfig if LOG return if not heroConfig url = "/db/thang.type/#{heroConfig.thangType}/version" if heroResource = @maybeLoadURL(url, ThangType, 'thang') - console.log "Pushing resource: ", heroResource + console.log "Pushing resource: ", heroResource if LOG @worldNecessities.push heroResource @sessionDependenciesRegistered[session.id] = true return @@ -345,7 +347,7 @@ module.exports = class LevelLoader extends CocoClass true onWorldNecessitiesLoaded: -> - console.log "World necessities loaded." + console.log "World necessities loaded." if LOG @initWorld() @supermodel.clearMaxProgress() @trigger 'world-necessities-loaded' @@ -374,7 +376,7 @@ module.exports = class LevelLoader extends CocoClass onSupermodelLoaded: -> return if @destroyed - console.log 'SuperModel for Level loaded in', new Date().getTime() - @t0, 'ms' + console.log 'SuperModel for Level loaded in', new Date().getTime() - @t0, 'ms' if LOG @loadLevelSounds() @denormalizeSession() @@ -482,7 +484,7 @@ module.exports = class LevelLoader extends CocoClass @world.difficulty = Math.max 0, @world.difficulty - 1 # Show the difficulty they won, not the next one. serializedLevel = @level.serialize(@supermodel, @session, @opponentSession) @world.loadFromLevel serializedLevel, false - console.log 'World has been initialized from level loader.' + console.log 'World has been initialized from level loader.' if LOG # Initial Sound Loading diff --git a/app/lib/coursesHelper.coffee b/app/lib/coursesHelper.coffee index 693234fa2..ad68f1fee 100644 --- a/app/lib/coursesHelper.coffee +++ b/app/lib/coursesHelper.coffee @@ -12,20 +12,18 @@ module.exports = continue if not instance instance.numCompleted = 0 instance.started = false - levels = classroom.getLevels({courseID: course.id, withoutLadderLevels: true}) + levels = classroom.getLevels({courseID: course.id}) for userID in instance.get('members') instance.started ||= _.any levels.models, (level) -> - return false if level.isLadder() session = _.find classroom.sessions.models, (session) -> session.get('creator') is userID and session.get('level').original is level.get('original') session? levelCompletes = _.map levels.models, (level) -> - return true if level.isLadder() #TODO: Hella slow! Do the mapping first! - session = _.find classroom.sessions.models, (session) -> + sessions = _.filter classroom.sessions.models, (session) -> session.get('creator') is userID and session.get('level').original is level.get('original') # sessionMap[userID][level].completed() - session?.completed() + _.find(sessions, (s) -> s.completed()) if _.every levelCompletes instance.numCompleted += 1 @@ -34,14 +32,14 @@ module.exports = for course, courseIndex in courses.models instance = courseInstances.findWhere({ courseID: course.id, classroomID: classroom.id }) continue if not instance - levels = classroom.getLevels({courseID: course.id, withoutLadderLevels: true}) + levels = classroom.getLevels({courseID: course.id}) for level, levelIndex in levels.models userIDs = [] for user in students.models userID = user.id - session = _.find classroom.sessions.models, (session) -> + sessions = _.filter classroom.sessions.models, (session) -> session.get('creator') is userID and session.get('level').original is level.get('original') - if not session?.completed() + if not _.find(sessions, (s) -> s.completed()) userIDs.push userID if userIDs.length > 0 users = _.map userIDs, (id) -> @@ -61,16 +59,16 @@ module.exports = courseIndex = courses.models.length - courseIndex - 1 #compensate for reverse instance = courseInstances.findWhere({ courseID: course.id, classroomID: classroom.id }) continue if not instance - levels = classroom.getLevels({courseID: course.id, withoutLadderLevels: true}) + levels = classroom.getLevels({courseID: course.id}) levelModels = levels.models.slice() for level, levelIndex in levelModels.reverse() # levelIndex = levelModels.length - levelIndex - 1 #compensate for reverse userIDs = [] for user in students.models userID = user.id - session = _.find classroom.sessions.models, (session) -> + sessions = _.filter classroom.sessions.models, (session) -> session.get('creator') is userID and session.get('level').original is level.get('original') - if session?.completed() # + if _.find(sessions, (s) -> s.completed()) # userIDs.push userID if userIDs.length > 0 users = _.map userIDs, (id) -> @@ -91,7 +89,7 @@ module.exports = conceptData[classroom.id] = {} for course, courseIndex in courses.models - levels = classroom.getLevels({courseID: course.id, withoutLadderLevels: true}) + levels = classroom.getLevels({courseID: course.id}) for level in levels.models levelID = level.get('original') @@ -102,16 +100,16 @@ module.exports = for concept in level.get('concepts') for userID in classroom.get('members') - session = _.find classroom.sessions.models, (session) -> + sessions = _.filter classroom.sessions.models, (session) -> session.get('creator') is userID and session.get('level').original is levelID - if not session # haven't gotten to this level yet, but might have completed others before + if _.size(sessions) is 0 # haven't gotten to this level yet, but might have completed others before for concept in level.get('concepts') conceptData[classroom.id][concept].completed = false - if session # have gotten to the level and at least started it + if _.size(sessions) > 0 # have gotten to the level and at least started it for concept in level.get('concepts') conceptData[classroom.id][concept].started = true - if not session?.completed() # level started but not completed + if not _.find(sessions, (s) -> s.completed()) # level started but not completed for concept in level.get('concepts') conceptData[classroom.id][concept].completed = false conceptData @@ -139,7 +137,7 @@ module.exports = continue progressData[classroom.id][course.id] = { completed: true, started: false } # to be updated - levels = classroom.getLevels({courseID: course.id, withoutLadderLevels: true}) + levels = classroom.getLevels({courseID: course.id}) for level in levels.models levelID = level.get('original') progressData[classroom.id][course.id][levelID] = { @@ -154,12 +152,12 @@ module.exports = courseProgress = progressData[classroom.id][course.id] courseProgress[userID] ?= { completed: true, started: false, levelsCompleted: 0 } # Only set it the first time through a user courseProgress[levelID][userID] = { completed: true, started: false } # These don't matter, will always be set - session = _.find classroom.sessions.models, (session) -> + sessions = _.filter classroom.sessions.models, (session) -> session.get('creator') is userID and session.get('level').original is levelID - - courseProgress[levelID][userID].session = session - if not session # haven't gotten to this level yet, but might have completed others before + courseProgress[levelID][userID].session = _.find(sessions, (s) -> s.completed()) or _.first(sessions) + + if _.size(sessions) is 0 # haven't gotten to this level yet, but might have completed others before courseProgress.started ||= false #no-op courseProgress.completed = false courseProgress[userID].started ||= false #no-op @@ -169,22 +167,23 @@ module.exports = courseProgress[levelID][userID].started = false courseProgress[levelID][userID].completed = false - if session # have gotten to the level and at least started it + if _.size(sessions) > 0 # have gotten to the level and at least started it courseProgress.started = true courseProgress[userID].started = true courseProgress[levelID].started = true courseProgress[levelID][userID].started = true - courseProgress[levelID][userID].lastPlayed = new Date(session.get('changed')) + courseProgress[levelID][userID].lastPlayed = new Date(Math.max(_.map(sessions, 'changed'))) courseProgress[levelID].numStarted += 1 - if session?.completed() # have finished this level + if _.find(sessions, (s) -> s.completed()) # have finished this level courseProgress.completed &&= true #no-op courseProgress[userID].completed &&= true #no-op courseProgress[userID].levelsCompleted += 1 courseProgress[levelID].completed &&= true #no-op # courseProgress[levelID].numCompleted += 1 courseProgress[levelID][userID].completed = true - courseProgress[levelID][userID].dateFirstCompleted = new Date(session.get('dateFirstCompleted') || session.get('changed')) + dates = (s.get('dateFirstCompleted') || s.get('changed') for s in sessions) + courseProgress[levelID][userID].dateFirstCompleted = new Date(Math.max(dates...)) else # level started but not completed courseProgress.completed = false courseProgress[userID].completed = false diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee index 4a5c84fb5..90310d5de 100644 --- a/app/models/CocoModel.coffee +++ b/app/models/CocoModel.coffee @@ -124,10 +124,11 @@ class CocoModel extends Backbone.Model validate: -> errors = @getValidationErrors() if errors?.length - console.debug "Validation failed for #{@constructor.className}: '#{@get('name') or @}'." - for error in errors - console.debug "\t", error.dataPath, ':', error.message - console.trace?() + unless application.testing + console.debug "Validation failed for #{@constructor.className}: '#{@get('name') or @}'." + for error in errors + console.debug "\t", error.dataPath, ':', error.message + console.trace?() return errors save: (attrs, options) -> @@ -188,7 +189,6 @@ class CocoModel extends Backbone.Model keys.push key return unless keys.length - console.debug 'Patching', @get('name') or @, keys @save(attrs, options) fetch: (options) -> diff --git a/app/models/LevelSession.coffee b/app/models/LevelSession.coffee index 63621fa66..8b2b73104 100644 --- a/app/models/LevelSession.coffee +++ b/app/models/LevelSession.coffee @@ -41,7 +41,7 @@ module.exports = class LevelSession extends CocoModel @get('submittedCodeLanguage')? and @get('team')? completed: -> - @get('state')?.complete || false + @get('state')?.complete || @get('submitted') || false shouldAvoidCorruptData: (attrs) -> return false unless me.team is 'humans' diff --git a/app/templates/account/payments-view.jade b/app/templates/account/payments-view.jade index fc625f656..f9a55bd8b 100644 --- a/app/templates/account/payments-view.jade +++ b/app/templates/account/payments-view.jade @@ -10,7 +10,6 @@ block content a(href="/account", data-i18n="nav.account") li.active(data-i18n="account.payments") - - console.log('render', view.payments.size()) if view.payments.size() table.table.table-striped tr diff --git a/app/templates/courses/teacher-class-view.jade b/app/templates/courses/teacher-class-view.jade index 7215a08cf..453f8485c 100644 --- a/app/templates/courses/teacher-class-view.jade +++ b/app/templates/courses/teacher-class-view.jade @@ -300,7 +300,7 @@ mixin courseProgressTab mixin courseOverview - var course = state.get('selectedCourse') - - var levels = view.classroom.getLevels({courseID: course.id, withoutLadderLevels: true}).models + - var levels = view.classroom.getLevels({courseID: course.id}).models .course-overview-row .course-title.student-name span= course.get('name') @@ -318,7 +318,7 @@ mixin studentLevelsRow(student) div.student-email.small-details= student.get('email') div.student-levels-progress - var course = state.get('selectedCourse') - - var levels = view.classroom.getLevels({courseID: course.id, withoutLadderLevels: true}).models + - var levels = view.classroom.getLevels({courseID: course.id}).models each level, index in levels - var progress = state.get('progressData').get({ classroom: view.classroom, course: course, level: level, user: student }) +studentLevelProgressDot(progress, level, index+1, session) diff --git a/server/middleware/classrooms.coffee b/server/middleware/classrooms.coffee index 1c2ec0f78..8a12b3c5a 100644 --- a/server/middleware/classrooms.coffee +++ b/server/middleware/classrooms.coffee @@ -22,7 +22,7 @@ module.exports = fetchByCode: wrap (req, res, next) -> code = req.query.code return next() unless code - classroom = yield Classroom.findOne({ code: code.toLowerCase().replace(/ /g, '') }).select('name ownerID aceConfig') + classroom = yield Classroom.findOne({ code: code.toLowerCase().replace(RegExp(' ', 'g') , '') }).select('name ownerID aceConfig') if not classroom log.debug("classrooms.fetchByCode: Couldn't find Classroom with code: #{code}") throw new errors.NotFound('Classroom not found.') @@ -104,7 +104,7 @@ module.exports = members = classroom.get('members') or [] members = members.slice(memberSkip, memberSkip + memberLimit) dbqs = [] - select = 'state.complete level creator playtime changed dateFirstCompleted' + select = 'state.complete level creator playtime changed dateFirstCompleted submitted' for member in members dbqs.push(LevelSession.find({creator: member.toHexString()}).select(select).exec()) results = yield dbqs @@ -170,7 +170,7 @@ module.exports = if req.user.isTeacher() log.debug("classrooms.join: Cannot join a classroom as a teacher: #{req.user.id}") throw new errors.Forbidden('Cannot join a classroom as a teacher') - code = req.body.code.toLowerCase().replace(/ /g, '') + code = req.body.code.toLowerCase().replace(RegExp(' ', 'g'), '') classroom = yield Classroom.findOne({code: code}) if not classroom log.debug("classrooms.join: Classroom not found with code #{code}") diff --git a/test/app/lib/CoursesHelper.spec.coffee b/test/app/lib/CoursesHelper.spec.coffee index 243f01920..2512c8eb5 100644 --- a/test/app/lib/CoursesHelper.spec.coffee +++ b/test/app/lib/CoursesHelper.spec.coffee @@ -36,7 +36,6 @@ describe 'CoursesHelper', -> describe 'progressData.get({classroom, course})', -> it 'returns object with .completed=true and .started=true', -> progressData = helper.calculateAllProgress(@classrooms, @courses, @courseInstances, @members) - console.log 'progress data?', progressData progress = progressData.get {@classroom, @course} expect(progress.completed).toBe true expect(progress.started).toBe true