mirror of
https://github.com/ankitects/anki.git
synced 2026-01-11 13:03:55 -05:00
Implement 'Interleaved Decks' gathering priority.
This commit is contained in:
parent
666ac11e2c
commit
54226104c4
1 changed files with 91 additions and 2 deletions
|
|
@ -1,6 +1,11 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use rand::rng;
|
||||
use rand::Rng;
|
||||
|
||||
use super::DueCard;
|
||||
use super::NewCard;
|
||||
use super::QueueBuilder;
|
||||
|
|
@ -70,8 +75,7 @@ impl QueueBuilder {
|
|||
self.gather_new_cards_by_deck(col, NewCardSorting::RandomNotes(salt))
|
||||
}
|
||||
NewCardGatherPriority::InterleavedDecks => {
|
||||
// TODO: Actually implement the new gathering option
|
||||
self.gather_new_cards_by_deck(col, NewCardSorting::RandomNotes(salt))
|
||||
self.gather_new_cards_by_interleaved_decks(col, NewCardSorting::LowestPosition)
|
||||
}
|
||||
NewCardGatherPriority::LowestPosition => {
|
||||
self.gather_new_cards_sorted(col, NewCardSorting::LowestPosition)
|
||||
|
|
@ -114,6 +118,91 @@ impl QueueBuilder {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn gather_new_cards_by_interleaved_decks(
|
||||
&mut self,
|
||||
col: &mut Collection,
|
||||
sort: NewCardSorting,
|
||||
) -> Result<()> {
|
||||
struct InterleavedDeckData {
|
||||
deck_id: DeckId,
|
||||
depleted: bool,
|
||||
cards: std::iter::Peekable<std::vec::IntoIter<NewCard>>,
|
||||
}
|
||||
let mut decks: Vec<InterleavedDeckData> = vec![];
|
||||
for deck_id in col.storage.get_active_deck_ids_sorted()? {
|
||||
let x: std::iter::Peekable<std::vec::IntoIter<NewCard>> = col
|
||||
.storage
|
||||
.new_cards_in_deck(deck_id, sort)?
|
||||
.into_iter()
|
||||
.peekable();
|
||||
decks.push(InterleavedDeckData {
|
||||
deck_id,
|
||||
depleted: false,
|
||||
cards: x,
|
||||
});
|
||||
}
|
||||
let mut rng = rng();
|
||||
let mut do_continue = true;
|
||||
while do_continue {
|
||||
do_continue = false;
|
||||
let mut non_depleted_decks = 0;
|
||||
for deck_data in &mut decks {
|
||||
if self
|
||||
.limits
|
||||
.limit_reached(deck_data.deck_id, LimitKind::New)?
|
||||
{
|
||||
deck_data.depleted = true;
|
||||
continue;
|
||||
}
|
||||
if deck_data.cards.peek().is_none() {
|
||||
deck_data.depleted = true;
|
||||
} else {
|
||||
non_depleted_decks += 1;
|
||||
}
|
||||
}
|
||||
let root_limit = self.limits.get_root_limits().get(LimitKind::New);
|
||||
let mut sampled_deck_ids = HashSet::<DeckId>::new();
|
||||
let sampling = root_limit < non_depleted_decks;
|
||||
if sampling {
|
||||
// switch to sampling
|
||||
|
||||
let mut deck_ids: Vec<DeckId> = vec![];
|
||||
for deck_data in &decks {
|
||||
if !deck_data.depleted {
|
||||
deck_ids.push(deck_data.deck_id);
|
||||
}
|
||||
}
|
||||
for _i in 0..root_limit {
|
||||
let selected_index = rng.random_range(0..deck_ids.len());
|
||||
let selected_deck_id = deck_ids[selected_index];
|
||||
sampled_deck_ids.insert(selected_deck_id);
|
||||
deck_ids.swap_remove(selected_index);
|
||||
}
|
||||
}
|
||||
for deck_data in &mut decks {
|
||||
if self.limits.root_limit_reached(LimitKind::New) {
|
||||
do_continue = false;
|
||||
break;
|
||||
}
|
||||
if sampling && !sampled_deck_ids.contains(&deck_data.deck_id) {
|
||||
continue;
|
||||
}
|
||||
if deck_data.depleted {
|
||||
continue;
|
||||
}
|
||||
if let Some(card) = deck_data.cards.next() {
|
||||
if self.add_new_card(card) {
|
||||
self.limits
|
||||
.decrement_deck_and_parent_limits(deck_data.deck_id, LimitKind::New)?;
|
||||
do_continue = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn gather_new_cards_sorted(
|
||||
&mut self,
|
||||
col: &mut Collection,
|
||||
|
|
|
|||
Loading…
Reference in a new issue