import { describe, expect, it } from "vitest"; import { separateShips, shipRotation, type FlightLayout } from "../src/map/layout"; import { mapStyle } from "../src/map/style"; const deg = (radians: number) => (radians * 180) / Math.PI; describe("ships in flight (Step 10C.8)", () => { it("turns the up-pointing art to face the direction of travel", () => { expect(deg(shipRotation({ x: 0, y: 0 }, { x: 10, y: 0 }))).toBeCloseTo(90); expect(deg(shipRotation({ x: 0, y: 0 }, { x: 0, y: 10 }))).toBeCloseTo(180); expect(deg(shipRotation({ x: 0, y: 10 }, { x: 0, y: 0 }))).toBeCloseTo(0); expect(deg(shipRotation({ x: 10, y: 0 }, { x: 0, y: 0 }))).toBeCloseTo(270); // = -90° }); const flight = (dispatchId: string, x = 100, y = 100): FlightLayout => ({ dispatchId, from: { x: 0, y: 100 }, to: { x: 200, y: 100 }, center: { x, y }, rotation: Math.PI / 2, size: 24, tap: 44, }); it("spreads three ships at the same spot apart, at least a tap target apart", () => { const spread = separateShips([flight("a"), flight("b"), flight("c")]); const points = spread.map((f) => f.center); for (let i = 0; i < points.length; i++) { for (let j = i + 1; j < points.length; j++) { const d = Math.hypot(points[i]!.x - points[j]!.x, points[i]!.y - points[j]!.y); expect(d).toBeGreaterThanOrEqual(mapStyle.minTapPx); } } // Perpendicular to the (horizontal) route, centred on where they were. expect(points.map((p) => p.x)).toEqual([100, 100, 100]); expect(points.map((p) => p.y).reduce((a, b) => a + b) / 3).toBeCloseTo(100); }); it("leaves ships that are already apart where they are", () => { const apart = [flight("a", 20), flight("b", 180)]; expect(separateShips(apart)).toEqual(apart); }); });