mirror of
https://github.com/ankitects/anki.git
synced 2025-09-25 09:16:38 -04:00
Avoid creating CardGenContexts for every note
This requires CardGenContext to be generic, so it works both with an owned and borrowed notetype.
This commit is contained in:
parent
fe862523e6
commit
b740be6554
5 changed files with 47 additions and 31 deletions
|
@ -262,7 +262,11 @@ impl Collection {
|
||||||
|
|
||||||
// write note, updating tags and generating missing cards
|
// write note, updating tags and generating missing cards
|
||||||
let ctx = genctx.get_or_insert_with(|| {
|
let ctx = genctx.get_or_insert_with(|| {
|
||||||
CardGenContext::new(&nt, self.get_last_deck_added_to_for_notetype(nt.id), usn)
|
CardGenContext::new(
|
||||||
|
nt.as_ref(),
|
||||||
|
self.get_last_deck_added_to_for_notetype(nt.id),
|
||||||
|
usn,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
self.update_note_inner_generating_cards(
|
self.update_note_inner_generating_cards(
|
||||||
ctx, &mut note, &original, false, norm, true,
|
ctx, &mut note, &original, false, norm, true,
|
||||||
|
|
|
@ -32,6 +32,7 @@ struct Context<'a> {
|
||||||
deck_ids: HashMap<String, Option<DeckId>>,
|
deck_ids: HashMap<String, Option<DeckId>>,
|
||||||
usn: Usn,
|
usn: Usn,
|
||||||
normalize_notes: bool,
|
normalize_notes: bool,
|
||||||
|
card_gen_ctxs: HashMap<(NotetypeId, DeckId), CardGenContext<Arc<Notetype>>>,
|
||||||
//progress: IncrementableProgress<ImportProgress>,
|
//progress: IncrementableProgress<ImportProgress>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +53,7 @@ impl<'a> Context<'a> {
|
||||||
normalize_notes,
|
normalize_notes,
|
||||||
notetypes,
|
notetypes,
|
||||||
deck_ids,
|
deck_ids,
|
||||||
|
card_gen_ctxs: HashMap::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +91,7 @@ impl<'a> Context<'a> {
|
||||||
for foreign in notes {
|
for foreign in notes {
|
||||||
if let Some(notetype) = self.notetype_for_note(&foreign)? {
|
if let Some(notetype) = self.notetype_for_note(&foreign)? {
|
||||||
if let Some(deck_id) = self.deck_id_for_note(&foreign)? {
|
if let Some(deck_id) = self.deck_id_for_note(&foreign)? {
|
||||||
let log_note = self.import_foreign_note(foreign, ¬etype, deck_id)?;
|
let log_note = self.import_foreign_note(foreign, notetype, deck_id)?;
|
||||||
log.new.push(log_note);
|
log.new.push(log_note);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,12 +102,12 @@ impl<'a> Context<'a> {
|
||||||
fn import_foreign_note(
|
fn import_foreign_note(
|
||||||
&mut self,
|
&mut self,
|
||||||
foreign: ForeignNote,
|
foreign: ForeignNote,
|
||||||
notetype: &Notetype,
|
notetype: Arc<Notetype>,
|
||||||
deck_id: DeckId,
|
deck_id: DeckId,
|
||||||
) -> Result<LogNote> {
|
) -> Result<LogNote> {
|
||||||
let today = self.col.timing_today()?.days_elapsed;
|
let today = self.col.timing_today()?.days_elapsed;
|
||||||
let (mut note, mut cards) = foreign.into_native(notetype, deck_id, today);
|
let (mut note, mut cards) = foreign.into_native(¬etype, deck_id, today);
|
||||||
self.import_note(&mut note, notetype)?;
|
self.import_note(&mut note, ¬etype)?;
|
||||||
self.import_cards(&mut cards, note.id)?;
|
self.import_cards(&mut cards, note.id)?;
|
||||||
self.generate_missing_cards(notetype, deck_id, ¬e)?;
|
self.generate_missing_cards(notetype, deck_id, ¬e)?;
|
||||||
Ok(note.into_log_note())
|
Ok(note.into_log_note())
|
||||||
|
@ -128,13 +130,16 @@ impl<'a> Context<'a> {
|
||||||
|
|
||||||
fn generate_missing_cards(
|
fn generate_missing_cards(
|
||||||
&mut self,
|
&mut self,
|
||||||
notetype: &Notetype,
|
notetype: Arc<Notetype>,
|
||||||
deck_id: DeckId,
|
deck_id: DeckId,
|
||||||
note: &Note,
|
note: &Note,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let card_gen_context = CardGenContext::new(notetype, Some(deck_id), self.usn);
|
let card_gen_context = self
|
||||||
|
.card_gen_ctxs
|
||||||
|
.entry((notetype.id, deck_id))
|
||||||
|
.or_insert_with(|| CardGenContext::new(notetype, Some(deck_id), self.usn));
|
||||||
self.col
|
self.col
|
||||||
.generate_cards_for_existing_note(&card_gen_context, note)
|
.generate_cards_for_existing_note(card_gen_context, note)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ impl Collection {
|
||||||
.get_notetype(note.notetype_id)?
|
.get_notetype(note.notetype_id)?
|
||||||
.ok_or_else(|| AnkiError::invalid_input("missing note type"))?;
|
.ok_or_else(|| AnkiError::invalid_input("missing note type"))?;
|
||||||
let last_deck = col.get_last_deck_added_to_for_notetype(note.notetype_id);
|
let last_deck = col.get_last_deck_added_to_for_notetype(note.notetype_id);
|
||||||
let ctx = CardGenContext::new(&nt, last_deck, col.usn()?);
|
let ctx = CardGenContext::new(nt.as_ref(), last_deck, col.usn()?);
|
||||||
let norm = col.get_config_bool(BoolKey::NormalizeNoteText);
|
let norm = col.get_config_bool(BoolKey::NormalizeNoteText);
|
||||||
col.add_note_inner(&ctx, note, did, norm)
|
col.add_note_inner(&ctx, note, did, norm)
|
||||||
})
|
})
|
||||||
|
@ -334,7 +334,7 @@ impl Collection {
|
||||||
|
|
||||||
pub(crate) fn add_note_inner(
|
pub(crate) fn add_note_inner(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &CardGenContext,
|
ctx: &CardGenContext<&Notetype>,
|
||||||
note: &mut Note,
|
note: &mut Note,
|
||||||
did: DeckId,
|
did: DeckId,
|
||||||
normalize_text: bool,
|
normalize_text: bool,
|
||||||
|
@ -397,7 +397,7 @@ impl Collection {
|
||||||
.get_notetype(note.notetype_id)?
|
.get_notetype(note.notetype_id)?
|
||||||
.ok_or_else(|| AnkiError::invalid_input("missing note type"))?;
|
.ok_or_else(|| AnkiError::invalid_input("missing note type"))?;
|
||||||
let last_deck = self.get_last_deck_added_to_for_notetype(note.notetype_id);
|
let last_deck = self.get_last_deck_added_to_for_notetype(note.notetype_id);
|
||||||
let ctx = CardGenContext::new(&nt, last_deck, self.usn()?);
|
let ctx = CardGenContext::new(nt.as_ref(), last_deck, self.usn()?);
|
||||||
let norm = self.get_config_bool(BoolKey::NormalizeNoteText);
|
let norm = self.get_config_bool(BoolKey::NormalizeNoteText);
|
||||||
self.update_note_inner_generating_cards(&ctx, note, &existing_note, true, norm, true)?;
|
self.update_note_inner_generating_cards(&ctx, note, &existing_note, true, norm, true)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -405,7 +405,7 @@ impl Collection {
|
||||||
|
|
||||||
pub(crate) fn update_note_inner_generating_cards(
|
pub(crate) fn update_note_inner_generating_cards(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &CardGenContext,
|
ctx: &CardGenContext<&Notetype>,
|
||||||
note: &mut Note,
|
note: &mut Note,
|
||||||
original: &Note,
|
original: &Note,
|
||||||
mark_note_modified: bool,
|
mark_note_modified: bool,
|
||||||
|
@ -508,7 +508,7 @@ impl Collection {
|
||||||
if out.generate_cards {
|
if out.generate_cards {
|
||||||
let ctx = genctx.get_or_insert_with(|| {
|
let ctx = genctx.get_or_insert_with(|| {
|
||||||
CardGenContext::new(
|
CardGenContext::new(
|
||||||
&nt,
|
nt.as_ref(),
|
||||||
self.get_last_deck_added_to_for_notetype(nt.id),
|
self.get_last_deck_added_to_for_notetype(nt.id),
|
||||||
usn,
|
usn,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
// Copyright: Ankitects Pty Ltd and contributors
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::{
|
||||||
|
collections::{HashMap, HashSet},
|
||||||
|
ops::Deref,
|
||||||
|
};
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rand::{rngs::StdRng, Rng, SeedableRng};
|
use rand::{rngs::StdRng, Rng, SeedableRng};
|
||||||
|
@ -38,9 +41,9 @@ pub(crate) struct SingleCardGenContext {
|
||||||
|
|
||||||
/// Info required to determine which cards should be generated when note added/updated,
|
/// Info required to determine which cards should be generated when note added/updated,
|
||||||
/// and where they should be placed.
|
/// and where they should be placed.
|
||||||
pub(crate) struct CardGenContext<'a> {
|
pub(crate) struct CardGenContext<N: Deref<Target = Notetype>> {
|
||||||
pub usn: Usn,
|
pub usn: Usn,
|
||||||
pub notetype: &'a Notetype,
|
pub notetype: N,
|
||||||
/// The last deck that was added to with this note type
|
/// The last deck that was added to with this note type
|
||||||
pub last_deck: Option<DeckId>,
|
pub last_deck: Option<DeckId>,
|
||||||
cards: Vec<SingleCardGenContext>,
|
cards: Vec<SingleCardGenContext>,
|
||||||
|
@ -53,20 +56,21 @@ pub(crate) struct CardGenCache {
|
||||||
deck_configs: HashMap<DeckId, DeckConfig>,
|
deck_configs: HashMap<DeckId, DeckConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CardGenContext<'_> {
|
impl<N: Deref<Target = Notetype>> CardGenContext<N> {
|
||||||
pub(crate) fn new(nt: &Notetype, last_deck: Option<DeckId>, usn: Usn) -> CardGenContext<'_> {
|
pub(crate) fn new(nt: N, last_deck: Option<DeckId>, usn: Usn) -> CardGenContext<N> {
|
||||||
|
let cards = nt
|
||||||
|
.templates
|
||||||
|
.iter()
|
||||||
|
.map(|tmpl| SingleCardGenContext {
|
||||||
|
template: tmpl.parsed_question(),
|
||||||
|
target_deck_id: tmpl.target_deck_id(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
CardGenContext {
|
CardGenContext {
|
||||||
usn,
|
usn,
|
||||||
last_deck,
|
last_deck,
|
||||||
notetype: nt,
|
notetype: nt,
|
||||||
cards: nt
|
cards,
|
||||||
.templates
|
|
||||||
.iter()
|
|
||||||
.map(|tmpl| SingleCardGenContext {
|
|
||||||
template: tmpl.parsed_question(),
|
|
||||||
target_deck_id: tmpl.target_deck_id(),
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +213,7 @@ pub(crate) fn extract_data_from_existing_cards(
|
||||||
impl Collection {
|
impl Collection {
|
||||||
pub(crate) fn generate_cards_for_new_note(
|
pub(crate) fn generate_cards_for_new_note(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &CardGenContext,
|
ctx: &CardGenContext<impl Deref<Target = Notetype>>,
|
||||||
note: &Note,
|
note: &Note,
|
||||||
target_deck_id: DeckId,
|
target_deck_id: DeckId,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
@ -224,7 +228,7 @@ impl Collection {
|
||||||
|
|
||||||
pub(crate) fn generate_cards_for_existing_note(
|
pub(crate) fn generate_cards_for_existing_note(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &CardGenContext,
|
ctx: &CardGenContext<impl Deref<Target = Notetype>>,
|
||||||
note: &Note,
|
note: &Note,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let existing = self.storage.existing_cards_for_note(note.id)?;
|
let existing = self.storage.existing_cards_for_note(note.id)?;
|
||||||
|
@ -233,7 +237,7 @@ impl Collection {
|
||||||
|
|
||||||
fn generate_cards_for_note(
|
fn generate_cards_for_note(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &CardGenContext,
|
ctx: &CardGenContext<impl Deref<Target = Notetype>>,
|
||||||
note: &Note,
|
note: &Note,
|
||||||
existing: &[AlreadyGeneratedCardInfo],
|
existing: &[AlreadyGeneratedCardInfo],
|
||||||
target_deck_id: Option<DeckId>,
|
target_deck_id: Option<DeckId>,
|
||||||
|
@ -246,7 +250,10 @@ impl Collection {
|
||||||
self.add_generated_cards(note.id, &cards, target_deck_id, cache)
|
self.add_generated_cards(note.id, &cards, target_deck_id, cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn generate_cards_for_notetype(&mut self, ctx: &CardGenContext) -> Result<()> {
|
pub(crate) fn generate_cards_for_notetype(
|
||||||
|
&mut self,
|
||||||
|
ctx: &CardGenContext<impl Deref<Target = Notetype>>,
|
||||||
|
) -> Result<()> {
|
||||||
let existing_cards = self.storage.existing_cards_for_notetype(ctx.notetype.id)?;
|
let existing_cards = self.storage.existing_cards_for_notetype(ctx.notetype.id)?;
|
||||||
let by_note = group_generated_cards_by_note(existing_cards);
|
let by_note = group_generated_cards_by_note(existing_cards);
|
||||||
let mut cache = CardGenCache::default();
|
let mut cache = CardGenCache::default();
|
||||||
|
|
|
@ -255,7 +255,7 @@ impl Collection {
|
||||||
.get_notetype(new_notetype_id)?
|
.get_notetype(new_notetype_id)?
|
||||||
.ok_or(AnkiError::NotFound)?;
|
.ok_or(AnkiError::NotFound)?;
|
||||||
let last_deck = self.get_last_deck_added_to_for_notetype(notetype.id);
|
let last_deck = self.get_last_deck_added_to_for_notetype(notetype.id);
|
||||||
let ctx = CardGenContext::new(¬etype, last_deck, usn);
|
let ctx = CardGenContext::new(notetype.as_ref(), last_deck, usn);
|
||||||
|
|
||||||
for nid in note_ids {
|
for nid in note_ids {
|
||||||
let mut note = self.storage.get_note(*nid)?.ok_or(AnkiError::NotFound)?;
|
let mut note = self.storage.get_note(*nid)?.ok_or(AnkiError::NotFound)?;
|
||||||
|
|
Loading…
Reference in a new issue