mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
fix new cards not being correctly limited
https://forums.ankiweb.net/t/ios-beta-20080-2-more-new-cards-after-review-limit-is-met/13728/10
This commit is contained in:
parent
b1dda8db64
commit
0e00c4a461
4 changed files with 69 additions and 6 deletions
|
@ -16,10 +16,14 @@ pub(crate) struct RemainingLimits {
|
|||
}
|
||||
|
||||
impl RemainingLimits {
|
||||
pub(crate) fn new(deck: &Deck, config: Option<&DeckConfig>, today: u32) -> Self {
|
||||
pub(crate) fn new(deck: &Deck, config: Option<&DeckConfig>, today: u32, v3: bool) -> Self {
|
||||
config
|
||||
.map(|config| {
|
||||
let (new_today, rev_today) = deck.new_rev_counts(today);
|
||||
let (new_today, mut rev_today) = deck.new_rev_counts(today);
|
||||
if v3 {
|
||||
// any reviewed new cards contribute to the review limit
|
||||
rev_today += new_today;
|
||||
}
|
||||
RemainingLimits {
|
||||
review: ((config.inner.reviews_per_day as i32) - rev_today).max(0) as u32,
|
||||
new: ((config.inner.new_per_day as i32) - new_today).max(0) as u32,
|
||||
|
@ -47,12 +51,18 @@ pub(crate) fn remaining_limits_map<'a>(
|
|||
decks: impl Iterator<Item = &'a Deck>,
|
||||
config: &'a HashMap<DeckConfigId, DeckConfig>,
|
||||
today: u32,
|
||||
v3: bool,
|
||||
) -> HashMap<DeckId, RemainingLimits> {
|
||||
decks
|
||||
.map(|deck| {
|
||||
(
|
||||
deck.id,
|
||||
RemainingLimits::new(deck, deck.config_id().and_then(|id| config.get(&id)), today),
|
||||
RemainingLimits::new(
|
||||
deck,
|
||||
deck.config_id().and_then(|id| config.get(&id)),
|
||||
today,
|
||||
v3,
|
||||
),
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
|
|
|
@ -316,7 +316,7 @@ impl Collection {
|
|||
let counts = self.due_counts(days_elapsed, learn_cutoff, limit)?;
|
||||
let dconf = self.storage.get_deck_config_map()?;
|
||||
add_counts(&mut tree, &counts);
|
||||
let limits = remaining_limits_map(decks_map.values(), &dconf, days_elapsed);
|
||||
let limits = remaining_limits_map(decks_map.values(), &dconf, days_elapsed, v3);
|
||||
if sched_ver == SchedulerVersion::V2 {
|
||||
if v3 {
|
||||
sum_counts_and_apply_limits_v3(&mut tree, &limits);
|
||||
|
|
|
@ -431,7 +431,9 @@ fn get_fuzz_seed(card: &Card) -> Option<u64> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::{card::CardType, collection::open_test_collection};
|
||||
use crate::{
|
||||
card::CardType, collection::open_test_collection, deckconfig::ReviewMix, search::SortMode,
|
||||
};
|
||||
|
||||
fn current_state(col: &mut Collection, card_id: CardId) -> CardState {
|
||||
col.get_next_card_states(card_id).unwrap().current
|
||||
|
@ -554,4 +556,55 @@ mod test {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn v3_test_collection(cards: usize) -> Result<(Collection, Vec<CardId>)> {
|
||||
let mut col = open_test_collection();
|
||||
let nt = col.get_notetype_by_name("Basic")?.unwrap();
|
||||
for _ in 0..cards {
|
||||
let mut note = Note::new(&nt);
|
||||
col.add_note(&mut note, DeckId(1))?;
|
||||
}
|
||||
col.set_config_bool(BoolKey::Sched2021, true, false)?;
|
||||
let cids = col.search_cards("", SortMode::NoOrder)?;
|
||||
Ok((col, cids))
|
||||
}
|
||||
|
||||
macro_rules! assert_counts {
|
||||
($col:ident, $new:expr, $learn:expr, $review:expr) => {{
|
||||
let tree = $col.deck_tree(Some(TimestampSecs::now()), None).unwrap();
|
||||
assert_eq!(tree.new_count, $new);
|
||||
assert_eq!(tree.learn_count, $learn);
|
||||
assert_eq!(tree.review_count, $review);
|
||||
let queued = $col.get_queued_cards(1, false).unwrap();
|
||||
assert_eq!(queued.new_count, $new);
|
||||
assert_eq!(queued.learning_count, $learn);
|
||||
assert_eq!(queued.review_count, $review);
|
||||
}};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_limited_by_reviews() -> Result<()> {
|
||||
let (mut col, cids) = v3_test_collection(4)?;
|
||||
col.set_due_date(&cids[0..2], "0", None)?;
|
||||
// set a limit of 3 reviews, which should give us 2 reviews and 1 new card
|
||||
let mut conf = col.get_deck_config(DeckConfigId(1), false)?.unwrap();
|
||||
conf.inner.reviews_per_day = 3;
|
||||
conf.inner.set_new_mix(ReviewMix::BeforeReviews);
|
||||
col.storage.update_deck_conf(&conf)?;
|
||||
|
||||
assert_counts!(col, 1, 0, 2);
|
||||
// first card is the new card
|
||||
col.answer_good();
|
||||
assert_counts!(col, 0, 1, 2);
|
||||
// then the two reviews
|
||||
col.answer_good();
|
||||
assert_counts!(col, 0, 1, 1);
|
||||
col.answer_good();
|
||||
assert_counts!(col, 0, 1, 0);
|
||||
// after the final 10 minute step, the queues should be empty
|
||||
col.answer_good();
|
||||
assert_counts!(col, 0, 0, 0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -235,7 +235,7 @@ impl Collection {
|
|||
|
||||
// fetch remaining limits, and cap to selected deck limits so that we don't
|
||||
// do more work than necessary
|
||||
let mut remaining = remaining_limits_map(decks.iter(), &config, timing.days_elapsed);
|
||||
let mut remaining = remaining_limits_map(decks.iter(), &config, timing.days_elapsed, true);
|
||||
let selected_deck_limits_at_start = *remaining.get(&deck_id).unwrap();
|
||||
let mut selected_deck_limits = selected_deck_limits_at_start;
|
||||
for limit in remaining.values_mut() {
|
||||
|
|
Loading…
Reference in a new issue