diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 19bbc0603..fa8a8f700 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -118,6 +118,7 @@ yellowjello Ingemar Berg Ben Kerman Euan Kemp +Kieran Black ******************** diff --git a/proto/anki/stats.proto b/proto/anki/stats.proto index a800b33ae..8e1ca8566 100644 --- a/proto/anki/stats.proto +++ b/proto/anki/stats.proto @@ -141,6 +141,7 @@ message GraphsResponse { FutureDue future_due = 7; Added added = 8; ReviewCountsAndTimes reviews = 9; + uint32 rollover_hour = 10; } message GraphPreferences { diff --git a/qt/aqt/about.py b/qt/aqt/about.py index 3c7241385..c795c74b6 100644 --- a/qt/aqt/about.py +++ b/qt/aqt/about.py @@ -230,6 +230,7 @@ def show(mw: aqt.AnkiQt) -> QDialog: "hafatsat anki", "Carlos Duarte", "Edgar Benavent CatalĂ ", + "Kieran Black", ) ) diff --git a/rslib/src/stats/graphs/mod.rs b/rslib/src/stats/graphs/mod.rs index 38d482437..a25ad9e8a 100644 --- a/rslib/src/stats/graphs/mod.rs +++ b/rslib/src/stats/graphs/mod.rs @@ -71,6 +71,7 @@ impl Collection { hours: Some(ctx.hours()), buttons: Some(ctx.buttons()), card_counts: Some(ctx.card_counts()), + rollover_hour: self.rollover_for_current_scheduler()? as u32, }; Ok(resp) } diff --git a/ts/graphs/calendar.ts b/ts/graphs/calendar.ts index ae9cab3e4..51506e454 100644 --- a/ts/graphs/calendar.ts +++ b/ts/graphs/calendar.ts @@ -5,6 +5,7 @@ import * as tr from "@tslib/ftl"; import { localizedDate, weekdayLabel } from "@tslib/i18n"; import { Stats } from "@tslib/proto"; import type { CountableTimeInterval } from "d3"; +import { timeHour } from "d3"; import { interpolateBlues, pointer, @@ -29,6 +30,7 @@ export interface GraphData { reviewCount: Map; timeFunction: CountableTimeInterval; weekdayLabels: number[]; + rolloverHour: number; } interface DayDatum { @@ -59,7 +61,7 @@ export function gatherData( weekdayLabels.push((firstDayOfWeek + i) % 7); } - return { reviewCount, timeFunction, weekdayLabels }; + return { reviewCount, timeFunction, weekdayLabels, rolloverHour: data.rolloverHour }; } export function renderCalendar( @@ -85,7 +87,9 @@ export function renderCalendar( const dayMap: Map = new Map(); let maxCount = 0; for (const [day, count] of sourceData.reviewCount.entries()) { - const date = new Date(now.getTime() + day * 86400 * 1000); + let date = timeDay.offset(now, day); + // anki day does not necessarily roll over at midnight, we account for this when mapping onto calendar days + date = timeHour.offset(date, -1 * sourceData.rolloverHour); if (count > maxCount) { maxCount = count; } @@ -105,12 +109,12 @@ export function renderCalendar( setDataAvailable(svg, true); } - // fill in any blanks + // fill in any blanks, including the current calendar day even if the anki day has not rolled over const startDate = timeYear(nowForYear); const oneYearAgoFromNow = new Date(now); oneYearAgoFromNow.setFullYear(now.getFullYear() - 1); for (let i = 0; i < 365; i++) { - const date = new Date(startDate.getTime() + i * 86400 * 1000); + const date = timeDay.offset(startDate, i); if (date > now) { // don't fill out future dates continue;