Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FSRS wrongly converts a card to interday learning card? #3712

Open
user1823 opened this issue Jan 10, 2025 · 10 comments
Open

FSRS wrongly converts a card to interday learning card? #3712

user1823 opened this issue Jan 10, 2025 · 10 comments

Comments

@user1823
Copy link
Contributor

@L-M-Sherlock

I am using fsrs_short_term_with_steps. Many times, I notice that after a review, FSRS converts a intraday learning card into a interday learning card.

But, if the interval is 1d or more, shouldn't it simply convert the card to a review card?

Card info of one such card:

This is currently a interday learning card with a 1d interval.

@L-M-Sherlock
Copy link
Contributor

L-M-Sherlock commented Jan 15, 2025

According to the code, if the interval is greater than 0.5 day, the short_term is false, so the next stats should be ReviewState.

let (interval, short_term) = if let Some(states) = &ctx.fsrs_next_states {
(
states.good.interval,
(ctx.fsrs_short_term_with_steps_enabled || ctx.steps.is_empty())
&& states.good.interval < 0.5,
)
} else {
(ctx.graduating_interval_good as f32, false)
};
if short_term {
LearnState {
scheduled_secs: (interval * 86_400.0) as u32,
elapsed_secs: 0,
memory_state,
..self
}
.into()
} else {
ReviewState {
scheduled_days: ctx.with_review_fuzz(
interval.round().max(1.0),
minimum,
maximum,
),
ease_factor: ctx.initial_ease_factor,
memory_state,
..Default::default()
}
.into()
}

How did you know that the card is a interday learning card?

@L-M-Sherlock
Copy link
Contributor

I cannot reproduce this issue:

Image Image

@user1823
Copy link
Contributor Author

user1823 commented Jan 15, 2025

How did you know that the card is a interday learning card?

Because it appears as red in the deck picker and has an interval of 1d. I also verified that it has type = 1 in the database.

I can share the card from the backup created on 10th Jan. I don't have a backup before the last rating in the above screenshot.

After.apkg.zip

Parameters:
2.4860, 8.1461, 48.3187, 73.8801, 7.1577, 0.9967, 3.9325, 0.0010, 1.9119, 0.3130, 1.4081, 2.0449, 0.0167, 0.3757, 2.3958, 0.0000, 6.0000, 0.7905, 0.6943

Desired retention: 0.94

Edit:
I tried to reconstruct the "before" card by deleting the last revlog entry using debug console and then recalculating the memory states.

Before.apkg.zip

@L-M-Sherlock
Copy link
Contributor

I'm sorry but I cannot reproduce the bug. I tried to increase the desired retention to 0.99 and press good in the card. After several pressing, the card is converted to a review card.

@user1823
Copy link
Contributor Author

Ok, then let me guess.

For a stability of 14h and DR = 0.94, FSRS would have calculated an interval of about 8 hours. Since this is less than 0.5d, short_term would be true. But, at 23:12, the time left for day turnover (04:00) was only 4h and 48 min. So, Anki converted the interval to 1d.

@user1823
Copy link
Contributor Author

user1823 commented Jan 15, 2025

Ok, I ran the following commands in the debug console to regenerate the "before" card after deleting the revlogs and updating the memory states.

mw.col.db.execute("update cards set due=1736444160 where id = 1736346558840")
mw.col.db.execute("update cards set ivl=0 where id = 1736346558840")
mw.col.db.execute("update cards set queue=1 where id = 1736346558840")

Here's the result: Before.apkg.zip

To reproduce the issue, set your device time to 01:40 (night) on 10th Jan (Shanghai time). Launch Anki and set "next day starts at" to 6:30 (Shanghai time) (not really required because the default value will also reproduce the issue) and then rate Good.

Upon rating the card with the above steps, I get the following:

due = 1525
ivl = 0
queue = 3
type = 1
left = 1

So, in this case, Anki is indeed converting the intraday learning card (queue = 1) to an interday learning card (queue = 3).

@L-M-Sherlock
Copy link
Contributor

So, what's the expected behavior here? Should Anki keep the card in learning or convert it to review?

@user1823
Copy link
Contributor Author

user1823 commented Jan 15, 2025

If it remains a intraday learning card (queue = 1), would FSRS be able to know that I rated it on the next day so that it can calculate the next interval accordingly?

If yes, keep it as an intraday learning card.

If not, convert to review card.

My main problem with the current behaviour is that on the next day, this card has a very low R but it doesn't show up in the early part of the reviews (even with ascending R sort order) because Anki is trying to shuffle interday learning and review cards evenly.

@user1823
Copy link
Contributor Author

Spitballing, instead of changing the behaviour of FSRS, we can also solve this issue (and possibly others) by treating the interday learning cards and review cards in the same way during review sorting if Interday learning/review order is set to Mix with reviews

@L-M-Sherlock
Copy link
Contributor

If it remains a intraday learning card (queue = 1), would FSRS be able to know that I rated it on the next day so that it can calculate the next interval accordingly?

Yes. FSRS treats it as a review card if you review it in the next day.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants