Working on repeatable achievement posting. Two tests still fail, though, so it's not there yet.

This commit is contained in:
Nick Winter 2015-01-07 12:25:31 -08:00
parent a0a8b2a961
commit 1455dc0550
8 changed files with 23 additions and 20 deletions

View file

@ -84,7 +84,7 @@ module.exports = class User extends CocoModel
gemsEarned = @get('earned')?.gems ? 0
gemsPurchased = @get('purchased')?.gems ? 0
gemsSpent = @get('spent') ? 0
gemsEarned + gemsPurchased - gemsSpent
Math.floor gemsEarned + gemsPurchased - gemsSpent
heroes: ->
heroes = (me.get('purchased')?.heroes ? []).concat([ThangType.heroes.captain, ThangType.heroes.knight])
@ -139,7 +139,7 @@ module.exports = class User extends CocoModel
else
@subscribeCopyGroup = 'original'
@subscribeCopyGroup
getVideoTutorialStylesIndex: (numVideos=0)->
# A/B Testing video tutorial styles
# Not a constant number of videos available (e.g. could be 0, 1, 3, or 4 currently)

View file

@ -34,7 +34,7 @@ defaultTasks = [
'Write a loading tip, if needed.'
'Click the Populate i18n button.'
'Mark whether it requires a subscription (after adventurer week).'
'Mark whether it requires a subscription.'
'Release to everyone via MailChimp.'
'Check completion/engagement/problem analytics.'

View file

@ -227,7 +227,7 @@ me.RewardSchema = (descriptionFragment='earned by achievements') ->
me.stringID(links: [{rel: 'db', href: '/db/thang.type/{($)}/version'}], title: 'Item ThangType', description: 'A reference to the earned item ThangType.', format: 'thang-type')
levels: me.array {uniqueItems: true, description: "Levels #{descriptionFragment}."},
me.stringID(links: [{rel: 'db', href: '/db/level/{($)}/version'}], title: 'Level', description: 'A reference to the earned Level.', format: 'latest-version-original-reference')
gems: me.int {description: "Gems #{descriptionFragment}."}
gems: me.float {description: "Gems #{descriptionFragment}."}
me.task = me.object {title: 'Task', description: 'A task to be completed', format: 'task', default: {name: 'TODO', complete: false}},
name: {title: 'Name', description: 'What must be done?', type: 'string'}

View file

@ -16,7 +16,7 @@ EarnedAchievementSchema.pre 'save', (next) ->
EarnedAchievementSchema.index({user: 1, achievement: 1}, {unique: true, name: 'earned achievement index'})
EarnedAchievementSchema.index({user: 1, changed: -1}, {name: 'latest '})
EarnedAchievementSchema.statics.createForAchievement = (achievement, doc, originalDocObj, done) ->
EarnedAchievementSchema.statics.createForAchievement = (achievement, doc, originalDocObj=null, previouslyEarnedAchievement=null, done) ->
User = require '../users/User'
userObjectID = doc.get(achievement.get('userField'))
userID = if _.isObject userObjectID then userObjectID.toHexString() else userObjectID # Standardize! Use strings, not ObjectId's
@ -48,16 +48,21 @@ EarnedAchievementSchema.statics.createForAchievement = (achievement, doc, origin
if isRepeatable
#log.debug 'Upserting repeatable achievement called \'' + (achievement.get 'name') + '\' for ' + userID
proportionalTo = achievement.get 'proportionalTo'
originalAmount = if originalDocObj then util.getByPath(originalDocObj, proportionalTo) or 0 else 0
docObj = doc.toObject()
newAmount = util.getByPath(docObj, proportionalTo) or 0
console.log 'original amount is', originalAmount, 'and new amount is', newAmount, 'for', proportionalTo, 'with doc', docObj
if previouslyEarnedAchievement
originalAmount = previouslyEarnedAchievement.get('achievedAmount') or 0
else if originalDocObj and not newAmount # This branch could get buggy if unchangedCopy tracking isn't working.
originalAmount = util.getByPath(originalDocObj, proportionalTo) or 0
else
originalAmount = 0
#console.log 'original amount is', originalAmount, 'and new amount is', newAmount, 'for', proportionalTo, 'with doc', docObj, 'and previously earned achievement amount', previouslyEarnedAchievement?.get('achievedAmount')
if originalAmount isnt newAmount
expFunction = achievement.getExpFunction()
earned.notified = false
earned.achievedAmount = newAmount
console.log 'earnedPoints is', (expFunction(newAmount) - expFunction(originalAmount)) * pointWorth, 'was', earned.earnedPoints, earned.previouslyAchievedAmount, 'got exp function for new amount', newAmount, expFunction(newAmount), 'for original amount', originalAmount, expFunction(originalAmount), 'with point worth', pointWorth
#console.log 'earnedPoints is', (expFunction(newAmount) - expFunction(originalAmount)) * pointWorth, 'was', earned.earnedPoints, earned.previouslyAchievedAmount, 'got exp function for new amount', newAmount, expFunction(newAmount), 'for original amount', originalAmount, expFunction(originalAmount), 'with point worth', pointWorth
earnedPoints = earned.earnedPoints = (expFunction(newAmount) - expFunction(originalAmount)) * pointWorth
earnedGems = earned.earnedGems = (expFunction(newAmount) - expFunction(originalAmount)) * gemWorth
earned.previouslyAchievedAmount = originalAmount

View file

@ -66,7 +66,7 @@ class EarnedAchievementHandler extends Handler
else if not trigger
return @sendNotFoundError(res, 'Could not find trigger.')
else if achievement.get('proportionalTo')
EarnedAchievement.createForAchievement(achievement, trigger, trigger.unchangedCopy, (earnedAchievementDoc) =>
EarnedAchievement.createForAchievement(achievement, trigger, trigger.unchangedCopy, earned, (earnedAchievementDoc) =>
@sendCreated(res, (earnedAchievementDoc or earned)?.toObject())
)
else if earned
@ -87,7 +87,7 @@ class EarnedAchievementHandler extends Handler
return @sendSuccess(res, earned.toObject())
)
else
EarnedAchievement.createForAchievement(achievement, trigger, null, (earnedAchievementDoc) =>
EarnedAchievement.createForAchievement(achievement, trigger, null, null, (earnedAchievementDoc) =>
@sendCreated(res, earnedAchievementDoc.toObject())
)
)

View file

@ -14,10 +14,8 @@ AchievablePlugin = (schema, options) ->
# Keep track the document before it's saved
schema.post 'init', (doc) ->
doc.unchangedCopy = doc.toObject()
## Haaaaaaack, but better than cloneDeeping everything TODOOOO: otherwise the achievement doesn't realize that the document just changed
#doc.unchangedCopy.state = _.cloneDeep doc.unchangedCopy.state if doc.unchangedCopy.state
## Actually, it doesn't work still.
unless doc.unchangedCopy
doc.unchangedCopy = doc.toObject()
# Check if an achievement has been earned
schema.post 'save', (doc) ->

View file

@ -575,8 +575,8 @@ sendLadderUpdateEmail = (session, now, daysAgo) ->
unless user.get('email') and allowNotes and not session.unsubscribed
#log.info "Not sending email to #{user.get('email')} #{user.get('name')} because they only want emails about #{user.get('emailSubscriptions')}, #{user.get('emails')} - session unsubscribed: #{session.unsubscribed}"
return
unless session.levelName
#log.info "Not sending email to #{user.get('email')} #{user.get('name')} because the session had no levelName in it."
unless session.levelName and session.team
#log.info "Not sending email to #{user.get('email')} #{user.get('name')} because the session had levelName #{session.levelName} or team #{session.team} in it."
return
name = if user.get('firstName') and user.get('lastName') then "#{user.get('firstName')}" else user.get('name')
name = 'Wizard' if not name or name is 'Anoner'

View file

@ -174,12 +174,12 @@ describe 'Achieving Achievements', ->
User.findById(joe.get('_id')).exec (err, joe2) ->
expect(joe2.get('earned').gems).toBe(2)
EarnedAchievement.find {achievementName: repeatable.name}, (err, docs) ->
expect(err).toBeNull()
expect(docs.length).toBe(1)
achievement = docs[0]
if achievement
expect(achievement.get 'achievement').toBe repeatable._id
expect(achievement.get 'user').toBe joe._id.toHexString()
@ -201,7 +201,7 @@ describe 'Achieving Achievements', ->
expect(achievement.get 'earnedPoints').toBe (Math.log(.5 * (2 + .5)) + 1) * diminishing.worth
done()
it 'increases gems proportionally to changes made', (done) ->
unittest.getNormalJoe (joe) ->
User.findById(joe.get('_id')).exec (err, joe2) ->
@ -209,7 +209,7 @@ describe 'Achieving Achievements', ->
joe2.save (err, joe3) ->
expect(err).toBeNull()
User.findById(joe3.get('_id')).exec (err, joe4) ->
expect(joe4.get('earned').gems).toBe(4)
expect(joe4.get('earned').gems).toBe(4) # Crap, it's 6 TODO
done()