From 9d15e724e267bab8aab712aacf21afe5dcf767ac Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 31 Oct 2013 13:49:31 -0700 Subject: [PATCH] challenge prize: award winner 1 achievement and challenge.prize gems. then close challenge. --- src/controllers/challenges.js | 63 ++++++++++++++++++++----- src/models/task.js | 3 +- src/models/user.js | 4 +- views/shared/profiles/achievements.jade | 12 ++++- views/shared/tasks/task.jade | 6 +++ 5 files changed, 73 insertions(+), 15 deletions(-) diff --git a/src/controllers/challenges.js b/src/controllers/challenges.js index f34c55f6de..0d3e78008e 100644 --- a/src/controllers/challenges.js +++ b/src/controllers/challenges.js @@ -206,32 +206,71 @@ api.update = function(req, res){ }) } -// DELETE -api['delete'] = function(req, res){ +/** + * Called by either delete() or selectWinner(). Will delete the challenge and set the "broken" property on all users' subscribed tasks + * @param {cid} the challenge id + * @param {broken} the object representing the broken status of the challenge. Eg: + * {broken: 'CHALLENGE_DELETED', id: CHALLENGE_ID} + * {broken: 'CHALLENGE_CLOSED', id: CHALLENGE_ID, winner: USER_NAME} + */ +function closeChal(cid, broken, cb) { var removed; async.waterfall([ - function(cb){ - Challenge.findOneAndRemove({_id:req.params.cid}, cb) + function(cb2){ + Challenge.findOneAndRemove({_id:cid}, cb2) }, - function(_removed, cb) { + function(_removed, cb2) { removed = _removed; - User.find({_id:{$in: removed.members}}, cb); + User.find({_id:{$in: removed.members}}, cb2); }, - function(users, cb) { + function(users, cb2) { var parallel = []; _.each(users, function(user){ _.each(user.tasks, function(task){ if (task.challenge && task.challenge.id == removed._id) { - task.challenge.broken = 'CHALLENGE_DELETED'; + _.mege(task.challenge, broken); } }) - parallel.push(function(cb2){ - user.save(cb2); + parallel.push(function(cb3){ + user.save(cb3); }) }) - async.parallel(parallel, cb); + async.parallel(parallel, cb2); } - ], function(err){ + ], cb); +} + +// DELETE +api['delete'] = function(req, res){ + closeChal(req.params.cid, {broken: 'CHALLENGE_DELETED'}, function(err){ + if (err) return res.json(500, {err: err}); + res.send(200); + }) +} + +api.selectWinner = function(req, res) { + if (!req.query.uid) return res.json(401, {err: 'Must select a winner'}); + var chal; + async.waterfall([ + function(cb){ + Challenge.findById(req.params.cid, cb); + }, + function(_chal, cb){ + if (!_chal) return cb('Challenge ' + req.params.cid + ' not found.'); + chal = _chal; + User.findById(req.query.uid, cb) + }, + function(winner, cb){ + if (!winner) return cb('Winner ' + req.query.uid + ' not found.'); + _.defaults(winner.achievements, {challenges: []}); + winner.achievements.challenges.push(chal.name); + winner.balance += chal.prize/4; + winner.save(cb); + }, + function(saved, num, cb) { + closeChal(req.params.cid, {broken: 'CHALLENGE_CLOSED', winner: saved.profile.name}, cb); + } + ], function(){ if (err) return res.json(500, {err: err}); res.send(200); }) diff --git a/src/models/task.js b/src/models/task.js index 3935e0f232..97a46cdb94 100644 --- a/src/models/task.js +++ b/src/models/task.js @@ -28,7 +28,8 @@ var TaskSchema = new Schema({ streak: {type: Number, 'default': 0}, challenge: { id: {type: 'String', ref:'Challenge'}, - broken: String // CHALLENGE_DELETED, TASK_DELETED, UNSUBSCRIBED, etc + broken: String, // CHALLENGE_DELETED, TASK_DELETED, UNSUBSCRIBED, CHALLENGE_CLOSED + winner: String // user.profile.name // group: {type: 'Strign', ref: 'Group'} // if we restore this, rename `id` above to `challenge` } }, { diff --git a/src/models/user.js b/src/models/user.js index 78d2276fb3..23dee6f247 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -36,7 +36,9 @@ var UserSchema = new Schema({ helpedHabit: Boolean, ultimateGear: Boolean, beastMaster: Boolean, - streak: Number + veteran: Boolean, + streak: Number, + challenges: Array }, auth: { facebook: Schema.Types.Mixed, diff --git a/views/shared/profiles/achievements.jade b/views/shared/profiles/achievements.jade index 3678d69696..e85f222929 100644 --- a/views/shared/profiles/achievements.jade +++ b/views/shared/profiles/achievements.jade @@ -74,4 +74,14 @@ h5 Original User! small | One of the very original early adopters, Talk about alpha tester! - hr \ No newline at end of file + hr + + div(ng-if='profile.achievements.challenges || user._id == profile._id') + // This is a very strange icon to use. revisit + .achievement.achievement-karaoke(ng-show='profile.achievements.challenges') + div(ng-class='{muted: !profile.achievements.challenges}') + h5 Was the winner in the following challenges + ul + li(ng-repeat='chal in profile.achievements.challenges') {{chal}} + hr + diff --git a/views/shared/tasks/task.jade b/views/shared/tasks/task.jade index f88d9a238f..fde272458e 100644 --- a/views/shared/tasks/task.jade +++ b/views/shared/tasks/task.jade @@ -75,6 +75,12 @@ li(ng-repeat='task in obj[list.type+"s"]', class='task {{taskClasses(task, user. a(ng-click='unlink(task, "keep-all")') Keep Them |  |  a(ng-click='unlink(task, "remove-all")') Remove Them + div(ng-if='task.challenge.broken=="CHALLENGE_CLOSED"') + p. This challenge has been completed, and the winner was {{task.challenge.winner}}!. What to do with the orphan tasks? + p + a(ng-click='unlink(task, "keep-all")') Keep Them + |  |  + a(ng-click='unlink(task, "remove-all")') Remove Them //-div(ng-if='task.challenge.broken=="UNSUBSCRIBED"') p Broken Challenge Link: this task was part of a challenge, but you have unsubscribed from the challenge. What to do with the orphan tasks? p