diff --git a/anki/cram.py b/anki/cram.py index c1d963880..b97ba1f1d 100644 --- a/anki/cram.py +++ b/anki/cram.py @@ -24,6 +24,7 @@ class CramScheduler(Scheduler): def reset(self): self._updateCutoff() self._resetConf() + self._resetLrnCount() self._resetLrn() self._resetNew() self._resetRev() diff --git a/anki/deck.py b/anki/deck.py index 023462cc3..698bad916 100644 --- a/anki/deck.py +++ b/anki/deck.py @@ -21,7 +21,6 @@ import anki.cards, anki.facts, anki.models, anki.template, anki.cram defaultQconf = { 'revGroups': [], 'newGroups': [], - 'groupsOn': True, 'newPerDay': 20, 'newToday': [0, 0], # currentDay, count 'newTodayOrder': NEW_TODAY_ORD, @@ -557,8 +556,6 @@ select conf from gconf where id = (select gcid from groups where id = ?)""", gid)) def activeGroups(self, type): - if not self.qconf['groupsOn']: - return [] return self.qconf[type+"Groups"] def setActiveGroups(self, type, list): diff --git a/anki/sched.py b/anki/sched.py index d8dccc500..6efc452ee 100644 --- a/anki/sched.py +++ b/anki/sched.py @@ -19,6 +19,8 @@ class Scheduler(object): self.db = deck.db self.queueLimit = 200 self.reportLimit = 1000 + self.useGroups = True + self._updateCutoff() def getCard(self): "Pop the next card from the queue. None if finished." @@ -30,15 +32,11 @@ class Scheduler(object): return c def reset(self): - self._updateCutoff() self._resetConf() - t = time.time() + self._resetCounts() self._resetLrn() - #print "lrn %0.2fms" % ((time.time() - t)*1000); t = time.time() self._resetRev() - #print "rev %0.2fms" % ((time.time() - t)*1000); t = time.time() self._resetNew() - #print "new %0.2fms" % ((time.time() - t)*1000); t = time.time() def answerCard(self, card, ease): if card.queue == 0: @@ -76,6 +74,27 @@ order by due""" % self._groupLimit("rev"), self.db.execute( "update cards set queue = type where queue between -3 and -2") + # Counts + ########################################################################## + + def selCounts(self): + "Return counts for selected groups, without building queue." + self.useGroups = True + self._resetCounts() + return self.counts() + + def allCounts(self): + "Return counts for all groups, without building queue." + self.useGroups = False + self._resetCounts() + return self.counts() + + def _resetCounts(self): + self._updateCutoff() + self._resetLrnCount() + self._resetRevCount() + self._resetNewCount() + # Getting the next card ########################################################################## @@ -118,7 +137,6 @@ select count() from (select id from cards where 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 @@ -173,7 +191,6 @@ queue = 0 %s order by due limit %d""" % (self._groupLimit('new'), intTime() + self.deck.qconf['collapseTime']) def _resetLrn(self): - self._resetLrnCount() self.lrnQueue = self.db.all(""" select due, id from cards where queue = 1 and due < :lim order by due @@ -282,7 +299,6 @@ queue = 2 %s and due <= :lim limit %d)""" % ( lim=self.today) def _resetRev(self): - self._resetRevCount() self.revQueue = self.db.list(""" select id from cards where queue = 2 %s and due <= :lim order by %s limit %d""" % ( @@ -451,6 +467,8 @@ queue = 2 %s and due <= :lim order by %s limit %d""" % ( return self.confCache[id] def _groupLimit(self, type): + if not self.useGroups: + return "" l = self.deck.activeGroups(type) if not l: # everything diff --git a/anki/storage.py b/anki/storage.py index 138ffd6c1..c715eda52 100644 --- a/anki/storage.py +++ b/anki/storage.py @@ -457,9 +457,16 @@ questionAlign, lastFontColour, allowEmptyAnswer, typeAnswer from cardModels"""): conf['typeAns'] = ordN else: conf['typeAns'] = None - # ensure the new style field format - conf['qfmt'] = re.sub("%\((.+?)\)s", "{{\\1}}", conf['qfmt']) - conf['afmt'] = re.sub("%\((.+?)\)s", "{{\\1}}", conf['afmt']) + for type in ("qfmt", "afmt"): + # ensure the new style field format + conf[type] = re.sub("%\((.+?)\)s", "{{\\1}}", conf[type]) + # some special names have changed + conf[type] = re.sub( + "(?i){{tags}}", "{{Tags}}", conf[type]) + conf[type] = re.sub( + "(?i){{cardModel}}", "{{Template}}", conf[type]) + conf[type] = re.sub( + "(?i){{modelTags}}", "{{Model}}", conf[type]) # add to model list with ordinal for sorting mods[row[0]].append((row[1], conf)) # now we've gathered all the info, save it into the models diff --git a/tests/test_sched.py b/tests/test_sched.py index 419f58e16..8810d8f88 100644 --- a/tests/test_sched.py +++ b/tests/test_sched.py @@ -496,3 +496,39 @@ def test_ordcycle(): assert d.sched.getCard().ord == 0 assert d.sched.getCard().ord == 1 assert d.sched.getCard().ord == 2 + +def test_counts(): + d = getEmptyDeck() + # add a second group + assert d.groupId("new group") == 2 + # for each card type + for type in range(3): + # and each of the groups + for gid in (1,2): + # 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.gid = gid + c.due = 0 + c.flush() + d.reset() + # with the default settings, there's no count limit + assert d.sched.counts() == (2,2,2) + # check limit to one group + d.qconf['revGroups'] = [1] + d.qconf['newGroups'] = [1] + d.reset() + assert d.sched.counts() == (1,2,1) + # we can disable the groups without forgetting them + d.sched.useGroups = False + d.reset() + assert d.sched.counts() == (2,2,2) + # we don't need to build the queue to get the counts + assert d.sched.allCounts() == (2,2,2) + assert d.sched.selCounts() == (1,2,1) + assert d.sched.allCounts() == (2,2,2)