diff --git a/anki/consts.py b/anki/consts.py index 4dbdcbacb..d6d0a2957 100644 --- a/anki/consts.py +++ b/anki/consts.py @@ -24,6 +24,10 @@ REV_CARDS_RANDOM = 2 REM_CARD = 0 REM_FACT = 1 +# count display +COUNT_ANSWERED = 0 +COUNT_REMAINING = 1 + # Labels ########################################################################## diff --git a/anki/deck.py b/anki/deck.py index 32a080980..2c0ddffe6 100644 --- a/anki/deck.py +++ b/anki/deck.py @@ -24,6 +24,7 @@ defaultConf = { 'topGroup': 1, 'curGroup': None, 'revOrder': REV_CARDS_RANDOM, + 'counts': COUNT_ANSWERED, # other config 'nextPos': 1, 'fontFamilies': [ diff --git a/anki/sched.py b/anki/sched.py index 84a531a2c..dd7aa79ef 100644 --- a/anki/sched.py +++ b/anki/sched.py @@ -66,7 +66,14 @@ class Scheduler(object): def counts(self): "Does not include fetched but unanswered." - return (self.newCount, self.lrnCount, self.revCount) + if self.deck.conf['counts'] == COUNT_REMAINING: + return (self.newCount, self.lrnCount, self.revCount) + else: + return self.answeredCounts() + + def answeredCounts(self): + t = self.deck.groups.top() + return (t['newToday'][1], t['lrnToday'][1], t['revToday'][1]) def dueForecast(self, days=7): "Return counts over next DAYS. Includes today." @@ -726,15 +733,12 @@ queue = 2 %s and due <= :lim order by %s limit %d""" % ( def timeToday(self): "Time spent learning today, in seconds." - return self.deck.db.scalar( - "select sum(time/1000.0) from revlog where id > ?*1000", - self.dayCutoff-86400) or 0 + t = self.deck.groups.top() + return t['timeToday'][1] / 1000 def repsToday(self): "Number of cards answered today." - return self.deck.db.scalar( - "select count() from revlog where id > ?*1000", - self.dayCutoff-86400) + return sum(self.answeredCounts()) # Dynamic indices ########################################################################## diff --git a/tests/test_deck.py b/tests/test_deck.py index 3a21e256d..042919b2e 100644 --- a/tests/test_deck.py +++ b/tests/test_deck.py @@ -3,6 +3,7 @@ import os, re, datetime from tests.shared import assertException, getEmptyDeck, testDir from anki.stdmodels import addBasicModel +from anki.consts import * from anki import Deck @@ -126,6 +127,7 @@ def test_upgrade(): d = datetime.datetime.fromtimestamp(deck.crt) assert d.hour == 4 and d.minute == 0 # 3 new, 2 failed, 1 due + deck.conf['counts'] = COUNT_REMAINING assert deck.sched.counts() == (3,2,1) # now's a good time to test the integrity check too deck.fixIntegrity() diff --git a/tests/test_sched.py b/tests/test_sched.py index 502431c53..1c843d2ef 100644 --- a/tests/test_sched.py +++ b/tests/test_sched.py @@ -4,6 +4,7 @@ import time, copy from tests.shared import assertException, getEmptyDeck from anki.utils import stripHTML, intTime from anki.hooks import addHook +from anki.consts import * def test_basics(): d = getEmptyDeck() @@ -578,8 +579,47 @@ def test_ordcycle(): assert d.sched.getCard().ord == 1 assert d.sched.getCard().ord == 2 -def test_counts(): +def test_counts_up(): d = getEmptyDeck() + # for each card type + for type in range(3): + # create a new fact + f = d.newFact() + f['Front'] = u"one" + d.addFact(f) + c = f.cards()[0] + # set type/gid + c.type = type + c.queue = type + c.due = 0 + c.flush() + d.reset() + # all zeros first + assert d.sched.counts() == (0,0,0) + # answer the first card, which is a lrn one + c = d.sched.getCard() + assert c.queue == 1 + d.sched.answerCard(c, 4) + assert d.sched.counts() == (0,1,0) + # and the next, which is a rev card + c = d.sched.getCard() + assert c.queue == 2 + d.sched.answerCard(c, 4) + assert d.sched.counts() == (0,1,1) + # and the last, which is a new one + c = d.sched.getCard() + assert c.queue == 0 + d.sched.answerCard(c, 4) + assert d.sched.counts() == (1,1,1) + # total should match + assert d.sched.repsToday() == 3 + # the time should have been updated as well, but it gets rounded to zero + # in the test so we need to grab it manually + assert d.groups.top()['timeToday'][1] + +def test_counts_down(): + d = getEmptyDeck() + d.conf['counts'] = COUNT_REMAINING # add a second group grp = d.groups.id("new group") # for each card type @@ -605,8 +645,9 @@ def test_counts(): d.reset() assert d.sched.counts() == (1,1,1) -def test_counts2(): +def test_counts_idx(): d = getEmptyDeck() + d.conf['counts'] = COUNT_REMAINING f = d.newFact() f['Front'] = u"one"; f['Back'] = u"two" d.addFact(f) @@ -669,6 +710,7 @@ def test_collapse(): def test_groupCounts(): d = getEmptyDeck() + d.conf['counts'] = COUNT_REMAINING # add a fact with default group f = d.newFact() f['Front'] = u"one" @@ -754,6 +796,7 @@ def test_reorder(): def test_forget(): d = getEmptyDeck() + d.conf['counts'] = COUNT_REMAINING f = d.newFact() f['Front'] = u"one" d.addFact(f) diff --git a/tests/test_undo.py b/tests/test_undo.py index 8150d7ebe..9400f971f 100644 --- a/tests/test_undo.py +++ b/tests/test_undo.py @@ -2,6 +2,8 @@ import time from tests.shared import assertException, getEmptyDeck +from anki.consts import * + def test_op(): d = getEmptyDeck() # should have no undo by default @@ -35,6 +37,7 @@ def test_op(): def test_review(): d = getEmptyDeck() + d.conf['counts'] = COUNT_REMAINING f = d.newFact() f['Front'] = u"one" d.addFact(f)