From cec613d989f14cc235b9a688f3ac76da16d1d3e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ullrich=20Sch=C3=A4fer?= Date: Sat, 11 Apr 2026 09:06:30 +0200 Subject: [PATCH] Fix E2E select locator, remove maxspeed mode (data unavailable) E2E fixes: - Color mode select locator uses option[value='highway'] filter instead of fragile page.locator("select").last() Removed maxspeed color mode: - BRouter does not expose maxspeed in WayTags output despite the tag existing in its lookup table. The dummyUsage profile trick only affects cost calculation, not tiledesc output. - Can revisit if BRouter adds maxspeed to WayTags in a future version or if we fork/patch the BRouter profiles more deeply. Co-Authored-By: Claude Opus 4.6 (1M context) --- apps/planner/app/components/ColoredRoute.tsx | 40 ++-------------- .../planner/app/components/ElevationChart.tsx | 47 ++----------------- apps/planner/app/components/PlannerMap.tsx | 9 ---- apps/planner/app/lib/brouter.ts | 21 ++------- apps/planner/app/lib/use-routing.ts | 3 -- e2e/fixtures/brouter-mock.ts | 7 --- packages/i18n/src/locales/de.ts | 2 - packages/i18n/src/locales/en.ts | 2 - 8 files changed, 9 insertions(+), 122 deletions(-) diff --git a/apps/planner/app/components/ColoredRoute.tsx b/apps/planner/app/components/ColoredRoute.tsx index 469c27e..a4b06d7 100644 --- a/apps/planner/app/components/ColoredRoute.tsx +++ b/apps/planner/app/components/ColoredRoute.tsx @@ -2,14 +2,13 @@ import { useMemo } from "react"; import { Polyline } from "react-leaflet"; import type L from "leaflet"; -export type ColorMode = "plain" | "elevation" | "surface" | "grade" | "highway" | "maxspeed"; +export type ColorMode = "plain" | "elevation" | "surface" | "grade" | "highway"; interface ColoredRouteProps { coordinates: [number, number, number][]; // [lon, lat, ele] colorMode: ColorMode; surfaces?: string[]; highways?: string[]; - maxspeeds?: string[]; } const SURFACE_COLORS: Record = { @@ -64,22 +63,6 @@ const HIGHWAY_COLORS: Record = { const DEFAULT_HIGHWAY_COLOR = "#9ca3af"; -export function maxspeedColor(speed: string): string { - const num = parseInt(speed, 10); - if (isNaN(num)) { - // Handle text values: "walk", "none", "unknown" - if (speed === "walk") return "#22c55e"; - if (speed === "none") return "#991b1b"; - return "#9ca3af"; - } - if (num <= 20) return "#22c55e"; // green: walking pace - if (num <= 30) return "#16a34a"; // green: slow zone - if (num <= 50) return "#eab308"; // yellow: urban - if (num <= 70) return "#f97316"; // orange: suburban - if (num <= 100) return "#ef4444"; // red: rural - return "#991b1b"; // dark red: highway -} - export function routeGradeColor(grade: number): string { const absGrade = Math.abs(grade); if (absGrade < 3) return "#22c55e"; @@ -99,7 +82,7 @@ export function elevationColor(t: number): string { return `rgb(255, ${g}, 50)`; } -export function ColoredRoute({ coordinates, colorMode, surfaces, highways, maxspeeds }: ColoredRouteProps) { +export function ColoredRoute({ coordinates, colorMode, surfaces, highways }: ColoredRouteProps) { const segments = useMemo(() => { if (colorMode === "plain" || coordinates.length < 2) { return null; @@ -164,23 +147,6 @@ export function ColoredRoute({ coordinates, colorMode, surfaces, highways, maxsp return result; } - // maxspeed mode - if (colorMode === "maxspeed") { - if (!maxspeeds || maxspeeds.length < coordinates.length) return null; - - const result: { positions: L.LatLngExpression[]; color: string }[] = []; - for (let i = 0; i < coordinates.length - 1; i++) { - result.push({ - positions: [ - [coordinates[i]![1], coordinates[i]![0]], - [coordinates[i + 1]![1], coordinates[i + 1]![0]], - ], - color: maxspeedColor(maxspeeds[i] ?? "unknown"), - }); - } - return result; - } - // surface mode if (!surfaces || surfaces.length < coordinates.length) return null; @@ -196,7 +162,7 @@ export function ColoredRoute({ coordinates, colorMode, surfaces, highways, maxsp }); } return result; - }, [coordinates, colorMode, surfaces, highways, maxspeeds]); + }, [coordinates, colorMode, surfaces, highways]); const plainPositions = useMemo( () => coordinates.map((c) => [c[1], c[0]] as L.LatLngExpression), diff --git a/apps/planner/app/components/ElevationChart.tsx b/apps/planner/app/components/ElevationChart.tsx index 0cecc7f..0d8edc0 100644 --- a/apps/planner/app/components/ElevationChart.tsx +++ b/apps/planner/app/components/ElevationChart.tsx @@ -2,7 +2,7 @@ import { useEffect, useState, useRef, useCallback } from "react"; import { useTranslation } from "react-i18next"; import type { DayStage } from "@trails-cool/gpx"; import type { YjsState } from "~/lib/use-yjs"; -import { elevationColor, SURFACE_COLORS, DEFAULT_SURFACE_COLOR, HIGHWAY_COLORS, DEFAULT_HIGHWAY_COLOR, maxspeedColor, type ColorMode } from "~/components/ColoredRoute"; +import { elevationColor, SURFACE_COLORS, DEFAULT_SURFACE_COLOR, HIGHWAY_COLORS, DEFAULT_HIGHWAY_COLOR, type ColorMode } from "~/components/ColoredRoute"; function gradeColor(grade: number): string { const absGrade = Math.abs(grade); @@ -76,7 +76,6 @@ export function ElevationChart({ yjs, onHover, days }: ElevationChartProps) { const [colorMode, setColorMode] = useState("plain"); const [surfaces, setSurfaces] = useState([]); const [highways, setHighways] = useState([]); - const [maxspeeds, setMaxspeeds] = useState([]); const canvasRef = useRef(null); const pointsRef = useRef([]); pointsRef.current = points; @@ -103,12 +102,6 @@ export function ElevationChart({ yjs, onHover, days }: ElevationChartProps) { } else { setHighways([]); } - const maxspeedsJson = yjs.routeData.get("maxspeeds") as string | undefined; - if (maxspeedsJson) { - try { setMaxspeeds(JSON.parse(maxspeedsJson)); } catch { setMaxspeeds([]); } - } else { - setMaxspeeds([]); - } }; yjs.routeData.observe(update); update(); @@ -241,29 +234,6 @@ export function ElevationChart({ yjs, onHover, days }: ElevationChartProps) { ctx.fillStyle = color + "40"; ctx.fill(); - ctx.beginPath(); - ctx.moveTo(toX(p0.distance), toY(p0.elevation)); - ctx.lineTo(toX(p1.distance), toY(p1.elevation)); - ctx.strokeStyle = color; - ctx.lineWidth = 2; - ctx.stroke(); - } - } else if (colorMode === "maxspeed" && maxspeeds.length >= points.length) { - // Maxspeed-colored segments - for (let i = 0; i < points.length - 1; i++) { - const p0 = points[i]!; - const p1 = points[i + 1]!; - const color = maxspeedColor(maxspeeds[i] ?? "unknown"); - - ctx.beginPath(); - ctx.moveTo(toX(p0.distance), PADDING.top + chartH); - ctx.lineTo(toX(p0.distance), toY(p0.elevation)); - ctx.lineTo(toX(p1.distance), toY(p1.elevation)); - ctx.lineTo(toX(p1.distance), PADDING.top + chartH); - ctx.closePath(); - ctx.fillStyle = color + "40"; - ctx.fill(); - ctx.beginPath(); ctx.moveTo(toX(p0.distance), toY(p0.elevation)); ctx.lineTo(toX(p1.distance), toY(p1.elevation)); @@ -369,15 +339,12 @@ export function ElevationChart({ yjs, onHover, days }: ElevationChartProps) { if (colorMode === "highway" && highways[highlightIdx]) { label += ` · ${highways[highlightIdx]}`; } - if (colorMode === "maxspeed" && maxspeeds[highlightIdx]) { - label += ` · ${maxspeeds[highlightIdx]} km/h`; - } const labelX = hx + 8 > w - 80 ? hx - 8 : hx + 8; ctx.textAlign = hx + 8 > w - 80 ? "right" : "left"; ctx.fillText(label, labelX, PADDING.top + 10); } }, - [points, colorMode, surfaces, highways, maxspeeds, days, t], + [points, colorMode, surfaces, highways, days, t], ); useEffect(() => { @@ -436,7 +403,7 @@ export function ElevationChart({ yjs, onHover, days }: ElevationChartProps) {

- {colorMode === "grade" ? t("elevation.grade") : colorMode === "highway" ? t("elevation.highway") : colorMode === "maxspeed" ? t("elevation.maxspeed") : t("elevation.profile")} + {colorMode === "grade" ? t("elevation.grade") : colorMode === "highway" ? t("elevation.highway") : t("elevation.profile")}

{colorMode === "grade" && (<> @@ -469,13 +436,6 @@ export function ElevationChart({ yjs, onHover, days }: ElevationChartProps) { ))} {[...new Set(highways)].length > 6 && +{[...new Set(highways)].length - 6}} )} - {colorMode === "maxspeed" && (<> - ≤30 - ≤50 - ≤70 - ≤100 - 100+ - )}
([]); const [surfaces, setSurfaces] = useState([]); const [highways, setHighways] = useState([]); - const [maxspeeds, setMaxspeeds] = useState([]); const [colorMode, setColorMode] = useState("plain"); const [noGoDrawing, setNoGoDrawing] = useState(false); const toggleNoGoDraw = useCallback(() => setNoGoDrawing((v) => !v), []); @@ -451,13 +450,6 @@ export function PlannerMap({ yjs, onRouteRequest, highlightPosition, highlighted setHighways([]); } - const maxspeedsJson = yjs.routeData.get("maxspeeds") as string | undefined; - if (maxspeedsJson) { - try { setMaxspeeds(JSON.parse(maxspeedsJson)); } catch { setMaxspeeds([]); } - } else { - setMaxspeeds([]); - } - if (modeVal) setColorMode(modeVal); }; @@ -739,7 +731,6 @@ export function PlannerMap({ yjs, onRouteRequest, highlightPosition, highlighted colorMode={colorMode} surfaces={surfaces} highways={highways} - maxspeeds={maxspeeds} /> []): Enric const allCoords: [number, number, number][] = []; const allSurfaces: string[] = []; const allHighways: string[] = []; - const allMaxspeeds: string[] = []; const segmentBoundaries: number[] = []; let totalLength = 0; let totalAscend = 0; @@ -122,7 +120,6 @@ export function mergeGeoJsonSegments(segments: Record[]): Enric allCoords.push([c[0]!, c[1]!, c[2] ?? 0]); allSurfaces.push(wayTagData.surfaces.get(j) ?? wayTagData.surfaces.get(j - 1) ?? "unknown"); allHighways.push(wayTagData.highways.get(j) ?? wayTagData.highways.get(j - 1) ?? "unknown"); - allMaxspeeds.push(wayTagData.maxspeeds.get(j) ?? wayTagData.maxspeeds.get(j - 1) ?? "unknown"); } // Accumulate stats @@ -156,7 +153,6 @@ export function mergeGeoJsonSegments(segments: Record[]): Enric segmentBoundaries, surfaces: allSurfaces, highways: allHighways, - maxspeeds: allMaxspeeds, totalLength, totalAscend, totalTime, @@ -167,7 +163,6 @@ export function mergeGeoJsonSegments(segments: Record[]): Enric interface WayTagData { surfaces: Map; highways: Map; - maxspeeds: Map; } /** @@ -178,13 +173,12 @@ interface WayTagData { function extractWayTagData(properties: Record): WayTagData { const surfaces = new Map(); const highways = new Map(); - const maxspeeds = new Map(); const messages = properties.messages as string[][] | undefined; - if (!messages || messages.length < 2) return { surfaces, highways, maxspeeds }; + if (!messages || messages.length < 2) return { surfaces, highways }; const headers = messages[0]!; const wayTagsIdx = headers.indexOf("WayTags"); - if (wayTagsIdx === -1) return { surfaces, highways, maxspeeds }; + if (wayTagsIdx === -1) return { surfaces, highways }; for (let i = 1; i < messages.length; i++) { const row = messages[i]!; @@ -193,17 +187,8 @@ function extractWayTagData(properties: Record): WayTagData { surfaces.set(i - 1, surfaceMatch ? surfaceMatch[1]! : "unknown"); const highwayMatch = tags.match(/highway=(\S+)/); highways.set(i - 1, highwayMatch ? highwayMatch[1]! : "unknown"); - // Handle maxspeed variants: maxspeed:forward, maxspeed:backward, maxspeed - const hasReverse = tags.includes("reversedirection=yes"); - const forwardMatch = tags.match(/maxspeed:forward=(\S+)/); - const backwardMatch = tags.match(/maxspeed:backward=(\S+)/); - const plainMatch = tags.match(/(?