mirror of
https://github.com/ankitects/anki.git
synced 2026-01-16 23:39:01 -05:00
So, this is fun. Apparently "DeckId" is considered preferable to the "DeckID" were were using until now, and the latest clippy will start warning about it. We could of course disable the warning, but probably better to bite the bullet and switch to the naming that's generally considered best.
119 lines
3.9 KiB
Rust
119 lines
3.9 KiB
Rust
// Copyright: Ankitects Pty Ltd and contributors
|
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
|
|
use crate::{
|
|
collection::Collection,
|
|
define_newtype,
|
|
err::{AnkiError, Result},
|
|
scheduler::states::review::INITIAL_EASE_FACTOR,
|
|
timestamp::{TimestampMillis, TimestampSecs},
|
|
types::Usn,
|
|
};
|
|
|
|
pub use crate::backend_proto::{
|
|
deck_config_inner::{LeechAction, NewCardOrder, ReviewCardOrder, ReviewMix},
|
|
DeckConfigInner,
|
|
};
|
|
pub use schema11::{DeckConfSchema11, NewCardOrderSchema11};
|
|
/// Old deck config and cards table store 250% as 2500.
|
|
pub(crate) const INITIAL_EASE_FACTOR_THOUSANDS: u16 = (INITIAL_EASE_FACTOR * 1000.0) as u16;
|
|
|
|
mod schema11;
|
|
|
|
define_newtype!(DeckConfId, i64);
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
pub struct DeckConf {
|
|
pub id: DeckConfId,
|
|
pub name: String,
|
|
pub mtime_secs: TimestampSecs,
|
|
pub usn: Usn,
|
|
pub inner: DeckConfigInner,
|
|
}
|
|
|
|
impl Default for DeckConf {
|
|
fn default() -> Self {
|
|
DeckConf {
|
|
id: DeckConfId(0),
|
|
name: "".to_string(),
|
|
mtime_secs: Default::default(),
|
|
usn: Default::default(),
|
|
inner: DeckConfigInner {
|
|
learn_steps: vec![1.0, 10.0],
|
|
relearn_steps: vec![10.0],
|
|
new_per_day: 20,
|
|
reviews_per_day: 200,
|
|
new_per_day_minimum: 0,
|
|
initial_ease: 2.5,
|
|
easy_multiplier: 1.3,
|
|
hard_multiplier: 1.2,
|
|
lapse_multiplier: 0.0,
|
|
interval_multiplier: 1.0,
|
|
maximum_review_interval: 36_500,
|
|
minimum_lapse_interval: 1,
|
|
graduating_interval_good: 1,
|
|
graduating_interval_easy: 4,
|
|
new_card_order: NewCardOrder::Due as i32,
|
|
review_order: ReviewCardOrder::ShuffledByDay as i32,
|
|
new_mix: ReviewMix::MixWithReviews as i32,
|
|
interday_learning_mix: ReviewMix::MixWithReviews as i32,
|
|
leech_action: LeechAction::TagOnly as i32,
|
|
leech_threshold: 8,
|
|
disable_autoplay: false,
|
|
cap_answer_time_to_secs: 60,
|
|
visible_timer_secs: 0,
|
|
skip_question_when_replaying_answer: false,
|
|
bury_new: false,
|
|
bury_reviews: false,
|
|
other: vec![],
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Collection {
|
|
/// If fallback is true, guaranteed to return a deck config.
|
|
pub fn get_deck_config(&self, dcid: DeckConfId, fallback: bool) -> Result<Option<DeckConf>> {
|
|
if let Some(conf) = self.storage.get_deck_config(dcid)? {
|
|
return Ok(Some(conf));
|
|
}
|
|
if fallback {
|
|
if let Some(conf) = self.storage.get_deck_config(DeckConfId(1))? {
|
|
return Ok(Some(conf));
|
|
}
|
|
// if even the default deck config is missing, just return the defaults
|
|
Ok(Some(DeckConf::default()))
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
}
|
|
|
|
pub(crate) fn add_or_update_deck_config(
|
|
&self,
|
|
conf: &mut DeckConf,
|
|
preserve_usn_and_mtime: bool,
|
|
) -> Result<()> {
|
|
if !preserve_usn_and_mtime {
|
|
conf.mtime_secs = TimestampSecs::now();
|
|
conf.usn = self.usn()?;
|
|
}
|
|
let orig = self.storage.get_deck_config(conf.id)?;
|
|
if let Some(_orig) = orig {
|
|
self.storage.update_deck_conf(&conf)
|
|
} else {
|
|
if conf.id.0 == 0 {
|
|
conf.id.0 = TimestampMillis::now().0;
|
|
}
|
|
self.storage.add_deck_conf(conf)
|
|
}
|
|
}
|
|
|
|
/// Remove a deck configuration. This will force a full sync.
|
|
pub(crate) fn remove_deck_config(&self, dcid: DeckConfId) -> Result<()> {
|
|
if dcid.0 == 1 {
|
|
return Err(AnkiError::invalid_input("can't delete default conf"));
|
|
}
|
|
self.storage.set_schema_modified()?;
|
|
self.storage.remove_deck_conf(dcid)
|
|
}
|
|
}
|