diff --git a/scripts/statistics.js b/scripts/statistics.js index 83e042d..6401cc3 100644 --- a/scripts/statistics.js +++ b/scripts/statistics.js @@ -648,6 +648,24 @@ const seriesWatched = list.filter((p) => p.percentage === 100).length; const episodesWatched = list.reduce((total, p) => total + (p.watchedCount || 0), 0); const moviesWatched = (movies || []).length; + + let totalTicks = 0; + (movies || []).forEach((movie) => { + totalTicks += Number(movie.RunTimeTicks) || 0; + }); + list.forEach((progress) => { + const source = Array.isArray(progress.episodes) && progress.episodes.length + ? progress.episodes + : (progress.playEvents || []); + source.forEach((ep) => { + const key = ep?.UserData?.LastPlayedDate || ep?.LastPlayedDate; + const played = ep?.UserData ? ep.UserData.Played === true : !!key; + if (!played) return; + totalTicks += Number(ep.RunTimeTicks) || 0; + }); + }); + const hoursWatched = Math.round(totalTicks / 10000000 / 3600); + const topShows = list .map((progress) => ({ name: progress.series?.Name || 'Unknown', @@ -663,7 +681,7 @@ }) .slice(0, 5); - return { seriesStarted, seriesWatched, episodesWatched, moviesWatched, topShows }; + return { seriesStarted, seriesWatched, episodesWatched, moviesWatched, hoursWatched, topShows }; } function updateSummaryCards(root, stats) { @@ -675,6 +693,7 @@ setText('stat-series-watched', stats.seriesWatched); setText('stat-episodes-watched', stats.episodesWatched); setText('stat-movies-watched', stats.moviesWatched); + setText('stat-hours-watched', stats.hoursWatched); const topShowsList = root.querySelector('#top-shows-list') || document.getElementById('top-shows-list'); if (!topShowsList) return; @@ -967,7 +986,7 @@ renderFavoritesList(root, computeFavoriteRecents(progressList, movieList)); resizeCharts(); - LOG(`Statistics updated: ${summary.seriesStarted} started, ${summary.seriesWatched} watched, ${summary.episodesWatched} episodes, ${summary.moviesWatched} movies`); + LOG(`Statistics updated: ${summary.seriesStarted} started, ${summary.seriesWatched} watched, ${summary.episodesWatched} episodes, ${summary.moviesWatched} movies, ${summary.hoursWatched} hours`); } function resizeCharts() { diff --git a/scripts/watchlist.js b/scripts/watchlist.js index 31110fa..7bea8a1 100644 --- a/scripts/watchlist.js +++ b/scripts/watchlist.js @@ -2747,6 +2747,25 @@ In the Custom Tabs plugin, add a new tab with the following HTML content: } // Statistics calculation functions + function sumWatchedRuntimeHours(progressData, movies) { + let totalTicks = 0; + (movies || []).forEach((movie) => { + totalTicks += Number(movie.RunTimeTicks) || 0; + }); + (progressData || []).forEach((progress) => { + const source = Array.isArray(progress.episodes) && progress.episodes.length + ? progress.episodes + : (progress.playEvents || []); + source.forEach((ep) => { + const key = ep?.UserData?.LastPlayedDate || ep?.LastPlayedDate; + const played = ep?.UserData ? ep.UserData.Played === true : !!key; + if (!played) return; + totalTicks += Number(ep.RunTimeTicks) || 0; + }); + }); + return Math.round(totalTicks / 10000000 / 3600); + } + async function calculateProgressStatistics(progressData) { if (!progressData || progressData.length === 0) { // Still try to get movie count even if no series data @@ -2756,6 +2775,7 @@ In the Custom Tabs plugin, add a new tab with the following HTML content: seriesWatched: 0, episodesWatched: 0, moviesWatched: movieCache.data.length, + hoursWatched: sumWatchedRuntimeHours([], movieCache.data), topShows: [] }; } @@ -2768,6 +2788,7 @@ In the Custom Tabs plugin, add a new tab with the following HTML content: // Get movie count from cache await fetchWatchedMovies(true); // Use cached data const moviesWatched = movieCache.data.length; + const hoursWatched = sumWatchedRuntimeHours(progressData, movieCache.data); // Calculate top 5 shows by completion percentage, then by episode count const topShows = progressData @@ -2794,6 +2815,7 @@ In the Custom Tabs plugin, add a new tab with the following HTML content: seriesWatched, episodesWatched, moviesWatched, + hoursWatched, topShows }; } @@ -2806,16 +2828,18 @@ In the Custom Tabs plugin, add a new tab with the following HTML content: const seriesWatchedEl = getElementByIdSafe('stat-series-watched'); const episodesWatchedEl = getElementByIdSafe('stat-episodes-watched'); const moviesWatchedEl = getElementByIdSafe('stat-movies-watched'); + const hoursWatchedEl = getElementByIdSafe('stat-hours-watched'); if (seriesStartedEl) seriesStartedEl.textContent = stats.seriesStarted.toLocaleString(); if (seriesWatchedEl) seriesWatchedEl.textContent = stats.seriesWatched.toLocaleString(); if (episodesWatchedEl) episodesWatchedEl.textContent = stats.episodesWatched.toLocaleString(); if (moviesWatchedEl) moviesWatchedEl.textContent = stats.moviesWatched.toLocaleString(); + if (hoursWatchedEl) hoursWatchedEl.textContent = stats.hoursWatched.toLocaleString(); // Update top shows list updateTopShowsList(stats.topShows); - LOG(`Statistics updated: ${stats.seriesStarted} started, ${stats.seriesWatched} watched, ${stats.episodesWatched} episodes, ${stats.moviesWatched} movies`); + LOG(`Statistics updated: ${stats.seriesStarted} started, ${stats.seriesWatched} watched, ${stats.episodesWatched} episodes, ${stats.moviesWatched} movies, ${stats.hoursWatched} hours`); } function updateTopShowsList(topShows) { @@ -3450,11 +3474,11 @@ In the Custom Tabs plugin, add a new tab with the following HTML content:
- +
-
0
-
Series Started
+
0
+
Movies Watched
@@ -3477,11 +3501,20 @@ In the Custom Tabs plugin, add a new tab with the following HTML content:
- +
-
0
-
Movies Watched
+
0
+
Series Started
+
+
+
+
+ +
+
+
0
+
Hours Watched