mirror of
https://github.com/ankitects/anki.git
synced 2025-11-12 07:37:11 -05:00
start on filter/cram updates, deck:filtered
- cram decks no longer pull cards from other cram decks, as tests like is:due don't make sense on crammed decks - cram decks now default to not overriding the original deck's steps - remove obsolote dyn_failed sort order - have to fix this in upgrade - search/limit/order properties have been merged into a list, in case we may want to support multiple queries in the future (eg 10 cards from tag A, 20 cards from tag B) - added a resched option to disable boosting/failure - not yet implemented - added an unused flag to allow cards to persist in the cram deck after graduation. implementing this will take some work and won't come in 2.0 - instead of is:filtereddeck, use deck:filtered
This commit is contained in:
parent
44b4f18e6c
commit
d6bce7c873
6 changed files with 59 additions and 47 deletions
|
|
@ -33,9 +33,8 @@ DYN_RANDOM = 1
|
|||
DYN_SMALLINT = 2
|
||||
DYN_BIGINT = 3
|
||||
DYN_LAPSES = 4
|
||||
DYN_FAILED = 5
|
||||
DYN_ADDED = 6
|
||||
DYN_DUE = 7
|
||||
DYN_ADDED = 5
|
||||
DYN_DUE = 6
|
||||
|
||||
# model types
|
||||
MODEL_STD = 0
|
||||
|
|
@ -77,7 +76,6 @@ def dynOrderLabels():
|
|||
2: _("Increasing intervals"),
|
||||
3: _("Decreasing intervals"),
|
||||
4: _("Most lapses"),
|
||||
5: _("Failed today"),
|
||||
6: _("Order added"),
|
||||
7: _("Order due"),
|
||||
5: _("Order added"),
|
||||
6: _("Order due"),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,13 +35,13 @@ defaultDynamicDeck = {
|
|||
'dyn': 1,
|
||||
'desc': "",
|
||||
'usn': 0,
|
||||
'delays': [1, 10],
|
||||
'delays': None,
|
||||
'separate': True,
|
||||
'search': "",
|
||||
'limit': 100,
|
||||
'order': 0,
|
||||
# added in beta13
|
||||
'resched': True,
|
||||
# list of (search, limit, order); we only use first element for now
|
||||
'terms': [["", 100, 0]],
|
||||
'return': True, # currently unused
|
||||
}
|
||||
|
||||
defaultConf = {
|
||||
|
|
@ -142,7 +142,7 @@ class DeckManager(object):
|
|||
if deck['dyn']:
|
||||
# deleting a cramming deck returns cards to their previous deck
|
||||
# rather than deleting the cards
|
||||
self.col.sched.remDyn(did)
|
||||
self.col.sched.emptyDyn(did)
|
||||
if childrenToo:
|
||||
for name, id in self.children(did):
|
||||
self.rem(id, cardsToo)
|
||||
|
|
|
|||
|
|
@ -236,10 +236,6 @@ class Finder(object):
|
|||
return "type = %d" % n
|
||||
elif val == "suspended":
|
||||
return "c.queue = -1"
|
||||
elif val == "regulardeck":
|
||||
return "not c.odid"
|
||||
elif val == "filterdeck":
|
||||
return "c.odid"
|
||||
elif val == "due":
|
||||
return """
|
||||
(c.queue in (2,3) and c.due <= %d) or
|
||||
|
|
@ -312,6 +308,9 @@ class Finder(object):
|
|||
# if searching for all decks, skip
|
||||
if val == "*":
|
||||
return "skip"
|
||||
# deck types
|
||||
elif val == "filtered":
|
||||
return "c.odid"
|
||||
def dids(did):
|
||||
if not did:
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ order by due""" % self._deckLimit(),
|
|||
return card.queue
|
||||
|
||||
def answerButtons(self, card):
|
||||
if not card.odid and card.odue:
|
||||
if card.odue:
|
||||
conf = self._lapseConf(card)
|
||||
if len(conf['delays']) > 1:
|
||||
return 3
|
||||
|
|
@ -849,22 +849,29 @@ did = ? and queue = 2 and due <= ? limit ?""",
|
|||
did = did or self.col.decks.selected()
|
||||
deck = self.col.decks.get(did)
|
||||
assert deck['dyn']
|
||||
# move any existing cards back first
|
||||
self.remDyn(did)
|
||||
# gather card ids and sort
|
||||
order = self._dynOrder(deck)
|
||||
limit = " limit %d" % deck['limit']
|
||||
search = deck['search'] + " -is:suspended is:regulardeck"
|
||||
try:
|
||||
ids = self.col.findCards(search, order=order+limit)
|
||||
except:
|
||||
ids = []
|
||||
# move the cards over
|
||||
self._moveToDyn(did, ids)
|
||||
# move any existing cards back first, then fill
|
||||
self.emptyDyn(did)
|
||||
ids = self._fillDyn(deck)
|
||||
if not ids:
|
||||
return
|
||||
# and change to our new deck
|
||||
self.col.decks.select(did)
|
||||
return ids
|
||||
|
||||
def remDyn(self, did, lim=None):
|
||||
def _fillDyn(self, deck):
|
||||
search, limit, order = deck['terms'][0]
|
||||
orderlimit = self._dynOrder(order, limit)
|
||||
search += " -is:suspended -deck:filtered"
|
||||
try:
|
||||
ids = self.col.findCards(search, order=orderlimit)
|
||||
except:
|
||||
ids = []
|
||||
return ids
|
||||
# move the cards over
|
||||
self._moveToDyn(deck['id'], ids)
|
||||
return ids
|
||||
|
||||
def emptyDyn(self, did, lim=None):
|
||||
if not lim:
|
||||
lim = "did = %s" % did
|
||||
# move out of cram queue
|
||||
|
|
@ -875,28 +882,26 @@ due = odue, odue = 0, odid = 0, usn = ?, mod = ? where %s""" % lim,
|
|||
self.col.usn(), intTime())
|
||||
|
||||
def remFromDyn(self, cids):
|
||||
self.remDyn(None, "id in %s and odid" % ids2str(cids))
|
||||
self.emptyDyn(None, "id in %s and odid" % ids2str(cids))
|
||||
|
||||
def _dynOrder(self, deck):
|
||||
o = deck['order']
|
||||
def _dynOrder(self, o, l):
|
||||
if o == DYN_OLDEST:
|
||||
return "c.mod"
|
||||
t = "c.mod"
|
||||
elif o == DYN_RANDOM:
|
||||
return "random()"
|
||||
t = "random()"
|
||||
elif o == DYN_SMALLINT:
|
||||
return "ivl"
|
||||
t = "ivl"
|
||||
elif o == DYN_BIGINT:
|
||||
return "ivl desc"
|
||||
t = "ivl desc"
|
||||
elif o == DYN_LAPSES:
|
||||
return "lapses desc"
|
||||
# elif o == DYN_FAILED:
|
||||
# return """
|
||||
# and c.id in (select cid from revlog where ease = 1 and time > %d)
|
||||
# order by c.mod""" % ((self.dayCutoff-86400)*1000)
|
||||
t = "lapses desc"
|
||||
elif o == DYN_ADDED:
|
||||
return "n.id"
|
||||
t = "n.id"
|
||||
elif o == DYN_DUE:
|
||||
return "c.due"
|
||||
t = "c.due"
|
||||
else:
|
||||
raise Exception()
|
||||
return t + " limit %d" % l
|
||||
|
||||
def _moveToDyn(self, did, ids):
|
||||
deck = self.col.decks.get(did)
|
||||
|
|
@ -966,12 +971,13 @@ did = ?, queue = %s, due = ?, mod = ?, usn = ? where id = ?""" % queue, data)
|
|||
return conf['new']
|
||||
# dynamic deck; override some attributes, use original deck for others
|
||||
oconf = self.col.decks.confForDid(card.odid)
|
||||
delays = conf['delays'] or oconf['new']['delays']
|
||||
return dict(
|
||||
# original deck
|
||||
ints=oconf['new']['ints'],
|
||||
initialFactor=oconf['new']['initialFactor'],
|
||||
# overrides
|
||||
delays=conf['delays'],
|
||||
delays=delays,
|
||||
separate=conf['separate'],
|
||||
order=NEW_CARDS_DUE,
|
||||
perDay=self.reportLimit
|
||||
|
|
@ -984,6 +990,7 @@ did = ?, queue = %s, due = ?, mod = ?, usn = ? where id = ?""" % queue, data)
|
|||
return conf['lapse']
|
||||
# dynamic deck; override some attributes, use original deck for others
|
||||
oconf = self.col.decks.confForDid(card.odid)
|
||||
delays = conf['delays'] or oconf['lapse']['delays']
|
||||
return dict(
|
||||
# original deck
|
||||
minInt=oconf['lapse']['minInt'],
|
||||
|
|
@ -991,7 +998,7 @@ did = ?, queue = %s, due = ?, mod = ?, usn = ? where id = ?""" % queue, data)
|
|||
leechAction=oconf['lapse']['leechAction'],
|
||||
mult=oconf['lapse']['mult'],
|
||||
# overrides
|
||||
delays=conf['delays'],
|
||||
delays=delays,
|
||||
resched=conf['resched'],
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -527,6 +527,12 @@ def test_cram():
|
|||
assert d.sched.counts() == (1,0,0)
|
||||
# grab it and check estimates
|
||||
c = d.sched.getCard()
|
||||
assert d.sched.answerButtons(c) == 2
|
||||
assert d.sched.nextIvl(c, 1) == 600
|
||||
assert d.sched.nextIvl(c, 2) == 138*60*60*24
|
||||
cram = d.decks.get(did)
|
||||
cram['delays'] = [1, 10]
|
||||
assert d.sched.answerButtons(c) == 3
|
||||
assert d.sched.nextIvl(c, 1) == 60
|
||||
assert d.sched.nextIvl(c, 2) == 600
|
||||
assert d.sched.nextIvl(c, 3) == 138*60*60*24
|
||||
|
|
@ -618,7 +624,7 @@ def test_cram_rem():
|
|||
assert c.type == c.queue == 1
|
||||
assert c.due != oldDue
|
||||
# if we terminate cramming prematurely it should be set back to new
|
||||
d.sched.remDyn(did)
|
||||
d.sched.emptyDyn(did)
|
||||
c.load()
|
||||
assert c.type == c.queue == 0
|
||||
assert c.due == oldDue
|
||||
|
|
|
|||
4
thirdparty/README
vendored
4
thirdparty/README
vendored
|
|
@ -1 +1,3 @@
|
|||
The files in this folder are covered by their respective licenses.
|
||||
The files in this folder are covered by their respective licenses and are
|
||||
provided to minimize external dependencies. The _portaudio.so files were
|
||||
extracted from Ubuntu 32bit and 64 distributions - check md5s to confirm.
|
||||
|
|
|
|||
Loading…
Reference in a new issue