Anki/rslib/src/scheduler/queue/builder/burying.rs
RumovZ 682bf8ce46 Disable burying of previously gathered cards (#2361)
* Enforce hierarchical bury modes

Interday learning burying is only allowed if review burying is enabled
and review burying is only allowed if new burying is enabled.
Closes #2352.

* Switch front end to new bury modes

* Wording tweaks (dae)

* Hide interday option if using v2 scheduler (dae)
2023-02-06 12:02:27 +10:00

99 lines
3.1 KiB
Rust

// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use super::super::BuryMode;
use super::Context;
use super::DueCard;
use super::NewCard;
use super::QueueBuilder;
use crate::deckconfig::DeckConfig;
use crate::prelude::*;
pub(super) enum DueOrNewCard {
Due(DueCard),
New(NewCard),
}
impl DueOrNewCard {
fn original_deck_id(&self) -> DeckId {
match self {
Self::Due(card) => card.original_deck_id.or(card.current_deck_id),
Self::New(card) => card.original_deck_id.or(card.current_deck_id),
}
}
fn note_id(&self) -> NoteId {
match self {
Self::Due(card) => card.note_id,
Self::New(card) => card.note_id,
}
}
}
impl From<DueCard> for DueOrNewCard {
fn from(card: DueCard) -> DueOrNewCard {
DueOrNewCard::Due(card)
}
}
impl From<NewCard> for DueOrNewCard {
fn from(card: NewCard) -> DueOrNewCard {
DueOrNewCard::New(card)
}
}
impl Context {
pub(super) fn bury_mode(&self, deck_id: DeckId) -> BuryMode {
self.deck_map
.get(&deck_id)
.and_then(|deck| deck.config_id())
.and_then(|config_id| self.config_map.get(&config_id))
.map(BuryMode::from_deck_config)
.unwrap_or_default()
}
}
impl BuryMode {
pub(crate) fn from_deck_config(config: &DeckConfig) -> BuryMode {
let cfg = &config.inner;
// Since cards are gathered in a certain order (learning > review > new) and
// a card can only bury siblings that are gathered later, only the four bury
// modes following this order are allowed.
// Booleans are continued to be used for reasons of backwards compatibility.
// https://github.com/ankitects/anki/issues/2352
BuryMode {
bury_new: cfg.bury_new,
bury_reviews: cfg.bury_new && cfg.bury_reviews,
bury_interday_learning: cfg.bury_new && cfg.bury_reviews && cfg.bury_interday_learning,
}
}
pub(crate) fn any_burying(self) -> bool {
self.bury_interday_learning || self.bury_reviews || self.bury_new
}
}
impl QueueBuilder {
/// If burying is enabled in `new_settings`, existing entry will be updated.
/// Returns a copy made before changing the entry, so that a card with
/// burying enabled will bury future siblings, but not itself.
pub(super) fn get_and_update_bury_mode_for_note(
&mut self,
card: DueOrNewCard,
) -> Option<BuryMode> {
let mut previous_mode = None;
let new_mode = self.context.bury_mode(card.original_deck_id());
self.context
.seen_note_ids
.entry(card.note_id())
.and_modify(|entry| {
previous_mode = Some(*entry);
entry.bury_new |= new_mode.bury_new;
entry.bury_reviews |= new_mode.bury_reviews;
entry.bury_interday_learning |= new_mode.bury_interday_learning;
})
.or_insert(new_mode);
previous_mode
}
}