Initial Watermaps import

This commit is contained in:
BuTzZ
2026-07-24 11:29:24 +02:00
commit 57f7b4dedb
129 changed files with 43136 additions and 0 deletions
+155
View File
@@ -0,0 +1,155 @@
import { describe, expect, it } from "vitest";
import type { FeatureCollection, Geometry } from "geojson";
import {
routeFeatureBounds,
routeLocksFromFeatures,
voyageHarboursFromFeatures
} from "../src/voyageHarbours";
describe("voyage harbour feature adapter", () => {
it("turns normalized point features into amenity-aware harbour candidates", () => {
const collection: FeatureCollection<Geometry> = {
type: "FeatureCollection",
features: [
{
type: "Feature",
id: "hamm-marina",
geometry: { type: "Point", coordinates: [7.8, 51.68] },
properties: {
layer: "harbours",
name: "Marina Hamm",
leisure: "marina",
phone: "+49 2381 123",
website: "hamm.example",
email: "hafen@hamm.example",
vhf: "12",
opening_hours: "täglich 08:00-20:00",
operator: "Hafen Hamm",
"addr:street": "Uferweg",
"addr:housenumber": "4",
"addr:postcode": "59000",
"addr:city": "Hamm",
power_supply: "yes",
drinking_water: "yes",
guest_berths: 8
}
},
{
type: "Feature",
geometry: { type: "LineString", coordinates: [[7, 52], [8, 52]] },
properties: { layer: "harbours", name: "Keine Punktgeometrie" }
},
{
type: "Feature",
geometry: { type: "Point", coordinates: [7.7, 51.7] },
properties: { layer: "locks", name: "Keine Marina" }
}
]
};
expect(voyageHarboursFromFeatures(collection)).toEqual([
expect.objectContaining({
id: "hamm-marina",
name: "Marina Hamm",
kind: "marina",
coordinate: { lat: 51.68, lon: 7.8 },
email: "hafen@hamm.example",
vhf: "12",
openingHours: "täglich 08:00-20:00",
operator: "Hafen Hamm",
address: "Uferweg 4, 59000 Hamm",
amenities: expect.objectContaining({
electricity: "available",
water: "available",
overnight: "available"
})
})
]);
});
it("calculates a nautical-mile padded feature request box", () => {
const bounds = routeFeatureBounds(
{
geometry: {
type: "LineString",
coordinates: [[7, 52], [8, 53]]
}
},
6
);
expect(bounds[0]).toBeLessThan(6.84);
expect(bounds[1]).toBeCloseTo(51.9, 5);
expect(bounds[2]).toBeGreaterThan(8.16);
expect(bounds[3]).toBeCloseTo(53.1, 5);
});
it("filters and orders route locks while preserving opening hours and phone", () => {
const collection: FeatureCollection<Geometry> = {
type: "FeatureCollection",
features: [
{
type: "Feature",
id: "lock-late",
geometry: { type: "Point", coordinates: [7.8, 52] },
properties: {
layer: "locks",
name: "Schleuse Ost",
openingHours: "Mo-Su 06:00-22:00",
phone: "+49 2381 200"
}
},
{
type: "Feature",
id: "lock-off-route",
geometry: { type: "Point", coordinates: [7.5, 52.02] },
properties: { layer: "locks", name: "Entfernte Schleuse" }
},
{
type: "Feature",
id: "lock-early",
geometry: { type: "Point", coordinates: [7.2, 52] },
properties: {
layer: "locks",
name: "Schleuse West",
opening_hours: "nach Anmeldung",
phone: "+49 2381 100"
}
},
{
type: "Feature",
id: "harbour-on-route",
geometry: { type: "Point", coordinates: [7.4, 52] },
properties: { layer: "harbours", name: "Kein Schleusenpunkt" }
}
]
};
const locks = routeLocksFromFeatures(collection, {
geometry: {
type: "LineString",
coordinates: [[7, 52], [8, 52]]
},
distanceNm: 41
});
expect(locks.map((lock) => lock.id)).toEqual(["lock-early", "lock-late"]);
expect(locks[0]).toEqual(
expect.objectContaining({
name: "Schleuse West",
openingHours: "nach Anmeldung",
phone: "+49 2381 100",
distanceFromRouteNm: 0
})
);
expect(locks[1]).toEqual(
expect.objectContaining({
name: "Schleuse Ost",
openingHours: "Mo-Su 06:00-22:00",
phone: "+49 2381 200",
distanceFromRouteNm: 0
})
);
expect(locks[0]!.routeDistanceNm).toBeLessThan(locks[1]!.routeDistanceNm);
});
});