mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
revert some interday learning changes in v3
Interday learning cards are now counted in the learning count again, and are no longer subject to the daily review limit. The thinking behind the original change was that interday learning cards are scheduled more like reviews, and counting them in the review count would allow the learning count to focus on intraday learning - the red number reflecting the fact that they are the most fragile memories. And counting them together made it practical to apply the review limit to both at once. Since the release, there have been a number of users expecting to see interday learning cards included in the learning count (the latest being https://forums.ankiweb.net/t/feedback-and-a-feature-adjustment-request-for-2-1-45/12308), and a good argument can be made for that too - they are, after all, listed in the learning steps, and do tend to be harder than reviews. Short of introducing another count to keep track of interday and intraday learning separately, moving back to the old behaviour seems like the best move. This also means it is not really practical to apply the review limit to interday learning cards anymore, as the limit would be split between two different numbers, and how much each number is capped would depend on the order cards are introduced. The scheduler could figure this out, but the deck list code does not know card order, and would need significant changes to be able to produce numbers that matched the scheduler. And even if we ignore implementation complexities, I think it would be more difficult for users to reason about - the influence of the review limit on new cards is confusing enough as it is.
This commit is contained in:
parent
272a610832
commit
8830d33826
13 changed files with 95 additions and 78 deletions
|
@ -317,11 +317,7 @@ def test_learn_day():
|
||||||
c.due -= 1
|
c.due -= 1
|
||||||
c.flush()
|
c.flush()
|
||||||
col.reset()
|
col.reset()
|
||||||
if is_2021():
|
assert col.sched.counts() == (0, 1, 0)
|
||||||
# it appears in the review queue
|
|
||||||
assert col.sched.counts() == (0, 0, 1)
|
|
||||||
else:
|
|
||||||
assert col.sched.counts() == (0, 1, 0)
|
|
||||||
c = col.sched.getCard()
|
c = col.sched.getCard()
|
||||||
# nextIvl should work
|
# nextIvl should work
|
||||||
assert ni(c, 3) == 86400 * 2
|
assert ni(c, 3) == 86400 * 2
|
||||||
|
|
|
@ -30,14 +30,12 @@ impl Collection {
|
||||||
days_elapsed: u32,
|
days_elapsed: u32,
|
||||||
learn_cutoff: u32,
|
learn_cutoff: u32,
|
||||||
limit_to: Option<&str>,
|
limit_to: Option<&str>,
|
||||||
v3: bool,
|
|
||||||
) -> Result<HashMap<DeckId, DueCounts>> {
|
) -> Result<HashMap<DeckId, DueCounts>> {
|
||||||
self.storage.due_counts(
|
self.storage.due_counts(
|
||||||
self.scheduler_version(),
|
self.scheduler_version(),
|
||||||
days_elapsed,
|
days_elapsed,
|
||||||
learn_cutoff,
|
learn_cutoff,
|
||||||
limit_to,
|
limit_to,
|
||||||
v3,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -277,7 +277,7 @@ impl Collection {
|
||||||
let learn_cutoff = (now.0 as u32) + self.learn_ahead_secs();
|
let learn_cutoff = (now.0 as u32) + self.learn_ahead_secs();
|
||||||
let sched_ver = self.scheduler_version();
|
let sched_ver = self.scheduler_version();
|
||||||
let v3 = self.get_config_bool(BoolKey::Sched2021);
|
let v3 = self.get_config_bool(BoolKey::Sched2021);
|
||||||
let counts = self.due_counts(days_elapsed, learn_cutoff, limit, v3)?;
|
let counts = self.due_counts(days_elapsed, learn_cutoff, limit)?;
|
||||||
let dconf = self.storage.get_deck_config_map()?;
|
let dconf = self.storage.get_deck_config_map()?;
|
||||||
add_counts(&mut tree, &counts);
|
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);
|
||||||
|
|
|
@ -315,7 +315,7 @@ impl Collection {
|
||||||
let mut review_delta = 0;
|
let mut review_delta = 0;
|
||||||
match from_queue {
|
match from_queue {
|
||||||
CardQueue::New => new_delta += 1,
|
CardQueue::New => new_delta += 1,
|
||||||
CardQueue::Review | CardQueue::DayLearn => review_delta += 1,
|
CardQueue::Review => review_delta += 1,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
self.update_deck_stats(
|
self.update_deck_stats(
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
use super::{BuryMode, DueCard, NewCard, QueueBuilder};
|
use super::{BuryMode, DueCard, NewCard, QueueBuilder};
|
||||||
use crate::{card::CardQueue, prelude::*};
|
use crate::{prelude::*, scheduler::queue::DueCardKind};
|
||||||
|
|
||||||
impl QueueBuilder {
|
impl QueueBuilder {
|
||||||
pub(in super::super) fn add_intraday_learning_card(
|
pub(in super::super) fn add_intraday_learning_card(
|
||||||
|
@ -15,12 +15,7 @@ impl QueueBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// True if limit should be decremented.
|
/// True if limit should be decremented.
|
||||||
pub(in super::super) fn add_due_card(
|
pub(in super::super) fn add_due_card(&mut self, card: DueCard, bury_mode: BuryMode) -> bool {
|
||||||
&mut self,
|
|
||||||
queue: CardQueue,
|
|
||||||
card: DueCard,
|
|
||||||
bury_mode: BuryMode,
|
|
||||||
) -> bool {
|
|
||||||
let bury_this_card = self
|
let bury_this_card = self
|
||||||
.get_and_update_bury_mode_for_note(card.note_id, bury_mode)
|
.get_and_update_bury_mode_for_note(card.note_id, bury_mode)
|
||||||
.map(|mode| mode.bury_reviews)
|
.map(|mode| mode.bury_reviews)
|
||||||
|
@ -28,14 +23,9 @@ impl QueueBuilder {
|
||||||
if bury_this_card {
|
if bury_this_card {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
match queue {
|
match card.kind {
|
||||||
CardQueue::DayLearn => {
|
DueCardKind::Review => self.review.push(card),
|
||||||
self.day_learning.push(card);
|
DueCardKind::Learning => self.day_learning.push(card),
|
||||||
}
|
|
||||||
CardQueue::Review => {
|
|
||||||
self.review.push(card);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
|
|
|
@ -19,7 +19,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Temporary holder for review cards that will be built into a queue.
|
/// Temporary holder for review cards that will be built into a queue.
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct DueCard {
|
pub(crate) struct DueCard {
|
||||||
pub id: CardId,
|
pub id: CardId,
|
||||||
pub note_id: NoteId,
|
pub note_id: NoteId,
|
||||||
|
@ -29,6 +29,13 @@ pub(crate) struct DueCard {
|
||||||
pub hash: u64,
|
pub hash: u64,
|
||||||
pub current_deck_id: DeckId,
|
pub current_deck_id: DeckId,
|
||||||
pub original_deck_id: DeckId,
|
pub original_deck_id: DeckId,
|
||||||
|
pub kind: DueCardKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub(crate) enum DueCardKind {
|
||||||
|
Review,
|
||||||
|
Learning,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Temporary holder for new cards that will be built into a queue.
|
/// Temporary holder for new cards that will be built into a queue.
|
||||||
|
@ -48,7 +55,10 @@ impl From<DueCard> for MainQueueEntry {
|
||||||
MainQueueEntry {
|
MainQueueEntry {
|
||||||
id: c.id,
|
id: c.id,
|
||||||
mtime: c.mtime,
|
mtime: c.mtime,
|
||||||
kind: MainQueueEntryKind::Review,
|
kind: match c.kind {
|
||||||
|
DueCardKind::Review => MainQueueEntryKind::Review,
|
||||||
|
DueCardKind::Learning => MainQueueEntryKind::InterdayLearning,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,25 +127,33 @@ impl QueueBuilder {
|
||||||
) -> CardQueues {
|
) -> CardQueues {
|
||||||
self.sort_new();
|
self.sort_new();
|
||||||
|
|
||||||
// intraday learning
|
// intraday learning and total learn count
|
||||||
let learning = sort_learning(self.learning);
|
let intraday_learning = sort_learning(self.learning);
|
||||||
let now = TimestampSecs::now();
|
let now = TimestampSecs::now();
|
||||||
let cutoff = now.adding_secs(learn_ahead_secs);
|
let cutoff = now.adding_secs(learn_ahead_secs);
|
||||||
let learn_count = learning.iter().take_while(|e| e.due <= cutoff).count();
|
let learn_count = intraday_learning
|
||||||
|
.iter()
|
||||||
|
.take_while(|e| e.due <= cutoff)
|
||||||
|
.count()
|
||||||
|
+ self.day_learning.len();
|
||||||
|
|
||||||
// merge interday learning into main, and cap to parent review count
|
// cap and note down review + new counts
|
||||||
let main_iter = merge_day_learning(
|
self.review.truncate(top_deck_limits.review as usize);
|
||||||
|
let review_count = self.review.len();
|
||||||
|
self.new.truncate(top_deck_limits.new as usize);
|
||||||
|
let new_count = self.new.len();
|
||||||
|
|
||||||
|
// merge interday and new cards into main
|
||||||
|
let with_interday_learn = merge_day_learning(
|
||||||
self.review,
|
self.review,
|
||||||
self.day_learning,
|
self.day_learning,
|
||||||
self.sort_options.day_learn_mix,
|
self.sort_options.day_learn_mix,
|
||||||
);
|
);
|
||||||
let main_iter = main_iter.take(top_deck_limits.review as usize);
|
let main_iter = merge_new(
|
||||||
let review_count = main_iter.len();
|
with_interday_learn,
|
||||||
|
self.new,
|
||||||
// cap to parent new count, note down the new count, then merge new in
|
self.sort_options.new_review_mix,
|
||||||
self.new.truncate(top_deck_limits.new as usize);
|
);
|
||||||
let new_count = self.new.len();
|
|
||||||
let main_iter = merge_new(main_iter, self.new, self.sort_options.new_review_mix);
|
|
||||||
|
|
||||||
CardQueues {
|
CardQueues {
|
||||||
counts: Counts {
|
counts: Counts {
|
||||||
|
@ -144,7 +162,7 @@ impl QueueBuilder {
|
||||||
learning: learn_count,
|
learning: learn_count,
|
||||||
},
|
},
|
||||||
main: main_iter.collect(),
|
main: main_iter.collect(),
|
||||||
intraday_learning: learning,
|
intraday_learning,
|
||||||
learn_ahead_secs,
|
learn_ahead_secs,
|
||||||
selected_deck,
|
selected_deck,
|
||||||
current_day,
|
current_day,
|
||||||
|
@ -192,7 +210,7 @@ impl Collection {
|
||||||
let now = TimestampSecs::now();
|
let now = TimestampSecs::now();
|
||||||
let timing = self.timing_for_timestamp(now)?;
|
let timing = self.timing_for_timestamp(now)?;
|
||||||
let decks = self.storage.deck_with_children(deck_id)?;
|
let decks = self.storage.deck_with_children(deck_id)?;
|
||||||
// need full map, since filtered decks may contain cards from decks/
|
// need full map, since filtered decks may contain cards from decks
|
||||||
// outside tree
|
// outside tree
|
||||||
let deck_map = self.storage.get_decks_map()?;
|
let deck_map = self.storage.get_decks_map()?;
|
||||||
let config = self.storage.get_deck_config_map()?;
|
let config = self.storage.get_deck_config_map()?;
|
||||||
|
@ -245,18 +263,31 @@ impl Collection {
|
||||||
queues.add_intraday_learning_card(card, bury)
|
queues.add_intraday_learning_card(card, bury)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// reviews and interday learning next
|
// interday learning
|
||||||
|
self.storage.for_each_due_card_in_active_decks(
|
||||||
|
timing.days_elapsed,
|
||||||
|
sort_options.review_order,
|
||||||
|
DueCardKind::Learning,
|
||||||
|
|card| {
|
||||||
|
let bury = get_bury_mode(card.original_deck_id.or(card.current_deck_id));
|
||||||
|
queues.add_due_card(card, bury);
|
||||||
|
true
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// reviews
|
||||||
if selected_deck_limits.review != 0 {
|
if selected_deck_limits.review != 0 {
|
||||||
self.storage.for_each_review_card_in_active_decks(
|
self.storage.for_each_due_card_in_active_decks(
|
||||||
timing.days_elapsed,
|
timing.days_elapsed,
|
||||||
sort_options.review_order,
|
sort_options.review_order,
|
||||||
|queue, card| {
|
DueCardKind::Review,
|
||||||
|
|card| {
|
||||||
if selected_deck_limits.review == 0 {
|
if selected_deck_limits.review == 0 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let bury = get_bury_mode(card.original_deck_id.or(card.current_deck_id));
|
let bury = get_bury_mode(card.original_deck_id.or(card.current_deck_id));
|
||||||
let limits = remaining.get_mut(&card.current_deck_id).unwrap();
|
let limits = remaining.get_mut(&card.current_deck_id).unwrap();
|
||||||
if limits.review != 0 && queues.add_due_card(queue, card, bury) {
|
if limits.review != 0 && queues.add_due_card(card, bury) {
|
||||||
selected_deck_limits.review -= 1;
|
selected_deck_limits.review -= 1;
|
||||||
limits.review -= 1;
|
limits.review -= 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ impl QueueEntry {
|
||||||
QueueEntry::Main(e) => match e.kind {
|
QueueEntry::Main(e) => match e.kind {
|
||||||
MainQueueEntryKind::New => QueueEntryKind::New,
|
MainQueueEntryKind::New => QueueEntryKind::New,
|
||||||
MainQueueEntryKind::Review => QueueEntryKind::Review,
|
MainQueueEntryKind::Review => QueueEntryKind::Review,
|
||||||
|
MainQueueEntryKind::InterdayLearning => QueueEntryKind::Learning,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,8 +181,8 @@ impl CardQueues {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adapted from the Rust stdlib VecDeque implementation; we can drop this when the following
|
/// Adapted from the Rust stdlib VecDeque implementation; we can drop this after updating
|
||||||
/// lands: https://github.com/rust-lang/rust/issues/78021
|
/// to Rust 1.54.0
|
||||||
fn binary_search_by<'a, F, T>(deque: &'a VecDeque<T>, mut f: F) -> Result<usize, usize>
|
fn binary_search_by<'a, F, T>(deque: &'a VecDeque<T>, mut f: F) -> Result<usize, usize>
|
||||||
where
|
where
|
||||||
F: FnMut(&'a T) -> Ordering,
|
F: FnMut(&'a T) -> Ordering,
|
||||||
|
|
|
@ -15,6 +15,7 @@ pub(crate) struct MainQueueEntry {
|
||||||
pub(crate) enum MainQueueEntryKind {
|
pub(crate) enum MainQueueEntryKind {
|
||||||
New,
|
New,
|
||||||
Review,
|
Review,
|
||||||
|
InterdayLearning,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CardQueues {
|
impl CardQueues {
|
||||||
|
@ -24,6 +25,7 @@ impl CardQueues {
|
||||||
match head.kind {
|
match head.kind {
|
||||||
MainQueueEntryKind::New => self.counts.new -= 1,
|
MainQueueEntryKind::New => self.counts.new -= 1,
|
||||||
MainQueueEntryKind::Review => self.counts.review -= 1,
|
MainQueueEntryKind::Review => self.counts.review -= 1,
|
||||||
|
MainQueueEntryKind::InterdayLearning => self.counts.learning -= 1,
|
||||||
};
|
};
|
||||||
head
|
head
|
||||||
})
|
})
|
||||||
|
@ -34,6 +36,7 @@ impl CardQueues {
|
||||||
match entry.kind {
|
match entry.kind {
|
||||||
MainQueueEntryKind::New => self.counts.new += 1,
|
MainQueueEntryKind::New => self.counts.new += 1,
|
||||||
MainQueueEntryKind::Review => self.counts.review += 1,
|
MainQueueEntryKind::Review => self.counts.review += 1,
|
||||||
|
MainQueueEntryKind::InterdayLearning => self.counts.learning += 1,
|
||||||
};
|
};
|
||||||
self.main.push_front(entry);
|
self.main.push_front(entry);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ pub(crate) mod undo;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
pub(crate) use builder::{DueCard, NewCard};
|
pub(crate) use builder::{DueCard, DueCardKind, NewCard};
|
||||||
pub(crate) use entry::{QueueEntry, QueueEntryKind};
|
pub(crate) use entry::{QueueEntry, QueueEntryKind};
|
||||||
pub(crate) use learning::LearningQueueEntry;
|
pub(crate) use learning::LearningQueueEntry;
|
||||||
pub(crate) use main::{MainQueueEntry, MainQueueEntryKind};
|
pub(crate) use main::{MainQueueEntry, MainQueueEntryKind};
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
SELECT queue,
|
SELECT id,
|
||||||
id,
|
|
||||||
nid,
|
nid,
|
||||||
due,
|
due,
|
||||||
cast(ivl AS integer),
|
cast(ivl AS integer),
|
||||||
|
@ -12,6 +11,6 @@ WHERE did IN (
|
||||||
FROM active_decks
|
FROM active_decks
|
||||||
)
|
)
|
||||||
AND (
|
AND (
|
||||||
queue IN (2, 3)
|
queue = ?
|
||||||
AND due <= ?
|
AND due <= ?
|
||||||
)
|
)
|
|
@ -20,7 +20,7 @@ use crate::{
|
||||||
notes::NoteId,
|
notes::NoteId,
|
||||||
scheduler::{
|
scheduler::{
|
||||||
congrats::CongratsInfo,
|
congrats::CongratsInfo,
|
||||||
queue::{DueCard, NewCard},
|
queue::{DueCard, DueCardKind, NewCard},
|
||||||
},
|
},
|
||||||
timestamp::{TimestampMillis, TimestampSecs},
|
timestamp::{TimestampMillis, TimestampSecs},
|
||||||
types::Usn,
|
types::Usn,
|
||||||
|
@ -184,20 +184,24 @@ impl super::SqliteStorage {
|
||||||
original_deck_id: row.get(5)?,
|
original_deck_id: row.get(5)?,
|
||||||
interval: 0,
|
interval: 0,
|
||||||
hash: 0,
|
hash: 0,
|
||||||
|
kind: DueCardKind::Learning,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn for_each_review_card_in_active_decks<F>(
|
/// Call func() for each review card or interday learning card, stopping
|
||||||
|
/// when it returns false or no more cards found.
|
||||||
|
pub(crate) fn for_each_due_card_in_active_decks<F>(
|
||||||
&self,
|
&self,
|
||||||
day_cutoff: u32,
|
day_cutoff: u32,
|
||||||
order: ReviewCardOrder,
|
order: ReviewCardOrder,
|
||||||
|
kind: DueCardKind,
|
||||||
mut func: F,
|
mut func: F,
|
||||||
) -> Result<()>
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
F: FnMut(CardQueue, DueCard) -> bool,
|
F: FnMut(DueCard) -> bool,
|
||||||
{
|
{
|
||||||
let order_clause = review_order_sql(order);
|
let order_clause = review_order_sql(order);
|
||||||
let mut stmt = self.db.prepare_cached(&format!(
|
let mut stmt = self.db.prepare_cached(&format!(
|
||||||
|
@ -205,22 +209,23 @@ impl super::SqliteStorage {
|
||||||
include_str!("due_cards.sql"),
|
include_str!("due_cards.sql"),
|
||||||
order_clause
|
order_clause
|
||||||
))?;
|
))?;
|
||||||
let mut rows = stmt.query(params![day_cutoff])?;
|
let queue = match kind {
|
||||||
|
DueCardKind::Review => CardQueue::Review,
|
||||||
|
DueCardKind::Learning => CardQueue::DayLearn,
|
||||||
|
};
|
||||||
|
let mut rows = stmt.query(params![queue as i8, day_cutoff])?;
|
||||||
while let Some(row) = rows.next()? {
|
while let Some(row) = rows.next()? {
|
||||||
let queue: CardQueue = row.get(0)?;
|
if !func(DueCard {
|
||||||
if !func(
|
id: row.get(0)?,
|
||||||
queue,
|
note_id: row.get(1)?,
|
||||||
DueCard {
|
due: row.get(2).ok().unwrap_or_default(),
|
||||||
id: row.get(1)?,
|
interval: row.get(3)?,
|
||||||
note_id: row.get(2)?,
|
mtime: row.get(4)?,
|
||||||
due: row.get(3).ok().unwrap_or_default(),
|
current_deck_id: row.get(5)?,
|
||||||
interval: row.get(4)?,
|
original_deck_id: row.get(6)?,
|
||||||
mtime: row.get(5)?,
|
hash: 0,
|
||||||
current_deck_id: row.get(6)?,
|
kind,
|
||||||
original_deck_id: row.get(7)?,
|
}) {
|
||||||
hash: 0,
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,18 +38,13 @@ fn row_to_deck(row: &Row) -> Result<Deck> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn row_to_due_counts(row: &Row, v3: bool) -> Result<(DeckId, DueCounts)> {
|
fn row_to_due_counts(row: &Row) -> Result<(DeckId, DueCounts)> {
|
||||||
let deck_id = row.get(0)?;
|
let deck_id = row.get(0)?;
|
||||||
let new = row.get(1)?;
|
let new = row.get(1)?;
|
||||||
let mut review = row.get(2)?;
|
let review = row.get(2)?;
|
||||||
let interday: u32 = row.get(3)?;
|
let interday: u32 = row.get(3)?;
|
||||||
let intraday: u32 = row.get(4)?;
|
let intraday: u32 = row.get(4)?;
|
||||||
let learning = if v3 {
|
let learning = intraday + interday;
|
||||||
review += interday;
|
|
||||||
intraday
|
|
||||||
} else {
|
|
||||||
intraday + interday
|
|
||||||
};
|
|
||||||
Ok((
|
Ok((
|
||||||
deck_id,
|
deck_id,
|
||||||
DueCounts {
|
DueCounts {
|
||||||
|
@ -265,7 +260,6 @@ impl SqliteStorage {
|
||||||
day_cutoff: u32,
|
day_cutoff: u32,
|
||||||
learn_cutoff: u32,
|
learn_cutoff: u32,
|
||||||
top_deck: Option<&str>,
|
top_deck: Option<&str>,
|
||||||
v3: bool,
|
|
||||||
) -> Result<HashMap<DeckId, DueCounts>> {
|
) -> Result<HashMap<DeckId, DueCounts>> {
|
||||||
let sched_ver = sched as u8;
|
let sched_ver = sched as u8;
|
||||||
let mut params = named_params! {
|
let mut params = named_params! {
|
||||||
|
@ -306,7 +300,7 @@ impl SqliteStorage {
|
||||||
|
|
||||||
self.db
|
self.db
|
||||||
.prepare_cached(sql)?
|
.prepare_cached(sql)?
|
||||||
.query_and_then(&*params, |row| row_to_due_counts(row, v3))?
|
.query_and_then(&*params, |row| row_to_due_counts(row))?
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue