From 8e0b009173fd555081d4b0fe27c805e8ff97bb81 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Wed, 31 Jan 2018 14:50:17 +1000 Subject: [PATCH] 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. --- anki/schedv2.py | 52 +++++++++++++++++++++---------------------- tests/test_schedv2.py | 12 +++++----- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/anki/schedv2.py b/anki/schedv2.py index 1d9f2de52..0620f6fc7 100644 --- a/anki/schedv2.py +++ b/anki/schedv2.py @@ -111,10 +111,7 @@ class Scheduler: counts = [self.newCount, self.lrnCount, self.revCount] if card: idx = self.countIdx(card) - if idx == 1 and not self._previewingCard(card): - counts[1] += card.left // 1000 - else: - counts[idx] += 1 + counts[idx] += 1 return tuple(counts) def dueForecast(self, days=7): @@ -442,21 +439,23 @@ select id from cards where did in %s and queue = 0 limit ?)""" ########################################################################## def _resetLrnCount(self): + cutoff = intTime() + self.col.conf['collapseTime'] + # sub-day self.lrnCount = self.col.db.scalar(""" -select sum(left/1000) from (select left from cards where -did in %s and queue = 1 and due < ? limit %d)""" % ( +select count() from (select null from cards where did in %s and queue = 1 +and due < ? limit %d)""" % ( self._deckLimit(), self.reportLimit), - self.dayCutoff) or 0 + cutoff) or 0 # day self.lrnCount += self.col.db.scalar(""" -select count() from cards where did in %s and queue = 3 -and due <= ? limit %d""" % (self._deckLimit(), self.reportLimit), +select count() from (select null from cards where did in %s and queue = 3 +and due <= ? limit %d)""" % (self._deckLimit(), self.reportLimit), 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)) +select count() from (select null from cards where did in %s and queue = 4 +limit %d)""" % (self._deckLimit(), self.reportLimit)) def _resetLrn(self): self._resetLrnCount() @@ -470,10 +469,11 @@ limit %d""" % (self._deckLimit(), self.reportLimit)) return False if self._lrnQueue: return True + cutoff = intTime() + self.col.conf['collapseTime'] self._lrnQueue = self.col.db.all(""" select due, id from cards where 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 self._lrnQueue.sort() return self._lrnQueue @@ -486,10 +486,7 @@ limit %d""" % (self._deckLimit(), self.reportLimit), lim=self.dayCutoff) if self._lrnQueue[0][0] < cutoff: id = heappop(self._lrnQueue)[1] card = self.col.getCard(id) - if self._previewingCard(card): - self.lrnCount -= 1 - else: - self.lrnCount -= card.left // 1000 + self.lrnCount -= 1 return card # daily learning @@ -588,15 +585,16 @@ did = ? and queue = 3 and due <= ? limit ?""", card.due = int(time.time() + delay) # due today? 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 - 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)) + if card.due < (intTime() + self.col.conf['collapseTime']): + self.lrnCount += 1 + # 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 + 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: # the card is due in one or more days, so we need to use the # day learn queue @@ -707,13 +705,13 @@ did = ? and queue = 3 and due <= ? limit ?""", def _lrnForDeck(self, did): cnt = self.col.db.scalar( """ -select sum(left/1000) from -(select left from cards where did = ? and queue = 1 and due < ? limit ?)""", +select count() from +(select null from cards where did = ? and queue = 1 and due < ? limit ?)""", did, intTime() + self.col.conf['collapseTime'], self.reportLimit) or 0 return cnt + self.col.db.scalar( """ select count() from -(select 1 from cards where did = ? and queue = 3 +(select null from cards where did = ? and queue = 3 and due <= ? limit ?)""", did, self.today, self.reportLimit) diff --git a/tests/test_schedv2.py b/tests/test_schedv2.py index 756126d2a..6d55a3f68 100644 --- a/tests/test_schedv2.py +++ b/tests/test_schedv2.py @@ -789,14 +789,14 @@ def test_counts_idx(): assert d.sched.countIdx(c) == 0 # answer to move to learn queue 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 c = d.sched.getCard() assert d.sched.counts() == (0, 0, 0) assert d.sched.countIdx(c) == 1 # answering should add it back again d.sched.answerCard(c, 1) - assert d.sched.counts() == (0, 2, 0) + assert d.sched.counts() == (0, 1, 0) def test_repCounts(): d = getEmptyCol() @@ -807,13 +807,13 @@ def test_repCounts(): # lrnReps should be accurate on pass/fail assert d.sched.counts() == (1, 0, 0) 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) - assert d.sched.counts() == (0, 2, 0) + assert d.sched.counts() == (0, 1, 0) d.sched.answerCard(d.sched.getCard(), 3) assert d.sched.counts() == (0, 1, 0) 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) assert d.sched.counts() == (0, 1, 0) d.sched.answerCard(d.sched.getCard(), 3) @@ -826,7 +826,7 @@ def test_repCounts(): d.sched.answerCard(d.sched.getCard(), 3) assert d.sched.counts() == (0, 1, 0) 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) assert d.sched.counts() == (0, 0, 0) # immediate graduate should work