add LIFO sorting options for new cards
This commit is contained in:
parent
afaaa763ec
commit
410660990e
@ -97,18 +97,21 @@ deck-config-new-gather-priority-tooltip =
|
||||
to prioritize subdecks that are closer to the top.
|
||||
|
||||
`Position`: gathers cards from all decks before they are sorted. This
|
||||
ensures the oldest cards will be shown first, even if the parent limit is
|
||||
ensures cards appear in strict position order, even if the parent limit is
|
||||
not high enough to see cards from all decks.
|
||||
deck-config-new-gather-priority-deck = Deck
|
||||
deck-config-new-gather-priority-position = Position
|
||||
deck-config-new-gather-priority-position-lowest-first = Position (lowest first)
|
||||
deck-config-new-gather-priority-position-highest-first = Position (highest first)
|
||||
deck-config-new-card-sort-order = New card sort order
|
||||
deck-config-new-card-sort-order-tooltip =
|
||||
How cards are sorted after they have been gathered. By default, Anki sorts
|
||||
by card template first, to avoid multiple cards of the same note from being
|
||||
shown in succession.
|
||||
deck-config-sort-order-card-template-then-position = Card template, then position
|
||||
deck-config-sort-order-card-template-then-lowest-position = Card template, then lowest position
|
||||
deck-config-sort-order-card-template-then-highest-position = Card template, then highest position
|
||||
deck-config-sort-order-card-template-then-random = Card template, then random
|
||||
deck-config-sort-order-position = Position (siblings together)
|
||||
deck-config-sort-order-lowest-position = Lowest position
|
||||
deck-config-sort-order-highest-position = Highest position
|
||||
deck-config-sort-order-random = Random
|
||||
deck-config-new-review-priority = New/review priority
|
||||
deck-config-new-review-priority-tooltip = When to show new cards in relation to review cards.
|
||||
|
@ -320,13 +320,16 @@ message DeckConfig {
|
||||
}
|
||||
enum NewCardGatherPriority {
|
||||
NEW_CARD_GATHER_PRIORITY_DECK = 0;
|
||||
NEW_CARD_GATHER_PRIORITY_POSITION = 1;
|
||||
NEW_CARD_GATHER_PRIORITY_LOWEST_POSITION = 1;
|
||||
NEW_CARD_GATHER_PRIORITY_HIGHEST_POSITION = 2;
|
||||
}
|
||||
enum NewCardSortOrder {
|
||||
NEW_CARD_SORT_ORDER_TEMPLATE_THEN_DUE = 0;
|
||||
NEW_CARD_SORT_ORDER_TEMPLATE_THEN_RANDOM = 1;
|
||||
NEW_CARD_SORT_ORDER_DUE = 2;
|
||||
NEW_CARD_SORT_ORDER_RANDOM = 3;
|
||||
NEW_CARD_SORT_ORDER_TEMPLATE_THEN_LOWEST_POSITION = 0;
|
||||
NEW_CARD_SORT_ORDER_TEMPLATE_THEN_HIGHEST_POSITION = 1;
|
||||
NEW_CARD_SORT_ORDER_TEMPLATE_THEN_RANDOM = 2;
|
||||
NEW_CARD_SORT_ORDER_LOWEST_POSITION = 3;
|
||||
NEW_CARD_SORT_ORDER_HIGHEST_POSITION = 4;
|
||||
NEW_CARD_SORT_ORDER_RANDOM = 5;
|
||||
}
|
||||
enum ReviewCardOrder {
|
||||
REVIEW_CARD_ORDER_DAY = 0;
|
||||
|
@ -63,7 +63,7 @@ impl Default for DeckConfig {
|
||||
graduating_interval_easy: 4,
|
||||
new_card_insert_order: NewCardInsertOrder::Due as i32,
|
||||
new_card_gather_priority: NewCardGatherPriority::Deck as i32,
|
||||
new_card_sort_order: NewCardSortOrder::TemplateThenDue as i32,
|
||||
new_card_sort_order: NewCardSortOrder::TemplateThenLowestPosition as i32,
|
||||
review_order: ReviewCardOrder::Day as i32,
|
||||
new_mix: ReviewMix::MixWithReviews as i32,
|
||||
interday_learning_mix: ReviewMix::MixWithReviews as i32,
|
||||
|
@ -209,7 +209,7 @@ impl Collection {
|
||||
.unwrap_or_else(|| {
|
||||
// filtered decks do not space siblings
|
||||
QueueSortOptions {
|
||||
new_order: NewCardSortOrder::Due,
|
||||
new_order: NewCardSortOrder::LowestPosition,
|
||||
..Default::default()
|
||||
}
|
||||
});
|
||||
@ -272,25 +272,28 @@ impl Collection {
|
||||
}
|
||||
selected_deck_limits.new = selected_deck_limits.new.min(selected_deck_limits.review);
|
||||
let can_exit_early = sort_options.new_gather_priority == NewCardGatherPriority::Deck;
|
||||
let reverse = sort_options.new_gather_priority == NewCardGatherPriority::HighestPosition;
|
||||
for deck in &decks {
|
||||
if can_exit_early && selected_deck_limits.new == 0 {
|
||||
break;
|
||||
}
|
||||
let limit = remaining.get_mut(&deck.id).unwrap();
|
||||
if limit.new > 0 {
|
||||
self.storage.for_each_new_card_in_deck(deck.id, |card| {
|
||||
let bury = get_bury_mode(card.original_deck_id.or(deck.id));
|
||||
if limit.new != 0 {
|
||||
if queues.add_new_card(card, bury) {
|
||||
limit.new -= 1;
|
||||
selected_deck_limits.new = selected_deck_limits.new.saturating_sub(1);
|
||||
}
|
||||
self.storage
|
||||
.for_each_new_card_in_deck(deck.id, reverse, |card| {
|
||||
let bury = get_bury_mode(card.original_deck_id.or(deck.id));
|
||||
if limit.new != 0 {
|
||||
if queues.add_new_card(card, bury) {
|
||||
limit.new -= 1;
|
||||
selected_deck_limits.new =
|
||||
selected_deck_limits.new.saturating_sub(1);
|
||||
}
|
||||
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})?;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,14 +10,18 @@ use super::{NewCard, NewCardSortOrder, QueueBuilder};
|
||||
impl QueueBuilder {
|
||||
pub(super) fn sort_new(&mut self) {
|
||||
match self.sort_options.new_order {
|
||||
NewCardSortOrder::TemplateThenDue => {
|
||||
self.new.sort_unstable_by(template_then_due);
|
||||
NewCardSortOrder::TemplateThenLowestPosition => {
|
||||
self.new.sort_unstable_by(template_then_lowest_position);
|
||||
}
|
||||
NewCardSortOrder::TemplateThenHighestPosition => {
|
||||
self.new.sort_unstable_by(template_then_highest_position);
|
||||
}
|
||||
NewCardSortOrder::TemplateThenRandom => {
|
||||
self.new.iter_mut().for_each(NewCard::hash_id_and_mtime);
|
||||
self.new.sort_unstable_by(template_then_random);
|
||||
}
|
||||
NewCardSortOrder::Due => self.new.sort_unstable_by(new_position),
|
||||
NewCardSortOrder::LowestPosition => self.new.sort_unstable_by(lowest_position),
|
||||
NewCardSortOrder::HighestPosition => self.new.sort_unstable_by(highest_position),
|
||||
NewCardSortOrder::Random => {
|
||||
self.new.iter_mut().for_each(NewCard::hash_id_and_mtime);
|
||||
self.new.sort_unstable_by(new_hash)
|
||||
@ -26,18 +30,26 @@ impl QueueBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
fn template_then_due(a: &NewCard, b: &NewCard) -> Ordering {
|
||||
fn template_then_lowest_position(a: &NewCard, b: &NewCard) -> Ordering {
|
||||
(a.template_index, a.due).cmp(&(b.template_index, b.due))
|
||||
}
|
||||
|
||||
fn template_then_highest_position(a: &NewCard, b: &NewCard) -> Ordering {
|
||||
(a.template_index, b.due).cmp(&(b.template_index, a.due))
|
||||
}
|
||||
|
||||
fn template_then_random(a: &NewCard, b: &NewCard) -> Ordering {
|
||||
(a.template_index, a.hash).cmp(&(b.template_index, b.hash))
|
||||
}
|
||||
|
||||
fn new_position(a: &NewCard, b: &NewCard) -> Ordering {
|
||||
fn lowest_position(a: &NewCard, b: &NewCard) -> Ordering {
|
||||
a.due.cmp(&b.due)
|
||||
}
|
||||
|
||||
fn highest_position(a: &NewCard, b: &NewCard) -> Ordering {
|
||||
b.due.cmp(&a.due)
|
||||
}
|
||||
|
||||
fn new_hash(a: &NewCard, b: &NewCard) -> Ordering {
|
||||
a.hash.cmp(&b.hash)
|
||||
}
|
||||
|
@ -229,12 +229,21 @@ impl super::SqliteStorage {
|
||||
}
|
||||
|
||||
/// Call func() for each new card, stopping when it returns false
|
||||
/// or no more cards found. Cards will arrive in (deck_id, due) order.
|
||||
pub(crate) fn for_each_new_card_in_deck<F>(&self, deck: DeckId, mut func: F) -> Result<()>
|
||||
/// or no more cards found.
|
||||
pub(crate) fn for_each_new_card_in_deck<F>(
|
||||
&self,
|
||||
deck: DeckId,
|
||||
reverse: bool,
|
||||
mut func: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(NewCard) -> bool,
|
||||
{
|
||||
let mut stmt = self.db.prepare_cached(include_str!("new_cards.sql"))?;
|
||||
let mut stmt = self.db.prepare_cached(&format!(
|
||||
"{}{}",
|
||||
include_str!("new_cards.sql"),
|
||||
if reverse { " order by due desc" } else { "" }
|
||||
))?;
|
||||
let mut rows = stmt.query(params![deck])?;
|
||||
while let Some(row) = rows.next()? {
|
||||
if !func(NewCard {
|
||||
|
@ -15,12 +15,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
const newGatherPriorityChoices = [
|
||||
tr.deckConfigNewGatherPriorityDeck(),
|
||||
tr.deckConfigNewGatherPriorityPosition(),
|
||||
tr.deckConfigNewGatherPriorityPositionLowestFirst(),
|
||||
tr.deckConfigNewGatherPriorityPositionHighestFirst(),
|
||||
];
|
||||
const newSortOrderChoices = [
|
||||
tr.deckConfigSortOrderCardTemplateThenPosition(),
|
||||
tr.deckConfigSortOrderCardTemplateThenLowestPosition(),
|
||||
tr.deckConfigSortOrderCardTemplateThenHighestPosition(),
|
||||
tr.deckConfigSortOrderCardTemplateThenRandom(),
|
||||
tr.deckConfigSortOrderPosition(),
|
||||
tr.deckConfigSortOrderLowestPosition(),
|
||||
tr.deckConfigSortOrderHighestPosition(),
|
||||
tr.deckConfigSortOrderRandom(),
|
||||
];
|
||||
const reviewOrderChoices = [
|
||||
|
Loading…
Reference in New Issue
Block a user