feat: add tram lines

This commit is contained in:
uku 2024-10-26 00:05:14 +02:00
parent a38d7dc5c2
commit ef8db66bfb
Signed by: uku
SSH key fingerprint: SHA256:4P0aN6M8ajKukNi6aPOaX0LacanGYtlfjmN+m/sHY/o
3 changed files with 52 additions and 13 deletions

View file

@ -1,5 +1,7 @@
export interface GameOptions { export interface GameOptions {
mode: "easy" | "hard" | "extreme demon ultra miguel"; mode: "easy" | "hard" | "extreme demon ultra miguel";
metro: boolean;
tram: boolean;
} }
export interface GameData { export interface GameData {
@ -22,12 +24,15 @@ export interface CheckResponse {
type FetchType = typeof fetch; 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"; "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 = 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"; "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; let lazyStops: GeoJSON.Feature[] | null = null;
const games: Record<string, GeoJSON.Feature> = {}; const games: Record<string, GeoJSON.Feature> = {};
@ -44,8 +49,30 @@ export function stopGame(uuid: string): GeoJSON.Feature | null {
return stop; return stop;
} }
export async function getLines(fetch: FetchType): Promise<GeoJSON.FeatureCollection> { export async function getMetro(fetch: FetchType): Promise<[GeoJSON.Feature, string][]> {
return lazyLines ?? (lazyLines = await fetch(linesUrl).then((r) => r.json())); 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<GeoJSON.Feature[]> { export async function getStops(fetch: FetchType): Promise<GeoJSON.Feature[]> {

View file

@ -15,6 +15,11 @@
</select> </select>
</label> </label>
<div>
<label>metro: <input type="checkbox" name="metro" checked /></label>
<label>tram: <input type="checkbox" name="tram" /></label>
</div>
<input type="submit" value="LANCER LA PARTIE" /> <input type="submit" value="LANCER LA PARTIE" />
</form> </form>
</div> </div>

View file

@ -1,9 +1,8 @@
import type { RequestHandler } from "./$types"; 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"; import { error } from "@sveltejs/kit";
export const GET: RequestHandler = async ({ fetch, url }) => { export const GET: RequestHandler = async ({ fetch, url }) => {
const lines = await getLines(fetch);
const stops = await getStops(fetch); const stops = await getStops(fetch);
const mode = url.searchParams.get("mode"); const mode = url.searchParams.get("mode");
@ -11,14 +10,18 @@ export const GET: RequestHandler = async ({ fetch, url }) => {
return error(400, "gamemode is invalid"); 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 lineColors: [GeoJSON.Feature, string][] = [];
const components = f.properties!.couleur!.split(" ");
return [f, `rgb(${components.join(",")})`];
});
const lineCodes = new Set<string>(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<string>(lineColors.map(([f, _]) => f.properties!.code_ligne));
const crossingStops = stops.filter((f) => { const crossingStops = stops.filter((f) => {
if (f.properties?.desserte) { 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 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 = { const data: GameData = {
lines: options.mode === "easy" || options.mode === "hard" ? lineColors : [], lines: options.mode === "easy" || options.mode === "hard" ? lineColors : [],
stops: options.mode === "easy" ? crossingStops : [], stops: options.mode === "easy" ? crossingStops : [],