experiment with counting learning cards instead of learning steps

When studying, the learning count now indicates the number of
learning cards due within the learn ahead limit, instead of the total
number of learning steps required to complete that day.

Also fix the ineffective limit clauses in the learning counts.
This commit is contained in:
Damien Elmes 2018-01-31 14:50:17 +10:00
parent 49d1d8f9fd
commit 8e0b009173
2 changed files with 31 additions and 33 deletions

View File

@ -111,10 +111,7 @@ class Scheduler:
counts = [self.newCount, self.lrnCount, self.revCount] counts = [self.newCount, self.lrnCount, self.revCount]
if card: if card:
idx = self.countIdx(card) idx = self.countIdx(card)
if idx == 1 and not self._previewingCard(card): counts[idx] += 1
counts[1] += card.left // 1000
else:
counts[idx] += 1
return tuple(counts) return tuple(counts)
def dueForecast(self, days=7): def dueForecast(self, days=7):
@ -442,21 +439,23 @@ select id from cards where did in %s and queue = 0 limit ?)"""
########################################################################## ##########################################################################
def _resetLrnCount(self): def _resetLrnCount(self):
cutoff = intTime() + self.col.conf['collapseTime']
# sub-day # sub-day
self.lrnCount = self.col.db.scalar(""" self.lrnCount = self.col.db.scalar("""
select sum(left/1000) from (select left from cards where select count() from (select null from cards where did in %s and queue = 1
did in %s and queue = 1 and due < ? limit %d)""" % ( and due < ? limit %d)""" % (
self._deckLimit(), self.reportLimit), self._deckLimit(), self.reportLimit),
self.dayCutoff) or 0 cutoff) or 0
# day # day
self.lrnCount += self.col.db.scalar(""" self.lrnCount += self.col.db.scalar("""
select count() from cards where did in %s and queue = 3 select count() from (select null 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 # previews
self.lrnCount += self.col.db.scalar(""" self.lrnCount += self.col.db.scalar("""
select count() from cards where did in %s and queue = 4 select count() from (select null from cards where did in %s and queue = 4
limit %d""" % (self._deckLimit(), self.reportLimit)) limit %d)""" % (self._deckLimit(), self.reportLimit))
def _resetLrn(self): def _resetLrn(self):
self._resetLrnCount() self._resetLrnCount()
@ -470,10 +469,11 @@ limit %d""" % (self._deckLimit(), self.reportLimit))
return False return False
if self._lrnQueue: if self._lrnQueue:
return True return True
cutoff = intTime() + self.col.conf['collapseTime']
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 in (1,4) 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=cutoff)
# 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()
return self._lrnQueue return self._lrnQueue
@ -486,10 +486,7 @@ 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)
if self._previewingCard(card): self.lrnCount -= 1
self.lrnCount -= 1
else:
self.lrnCount -= card.left // 1000
return card return card
# daily learning # daily learning
@ -588,15 +585,16 @@ did = ? and queue = 3 and due <= ? limit ?""",
card.due = int(time.time() + delay) card.due = int(time.time() + delay)
# due today? # due today?
if card.due < self.dayCutoff: if card.due < self.dayCutoff:
self.lrnCount += card.left // 1000
# if the queue is not empty and there's nothing else to do, make
# sure we don't put it at the head of the queue and end up showing
# it twice in a row
card.queue = 1 card.queue = 1
if self._lrnQueue and not self.revCount and not self.newCount: if card.due < (intTime() + self.col.conf['collapseTime']):
smallestDue = self._lrnQueue[0][0] self.lrnCount += 1
card.due = max(card.due, smallestDue+1) # if the queue is not empty and there's nothing else to do, make
heappush(self._lrnQueue, (card.due, card.id)) # sure we don't put it at the head of the queue and end up showing
# it twice in a row
if self._lrnQueue and not self.revCount and not self.newCount:
smallestDue = self._lrnQueue[0][0]
card.due = max(card.due, smallestDue+1)
heappush(self._lrnQueue, (card.due, card.id))
else: else:
# the card is due in one or more days, so we need to use the # the card is due in one or more days, so we need to use the
# day learn queue # day learn queue
@ -707,13 +705,13 @@ did = ? and queue = 3 and due <= ? limit ?""",
def _lrnForDeck(self, did): def _lrnForDeck(self, did):
cnt = self.col.db.scalar( cnt = self.col.db.scalar(
""" """
select sum(left/1000) from select count() from
(select left from cards where did = ? and queue = 1 and due < ? limit ?)""", (select null from cards where did = ? and queue = 1 and due < ? limit ?)""",
did, intTime() + self.col.conf['collapseTime'], self.reportLimit) or 0 did, intTime() + self.col.conf['collapseTime'], self.reportLimit) or 0
return cnt + self.col.db.scalar( return cnt + self.col.db.scalar(
""" """
select count() from select count() from
(select 1 from cards where did = ? and queue = 3 (select null from cards where did = ? and queue = 3
and due <= ? limit ?)""", and due <= ? limit ?)""",
did, self.today, self.reportLimit) did, self.today, self.reportLimit)

View File

@ -789,14 +789,14 @@ def test_counts_idx():
assert d.sched.countIdx(c) == 0 assert d.sched.countIdx(c) == 0
# answer to move to learn queue # answer to move to learn queue
d.sched.answerCard(c, 1) d.sched.answerCard(c, 1)
assert d.sched.counts() == (0, 2, 0) assert d.sched.counts() == (0, 1, 0)
# fetching again will decrement the count # fetching again will decrement the count
c = d.sched.getCard() c = d.sched.getCard()
assert d.sched.counts() == (0, 0, 0) assert d.sched.counts() == (0, 0, 0)
assert d.sched.countIdx(c) == 1 assert d.sched.countIdx(c) == 1
# answering should add it back again # answering should add it back again
d.sched.answerCard(c, 1) d.sched.answerCard(c, 1)
assert d.sched.counts() == (0, 2, 0) assert d.sched.counts() == (0, 1, 0)
def test_repCounts(): def test_repCounts():
d = getEmptyCol() d = getEmptyCol()
@ -807,13 +807,13 @@ def test_repCounts():
# lrnReps should be accurate on pass/fail # lrnReps should be accurate on pass/fail
assert d.sched.counts() == (1, 0, 0) assert d.sched.counts() == (1, 0, 0)
d.sched.answerCard(d.sched.getCard(), 1) d.sched.answerCard(d.sched.getCard(), 1)
assert d.sched.counts() == (0, 2, 0) assert d.sched.counts() == (0, 1, 0)
d.sched.answerCard(d.sched.getCard(), 1) d.sched.answerCard(d.sched.getCard(), 1)
assert d.sched.counts() == (0, 2, 0) assert d.sched.counts() == (0, 1, 0)
d.sched.answerCard(d.sched.getCard(), 3) d.sched.answerCard(d.sched.getCard(), 3)
assert d.sched.counts() == (0, 1, 0) assert d.sched.counts() == (0, 1, 0)
d.sched.answerCard(d.sched.getCard(), 1) d.sched.answerCard(d.sched.getCard(), 1)
assert d.sched.counts() == (0, 2, 0) assert d.sched.counts() == (0, 1, 0)
d.sched.answerCard(d.sched.getCard(), 3) d.sched.answerCard(d.sched.getCard(), 3)
assert d.sched.counts() == (0, 1, 0) assert d.sched.counts() == (0, 1, 0)
d.sched.answerCard(d.sched.getCard(), 3) d.sched.answerCard(d.sched.getCard(), 3)
@ -826,7 +826,7 @@ def test_repCounts():
d.sched.answerCard(d.sched.getCard(), 3) d.sched.answerCard(d.sched.getCard(), 3)
assert d.sched.counts() == (0, 1, 0) assert d.sched.counts() == (0, 1, 0)
d.sched.answerCard(d.sched.getCard(), 1) d.sched.answerCard(d.sched.getCard(), 1)
assert d.sched.counts() == (0, 2, 0) assert d.sched.counts() == (0, 1, 0)
d.sched.answerCard(d.sched.getCard(), 4) d.sched.answerCard(d.sched.getCard(), 4)
assert d.sched.counts() == (0, 0, 0) assert d.sched.counts() == (0, 0, 0)
# immediate graduate should work # immediate graduate should work