diff --git a/src/lib/index.ts b/src/lib/index.ts index 529302e..9d84954 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,5 +1,7 @@ export interface GameOptions { mode: "easy" | "hard" | "extreme demon ultra miguel"; + metro: boolean; + tram: boolean; } export interface GameData { @@ -22,12 +24,15 @@ export interface CheckResponse { type FetchType = typeof fetch; -const linesUrl = +const metroUrl = "https://data.grandlyon.com/geoserver/sytral/ows?SERVICE=WFS&VERSION=2.0.0&request=GetFeature&typename=sytral:tcl_sytral.tcllignemf_2_0_0&outputFormat=application/json&SRSNAME=EPSG:4171&sortBy=gid"; +const tramUrl = + "https://data.grandlyon.com/geoserver/sytral/ows?SERVICE=WFS&VERSION=2.0.0&request=GetFeature&typename=sytral:tcl_sytral.tcllignetram_2_0_0&outputFormat=application/json&SRSNAME=EPSG:4171&sortBy=gid"; const stopsUrl = "https://data.grandlyon.com/geoserver/sytral/ows?SERVICE=WFS&VERSION=2.0.0&request=GetFeature&typename=sytral:tcl_sytral.tclarret&outputFormat=application/json&SRSNAME=EPSG:4171&sortBy=gid"; -let lazyLines: GeoJSON.FeatureCollection | null = null; +let lazyMetro: [GeoJSON.Feature, string][] | null = null; +let lazyTram: [GeoJSON.Feature, string][] | null = null; let lazyStops: GeoJSON.Feature[] | null = null; const games: Record = {}; @@ -44,8 +49,30 @@ export function stopGame(uuid: string): GeoJSON.Feature | null { return stop; } -export async function getLines(fetch: FetchType): Promise { - return lazyLines ?? (lazyLines = await fetch(linesUrl).then((r) => r.json())); +export async function getMetro(fetch: FetchType): Promise<[GeoJSON.Feature, string][]> { + if (!lazyMetro) { + const metro: GeoJSON.FeatureCollection = await fetch(metroUrl).then((r) => r.json()); + + lazyMetro = metro.features.map((f) => { + const components = f.properties!.couleur!.split(" "); + return [f, `rgb(${components.join(",")})`]; + }); + } + + return lazyMetro; +} + +export async function getTram(fetch: FetchType): Promise<[GeoJSON.Feature, string][]> { + if (!lazyTram) { + const tram: GeoJSON.FeatureCollection = await fetch(tramUrl).then((r) => r.json()); + + lazyTram = tram.features.map((f) => { + const components = f.properties!.couleur!.split(" "); + return [f, `rgb(${components.join(",")})`]; + }); + } + + return lazyTram; } export async function getStops(fetch: FetchType): Promise { diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index d4afdf3..2a9d3ed 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -15,6 +15,11 @@ +
+ + +
+ diff --git a/src/routes/api/data/+server.ts b/src/routes/api/data/+server.ts index d3788e2..e16f72c 100644 --- a/src/routes/api/data/+server.ts +++ b/src/routes/api/data/+server.ts @@ -1,9 +1,8 @@ import type { RequestHandler } from "./$types"; -import { createGame, getLines, getStops, type GameData, type GameOptions } from "$lib"; +import { createGame, getMetro, getStops, getTram, type GameData, type GameOptions } from "$lib"; import { error } from "@sveltejs/kit"; export const GET: RequestHandler = async ({ fetch, url }) => { - const lines = await getLines(fetch); const stops = await getStops(fetch); const mode = url.searchParams.get("mode"); @@ -11,14 +10,18 @@ export const GET: RequestHandler = async ({ fetch, url }) => { return error(400, "gamemode is invalid"); } - const options: GameOptions = { mode }; + const options: GameOptions = { + mode, + metro: url.searchParams.has("metro"), + tram: url.searchParams.has("tram"), + }; - const lineColors: [GeoJSON.Feature, string][] = lines.features.map((f) => { - const components = f.properties!.couleur!.split(" "); - return [f, `rgb(${components.join(",")})`]; - }); + const lineColors: [GeoJSON.Feature, string][] = []; - const lineCodes = new Set(lines.features.map((f) => f.properties!.code_ligne)); + if (options.metro) lineColors.push(...(await getMetro(fetch))); + if (options.tram) lineColors.push(...(await getTram(fetch))); + + const lineCodes = new Set(lineColors.map(([f, _]) => f.properties!.code_ligne)); const crossingStops = stops.filter((f) => { if (f.properties?.desserte) { @@ -32,8 +35,12 @@ export const GET: RequestHandler = async ({ fetch, url }) => { }); const randomStop = crossingStops[Math.floor(Math.random() * crossingStops.length)]; - const gameId = createGame(randomStop); + if (!randomStop) { + return error(400, "could not select random stop"); + } + + const gameId = createGame(randomStop); const data: GameData = { lines: options.mode === "easy" || options.mode === "hard" ? lineColors : [], stops: options.mode === "easy" ? crossingStops : [],