From 34715befccdad4eab62866eb315c47d6aaa53cb4 Mon Sep 17 00:00:00 2001 From: Nick Winter Date: Wed, 4 Nov 2015 13:42:01 -0800 Subject: [PATCH] Increment user's concept stats on level completion --- app/schemas/models/user.coffee | 1 + app/views/play/level/tome/SpellView.coffee | 3 ++- server/levels/sessions/LevelSession.coffee | 19 ++++++++++++++----- server/users/User.coffee | 9 ++++++++- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/app/schemas/models/user.coffee b/app/schemas/models/user.coffee index 18f63e67f..8955bafb6 100644 --- a/app/schemas/models/user.coffee +++ b/app/schemas/models/user.coffee @@ -280,6 +280,7 @@ _.extend UserSchema.properties, pollMiscPatches: c.int() campaignTranslationPatches: c.int() campaignMiscPatches: c.int() + concepts: {type: 'object', additionalProperties: c.int(), description: 'Number of levels completed using each programming concept.'} earned: c.RewardSchema 'earned by achievements' purchased: c.RewardSchema 'purchased with gems or money' diff --git a/app/views/play/level/tome/SpellView.coffee b/app/views/play/level/tome/SpellView.coffee index 84386d734..88c64f6a0 100644 --- a/app/views/play/level/tome/SpellView.coffee +++ b/app/views/play/level/tome/SpellView.coffee @@ -106,6 +106,7 @@ module.exports = class SpellView extends CocoView @ace.setAnimatedScroll true @ace.setShowFoldWidgets false @ace.setKeyboardHandler @keyBindings[aceConfig.keyBindings ? 'default'] + @ace.$blockScrolling = Infinity @toggleControls null, @writable @aceSession.selection.on 'changeCursor', @onCursorActivity $(@ace.container).find('.ace_gutter').on 'click mouseenter', '.ace_error, .ace_warning, .ace_info', @onAnnotationClick @@ -459,7 +460,7 @@ module.exports = class SpellView extends CocoView entry.captureReturn = switch e.language when 'io' then varName + ' := ' when 'javascript' then 'var ' + varName + ' = ' - when 'clojure' then '(let [' + varName + ' ' + when 'clojure' then '(let [' + varName + ' ' else varName + ' = ' # TODO: Generalize this snippet replacement diff --git a/server/levels/sessions/LevelSession.coffee b/server/levels/sessions/LevelSession.coffee index e8d218bbb..04c22a5e9 100644 --- a/server/levels/sessions/LevelSession.coffee +++ b/server/levels/sessions/LevelSession.coffee @@ -44,6 +44,7 @@ LevelSessionSchema.post 'init', (doc) -> LevelSessionSchema.pre 'save', (next) -> User = require '../../users/User' # Avoid mutual inclusion cycles + Level = require '../Level' @set('changed', new Date()) id = @get('id') @@ -54,12 +55,20 @@ LevelSessionSchema.pre 'save', (next) -> # Newly completed level if not (initd and @previousStateInfo['state.complete']) and @get('state.complete') - User.findByIdAndUpdate userID, {$inc: 'stats.gamesCompleted': 1}, {}, (err, doc) -> + Level.findOne({slug: levelID}).select('concepts -_id').lean().exec (err, level) -> log.error err if err? - oldCopy = doc.toObject() - oldCopy.stats = _.clone oldCopy.stats - oldCopy.stats.gamesCompleted = oldCopy.stats.gamesCompleted - 1 - User.schema.statics.createNewEarnedAchievements doc, oldCopy + update = $inc: {'stats.gamesCompleted': 1} + for concept in level?.concepts ? [] + update.$inc["stats.concepts.#{concept}"] = 1 + User.findByIdAndUpdate userID, update, {}, (err, user) -> + log.error err if err? + oldCopy = user.toObject() + oldCopy.stats = _.clone oldCopy.stats + --oldCopy.stats.gamesCompleted + oldCopy.stats.concepts ?= {} + for concept in level?.concepts ? [] + --oldCopy.stats.concepts[concept] + User.schema.statics.createNewEarnedAchievements user, oldCopy activeUserEvent = "level-completed/#{levelID}" # Spent at least 30s playing this level diff --git a/server/users/User.coffee b/server/users/User.coffee index 88c99d0e2..08140b999 100644 --- a/server/users/User.coffee +++ b/server/users/User.coffee @@ -192,7 +192,14 @@ UserSchema.statics.incrementStat = (id, statName, done, inc=1) -> user.incrementStat statName, done, inc UserSchema.methods.incrementStat = (statName, done, inc=1) -> - @set statName, (@get(statName) or 0) + inc + if /^concepts\./.test statName + # Concept stats are nested a level deeper. + concepts = @get('concepts') or {} + concept = statName.split('.')[1] + concepts[concept] = (concepts[concept] or 0) + inc + @set 'concepts', concepts + else + @set statName, (@get(statName) or 0) + inc @save (err) -> done?(err) UserSchema.statics.unconflictName = unconflictName = (name, done) ->