From d0f7654998aa4b7ad8acdf0f344a51fcd5e75a1a Mon Sep 17 00:00:00 2001 From: dal4segno Date: Tue, 18 Aug 2026 20:59:20 +0900 Subject: [PATCH] feat: improve combination search and offline build --- .gitignore | 2 + offline/OfflineApp.svelte | 127 +++++++++++ offline/chart-loader.ts | 24 ++ offline/index.html | 13 ++ offline/main.ts | 7 + offline/page-store.ts | 11 + package.json | 2 + scripts/finalize-offline-build.mjs | 56 +++++ scripts/package-offline.ps1 | 19 ++ src/lib/data/chart-loader.ts | 7 + src/lib/engine/combination-search.test.ts | 26 ++- src/lib/engine/combination-search.ts | 18 +- src/lib/styles/layout-tokens.css | 8 + .../workers/create-score-optimizer-worker.ts | 5 + src/routes/+layout.svelte | 6 +- src/routes/analysis/+page.svelte | 20 +- src/routes/cards/+page.svelte | 41 ++-- src/routes/combination/+page.svelte | 212 ++++++++++++++---- src/routes/data/+page.svelte | 13 +- vite.offline.config.ts | 34 +++ 20 files changed, 552 insertions(+), 99 deletions(-) create mode 100644 offline/OfflineApp.svelte create mode 100644 offline/chart-loader.ts create mode 100644 offline/index.html create mode 100644 offline/main.ts create mode 100644 offline/page-store.ts create mode 100644 scripts/finalize-offline-build.mjs create mode 100644 scripts/package-offline.ps1 create mode 100644 src/lib/data/chart-loader.ts create mode 100644 src/lib/styles/layout-tokens.css create mode 100644 src/lib/workers/create-score-optimizer-worker.ts create mode 100644 vite.offline.config.ts diff --git a/.gitignore b/.gitignore index 2e161f5..97ee043 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ node_modules .svelte-kit build +offline-dist +release .env .env.* !.env.example diff --git a/offline/OfflineApp.svelte b/offline/OfflineApp.svelte new file mode 100644 index 0000000..15d8f3a --- /dev/null +++ b/offline/OfflineApp.svelte @@ -0,0 +1,127 @@ + + + + + + + diff --git a/offline/chart-loader.ts b/offline/chart-loader.ts new file mode 100644 index 0000000..33a1208 --- /dev/null +++ b/offline/chart-loader.ts @@ -0,0 +1,24 @@ +import type { ExactSongChart } from '$lib/engine/index.ts'; + +const chartSources = import.meta.glob('../static/data/charts/*.json', { + eager: true, + query: '?raw', + import: 'default' +}) as Record; + +const sourceByFilename = new Map( + Object.entries(chartSources).map(([path, source]) => [path.split('/').at(-1) ?? path, source]) +); +const parsedCharts = new Map(); + +export async function loadExactSongChart(path: string): Promise { + const filename = path.split('/').at(-1) ?? path; + const cached = parsedCharts.get(filename); + if (cached) return cached; + + const source = sourceByFilename.get(filename); + if (!source) throw new Error(`포함된 채보 데이터를 찾지 못했습니다: ${filename}`); + const chart = JSON.parse(source) as ExactSongChart; + parsedCharts.set(filename, chart); + return chart; +} diff --git a/offline/index.html b/offline/index.html new file mode 100644 index 0000000..bbcf80f --- /dev/null +++ b/offline/index.html @@ -0,0 +1,13 @@ + + + + + + + 홀로도리 계산기 + + +
+ + + diff --git a/offline/main.ts b/offline/main.ts new file mode 100644 index 0000000..ba93d51 --- /dev/null +++ b/offline/main.ts @@ -0,0 +1,7 @@ +import { mount } from 'svelte'; +import App from './OfflineApp.svelte'; +import '../src/lib/styles/layout-tokens.css'; + +mount(App, { + target: document.getElementById('app')! +}); diff --git a/offline/page-store.ts b/offline/page-store.ts new file mode 100644 index 0000000..a83cce3 --- /dev/null +++ b/offline/page-store.ts @@ -0,0 +1,11 @@ +import { writable } from 'svelte/store'; + +function pageValue(pathname: string) { + return { url: new URL(pathname, 'https://offline.holodori.local') }; +} + +export const page = writable(pageValue('/')); + +export function setOfflinePage(pathname: string) { + page.set(pageValue(pathname)); +} diff --git a/package.json b/package.json index 7687873..c9af01c 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,8 @@ "scripts": { "dev": "vite dev --host 0.0.0.0 --port 5173", "build": "vite build", + "build:offline": "vite build --config vite.offline.config.ts && node scripts/finalize-offline-build.mjs", + "package:offline": "npm run build:offline && powershell -NoProfile -ExecutionPolicy Bypass -File scripts/package-offline.ps1", "preview": "vite preview --host 0.0.0.0", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "test:engine": "node --test src/lib/engine/*.test.ts", diff --git a/scripts/finalize-offline-build.mjs b/scripts/finalize-offline-build.mjs new file mode 100644 index 0000000..eedff36 --- /dev/null +++ b/scripts/finalize-offline-build.mjs @@ -0,0 +1,56 @@ +import { readFile, rm, writeFile } from 'node:fs/promises'; +import path from 'node:path'; + +const output = path.resolve('offline-dist'); +const htmlPath = path.join(output, 'index.html'); +const scriptPath = path.join(output, 'assets', 'app.js'); +const stylePath = path.join(output, 'assets', 'app.css'); +const packageJson = JSON.parse(await readFile(path.resolve('package.json'), 'utf8')); + +let html = await readFile(htmlPath, 'utf8'); +html = html.replace(/