diff --git a/anki/cards.py b/anki/cards.py index dfa063ab3..471fe0fdf 100644 --- a/anki/cards.py +++ b/anki/cards.py @@ -29,7 +29,7 @@ class Card(object): else: # to flush, set nid, ord, and due self.id = timestampID(col.db, "cards") - self.gid = 1 + self.did = 1 self.crt = intTime() self.type = 0 self.queue = 0 @@ -45,7 +45,7 @@ class Card(object): def load(self): (self.id, self.nid, - self.gid, + self.did, self.ord, self.mod, self.usn, @@ -73,7 +73,7 @@ insert or replace into cards values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", self.id, self.nid, - self.gid, + self.did, self.ord, self.mod, self.usn, @@ -109,7 +109,7 @@ lapses=?, left=?, edue=? where id = ?""", def _getQA(self, reload=False): if not self._qa or reload: f = self.note(); m = self.model() - data = [self.id, f.id, m['id'], self.gid, self.ord, f.stringTags(), + data = [self.id, f.id, m['id'], self.did, self.ord, f.stringTags(), f.joinedFields()] self._qa = self.col._renderQA(data) return self._qa @@ -128,8 +128,8 @@ lapses=?, left=?, edue=? where id = ?""", def model(self, reload=False): return self._reviewData()[1] - def groupConf(self): - return self.col.groups.conf(self.gid) + def deckConf(self): + return self.col.decks.conf(self.did) def template(self): return self._reviewData()[1]['tmpls'][self.ord] @@ -140,4 +140,4 @@ lapses=?, left=?, edue=? where id = ?""", def timeTaken(self): "Time taken to answer card, in integer MS." total = int((time.time() - self.timerStarted)*1000) - return min(total, self.groupConf()['maxTaken']*1000) + return min(total, self.deckConf()['maxTaken']*1000) diff --git a/anki/collection.py b/anki/collection.py index bd98dc659..6c94a7ff0 100644 --- a/anki/collection.py +++ b/anki/collection.py @@ -10,7 +10,7 @@ from anki.hooks import runHook, runFilter from anki.sched import Scheduler from anki.models import ModelManager from anki.media import MediaManager -from anki.groups import GroupManager +from anki.decks import DeckManager from anki.tags import TagManager from anki.consts import * from anki.errors import AnkiError @@ -20,9 +20,9 @@ import anki.cards, anki.notes, anki.template, anki.cram, anki.find defaultConf = { # scheduling options - 'activeGroups': [1], - 'topGroup': 1, - 'curGroup': 1, + 'activeDecks': [1], + 'topDeck': 1, + 'curDeck': 1, 'revOrder': REV_CARDS_RANDOM, # other config 'nextPos': 1, @@ -44,7 +44,7 @@ class _Collection(object): self.clearUndo() self.media = MediaManager(self) self.models = ModelManager(self) - self.groups = GroupManager(self) + self.decks = DeckManager(self) self.tags = TagManager(self) self.load() if not self.crt: @@ -78,14 +78,14 @@ class _Collection(object): self.ls, self.conf, models, - groups, - gconf, + decks, + dconf, tags) = self.db.first(""" select crt, mod, scm, dty, usn, ls, -conf, models, groups, gconf, tags from col""") +conf, models, decks, dconf, tags from col""") self.conf = simplejson.loads(self.conf) self.models.load(models) - self.groups.load(groups, gconf) + self.decks.load(decks, dconf) self.tags.load(tags) def flush(self, mod=None): @@ -97,7 +97,7 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""", self.crt, self.mod, self.scm, self.dty, self._usn, self.ls, simplejson.dumps(self.conf)) self.models.flush() - self.groups.flush() + self.decks.flush() self.tags.flush() def save(self, name=None, mod=None): @@ -291,8 +291,8 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""", data = [] ts = maxID(self.db) now = intTime() - for nid, mid, gid, flds in self.db.execute( - "select id, mid, gid, flds from notes where id in "+snids): + for nid, mid, did, flds in self.db.execute( + "select id, mid, did, flds from notes where id in "+snids): model = self.models.get(mid) avail = self.models.availOrds(model, flds) ok = [] @@ -300,7 +300,7 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""", if (nid,t['ord']) in have: continue if t['ord'] in avail: - data.append((ts, nid, t['gid'] or gid, t['ord'], + data.append((ts, nid, t['did'] or did, t['ord'], now, nid)) ts += 1 # bulk update @@ -330,7 +330,7 @@ insert into cards values (?,?,?,?,?,-1,0,0,?,0,0,0,0,0,0,0,"")""", card = anki.cards.Card(self) card.nid = note.id card.ord = template['ord'] - card.gid = template['gid'] or note.gid + card.did = template['did'] or note.did card.due = due if flush: card.flush() @@ -407,7 +407,7 @@ select id from notes where id in %s and id not in (select nid from cards)""" % def _renderQA(self, data): "Returns hash of id, question, answer." - # data is [cid, nid, mid, gid, ord, tags, flds] + # data is [cid, nid, mid, did, ord, tags, flds] # unpack fields and create dict flist = splitFields(data[6]) fields = {} @@ -416,7 +416,7 @@ select id from notes where id in %s and id not in (select nid from cards)""" % fields[name] = flist[idx] fields['Tags'] = data[5] fields['Model'] = model['name'] - fields['Group'] = self.groups.name(data[3]) + fields['Deck'] = self.decks.name(data[3]) template = model['tmpls'][data[4]] fields['Template'] = template['name'] # render q & a @@ -437,9 +437,9 @@ select id from notes where id in %s and id not in (select nid from cards)""" % return d def _qaData(self, where=""): - "Return [cid, nid, mid, gid, ord, tags, flds] db query" + "Return [cid, nid, mid, did, ord, tags, flds] db query" return self.db.execute(""" -select c.id, f.id, f.mid, c.gid, c.ord, f.tags, f.flds +select c.id, f.id, f.mid, c.did, c.ord, f.tags, f.flds from cards c, notes f where c.nid == f.id %s""" % where) @@ -503,7 +503,7 @@ where c.nid == f.id self.sched = self._stdSched return True - def cramGroups(self, order="mod desc", min=0, max=None): + def cramDecks(self, order="mod desc", min=0, max=None): self.stdSched() self.sched = anki.cram.CramScheduler(self, order, min, max) diff --git a/anki/consts.py b/anki/consts.py index bd5c586b5..2c4508dd9 100644 --- a/anki/consts.py +++ b/anki/consts.py @@ -25,7 +25,7 @@ REV_CARDS_NEW_FIRST = 2 # removal types REM_CARD = 0 REM_NOTE = 1 -REM_GROUP = 2 +REM_DECK = 2 # count display COUNT_ANSWERED = 0 diff --git a/anki/cram.py b/anki/cram.py index 3eb8fc158..1155894e1 100644 --- a/anki/cram.py +++ b/anki/cram.py @@ -66,8 +66,8 @@ class CramScheduler(Scheduler): else: maxlim = "" self.newQueue = self.col.db.list(""" -select id from cards where gid in %s and queue = 2 and due >= %d -%s order by %s limit %d""" % (self._groupLimit(), +select id from cards where did in %s and queue = 2 and due >= %d +%s order by %s limit %d""" % (self._deckLimit(), self.today+1+self.min, maxlim, self.order, diff --git a/anki/groups.py b/anki/decks.py similarity index 58% rename from anki/groups.py rename to anki/decks.py index 79f54c910..f12d72be1 100644 --- a/anki/groups.py +++ b/anki/decks.py @@ -9,21 +9,21 @@ from anki.lang import _ # fixmes: # - make sure users can't set grad interval < 1 -# - make sure lists like new[delays] are not being shared by multiple groups +# - make sure lists like new[delays] are not being shared by multiple decks # - make sure all children have parents (create as necessary) -# - when renaming a group, top level properties should be added or removed as +# - when renaming a deck, top level properties should be added or removed as # appropriate # notes: -# - it's difficult to enforce valid gids for models/notes/cards, as we -# may update the gid locally only to have it overwritten by a more recent -# change from somewhere else. to avoid this, we allow invalid gid -# references, and treat any invalid gids as the default group. -# - deletions of group config force a full sync +# - it's difficult to enforce valid dids for models/notes/cards, as we +# may update the did locally only to have it overwritten by a more recent +# change from somewhere else. to avoid this, we allow invalid did +# references, and treat any invalid dids as the default deck. +# - deletions of deck config force a full sync # these are a cache of the current day's reviews. they may be wrong after a # sync merge if someone reviewed from two locations -defaultGroup = { +defaultDeck = { 'newToday': [0, 0], # currentDay, count 'revToday': [0, 0], 'lrnToday': [0, 0], @@ -31,7 +31,7 @@ defaultGroup = { 'conf': 1, } -# configuration only available to top level groups +# configuration only available to top level decks defaultTopConf = { 'revLim': 100, 'newSpread': NEW_CARDS_DISTRIBUTE, @@ -41,7 +41,7 @@ defaultTopConf = { 'curModel': None, } -# configuration available to all groups +# configuration available to all decks defaultConf = { 'name': _("Default"), 'new': { @@ -78,7 +78,7 @@ defaultConf = { 'usn': 0, } -class GroupManager(object): +class DeckManager(object): # Registry save/load ############################################################# @@ -86,13 +86,13 @@ class GroupManager(object): def __init__(self, col): self.col = col - def load(self, groups, gconf): - self.groups = simplejson.loads(groups) - self.gconf = simplejson.loads(gconf) + def load(self, decks, dconf): + self.decks = simplejson.loads(decks) + self.dconf = simplejson.loads(dconf) self.changed = False def save(self, g=None): - "Can be called with either a group or a group configuration." + "Can be called with either a deck or a deck configuration." if g: g['mod'] = intTime() g['usn'] = self.col.usn() @@ -100,86 +100,86 @@ class GroupManager(object): def flush(self): if self.changed: - self.col.db.execute("update col set groups=?, gconf=?", - simplejson.dumps(self.groups), - simplejson.dumps(self.gconf)) + self.col.db.execute("update col set decks=?, dconf=?", + simplejson.dumps(self.decks), + simplejson.dumps(self.dconf)) - # Group save/load + # Deck save/load ############################################################# def id(self, name, create=True): - "Add a group with NAME. Reuse group if already exists. Return id as int." - for id, g in self.groups.items(): + "Add a deck with NAME. Reuse deck if already exists. Return id as int." + for id, g in self.decks.items(): if g['name'].lower() == name.lower(): return int(id) if not create: return None if "::" not in name: - # if it's a top level group, it gets the top level config + # if it's a top level deck, it gets the top level config g = defaultTopConf.copy() else: # not top level; ensure all parents exist g = {} self._ensureParents(name) - for (k,v) in defaultGroup.items(): + for (k,v) in defaultDeck.items(): g[k] = v g['name'] = name while 1: id = intTime(1000) - if str(id) not in self.groups: + if str(id) not in self.decks: break g['id'] = id - self.groups[str(id)] = g + self.decks[str(id)] = g self.save(g) self.maybeAddToActive() return int(id) - def rem(self, gid, cardsToo=False): - "Remove the group. If cardsToo, delete any cards inside." - assert gid != 1 - if not str(gid) in self.groups: + def rem(self, did, cardsToo=False): + "Remove the deck. If cardsToo, delete any cards inside." + assert did != 1 + if not str(did) in self.decks: return # delete children first - for name, id in self.children(gid): + for name, id in self.children(did): self.rem(id, cardsToo) # delete cards too? if cardsToo: - self.col.remCards(self.cids(gid)) - # delete the group and add a grave - del self.groups[str(gid)] - self.col._logRem([gid], REM_GROUP) - # ensure we have an active group - if gid in self.active(): - self.select(int(self.groups.keys()[0])) + self.col.remCards(self.cids(did)) + # delete the deck and add a grave + del self.decks[str(did)] + self.col._logRem([did], REM_DECK) + # ensure we have an active deck + if did in self.active(): + self.select(int(self.decks.keys()[0])) self.save() def allNames(self): - "An unsorted list of all group names." - return [x['name'] for x in self.groups.values()] + "An unsorted list of all deck names." + return [x['name'] for x in self.decks.values()] def all(self): - "A list of all groups." - return self.groups.values() + "A list of all decks." + return self.decks.values() - def get(self, gid, default=True): - id = str(gid) - if id in self.groups: - return self.groups[id] + def get(self, did, default=True): + id = str(did) + if id in self.decks: + return self.decks[id] elif default: - return self.groups['1'] + return self.decks['1'] def update(self, g): - "Add or update an existing group. Used for syncing and merging." - self.groups[str(g['id'])] = g + "Add or update an existing deck. Used for syncing and merging." + self.decks[str(g['id'])] = g self.maybeAddToActive() # mark registry changed, but don't bump mod time self.save() def rename(self, g, newName): - "Rename group prefix to NAME if not exists. Updates children." + "Rename deck prefix to NAME if not exists. Updates children." # make sure target node doesn't already exist if newName in self.allNames(): - raise Exception("Group exists") + raise Exception("Deck exists") # rename children for grp in self.all(): if grp['name'].startswith(g['name'] + "::"): @@ -209,18 +209,18 @@ class GroupManager(object): s += "::" + p self.id(s) - # Group configurations + # Deck configurations ############################################################# def allConf(self): - "A list of all group config." - return self.gconf.values() + "A list of all deck config." + return self.dconf.values() - def conf(self, gid): - return self.gconf[str(self.groups[str(gid)]['conf'])] + def conf(self, did): + return self.dconf[str(self.decks[str(did)]['conf'])] def updateConf(self, g): - self.gconf[str(g['id'])] = g + self.dconf[str(g['id'])] = g self.save() def confId(self, name): @@ -228,19 +228,19 @@ class GroupManager(object): c = copy.deepcopy(defaultConf) while 1: id = intTime(1000) - if str(id) not in self.gconf: + if str(id) not in self.dconf: break c['id'] = id c['name'] = name - self.gconf[str(id)] = c + self.dconf[str(id)] = c self.save(c) return id def remConf(self, id): - "Remove a configuration and update all groups using it." + "Remove a configuration and update all decks using it." assert int(id) != 1 self.col.modSchema() - del self.gconf[str(id)] + del self.dconf[str(id)] for g in self.all(): if str(g['conf']) == str(id): g['conf'] = 1 @@ -250,16 +250,16 @@ class GroupManager(object): grp['conf'] = id self.save(grp) - # Group utils + # Deck utils ############################################################# - def name(self, gid): - return self.get(gid)['name'] + def name(self, did): + return self.get(did)['name'] - def setGroup(self, cids, gid): + def setDeck(self, cids, did): self.col.db.execute( - "update cards set gid=?,usn=?,mod=? where id in "+ - ids2str(cids), gid, self.col.usn(), intTime()) + "update cards set did=?,usn=?,mod=? where id in "+ + ids2str(cids), did, self.col.usn(), intTime()) def maybeAddToActive(self): @@ -268,59 +268,59 @@ class GroupManager(object): def sendHome(self, cids): self.col.db.execute(""" -update cards set gid=(select gid from notes f where f.id=nid), +update cards set did=(select did from notes f where f.id=nid), usn=?,mod=? where id in %s""" % ids2str(cids), - self.col.usn(), intTime(), gid) + self.col.usn(), intTime(), did) - def cids(self, gid): - return self.col.db.list("select id from cards where gid=?", gid) + def cids(self, did): + return self.col.db.list("select id from cards where did=?", did) - # Group selection + # Deck selection ############################################################# def top(self): - "The current top level group as an object." - g = self.get(self.col.conf['topGroup']) + "The current top level deck as an object." + g = self.get(self.col.conf['topDeck']) return g def active(self): - "The currrently active gids." - return self.col.conf['activeGroups'] + "The currrently active dids." + return self.col.conf['activeDecks'] def selected(self): - "The currently selected gid." - return self.col.conf['curGroup'] + "The currently selected did." + return self.col.conf['curDeck'] def current(self): return self.get(self.selected()) - def select(self, gid): + def select(self, did): "Select a new branch." - # save the top level group - name = self.groups[str(gid)]['name'] - self.col.conf['topGroup'] = self._topFor(name) - # current group - self.col.conf['curGroup'] = gid - # and active groups (current + all children) - actv = self.children(gid) + # save the top level deck + name = self.decks[str(did)]['name'] + self.col.conf['topDeck'] = self._topFor(name) + # current deck + self.col.conf['curDeck'] = did + # and active decks (current + all children) + actv = self.children(did) actv.sort() - self.col.conf['activeGroups'] = [gid] + [a[1] for a in actv] + self.col.conf['activeDecks'] = [did] + [a[1] for a in actv] - def children(self, gid): - "All children of gid, as (name, id)." - name = self.get(gid)['name'] + def children(self, did): + "All children of did, as (name, id)." + name = self.get(did)['name'] actv = [] for g in self.all(): if g['name'].startswith(name + "::"): actv.append((g['name'], g['id'])) return actv - def parents(self, gid): - "All parents of gid." - path = self.get(gid)['name'].split("::") + def parents(self, did): + "All parents of did." + path = self.get(did)['name'].split("::") return [self.get(x) for x in path[:-1]] def _topFor(self, name): - "The top level gid for NAME." + "The top level did for NAME." path = name.split("::") return self.id(path[0]) diff --git a/anki/find.py b/anki/find.py index 8ea9cf4ab..9f69f0eda 100644 --- a/anki/find.py +++ b/anki/find.py @@ -13,7 +13,7 @@ SEARCH_NID = 3 SEARCH_TEMPLATE = 4 SEARCH_FIELD = 5 SEARCH_MODEL = 6 -SEARCH_GROUP = 7 +SEARCH_DECK = 7 # Tools ########################################################################## @@ -121,8 +121,8 @@ order by %s""" % (lim, sort) self._findField(token, isNeg) elif type == SEARCH_MODEL: self._findModel(token, isNeg) - elif type == SEARCH_GROUP: - self._findGroup(token, isNeg) + elif type == SEARCH_DECK: + self._findDeck(token, isNeg) else: self._findText(token, isNeg, c) @@ -191,10 +191,10 @@ order by %s""" % (lim, sort) ids.append(m['id']) self.lims['note'].append("mid %s in %s" % (extra, ids2str(ids))) - def _findGroup(self, val, isNeg): + def _findDeck(self, val, isNeg): extra = "!" if isNeg else "" - id = self.col.groups.id(val, create=False) or 0 - self.lims['card'].append("c.gid %s= %s" % (extra, id)) + id = self.col.decks.id(val, create=False) or 0 + self.lims['card'].append("c.did %s= %s" % (extra, id)) def _findTemplate(self, val, isNeg): lims = [] @@ -329,9 +329,9 @@ where mid in %s and flds like ? escape '\\'""" % ( elif token['value'].startswith("model:"): token['value'] = token['value'][6:].lower() type = SEARCH_MODEL - elif token['value'].startswith("group:"): - token['value'] = token['value'][6:].lower() - type = SEARCH_GROUP + elif token['value'].startswith("deck:"): + token['value'] = token['value'][5:].lower() + type = SEARCH_DECK elif token['value'].startswith("nid:") and len(token['value']) > 4: dec = token['value'][4:] try: diff --git a/anki/importing/anki1.py b/anki/importing/anki1.py index 6d6831cf8..a9190bb19 100644 --- a/anki/importing/anki1.py +++ b/anki/importing/anki1.py @@ -27,7 +27,7 @@ class Anki1Importer(Anki2Importer): # merge deck.close() mdir = self.file.replace(".anki", ".media") - self.groupPrefix = os.path.basename(self.file).replace(".anki", "") + self.deckPrefix = os.path.basename(self.file).replace(".anki", "") self.file = deck.path Anki2Importer.run(self, mdir) diff --git a/anki/importing/anki2.py b/anki/importing/anki2.py index 3229a0852..91a6d1720 100644 --- a/anki/importing/anki2.py +++ b/anki/importing/anki2.py @@ -14,13 +14,13 @@ from anki.importing.base import Importer # - compare notes by guid # - compare models by schema signature # - compare cards by note guid + ordinal -# - compare groups by name +# - compare decks by name # class Anki2Importer(Importer): needMapper = False - groupPrefix = None + deckPrefix = None needCards = True def run(self, media=None): @@ -38,10 +38,10 @@ class Anki2Importer(Importer): self.src = Collection(self.file, queue=False) def _import(self): - self._groups = {} - if self.groupPrefix: - id = self.dst.groups.id(self.groupPrefix) - self.dst.groups.select(id) + self._decks = {} + if self.deckPrefix: + id = self.dst.decks.id(self.deckPrefix) + self.dst.decks.select(id) self._prepareTS() self._prepareModels() self._importNotes() @@ -76,7 +76,7 @@ class Anki2Importer(Importer): # rewrite internal ids, models, etc note[0] = self.ts() note[2] = lmid - note[3] = self._gid(note[3]) + note[3] = self._did(note[3]) note[4] = intTime() note[5] = -1 # usn add.append(note) @@ -136,27 +136,27 @@ class Anki2Importer(Importer): else: dst['vers'] = [src['id']] - # Groups + # Decks ###################################################################### - def _gid(self, gid): - "Given gid in src col, return local id." + def _did(self, did): + "Given did in src col, return local id." # already converted? - if gid in self._groups: - return self._groups[gid] + if did in self._decks: + return self._decks[did] # get the name in src - g = self.src.groups.get(gid) + g = self.src.decks.get(did) name = g['name'] - # if there's a prefix, replace the top level group - if self.groupPrefix: + # if there's a prefix, replace the top level deck + if self.deckPrefix: tmpname = "::".join(name.split("::")[1:]) - name = self.groupPrefix + name = self.deckPrefix if tmpname: name += "::" + name # create in local - newid = self.dst.groups.id(name) - # add to group map and return - self._groups[gid] = newid + newid = self.dst.decks.id(name) + # add to deck map and return + self._decks[did] = newid return newid # Cards @@ -199,7 +199,7 @@ class Anki2Importer(Importer): # update cid, nid, etc card[0] = self.ts() card[1] = self._notes[guid][0] - card[2] = self._gid(card[2]) + card[2] = self._did(card[2]) card[4] = intTime() cards.append(card) # we need to import revlog, rewriting card ids diff --git a/anki/models.py b/anki/models.py index bef5ec4d7..c977ca842 100644 --- a/anki/models.py +++ b/anki/models.py @@ -15,7 +15,7 @@ from anki.consts import * defaultModel = { 'sortf': 0, - 'gid': 1, + 'did': 1, 'clozectx': False, 'newOrder': NEW_CARDS_DUE, 'latexPre': """\ @@ -52,7 +52,7 @@ defaultTemplate = { 'qfmt': "", 'afmt': "", 'typeAns': None, - 'gid': None, + 'did': None, } class ModelManager(object): @@ -90,16 +90,16 @@ class ModelManager(object): def current(self): "Get current model." try: - m = self.get(self.col.groups.top()['curModel']) + m = self.get(self.col.decks.top()['curModel']) assert m return m except: return self.models.values()[0] def setCurrent(self, m): - t = self.col.groups.top() + t = self.col.decks.top() t['curModel'] = m['id'] - self.col.groups.save(t) + self.col.decks.save(t) def get(self, id): "Get model with ID, or None." diff --git a/anki/notes.py b/anki/notes.py index 22a053f29..910228452 100644 --- a/anki/notes.py +++ b/anki/notes.py @@ -19,7 +19,7 @@ class Note(object): self.id = timestampID(col.db, "notes") self.guid = guid64() self._model = model - self.gid = model['gid'] + self.did = model['did'] self.mid = model['id'] self.tags = [] self.fields = [""] * len(self._model['flds']) @@ -30,14 +30,14 @@ class Note(object): def load(self): (self.guid, self.mid, - self.gid, + self.did, self.mod, self.usn, self.tags, self.fields, self.flags, self.data) = self.col.db.first(""" -select guid, mid, gid, mod, usn, tags, flds, flags, data +select guid, mid, did, mod, usn, tags, flds, flags, data from notes where id = ?""", self.id) self.fields = splitFields(self.fields) self.tags = self.col.tags.split(self.tags) @@ -53,7 +53,7 @@ from notes where id = ?""", self.id) tags = self.stringTags() res = self.col.db.execute(""" insert or replace into notes values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", - self.id, self.guid, self.mid, self.gid, + self.id, self.guid, self.mid, self.did, self.mod, self.usn, tags, self.joinedFields(), sfld, self.flags, self.data) self.id = res.lastrowid @@ -84,10 +84,10 @@ insert or replace into notes values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", def model(self): return self._model - def updateCardGids(self): + def updateCardDids(self): for c in self.cards(): - if c.gid != self.gid and not c.template()['gid']: - c.gid = self.gid + if c.did != self.did and not c.template()['did']: + c.did = self.did c.flush() # Dict interface diff --git a/anki/sched.py b/anki/sched.py index 3bdf089cf..e7cdb0ecb 100644 --- a/anki/sched.py +++ b/anki/sched.py @@ -22,7 +22,7 @@ class Scheduler(object): self.col = col self.queueLimit = 50 self.reportLimit = 1000 - # fixme: replace reps with group based counts + # fixme: replace reps with deck based counts self.reps = 0 self._updateCutoff() @@ -78,10 +78,10 @@ class Scheduler(object): "Return counts over next DAYS. Includes today." daysd = dict(self.col.db.all(""" select due, count() from cards -where gid in %s and queue = 2 +where did in %s and queue = 2 and due between ? and ? group by due -order by due""" % self._groupLimit(), +order by due""" % self._deckLimit(), self.today, self.today+days-1)) for d in range(days): @@ -111,34 +111,34 @@ order by due""" % self._groupLimit(), def _updateStats(self, card, type, cnt=1): key = type+"Today" - for g in ([self.col.groups.get(card.gid)] + - self.col.groups.parents(card.gid)): + for g in ([self.col.decks.get(card.did)] + + self.col.decks.parents(card.did)): # add g[key][1] += cnt - self.col.groups.save(g) + self.col.decks.save(g) - # Group counts + # Deck counts ########################################################################## - def groupCounts(self): - "Returns [groupname, gid, hasDue, hasNew]" - # find groups with 1 or more due cards - gids = {} - for g in self.col.groups.all(): - hasDue = self._groupHasLrn(g['id']) or self._groupHasRev(g['id']) - hasNew = self._groupHasNew(g['id']) - gids[g['id']] = [hasDue or 0, hasNew or 0] - return [[grp['name'], int(gid)]+gids[int(gid)] #.get(int(gid)) - for (gid, grp) in self.col.groups.groups.items()] + def deckCounts(self): + "Returns [deckname, did, hasDue, hasNew]" + # find decks with 1 or more due cards + dids = {} + for g in self.col.decks.all(): + hasDue = self._deckHasLrn(g['id']) or self._deckHasRev(g['id']) + hasNew = self._deckHasNew(g['id']) + dids[g['id']] = [hasDue or 0, hasNew or 0] + return [[grp['name'], int(did)]+dids[int(did)] #.get(int(did)) + for (did, grp) in self.col.decks.decks.items()] - def groupCountTree(self): - return self._groupChildren(self.groupCounts()) + def deckCountTree(self): + return self._groupChildren(self.deckCounts()) - def groupTree(self): + def deckTree(self): "Like the count tree without the counts. Faster." return self._groupChildren( - [[grp['name'], int(gid), 0, 0, 0] - for (gid, grp) in self.col.groups.groups.items()]) + [[grp['name'], int(did), 0, 0, 0] + for (did, grp) in self.col.decks.decks.items()]) def _groupChildren(self, grps): # first, split the group names into components @@ -156,14 +156,14 @@ order by due""" % self._groupLimit(), return grp[0][0] for (head, tail) in itertools.groupby(grps, key=key): tail = list(tail) - gid = None + did = None rev = 0 new = 0 children = [] for c in tail: if len(c[0]) == 1: # current node - gid = c[1] + did = c[1] rev += c[2] new += c[3] else: @@ -175,7 +175,7 @@ order by due""" % self._groupLimit(), for ch in children: rev += ch[2] new += ch[3] - tree.append((head, gid, rev, new, children)) + tree.append((head, did, rev, new, children)) return tuple(tree) # Getting the next card @@ -207,35 +207,35 @@ order by due""" % self._groupLimit(), def _resetNewCount(self): self.newCount = 0 pcounts = {} - # for each of the active groups - for gid in self.col.groups.active(): - # get the individual group's limit - lim = self._groupNewLimitSingle(self.col.groups.get(gid)) + # for each of the active decks + for did in self.col.decks.active(): + # get the individual deck's limit + lim = self._deckNewLimitSingle(self.col.decks.get(did)) if not lim: continue # check the parents - parents = self.col.groups.parents(gid) + parents = self.col.decks.parents(did) for p in parents: # add if missing if p['id'] not in pcounts: - pcounts[p['id']] = self._groupNewLimitSingle(p) + pcounts[p['id']] = self._deckNewLimitSingle(p) # take minimum of child and parent lim = min(pcounts[p['id']], lim) # see how many cards we actually have cnt = self.col.db.scalar(""" select count() from (select 1 from cards where -gid = ? and queue = 0 limit ?)""", gid, lim) +did = ? and queue = 0 limit ?)""", did, lim) # if non-zero, decrement from parent counts for p in parents: pcounts[p['id']] -= cnt # we may also be a parent - pcounts[gid] = lim - cnt + pcounts[did] = lim - cnt # and add to running total self.newCount += cnt def _resetNew(self): self._resetNewCount() - self.newGids = self.col.groups.active() + self.newDids = self.col.decks.active() self._newQueue = [] self._updateNewCardRatio() @@ -244,25 +244,25 @@ gid = ? and queue = 0 limit ?)""", gid, lim) return True if not self.newCount: return False - while self.newGids: - gid = self.newGids[0] - lim = min(self.queueLimit, self._groupNewLimit(gid)) + while self.newDids: + did = self.newDids[0] + lim = min(self.queueLimit, self._deckNewLimit(did)) if lim: - # fill the queue with the current gid + # fill the queue with the current did self._newQueue = self.col.db.all(""" -select id, due from cards where gid = ? and queue = 0 limit ?""", gid, lim) +select id, due from cards where did = ? and queue = 0 limit ?""", did, lim) if self._newQueue: self._newQueue.reverse() return True - # nothing left in the group; move to next - self.newGids.pop(0) + # nothing left in the deck; move to next + self.newDids.pop(0) def _getNewCard(self): if not self._fillNew(): return (id, due) = self._newQueue.pop() # move any siblings to the end? - conf = self.col.groups.conf(self.newGids[0]) + conf = self.col.decks.conf(self.newDids[0]) if conf['new']['order'] == NEW_TODAY_ORD: n = len(self._newQueue) while self._newQueue and self._newQueue[-1][1] == due: @@ -275,7 +275,7 @@ select id, due from cards where gid = ? and queue = 0 limit ?""", gid, lim) return id def _updateNewCardRatio(self): - if self.col.groups.top()['newSpread'] == NEW_CARDS_DISTRIBUTE: + if self.col.decks.top()['newSpread'] == NEW_CARDS_DISTRIBUTE: if self.newCount: self.newCardModulus = ( (self.newCount + self.revCount) / self.newCount) @@ -289,33 +289,33 @@ select id, due from cards where gid = ? and queue = 0 limit ?""", gid, lim) "True if it's time to display a new card when distributing." if not self.newCount: return False - if self.col.groups.top()['newSpread'] == NEW_CARDS_LAST: + if self.col.decks.top()['newSpread'] == NEW_CARDS_LAST: return False - elif self.col.groups.top()['newSpread'] == NEW_CARDS_FIRST: + elif self.col.decks.top()['newSpread'] == NEW_CARDS_FIRST: return True elif self.newCardModulus: return self.reps and self.reps % self.newCardModulus == 0 - def _groupHasNew(self, gid): - if not self._groupNewLimit(gid): + def _deckHasNew(self, did): + if not self._deckNewLimit(did): return False return self.col.db.scalar( - "select 1 from cards where gid = ? and queue = 0 limit 1", gid) + "select 1 from cards where did = ? and queue = 0 limit 1", did) - def _groupNewLimit(self, gid): - sel = self.col.groups.get(gid) + def _deckNewLimit(self, did): + sel = self.col.decks.get(did) lim = -1 - # for the group and each of its parents - for g in [sel] + self.col.groups.parents(gid): - rem = self._groupNewLimitSingle(g) + # for the deck and each of its parents + for g in [sel] + self.col.decks.parents(did): + rem = self._deckNewLimitSingle(g) if lim == -1: lim = rem else: lim = min(rem, lim) return lim - def _groupNewLimitSingle(self, g): - c = self.col.groups.conf(g['id']) + def _deckNewLimitSingle(self, g): + c = self.col.decks.conf(g['id']) return max(0, c['new']['perDay'] - g['newToday'][1]) # Learning queue @@ -324,8 +324,8 @@ select id, due from cards where gid = ? and queue = 0 limit ?""", gid, lim) def _resetLrnCount(self): (self.lrnCount, self.lrnRepCount) = self.col.db.first(""" select count(), sum(left) from (select left from cards where -gid in %s and queue = 1 and due < ? limit %d)""" % ( - self._groupLimit(), self.reportLimit), +did in %s and queue = 1 and due < ? limit %d)""" % ( + self._deckLimit(), self.reportLimit), self.dayCutoff) self.lrnRepCount = self.lrnRepCount or 0 @@ -340,9 +340,9 @@ gid in %s and queue = 1 and due < ? limit %d)""" % ( return True self._lrnQueue = self.col.db.all(""" select due, id from cards where -gid in %s and queue = 1 and due < :lim -limit %d""" % (self._groupLimit(), self.reportLimit), lim=self.dayCutoff) - # as it arrives sorted by gid first, we need to sort it +did in %s and queue = 1 and due < :lim +limit %d""" % (self._deckLimit(), self.reportLimit), lim=self.dayCutoff) + # as it arrives sorted by did first, we need to sort it self._lrnQueue.sort() return self._lrnQueue @@ -350,7 +350,7 @@ limit %d""" % (self._groupLimit(), self.reportLimit), lim=self.dayCutoff) if self._fillLrn(): cutoff = time.time() if collapse: - cutoff += self.col.groups.top()['collapseTime'] + cutoff += self.col.decks.top()['collapseTime'] if self._lrnQueue[0][0] < cutoff: id = heappop(self._lrnQueue)[1] self.lrnCount -= 1 @@ -459,29 +459,29 @@ where queue = 1 and type = 2 %s """ % (intTime(), self.col.usn(), extra)) - def _groupHasLrn(self, gid): + def _deckHasLrn(self, did): return self.col.db.scalar( - "select 1 from cards where gid = ? and queue = 1 " + "select 1 from cards where did = ? and queue = 1 " "and due < ? limit 1", - gid, intTime() + self.col.groups.top()['collapseTime']) + did, intTime() + self.col.decks.top()['collapseTime']) # Reviews ########################################################################## - def _groupHasRev(self, gid): + def _deckHasRev(self, did): return self.col.db.scalar( - "select 1 from cards where gid = ? and queue = 2 " + "select 1 from cards where did = ? and queue = 2 " "and due <= ? limit 1", - gid, self.today) + did, self.today) def _resetRevCount(self): - top = self.col.groups.top() + top = self.col.decks.top() lim = min(self.reportLimit, max(0, top['revLim'] - top['revToday'][1])) self.revCount = self.col.db.scalar(""" select count() from (select id from cards where -gid in %s and queue = 2 and due <= :day limit %d)""" % ( - self._groupLimit(), lim), day=self.today) +did in %s and queue = 2 and due <= :day limit %d)""" % ( + self._deckLimit(), lim), day=self.today) def _resetRev(self): self._resetRevCount() @@ -494,8 +494,8 @@ gid in %s and queue = 2 and due <= :day limit %d)""" % ( return True self._revQueue = self.col.db.list(""" select id from cards where -gid in %s and queue = 2 and due <= :lim %s limit %d""" % ( - self._groupLimit(), self._revOrder(), self.queueLimit), +did in %s and queue = 2 and due <= :lim %s limit %d""" % ( + self._deckLimit(), self._revOrder(), self.queueLimit), lim=self.today) if not self.col.conf['revOrder']: r = random.Random() @@ -653,10 +653,10 @@ gid in %s and queue = 2 and due <= :lim %s limit %d""" % ( ########################################################################## def _cardConf(self, card): - return self.col.groups.conf(card.gid) + return self.col.decks.conf(card.did) - def _groupLimit(self): - return ids2str(self.col.groups.active()) + def _deckLimit(self): + return ids2str(self.col.decks.active()) # Daily cutoff ########################################################################## @@ -666,7 +666,7 @@ gid in %s and queue = 2 and due <= :lim %s limit %d""" % ( self.today = int((time.time() - self.col.crt) / 86400) # end of day cutoff self.dayCutoff = self.col.crt + (self.today+1)*86400 - # update all selected groups + # update all selected decks def update(g): save = False for t in "new", "rev", "lrn", "time": @@ -675,11 +675,11 @@ gid in %s and queue = 2 and due <= :lim %s limit %d""" % ( save = True g[key] = [self.today, 0] if save: - self.col.groups.save(g) - for gid in self.col.groups.active(): - update(self.col.groups.get(gid)) + self.col.decks.save(g) + for did in self.col.decks.active(): + update(self.col.decks.get(did)) # update parents too - for grp in self.col.groups.parents(self.col.groups.selected()): + for grp in self.col.decks.parents(self.col.decks.selected()): update(grp) def _checkDay(self): @@ -713,15 +713,15 @@ your short-term review workload will become.""")) def revDue(self): "True if there are any rev cards due." return self.col.db.scalar( - ("select 1 from cards where gid in %s and queue = 2 " - "and due <= ? limit 1") % self._groupLimit(), + ("select 1 from cards where did in %s and queue = 2 " + "and due <= ? limit 1") % self._deckLimit(), self.today) def newDue(self): "True if there are any new cards due." return self.col.db.scalar( - ("select 1 from cards where gid in %s and queue = 0 " - "limit 1") % self._groupLimit()) + ("select 1 from cards where did in %s and queue = 0 " + "limit 1") % self._deckLimit()) # Next time reports ########################################################################## diff --git a/anki/stats.py b/anki/stats.py index 8440af733..459353cd8 100644 --- a/anki/stats.py +++ b/anki/stats.py @@ -49,8 +49,8 @@ class CardStats(object): self.addLine(_("Position"), c.due) self.addLine(_("Model"), c.model()['name']) self.addLine(_("Template"), c.template()['name']) - self.addLine(_("Current Group"), self.col.groups.name(c.gid)) - self.addLine(_("Home Group"), self.col.groups.name(c.note().gid)) + self.addLine(_("Current Deck"), self.col.decks.name(c.did)) + self.addLine(_("Original Deck"), self.col.decks.name(c.note().did)) self.txt += "" return self.txt @@ -178,7 +178,7 @@ select (due-:today)/:chunk as day, sum(case when ivl < 21 then 1 else 0 end), -- yng sum(case when ivl >= 21 then 1 else 0 end) -- mtr from cards -where gid in %s and queue = 2 +where did in %s and queue = 2 %s group by day order by day""" % (self._limit(), lim), today=self.col.sched.today, @@ -391,11 +391,11 @@ group by day order by day)""" % lim, chunk = 30; lim = "" data = [self.col.db.all(""" select ivl / :chunk as grp, count() from cards -where gid in %s and queue = 2 %s +where did in %s and queue = 2 %s group by grp order by grp""" % (self._limit(), lim), chunk=chunk)] return data + list(self.col.db.first(""" -select count(), avg(ivl), max(ivl) from cards where gid in %s and queue = 2""" % +select count(), avg(ivl), max(ivl) from cards where did in %s and queue = 2""" % self._limit())) # Eases @@ -539,7 +539,7 @@ group by hour having count() > 30 order by hour""" % lim, i = [] (c, f) = self.col.db.first(""" select count(id), count(distinct nid) from cards -where gid in %s """ % self._limit()) +where did in %s """ % self._limit()) self._line(i, _("Total cards"), c) self._line(i, _("Total notes"), f) (low, avg, high) = self._factors() @@ -548,7 +548,7 @@ where gid in %s """ % self._limit()) self._line(i, _("Average ease factor"), "%d%%" % avg) self._line(i, _("Highest ease factor"), "%d%%" % high) min = self.col.db.scalar( - "select min(id) from cards where gid in %s " % self._limit()) + "select min(id) from cards where did in %s " % self._limit()) if min: self._line(i, _("First card created"), _("%s ago") % fmtTimeSpan( time.time() - (min/1000))) @@ -579,7 +579,7 @@ select min(factor) / 10.0, avg(factor) / 10.0, max(factor) / 10.0 -from cards where gid in %s and queue = 2""" % self._limit()) +from cards where did in %s and queue = 2""" % self._limit()) def _cards(self): return self.col.db.first(""" @@ -588,7 +588,7 @@ sum(case when queue=2 and ivl >= 21 then 1 else 0 end), -- mtr sum(case when queue=1 or (queue=2 and ivl < 21) then 1 else 0 end), -- yng/lrn sum(case when queue=0 then 1 else 0 end), -- new sum(case when queue=-1 then 1 else 0 end) -- susp -from cards where gid in %s""" % self._limit()) +from cards where did in %s""" % self._limit()) # Tools ###################################################################### @@ -668,11 +668,11 @@ $(function () { data=simplejson.dumps(data), conf=simplejson.dumps(conf))) def _limit(self): - return self.col.sched._groupLimit() + return self.col.sched._deckLimit() def _revlogLimit(self): - return ("cid in (select id from cards where gid in %s)" % - ids2str(self.col.groups.active())) + return ("cid in (select id from cards where did in %s)" % + ids2str(self.col.decks.active())) def _title(self, title, subtitle=""): return '