diff options
| -rw-r--r-- | src/lib/AniList/wrapped.ts | 47 | ||||
| -rw-r--r-- | src/lib/Tools/Wrapped.svelte | 10 |
2 files changed, 49 insertions, 8 deletions
diff --git a/src/lib/AniList/wrapped.ts b/src/lib/AniList/wrapped.ts index f9f3c409..1eeeeac2 100644 --- a/src/lib/AniList/wrapped.ts +++ b/src/lib/AniList/wrapped.ts @@ -1,6 +1,12 @@ import type { AniListAuthorisation, UserIdentity } from './identity'; import type { Media } from './media'; +export enum SortOptions { + SCORE, + MINUTES_WATCHED, + COUNT +} + export interface WrappedMediaFormat { startYears: { startYear: number; @@ -158,30 +164,40 @@ export interface TopMedia { topTagMedia: Media; } -export const tops = (media: Media[], amount: number, excludedKeywords: string[] = []): TopMedia => { - const genresMap: { [genre: string]: { totalScore: number; count: number } } = {}; - const tagsMap: { [tag: string]: { totalScore: number; count: number } } = {}; +export const tops = ( + media: Media[], + amount: number, + sortMode: SortOptions, + excludedKeywords: string[] = [] +): TopMedia => { + const genresMap: { + [genre: string]: { totalScore: number; count: number; minutesWatched: number }; + } = {}; + const tagsMap: { [tag: string]: { totalScore: number; count: number; minutesWatched: number } } = + {}; media.forEach((m) => { if (m.mediaListEntry && m.mediaListEntry.score) { m.genres.forEach((genre) => { - if (!genresMap[genre]) genresMap[genre] = { totalScore: 0, count: 0 }; + if (!genresMap[genre]) genresMap[genre] = { totalScore: 0, count: 0, minutesWatched: 0 }; const score = m.mediaListEntry?.score; if (score) { genresMap[genre].totalScore += score; + genresMap[genre].minutesWatched += m.duration; genresMap[genre].count++; } }); m.tags.forEach((tag) => { - if (!tagsMap[tag.name]) tagsMap[tag.name] = { totalScore: 0, count: 0 }; + if (!tagsMap[tag.name]) tagsMap[tag.name] = { totalScore: 0, count: 0, minutesWatched: 0 }; const score = m.mediaListEntry?.score; if (score) { tagsMap[tag.name].totalScore += score; + tagsMap[tag.name].minutesWatched += m.duration; tagsMap[tag.name].count++; } }); @@ -201,8 +217,25 @@ export const tops = (media: Media[], amount: number, excludedKeywords: string[] averageScore: Math.round(tagsMap[tag].totalScore / tagsMap[tag].count) })); - genres.sort((a, b) => b.averageScore - a.averageScore); - tags.sort((a, b) => b.averageScore - a.averageScore); + switch (sortMode) { + case SortOptions.SCORE: + genres = genres.sort((a, b) => b.averageScore - a.averageScore); + tags = tags.sort((a, b) => b.averageScore - a.averageScore); + + break; + case SortOptions.MINUTES_WATCHED: + genres = genres.sort( + (a, b) => genresMap[b.genre].minutesWatched - genresMap[a.genre].minutesWatched + ); + tags = tags.sort((a, b) => tagsMap[b.tag].minutesWatched - tagsMap[a.tag].minutesWatched); + + break; + case SortOptions.COUNT: + genres = genres.sort((a, b) => genresMap[b.genre].count - genresMap[a.genre].count); + tags = tags.sort((a, b) => tagsMap[b.tag].count - tagsMap[a.tag].count); + + break; + } genres = genres.slice(0, amount); tags = tags.slice(0, amount); diff --git a/src/lib/Tools/Wrapped.svelte b/src/lib/Tools/Wrapped.svelte index 4f05626f..2ec74a42 100644 --- a/src/lib/Tools/Wrapped.svelte +++ b/src/lib/Tools/Wrapped.svelte @@ -5,7 +5,7 @@ type AniListAuthorisation } from '$lib/AniList/identity'; import { onMount } from 'svelte'; - import { tops, wrapped, type TopMedia } from '$lib/AniList/wrapped'; + import { tops, wrapped, type TopMedia, SortOptions } from '$lib/AniList/wrapped'; import { fullActivityHistory, activityHistory as getActivityHistory @@ -58,6 +58,7 @@ let topMedia: TopMedia; let highestRatedMediaPercentage = true; let highestRatedGenreTagPercentage = true; + let genreTagsSort = SortOptions.SCORE; $: { if (browser && mounted) { @@ -108,6 +109,7 @@ topMedia = tops( [...(animeList || []), ...(mangaList || [])], genreTagCount, + genreTagsSort, excludedKeywords ); @@ -686,6 +688,12 @@ <a href={'#'} on:click={pruneFullYear}>Refresh data</a> </SettingHint><br /> <p /> + <select bind:value={genreTagsSort}> + <option value={SortOptions.SCORE}>Score</option> + <option value={SortOptions.MINUTES_WATCHED}>Minutes Watched</option> + <option value={SortOptions.COUNT}>Count</option> + </select> + Genre and tag sort<br /> <input type="checkbox" bind:checked={includeMusic} /> Include music<br /> <input type="checkbox" bind:checked={includeRepeats} /> Include rewatches & rereads<br /> |