mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-20 12:11:28 -07:00
chore: apply remaining workspace formatting and updates
This commit is contained in:
@@ -1,7 +1,13 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import type { DailyRollup, OverviewData, SessionSummary, StreakCalendarDay, VocabularyEntry } from '../types/stats';
|
||||
import type {
|
||||
DailyRollup,
|
||||
OverviewData,
|
||||
SessionSummary,
|
||||
StreakCalendarDay,
|
||||
VocabularyEntry,
|
||||
} from '../types/stats';
|
||||
import {
|
||||
buildOverviewSummary,
|
||||
buildStreakCalendar,
|
||||
@@ -49,7 +55,14 @@ test('buildOverviewSummary aggregates tracked totals and recent windows', () =>
|
||||
const overview: OverviewData = {
|
||||
sessions,
|
||||
rollups,
|
||||
hints: { totalSessions: 1, activeSessions: 0, episodesToday: 2, activeAnimeCount: 3, totalEpisodesWatched: 5, totalAnimeCompleted: 1 },
|
||||
hints: {
|
||||
totalSessions: 1,
|
||||
activeSessions: 0,
|
||||
episodesToday: 2,
|
||||
activeAnimeCount: 3,
|
||||
totalEpisodesWatched: 5,
|
||||
totalAnimeCompleted: 1,
|
||||
},
|
||||
};
|
||||
|
||||
const summary = buildOverviewSummary(overview, now);
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import type { DailyRollup, KanjiEntry, OverviewData, StreakCalendarDay, VocabularyEntry } from '../types/stats';
|
||||
import type {
|
||||
DailyRollup,
|
||||
KanjiEntry,
|
||||
OverviewData,
|
||||
StreakCalendarDay,
|
||||
VocabularyEntry,
|
||||
} from '../types/stats';
|
||||
import { epochDayToDate, localDayFromMs } from './formatters';
|
||||
|
||||
export interface ChartPoint {
|
||||
@@ -110,7 +116,9 @@ function buildAggregatedDailyRows(rollups: DailyRollup[]) {
|
||||
averageSessionMinutes:
|
||||
value.sessions > 0 ? +(value.activeMin / value.sessions).toFixed(1) : 0,
|
||||
lookupHitRate:
|
||||
value.lookupWeight > 0 ? Math.round((value.lookupHitRateSum / value.lookupWeight) * 100) : 0,
|
||||
value.lookupWeight > 0
|
||||
? Math.round((value.lookupHitRateSum / value.lookupWeight) * 100)
|
||||
: 0,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -142,7 +150,10 @@ export function buildOverviewSummary(
|
||||
|
||||
return {
|
||||
todayActiveMs: Math.max(todayActiveFromRollup, todayActiveFromSessions),
|
||||
todayCards: Math.max(todayRow?.cards ?? 0, sumBy(todaySessions, (session) => session.cardsMined)),
|
||||
todayCards: Math.max(
|
||||
todayRow?.cards ?? 0,
|
||||
sumBy(todaySessions, (session) => session.cardsMined),
|
||||
),
|
||||
streakDays,
|
||||
allTimeHours: Math.round(sumBy(aggregated, (row) => row.activeMin) / 60),
|
||||
totalTrackedCards: Math.max(sessionCards, rollupCards),
|
||||
@@ -152,17 +163,21 @@ export function buildOverviewSummary(
|
||||
totalAnimeCompleted: overview.hints.totalAnimeCompleted ?? 0,
|
||||
averageSessionMinutes:
|
||||
overview.sessions.length > 0
|
||||
? Math.round(sumBy(overview.sessions, (session) => session.activeWatchedMs) / overview.sessions.length / 60_000)
|
||||
? Math.round(
|
||||
sumBy(overview.sessions, (session) => session.activeWatchedMs) /
|
||||
overview.sessions.length /
|
||||
60_000,
|
||||
)
|
||||
: 0,
|
||||
totalSessions: overview.hints.totalSessions,
|
||||
activeDays: daysWithActivity.size,
|
||||
recentWatchTime: aggregated.slice(-14).map((row) => ({ label: row.label, value: row.activeMin })),
|
||||
recentWatchTime: aggregated
|
||||
.slice(-14)
|
||||
.map((row) => ({ label: row.label, value: row.activeMin })),
|
||||
};
|
||||
}
|
||||
|
||||
export function buildTrendDashboard(
|
||||
rollups: DailyRollup[],
|
||||
): TrendDashboard {
|
||||
export function buildTrendDashboard(rollups: DailyRollup[]): TrendDashboard {
|
||||
const aggregated = buildAggregatedDailyRows(rollups);
|
||||
return {
|
||||
watchTime: aggregated.map((row) => ({ label: row.label, value: row.activeMin })),
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
import type {
|
||||
OverviewData, DailyRollup, MonthlyRollup,
|
||||
SessionSummary, SessionTimelinePoint, SessionEvent,
|
||||
VocabularyEntry, KanjiEntry,
|
||||
OverviewData,
|
||||
DailyRollup,
|
||||
MonthlyRollup,
|
||||
SessionSummary,
|
||||
SessionTimelinePoint,
|
||||
SessionEvent,
|
||||
VocabularyEntry,
|
||||
KanjiEntry,
|
||||
VocabularyOccurrenceEntry,
|
||||
MediaLibraryItem, MediaDetailData,
|
||||
AnimeLibraryItem, AnimeDetailData, AnimeWord,
|
||||
StreakCalendarDay, EpisodesPerDay, NewAnimePerDay, WatchTimePerAnime,
|
||||
WordDetailData, KanjiDetailData,
|
||||
MediaLibraryItem,
|
||||
MediaDetailData,
|
||||
AnimeLibraryItem,
|
||||
AnimeDetailData,
|
||||
AnimeWord,
|
||||
StreakCalendarDay,
|
||||
EpisodesPerDay,
|
||||
NewAnimePerDay,
|
||||
WatchTimePerAnime,
|
||||
WordDetailData,
|
||||
KanjiDetailData,
|
||||
EpisodeDetailData,
|
||||
} from '../types/stats';
|
||||
|
||||
@@ -47,7 +59,9 @@ interface StatsElectronAPI {
|
||||
getKanjiDetail: (kanjiId: number) => Promise<KanjiDetailData>;
|
||||
getEpisodeDetail: (videoId: number) => Promise<EpisodeDetailData>;
|
||||
ankiBrowse: (noteId: number) => Promise<void>;
|
||||
ankiNotesInfo: (noteIds: number[]) => Promise<Array<{ noteId: number; fields: Record<string, { value: string }> }>>;
|
||||
ankiNotesInfo: (
|
||||
noteIds: number[],
|
||||
) => Promise<Array<{ noteId: number; fields: Record<string, { value: string }> }>>;
|
||||
hideOverlay: () => void;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user