1
0

SoCal, the whole bay, a moon, and gates that actually run

Six agents in parallel, and the two city packs independently reported the same
blocker: `focusRegions` and `coarseFactor` existed on the `City` type and
nothing implemented them. Uniform lattices would have been 2.9M points for
Southern California and 3.7M for the expanded bay. Both packs were unloadable
as written.

`buildAxis` is the answer, and it is honest about its limits: refinement is per
axis, not per rectangle, so a focus region sharpens its whole row *and* its
whole column. Two regions at opposite corners refine nearly everything between
them. Measured, not guessed — the bay went 0.53M points with one region and
1.64M with three, for detail nobody is looking at from a board this wide. One
region each, coarse factor ten, and the builds land at 3.8 s and 2.3 s.

Then three things that were only ever right because San Francisco was the only
city. `maxDistance: 340` and a 170-unit shadow box were constants tuned for a
230-unit board; the bay is 1003 units across and the camera physically could
not retreat far enough to frame it. Fog distances were scene units pinned to
the same assumption. And `minVisibilityM` defaulted to 4.5 km of honest
weather, which over ninety-four kilometres of bay correctly hides three
quarters of it — the night view was a black rectangle for a completely
reasonable reason. All three now derive from the board.

The moon is a real ephemeris and its light is a deliberate lie: 1.15, against a
physical ratio of one to four hundred thousand. What is being reproduced is
what a moonlit night looks like on a screen in a lit room.

The CI gate caught itself, which is the part worth keeping. Port 8431 was
already held by a server from an earlier session, so the boot check polled a
healthy stranger while the process it started died on EADDRINUSE. It now
refuses to run rather than pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Karti Tripathi
2026-08-05 03:13:32 -07:00
parent 8bcb391455
commit 44c5a79424
25 changed files with 9246 additions and 220 deletions
+183 -100
View File
@@ -1,73 +1,55 @@
/**
* The standalone demo: San Francisco under a real sun, and one office you can
* step into.
* The demo: two cities under a real sun and moon, and one office you can step
* into.
*
* Deliberately ships **no company data**. Markers are demonstrated using the
* city's own landmarks — buildings, not businesses — because company positions
* are geocoded and company pipeline status is private, and neither belongs in
* this repo. Real markers arrive at runtime from an adapter; see `src/adapters/`
* and ARCHITECTURE.md §3.
* It ships **no real company data**. The markers are fabricated — see
* `src/adapters/sample.ts`, which says so loudly — because real positions are
* geocoded and real pipeline status is private, and neither belongs in this
* repo. When a Tera API is present the same markers arrive from it instead, and
* the UI says which of the two it is showing.
*
* It also makes no network calls. The sun is computed locally, the traffic is
* simulated and the office is a data file, so a clone of this repo runs.
* It also runs with no server at all: the sun and moon are computed locally,
* the traffic is simulated, the office is a data file. Clone it and it works.
*/
import { createAtmosphere, observe, PACIFIC_MARINE_LAYER } from "./engine/atmosphere.ts";
import { createScene, type SceneHandle } from "./engine/scene.ts";
import { SimulatedFlights } from "./engine/flights.ts";
import { daylightPhase } from "./engine/solar.ts";
import { SimulatedFlights, type SimRoute } from "./engine/flights.ts";
import { createScene } from "./engine/scene.ts";
import type { Marker, MarkerPalette, View } from "./engine/types.ts";
import type { City, Marker, MarkerPalette, View } from "./engine/types.ts";
import SAN_FRANCISCO from "./cities/sf.ts";
import SOCAL from "./cities/socal.ts";
import { createTeraClient } from "./adapters/http.ts";
import { SAMPLE_MARKERS, SAMPLE_PALETTE, SAMPLE_ROUTES } from "./adapters/sample.ts";
import { createOfficeScene, type OfficeScene } from "./interiors/officeScene.ts";
import LUMBRIDGE_HQ from "./offices/lumbridge-hq.ts";
/**
* Bay Area traffic, roughly where it actually is: SFO sits south of frame and
* its arrivals run down the peninsula, Oakland is east across the bay, and the
* coastal departures turn out over the Pacific.
*/
const ROUTES: SimRoute[] = [
{ callsign: "UAL 1", from: [37.95, -122.36], to: [37.66, -122.4], fromAlt: 2400, toAlt: 500, duration: 190 },
{ callsign: "ASA 22", from: [37.93, -122.31], to: [37.65, -122.38], fromAlt: 2100, toAlt: 450, duration: 210 },
{ callsign: "SWA 118", from: [37.64, -122.39], to: [37.9, -122.62], fromAlt: 700, toAlt: 5200, duration: 165 },
{ callsign: "DAL 407", from: [37.7, -122.21], to: [37.88, -122.55], fromAlt: 1800, toAlt: 6100, duration: 230 },
{ callsign: "UAL 88", from: [37.62, -122.6], to: [37.95, -122.28], fromAlt: 6800, toAlt: 8200, duration: 260 },
{ callsign: "N512SP", from: [37.83, -122.56], to: [37.7, -122.22], fromAlt: 1100, toAlt: 1300, duration: 300 },
{ callsign: "JBU 915", from: [37.96, -122.48], to: [37.63, -122.36], fromAlt: 3100, toAlt: 600, duration: 205 },
const CITIES: { id: string; label: string; city: City }[] = [
{ id: "sf", label: "Bay Area", city: SAN_FRANCISCO },
{ id: "socal", label: "SoCal", city: SOCAL },
];
const MARKER_PALETTE: MarkerPalette = { landmark: 0xf2b134, neutral: 0x9aa4ad };
const canvas = document.querySelector<HTMLCanvasElement>("#scene");
if (!canvas) throw new Error("#scene canvas missing");
const city = createScene(canvas, {
city: SAN_FRANCISCO,
markerPalette: MARKER_PALETTE,
flights: new SimulatedFlights(ROUTES),
onMarkerPick: (marker) => showDetail(marker?.label ?? null),
});
const tera = createTeraClient();
// ---- The sun --------------------------------------------------------------
let city: SceneHandle | null = null;
let cityId = "sf";
let office: OfficeScene | null = null;
let inside = false;
let markers: Marker[] = SAMPLE_MARKERS;
let palette: MarkerPalette = SAMPLE_PALETTE;
let liveData = false;
let canEnterOffice = false;
let atmosphere: ReturnType<typeof createAtmosphere> | null = null;
// ---- Time -----------------------------------------------------------------
/**
* Real solar position for San Francisco, right now, recomputed every minute.
*
* No network and no timezone database — `solar.ts` is arithmetic — so this
* keeps working on a laptop in a field. The marine layer is switched on because
* the fog is the single most recognisable atmospheric fact about this city.
*/
const atmosphere = createAtmosphere({
lng: SAN_FRANCISCO.center.lng,
metresPerUnit: city.world.metresPerUnit,
marineLayer: PACIFIC_MARINE_LAYER,
});
/**
* `null` follows the wall clock. A number is an hour-of-day override from the
* scrubber, which exists because the honest answer at 2 a.m. is a black
* rectangle — correct, and impossible to look at. Being able to drag the sun is
* also the only practical way to eyeball whether the solar maths is right.
* `null` follows the wall clock. The scrubber exists because the honest answer
* at 2 a.m. is a very dark city — correct, and not what you want to be looking
* at while judging whether the sun is in the right place.
*/
let hourOverride: number | null = null;
@@ -80,55 +62,80 @@ function currentInstant(): Date {
}
function updateSun() {
const env = observe(SAN_FRANCISCO.center.lat, SAN_FRANCISCO.center.lng, currentInstant());
const active = CITIES.find((c) => c.id === cityId)?.city ?? SAN_FRANCISCO;
if (!city || !atmosphere) return;
const env = observe(active.center.lat, active.center.lng, currentInstant());
city.setLighting(atmosphere.apply(env));
city.setSolarElevation(env.sun.elevation);
const clock = document.querySelector<HTMLElement>("#clock");
if (!clock) return;
const el = env.sun.elevation;
const time = env.time.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
const phase = daylightPhase(el);
clock.textContent = `${time} · sun ${el >= 0 ? "+" : ""}${el.toFixed(1)}° · ${phase}${hourOverride === null ? "" : " (held)"}`;
const moon = env.moon ? ` · moon ${Math.round(env.moon.illuminated * 100)}%` : "";
clock.textContent = `${time} · sun ${el >= 0 ? "+" : ""}${el.toFixed(1)}° · ${daylightPhase(el)}${moon}`;
}
const scrubber = document.querySelector<HTMLInputElement>("#hour");
scrubber?.addEventListener("input", () => {
hourOverride = Number(scrubber.value);
updateSun();
});
document.querySelector<HTMLElement>("#now")?.addEventListener("click", () => {
hourOverride = null;
if (scrubber) scrubber.value = String(new Date().getHours());
updateSun();
});
updateSun();
window.setInterval(() => hourOverride === null && updateSun(), 60_000);
// ---- Demo markers ---------------------------------------------------------
const demoMarkers: Marker[] = SAN_FRANCISCO.landmarks
.filter((l) => l.label)
.map((l) => ({
id: l.name,
lat: l.lat,
lng: l.lng,
label: l.name,
colorKey: "landmark",
located: true,
}));
city.setMarkers(demoMarkers);
// ---- The office -----------------------------------------------------------
// ---- Cities ---------------------------------------------------------------
/**
* Built on first entry and then kept, for the same reason the city is paused
* rather than disposed on the way in: rebuilding either scene costs far more
* than holding it.
* Switching city tears the old one down completely.
*
* Unlike the city↔office move — where the city is paused and kept, because you
* are coming straight back — nobody flips between metros often enough to
* justify holding two heightfields and 140k building instances at once.
*/
let office: OfficeScene | null = null;
let inside = false;
function mountCity(id: string) {
const entry = CITIES.find((c) => c.id === id);
if (!entry || !canvas) return;
office?.dispose();
office = null;
inside = false;
city?.dispose();
cityId = id;
city = createScene(canvas, {
city: entry.city,
markerPalette: palette,
flights: liveData ? tera.flights() : new SimulatedFlights(SAMPLE_ROUTES),
onMarkerPick: (m) => showDetail(m ? `${m.label}${m.blurb ? `${m.blurb}` : ""}` : null),
});
// Fog distances are scene units, so they have to follow the board — 210/460
// was tuned for a 230-unit San Francisco and fogs out most of a 1000-unit
// Bay Area. They also have to clear the CAMERA, which sits about 0.6 spans
// out on the whole-board view: a fog starting nearer than that is behind the
// viewer's own shoulder, and at night, when the fog colour is nearly black
// rather than bright haze, it turns the entire map off.
const [wx, nz] = city.world.project(entry.city.bounds.maxLat, entry.city.bounds.minLng);
const [ex, sz] = city.world.project(entry.city.bounds.minLat, entry.city.bounds.maxLng);
const span = Math.max(Math.abs(ex - wx), Math.abs(sz - nz));
atmosphere = createAtmosphere({
lng: entry.city.center.lng,
metresPerUnit: city.world.metresPerUnit,
clearFog: { near: span * 1.15, far: span * 2.8 },
// The floor on how far you can see, and it has to know how big the board
// is. `minVisibilityM` defaults to 4.5 km, which is honest weather and
// completely wrong here: this board is ninety-four kilometres across, so
// real visibility correctly hides three quarters of it and the night view
// renders as a black rectangle. A map is looked at from outside the
// atmosphere it is depicting.
minVisibilityM: span * city.world.metresPerUnit * 1.6,
// The marine layer is a fact about the eastern Pacific at this latitude,
// not a decoration. LA gets its own weather, not San Francisco's fog.
marineLayer: id === "sf" ? PACIFIC_MARINE_LAYER : null,
});
city.setMarkers(id === "sf" ? markers : []);
city.onChapterChange(() => renderLegend());
updateSun();
renderLegend();
}
// ---- Office ---------------------------------------------------------------
function enterOffice() {
if (!city || !canEnterOffice) return;
if (!office) {
office = createOfficeScene(LUMBRIDGE_HQ, {
dom: city.stage.renderer.domElement,
@@ -143,6 +150,7 @@ function enterOffice() {
}
function leaveOffice() {
if (!city) return;
city.stage.setScene(city.stageScene);
inside = false;
showDetail(null);
@@ -156,6 +164,8 @@ const blurb = document.querySelector<HTMLElement>("#blurb");
const title = document.querySelector<HTMLElement>("#title");
const subtitle = document.querySelector<HTMLElement>("#subtitle");
const enterButton = document.querySelector<HTMLButtonElement>("#enter");
const cityNav = document.querySelector<HTMLElement>("#cities");
const source = document.querySelector<HTMLElement>("#source");
function showDetail(text: string | null) {
const card = document.querySelector<HTMLElement>("#detail");
@@ -164,12 +174,25 @@ function showDetail(text: string | null) {
card.textContent = text ?? "";
}
/**
* One legend for both places. A city chapter and an office viewpoint are both
* `View`s, which is the whole reason that type was extracted.
*/
function renderCityPicker() {
if (!cityNav) return;
cityNav.replaceChildren();
for (const c of CITIES) {
const b = document.createElement("button");
b.className = c.id === cityId && !inside ? "city active" : "city";
b.textContent = c.label;
b.addEventListener("click", () => {
if (inside) leaveOffice();
if (c.id !== cityId) mountCity(c.id);
});
cityNav.append(b);
}
}
/** One legend for both places — a city chapter and an office viewpoint are both `View`s. */
function renderLegend() {
if (!nav) return;
renderCityPicker();
if (!nav || !city) return;
const views: View[] = inside && office ? office.views : city.chapters;
const activeId = inside && office ? office.current() : city.current();
@@ -181,7 +204,7 @@ function renderLegend() {
button.innerHTML = `<span class="num">${number}</span><span>${view.shortLabel}</span>`;
button.addEventListener("click", () => {
if (inside && office) office.flyTo(view.id);
else city.flyTo(view.id);
else city?.flyTo(view.id);
});
nav.append(button);
});
@@ -191,11 +214,71 @@ function renderLegend() {
blurb.textContent = active?.description ?? "";
blurb.hidden = !active?.description;
}
if (title) title.textContent = inside ? LUMBRIDGE_HQ.name : SAN_FRANCISCO.name;
if (subtitle) subtitle.textContent = inside ? "Spaces · a Lumbridge office" : "Tera · Lumbridge Simulate";
if (enterButton) enterButton.textContent = inside ? "← Back to the city" : "Enter the office →";
const cityLabel = CITIES.find((c) => c.id === cityId)?.city.name ?? "";
if (title) title.textContent = inside ? LUMBRIDGE_HQ.name : cityLabel;
if (subtitle) {
subtitle.textContent = inside ? "Spaces · a Lumbridge office" : "Tera · Lumbridge Simulate";
}
if (enterButton) {
if (inside) enterButton.textContent = "← Back to the city";
else if (canEnterOffice) enterButton.textContent = "Enter the office →";
else enterButton.textContent = "Sign in to enter the office →";
}
if (source) {
source.textContent = liveData ? "live data" : "sample data · fabricated, not real companies";
source.className = liveData ? "source live" : "source";
}
}
enterButton?.addEventListener("click", () => (inside ? leaveOffice() : enterOffice()));
city.onChapterChange(() => renderLegend());
renderLegend();
enterButton?.addEventListener("click", () => {
if (inside) leaveOffice();
else if (canEnterOffice) enterOffice();
else window.location.href = "/login.html";
});
const scrubber = document.querySelector<HTMLInputElement>("#hour");
scrubber?.addEventListener("input", () => {
hourOverride = Number(scrubber.value);
updateSun();
});
document.querySelector<HTMLElement>("#now")?.addEventListener("click", () => {
hourOverride = null;
if (scrubber) scrubber.value = String(new Date().getHours());
updateSun();
});
// ---- Boot -----------------------------------------------------------------
/**
* Markers are awaited before the scene is built, because `markerPalette` is
* fixed at construction and the sample palette's keys are not the API's.
* Everything else about the API is optional: no server means sample data and a
* label saying so.
*/
async function boot() {
try {
const feed = await tera.markers();
markers = feed.value;
palette = feed.palette;
liveData = feed.live;
} catch {
// A missing API is the self-host default, not an error.
}
try {
const res = await fetch("/api/v1/session", { credentials: "same-origin" });
if (res.ok) {
const s = (await res.json()) as { authenticated: boolean; passwordLogin: boolean };
canEnterOffice = s.authenticated || !s.passwordLogin;
} else {
canEnterOffice = true;
}
} catch {
// No server means nothing to sign in to, so the office is open. That is the
// self-host posture: auth is something a deployment adds, not removes.
canEnterOffice = true;
}
mountCity("sf");
window.setInterval(() => hourOverride === null && updateSun(), 60_000);
}
void boot();