mirror of
https://github.com/ankitects/anki.git
synced 2025-09-21 07:22:23 -04:00
rewrite groupCounts()
Instead of collecting the exact number of cards, we just record whether a group has any reviews or new cards. By not needing to calculate the exact numbers, it runs a lot faster than before. Also, changed the group code to ensure parents are automatically created when a group is added.
This commit is contained in:
parent
de8a5b69ed
commit
28d045feef
3 changed files with 55 additions and 38 deletions
|
@ -94,8 +94,9 @@ class GroupManager(object):
|
||||||
# if it's a top level group, it gets the top level config
|
# if it's a top level group, it gets the top level config
|
||||||
g = defaultTopConf.copy()
|
g = defaultTopConf.copy()
|
||||||
else:
|
else:
|
||||||
# not top level. calling code should ensure parents already exist?
|
# not top level; ensure all parents exist
|
||||||
g = {}
|
g = {}
|
||||||
|
self._ensureParents(name)
|
||||||
g['name'] = name
|
g['name'] = name
|
||||||
g['conf'] = 1
|
g['conf'] = 1
|
||||||
while 1:
|
while 1:
|
||||||
|
@ -122,6 +123,16 @@ class GroupManager(object):
|
||||||
"A list of all groups."
|
"A list of all groups."
|
||||||
return self.groups.values()
|
return self.groups.values()
|
||||||
|
|
||||||
|
def _ensureParents(self, name):
|
||||||
|
path = name.split("::")
|
||||||
|
s = ""
|
||||||
|
for p in path[:-1]:
|
||||||
|
if not s:
|
||||||
|
s += p
|
||||||
|
else:
|
||||||
|
s += "::" + p
|
||||||
|
self.id(s)
|
||||||
|
|
||||||
# Group utils
|
# Group utils
|
||||||
#############################################################
|
#############################################################
|
||||||
|
|
||||||
|
@ -164,8 +175,7 @@ class GroupManager(object):
|
||||||
return
|
return
|
||||||
# save the top level group
|
# save the top level group
|
||||||
name = self.groups[str(gid)]['name']
|
name = self.groups[str(gid)]['name']
|
||||||
path = name.split("::")
|
self.deck.conf['topGroup'] = self.topFor(name)
|
||||||
self.deck.conf['topGroup'] = self.id(path[0])
|
|
||||||
# current group
|
# current group
|
||||||
self.deck.conf['curGroup'] = gid
|
self.deck.conf['curGroup'] = gid
|
||||||
# and active groups (current + all children)
|
# and active groups (current + all children)
|
||||||
|
@ -174,3 +184,8 @@ class GroupManager(object):
|
||||||
if g['name'].startswith(name + "::"):
|
if g['name'].startswith(name + "::"):
|
||||||
actv.append(g['id'])
|
actv.append(g['id'])
|
||||||
self.deck.conf['activeGroups'] = actv
|
self.deck.conf['activeGroups'] = actv
|
||||||
|
|
||||||
|
def topFor(self, name):
|
||||||
|
"The top level gid for NAME."
|
||||||
|
path = name.split("::")
|
||||||
|
return self.id(path[0])
|
||||||
|
|
|
@ -108,15 +108,28 @@ order by due""" % self._groupLimit(),
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def groupCounts(self):
|
def groupCounts(self):
|
||||||
"Returns [groupname, cards, due, new]"
|
"Returns [groupname, hasDue, hasNew]"
|
||||||
|
# find groups with 1 or more due cards
|
||||||
gids = {}
|
gids = {}
|
||||||
for (gid, all, rev, new) in self.deck.db.execute("""
|
for g in self.deck.groups.all():
|
||||||
select gid, count(),
|
hasDue = self.deck.db.scalar("""
|
||||||
sum(case when queue = 2 and due <= ? then 1 else 0 end),
|
select 1 from cards where gid = ? and
|
||||||
sum(case when queue = 0 then 1 else 0 end)
|
((queue = 2 and due <= ?) or (queue = 1 and due < ?)) limit 1""",
|
||||||
from cards group by gid""", self.today):
|
g['id'], self.today, intTime())
|
||||||
gids[gid] = [all, rev, new]
|
top = self.deck.groups.get(
|
||||||
return [[grp['name'], int(gid)]+gids.get(int(gid), [0, 0, 0])
|
self.deck.groups.topFor(g['name']))
|
||||||
|
if top['newToday'][0] != self.today:
|
||||||
|
# it's a new day; reset counts
|
||||||
|
top['newToday'] = [self.today, 0]
|
||||||
|
hasNew = max(0, top['newPerDay'] - top['newToday'][1])
|
||||||
|
if hasNew:
|
||||||
|
# if the limit hasn't run out, check to see if there are
|
||||||
|
# actually cards
|
||||||
|
hasNew = self.deck.db.scalar(
|
||||||
|
"select 1 from cards where queue = 0 and gid = ? limit 1",
|
||||||
|
g['id'])
|
||||||
|
gids[g['id']] = [hasDue or 0, hasNew or 0]
|
||||||
|
return [[grp['name'], int(gid)]+gids.get(int(gid))
|
||||||
for (gid, grp) in self._orderedGroups()]
|
for (gid, grp) in self._orderedGroups()]
|
||||||
|
|
||||||
def _orderedGroups(self):
|
def _orderedGroups(self):
|
||||||
|
@ -145,7 +158,6 @@ from cards group by gid""", self.today):
|
||||||
for (head, tail) in itertools.groupby(grps, key=key):
|
for (head, tail) in itertools.groupby(grps, key=key):
|
||||||
tail = list(tail)
|
tail = list(tail)
|
||||||
gid = None
|
gid = None
|
||||||
all = 0
|
|
||||||
rev = 0
|
rev = 0
|
||||||
new = 0
|
new = 0
|
||||||
children = []
|
children = []
|
||||||
|
@ -153,9 +165,8 @@ from cards group by gid""", self.today):
|
||||||
if len(c[0]) == 1:
|
if len(c[0]) == 1:
|
||||||
# current node
|
# current node
|
||||||
gid = c[1]
|
gid = c[1]
|
||||||
all += c[2]
|
rev += c[2]
|
||||||
rev += c[3]
|
new += c[3]
|
||||||
new += c[4]
|
|
||||||
else:
|
else:
|
||||||
# set new string to tail
|
# set new string to tail
|
||||||
c[0] = c[0][1]
|
c[0] = c[0][1]
|
||||||
|
@ -163,10 +174,9 @@ from cards group by gid""", self.today):
|
||||||
children = self._groupChildren(children)
|
children = self._groupChildren(children)
|
||||||
# tally up children counts
|
# tally up children counts
|
||||||
for ch in children:
|
for ch in children:
|
||||||
all += ch[2]
|
rev += ch[2]
|
||||||
rev += ch[3]
|
new += ch[3]
|
||||||
new += ch[4]
|
tree.append((head, gid, rev, new, children))
|
||||||
tree.append((head, gid, all, rev, new, children))
|
|
||||||
return tuple(tree)
|
return tuple(tree)
|
||||||
|
|
||||||
# Getting the next card
|
# Getting the next card
|
||||||
|
|
|
@ -695,32 +695,24 @@ def test_groupCounts():
|
||||||
d.addFact(f)
|
d.addFact(f)
|
||||||
d.reset()
|
d.reset()
|
||||||
assert d.sched.counts() == (3, 0, 1)
|
assert d.sched.counts() == (3, 0, 1)
|
||||||
assert len(d.groups.groups) == 4
|
assert len(d.groups.groups) == 5
|
||||||
cnts = d.sched.groupCounts()
|
cnts = d.sched.groupCounts()
|
||||||
assert cnts[0] == ["Default", 1, 1, 0, 1]
|
assert cnts[0] == ["Default", 1, 0, 1]
|
||||||
assert cnts[1] == ["Default::1", default1, 1, 1, 0]
|
assert cnts[1] == ["Default::1", default1, 1, 0]
|
||||||
assert cnts[2] == ["foo::bar", foobar, 1, 0, 1]
|
assert cnts[2] == ["foo", d.groups.id("foo"), 0, 0]
|
||||||
assert cnts[3] == ["foo::baz", foobaz, 1, 0, 1]
|
assert cnts[3] == ["foo::bar", foobar, 0, 1]
|
||||||
|
assert cnts[4] == ["foo::baz", foobaz, 0, 1]
|
||||||
tree = d.sched.groupCountTree()
|
tree = d.sched.groupCountTree()
|
||||||
assert tree[0][0] == "Default"
|
assert tree[0][0] == "Default"
|
||||||
# sum of child and parent
|
# sum of child and parent
|
||||||
assert tree[0][1] == 1
|
assert tree[0][1] == 1
|
||||||
assert tree[0][2] == 2
|
assert tree[0][2] == 1
|
||||||
assert tree[0][3] == 1
|
assert tree[0][3] == 1
|
||||||
assert tree[0][4] == 1
|
|
||||||
# child count is just review
|
# child count is just review
|
||||||
assert tree[0][5][0][0] == "1"
|
assert tree[0][4][0][0] == "1"
|
||||||
assert tree[0][5][0][1] == default1
|
assert tree[0][4][0][1] == default1
|
||||||
assert tree[0][5][0][2] == 1
|
assert tree[0][4][0][2] == 1
|
||||||
assert tree[0][5][0][3] == 1
|
assert tree[0][4][0][3] == 0
|
||||||
assert tree[0][5][0][4] == 0
|
|
||||||
# event if parent group didn't exist, it should have been created with a
|
|
||||||
# counts summary, with an empty gid
|
|
||||||
assert tree[1][0] == "foo"
|
|
||||||
assert tree[1][1] == None
|
|
||||||
assert tree[1][2] == 2
|
|
||||||
assert tree[1][3] == 0
|
|
||||||
assert tree[1][4] == 2
|
|
||||||
|
|
||||||
def test_reorder():
|
def test_reorder():
|
||||||
d = getEmptyDeck()
|
d = getEmptyDeck()
|
||||||
|
|
Loading…
Reference in a new issue