diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/AniList/media.ts | 4 | ||||
| -rw-r--r-- | src/lib/AniList/wrapped.ts | 76 | ||||
| -rw-r--r-- | src/lib/Tools/Wrapped.svelte | 85 |
3 files changed, 128 insertions, 37 deletions
diff --git a/src/lib/AniList/media.ts b/src/lib/AniList/media.ts index 52d7da85..3fdd54dc 100644 --- a/src/lib/AniList/media.ts +++ b/src/lib/AniList/media.ts @@ -87,7 +87,9 @@ export const flattenLists = ( self.findIndex((itemToCompare) => itemToCompare.id === item.id) === index ); - if (!all) { + if (all) { + for (const list of lists) flattenedList.push(...list.entries.map((entry) => entry.media)); + } else { for (const list of lists) { if (list.name.toLowerCase().includes('#dueinclude')) { dueInclude = true; diff --git a/src/lib/AniList/wrapped.ts b/src/lib/AniList/wrapped.ts index 35ce7554..40a81957 100644 --- a/src/lib/AniList/wrapped.ts +++ b/src/lib/AniList/wrapped.ts @@ -1,4 +1,5 @@ import type { AniListAuthorisation, UserIdentity } from './identity'; +import type { Media } from './media'; export interface WrappedMediaFormat { startYears: { @@ -143,3 +144,78 @@ export const wrapped = async ( avatar: wrappedResponse['data']['User']['avatar'] }; }; + +export interface TopMedia { + genres: { + genre: string; + averageScore: number; + }[]; + tags: { + tag: string; + averageScore: number; + }[]; + topGenreMedia: Media; + topTagMedia: Media; +} + +export const tops = (media: Media[], amount: number): TopMedia => { + const genresMap: { [genre: string]: { totalScore: number; count: number } } = {}; + const tagsMap: { [tag: string]: { totalScore: number; count: number } } = {}; + + media.forEach((m) => { + if (m.mediaListEntry && m.mediaListEntry.score) { + m.genres.forEach((genre) => { + if (!genresMap[genre]) genresMap[genre] = { totalScore: 0, count: 0 }; + + const score = m.mediaListEntry?.score; + + if (score) { + genresMap[genre].totalScore += score; + genresMap[genre].count++; + } + }); + + m.tags.forEach((tag) => { + if (!tagsMap[tag.name]) tagsMap[tag.name] = { totalScore: 0, count: 0 }; + + const score = m.mediaListEntry?.score; + + if (score) { + tagsMap[tag.name].totalScore += score; + tagsMap[tag.name].count++; + } + }); + } + }); + + // const limitNumber = (n: number) => { + // const formatted = Number(n).toFixed(2); + + // return formatted.endsWith('00') ? Number(formatted).toString() : formatted; + // }; + + let genres = Object.keys(genresMap).map((genre) => ({ + genre, + averageScore: Math.round(genresMap[genre].totalScore / genresMap[genre].count) + })); + let tags = Object.keys(tagsMap).map((tag) => ({ + tag, + averageScore: Math.round(tagsMap[tag].totalScore / tagsMap[tag].count) + })); + + genres = genres.slice(0, amount); + tags = tags.slice(0, amount); + + const topGenreMedia = media.find((m) => m.genres.includes(genres[0].genre)) || media[0]; + const topTagMedia = media.find((m) => m.tags.some((tag) => tag.name === tags[0].tag)) || media[0]; + + // if (topGenreMedia.id === topTagMedia.id) + // topTagMedia = media.find((m) => m.id !== topGenreMedia.id) || media[1]; + + return { + genres, + tags, + topGenreMedia, + topTagMedia + }; +}; diff --git a/src/lib/Tools/Wrapped.svelte b/src/lib/Tools/Wrapped.svelte index 6c7e16d1..0e8ad66d 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 { wrapped } from '$lib/AniList/wrapped.js'; + import { tops, wrapped, type TopMedia } from '$lib/AniList/wrapped.js'; import { fullActivityHistory, activityHistory as getActivityHistory @@ -51,6 +51,7 @@ let excludedKeywords: string[] = []; let useFullActivityHistory = false; let topGenresTags = true; + let topMedia: TopMedia; $: { if (browser && mounted) { @@ -174,9 +175,7 @@ currentUserIdentity.name = currentUserIdentity.name; } else currentUserIdentity.id = -2; - await update(); - - mounted = true; + await update().then(() => (mounted = true)); }); const update = async () => { @@ -191,7 +190,8 @@ $lastPruneTimes.anime, { forcePrune: true, - includeCompleted: true + includeCompleted: true, + all: true } ) ) @@ -217,7 +217,8 @@ $lastPruneTimes.manga, { forcePrune: true, - includeCompleted: true + includeCompleted: true, + all: true } ) ) @@ -244,6 +245,8 @@ } for (const media of mangaList) chapters += media.mediaListEntry?.progress || 0; + + topMedia = tops([...animeList, ...mangaList], 5); }; /* eslint-disable @typescript-eslint/no-explicit-any */ @@ -350,29 +353,29 @@ await database.activities.bulkDelete((await database.activities.toArray()).map((m) => m.page)); }; - const mergeArraySort = (a: any, b: any, mode: 'tags' | 'genres') => { - let merged = [...a, ...b].sort((a, b) => b.meanScore - a.meanScore); + // const mergeArraySort = (a: any, b: any, mode: 'tags' | 'genres') => { + // let merged = [...a, ...b].sort((a, b) => b.meanScore - a.meanScore); - merged = merged.filter( - (item, index, self) => - self.findIndex((itemToCompare) => - mode === 'genres' - ? itemToCompare.genre === item.genre - : itemToCompare.tag.name === item.tag.name - ) === index - ); + // merged = merged.filter( + // (item, index, self) => + // self.findIndex((itemToCompare) => + // mode === 'genres' + // ? itemToCompare.genre === item.genre + // : itemToCompare.tag.name === item.tag.name + // ) === index + // ); - return merged; - }; + // return merged; + // }; - const randomCoverFromTop10 = ( - statistics: { anime: any; manga: any }, - mode: 'tags' | 'genres' - ) => { - const top = mergeArraySort(statistics.anime[mode], statistics.manga[mode], mode); + // const randomCoverFromTop10 = ( + // statistics: { anime: any; manga: any }, + // mode: 'tags' | 'genres' + // ) => { + // const top = mergeArraySort(statistics.anime[mode], statistics.manga[mode], mode); - return mediaCover(top[Math.floor(Math.random() * top.length)].mediaIds[0]); - }; + // return mediaCover(top[Math.floor(Math.random() * top.length)].mediaIds[0]); + // }; </script> {#if currentUserIdentity.id === -2} @@ -503,24 +506,29 @@ <div class="categories-grid" style="padding-top: 0;"> <div class="category-grid pure-category category"> <div class="grid-item image-grid"> - {#await randomCoverFromTop10(wrapped.statistics, 'genres') then cover} + <a + href={`https://anilist.co/${topMedia.topGenreMedia.type.toLowerCase()}/${ + topMedia.topGenreMedia.id + }`} + target="_blank" + > <img - src={proxy(cover)} + src={proxy(topMedia.topGenreMedia.coverImage.extraLarge)} alt="Highest Rated Genre Cover" class="cover-image" on:load={updateWidth} /> - {/await} + </a> <div> <b>Highest Rated Genres</b> <ol> - {#each mergeArraySort(wrapped.statistics.anime.genres, wrapped.statistics.manga.genres, 'genres').slice(0, highestRatedCount) as genre} + {#each topMedia.genres as genre} <li> <a href={`https://anilist.co/search/anime?genres=${genre.genre}`} target="_blank" > - {genre.genre}: {genre.meanScore}% + {genre.genre}: {genre.averageScore}% </a> </li> {/each} @@ -530,24 +538,29 @@ </div> <div class="category-grid pure-category category"> <div class="grid-item image-grid"> - {#await randomCoverFromTop10(wrapped.statistics, 'tags') then cover} + <a + href={`https://anilist.co/${topMedia.topTagMedia.type.toLowerCase()}/${ + topMedia.topTagMedia.id + }`} + target="_blank" + > <img - src={proxy(cover)} + src={proxy(topMedia.topTagMedia.coverImage.extraLarge)} alt="Highest Rated Tag Cover" class="cover-image" on:load={updateWidth} /> - {/await} + </a> <div> <b>Highest Rated Tags</b> <ol> - {#each mergeArraySort(wrapped.statistics.anime.tags, wrapped.statistics.manga.tags, 'tags').slice(0, highestRatedCount) as tag} + {#each topMedia.tags as tag} <li> <a - href={`https://anilist.co/search/anime?genres=${tag.tag.name}`} + href={`https://anilist.co/search/anime?genres=${tag.tag}`} target="_blank" > - {tag.tag.name}: {tag.meanScore}% + {tag.tag}: {tag.averageScore}% </a> </li> {/each} |