add rescheduling and interval reset to cram; don't include already due cards

This commit is contained in:
Damien Elmes 2011-03-19 12:38:18 +09:00
parent be045d451c
commit 9b70af678c
4 changed files with 61 additions and 12 deletions

View file

@ -34,6 +34,13 @@ class CramScheduler(Scheduler):
self._answerLrnCard(card, ease) self._answerLrnCard(card, ease)
else: else:
raise Exception("Invalid queue") raise Exception("Invalid queue")
if ease == 1:
conf = self._lrnConf(card)
if conf['reset']:
# reset interval
card.ivl = max(1, int(card.ivl * conf['mult']))
# mark card as due today so that it doesn't get rescheduled
card.due = card.edue = self.today
card.mod = intTime() card.mod = intTime()
card.flushSched() card.flushSched()
@ -47,9 +54,11 @@ class CramScheduler(Scheduler):
########################################################################## ##########################################################################
def _resetNew(self): def _resetNew(self):
"All review cards that are not due yet."
self.newQueue = self.db.list(""" self.newQueue = self.db.list("""
select id from cards where queue = 2 select id from cards where queue = 2 and due > %d
and gid in %s order by %s limit %d""" % (ids2str(self.gids), and gid in %s order by %s limit %d""" % (self.today,
ids2str(self.gids),
self.order, self.order,
self.reportLimit)) self.reportLimit))
self.newCount = len(self.newQueue) self.newCount = len(self.newQueue)
@ -72,15 +81,15 @@ and gid in %s order by %s limit %d""" % (ids2str(self.gids),
def _rescheduleAsRev(self, card, conf, early): def _rescheduleAsRev(self, card, conf, early):
Scheduler._rescheduleAsRev(self, card, conf, early) Scheduler._rescheduleAsRev(self, card, conf, early)
card.ivl = self._graduatingIvl(card, conf, early) ivl = self._graduatingIvl(card, conf, early)
card.due = self.today + card.ivl card.due = self.today + ivl
# temporarily suspend it # temporarily suspend it
card.queue = -3 card.queue = -3
def _graduatingIvl(self, card, conf, early): def _graduatingIvl(self, card, conf, early):
if conf['resched']: if conf['resched']:
print "fixme" # shift card by the time it was delayed
return card.ivl return card.ivl - card.edue - self.today
else: else:
return card.ivl return card.ivl

View file

@ -2,7 +2,7 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html # License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html
import simplejson, time import simplejson
from anki.utils import intTime from anki.utils import intTime
# maybe define a random cutoff at say +/-30% which controls exit interval # maybe define a random cutoff at say +/-30% which controls exit interval
@ -26,6 +26,8 @@ defaultConf = {
'cram': { 'cram': {
'delays': [0.5, 3, 10], 'delays': [0.5, 3, 10],
'resched': True, 'resched': True,
'reset': True,
'mult': 0,
}, },
'rev': { 'rev': {
'ease4': 1.3, 'ease4': 1.3,

View file

@ -160,6 +160,7 @@ If the same name exists, compare checksums."""
########################################################################## ##########################################################################
def downloadMissing(self): def downloadMissing(self):
raise Exception()
urlbase = self.deck.getVar("mediaURL") urlbase = self.deck.getVar("mediaURL")
if not urlbase: if not urlbase:
return None return None
@ -189,6 +190,7 @@ If the same name exists, compare checksums."""
########################################################################## ##########################################################################
def downloadRemote(self): def downloadRemote(self):
raise Exception()
mdir = self.deck.dir(create=True) mdir = self.deck.dir(create=True)
refs = {} refs = {}
for (question, answer) in self.deck.db.all( for (question, answer) in self.deck.db.all(

View file

@ -310,19 +310,29 @@ def test_cram():
c = f.cards()[0] c = f.cards()[0]
c.ivl = 100 c.ivl = 100
c.type = c.queue = 2 c.type = c.queue = 2
c.due = d.sched.today + 50 # due in 25 days, so it's been waiting 75 days
c.due = d.sched.today + 25
c.mod = 1 c.mod = 1
c.startTimer()
c.flush() c.flush()
cardcopy = copy.copy(c)
d.cramGroups([1]) d.cramGroups([1])
# first, test with initial intervals preserved
conf = d.sched._lrnConf(c)
conf['reset'] = False
conf['resched'] = False
assert d.sched.counts() == (1, 0, 0) assert d.sched.counts() == (1, 0, 0)
c = d.sched.getCard() c = d.sched.getCard()
assert d.sched.counts() == (0, 0, 0) assert d.sched.counts() == (0, 0, 0)
# check that estimates work # check that estimates work
assert d.sched.nextIvl(c, 1) == 30 assert d.sched.nextIvl(c, 1) == 30
assert d.sched.nextIvl(c, 2) == 180 assert d.sched.nextIvl(c, 2) == 180
print "fixme" assert d.sched.nextIvl(c, 3) == 86400*100
print d.sched.nextIvl(c, 3) == 86400*100 # failing it should not reset ivl
# answer it assert c.ivl == 100
d.sched.answerCard(c, 1)
assert c.ivl == 100
# reset ivl for exit test, and pass card
d.sched.answerCard(c, 2) d.sched.answerCard(c, 2)
delta = c.due - time.time() delta = c.due - time.time()
assert delta > 175 and delta <= 180 assert delta > 175 and delta <= 180
@ -331,8 +341,34 @@ def test_cram():
d.sched.answerCard(c, 2) d.sched.answerCard(c, 2)
d.sched.answerCard(c, 2) d.sched.answerCard(c, 2)
assert c.queue == -3 assert c.queue == -3
print "fixme"
assert c.ivl == 100 assert c.ivl == 100
# and if the queue is reset, it shouldn't appear in the new queue again # and if the queue is reset, it shouldn't appear in the new queue again
d.reset() d.reset()
assert d.sched.counts() == (0, 0, 0) assert d.sched.counts() == (0, 0, 0)
# now try again with ivl rescheduling
c = copy.copy(cardcopy)
c.flush()
d.cramGroups([1])
conf = d.sched._lrnConf(c)
conf['reset'] = False
conf['resched'] = True
# failures shouldn't matter
d.sched.answerCard(c, 1)
# graduating the card will keep the same interval, but shift the card
# forward the number of days it had been waiting (75)
assert d.sched.nextIvl(c, 3) == 75*86400
d.sched.answerCard(c, 3)
assert c.ivl == 100
assert c.due == d.sched.today + 75
# try with ivl reset
c = copy.copy(cardcopy)
c.flush()
d.cramGroups([1])
conf = d.sched._lrnConf(c)
conf['reset'] = True
conf['resched'] = True
d.sched.answerCard(c, 1)
assert d.sched.nextIvl(c, 3) == 1*86400
d.sched.answerCard(c, 3)
assert c.ivl == 1
assert c.due == d.sched.today + 1