merge deck.qconf and deck.conf

This commit is contained in:
Damien Elmes 2011-08-28 14:17:33 +09:00
parent a30836445e
commit 6a00419ebc
8 changed files with 47 additions and 57 deletions

View file

@ -18,9 +18,8 @@ from anki.errors import AnkiError
import anki.latex # sets up hook
import anki.cards, anki.facts, anki.template, anki.cram, anki.find
# Settings related to queue building. These may be loaded without the rest of
# the config to check due counts faster on mobile clients.
defaultQconf = {
defaultConf = {
# scheduling options
'groups': [],
'newPerDay': 20,
'newToday': [0, 0], # currentDay, count
@ -31,10 +30,7 @@ defaultQconf = {
'collapseTime': 1200,
'repLim': 0,
'timeLim': 600,
}
# other options
defaultConf = {
# other config
'nextPos': 1,
'mediaURL': "",
'fontFamilies': [
@ -86,15 +82,13 @@ class _Deck(object):
self.dty,
self.syncName,
self.lastSync,
self.qconf,
self.conf,
models,
groups,
gconf,
tags) = self.db.first("""
select crt, mod, scm, dty, syncName, lastSync,
qconf, conf, models, groups, gconf, tags from deck""")
self.qconf = simplejson.loads(self.qconf)
conf, models, groups, gconf, tags from deck""")
self.conf = simplejson.loads(self.conf)
self.models.load(models)
self.groups.load(groups, gconf)
@ -105,11 +99,9 @@ qconf, conf, models, groups, gconf, tags from deck""")
self.mod = intTime() if mod is None else mod
self.db.execute(
"""update deck set
crt=?, mod=?, scm=?, dty=?, syncName=?, lastSync=?,
qconf=?, conf=?""",
crt=?, mod=?, scm=?, dty=?, syncName=?, lastSync=?, conf=?""",
self.crt, self.mod, self.scm, self.dty,
self.syncName, self.lastSync,
simplejson.dumps(self.qconf),
simplejson.dumps(self.conf))
self.models.flush()
self.groups.flush()
@ -165,9 +157,11 @@ qconf=?, conf=?""",
return not self.syncingEnabled() or self.scm > self.lastSync
def setDirty(self):
"Signal there are temp. suspended cards that need cleaning up on close."
self.dty = True
def cleanup(self):
"Unsuspend any temporarily suspended cards."
if self.dty:
self.sched.onClose()
self.dty = False
@ -338,7 +332,7 @@ qconf=?, conf=?""",
return card
def randomNew(self):
return self.qconf['newOrder'] == NEW_CARDS_RANDOM
return self.conf['newOrder'] == NEW_CARDS_RANDOM
# Cards
##########################################################################

View file

@ -49,7 +49,7 @@ class Scheduler(object):
# put it in the learn queue
card.queue = 1
card.type = 1
self.deck.qconf['newToday'][1] += 1
self.deck.conf['newToday'][1] += 1
if card.queue == 1:
self._answerLrnCard(card, ease)
elif card.queue == 2:
@ -125,11 +125,11 @@ order by time desc limit 10)""")
def allCounts(self):
"Return counts for all groups, without building queue."
conf = self.deck.qconf['groups']
conf = self.deck.conf['groups']
if conf:
self.deck.qconf['groups'] = []
self.deck.conf['groups'] = []
self._resetCounts()
self.deck.qconf['groups'] = conf
self.deck.conf['groups'] = conf
return self.counts()
def _resetCounts(self):
@ -232,7 +232,7 @@ from cards group by gid""", self.today):
# FIXME: need to keep track of reps for timebox and new card introduction
def _resetNewCount(self):
l = self.deck.qconf
l = self.deck.conf
if l['newToday'][0] != self.today:
# it's a new day; reset counts
l['newToday'] = [self.today, 0]
@ -261,7 +261,7 @@ queue = 0 %s order by due limit %d""" % (self._groupLimit(),
if self.newQueue:
(id, due) = self.newQueue.pop()
# move any siblings to the end?
if self.deck.qconf['newTodayOrder'] == NEW_TODAY_ORD:
if self.deck.conf['newTodayOrder'] == NEW_TODAY_ORD:
n = len(self.newQueue)
while self.newQueue and self.newQueue[-1][1] == due:
self.newQueue.insert(0, self.newQueue.pop())
@ -273,7 +273,7 @@ queue = 0 %s order by due limit %d""" % (self._groupLimit(),
return id
def _updateNewCardRatio(self):
if self.deck.qconf['newSpread'] == NEW_CARDS_DISTRIBUTE:
if self.deck.conf['newSpread'] == NEW_CARDS_DISTRIBUTE:
if self.newCount:
self.newCardModulus = (
(self.newCount + self.revCount) / self.newCount)
@ -287,9 +287,9 @@ queue = 0 %s order by due limit %d""" % (self._groupLimit(),
"True if it's time to display a new card when distributing."
if not self.newCount:
return False
if self.deck.qconf['newSpread'] == NEW_CARDS_LAST:
if self.deck.conf['newSpread'] == NEW_CARDS_LAST:
return False
elif self.deck.qconf['newSpread'] == NEW_CARDS_FIRST:
elif self.deck.conf['newSpread'] == NEW_CARDS_FIRST:
return True
elif self.newCardModulus:
return self.reps and self.reps % self.newCardModulus == 0
@ -302,7 +302,7 @@ queue = 0 %s order by due limit %d""" % (self._groupLimit(),
select count() from (select id from cards where
queue = 1 %s and due < ? limit %d)""" % (
self._groupLimit(), self.reportLimit),
intTime() + self.deck.qconf['collapseTime'])
intTime() + self.deck.conf['collapseTime'])
def _resetLrn(self):
self.lrnQueue = self.deck.db.all("""
@ -314,7 +314,7 @@ limit %d""" % (self._groupLimit(), self.reportLimit), lim=self.dayCutoff)
if self.lrnQueue:
cutoff = time.time()
if collapse:
cutoff += self.deck.qconf['collapseTime']
cutoff += self.deck.conf['collapseTime']
if self.lrnQueue[0][0] < cutoff:
id = heappop(self.lrnQueue)[1]
self.lrnCount -= 1
@ -347,7 +347,7 @@ limit %d""" % (self._groupLimit(), self.reportLimit), lim=self.dayCutoff)
card.due = int(time.time() + delay)
heappush(self.lrnQueue, (card.due, card.id))
# if it's due within the cutoff, increment count
if delay <= self.deck.qconf['collapseTime']:
if delay <= self.deck.conf['collapseTime']:
self.lrnCount += 1
self._logLrn(card, ease, conf, leaving, type)
@ -440,7 +440,7 @@ select id from cards where
queue = 2 %s and due <= :lim order by %s limit %d""" % (
self._groupLimit(), self._revOrder(), self.queueLimit),
lim=self.today)
if self.deck.qconf['revOrder'] == REV_CARDS_RANDOM:
if self.deck.conf['revOrder'] == REV_CARDS_RANDOM:
r = random.Random()
r.seed(self.today)
r.shuffle(self.revQueue)
@ -461,7 +461,7 @@ queue = 2 %s and due <= :lim order by %s limit %d""" % (
def _revOrder(self):
return ("ivl desc",
"ivl",
"due")[self.deck.qconf['revOrder']]
"due")[self.deck.conf['revOrder']]
# Answering a review card
##########################################################################
@ -598,7 +598,7 @@ queue = 2 %s and due <= :lim order by %s limit %d""" % (
return self.deck.groups.conf(card.gid)
def _groupLimit(self):
l = self.deck.qconf['groups']
l = self.deck.conf['groups']
if not l:
# everything
return ""
@ -630,7 +630,7 @@ queue = 2 %s and due <= :lim order by %s limit %d""" % (
self._nextDueMsg())
def _finishedSubtitle(self):
if self.deck.qconf['groups']:
if self.deck.conf['groups']:
return _("You have finished the selected groups for now.")
else:
return _("You have finished the deck for now.")
@ -670,7 +670,7 @@ queue = 2 %s and due <= :lim order by %s limit %d""" % (
def newTomorrow(self):
"Number of new cards tomorrow."
lim = self.deck.qconf['newPerDay']
lim = self.deck.conf['newPerDay']
return self.deck.db.scalar(
"select count() from (select id from cards where "
"queue = 0 %s limit %d)" % (self._groupLimit(), lim))
@ -760,7 +760,7 @@ queue = 2 %s and due <= :lim order by %s limit %d""" % (
def updateDynamicIndices(self):
# determine required columns
required = []
if self.deck.qconf['revOrder'] in (
if self.deck.conf['revOrder'] in (
REV_CARDS_OLD_FIRST, REV_CARDS_NEW_FIRST):
required.append("interval")
cols = ["queue", "due", "gid"] + required

View file

@ -675,7 +675,7 @@ $(function () {
return ""
def _revlogLimit(self):
lim = self.deck.qconf['groups']
lim = self.deck.conf['groups']
if self.selective and lim:
return ("cid in (select id from cards where gid in %s)" %
ids2str(lim))

View file

@ -65,7 +65,6 @@ create table if not exists deck (
dty integer not null,
syncName text not null,
lastSync integer not null,
qconf text not null,
conf text not null,
models text not null,
groups text not null,
@ -127,14 +126,13 @@ create table if not exists revlog (
);
insert or ignore into deck
values(1,0,0,0,%(v)s,0,'',0,'','','{}','','','{}');
values(1,0,0,0,%(v)s,0,'',0,'','{}','','','{}');
""" % ({'v':CURRENT_VERSION}))
import anki.deck
import anki.groups
if setDeckConf:
db.execute("""
update deck set qconf = ?, conf = ?, groups = ?, gconf = ?""",
simplejson.dumps(anki.deck.defaultQconf),
update deck set conf = ?, groups = ?, gconf = ?""",
simplejson.dumps(anki.deck.defaultConf),
simplejson.dumps({'1': {'name': _("Default"), 'conf': 1,
'mod': intTime()}}),
@ -339,30 +337,29 @@ def _migrateDeckTbl(db):
db.execute("""
insert or replace into deck select id, cast(created as int), :t,
:t, 99, 0, ifnull(syncName, ""), cast(lastSync as int),
"", "", "", "", "", "" from decks""", t=intTime())
"", "", "", "", "" from decks""", t=intTime())
# update selective study
qconf = anki.deck.defaultQconf.copy()
conf = anki.deck.defaultConf.copy()
# delete old selective study settings, which we can't auto-upgrade easily
keys = ("newActive", "newInactive", "revActive", "revInactive")
for k in keys:
db.execute("delete from deckVars where key=:k", k=k)
# copy other settings, ignoring deck order as there's a new default
qconf['newSpread'] = db.scalar(
conf['newSpread'] = db.scalar(
"select newCardSpacing from decks")
qconf['newOrder'] = db.scalar(
conf['newOrder'] = db.scalar(
"select newCardOrder from decks")
qconf['newPerDay'] = db.scalar(
conf['newPerDay'] = db.scalar(
"select newCardsPerDay from decks")
# fetch remaining settings from decks table
conf = anki.deck.defaultConf.copy()
data = {}
keys = ("sessionRepLimit", "sessionTimeLimit")
for k in keys:
conf[k] = db.scalar("select %s from decks" % k)
# random and due options merged
qconf['revOrder'] = 2
conf['revOrder'] = 2
# no reverse option anymore
qconf['newOrder'] = min(1, qconf['newOrder'])
conf['newOrder'] = min(1, conf['newOrder'])
# add any deck vars and save
dkeys = ("hexCache", "cssCache")
for (k, v) in db.execute("select * from deckVars").fetchall():
@ -371,8 +368,7 @@ insert or replace into deck select id, cast(created as int), :t,
else:
conf[k] = v
import anki.groups
db.execute("update deck set qconf = :l,conf = :c,groups=:g,gconf=:gc",
l=simplejson.dumps(qconf),
db.execute("update deck set conf=:c,groups=:g,gconf=:gc",
c=simplejson.dumps(conf),
g=simplejson.dumps({'1': {'name': _("Default"), 'conf': 1}}),
gc=simplejson.dumps({'1': anki.groups.defaultConf}))

View file

@ -18,7 +18,7 @@ def test_genCards():
assert deck.cardCount() == 2
assert cards[0].due == f.id
# should work on random mode too
deck.qconf['newOrder'] = NEW_CARDS_RANDOM
deck.conf['newOrder'] = NEW_CARDS_RANDOM
f = deck.newFact()
f['Front'] = u'1'
f['Back'] = u'2'

View file

@ -143,7 +143,7 @@ def test_groups():
# should get the same id
assert deck.groups.id("new group") == g
# by default, everything should be shown
assert not deck.qconf['groups']
assert not deck.conf['groups']
def test_selective():
deck = getEmptyDeck()

View file

@ -65,7 +65,7 @@ def test_newOrder():
d.addFact(f)
# generate second half
d.db.execute("update cards set gid = random()")
d.qconf['newPerDay'] = 100
d.conf['newPerDay'] = 100
d.reset()
# cards should be sorted by id
assert d.sched.newQueue == list(reversed(sorted(d.sched.newQueue)))
@ -387,7 +387,7 @@ def test_cram():
c.startTimer()
c.flush()
cardcopy = copy.copy(c)
d.qconf['groups'] = [1]
d.conf['groups'] = [1]
d.cramGroups()
# first, test with initial intervals preserved
conf = d.sched._lrnConf(c)
@ -449,7 +449,7 @@ def test_cram():
assert c.ivl == 1
assert c.due == d.sched.today + 1
# users should be able to cram entire deck too
d.qconf['groups'] = []
d.conf['groups'] = []
d.cramGroups()
assert d.sched.counts()[0] > 0
@ -465,7 +465,7 @@ def test_cramLimits():
c.due = d.sched.today + 1 + i
c.flush()
# the default cram should return all three
d.qconf['groups'] = [1]
d.conf['groups'] = [1]
d.cramGroups()
assert d.sched.counts()[0] == 3
# if we start from the day after tomorrow, it should be 2
@ -601,7 +601,7 @@ def test_counts():
# with the default settings, there's no count limit
assert d.sched.counts() == (2,2,2)
# check limit to one group
d.qconf['groups'] = [1]
d.conf['groups'] = [1]
d.reset()
assert d.sched.counts() == (1,1,1)
# we don't need to build the queue to get the counts

View file

@ -7,9 +7,9 @@ def test_op():
# should have no undo by default
assert not d.undoName()
# let's adjust a study option
assert d.qconf['repLim'] == 0
assert d.conf['repLim'] == 0
d.save("studyopts")
d.qconf['repLim'] = 10
d.conf['repLim'] = 10
# it should be listed as undoable
assert d.undoName() == "studyopts"
# with about 5 minutes until it's clobbered
@ -17,7 +17,7 @@ def test_op():
# undoing should restore the old value
d.undo()
assert not d.undoName()
assert d.qconf['repLim'] == 0
assert d.conf['repLim'] == 0
# an (auto)save will clear the undo
d.save("foo")
assert d.undoName() == "foo"