parkData.test.js prüfte die Fahrzeug-Startpunkte noch gegen c.roads, den es im neuen Chunk-Format nicht mehr gibt; jetzt gegen c.carriageway, die schärfere Aussage (das Auto steht auf der Fahrbahn, nicht nur irgendwo im alten, breiteren Korridor). materials.test.js und props.test.js trugen noch die toten Schlüssel roads/centerlines bzw. einen Kommentar auf centerlines() — beides Relikte vor dem Straßen-Umbau, ersatzlos entfernt bzw. auf edges umformuliert. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
61 lines
3.2 KiB
JavaScript
61 lines
3.2 KiB
JavaScript
import { readFileSync } from "node:fs";
|
|
import { describe, expect, it } from "vitest";
|
|
import { chunkForWorld } from "../src/world/coords.js";
|
|
import { PLACES } from "../src/world/places.js";
|
|
import { pointInPolygon } from "../src/world/props.js";
|
|
import { SPAWN, VEHICLE_SPAWN_POINTS } from "../src/world/spawn.js";
|
|
|
|
const PARK_FILE = readFileSync(new URL("../tools/extract/data/flamingo-park.toml", import.meta.url), "utf8");
|
|
|
|
/** Die [[keepout]]-Blöcke der Parkdatei. Ihr Format steht in der Spec fest; ein allgemeiner TOML-Leser wäre zu viel. */
|
|
function keepouts(text) {
|
|
const number = "(-?[\\d.]+)";
|
|
return text.split("[[keepout]]").slice(1).map((block) => {
|
|
const body = block.split(/\n\[/)[0];
|
|
const at = body.match(new RegExp(`\\nat\\s*=\\s*\\[${number},\\s*${number}\\]`));
|
|
const rotation = body.match(new RegExp(`\\nrotation\\s*=\\s*${number}`));
|
|
const bounds = body.match(new RegExp(
|
|
`bounds\\s*=\\s*\\{\\s*min_x\\s*=\\s*${number},\\s*max_x\\s*=\\s*${number},\\s*min_z\\s*=\\s*${number},\\s*max_z\\s*=\\s*${number}\\s*\\}`));
|
|
return {
|
|
name: body.match(/name\s*=\s*"([^"]+)"/)[1],
|
|
at: [Number(at[1]), Number(at[2])],
|
|
rotation: Number(rotation[1]),
|
|
bounds: { minX: Number(bounds[1]), maxX: Number(bounds[2]), minZ: Number(bounds[3]), maxZ: Number(bounds[4]) },
|
|
};
|
|
});
|
|
}
|
|
|
|
function chunkAt(X, Y) {
|
|
const { i, j } = chunkForWorld(X, Y);
|
|
return JSON.parse(readFileSync(new URL(`../public/data/vice-a/chunk_${i}_${j}.json`, import.meta.url), "utf8"));
|
|
}
|
|
|
|
describe("Flamingo-Park-Daten", () => {
|
|
// Bruch: ein Ort wird verschoben oder gedreht, die Pipeline hält aber die alte Fläche frei — Palmen,
|
|
// Wege oder OSM-Gebäude landeten dann im Ort.
|
|
it("hat für jeden Ort eine Sperrfläche mit dessen Lage, Drehung und Außenmaßen", () => {
|
|
const byName = Object.fromEntries(keepouts(PARK_FILE).map((keepout) => [keepout.name, keepout]));
|
|
for (const place of PLACES) {
|
|
expect(byName[place.id], place.id).toEqual({ name: place.id, at: place.at, rotation: place.rotation, bounds: place.bounds });
|
|
}
|
|
});
|
|
|
|
// Bruch: der Startpunkt liegt nach dem Umbau des Parks in einem Gebäude oder über Wasser.
|
|
it("setzt den Startpunkt auf Land und in kein Gebäude", () => {
|
|
const c = chunkAt(SPAWN.x, -SPAWN.z);
|
|
const u = SPAWN.x - c.origin[0], v = SPAWN.z - c.origin[1];
|
|
expect(c.land.some((rings) => pointInPolygon(u, v, rings))).toBe(true);
|
|
expect(c.buildings.some((building) => pointInPolygon(u, v, building.poly))).toBe(false);
|
|
});
|
|
|
|
// Bruch: das Abschneiden am Park nimmt der 11th Street ein Stück, und ein Auto fällt beim Start durch.
|
|
// Gemessen wird gegen die Fahrbahn (carriageway), nicht den alten, breiteren Korridor: Ein stehendes
|
|
// Auto gehört auf die Fahrbahn selbst, das ist die schärfere Aussage.
|
|
it("lässt die vier Autos auf einer Straße stehen", () => {
|
|
for (const [x, , z] of VEHICLE_SPAWN_POINTS) {
|
|
const c = chunkAt(x, -z);
|
|
expect(c.carriageway.some((road) => pointInPolygon(x - c.origin[0], z - c.origin[1], road.poly)), `${x} / ${-z}`).toBe(true);
|
|
}
|
|
});
|
|
});
|