Got proportionalTo working with gems as well as points. Probably also got it working for LevelSessions, but this should be tested.

This commit is contained in:
Scott Erickson 2015-01-06 18:14:19 -08:00
parent 7f203f246c
commit 2f36884456
3 changed files with 52 additions and 26 deletions

View file

@ -27,18 +27,20 @@ EarnedAchievementSchema.statics.createForAchievement = (achievement, doc, origin
achievementName: achievement.get 'name'
earnedRewards: achievement.get 'rewards'
worth = achievement.get('worth') ? 10
pointWorth = achievement.get('worth') ? 10
gemWorth = achievement.get('rewards')?.gems ? 0
earnedPoints = 0
earnedGems = 0
wrapUp = (earnedAchievementDoc) ->
# Update user's experience points
update = {$inc: {points: earnedPoints}}
update = {$inc: {points: earnedPoints, 'earned.gems': earnedGems}}
for rewardType, rewards of achievement.get('rewards') ? {}
if rewardType is 'gems'
update.$inc['earned.gems'] = rewards if rewards
else if rewards.length
continue if rewardType is 'gems'
if rewards.length
update.$addToSet ?= {}
update.$addToSet["earned.#{rewardType}"] = $each: rewards
User.update {_id: userID}, update, {}, (err, count) ->
User.update {_id: mongoose.Types.ObjectId(userID)}, update, {}, (err, count) ->
log.error err if err?
done?(earnedAchievementDoc)
@ -54,21 +56,25 @@ EarnedAchievementSchema.statics.createForAchievement = (achievement, doc, origin
expFunction = achievement.getExpFunction()
earned.notified = false
earned.achievedAmount = newAmount
earned.earnedPoints = (expFunction(newAmount) - expFunction(originalAmount)) * worth
earnedPoints = earned.earnedPoints = (expFunction(newAmount) - expFunction(originalAmount)) * pointWorth
earnedGems = earned.earnedGems = (expFunction(newAmount) - expFunction(originalAmount)) * gemWorth
earned.previouslyAchievedAmount = originalAmount
EarnedAchievement.update {achievement: earned.achievement, user: earned.user}, earned, {upsert: true}, (err) ->
return log.debug err if err?
earnedPoints = earned.earnedPoints
#log.debug earnedPoints
wrapUp()
wrapUp(new EarnedAchievement(earned))
else
done?()
else # not alreadyAchieved
#log.debug 'Creating a new earned achievement called \'' + (achievement.get 'name') + '\' for ' + userID
earned.earnedPoints = worth
earned.earnedPoints = pointWorth
earned.earnedGems = gemWorth
(new EarnedAchievement(earned)).save (err, doc) ->
return log.error err if err?
earnedPoints = worth
earnedPoints = pointWorth
earnedGems = gemWorth
wrapUp(doc)
User.saveActiveUser userID, "achievement"

View file

@ -65,6 +65,10 @@ class EarnedAchievementHandler extends Handler
return @sendNotFoundError(res, 'Could not find achievement.')
else if not trigger
return @sendNotFoundError(res, 'Could not find trigger.')
else if achievement.get('proportionalTo')
EarnedAchievement.createForAchievement(achievement, trigger, trigger.unchangedCopy, (earnedAchievementDoc) =>
@sendCreated(res, (earnedAchievementDoc or earned)?.toObject())
)
else if earned
achievementEarned = achievement.get('rewards')
actuallyEarned = earned.get('earnedRewards')
@ -82,8 +86,6 @@ class EarnedAchievementHandler extends Handler
return @sendDatabaseError(res, err) if err
return @sendSuccess(res, earned.toObject())
)
else if achievement.get('proportionalTo')
return @sendBadInputError(res, 'Cannot currently do this to repeatable docs...')
else
EarnedAchievement.createForAchievement(achievement, trigger, null, (earnedAchievementDoc) =>
@sendCreated(res, earnedAchievementDoc.toObject())

View file

@ -21,6 +21,8 @@ repeatable =
userField: '_id'
proportionalTo: 'simulatedBy'
recalculable: true
rewards:
gems: 1
diminishing =
name: 'Simulated2'
@ -169,19 +171,23 @@ describe 'Achieving Achievements', ->
it 'verify that a repeatable achievement has been earned', (done) ->
unittest.getNormalJoe (joe) ->
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()
expect(achievement.get 'notified').toBeFalsy()
expect(achievement.get 'earnedPoints').toBe 2 * repeatable.worth
expect(achievement.get 'achievedAmount').toBe 2
expect(achievement.get 'previouslyAchievedAmount').toBeFalsy()
done()
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()
expect(achievement.get 'notified').toBeFalsy()
expect(achievement.get 'earnedPoints').toBe 2 * repeatable.worth
expect(achievement.get 'achievedAmount').toBe 2
expect(achievement.get 'previouslyAchievedAmount').toBeFalsy()
done()
it 'verify that the repeatable achievement with complex exp has been earned', (done) ->
unittest.getNormalJoe (joe) ->
@ -195,6 +201,17 @@ 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) ->
joe2.set('simulatedBy', 4)
joe2.save (err, joe3) ->
expect(err).toBeNull()
User.findById(joe3.get('_id')).exec (err, joe4) ->
expect(joe4.get('earned').gems).toBe(4)
done()
describe 'Recalculate Achievements', ->
EarnedAchievementHandler = require '../../../server/achievements/earned_achievement_handler'
@ -241,7 +258,8 @@ describe 'Recalculate Achievements', ->
unittest.getNormalJoe (joe) ->
User.findById joe.get('id'), (err, guy) ->
expect(err).toBeNull()
expect(guy.get 'points').toBe unlockable.worth + 2 * repeatable.worth + (Math.log(.5 * (2 + .5)) + 1) * diminishing.worth
# TODO: fix this to properly handle recalculating proportionalTo recalculation
expect(guy.get 'points').toBe unlockable.worth + 2 * repeatable.worth + (Math.log(.5 * (4 + .5)) + 1) * diminishing.worth
done()
it 'cleaning up test: deleting all Achievements and related', (done) ->