support matches on card properties

This commit is contained in:
Damien Elmes 2012-05-23 14:18:01 +09:00
parent a76d34dc19
commit 3755a8f82d
2 changed files with 66 additions and 1 deletions

View file

@ -14,6 +14,7 @@ SEARCH_TEMPLATE = 4
SEARCH_FIELD = 5 SEARCH_FIELD = 5
SEARCH_MODEL = 6 SEARCH_MODEL = 6
SEARCH_DECK = 7 SEARCH_DECK = 7
SEARCH_PROP = 8
# Tools # Tools
########################################################################## ##########################################################################
@ -119,6 +120,8 @@ and c.nid=n.id %s""" % (q, order)
self._findModel(token, isNeg) self._findModel(token, isNeg)
elif type == SEARCH_DECK: elif type == SEARCH_DECK:
self._findDeck(token, isNeg) self._findDeck(token, isNeg)
elif type == SEARCH_PROP:
self._findProp(token, isNeg)
else: else:
self._findText(token, isNeg, c) self._findText(token, isNeg, c)
@ -161,6 +164,40 @@ and c.nid=n.id %s""" % (q, order)
else: else:
self.lims['valid'] = False self.lims['valid'] = False
def _findProp(self, val, neg):
# extract
m = re.match("(^.+?)(<=|>=|=|<|>)(.+?$)", val)
if not m:
self.lims['valid'] = False
return
prop, cmp, val = m.groups()
prop = prop.lower()
# is val valid?
try:
if prop == "ease":
val = float(val)
else:
val = int(val)
except ValueError:
self.lims['valid'] = False
return
# is prop valid?
if prop not in ("due", "ivl", "reps", "lapses", "ease"):
self.lims['valid'] = False
return
# query
extra = "not" if neg else ""
if prop == "due":
val += self.col.sched.today
# only valid for review/daily learning
self.lims['preds'].append("queue in (2,3)")
elif prop == "ease":
prop = "factor"
val = int(val*1000)
sql = "%s (%s %s %s)" % ("not" if neg else "",
prop, cmp, val)
self.lims['preds'].append(sql)
def _findText(self, val, neg, c): def _findText(self, val, neg, c):
val = val.replace("*", "%") val = val.replace("*", "%")
if not self.full: if not self.full:
@ -378,6 +415,9 @@ n.mid in %s and n.id %s in %s""" % (
elif token['value'].startswith("deck:"): elif token['value'].startswith("deck:"):
token['value'] = token['value'][5:].lower() token['value'] = token['value'][5:].lower()
type = SEARCH_DECK type = SEARCH_DECK
elif token['value'].startswith("prop:"):
token['value'] = token['value'][5:].lower()
type = SEARCH_PROP
elif token['value'].startswith("nid:") and len(token['value']) > 4: elif token['value'].startswith("nid:") and len(token['value']) > 4:
dec = token['value'][4:] dec = token['value'][4:]
try: try:

View file

@ -68,8 +68,8 @@ def test_findCards():
assert len(deck.findCards("-is:due")) == 4 assert len(deck.findCards("-is:due")) == 4
c.queue = -1 c.queue = -1
# ensure this card gets a later mod time # ensure this card gets a later mod time
import time; time.sleep(1)
c.flush() c.flush()
deck.db.execute("update cards set mod = mod + 1 where id = ?", c.id)
assert deck.findCards("is:suspended") == [c.id] assert deck.findCards("is:suspended") == [c.id]
# nids # nids
assert deck.findCards("nid:54321") == [] assert deck.findCards("nid:54321") == []
@ -135,6 +135,31 @@ def test_findCards():
assert len(deck.findCards("deck:default")) == 7 assert len(deck.findCards("deck:default")) == 7
assert len(deck.findCards("deck:default::child")) == 1 assert len(deck.findCards("deck:default::child")) == 1
assert len(deck.findCards("deck:default -deck:default::*")) == 6 assert len(deck.findCards("deck:default -deck:default::*")) == 6
# properties
id = deck.db.scalar("select id from cards limit 1")
deck.db.execute(
"update cards set queue=2, ivl=10, reps=20, due=30, factor=2200 "
"where id = ?", id)
assert len(deck.findCards("prop:ivl>5")) == 1
assert len(deck.findCards("prop:ivl<5")) > 1
assert len(deck.findCards("prop:ivl>=5")) == 1
assert len(deck.findCards("prop:ivl=9")) == 0
assert len(deck.findCards("prop:ivl=10")) == 1
assert len(deck.findCards("prop:due>0")) == 1
# due dates should work
deck.sched.today = 15
assert len(deck.findCards("prop:due=14")) == 0
assert len(deck.findCards("prop:due=15")) == 1
assert len(deck.findCards("prop:due=16")) == 0
# including negatives
deck.sched.today = 32
assert len(deck.findCards("prop:due=-1")) == 0
assert len(deck.findCards("prop:due=-2")) == 1
# ease factors
assert len(deck.findCards("prop:ease=2.3")) == 0
assert len(deck.findCards("prop:ease=2.2")) == 1
assert len(deck.findCards("prop:ease>2")) == 1
assert len(deck.findCards("-prop:ease>2")) > 1
def test_findReplace(): def test_findReplace():
deck = getEmptyDeck() deck = getEmptyDeck()