Highscore: bei voll geschafften Läufen (Sterne) die gebrauchte Zeit anzeigen

This commit is contained in:
schmop 2026-05-31 18:01:03 +02:00
parent 72aa9837ce
commit 684a430005
4 changed files with 41 additions and 7 deletions

View File

@ -22,8 +22,15 @@
1: { c: Balloon, size: 38 },
2: { c: Cloud, size: 52 },
3: { c: Moon, size: 40 },
4: { c: Star, size: 36 },
4: { c: Star, size: 34 },
};
// Gebrauchte Zeit nur bei voll geschafften Läufen (Sterne): Sekunden, ab 60s als M:SS.
function fmtTime(ms: number): string {
const s = Math.round(ms / 1000);
if (s < 60) return `${s}`;
return `${Math.floor(s / 60)}:${String(s % 60).padStart(2, '0')}`;
}
</script>
<div class="column" aria-label="Beste Flüge">
@ -46,6 +53,15 @@
<Symbol size={SYMBOL[slot.stage as Stage].size} />
{/if}
</span>
{#if slot.stage === 4 && slot.timeMs != null}
<span class="time" aria-label={`Zeit ${fmtTime(slot.timeMs)}`}>
<svg width="13" height="13" viewBox="0 0 24 24" aria-hidden="true">
<circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="2.4" />
<path d="M12 7 L12 12 L16 14" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" />
</svg>
<span class="time-num">{fmtTime(slot.timeMs)}</span>
</span>
{/if}
{:else}
<div class="placeholder"></div>
{/if}
@ -93,6 +109,21 @@
align-items: center;
justify-content: center;
}
.time {
position: absolute;
bottom: 5px;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
gap: 3px;
color: var(--c-rocket-window);
}
.time-num {
font-size: 13px;
font-weight: 800;
line-height: 1;
}
.placeholder {
width: 32px;
height: 32px;

View File

@ -6,7 +6,7 @@ const SCHEMA_VERSION = 1;
const PROGRESS_KEY = 'zahlzerlegung.progress';
const SETTINGS_KEY = 'zahlzerlegung.settings';
export type RunRecord = { stage: Stage; date: string };
export type RunRecord = { stage: Stage; date: string; timeMs?: number };
export type TargetProgress = {
runs: number;
@ -87,10 +87,11 @@ export function recordRun(
p: Progress,
target: Target,
stage: Stage,
date: string = new Date().toISOString()
date: string = new Date().toISOString(),
timeMs?: number
): Progress {
const prev = p.perTarget[target] ?? { runs: 0, top5: [] };
const next: RunRecord = { stage, date };
const next: RunRecord = { stage, date, timeMs };
const merged = [...prev.top5, next].sort((a, b) => {
if (b.stage !== a.stage) return b.stage - a.stage;
return b.date.localeCompare(a.date);

View File

@ -71,7 +71,9 @@ function tick() {
function finalize() {
const g = get(game);
if (g.target === null) return;
recordResult(g.target, stageFor(g.correctCount));
// Gebrauchte Zeit = verstrichene Zeit bis zum Ende (bei Sieg = Lösezeit für alle 10).
const elapsedMs = Math.max(0, g.totalMs - g.timeLeftMs);
recordResult(g.target, stageFor(g.correctCount), elapsedMs);
}
export function startGame(target: Target): void {

View File

@ -21,8 +21,8 @@ progress.subscribe((p) => {
if (typeof window !== 'undefined') saveProgress(p);
});
export function recordResult(target: Target, stage: Stage): void {
export function recordResult(target: Target, stage: Stage, timeMs?: number): void {
const date = new Date().toISOString();
progress.update((p) => recordRun(p, target, stage, date));
progress.update((p) => recordRun(p, target, stage, date, timeMs));
lastRun.set({ target, stage, date });
}