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;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
|
@ -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
|
||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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)
|
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
|
@ -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 ¬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> {
|
fn to_nids(ids: Vec<i64>) -> Vec<NoteID> {
|
||||||
|
|
Loading…
Reference in a new issue