diff --git a/rslib/src/stats/graphs/eases.rs b/rslib/src/stats/graphs/eases.rs index 27b59343f..f4a5092f5 100644 --- a/rslib/src/stats/graphs/eases.rs +++ b/rslib/src/stats/graphs/eases.rs @@ -15,7 +15,7 @@ impl GraphsContext { if let Some(state) = card.memory_state { *difficulty .eases - .entry(round_to_nearest_five(state.difficulty() * 100.0)) + .entry(percent_to_bin(state.difficulty() * 100.0)) .or_insert_with(Default::default) += 1; } else if matches!(card.ctype, CardType::Review | CardType::Relearn) { *eases @@ -28,8 +28,26 @@ impl GraphsContext { } } -pub(super) fn round_to_nearest_five(x: f32) -> u32 { - let scaled = x * 10.0; - let rounded = (scaled / 5.0).round() * 5.0; - (rounded / 10.0) as u32 +/// Bins the number into a bin of 0, 5, .. 95 +pub(super) fn percent_to_bin(x: f32) -> u32 { + if x == 100.0 { + 95 + } else { + ((x / 5.0).floor() * 5.0) as u32 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn bins() { + assert_eq!(percent_to_bin(0.0), 0); + assert_eq!(percent_to_bin(4.9), 0); + assert_eq!(percent_to_bin(5.0), 5); + assert_eq!(percent_to_bin(9.9), 5); + assert_eq!(percent_to_bin(99.9), 95); + assert_eq!(percent_to_bin(100.0), 95); + } } diff --git a/rslib/src/stats/graphs/retrievability.rs b/rslib/src/stats/graphs/retrievability.rs index c1ac3febd..7356b95c3 100644 --- a/rslib/src/stats/graphs/retrievability.rs +++ b/rslib/src/stats/graphs/retrievability.rs @@ -5,7 +5,7 @@ use anki_proto::stats::graphs_response::Retrievability; use fsrs::FSRS; use crate::scheduler::timing::SchedTimingToday; -use crate::stats::graphs::eases::round_to_nearest_five; +use crate::stats::graphs::eases::percent_to_bin; use crate::stats::graphs::GraphsContext; impl GraphsContext { @@ -26,7 +26,7 @@ impl GraphsContext { ); *retrievability .retrievability - .entry(round_to_nearest_five(r * 100.0)) + .entry(percent_to_bin(r * 100.0)) .or_insert_with(Default::default) += 1; } }