Merge pull request #5756 from Alys/cron-missed-days-ignore-multiple-2015-07-21

make cron count multiple missed days as one missed day (part 2)
This commit is contained in:
Alys
2015-08-12 08:35:37 +10:00
3 changed files with 124 additions and 20 deletions
+10 -4
View File
@@ -1722,12 +1722,16 @@ api.wrap = (user, main=true) ->
daily.completed = false
return
multiDaysCountAsOneDay = true
# If the user does not log in for two or more days, cron (mostly) acts as if it were only one day.
# When site-wide difficulty settings are introduced, this can be a user preference option.
# Tally each task
todoTally = 0
user.todos.forEach (task) -> # make uncompleted todos redder
return unless task
{id, completed} = task
delta = user.ops.score({params:{id:task.id, direction:'down'}, query:{times:(daysMissed), cron:true}})
delta = user.ops.score({params:{id:task.id, direction:'down'}, query:{times:(multiDaysCountAsOneDay ? 1 : daysMissed), cron:true}})
absVal = if (completed) then Math.abs(task.value) else task.value
todoTally += absVal
@@ -1738,7 +1742,7 @@ api.wrap = (user, main=true) ->
return unless task
{id, completed} = task
# Deduct points for missed Daily tasks, but not for Todos (just increase todo's value)
# Deduct points for missed Daily tasks
EvadeTask = 0
scheduleMisses = daysMissed
if completed
@@ -1746,13 +1750,15 @@ api.wrap = (user, main=true) ->
else
# dailys repeat, so need to calculate how many they've missed according to their own schedule
scheduleMisses = 0
_.times daysMissed, (n) ->
for n in [0...daysMissed]
thatDay = moment(now).subtract({days: n + 1})
if api.shouldDo(thatDay.toDate(), task, user.preferences)
scheduleMisses++
if user.stats.buffs.stealth
user.stats.buffs.stealth--
EvadeTask++
if multiDaysCountAsOneDay
break
if scheduleMisses > EvadeTask
perfect = false
@@ -1762,7 +1768,7 @@ api.wrap = (user, main=true) ->
dailyChecked += fractionChecked
else
dailyDueUnchecked += 1
delta = user.ops.score({params:{id:task.id, direction:'down'}, query:{times:(scheduleMisses-EvadeTask), cron:true}})
delta = user.ops.score({params:{id:task.id, direction:'down'}, query:{times:(multiDaysCountAsOneDay ? 1 : (scheduleMisses-EvadeTask)), cron:true}})
# Apply damage from a boss, less damage for Trivial priority (difficulty)
user.party.quest.progress.down += delta * (if task.priority < 1 then task.priority else 1)
+12 -2
View File
@@ -644,7 +644,7 @@ describe 'Cron', ->
# paths = {};algos.cron user, {paths}
# expect(paths.lastCron).to.be true # busted cron (was set to after today's date)
it 'only dailies & todos are effected', ->
it 'only dailies & todos are affected', ->
{before,after} = beforeAfter({daysAgo:1})
before.dailys = before.todos = after.dailys = after.todos = []
after.fns.cron()
@@ -732,9 +732,19 @@ describe 'Cron', ->
expect(after).toHaveGP 0
# but they devalue
expect(after.todos[0].value).to.be.lessThan before.todos[0].value
expect(before.todos[0].value).to.be 0 # sanity check for task setup
expect(after.todos[0].value).to.be -1 # the actual test
expect(after.history.todos).to.have.length 1
it '2 days missed', ->
{before,after} = beforeAfter({daysAgo:2})
before.dailys = after.dailys = []
after.fns.cron()
# todos devalue by only one day's worth of devaluation
expect(before.todos[0].value).to.be 0 # sanity check for task setup
expect(after.todos[0].value).to.be -1 # the actual test
# I used hard-coded dates here instead of 'now' so the tests don't fail
# when you run them between midnight and dayStart. Nothing worse than
# intermittent failures.
+102 -14
View File
@@ -49,8 +49,8 @@ newUser = (addTasks=true)->
user.ops.addTask {body: {type: task, id: shared.uuid()}}
user
cron = (usr) ->
usr.lastCron = moment().subtract(1,'days')
cron = (usr, missedDays=1) ->
usr.lastCron = moment().subtract(missedDays,'days')
usr.fns.cron()
describe 'daily/weekly that repeats everyday (default)', ->
@@ -59,7 +59,6 @@ describe 'daily/weekly that repeats everyday (default)', ->
weekly = null
describe 'when startDate is in the future', ->
beforeEach ->
user = newUser()
user.dailys = [
@@ -141,19 +140,17 @@ describe 'daily/weekly that repeats everyday (default)', ->
it 'is due on startDate', ->
daily_due_today = shared.shouldDo moment(), daily
daily_due_on_start_date = shared.shouldDo moment().add(7, 'days'), daily
expect(daily_due_today).to.be false
expect(daily_due_on_start_date).to.be true
weekly_due_today = shared.shouldDo moment(), weekly
weekly_due_on_start_date = shared.shouldDo moment().add(7, 'days'), weekly
expect(weekly_due_today).to.be false
expect(weekly_due_on_start_date).to.be true
describe 'when startDate is in the past', ->
completeDaily = null
beforeEach ->
user = newUser()
user.dailys = [
@@ -168,9 +165,14 @@ describe 'daily/weekly that repeats everyday (default)', ->
expect(user.stats.hp).to.be.lessThan 50
it 'decreases value on cron if daily is incomplete', ->
cron(user)
expect(daily.value).to.be.lessThan 0
expect(weekly.value).to.be.lessThan 0
cron(user, 1)
expect(daily.value).to.be -1
expect(weekly.value).to.be -1
it 'decreases value on cron once only if daily is incomplete and multiple days are missed', ->
cron(user, 7)
expect(daily.value).to.be -1
expect(weekly.value).to.be -1
it 'resets checklists if daily is not marked as complete', ->
checklist = [
@@ -196,7 +198,7 @@ describe 'daily/weekly that repeats everyday (default)', ->
_.each daily.checklist, (box)->
expect(box.completed).to.be false
_.each weekly.checklist, (box)->
expect(box.completed).to.be false
@@ -231,8 +233,6 @@ describe 'daily/weekly that repeats everyday (default)', ->
expect(box.completed).to.be false
describe 'when startDate is today', ->
completeDaily = null
beforeEach ->
user = newUser()
user.dailys = [
@@ -276,7 +276,7 @@ describe 'daily/weekly that repeats everyday (default)', ->
_.each daily.checklist, (box)->
expect(box.completed).to.be false
_.each weekly.checklist, (box)->
expect(box.completed).to.be false
@@ -328,3 +328,91 @@ describe 'daily that repeats every x days', ->
isDue = shared.shouldDo moment().add(day, 'days'), daily
expect(isDue).to.be true if day % due == 0
expect(isDue).to.be false if day % due != 0
describe 'daily that repeats every X days when multiple days are missed', ->
everyX = 3
startDateDaysAgo = everyX * 3
user = null
daily = null
describe 'including missing a due date', ->
missedDays = everyX * 2 + 1
beforeEach ->
user = newUser()
user.dailys = [
shared.taskDefaults({type:'daily', startDate: moment().subtract(startDateDaysAgo, 'days'), frequency: 'daily', everyX: everyX})
]
daily = user.dailys[0]
it 'decreases value on cron once only if daily is incomplete', ->
cron(user, missedDays)
expect(daily.value).to.be -1
it 'resets checklists if daily is incomplete', ->
checklist = [
{
'text' : '1',
'id' : 'checklist-one',
'completed' : true
}
]
daily.checklist = checklist
cron(user, missedDays)
_.each daily.checklist, (box)->
expect(box.completed).to.be false
it 'resets checklists if daily is marked as complete', ->
checklist = [
{
'text' : '1',
'id' : 'checklist-one',
'completed' : true
}
]
daily.checklist = checklist
daily.completed = true
cron(user, missedDays)
_.each daily.checklist, (box)->
expect(box.completed).to.be false
describe 'but not missing a due date', ->
missedDays = everyX - 1
beforeEach ->
user = newUser()
user.dailys = [
shared.taskDefaults({type:'daily', startDate: moment().subtract(startDateDaysAgo, 'days'), frequency: 'daily', everyX: everyX})
]
daily = user.dailys[0]
it 'does not decrease value on cron', ->
cron(user, missedDays)
expect(daily.value).to.be 0
it 'does not reset checklists if daily is incomplete', ->
checklist = [
{
'text' : '1',
'id' : 'checklist-one',
'completed' : true
}
]
daily.checklist = checklist
cron(user, missedDays)
_.each daily.checklist, (box)->
expect(box.completed).to.be true
it 'resets checklists if daily is marked as complete', ->
checklist = [
{
'text' : '1',
'id' : 'checklist-one',
'completed' : true
}
]
daily.checklist = checklist
daily.completed = true
cron(user, missedDays)
_.each daily.checklist, (box)->
expect(box.completed).to.be false