Merge and fix tests

This commit is contained in:
Daniel Saewitz 2013-02-26 19:17:11 -05:00
commit 822f779812
8 changed files with 308 additions and 327 deletions

View file

@ -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)

View file

@ -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

View file

@ -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
}

View file

@ -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)

View file

@ -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)

View file

@ -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')

View file

@ -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(@)

View file

@ -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