mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 22:42:25 -04:00
give card types a more logical order
they are now 0=new, 1=learning, 2=due, to reflect the natural progression
This commit is contained in:
parent
6f5918e8cd
commit
22a72d82c6
4 changed files with 58 additions and 57 deletions
|
@ -10,9 +10,9 @@ MAX_TIMER = 60
|
|||
# Cards
|
||||
##########################################################################
|
||||
|
||||
# Type: 0=learning, 1=due, 2=new
|
||||
# Queue: 0=learning, 1=due, 2=new
|
||||
# -1=suspended, -2=user buried, -3=sched buried
|
||||
# Type: 0=new, 1=learning, 2=due
|
||||
# Queue: same as above, and:
|
||||
# -1=suspended, -2=user buried, -3=sched buried, -4=deleted
|
||||
# Due is used differently for different queues.
|
||||
# - new queue: fact id or random int
|
||||
# - rev queue: integer day
|
||||
|
@ -32,8 +32,8 @@ class Card(object):
|
|||
self.id = None
|
||||
self.gid = 1
|
||||
self.crt = intTime()
|
||||
self.type = 2
|
||||
self.queue = 2
|
||||
self.type = 0
|
||||
self.queue = 0
|
||||
self.ivl = 0
|
||||
self.factor = 0
|
||||
self.reps = 0
|
||||
|
|
|
@ -256,7 +256,7 @@ select id from facts where id not in (select distinct fid from cards)""")
|
|||
if self.qconf['newCardOrder'] == NEW_CARDS_RANDOM:
|
||||
# if this fact has existing new cards, use their due time
|
||||
due = self.db.scalar(
|
||||
"select due from cards where fid = ? and queue = 2", fact.id)
|
||||
"select due from cards where fid = ? and queue = 0", fact.id)
|
||||
due = due or random.randrange(1, 1000000)
|
||||
else:
|
||||
due = fact.id
|
||||
|
|
|
@ -42,13 +42,12 @@ class Scheduler(object):
|
|||
|
||||
def answerCard(self, card, ease):
|
||||
if card.queue == 0:
|
||||
self._answerLearnCard(card, ease)
|
||||
elif card.queue == 1:
|
||||
self._answerRevCard(card, ease)
|
||||
elif card.queue == 2:
|
||||
# put it in the learn queue
|
||||
card.queue = 0
|
||||
card.queue = 1
|
||||
if card.queue == 1:
|
||||
self._answerLearnCard(card, ease)
|
||||
elif card.queue == 2:
|
||||
self._answerRevCard(card, ease)
|
||||
else:
|
||||
raise Exception("Invalid queue")
|
||||
card.mod = intTime()
|
||||
|
@ -56,7 +55,7 @@ class Scheduler(object):
|
|||
|
||||
def counts(self):
|
||||
"Does not include fetched but unanswered."
|
||||
return (self.learnCount, self.revCount, self.newCount)
|
||||
return (self.newCount, self.learnCount, self.revCount)
|
||||
|
||||
def cardQueue(self, card):
|
||||
return card.queue
|
||||
|
@ -110,14 +109,14 @@ class Scheduler(object):
|
|||
else:
|
||||
self.newCount = self.db.scalar("""
|
||||
select count() from (select id from cards where
|
||||
queue = 2 %s limit %d)""" % (self._groupLimit('new'), lim))
|
||||
queue = 0 %s limit %d)""" % (self._groupLimit('new'), lim))
|
||||
|
||||
def _resetNew(self):
|
||||
self._resetNewCount()
|
||||
lim = min(self.queueLimit, self.newCount)
|
||||
self.newQueue = self.db.all("""
|
||||
select id, due from cards where
|
||||
queue = 2 %s order by due limit %d""" % (self._groupLimit('new'),
|
||||
queue = 0 %s order by due limit %d""" % (self._groupLimit('new'),
|
||||
lim))
|
||||
self.newQueue.reverse()
|
||||
self._updateNewCardRatio()
|
||||
|
@ -159,14 +158,14 @@ queue = 2 %s order by due limit %d""" % (self._groupLimit('new'),
|
|||
|
||||
def _resetLearnCount(self):
|
||||
self.learnCount = self.db.scalar(
|
||||
"select count() from cards where queue = 0 and due < ?",
|
||||
"select count() from cards where queue = 1 and due < ?",
|
||||
intTime() + self.deck.qconf['collapseTime'])
|
||||
|
||||
def _resetLearn(self):
|
||||
self._resetLearnCount()
|
||||
self.learnQueue = self.db.all("""
|
||||
select due, id from cards where
|
||||
queue = 0 and due < :lim order by due
|
||||
queue = 1 and due < :lim order by due
|
||||
limit %d""" % self.reportLimit, lim=self.dayCutoff)
|
||||
|
||||
def _getLearnCard(self, collapse=False):
|
||||
|
@ -208,18 +207,18 @@ limit %d""" % self.reportLimit, lim=self.dayCutoff)
|
|||
def _learnConf(self, card):
|
||||
conf = self._cardConf(card)
|
||||
if card.type == 2:
|
||||
return conf['new']
|
||||
else:
|
||||
return conf['lapse']
|
||||
else:
|
||||
return conf['new']
|
||||
|
||||
def _rescheduleAsReview(self, card, conf, early):
|
||||
if card.type == 1:
|
||||
if card.type == 2:
|
||||
# failed; put back entry due
|
||||
card.due = card.edue
|
||||
else:
|
||||
self._rescheduleNew(card, conf, early)
|
||||
card.queue = 1
|
||||
card.type = 1
|
||||
card.queue = 2
|
||||
card.type = 2
|
||||
|
||||
def _graduatingIvl(self, card, conf, early):
|
||||
if not early:
|
||||
|
@ -258,8 +257,8 @@ limit %d""" % self.reportLimit, lim=self.dayCutoff)
|
|||
"Remove failed cards from the learning queue."
|
||||
self.deck.db.execute("""
|
||||
update cards set
|
||||
due = edue, queue = 1
|
||||
where queue = 0 and type = 1
|
||||
due = edue, queue = 2
|
||||
where queue = 1 and type = 2
|
||||
""")
|
||||
|
||||
# Reviews
|
||||
|
@ -268,7 +267,7 @@ where queue = 0 and type = 1
|
|||
def _resetReviewCount(self):
|
||||
self.revCount = self.db.scalar("""
|
||||
select count() from (select id from cards where
|
||||
queue = 1 %s and due <= :lim limit %d)""" % (
|
||||
queue = 2 %s and due <= :lim limit %d)""" % (
|
||||
self._groupLimit("rev"), self.reportLimit),
|
||||
lim=self.today)
|
||||
|
||||
|
@ -276,7 +275,7 @@ queue = 1 %s and due <= :lim limit %d)""" % (
|
|||
self._resetReviewCount()
|
||||
self.revQueue = self.db.list("""
|
||||
select id from cards where
|
||||
queue = 1 %s and due <= :lim order by %s limit %d""" % (
|
||||
queue = 2 %s and due <= :lim order by %s limit %d""" % (
|
||||
self._groupLimit("rev"), self._revOrder(), self.queueLimit),
|
||||
lim=self.today)
|
||||
if self.deck.qconf['revCardOrder'] == REV_CARDS_RANDOM:
|
||||
|
@ -321,7 +320,7 @@ queue = 1 %s and due <= :lim order by %s limit %d""" % (
|
|||
card.due = card.edue = self.today + card.ivl
|
||||
# put back in the learn queue?
|
||||
if conf['relearn']:
|
||||
card.queue = 0
|
||||
card.queue = 1
|
||||
self.learnCount += 1
|
||||
# leech?
|
||||
self._checkLeech(card, conf)
|
||||
|
@ -382,7 +381,7 @@ queue = 1 %s and due <= :lim order by %s limit %d""" % (
|
|||
conf = self._cardConf(card)['rev']
|
||||
# find sibling positions
|
||||
dues = self.db.list(
|
||||
"select due from cards where fid = ? and queue = 1"
|
||||
"select due from cards where fid = ? and queue = 2"
|
||||
" and id != ?", card.fid, card.id)
|
||||
if not dues or idealDue not in dues:
|
||||
card.ivl = idealIvl
|
||||
|
@ -508,13 +507,13 @@ queue = 1 %s and due <= :lim order by %s limit %d""" % (
|
|||
def lrnTomorrow(self):
|
||||
"Number of cards in the learning queue due tomorrow."
|
||||
return self.db.scalar(
|
||||
"select count() from cards where queue = 0 and due < ?",
|
||||
"select count() from cards where queue = 1 and due < ?",
|
||||
self.dayCutoff+86400)
|
||||
|
||||
def revTomorrow(self):
|
||||
"Number of reviews due tomorrow."
|
||||
return self.db.scalar(
|
||||
"select count() from cards where queue = 1 and due = ?"+
|
||||
"select count() from cards where queue = 2 and due = ?"+
|
||||
self._groupLimit("rev"),
|
||||
self.today+1)
|
||||
|
||||
|
@ -523,7 +522,7 @@ queue = 1 %s and due <= :lim order by %s limit %d""" % (
|
|||
lim = self.deck.qconf['newPerDay']
|
||||
return self.db.scalar(
|
||||
"select count() from (select id from cards where "
|
||||
"queue = 2 limit %d)" % lim)
|
||||
"queue = 0 limit %d)" % lim)
|
||||
|
||||
# Next time reports
|
||||
##########################################################################
|
||||
|
@ -535,7 +534,7 @@ queue = 1 %s and due <= :lim order by %s limit %d""" % (
|
|||
|
||||
def nextIvl(self, card, ease):
|
||||
"Return the next interval for CARD, in seconds."
|
||||
if card.queue in (0,2):
|
||||
if card.queue in (0,1):
|
||||
# in learning
|
||||
return self._nextLrnIvl(card, ease)
|
||||
elif ease == 1:
|
||||
|
|
|
@ -22,13 +22,13 @@ def test_new():
|
|||
# fetch it
|
||||
c = d.sched.getCard()
|
||||
assert c
|
||||
assert c.queue == 2
|
||||
assert c.type == 2
|
||||
assert c.queue == 0
|
||||
assert c.type == 0
|
||||
# if we answer it, it should become a learn card
|
||||
t = intTime()
|
||||
d.sched.answerCard(c, 1)
|
||||
assert c.queue == 0
|
||||
assert c.type == 2
|
||||
assert c.queue == 1
|
||||
assert c.type == 0
|
||||
assert c.due >= t
|
||||
# the default order should ensure siblings are not seen together, and
|
||||
# should show all cards
|
||||
|
@ -55,7 +55,7 @@ def test_learn():
|
|||
f['Front'] = u"one"; f['Back'] = u"two"
|
||||
f = d.addFact(f)
|
||||
# set as a learn card and rebuild queues
|
||||
d.db.execute("update cards set queue=0, type=2")
|
||||
d.db.execute("update cards set queue=0, type=0")
|
||||
d.reset()
|
||||
# sched.getCard should return it, since it's due in the past
|
||||
c = d.sched.getCard()
|
||||
|
@ -90,46 +90,47 @@ def test_learn():
|
|||
assert c.grade == 2
|
||||
assert c.cycles == 3
|
||||
# the next pass should graduate the card
|
||||
assert c.queue == 0
|
||||
assert c.type == 2
|
||||
d.sched.answerCard(c, 2)
|
||||
assert c.queue == 1
|
||||
assert c.type == 1
|
||||
assert c.type == 0
|
||||
d.sched.answerCard(c, 2)
|
||||
assert c.queue == 2
|
||||
assert c.type == 2
|
||||
# should be due tomorrow, with an interval of 1
|
||||
assert c.due == d.sched.today+1
|
||||
assert c.ivl == 1
|
||||
# let's try early removal bonus
|
||||
c.type = 2
|
||||
c.queue = 0
|
||||
c.type = 0
|
||||
c.queue = 1
|
||||
c.cycles = 0
|
||||
d.sched.answerCard(c, 3)
|
||||
assert c.type == 1
|
||||
assert c.type == 2
|
||||
assert c.ivl == 7
|
||||
# or normal removal
|
||||
c.type = 2
|
||||
c.queue = 0
|
||||
c.type = 0
|
||||
c.queue = 1
|
||||
c.cycles = 1
|
||||
d.sched.answerCard(c, 3)
|
||||
assert c.type == 1
|
||||
assert c.type == 2
|
||||
assert c.queue == 2
|
||||
assert c.ivl == 4
|
||||
# revlog should have been updated each time
|
||||
d.db.scalar("select count() from revlog where type = 0") == 6
|
||||
# now failed card handling
|
||||
c.type = 1
|
||||
c.queue = 0
|
||||
c.type = 2
|
||||
c.queue = 1
|
||||
c.edue = 123
|
||||
d.sched.answerCard(c, 3)
|
||||
assert c.due == 123
|
||||
assert c.type == 1
|
||||
assert c.queue == 1
|
||||
assert c.type == 2
|
||||
assert c.queue == 2
|
||||
# we should be able to remove manually, too
|
||||
c.type = 1
|
||||
c.queue = 0
|
||||
c.type = 2
|
||||
c.queue = 1
|
||||
c.edue = 321
|
||||
c.flush()
|
||||
d.sched.removeFailed()
|
||||
c.load()
|
||||
assert c.queue == 1
|
||||
assert c.queue == 2
|
||||
assert c.due == 321
|
||||
|
||||
def test_reviews():
|
||||
|
@ -140,8 +141,8 @@ def test_reviews():
|
|||
d.addFact(f)
|
||||
# set the card up as a review card, due yesterday
|
||||
c = f.cards()[0]
|
||||
c.type = 1
|
||||
c.queue = 1
|
||||
c.type = 2
|
||||
c.queue = 2
|
||||
c.due = d.sched.today - 8
|
||||
c.factor = 2500
|
||||
c.reps = 3
|
||||
|
@ -156,7 +157,7 @@ def test_reviews():
|
|||
# failing it should put it in the learn queue with the default options
|
||||
##################################################
|
||||
d.sched.answerCard(c, 1)
|
||||
assert c.queue == 0
|
||||
assert c.queue == 1
|
||||
# it should be due tomorrow, with an interval of 1
|
||||
assert c.due == d.sched.today + 1
|
||||
assert c.ivl == 1
|
||||
|
@ -171,6 +172,7 @@ def test_reviews():
|
|||
c = copy.copy(cardcopy)
|
||||
c.flush()
|
||||
d.sched.answerCard(c, 2)
|
||||
assert c.queue == 2
|
||||
# the new interval should be (100 + 8/4) * 1.2 = 122
|
||||
assert c.ivl == 122
|
||||
assert c.due == d.sched.today + 122
|
||||
|
@ -257,7 +259,7 @@ def test_nextIvl():
|
|||
assert ni(c, 3) == 4*86400
|
||||
# review cards
|
||||
##################################################
|
||||
c.queue = 1
|
||||
c.queue = 2
|
||||
c.ivl = 100
|
||||
c.factor = 2500
|
||||
# failing it puts it at tomorrow
|
||||
|
|
Loading…
Reference in a new issue