fix lapse card scheduling

- make sure we set a timestamp due time, and put the card back in the queue
- add a unit test for it
This commit is contained in:
Damien Elmes 2011-03-24 08:04:04 +09:00
parent 765720b928
commit 31427f0133
3 changed files with 34 additions and 7 deletions

View file

@ -5,10 +5,6 @@
import simplejson import simplejson
from anki.utils import intTime from anki.utils import intTime
# maybe define a random cutoff at say +/-30% which controls exit interval
# variation - 30% of 1 day is 0.7 or 1.3 so always 1 day; 30% of 4 days is
# 2.8-5.2, so any time from 3-5 days is acceptable
defaultConf = { defaultConf = {
'new': { 'new': {
'delays': [0.5, 3, 10], 'delays': [0.5, 3, 10],

View file

@ -354,11 +354,14 @@ queue = 2 %s and due <= :lim order by %s limit %d""" % (
card.lastIvl = card.ivl card.lastIvl = card.ivl
card.ivl = self._nextLapseIvl(card, conf) card.ivl = self._nextLapseIvl(card, conf)
card.factor = max(1300, card.factor-200) card.factor = max(1300, card.factor-200)
card.due = card.edue = self.today + card.ivl card.due = self.today + card.ivl
# put back in the learn queue? # put back in the learn queue?
if conf['relearn']: if conf['relearn']:
card.edue = card.due
card.due = int(self._delayForGrade(conf, 0) + time.time())
card.queue = 1 card.queue = 1
self.lrnCount += 1 self.lrnCount += 1
heappush(self.lrnQueue, (card.due, card.id))
# leech? # leech?
self._checkLeech(card, conf) self._checkLeech(card, conf)

View file

@ -158,8 +158,11 @@ def test_reviews():
d.sched.answerCard(c, 1) d.sched.answerCard(c, 1)
assert c.queue == 1 assert c.queue == 1
# it should be due tomorrow, with an interval of 1 # it should be due tomorrow, with an interval of 1
assert c.due == d.sched.today + 1 assert c.edue == d.sched.today + 1
assert c.ivl == 1 assert c.ivl == 1
# but because it's in the learn queue, its current due time should be in
# the future
assert c.due >= time.time()
# factor should have been decremented # factor should have been decremented
assert c.factor == 2300 assert c.factor == 2300
# check counters # check counters
@ -364,7 +367,6 @@ def test_cram():
d.sched.answerCard(c, 1) d.sched.answerCard(c, 1)
# graduating the card will keep the same interval, but shift the card # graduating the card will keep the same interval, but shift the card
# forward the number of days it had been waiting (75) # forward the number of days it had been waiting (75)
print d.sched.nextIvl(c, 3)
assert d.sched.nextIvl(c, 3) == 75*86400 assert d.sched.nextIvl(c, 3) == 75*86400
d.sched.answerCard(c, 3) d.sched.answerCard(c, 3)
assert c.ivl == 100 assert c.ivl == 100
@ -541,3 +543,29 @@ def test_counts():
assert d.sched.allCounts() == (2,2,2) assert d.sched.allCounts() == (2,2,2)
assert d.sched.selCounts() == (1,2,1) assert d.sched.selCounts() == (1,2,1)
assert d.sched.allCounts() == (2,2,2) assert d.sched.allCounts() == (2,2,2)
def test_timing():
d = getEmptyDeck()
# add a few review cards, due today
for i in range(5):
f = d.newFact()
f['Front'] = "num"+str(i)
d.addFact(f)
c = f.cards()[0]
c.type = 2
c.queue = 2
c.due = 0
c.flush()
# fail the first one
d.reset()
c = d.sched.getCard()
# set a a fail delay of 1 second so we don't have to wait
d.sched._cardConf(c)['lapse']['delays'][0] = 1/60.0
d.sched.answerCard(c, 1)
# the next card should be another review
c = d.sched.getCard()
assert c.queue == 2
# but if we wait for a second, the failed card should come back
time.sleep(1)
c = d.sched.getCard()
assert c.queue == 1