@johnmorrisdotca/kyogijo-stadiums 0.57.0 → 0.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/NOTICE.md +2 -0
- package/README.md +1 -1
- package/catalogue.json +1 -1
- package/dist/areas.d.ts +8 -3
- package/dist/areas.js +14 -5
- package/dist/athletics/plan.d.ts +2 -0
- package/dist/athletics/plan.js +20 -4
- package/dist/catalogue.data.js +1 -1
- package/dist/circuits-entry.d.ts +1 -1
- package/dist/circuits-entry.js +1 -1
- package/dist/circuits.draw.js +7 -4
- package/dist/circuits.held.d.ts +1 -0
- package/dist/circuits.held.js +13 -0
- package/dist/circuits.index.d.ts +15 -0
- package/dist/circuits.index.js +28 -0
- package/dist/circuits.race.dom.d.ts +25 -5
- package/dist/circuits.race.dom.js +22 -7
- package/dist/circuits.race.draw.d.ts +1 -1
- package/dist/circuits.race.draw.js +4 -4
- package/dist/circuits.turn.d.ts +8 -0
- package/dist/circuits.turn.js +29 -21
- package/dist/circuits.types.d.ts +2 -0
- package/dist/circuits.words.d.ts +4 -0
- package/dist/circuits.words.js +6 -0
- package/dist/cityctx-entry.d.ts +1 -1
- package/dist/cityctx-entry.js +1 -1
- package/dist/cityctx.d.ts +2 -2
- package/dist/cityctx.data.d.ts +2 -1
- package/dist/cityctx.data.js +3 -2
- package/dist/cityctx.js +9 -3
- package/dist/cityctx.las-vegas.data.d.ts +3 -0
- package/dist/cityctx.las-vegas.data.js +1387 -0
- package/dist/context.d.ts +11 -1
- package/dist/context.js +18 -4
- package/dist/crowd.d.ts +18 -0
- package/dist/crowd.js +88 -18
- package/dist/district-entry.d.ts +1 -0
- package/dist/district-entry.js +2 -0
- package/dist/district.api.d.ts +9 -2
- package/dist/district.api.js +7 -1
- package/dist/district.circuit.d.ts +34 -0
- package/dist/district.circuit.js +13 -0
- package/dist/district.d.ts +27 -3
- package/dist/district.js +85 -15
- package/dist/district.race.d.ts +40 -0
- package/dist/district.race.js +60 -0
- package/dist/district.turn.js +27 -1
- package/dist/draw.js +22 -7
- package/dist/landmarks.d.ts +105 -0
- package/dist/landmarks.js +160 -0
- package/dist/surfaces/artistic.js +3 -1
- package/dist/surfaces/athletics.js +2 -0
- package/dist/surfaces/hockey.js +3 -1
- package/dist/surfaces/surface.d.ts +7 -0
- package/dist/surfaces/surface.js +9 -0
- package/dist/turn.dom.js +5 -5
- package/dist/turn.markup.js +12 -1
- package/dist/turn.style.js +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -1
package/dist/context.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type LonLat } from "./venues.geo.ts";
|
|
2
2
|
import { type Plane, type Upright } from "./turn.kit.ts";
|
|
3
3
|
import type { Pt } from "./crowd.ts";
|
|
4
|
+
import { type ContextLandmark, type PlacedLandmark } from "./landmarks.ts";
|
|
4
5
|
/** One layer of an area's data: its rows, and where they came from and under what terms, since a layer has a source of its own (buildings from PLATEAU; trees and land cover from another). */
|
|
5
6
|
export interface ContextLayer {
|
|
6
7
|
/** What it was made from: the dataset and its page. */
|
|
@@ -44,6 +45,11 @@ export interface ContextArea {
|
|
|
44
45
|
trees?: ContextLayer;
|
|
45
46
|
landCover?: ContextLayer;
|
|
46
47
|
};
|
|
48
|
+
/** The most of this area's buildings the 3D view raises, when that is fewer than the tier's count (`CONTEXT_BLOCKS` at its best): a city of big, many-sided buildings (the casinos of the Las Vegas Strip) raises fewer, to stay within the
|
|
49
|
+
* district's budget of planes. Missing: the tier's count. */
|
|
50
|
+
blocks?: number;
|
|
51
|
+
/** The area's famous landmarks, each drawn by a shape of its own and named (`landmarks.ts`): the Sphere, the High Roller and the Fountains of Bellagio round the Las Vegas Strip Circuit. Missing: none. */
|
|
52
|
+
landmarks?: readonly ContextLandmark[];
|
|
47
53
|
}
|
|
48
54
|
/** One building as the district holds it: its outline in feet in the district's frame (x to the right, y down the page), its height and the rise of its roof in feet. */
|
|
49
55
|
export interface ContextBlock {
|
|
@@ -91,6 +97,10 @@ export interface ContextPlan {
|
|
|
91
97
|
trees?: ContextTree[];
|
|
92
98
|
/** The buildings of the model that are a venue (the Dome's own parts), left out: the venue draws them. */
|
|
93
99
|
owned: number;
|
|
100
|
+
/** The landmarks of the areas in the frame, each with its own shape; missing when the areas have none. */
|
|
101
|
+
landmarks?: PlacedLandmark[];
|
|
102
|
+
/** The most buildings the areas let the 3D view raise (the least of their `blocks`); missing when none sets it. */
|
|
103
|
+
most?: number;
|
|
94
104
|
/** The credits of the areas used, in each language. */
|
|
95
105
|
attribution: {
|
|
96
106
|
en: string[];
|
|
@@ -172,6 +182,6 @@ export declare function slabPlanes(ring: readonly Pt[], level: number, thickness
|
|
|
172
182
|
side: string;
|
|
173
183
|
}, look: "chosen" | "faint" | "plain"): Plane[];
|
|
174
184
|
/** The blocks of the 3D view: the `most` buildings that matter most (the tallest and widest, by height times the side of their ground), each a few planes, in the order the plan lists them. */
|
|
175
|
-
export declare function contextUprights(plan: ContextPlan,
|
|
185
|
+
export declare function contextUprights(plan: ContextPlan, asked?: number): Upright[];
|
|
176
186
|
/** The building a raised venue stands in as a block: its outline in feet, its height, `xray` the middle of what is seen through its walls (none for a solid one). */
|
|
177
187
|
export declare function shellBlock(key: string, ring: readonly Pt[], height: number, xray: Pt | undefined): ContextBlock;
|
package/dist/context.js
CHANGED
|
@@ -6,6 +6,7 @@ import { FEET_PER_METRE } from "./geometry.js";
|
|
|
6
6
|
import { boxOf, hullOf, inside, metresFrom } from "./venues.geo.js";
|
|
7
7
|
import { n, shy, wall } from "./turn.kit.js";
|
|
8
8
|
import { pointList, raked } from "./venue.geom.js";
|
|
9
|
+
import { landmarksFloor, ownedByLandmark, placeLandmarks, underLandmark } from "./landmarks.js";
|
|
9
10
|
/** How many buildings are raised as blocks in the 3D view (the biggest and the tallest of those on the plan): the rest are the floor's own, flat. Every block is a few elements of the page. */
|
|
10
11
|
export const CONTEXT_BLOCKS = 130;
|
|
11
12
|
/** Feet of the plan's frame beyond the venues' buildings that a district with context shows, so that the streets round them are in it: 150 metres. */
|
|
@@ -79,6 +80,7 @@ export function placeContext(areas, origin, turn, frame, venues) {
|
|
|
79
80
|
let owned = 0;
|
|
80
81
|
const hulls = venues.map((v) => hullOf([...v.footprint]));
|
|
81
82
|
const [fx0, fy0, fx1, fy1] = [frame.x, frame.y, frame.x + frame.w, frame.y + frame.h];
|
|
83
|
+
const landmarks = placeLandmarks(areas, origin, turn, frame);
|
|
82
84
|
for (const area of areas) {
|
|
83
85
|
const [east, north] = metresFrom(origin, [area.origin])[0];
|
|
84
86
|
(area.layers.buildings?.rows ?? []).forEach((row, index) => {
|
|
@@ -96,6 +98,11 @@ export function placeContext(areas, origin, turn, frame, venues) {
|
|
|
96
98
|
owned += 1;
|
|
97
99
|
return;
|
|
98
100
|
}
|
|
101
|
+
// A building that is a landmark's own (the Sphere's, drawn as a dome) is left out too.
|
|
102
|
+
if (ownedByLandmark(landmarks, ring)) {
|
|
103
|
+
owned += 1;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
99
106
|
blocks.push({ id: `${area.key}-${index}`, ring, height: b.height * FEET_PER_METRE, rise: b.rise * FEET_PER_METRE, area: Math.abs(signedArea(ring)), ghost: holds, whole: box.x0 >= fx0 && box.x1 <= fx1 && box.y0 >= fy0 && box.y1 <= fy1 });
|
|
100
107
|
});
|
|
101
108
|
}
|
|
@@ -147,7 +154,8 @@ export function placeContext(areas, origin, turn, frame, venues) {
|
|
|
147
154
|
// An empty credit (a layer whose credit another layer of the area has said) adds nothing.
|
|
148
155
|
const layers = areas.flatMap((a) => Object.values(a.layers));
|
|
149
156
|
const credits = (language) => [...new Set(layers.map((l) => l.attribution[language]).filter((text) => text !== ""))];
|
|
150
|
-
|
|
157
|
+
const most = areas.reduce((least, a) => (a.blocks === undefined ? least : Math.min(least, a.blocks)), Infinity);
|
|
158
|
+
return { blocks, streets, land, trees, owned, ...(landmarks.length === 0 ? {} : { landmarks }), ...(Number.isFinite(most) ? { most } : {}), attribution: { en: credits("en"), ja: credits("ja") } };
|
|
151
159
|
}
|
|
152
160
|
/** A share of the trees, spread evenly over the lot: every tree at 1, none at 0, and at 0.5 every other. The same trees every time, so that a view drawn again at a tier keeps the ones it kept. */
|
|
153
161
|
export function thinTrees(trees, share) {
|
|
@@ -209,12 +217,12 @@ export function treesFloor(trees) {
|
|
|
209
217
|
export function contextFloor(plan) {
|
|
210
218
|
const under = `${landFloor(plan.land ?? [])}${streetsFloor(plan.streets ?? [])}${treesFloor(plan.trees ?? [])}`;
|
|
211
219
|
if (plan.blocks.length === 0)
|
|
212
|
-
return under
|
|
220
|
+
return `${under}${landmarksFloor(plan.landmarks ?? [])}`;
|
|
213
221
|
const paths = [[], [], [], [], []];
|
|
214
222
|
for (const b of plan.blocks)
|
|
215
223
|
paths[b.ghost ? 4 : toneOf(b.height)].push(`M${b.ring.map(([x, y]) => `${num(x)} ${num(y)}`).join("L")}Z`);
|
|
216
224
|
const classes = ["ky-dist-b0", "ky-dist-b1", "ky-dist-b2", "ky-dist-b3", "ky-dist-ghost"];
|
|
217
|
-
return `${under}<g class="ky-dist-context" aria-hidden="true">${paths.map((d, i) => (d.length === 0 ? "" : `<path class="ky-dist-block ${classes[i]}" d="${d.join("")}"/>`)).join("")}</g
|
|
225
|
+
return `${under}<g class="ky-dist-context" aria-hidden="true">${paths.map((d, i) => (d.length === 0 ? "" : `<path class="ky-dist-block ${classes[i]}" d="${d.join("")}"/>`)).join("")}</g>${landmarksFloor(plan.landmarks ?? [])}`;
|
|
218
226
|
}
|
|
219
227
|
// ---- The blocks of the 3D view. ----
|
|
220
228
|
/** How much a building matters to the view: tall and wide first. */
|
|
@@ -368,8 +376,14 @@ export function slabPlanes(ring, level, thickness, ids, look) {
|
|
|
368
376
|
return planes;
|
|
369
377
|
}
|
|
370
378
|
/** The blocks of the 3D view: the `most` buildings that matter most (the tallest and widest, by height times the side of their ground), each a few planes, in the order the plan lists them. */
|
|
371
|
-
export function contextUprights(plan,
|
|
379
|
+
export function contextUprights(plan, asked = CONTEXT_BLOCKS) {
|
|
380
|
+
const most = Math.min(asked, plan.most ?? Infinity);
|
|
372
381
|
const wanted = new Set(plan.blocks.filter((b) => b.whole).sort((a, b) => weight(b) - weight(a) || (a.id < b.id ? -1 : 1)).slice(0, Math.max(0, most)).map((b) => b.id));
|
|
382
|
+
// The buildings of a named landmark stand whatever the count (at a tier that raises any).
|
|
383
|
+
if (most > 0)
|
|
384
|
+
for (const b of plan.blocks)
|
|
385
|
+
if (b.whole && underLandmark(plan.landmarks ?? [], b.ring))
|
|
386
|
+
wanted.add(b.id);
|
|
373
387
|
const items = [];
|
|
374
388
|
for (const b of plan.blocks) {
|
|
375
389
|
if (!wanted.has(b.id))
|
package/dist/crowd.d.ts
CHANGED
|
@@ -70,6 +70,14 @@ export interface CrowdStands {
|
|
|
70
70
|
stadium?: "purpose" | "nfl" | "cfl";
|
|
71
71
|
/** The playing surface, in the wide frame. */
|
|
72
72
|
box: Box;
|
|
73
|
+
/**
|
|
74
|
+
* The floor round the playing surface, where the surface draws more than its box (a court's run-off, a track's sprint straight, runways and pits): its bounding box and its outline as points, in the wide frame.
|
|
75
|
+
* The first row of seats clears all of it by `FLOOR_CLEAR`, and the opening is centred on its box. Missing for a real venue's stands and a ballpark's, which are laid out from their own data.
|
|
76
|
+
*/
|
|
77
|
+
floor?: {
|
|
78
|
+
box: Box;
|
|
79
|
+
points: Pt[];
|
|
80
|
+
};
|
|
73
81
|
rings: StandRing[];
|
|
74
82
|
/** Boxes where the stands are left out (the open end of a horseshoe, the ends of two sides). */
|
|
75
83
|
covers: [x0: number, y0: number, x1: number, y1: number][];
|
|
@@ -310,10 +318,20 @@ export interface LayoutInput {
|
|
|
310
318
|
};
|
|
311
319
|
/** A real venue's stands in place of the sport's usual tiers (see `venueBowl`). */
|
|
312
320
|
real?: RealBowl;
|
|
321
|
+
/**
|
|
322
|
+
* Everything the surface draws round its playing area, in the wide frame: the bounding box (the surface's own view with no margin) and, where the floor is not that rectangle (an athletics track, an oval
|
|
323
|
+
* ground), its outline as points. The opening of the stands is centred on it and clears it. Without it the floor is the box.
|
|
324
|
+
*/
|
|
325
|
+
floor?: {
|
|
326
|
+
box: Box;
|
|
327
|
+
points?: readonly (readonly [number, number])[];
|
|
328
|
+
};
|
|
313
329
|
/** The ballpark's fence as points on the field, for a ballpark (see `parkLayout`). */
|
|
314
330
|
fence?: readonly Pt[];
|
|
315
331
|
/** The foul lines' length at the poles and the backstop's distance, for a ballpark. */
|
|
316
332
|
backstop?: number;
|
|
317
333
|
}
|
|
334
|
+
/** The room kept between the floor (everything the surface draws round its playing area) and the first row of seats, in feet. */
|
|
335
|
+
export declare const FLOOR_CLEAR = 2;
|
|
318
336
|
/** The layout of a sport's stands round its surface: rings, covers, sectors and gaps. For a ballpark see `parkLayout`. */
|
|
319
337
|
export declare function layoutOf(input: LayoutInput): CrowdStands;
|
package/dist/crowd.js
CHANGED
|
@@ -330,6 +330,62 @@ function offsets(p, box, stadium) {
|
|
|
330
330
|
const side = g.side + (f.width - box.h) / 2;
|
|
331
331
|
return { left: end, right: end, top: side, bottom: side + g.bench };
|
|
332
332
|
}
|
|
333
|
+
/** The room kept between the floor (everything the surface draws round its playing area) and the first row of seats, in feet. */
|
|
334
|
+
export const FLOOR_CLEAR = 2;
|
|
335
|
+
/** A point inside a rounded rectangle or an ellipse of half sizes `hx`, `hy` about the origin, with `clear` to spare. */
|
|
336
|
+
function insideOpening(ax, ay, hx, hy, r, oval, clear) {
|
|
337
|
+
const [w, h] = [hx - clear, hy - clear];
|
|
338
|
+
if (w <= 0 || h <= 0)
|
|
339
|
+
return false;
|
|
340
|
+
if (oval)
|
|
341
|
+
return sq(ax / w) + sq(ay / h) <= 1 + 1e-9;
|
|
342
|
+
const rr = Math.max(0, Math.min(r, hx, hy) - clear);
|
|
343
|
+
if (ax > w + 1e-9 || ay > h + 1e-9)
|
|
344
|
+
return false;
|
|
345
|
+
const kx = ax - (w - rr);
|
|
346
|
+
const ky = ay - (h - rr);
|
|
347
|
+
return kx <= 0 || ky <= 0 || sq(kx) + sq(ky) <= sq(rr) + 1e-9;
|
|
348
|
+
}
|
|
349
|
+
/** The first row's opening round a floor, centred on it (the bench room shared by both sides): the sport's distances, or the floor's own shape where they do not clear it, grown alike until its whole outline clears by `FLOOR_CLEAR`. */
|
|
350
|
+
function openingOf(input) {
|
|
351
|
+
const { off, corner, oval, box } = input;
|
|
352
|
+
const floor = input.floor?.box ?? box;
|
|
353
|
+
const cx = floor.x + floor.w / 2;
|
|
354
|
+
const cy = floor.y + floor.h / 2;
|
|
355
|
+
let hx = Math.max(cx - box.x, box.x + box.w - cx) + (off.left + off.right) / 2;
|
|
356
|
+
let hy = Math.max(cy - box.y, box.y + box.h - cy) + (off.top + off.bottom) / 2;
|
|
357
|
+
// A floor the sport's distances do not clear (table tennis): the floor's own shape.
|
|
358
|
+
if (Math.min(hx - floor.w / 2, hy - floor.h / 2) < FLOOR_CLEAR) {
|
|
359
|
+
hx = floor.w / 2 + FLOOR_CLEAR;
|
|
360
|
+
hy = floor.h / 2 + FLOOR_CLEAR;
|
|
361
|
+
}
|
|
362
|
+
const given = input.floor?.points;
|
|
363
|
+
const points = given !== undefined && given.length > 0
|
|
364
|
+
? given.map(([x, y]) => [x, y])
|
|
365
|
+
: oval
|
|
366
|
+
? Array.from({ length: 64 }, (_, i) => [cx + (floor.w / 2) * Math.cos((i * Math.PI) / 32), cy + (floor.h / 2) * Math.sin((i * Math.PI) / 32)])
|
|
367
|
+
: [[floor.x, floor.y], [floor.x + floor.w, floor.y], [floor.x + floor.w, floor.y + floor.h], [floor.x, floor.y + floor.h]];
|
|
368
|
+
// A sampled curve: a little to spare.
|
|
369
|
+
const clear = FLOOR_CLEAR + (given !== undefined || oval ? 0.5 : 0);
|
|
370
|
+
const fits = (d) => points.every(([x, y]) => insideOpening(Math.abs(x - cx), Math.abs(y - cy), hx + d, hy + d, corner, oval, clear));
|
|
371
|
+
if (!fits(0)) {
|
|
372
|
+
let lo = 0;
|
|
373
|
+
let hi = 4;
|
|
374
|
+
while (!fits(hi) && hi < 4096)
|
|
375
|
+
hi *= 2;
|
|
376
|
+
for (let i = 0; i < 40; i += 1) {
|
|
377
|
+
const mid = (lo + hi) / 2;
|
|
378
|
+
if (fits(mid))
|
|
379
|
+
hi = mid;
|
|
380
|
+
else
|
|
381
|
+
lo = mid;
|
|
382
|
+
}
|
|
383
|
+
hx += hi;
|
|
384
|
+
hy += hi;
|
|
385
|
+
}
|
|
386
|
+
const round = (v) => Math.round(v * 1e6) / 1e6;
|
|
387
|
+
return { off: { left: round(box.x - (cx - hx)), right: round(cx + hx - box.x - box.w), top: round(box.y - (cy - hy)), bottom: round(cy + hy - box.y - box.h) }, cx, cy, floor, points };
|
|
388
|
+
}
|
|
333
389
|
/** The layout of a sport's stands round its surface: rings, covers, sectors and gaps. For a ballpark see `parkLayout`. */
|
|
334
390
|
export function layoutOf(input) {
|
|
335
391
|
const { sport, box } = input;
|
|
@@ -342,15 +398,16 @@ export function layoutOf(input) {
|
|
|
342
398
|
const stadium = sport === "soccer" && input.real === undefined ? host ?? "purpose" : undefined;
|
|
343
399
|
const p = stadium === "nfl" || stadium === "cfl" ? { ...PROFILES[stadium], shape: base.shape, away: base.away } : base;
|
|
344
400
|
const shape = input.real !== undefined ? "bowl" : crowd.shape ?? p.shape;
|
|
345
|
-
const
|
|
346
|
-
const
|
|
347
|
-
const
|
|
401
|
+
const fit = input.real === undefined ? openingOf({ off: offsets(base, box, stadium ?? "purpose"), corner: p.corner, oval: base.oval === true, box, floor: input.floor }) : undefined;
|
|
402
|
+
const off = input.real?.off ?? fit?.off ?? offsets(base, box, stadium ?? "purpose");
|
|
403
|
+
const cx = fit?.cx ?? box.x + box.w / 2;
|
|
404
|
+
const cy = fit?.cy ?? box.y + box.h / 2;
|
|
348
405
|
const rings = input.real === undefined ? [] : input.real.rings.map((ring) => ({ ...ring }));
|
|
349
406
|
const reachOf = input.real === undefined ? { left: 0, right: 0, top: 0, bottom: 0 } : { ...input.real.reach };
|
|
350
407
|
for (const t of input.real === undefined ? p.tiers : []) {
|
|
351
408
|
const at = (k) => {
|
|
352
409
|
if (base.oval === true)
|
|
353
|
-
return { kind: "ellipse", cx, cy, rx: box.w
|
|
410
|
+
return { kind: "ellipse", cx, cy, rx: (box.w + off.left + off.right) / 2 + k, ry: (box.h + off.top + off.bottom) / 2 + k };
|
|
354
411
|
return { kind: "rrect", x0: box.x - off.left - k, y0: box.y - off.top - k, x1: box.x + box.w + off.right + k, y1: box.y + box.h + off.bottom + k, r: p.corner + k };
|
|
355
412
|
};
|
|
356
413
|
const region = at(t.to);
|
|
@@ -379,17 +436,18 @@ export function layoutOf(input) {
|
|
|
379
436
|
const covers = [];
|
|
380
437
|
const x0 = box.x - off.left;
|
|
381
438
|
const x1 = box.x + box.w + off.right;
|
|
382
|
-
|
|
383
|
-
const
|
|
439
|
+
// The covers reach past the roof's shade (9 feet beyond the upper tier) too.
|
|
440
|
+
const yTop = last === undefined ? box.y : box.y - reachOf.top - 10;
|
|
441
|
+
const yBot = last === undefined ? box.y + box.h : box.y + box.h + reachOf.bottom + 10;
|
|
384
442
|
if (shape === "horseshoe") {
|
|
385
443
|
// The open end: everything beyond the surface's end line and the gap that is kept clear.
|
|
386
444
|
if (crowd.open === "left")
|
|
387
|
-
covers.push([box.x - reachOf.left -
|
|
445
|
+
covers.push([box.x - reachOf.left - 10, yTop, x0 + p.corner * 0.5, yBot]);
|
|
388
446
|
else
|
|
389
|
-
covers.push([x1 - p.corner * 0.5, yTop, box.x + box.w + reachOf.right +
|
|
447
|
+
covers.push([x1 - p.corner * 0.5, yTop, box.x + box.w + reachOf.right + 10, yBot]);
|
|
390
448
|
}
|
|
391
449
|
else if (shape === "sides") {
|
|
392
|
-
covers.push([box.x - reachOf.left -
|
|
450
|
+
covers.push([box.x - reachOf.left - 10, yTop, x0 + p.corner * 0.5, yBot], [x1 - p.corner * 0.5, yTop, box.x + box.w + reachOf.right + 10, yBot]);
|
|
393
451
|
}
|
|
394
452
|
const concourses = [];
|
|
395
453
|
rings.forEach((ring, i) => {
|
|
@@ -398,6 +456,8 @@ export function layoutOf(input) {
|
|
|
398
456
|
concourses.push({ region: ring.hole, hole: before.region });
|
|
399
457
|
});
|
|
400
458
|
const stands = { sport, shape, box, rings, covers, concourses, sectors: [], gaps: [], reach: reachOf, seats: rings.reduce((n, r) => n + r.seats, 0) };
|
|
459
|
+
if (fit !== undefined)
|
|
460
|
+
stands.floor = { box: fit.floor, points: fit.points };
|
|
401
461
|
if (input.real !== undefined)
|
|
402
462
|
stands.real = input.real.shell;
|
|
403
463
|
if (input.real?.closedSectors !== undefined)
|
|
@@ -490,21 +550,31 @@ export function layoutOf(input) {
|
|
|
490
550
|
}
|
|
491
551
|
}
|
|
492
552
|
if (crowd.gaps && shape !== "grandstand") {
|
|
493
|
-
|
|
494
|
-
const
|
|
553
|
+
// Nothing on the floor: the benches stand between the floor and the first row.
|
|
554
|
+
const edge = box.y + box.h + off.bottom;
|
|
555
|
+
const floorEdge = Math.max(box.y + box.h, fit === undefined ? -Infinity : fit.floor.y + fit.floor.h);
|
|
556
|
+
const mid = cx;
|
|
495
557
|
// A tunnel through the lower stands at the middle of the bench side, the camera platform above them, and the benches in the gap.
|
|
496
|
-
stands.gaps.push({ kind: "tunnel", box: [mid - 6,
|
|
558
|
+
stands.gaps.push({ kind: "tunnel", box: [mid - 6, edge, mid + 6, edge + lowerRing.to + 1] });
|
|
497
559
|
const media = rings[rings.length - 1];
|
|
498
560
|
if (media !== undefined && media.tier === "upper")
|
|
499
|
-
stands.gaps.push({ kind: "camera", box: [mid - 22,
|
|
500
|
-
if (
|
|
561
|
+
stands.gaps.push({ kind: "camera", box: [mid - 22, edge + media.from + 3, mid + 22, edge + media.from + 13] });
|
|
562
|
+
if (base.bench >= 4 || sport === "soccer" || sport === "nfl" || sport === "cfl" || sport === "ifaf" || sport === "rugby" || sport === "gaelic") {
|
|
501
563
|
const benchLen = Math.min(34, box.w * 0.12);
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
564
|
+
const depth = Math.min(5, off.bottom * 0.3);
|
|
565
|
+
if (floorEdge + 2.5 + depth <= edge - 1) {
|
|
566
|
+
for (const s of [-1, 1]) {
|
|
567
|
+
const bx = box.x + box.w / 2 + s * (box.w * 0.1 + benchLen / 2 + 4);
|
|
568
|
+
stands.gaps.push({ kind: "bench", box: [bx - benchLen / 2, floorEdge + 2.5, bx + benchLen / 2, floorEdge + 2.5 + depth] });
|
|
569
|
+
}
|
|
505
570
|
}
|
|
506
571
|
}
|
|
507
|
-
|
|
572
|
+
// The media's desks: along the straight of that side only.
|
|
573
|
+
const hole = lowerRing.hole;
|
|
574
|
+
const straight = hole?.kind === "rrect" ? (hole.x1 - hole.x0) / 2 - Math.min(hole.r, (hole.x1 - hole.x0) / 2, (hole.y1 - hole.y0) / 2) : 55;
|
|
575
|
+
const half = Math.min(55, straight);
|
|
576
|
+
if (half >= 8)
|
|
577
|
+
stands.gaps.push({ kind: "media", box: [mid - half, edge + 2, mid + half, edge + 6] });
|
|
508
578
|
}
|
|
509
579
|
}
|
|
510
580
|
return stands;
|
package/dist/district-entry.d.ts
CHANGED
package/dist/district-entry.js
CHANGED
|
@@ -5,4 +5,6 @@ import "./full.js";
|
|
|
5
5
|
import "./venues.all.js";
|
|
6
6
|
// The walkable ground of every district, for the crowd outside, as the district has always had it (the lean district reads one when `loadOutside` is asked to).
|
|
7
7
|
import "./walk.full.js";
|
|
8
|
+
// Every circuit, as a district's `circuit` option asks for one (the lean district reads them when `loadCircuits` is asked to).
|
|
9
|
+
import "./circuits.held.js";
|
|
8
10
|
export * from "./district.api.js";
|
package/dist/district.api.d.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
export { DISTRICT_IDS, DISTRICT_MARGIN, DISTRICT_MODES, KYOGIJO_DISTRICT_STYLE, describeDistrict, districtId, districtMember, districtRing, drawDistrict, isDistrictId, metresText, planDistrict, scaleOf, unknownVenues } from "./district.ts";
|
|
2
|
-
export type { DistrictMember, DistrictMode, DistrictOptions, DistrictPart, DistrictPlaced, DistrictPlan, DistrictVenueInput, PlacedPart } from "./district.ts";
|
|
1
|
+
export { DISTRICT_IDS, DISTRICT_MARGIN, DISTRICT_MODES, KYOGIJO_DISTRICT_STYLE, circuitPointIn, describeDistrict, districtId, districtMember, districtRing, drawDistrict, isDistrictId, metresText, planDistrict, scaleOf, unknownVenues } from "./district.ts";
|
|
2
|
+
export type { DistrictCircuit, DistrictMember, DistrictMode, DistrictOptions, DistrictPart, DistrictPlaced, DistrictPlan, DistrictVenueInput, PlacedPart } from "./district.ts";
|
|
3
3
|
export { buildDistrictTurn, districtPresets, districtTurnMarkup, mountDistrictTurn } from "./district.turn.ts";
|
|
4
4
|
export type { DistrictTurnSettings } from "./district.turn.ts";
|
|
5
5
|
export type { ContextArea } from "./context.ts";
|
|
6
|
+
export { CIRCUIT_INDEX, loadCircuits } from "./circuits.index.ts";
|
|
7
|
+
export { circuitsHeld } from "./district.circuit.ts";
|
|
8
|
+
export { drawDistrictRace, mountDistrictRace } from "./district.race.ts";
|
|
9
|
+
export type { DistrictRaceDrawOptions, DistrictRaceOptions, DistrictRaceSettings } from "./district.race.ts";
|
|
10
|
+
export type { KyogijoRace, RaceState } from "./circuits.race.dom.ts";
|
|
11
|
+
export { LANDMARK_SHAPES } from "./landmarks.ts";
|
|
12
|
+
export type { ContextLandmark, LandmarkShape, PlacedLandmark } from "./landmarks.ts";
|
|
6
13
|
export { KODOKAN, KODOKAN_DOJO, KODOKAN_FLOOR_HEIGHT, KODOKAN_FLOOR_IDS, KODOKAN_FLOORS, KODOKAN_ROOM_HEIGHT, kodokanLevel, kodokanMember } from "./kodokan.ts";
|
|
7
14
|
export type { KodokanFloor, KodokanRoom } from "./kodokan.ts";
|
|
8
15
|
export { VENUE_ATTRIBUTION } from "./venues.ts";
|
package/dist/district.api.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
// A district: several real venues of one city on one plan at their real relative positions and orientations (OpenStreetMap, ODbL 1.0), in 2D and in 3D, tight round neighbours or at the real distances of a city.
|
|
2
|
-
export { DISTRICT_IDS, DISTRICT_MARGIN, DISTRICT_MODES, KYOGIJO_DISTRICT_STYLE, describeDistrict, districtId, districtMember, districtRing, drawDistrict, isDistrictId, metresText, planDistrict, scaleOf, unknownVenues } from "./district.js";
|
|
2
|
+
export { DISTRICT_IDS, DISTRICT_MARGIN, DISTRICT_MODES, KYOGIJO_DISTRICT_STYLE, circuitPointIn, describeDistrict, districtId, districtMember, districtRing, drawDistrict, isDistrictId, metresText, planDistrict, scaleOf, unknownVenues } from "./district.js";
|
|
3
3
|
export { buildDistrictTurn, districtPresets, districtTurnMarkup, mountDistrictTurn } from "./district.turn.js";
|
|
4
|
+
// A race circuit on the same ground (`circuit`: the district entry has every circuit, the lean district reads them with `loadCircuits`), and the famous landmarks an area of context has round it.
|
|
5
|
+
export { CIRCUIT_INDEX, loadCircuits } from "./circuits.index.js";
|
|
6
|
+
export { circuitsHeld } from "./district.circuit.js";
|
|
7
|
+
// A race on that circuit, among the venues and the city (the circuits' race, made-up cars or a feed's): drawn at a moment, or played in a page flat or in 3D.
|
|
8
|
+
export { drawDistrictRace, mountDistrictRace } from "./district.race.js";
|
|
9
|
+
export { LANDMARK_SHAPES } from "./landmarks.js";
|
|
4
10
|
export { KODOKAN, KODOKAN_DOJO, KODOKAN_FLOOR_HEIGHT, KODOKAN_FLOOR_IDS, KODOKAN_FLOORS, KODOKAN_ROOM_HEIGHT, kodokanLevel, kodokanMember } from "./kodokan.js";
|
|
5
11
|
export { VENUE_ATTRIBUTION } from "./venues.js";
|
|
6
12
|
export { mountDistrict } from "./district.dom.js";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { CircuitDrawing } from "./circuits.draw.ts";
|
|
2
|
+
import type { carRadius, carsMarkup } from "./circuits.race.draw.ts";
|
|
3
|
+
import type { mountRaceIn } from "./circuits.race.dom.ts";
|
|
4
|
+
import type { raceAt } from "./circuits.race.moment.ts";
|
|
5
|
+
import type { simulateRace } from "./circuits.race.ts";
|
|
6
|
+
import type { RaceWords } from "./circuits.race.words.ts";
|
|
7
|
+
import type { CircuitPlan } from "./circuits.ts";
|
|
8
|
+
import type { Circuit, CircuitOptions } from "./circuits.types.ts";
|
|
9
|
+
import type { CircuitWords } from "./circuits.words.ts";
|
|
10
|
+
import type { Language } from "./types.ts";
|
|
11
|
+
import type { Upright } from "./turn.kit.ts";
|
|
12
|
+
/** The circuits' code a district uses. */
|
|
13
|
+
export interface CircuitSupport {
|
|
14
|
+
circuitOf: (id: string) => Circuit;
|
|
15
|
+
circuitPlan: (circuit: Circuit) => CircuitPlan;
|
|
16
|
+
circuitDrawing: (options: CircuitOptions) => CircuitDrawing;
|
|
17
|
+
circuitUprights: (drawn: CircuitDrawing, thin: number) => Upright[];
|
|
18
|
+
words: Readonly<Record<Language, CircuitWords>>;
|
|
19
|
+
/** A race on the circuit (`mountDistrictRace`, `drawDistrictRace`): the simulation, its moments, its cars' markup and its view in a page. */
|
|
20
|
+
race: {
|
|
21
|
+
simulateRace: typeof simulateRace;
|
|
22
|
+
raceAt: typeof raceAt;
|
|
23
|
+
carsMarkup: typeof carsMarkup;
|
|
24
|
+
carRadius: typeof carRadius;
|
|
25
|
+
mountRaceIn: typeof mountRaceIn;
|
|
26
|
+
words: Readonly<Record<Language, RaceWords>>;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Fill the table: `circuits.held.ts` does it when it is imported. */
|
|
30
|
+
export declare function holdCircuits(support: CircuitSupport): void;
|
|
31
|
+
/** The circuits' code, or an error that says how to have it. */
|
|
32
|
+
export declare function circuitSupport(): CircuitSupport;
|
|
33
|
+
/** Whether the circuits are held (the district entry, or the lean district after `loadCircuits()`). */
|
|
34
|
+
export declare const circuitsHeld: () => boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
let held;
|
|
2
|
+
/** Fill the table: `circuits.held.ts` does it when it is imported. */
|
|
3
|
+
export function holdCircuits(support) {
|
|
4
|
+
held = support;
|
|
5
|
+
}
|
|
6
|
+
/** The circuits' code, or an error that says how to have it. */
|
|
7
|
+
export function circuitSupport() {
|
|
8
|
+
if (held === undefined)
|
|
9
|
+
throw new Error("a district with a circuit needs the circuits: the district entry has them, and the lean district reads them with `await loadCircuits()` first");
|
|
10
|
+
return held;
|
|
11
|
+
}
|
|
12
|
+
/** Whether the circuits are held (the district entry, or the lean district after `loadCircuits()`). */
|
|
13
|
+
export const circuitsHeld = () => held !== undefined;
|
package/dist/district.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { type StadiumConfigId } from "./stadiums.ts";
|
|
|
3
3
|
import type { OutsideOptions } from "./outside.ts";
|
|
4
4
|
import type { Pt } from "./crowd.ts";
|
|
5
5
|
import type { Language, SurfaceOptions } from "./types.ts";
|
|
6
|
+
import type { CircuitPlan } from "./circuits.ts";
|
|
7
|
+
import type { CircuitOptions } from "./circuits.types.ts";
|
|
6
8
|
/** How a district is fitted: `neighbours` tight round venues that stand close together, `city` at the real distances between venues that are kilometres apart. */
|
|
7
9
|
export type DistrictMode = "neighbours" | "city";
|
|
8
10
|
export declare const DISTRICT_MODES: readonly DistrictMode[];
|
|
@@ -13,8 +15,13 @@ export type DistrictVenueInput = string | {
|
|
|
13
15
|
};
|
|
14
16
|
/** What can be asked of a district. */
|
|
15
17
|
export interface DistrictOptions {
|
|
16
|
-
/** The venues, by key: any key of `VENUES` (the arenas) and `STADIUMS` (the stadiums); at least one
|
|
18
|
+
/** The venues, by key: any key of `VENUES` (the arenas) and `STADIUMS` (the stadiums); at least one, unless the district has a `circuit`. */
|
|
17
19
|
venues: readonly DistrictVenueInput[];
|
|
20
|
+
/**
|
|
21
|
+
* A race circuit laid on the same ground (a key of `CIRCUIT_IDS`: `las-vegas`): its lap, pit lane, ground and pit building where OpenStreetMap maps them, under the venues, turned as it lies; in 3D its pit building and its turns'
|
|
22
|
+
* numbers stand up and a lap that crosses itself stands its pass over on a bridge, as in the circuit's own view. Missing: no circuit.
|
|
23
|
+
*/
|
|
24
|
+
circuit?: string;
|
|
18
25
|
/** `neighbours` (the default) or `city`. */
|
|
19
26
|
mode?: DistrictMode;
|
|
20
27
|
/** How far the plan is turned, in degrees clockwise: 0 (the default) has north at the top; `"auto"` turns it so that the district's long way lies across the page. */
|
|
@@ -171,6 +178,19 @@ export interface DistrictGate {
|
|
|
171
178
|
angle: number;
|
|
172
179
|
basis: "documented" | "plausible";
|
|
173
180
|
}
|
|
181
|
+
/** A circuit placed in a district: its own plan (feet round its own middle, its long side along x), and where that middle is put and how far the plan is turned to lie as it does in the world. */
|
|
182
|
+
export interface DistrictCircuit {
|
|
183
|
+
plan: CircuitPlan;
|
|
184
|
+
/** Where the circuit's own origin (the middle of its plan) is in the district's frame, in feet. */
|
|
185
|
+
at: Pt;
|
|
186
|
+
/** The degrees the circuit's plan is turned clockwise to lie in the district (its heading less a quarter turn, and the map's turn). */
|
|
187
|
+
angle: number;
|
|
188
|
+
/** The outline of everything it draws on the ground (its plan's box), and of its pit building, in the district's frame. */
|
|
189
|
+
footprint: Pt[];
|
|
190
|
+
building?: Pt[];
|
|
191
|
+
}
|
|
192
|
+
/** A point of a circuit's own plan (feet, `circuitPlan`) where the district puts it: for a page that draws something on the lap (a race's cars) in a district's frame. */
|
|
193
|
+
export declare function circuitPointIn(placed: Pick<DistrictCircuit, "at" | "angle">, p: Pt): Pt;
|
|
174
194
|
/** What a district is: its venues placed, the box that fits them, and how the map lies. */
|
|
175
195
|
export interface DistrictPlan {
|
|
176
196
|
options: DistrictOptions;
|
|
@@ -197,8 +217,10 @@ export interface DistrictPlan {
|
|
|
197
217
|
b: string;
|
|
198
218
|
metres: number;
|
|
199
219
|
}[];
|
|
200
|
-
/** The `[longitude, latitude]` the plan's metres are measured from: the middle of the venues' surfaces. */
|
|
220
|
+
/** The `[longitude, latitude]` the plan's metres are measured from: the middle of the venues' surfaces (and of the circuit's plan, where there is one). */
|
|
201
221
|
origin: readonly [number, number];
|
|
222
|
+
/** The circuit on the ground, where the options name one. */
|
|
223
|
+
circuit?: DistrictCircuit;
|
|
202
224
|
}
|
|
203
225
|
/** The margin round the buildings, as a share of the longer side of the district: tight for neighbours, wide for a city's grid and names. */
|
|
204
226
|
export declare const DISTRICT_MARGIN: Readonly<Record<DistrictMode, number>>;
|
|
@@ -217,7 +239,7 @@ export declare const OUTSIDE_ROOM = 160;
|
|
|
217
239
|
*/
|
|
218
240
|
export declare function planDistrict(options: DistrictOptions): DistrictPlan;
|
|
219
241
|
/** The colours and the type of a district's drawing, light and dark. Defaults sit in `:where()`, so a page's own rule wins. */
|
|
220
|
-
export declare const KYOGIJO_DISTRICT_STYLE = "\n:where(.ky-district){--ky-dist-ground:#e1e4da;--ky-dist-grid:rgba(40,46,42,.16);--ky-dist-ink:#1f2320;--ky-dist-halo:rgba(255,255,255,.9);--ky-dist-people:#c2410c;--ky-dist-b0:#d1d4cb;--ky-dist-b1:#c3c7be;--ky-dist-b2:#b2b7ae;--ky-dist-b3:#9ea49b;--ky-dist-bline:rgba(40,46,42,.28);--ky-dist-road:#cbcfc4;--ky-dist-deck:#bdc2b7;--ky-dist-walk:#eef0e8;--ky-dist-rail:#8b9288;--ky-dist-gate:#1f5fa8;--ky-dist-water:#c7d5dc;--ky-dist-green:#d2dcc4;--ky-dist-wood:#c3d0b6;--ky-dist-tree:#b3c2a3;--ky-dist-floor:#2f6db0}\n@media (prefers-color-scheme:dark){:where(html:not([data-theme=light]) .ky-district:not([data-theme=light])){--ky-dist-ground:#1b2025;--ky-dist-grid:rgba(220,226,220,.16);--ky-dist-ink:#e8ece8;--ky-dist-halo:rgba(14,18,16,.85);--ky-dist-people:#fbbf24;--ky-dist-b0:#262c31;--ky-dist-b1:#2e353b;--ky-dist-b2:#394148;--ky-dist-b3:#474f57;--ky-dist-bline:rgba(220,226,220,.22);--ky-dist-road:#2b3239;--ky-dist-deck:#353d45;--ky-dist-walk:#242b31;--ky-dist-rail:#5b646c;--ky-dist-gate:#7fb2ee;--ky-dist-water:#1c2d3b;--ky-dist-green:#202d26;--ky-dist-wood:#1c2b23;--ky-dist-tree:#2e4337;--ky-dist-floor:#7fb0e8}}\n:where(html[data-theme=dark] .ky-district,.ky-district[data-theme=dark]){--ky-dist-ground:#1b2025;--ky-dist-grid:rgba(220,226,220,.16);--ky-dist-ink:#e8ece8;--ky-dist-halo:rgba(14,18,16,.85);--ky-dist-people:#fbbf24;--ky-dist-b0:#262c31;--ky-dist-b1:#2e353b;--ky-dist-b2:#394148;--ky-dist-b3:#474f57;--ky-dist-bline:rgba(220,226,220,.22);--ky-dist-road:#2b3239;--ky-dist-deck:#353d45;--ky-dist-walk:#242b31;--ky-dist-rail:#5b646c;--ky-dist-gate:#7fb2ee;--ky-dist-water:#1c2d3b;--ky-dist-green:#202d26;--ky-dist-wood:#1c2b23;--ky-dist-tree:#2e4337;--ky-dist-floor:#7fb0e8}\n.ky-district .ky-dist-ground{fill:var(--ky-dist-ground)}\n.ky-district .ky-dist-grid{fill:none;stroke:var(--ky-dist-grid);stroke-width:1}\n.ky-district .ky-dist-block{stroke:var(--ky-dist-bline);stroke-width:.5;stroke-linejoin:round}\n.ky-district .ky-dist-b0{fill:var(--ky-dist-b0)}\n.ky-district .ky-dist-b1{fill:var(--ky-dist-b1)}\n.ky-district .ky-dist-b2{fill:var(--ky-dist-b2)}\n.ky-district .ky-dist-b3{fill:var(--ky-dist-b3)}\n.ky-district .ky-dist-street{stroke-linejoin:round;stroke-linecap:butt}\n.ky-district .ky-dist-street-0{stroke:var(--ky-dist-road)}\n.ky-district .ky-dist-street-1{stroke:var(--ky-dist-deck)}\n.ky-district .ky-dist-street-2{stroke:var(--ky-dist-rail);stroke-dasharray:6 3}\n.ky-district .ky-dist-street-3{stroke:var(--ky-dist-walk)}\n.ky-district .ky-dist-land{stroke:none}\n.ky-district .ky-dist-water{fill:var(--ky-dist-water)}\n.ky-district .ky-dist-green{fill:var(--ky-dist-green)}\n.ky-district .ky-dist-wood{fill:var(--ky-dist-wood)}\n.ky-district .ky-dist-tree{fill:none;stroke:var(--ky-dist-tree);stroke-linecap:round}\n.ky-district .ky-dist-gate rect{fill:var(--ky-dist-gate);stroke:var(--ky-dist-gate);stroke-width:2.4}\n.ky-district .ky-dist-gate-plausible rect{fill:var(--ky-dist-ground);fill-opacity:.85}\n.ky-district .ky-dist-gate-queue{fill:none;stroke:var(--ky-dist-gate);stroke-width:3;stroke-dasharray:9 7}\n.ky-district .ky-dist-ghost{fill:var(--ky-dist-b1);fill-opacity:.35}\n.ky-district .ky-dist-floor{stroke:var(--ky-dist-floor);stroke-width:2}\n.ky-district .ky-dist-ink{fill:none;stroke:var(--ky-dist-ink);stroke-linecap:round;stroke-linejoin:round}\n.ky-district .ky-dist-text{fill:var(--ky-dist-ink);font-family:var(--ky-font,system-ui,-apple-system,\"Segoe UI\",\"Hiragino Sans\",\"Noto Sans JP\",sans-serif);font-weight:600;paint-order:stroke;stroke:var(--ky-dist-halo);stroke-linejoin:round}";
|
|
242
|
+
export declare const KYOGIJO_DISTRICT_STYLE = "\n:where(.ky-district){--ky-dist-ground:#e1e4da;--ky-dist-grid:rgba(40,46,42,.16);--ky-dist-ink:#1f2320;--ky-dist-halo:rgba(255,255,255,.9);--ky-dist-people:#c2410c;--ky-dist-b0:#d1d4cb;--ky-dist-b1:#c3c7be;--ky-dist-b2:#b2b7ae;--ky-dist-b3:#9ea49b;--ky-dist-bline:rgba(40,46,42,.28);--ky-dist-road:#cbcfc4;--ky-dist-deck:#bdc2b7;--ky-dist-walk:#eef0e8;--ky-dist-rail:#8b9288;--ky-dist-gate:#1f5fa8;--ky-dist-water:#c7d5dc;--ky-dist-green:#d2dcc4;--ky-dist-wood:#c3d0b6;--ky-dist-tree:#b3c2a3;--ky-dist-floor:#2f6db0}\n@media (prefers-color-scheme:dark){:where(html:not([data-theme=light]) .ky-district:not([data-theme=light])){--ky-dist-ground:#1b2025;--ky-dist-grid:rgba(220,226,220,.16);--ky-dist-ink:#e8ece8;--ky-dist-halo:rgba(14,18,16,.85);--ky-dist-people:#fbbf24;--ky-dist-b0:#262c31;--ky-dist-b1:#2e353b;--ky-dist-b2:#394148;--ky-dist-b3:#474f57;--ky-dist-bline:rgba(220,226,220,.22);--ky-dist-road:#2b3239;--ky-dist-deck:#353d45;--ky-dist-walk:#242b31;--ky-dist-rail:#5b646c;--ky-dist-gate:#7fb2ee;--ky-dist-water:#1c2d3b;--ky-dist-green:#202d26;--ky-dist-wood:#1c2b23;--ky-dist-tree:#2e4337;--ky-dist-floor:#7fb0e8}}\n:where(html[data-theme=dark] .ky-district,.ky-district[data-theme=dark]){--ky-dist-ground:#1b2025;--ky-dist-grid:rgba(220,226,220,.16);--ky-dist-ink:#e8ece8;--ky-dist-halo:rgba(14,18,16,.85);--ky-dist-people:#fbbf24;--ky-dist-b0:#262c31;--ky-dist-b1:#2e353b;--ky-dist-b2:#394148;--ky-dist-b3:#474f57;--ky-dist-bline:rgba(220,226,220,.22);--ky-dist-road:#2b3239;--ky-dist-deck:#353d45;--ky-dist-walk:#242b31;--ky-dist-rail:#5b646c;--ky-dist-gate:#7fb2ee;--ky-dist-water:#1c2d3b;--ky-dist-green:#202d26;--ky-dist-wood:#1c2b23;--ky-dist-tree:#2e4337;--ky-dist-floor:#7fb0e8}\n.ky-district .ky-dist-ground{fill:var(--ky-dist-ground)}\n.ky-district .ky-dist-grid{fill:none;stroke:var(--ky-dist-grid);stroke-width:1}\n.ky-district .ky-dist-block{stroke:var(--ky-dist-bline);stroke-width:.5;stroke-linejoin:round}\n.ky-district .ky-dist-b0{fill:var(--ky-dist-b0)}\n.ky-district .ky-dist-b1{fill:var(--ky-dist-b1)}\n.ky-district .ky-dist-b2{fill:var(--ky-dist-b2)}\n.ky-district .ky-dist-b3{fill:var(--ky-dist-b3)}\n.ky-district .ky-dist-street{stroke-linejoin:round;stroke-linecap:butt}\n.ky-district .ky-dist-street-0{stroke:var(--ky-dist-road)}\n.ky-district .ky-dist-street-1{stroke:var(--ky-dist-deck)}\n.ky-district .ky-dist-street-2{stroke:var(--ky-dist-rail);stroke-dasharray:6 3}\n.ky-district .ky-dist-street-3{stroke:var(--ky-dist-walk)}\n.ky-district .ky-dist-land{stroke:none}\n.ky-district .ky-dist-water{fill:var(--ky-dist-water)}\n.ky-district .ky-dist-green{fill:var(--ky-dist-green)}\n.ky-district .ky-dist-wood{fill:var(--ky-dist-wood)}\n.ky-district .ky-dist-tree{fill:none;stroke:var(--ky-dist-tree);stroke-linecap:round}\n.ky-district .ky-dist-jet{fill:none;stroke:var(--ky-dist-halo);stroke-linecap:round}\n.ky-district .ky-dist-gate rect{fill:var(--ky-dist-gate);stroke:var(--ky-dist-gate);stroke-width:2.4}\n.ky-district .ky-dist-gate-plausible rect{fill:var(--ky-dist-ground);fill-opacity:.85}\n.ky-district .ky-dist-gate-queue{fill:none;stroke:var(--ky-dist-gate);stroke-width:3;stroke-dasharray:9 7}\n.ky-district .ky-dist-ghost{fill:var(--ky-dist-b1);fill-opacity:.35}\n.ky-district .ky-dist-floor{stroke:var(--ky-dist-floor);stroke-width:2}\n.ky-district .ky-dist-ink{fill:none;stroke:var(--ky-dist-ink);stroke-linecap:round;stroke-linejoin:round}\n.ky-district .ky-dist-text{fill:var(--ky-dist-ink);font-family:var(--ky-font,system-ui,-apple-system,\"Segoe UI\",\"Hiragino Sans\",\"Noto Sans JP\",sans-serif);font-weight:600;paint-order:stroke;stroke:var(--ky-dist-halo);stroke-linejoin:round}";
|
|
221
243
|
/**
|
|
222
244
|
* A venue's drawing as a part of the district's: its root made a nested `svg` that keeps the class, the sport and the colours the drawing's stylesheet reads, its box laid in its own frame (so that the group's turn
|
|
223
245
|
* and shift put it in place), and its title, description, apron, arrow and stylesheet taken out (the stylesheet is given back in `styles`).
|
|
@@ -263,5 +285,7 @@ export declare function drawMember(member: DistrictMember, options: DistrictOpti
|
|
|
263
285
|
* ```
|
|
264
286
|
*/
|
|
265
287
|
export declare function drawDistrict(options: DistrictOptions, plan?: DistrictPlan, drawing?: (member: DistrictMember, index: number, part: number) => string): string;
|
|
288
|
+
/** The options a district's circuit is drawn from: the circuit's own drawing in the district's language and theme, without its frame, and for the floor of the 3D view without its turns' numbers (they stand up). */
|
|
289
|
+
export declare function circuitInDistrict(options: DistrictOptions, id: string, floor: boolean): CircuitOptions;
|
|
266
290
|
/** The venues a district was asked for that the package has no key for: none when it can be drawn. */
|
|
267
291
|
export declare const unknownVenues: (venues: readonly DistrictVenueInput[]) => string[];
|