gamesCompleted now properly fires achievements even though it's not using normal saves.

This commit is contained in:
Nick Winter 2015-02-18 17:08:54 -08:00
parent 880d22ed50
commit 87f3b9e135
3 changed files with 16 additions and 7 deletions

View file

@ -47,8 +47,12 @@ LevelSessionSchema.pre 'save', (next) ->
# Newly completed level
if not (initd and @previousStateInfo['state.complete']) and @get('state.complete')
User.update {_id: userID}, {$inc: 'stats.gamesCompleted': 1}, {}, (err, count) ->
User.findByIdAndUpdate userID, {$inc: 'stats.gamesCompleted': 1}, {}, (err, doc) ->
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
activeUserEvent = "level-completed/#{levelID}"
# Spent at least 30s playing this level

View file

@ -19,26 +19,30 @@ AchievablePlugin = (schema, options) ->
# Check if an achievement has been earned
schema.post 'save', (doc) ->
isNew = not doc.isInit('_id') or not doc.unchangedCopy
schema.statics.createNewEarnedAchievements doc
if doc.isInit('_id') and not doc.unchangedCopy
schema.statics.createNewEarnedAchievements = (doc, unchangedCopy) ->
unchangedCopy ?= doc.unchangedCopy
isNew = not doc.isInit('_id') or not unchangedCopy
if doc.isInit('_id') and not unchangedCopy
log.warn 'document was already initialized but did not go through `init` and is therefore treated as new while it might not be'
category = doc.constructor.collection.name
loadedAchievements = Achievement.getLoadedAchievements()
#log.debug 'about to save ' + category + ', number of achievements is ' + Object.keys(loadedAchievements).length
if category of loadedAchievements
#log.debug 'about to save ' + category + ', number of achievements is ' + loadedAchievements[category].length
docObj = doc.toObject()
for achievement in loadedAchievements[category]
do (achievement) ->
query = achievement.get('query')
return log.error("Empty achievement query for #{achievement.get('name')}.") if _.isEmpty query
isRepeatable = achievement.get('proportionalTo')?
alreadyAchieved = if isNew then false else LocalMongo.matchesQuery doc.unchangedCopy, query
alreadyAchieved = if isNew then false else LocalMongo.matchesQuery unchangedCopy, query
newlyAchieved = LocalMongo.matchesQuery(docObj, query)
return unless newlyAchieved and (not alreadyAchieved or isRepeatable)
#log.info "Making an achievement: #{achievement.get('name')} #{achievement.get('_id')} for doc: #{doc.get('name')} #{doc.get('_id')}"
EarnedAchievement.createForAchievement(achievement, doc, doc.unchangedCopy)
EarnedAchievement.createForAchievement(achievement, doc, unchangedCopy)
module.exports = AchievablePlugin

View file

@ -206,10 +206,11 @@ describe 'Achieving Achievements', ->
unittest.getNormalJoe (joe) ->
User.findById(joe.get('_id')).exec (err, joe2) ->
joe2.set('simulatedBy', 4)
expect(joe2.get('earned').gems).toBe(2)
joe2.save (err, joe3) ->
expect(err).toBeNull()
User.findById(joe3.get('_id')).exec (err, joe4) ->
expect(joe4.get('earned').gems).toBe(4) # Crap, it's 6 TODO
expect(joe4.get('earned').gems).toBe(4) # ... this sometimes gives 4, sometimes 2. Race condition?
done()