Hinweise optimiert
This commit is contained in:
+1
-10
@@ -56,16 +56,7 @@ const routeRequestSchema = z.object({
|
||||
airDraftM: z.number().positive().max(80).optional(),
|
||||
beamM: z.number().positive().max(80).optional(),
|
||||
cruiseSpeedKn: z.number().positive().max(80).optional()
|
||||
}),
|
||||
depthSamples: z
|
||||
.array(
|
||||
z.object({
|
||||
coordinate: coordinateSchema,
|
||||
depthM: z.number().nullable()
|
||||
})
|
||||
)
|
||||
.max(500)
|
||||
.optional()
|
||||
})
|
||||
}) satisfies z.ZodType<RouteRequest>;
|
||||
|
||||
const coordinateQuerySchema = z.object({
|
||||
|
||||
@@ -54,7 +54,6 @@ export type FairwayRow = {
|
||||
source: string;
|
||||
source_id: string | null;
|
||||
name: string | null;
|
||||
min_depth_m: string | number | null;
|
||||
properties?: Record<string, unknown> | null;
|
||||
geometry: {
|
||||
type: "LineString";
|
||||
@@ -165,7 +164,6 @@ export class FairwayService {
|
||||
source,
|
||||
source_id,
|
||||
name,
|
||||
min_depth_m,
|
||||
properties,
|
||||
ST_AsGeoJSON(geom)::json AS geometry
|
||||
FROM marine_fairway_edges
|
||||
@@ -328,7 +326,6 @@ export function fairwayRowsToGraph(rows: FairwayRow[], bbox: [number, number, nu
|
||||
id: `postgis-edge-${row.id}`,
|
||||
name: row.name ?? row.source_id ?? `PostGIS ${row.id}`,
|
||||
coordinates: row.geometry.coordinates.map(([lon, lat]) => ({ lon, lat })),
|
||||
minDepthM: parseNumeric(row.min_depth_m),
|
||||
source: `postgis-${row.source}`,
|
||||
...edgeRestrictions(tags)
|
||||
};
|
||||
@@ -352,7 +349,6 @@ export function overpassToGraph(response: OverpassResponse, bbox: [number, numbe
|
||||
id: `osm-way-${element.id}`,
|
||||
name: tags.name ?? tags.ref ?? `OSM ${element.id}`,
|
||||
coordinates,
|
||||
minDepthM: parseDepth(tags),
|
||||
source: sourceFor(tags),
|
||||
...edgeRestrictions(tags)
|
||||
};
|
||||
@@ -386,7 +382,6 @@ export function localFairwaysToGraph(
|
||||
id: `local-osm-way-${way.id}`,
|
||||
name: tags.name ?? tags.ref ?? `OSM ${way.id}`,
|
||||
coordinates,
|
||||
minDepthM: parseDepth(tags),
|
||||
source: `local-geofabrik-${source}`,
|
||||
...edgeRestrictions(tags)
|
||||
};
|
||||
@@ -443,7 +438,6 @@ function waysToGraph(
|
||||
id: string;
|
||||
name: string;
|
||||
coordinates: Coordinate[];
|
||||
minDepthM: number | null;
|
||||
source: string;
|
||||
maxAirDraftM?: number | null;
|
||||
maxBeamM?: number | null;
|
||||
@@ -473,7 +467,6 @@ function waysToGraph(
|
||||
from,
|
||||
to,
|
||||
coordinates: [start, end],
|
||||
minDepthM: way.minDepthM,
|
||||
source: way.source,
|
||||
maxAirDraftM: way.maxAirDraftM,
|
||||
maxBeamM: way.maxBeamM,
|
||||
@@ -579,28 +572,6 @@ function nodeIdFor(nodes: Map<string, FairwayNode>, coordinate: Coordinate) {
|
||||
return id;
|
||||
}
|
||||
|
||||
function parseDepth(tags: Record<string, string>) {
|
||||
const candidates = [
|
||||
tags["seamark:fairway:minimum_depth"],
|
||||
tags["seamark:recommended_track:minimum_depth"],
|
||||
tags["seamark:navigation_line:minimum_depth"],
|
||||
tags["depth"],
|
||||
tags["min_depth"]
|
||||
];
|
||||
|
||||
for (const candidate of candidates) {
|
||||
if (!candidate) {
|
||||
continue;
|
||||
}
|
||||
const parsed = parseNumeric(candidate);
|
||||
if (Number.isFinite(parsed)) {
|
||||
return parsed;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function edgeRestrictions(tags: Record<string, string>) {
|
||||
return {
|
||||
maxAirDraftM: firstNumericTag(tags, [
|
||||
|
||||
@@ -36,7 +36,6 @@ const testFairwayGraph = (
|
||||
from: `${id}-start`,
|
||||
to: `${id}-destination`,
|
||||
coordinates: [start, destination],
|
||||
minDepthM: null,
|
||||
source: "test-fairway-source"
|
||||
}
|
||||
]
|
||||
@@ -68,7 +67,6 @@ const boundedSnapSearchFixture = () => {
|
||||
from: "junction",
|
||||
to: `trap-${index + 1}`,
|
||||
coordinates: [{ lat: 52, lon: 7 }, coordinate],
|
||||
minDepthM: 4,
|
||||
oneway: true as const,
|
||||
source: `api-bounded-trap-${index + 1}`
|
||||
})),
|
||||
@@ -78,7 +76,6 @@ const boundedSnapSearchFixture = () => {
|
||||
from: "junction",
|
||||
to: "destination",
|
||||
coordinates: [{ lat: 52, lon: 7 }, destination],
|
||||
minDepthM: 4,
|
||||
oneway: true as const,
|
||||
source: "api-ninth-main-route"
|
||||
}
|
||||
@@ -220,26 +217,6 @@ describe("Watermaps API", () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
it("returns critical route warnings for shallow samples", async () => {
|
||||
const app = await buildServer({ cache: createCache(), env: demoEnv });
|
||||
const response = await app.inject({
|
||||
method: "POST",
|
||||
url: "/api/routes",
|
||||
payload: {
|
||||
start: { lat: 53.344167, lon: 7.186111 },
|
||||
destination: { lat: 53.563776, lon: 6.750562 },
|
||||
vesselProfile: { draughtM: 1.5, safetyReserveM: 0.4 },
|
||||
depthSamples: [{ coordinate: { lat: 53.442996, lon: 6.833146 }, depthM: 1.6 }]
|
||||
}
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.json().warnings.some((warning: { severity: string }) => warning.severity === "critical")).toBe(
|
||||
true
|
||||
);
|
||||
await app.close();
|
||||
});
|
||||
|
||||
it("rejects routes without a known fairway instead of returning a straight line", async () => {
|
||||
const app = await buildServer({
|
||||
cache: createCache(),
|
||||
@@ -443,7 +420,6 @@ describe("Watermaps API", () => {
|
||||
expect(body.routingMode).toBe("fairway");
|
||||
expect(body.dataSources).toContain("fairway-graph:ems-borkum-seed");
|
||||
expect(body.geometry.coordinates.length).toBeGreaterThan(20);
|
||||
expect(body.warnings.some((warning: { code: string }) => warning.code === "FAIRWAY_ROUTE")).toBe(true);
|
||||
await app.close();
|
||||
});
|
||||
|
||||
@@ -469,7 +445,6 @@ describe("Watermaps API", () => {
|
||||
name: "Norddeich Fahrwasser",
|
||||
from: "norddeich",
|
||||
to: "fairway",
|
||||
minDepthM: null,
|
||||
source: "local-geofabrik-test",
|
||||
coordinates: [
|
||||
{ lat: 53.6234, lon: 7.1559 },
|
||||
@@ -481,7 +456,6 @@ describe("Watermaps API", () => {
|
||||
name: "Norderney Fahrwasser",
|
||||
from: "fairway",
|
||||
to: "norderney",
|
||||
minDepthM: null,
|
||||
source: "local-geofabrik-test",
|
||||
coordinates: [
|
||||
{ lat: 53.66, lon: 7.16 },
|
||||
@@ -605,7 +579,6 @@ describe("Watermaps API", () => {
|
||||
name: "AB",
|
||||
from: "a",
|
||||
to: "b",
|
||||
minDepthM: 4,
|
||||
source: "test-overpass",
|
||||
coordinates: [
|
||||
{ lat: 54, lon: 10 },
|
||||
@@ -617,7 +590,6 @@ describe("Watermaps API", () => {
|
||||
name: "BC",
|
||||
from: "b",
|
||||
to: "c",
|
||||
minDepthM: 4,
|
||||
source: "test-overpass",
|
||||
coordinates: [
|
||||
{ lat: 54.02, lon: 10.05 },
|
||||
@@ -679,7 +651,6 @@ describe("Watermaps API", () => {
|
||||
from: "start-decoy-a",
|
||||
to: "start-decoy-b",
|
||||
coordinates: [coordinate(53.3416, 7.186), coordinate(53.342, 7.187)],
|
||||
minDepthM: null,
|
||||
source: "closer-but-disconnected-start"
|
||||
},
|
||||
{
|
||||
@@ -688,7 +659,6 @@ describe("Watermaps API", () => {
|
||||
from: "destination-decoy-a",
|
||||
to: "destination-decoy-b",
|
||||
coordinates: [coordinate(53.3282, 6.9304), coordinate(53.3286, 6.9294)],
|
||||
minDepthM: null,
|
||||
source: "closer-but-disconnected-destination"
|
||||
},
|
||||
{
|
||||
@@ -697,7 +667,6 @@ describe("Watermaps API", () => {
|
||||
from: "shared-start",
|
||||
to: "shared-east",
|
||||
coordinates: [coordinate(53.34145, 7.18585), coordinate(53.3321722, 7.1329034)],
|
||||
minDepthM: null,
|
||||
source: "local-geofabrik-germany+netherlands"
|
||||
},
|
||||
{
|
||||
@@ -706,7 +675,6 @@ describe("Watermaps API", () => {
|
||||
from: "shared-east",
|
||||
to: "shared-south",
|
||||
coordinates: [coordinate(53.3321722, 7.1329034), coordinate(53.313849, 7.0011017)],
|
||||
minDepthM: null,
|
||||
source: "local-geofabrik-germany+netherlands"
|
||||
},
|
||||
{
|
||||
@@ -715,7 +683,6 @@ describe("Watermaps API", () => {
|
||||
from: "shared-south",
|
||||
to: "shared-destination",
|
||||
coordinates: [coordinate(53.313849, 7.0011017), coordinate(53.32805, 6.9302)],
|
||||
minDepthM: null,
|
||||
source: "local-geofabrik-germany+netherlands"
|
||||
}
|
||||
]
|
||||
@@ -765,7 +732,6 @@ describe("Watermaps API", () => {
|
||||
from,
|
||||
to,
|
||||
coordinates,
|
||||
minDepthM: 4,
|
||||
source: "test-alternatives"
|
||||
});
|
||||
const app = await buildServer({
|
||||
|
||||
@@ -378,7 +378,6 @@ describe("fairway graph extraction", () => {
|
||||
source: "osm",
|
||||
source_id: "way-1",
|
||||
name: "Harbour Reach",
|
||||
min_depth_m: "4.2",
|
||||
geometry: {
|
||||
type: "LineString",
|
||||
coordinates: [
|
||||
@@ -392,7 +391,6 @@ describe("fairway graph extraction", () => {
|
||||
source: "osm",
|
||||
source_id: "way-2",
|
||||
name: "Outer Reach",
|
||||
min_depth_m: 4.2,
|
||||
geometry: {
|
||||
type: "LineString",
|
||||
coordinates: [
|
||||
@@ -430,7 +428,6 @@ describe("fairway graph extraction", () => {
|
||||
source: "osm",
|
||||
source_id: "way-main",
|
||||
name: "Ems Fahrwasser",
|
||||
min_depth_m: null,
|
||||
geometry: {
|
||||
type: "LineString",
|
||||
coordinates: [
|
||||
@@ -447,7 +444,6 @@ describe("fairway graph extraction", () => {
|
||||
source: "osm",
|
||||
source_id: "way-branch",
|
||||
name: "Busetief",
|
||||
min_depth_m: null,
|
||||
geometry: {
|
||||
type: "LineString",
|
||||
coordinates: [
|
||||
@@ -495,8 +491,7 @@ describe("fairway graph extraction", () => {
|
||||
type: "way",
|
||||
id: 123,
|
||||
tags: {
|
||||
"seamark:type": "navigation_line",
|
||||
"seamark:navigation_line:minimum_depth": "3.5"
|
||||
"seamark:type": "navigation_line"
|
||||
},
|
||||
geometry: [
|
||||
{ lat: 54, lon: 10 },
|
||||
@@ -510,7 +505,6 @@ describe("fairway graph extraction", () => {
|
||||
|
||||
expect(graph).not.toBeNull();
|
||||
expect(graph?.edges[0]?.source).toBe("osm-overpass-seamarks");
|
||||
expect(graph?.edges[0]?.minDepthM).toBe(3.5);
|
||||
});
|
||||
|
||||
it("accepts navigable canals but rejects explicitly closed waterways", () => {
|
||||
@@ -553,7 +547,6 @@ describe("fairway graph extraction", () => {
|
||||
source: "osm",
|
||||
source_id: "north",
|
||||
name: "Dortmund-Ems-Kanal",
|
||||
min_depth_m: null,
|
||||
geometry: {
|
||||
type: "LineString",
|
||||
coordinates: [
|
||||
@@ -604,7 +597,6 @@ describe("fairway graph extraction", () => {
|
||||
source: "osm",
|
||||
source_id: "way-restricted",
|
||||
name: "Niedrige Durchfahrt",
|
||||
min_depth_m: "3.0",
|
||||
properties: { maxheight: "2.4 m", maxwidth: "3.2", maxdraft: "1.8", oneway: "yes" },
|
||||
geometry: {
|
||||
type: "LineString",
|
||||
|
||||
Reference in New Issue
Block a user