mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 14:32:22 -04:00
drop availOrds(), and use backend for getting cloze numbers
This commit is contained in:
parent
9f676dbe0b
commit
f23eb350e4
7 changed files with 31 additions and 103 deletions
|
@ -98,6 +98,7 @@ message BackendInput {
|
|||
Empty get_preferences = 84;
|
||||
Preferences set_preferences = 85;
|
||||
RenderExistingCardIn render_existing_card = 86;
|
||||
Note cloze_numbers_in_note = 87;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,6 +115,7 @@ message BackendOutput {
|
|||
string congrats_learn_msg = 33;
|
||||
Empty abort_media_sync = 46;
|
||||
AllStockNotetypesOut all_stock_notetypes = 60;
|
||||
ClozeNumbersInNoteOut cloze_numbers_in_note = 87;
|
||||
|
||||
// fallible commands
|
||||
SchedTimingTodayOut sched_timing_today = 17;
|
||||
|
@ -781,3 +783,7 @@ message CollectionSchedulingSettings {
|
|||
message Preferences {
|
||||
CollectionSchedulingSettings sched = 1;
|
||||
}
|
||||
|
||||
message ClozeNumbersInNoteOut {
|
||||
repeated uint32 numbers = 1;
|
||||
}
|
||||
|
|
|
@ -521,63 +521,13 @@ class ModelManager:
|
|||
s += t["name"]
|
||||
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:
|
||||
sflds = splitFields(flds)
|
||||
map = self.fieldMap(m)
|
||||
ords = set()
|
||||
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)
|
||||
print("_availClozeOrds() is deprecated")
|
||||
note = anki.rsbackend.BackendNote(fields=[flds])
|
||||
return self.col.backend.cloze_numbers_in_note(note)
|
||||
|
||||
# Sync handling
|
||||
##########################################################################
|
||||
|
|
|
@ -82,6 +82,9 @@ class Note:
|
|||
|
||||
_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
|
||||
##################################################
|
||||
|
||||
|
|
|
@ -808,6 +808,8 @@ class RustBackend:
|
|||
def set_preferences(self, prefs: pb.Preferences) -> None:
|
||||
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(
|
||||
key: TR, **kwargs: Union[str, int, float]
|
||||
|
|
|
@ -355,37 +355,6 @@ def test_modelChange():
|
|||
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 reqSize(model):
|
||||
if model["type"] == MODEL_CLOZE:
|
||||
|
@ -421,19 +390,3 @@ def test_req():
|
|||
r = opt["req"][0]
|
||||
assert r[1] in ("any", "all")
|
||||
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)
|
||||
|
|
|
@ -241,7 +241,7 @@ class CardLayout(QDialog):
|
|||
|
||||
def updateMainArea(self):
|
||||
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:
|
||||
g.setTitle(g.title() + _(" (1 of %d)") % max(cnt, 1))
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ use crate::{
|
|||
backend_proto::{AddOrUpdateDeckConfigIn, Empty, RenderedTemplateReplacement, SyncMediaIn},
|
||||
card::{Card, CardID},
|
||||
card::{CardQueue, CardType},
|
||||
cloze::add_cloze_numbers_in_string,
|
||||
collection::{open_collection, Collection},
|
||||
config::SortKind,
|
||||
deckconf::{DeckConf, DeckConfID},
|
||||
|
@ -39,7 +40,7 @@ use log::error;
|
|||
use pb::backend_input::Value;
|
||||
use prost::Message;
|
||||
use serde_json::Value as JsonValue;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::convert::TryFrom;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
@ -381,6 +382,9 @@ impl Backend {
|
|||
Value::RenderUncommittedCard(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<()> {
|
||||
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 ¬e.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> {
|
||||
|
|
Loading…
Reference in a new issue