diff --git a/anki/deck.py b/anki/deck.py index 057d52d3b..dd98bd822 100644 --- a/anki/deck.py +++ b/anki/deck.py @@ -29,26 +29,23 @@ import anki.latex # sets up hook # ensure all the DB metadata in other files is loaded before proceeding import anki.models, anki.facts, anki.cards, anki.media, anki.groups, anki.graves -# Selective study and new card limits. These vars are necessary to determine -# counts even on a minimum deck load, and thus are separate from the rest of -# the config. -defaultLim = { +# Settings related to queue building. These may be loaded without the rest of +# the config to check due counts faster on mobile clients. +defaultQconf = { 'newActive': u"", 'newInactive': u"", 'revActive': u"", 'revInactive': u"", 'newPerDay': 20, - # currentDay, count - 'newToday': [0, 0], + 'newToday': [0, 0], # currentDay, count 'newTodayOrder': NEW_TODAY_ORDINAL, + 'newCardOrder': 1, + 'newCardSpacing': NEW_CARDS_DISTRIBUTE, + 'revCardOrder': REV_CARDS_OLD_FIRST, } # scheduling and other options defaultConf = { - 'utcOffset': -2, - 'newCardOrder': 1, - 'newCardSpacing': NEW_CARDS_DISTRIBUTE, - 'revCardOrder': REV_CARDS_OLD_FIRST, 'collapseTime': 600, 'sessionRepLimit': 0, 'sessionTimeLimit': 600, @@ -78,8 +75,8 @@ deckTable = Table( Column('syncName', UnicodeText, nullable=False, default=u""), Column('lastSync', Integer, nullable=False, default=0), Column('utcOffset', Integer, nullable=False, default=-2), - Column('limits', UnicodeText, nullable=False, default=unicode( - simplejson.dumps(defaultLim))), + Column('qconf', UnicodeText, nullable=False, default=unicode( + simplejson.dumps(defaultQconf))), Column('config', UnicodeText, nullable=False, default=unicode( simplejson.dumps(defaultConf))), Column('data', UnicodeText, nullable=False, default=u"{}") @@ -144,7 +141,7 @@ interval=0, due=created, factor=2.5, reps=0, successive=0, lapses=0, flags=0""" sql2 += " where cardId in "+sids self.db.statement(sql, now=time.time()) self.db.statement(sql2) - if self.config['newCardOrder'] == NEW_CARDS_RANDOM: + if self.qconf['newCardOrder'] == NEW_CARDS_RANDOM: # we need to re-randomize now self.randomizeNewCards(ids) self.flushMod() @@ -435,7 +432,7 @@ due > :now and due < :now""", now=time.time()) self.db.save(fact) # update field cache self.flushMod() - isRandom = self.config['newCardOrder'] == NEW_CARDS_RANDOM + isRandom = self.qconf['newCardOrder'] == NEW_CARDS_RANDOM if isRandom: due = random.uniform(0, time.time()) t = time.time() @@ -2148,7 +2145,7 @@ Return new path, relative to media dir.""" def flushConfig(self): print "make flushConfig() more intelligent" self._config = unicode(simplejson.dumps(self.config)) - self._limits = unicode(simplejson.dumps(self.limits)) + self._qconf = unicode(simplejson.dumps(self.qconf)) self._data = unicode(simplejson.dumps(self.data)) def close(self): @@ -2634,9 +2631,9 @@ seq > :s and seq <= :e order by seq desc""", s=start, e=end) def updateDynamicIndices(self): # determine required columns required = [] - if self.limits['newTodayOrder'] == NEW_TODAY_ORDINAL: + if self.qconf['newTodayOrder'] == NEW_TODAY_ORDINAL: required.append("ordinal") - if self.config['revCardOrder'] in (REV_CARDS_OLD_FIRST, REV_CARDS_NEW_FIRST): + if self.qconf['revCardOrder'] in (REV_CARDS_OLD_FIRST, REV_CARDS_NEW_FIRST): required.append("interval") cols = ["queue", "due", "groupId"] + required # update if changed @@ -2652,7 +2649,7 @@ seq > :s and seq <= :e order by seq desc""", s=start, e=end) self.db.statement("analyze") mapper(Deck, deckTable, properties={ - '_limits': deckTable.c.limits, + '_qconf': deckTable.c.qconf, '_config': deckTable.c.config, '_data': deckTable.c.data, }) @@ -2831,7 +2828,7 @@ confId integer not null)""" create = not os.path.exists(path) deck = DeckStorage._getDeck(path, create, pool) oldMod = deck.modified - deck.limits = simplejson.loads(deck._limits) + deck.qconf = simplejson.loads(deck._qconf) deck.config = simplejson.loads(deck._config) deck.data = simplejson.loads(deck._data) if minimal: diff --git a/anki/sched.py b/anki/sched.py index 613dac131..880ea5785 100644 --- a/anki/sched.py +++ b/anki/sched.py @@ -92,7 +92,7 @@ class Scheduler(object): # need to keep track of reps for timebox and new card introduction def resetNew(self): - l = self.deck.limits + l = self.deck.qconf if l['newToday'][0] != self.today: # it's a new day; reset counts l['newToday'] = [self.today, 0] @@ -114,10 +114,10 @@ queue = 2 %s order by due limit %d""" % (self.newOrder(), self.groupLimit('new') return self.newQueue.pop()[0] def newOrder(self): - return (",ordinal", "")[self.deck.limits['newTodayOrder']] + return (",ordinal", "")[self.deck.qconf['newTodayOrder']] def updateNewCardRatio(self): - if self.deck.config['newCardSpacing'] == NEW_CARDS_DISTRIBUTE: + if self.deck.qconf['newCardSpacing'] == NEW_CARDS_DISTRIBUTE: if self.newCount: self.newCardModulus = ( (self.newCount + self.revCount) / self.newCount) @@ -131,9 +131,9 @@ queue = 2 %s order by due limit %d""" % (self.newOrder(), self.groupLimit('new') "True if it's time to display a new card when distributing." if not self.newCount: return False - if self.deck.config['newCardSpacing'] == NEW_CARDS_LAST: + if self.deck.qconf['newCardSpacing'] == NEW_CARDS_LAST: return False - elif self.deck.config['newCardSpacing'] == NEW_CARDS_FIRST: + elif self.deck.qconf['newCardSpacing'] == NEW_CARDS_FIRST: return True elif self.newCardModulus: return self.deck.reps and self.deck.reps % self.newCardModulus == 0 @@ -227,13 +227,10 @@ queue = 1 %s and due < :lim order by %s limit %d""" % ( self.fillRevQueue() return self.revQueue - # FIXME: current random order won't work with new spacing - # FIXME: limits for new, config for rev is strange atm def revOrder(self): return ("interval desc", "interval", - "due", - "factId, ordinal")[self.deck.config['revCardOrder']] + "due")[self.deck.qconf['revCardOrder']] # FIXME: rewrite def showFailedLast(self): @@ -485,8 +482,8 @@ and queue between 1 and 2""", return "" def cardLimit(self, active, inactive, sql): - yes = parseTags(self.deck.limits.get(active)) - no = parseTags(self.deck.limits.get(inactive)) + yes = parseTags(self.deck.qconf.get(active)) + no = parseTags(self.deck.qconf.get(inactive)) if yes: yids = tagIds(self.db, yes).values() nids = tagIds(self.db, no).values() diff --git a/anki/upgrade.py b/anki/upgrade.py index 6bbafcd76..a5997a0f6 100644 --- a/anki/upgrade.py +++ b/anki/upgrade.py @@ -90,13 +90,12 @@ def migrateDeck(s, engine): insert into deck select id, created, modified, 0, 99, ifnull(syncName, ""), lastSync, utcOffset, "", "", "" from decks""") # update selective study - lim = deck.defaultLim.copy() + qconf = deck.defaultQconf.copy() + # delete old selective study settings, which we can't auto-upgrade easily keys = ("newActive", "newInactive", "revActive", "revInactive") for k in keys: - lim[k] = s.execute("select value from deckVars where key=:k", - {'k':k}).scalar() s.execute("delete from deckVars where key=:k", {'k':k}) - lim['newPerDay'] = s.execute( + qconf['newPerDay'] = s.execute( "select newCardsPerDay from decks").scalar() # fetch remaining settings from decks table conf = deck.defaultConf.copy() @@ -116,8 +115,8 @@ ifnull(syncName, ""), lastSync, utcOffset, "", "", "" from decks""") data[k] = v else: conf[k] = v - s.execute("update deck set limits = :l, config = :c, data = :d", - {'l':simplejson.dumps(lim), + s.execute("update deck set qconf = :l, config = :c, data = :d", + {'l':simplejson.dumps(qconf), 'c':simplejson.dumps(conf), 'd':simplejson.dumps(data)}) # clean up @@ -205,8 +204,8 @@ cast(min(thinkingTime, 60)*1000 as int), 0 from reviewHistory""") deck.db.statement("drop table if exists %sDeleted" % t) # finally, update indices & optimize updateIndices(deck.db) - # setup limits & config for dynamicIndices() - deck.limits = simplejson.loads(deck._limits) + # setup qconf & config for dynamicIndices() + deck.qconf = simplejson.loads(deck._qconf) deck.config = simplejson.loads(deck._config) # add default config import deck as deckMod