mirror of
https://github.com/ankitects/anki.git
synced 2025-09-21 15:32:23 -04:00
experiment with simple resched=off case to 'preview mode'
the previous approach meant we weren't able to preserve the card state exactly when cards were in learning, since we didn't record the step position prior to cards being moved into the filtered deck. it also meant the answer buttons needed to change depending on state - 4 for cards in learning/review, but 2 when the card is on the final step or is a review. instead, in preview mode cards always have 2 buttons: again will repeat again after a delay, and good immediately removes the card and restores it to its previous state. to accomplish this, we use a separate queue #, as the learn count always needs to have a 1:1 correspondence to the number of cards
This commit is contained in:
parent
575f61c384
commit
ba87fc7736
2 changed files with 110 additions and 222 deletions
154
anki/sched.py
154
anki/sched.py
|
@ -57,11 +57,10 @@ class Scheduler:
|
||||||
def answerCard(self, card, ease):
|
def answerCard(self, card, ease):
|
||||||
self.col.log()
|
self.col.log()
|
||||||
assert 1 <= ease <= 4
|
assert 1 <= ease <= 4
|
||||||
assert 0 <= card.queue <= 3
|
assert 0 <= card.queue <= 4
|
||||||
self.col.markReview(card)
|
self.col.markReview(card)
|
||||||
if self._burySiblingsOnAnswer:
|
if self._burySiblingsOnAnswer:
|
||||||
self._burySiblings(card)
|
self._burySiblings(card)
|
||||||
card.reps += 1
|
|
||||||
|
|
||||||
self._answerCard(card, ease)
|
self._answerCard(card, ease)
|
||||||
|
|
||||||
|
@ -71,6 +70,11 @@ class Scheduler:
|
||||||
card.flushSched()
|
card.flushSched()
|
||||||
|
|
||||||
def _answerCard(self, card, ease):
|
def _answerCard(self, card, ease):
|
||||||
|
if self._previewingCard(card):
|
||||||
|
self._answerCardPreview(card, ease)
|
||||||
|
return
|
||||||
|
|
||||||
|
card.reps += 1
|
||||||
card.wasNew = card.type == 0
|
card.wasNew = card.type == 0
|
||||||
|
|
||||||
if card.queue == 0:
|
if card.queue == 0:
|
||||||
|
@ -88,6 +92,22 @@ class Scheduler:
|
||||||
# update daily limit
|
# update daily limit
|
||||||
self._updateStats(card, 'rev')
|
self._updateStats(card, 'rev')
|
||||||
|
|
||||||
|
# hard-coded for now
|
||||||
|
_previewDelay = 600
|
||||||
|
|
||||||
|
def _answerCardPreview(self, card, ease):
|
||||||
|
assert 1 <= ease <= 2
|
||||||
|
|
||||||
|
if ease == 1:
|
||||||
|
# repeat after delay
|
||||||
|
card.queue = 4
|
||||||
|
card.due = intTime() + self._previewDelay
|
||||||
|
self.lrnCount += 1
|
||||||
|
else:
|
||||||
|
# restore original card state and remove from filtered deck
|
||||||
|
self._restoreFromFiltered(card)
|
||||||
|
self._removeFromFiltered(card)
|
||||||
|
|
||||||
def counts(self, card=None):
|
def counts(self, card=None):
|
||||||
counts = [self.newCount, self.lrnCount, self.revCount]
|
counts = [self.newCount, self.lrnCount, self.revCount]
|
||||||
if card:
|
if card:
|
||||||
|
@ -117,23 +137,14 @@ order by due""" % self._deckLimit(),
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def countIdx(self, card):
|
def countIdx(self, card):
|
||||||
if card.queue == 3:
|
if card.queue in (3,4):
|
||||||
return 1
|
return 1
|
||||||
return card.queue
|
return card.queue
|
||||||
|
|
||||||
def answerButtons(self, card):
|
def answerButtons(self, card):
|
||||||
conf = self._cardConf(card)
|
conf = self._cardConf(card)
|
||||||
|
if card.odid and not conf['resched']:
|
||||||
# fixme: resched=off case
|
return 2
|
||||||
# if card.odid:
|
|
||||||
# if not conf['resched']:
|
|
||||||
# if card.queue == 2:
|
|
||||||
# return 4
|
|
||||||
# conf = self._lrnConf(card)
|
|
||||||
# if card.type in (0,1) or len(conf['delays']) > 1:
|
|
||||||
# return 3
|
|
||||||
# return 2
|
|
||||||
|
|
||||||
return 4
|
return 4
|
||||||
|
|
||||||
def unburyCards(self):
|
def unburyCards(self):
|
||||||
|
@ -449,6 +460,10 @@ did in %s and queue = 1 and due < ? limit %d)""" % (
|
||||||
select count() from cards where did in %s and queue = 3
|
select count() from cards where did in %s and queue = 3
|
||||||
and due <= ? limit %d""" % (self._deckLimit(), self.reportLimit),
|
and due <= ? limit %d""" % (self._deckLimit(), self.reportLimit),
|
||||||
self.today)
|
self.today)
|
||||||
|
# previews
|
||||||
|
self.lrnCount += self.col.db.scalar("""
|
||||||
|
select count() from cards where did in %s and queue = 4
|
||||||
|
limit %d""" % (self._deckLimit(), self.reportLimit))
|
||||||
|
|
||||||
def _resetLrn(self):
|
def _resetLrn(self):
|
||||||
self._resetLrnCount()
|
self._resetLrnCount()
|
||||||
|
@ -464,7 +479,7 @@ and due <= ? limit %d""" % (self._deckLimit(), self.reportLimit),
|
||||||
return True
|
return True
|
||||||
self._lrnQueue = self.col.db.all("""
|
self._lrnQueue = self.col.db.all("""
|
||||||
select due, id from cards where
|
select due, id from cards where
|
||||||
did in %s and queue = 1 and due < :lim
|
did in %s and queue in (1,4) and due < :lim
|
||||||
limit %d""" % (self._deckLimit(), self.reportLimit), lim=self.dayCutoff)
|
limit %d""" % (self._deckLimit(), self.reportLimit), lim=self.dayCutoff)
|
||||||
# as it arrives sorted by did first, we need to sort it
|
# as it arrives sorted by did first, we need to sort it
|
||||||
self._lrnQueue.sort()
|
self._lrnQueue.sort()
|
||||||
|
@ -478,7 +493,10 @@ limit %d""" % (self._deckLimit(), self.reportLimit), lim=self.dayCutoff)
|
||||||
if self._lrnQueue[0][0] < cutoff:
|
if self._lrnQueue[0][0] < cutoff:
|
||||||
id = heappop(self._lrnQueue)[1]
|
id = heappop(self._lrnQueue)[1]
|
||||||
card = self.col.getCard(id)
|
card = self.col.getCard(id)
|
||||||
self.lrnCount -= card.left // 1000
|
if self._previewingCard(card):
|
||||||
|
self.lrnCount -= 1
|
||||||
|
else:
|
||||||
|
self.lrnCount -= card.left // 1000
|
||||||
return card
|
return card
|
||||||
|
|
||||||
# daily learning
|
# daily learning
|
||||||
|
@ -542,10 +560,9 @@ did = ? and queue = 3 and due <= ? limit ?""",
|
||||||
|
|
||||||
def _moveToFirstStep(self, card, conf):
|
def _moveToFirstStep(self, card, conf):
|
||||||
card.left = self._startingLeft(card)
|
card.left = self._startingLeft(card)
|
||||||
resched = self._resched(card)
|
|
||||||
|
|
||||||
card.lastIvl = card.ivl
|
card.lastIvl = card.ivl
|
||||||
if card.type == 2 and resched:
|
if card.type == 2:
|
||||||
# review card that will move to relearning
|
# review card that will move to relearning
|
||||||
card.ivl = self._lapseIvl(card, self._lrnConf(card))
|
card.ivl = self._lapseIvl(card, self._lrnConf(card))
|
||||||
|
|
||||||
|
@ -624,27 +641,15 @@ did = ? and queue = 3 and due <= ? limit ?""",
|
||||||
|
|
||||||
def _rescheduleAsRev(self, card, conf, early):
|
def _rescheduleAsRev(self, card, conf, early):
|
||||||
lapse = card.type == 2
|
lapse = card.type == 2
|
||||||
resched = self._resched(card)
|
|
||||||
|
|
||||||
if resched:
|
if lapse:
|
||||||
if lapse:
|
self._rescheduleGraduatingLapse(card)
|
||||||
self._rescheduleGraduatingLapse(card)
|
else:
|
||||||
else:
|
self._rescheduleNew(card, conf, early)
|
||||||
self._rescheduleNew(card, conf, early)
|
|
||||||
|
|
||||||
# if we were dynamic, graduating means moving back to the old deck
|
# if we were dynamic, graduating means moving back to the old deck
|
||||||
if card.odid:
|
if card.odid:
|
||||||
# and leaving learning if scheduling off
|
self._removeFromFiltered(card)
|
||||||
if not resched:
|
|
||||||
card.due = card.odue
|
|
||||||
if card.type == 2:
|
|
||||||
card.queue = 2
|
|
||||||
else:
|
|
||||||
card.queue = card.type = 0
|
|
||||||
|
|
||||||
card.did = card.odid
|
|
||||||
card.odue = 0
|
|
||||||
card.odid = 0
|
|
||||||
|
|
||||||
def _rescheduleGraduatingLapse(self, card):
|
def _rescheduleGraduatingLapse(self, card):
|
||||||
card.due = self.today+card.ivl
|
card.due = self.today+card.ivl
|
||||||
|
@ -860,40 +865,28 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)"""
|
||||||
# update interval
|
# update interval
|
||||||
card.lastIvl = card.ivl
|
card.lastIvl = card.ivl
|
||||||
|
|
||||||
if self._resched(card):
|
self._updateRevIvl(card, ease)
|
||||||
self._updateRevIvl(card, ease)
|
# then the rest
|
||||||
# then the rest
|
card.factor = max(1300, card.factor+[-150, 0, 150][ease-2])
|
||||||
card.factor = max(1300, card.factor+[-150, 0, 150][ease-2])
|
card.due = self.today + card.ivl
|
||||||
card.due = self.today + card.ivl
|
|
||||||
else:
|
|
||||||
card.due = card.odue
|
|
||||||
|
|
||||||
# card leaves filtered deck
|
# card leaves filtered deck
|
||||||
if card.odid:
|
self._removeFromFiltered(card)
|
||||||
card.did = card.odid
|
|
||||||
card.odid = 0
|
|
||||||
card.odue = 0
|
|
||||||
|
|
||||||
def _rescheduleEarlyRev(self, card, ease):
|
def _rescheduleEarlyRev(self, card, ease):
|
||||||
# update interval
|
# update interval
|
||||||
card.lastIvl = card.ivl
|
card.lastIvl = card.ivl
|
||||||
|
|
||||||
if self._resched(card):
|
self._updateEarlyRevIvl(card, ease)
|
||||||
self._updateEarlyRevIvl(card, ease)
|
# then the rest
|
||||||
# then the rest
|
card.factor = max(1300, card.factor+[-150, 0, 150][ease-2])
|
||||||
card.factor = max(1300, card.factor+[-150, 0, 150][ease-2])
|
card.due = self.today + card.ivl
|
||||||
card.due = self.today + card.ivl
|
|
||||||
else:
|
|
||||||
card.due = card.odue
|
|
||||||
|
|
||||||
# move from 0->2
|
# move from 0->2
|
||||||
card.queue = 2
|
card.queue = 2
|
||||||
|
|
||||||
# card leaves filtered deck
|
# card leaves filtered deck
|
||||||
if card.odid:
|
self._removeFromFiltered(card)
|
||||||
card.did = card.odid
|
|
||||||
card.odid = 0
|
|
||||||
card.odue = 0
|
|
||||||
|
|
||||||
def _logRev(self, card, ease, delay, type):
|
def _logRev(self, card, ease, delay, type):
|
||||||
def log():
|
def log():
|
||||||
|
@ -1111,6 +1104,25 @@ did = ?, due = ?, usn = ? where id = ?
|
||||||
"""
|
"""
|
||||||
self.col.db.executemany(query, data)
|
self.col.db.executemany(query, data)
|
||||||
|
|
||||||
|
def _removeFromFiltered(self, card):
|
||||||
|
if card.odid:
|
||||||
|
card.did = card.odid
|
||||||
|
card.odue = 0
|
||||||
|
card.odid = 0
|
||||||
|
|
||||||
|
def _restoreFromFiltered(self, card):
|
||||||
|
assert card.odid
|
||||||
|
|
||||||
|
card.due = card.odue
|
||||||
|
|
||||||
|
if card.type in (0, 2):
|
||||||
|
card.queue = card.type
|
||||||
|
else:
|
||||||
|
if card.odue > 1000000000:
|
||||||
|
card.queue = 1
|
||||||
|
else:
|
||||||
|
card.queue = 3
|
||||||
|
|
||||||
# Leeches
|
# Leeches
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
|
@ -1129,12 +1141,6 @@ did = ?, due = ?, usn = ? where id = ?
|
||||||
# handle
|
# handle
|
||||||
a = conf['leechAction']
|
a = conf['leechAction']
|
||||||
if a == 0:
|
if a == 0:
|
||||||
# if it has an old due, remove it from cram/relearning
|
|
||||||
if card.odue:
|
|
||||||
card.due = card.odue
|
|
||||||
if card.odid:
|
|
||||||
card.did = card.odid
|
|
||||||
card.odue = card.odid = 0
|
|
||||||
card.queue = -1
|
card.queue = -1
|
||||||
# notify UI
|
# notify UI
|
||||||
runHook("leech", card)
|
runHook("leech", card)
|
||||||
|
@ -1194,11 +1200,9 @@ did = ?, due = ?, usn = ? where id = ?
|
||||||
def _deckLimit(self):
|
def _deckLimit(self):
|
||||||
return ids2str(self.col.decks.active())
|
return ids2str(self.col.decks.active())
|
||||||
|
|
||||||
def _resched(self, card):
|
def _previewingCard(self, card):
|
||||||
conf = self._cardConf(card)
|
conf = self._cardConf(card)
|
||||||
if not conf['dyn']:
|
return conf['dyn'] and not conf['resched']
|
||||||
return True
|
|
||||||
return conf['resched']
|
|
||||||
|
|
||||||
# Daily cutoff
|
# Daily cutoff
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
@ -1299,6 +1303,12 @@ To study outside of the normal schedule, click the Custom Study button below."""
|
||||||
|
|
||||||
def nextIvl(self, card, ease):
|
def nextIvl(self, card, ease):
|
||||||
"Return the next interval for CARD, in seconds."
|
"Return the next interval for CARD, in seconds."
|
||||||
|
# preview mode?
|
||||||
|
if self._previewingCard(card):
|
||||||
|
if ease == 1:
|
||||||
|
return self._previewDelay
|
||||||
|
return 0
|
||||||
|
|
||||||
# (re)learning?
|
# (re)learning?
|
||||||
if card.queue in (0,1,3):
|
if card.queue in (0,1,3):
|
||||||
return self._nextLrnIvl(card, ease)
|
return self._nextLrnIvl(card, ease)
|
||||||
|
@ -1312,10 +1322,7 @@ To study outside of the normal schedule, click the Custom Study button below."""
|
||||||
# review
|
# review
|
||||||
early = card.odid and (card.odue > self.today)
|
early = card.odid and (card.odue > self.today)
|
||||||
if early:
|
if early:
|
||||||
if self._resched(card):
|
return self._earlyReviewIvl(card, ease)*86400
|
||||||
return self._earlyReviewIvl(card, ease)*86400
|
|
||||||
else:
|
|
||||||
return 0
|
|
||||||
else:
|
else:
|
||||||
return self._nextRevIvl(card, ease, fuzz=False)*86400
|
return self._nextRevIvl(card, ease, fuzz=False)*86400
|
||||||
|
|
||||||
|
@ -1330,16 +1337,11 @@ To study outside of the normal schedule, click the Custom Study button below."""
|
||||||
elif ease == 2:
|
elif ease == 2:
|
||||||
return self._delayForRepeatingGrade(conf, card.left)
|
return self._delayForRepeatingGrade(conf, card.left)
|
||||||
elif ease == 4:
|
elif ease == 4:
|
||||||
# early removal
|
|
||||||
if not self._resched(card):
|
|
||||||
return 0
|
|
||||||
return self._graduatingIvl(card, conf, True, fuzz=False) * 86400
|
return self._graduatingIvl(card, conf, True, fuzz=False) * 86400
|
||||||
else: # ease == 3
|
else: # ease == 3
|
||||||
left = card.left%1000 - 1
|
left = card.left%1000 - 1
|
||||||
if left <= 0:
|
if left <= 0:
|
||||||
# graduate
|
# graduate
|
||||||
if not self._resched(card):
|
|
||||||
return 0
|
|
||||||
return self._graduatingIvl(card, conf, False, fuzz=False) * 86400
|
return self._graduatingIvl(card, conf, False, fuzz=False) * 86400
|
||||||
else:
|
else:
|
||||||
return self._delayForGrade(conf, left)
|
return self._delayForGrade(conf, left)
|
||||||
|
|
|
@ -627,112 +627,51 @@ def test_filt_keep_lrn_state():
|
||||||
c.load()
|
c.load()
|
||||||
assert c.type == c.queue == 1
|
assert c.type == c.queue == 1
|
||||||
|
|
||||||
def test_filt_reschedoff():
|
def test_preview():
|
||||||
# add card
|
# add cards
|
||||||
d = getEmptyCol()
|
d = getEmptyCol()
|
||||||
f = d.newNote()
|
f = d.newNote()
|
||||||
f['Front'] = "one"
|
f['Front'] = "one"
|
||||||
d.addNote(f)
|
d.addNote(f)
|
||||||
|
c = f.cards()[0]
|
||||||
|
orig = copy.copy(c)
|
||||||
|
f2 = d.newNote()
|
||||||
|
f2['Front'] = "two"
|
||||||
|
d.addNote(f2)
|
||||||
# cram deck
|
# cram deck
|
||||||
did = d.decks.newDyn("Cram")
|
did = d.decks.newDyn("Cram")
|
||||||
cram = d.decks.get(did)
|
cram = d.decks.get(did)
|
||||||
cram['resched'] = False
|
cram['resched'] = False
|
||||||
d.sched.rebuildDyn(did)
|
d.sched.rebuildDyn(did)
|
||||||
d.reset()
|
d.reset()
|
||||||
# graduate should return it to new
|
# grab the first card
|
||||||
c = d.sched.getCard()
|
c = d.sched.getCard()
|
||||||
ni = d.sched.nextIvl
|
assert d.sched.answerButtons(c) == 2
|
||||||
assert ni(c, 1) == 60
|
assert d.sched.nextIvl(c, 1) == d.sched._previewDelay
|
||||||
assert ni(c, 2) == (60+600)//2
|
assert d.sched.nextIvl(c, 2) == 0
|
||||||
assert ni(c, 3) == 600
|
# failing it will push its due time back
|
||||||
assert ni(c, 4) == 0
|
due = c.due
|
||||||
assert d.sched.nextIvlStr(c, 4) == "(end)"
|
d.sched.answerCard(c, 1)
|
||||||
d.sched.answerCard(c, 4)
|
assert c.due != due
|
||||||
assert c.queue == c.type == 0
|
|
||||||
# undue reviews should also be unaffected
|
# the other card should come next
|
||||||
c.ivl = 100
|
c2 = d.sched.getCard()
|
||||||
c.type = 2
|
assert c2.id != c.id
|
||||||
c.queue = 2
|
|
||||||
c.due = d.sched.today + 25
|
# passing it will remove it
|
||||||
c.factor = STARTING_FACTOR
|
d.sched.answerCard(c2, 2)
|
||||||
c.flush()
|
|
||||||
cardcopy = copy.copy(c)
|
# the other card should appear again
|
||||||
d.sched.rebuildDyn(did)
|
|
||||||
d.reset()
|
|
||||||
c = d.sched.getCard()
|
c = d.sched.getCard()
|
||||||
assert ni(c, 1) == 600
|
assert c.id == orig.id
|
||||||
assert ni(c, 2) == 0
|
|
||||||
assert ni(c, 3) == 0
|
# remove it
|
||||||
d.sched.answerCard(c, 2)
|
d.sched.answerCard(c, 2)
|
||||||
assert c.ivl == 100
|
|
||||||
assert c.due == d.sched.today + 25
|
# ensure it's in the same state as it started
|
||||||
# check failure too
|
assert c.queue == 0
|
||||||
c = cardcopy
|
assert c.reps == 0
|
||||||
c.flush()
|
assert c.type == 0
|
||||||
d.sched.rebuildDyn(did)
|
|
||||||
d.reset()
|
|
||||||
c = d.sched.getCard()
|
|
||||||
d.sched.answerCard(c, 1)
|
|
||||||
d.sched.emptyDyn(did)
|
|
||||||
c.load()
|
|
||||||
assert c.ivl == 100
|
|
||||||
assert c.due == d.sched.today + 25
|
|
||||||
# fail+grad early
|
|
||||||
c = cardcopy
|
|
||||||
c.flush()
|
|
||||||
d.sched.rebuildDyn(did)
|
|
||||||
d.reset()
|
|
||||||
c = d.sched.getCard()
|
|
||||||
d.sched.answerCard(c, 1)
|
|
||||||
d.sched.answerCard(c, 4)
|
|
||||||
d.sched.emptyDyn(did)
|
|
||||||
c.load()
|
|
||||||
assert c.ivl == 100
|
|
||||||
assert c.due == d.sched.today + 25
|
|
||||||
# due cards - pass
|
|
||||||
c = cardcopy
|
|
||||||
c.due = -25
|
|
||||||
c.flush()
|
|
||||||
d.sched.rebuildDyn(did)
|
|
||||||
d.reset()
|
|
||||||
c = d.sched.getCard()
|
|
||||||
d.sched.answerCard(c, 3)
|
|
||||||
d.sched.emptyDyn(did)
|
|
||||||
c.load()
|
|
||||||
assert c.ivl == 100
|
|
||||||
assert c.due == -25
|
|
||||||
# fail
|
|
||||||
c = cardcopy
|
|
||||||
c.due = -25
|
|
||||||
c.flush()
|
|
||||||
d.sched.rebuildDyn(did)
|
|
||||||
d.reset()
|
|
||||||
c = d.sched.getCard()
|
|
||||||
d.sched.answerCard(c, 1)
|
|
||||||
d.sched.emptyDyn(did)
|
|
||||||
c.load()
|
|
||||||
assert c.ivl == 100
|
|
||||||
assert c.due == -25
|
|
||||||
# fail with normal grad
|
|
||||||
c = cardcopy
|
|
||||||
c.due = -25
|
|
||||||
c.flush()
|
|
||||||
d.sched.rebuildDyn(did)
|
|
||||||
d.reset()
|
|
||||||
c = d.sched.getCard()
|
|
||||||
d.sched.answerCard(c, 1)
|
|
||||||
d.sched.answerCard(c, 4)
|
|
||||||
c.load()
|
|
||||||
assert c.ivl == 100
|
|
||||||
assert c.due == -25
|
|
||||||
# lapsed card pulled into cram
|
|
||||||
# d.sched._cardConf(c)['lapse']['mult']=0.5
|
|
||||||
# d.sched.answerCard(c, 1)
|
|
||||||
# d.sched.rebuildDyn(did)
|
|
||||||
# d.reset()
|
|
||||||
# c = d.sched.getCard()
|
|
||||||
# d.sched.answerCard(c, 2)
|
|
||||||
# print c.__dict__
|
|
||||||
|
|
||||||
def test_ordcycle():
|
def test_ordcycle():
|
||||||
d = getEmptyCol()
|
d = getEmptyCol()
|
||||||
|
@ -1067,56 +1006,3 @@ def test_failmult():
|
||||||
# so the card is reset to new
|
# so the card is reset to new
|
||||||
d.sched.answerCard(c, 1)
|
d.sched.answerCard(c, 1)
|
||||||
assert c.ivl == 1
|
assert c.ivl == 1
|
||||||
|
|
||||||
# answering a new card with scheduling off should not change
|
|
||||||
# the original position
|
|
||||||
def test_preview_order():
|
|
||||||
d = getEmptyCol()
|
|
||||||
f = d.newNote()
|
|
||||||
f['Front'] = "oneone"
|
|
||||||
d.addNote(f)
|
|
||||||
f = d.newNote()
|
|
||||||
f['Front'] = "twotwo"
|
|
||||||
d.addNote(f)
|
|
||||||
assert d.getCard(d.findCards("oneone")[0]).due == 1
|
|
||||||
assert d.getCard(d.findCards("twotwo")[0]).due == 2
|
|
||||||
|
|
||||||
did = d.decks.newDyn("Cram")
|
|
||||||
cram = d.decks.get(did)
|
|
||||||
cram['resched'] = False
|
|
||||||
d.sched.rebuildDyn(did)
|
|
||||||
d.reset()
|
|
||||||
|
|
||||||
c = d.sched.getCard()
|
|
||||||
assert "oneone" in c.q()
|
|
||||||
d.sched.answerCard(c, 3)
|
|
||||||
d.sched.answerCard(c, 3)
|
|
||||||
|
|
||||||
assert c.due == 1
|
|
||||||
|
|
||||||
# answering a due review with scheduling off should not change scheduling
|
|
||||||
def test_reviews_reschedoff():
|
|
||||||
d = getEmptyCol()
|
|
||||||
f = d.newNote()
|
|
||||||
f['Front'] = "one"
|
|
||||||
d.addNote(f)
|
|
||||||
|
|
||||||
c = f.cards()[0]
|
|
||||||
c.ivl = 100
|
|
||||||
c.queue = c.type = 2
|
|
||||||
c.due = d.sched.today
|
|
||||||
c.factor = 2500
|
|
||||||
c.flush()
|
|
||||||
|
|
||||||
did = d.decks.newDyn("Cram")
|
|
||||||
cram = d.decks.get(did)
|
|
||||||
cram['resched'] = False
|
|
||||||
d.sched.rebuildDyn(did)
|
|
||||||
d.reset()
|
|
||||||
|
|
||||||
c = d.sched.getCard()
|
|
||||||
d.sched.answerCard(c, 4)
|
|
||||||
|
|
||||||
assert c.ivl == 100
|
|
||||||
assert c.due == d.sched.today
|
|
||||||
assert c.factor == 2500
|
|
||||||
|
|
Loading…
Reference in a new issue