mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-30 10:56:53 -05:00
d72e4eb750
Update classroom and gameplay Ux to surface practice levels as 3a, 3b, etc. Update next level logic to leverage practice levels based on per level completion playtime thresholds. Patrol buster and patrol buster A are live for testing. Fix a few classroom Ux progress hover bubble info bugs. Closes #3767
85 lines
3.5 KiB
CoffeeScript
85 lines
3.5 KiB
CoffeeScript
wrap = require 'co-express'
|
|
errors = require '../commons/errors'
|
|
Level = require '../models/Level'
|
|
LevelSession = require '../models/LevelSession'
|
|
CourseInstance = require '../models/CourseInstance'
|
|
Classroom = require '../models/Classroom'
|
|
Course = require '../models/Course'
|
|
database = require '../commons/database'
|
|
|
|
module.exports =
|
|
upsertSession: wrap (req, res) ->
|
|
level = yield database.getDocFromHandle(req, Level)
|
|
if not level
|
|
throw new errors.NotFound('Level not found.')
|
|
|
|
sessionQuery =
|
|
level:
|
|
original: level.get('original').toString()
|
|
majorVersion: level.get('version').major
|
|
creator: req.user.id
|
|
|
|
if req.query.team?
|
|
sessionQuery.team = req.query.team
|
|
|
|
session = yield LevelSession.findOne(sessionQuery)
|
|
if session
|
|
return res.send(session.toObject({req: req}))
|
|
|
|
attrs = sessionQuery
|
|
_.extend(attrs, {
|
|
state:
|
|
complete: false
|
|
scripts:
|
|
currentScript: null # will not save empty objects
|
|
permissions: [
|
|
{target: req.user.id, access: 'owner'}
|
|
{target: 'public', access: 'write'}
|
|
]
|
|
codeLanguage: req.user.get('aceConfig')?.language ? 'python'
|
|
})
|
|
|
|
if level.get('type') in ['course', 'course-ladder'] or req.query.course?
|
|
|
|
# Find the course and classroom that has assigned this level, verify access
|
|
courseInstances = yield CourseInstance.find({members: req.user._id})
|
|
classroomIDs = (courseInstance.get('classroomID') for courseInstance in courseInstances)
|
|
classroomIDs = _.filter _.uniq classroomIDs, false, (objectID='') -> objectID.toString()
|
|
classrooms = yield Classroom.find({ _id: { $in: classroomIDs }})
|
|
classroomWithLevel = null
|
|
courseID = null
|
|
classroomMap = {}
|
|
classroomMap[classroom.id] = classroom for classroom in classrooms
|
|
levelOriginal = level.get('original')
|
|
for courseInstance in courseInstances
|
|
classroomID = courseInstance.get('classroomID')
|
|
continue unless classroomID
|
|
classroom = classroomMap[classroomID.toString()]
|
|
continue unless classroom
|
|
courseID = courseInstance.get('courseID')
|
|
classroomCourse = _.find(classroom.get('courses'), (c) -> c._id.equals(courseID))
|
|
for courseLevel in classroomCourse.levels
|
|
if courseLevel.original.equals(levelOriginal)
|
|
classroomWithLevel = classroom
|
|
break
|
|
break if classroomWithLevel
|
|
|
|
unless classroomWithLevel
|
|
throw new errors.PaymentRequired('You must be in a course which includes this level to play it')
|
|
|
|
course = yield Course.findById(courseID).select('free')
|
|
unless course.get('free') or req.user.isEnrolled()
|
|
throw new errors.PaymentRequired('You must be enrolled to access this content')
|
|
|
|
lang = classroomWithLevel.get('aceConfig')?.language
|
|
attrs.codeLanguage = lang if lang
|
|
|
|
else
|
|
requiresSubscription = level.get('requiresSubscription') or (req.user.isOnPremiumServer() and level.get('campaign') and not (level.slug in ['dungeons-of-kithgard', 'gems-in-the-deep', 'shadow-guard', 'forgetful-gemsmith', 'signs-and-portents', 'true-names']))
|
|
canPlayAnyway = req.user.isPremium() or level.get 'adventurer'
|
|
if requiresSubscription and not canPlayAnyway
|
|
throw new errors.PaymentRequired('This level requires a subscription to play')
|
|
|
|
session = new LevelSession(attrs)
|
|
yield session.save()
|
|
res.send(session.toObject({req: req}))
|