From c3d65f0bcf05bd5a546d1164d71dedd3e3f8e0b3 Mon Sep 17 00:00:00 2001 From: Alys Date: Tue, 28 Jul 2015 14:39:47 +1000 Subject: [PATCH 1/7] initial changes to cause cron to count multiple missed days as one missed day --- common/script/index.coffee | 28 ++++++++++++++++++++-------- test/common/dailies.coffee | 4 ++-- website/views/shared/footer.jade | 9 +++++++++ 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/common/script/index.coffee b/common/script/index.coffee index 8d71e8e3d6..a146923abf 100644 --- a/common/script/index.coffee +++ b/common/script/index.coffee @@ -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 @@ -1745,14 +1749,22 @@ api.wrap = (user, main=true) -> dailyChecked += 1 else # dailys repeat, so need to calculate how many they've missed according to their own schedule + console.log("task: " + task.text) # XXX Alys to remove these scheduleMisses = 0 + keepGoing = true # XXX Alys to improve how we break out of _.times _.times daysMissed, (n) -> - 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 keepGoing + console.log("n: " + n) + thatDay = moment(now).subtract({days: n + 1}) + if api.shouldDo(thatDay.toDate(), task, user.preferences) + console.log("damage") + scheduleMisses++ + if user.stats.buffs.stealth + user.stats.buffs.stealth-- + EvadeTask++ + if multiDaysCountAsOneDay + console.log("end") + keepGoing = false if scheduleMisses > EvadeTask perfect = false @@ -1762,7 +1774,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) diff --git a/test/common/dailies.coffee b/test/common/dailies.coffee index fc88adfbf3..9a9498d24e 100644 --- a/test/common/dailies.coffee +++ b/test/common/dailies.coffee @@ -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)', -> diff --git a/website/views/shared/footer.jade b/website/views/shared/footer.jade index 2e81898d9c..256a33894b 100644 --- a/website/views/shared/footer.jade +++ b/website/views/shared/footer.jade @@ -79,6 +79,15 @@ footer.footer(ng-controller='FooterCtrl') a.btn.btn-default(ng-click='setHealthLow()') Health = 1 a.btn.btn-default(ng-click='addMissedDay(1)') +1 Missed Day a.btn.btn-default(ng-click='addMissedDay(2)') +2 Missed Days + // XXX Alys to remove these excess ones when testing is done: + a.btn.btn-default(ng-click='addMissedDay(3)') +3 Missed Days + a.btn.btn-default(ng-click='addMissedDay(4)') +4 Missed Days + a.btn.btn-default(ng-click='addMissedDay(5)') +5 Missed Days + a.btn.btn-default(ng-click='addMissedDay(6)') +6 Missed Days + a.btn.btn-default(ng-click='addMissedDay(7)') +7 Missed Days + a.btn.btn-default(ng-click='addMissedDay(8)') +8 Missed Days + a.btn.btn-default(ng-click='addMissedDay(9)') +9 Missed Days + a.btn.btn-default(ng-click='addMissedDay(10)') +10 Missed Day a.btn.btn-default(ng-click='addTenGems()') +10 Gems a.btn.btn-default(ng-click='addGold()') +GP a.btn.btn-default(ng-click='addMana()') +MP From 06fd9c7a67df5562c3015dcc0b9adc862ec88679 Mon Sep 17 00:00:00 2001 From: Alys Date: Tue, 4 Aug 2015 04:30:42 +1000 Subject: [PATCH 2/7] replace _.times with for loop to allow break --- common/script/index.coffee | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/common/script/index.coffee b/common/script/index.coffee index a146923abf..aeab2f76e8 100644 --- a/common/script/index.coffee +++ b/common/script/index.coffee @@ -1749,22 +1749,20 @@ api.wrap = (user, main=true) -> dailyChecked += 1 else # dailys repeat, so need to calculate how many they've missed according to their own schedule - console.log("task: " + task.text) # XXX Alys to remove these + console.log("---- task: " + task.text) # XXX Alys to remove these scheduleMisses = 0 - keepGoing = true # XXX Alys to improve how we break out of _.times - _.times daysMissed, (n) -> - if keepGoing - console.log("n: " + n) - thatDay = moment(now).subtract({days: n + 1}) - if api.shouldDo(thatDay.toDate(), task, user.preferences) - console.log("damage") - scheduleMisses++ - if user.stats.buffs.stealth - user.stats.buffs.stealth-- - EvadeTask++ - if multiDaysCountAsOneDay - console.log("end") - keepGoing = false + for n in [0...daysMissed] + console.log("n: " + n) + thatDay = moment(now).subtract({days: n + 1}) + if api.shouldDo(thatDay.toDate(), task, user.preferences) + console.log("damage") + scheduleMisses++ + if user.stats.buffs.stealth + user.stats.buffs.stealth-- + EvadeTask++ + if multiDaysCountAsOneDay + console.log("end") + break if scheduleMisses > EvadeTask perfect = false From 696027025be835c03214d1959bc0b4739488bdda Mon Sep 17 00:00:00 2001 From: Alys Date: Sun, 9 Aug 2015 12:41:06 +1000 Subject: [PATCH 3/7] add tests for Dailies under new cron behaviour where multiple missed days are treated as one --- test/common/dailies.coffee | 112 +++++++++++++++++++++++++++++++++---- 1 file changed, 102 insertions(+), 10 deletions(-) diff --git a/test/common/dailies.coffee b/test/common/dailies.coffee index 9a9498d24e..3802ad1609 100644 --- a/test/common/dailies.coffee +++ b/test/common/dailies.coffee @@ -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,19 @@ 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 +167,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 +200,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 @@ -232,7 +236,7 @@ describe 'daily/weekly that repeats everyday (default)', -> describe 'when startDate is today', -> completeDaily = null - + beforeEach -> user = newUser() user.dailys = [ @@ -276,7 +280,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 +332,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 From 262340147d83d27052596d7aa91ba9e46bb6ee06 Mon Sep 17 00:00:00 2001 From: Alys Date: Sun, 9 Aug 2015 14:08:28 +1000 Subject: [PATCH 4/7] remove code that was added purely for testing and development --- common/script/index.coffee | 4 ---- website/views/shared/footer.jade | 9 --------- 2 files changed, 13 deletions(-) diff --git a/common/script/index.coffee b/common/script/index.coffee index aeab2f76e8..daee2a07dc 100644 --- a/common/script/index.coffee +++ b/common/script/index.coffee @@ -1749,19 +1749,15 @@ api.wrap = (user, main=true) -> dailyChecked += 1 else # dailys repeat, so need to calculate how many they've missed according to their own schedule - console.log("---- task: " + task.text) # XXX Alys to remove these scheduleMisses = 0 for n in [0...daysMissed] - console.log("n: " + n) thatDay = moment(now).subtract({days: n + 1}) if api.shouldDo(thatDay.toDate(), task, user.preferences) - console.log("damage") scheduleMisses++ if user.stats.buffs.stealth user.stats.buffs.stealth-- EvadeTask++ if multiDaysCountAsOneDay - console.log("end") break if scheduleMisses > EvadeTask diff --git a/website/views/shared/footer.jade b/website/views/shared/footer.jade index 256a33894b..2e81898d9c 100644 --- a/website/views/shared/footer.jade +++ b/website/views/shared/footer.jade @@ -79,15 +79,6 @@ footer.footer(ng-controller='FooterCtrl') a.btn.btn-default(ng-click='setHealthLow()') Health = 1 a.btn.btn-default(ng-click='addMissedDay(1)') +1 Missed Day a.btn.btn-default(ng-click='addMissedDay(2)') +2 Missed Days - // XXX Alys to remove these excess ones when testing is done: - a.btn.btn-default(ng-click='addMissedDay(3)') +3 Missed Days - a.btn.btn-default(ng-click='addMissedDay(4)') +4 Missed Days - a.btn.btn-default(ng-click='addMissedDay(5)') +5 Missed Days - a.btn.btn-default(ng-click='addMissedDay(6)') +6 Missed Days - a.btn.btn-default(ng-click='addMissedDay(7)') +7 Missed Days - a.btn.btn-default(ng-click='addMissedDay(8)') +8 Missed Days - a.btn.btn-default(ng-click='addMissedDay(9)') +9 Missed Days - a.btn.btn-default(ng-click='addMissedDay(10)') +10 Missed Day a.btn.btn-default(ng-click='addTenGems()') +10 Gems a.btn.btn-default(ng-click='addGold()') +GP a.btn.btn-default(ng-click='addMana()') +MP From fd0176f4fcf384c21719b237a8ab0c2021025ea9 Mon Sep 17 00:00:00 2001 From: Alys Date: Sun, 9 Aug 2015 14:09:10 +1000 Subject: [PATCH 5/7] fix an outdated comment --- common/script/index.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/script/index.coffee b/common/script/index.coffee index daee2a07dc..27b44392f1 100644 --- a/common/script/index.coffee +++ b/common/script/index.coffee @@ -1742,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 From a53625aafbe45eaaa5ee93a318649a96f0070457 Mon Sep 17 00:00:00 2001 From: Alys Date: Sun, 9 Aug 2015 14:10:29 +1000 Subject: [PATCH 6/7] remove (probably) unused completeDaily code from dailies tests --- test/common/dailies.coffee | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/common/dailies.coffee b/test/common/dailies.coffee index 3802ad1609..d06c291f27 100644 --- a/test/common/dailies.coffee +++ b/test/common/dailies.coffee @@ -151,8 +151,6 @@ describe 'daily/weekly that repeats everyday (default)', -> expect(weekly_due_on_start_date).to.be true describe 'when startDate is in the past', -> - completeDaily = null - beforeEach -> user = newUser() user.dailys = [ @@ -235,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 = [ From 9db46bd9992c3bea3f3a9dc898e7d2c08abaf5b5 Mon Sep 17 00:00:00 2001 From: Alys Date: Sun, 9 Aug 2015 16:32:35 +1000 Subject: [PATCH 7/7] add test for cron reducing the value of a todo by only one day's worth when multiple days are missed --- test/common/algos.mocha.coffee | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/common/algos.mocha.coffee b/test/common/algos.mocha.coffee index 3173ba5e55..5be39a7ae3 100644 --- a/test/common/algos.mocha.coffee +++ b/test/common/algos.mocha.coffee @@ -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.