Rewrite some of vaukuivali to optimize split timer
Use watch from runed for more finegrained updates Start time only after the first scroll Add fallbacks/estimations if we still didn't collect the time Track the current checkpoint using only the decibel, as other info is now in a Record accessible via the decibel as the key
This commit is contained in:
parent
626dd22cb1
commit
2130ae5c39
5 changed files with 278 additions and 244 deletions
|
@ -62,6 +62,7 @@
|
||||||
"better-sqlite3": "^11.8.0",
|
"better-sqlite3": "^11.8.0",
|
||||||
"drizzle-orm": "^0.38.4",
|
"drizzle-orm": "^0.38.4",
|
||||||
"nanoid": "^5.0.9",
|
"nanoid": "^5.0.9",
|
||||||
|
"runed": "^0.23.3",
|
||||||
"spotify-web-api-node": "^5.0.2",
|
"spotify-web-api-node": "^5.0.2",
|
||||||
"svelte-kit-sessions": "^0.4.0"
|
"svelte-kit-sessions": "^0.4.0"
|
||||||
},
|
},
|
||||||
|
|
13
pnpm-lock.yaml
generated
13
pnpm-lock.yaml
generated
|
@ -29,6 +29,9 @@ importers:
|
||||||
nanoid:
|
nanoid:
|
||||||
specifier: ^5.0.9
|
specifier: ^5.0.9
|
||||||
version: 5.0.9
|
version: 5.0.9
|
||||||
|
runed:
|
||||||
|
specifier: ^0.23.3
|
||||||
|
version: 0.23.3(svelte@5.19.1)
|
||||||
spotify-web-api-node:
|
spotify-web-api-node:
|
||||||
specifier: ^5.0.2
|
specifier: ^5.0.2
|
||||||
version: 5.0.2
|
version: 5.0.2
|
||||||
|
@ -2323,8 +2326,8 @@ packages:
|
||||||
run-parallel@1.2.0:
|
run-parallel@1.2.0:
|
||||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||||
|
|
||||||
runed@0.23.2:
|
runed@0.23.3:
|
||||||
resolution: {integrity: sha512-AhHCb5/B+YQW6ar1pzhGQOQy+byfjCH63ofuhrexSWwQKhC0EbQ60Z/wMYwETLo3ZubhwlNryxBt0seOMOrVFQ==}
|
resolution: {integrity: sha512-qmL6JOvI9fg2XrSI9eP8bVIaAyk1ztVZsoj37hTs4BSuOOyeLkrIPI16mwarXFYbxSfyJGCwAWgfpSq+ehQmgg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
svelte: ^5.7.0
|
svelte: ^5.7.0
|
||||||
|
|
||||||
|
@ -3615,7 +3618,7 @@ snapshots:
|
||||||
'@floating-ui/dom': 1.6.13
|
'@floating-ui/dom': 1.6.13
|
||||||
'@internationalized/date': 3.7.0
|
'@internationalized/date': 3.7.0
|
||||||
esm-env: 1.2.2
|
esm-env: 1.2.2
|
||||||
runed: 0.23.2(svelte@5.19.1)
|
runed: 0.23.3(svelte@5.19.1)
|
||||||
svelte: 5.19.1
|
svelte: 5.19.1
|
||||||
svelte-toolbelt: 0.7.1(svelte@5.19.1)
|
svelte-toolbelt: 0.7.1(svelte@5.19.1)
|
||||||
tabbable: 6.2.0
|
tabbable: 6.2.0
|
||||||
|
@ -4592,7 +4595,7 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
queue-microtask: 1.2.3
|
queue-microtask: 1.2.3
|
||||||
|
|
||||||
runed@0.23.2(svelte@5.19.1):
|
runed@0.23.3(svelte@5.19.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
esm-env: 1.2.2
|
esm-env: 1.2.2
|
||||||
svelte: 5.19.1
|
svelte: 5.19.1
|
||||||
|
@ -4818,7 +4821,7 @@ snapshots:
|
||||||
svelte-toolbelt@0.7.1(svelte@5.19.1):
|
svelte-toolbelt@0.7.1(svelte@5.19.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
clsx: 2.1.1
|
clsx: 2.1.1
|
||||||
runed: 0.23.2(svelte@5.19.1)
|
runed: 0.23.3(svelte@5.19.1)
|
||||||
style-to-object: 1.0.8
|
style-to-object: 1.0.8
|
||||||
svelte: 5.19.1
|
svelte: 5.19.1
|
||||||
|
|
||||||
|
|
|
@ -80,3 +80,9 @@ export type TagsObj = Record<string, Tag>;
|
||||||
|
|
||||||
export type Answer = typeof answers.$inferSelect;
|
export type Answer = typeof answers.$inferSelect;
|
||||||
export type Question = typeof questions.$inferSelect & { answers: Answer[] };
|
export type Question = typeof questions.$inferSelect & { answers: Answer[] };
|
||||||
|
|
||||||
|
export interface SoundCheckpoint {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
image: EnhancedImage | undefined;
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import type { SoundCheckpoint } from '$lib/types';
|
||||||
|
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { Tween } from 'svelte/motion';
|
import { Tween } from 'svelte/motion';
|
||||||
import { expoOut } from 'svelte/easing';
|
import { expoOut } from 'svelte/easing';
|
||||||
|
@ -11,220 +13,11 @@
|
||||||
import ArrowUpToLine from 'lucide-svelte/icons/arrow-up-to-line';
|
import ArrowUpToLine from 'lucide-svelte/icons/arrow-up-to-line';
|
||||||
import ChevronsUpDown from 'lucide-svelte/icons/chevrons-up-down';
|
import ChevronsUpDown from 'lucide-svelte/icons/chevrons-up-down';
|
||||||
|
|
||||||
import SevenSegmentDigit from './SevenSegmentDigit.svelte';
|
import { watch } from 'runed';
|
||||||
import { getTimeRemaining } from '$lib/utils';
|
import { getTimeRemaining } from '$lib/utils';
|
||||||
|
|
||||||
import roomImg from '$lib/assets/vaukuivali/roomtone.jpg?enhanced';
|
import SevenSegmentDigit from './SevenSegmentDigit.svelte';
|
||||||
import watchImg from '$lib/assets/vaukuivali/oldwatch.jpg?enhanced';
|
import { soundCheckpoints } from './checkpoints';
|
||||||
import convoImg from '$lib/assets/vaukuivali/conversation.jpg?enhanced';
|
|
||||||
import gennImg from '$lib/assets/vaukuivali/genn.webp?enhanced';
|
|
||||||
import tvImg from '$lib/assets/vaukuivali/tv.jpg?enhanced';
|
|
||||||
import trafficImg from '$lib/assets/vaukuivali/kaubamaja.jpg?enhanced';
|
|
||||||
import harleyImg from '$lib/assets/vaukuivali/harley.jpg?enhanced';
|
|
||||||
import landingImg from '$lib/assets/vaukuivali/landing.jpg?enhanced';
|
|
||||||
import carCrashImg from '$lib/assets/vaukuivali/carcrash.jpg?enhanced';
|
|
||||||
import chainsawImg from '$lib/assets/vaukuivali/chainsaw.jpg?enhanced';
|
|
||||||
import jetImg from '$lib/assets/vaukuivali/fighters.jpg?enhanced';
|
|
||||||
import hearingaidImg from '$lib/assets/vaukuivali/eardamage.jpg?enhanced';
|
|
||||||
import { ImageCreditType, type EnhancedImage } from '$lib/types';
|
|
||||||
|
|
||||||
interface SoundCheckpoint {
|
|
||||||
db: number;
|
|
||||||
title: string;
|
|
||||||
description: string;
|
|
||||||
crossedTime: undefined | Date;
|
|
||||||
image: EnhancedImage | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const soundCheckpoints: SoundCheckpoint[] = $state([
|
|
||||||
{
|
|
||||||
db: 0,
|
|
||||||
title: '',
|
|
||||||
description: 'Kesket metsa mingis koopas, kedagi pole ümber',
|
|
||||||
image: undefined,
|
|
||||||
crossedTime: undefined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
db: 30,
|
|
||||||
title: '"Vaikus"',
|
|
||||||
description: 'ehk elutoa pasiivne müra',
|
|
||||||
image: {
|
|
||||||
src: roomImg,
|
|
||||||
credit: {
|
|
||||||
type: ImageCreditType.web,
|
|
||||||
author: 'Kam Idris',
|
|
||||||
href: 'https://unsplash.com/@ka_idris'
|
|
||||||
},
|
|
||||||
alt: 'Modernse ja minimalistliku disainiga siseruum.'
|
|
||||||
},
|
|
||||||
crossedTime: undefined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
db: 40,
|
|
||||||
title: 'Tikk takk',
|
|
||||||
description: 'Mehaanilise kella tiksumine (va täistundidel)',
|
|
||||||
image: {
|
|
||||||
src: watchImg,
|
|
||||||
credit: {
|
|
||||||
type: ImageCreditType.web,
|
|
||||||
author: 'János Venczák',
|
|
||||||
href: 'https://unsplash.com/@venczakjanos'
|
|
||||||
},
|
|
||||||
alt: 'Lahti võetud vanamoodne käekell. Näha on kella sisemust, hammasrattaid.'
|
|
||||||
},
|
|
||||||
crossedTime: undefined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
db: 50,
|
|
||||||
title: 'Tava jutt',
|
|
||||||
description: 'Rahulik vestlus kodus',
|
|
||||||
image: {
|
|
||||||
src: convoImg,
|
|
||||||
credit: {
|
|
||||||
type: ImageCreditType.web,
|
|
||||||
author: 'Toa Heftiba',
|
|
||||||
href: 'https://unsplash.com/@heftiba'
|
|
||||||
},
|
|
||||||
alt: 'Noor paar köögis. Mees lõikab taldriku peal pannkooki, naine istub ta kõrval pliidi peal ja vaatab.'
|
|
||||||
},
|
|
||||||
crossedTime: undefined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
db: 60,
|
|
||||||
title: 'Ma sain nurgad täis',
|
|
||||||
description: 'Bingo õhtu Gennis (keset mängu)',
|
|
||||||
image: {
|
|
||||||
src: gennImg,
|
|
||||||
credit: {
|
|
||||||
type: ImageCreditType.web,
|
|
||||||
author: 'Laila Kaasik',
|
|
||||||
href: 'https://tartu.postimees.ee/8154041/lallavad-pidutsejad-panid-tartu-otsima-tasakaalu-ooelu-ja-oorahu-vahel'
|
|
||||||
},
|
|
||||||
alt: 'Genialistide klubi tegutseb Tartus Magasini tänavas. Pilt on õhtusest ajast, rohkelt inimesti klubi välialal.'
|
|
||||||
},
|
|
||||||
crossedTime: undefined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
db: 70,
|
|
||||||
title: 'Pult on kadunud',
|
|
||||||
description: 'Telekas, mis mängib natuke liiga valjult',
|
|
||||||
image: {
|
|
||||||
src: tvImg,
|
|
||||||
credit: {
|
|
||||||
type: ImageCreditType.web,
|
|
||||||
author: 'Jonas Leupe',
|
|
||||||
href: 'https://unsplash.com/@jonasleupe'
|
|
||||||
},
|
|
||||||
alt: 'Keegi vaatab televiisorist filmi. Esiplaanil fookuses teleka pult, tagaplaanil udune tuba, mille seina vastas on telekas.'
|
|
||||||
},
|
|
||||||
crossedTime: undefined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
db: 80,
|
|
||||||
title: 'USAs oleks hullem',
|
|
||||||
description: 'Riia mäe liiklus (ootad bussi Kaubamaja ees)',
|
|
||||||
image: {
|
|
||||||
src: trafficImg,
|
|
||||||
credit: {
|
|
||||||
type: ImageCreditType.web,
|
|
||||||
author: 'Google Street View',
|
|
||||||
href: 'https://maps.app.goo.gl/ZfADP4LnUid7d571A'
|
|
||||||
},
|
|
||||||
alt: 'Aastal 2012 tehtud Google Street View pilt. Näha on Tartu Kaubamaja ning selle Riia tänava küljel olevat bussipeatust.'
|
|
||||||
},
|
|
||||||
crossedTime: undefined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
db: 90,
|
|
||||||
title: 'USAs oleks rohkem',
|
|
||||||
description: 'Harley sõidab sinust mööda',
|
|
||||||
image: {
|
|
||||||
src: harleyImg,
|
|
||||||
credit: {
|
|
||||||
type: ImageCreditType.web,
|
|
||||||
author: 'Harley-Davidson',
|
|
||||||
href: 'https://unsplash.com/@harleydavidson'
|
|
||||||
},
|
|
||||||
alt: 'Uue välimusega Harley-Davidson mootorrattas sõidab kiiresti mööda sirget maanteed.'
|
|
||||||
},
|
|
||||||
crossedTime: undefined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
db: 100,
|
|
||||||
title: 'Põgenesid terminalist',
|
|
||||||
description: 'Boeing 707 1 meremiil enne maandumist',
|
|
||||||
image: {
|
|
||||||
src: landingImg,
|
|
||||||
credit: {
|
|
||||||
type: ImageCreditType.web,
|
|
||||||
author: 'Scott Fillmer',
|
|
||||||
href: 'https://unsplash.com/@scottfillmer'
|
|
||||||
},
|
|
||||||
alt: 'Continental Airlines Boeing 777 maandub uduses Houston IAH lennujaamas.'
|
|
||||||
},
|
|
||||||
crossedTime: undefined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
db: 110,
|
|
||||||
title: 'Maanteeraev',
|
|
||||||
description: 'Autosignaal 1m kauguselt',
|
|
||||||
image: {
|
|
||||||
src: carCrashImg,
|
|
||||||
credit: {
|
|
||||||
type: ImageCreditType.instagram,
|
|
||||||
author: 'Jordan Besson',
|
|
||||||
href: 'https://www.instagram.com/mr.blue.photographie'
|
|
||||||
},
|
|
||||||
alt: 'Dramaatiline auto trikk filmi jaoks. Kahe auto kokkupõrge.'
|
|
||||||
},
|
|
||||||
crossedTime: undefined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
db: 120,
|
|
||||||
title: 'Mootorsaag',
|
|
||||||
description: 'Nüüd on juba valus. Soovitan kanda kõrvatroppe.',
|
|
||||||
image: {
|
|
||||||
src: chainsawImg,
|
|
||||||
credit: {
|
|
||||||
type: ImageCreditType.web,
|
|
||||||
author: 'Benjamin Jopen',
|
|
||||||
href: 'https://unsplash.com/@benjopen'
|
|
||||||
},
|
|
||||||
alt: 'Oranži ja musta värvi mootorsega lõigatakse langenud puud väiksemateks tükkideks.'
|
|
||||||
},
|
|
||||||
crossedTime: undefined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
db: 130,
|
|
||||||
title: 'Kuidas sa nii lähedale said?',
|
|
||||||
description: 'Turboreaktiivmootoriga hävitaja lendutõus 15m kauguselt',
|
|
||||||
image: {
|
|
||||||
src: jetImg,
|
|
||||||
credit: {
|
|
||||||
type: ImageCreditType.web,
|
|
||||||
author: 'Colin Lloyd',
|
|
||||||
href: 'https://unsplash.com/@onthesearchforpineapples'
|
|
||||||
},
|
|
||||||
alt: 'Kaheksa F-16 hävitajat lendavad koos formatsioonis taevas.'
|
|
||||||
},
|
|
||||||
crossedTime: undefined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
db: 150,
|
|
||||||
title: 'Aia mu kõrvad',
|
|
||||||
description: 'Tubli töö! Su trummikile rebenes!',
|
|
||||||
image: {
|
|
||||||
src: hearingaidImg,
|
|
||||||
credit: {
|
|
||||||
type: ImageCreditType.web,
|
|
||||||
author: 'Mark Paton',
|
|
||||||
href: 'https://unsplash.com/@heftiba'
|
|
||||||
},
|
|
||||||
alt: 'Lähivõte inimesest sisestamas oma kõrva kuuldeaparaati.'
|
|
||||||
},
|
|
||||||
crossedTime: undefined
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Source: Claude 3.5 Sonnet
|
// Source: Claude 3.5 Sonnet
|
||||||
function scrollToDecibels(scroll: number) {
|
function scrollToDecibels(scroll: number) {
|
||||||
|
@ -237,11 +30,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Source: Claude 3.5 Sonnet
|
// Source: Claude 3.5 Sonnet
|
||||||
function getCurrentCheckpoint(arr: SoundCheckpoint[], current: number) {
|
function getCurrentCheckpoint(arr: number[], current: number) {
|
||||||
return (
|
return (
|
||||||
arr.reduce(
|
arr.reduce(
|
||||||
(prev: SoundCheckpoint | undefined, item) =>
|
(prev: SoundCheckpoint | undefined, item) =>
|
||||||
item.db <= current && (!prev || item.db > prev.db) ? item : prev,
|
item <= current && (!prev || item > prev) ? item : prev,
|
||||||
undefined
|
undefined
|
||||||
) || arr.at(0)
|
) || arr.at(0)
|
||||||
);
|
);
|
||||||
|
@ -262,7 +55,9 @@
|
||||||
|
|
||||||
let innerHeight = $state(0);
|
let innerHeight = $state(0);
|
||||||
let innerWidth = $state(0);
|
let innerWidth = $state(0);
|
||||||
let prevCheckpoint: SoundCheckpoint | undefined = $state(undefined);
|
|
||||||
|
let startTime: Date | undefined = $state();
|
||||||
|
let firstScroll: Date | undefined = $state();
|
||||||
|
|
||||||
let scrollScale = $derived(innerHeight * 0.1);
|
let scrollScale = $derived(innerHeight * 0.1);
|
||||||
let containerHeight = $derived(decibelsToScroll(150) + innerHeight + innerHeight);
|
let containerHeight = $derived(decibelsToScroll(150) + innerHeight + innerHeight);
|
||||||
|
@ -272,7 +67,10 @@
|
||||||
|
|
||||||
let currentDecibel = $derived(scrollToDecibels(scrollY.target));
|
let currentDecibel = $derived(scrollToDecibels(scrollY.target));
|
||||||
let currentDecibelTweened = $derived(scrollToDecibels(scrollY.current));
|
let currentDecibelTweened = $derived(scrollToDecibels(scrollY.current));
|
||||||
let currentCheckpoint = $derived(getCurrentCheckpoint(soundCheckpoints, currentDecibel));
|
|
||||||
|
let checkpointDecibels = $derived(Object.keys(soundCheckpoints).map((value) => Number(value)));
|
||||||
|
let currentCheckpoint = $derived(getCurrentCheckpoint(checkpointDecibels, currentDecibel));
|
||||||
|
let checkpointTimes: Record<number, Date> = $state({});
|
||||||
|
|
||||||
let decibelMeter = $derived.by(() => {
|
let decibelMeter = $derived.by(() => {
|
||||||
const clampedValue = Math.min(999.99, Math.max(0, currentDecibel));
|
const clampedValue = Math.min(999.99, Math.max(0, currentDecibel));
|
||||||
|
@ -293,19 +91,64 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$effect(() => {
|
watch.pre(
|
||||||
if (
|
() => currentCheckpoint,
|
||||||
currentCheckpoint?.title &&
|
(curr, prev) => {
|
||||||
currentCheckpoint != prevCheckpoint &&
|
if (curr === prev) return;
|
||||||
!currentCheckpoint?.crossedTime
|
|
||||||
) {
|
if (checkpointTimes[curr]) return;
|
||||||
currentCheckpoint.crossedTime = new Date();
|
|
||||||
|
checkpointTimes[curr] = new Date();
|
||||||
|
|
||||||
|
// We reached the end
|
||||||
|
// Fill out any checkpoint times we missed with crude predictions
|
||||||
|
if (curr === checkpointDecibels.at(-1) && checkpointDecibels.length > 1) {
|
||||||
|
for (let i = 0; i < checkpointDecibels.length; i++) {
|
||||||
|
const db = checkpointDecibels[i];
|
||||||
|
const capturedTime = checkpointTimes[db];
|
||||||
|
|
||||||
|
if (!capturedTime) {
|
||||||
|
// If the next closest previous time is page load
|
||||||
|
// use first scroll for a more accurate prediction (if possible)
|
||||||
|
const prevDb = checkpointDecibels[Math.max(i - 1, 0)];
|
||||||
|
const prevTime = prevDb === 0 && firstScroll ? firstScroll : checkpointTimes[prevDb];
|
||||||
|
|
||||||
|
if (!prevTime) {
|
||||||
|
checkpointTimes[db] = firstScroll ? firstScroll : checkpointTimes[0];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextDb = checkpointDecibels[Math.min(i + 1, checkpointDecibels.length - 1)];
|
||||||
|
const nextTime = checkpointTimes[nextDb];
|
||||||
|
|
||||||
|
if (!nextTime) {
|
||||||
|
checkpointTimes[db] = prevTime;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkpointTimes[db] = new Date((prevTime.getTime() + nextTime.getTime()) / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
|
// Get the time of first scroll
|
||||||
|
watch.pre(
|
||||||
|
() => scrollY.current,
|
||||||
|
() => {
|
||||||
|
if (!startTime) return;
|
||||||
|
if (firstScroll) return;
|
||||||
|
|
||||||
|
firstScroll = new Date();
|
||||||
|
checkpointTimes[checkpointDecibels[0]] = firstScroll;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
soundCheckpoints[0].crossedTime = new Date();
|
scrollY.set(0, { duration: 0 });
|
||||||
scrollY.target = 0;
|
|
||||||
|
startTime = new Date();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -321,11 +164,11 @@
|
||||||
</div>
|
</div>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
||||||
{#snippet timeCard(point: SoundCheckpoint)}
|
{#snippet timeCard(db: number | undefined)}
|
||||||
<div class="rounded-md border px-4 py-3 font-mono text-sm">
|
<div class="rounded-md border px-4 py-3 font-mono text-sm">
|
||||||
<p class="leading-7">
|
<p class="leading-7">
|
||||||
<strong>{point.db}dBA</strong> -
|
<strong>{db}dBA</strong> -
|
||||||
<span>{getElapsedTime(soundCheckpoints.at(0)?.crossedTime, point.crossedTime)}</span>
|
<span>{getElapsedTime(firstScroll, db ? checkpointTimes[db] : firstScroll)}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
@ -367,7 +210,7 @@
|
||||||
<div
|
<div
|
||||||
class="relative h-[70svh] w-4 bg-gradient-to-b from-lime-300 via-yellow-400 to-red-500 dark:from-lime-500 dark:via-yellow-400 dark:to-red-500"
|
class="relative h-[70svh] w-4 bg-gradient-to-b from-lime-300 via-yellow-400 to-red-500 dark:from-lime-500 dark:via-yellow-400 dark:to-red-500"
|
||||||
>
|
>
|
||||||
{#each soundCheckpoints as { db }}
|
{#each checkpointDecibels as db}
|
||||||
<div
|
<div
|
||||||
transition:fade
|
transition:fade
|
||||||
style="top: calc({(db / 150) * 70}svh - 0.5rem)"
|
style="top: calc({(db / 150) * 70}svh - 0.5rem)"
|
||||||
|
@ -386,18 +229,21 @@
|
||||||
<div
|
<div
|
||||||
class="mx-auto flex w-full max-w-2xl flex-col-reverse items-center gap-8 self-center px-12 md:grid md:gap-0 md:*:[grid-area:1/1/2/2]"
|
class="mx-auto flex w-full max-w-2xl flex-col-reverse items-center gap-8 self-center px-12 md:grid md:gap-0 md:*:[grid-area:1/1/2/2]"
|
||||||
>
|
>
|
||||||
<Image image={currentCheckpoint?.image} class="aspect-square object-cover " />
|
<Image
|
||||||
|
image={soundCheckpoints[currentCheckpoint]?.image}
|
||||||
|
class="aspect-square object-cover "
|
||||||
|
/>
|
||||||
<header
|
<header
|
||||||
class="flex flex-col items-center py-4 text-center font-title backdrop-blur-sm backdrop-grayscale md:bg-background/75 dark:md:bg-background/90"
|
class="flex flex-col items-center py-4 text-center font-title backdrop-blur-sm backdrop-grayscale md:bg-background/75 dark:md:bg-background/90"
|
||||||
>
|
>
|
||||||
<h1 class="mb-1 scroll-m-20 text-5xl font-extrabold tracking-tight lg:text-6xl">
|
<h1 class="mb-1 scroll-m-20 text-5xl font-extrabold tracking-tight lg:text-6xl">
|
||||||
{#if currentCheckpoint?.db === 0}
|
{#if currentCheckpoint === 0}
|
||||||
Vau kui vali!
|
Vau kui vali!
|
||||||
{:else}
|
{:else}
|
||||||
{currentCheckpoint?.title}
|
{soundCheckpoints[currentCheckpoint]?.title}
|
||||||
{/if}
|
{/if}
|
||||||
</h1>
|
</h1>
|
||||||
{#if currentCheckpoint?.db === 0}
|
{#if currentCheckpoint === 0}
|
||||||
<p class="max-w-prose text-2xl font-semibold leading-7 text-muted-foreground">
|
<p class="max-w-prose text-2xl font-semibold leading-7 text-muted-foreground">
|
||||||
Nagu paljud võivad teada, on detsibellide skaala logaritmiline.<br /> 60dB on 2x valjem,
|
Nagu paljud võivad teada, on detsibellide skaala logaritmiline.<br /> 60dB on 2x valjem,
|
||||||
kui 50dB.
|
kui 50dB.
|
||||||
|
@ -410,7 +256,7 @@
|
||||||
</p>
|
</p>
|
||||||
{:else}
|
{:else}
|
||||||
<p class="max-w-prose text-2xl font-semibold leading-7 text-primary/80">
|
<p class="max-w-prose text-2xl font-semibold leading-7 text-primary/80">
|
||||||
{currentCheckpoint?.description}
|
{soundCheckpoints[currentCheckpoint]?.description}
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
</header>
|
</header>
|
||||||
|
@ -430,10 +276,10 @@
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</Collapsible.Trigger>
|
</Collapsible.Trigger>
|
||||||
</div>
|
</div>
|
||||||
{@render timeCard(soundCheckpoints.at(-1) as SoundCheckpoint)}
|
{@render timeCard(checkpointDecibels.at(-1))}
|
||||||
<Collapsible.Content class="space-y-2">
|
<Collapsible.Content class="space-y-2">
|
||||||
{#each soundCheckpoints.slice(1, -1).reverse() as point}
|
{#each checkpointDecibels.slice(1, -1).reverse() as db}
|
||||||
{@render timeCard(point)}
|
{@render timeCard(db)}
|
||||||
{/each}
|
{/each}
|
||||||
</Collapsible.Content>
|
</Collapsible.Content>
|
||||||
</Collapsible.Root>
|
</Collapsible.Root>
|
||||||
|
@ -450,7 +296,7 @@
|
||||||
<a
|
<a
|
||||||
href="https://www.chem.purdue.edu/chemsafety/Training/PPETrain/dblevels.htm"
|
href="https://www.chem.purdue.edu/chemsafety/Training/PPETrain/dblevels.htm"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class=" underline underline-offset-4">Purdue University PPE training materials</a
|
class="underline underline-offset-4">Purdue University PPE training materials</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
178
src/routes/vinge/vaukuivali/checkpoints.ts
Normal file
178
src/routes/vinge/vaukuivali/checkpoints.ts
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
import { ImageCreditType, type SoundCheckpoint } from '$lib/types';
|
||||||
|
|
||||||
|
import roomImg from '$lib/assets/vaukuivali/roomtone.jpg?enhanced';
|
||||||
|
import watchImg from '$lib/assets/vaukuivali/oldwatch.jpg?enhanced';
|
||||||
|
import convoImg from '$lib/assets/vaukuivali/conversation.jpg?enhanced';
|
||||||
|
import gennImg from '$lib/assets/vaukuivali/genn.webp?enhanced';
|
||||||
|
import tvImg from '$lib/assets/vaukuivali/tv.jpg?enhanced';
|
||||||
|
import trafficImg from '$lib/assets/vaukuivali/kaubamaja.jpg?enhanced';
|
||||||
|
import harleyImg from '$lib/assets/vaukuivali/harley.jpg?enhanced';
|
||||||
|
import landingImg from '$lib/assets/vaukuivali/landing.jpg?enhanced';
|
||||||
|
import carCrashImg from '$lib/assets/vaukuivali/carcrash.jpg?enhanced';
|
||||||
|
import chainsawImg from '$lib/assets/vaukuivali/chainsaw.jpg?enhanced';
|
||||||
|
import jetImg from '$lib/assets/vaukuivali/fighters.jpg?enhanced';
|
||||||
|
import hearingaidImg from '$lib/assets/vaukuivali/eardamage.jpg?enhanced';
|
||||||
|
|
||||||
|
export const soundCheckpoints: Record<number, SoundCheckpoint> = {
|
||||||
|
0: {
|
||||||
|
title: '',
|
||||||
|
description: 'Kesket metsa mingis koopas, kedagi pole ümber',
|
||||||
|
image: undefined
|
||||||
|
},
|
||||||
|
30: {
|
||||||
|
title: '"Vaikus"',
|
||||||
|
description: 'ehk elutoa pasiivne müra',
|
||||||
|
image: {
|
||||||
|
src: roomImg,
|
||||||
|
credit: {
|
||||||
|
type: ImageCreditType.web,
|
||||||
|
author: 'Kam Idris',
|
||||||
|
href: 'https://unsplash.com/@ka_idris'
|
||||||
|
},
|
||||||
|
alt: 'Modernse ja minimalistliku disainiga siseruum.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
40: {
|
||||||
|
title: 'Tikk takk',
|
||||||
|
description: 'Mehaanilise kella tiksumine (va täistundidel)',
|
||||||
|
image: {
|
||||||
|
src: watchImg,
|
||||||
|
credit: {
|
||||||
|
type: ImageCreditType.web,
|
||||||
|
author: 'János Venczák',
|
||||||
|
href: 'https://unsplash.com/@venczakjanos'
|
||||||
|
},
|
||||||
|
alt: 'Lahti võetud vanamoodne käekell. Näha on kella sisemust, hammasrattaid.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
50: {
|
||||||
|
title: 'Tava jutt',
|
||||||
|
description: 'Rahulik vestlus kodus',
|
||||||
|
image: {
|
||||||
|
src: convoImg,
|
||||||
|
credit: {
|
||||||
|
type: ImageCreditType.web,
|
||||||
|
author: 'Toa Heftiba',
|
||||||
|
href: 'https://unsplash.com/@heftiba'
|
||||||
|
},
|
||||||
|
alt: 'Noor paar köögis. Mees lõikab taldriku peal pannkooki, naine istub ta kõrval pliidi peal ja vaatab.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
60: {
|
||||||
|
title: 'Ma sain nurgad täis',
|
||||||
|
description: 'Bingo õhtu Gennis (keset mängu)',
|
||||||
|
image: {
|
||||||
|
src: gennImg,
|
||||||
|
credit: {
|
||||||
|
type: ImageCreditType.web,
|
||||||
|
author: 'Laila Kaasik',
|
||||||
|
href: 'https://tartu.postimees.ee/8154041/lallavad-pidutsejad-panid-tartu-otsima-tasakaalu-ooelu-ja-oorahu-vahel'
|
||||||
|
},
|
||||||
|
alt: 'Genialistide klubi tegutseb Tartus Magasini tänavas. Pilt on õhtusest ajast, rohkelt inimesti klubi välialal.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
70: {
|
||||||
|
title: 'Pult on kadunud',
|
||||||
|
description: 'Telekas, mis mängib natuke liiga valjult',
|
||||||
|
image: {
|
||||||
|
src: tvImg,
|
||||||
|
credit: {
|
||||||
|
type: ImageCreditType.web,
|
||||||
|
author: 'Jonas Leupe',
|
||||||
|
href: 'https://unsplash.com/@jonasleupe'
|
||||||
|
},
|
||||||
|
alt: 'Keegi vaatab televiisorist filmi. Esiplaanil fookuses teleka pult, tagaplaanil udune tuba, mille seina vastas on telekas.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
80: {
|
||||||
|
title: 'USAs oleks hullem',
|
||||||
|
description: 'Riia mäe liiklus (ootad bussi Kaubamaja ees)',
|
||||||
|
image: {
|
||||||
|
src: trafficImg,
|
||||||
|
credit: {
|
||||||
|
type: ImageCreditType.web,
|
||||||
|
author: 'Google Street View',
|
||||||
|
href: 'https://maps.app.goo.gl/ZfADP4LnUid7d571A'
|
||||||
|
},
|
||||||
|
alt: 'Aastal 2012 tehtud Google Street View pilt. Näha on Tartu Kaubamaja ning selle Riia tänava küljel olevat bussipeatust.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
90: {
|
||||||
|
title: 'USAs oleks rohkem',
|
||||||
|
description: 'Harley sõidab sinust mööda',
|
||||||
|
image: {
|
||||||
|
src: harleyImg,
|
||||||
|
credit: {
|
||||||
|
type: ImageCreditType.web,
|
||||||
|
author: 'Harley-Davidson',
|
||||||
|
href: 'https://unsplash.com/@harleydavidson'
|
||||||
|
},
|
||||||
|
alt: 'Uue välimusega Harley-Davidson mootorrattas sõidab kiiresti mööda sirget maanteed.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
100: {
|
||||||
|
title: 'Põgenesid terminalist',
|
||||||
|
description: 'Boeing 707 1 meremiil enne maandumist',
|
||||||
|
image: {
|
||||||
|
src: landingImg,
|
||||||
|
credit: {
|
||||||
|
type: ImageCreditType.web,
|
||||||
|
author: 'Scott Fillmer',
|
||||||
|
href: 'https://unsplash.com/@scottfillmer'
|
||||||
|
},
|
||||||
|
alt: 'Continental Airlines Boeing 777 maandub uduses Houston IAH lennujaamas.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
110: {
|
||||||
|
title: 'Maanteeraev',
|
||||||
|
description: 'Autosignaal 1m kauguselt',
|
||||||
|
image: {
|
||||||
|
src: carCrashImg,
|
||||||
|
credit: {
|
||||||
|
type: ImageCreditType.instagram,
|
||||||
|
author: 'Jordan Besson',
|
||||||
|
href: 'https://www.instagram.com/mr.blue.photographie'
|
||||||
|
},
|
||||||
|
alt: 'Dramaatiline auto trikk filmi jaoks. Kahe auto kokkupõrge.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
120: {
|
||||||
|
title: 'Mootorsaag',
|
||||||
|
description: 'Nüüd on juba valus. Soovitan kanda kõrvatroppe.',
|
||||||
|
image: {
|
||||||
|
src: chainsawImg,
|
||||||
|
credit: {
|
||||||
|
type: ImageCreditType.web,
|
||||||
|
author: 'Benjamin Jopen',
|
||||||
|
href: 'https://unsplash.com/@benjopen'
|
||||||
|
},
|
||||||
|
alt: 'Oranži ja musta värvi mootorsega lõigatakse langenud puud väiksemateks tükkideks.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
130: {
|
||||||
|
title: 'Kuidas sa nii lähedale said?',
|
||||||
|
description: 'Turboreaktiivmootoriga hävitaja lendutõus 15m kauguselt',
|
||||||
|
image: {
|
||||||
|
src: jetImg,
|
||||||
|
credit: {
|
||||||
|
type: ImageCreditType.web,
|
||||||
|
author: 'Colin Lloyd',
|
||||||
|
href: 'https://unsplash.com/@onthesearchforpineapples'
|
||||||
|
},
|
||||||
|
alt: 'Kaheksa F-16 hävitajat lendavad koos formatsioonis taevas.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
150: {
|
||||||
|
title: 'Aia mu kõrvad',
|
||||||
|
description: 'Tubli töö! Su trummikile rebenes!',
|
||||||
|
image: {
|
||||||
|
src: hearingaidImg,
|
||||||
|
credit: {
|
||||||
|
type: ImageCreditType.web,
|
||||||
|
author: 'Mark Paton',
|
||||||
|
href: 'https://unsplash.com/@heftiba'
|
||||||
|
},
|
||||||
|
alt: 'Lähivõte inimesest sisestamas oma kõrva kuuldeaparaati.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
Loading…
Add table
Reference in a new issue