From c3982bc268159adcac47ee131fa8402302853978 Mon Sep 17 00:00:00 2001 From: Azalea <22280294+hykilpikonna@users.noreply.github.com> Date: Thu, 20 Nov 2025 19:06:43 +0800 Subject: [PATCH] [+] Location state --- src/lib/server/tools/lyrics.ts | 3 +- src/routes/playlist/[id]/+page.svelte | 22 +++- src/routes/results/[id]/+page.server.ts | 8 +- src/routes/results/[id]/+page.svelte | 117 +++++++++++++++------ src/routes/song/[id]/+page.svelte | 11 +- src/shared/types.ts | 132 +++++++++++++----------- 6 files changed, 194 insertions(+), 99 deletions(-) diff --git a/src/lib/server/tools/lyrics.ts b/src/lib/server/tools/lyrics.ts index f14f1c5..93fc615 100644 --- a/src/lib/server/tools/lyrics.ts +++ b/src/lib/server/tools/lyrics.ts @@ -5,7 +5,8 @@ import { isKanji } from 'wanakana' // Please put OPENAI_API_KEY in your environment variables. const client = new OpenAI() const req = { - model: "gpt-5.1-chat-latest", + // model: "gpt-5.1-chat-latest", + model: "gpt-4.1", messages: [ { role: "system", diff --git a/src/routes/playlist/[id]/+page.svelte b/src/routes/playlist/[id]/+page.svelte index 7024e0d..1ed2351 100644 --- a/src/routes/playlist/[id]/+page.svelte +++ b/src/routes/playlist/[id]/+page.svelte @@ -1,5 +1,6 @@ 歌曲数: {meta.trackCount}
- +
diff --git a/src/routes/results/[id]/+page.server.ts b/src/routes/results/[id]/+page.server.ts index 463b717..66a0932 100644 --- a/src/routes/results/[id]/+page.server.ts +++ b/src/routes/results/[id]/+page.server.ts @@ -1,9 +1,10 @@ import { error } from '@sveltejs/kit' import { getResult } from '$lib/server/result' import type { PageServerLoad } from './$types' -import { getLyricsProcessed, getSongRaw } from "$lib/server/songs.ts"; +import { getLyricsProcessed, getSongRaw, getPlaylist } from "$lib/server/songs.ts"; -export const load: PageServerLoad = async ({ params }) => { +export const load: PageServerLoad = async ({ params, parent }) => { + const { user } = await parent() const result = await getResult(params.id) if (!result) throw error(404, 'Result not found') @@ -12,6 +13,7 @@ export const load: PageServerLoad = async ({ params }) => { return { result: structuredClone(result), lrc: await getLyricsProcessed(result.songId), - song + song, + playlist: await user.data?.loc?.currentPlaylistId?.let(getPlaylist) } } diff --git a/src/routes/results/[id]/+page.svelte b/src/routes/results/[id]/+page.svelte index cb1e823..ea4471c 100644 --- a/src/routes/results/[id]/+page.svelte +++ b/src/routes/results/[id]/+page.svelte @@ -1,39 +1,34 @@ @@ -125,6 +180,6 @@
- +
diff --git a/src/routes/song/[id]/+page.svelte b/src/routes/song/[id]/+page.svelte index 0aaffdb..439eb60 100644 --- a/src/routes/song/[id]/+page.svelte +++ b/src/routes/song/[id]/+page.svelte @@ -148,10 +148,17 @@ const res = await API.saveResult({ songId: data.song.id, endTime: Date.now(), - realTimeFactor: (Date.now() - startTime) / (data.song.dt / 1000), + realTimeFactor: data.song.dt / (Date.now() - startTime), totalTyped, totalRight, startTime, statsHistory }) - goto(`/results/${res.id}`) + + if (data.user.data.loc?.currentPlaylistId) { + data.user.data.loc.isFinished = true; + data.user.data.loc.lastResultId = res.id; + await API.saveUserData({ loc: data.user.data.loc }); + } + + goto(`/results/${res.id}`, { replaceState: true }) } diff --git a/src/shared/types.ts b/src/shared/types.ts index a0f85eb..f41f855 100644 --- a/src/shared/types.ts +++ b/src/shared/types.ts @@ -1,96 +1,106 @@ -export type LyricSegment = string | string[] +export type LyricSegment = string | string[]; export interface LyricLine { - time: string - lyric: LyricSegment[] + time: string; + lyric: LyricSegment[]; } export interface Song { - title: string - lyrics: LyricLine[] + title: string; + lyrics: LyricLine[]; } -export interface NeteaseSong { - id: number - name: string - al: { - id: number - name: string - picUrl: string - } - ar: { id: number, name: string }[] - dt: number +export interface NeteaseSong { + id: number; + name: string; + al: { + id: number; + name: string; + picUrl: string; + }; + ar: { id: number; name: string }[]; + dt: number; } export interface NeteasePlaylist { - id: number - name: string - coverImgUrl: string - creator: { - nickname: string - } - tracks: NeteaseSong[] + id: number; + name: string; + coverImgUrl: string; + creator: { + nickname: string; + }; + tracks: NeteaseSong[]; } export interface ProcessedLyricLine { - jp: LyricSegment[] - kanji: string - hiragana: string - cleanHiragana: string - romaji: string - cleanRomaji: string + jp: LyricSegment[]; + kanji: string; + hiragana: string; + cleanHiragana: string; + romaji: string; + cleanRomaji: string; } export interface DisplayCharacter { - char: string - state: 'correct' | 'incorrect' | 'untyped' | 'ignored' - originalSegment?: LyricSegment - segmentHiragana?: string + char: string; + state: "correct" | "incorrect" | "untyped" | "ignored"; + originalSegment?: LyricSegment; + segmentHiragana?: string; } export interface GameStats { - wpm: number - accuracy: number - totalTyped: number - totalCorrect: number - startTime: number - totalTime: number + wpm: number; + accuracy: number; + totalTyped: number; + totalCorrect: number; + startTime: number; + totalTime: number; } export interface UserDocument { - _id?: any - registUA: string - createdAt: Date - sessions: string[] - syncCode?: string - syncCodeCreated?: Date + _id?: any; + registUA: string; + createdAt: Date; + sessions: string[]; + syncCode?: string; + syncCodeCreated?: Date; // User data - data: UserData + data: UserData; } export interface ResultDocument { - _id?: any - userId?: any // Optional, if we want to link to user - songId: number - totalTyped: number - totalRight: number - startTime: number - endTime: number - realTimeFactor: number - statsHistory: { t: number, cpm: number, acc: number }[] - createdAt: Date + _id?: any; + userId?: any; // Optional, if we want to link to user + songId: number; + totalTyped: number; + totalRight: number; + startTime: number; + endTime: number; + realTimeFactor: number; + statsHistory: { t: number; cpm: number; acc: number }[]; + createdAt: Date; } export const typingSettingsDefault = { isFuri: true, allKata: false, showRomaji: true, - showRomajiOnError: true -} + showRomajiOnError: true, +}; export interface UserData { - myPlaylists?: number[] - playHistory?: GameStats[] - typingSettings?: typeof typingSettingsDefault -} \ No newline at end of file + myPlaylists?: number[]; + playHistory?: GameStats[]; + typingSettings?: typeof typingSettingsDefault; + + // Playlist state + loc?: { + currentPlaylistId: number; + currentSongIndex: number; + playedSongIds: number[]; + playMode: "random" | "sequential"; + isFinished: boolean; + lastResultId: string | null; + }; +}