drop availOrds(), and use backend for getting cloze numbers

This commit is contained in:
Damien Elmes 2020-05-14 12:14:00 +10:00
parent 9f676dbe0b
commit f23eb350e4
7 changed files with 31 additions and 103 deletions

View file

@ -98,6 +98,7 @@ message BackendInput {
Empty get_preferences = 84; Empty get_preferences = 84;
Preferences set_preferences = 85; Preferences set_preferences = 85;
RenderExistingCardIn render_existing_card = 86; RenderExistingCardIn render_existing_card = 86;
Note cloze_numbers_in_note = 87;
} }
} }
@ -114,6 +115,7 @@ message BackendOutput {
string congrats_learn_msg = 33; string congrats_learn_msg = 33;
Empty abort_media_sync = 46; Empty abort_media_sync = 46;
AllStockNotetypesOut all_stock_notetypes = 60; AllStockNotetypesOut all_stock_notetypes = 60;
ClozeNumbersInNoteOut cloze_numbers_in_note = 87;
// fallible commands // fallible commands
SchedTimingTodayOut sched_timing_today = 17; SchedTimingTodayOut sched_timing_today = 17;
@ -781,3 +783,7 @@ message CollectionSchedulingSettings {
message Preferences { message Preferences {
CollectionSchedulingSettings sched = 1; CollectionSchedulingSettings sched = 1;
} }
message ClozeNumbersInNoteOut {
repeated uint32 numbers = 1;
}

View file

@ -521,63 +521,13 @@ class ModelManager:
s += t["name"] s += t["name"]
return checksum(s) return checksum(s)
# Required field/text cache # Cloze
########################################################################## ##########################################################################
# fixme: clayout, importing
def availOrds(self, m: NoteType, flds: str) -> List:
"Given a joined field string, return available template ordinals."
if m["type"] == MODEL_CLOZE:
return self._availClozeOrds(m, flds)
fields = {}
for c, f in enumerate(splitFields(flds)):
fields[c] = f.strip()
avail = []
for ord, type, req in m["req"]:
# unsatisfiable template
if type == "none":
continue
# AND requirement?
elif type == "all":
ok = True
for idx in req:
if not fields[idx]:
# missing and was required
ok = False
break
if not ok:
continue
# OR requirement?
elif type == "any":
ok = False
for idx in req:
if fields[idx]:
ok = True
break
if not ok:
continue
avail.append(ord)
return avail
def _availClozeOrds(self, m: NoteType, flds: str, allowEmpty: bool = True) -> List: def _availClozeOrds(self, m: NoteType, flds: str, allowEmpty: bool = True) -> List:
sflds = splitFields(flds) print("_availClozeOrds() is deprecated")
map = self.fieldMap(m) note = anki.rsbackend.BackendNote(fields=[flds])
ords = set() return self.col.backend.cloze_numbers_in_note(note)
matches = re.findall("{{[^}]*?cloze:(?:[^}]?:)*(.+?)}}", m["tmpls"][0]["qfmt"])
matches += re.findall("<%cloze:(.+?)%>", m["tmpls"][0]["qfmt"])
for fname in matches:
if fname not in map:
continue
ord = map[fname][0]
ords.update(
[int(m) - 1 for m in re.findall(r"(?s){{c(\d+)::.+?}}", sflds[ord])]
)
if -1 in ords:
ords.remove(-1)
if not ords and allowEmpty:
# empty clozes use first ord
return [0]
return list(ords)
# Sync handling # Sync handling
########################################################################## ##########################################################################

View file

@ -82,6 +82,9 @@ class Note:
_model = property(model) _model = property(model)
def cloze_numbers_in_fields(self) -> List[int]:
return self.col.backend.cloze_numbers_in_note(self.to_backend_note())
# Dict interface # Dict interface
################################################## ##################################################

View file

@ -808,6 +808,8 @@ class RustBackend:
def set_preferences(self, prefs: pb.Preferences) -> None: def set_preferences(self, prefs: pb.Preferences) -> None:
self._run_command(pb.BackendInput(set_preferences=prefs)) self._run_command(pb.BackendInput(set_preferences=prefs))
def cloze_numbers_in_note(self, note: pb.Note) -> List[int]:
return list(self._run_command(pb.BackendInput(cloze_numbers_in_note=note)).cloze_numbers_in_note.numbers)
def translate_string_in( def translate_string_in(
key: TR, **kwargs: Union[str, int, float] key: TR, **kwargs: Union[str, int, float]

View file

@ -355,37 +355,6 @@ def test_modelChange():
assert deck.db.scalar("select count() from cards where nid = ?", f.id) == 1 assert deck.db.scalar("select count() from cards where nid = ?", f.id) == 1
def test_availOrds():
d = getEmptyCol()
m = d.models.current()
mm = d.models
t = m["tmpls"][0]
f = d.newNote()
f["Front"] = "1"
# simple templates
assert mm.availOrds(m, joinFields(f.fields)) == [0]
t["qfmt"] = "{{Back}}"
mm.save(m, templates=True)
assert not mm.availOrds(m, joinFields(f.fields))
# AND
t = m["tmpls"][0]
t["qfmt"] = "{{#Front}}{{#Back}}{{Front}}{{/Back}}{{/Front}}"
mm.save(m, templates=True)
assert not mm.availOrds(m, joinFields(f.fields))
t = m["tmpls"][0]
t["qfmt"] = "{{#Front}}\n{{#Back}}\n{{Front}}\n{{/Back}}\n{{/Front}}"
mm.save(m, templates=True)
assert not mm.availOrds(m, joinFields(f.fields))
# OR
t = m["tmpls"][0]
t["qfmt"] = "{{Front}}\n{{Back}}"
mm.save(m, templates=True)
assert mm.availOrds(m, joinFields(f.fields)) == [0]
t["Front"] = ""
t["Back"] = "1"
assert mm.availOrds(m, joinFields(f.fields)) == [0]
def test_req(): def test_req():
def reqSize(model): def reqSize(model):
if model["type"] == MODEL_CLOZE: if model["type"] == MODEL_CLOZE:
@ -421,19 +390,3 @@ def test_req():
r = opt["req"][0] r = opt["req"][0]
assert r[1] in ("any", "all") assert r[1] in ("any", "all")
assert r[2] == [0, 1] assert r[2] == [0, 1]
# def test_updatereqs_performance():
# import time
# d = getEmptyCol()
# mm = d.models
# m = mm.byName("Basic")
# for i in range(100):
# fld = mm.newField(f"field{i}")
# mm.addField(m, fld)
# tmpl = mm.newTemplate(f"template{i}")
# tmpl['qfmt'] = "{{field%s}}" % i
# mm.addTemplate(m, tmpl)
# t = time.time()
# mm.save(m, templates=True)
# print("took", (time.time()-t)*100)

View file

@ -241,7 +241,7 @@ class CardLayout(QDialog):
def updateMainArea(self): def updateMainArea(self):
if self._isCloze(): if self._isCloze():
cnt = len(self.mm.availOrds(self.model, joinFields(self.note.fields))) cnt = len(self.note.cloze_numbers_in_fields())
for g in self.pform.groupBox, self.pform.groupBox_2: for g in self.pform.groupBox, self.pform.groupBox_2:
g.setTitle(g.title() + _(" (1 of %d)") % max(cnt, 1)) g.setTitle(g.title() + _(" (1 of %d)") % max(cnt, 1))

View file

@ -8,6 +8,7 @@ use crate::{
backend_proto::{AddOrUpdateDeckConfigIn, Empty, RenderedTemplateReplacement, SyncMediaIn}, backend_proto::{AddOrUpdateDeckConfigIn, Empty, RenderedTemplateReplacement, SyncMediaIn},
card::{Card, CardID}, card::{Card, CardID},
card::{CardQueue, CardType}, card::{CardQueue, CardType},
cloze::add_cloze_numbers_in_string,
collection::{open_collection, Collection}, collection::{open_collection, Collection},
config::SortKind, config::SortKind,
deckconf::{DeckConf, DeckConfID}, deckconf::{DeckConf, DeckConfID},
@ -39,7 +40,7 @@ use log::error;
use pb::backend_input::Value; use pb::backend_input::Value;
use prost::Message; use prost::Message;
use serde_json::Value as JsonValue; use serde_json::Value as JsonValue;
use std::collections::HashMap; use std::collections::{HashMap, HashSet};
use std::convert::TryFrom; use std::convert::TryFrom;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@ -381,6 +382,9 @@ impl Backend {
Value::RenderUncommittedCard(input) => { Value::RenderUncommittedCard(input) => {
OValue::RenderUncommittedCard(self.render_uncommitted_card(input)?) OValue::RenderUncommittedCard(self.render_uncommitted_card(input)?)
} }
Value::ClozeNumbersInNote(note) => {
OValue::ClozeNumbersInNote(self.cloze_numbers_in_note(note))
}
}) })
} }
@ -1136,6 +1140,16 @@ impl Backend {
fn set_preferences(&self, prefs: pb::Preferences) -> Result<()> { fn set_preferences(&self, prefs: pb::Preferences) -> Result<()> {
self.with_col(|col| col.transact(None, |col| col.set_preferences(prefs))) self.with_col(|col| col.transact(None, |col| col.set_preferences(prefs)))
} }
fn cloze_numbers_in_note(&self, note: pb::Note) -> pb::ClozeNumbersInNoteOut {
let mut set = HashSet::with_capacity(4);
for field in &note.fields {
add_cloze_numbers_in_string(field, &mut set);
}
pb::ClozeNumbersInNoteOut {
numbers: set.into_iter().map(|n| n as u32).collect(),
}
}
} }
fn to_nids(ids: Vec<i64>) -> Vec<NoteID> { fn to_nids(ids: Vec<i64>) -> Vec<NoteID> {