@johnmorrisdotca/kyogijo-stadiums 0.56.0 → 0.58.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 +15 -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/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/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/landmarks.d.ts +105 -0
- package/dist/landmarks.js +160 -0
- package/dist/turn.camera.d.ts +6 -3
- package/dist/turn.camera.js +10 -3
- package/dist/turn.dom.js +27 -14
- 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/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,21 @@ All notable changes to this project are written here. The format follows
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.58.0] - 2026-11-03
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Las Vegas: the Strip Circuit, T-Mobile Arena and the Strip's landmarks on one ground (KYOGIJO-STADIUMS-30)** ([districts](./docs/district.md#las-vegas-a-circuit-on-the-ground-and-the-strips-landmarks)): a district's `circuit` option lays a circuit on its ground with the venues, turned as it lies, its pit building and turns' numbers standing in 3D (`circuitPointIn` maps a point of the circuit's plan into the district's, for a race on it); a circuit alone is a district too. A new area of context, `LAS_VEGAS` (`las-vegas`, OpenStreetMap, ODbL), 1.9 km round the lap and the arena: the Strip's buildings and towers at their mapped heights, the streets and the water, and four landmarks by shapes of their own at published sizes, named in English and Japanese (`ContextArea.landmarks`, `landmarks.ts`): the Sphere a dome, the High Roller a wheel, the jets of the Fountains of Bellagio, and Caesars Palace's name over its tallest building. `areaKeysFor` and `loadAreasFor` take the circuit; the lean district reads the circuits with `loadCircuits()` (`CIRCUIT_INDEX` names them). Held to 2,100 planes in 3D (under Seattle's three venues) and 2,565 KB for the demo's page. The demo's district page has the preset "Las Vegas: the Strip Circuit, T-Mobile Arena and the Sphere".
|
|
15
|
+
- **A race on the Strip (KYOGIJO-STADIUMS-30)** ([a race on the Strip](./docs/district.md#a-race-on-the-strip)): the circuits' race runs on a district's ground, its twenty made-up cars on the Strip Circuit among T-Mobile Arena, the hotels, the Sphere, the High Roller and the Fountains of Bellagio, flat or in 3D, with the race clock, the speeds, the slider and the timing board. `drawDistrictRace` draws a moment and `mountDistrictRace` plays it in a page (a feed's race too, as `settings.race`); the race's view in a page takes the scene it is drawn in (`mountRaceIn`, `RaceScene`), and the cars are put on the district's ground with `circuitPointIn`. The demo's district page has **Race** beside the view when a circuit is chosen, kept in the address, and the circuits page's link to the district takes the race along. The lean district reads the race with the circuits (`loadCircuits`).
|
|
16
|
+
- Fixed: a 3D view in `auto` quality times its frames in the view's one shared animation frame: a district's view that turned or played a race while its quality was being chosen asked for two frames a frame.
|
|
17
|
+
|
|
18
|
+
## [0.57.0] - 2026-11-03
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **The wheel zooms the 3D view** (KAZOKU-UI-45). The wheel over the view now zooms it, as a map does (up in, down out, about the view's middle, which is where the pinch and the buttons zoom; a notch about as much as the + key); before, the plain wheel was the page's and tipped a focused view. A trackpad's pinch (Ctrl or Command and the wheel) still zooms. Shift and the wheel, or a sideways swipe, turns the view. The wheel never tips it: a drag, the arrows and the buttons do. With the pointer anywhere else the wheel scrolls the page, and a wheel that starts while the zoom is already at its end that way scrolls the page too, so a page of views is never trapped; the steps of a turn that reaches the end part-way through stay with the view, so the page does not jump.
|
|
23
|
+
|
|
24
|
+
|
|
10
25
|
## [0.56.0] - 2026-11-03
|
|
11
26
|
|
|
12
27
|
### Added
|
package/NOTICE.md
CHANGED
|
@@ -52,6 +52,8 @@ picture or code of the sources is copied; each source is named here so that the
|
|
|
52
52
|
| `walk`: the ground a crowd outside a district's venues may stand on and what stops it (`WALK_DATA`, `src/walk.data.ts`): paths and sidewalks, plazas, squares, parks and platforms, and carriageways, cycle tracks, railways, water and buildings, as lines with a width and as rings | OpenStreetMap, through the Overpass API: every way and relation of the highways, buildings, railways, water, squares, parks and platforms within 350 metres of the district's venues, read on 2026-10-22, with the raw answer kept in `data-sources/walk/2026-10-22/`; laid flat in metres, simplified to 30 centimetres and written in quarter-metres, by the rules of `scripts/walk-rules.mjs` (no name, id or tag is copied) | ODbL 1.0, (c) OpenStreetMap contributors (https://www.openstreetmap.org/copyright): a derived database, kept in its own file and offered under the ODbL; a crowd or a drawing made from it is a produced work and carries the credit (`VENUE_ATTRIBUTION`) |
|
|
53
53
|
| `plateau`: the buildings round Tokyo Dome City (`TOKYO_DOME_CITY`, `src/plateau.data.ts`): each building's roof-edge outline simplified to 0.6 metres on a half-metre grid, its height and, for a pitched LOD2 roof, the rise of the roof | Project PLATEAU, the Ministry of Land, Infrastructure, Transport and Tourism's (MLIT) 3D city model of Bunkyo ward, 2025 edition (product specification 5.0, CityGML, https://www.geospatial.jp/ckan/dataset/plateau-13105-bunkyo-ku-2025), read on 2026-10-22: the buildings within 500 metres of the middle of the district, with the raw fields kept in `data-sources/plateau/2026-10-22/` (`pnpm plateau:fetch`, `pnpm plateau`) | PLATEAU Site Policy (https://www.mlit.go.jp/plateau/site-policy/), clause 3: free use, commercial use included, compatible with CC BY 4.0 and the Public Data License 1.0; the source is credited and the data says it was edited and not made by MLIT (`PLATEAU_ATTRIBUTION`: "Project PLATEAU, Ministry of Land, Infrastructure, Transport and Tourism (MLIT), https://www.mlit.go.jp/plateau/ (3D city model of Bunkyo ward, 2025 edition), simplified and edited by Kyogijo Stadiums; not made by MLIT"); the copyright of a ward's data belongs to its local government. Kept in its own file, apart from the OpenStreetMap data (ODbL) and the CC0 files |
|
|
54
54
|
| `cityctx`: the surroundings of the venues of Seattle (`SEATTLE_SODO`, `SEATTLE_CENTER`, `SEATTLE_CITY`) and the land cover and trees round Vancouver's (`VANCOUVER_NATURE`), in `src/cityctx.data.ts`: buildings (outline, height, for a pitched roof its rise), streets, railways, sidewalks and paths as lines with a width, water, green and wood outlines, and single trees | OpenStreetMap, through the Overpass API: the buildings (with their `height` and `building:levels`), the highways and railways, the tree nodes and rows within the radius of each area, read on 2026-10-22, the raw answers kept in `data-sources/cityctx/2026-10-22/` (`pnpm cityctx:fetch`, `pnpm cityctx:vox`, `pnpm cityctx`); laid flat in metres, simplified and put on a grid of half a metre (two metres for Seattle's city view) | OpenStreetMap's data is ODbL 1.0 (https://opendatacommons.org/licenses/odbl/1-0/), credited "(c) OpenStreetMap contributors, ODbL 1.0, openstreetmap.org/copyright"; the file is a derived database kept in its own file, apart from the CC0 files and from PLATEAU's data |
|
|
55
|
+
| `cityctx`: the surroundings of the Las Vegas Strip Circuit and T-Mobile Arena (`LAS_VEGAS`, `src/cityctx.las-vegas.data.ts`): the buildings and the tall parts of buildings that matter from far, the streets and railways, the water, and four landmarks' outlines (the Sphere way/976405284, the High Roller way/402543930, the Fountains of Bellagio relation/19511963, Caesars Palace way/495449303) | OpenStreetMap, through the Overpass API (every building and every part of a building with a `height` or `building:levels`, the highways, railways, water and parks, and the landmarks' elements), read on 2026-11-03 and kept in `data-sources/cityctx/2026-11-03/` (`pnpm cityctx:fetch`, `pnpm cityctx`) | ODbL 1.0, (c) OpenStreetMap contributors; a derived database kept apart from the CC0 files |
|
|
56
|
+
| `cityctx`: the landmarks' names and sizes (`LAS_VEGAS.landmarks`) | Wikidata's labels in English and Japanese and its heights (P2048) of Q60749353 (Sphere), Q892103 (High Roller), Q2735117 (Fountains of Bellagio) and Q569978 (Caesars Palace); the widths and the fountains' height from the English Wikipedia articles "Sphere (venue)" (revision 1382276386), "High Roller (Ferris wheel)" (1344683153) and "Fountains of Bellagio" (1381701116), kept as evidence in `data-sources/cityctx/2026-11-03/landmarks-las-vegas.json`; two Japanese names are ours (`スフィア`, `ベラージオの噴水`) | Wikidata is CC0; the figures read from the articles are facts, in our own words (the articles are CC BY-SA 4.0) |
|
|
55
57
|
| `cityctx`: the surroundings of New York's venues (`NYC_MIDTOWN`, `NYC_BRONX`, `NYC_FLUSHING`, `NYC_BROOKLYN`), of the Meadowlands (`MEADOWLANDS`), of Belmont Park (`BELMONT_PARK`) and of Montreal's (`MONTREAL_DOWNTOWN`, `MONTREAL_OLYMPIC`, `MONTREAL_CITY`), one file each (`src/cityctx.<area>.data.ts`): buildings, streets, railways, sidewalks and paths, water, green and wood outlines, and single trees | OpenStreetMap, through the Overpass API (the buildings with their `height` and `building:levels`, the highways, railways, water and parks, the tree nodes and rows), read on 2026-10-30 and kept in `data-sources/cityctx/2026-10-30/` (`pnpm cityctx:fetch`, `pnpm cityctx`); the water, wetland, park, grass and wood outlines are OpenStreetMap's as mapped (VoxCity is not used for these areas) | OpenStreetMap's data is ODbL 1.0, credited "(c) OpenStreetMap contributors, ODbL 1.0, openstreetmap.org/copyright"; each file is a derived database kept apart from the CC0 files and from PLATEAU's data |
|
|
56
58
|
| `cityctx`: the heights of New York's buildings | The City of New York's Building Footprints (NYC Open Data, dataset 5zhs-2jue, Office of Technology and Innovation: the outline, the roof height above the ground in feet and the construction year of each building), read through the portal's API on 2026-10-30 and kept in `data-sources/cityctx/2026-10-30/nyc-footprints-*.json`; the roof height is used where a footprint matches an OpenStreetMap building, and a footprint OpenStreetMap lacks is a building of its own | A public data set of the City under its Open Data Law (Administrative Code 23-502: made available without registration, licence requirement or restriction on use, the City being able to ask a third party that publishes it to name its source and version and to say what it changed); the City gives no warranty of the data's accuracy (the credit says it): the credit names the data set, the date read and that it was edited |
|
|
57
59
|
| `cityctx`: Vancouver's trees | The City of Vancouver's open data, "Public trees" (place and diameter), read through the portal's API on 2026-10-22 and kept in `data-sources/cityctx/2026-10-22/` | The Open Government Licence - Vancouver (https://opendata.vancouver.ca/pages/licence/): free to use, with the City credited, in each layer, in English and in Japanese |
|
package/README.md
CHANGED
|
@@ -254,7 +254,7 @@ console.log(svg.startsWith("<svg"), svg.includes("USA 3, Canada 2"));
|
|
|
254
254
|
- **A catalogue of venues**: every venue drawn today, the ones being built and the ones wanted (every NBA, MLB, NFL, CFL and NHL venue of the season, world soccer, cricket, rugby, the Olympics, Formula One and more), with ids, names in English and Japanese and Wikidata items, as a [JSON file](https://johnmorrisdotca.github.io/kyogijo-stadiums/catalogue.json) and a typed entry. [The catalogue](./docs/catalogue.md).
|
|
255
255
|
- **Real venues**: arenas and stadiums in the outline of their buildings, districts of several venues on one plan, the crowd in the stands and outside. [Ballparks](./docs/ballparks.md), [venues](./docs/venues.md), [districts](./docs/district.md).
|
|
256
256
|
- **A 3D view** of any surface or venue that turns by mouse, touch or keys, with the roof and the walls to switch and a quality level for every device. [The 3D view](./docs/turn.md), [quality](./docs/quality.md).
|
|
257
|
-
- **Circuits**: a famous race track as OpenStreetMap maps it, the Las Vegas Strip Circuit first, with its turns numbered and its pit building standing in 3D, and a simulated race on it: twenty made-up cars over a full race distance, with a race clock, a timing board and 1×, 10× and 60
|
|
257
|
+
- **Circuits**: a famous race track as OpenStreetMap maps it, the Las Vegas Strip Circuit first, with its turns numbered and its pit building standing in 3D, and a simulated race on it: twenty made-up cars over a full race distance, with a race clock, a timing board and 1×, 10× and 60×; on a district's ground beside T-Mobile Arena among the Strip, with the Sphere, the High Roller and the Fountains of Bellagio, where the race runs too. [Circuits](./docs/circuits.md#a-race), [Las Vegas](./docs/district.md#las-vegas-a-circuit-on-the-ground-and-the-strips-landmarks), [a race on the Strip](./docs/district.md#a-race-on-the-strip).
|
|
258
258
|
- **Bring your own race feed**: a race plays from a feed you choose, read by your own browser from an address, pasted or from a file, and followed while it is live: kyogijo's open race timeline or OpenF1-style lap rows, with our made-up sample feed first. [The race feed](./docs/race-feed.md), [Where to find a feed](./docs/where-to-find-a-feed.md).
|
|
259
259
|
- **Tournaments**: several surfaces on one floor, who judges where, boards laid over a surface. [Layouts](./docs/multi.md), [judging](./docs/judging.md), [boards](./docs/boards.md).
|
|
260
260
|
- **Data on a surface**: points, heat maps, shot and pass charts, team shapes and a replay, flat or in 3D with the players standing on the ice, in 48 providers' coordinate frames. [Layers](./docs/layers.md), [frames](./docs/frames.md), [replay](./docs/replay.md), [an example game](./docs/example-games.md).
|
package/catalogue.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"generatedAt": "2026-11-03",
|
|
4
4
|
"package": {
|
|
5
5
|
"name": "@johnmorrisdotca/kyogijo-stadiums",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.58.0"
|
|
7
7
|
},
|
|
8
8
|
"address": "https://johnmorrisdotca.github.io/kyogijo-stadiums/catalogue.json",
|
|
9
9
|
"site": "https://johnmorrisdotca.github.io/kyogijo-stadiums/",
|
package/dist/areas.d.ts
CHANGED
|
@@ -9,6 +9,11 @@ export declare const CITYCTX_VENUES: Readonly<{
|
|
|
9
9
|
export declare const CITYCTX_DETAIL: Readonly<Record<string, readonly string[]>>;
|
|
10
10
|
/** The most patches of New York's surroundings a choice of venues takes: more than this many venues of the city are too far apart for patches of detail round each. */
|
|
11
11
|
export declare const MOST_DETAIL_AREAS = 2;
|
|
12
|
+
/** The venues and the circuits each area of a circuit's surroundings is drawn round: Las Vegas's (the Strip Circuit, T-Mobile Arena and the Strip between them, with the Sphere, the High Roller and the Fountains of Bellagio). */
|
|
13
|
+
export declare const CIRCUIT_AREAS: Readonly<Record<string, {
|
|
14
|
+
venues: readonly string[];
|
|
15
|
+
circuits: readonly string[];
|
|
16
|
+
}>>;
|
|
12
17
|
/** The venues of Tokyo Dome City, round which Project PLATEAU's buildings are drawn (the Kodokan stands a little way off, inside the area). */
|
|
13
18
|
export declare const TOKYO_VENUES: readonly string[];
|
|
14
19
|
/** The key of every area there is data for, in the order a district draws them: each is one file. */
|
|
@@ -16,7 +21,7 @@ export declare const AREA_KEYS: readonly string[];
|
|
|
16
21
|
/**
|
|
17
22
|
* The keys of the areas that go with some venues, in the order to draw them: downtown Vancouver's buildings and streets and its water, green and trees for BC Place and Rogers Arena; Seattle's SoDo for Lumen Field and
|
|
18
23
|
* T-Mobile Park, Seattle Center's for Climate Pledge Arena, and the city's own for a district that holds venues of both (they are three kilometres apart, so the detail of either would be a speck); Tokyo Dome City's for
|
|
19
|
-
* Tokyo Dome, Korakuen Hall and the Kodokan, which take it before any other. A venue of none of these has no area.
|
|
24
|
+
* Tokyo Dome, Korakuen Hall and the Kodokan, which take it before any other; Las Vegas's for T-Mobile Arena and for the Las Vegas Strip Circuit (`circuit`, a district's circuit). A venue of none of these has no area.
|
|
20
25
|
* @example
|
|
21
26
|
* ```ts
|
|
22
27
|
* import { areaKeysFor } from "@johnmorrisdotca/kyogijo-stadiums/areas";
|
|
@@ -24,7 +29,7 @@ export declare const AREA_KEYS: readonly string[];
|
|
|
24
29
|
* // [ 'vancouver', 'vancouver-nature' ]
|
|
25
30
|
* ```
|
|
26
31
|
*/
|
|
27
|
-
export declare function areaKeysFor(venues: readonly string[]): string[];
|
|
32
|
+
export declare function areaKeysFor(venues: readonly string[], circuit?: string): string[];
|
|
28
33
|
/**
|
|
29
34
|
* One area by its key (`AREA_KEYS`), read from its own file the first time and kept after: asking again gives the same promise. A key that is not an area rejects, naming the keys there are.
|
|
30
35
|
* @example
|
|
@@ -47,4 +52,4 @@ export declare function loadArea(key: string): Promise<ContextArea>;
|
|
|
47
52
|
* console.log(plan.context?.attribution.en.length);
|
|
48
53
|
* ```
|
|
49
54
|
*/
|
|
50
|
-
export declare function loadAreasFor(venues: readonly string[]): Promise<ContextArea[]>;
|
|
55
|
+
export declare function loadAreasFor(venues: readonly string[], circuit?: string): Promise<ContextArea[]>;
|
package/dist/areas.js
CHANGED
|
@@ -17,10 +17,14 @@ export const CITYCTX_DETAIL = Object.freeze({
|
|
|
17
17
|
});
|
|
18
18
|
/** The most patches of New York's surroundings a choice of venues takes: more than this many venues of the city are too far apart for patches of detail round each. */
|
|
19
19
|
export const MOST_DETAIL_AREAS = 2;
|
|
20
|
+
/** The venues and the circuits each area of a circuit's surroundings is drawn round: Las Vegas's (the Strip Circuit, T-Mobile Arena and the Strip between them, with the Sphere, the High Roller and the Fountains of Bellagio). */
|
|
21
|
+
export const CIRCUIT_AREAS = Object.freeze({
|
|
22
|
+
"las-vegas": { venues: ["t-mobile-arena"], circuits: ["las-vegas"] },
|
|
23
|
+
});
|
|
20
24
|
/** The venues of Tokyo Dome City, round which Project PLATEAU's buildings are drawn (the Kodokan stands a little way off, inside the area). */
|
|
21
25
|
export const TOKYO_VENUES = Object.freeze(["tokyo-dome", "korakuen-hall", "kodokan"]);
|
|
22
26
|
/** The key of every area there is data for, in the order a district draws them: each is one file. */
|
|
23
|
-
export const AREA_KEYS = Object.freeze(["vancouver", "vancouver-nature", "seattle-sodo", "seattle-center", "seattle-city", "tokyo-dome-city", "nyc-midtown", "nyc-bronx", "nyc-flushing", "nyc-brooklyn", "meadowlands", "belmont-park", "montreal-downtown", "montreal-olympic", "montreal-city"]);
|
|
27
|
+
export const AREA_KEYS = Object.freeze(["vancouver", "vancouver-nature", "seattle-sodo", "seattle-center", "seattle-city", "tokyo-dome-city", "nyc-midtown", "nyc-bronx", "nyc-flushing", "nyc-brooklyn", "meadowlands", "belmont-park", "montreal-downtown", "montreal-olympic", "montreal-city", "las-vegas"]);
|
|
24
28
|
/** Each area's loader: the one `import()` of the one file that holds it. */
|
|
25
29
|
const LOADERS = {
|
|
26
30
|
"vancouver": async () => (await import("./osm.context.data.js")).VANCOUVER_CENTRE,
|
|
@@ -38,11 +42,12 @@ const LOADERS = {
|
|
|
38
42
|
"montreal-downtown": async () => (await import("./cityctx.montreal-downtown.data.js")).MONTREAL_DOWNTOWN,
|
|
39
43
|
"montreal-olympic": async () => (await import("./cityctx.montreal-olympic.data.js")).MONTREAL_OLYMPIC,
|
|
40
44
|
"montreal-city": async () => (await import("./cityctx.montreal-city.data.js")).MONTREAL_CITY,
|
|
45
|
+
"las-vegas": async () => (await import("./cityctx.las-vegas.data.js")).LAS_VEGAS,
|
|
41
46
|
};
|
|
42
47
|
/**
|
|
43
48
|
* The keys of the areas that go with some venues, in the order to draw them: downtown Vancouver's buildings and streets and its water, green and trees for BC Place and Rogers Arena; Seattle's SoDo for Lumen Field and
|
|
44
49
|
* T-Mobile Park, Seattle Center's for Climate Pledge Arena, and the city's own for a district that holds venues of both (they are three kilometres apart, so the detail of either would be a speck); Tokyo Dome City's for
|
|
45
|
-
* Tokyo Dome, Korakuen Hall and the Kodokan, which take it before any other. A venue of none of these has no area.
|
|
50
|
+
* Tokyo Dome, Korakuen Hall and the Kodokan, which take it before any other; Las Vegas's for T-Mobile Arena and for the Las Vegas Strip Circuit (`circuit`, a district's circuit). A venue of none of these has no area.
|
|
46
51
|
* @example
|
|
47
52
|
* ```ts
|
|
48
53
|
* import { areaKeysFor } from "@johnmorrisdotca/kyogijo-stadiums/areas";
|
|
@@ -50,12 +55,16 @@ const LOADERS = {
|
|
|
50
55
|
* // [ 'vancouver', 'vancouver-nature' ]
|
|
51
56
|
* ```
|
|
52
57
|
*/
|
|
53
|
-
export function areaKeysFor(venues) {
|
|
58
|
+
export function areaKeysFor(venues, circuit) {
|
|
54
59
|
const ids = new Set(venues.map((key) => key.split(":")[0]));
|
|
55
60
|
const has = (list) => list.some((id) => ids.has(id));
|
|
56
61
|
if (has(TOKYO_VENUES))
|
|
57
62
|
return ["tokyo-dome-city"];
|
|
58
63
|
const keys = [];
|
|
64
|
+
// A circuit's surroundings, for the circuit or a venue beside it (T-Mobile Arena, by the Las Vegas Strip Circuit).
|
|
65
|
+
for (const [key, round] of Object.entries(CIRCUIT_AREAS))
|
|
66
|
+
if (has(round.venues) || (circuit !== undefined && round.circuits.includes(circuit)))
|
|
67
|
+
keys.push(key);
|
|
59
68
|
// Montreal's two venues stand six kilometres apart: together they take the city between them, each alone its own surroundings. New York's and New Jersey's venues are in different boroughs and states: each shown takes its own.
|
|
60
69
|
const montreal = ["montreal-downtown", "montreal-olympic"].filter((key) => has(CITYCTX_DETAIL[key]));
|
|
61
70
|
if (montreal.length === 2)
|
|
@@ -114,6 +123,6 @@ export function loadArea(key) {
|
|
|
114
123
|
* console.log(plan.context?.attribution.en.length);
|
|
115
124
|
* ```
|
|
116
125
|
*/
|
|
117
|
-
export function loadAreasFor(venues) {
|
|
118
|
-
return Promise.all(areaKeysFor(venues).map(loadArea));
|
|
126
|
+
export function loadAreasFor(venues, circuit) {
|
|
127
|
+
return Promise.all(areaKeysFor(venues, circuit).map(loadArea));
|
|
119
128
|
}
|
package/dist/catalogue.data.js
CHANGED
|
@@ -3,7 +3,7 @@ export const CATALOGUE_DATA = {
|
|
|
3
3
|
"generatedAt": "2026-11-03",
|
|
4
4
|
"package": {
|
|
5
5
|
"name": "@johnmorrisdotca/kyogijo-stadiums",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.58.0"
|
|
7
7
|
},
|
|
8
8
|
"address": "https://johnmorrisdotca.github.io/kyogijo-stadiums/catalogue.json",
|
|
9
9
|
"site": "https://johnmorrisdotca.github.io/kyogijo-stadiums/",
|
package/dist/circuits-entry.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { CIRCUITS, CIRCUIT_ATTRIBUTION, CIRCUIT_IDS, circuitById, circuitPlan }
|
|
|
3
3
|
export type { CircuitPlan, PlanTurn } from "./circuits.ts";
|
|
4
4
|
export { circuitDrawing, circuitTable, circuitText, drawCircuit } from "./circuits.draw.ts";
|
|
5
5
|
export type { CircuitDrawing } from "./circuits.draw.ts";
|
|
6
|
-
export { CIRCUIT_MARKER, CIRCUIT_PLANES_MAX, CIRCUIT_PRESETS, buildCircuitTurn, circuitTurnMarkup, mountCircuitTurn } from "./circuits.turn.ts";
|
|
6
|
+
export { CIRCUIT_MARKER, CIRCUIT_PLANES_MAX, CIRCUIT_PRESETS, buildCircuitTurn, circuitTurnMarkup, circuitUprights, mountCircuitTurn } from "./circuits.turn.ts";
|
|
7
7
|
export { KYOGIJO_CIRCUIT_STYLE } from "./circuits.style.ts";
|
|
8
8
|
export { CIRCUIT_WORDS } from "./circuits.words.ts";
|
|
9
9
|
export type { CircuitWords } from "./circuits.words.ts";
|
package/dist/circuits-entry.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import "./strings.js";
|
|
4
4
|
export { CIRCUITS, CIRCUIT_ATTRIBUTION, CIRCUIT_IDS, circuitById, circuitPlan } from "./circuits.js";
|
|
5
5
|
export { circuitDrawing, circuitTable, circuitText, drawCircuit } from "./circuits.draw.js";
|
|
6
|
-
export { CIRCUIT_MARKER, CIRCUIT_PLANES_MAX, CIRCUIT_PRESETS, buildCircuitTurn, circuitTurnMarkup, mountCircuitTurn } from "./circuits.turn.js";
|
|
6
|
+
export { CIRCUIT_MARKER, CIRCUIT_PLANES_MAX, CIRCUIT_PRESETS, buildCircuitTurn, circuitTurnMarkup, circuitUprights, mountCircuitTurn } from "./circuits.turn.js";
|
|
7
7
|
export { KYOGIJO_CIRCUIT_STYLE } from "./circuits.style.js";
|
|
8
8
|
export { CIRCUIT_WORDS } from "./circuits.words.js";
|
|
9
9
|
export { lineLength } from "./circuits.geo.js";
|
package/dist/circuits.draw.js
CHANGED
|
@@ -164,7 +164,8 @@ export function circuitDrawing(options) {
|
|
|
164
164
|
const { title, description } = circuitText(plan, language);
|
|
165
165
|
const r = 13 * k;
|
|
166
166
|
const placed = badgesOf(plan, r, k);
|
|
167
|
-
|
|
167
|
+
const framed = options.frame !== false;
|
|
168
|
+
let body = framed ? el("rect", { class: "ky-ci-ground", x: viewBox.x, y: viewBox.y, width: viewBox.w, height: viewBox.h }) : "";
|
|
168
169
|
body += el("path", { class: "ky-ci-area", d: path(plan.area, true), "stroke-width": num(1.2 * k) });
|
|
169
170
|
if (plan.building !== undefined)
|
|
170
171
|
body += el("path", { class: "ky-ci-building", d: path(plan.building.ring, true), "stroke-width": num(1.2 * k), "data-height": num(plan.building.height / FT) });
|
|
@@ -200,9 +201,11 @@ export function circuitDrawing(options) {
|
|
|
200
201
|
body += el("text", { class: "ky-ci-name", x: viewBox.x + pad * 0.6, y: viewBox.y + 36 * k, "font-size": num(26 * k) }, esc(circuit.names[language]));
|
|
201
202
|
body += el("text", { class: "ky-ci-facts", x: viewBox.x + pad * 0.6, y: viewBox.y + 60 * k, "font-size": num(16 * k) }, esc(fill(words.facts, { km: km(circuit.length.value, language), turns: circuit.corners.value })));
|
|
202
203
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
204
|
+
if (framed) {
|
|
205
|
+
body += northArrow([viewBox.x + viewBox.w - pad * 0.6 - 20 * k, viewBox.y + (label ? 44 * k : pad)], plan.north, 40 * k, words.northArrow);
|
|
206
|
+
body += scaleBar([viewBox.x + pad * 0.6, viewBox.y + viewBox.h - 14 * k], viewBox.w, k, words.metres);
|
|
207
|
+
body += el("text", { class: "ky-ci-credit", x: viewBox.x + viewBox.w - pad * 0.6, y: viewBox.y + viewBox.h - 14 * k, "font-size": num(11 * k), "text-anchor": "end" }, esc(CIRCUIT_ATTRIBUTION));
|
|
208
|
+
}
|
|
206
209
|
const titleId = `${gid}-t`;
|
|
207
210
|
const descId = `${gid}-d`;
|
|
208
211
|
const css = options.css === "none" ? "" : `<style>${KYOGIJO_CIRCUIT_STYLE}</style>`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Every circuit, and the race on one, held for a district (`district.circuit.ts`): importing this fills the table a district reads a circuit from. The `district` entry imports it; the lean district reads it with `loadCircuits()`. A bundler keeps it for its
|
|
2
|
+
// effect: package.json lists it in `sideEffects`.
|
|
3
|
+
import { circuitDrawing } from "./circuits.draw.js";
|
|
4
|
+
import { carRadius, carsMarkup } from "./circuits.race.draw.js";
|
|
5
|
+
import { mountRaceIn } from "./circuits.race.dom.js";
|
|
6
|
+
import { raceAt } from "./circuits.race.moment.js";
|
|
7
|
+
import { simulateRace } from "./circuits.race.js";
|
|
8
|
+
import { RACE_WORDS } from "./circuits.race.words.js";
|
|
9
|
+
import { circuitOf, circuitPlan } from "./circuits.js";
|
|
10
|
+
import { circuitUprights } from "./circuits.turn.js";
|
|
11
|
+
import { CIRCUIT_WORDS } from "./circuits.words.js";
|
|
12
|
+
import { holdCircuits } from "./district.circuit.js";
|
|
13
|
+
holdCircuits({ circuitOf, circuitPlan, circuitDrawing, circuitUprights, words: CIRCUIT_WORDS, race: { simulateRace, raceAt, carsMarkup, carRadius, mountRaceIn, words: RACE_WORDS } });
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Every circuit's key and its names in English and Japanese (Wikidata's labels), in the order of `CIRCUITS`. */
|
|
2
|
+
export declare const CIRCUIT_INDEX: Readonly<Record<string, {
|
|
3
|
+
en: string;
|
|
4
|
+
ja: string;
|
|
5
|
+
}>>;
|
|
6
|
+
/**
|
|
7
|
+
* Read the circuits for the lean district (`district-lean`), which carries none until it is asked: after this a district's `circuit` option can name any of them. The `district` entry has them already. Asking again gives the same promise.
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts no-run
|
|
10
|
+
* import { loadCircuits, planDistrict } from "@johnmorrisdotca/kyogijo-stadiums/district-lean";
|
|
11
|
+
* await loadCircuits();
|
|
12
|
+
* planDistrict({ venues: [], circuit: "las-vegas" });
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadCircuits(): Promise<void>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// The circuits by key and name, without their data: what a page lists to choose from before it reads any circuit (the district's page lists them beside the venues), and `loadCircuits`, which reads them all for a lean district.
|
|
2
|
+
// A test holds this list to `CIRCUITS`.
|
|
3
|
+
/** Every circuit's key and its names in English and Japanese (Wikidata's labels), in the order of `CIRCUITS`. */
|
|
4
|
+
export const CIRCUIT_INDEX = Object.freeze({
|
|
5
|
+
"las-vegas": { en: "Las Vegas Strip Circuit", ja: "ラスベガス・ストリップ・サーキット" },
|
|
6
|
+
});
|
|
7
|
+
let loading;
|
|
8
|
+
/**
|
|
9
|
+
* Read the circuits for the lean district (`district-lean`), which carries none until it is asked: after this a district's `circuit` option can name any of them. The `district` entry has them already. Asking again gives the same promise.
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts no-run
|
|
12
|
+
* import { loadCircuits, planDistrict } from "@johnmorrisdotca/kyogijo-stadiums/district-lean";
|
|
13
|
+
* await loadCircuits();
|
|
14
|
+
* planDistrict({ venues: [], circuit: "las-vegas" });
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export function loadCircuits() {
|
|
18
|
+
if (loading === undefined) {
|
|
19
|
+
const read = async () => {
|
|
20
|
+
await import("./circuits.held.js");
|
|
21
|
+
};
|
|
22
|
+
loading = read().catch((error) => {
|
|
23
|
+
loading = undefined;
|
|
24
|
+
throw error;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return loading;
|
|
28
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { type RaceMoment } from "./circuits.race.moment.ts";
|
|
2
2
|
import { type CircuitRace, type RaceOptions } from "./circuits.race.ts";
|
|
3
3
|
import type { CircuitOptions } from "./circuits.types.ts";
|
|
4
|
+
import type { Pt } from "./crowd.ts";
|
|
4
5
|
import { type KyogijoTurn } from "./turn.dom.ts";
|
|
5
|
-
import type { TurnSettings } from "./turn.model.ts";
|
|
6
|
+
import type { TurnModel, TurnSettings } from "./turn.model.ts";
|
|
7
|
+
import type { Language } from "./types.ts";
|
|
6
8
|
/** The speeds the controls offer: real time, ten times and sixty times (a minute of the race a second). */
|
|
7
9
|
export declare const RACE_SPEEDS: readonly number[];
|
|
8
10
|
/** What a race's view is drawn from: the circuit's options and the race's. */
|
|
@@ -37,12 +39,26 @@ export interface RaceState {
|
|
|
37
39
|
speed: number;
|
|
38
40
|
motion: "smooth" | "step";
|
|
39
41
|
}
|
|
40
|
-
/**
|
|
41
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Where a race is drawn: the circuit's own drawing and 3D view (`mountCircuitRace`), or another scene the circuit lies in, a district's ground among its venues (`mountDistrictRace`). The cars are placed in the circuit's own plan
|
|
44
|
+
* (`raceAt`); `point` says where such a point is in the scene.
|
|
45
|
+
*/
|
|
46
|
+
export interface RaceScene<O, V> {
|
|
47
|
+
/** The scene's flat drawing at a moment, its cars as the `.ky-ci-car` groups of `carMarkup`: the race given when it came from a feed, else the simulation the options make. */
|
|
48
|
+
flat(options: O, t: number, given: CircuitRace | undefined): string;
|
|
49
|
+
/** The options the 3D view is mounted and updated with. */
|
|
50
|
+
view(options: O): V;
|
|
51
|
+
/** The 3D view's model. */
|
|
52
|
+
build(options: V, settings: TurnSettings): TurnModel;
|
|
53
|
+
/** Where a point of the circuit's plan lies in the scene: the same point for the circuit's own drawing. */
|
|
54
|
+
point(options: O): (p: Pt) => Pt;
|
|
55
|
+
}
|
|
56
|
+
/** What `mountCircuitRace` gives back (and `mountDistrictRace`, with a district's options and 3D view). */
|
|
57
|
+
export interface KyogijoRace<O = RaceViewOptions, V = CircuitOptions> {
|
|
42
58
|
/** The race it plays. */
|
|
43
59
|
readonly race: CircuitRace;
|
|
44
60
|
/** The 3D view, when the race is on one. */
|
|
45
|
-
readonly turn: KyogijoTurn<
|
|
61
|
+
readonly turn: KyogijoTurn<V> | undefined;
|
|
46
62
|
state(): RaceState;
|
|
47
63
|
/** The race at the clock's time: the standings, the lap, the fastest lap. */
|
|
48
64
|
moment(): RaceMoment;
|
|
@@ -55,7 +71,7 @@ export interface KyogijoRace {
|
|
|
55
71
|
nextLap(): void;
|
|
56
72
|
setSpeed(speed: number): void;
|
|
57
73
|
/** Draw again with new options (the language, the theme): the clock and the race stay where they are. A new circuit, seed, laps or cars is a new race: mount it again. */
|
|
58
|
-
update(options:
|
|
74
|
+
update(options: O): void;
|
|
59
75
|
/** Play another race in the same view (a feed that came in again while a race is followed): the clock stays where it is, held to the new race's end, and stays playing or paused. */
|
|
60
76
|
replace(race: CircuitRace): void;
|
|
61
77
|
destroy(): void;
|
|
@@ -71,3 +87,7 @@ export interface KyogijoRace {
|
|
|
71
87
|
* ```
|
|
72
88
|
*/
|
|
73
89
|
export declare function mountCircuitRace(host: HTMLElement, initial: RaceViewOptions, settings?: RaceViewSettings): KyogijoRace;
|
|
90
|
+
/** A race in a page, drawn in a scene: what `mountCircuitRace` does on the circuit's own drawing, and `mountDistrictRace` on a district's ground. */
|
|
91
|
+
export declare function mountRaceIn<O extends RaceOptions & {
|
|
92
|
+
language?: Language;
|
|
93
|
+
}, V>(host: HTMLElement, initial: O, scene: RaceScene<O, V>, settings?: RaceViewSettings): KyogijoRace<O, V>;
|
|
@@ -11,6 +11,13 @@ import { fill } from "./strings.core.js";
|
|
|
11
11
|
import { mountTurn } from "./turn.dom.js";
|
|
12
12
|
/** The speeds the controls offer: real time, ten times and sixty times (a minute of the race a second). */
|
|
13
13
|
export const RACE_SPEEDS = Object.freeze([1, 10, 60]);
|
|
14
|
+
/** The circuit's own scene. */
|
|
15
|
+
const CIRCUIT_SCENE = {
|
|
16
|
+
flat: (options, t, given) => raceDrawing({ ...options, t }, given).svg,
|
|
17
|
+
view: (options) => options,
|
|
18
|
+
build: buildCircuitTurn,
|
|
19
|
+
point: () => (p) => p,
|
|
20
|
+
};
|
|
14
21
|
const ICONS = { play: "M8 5v14l11-7z", pause: "M6 5h4v14H6zM14 5h4v14h-4z", next: "M6 5l8.5 7L6 19zM16 5h2v14h-2z" };
|
|
15
22
|
const icon = (d) => `<svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true" focusable="false" fill="currentColor"><path d="${d}"/></svg>`;
|
|
16
23
|
/** The plane of a car standing in a 3D view: a disc that faces the eye, its lower edge on the floor over its place. */
|
|
@@ -26,8 +33,13 @@ const carPlane = (id, x, y, d, svg) => ({ id: `car-${id}`, kind: "player", o: [x
|
|
|
26
33
|
* ```
|
|
27
34
|
*/
|
|
28
35
|
export function mountCircuitRace(host, initial, settings = {}) {
|
|
36
|
+
return mountRaceIn(host, initial, CIRCUIT_SCENE, settings);
|
|
37
|
+
}
|
|
38
|
+
/** A race in a page, drawn in a scene: what `mountCircuitRace` does on the circuit's own drawing, and `mountDistrictRace` on a district's ground. */
|
|
39
|
+
export function mountRaceIn(host, initial, scene, settings = {}) {
|
|
29
40
|
const doc = host.ownerDocument;
|
|
30
41
|
let options = { ...initial };
|
|
42
|
+
let place = scene.point(options);
|
|
31
43
|
let language = options.language === "ja" ? "ja" : "en";
|
|
32
44
|
let race = settings.race ?? simulateRace(options);
|
|
33
45
|
let fromFeed = settings.race !== undefined;
|
|
@@ -101,7 +113,7 @@ export function mountCircuitRace(host, initial, settings = {}) {
|
|
|
101
113
|
}
|
|
102
114
|
};
|
|
103
115
|
const drawFlat = () => {
|
|
104
|
-
stage.innerHTML =
|
|
116
|
+
stage.innerHTML = scene.flat(options, state.t, fromFeed ? race : undefined);
|
|
105
117
|
bindFlat();
|
|
106
118
|
};
|
|
107
119
|
/** The model of the 3D view with a disc for each car at the clock's time. */
|
|
@@ -113,7 +125,8 @@ export function mountCircuitRace(host, initial, settings = {}) {
|
|
|
113
125
|
planes.clear();
|
|
114
126
|
for (const line of [...moment.standings].sort((a, b) => a.index - b.index)) {
|
|
115
127
|
const svg = carMarkup({ ...line, at: [r, r] }, r * 0.9, language).replace(/ role="img"[^>]*?aria-label="[^"]*"/, "");
|
|
116
|
-
|
|
128
|
+
const at = place(line.at);
|
|
129
|
+
planes.set(line.car.id, carPlane(line.car.id, at[0], at[1], disc, svg));
|
|
117
130
|
}
|
|
118
131
|
return { ...model, planes: [...model.planes, ...planes.values()] };
|
|
119
132
|
};
|
|
@@ -130,7 +143,7 @@ export function mountCircuitRace(host, initial, settings = {}) {
|
|
|
130
143
|
if (settings.view === "3d") {
|
|
131
144
|
const holder = doc.createElement("div");
|
|
132
145
|
stage.replaceChildren(holder);
|
|
133
|
-
turn = mountTurn(holder, options, settings.turn ?? {},
|
|
146
|
+
turn = mountTurn(holder, scene.view(options), settings.turn ?? {}, scene.build, false, (lent) => {
|
|
134
147
|
inner = lent;
|
|
135
148
|
});
|
|
136
149
|
if (inner !== undefined) {
|
|
@@ -209,15 +222,16 @@ export function mountCircuitRace(host, initial, settings = {}) {
|
|
|
209
222
|
const car = cars.get(line.car.id);
|
|
210
223
|
if (car === undefined)
|
|
211
224
|
continue;
|
|
225
|
+
const p = place(line.at);
|
|
212
226
|
if (inner !== undefined) {
|
|
213
227
|
const plane = planes.get(line.car.id);
|
|
214
|
-
if (plane !== undefined && (plane.o[0] !==
|
|
215
|
-
plane.o = [
|
|
228
|
+
if (plane !== undefined && (plane.o[0] !== p[0] - disc / 2 || plane.o[1] !== p[1])) {
|
|
229
|
+
plane.o = [p[0] - disc / 2, p[1], disc];
|
|
216
230
|
moved = true;
|
|
217
231
|
}
|
|
218
232
|
}
|
|
219
233
|
else {
|
|
220
|
-
const at = `translate(${num(
|
|
234
|
+
const at = `translate(${num(p[0])} ${num(p[1])})`;
|
|
221
235
|
if (car.at !== at) {
|
|
222
236
|
car.at = at;
|
|
223
237
|
car.el?.setAttribute("transform", at);
|
|
@@ -375,8 +389,9 @@ export function mountCircuitRace(host, initial, settings = {}) {
|
|
|
375
389
|
update(next) {
|
|
376
390
|
options = { ...next, circuit: options.circuit, seed: options.seed, laps: options.laps, cars: options.cars };
|
|
377
391
|
language = options.language === "ja" ? "ja" : "en";
|
|
392
|
+
place = scene.point(options);
|
|
378
393
|
if (turn !== undefined)
|
|
379
|
-
turn.update(options);
|
|
394
|
+
turn.update(scene.view(options));
|
|
380
395
|
else
|
|
381
396
|
drawFlat();
|
|
382
397
|
buildBoard();
|
|
@@ -55,5 +55,5 @@ export declare function drawRace(options: RaceDrawOptions): string;
|
|
|
55
55
|
* ```
|
|
56
56
|
*/
|
|
57
57
|
export declare function raceBoard(moment: RaceMoment, language?: Language): string;
|
|
58
|
-
/** The rules of a race: the cars on the drawing, the clock, the controls and the board. Scoped to `.ky-race` and the
|
|
58
|
+
/** The rules of a race: the cars on the drawing, the clock, the controls and the board. Scoped to `.ky-race` and the cars of a circuit's or a district's drawing, in the page's own colours. */
|
|
59
59
|
export declare const RACE_STYLE: string;
|
|
@@ -123,11 +123,11 @@ export function raceBoard(moment, language = "en") {
|
|
|
123
123
|
});
|
|
124
124
|
return `<table class="ky-race-board"><caption>${esc(w.caption)}</caption>${head}<tbody>${rows.join("")}</tbody></table>`;
|
|
125
125
|
}
|
|
126
|
-
/** The rules of a race: the cars on the drawing, the clock, the controls and the board. Scoped to `.ky-race` and the
|
|
126
|
+
/** The rules of a race: the cars on the drawing, the clock, the controls and the board. Scoped to `.ky-race` and the cars of a circuit's or a district's drawing, in the page's own colours. */
|
|
127
127
|
export const RACE_STYLE = `
|
|
128
|
-
.ky-circuit .ky-ci-car-dot,.ky-turn .ky-ci-car-dot{stroke:var(--ky-ci-ground,#fff)}
|
|
129
|
-
.ky-circuit .ky-ci-car-n,.ky-turn .ky-ci-car-n{font-family:var(--ky-font,system-ui,sans-serif);font-weight:800;text-anchor:middle;font-variant-numeric:tabular-nums}
|
|
130
|
-
.ky-circuit .ky-ci-car[data-status=out]{opacity:.45}
|
|
128
|
+
.ky-circuit .ky-ci-car-dot,.ky-district .ky-ci-car-dot,.ky-turn .ky-ci-car-dot{stroke:var(--ky-ci-ground,#fff)}
|
|
129
|
+
.ky-circuit .ky-ci-car-n,.ky-district .ky-ci-car-n,.ky-turn .ky-ci-car-n{font-family:var(--ky-font,system-ui,sans-serif);font-weight:800;text-anchor:middle;font-variant-numeric:tabular-nums}
|
|
130
|
+
.ky-circuit .ky-ci-car[data-status=out],.ky-district .ky-ci-car[data-status=out]{opacity:.45}
|
|
131
131
|
.ky-race{display:block;color:inherit}
|
|
132
132
|
.ky-race .ky-race-bar{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;margin-top:.5rem}
|
|
133
133
|
.ky-race .ky-race-bar button{box-sizing:border-box;min-width:44px;min-height:44px;margin:0;padding:0 .7rem;border:1px solid currentColor;border-radius:8px;background:transparent;color:inherit;font:inherit;font-weight:700;cursor:pointer}
|
package/dist/circuits.turn.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { type CircuitDrawing } from "./circuits.draw.ts";
|
|
1
2
|
import type { CircuitOptions } from "./circuits.types.ts";
|
|
2
3
|
import { type PresetTable } from "./turn.camera.ts";
|
|
3
4
|
import { type KyogijoTurn } from "./turn.dom.ts";
|
|
5
|
+
import { type Upright } from "./turn.kit.ts";
|
|
4
6
|
import { type TurnModel, type TurnSettings } from "./turn.model.ts";
|
|
5
7
|
/**
|
|
6
8
|
* The four viewpoints of a circuit: straight down, the main camera high over the long side of the lap, the end-on view along it and the low corner. A lap is kilometres across and flat, so the eye is kept higher than
|
|
@@ -14,6 +16,12 @@ export declare const CIRCUIT_MARKER: Readonly<{
|
|
|
14
16
|
}>;
|
|
15
17
|
/** The most planes a circuit's 3D view may have: its markers (three planes each), its pit building and nothing else. A test holds every circuit to it. */
|
|
16
18
|
export declare const CIRCUIT_PLANES_MAX = 120;
|
|
19
|
+
/**
|
|
20
|
+
* What stands up on a circuit's floor, in its plan's frame (feet): the pit building at its mapped height and each turn's number on a post over its badge's place beside the bend, the marker turned to face the eye and leaning
|
|
21
|
+
* back to be read square on. `drawn` is the circuit's drawing (its badges are where the markers stand) and `thin` the width of a post. The 3D view of the circuit stands these, and a district with the circuit stands them where
|
|
22
|
+
* it puts the circuit.
|
|
23
|
+
*/
|
|
24
|
+
export declare function circuitUprights(drawn: CircuitDrawing, thin: number): Upright[];
|
|
17
25
|
/**
|
|
18
26
|
* A circuit as a 3D model: its drawing as the floor, the pit building standing on it at its mapped height, and a marker with each turn's number on a post over its bend. `settings.uprights: false` is the floor alone.
|
|
19
27
|
* A `TurnModel` like any other: `turnMarkupOf` and `mountCircuitTurn` make a view of it.
|
package/dist/circuits.turn.js
CHANGED
|
@@ -23,6 +23,34 @@ export const CIRCUIT_PRESETS = { overhead: TURN_PRESETS.overhead, broadcast: { y
|
|
|
23
23
|
export const CIRCUIT_MARKER = Object.freeze({ size: 30, post: 22 });
|
|
24
24
|
/** The most planes a circuit's 3D view may have: its markers (three planes each), its pit building and nothing else. A test holds every circuit to it. */
|
|
25
25
|
export const CIRCUIT_PLANES_MAX = 120;
|
|
26
|
+
/**
|
|
27
|
+
* What stands up on a circuit's floor, in its plan's frame (feet): the pit building at its mapped height and each turn's number on a post over its badge's place beside the bend, the marker turned to face the eye and leaning
|
|
28
|
+
* back to be read square on. `drawn` is the circuit's drawing (its badges are where the markers stand) and `thin` the width of a post. The 3D view of the circuit stands these, and a district with the circuit stands them where
|
|
29
|
+
* it puts the circuit.
|
|
30
|
+
*/
|
|
31
|
+
export function circuitUprights(drawn, thin) {
|
|
32
|
+
const plan = drawn.plan;
|
|
33
|
+
const k = drawn.k;
|
|
34
|
+
const items = [];
|
|
35
|
+
if (plan.building !== undefined) {
|
|
36
|
+
const planes = blockPlanes(shellBlock("pit", plan.building.ring, plan.building.height, undefined), "pit-");
|
|
37
|
+
const [cx, cy] = plan.building.ring.reduce((s, p) => [s[0] + p[0] / plan.building.ring.length, s[1] + p[1] / plan.building.ring.length], [0, 0]);
|
|
38
|
+
items.push({ id: "pit-building", kind: "blocks", at: [cx, cy], height: plan.building.height, planes });
|
|
39
|
+
}
|
|
40
|
+
const size = CIRCUIT_MARKER.size * k;
|
|
41
|
+
const top = CIRCUIT_MARKER.post * k;
|
|
42
|
+
const marks = [];
|
|
43
|
+
for (const b of drawn.badges) {
|
|
44
|
+
const [x, y] = b.at;
|
|
45
|
+
const r = size / 2;
|
|
46
|
+
const svg = `<circle class="u-ci-badge" cx="${num(r)}" cy="${num(r)}" r="${num(r * 0.94)}" stroke-width="${num(r * 0.1)}"/><text class="u-ci-badge-n" x="${num(r)}" y="${num(r + r * 0.4)}" font-size="${num(r * (b.n >= 10 ? 1.05 : 1.25))}">${b.n}</text>`;
|
|
47
|
+
marks.push({ ...plane(`turn-${b.n}`, "sign", [x - r, y, top + size], [size, 0, 0], [0, 0, -size], svg), billboard: true, lean: true });
|
|
48
|
+
marks.push(...pole(`turn-${b.n}-post`, "pole", x, y, 0, top, thin, "u-pole"));
|
|
49
|
+
}
|
|
50
|
+
if (marks.length > 0)
|
|
51
|
+
items.push({ id: "turns", kind: "flags", at: [(plan.box.x0 + plan.box.x1) / 2, (plan.box.y0 + plan.box.y1) / 2], height: top + size, planes: marks });
|
|
52
|
+
return items;
|
|
53
|
+
}
|
|
26
54
|
/**
|
|
27
55
|
* A circuit as a 3D model: its drawing as the floor, the pit building standing on it at its mapped height, and a marker with each turn's number on a post over its bend. `settings.uprights: false` is the floor alone.
|
|
28
56
|
* A `TurnModel` like any other: `turnMarkupOf` and `mountCircuitTurn` make a view of it.
|
|
@@ -37,27 +65,7 @@ export function buildCircuitTurn(options, settings = {}) {
|
|
|
37
65
|
const drawn = circuitDrawing({ ...options, id: `${id}-floor`, label: false, turns: !standUp });
|
|
38
66
|
const plan = drawn.plan;
|
|
39
67
|
const { x: vx, y: vy, w: vw, h: vh } = drawn.viewBox;
|
|
40
|
-
const
|
|
41
|
-
const items = [];
|
|
42
|
-
if (standUp && plan.building !== undefined) {
|
|
43
|
-
const planes = blockPlanes(shellBlock("pit", plan.building.ring, plan.building.height, undefined), "pit-");
|
|
44
|
-
const [cx, cy] = plan.building.ring.reduce((s, p) => [s[0] + p[0] / plan.building.ring.length, s[1] + p[1] / plan.building.ring.length], [0, 0]);
|
|
45
|
-
items.push({ id: "pit-building", kind: "blocks", at: [cx, cy], height: plan.building.height, planes });
|
|
46
|
-
}
|
|
47
|
-
if (standUp) {
|
|
48
|
-
// Each turn's number on a post, over the badge's place beside the bend; the marker turns to face the eye and leans back to be read square on, and lies flat seen from above.
|
|
49
|
-
const size = CIRCUIT_MARKER.size * k;
|
|
50
|
-
const top = CIRCUIT_MARKER.post * k;
|
|
51
|
-
const marks = [];
|
|
52
|
-
for (const b of drawn.badges) {
|
|
53
|
-
const [x, y] = b.at;
|
|
54
|
-
const r = size / 2;
|
|
55
|
-
const svg = `<circle class="u-ci-badge" cx="${num(r)}" cy="${num(r)}" r="${num(r * 0.94)}" stroke-width="${num(r * 0.1)}"/><text class="u-ci-badge-n" x="${num(r)}" y="${num(r + r * 0.4)}" font-size="${num(r * (b.n >= 10 ? 1.05 : 1.25))}">${b.n}</text>`;
|
|
56
|
-
marks.push({ ...plane(`turn-${b.n}`, "sign", [x - r, y, top + size], [size, 0, 0], [0, 0, -size], svg), billboard: true, lean: true });
|
|
57
|
-
marks.push(...pole(`turn-${b.n}-post`, "pole", x, y, 0, top, thinnest(vw, vh), "u-pole"));
|
|
58
|
-
}
|
|
59
|
-
items.push({ id: "turns", kind: "flags", at: [(plan.box.x0 + plan.box.x1) / 2, (plan.box.y0 + plan.box.y1) / 2], height: top + size, planes: marks });
|
|
60
|
-
}
|
|
68
|
+
const items = standUp ? circuitUprights(drawn, thinnest(vw, vh)) : [];
|
|
61
69
|
const area = plan.box;
|
|
62
70
|
const uprights = { items, lift: 0, thin: thinnest(vw, vh), area };
|
|
63
71
|
const planes = planesOf(uprights);
|
package/dist/circuits.types.d.ts
CHANGED
|
@@ -112,6 +112,8 @@ export interface CircuitOptions {
|
|
|
112
112
|
turns?: boolean;
|
|
113
113
|
/** The arrows that show which way the lap runs: `true` (the default) or `false`. */
|
|
114
114
|
arrows?: boolean;
|
|
115
|
+
/** `false` leaves out the drawing's frame (its ground, the north arrow, the scale bar and the credit): for a drawing laid inside another that has its own (a district). `true` when missing. */
|
|
116
|
+
frame?: boolean;
|
|
115
117
|
/** The prefix of the ids inside the drawing, for a page with more than one; a hash of the options when missing. */
|
|
116
118
|
id?: string;
|
|
117
119
|
/** More classes on the root. */
|
package/dist/circuits.words.d.ts
CHANGED
|
@@ -18,6 +18,10 @@ export interface CircuitWords {
|
|
|
18
18
|
standingNoBuilding: string;
|
|
19
19
|
/** The credit of the data. */
|
|
20
20
|
credit: string;
|
|
21
|
+
/** A circuit in a district: its sentence beside the venues', the description of a district of the circuit alone, and its title. */
|
|
22
|
+
inDistrict: string;
|
|
23
|
+
districtAlone: string;
|
|
24
|
+
districtTitle: string;
|
|
21
25
|
/** A turn's number, for a screen reader. */
|
|
22
26
|
turn: string;
|
|
23
27
|
/** The scale bar's unit. */
|
package/dist/circuits.words.js
CHANGED
|
@@ -12,6 +12,9 @@ export const CIRCUIT_WORDS = Object.freeze({
|
|
|
12
12
|
standing: "In 3D the pit building stands {height} m high, and each turn's number stands on a post.",
|
|
13
13
|
standingNoBuilding: "In 3D each turn's number stands on a post.",
|
|
14
14
|
credit: "Map data: {credit}.",
|
|
15
|
+
inDistrict: "{name}, a lap of {km} km, lies on the same ground where OpenStreetMap maps it.",
|
|
16
|
+
districtAlone: "A plan of {name}, a lap of {km} km, where OpenStreetMap maps it, among what lies round it.",
|
|
17
|
+
districtTitle: "{name} and its surroundings",
|
|
15
18
|
turn: "Turn {n}",
|
|
16
19
|
metres: "m",
|
|
17
20
|
northArrow: "North",
|
|
@@ -30,6 +33,9 @@ export const CIRCUIT_WORDS = Object.freeze({
|
|
|
30
33
|
standing: "3D表示では、ピットビルは高さ{height} mで建ち、各コーナーの番号はポールの上に掲げられます。",
|
|
31
34
|
standingNoBuilding: "3D表示では、各コーナーの番号はポールの上に掲げられます。",
|
|
32
35
|
credit: "地図データ:{credit}。",
|
|
36
|
+
inDistrict: "1周{km} kmの{name}も、OpenStreetMapに登録された位置のとおり同じ地面に描いています。",
|
|
37
|
+
districtAlone: "1周{km} kmの{name}を、OpenStreetMapに登録された位置のとおり、周辺の様子とあわせて描いた平面図です。",
|
|
38
|
+
districtTitle: "{name}とその周辺",
|
|
33
39
|
turn: "ターン{n}",
|
|
34
40
|
metres: "m",
|
|
35
41
|
northArrow: "北",
|
package/dist/cityctx-entry.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import "./strings.ts";
|
|
2
|
-
export { CITYCTX_AREAS, SEATTLE_CENTER, SEATTLE_CITY, SEATTLE_SODO, VANCOUVER_NATURE } from "./cityctx.data.ts";
|
|
2
|
+
export { CITYCTX_AREAS, LAS_VEGAS, SEATTLE_CENTER, SEATTLE_CITY, SEATTLE_SODO, VANCOUVER_NATURE } from "./cityctx.data.ts";
|
|
3
3
|
export { CITYCTX_VENUES, contextFor } from "./cityctx.ts";
|
|
4
4
|
export type { ContextArea } from "./context.ts";
|
package/dist/cityctx-entry.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// The surroundings of the venues of Vancouver and Seattle (streets, buildings, water, green, trees), as data a district takes in its `context` option, from OpenStreetMap (ODbL 1.0) and the Cities' open data, with their credits; `contextFor` says which go with some venues.
|
|
2
2
|
// The words in both languages, as this entry has always carried them (the lean district reads one language when it is asked to).
|
|
3
3
|
import "./strings.js";
|
|
4
|
-
export { CITYCTX_AREAS, SEATTLE_CENTER, SEATTLE_CITY, SEATTLE_SODO, VANCOUVER_NATURE } from "./cityctx.data.js";
|
|
4
|
+
export { CITYCTX_AREAS, LAS_VEGAS, SEATTLE_CENTER, SEATTLE_CITY, SEATTLE_SODO, VANCOUVER_NATURE } from "./cityctx.data.js";
|
|
5
5
|
export { CITYCTX_VENUES, contextFor } from "./cityctx.js";
|