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:
RumovZ 2022-05-11 10:59:49 +02:00
parent fe862523e6
commit b740be6554
5 changed files with 47 additions and 31 deletions

View file

@ -262,7 +262,11 @@ impl Collection {
// write note, updating tags and generating missing cards
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(
ctx, &mut note, &original, false, norm, true,

View file

@ -32,6 +32,7 @@ struct Context<'a> {
deck_ids: HashMap<String, Option<DeckId>>,
usn: Usn,
normalize_notes: bool,
card_gen_ctxs: HashMap<(NotetypeId, DeckId), CardGenContext<Arc<Notetype>>>,
//progress: IncrementableProgress<ImportProgress>,
}
@ -52,6 +53,7 @@ impl<'a> Context<'a> {
normalize_notes,
notetypes,
deck_ids,
card_gen_ctxs: HashMap::new(),
})
}
@ -89,7 +91,7 @@ impl<'a> Context<'a> {
for foreign in notes {
if let Some(notetype) = self.notetype_for_note(&foreign)? {
if let Some(deck_id) = self.deck_id_for_note(&foreign)? {
let log_note = self.import_foreign_note(foreign, &notetype, deck_id)?;
let log_note = self.import_foreign_note(foreign, notetype, deck_id)?;
log.new.push(log_note);
}
}
@ -100,12 +102,12 @@ impl<'a> Context<'a> {
fn import_foreign_note(
&mut self,
foreign: ForeignNote,
notetype: &Notetype,
notetype: Arc<Notetype>,
deck_id: DeckId,
) -> Result<LogNote> {
let today = self.col.timing_today()?.days_elapsed;
let (mut note, mut cards) = foreign.into_native(notetype, deck_id, today);
self.import_note(&mut note, notetype)?;
let (mut note, mut cards) = foreign.into_native(&notetype, deck_id, today);
self.import_note(&mut note, &notetype)?;
self.import_cards(&mut cards, note.id)?;
self.generate_missing_cards(notetype, deck_id, &note)?;
Ok(note.into_log_note())
@ -128,13 +130,16 @@ impl<'a> Context<'a> {
fn generate_missing_cards(
&mut self,
notetype: &Notetype,
notetype: Arc<Notetype>,
deck_id: DeckId,
note: &Note,
) -> 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
.generate_cards_for_existing_note(&card_gen_context, note)
.generate_cards_for_existing_note(card_gen_context, note)
}
}

View file

@ -80,7 +80,7 @@ impl Collection {
.get_notetype(note.notetype_id)?
.ok_or_else(|| AnkiError::invalid_input("missing note type"))?;
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);
col.add_note_inner(&ctx, note, did, norm)
})
@ -334,7 +334,7 @@ impl Collection {
pub(crate) fn add_note_inner(
&mut self,
ctx: &CardGenContext,
ctx: &CardGenContext<&Notetype>,
note: &mut Note,
did: DeckId,
normalize_text: bool,
@ -397,7 +397,7 @@ impl Collection {
.get_notetype(note.notetype_id)?
.ok_or_else(|| AnkiError::invalid_input("missing note type"))?;
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);
self.update_note_inner_generating_cards(&ctx, note, &existing_note, true, norm, true)?;
Ok(())
@ -405,7 +405,7 @@ impl Collection {
pub(crate) fn update_note_inner_generating_cards(
&mut self,
ctx: &CardGenContext,
ctx: &CardGenContext<&Notetype>,
note: &mut Note,
original: &Note,
mark_note_modified: bool,
@ -508,7 +508,7 @@ impl Collection {
if out.generate_cards {
let ctx = genctx.get_or_insert_with(|| {
CardGenContext::new(
&nt,
nt.as_ref(),
self.get_last_deck_added_to_for_notetype(nt.id),
usn,
)

View file

@ -1,7 +1,10 @@
// Copyright: Ankitects Pty Ltd and contributors
// 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 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,
/// and where they should be placed.
pub(crate) struct CardGenContext<'a> {
pub(crate) struct CardGenContext<N: Deref<Target = Notetype>> {
pub usn: Usn,
pub notetype: &'a Notetype,
pub notetype: N,
/// The last deck that was added to with this note type
pub last_deck: Option<DeckId>,
cards: Vec<SingleCardGenContext>,
@ -53,20 +56,21 @@ pub(crate) struct CardGenCache {
deck_configs: HashMap<DeckId, DeckConfig>,
}
impl CardGenContext<'_> {
pub(crate) fn new(nt: &Notetype, last_deck: Option<DeckId>, usn: Usn) -> CardGenContext<'_> {
impl<N: Deref<Target = Notetype>> CardGenContext<N> {
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 {
usn,
last_deck,
notetype: nt,
cards: nt
.templates
.iter()
.map(|tmpl| SingleCardGenContext {
template: tmpl.parsed_question(),
target_deck_id: tmpl.target_deck_id(),
})
.collect(),
cards,
}
}
@ -209,7 +213,7 @@ pub(crate) fn extract_data_from_existing_cards(
impl Collection {
pub(crate) fn generate_cards_for_new_note(
&mut self,
ctx: &CardGenContext,
ctx: &CardGenContext<impl Deref<Target = Notetype>>,
note: &Note,
target_deck_id: DeckId,
) -> Result<()> {
@ -224,7 +228,7 @@ impl Collection {
pub(crate) fn generate_cards_for_existing_note(
&mut self,
ctx: &CardGenContext,
ctx: &CardGenContext<impl Deref<Target = Notetype>>,
note: &Note,
) -> Result<()> {
let existing = self.storage.existing_cards_for_note(note.id)?;
@ -233,7 +237,7 @@ impl Collection {
fn generate_cards_for_note(
&mut self,
ctx: &CardGenContext,
ctx: &CardGenContext<impl Deref<Target = Notetype>>,
note: &Note,
existing: &[AlreadyGeneratedCardInfo],
target_deck_id: Option<DeckId>,
@ -246,7 +250,10 @@ impl Collection {
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 by_note = group_generated_cards_by_note(existing_cards);
let mut cache = CardGenCache::default();

View file

@ -255,7 +255,7 @@ impl Collection {
.get_notetype(new_notetype_id)?
.ok_or(AnkiError::NotFound)?;
let last_deck = self.get_last_deck_added_to_for_notetype(notetype.id);
let ctx = CardGenContext::new(&notetype, last_deck, usn);
let ctx = CardGenContext::new(notetype.as_ref(), last_deck, usn);
for nid in note_ids {
let mut note = self.storage.get_note(*nid)?.ok_or(AnkiError::NotFound)?;