Reading history data.
Time range to analyze.
Array of daily reading data points (date, chapters, count).
export function computeReadingTrends(
history: ReadingHistory,
timeRange: TimeRange,
): Array<{ date: string; chapters: number; count: number }> {
const filtered = filterHistoryByTimeRange(history, timeRange);
if (!filtered.length) return [];
// Establish baseline from pre-range history
const now = Date.now();
const ranges = {
"7d": 7 * 24 * 60 * 60 * 1000,
"30d": 30 * 24 * 60 * 60 * 1000,
"90d": 90 * 24 * 60 * 60 * 1000,
};
const cutoff = timeRange === "all" ? 0 : now - ranges[timeRange];
const preRangeBaseline =
timeRange === "all" ? new Map() : getPreRangeBaseline(history, cutoff);
// Group by date and calculate chapters read per day
const dailyMap = new Map<string, { chapters: number; count: number }>();
// Sort by timestamp to calculate deltas
const sorted = [...filtered].sort((a, b) => a.timestamp - b.timestamp);
// Track previous chapters per manga, seeded with pre-range baseline
const previousChapters = new Map<string | number, number>(preRangeBaseline);
for (const entry of sorted) {
const date = getDateKey(entry.timestamp);
const prev = previousChapters.get(entry.mangaId) ?? 0;
const delta = Math.max(0, entry.chaptersRead - prev);
const existing = dailyMap.get(date) ?? { chapters: 0, count: 0 };
dailyMap.set(date, {
chapters: existing.chapters + delta,
count: existing.count + (delta > 0 ? 1 : 0),
});
previousChapters.set(entry.mangaId, entry.chaptersRead);
}
// Convert to array and sort by date
return Array.from(dailyMap.entries())
.map(([date, data]) => ({ date, ...data }))
.sort((a, b) => a.date.localeCompare(b.date));
}
Computes daily reading trends with per-manga baseline from pre-range history to avoid inflated first-day deltas.