style: run prettier
All checks were successful
TrafficCue CI / check (push) Successful in 53s
TrafficCue CI / build (push) Successful in 46s

This commit is contained in:
Cfp
2025-06-27 14:34:45 +02:00
parent c861981ec4
commit c16e2e98ec
9 changed files with 114 additions and 71 deletions

View File

@ -9,7 +9,10 @@
} from "svelte-maplibre-gl";
import { view } from "./sidebar.svelte";
import { map, pin } from "./map.svelte";
import { decodePolyline, routing } from "$lib/services/navigation/routing.svelte";
import {
decodePolyline,
routing,
} from "$lib/services/navigation/routing.svelte";
import { location } from "./location.svelte";
onMount(() => {
@ -84,15 +87,23 @@
{/each} -->
<Marker
lnglat={{
lat: decodePolyline(routing.currentTrip!.legs[0].shape)[routing.currentTripInfo.currentManeuver!.begin_shape_index].lat,
lng: decodePolyline(routing.currentTrip!.legs[0].shape)[routing.currentTripInfo.currentManeuver!.begin_shape_index].lon
lat: decodePolyline(routing.currentTrip!.legs[0].shape)[
routing.currentTripInfo.currentManeuver!.begin_shape_index
].lat,
lng: decodePolyline(routing.currentTrip!.legs[0].shape)[
routing.currentTripInfo.currentManeuver!.begin_shape_index
].lon,
}}
color="lime"
/>
<Marker
lnglat={{
lat: decodePolyline(routing.currentTrip!.legs[0].shape)[routing.currentTripInfo.currentManeuver!.end_shape_index].lat,
lng: decodePolyline(routing.currentTrip!.legs[0].shape)[routing.currentTripInfo.currentManeuver!.end_shape_index].lon
lat: decodePolyline(routing.currentTrip!.legs[0].shape)[
routing.currentTripInfo.currentManeuver!.end_shape_index
].lat,
lng: decodePolyline(routing.currentTrip!.legs[0].shape)[
routing.currentTripInfo.currentManeuver!.end_shape_index
].lon,
}}
color="red"
/>

View File

@ -108,10 +108,15 @@
>
<div class="p-2 flex gap-2">
{#if routing.currentTripInfo.currentManeuver?.type === 26 || routing.currentTripInfo.currentManeuver?.type === 27}
{@const exit = routing.currentTripInfo.currentManeuver?.type === 26
{@const exit =
routing.currentTripInfo.currentManeuver?.type === 26
? routing.currentTripInfo.currentManeuver?.roundabout_exit_count
: routing.currentTrip?.legs[0].maneuvers[routing.currentTripInfo.maneuverIdx - 1].roundabout_exit_count}
<span class="border-white border-4 rounded-full text-3xl flex items-center justify-center w-12 h-12">
: routing.currentTrip?.legs[0].maneuvers[
routing.currentTripInfo.maneuverIdx - 1
].roundabout_exit_count}
<span
class="border-white border-4 rounded-full text-3xl flex items-center justify-center w-12 h-12"
>
{exit}
</span>
{:else}

View File

@ -65,7 +65,9 @@
<Input bind:value={toLocation} />
</div>
<span>
You can use <strong>current</strong> for your current location, <strong>home</strong> or <strong>work</strong> for saved locations.
You can use <strong>current</strong> for your current location,
<strong>home</strong>
or <strong>work</strong> for saved locations.
</span>
</div>
<Button
@ -122,7 +124,9 @@
{#if i == 0}
<StarIcon />
{/if}
{Math.round(route.summary.length)}km - {formatTime(Math.round(route.summary.time))}
{Math.round(route.summary.length)}km - {formatTime(
Math.round(route.summary.time),
)}
</Button>
{/each}
</div>

View File

@ -13,7 +13,7 @@ class DuckWeb extends WebPlugin implements DuckPlugin {
}
const Duck = registerPlugin<DuckPlugin>("Duck", {
web: new DuckWeb()
web: new DuckWeb(),
});
export default Duck;

View File

@ -1,12 +1,14 @@
import * as tts from '@diffusionstudio/vits-web';
import TTSWorker from './TTSWorker.ts?worker';
import * as tts from "@diffusionstudio/vits-web";
import TTSWorker from "./TTSWorker.ts?worker";
// const VOICE = "en_US-hfc_female-medium";
const VOICE = "de_DE-thorsten-medium";
export async function downloadVoice(): Promise<void> {
await tts.download(VOICE, (progress) => {
console.log(`Downloading ${progress.url} - ${Math.round(progress.loaded * 100 / progress.total)}%`);
console.log(
`Downloading ${progress.url} - ${Math.round((progress.loaded * 100) / progress.total)}%`,
);
});
}
@ -21,8 +23,10 @@ let playing = false;
let generating = 0;
const worker = new TTSWorker();
worker.addEventListener('message', (event: MessageEvent<{ type: 'result', audio: Blob, text: string }>) => {
if (event.data.type != 'result') return;
worker.addEventListener(
"message",
(event: MessageEvent<{ type: "result"; audio: Blob; text: string }>) => {
if (event.data.type != "result") return;
// const audio = new Audio();
// audio.src = URL.createObjectURL(event.data.audio);
@ -31,12 +35,13 @@ worker.addEventListener('message', (event: MessageEvent<{ type: 'result', audio:
// audio.onended = () => {
// playing = false;
// };
const item = queue.find(item => item.text === event.data.text);
const item = queue.find((item) => item.text === event.data.text);
if (item) {
item.audio = event.data.audio; // Set the audio blob for the item
generating--;
}
});
},
);
setInterval(() => {
// if(playing) return;
@ -73,9 +78,9 @@ setInterval(() => {
generating++;
console.log("Generating audio for:", item.text);
worker.postMessage({
type: 'init',
type: "init",
text: item.text,
voiceId: VOICE
voiceId: VOICE,
});
item.audio = undefined; // Reset audio to undefined until generated
}
@ -110,26 +115,28 @@ export function queueSpeech(text: string) {
// const audio = new Audio();
// audio.src = URL.createObjectURL(wav);
// audio.play();
if (queue.some(item => item.text === text)) {
if (queue.some((item) => item.text === text)) {
// console.warn("Text already in queue, not adding again:", text);
return;
}
console.log("Queuing text for speech:", text);
queue.push({
text,
shouldPlay: false
shouldPlay: false,
});
}
export function speak(text: string) {
const existingItem = queue.find(item => item.text === text);
const existingItem = queue.find((item) => item.text === text);
if (existingItem) {
existingItem.shouldPlay = true;
} else {
console.warn("Adding new item to play immediately. Consider queuing instead!");
console.warn(
"Adding new item to play immediately. Consider queuing instead!",
);
queue.push({
text,
shouldPlay: true
shouldPlay: true,
});
}
}

View File

@ -1,16 +1,18 @@
import * as tts from '@diffusionstudio/vits-web';
import * as tts from "@diffusionstudio/vits-web";
async function main(event: MessageEvent<tts.InferenceConfg & { type: 'init' }>) {
if (event.data?.type != 'init') return;
async function main(
event: MessageEvent<tts.InferenceConfg & { type: "init" }>,
) {
if (event.data?.type != "init") return;
const start = performance.now();
const blob = await tts.predict({
text: event.data.text,
voiceId: event.data.voiceId,
});
console.log('Time taken:', performance.now() - start + ' ms');
console.log("Time taken:", performance.now() - start + " ms");
self.postMessage({ type: 'result', audio: blob, text: event.data.text });
self.postMessage({ type: "result", audio: blob, text: event.data.text });
}
self.addEventListener('message', main);
self.addEventListener("message", main);

View File

@ -1,7 +1,10 @@
import { OVERPASS_SERVER } from "../hosts";
import type { OverpassResult } from "../Overpass";
export async function generateVoiceGuidance(maneuver: Maneuver, shape: WorldLocation[]): Promise<string> {
export async function generateVoiceGuidance(
maneuver: Maneuver,
shape: WorldLocation[],
): Promise<string> {
if (maneuver.begin_shape_index == 0) {
return maneuver.verbal_pre_transition_instruction;
}
@ -10,11 +13,16 @@ export async function generateVoiceGuidance(maneuver: Maneuver, shape: WorldLoca
return `Im Kreisverkehr die ${maneuver.roundabout_exit_count}te Ausfahrt nehmen${(maneuver.street_names ?? []).length == 0 ? "." : ` auf ${(maneuver.street_names || []).join(", ")}.`}`;
}
const landmarks = await findNearbyLandmarks(shape[maneuver.begin_shape_index]);
const landmarks = await findNearbyLandmarks(
shape[maneuver.begin_shape_index],
);
if (landmarks.length == 0) {
return maneuver.verbal_pre_transition_instruction;
}
console.log("Original instruction:", maneuver.verbal_pre_transition_instruction);
console.log(
"Original instruction:",
maneuver.verbal_pre_transition_instruction,
);
return `Hinter ${landmarks[0].tags.name}, ${typeToName(maneuver.type)}${(maneuver.street_names ?? []).length == 0 ? "." : ` auf ${(maneuver.street_names || []).join(", ")}.`}`;
}
@ -86,8 +94,12 @@ export async function findNearbyLandmarks(location: WorldLocation) {
}).then((res) => res.json() as Promise<OverpassResult>);
// Sort by distance to the location
return res.elements.sort((a, b) => {
const distA = Math.sqrt(Math.pow(a.lat! - lat, 2) + Math.pow(a.lon! - lon, 2));
const distB = Math.sqrt(Math.pow(b.lat! - lat, 2) + Math.pow(b.lon! - lon, 2));
const distA = Math.sqrt(
Math.pow(a.lat! - lat, 2) + Math.pow(a.lon! - lon, 2),
);
const distB = Math.sqrt(
Math.pow(b.lat! - lat, 2) + Math.pow(b.lon! - lon, 2),
);
return distA - distB;
});
}

View File

@ -194,11 +194,13 @@ async function tickRoute() {
);
if (distanceToEnd <= verbalDistance) {
hasAnnouncedPreInstruction = true;
const instruction = USE_LANDMARK_INSTRUCTIONS ? await generateVoiceGuidance(currentManeuver, polyline) : currentManeuver.verbal_pre_transition_instruction;
const instruction = USE_LANDMARK_INSTRUCTIONS
? await generateVoiceGuidance(currentManeuver, polyline)
: currentManeuver.verbal_pre_transition_instruction;
console.log(
"[Verbal instruction] ",
// currentManeuver.verbal_pre_transition_instruction,
instruction
instruction,
);
say(instruction);
}
@ -253,7 +255,7 @@ async function tickRoute() {
}
function verbalPreInstructionDistance(speed: number): number {
return (speed * 2.222) + 37.144;
return speed * 2.222 + 37.144;
}
export function stopNavigation() {