diff --git a/src/app/index.coffee b/src/app/index.coffee index 55ebf7cc2f..b25e52cb9d 100644 --- a/src/app/index.coffee +++ b/src/app/index.coffee @@ -45,13 +45,13 @@ get '/', (page, model, params, next) -> ready (model) -> user = model.at('_user') - scoring.setModel(model) + score = new scoring.Scoring(model) #set cron immediately lastCron = user.get('lastCron') user.set('lastCron', +new Date) if (!lastCron? or lastCron == 'new') - scoring.cron() + score.cron() character.app(exports, model) tasks.app(exports, model) diff --git a/src/app/party.coffee b/src/app/party.coffee index 268214bb47..f1dcd2890e 100644 --- a/src/app/party.coffee +++ b/src/app/party.coffee @@ -16,6 +16,15 @@ partyUnsubscribe = (model, cb) -> 1) If the user is solo, just subscribe to the user. 2) If in a an empty party, just subscribe to the user & party meta. 3) If full party, subscribe to everything. + + Note a strange hack - we subscribe to queries incrementally. First self, then party, then party members. + Party members come with limited fields, so you can't hack their stuff. Strangely, subscribing to the members after + already subscribing to self limits self's fields to the fields which members are limited to. As a result, we have + to re-subscribe to self to get all the fields (otherwise everything breaks). Weirdly, this last subscription doesn't + do the opposite - granting all the fields back to members. I dont' know what's going on here + + Another issue: `model.unsubscribe(selfQ)` would seem to mitigate the above, so we at least don't have a stray + subscription floating around - but alas, it doesn't seem to work (or at least never calls the callback) ### module.exports.partySubscribe = partySubscribe = (page, model, params, next, cb) -> @@ -23,65 +32,41 @@ module.exports.partySubscribe = partySubscribe = (page, model, params, next, cb) # partyUnsubscribe model, -> # Restart subscription to the main user - selfQ = model.query('users').withId model.get('_userId') #or model.session.userId # see http://goo.gl/TPYIt - selfQ.subscribe (err, self) -> + selfQ = model.query('users').withId (model.get('_userId') or model.session.userId) # see http://goo.gl/TPYIt + selfQ.fetch (err, user) -> return next(err) if err - u = self.at(0) - uObj = u.get() + return next("User not found - this shouldn't be happening!") unless user.get() + + finished = (descriptors, paths) -> + model.subscribe.apply model, descriptors.concat -> + [err, refs] = [arguments[0], arguments] + return next(err) if err + _.each paths, (path, idx) -> model.ref path, refs[idx+1] + cb() + # Attempted handling for 'party of undefined' error, which is caused by bustedSession (see derby-auth). # Theoretically simply reloading the page should restore model.at('_userId') and the second load should work just fine # bustedSession victims might hit a redirection loop if I'm wrong :/ - return page.redirect('/') unless uObj +# return page.redirect('/') unless uObj - ## (1) User is solo, just return that subscription - unless uObj.party?.current? - model.ref '_user', u - return cb() + partyId = user.get('party.current') - ### - Note this strange hack - we subscribe to queries incrementally. First self, then party, then party members. - Party members come with limited fields, so you can't hack their stuff. Strangely, subscribing to the members after - already subscribing to self limits self's fields to the fields which members are limited to. As a result, we have - to re-subscribe to self to get all the fields (otherwise everything breaks). Weirdly, this last subscription doesn't - do the opposite - granting all the fields back to members. I dont' know what's going on here - - Another issue: `model.unsubscribe(selfQ)` would seem to mitigate the above, so we at least don't have a stray - subscription floating around - but alas, it doesn't seem to work (or at least never calls the callback) - ### - finished = -> - # model.unsubscribe selfQ, -> - selfQ.subscribe (err, self) -> - return next(err) if err - model.ref '_user', self.at(0) - cb() + # (1) Solo player + return finished([selfQ], ['_user']) unless partyId # User in a party - partiesQ = model.query('parties').withId(uObj.party.current) - partiesQ.fetch (err, res) -> + partyQ = model.query('parties').withId(partyId) + partyQ.fetch (err, party) -> return next(err) if err - p = res.at(0) - model.ref '_party', p - ids = p.get('members') - - # FIXME this is the kicker right here. This isn't getting triggered, and it's the reason why we have to refresh - # after every event. Get this working - #p.on '*', 'members', (ids) -> - # console.log("members listener got called") - # debugger - # membersSubscribe model, ids + members = party.get('members') ## (2) Party has no members, just subscribe to the party itself - if _.isEmpty(ids) - return finished() + return finished([partyQ, selfQ], ['_party', '_user']) if _.isEmpty(members) - else - ## (3) Party has members, subscribe to those users too - membersQ = model.query('users').party(ids) - membersQ.fetch (err, members) -> - return next(err) if err - model.ref '_partyMembers', members - finished() + ## (3) Party has members, subscribe to those users too + membersQ = model.query('users').party(members) + return finished [partyQ, membersQ, selfQ], ['_party', '_partyMembers', '_user'] module.exports.app = (appExports, model) -> user = model.at('_user') @@ -121,7 +106,7 @@ module.exports.app = (appExports, model) -> query = model.query('users').party([id]) model.fetch query, (err, res) -> throw err if err - u = res.at(0).get() + u = res.get() if !u?.id? model.set "_view.partyError", "User with id #{id} not found." return @@ -143,9 +128,9 @@ module.exports.app = (appExports, model) -> user.set 'party.current', partyId # model.push "parties.#{partyId}.members", user.get('id'), -> #FIXME why this not working? model.query('parties').withId(partyId).fetch (err, p) -> - members = p.at(0).get('members') + members = p.get('members') members.push user.get('id') - p.at(0).set 'members', members, -> + p.set 'members', members, -> window.location.reload true # partySubscribe model, -> # p = model.at('_party') @@ -174,5 +159,5 @@ module.exports.app = (appExports, model) -> # partyUnsubscribe model, -> # selfQ = model.query('users').withId model.get('_userId') #or model.session.userId # see http://goo.gl/TPYIt # selfQ.subscribe (err, u) -> -# model.ref '_user', u.at(0) +# model.ref '_user', u # browser.resetDom model \ No newline at end of file diff --git a/src/app/scoring.coffee b/src/app/scoring.coffee index 2eb2065c60..4f1b78db70 100644 --- a/src/app/scoring.coffee +++ b/src/app/scoring.coffee @@ -5,273 +5,269 @@ helpers = require './helpers' browser = require './browser' character = require './character' items = require './items' -MODIFIER = .02 # each new level, armor, weapon add 2% modifier (this number may change) -user = undefined -model = undefined -# This is required by all the functions, make sure it's set before anythign else is called -setModel = (m) -> - model = m - user = model.at('_user') +module.exports.Scoring = (model) -> -### - Calculates Exp & GP modification based on weapon & lvl - {value} task.value for gain - {modifiers} may manually pass in stats as {weapon, exp}. This is used for testing -### -expModifier = (value, modifiers = {}) -> - weapon = modifiers.weapon || user.get('items.weapon') - lvl = modifiers.lvl || user.get('stats.lvl') - dmg = items.items.weapon[weapon].modifier # each new weapon increases exp gain - dmg += (lvl-1) * MODIFIER # same for lvls - modified = value + (value * dmg) - return modified + MODIFIER = .02 # each new level, armor, weapon add 2% modifier (this mechanism will change) + user = model.at '_user' -### - Calculates HP-loss modification based on armor & lvl - {value} task.value which is hurting us - {modifiers} may manually pass in modifier as {armor, lvl}. This is used for testing -### -hpModifier = (value, modifiers = {}) -> - armor = modifiers.armor || user.get('items.armor') - head = modifiers.head || user.get('items.head') - shield = modifiers.shield || user.get('items.shield') - lvl = modifiers.lvl || user.get('stats.lvl') - ac = items.items.armor[armor].modifier + items.items.head[head].modifier + items.items.shield[shield].modifier # each new armor decreases HP loss - ac += (lvl-1) * MODIFIER # same for lvls - modified = value - (value * ac) - return modified - -### - Calculates the next task.value based on direction - For negative values, use a line: something like y=-.1x+1 - For positibe values, taper off with inverse log: y=.9^x - Would love to use inverse log for the whole thing, but after 13 fails it hits infinity. Revisit this formula later - {currentValue} the current value of the task, determines it's next value - {direction} 'up' or 'down' -### -taskDeltaFormula = (currentValue, direction) -> - sign = if (direction == "up") then 1 else -1 - delta = if (currentValue < 0) then (( -0.1 * currentValue + 1 ) * sign) else (( Math.pow(0.9,currentValue) ) * sign) - return delta + ### + Calculates Exp & GP modification based on weapon & lvl + {value} task.value for gain + {modifiers} may manually pass in stats as {weapon, exp}. This is used for testing + ### + expModifier = (value, modifiers = {}) -> + weapon = modifiers.weapon || user.get('items.weapon') + lvl = modifiers.lvl || user.get('stats.lvl') + dmg = items.items.weapon[weapon].modifier # each new weapon increases exp gain + dmg += (lvl-1) * MODIFIER # same for lvls + modified = value + (value * dmg) + return modified -### - Updates user stats with new stats. Handles death, leveling up, etc - {stats} new stats - {update} if aggregated changes, pass in userObj as update. otherwise commits will be made immediately -### -updateStats = (newStats, batch) -> - obj = batch.obj() + ### + Calculates HP-loss modification based on armor & lvl + {value} task.value which is hurting us + {modifiers} may manually pass in modifier as {armor, lvl}. This is used for testing + ### + hpModifier = (value, modifiers = {}) -> + armor = modifiers.armor || user.get('items.armor') + head = modifiers.head || user.get('items.head') + shield = modifiers.shield || user.get('items.shield') + lvl = modifiers.lvl || user.get('stats.lvl') + ac = items.items.armor[armor].modifier + items.items.head[head].modifier + items.items.shield[shield].modifier # each new armor decreases HP loss + ac += (lvl-1) * MODIFIER # same for lvls + modified = value - (value * ac) + return modified - # if user is dead, dont do anything - return if obj.stats.lvl == 0 + ### + Calculates the next task.value based on direction + For negative values, use a line: something like y=-.1x+1 + For positibe values, taper off with inverse log: y=.9^x + Would love to use inverse log for the whole thing, but after 13 fails it hits infinity. Revisit this formula later + {currentValue} the current value of the task, determines it's next value + {direction} 'up' or 'down' + ### + taskDeltaFormula = (currentValue, direction) -> + sign = if (direction == "up") then 1 else -1 + delta = if (currentValue < 0) then (( -0.1 * currentValue + 1 ) * sign) else (( Math.pow(0.9,currentValue) ) * sign) + return delta - if newStats.hp? - # Game Over - if newStats.hp <= 0 - obj.stats.lvl = 0 # signifies dead - obj.stats.hp = 0 - return - else - obj.stats.hp = newStats.hp - - if newStats.exp? - # level up & carry-over exp - tnl = model.get '_tnl' - if newStats.exp >= tnl - newStats.exp -= tnl - obj.stats.lvl++ - obj.stats.hp = 50 - - obj.stats.exp = newStats.exp - - # Set flags when they unlock features - if !obj.flags.customizationsNotification and (obj.stats.exp > 10 or obj.stats.lvl > 1) - batch.set 'flags.customizationsNotification', true - obj.flags.customizationsNotification = true - if !obj.flags.itemsEnabled and obj.stats.lvl >= 2 - # Set to object, then also send to browser right away to get model.on() subscription notification - batch.set 'flags.itemsEnabled', true - obj.flags.itemsEnabled = true - if !obj.flags.partyEnabled and obj.stats.lvl >= 3 - batch.set 'flags.partyEnabled', true - obj.flags.partyEnabled = true - if !obj.flags.petsEnabled and obj.stats.lvl >= 4 - batch.set 'flags.petsEnabled', true - obj.flags.petsEnabled = true - - if newStats.gp? - #FIXME what was I doing here? I can't remember, gp isn't defined - gp = 0.0 if (!gp? or gp<0) - obj.stats.gp = newStats.gp - -# {taskId} task you want to score -# {direction} 'up' or 'down' -# {times} # times to call score on this task (1 unless cron, usually) -# {update} if we're running updates en-mass (eg, cron on server) pass in userObj -score = (taskId, direction, times, batch, cron) -> - - commit = false - unless batch? - commit = true - batch = new character.BatchUpdate(model) - batch.startTransaction() - obj = batch.obj() - - {gp, hp, exp, lvl} = obj.stats - - taskPath = "tasks.#{taskId}" - taskObj = obj.tasks[taskId] - {type, value} = taskObj - - # If they're trying to purhcase a too-expensive reward, confirm they want to take a hit for it - if taskObj.value > obj.stats.gp and taskObj.type is 'reward' - r = confirm "Not enough GP to purchase this reward, buy anyway and lose HP? (Punishment for taking a reward you didn't earn)." - unless r - batch.commit() - return - - delta = 0 - times ?= 1 - calculateDelta = (adjustvalue=true) -> - # If multiple days have passed, multiply times days missed - _.times times, (n) -> - # Each iteration calculate the delta (nextDelta), which is then accumulated in delta - # (aka, the total delta). This weirdness won't be necessary when calculating mathematically - # rather than iteratively - nextDelta = taskDeltaFormula(value, direction) - value += nextDelta if adjustvalue - delta += nextDelta - - addPoints = -> - modified = expModifier(delta) - exp += modified - gp += modified - - subtractPoints = -> - modified = hpModifier(delta) - hp += modified - - switch type - when 'habit' - # Don't adjust values for habits that don't have both + and - - adjustvalue = if (taskObj.up==false or taskObj.down==false) then false else true - calculateDelta(adjustvalue) - # Add habit value to habit-history (if different) - if (delta > 0) then addPoints() else subtractPoints() - taskObj.history ?= [] - if taskObj.value != value - historyEntry = { date: +new Date, value: value } - taskObj.history.push historyEntry - batch.set "#{taskPath}.history", taskObj.history - - when 'daily' - calculateDelta() - if cron? # cron - subtractPoints() - else - addPoints() # obviously for delta>0, but also a trick to undo accidental checkboxes - - when 'todo' - calculateDelta() - unless cron? # don't touch stats on cron - addPoints() # obviously for delta>0, but also a trick to undo accidental checkboxes - - when 'reward' - # Don't adjust values for rewards - calculateDelta(false) - # purchase item - gp -= Math.abs(taskObj.value) - num = parseFloat(taskObj.value).toFixed(2) - # if too expensive, reduce health & zero gp - if gp < 0 - hp += gp # hp - gp difference - gp = 0 - - taskObj.value = value - batch.set "#{taskPath}.value", taskObj.value - origStats = _.clone obj.stats - updateStats {hp: hp, exp: exp, gp: gp}, batch - if commit - # newStats / origStats is a glorious hack to trick Derby into seeing the change in model.on(*) - newStats = _.clone batch.obj().stats - _.each Object.keys(origStats), (key) -> obj.stats[key] = origStats[key] - batch.setStats(newStats) -# batch.setStats() - batch.commit() - return delta - -### - At end of day, add value to all incomplete Daily & Todo tasks (further incentive) - For incomplete Dailys, deduct experience -### -cron = () -> - today = +new Date - daysPassed = helpers.daysBetween(today, user.get('lastCron')) - if daysPassed > 0 - batch = new character.BatchUpdate(model) - batch.startTransaction() - batch.set 'lastCron', today + ### + Updates user stats with new stats. Handles death, leveling up, etc + {stats} new stats + {update} if aggregated changes, pass in userObj as update. otherwise commits will be made immediately + ### + updateStats = (newStats, batch) -> obj = batch.obj() - hpBefore = obj.stats.hp #we'll use this later so we can animate hp loss - # Tally each task - todoTally = 0 - _.each obj.tasks, (taskObj) -> - {id, type, completed, repeat} = taskObj - if type in ['todo', 'daily'] - # Deduct experience for missed Daily tasks, - # but not for Todos (just increase todo's value) - unless completed - # for todos & typical dailies, these are equivalent - daysFailed = daysPassed - # however, for dailys which have repeat dates, need - # to calculate how many they've missed according to their own schedule - if type=='daily' && repeat - daysFailed = 0 - _.times daysPassed, (n) -> - thatDay = moment().subtract('days', n+1) - if repeat[helpers.dayMapping[thatDay.day()]]==true - daysFailed++ - score id, 'down', daysFailed, batch, true - if type == 'daily' - taskObj.history ?= [] - taskObj.history.push { date: +new Date, value: value } - batch.set "tasks.#{taskObj.id}.history", taskObj.history - batch.set "tasks.#{taskObj.id}.completed", false + # if user is dead, dont do anything + return if obj.stats.lvl == 0 + + if newStats.hp? + # Game Over + if newStats.hp <= 0 + obj.stats.lvl = 0 # signifies dead + obj.stats.hp = 0 + return + else + obj.stats.hp = newStats.hp + + if newStats.exp? + # level up & carry-over exp + tnl = model.get '_tnl' + if newStats.exp >= tnl + newStats.exp -= tnl + obj.stats.lvl++ + obj.stats.hp = 50 + + obj.stats.exp = newStats.exp + + # Set flags when they unlock features + if !obj.flags.customizationsNotification and (obj.stats.exp > 10 or obj.stats.lvl > 1) + batch.set 'flags.customizationsNotification', true + obj.flags.customizationsNotification = true + if !obj.flags.itemsEnabled and obj.stats.lvl >= 2 + # Set to object, then also send to browser right away to get model.on() subscription notification + batch.set 'flags.itemsEnabled', true + obj.flags.itemsEnabled = true + if !obj.flags.partyEnabled and obj.stats.lvl >= 3 + batch.set 'flags.partyEnabled', true + obj.flags.partyEnabled = true + if !obj.flags.petsEnabled and obj.stats.lvl >= 4 + batch.set 'flags.petsEnabled', true + obj.flags.petsEnabled = true + + if newStats.gp? + #FIXME what was I doing here? I can't remember, gp isn't defined + gp = 0.0 if (!gp? or gp<0) + obj.stats.gp = newStats.gp + + # {taskId} task you want to score + # {direction} 'up' or 'down' + # {times} # times to call score on this task (1 unless cron, usually) + # {update} if we're running updates en-mass (eg, cron on server) pass in userObj + score = (taskId, direction, times, batch, cron) -> + + commit = false + unless batch? + commit = true + batch = new character.BatchUpdate(model) + batch.startTransaction() + obj = batch.obj() + + {gp, hp, exp, lvl} = obj.stats + + taskPath = "tasks.#{taskId}" + taskObj = obj.tasks[taskId] + {type, value} = taskObj + + # If they're trying to purhcase a too-expensive reward, confirm they want to take a hit for it + if taskObj.value > obj.stats.gp and taskObj.type is 'reward' + r = confirm "Not enough GP to purchase this reward, buy anyway and lose HP? (Punishment for taking a reward you didn't earn)." + unless r + batch.commit() + return + + delta = 0 + times ?= 1 + calculateDelta = (adjustvalue=true) -> + # If multiple days have passed, multiply times days missed + _.times times, (n) -> + # Each iteration calculate the delta (nextDelta), which is then accumulated in delta + # (aka, the total delta). This weirdness won't be necessary when calculating mathematically + # rather than iteratively + nextDelta = taskDeltaFormula(value, direction) + value += nextDelta if adjustvalue + delta += nextDelta + + addPoints = -> + modified = expModifier(delta) + exp += modified + gp += modified + + subtractPoints = -> + modified = hpModifier(delta) + hp += modified + + switch type + when 'habit' + # Don't adjust values for habits that don't have both + and - + adjustvalue = if (taskObj.up==false or taskObj.down==false) then false else true + calculateDelta(adjustvalue) + # Add habit value to habit-history (if different) + if (delta > 0) then addPoints() else subtractPoints() + taskObj.history ?= [] + if taskObj.value != value + historyEntry = { date: +new Date, value: value } + taskObj.history.push historyEntry + batch.set "#{taskPath}.history", taskObj.history + + when 'daily' + calculateDelta() + if cron? # cron + subtractPoints() else - value = obj.tasks[taskObj.id].value #get updated value - absVal = if (completed) then Math.abs(value) else value - todoTally += absVal + addPoints() # obviously for delta>0, but also a trick to undo accidental checkboxes - # Finished tallying - obj.history ?= {}; obj.history.todos ?= []; obj.history.exp ?= [] - obj.history.todos.push { date: today, value: todoTally } - # tally experience - expTally = obj.stats.exp - lvl = 0 #iterator - while lvl < (obj.stats.lvl-1) - lvl++ - expTally += (lvl*100)/5 - obj.history.exp.push { date: today, value: expTally } + when 'todo' + calculateDelta() + unless cron? # don't touch stats on cron + addPoints() # obviously for delta>0, but also a trick to undo accidental checkboxes - # Set the new user specs, and animate HP loss - [hpAfter, obj.stats.hp] = [obj.stats.hp, hpBefore] - batch.setStats() - batch.set('history', obj.history) - batch.commit() - browser.resetDom(model) - setTimeout (-> user.set 'stats.hp', hpAfter), 1000 # animate hp loss + when 'reward' + # Don't adjust values for rewards + calculateDelta(false) + # purchase item + gp -= Math.abs(taskObj.value) + num = parseFloat(taskObj.value).toFixed(2) + # if too expensive, reduce health & zero gp + if gp < 0 + hp += gp # hp - gp difference + gp = 0 + + taskObj.value = value + batch.set "#{taskPath}.value", taskObj.value + origStats = _.clone obj.stats + updateStats {hp: hp, exp: exp, gp: gp}, batch + if commit + # newStats / origStats is a glorious hack to trick Derby into seeing the change in model.on(*) + newStats = _.clone batch.obj().stats + _.each Object.keys(origStats), (key) -> obj.stats[key] = origStats[key] + batch.setStats(newStats) + # batch.setStats() + batch.commit() + return delta + + ### + At end of day, add value to all incomplete Daily & Todo tasks (further incentive) + For incomplete Dailys, deduct experience + ### + cron = () -> + today = +new Date + daysPassed = helpers.daysBetween(today, user.get('lastCron')) + if daysPassed > 0 + batch = new character.BatchUpdate(model) + batch.startTransaction() + batch.set 'lastCron', today + obj = batch.obj() + hpBefore = obj.stats.hp #we'll use this later so we can animate hp loss + # Tally each task + todoTally = 0 + _.each obj.tasks, (taskObj) -> + {id, type, completed, repeat} = taskObj + if type in ['todo', 'daily'] + # Deduct experience for missed Daily tasks, + # but not for Todos (just increase todo's value) + unless completed + # for todos & typical dailies, these are equivalent + daysFailed = daysPassed + # however, for dailys which have repeat dates, need + # to calculate how many they've missed according to their own schedule + if type=='daily' && repeat + daysFailed = 0 + _.times daysPassed, (n) -> + thatDay = moment().subtract('days', n+1) + if repeat[helpers.dayMapping[thatDay.day()]]==true + daysFailed++ + score id, 'down', daysFailed, batch, true + + if type == 'daily' + taskObj.history ?= [] + taskObj.history.push { date: +new Date, value: value } + batch.set "tasks.#{taskObj.id}.history", taskObj.history + batch.set "tasks.#{taskObj.id}.completed", false + else + value = obj.tasks[taskObj.id].value #get updated value + absVal = if (completed) then Math.abs(value) else value + todoTally += absVal + + # Finished tallying + obj.history ?= {}; obj.history.todos ?= []; obj.history.exp ?= [] + obj.history.todos.push { date: today, value: todoTally } + # tally experience + expTally = obj.stats.exp + lvl = 0 #iterator + while lvl < (obj.stats.lvl-1) + lvl++ + expTally += (lvl*100)/5 + obj.history.exp.push { date: today, value: expTally } + + # Set the new user specs, and animate HP loss + [hpAfter, obj.stats.hp] = [obj.stats.hp, hpBefore] + batch.setStats() + batch.set('history', obj.history) + batch.commit() + browser.resetDom(model) + setTimeout (-> user.set 'stats.hp', hpAfter), 1000 # animate hp loss -module.exports = { - setModel: setModel - MODIFIER: MODIFIER - score: score - cron: cron + return { + MODIFIER: MODIFIER + score: score + cron: cron - # testing stuff - expModifier: expModifier - hpModifier: hpModifier - taskDeltaFormula: taskDeltaFormula -} + # testing stuff + expModifier: expModifier + hpModifier: hpModifier + taskDeltaFormula: taskDeltaFormula + } diff --git a/src/app/tasks.coffee b/src/app/tasks.coffee index 8f14840e9f..22995d868c 100644 --- a/src/app/tasks.coffee +++ b/src/app/tasks.coffee @@ -26,6 +26,7 @@ module.exports.view = (view) -> module.exports.app = (appExports, model) -> user = model.at('_user') + score = new scoring.Scoring(model) user.on 'set', 'tasks.*.completed', (i, completed, previous, isLocal, passed) -> return if passed? && passed.cron # Don't do this stuff on cron @@ -36,7 +37,7 @@ module.exports.app = (appExports, model) -> # Score the user based on todo task task = user.at("tasks.#{i}") - scoring.score(i, direction()) + score.score(i, direction()) appExports.addTask = (e, el, next) -> type = $(el).attr('data-task-type') @@ -81,7 +82,7 @@ module.exports.app = (appExports, model) -> return # Cancel. Don't delete, don't hurt user else task.set('type','habit') # hack to make sure it hits HP, instead of performing "undo checkbox" - scoring.score(id, direction:'down') + score.score(id, direction:'down') # prevent accidently deleting long-standing tasks else @@ -171,4 +172,4 @@ module.exports.app = (appExports, model) -> direction = 'up' if direction == 'true/' direction = 'down' if direction == 'false/' task = model.at $(el).parents('li')[0] - scoring.score(task.get('id'), direction) + score.score(task.get('id'), direction) diff --git a/src/server/api.coffee b/src/server/api.coffee index fba15fc09f..c20e0d9582 100644 --- a/src/server/api.coffee +++ b/src/server/api.coffee @@ -30,7 +30,6 @@ auth = (req, res, next) -> query.fetch (err, user) -> return res.json err: err if err - user = user.at(0) req.user = user req.userObj = user.get() return res.json 401, NO_USER_FOUND if !req.userObj || _.isEmpty(req.userObj) @@ -109,7 +108,7 @@ router.get '/users/:uid/calendar.ics', (req, res) -> query = model.query('users').withIdAndToken(uid, apiToken) query.fetch (err, result) -> return res.send(400, err) if err - tasks = result.at(0).get('tasks') + tasks = result.get('tasks') # tasks = result[0].tasks tasksWithDates = _.filter tasks, (task) -> !!task.date return res.send(400, "No events found") if _.isEmpty(tasksWithDates) diff --git a/src/server/private.coffee b/src/server/private.coffee index f882bac83b..3f7bc8e5cc 100644 --- a/src/server/private.coffee +++ b/src/server/private.coffee @@ -12,13 +12,13 @@ module.exports.app = (appExports, model) -> token = (res) -> console.log(res); $.ajax({ - type:"POST", - url:"/charge", - data:res - }).success -> - window.location.href = "/" - .error (err) -> - alert err.responseText + type: "POST", + url: "/charge", + data: res + }).success -> + window.location.href = "/" + .error (err) -> + alert err.responseText StripeCheckout.open key: model.get('_stripePubKey') diff --git a/src/server/store.coffee b/src/server/store.coffee index 4d71f36262..659d890685 100644 --- a/src/server/store.coffee +++ b/src/server/store.coffee @@ -74,7 +74,7 @@ REST = (store) -> store.query.expose "users", "withIdAndToken", (uid, token) -> @byId(uid) .where('apiToken').equals(token) - .one + .findOne() store.queryAccess "users", "withIdAndToken", (uid, token, accept, err) -> return accept(true) if uid && token @@ -101,6 +101,7 @@ partySystem = (store) -> store.query.expose "parties", "withId", (id) -> @where("id").equals(id) + .findOne() store.queryAccess "parties", "withId", (id, accept, err) -> # return err(derbyAuth.SESSION_INVALIDATED_ERROR) if derbyAuth.bustedSession(@) return accept(false) if derbyAuth.bustedSession(@) diff --git a/test/api.mocha.coffee b/test/api.mocha.coffee index 1195eb1f2e..2b1931fcce 100644 --- a/test/api.mocha.coffee +++ b/test/api.mocha.coffee @@ -119,7 +119,7 @@ describe 'API', -> expect(res.statusCode).to.be 201 expect(res.body.id).not.to.be.empty() # Ensure that user owns the newly created object - expect(user.at(0).get().tasks[res.body.id]).to.be.an('object') + expect(user.get().tasks[res.body.id]).to.be.an('object') done() it 'PUT /api/v1/task/:id', (done) -> @@ -128,11 +128,12 @@ describe 'API', -> .set('Accept', 'application/json') .set('X-API-User', currentUser.id) .set('X-API-Key', currentUser.apiToken) - .send(title: 'a new title') + .send(title: 'a new title',text: 'hi') .end (res) -> expect(res.body.err).to.be undefined expect(res.statusCode).to.be 200 currentUser.tasks[tid].title = 'a new title' + currentUser.tasks[tid].text = 'hi' expect(res.body).to.eql currentUser.tasks[tid] done() @@ -146,8 +147,7 @@ describe 'API', -> query.fetch (err, user) -> expect(res.body.err).to.be undefined expect(res.statusCode).to.be 200 - currentUser = user.at(0).get() - model.ref '_user', user.at(0) + model.ref '_user', user tasks = [] for type in ['habit','todo','daily','reward'] model.refList "_#{type}List", "_user.tasks", "_user.#{type}Ids" @@ -169,8 +169,7 @@ describe 'API', -> query.fetch (err, user) -> expect(res.body.err).to.be undefined expect(res.statusCode).to.be 200 - currentUser = user.at(0).get() - model.ref '_user', user.at(0) + model.ref '_user', user model.refList "_todoList", "_user.tasks", "_user.todoIds" tasks = model.get("_todoList") # Ensure that user owns the tasks