@johnmorrisdotca/kyogijo-stadiums 0.11.0 → 0.12.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 CHANGED
@@ -7,6 +7,17 @@ All notable changes to this project are written here. The format follows
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.12.0] - 2026-10-19
11
+
12
+ ### Added
13
+
14
+ - **Tournament layouts** (`@johnmorrisdotca/kyogijo-stadiums/multi`): `drawMulti` lays several of the package's own surfaces out together for one large event, to scale, on one floor, as one SVG, with the barriers, the officials' chairs, a scoreboard hung over the middle, the boards along the edges and empty places for the event's own words and marks (on the mats themselves for judo and karate, as those sports print them). Thirteen presets, each with its rule and sources, from table tennis (four and eight areas), pickleball (2 x 2, 2 x 4, 4 x 4), curling (four sheets), judo (three and four areas), karate (six and eight), badminton (the least spacing, and the 4 m the BWF recommends at Grade 1 and 2) and tennis; each says whether it is a rulebook's spacing or an arrangement an event used. `multiLayout` gives the floor a layout needs, `multiFit` whether it fits a hall (a rectangle, an octagon, or a floor of which only the area is known) with five halls and ice pads whose floors are published, and `venue` and `stadium` set the layout in a hall with a real stadium round it at the same scale, reusing the package's stands and crowd. `multiTable` is the text alternative; light and dark, English and Japanese. A demo page, `halls.html`, picks a preset, sets it in a hall and switches the stadium on and off (linked from the demo's gallery section), and the docs gallery has a page for every preset. See [Tournament layouts](./docs/multi.md).
15
+ - **Two more parks place a dugout or a bullpen, where their articles do:** `wrigley-field`'s home dugout (third base line) and `griffith-stadium`'s left-field bullpen (388 feet, 1956 to 1961). No generic dugout or bullpen is drawn for the others; `docs/ballparks.md` and `docs/references.md` list what was read and left out and why.
16
+
17
+ ### Changed
18
+
19
+ - **Docs only:** `docs/situation.md` says plainly what is left undrawn for want of a source (the NHL's older creases, an Olympic hybrid sheet, Buffalo Memorial Auditorium's rink) and what would be needed; `docs/team-shape.md` says the lineup's `jersey` is a flat marker of our own and where full jerseys are drawn.
20
+
10
21
  ## [0.11.0] - 2026-10-19
11
22
 
12
23
  ### Added
package/README.md CHANGED
@@ -129,6 +129,7 @@ console.log(svg.startsWith("<svg"), svg.includes("USA 3, Canada 2"));
129
129
  | `./parks`, `./grounds`, `./arenas`, `./atlas`, `./eras`, `./leagues`, `./events` | The ballparks, the grounds, the arenas, every place, the markings of a season, each league's rulebook, the special games. |
130
130
  | `./turn` | A surface as a 3D view that turns, with the net, basket, goal or posts standing on it. |
131
131
  | `./scene`, `./canvas`, `./d3`, `./plot`, `./geojson`, `./png` | The drawing as data; on a canvas; in a d3 selection; as an Observable Plot mark; as GeoJSON; as a PNG (the optional peer `@resvg/resvg-js`). |
132
+ | `./multi` | `drawMulti`, `multiFit`: several surfaces laid out for one event, in a hall ([docs](./docs/multi.md), [demo](https://johnmorrisdotca.github.io/kyogijo-stadiums/halls.html)). |
132
133
  | `./layouts` | `drawGrid` and `GRID_PRESETS`: small multiples with a title, a subtitle, a key and a credit line; the grounds behind a drawing or a grid. |
133
134
  | `./mount`, `./react`, `./element`, `./element/define` | Draw into a container; React props; the `<kyogijo-field>` element and its registration. |
134
135
 
@@ -0,0 +1,7 @@
1
+ export { drawMulti, multiSetting, multiTable } from "./multi.draw.ts";
2
+ export { MULTI_MAX, fitSentence, multiFit, multiLayout, needsSentence, specOf, venueOf } from "./multi.ts";
3
+ export { MULTI_PRESETS, MULTI_PRESET_IDS, MULTI_SOURCES, MULTI_VENUES, multiPreset, multiSource, multiVenueById } from "./multi.data.ts";
4
+ export { KYOGIJO_MULTI_STYLE } from "./multi.style.ts";
5
+ export { MULTI_WORDS } from "./multi.words.ts";
6
+ export type { MultiWords } from "./multi.words.ts";
7
+ export type { MultiBasis, MultiCell, MultiEvent, MultiFit, MultiFloor, MultiLayout, MultiNeeds, MultiOptions, MultiParts, MultiSize, MultiSlot, MultiSpec, MultiSurface, MultiUnit, MultiVenue, MultiWord } from "./multi.types.ts";
@@ -0,0 +1,8 @@
1
+ // Tournament layouts: several of the package's surfaces laid out together for one large event, to scale, on one floor (tables, courts, sheets, a judo floor's contest areas in a row), with the barriers, the
2
+ // officials' chairs, a scoreboard hung over the middle, the boards and the empty places for the event's own words and marks; the real configurations of events as presets, each with its rule; the halls whose
3
+ // floors are published, and whether a layout fits one; and a real stadium round the floor at the same scale. `multiTable` is the text alternative.
4
+ export { drawMulti, multiSetting, multiTable } from "./multi.draw.js";
5
+ export { MULTI_MAX, fitSentence, multiFit, multiLayout, needsSentence, specOf, venueOf } from "./multi.js";
6
+ export { MULTI_PRESETS, MULTI_PRESET_IDS, MULTI_SOURCES, MULTI_VENUES, multiPreset, multiSource, multiVenueById } from "./multi.data.js";
7
+ export { KYOGIJO_MULTI_STYLE } from "./multi.style.js";
8
+ export { MULTI_WORDS } from "./multi.words.js";
@@ -0,0 +1,42 @@
1
+ import type { MultiFit, MultiLayout, MultiNeeds, MultiOptions, MultiSpec, MultiVenue } from "./multi.types.ts";
2
+ import type { Language } from "./types.ts";
3
+ /** The most rows or columns a layout takes. */
4
+ export declare const MULTI_MAX = 12;
5
+ /** A number as a language writes it: thousands separated, two decimals at most (`3,234.5`). */
6
+ export declare const multiNumber: (value: number, language?: Language) => string;
7
+ /**
8
+ * The layout the options ask for: a preset or a layout of the caller's own, with the grid and the stagger it is given in place of its own.
9
+ * @throws Error for a preset that is not one, an option that is not a whole number or a share, or neither a preset nor a layout.
10
+ */
11
+ export declare function specOf(o: Pick<MultiOptions, "preset" | "layout" | "rows" | "columns" | "stagger">): MultiSpec;
12
+ /**
13
+ * A layout laid out: where each surface stands, the floor it needs and the empty places for the event's own words and marks, all in feet from the top left corner of the floor (and the floor's size
14
+ * and what the layout needs in metres).
15
+ * @example
16
+ * ```ts
17
+ * import { multiLayout } from "@johnmorrisdotca/kyogijo-stadiums/multi";
18
+ * const layout = multiLayout({ preset: "tabletennis-4" });
19
+ * console.log(layout.cells.length, layout.needs.length, layout.needs.width);
20
+ * // 4 28 14
21
+ * ```
22
+ */
23
+ export declare function multiLayout(options?: Pick<MultiOptions, "preset" | "layout" | "rows" | "columns" | "stagger" | "language">): MultiLayout;
24
+ /** A hall as the caller gives it, or a key of `MULTI_VENUES`. @throws Error for a key that is not one, a size that is not positive. */
25
+ export declare function venueOf(venue: MultiOptions["venue"]): MultiVenue | undefined;
26
+ /**
27
+ * Whether a layout fits a hall's floor. A floor that is a rectangle takes the layout as it is or turned a quarter; an octagon takes it if its corners are inside; a floor of which only the area is published
28
+ * can only be compared by area, and says so (`fits` is `null` when the area is enough, because the shape may still not take it).
29
+ * @example
30
+ * ```ts
31
+ * import { multiFit, multiLayout } from "@johnmorrisdotca/kyogijo-stadiums/multi";
32
+ * const four = multiFit(multiLayout({ preset: "curling-1x4" }), "nhl-ice-pad");
33
+ * const six = multiFit(multiLayout({ preset: "curling-1x4", columns: 6 }), "nhl-ice-pad");
34
+ * console.log(four.fits, four.turned, six.fits);
35
+ * // true true false
36
+ * ```
37
+ */
38
+ export declare function multiFit(layout: MultiLayout, venue: MultiOptions["venue"]): MultiFit;
39
+ /** The sentence that says how a layout sits in a hall, in a language. */
40
+ export declare function fitSentence(fit: MultiFit, language?: Language): string;
41
+ /** The size of a layout as words, in a language: `28 by 14 metres (392 square metres)`; along the layout first, then across it. */
42
+ export declare const needsSentence: (needs: MultiNeeds, language?: Language) => string;
@@ -0,0 +1,22 @@
1
+ import { type LeagueSource } from "./leagues/sources.ts";
2
+ import type { MultiSpec, MultiVenue } from "./multi.types.ts";
3
+ /** The documents a layout's figures were read from, by id, beside the rulebooks of `LEAGUE_SOURCES` (a key of either names a source). */
4
+ export declare const MULTI_SOURCES: Readonly<Record<string, Readonly<LeagueSource>>>;
5
+ /** The source a key names, from `MULTI_SOURCES` or `LEAGUE_SOURCES`. */
6
+ export declare const multiSource: (id: string) => Readonly<LeagueSource> | undefined;
7
+ /**
8
+ * The halls whose floor is published, and the two ice pads an arena lays in winter. A venue with no length and width (only an area) is compared by area. The package does not hold the floors of
9
+ * halls it could not source: a layout for such a hall is set on a floor of the caller's own size.
10
+ */
11
+ export declare const MULTI_VENUES: readonly MultiVenue[];
12
+ /** The hall with a key, or `undefined`. */
13
+ export declare const multiVenueById: (id: string | undefined) => MultiVenue | undefined;
14
+ /**
15
+ * The presets: layouts of real configurations, each with its rule and, where one is named, the event and the hall. `rulebook` means the spacing is what a rulebook or a specification asks for; `event`
16
+ * means an event used the arrangement (read from reports and photographs, with no plan seen). The list is in the order of the sports of this package's own menu.
17
+ */
18
+ export declare const MULTI_PRESETS: readonly MultiSpec[];
19
+ /** The keys of `MULTI_PRESETS`, in order. */
20
+ export declare const MULTI_PRESET_IDS: readonly string[];
21
+ /** The preset with a key, or `undefined`. */
22
+ export declare const multiPreset: (id: string | undefined) => MultiSpec | undefined;
@@ -0,0 +1,499 @@
1
+ // The tournament layouts and the halls they are set in, as data. Every figure is a rulebook's or a federation's specification, or a venue's published floor, and says where in `sources`; docs/sources.md
2
+ // (Tournament layouts) has the rule for each and says plainly what is ours. Nothing here draws.
3
+ import { LEAGUE_SOURCES } from "./leagues/sources.js";
4
+ const READ = "2026-10-19";
5
+ const source = (s) => [s.id, Object.freeze(s)];
6
+ /** The documents a layout's figures were read from, by id, beside the rulebooks of `LEAGUE_SOURCES` (a key of either names a source). */
7
+ export const MULTI_SOURCES = Object.freeze(Object.fromEntries([
8
+ source({
9
+ id: "ittf-handbook",
10
+ title: "The ITTF Handbook 2022, Section 3 Regulations for International Competitions, 3.2.3 Playing Conditions and 3.2.5.5 (advertisements on the floor)",
11
+ by: "International Table Tennis Federation",
12
+ edition: "2022 (v1.0, clean)",
13
+ url: "https://documents.ittf.sport/sites/default/files/public/2022-02/ITTF_HB_2022_clean_v1_0.pdf",
14
+ read: READ,
15
+ note: "the playing space at least 14 m by 7 m by 5 m, the four corners may be covered by surrounds of at most 1.5 m (3.2.3.1); each playing area enclosed by surrounds about 75 cm high, of one dark colour, separating it from its neighbours and from the spectators (3.2.3.3); the umpire's table and chair and the score indicators are part of the area (3.2.3.2); up to 6 advertisements on the floor of the area (3.2.5.5). A later edition (the 2024 Statutes) was seen only in a search summary, which says the space may be of any shape within a rectangle of the same size; the 2022 text is the one drawn.",
16
+ }),
17
+ source({
18
+ id: "bwf-facilities",
19
+ title: "BWF Statutes, Section 5.3.4 Specifications for International Standard Facilities, 2.1.3, 2.1.4 and 2.2.3 (the space round and between courts)",
20
+ by: "Badminton World Federation",
21
+ edition: "in force 14 October 2019, version 1.1",
22
+ url: "https://www.badmintonpanam.org/wp-content/uploads/2023/01/3.3.4-Specs-for-Int_l-Standard-Facilities-14-October-2019-V1.1.pdf",
23
+ read: READ,
24
+ note: "at least 2 m clear behind the baselines and 1.5 m from the side lines, and 1.5 m between any two courts marked out side by side; at Grade 1 and Grade 2 tournaments at least 4 m between courts is recommended, for A-boards and the officials' chairs; competition courts are always laid side by side. The copy read is Badminton Panam's, a continental confederation's; the BWF's own current text was not read.",
25
+ }),
26
+ source({
27
+ id: "ppa-host",
28
+ title: "Host a PPA Tour tournament: what the host provides (a minimum of 16 courts, a championship court that seats at least 250)",
29
+ by: "Professional Pickleball Association",
30
+ edition: "the page as read",
31
+ url: "https://www.ppatour.com/host-a-ppa-tour-tournament/",
32
+ read: READ,
33
+ note: "only the number of courts a host provides, for the tour's Challenger Series stops; the page names no court size, spacing or floor.",
34
+ }),
35
+ source({
36
+ id: "copper-box",
37
+ title: "Copper Box Arena, the sports arena: 60 m by 40 m, up to 2,700 m², divisible into three 40 m by 20 m courts",
38
+ by: "Copper Box Arena (Better, for the Lee Valley Regional Park Authority)",
39
+ edition: "the pages as read",
40
+ url: "https://copperboxarena.org.uk/facilities",
41
+ read: READ,
42
+ note: "the facilities page gives 60 m by 40 m and up to 2,700 m² of flexible space; the sports arena page gives the three courts of 40 m by 20 m (https://copperboxarena.org.uk/facilities/sports-arena).",
43
+ }),
44
+ source({
45
+ id: "ovo-arena",
46
+ title: "OVO Arena Wembley, corporate hire: 2,655 square metres of uninterrupted floor space",
47
+ by: "OVO Arena Wembley",
48
+ edition: "the page as read",
49
+ url: "https://www.ovoarena.co.uk/your-visit/corporate-hire",
50
+ read: READ,
51
+ note: "an area only: the venue's pages give no length and width, so the shape of the floor is not known.",
52
+ }),
53
+ source({
54
+ id: "ittf-london-2026",
55
+ title: "ITTF World Team Table Tennis Championships Finals London 2026: the event page and Wembley Park's listing (Stage 1B at the Copper Box Arena, Stage 1A and the knockout rounds at OVO Arena Wembley, 28 April to 10 May 2026)",
56
+ by: "International Table Tennis Federation; Wembley Park",
57
+ edition: "the pages as read",
58
+ url: "https://www.ittf.com/tournament/3216/WTTTC_Finals_2026",
59
+ read: READ,
60
+ note: "the dates, the two halls and which stage was held in which; also https://wembleypark.com/whats-on/ovo-arena-wembley-ittf-table-tennis-championships-final-2-may-26. The number of playing areas on the floor, the one scoreboard over their middle and the umpires' chairs are read from photographs the owner supplied (not shipped: their licences are not known); no plan of the floor was seen.",
61
+ }),
62
+ source({
63
+ id: "ijf-baku-2018",
64
+ title: "World Judo Championships 2018, Baku: held 20 to 27 September 2018 at the National Gymnastics Arena (Milli Gimnastika Arenası)",
65
+ by: "International Judo Federation; English Wikipedia, 2018 World Judo Championships",
66
+ edition: "the pages as read",
67
+ url: "https://en.wikipedia.org/wiki/2018_World_Judo_Championships",
68
+ read: READ,
69
+ note: "the venue and the dates (also the IJF's own news item, https://www.ijf.org/news/show/baku-bustling-beehive, which names the Milli Gymnastika Arenasi, MGA). Neither gives the number of contest areas; three in a row, in one coloured floor with the event's name and year printed on it, is read from a photograph the owner supplied (not shipped).",
70
+ }),
71
+ source({
72
+ id: "wikipedia-tokyo-gs-2024",
73
+ title: "2024 Judo Grand Slam Tokyo: held 7 and 8 December 2024 at the Tokyo Metropolitan Gymnasium",
74
+ by: "English Wikipedia",
75
+ edition: "the page as read",
76
+ url: "https://en.wikipedia.org/wiki/2024_Judo_Grand_Slam_Tokyo",
77
+ read: READ,
78
+ note: "the venue and the dates only. Three contest areas in a row on one red floor, with 'TOKYO 2024' printed on it, are read from a photograph the owner supplied (not shipped).",
79
+ }),
80
+ source({
81
+ id: "wkf-karate1-branding",
82
+ title: "Karate1 Series A Branding Manual 2026 (six tatami areas, two rows of three, a number sign for each) and the Youth League manual (eight areas, two rows of four), as summarised in this package's research note",
83
+ by: "World Karate Federation",
84
+ edition: "2026",
85
+ url: "https://www.wkf.net/files/pdf/documents/SERIES%20A%20BRANDING%20MANUAL%202026.pdf",
86
+ read: READ,
87
+ note: "the count and the grid are the league's, from the manual as the research note (docs/research/multi-surface-research.md) read it; the manual itself is a file of more than 10 MB that could not be fetched here. The number of areas at the Karate1 Series A in Kuala Lumpur (Nilai, N9 Arena, 3 to 5 October 2025) is not published: the manual's six is the league's rule, not a count of that event.",
88
+ }),
89
+ source({
90
+ id: "swiss-tennis-distances",
91
+ title: "Tennisplätze: erforderliche Distanzen (the distances a tennis court needs: 3.66 m to the side and 6.40 m behind a single court; 7.32 m between adjacent courts)",
92
+ by: "Swiss Tennis, citing the ITF Rules of Tennis and the Swiss planning guide BASPO 530 (page dated 15 September 2025)",
93
+ edition: "2025",
94
+ url: "https://www.swisstennis.ch/media/12802/tennisplaetze_erforderliche_distanzen_f.pdf",
95
+ read: READ,
96
+ note: "a secondary source: a national federation's summary of the ITF's and BASPO's figures, taken from this package's research note; the ITF's own text was not read for the run-offs. It also lists two reduced gaps (5.95 m and 4.58 m) that lose singles or doubles on some courts; only the full 7.32 m is drawn.",
97
+ }),
98
+ source({
99
+ id: "beijing-2022-curling",
100
+ title: "Curling at the 2022 Winter Olympics: held at the Beijing National Aquatics Centre, the Water Cube of 2008 turned into the Ice Cube, its pool converted to four sheets of curling ice",
101
+ by: "English Wikipedia; World Aquatics; CBC Sports",
102
+ edition: "the pages as read",
103
+ url: "https://en.wikipedia.org/wiki/Curling_at_the_2022_Winter_Olympics",
104
+ read: READ,
105
+ note: "Wikipedia names the venue; the four sheets are from news reports (CBC Sports, 'China defeats Switzerland in mixed doubles curling for 1st Beijing 2022 victory', https://www.cbc.ca/lite/story/1.6336290, and World Aquatics, 'From water to ice', https://www.worldaquatics.com/news/2502409/from-water-to-ice-iconic-swimming-venue-transforms-into-olympic-and-paralympic-curling-venue), read through a search summary because the pages could not be fetched. No size of the ice was found.",
106
+ }),
107
+ ]));
108
+ /** The source a key names, from `MULTI_SOURCES` or `LEAGUE_SOURCES`. */
109
+ export const multiSource = (id) => (Object.prototype.hasOwnProperty.call(MULTI_SOURCES, id) ? MULTI_SOURCES[id] : LEAGUE_SOURCES[id]);
110
+ /**
111
+ * The halls whose floor is published, and the two ice pads an arena lays in winter. A venue with no length and width (only an area) is compared by area. The package does not hold the floors of
112
+ * halls it could not source: a layout for such a hall is set on a floor of the caller's own size.
113
+ */
114
+ export const MULTI_VENUES = Object.freeze([
115
+ {
116
+ id: "copper-box-arena",
117
+ name: { en: "Copper Box Arena, sports arena", ja: "コッパー・ボックス・アリーナ(スポーツアリーナ)" },
118
+ city: "London",
119
+ country: "GB",
120
+ shape: "rectangle",
121
+ length: 60,
122
+ width: 40,
123
+ area: 2700,
124
+ unit: "m",
125
+ what: { en: "the arena's floor, 60 m by 40 m, up to 2,700 m² (the venue's own figure; it divides into three courts of 40 m by 20 m)", ja: "アリーナの床。60m×40m、最大2,700m²(施設が公表している数値。40m×20mのコート3面に分割できる)" },
126
+ floor: "wood",
127
+ standsLike: "badminton",
128
+ sources: ["copper-box"],
129
+ },
130
+ {
131
+ id: "ovo-arena-wembley",
132
+ name: { en: "OVO Arena Wembley", ja: "OVOアリーナ・ウェンブリー" },
133
+ city: "London",
134
+ country: "GB",
135
+ shape: "area",
136
+ area: 2655,
137
+ unit: "m",
138
+ what: { en: "2,655 m² of uninterrupted floor space (the venue's own figure; its length and width are not published)", ja: "仕切りのない一続きの床面積2,655m²(施設が公表している数値。縦横の寸法は公表されていない)" },
139
+ floor: "neutral",
140
+ standsLike: "tabletennis",
141
+ sources: ["ovo-arena"],
142
+ },
143
+ {
144
+ id: "nhl-ice-pad",
145
+ name: { en: "An arena's ice laid as an NHL rink", ja: "NHLサイズのリンクとして張った氷" },
146
+ shape: "rectangle",
147
+ length: 200,
148
+ width: 85,
149
+ unit: "ft",
150
+ what: { en: "an NHL rink, 200 by 85 feet, the size of the ice an arena lays for hockey (the corners' radius of 28 feet is not taken off)", ja: "NHLのリンク。200×85フィート。アリーナがホッケー用に張る氷の大きさ(コーナーの丸み、半径28フィート分は差し引いていない)" },
151
+ floor: "ice",
152
+ standsLike: "nhl",
153
+ sources: ["nhl-rules"],
154
+ },
155
+ {
156
+ id: "iihf-ice-pad",
157
+ name: { en: "An arena's ice laid as an IIHF rink", ja: "IIHFサイズのリンクとして張った氷" },
158
+ shape: "rectangle",
159
+ length: 60,
160
+ width: 30,
161
+ unit: "m",
162
+ what: { en: "an IIHF rink at the largest size the rules allow, 60 m by 30 m (the width may be 26 m to 30 m)", ja: "IIHF規則が認めるリンクの最大の大きさ。60m×30m(幅は26〜30m)" },
163
+ floor: "ice",
164
+ standsLike: "nhl",
165
+ sources: ["iihf-2025"],
166
+ },
167
+ {
168
+ id: "nippon-budokan",
169
+ name: { en: "Nippon Budokan, the arena", ja: "日本武道館のアリーナ" },
170
+ city: "Tokyo",
171
+ country: "JP",
172
+ shape: "octagon",
173
+ across: 55,
174
+ area: 2513,
175
+ unit: "m",
176
+ what: { en: "the arena's regular octagon, 55 m across the flats, 2,513 m² (the Budokan's own leaflet)", ja: "アリーナの正八角形。対辺間55m、2,513m²(日本武道館のリーフレットによる)" },
177
+ floor: "neutral",
178
+ standsLike: "judo",
179
+ sources: ["budokan-overview"],
180
+ },
181
+ ]);
182
+ const venue = (id) => MULTI_VENUES.find((v) => v.id === id);
183
+ /** The hall with a key, or `undefined`. */
184
+ export const multiVenueById = (id) => (id === undefined ? undefined : venue(id));
185
+ /** Surrounds, umpires' chairs, a scoreboard hung over the middle, the edge boards and the places for the floor's own words: what a table tennis floor of the Worlds carries. */
186
+ const TT_PARTS = { barriers: true, officials: true, scoreboard: "shared", boards: true, brand: "floor" };
187
+ /**
188
+ * The presets: layouts of real configurations, each with its rule and, where one is named, the event and the hall. `rulebook` means the spacing is what a rulebook or a specification asks for; `event`
189
+ * means an event used the arrangement (read from reports and photographs, with no plan seen). The list is in the order of the sports of this package's own menu.
190
+ */
191
+ export const MULTI_PRESETS = Object.freeze([
192
+ {
193
+ id: "tabletennis-4",
194
+ name: { en: "Table tennis, four areas (2 x 2)", ja: "卓球 4面(2×2)" },
195
+ sport: "tabletennis",
196
+ surface: { sport: "tabletennis" },
197
+ kind: "cells",
198
+ rows: 2,
199
+ columns: 2,
200
+ bay: { length: 14, width: 7, unit: "m" },
201
+ word: "table",
202
+ parts: TT_PARTS,
203
+ floor: "blue",
204
+ basis: "event",
205
+ event: {
206
+ name: "ITTF World Team Table Tennis Championships Finals",
207
+ year: 2026,
208
+ venue: "OVO Arena Wembley",
209
+ city: "London",
210
+ country: "GB",
211
+ ja: { name: "世界卓球選手権団体戦ファイナルズ", venue: "OVOアリーナ・ウェンブリー", city: "ロンドン" },
212
+ floor: "ovo-arena-wembley",
213
+ note: {
214
+ en: "Four playing areas on one blue floor with seats round the perimeter, one scoreboard for all four hung over their middle, barriers and an umpire's chair at each (read from the owner's photographs; no plan was seen). Each area is drawn at the Handbook's least, 14 m by 7 m.",
215
+ ja: "青い床1枚の上に競技エリアが4面あり、周囲に客席があります。4面の中央の真上に共用のスコアボードが1台吊るされ、各エリアにフェンスと審判席があります(提供された写真から読み取りました。図面は見ていません)。各エリアは規則の最小値14m×7mで描いています。",
216
+ },
217
+ sources: ["ittf-london-2026", "ittf-handbook", "ovo-arena"],
218
+ },
219
+ rule: {
220
+ en: "ITTF Handbook 2022, 3.2.3.1: a playing space of at least 14 m by 7 m for each area; 3.2.3.3: surrounds about 75 cm high between neighbouring areas and the spectators.",
221
+ ja: "ITTFハンドブック2022 3.2.3.1:各エリアは14m×7m以上の競技空間。3.2.3.3:隣のエリアや観客との間に高さ約75cmのフェンス。",
222
+ },
223
+ sources: ["ittf-handbook", "ittf-london-2026", "ovo-arena"],
224
+ },
225
+ {
226
+ id: "tabletennis-8",
227
+ name: { en: "Table tennis, eight areas (2 x 4)", ja: "卓球 8面(2×4)" },
228
+ sport: "tabletennis",
229
+ surface: { sport: "tabletennis" },
230
+ kind: "cells",
231
+ rows: 2,
232
+ columns: 4,
233
+ bay: { length: 14, width: 7, unit: "m" },
234
+ word: "table",
235
+ parts: TT_PARTS,
236
+ floor: "blue",
237
+ basis: "rulebook",
238
+ rule: {
239
+ en: "ITTF Handbook 2022, 3.2.3.1 and 3.2.3.3: eight areas of 14 m by 7 m, in two rows. No event's count of areas was sourced for this one; it is the grid the rule allows.",
240
+ ja: "ITTFハンドブック2022 3.2.3.1と3.2.3.3:14m×7mのエリア8面を2行4列に並べます。特定の大会の面数は確認できていません。規則が認める並べ方です。",
241
+ },
242
+ sources: ["ittf-handbook"],
243
+ },
244
+ {
245
+ id: "pickleball-2x2",
246
+ name: { en: "Pickleball, four courts (2 x 2)", ja: "ピックルボール 4面(2×2)" },
247
+ sport: "pickleball",
248
+ surface: { sport: "pickleball" },
249
+ kind: "cells",
250
+ rows: 2,
251
+ columns: 2,
252
+ bay: { length: 64, width: 34, unit: "ft" },
253
+ word: "court",
254
+ parts: { barriers: false, officials: false, scoreboard: "none", boards: true, brand: "floor" },
255
+ floor: "blue",
256
+ basis: "rulebook",
257
+ rule: {
258
+ en: "USA Pickleball Official Rulebook 2026, 3.A.3: a playing surface of 34 by 64 feet is recommended for tournament play, so each court is given that. The rulebook names no spacing between adjoining courts: the surfaces are laid edge to edge. No event's court count was sourced.",
259
+ ja: "USAピックルボール公式ルールブック2026 3.A.3:大会向けの競技面は34×64フィートが推奨なので、各コートにこの広さを充てています。隣り合うコートの間隔の規定はないため、競技面を隙間なく並べています。特定の大会のコート数は確認できていません。",
260
+ },
261
+ sources: ["usap-rulebook"],
262
+ },
263
+ {
264
+ id: "pickleball-2x4",
265
+ name: { en: "Pickleball, eight courts (2 x 4)", ja: "ピックルボール 8面(2×4)" },
266
+ sport: "pickleball",
267
+ surface: { sport: "pickleball" },
268
+ kind: "cells",
269
+ rows: 2,
270
+ columns: 4,
271
+ bay: { length: 64, width: 34, unit: "ft" },
272
+ word: "court",
273
+ parts: { barriers: false, officials: false, scoreboard: "none", boards: true, brand: "floor" },
274
+ floor: "blue",
275
+ basis: "rulebook",
276
+ rule: {
277
+ en: "USA Pickleball Official Rulebook 2026, 3.A.3, as for the 2 x 2: 34 by 64 feet to each court, two rows of four.",
278
+ ja: "USAピックルボール公式ルールブック2026 3.A.3。2×2と同じく各コート34×64フィートで、4面ずつ2行に並べます。",
279
+ },
280
+ sources: ["usap-rulebook"],
281
+ },
282
+ {
283
+ id: "pickleball-4x4",
284
+ name: { en: "Pickleball, sixteen courts (4 x 4)", ja: "ピックルボール 16面(4×4)" },
285
+ sport: "pickleball",
286
+ surface: { sport: "pickleball" },
287
+ kind: "cells",
288
+ rows: 4,
289
+ columns: 4,
290
+ bay: { length: 64, width: 34, unit: "ft" },
291
+ word: "court",
292
+ parts: { barriers: false, officials: false, scoreboard: "none", boards: true, brand: "floor" },
293
+ floor: "blue",
294
+ basis: "rulebook",
295
+ rule: {
296
+ en: "USA Pickleball Official Rulebook 2026, 3.A.3: 34 by 64 feet to each court. Sixteen is the least number of courts the PPA Tour asks a host to provide (its page names no layout), so this is the block a host's hall has to hold.",
297
+ ja: "USAピックルボール公式ルールブック2026 3.A.3:各コート34×64フィート。16面はPPAツアーが開催者に求めるコート数の最小値で(配置の記載はありません)、開催会場が収容できなければならない範囲にあたります。",
298
+ },
299
+ sources: ["usap-rulebook", "ppa-host"],
300
+ },
301
+ {
302
+ id: "curling-1x4",
303
+ name: { en: "Curling, four sheets (1 x 4)", ja: "カーリング 4シート(1×4)" },
304
+ sport: "curling",
305
+ surface: { sport: "curling", orientation: "landscape" },
306
+ kind: "cells",
307
+ rows: 1,
308
+ columns: 4,
309
+ turn: 90,
310
+ bay: { length: 4.75, width: 45.72, unit: "m" },
311
+ word: "sheet",
312
+ parts: { barriers: false, officials: false, scoreboard: "none", boards: true, brand: "floor" },
313
+ floor: "ice",
314
+ basis: "event",
315
+ event: {
316
+ name: "Olympic Winter Games, curling",
317
+ year: 2022,
318
+ venue: "Beijing National Aquatics Centre (the Ice Cube)",
319
+ city: "Beijing",
320
+ country: "CN",
321
+ ja: { name: "オリンピック冬季競技大会 カーリング", venue: "北京国家水泳センター(アイスキューブ)", city: "北京" },
322
+ note: {
323
+ en: "Four sheets side by side on the ice built over the pool (from news reports; the venue's size of ice was not found, so no hall floor is recorded). Each sheet is drawn at World Curling's 45.72 m by 4.75 m, side by side.",
324
+ ja: "プールの上に張った氷に、4シートが並んでいました(報道による情報で、氷の大きさは確認できなかったため、会場の床は記録していません)。各シートはワールドカーリングの45.72m×4.75mで、並べて描いています。",
325
+ },
326
+ sources: ["beijing-2022-curling", "wcf-rules"],
327
+ },
328
+ rule: {
329
+ en: "World Curling, The Rules of Curling and Rules of Competition, R1(a), as read in the 1 September 2026 text: the length of the sheet from the inside edges of the back boards is a minimum of 45.720 m (150 ft), and its width from the inside edges of the side lines a maximum of 4.750 m (15 ft 7 in); an existing facility may reduce them to a minimum of 44.501 m and 4.420 m. The sheets are drawn at the full 45.720 m by 4.750 m, side by side, 4.75 m apart centre to centre; the rules give no thickness for the dividers between sheets, so none is allowed for (ours).",
330
+ ja: "ワールドカーリング「カーリング規則・競技規則」R1(a)(2026年9月1日版):シートの長さ(バックボードの内側の縁から測る)は最小45.720m(150フィート)、幅(サイドラインの内側の縁から測る)は最大4.750m(15フィート7インチ)です。既存の施設では、長さ44.501m、幅4.420mまで縮めてよいとされています。シートは45.720m×4.750mのまま隣り合わせに並べ、中心間は4.75mです。シート間の仕切りの厚さは規則に示されていないため、考慮していません(このパッケージの判断)。",
331
+ },
332
+ sources: ["wcf-rules", "beijing-2022-curling"],
333
+ },
334
+ {
335
+ id: "judo-1x3",
336
+ name: { en: "Judo, three contest areas in a row (1 x 3)", ja: "柔道 試合場3面を1列(1×3)" },
337
+ sport: "judo",
338
+ surface: { sport: "judo", league: "ijf", budo: { areas: { across: 3, down: 1 } } },
339
+ kind: "budo",
340
+ rows: 1,
341
+ columns: 3,
342
+ word: "area",
343
+ parts: { barriers: false, officials: false, scoreboard: "none", boards: true, brand: "mat" },
344
+ floor: "red",
345
+ basis: "event",
346
+ event: {
347
+ name: "World Judo Championships",
348
+ year: 2018,
349
+ venue: "National Gymnastics Arena",
350
+ city: "Baku",
351
+ country: "AZ",
352
+ ja: { name: "世界柔道選手権", venue: "ナショナル・ジムナスティクス・アリーナ", city: "バクー" },
353
+ note: {
354
+ en: "Three contest areas in a row inside one coloured floor of mats, with the event's name and year printed on the mats and boards along the edges (read from the owner's photograph; the number of areas is not in the sources). The Tokyo Grand Slam of 2024, at the Tokyo Metropolitan Gymnasium, is photographed the same way, with TOKYO 2024 printed on the floor. The areas are the IJF's 10 m, with 4 m of safety area and 4 m common.",
355
+ ja: "試合場3面が、マットを敷いた色付きの床1枚の上に1列で並び、マットと周囲のボードに大会名と年が印刷されています(提供された写真から読み取りました。面数は文献にありません)。2024年の東京グランドスラム(東京体育館)も同じ並びで、床に「TOKYO 2024」と印刷されています。試合場はIJF規定の10m四方、安全地帯4m、共通安全地帯4mです。",
356
+ },
357
+ sources: ["ijf-baku-2018", "wikipedia-tokyo-gs-2024", "ijf-sor"],
358
+ },
359
+ rule: {
360
+ en: "IJF Sport and Organisation Rules, 8.7: a contest area of 10 m at the World Championships, a safety area of 4 m, a common safe zone of at least 4 m between adjoining areas, a free zone of at least 0.5 m round all.",
361
+ ja: "IJFスポーツ・組織規程 8.7:世界選手権の試合場は10m四方、安全地帯は4m、隣り合う試合場の共通安全地帯は4m以上、全体の周りに自由地帯0.5m以上。",
362
+ },
363
+ sources: ["ijf-sor", "ijf-baku-2018", "wikipedia-tokyo-gs-2024"],
364
+ },
365
+ {
366
+ id: "judo-1x4",
367
+ name: { en: "Judo, four contest areas in a row (1 x 4)", ja: "柔道 試合場4面を1列(1×4)" },
368
+ sport: "judo",
369
+ surface: { sport: "judo", league: "ijf", budo: { areas: { across: 4, down: 1 } } },
370
+ kind: "budo",
371
+ rows: 1,
372
+ columns: 4,
373
+ word: "area",
374
+ parts: { barriers: false, officials: false, scoreboard: "none", boards: true, brand: "mat" },
375
+ floor: "red",
376
+ basis: "rulebook",
377
+ rule: {
378
+ en: "IJF Sport and Organisation Rules, 8.7, as for the 1 x 3: four contest areas of 10 m, 4 m of safety area and 4 m common between them. No event's count of four was sourced; it is the row the rules allow.",
379
+ ja: "IJFスポーツ・組織規程 8.7。1×3と同じく、10m四方の試合場4面、安全地帯4m、間の共通安全地帯4mです。4面の大会は確認できていません。規則が認める並べ方です。",
380
+ },
381
+ sources: ["ijf-sor"],
382
+ },
383
+ {
384
+ id: "karate-2x3",
385
+ name: { en: "Karate, six tatami (2 x 3)", ja: "空手 試合場6面(2×3)" },
386
+ sport: "karate",
387
+ surface: { sport: "karate", league: "wkf-kumite" },
388
+ kind: "budo",
389
+ rows: 2,
390
+ columns: 3,
391
+ word: "area",
392
+ parts: { barriers: false, officials: false, scoreboard: "none", boards: true, brand: "mat" },
393
+ floor: "blue",
394
+ basis: "rulebook",
395
+ event: {
396
+ name: "Karate1 Series A",
397
+ year: 2025,
398
+ venue: "N9 Arena, Nilai",
399
+ city: "Kuala Lumpur",
400
+ country: "MY",
401
+ ja: { name: "Karate1 シリーズA", venue: "N9アリーナ(ニライ)", city: "クアラルンプール" },
402
+ note: {
403
+ en: "The league's branding manual fixes six tatami areas in two rows of three on one carpet of the event's colour, each with its number printed on it. The number of areas at the Kuala Lumpur event of 3 to 5 October 2025 is not published: six is the league's rule, not that event's count.",
404
+ ja: "リーグのブランディングマニュアルは、大会の色の1枚のカーペット上に試合場6面を2行3列で置き、各面に番号を印刷すると定めています。2025年10月3〜5日のクアラルンプール大会の面数は公表されていません。6面はリーグの規定であり、その大会の実数ではありません。",
405
+ },
406
+ sources: ["wkf-karate1-branding"],
407
+ },
408
+ rule: {
409
+ en: "WKF Kumite Competition Rules 2026.01, Article 1: an 8 m matted square, a safety area of 2 m, 2 m between areas (Article 1.2 as the package already holds it; the 2024 text, read by the research note, gives 1.5 m, so the 2 m is the stricter). The grid is the league's manual's.",
410
+ ja: "WKF組手競技規則2026.01 第1条:一辺8mのマットの正方形、安全地帯2m、試合場の間2m(第1.2条。このパッケージがすでに採用している値。2024年版は1.5mとしているので、余裕のある2mを採っています)。並べ方はリーグのマニュアルによります。",
411
+ },
412
+ sources: ["wkf-kumite", "wkf-karate1-branding"],
413
+ },
414
+ {
415
+ id: "karate-2x4",
416
+ name: { en: "Karate, eight tatami (2 x 4)", ja: "空手 試合場8面(2×4)" },
417
+ sport: "karate",
418
+ surface: { sport: "karate", league: "wkf-kumite" },
419
+ kind: "budo",
420
+ rows: 2,
421
+ columns: 4,
422
+ word: "area",
423
+ parts: { barriers: false, officials: false, scoreboard: "none", boards: true, brand: "mat" },
424
+ floor: "blue",
425
+ basis: "rulebook",
426
+ rule: {
427
+ en: "WKF Kumite Competition Rules 2026.01, Article 1, as for the 2 x 3; the Youth League's branding manual lays eight areas in two rows of four. No event's count was sourced.",
428
+ ja: "WKF組手競技規則2026.01 第1条。2×3と同じです。ユースリーグのブランディングマニュアルは、8面を2行4列に置いています。特定の大会の面数は確認できていません。",
429
+ },
430
+ sources: ["wkf-kumite", "wkf-karate1-branding"],
431
+ },
432
+ {
433
+ id: "badminton-1x4",
434
+ name: { en: "Badminton, four courts side by side (1 x 4), the spacing recommended for Grade 1 and 2", ja: "バドミントン 4面を横並び(1×4)、グレード1・2の推奨間隔" },
435
+ sport: "badminton",
436
+ surface: { sport: "badminton" },
437
+ kind: "cells",
438
+ rows: 1,
439
+ columns: 4,
440
+ turn: 90,
441
+ bay: { length: 10.1, width: 17.4, unit: "m" },
442
+ edge: { length: 1.5, width: 2, unit: "m" },
443
+ word: "court",
444
+ parts: { barriers: false, officials: true, scoreboard: "none", boards: true, brand: "floor" },
445
+ floor: "green",
446
+ basis: "rulebook",
447
+ rule: {
448
+ en: "BWF Statutes 5.3.4 (2.1.3, 2.1.4): courts always side by side, 2 m clear behind the baselines and 1.5 m from the side lines, and at least 1.5 m between courts as the least; for Grade 1 and 2 tournaments the specification only recommends (it does not require) at least 4 m between courts, for the A-boards and the officials' chairs, and that is the spacing drawn here. No event's count of courts was sourced.",
449
+ ja: "BWF規程5.3.4(2.1.3、2.1.4):コートは常に横並びです。バックバウンダリーラインの後ろに2m、サイドラインの外側に1.5mの空きが必要で、コート間は最低1.5mです。グレード1・2の大会では、Aボード(広告ボード)と審判席のために、コート間を4m以上とすることが推奨されていますが、義務ではありません。ここで描いているのは、この推奨の間隔の4mです。特定の大会のコート数は確認できていません。",
450
+ },
451
+ sources: ["bwf-facilities", "bwf-laws"],
452
+ },
453
+ {
454
+ id: "badminton-1x4-min",
455
+ name: { en: "Badminton, four courts side by side (1 x 4), the least spacing", ja: "バドミントン 4面を横並び(1×4)、最小の間隔" },
456
+ sport: "badminton",
457
+ surface: { sport: "badminton" },
458
+ kind: "cells",
459
+ rows: 1,
460
+ columns: 4,
461
+ turn: 90,
462
+ bay: { length: 7.6, width: 17.4, unit: "m" },
463
+ edge: { length: 1.5, width: 2, unit: "m" },
464
+ word: "court",
465
+ parts: { barriers: false, officials: false, scoreboard: "none", boards: true, brand: "floor" },
466
+ floor: "green",
467
+ basis: "rulebook",
468
+ rule: {
469
+ en: "BWF Statutes 5.3.4 (2.1.3, 2.2.3): the least for any sanctioned tournament, 1.5 m between courts, 2 m behind the baselines and 1.5 m from the side lines.",
470
+ ja: "BWF規程5.3.4(2.1.3、2.2.3):公認大会に共通の最小値。コート間1.5m、バックバウンダリーラインの後ろ2m、サイドラインの外側1.5m。",
471
+ },
472
+ sources: ["bwf-facilities", "bwf-laws"],
473
+ },
474
+ {
475
+ id: "tennis-1x3",
476
+ name: { en: "Tennis, three courts side by side (1 x 3)", ja: "テニス 3面を横並び(1×3)" },
477
+ sport: "tennis",
478
+ surface: { sport: "tennis" },
479
+ kind: "cells",
480
+ rows: 1,
481
+ columns: 3,
482
+ turn: 90,
483
+ bay: { length: 18.29, width: 36.57, unit: "m" },
484
+ edge: { length: 3.66, width: 6.4, unit: "m" },
485
+ word: "court",
486
+ parts: { barriers: false, officials: false, scoreboard: "none", boards: true, brand: "floor" },
487
+ floor: "green",
488
+ basis: "rulebook",
489
+ rule: {
490
+ en: "Swiss Tennis, citing the ITF and BASPO 530 (secondary): 6.40 m behind the baselines, 3.66 m to the side, and 7.32 m between adjacent courts when three or more lie side by side. No event's layout was sourced (Wimbledon has 19 courts at the club; how the outside courts lie is not published).",
491
+ ja: "スイス・テニス連盟がITFとBASPO 530を引用した数値(二次資料):バックスペース(ベースラインの後ろ)6.40m、サイドスペース3.66m、3面以上を横に並べるときは隣のコートとの間7.32m。特定の大会の配置は確認できていません(ウィンブルドンのクラブには19面のコートがありますが、外側のコートの並びは公表されていません)。",
492
+ },
493
+ sources: ["swiss-tennis-distances", "itf-rules"],
494
+ },
495
+ ]);
496
+ /** The keys of `MULTI_PRESETS`, in order. */
497
+ export const MULTI_PRESET_IDS = Object.freeze(MULTI_PRESETS.map((p) => p.id));
498
+ /** The preset with a key, or `undefined`. */
499
+ export const multiPreset = (id) => MULTI_PRESETS.find((p) => p.id === id);