1
0
This repository has been archived on 2026-08-25. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
tera/src/test/office.test.ts
T

630 lines
24 KiB
TypeScript

/**
* The reference pack, against the checklist its own README ends with.
*
* `src/offices/README.md` closes with six things to check before calling a pack
* done, and until this file existed the pack those instructions are written
* about had none of them checked. That was survivable while it was one storey
* and fifteen rooms authored in one sitting. It stopped being survivable when a
* second level and a wing arrived, because the failure mode of a floorplan is
* not a crash — `Plan` never throws — it is a room nobody can get into, which
* renders perfectly and looks completely fine from every camera angle.
*
* Two of the checks here are worth their weight on their own:
*
* - **Reachability.** Item 2 on the list, and the one that cannot be eyeballed:
* a door authored 200 mm past the end of its wall is silently dropped, the
* room behind it is sealed, and the only evidence is a line in
* `plan.problems` that nothing reads. That exact bug happened once while the
* wing was being written.
* - **The balustrade.** The gallery is 16.8 m above terrazzo. `Plan` derives
* the walk collider from the wall list, so the difference between a
* balustrade and a decorative rail is whether it is in that list — and both
* look identical in a screenshot.
*/
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { Plan } from "../interiors/plan.ts";
import LUMBRIDGE_HQ from "../offices/lumbridge-hq.ts";
import FRONTIER_VALLEY from "../offices/frontier-valley.ts";
import MATEO_COURT from "../offices/mateo-court.ts";
import { OFFICE_SITES } from "../offices/sites.ts";
const plan = new Plan(LUMBRIDGE_HQ, { warn: false });
/**
* Which rooms on a level can be walked to from a point, at 0.1 m.
*
* Shared by all three packs, because it was written three times otherwise and
* the third copy is where a subtle divergence lives. The grid is finer than it
* looks like it needs to be and that is not optional: `blocked` inflates by the
* walker's radius, so threading a 0.9 m door with a 0.3 m radius leaves 0.3 m of
* clear width, and a 0.25 m grid can straddle that and report a sealed room that
* is fine. Erring the other way is not possible — a coarser grid only ever
* reaches fewer rooms, so a pass is always a real pass.
*/
function reachableRoomsOf(
plan: Plan,
levelId: string,
entry: { x: number; z: number },
): Set<string> {
const STEP = 0.1;
const RADIUS = 0.3;
const b = plan.bounds;
const cols = Math.ceil(b.width / STEP);
const rows = Math.ceil(b.depth / STEP);
const at = (c: number, r: number) => ({ x: b.minX + c * STEP, z: b.minZ + r * STEP });
const room: (string | null)[] = new Array(cols * rows).fill(null);
for (let r = 0; r < rows; r += 1) {
for (let c = 0; c < cols; c += 1) {
room[r * cols + c] = plan.roomAt(levelId, at(c, r))?.id ?? null;
}
}
const sc = Math.round((entry.x - b.minX) / STEP);
const sr = Math.round((entry.z - b.minZ) / STEP);
assert.ok(room[sr * cols + sc], `${levelId}'s entry point is not inside a room`);
const seen = new Uint8Array(cols * rows);
const queue: [number, number][] = [[sc, sr]];
seen[sr * cols + sc] = 1;
while (queue.length > 0) {
const [c, r] = queue.pop() as [number, number];
for (const [dc, dr] of [
[1, 0],
[-1, 0],
[0, 1],
[0, -1],
]) {
const nc = c + (dc as number);
const nr = r + (dr as number);
if (nc < 0 || nr < 0 || nc >= cols || nr >= rows) continue;
const i = nr * cols + nc;
if (seen[i] === 1 || room[i] === null) continue;
if (plan.blocked(levelId, at(c, r), at(nc, nr), RADIUS)) continue;
seen[i] = 1;
queue.push([nc, nr]);
}
}
const reached = new Set<string>();
for (let i = 0; i < seen.length; i += 1) {
const id = room[i];
if (seen[i] === 1 && id != null) reached.add(id);
}
return reached;
}
describe("the reference pack resolves cleanly", () => {
/** Checklist item 1, and the one everything else here depends on. */
it("reports no problems at all", () => {
assert.deepEqual(
plan.problems.map((p) => `${p.where}: ${p.message} (${p.action})`),
[],
);
});
/**
* The relationship, not the number.
*
* Floor-to-floor is deliberately exaggerated in this pack — see `PLENUM` in
* `lumbridge-hq.ts` — and an assertion on the literal would have to be edited
* every time somebody dials it, which makes it a change-detector rather than a
* test. What must stay true is that level 2 sits a clear interstitial *above*
* level 1's ceiling, and never at or below it: `elevation` is floor-to-floor,
* and setting it to the ceiling height is the classic way to bury one storey's
* slab inside the one below.
*/
it("is an honest twelve-by-nine metre single-level studio", () => {
assert.deepEqual(plan.levels.map((level) => [level.id, level.floorY]), [["level-1", 0]]);
assert.deepEqual(LUMBRIDGE_HQ.levels[0]?.floorplan.rooms[3]?.outline, [
{ x: 0.2, z: 3.15 },
{ x: 0.2, z: 8.8 },
{ x: 11.8, z: 8.8 },
{ x: 11.8, z: 3.15 },
]);
});
it("keeps every viewpoint on a level that exists", () => {
// `Plan` drops a viewpoint whose level does not resolve, so this is really
// an assertion that none were dropped — which the count makes visible in a
// way `problems` being empty already implies but does not state.
assert.equal(plan.viewpoints.length, 5);
const levels = new Set(plan.levels.map((l) => l.id));
for (const v of plan.viewpoints) assert.ok(levels.has(v.levelId), `${v.id} is on nothing`);
});
});
describe("seat ids", () => {
const seats = plan.allSeats();
/**
* The one property the README asks for in capitals, because a `Presence` binds
* to a seat id and ids are unique **per kind and building-wide**, not per
* level. Two storeys is exactly when somebody reuses a prefix.
*/
it("are unique across the whole building, not merely per storey", () => {
const ids = seats.map((s) => s.id);
assert.equal(new Set(ids).size, ids.length);
});
/**
* Not a count for its own sake. `DeskBank` expansion is contractual — stations
* numbered from 1 along each row and then down the rows, zero-padded to two —
* and a bank that silently expanded to the wrong size would change every id
* after it.
*/
it("expand the desk banks to the documented ids", () => {
const ids = new Set(seats.map((s) => s.id));
assert.equal(seats.length, 5);
for (const id of ["sf-agent-01", "sf-agent-02", "sf-island-01", "sf-island-02", "sf-lounge-01"]) {
assert.ok(ids.has(id), `${id} is missing`);
}
});
});
/**
* Checklist item 2: every room you can walk into can actually be walked into.
*
* A flood fill rather than a spot check, because a spot check finds the door you
* remembered to look at. The grid is 0.1 m, which is finer than it looks like it
* needs to be and is not optional: `blocked` inflates by the walker's radius, so
* threading a 0.9 m door with a 0.3 m radius leaves 0.3 m of clear width, and a
* 0.25 m grid can straddle that and report a sealed room that is fine. Getting
* that wrong the other way — a coarse grid that "passes" — is not possible here,
* since a coarser grid only ever reaches fewer rooms.
*/
describe("every room is reachable on foot", () => {
const STEP = 0.1;
const RADIUS = 0.3;
/** Where somebody arrives: the entrance downstairs, the landing upstairs. */
const ENTRY: Record<string, { x: number; z: number }> = {
"level-1": { x: 1.02, z: 7.68 },
};
function reachableRooms(levelId: string): Set<string> {
const b = plan.bounds;
const cols = Math.ceil(b.width / STEP);
const rows = Math.ceil(b.depth / STEP);
const at = (c: number, r: number) => ({ x: b.minX + c * STEP, z: b.minZ + r * STEP });
const room: (string | null)[] = new Array(cols * rows).fill(null);
for (let r = 0; r < rows; r += 1) {
for (let c = 0; c < cols; c += 1) {
room[r * cols + c] = plan.roomAt(levelId, at(c, r))?.id ?? null;
}
}
const entry = ENTRY[levelId];
assert.ok(entry, `no entry point declared for ${levelId}`);
const sc = Math.round((entry.x - b.minX) / STEP);
const sr = Math.round((entry.z - b.minZ) / STEP);
assert.ok(room[sr * cols + sc], `${levelId}'s entry point is not inside a room`);
const seen = new Uint8Array(cols * rows);
const queue: [number, number][] = [[sc, sr]];
seen[sr * cols + sc] = 1;
while (queue.length > 0) {
const [c, r] = queue.pop() as [number, number];
for (const [dc, dr] of [
[1, 0],
[-1, 0],
[0, 1],
[0, -1],
]) {
const nc = c + (dc as number);
const nr = r + (dr as number);
if (nc < 0 || nr < 0 || nc >= cols || nr >= rows) continue;
const i = nr * cols + nc;
if (seen[i] === 1 || room[i] === null) continue;
if (plan.blocked(levelId, at(c, r), at(nc, nr), RADIUS)) continue;
seen[i] = 1;
queue.push([nc, nr]);
}
}
const reached = new Set<string>();
for (let i = 0; i < seen.length; i += 1) {
// `!= null` rather than `!== null`: indexing a `(string | null)[]` under
// `noUncheckedIndexedAccess` widens to include `undefined` too.
const id = room[i];
if (seen[i] === 1 && id != null) reached.add(id);
}
return reached;
}
for (const level of plan.levels) {
it(`${level.id}: from the way in, without passing through a wall`, () => {
const reached = reachableRooms(level.id);
const sealed = level.rooms.map((r) => r.id).filter((id) => !reached.has(id));
assert.deepEqual(sealed, [], `sealed rooms on ${level.id}`);
});
}
});
/**
* The gallery is a balcony over a double-height room, and the drop is a storey.
*
* `Plan.blocked` is the collider a walk controller is told to use, so this is
* the only place the difference between a balustrade and a handrail-shaped prop
* is observable. A prop would leave the edge open and nothing would look wrong.
*/
describe("the studio arrival", () => {
it("starts inside the live/work room with collision-clear movement", () => {
const arrival = LUMBRIDGE_HQ.viewpoints[0]?.focus.at;
assert.ok(arrival);
assert.equal(plan.roomAt("level-1", arrival)?.id, "live-work");
assert.equal(plan.blocked("level-1", arrival, { x: arrival.x + 0.6, z: arrival.z }, 0.3), false);
});
/**
* And the way *on* is still open, which is the other half of the same claim: a
* balcony you cannot fall off and also cannot reach is a balcony nobody has
* noticed is broken.
*/
it("keeps all five authored views meaningful and distinct", () => {
assert.deepEqual(
LUMBRIDGE_HQ.viewpoints.map((view) => view.id),
["arrival", "studio", "agent-bench", "demo-lounge", "kitchen-home"],
);
});
});
/**
* The commons is the reason the wing exists, and "double height" is a property
* of the walls rather than of the room. A `Room` carries `ceiling: null` and a
* `Wall` carries a height; get the second wrong and the void has a lid at 2.8 m
* that you cannot see but the light rig can.
*/
describe("the studio programme", () => {
it("names every promised live/work zone without pretending it is a tower floor", () => {
const level1 = plan.levels.find((l) => l.id === "level-1");
assert.deepEqual(
level1?.rooms.map((room) => room.name),
["Kitchen", "Sleeping Alcove", "Bath / Storage", "Live / Work Studio"],
);
});
it("uses the complete original habitat kit", () => {
const kinds = new Set((LUMBRIDGE_HQ.levels[0]?.floorplan.props ?? []).map((prop) => prop.kind));
for (const id of [
"tera:bed.platform",
"tera:sofa.modular",
"tera:kitchen.run",
"tera:kitchen.island",
"tera:storage.wardrobe",
"tera:seat.stool",
"tera:light.floor",
]) assert.ok(kinds.has(id), `${id} is not placed in SF HQ`);
});
});
/**
* The second pack, held to the same bar as the first.
*
* A shipped pack that nothing asserts on is a pack that quietly stops resolving
* the first time somebody edits a shared constant. It gets the two checks that
* catch that — clean resolution and a walkable building — plus the one thing
* that is specific to it: it is a *hangar*, and the point of shipping it is that
* the format describes one room fifty-four metres across as readily as it
* describes a corridor with fifteen doors off it.
*/
describe("the Frontier Valley pack", () => {
const fv = new Plan(FRONTIER_VALLEY, { warn: false });
it("resolves with no problems", () => {
assert.deepEqual(
fv.problems.map((p) => `${p.where}: ${p.message} (${p.action})`),
[],
);
});
/**
* The deck is a level, and that is the fix for a real defect rather than a
* modelling preference: authored as a `Room` it had no floor height, so its
* slab lay on the concrete while its furniture floated 4.4 m over it.
*/
it("puts the mezzanine on its own level, at deck height", () => {
assert.deepEqual(
fv.levels.map((l) => [l.id, l.floorY]),
[
["level-1", 0],
["level-mezz", 4.4],
],
);
});
it("has unique seat ids, which must not collide with the other pack's", () => {
const mine = fv.allSeats().map((s) => s.id);
assert.equal(new Set(mine).size, mine.length);
// Not a hard requirement of the format — ids are unique per *building* — but
// a deployment serving both from one presence API would find out the hard
// way, and the two packs cost nothing by staying disjoint.
const theirs = new Set(plan.allSeats().map((s) => s.id));
const shared = mine.filter((id) => theirs.has(id));
assert.deepEqual(shared, [], "seat ids shared between the two shipped packs");
});
it("can be walked from the personnel door to every room", () => {
const STEP = 0.1;
const RADIUS = 0.3;
const b = fv.bounds;
const cols = Math.ceil(b.width / STEP);
const rows = Math.ceil(b.depth / STEP);
const at = (c: number, r: number) => ({ x: b.minX + c * STEP, z: b.minZ + r * STEP });
const room: (string | null)[] = new Array(cols * rows).fill(null);
for (let r = 0; r < rows; r += 1) {
for (let c = 0; c < cols; c += 1) {
room[r * cols + c] = fv.roomAt("level-1", at(c, r))?.id ?? null;
}
}
// Just inside the west gable's personnel door.
const sc = Math.round((1.0 - b.minX) / STEP);
const sr = Math.round((14.4 - b.minZ) / STEP);
assert.ok(room[sr * cols + sc], "the way in is not inside a room");
const seen = new Uint8Array(cols * rows);
const queue: [number, number][] = [[sc, sr]];
seen[sr * cols + sc] = 1;
while (queue.length > 0) {
const [c, r] = queue.pop() as [number, number];
for (const [dc, dr] of [[1, 0], [-1, 0], [0, 1], [0, -1]]) {
const nc = c + (dc as number);
const nr = r + (dr as number);
if (nc < 0 || nr < 0 || nc >= cols || nr >= rows) continue;
const i = nr * cols + nc;
if (seen[i] === 1 || room[i] === null) continue;
if (fv.blocked("level-1", at(c, r), at(nc, nr), RADIUS)) continue;
seen[i] = 1;
queue.push([nc, nr]);
}
}
const reached = new Set<string>();
for (let i = 0; i < seen.length; i += 1) {
const id = room[i];
if (seen[i] === 1 && id != null) reached.add(id);
}
// Level 1 only. The mezzanine is a level of its own now and is reached by a
// stair this pack does not model, so a flood fill across the slab cannot and
// should not walk onto it.
const sealed = fv.levels[0]!.rooms.map((r) => r.id).filter((id) => !reached.has(id));
assert.deepEqual(sealed, [], "sealed rooms in the hangar");
});
it("guards the mezzanine edge, which is a 4.4 m drop onto concrete", () => {
// On the deck's own level — the balustrade belongs to it, not to the slab
// below, which is the whole point of the deck being a level.
assert.ok(fv.blocked("level-mezz", { x: 39.0, z: 25.0 }, { x: 37.0, z: 25.0 }, 0.3));
assert.ok(fv.blocked("level-mezz", { x: 45.0, z: 21.0 }, { x: 45.0, z: 19.0 }, 0.3));
});
/**
* And the deck is genuinely up there. `Plan` resolves a seat's `y` from its
* level's floor, so this is the assertion that would have caught the original
* defect: authored as a ground-floor room, every one of these was at y = 0
* with a chair drawn 4.4 m above it.
*/
it("stands its occupants on the deck rather than on the concrete", () => {
for (const id of ["mezz-01", "mezz-02", "mezz-03"]) {
assert.equal(fv.seat(id)?.y, 4.4, `${id} is not on the deck`);
}
});
});
/**
* All shipped packs declare where they stand, and the three are deliberately
* nothing alike — which is the entire argument for the field existing.
*/
describe("the sites", () => {
const packs = [LUMBRIDGE_HQ, FRONTIER_VALLEY, MATEO_COURT];
it("are all declared", () => {
for (const pack of packs) assert.ok(pack.site, `${pack.name} has no site`);
});
it("put one high in the air and one on the ground", () => {
assert.ok(
(LUMBRIDGE_HQ.site?.elevation ?? 0) > 100,
"the tower office should be a long way up",
);
assert.ok(
(FRONTIER_VALLEY.site?.elevation ?? 999) < 20,
"the hangar should be near the ground",
);
});
it("carry headings inside the compass", () => {
for (const pack of packs) {
const h = pack.site?.heading ?? 0;
assert.ok(h >= 0 && h < 360, `${pack.id} has a heading of ${h}`);
}
});
it("puts the Bay Area offices on the board the city view draws", () => {
// Not a format requirement — an office may stand anywhere — but these two
// are meant to be places in *this* product's San Francisco, and a
// coordinate typo that put one in Nevada would otherwise render fine.
for (const pack of [LUMBRIDGE_HQ, FRONTIER_VALLEY]) {
const site = pack.site;
assert.ok(site);
assert.ok(site.lat > 37.2 && site.lat < 38.2, `${pack.id} latitude ${site.lat}`);
assert.ok(site.lng > -122.8 && site.lng < -121.8, `${pack.id} longitude ${site.lng}`);
}
});
it("gives every map destination a finite, aligned exterior glyph", () => {
for (const pack of packs) {
const site = pack.site;
assert.ok(site, `${pack.id} has no site`);
const exterior = site.exterior;
assert.ok(exterior, `${pack.id} has no exterior glyph`);
assert.equal(exterior.kind, "building");
assert.equal(exterior.heading, site.heading, `${pack.id} exterior faces away from its plan`);
for (const [field, value] of Object.entries({
width: exterior.width,
depth: exterior.depth,
height: exterior.height,
storeys: exterior.storeys,
})) {
assert.ok(Number.isFinite(value) && value > 0, `${pack.id} has invalid ${field}: ${value}`);
}
}
});
});
/**
* `offices/sites.ts` and the packs must not drift.
*
* The city draws its doors from `OFFICE_SITES` because a pack is a lazy chunk
* and the board wants the pins before anybody opens one. That means two places
* name the same building, and nothing in the type system ties them together —
* a coordinate edited in the pack and not in the table would put the marker on
* one building and the sun on another, and both would look entirely plausible.
*/
describe("the office site table", () => {
it("lists exactly the packs this build ships", () => {
assert.deepEqual(
OFFICE_SITES.map((e) => e.id).sort(),
[FRONTIER_VALLEY.id, LUMBRIDGE_HQ.id, MATEO_COURT.id].sort(),
);
});
it("hands each pack the very same site object it publishes", () => {
for (const pack of [LUMBRIDGE_HQ, FRONTIER_VALLEY, MATEO_COURT]) {
const entry = OFFICE_SITES.find((e) => e.id === pack.id);
assert.ok(entry, `${pack.id} is missing from OFFICE_SITES`);
// Identity, not equality: the packs import from the table, so anything
// less than the same reference means somebody has restated a coordinate.
assert.equal(entry.site, pack.site, `${pack.id} has a site of its own`);
}
});
it("publishes truthful environment names and runtime status", () => {
assert.deepEqual(
OFFICE_SITES.map(({ id, name, status }) => ({ id, name, status })),
[
{ id: "lumbridge-hq", name: "SF HQ · Studio", status: "active" },
{ id: "frontier-valley", name: "Frontier Valley", status: "building" },
{ id: "mateo-court", name: "LA HQ · Office", status: "active" },
],
);
});
});
/**
* The third pack, and the first on the other board.
*
* A courtyard block: a ring of rooms round an open-air yard with **no corridor
* anywhere** — every door opens onto the yard, and the yard does the job a
* corridor does in the other two. That makes it the first pack whose
* circulation is outdoors, and the first whose `ceiling: null` means there is
* genuinely no ceiling rather than "take the lid off so the shot can see in".
*/
describe("the Mateo Court pack", () => {
const mc = new Plan(MATEO_COURT, { warn: false });
it("resolves with no problems", () => {
assert.deepEqual(
mc.problems.map((p) => `${p.where}: ${p.message} (${p.action})`),
[],
);
});
it("stacks its upper floor floor-to-floor", () => {
assert.deepEqual(
mc.levels.map((l) => [l.id, l.floorY]),
[
["level-1", 0],
["level-2", 5],
],
);
});
it("keeps its seat ids disjoint from both other packs", () => {
const mine = mc.allSeats().map((s) => s.id);
assert.equal(new Set(mine).size, mine.length);
const others = new Set([
...plan.allSeats().map((s) => s.id),
...new Plan(FRONTIER_VALLEY, { warn: false }).allSeats().map((s) => s.id),
]);
assert.deepEqual(mine.filter((id) => others.has(id)), []);
});
it("caps the authored office at twenty-four useful seat addresses", () => {
const ids = mc.allSeats().map((seat) => seat.id);
assert.equal(ids.length, 24);
for (const id of ["works-a-01", "works-a-12", "loft-a-01", "loft-a-02", "review-04", "loggia-01"]) {
assert.ok(ids.includes(id), `${id} is missing`);
}
assert.equal(ids.some((id) => id.startsWith("works-b-")), false);
});
/**
* **The check that matters most in this pack.**
*
* Every door through the 0.25 m courtyard skin is 1.2 m rather than the 0.9 m
* the rest of the library uses, and that is not a style choice: `blocked`
* inflates by the walker's radius *and* by the wall's thickness, so a 0.9 m
* leaf in a wall this thick leaves too little clear width and seals the room
* behind it — while rendering perfectly. Two rooms were sealed exactly that
* way on the pack's first pass. A well-meaning edit back to 0.9 for
* consistency would do it again, and this is the only thing that would say so.
*/
for (const [levelId, entry] of [
["level-1", { x: 18.1, z: 1.0 }],
["level-2", { x: 8.4, z: 10.4 }],
] as const) {
it(`${levelId}: every room reachable from the way in`, () => {
const reached = reachableRoomsOf(mc, levelId, entry);
const sealed = mc.levels
.find((l) => l.id === levelId)!
.rooms.map((r) => r.id)
.filter((id) => !reached.has(id));
assert.deepEqual(sealed, [], `sealed rooms on ${levelId}`);
});
}
/**
* The loggia rail, and the gap in it.
*
* Both halves matter and only together: a rail that also sealed the stair head
* would pass an assertion that only checked you cannot fall off.
*/
it("guards the loggia edge without sealing the way up", () => {
assert.ok(mc.blocked("level-2", { x: 8.8, z: 9.0 }, { x: 10.6, z: 9.0 }, 0.3));
assert.ok(mc.blocked("level-2", { x: 8.8, z: 14.0 }, { x: 10.6, z: 14.0 }, 0.3));
assert.ok(mc.blocked("level-2", { x: 18.0, z: 7.6 }, { x: 18.0, z: 9.4 }, 0.3));
assert.ok(
!mc.blocked("level-2", { x: 8.8, z: 10.4 }, { x: 10.4, z: 10.4 }, 0.3),
"the stair head is walled off",
);
});
it("stands its upper-floor occupants on the deck", () => {
for (const id of ["loggia-01", "loft-a-01"]) {
assert.equal(mc.seat(id)?.y, 5, `${id} is not on the deck`);
}
});
it("leaves the yard open to the sky", () => {
const court = mc.levels[0]?.rooms.find((r) => r.id === "court");
assert.ok(court, "no courtyard");
assert.equal(court.ceiling, null);
});
/** The point of the pack: the Southland board finally has a door. */
it("stands on the Southland board", () => {
const site = MATEO_COURT.site;
assert.ok(site);
assert.ok(site.lat > 33.28 && site.lat < 34.36, `latitude ${site.lat}`);
assert.ok(site.lng > -118.88 && site.lng < -117.22, `longitude ${site.lng}`);
});
});