@johnmorrisdotca/kyogijo-stadiums 0.18.1 → 0.20.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 +26 -0
- package/NOTICE.md +1 -0
- package/README.md +62 -28
- package/dist/budo/cage.d.ts +46 -0
- package/dist/budo/cage.js +91 -0
- package/dist/budo/describe.js +11 -0
- package/dist/budo/looks.js +8 -0
- package/dist/budo/plan.d.ts +10 -2
- package/dist/budo/plan.js +15 -1
- package/dist/budo/types.d.ts +11 -3
- package/dist/budo-entry.d.ts +1 -1
- package/dist/budo-entry.js +1 -1
- package/dist/budo.style.js +7 -2
- package/dist/common.d.ts +5 -0
- package/dist/common.js +6 -1
- package/dist/crowd.js +2 -0
- package/dist/draw.js +8 -7
- package/dist/features.js +10 -0
- package/dist/fields.types.d.ts +1 -1
- package/dist/heat.zones.js +1 -1
- package/dist/homeside.js +2 -0
- package/dist/judging-entry.d.ts +6 -1
- package/dist/judging-entry.js +5 -1
- package/dist/judging.board.d.ts +26 -0
- package/dist/judging.board.js +125 -0
- package/dist/judging.broadcast.d.ts +6 -0
- package/dist/judging.broadcast.js +72 -0
- package/dist/judging.d.ts +5 -0
- package/dist/judging.draw.d.ts +19 -6
- package/dist/judging.draw.js +14 -104
- package/dist/judging.js +14 -2
- package/dist/judging.mount.d.ts +16 -0
- package/dist/judging.mount.js +69 -0
- package/dist/judging.plan.d.ts +52 -0
- package/dist/judging.plan.js +91 -0
- package/dist/judging.print.d.ts +58 -0
- package/dist/judging.print.js +86 -0
- package/dist/judging.style.d.ts +5 -0
- package/dist/judging.style.js +22 -0
- package/dist/judging.text.d.ts +7 -0
- package/dist/judging.text.js +23 -0
- package/dist/judging.types.d.ts +9 -0
- package/dist/judging.words.d.ts +1 -0
- package/dist/judging.words.js +2 -0
- package/dist/leagues/budo.d.ts +3 -2
- package/dist/leagues/budo.js +2 -1
- package/dist/leagues/combat.d.ts +54 -0
- package/dist/leagues/combat.js +27 -0
- package/dist/leagues/sources.js +6 -0
- package/dist/leagues/types.d.ts +1 -1
- package/dist/leagues.d.ts +1 -0
- package/dist/leagues.js +21 -1
- package/dist/outline.js +1 -0
- package/dist/ranges.names.js +1 -0
- package/dist/score.js +3 -0
- package/dist/strings.d.ts +7 -1
- package/dist/strings.js +22 -10
- package/dist/surfaces/budo.js +3 -2
- package/dist/turn.kit.d.ts +1 -1
- package/dist/turn.style.js +8 -3
- package/dist/types.d.ts +4 -2
- package/dist/units.js +2 -0
- package/dist/uprights.budo.js +4 -2
- package/dist/uprights.cage.d.ts +4 -0
- package/dist/uprights.cage.js +91 -0
- package/dist/uprights.js +3 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,32 @@ All notable changes to this project are written here. The format follows
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.20.0] - 2026-10-20
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **The MMA cage** (`sport: "mma"`, [the combat sports page](./docs/combat.md)): an eight-sided fenced area on its platform, to scale, from the Nevada Rules of Unarmed Combat (5.010 3) and the IMMAF's rules for amateur competition: 20 to 32 feet across the flats (`budo.size`, 30 feet drawn and 25 feet the smaller cage), a platform of at most 4 feet (`budo.height`) with steps up at each gate, a fence of 5 to 7 feet (`budo.fence`, 6 feet drawn), eight padded posts, two gates opposite each other and a canvas over foam, with a grey, a black and a blue look in light and dark. The leagues are `nruc` and `immaf`; `RANGES.mma` has `cage`, `gate` and `half`; the parts are named for `landmarks` and the features for `featureColors`, in English and Japanese. The cage is named for what it is, an eight-sided cage: no promotion's name or mark is used. It is a sport of the package (40 now), with `SPORTS`, a unit of feet, no home side, a badge glyph, a crowd profile and its sources in `LEAGUE_SOURCES` (the figure of the rule, the figure that is typical and the figure that is ours are told apart).
|
|
15
|
+
- **The cage in 3D** (`buildTurn({ sport: "mma" })`): the platform is a solid block (four sides to the floor of the hall and a top that is the drawing's own canvas, lifted), the fence is wire mesh on each of its eight flats with a pad along the top and the foot so that the canvas stays in sight, and gives way to an eye that has it in front of the cage, the posts are solid, the gates are frames of padded rails, and the steps are three blocks each. Tests hold the order the parts are drawn in from every side, the size of the view as it turns and the scene inside its box at every angle.
|
|
16
|
+
- **The demo** has the cage in its sport picker, with the looks, the cage's width (30 or 25 feet, `cagesize` in the address), the score of a bout and the 3D view; the docs have a page for it and a gallery of its own.
|
|
17
|
+
|
|
18
|
+
## [0.19.0] - 2026-10-20
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **A broadcast view of a judging assignment** (`view: "broadcast"`). The mat large and prominent as a television would show it, 16:9, with the officials superimposed on a board at its side: the package's own score panel drawn for officials (the same dark rounded plate, the mat's name where a score panel has the competition, column heads, a row for each seat with its number on the round badge the seats wear, the name on a coloured chip, the ID where a score would be, and the style at the foot). The board lies beside the contest area and never over it (a test holds the board clear of the mat's picture and of the middle of the contest area for kata and shiai, a bench close up, six long names, and every width), the seat badges stay on the seats, and the whole picture scales evenly: no text is stretched (a test: every font size is in proportion at twice the width). A mat takes a `line` (`Round 2`, `Pool B`, at most 60 characters) shown before the style at the board's foot. `drawJudging` draws it in 2D; `mountJudgingBroadcast` mounts the 3D view from the Broadcast camera with the board laid over it (a share of the view's width so it scales with it, under the view where that is narrower than 640 px, and never taking the pointer); `judgingBoard` is the board alone for a page of your own. Light and dark, English and Japanese. The demo opens it with `?view=broadcast` (3D) or `?view=broadcast&dim=2d`.
|
|
23
|
+
- **Printing the plan-and-chart layout** (`judgingPrint`, `judgingPrintSheets`, `judgingPrintStyle`, `JUDGING_PAPER`). One mat to a page on A4 or US letter, portrait or landscape, in the light colours, the picture scaled evenly to the page and anchored at its top; `judgingPrint` is a whole HTML document that opens as the pages on a grey desk and prints as they are (Save as PDF for a file). The demo has a "Print or save as PDF" button with a choice of paper (`?paper=letter`).
|
|
24
|
+
- `JudgingDrawing.boards` (where each mat's board, the part of the mat shown and the middle of the contest area are), `matLine`, `KYOGIJO_JUDGING_BOARD_STYLE`, `KYOGIJO_JUDGING_BROADCAST_STYLE`, `BOARD_BASE`, `BROADCAST_RATIO`, `boardFoot`.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- **A box with the picture's words no longer pops up over the mat.** A `<title>` that is a direct child of the root `<svg>` is the browser's tooltip for the whole drawing, so resting the pointer on the 2D plan showed "Judging assignments: Kata, 5 judges, 2 mats" in a box on top of the mat, and on a score on a surface "Mexico 11, USA 10, Final" over its top left. A judging picture now keeps its title and description in a `<defs>` (the picture is still named by them: `aria-labelledby` points at them), and the demo's pages move the title of every drawing they show into a `<defs>` the same way (`demo/quiet.js`); a surface's own markup is unchanged byte for byte, so a page that wants no tooltip does the same with its drawings.
|
|
29
|
+
|
|
30
|
+
- **Chart lines stay inside their rows in a wide face.** The chart's name and ID lines were fitted to an estimate of the face's width, and in a wider face (Verdana on Windows, DejaVu Sans on Linux, where the demo's browser test of 0.18.1 failed) the last words of a long name crossed the row's right edge by a few pixels. The chart now fits its lines to 94 % of the room, and a browser test sets the board and the chart in Verdana and DejaVu Sans.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- The plan view of a judging assignment moved its title and description into a `<defs>` (see above); everything else it draws is as it was. The plan's drawing code is in `judging.plan.ts` and the words in `judging.text.ts`, shared by both views.
|
|
35
|
+
|
|
10
36
|
## [0.18.1] - 2026-10-20
|
|
11
37
|
|
|
12
38
|
### Changed
|
package/NOTICE.md
CHANGED
|
@@ -35,6 +35,7 @@ picture or code of the sources is copied; each source is named here so that the
|
|
|
35
35
|
| `leagues`: the skating rinks | The International Skating Union's Sports Rules - Speed Skating (Special Regulations and Technical Rules, Rules 203 to 206, 226 to 228 and 253 to 257, and "H. Track", effective 12 June 2026), Special Regulations and Technical Rules Short Track Speed Skating (Rule 280 and the diagram of the tracks, 2024) and Sports Rules - Figure Skating (Rule 342, effective 12 June 2026) | Facts; no text or drawing copied |
|
|
36
36
|
| `leagues` and `halls`: the budō surfaces | The International Judo Federation's Sport and Organisation Rules (version of 21 January 2026, 8.7, Article 9, B1.8; and the June 2020 version, 18.1) and its Kata Commission's Tournament Handbook (2024) and Criteria for the Evaluation (January 2025); the All Japan Judo Federation's 大会運営ガイドブック2023; the World Karate Federation's Kumite and Kata Competition Rules (2026); the International Kendo Federation's Regulations of Kendo Shiai and Shinpan (Article 2 and Figure 1); the Japan Sumo Association's 相撲規則 土俵規定 第一条 and 大相撲クイズ, as the Sasakawa Sports Foundation and ozumo.jp quote them; the All Nippon Kyudo Federation's 弓道競技運営要領 (2016) and the National Sports Festival 2015's rules for kinteki and enteki; the tatami sizes of English and Japanese Wikipedia; the Kodokan's 施設のご案内, the Nippon Budokan's 日本武道館建物等概要 (October 2021), and English and Japanese Wikipedia and Wikidata on the five halls and the kimarite | Facts |
|
|
37
37
|
| `frames`: the soccer providers' coordinates | StatsBomb's Open Data Events specification (Appendix 2), the Wyscout and Impect glossaries, the Metrica Sports and SkillCorner open-data READMEs; for Opta, Tracab and Second Spectrum, whose specifications are not public, the figures of mplsoccer, ggsoccer, kloppy and floodlight (docs/sources.md) | Facts; no text, table or code copied |
|
|
38
|
+
| `leagues`: the MMA cage | The Nevada Rules of Unarmed Combat (NRUC 5.010, the file of 20 November 2024), Oregon Administrative Rule 230-070-0025, the IMMAF's Unified Rules for amateur, junior and senior competition (January 2021), and the English Wikipedia articles "Mixed martial arts cage" (revision 1377260922) and "Mixed martial arts" (revision 1381048799), for the sizes that are typical | Facts, CC BY-SA 4.0 for the Wikipedia text read |
|
|
38
39
|
| `parks`: the fence of each ballpark, current and past, and the seasons of a past park | The distances (and, for a park whose fence moved, the years an article dates them) published in the English and Japanese Wikipedia article of each park, at the revision cited below; the seasons a club played there from the same article's list of tenants | Facts. The articles are CC BY-SA 4.0 (https://creativecommons.org/licenses/by-sa/4.0/); none of their text, tables or images is used, and the angles between the distances are our own reading |
|
|
39
40
|
| `parks`: the Wikidata item of each ballpark (`wikidata`) | The item (`Q49136`) that each cited article is linked to, read with the MediaWiki API (`pageprops`, `wikibase_item`) and checked against the item's label | Wikidata's data is CC0 (https://creativecommons.org/publicdomain/zero/1.0/) |
|
|
40
41
|
| `parks` and `grounds`: the names (`name`, `nameJa`, `readingJa`, `localName`, `aliases`) | The names are facts. Each alias says where it was read (`source`): the title of the English or Japanese Wikipedia article a place cites (with its revision), a name the infobox or the opening text of the same revision gives (a former or sponsor's name with the years it dates, a nickname, the name in Japanese and its reading), or Wikidata's labels, aliases and properties "official name" (P1448), "nickname" (P1449), "name" (P2561), "short name" (P1813), read with the Wikidata API by `scripts/fetch-names.mjs` into `scripts/names.wikidata.json` | Facts; Wikidata's data is CC0 (https://creativecommons.org/publicdomain/zero/1.0/), and the articles are CC BY-SA 4.0 as above, none of their text copied. Which name is the everyday one is our reading, in docs/references.md ("Names") |
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<h1 align="center">Kyogijo Stadiums <sub>競技場</sub></h1>
|
|
2
2
|
|
|
3
3
|
<p align="center"><strong>Sports surfaces as SVG, drawn to scale, with the score on them.</strong><br>
|
|
4
|
-
The
|
|
4
|
+
The surfaces of forty sports, from football and curling to the budō and the MMA cage, each drawn from its rulebook or its published distances, with each team's name and logo on its side and the score in the middle, a lineup and the situation of the game on them, with stands and a crowd, a pageant of flags and a 3D view. Wide or tall, light or dark, a badge for a list, a helper for React, a custom element and a frame for a page that runs no script. One function, no dependencies.</p>
|
|
5
5
|
|
|
6
6
|
<p align="center">
|
|
7
7
|
<a href="https://github.com/johnmorrisdotca/kyogijo-stadiums/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/johnmorrisdotca/kyogijo-stadiums/actions/workflows/ci.yml/badge.svg"></a>
|
|
@@ -20,14 +20,14 @@ The NFL, CFL and IFAF football fields, the NHL rink, the NBA court, the soccer p
|
|
|
20
20
|
<td align="center" valign="top">
|
|
21
21
|
<picture>
|
|
22
22
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/hero-desk-dark.webp">
|
|
23
|
-
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/hero-desk-light.webp" alt="The demo on a desk, in English: the heading
|
|
23
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/hero-desk-light.webp" alt="The demo on a desk, in English: the heading, the language chooser and links, and an NHL rink drawn wide on an ice-blue background with a made-up game on it, the USA on the left, Canada on the right and the score 3 to 2, Final/OT, in the middle. The controls on the right list the sports, the layout and the teams." width="640">
|
|
24
24
|
</picture>
|
|
25
25
|
<br><em>The demo on a desk: a rink, with the teams on their sides and the score in the middle.</em>
|
|
26
26
|
</td>
|
|
27
27
|
<td align="center" valign="top">
|
|
28
28
|
<picture>
|
|
29
29
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/hero-phone-dark.webp">
|
|
30
|
-
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/hero-phone-light.webp" alt="The demo on a phone: the heading
|
|
30
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/hero-phone-light.webp" alt="The demo on a phone: the heading and controls, and under them, on a background of floodlight beams, a football field standing tall, Mexico's green end zone at the top and the USA's navy one at the bottom, each with its flag and name, and a score panel at midfield reading 27 to 24, Final." width="240">
|
|
31
31
|
</picture>
|
|
32
32
|
<br><em>On a phone the same surface stands tall, the words still upright.</em>
|
|
33
33
|
</td>
|
|
@@ -65,27 +65,27 @@ console.log(svg.startsWith("<svg"), svg.includes("USA 3, Canada 2"));
|
|
|
65
65
|
|
|
66
66
|
## Who it is for
|
|
67
67
|
|
|
68
|
-
- **A results page or a stats site** that has
|
|
68
|
+
- **A results page or a stats site** that has a game's score and wants a picture of where it was played.
|
|
69
69
|
- **A list of games** that needs a compact strip for each, small enough for a phone.
|
|
70
|
-
- **Anyone drawing a rink,
|
|
70
|
+
- **Anyone drawing a rink, field, court or ballpark** for a poster or a lesson, with the dimensions right and the colours their own.
|
|
71
71
|
- **A site that uses a framework or none**: the drawing is a string, so it works from a server, a build step, a framework, a custom element or a frame.
|
|
72
72
|
|
|
73
73
|
## Features
|
|
74
74
|
|
|
75
|
-
- **
|
|
75
|
+
- **Forty surfaces, to scale.** The NFL, CFL and IFAF fields, the NHL rink, the NBA court, the soccer pitch and futsal court, the baseball field, the curling sheet, twelve net and racket sports, the pools, the athletics stadium, the skating rinks, seven field sports, the budō and the MMA cage. Every figure is cited in [sources](./docs/sources.md). [The surfaces](./docs/surfaces.md).
|
|
76
76
|
- **Each league's rulebook.** `league: "fiba"` draws a court as FIBA marks it: 48 variants, from the WNBA, the NCAA and the IIHF to Little League, PONY, softball, Curling Canada, FIVB's beach volleyball, rugby league and the NLL's box lacrosse, each cited. [League variants](./docs/variants.md).
|
|
77
77
|
- **A realistic basketball floor.** `court: { hardwood: true }` draws maple boards that run the length of the court with staggered ends, grain, stained keys, the baskets and stanchions with soft shadows, a coaching box and benches, and a satin sheen, in every league and renderer. The clean floor stays the default. [Hardwood](./docs/hardwood.md).
|
|
78
78
|
- **The stands and the crowd.** `crowd: true` draws the seating round any surface that has spectators: a bowl, two sides, a horseshoe, courtside rows or a ballpark's grandstands, with the people as seeded heads and shoulders in the home colours and the empty seats showing (`density`, or `attendance` over `capacity`). [The crowd](./docs/crowd.md).
|
|
79
79
|
- **Curling, from the rule books.** A sheet from World Curling's and Curling Canada's rules, tall by default, with the board and the hammer in a score, `curlingStones` for the stones of an end, scored by the rules, `show: "folded"` for the whole sheet with both houses enlarged beside it, and a heat map and statistics for many ends. [Curling](./docs/curling.md).
|
|
80
80
|
- **Net, racket and court sports, from their rulebooks.** The ITF's, FIVB's (indoor, beach, sitting), BWF's, USA Pickleball's and ITTF's courts and table, the padel, squash, racquetball, sepak takraw, teqball, roundnet and netball courts, each in its look (hard court, clay, grass, wood, sand), with a board of sets and games. [Net, racket and court sports](./docs/courts.md).
|
|
81
|
-
- **Swimming, water polo, diving and artistic swimming, from World Aquatics' regulations.** The
|
|
81
|
+
- **Swimming, water polo, diving and artistic swimming, from World Aquatics' regulations.** The 50 or 25 m pool with its lanes, ropes, blocks and touch panels; the water polo field; the diving well; the artistic swimming area; several pools in a natatorium. A race's lanes carry names, flags, places, times and splits, with a replay and a `splitsChart`. [Pools](./docs/pools.md).
|
|
82
82
|
- **Lacrosse, rugby, Australian football, Gaelic games, cricket, field hockey and handball, from their rulebooks.** The fields and floors of World Lacrosse, World Rugby, the NRL, the AFL, the GAA, the FIH and the IHF, and a cricket ground with a boundary of your own. A score is goals and behinds, goals and points or a board of runs, wickets and overs. [Field sports](./docs/field-sports.md).
|
|
83
83
|
- **The athletics stadium, from World Athletics' rules.** The 400 m track with its lanes and staggers worked out from the running lines, curved and relay starts, hurdles, the steeplechase, every field event, a close-up of each start, the covered 200 m track, and lane draws, results, a race replay and the marks of throws and jumps. [The athletics stadium](./docs/athletics.md).
|
|
84
84
|
- **The skating rinks, from the ISU's rules.** The 400 m speed skating track with its lanes, blocks and the lines of every race worked out lane by lane; the short track's oval; the figure skating rink of 60 by 30 m with its judges' seats; and pairs, results, a race replay and the elements of a programme on the ice. [The skating rinks](./docs/skating.md).
|
|
85
|
-
- **The budō, from the federations' rules.** The IJF's and the All Japan Judo Federation's judo areas, the WKF's karate areas, the kendo shiai-jo, the sumo dohyō, the kyūdōjō, and **a dojo builder**: a floor of tatami laid as real units, in jō or metres, with its walls, doors, windows and shrine.
|
|
85
|
+
- **The budō, from the federations' rules.** The IJF's and the All Japan Judo Federation's judo areas, the WKF's karate areas, the kendo shiai-jo, the sumo dohyō, the kyūdōjō, and **a dojo builder**: a floor of tatami laid as real units, in jō or metres, with its walls, doors, windows and shrine. Scores are judo's ippon, waza-ari and shido, karate's and kendo's points and sumo's kimarite. [The budō](./docs/budo.md).
|
|
86
86
|
- **Soccer, to the Laws.** A pitch from Law 1 of the IFAB Laws of the Game of any size, with presets (international, UEFA, MLS, NCAA, the FA's 9-, 7- and 5-a-side, FIFA's futsal), half pitches, five mowing patterns, four goal styles, penalties and extra time in a score. [Soccer](./docs/soccer.md).
|
|
87
87
|
- **Every ballpark.** The 30 current MLB parks and 44 that MLB clubs have left, and the 12 home parks of Nippon Professional Baseball with eight other NPB grounds, each with its fence drawn from the distances published for it, as it stood in a season. [Ballparks](./docs/ballparks.md).
|
|
88
|
-
- **Soccer grounds, arenas and an atlas.** 64 soccer grounds
|
|
88
|
+
- **Soccer grounds, arenas and an atlas.** 64 soccer grounds at their published sizes, 167 NHL, NBA, WNBA and PWHL arenas (`drawKyogijo({ sport: "nhl", arena: "boston-garden" })`), and every park, ground, arena and budō hall (330 places) on a map, found by any of its names. [The grounds](./docs/grounds.md), [the arenas](./docs/arenas.md), [the atlas](./docs/atlas.md), [names](./docs/ballparks.md#names).
|
|
89
89
|
- **Walls and quirks.** How high the fence stands, stretch by stretch and season by season (the Green Monster at 37 feet 2 inches), drawn as a band outside the fence whose width and shade say the height, with a key (`walls`); and Tal's Hill, Wrigley Field's ivy and basket, poles, bullpens and dugouts (`quirks`), each from the park's article, none guessed: [ballparks](./docs/ballparks.md).
|
|
90
90
|
- **Special games.** A surface set inside another, to scale: an NHL rink on a ballpark's infield or a football stadium's field, a college basketball court on the deck of a carrier, a baseball field laid over a London stadium's pitch. 18 games, each with its day, its venue and its sources. [Special games](./docs/special-games.md).
|
|
91
91
|
- **Surfaces through the years.** `year: 1975` draws a surface as its league's rules marked it that season, each change cited. [Surfaces through the years](./docs/eras.md).
|
|
@@ -104,7 +104,7 @@ console.log(svg.startsWith("<svg"), svg.includes("USA 3, Canada 2"));
|
|
|
104
104
|
- **Tournament layouts.** Several surfaces laid out together for one large event, to scale, on one floor, as one SVG: thirteen presets from table tennis, pickleball, curling, judo, karate, badminton and tennis, each with its rule and sources, whether it fits a hall, and a real stadium round it. [Tournament layouts](./docs/multi.md).
|
|
105
105
|
- **Judging assignments.** Who judges where. [Judging](./docs/judging.md).
|
|
106
106
|
- **Replay.** Tracking data played on any surface: the players with their numbers, the ball and its trail, and the passes, shots and goals as they happen, with controls, the keyboard and a live region, steps for a reader who prefers reduced motion, and a pause when the page is hidden. [Replay](./docs/replay.md).
|
|
107
|
-
- **A 3D view.** Any surface as a floor that turns by mouse, touch, wheel or keys, with four viewpoints (overhead, broadcast, end-on, low corner), and what the rulebook stands on it at its height (nets, baskets, rink boards and glass, goals, a ballpark's fence,
|
|
107
|
+
- **A 3D view.** Any surface as a floor that turns by mouse, touch, wheel or keys, with four viewpoints (overhead, broadcast, end-on, low corner), and what the rulebook stands on it at its height (nets, baskets, rink boards and glass, goals, a ballpark's fence, a pool's blocks, a table tennis area's surrounds) and the venue round it (raked stands, roofs, a dojo's walls). Plain DOM and CSS. [The 3D view](./docs/turn.md).
|
|
108
108
|
- **Renderers.** The same drawing as plain data (a scene), on a canvas (a browser's or a Node canvas), in a d3 selection, as a mark of an Observable Plot, as GeoJSON and as a PNG in Node, each an entry of its own that imports nothing from outside the package. [Renderers](./docs/renderers.md).
|
|
109
109
|
- **Units and frames.** Each surface in its rulebook's unit and any other, and 48 coordinate frames (ten soccer providers, the NHL API, HockeyTech, NBA stats, NFL tracking, MLBAM, Retrosheet, and a place from the net, the centre or the middle of the water of each other surface) to move a provider's points onto a surface. [Units](./docs/units.md), [coordinate frames](./docs/frames.md).
|
|
110
110
|
- **A compact badge and a compact card.** One strip for a list, or the surface with that strip under it.
|
|
@@ -119,7 +119,7 @@ console.log(svg.startsWith("<svg"), svg.includes("USA 3, Canada 2"));
|
|
|
119
119
|
| Part | What it is |
|
|
120
120
|
| --- | --- |
|
|
121
121
|
| `drawKyogijo`, `drawSurface`, `drawScore`, `drawBadge` | The drawing, as a string of SVG. |
|
|
122
|
-
| `SPORTS`, `PARKS`, `PARK_IDS`, `COURT_THEMES` | The
|
|
122
|
+
| `SPORTS`, `PARKS`, `PARK_IDS`, `COURT_THEMES` | The forty sports, the 94 ballparks, the court looks. |
|
|
123
123
|
| `SOCCER_PITCHES`, `SOCCER_PROVIDERS`, `rescale`, `soccerSpec` | The soccer pitches, the data providers' coordinate systems and the map between them. |
|
|
124
124
|
| `GROUNDS`, `groundById` | The 64 soccer grounds, each pitch at its own size. |
|
|
125
125
|
| `EVENTS`, `eventOptions` | The 18 special games: a rink in a ballpark, a court on a carrier's deck, with `host` and `placement` in the options. |
|
|
@@ -132,7 +132,7 @@ console.log(svg.startsWith("<svg"), svg.includes("USA 3, Canada 2"));
|
|
|
132
132
|
| `./turn` | A surface as a 3D view that turns, with the net, basket, goal or posts standing on it. |
|
|
133
133
|
| `./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`). |
|
|
134
134
|
| `./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)). |
|
|
135
|
-
| `./judging` | `drawJudging`: who judges where ([docs](./docs/judging.md)). |
|
|
135
|
+
| `./judging` | `drawJudging`, `judgingBoard`, `mountJudgingBroadcast`, `judgingPrint`: who judges where, as a plan, on a broadcast board or on paper ([docs](./docs/judging.md)). |
|
|
136
136
|
| `./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. |
|
|
137
137
|
| `./mount`, `./react`, `./element`, `./element/define` | Draw into a container; React props; the `<kyogijo-field>` element and its registration. |
|
|
138
138
|
|
|
@@ -183,7 +183,7 @@ console.log(svg.includes("Cup Final, Game 7"), svg.includes("Final/OT"));
|
|
|
183
183
|
<p align="center">
|
|
184
184
|
<picture>
|
|
185
185
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/football-desk-dark.webp">
|
|
186
|
-
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/football-desk-light.webp" alt="A football field drawn wide on a background of floodlight beams: Mexico's green end zone on the left with its flag and
|
|
186
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/football-desk-light.webp" alt="A football field drawn wide on a background of floodlight beams: Mexico's green end zone on the left with its flag and name, the USA's navy one on the right, the yard lines and numbers between them, and the score panel at midfield reading 27 to 24, Final, Championship Game." width="720">
|
|
187
187
|
</picture>
|
|
188
188
|
<br><em>A football field: the end zones in the teams' colours, the score at midfield.</em>
|
|
189
189
|
</p>
|
|
@@ -228,12 +228,12 @@ console.log(box(wide), box(tall));
|
|
|
228
228
|
<p align="center">
|
|
229
229
|
<picture>
|
|
230
230
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/tall-phone-dark.webp">
|
|
231
|
-
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/tall-phone-light.webp" alt="A hockey rink standing tall on a phone, on
|
|
231
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/tall-phone-light.webp" alt="A hockey rink standing tall on a phone, on ice blue: the USA's flag and name in the upper zone, Canada's in the lower, each upright, the score panel between them." width="240">
|
|
232
232
|
</picture>
|
|
233
233
|
<br><em>The same game tall: the teams top and bottom, every word upright.</em>
|
|
234
234
|
</p>
|
|
235
235
|
|
|
236
|
-
[The surfaces](./docs/surfaces.md) lists the
|
|
236
|
+
[The surfaces](./docs/surfaces.md) lists the forty, with their sizes and what is drawn; [score and layout](./docs/score.md) has the options of a score, a strip and a compact card.
|
|
237
237
|
|
|
238
238
|
### A league's rulebook
|
|
239
239
|
|
|
@@ -263,7 +263,7 @@ console.log(svg.includes("甲子園球場のグラウンド"), svg.includes("阪
|
|
|
263
263
|
<p align="center">
|
|
264
264
|
<picture>
|
|
265
265
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/ballpark-desk-dark.webp">
|
|
266
|
-
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/ballpark-desk-light.webp" alt="The baseball field of Hanshin Koshien Stadium on a royal purple background
|
|
266
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/ballpark-desk-light.webp" alt="The baseball field of Hanshin Koshien Stadium on a royal purple background: the outfield fence at its published distances, 95 metres at the lines and 118 in the alleys, the infield dirt, and a red and a navy dugout panel with Japan's and the USA's flags." width="640">
|
|
267
267
|
</picture>
|
|
268
268
|
<br><em>A ballpark's fence, drawn through the distances its article publishes.</em>
|
|
269
269
|
</p>
|
|
@@ -368,7 +368,7 @@ console.log(items.map((item) => item.kind).join(), html.includes("preserve-3d"))
|
|
|
368
368
|
// net,netposts,antennae false
|
|
369
369
|
```
|
|
370
370
|
|
|
371
|
-
The flat drawing is the floor, turned by a drag, a swipe, the keys or four viewpoints, with what the rulebook stands on it at its height; each part is
|
|
371
|
+
The flat drawing is the floor, turned by a drag, a swipe, the keys or four viewpoints, with what the rulebook stands on it at its height; each part is one `matrix3d`, so there is no 3D context for a phone to lose. In the element: `<kyogijo-field sport="nhl" turn turn-view="broadcast">`. [The 3D view](./docs/turn.md).
|
|
372
372
|
|
|
373
373
|
<p align="center">
|
|
374
374
|
<picture>
|
|
@@ -496,7 +496,7 @@ console.log(svg.includes('viewBox="0 0 1200 675"'), svg.includes("Three ballpark
|
|
|
496
496
|
|
|
497
497
|
### Several surfaces on one floor
|
|
498
498
|
|
|
499
|
-
`drawMulti` lays the package's own surfaces out together for one large event, to scale, on one floor, with the officials' chairs and boards, and places for the event's words and marks (`sample: true` fills them with an invented event; [tournament layouts](./docs/multi.md)). Thirteen presets
|
|
499
|
+
`drawMulti` lays the package's own surfaces out together for one large event, to scale, on one floor, with the officials' chairs and boards, and places for the event's words and marks (`sample: true` fills them with an invented event; [tournament layouts](./docs/multi.md)). Thirteen presets; `multiFit` says whether a layout fits a hall, `stadium: true` sets it inside real stands, and `mountMultiTurn` turns it in 3D.
|
|
500
500
|
|
|
501
501
|
```ts
|
|
502
502
|
import { drawMulti, multiLayout } from "@johnmorrisdotca/kyogijo-stadiums/multi";
|
|
@@ -555,15 +555,32 @@ The [demo](https://johnmorrisdotca.github.io/kyogijo-stadiums/halls.html) turns
|
|
|
555
555
|
<br><em>Judges, in 3D.</em>
|
|
556
556
|
</p>
|
|
557
557
|
|
|
558
|
+
The broadcast view puts the mat large, with the officials on a board at its side; `judgingPrint` prints one mat to an A4 or US letter page.
|
|
559
|
+
|
|
560
|
+
<p align="center">
|
|
561
|
+
<picture>
|
|
562
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/judging-broadcast-3d-desk-dark.webp">
|
|
563
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/judging-broadcast-3d-desk-light.webp" alt="A kata mat in 3D from the Broadcast camera, with a dark board at its side listing each judge's number, name and ID." width="640">
|
|
564
|
+
</picture>
|
|
565
|
+
<br><em>The broadcast view.</em>
|
|
566
|
+
</p>
|
|
567
|
+
|
|
568
|
+
<p align="center">
|
|
569
|
+
<picture>
|
|
570
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/judging-print-a4-desk-dark.webp">
|
|
571
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/judging-print-a4-desk-light.webp" alt="An A4 page with the plan of one kata mat and the chart of its five judges under it." width="640">
|
|
572
|
+
</picture>
|
|
573
|
+
<br><em>One mat to an A4 page.</em>
|
|
574
|
+
</p>
|
|
558
575
|
|
|
559
576
|
### A table tennis area
|
|
560
577
|
|
|
561
|
-
A table
|
|
578
|
+
A table in the ITTF's playing area, 14 m by 7 m, with surrounds and chairs ([courts](./docs/courts.md#the-table-tennis-playing-area)).
|
|
562
579
|
|
|
563
580
|
<p align="center">
|
|
564
581
|
<picture>
|
|
565
582
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/tabletennis-area-desk-dark.webp">
|
|
566
|
-
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/tabletennis-area-desk-light.webp" alt="A table tennis table in its
|
|
583
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/tabletennis-area-desk-light.webp" alt="A table tennis table in its playing area, with surrounds and the umpires' chairs" width="660">
|
|
567
584
|
</picture>
|
|
568
585
|
<br><em>The table in its playing area.</em>
|
|
569
586
|
</p>
|
|
@@ -571,7 +588,7 @@ A table is drawn in the ITTF's playing area, 14 m by 7 m (`net.area` for Masters
|
|
|
571
588
|
<p align="center">
|
|
572
589
|
<picture>
|
|
573
590
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/tabletennis-area-3d-desk-dark.webp">
|
|
574
|
-
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/tabletennis-area-3d-desk-light.webp" alt="The same area in 3D
|
|
591
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/tabletennis-area-3d-desk-light.webp" alt="The same table area in 3D, from a low corner" width="660">
|
|
575
592
|
</picture>
|
|
576
593
|
<br><em>The same area in 3D.</em>
|
|
577
594
|
</p>
|
|
@@ -583,7 +600,7 @@ A table is drawn in the ITTF's playing area, 14 m by 7 m (`net.area` for Masters
|
|
|
583
600
|
<p align="center">
|
|
584
601
|
<picture>
|
|
585
602
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/judo-kata-desk-dark.webp">
|
|
586
|
-
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/judo-kata-desk-light.webp" alt="The IJF's kata area with the
|
|
603
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/judo-kata-desk-light.webp" alt="The IJF's kata area with the judges' seats above and the coach's chair below" width="660">
|
|
587
604
|
</picture>
|
|
588
605
|
<br><em>The kata area, its judges and the coach's chair.</em>
|
|
589
606
|
</p>
|
|
@@ -591,11 +608,31 @@ A table is drawn in the ITTF's playing area, 14 m by 7 m (`net.area` for Masters
|
|
|
591
608
|
<p align="center">
|
|
592
609
|
<picture>
|
|
593
610
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/judo-kata-tapes-desk-dark.webp">
|
|
594
|
-
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/judo-kata-tapes-desk-light.webp" alt="Three short white tapes
|
|
611
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/judo-kata-tapes-desk-light.webp" alt="Three short white tapes across the middle of a kata area" width="660">
|
|
595
612
|
</picture>
|
|
596
613
|
<br><em>Close up: the centre tape and the two starting tapes.</em>
|
|
597
614
|
</p>
|
|
598
615
|
|
|
616
|
+
### An MMA cage
|
|
617
|
+
|
|
618
|
+
[The combat sports page](./docs/combat.md).
|
|
619
|
+
|
|
620
|
+
<p align="center">
|
|
621
|
+
<picture>
|
|
622
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/mma-cage-desk-dark.webp">
|
|
623
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/mma-cage-desk-light.webp" alt="An MMA cage from above, with a score" width="660">
|
|
624
|
+
</picture>
|
|
625
|
+
<br><em>With a score.</em>
|
|
626
|
+
</p>
|
|
627
|
+
|
|
628
|
+
<p align="center">
|
|
629
|
+
<picture>
|
|
630
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/mma-cage-3d-desk-dark.webp">
|
|
631
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/mma-cage-3d-desk-light.webp" alt="The cage in 3D: a mesh fence on a solid platform" width="660">
|
|
632
|
+
</picture>
|
|
633
|
+
<br><em>The cage in 3D.</em>
|
|
634
|
+
</p>
|
|
635
|
+
|
|
599
636
|
### The element in a page
|
|
600
637
|
|
|
601
638
|
```html
|
|
@@ -669,7 +706,7 @@ Nothing is branded. The drawing is coloured by custom properties on its `svg`, w
|
|
|
669
706
|
|
|
670
707
|
## Limits
|
|
671
708
|
|
|
672
|
-
Each is held by a test:
|
|
709
|
+
Each is held by a test: forty sports, ten soccer pitches and ten providers, 94 ballparks, 64 grounds, six units, forty-eight frames, a drawing of under 22 kB. The table, made from the code, is [limits](./docs/limits.md).
|
|
673
710
|
|
|
674
711
|
## Accessibility
|
|
675
712
|
|
|
@@ -692,8 +729,7 @@ English and Japanese: the title, the description and the standard statuses of a
|
|
|
692
729
|
Not here yet, and each welcome as an [issue](https://github.com/johnmorrisdotca/kyogijo-stadiums/issues):
|
|
693
730
|
|
|
694
731
|
- **More surfaces**: the FIBA and college courts, the international rink, rugby pitches, a stadium's seating, soccer's beach and street formats.
|
|
695
|
-
- **
|
|
696
|
-
- **More parks of the past**: the grounds of the 19th century, and the parks whose articles give no distances yet (the Kingdome, Joe Robbie Stadium, the Los Angeles Coliseum), when they do.
|
|
732
|
+
- **More parks of the past**: the 19th-century grounds, and the parks whose articles give no distances yet (the Kingdome, Joe Robbie Stadium).
|
|
697
733
|
- **More charts on data layers**: a formation chart, a pass sonar chart and a Voronoi chart of their own (the layers exist; see [team shape](./docs/team-shape.md)).
|
|
698
734
|
- **Football in a different standard**: the college and high-school hash marks.
|
|
699
735
|
|
|
@@ -703,8 +739,6 @@ Left out on purpose: statistics, rosters and schedules. Kyogijo Stadiums draws t
|
|
|
703
739
|
|
|
704
740
|
The drawing is plain functions over plain data with no DOM and no dependency. The dimensions are in one file, the ballparks are generated from a reviewed list, and each surface is a function that returns its markup and the places the teams and the score go. Every entry point stands apart, so that importing the geometry, the parks or the grounds loads nothing else. The files and what each is for are in [architecture](./docs/architecture.md).
|
|
705
741
|
|
|
706
|
-
Tests sit beside the code. `scripts/` builds the demo and the docs site, checks the packed package and the README's examples, and takes the README's pictures; `demo/` is the page and the frame; `e2e/` plays the demo and the docs in a real browser.
|
|
707
|
-
|
|
708
742
|
## The name
|
|
709
743
|
|
|
710
744
|
*Kyogijo* (競技場, kyōgijō, きょうぎじょう) is Japanese for a sports ground: the place a contest is held. "Stadiums" is added in English, so that the name says what it draws; in Japanese the name stays 競技場. It is written with 競技, "contest" or "competition", and 場, "place", and said in five beats, *kyo-u-gi-jo-u*. In Japanese it is the general word for a place where sport is played, a stadium or a ground; the package uses it as a name for every surface it draws, the field, the rink, the court and the diamond. The long vowels are written without a macron in the package's name, as in the other packages of the family.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { MmaFigures } from "../leagues/combat.ts";
|
|
2
|
+
import { type MBox, type MMark, type Parts } from "./parts.ts";
|
|
3
|
+
/** One gate of the cage: the flat it is in, the two ends of its opening, and the way it opens (outward). */
|
|
4
|
+
export interface CageGate {
|
|
5
|
+
side: "north" | "south";
|
|
6
|
+
/** The number of the flat it is in, counted from the first corner. */
|
|
7
|
+
flat: number;
|
|
8
|
+
from: readonly [number, number];
|
|
9
|
+
to: readonly [number, number];
|
|
10
|
+
}
|
|
11
|
+
/** What a cage plan is. */
|
|
12
|
+
export interface CageLayout {
|
|
13
|
+
parts: Parts;
|
|
14
|
+
/** The platform, which is the surface's own box: the cage's canvas and the apron round it. */
|
|
15
|
+
platform: MBox;
|
|
16
|
+
extent: MBox;
|
|
17
|
+
centre: [number, number];
|
|
18
|
+
/** The cage's width across the flats, and the distance from its middle to a post. */
|
|
19
|
+
width: number;
|
|
20
|
+
apothem: number;
|
|
21
|
+
corner: number;
|
|
22
|
+
/** The posts, one at each corner of the cage, as points on the platform. */
|
|
23
|
+
posts: [number, number][];
|
|
24
|
+
/** The gates, and the steps (the boxes outside the platform's edge, where a gate faces). */
|
|
25
|
+
gates: CageGate[];
|
|
26
|
+
steps: MBox[];
|
|
27
|
+
/** The height of the platform over the floor of the building and of the fence over the canvas, in metres. */
|
|
28
|
+
height: number;
|
|
29
|
+
fence: number;
|
|
30
|
+
marks: MMark[];
|
|
31
|
+
ranges: Record<string, MBox>;
|
|
32
|
+
}
|
|
33
|
+
/** The width the options ask for, held to 20 feet to 32 feet. */
|
|
34
|
+
export declare const cageWidth: (asked: number | undefined, fig: MmaFigures) => number;
|
|
35
|
+
/** The platform's height the options ask for, held to 0 to 4 feet. */
|
|
36
|
+
export declare const cageHeight: (asked: number | undefined, fig: MmaFigures) => number;
|
|
37
|
+
/** The fence's height the options ask for, held to 5 feet to 7 feet. */
|
|
38
|
+
export declare const fenceHeight: (asked: number | undefined, fig: MmaFigures) => number;
|
|
39
|
+
/** The plan of the cage the options ask for. */
|
|
40
|
+
export declare function cageParts(fig: MmaFigures, o: {
|
|
41
|
+
width: number;
|
|
42
|
+
height: number;
|
|
43
|
+
fence: number;
|
|
44
|
+
gates: boolean;
|
|
45
|
+
steps: boolean;
|
|
46
|
+
}): CageLayout;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// An MMA cage (a fenced area): the platform it stands on with its steps, the canvas inside the fence, the eight-sided fence with its two gates and its padded posts, from the rules a commission or the IMMAF
|
|
2
|
+
// writes for a fenced area (the Nevada Rules of Unarmed Combat 5.010 3, the IMMAF's Unified Rules for amateur competition). The cage is named for what it is, an eight-sided cage: no promotion's own name is used.
|
|
3
|
+
// In metres, the origin at the top left of the platform, north at the top. Nothing here draws SVG.
|
|
4
|
+
import { arc, line } from "../fields.kit.js";
|
|
5
|
+
import { discArea, rectArea, within } from "./kit.js";
|
|
6
|
+
import { emptyParts, grow, union } from "./parts.js";
|
|
7
|
+
import { num } from "../format.js";
|
|
8
|
+
/** The width the options ask for, held to 20 feet to 32 feet. */
|
|
9
|
+
export const cageWidth = (asked, fig) => (asked === undefined ? fig.width.drawn : within(asked, fig.width.min, fig.width.max, "The cage's width", "NRUC 5.010 3(a) and the IMMAF's rules"));
|
|
10
|
+
/** The platform's height the options ask for, held to 0 to 4 feet. */
|
|
11
|
+
export const cageHeight = (asked, fig) => (asked === undefined ? fig.platform.height.drawn : within(asked, fig.platform.height.min, fig.platform.height.max, "The cage's platform", "NRUC 5.010 3(c)"));
|
|
12
|
+
/** The fence's height the options ask for, held to 5 feet to 7 feet. */
|
|
13
|
+
export const fenceHeight = (asked, fig) => (asked === undefined ? fig.fence.drawn : within(asked, fig.fence.min, fig.fence.max, "The cage's fence", "NRUC 5.010 3(d)"));
|
|
14
|
+
const rd = (v) => Math.round(v * 1000) / 1000;
|
|
15
|
+
/** The plan of the cage the options ask for. */
|
|
16
|
+
export function cageParts(fig, o) {
|
|
17
|
+
const a = o.width / 2;
|
|
18
|
+
const corner = a / Math.cos(Math.PI / fig.sides);
|
|
19
|
+
const side = o.width + 2 * fig.apron;
|
|
20
|
+
const c = side / 2;
|
|
21
|
+
const platform = { x0: 0, y0: 0, x1: side, y1: side };
|
|
22
|
+
const parts = emptyParts();
|
|
23
|
+
// The corners of the cage: the flats face the four sides of the platform and the four diagonals, and the first corner lies a sixteenth of a turn clockwise of north.
|
|
24
|
+
const step = (2 * Math.PI) / fig.sides;
|
|
25
|
+
const start = -Math.PI / 2 + step / 2;
|
|
26
|
+
const posts = Array.from({ length: fig.sides }, (_, i) => [rd(c + corner * Math.cos(start + i * step)), rd(c + corner * Math.sin(start + i * step))]);
|
|
27
|
+
parts.areas.push(rectArea("platform", "platform", "ky-bud-platform", platform));
|
|
28
|
+
parts.areas.push({ id: "canvas", feature: "canvas", cls: "ky-bud-t1", d: `M${posts.map(([x, y]) => `${num(x)} ${num(y)}`).join("L")}Z` });
|
|
29
|
+
// The steps, one at each gate: three treads, outside the platform's edge.
|
|
30
|
+
const steps = [];
|
|
31
|
+
const s = fig.platform.steps;
|
|
32
|
+
const gateSides = ["north", "south"];
|
|
33
|
+
if (o.steps && o.gates) {
|
|
34
|
+
for (const side_ of gateSides) {
|
|
35
|
+
const depth = s.treads * s.tread;
|
|
36
|
+
const b = side_ === "north" ? { x0: c - s.width / 2, y0: -depth, x1: c + s.width / 2, y1: 0 } : { x0: c - s.width / 2, y0: side, x1: c + s.width / 2, y1: side + depth };
|
|
37
|
+
steps.push(b);
|
|
38
|
+
for (let t = 0; t < s.treads; t += 1) {
|
|
39
|
+
const y0 = side_ === "north" ? -depth + t * s.tread : side + t * s.tread;
|
|
40
|
+
parts.areas.push(rectArea(`step-${side_}-${t + 1}`, "steps", "ky-bud-step", { x0: b.x0, y0, x1: b.x1, y1: y0 + s.tread }));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// The fence is one line along each flat; where a gate is, the line stops at its opening and the gate's swing is drawn dashed, outward.
|
|
45
|
+
const gates = [];
|
|
46
|
+
const g = fig.gates.width;
|
|
47
|
+
const gateAt = (i) => (o.gates ? (i === 7 ? "north" : i === 3 ? "south" : undefined) : undefined);
|
|
48
|
+
// Flat i runs from corner i to corner i+1; the flat that faces north is the last (corner 7 to corner 0), the one that faces south is 3.
|
|
49
|
+
for (let i = 0; i < fig.sides; i += 1) {
|
|
50
|
+
const p = posts[i];
|
|
51
|
+
const q = posts[(i + 1) % fig.sides];
|
|
52
|
+
const gate = gateAt(i);
|
|
53
|
+
if (gate === undefined) {
|
|
54
|
+
parts.shapes.push(line(`fence-${i + 1}`, "fence", p[0], p[1], q[0], q[1], { w: 0.1, cls: "ky-bud-ink", least: 0.1 }));
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
// Along the flat, from p to q, the opening lies in the middle.
|
|
58
|
+
const len = Math.hypot(q[0] - p[0], q[1] - p[1]);
|
|
59
|
+
const ux = (q[0] - p[0]) / len;
|
|
60
|
+
const uy = (q[1] - p[1]) / len;
|
|
61
|
+
const m = [(p[0] + q[0]) / 2, (p[1] + q[1]) / 2];
|
|
62
|
+
const from = [rd(m[0] - (ux * g) / 2), rd(m[1] - (uy * g) / 2)];
|
|
63
|
+
const to = [rd(m[0] + (ux * g) / 2), rd(m[1] + (uy * g) / 2)];
|
|
64
|
+
gates.push({ side: gate, flat: i, from, to });
|
|
65
|
+
parts.shapes.push(line(`fence-${i + 1}a`, "fence", p[0], p[1], from[0], from[1], { w: 0.1, cls: "ky-bud-ink", least: 0.1 }), line(`fence-${i + 1}b`, "fence", to[0], to[1], q[0], q[1], { w: 0.1, cls: "ky-bud-ink", least: 0.1 }));
|
|
66
|
+
// The gate opens outward, about the end of the opening that lies on the right of the north gate and on the left of the south one (the cage is the same turned half a turn).
|
|
67
|
+
const hinge = to;
|
|
68
|
+
parts.shapes.push(arc(`gate-${gate}`, "gates", hinge[0], hinge[1], g, gate === "north" ? 180 : 0, gate === "north" ? 270 : 90, { w: 0.04, dash: [0.14, 0.1], cls: "ky-bud-ink", least: 0.04 }));
|
|
69
|
+
}
|
|
70
|
+
gates.sort((x, y) => (x.side === "north" ? -1 : 1) - (y.side === "north" ? -1 : 1));
|
|
71
|
+
// The posts, padded, drawn over the fence.
|
|
72
|
+
posts.forEach(([x, y], i) => parts.areas.push(discArea(`post-${i + 1}`, "posts", "ky-bud-pad", x, y, fig.post.pad / 2)));
|
|
73
|
+
const extent = grow(union([platform, ...steps]), 0.6);
|
|
74
|
+
const north = gates.find((x) => x.side === "north");
|
|
75
|
+
const ranges = {
|
|
76
|
+
cage: { x0: c - a - 0.3, y0: c - a - 0.3, x1: c + a + 0.3, y1: c + a + 0.3 },
|
|
77
|
+
};
|
|
78
|
+
if (north !== undefined)
|
|
79
|
+
ranges.gate = { x0: c - 2.4, y0: -0.5 - s.treads * s.tread, x1: c + 2.4, y1: c - a + 2 };
|
|
80
|
+
const marks = [
|
|
81
|
+
{ id: "cage-canvas", x: c - a * 0.35, y: c + a * 0.25, side: "bottom" },
|
|
82
|
+
{ id: "cage-fence", x: c + a, y: c + a * 0.35, side: "bottom" },
|
|
83
|
+
{ id: "cage-post", x: posts[1][0], y: posts[1][1], side: "top" },
|
|
84
|
+
{ id: "cage-platform", x: side * 0.04, y: side * 0.1, side: "top" },
|
|
85
|
+
];
|
|
86
|
+
if (north !== undefined)
|
|
87
|
+
marks.push({ id: "cage-gate", x: (north.from[0] + north.to[0]) / 2, y: north.from[1] + 0.2, side: "top" });
|
|
88
|
+
if (steps.length > 0)
|
|
89
|
+
marks.push({ id: "cage-steps", x: c, y: side + s.treads * s.tread * 0.5, side: "bottom" });
|
|
90
|
+
return { parts, platform, extent, centre: [c, c], width: o.width, apothem: a, corner, posts, gates, steps, height: o.height, fence: o.fence, marks, ranges };
|
|
91
|
+
}
|
package/dist/budo/describe.js
CHANGED
|
@@ -35,6 +35,11 @@ export function budoAbout(o, language, plan = budoPlan(o)) {
|
|
|
35
35
|
const bare = !L.parts.areas.some((a) => a.id === "tawara");
|
|
36
36
|
return fill(bare ? words.sumoBare : words.sumo, { platform: trim(fig.platform), height: cm(L.height), circle: trim(fig.circle), count: fig.tawara.count });
|
|
37
37
|
}
|
|
38
|
+
if (plan.mma !== undefined) {
|
|
39
|
+
const L = plan.mma;
|
|
40
|
+
const platform = L.height > 0.0005 ? fill(words.mmaPlatform, { height: cm(L.height) }) : words.mmaFloor;
|
|
41
|
+
return fill(words.mma, { width: trim(L.width), feet: trim(L.width / 0.3048), fence: cm(L.fence), platform });
|
|
42
|
+
}
|
|
38
43
|
if (plan.kyudo !== undefined) {
|
|
39
44
|
const L = plan.kyudo;
|
|
40
45
|
const fig = plan.figures;
|
|
@@ -67,6 +72,12 @@ export function budoSentences(o, language, plan = budoPlan(o)) {
|
|
|
67
72
|
out.push(words.karateOfficials);
|
|
68
73
|
if (plan.sumo !== undefined && plan.areas.some((a) => a.feature === "tassels"))
|
|
69
74
|
out.push(words.tassels);
|
|
75
|
+
if (plan.mma !== undefined) {
|
|
76
|
+
if (plan.mma.gates.length > 0)
|
|
77
|
+
out.push(words.mmaGates);
|
|
78
|
+
if (plan.mma.steps.length > 0)
|
|
79
|
+
out.push(words.mmaSteps);
|
|
80
|
+
}
|
|
70
81
|
if (plan.dojo !== undefined) {
|
|
71
82
|
const L = plan.dojo;
|
|
72
83
|
out.push(fill(words.dojoKamiza, { side: words.sides[L.kamiza] }));
|
package/dist/budo/looks.js
CHANGED
|
@@ -14,6 +14,8 @@ function pair(light, k = 0.34) {
|
|
|
14
14
|
}
|
|
15
15
|
return { light, dark };
|
|
16
16
|
}
|
|
17
|
+
/** A look whose dark platform is a lighter one than the plain dimming makes, so that it stands out from the dark floor of the hall under it. */
|
|
18
|
+
const lifted = (p, floor) => ({ light: p.light, dark: { ...p.dark, floor } });
|
|
17
19
|
const FLOOR = "#c9a26a";
|
|
18
20
|
const WALLS = "#d8d0bd";
|
|
19
21
|
const COMMON = { apron: "#d6d3cb", free: "#e8e4d8", floor: FLOOR, boards: WALLS };
|
|
@@ -44,6 +46,12 @@ export const BUDO_LOOKS = Object.freeze({
|
|
|
44
46
|
blond: pair({ ...COMMON, surface: "#e0bf8a", alt: "#d3b27c", red: "#b32a2f", floor: "#e0bf8a", free: "#ece4d3" }),
|
|
45
47
|
},
|
|
46
48
|
sumo: { clay: pair({ ...COMMON, surface: "#b0794a", alt: "#a06c40", red: "#b32a2f", dirt: "#b0794a", sand: "#e8dcc2", straw: "#c8a45c" }) },
|
|
49
|
+
// The cage's canvas, over the platform's dark deck: a grey canvas (the default), black, and blue. Ours: no rule paints a cage.
|
|
50
|
+
mma: {
|
|
51
|
+
grey: lifted(pair({ ...COMMON, surface: "#8d949b", alt: "#6f767d", red: "#b32a2f", floor: "#43484e" }), "#444a52"),
|
|
52
|
+
black: lifted(pair({ ...COMMON, surface: "#2b2e33", alt: "#1f2226", red: "#b32a2f", floor: "#24272b" }), "#3b3f45"),
|
|
53
|
+
blue: lifted(pair({ ...COMMON, surface: "#3a68ad", alt: "#2b528d", red: "#b32a2f", floor: "#2c3440" }), "#3a4452"),
|
|
54
|
+
},
|
|
47
55
|
kyudo: { wood: pair({ ...COMMON, surface: "#9db57d", alt: "#d8cfb0", red: "#b32a2f", floor: "#b98c58", dirt: "#c9ad7a" }) },
|
|
48
56
|
});
|
|
49
57
|
/** The names of a sport's looks, the default first. */
|
package/dist/budo/plan.d.ts
CHANGED
|
@@ -7,9 +7,10 @@ import { type KarateLayout } from "./karate.ts";
|
|
|
7
7
|
import { type KendoLayout } from "./kendo.ts";
|
|
8
8
|
import { type KyudoLayout } from "./kyudo.ts";
|
|
9
9
|
import { boxD } from "./kit.ts";
|
|
10
|
+
import { type CageLayout } from "./cage.ts";
|
|
10
11
|
import { type MBox, type MMark, type MRange } from "./parts.ts";
|
|
11
12
|
import { type SumoLayout } from "./sumo.ts";
|
|
12
|
-
import type { BudoKind } from "./types.ts";
|
|
13
|
+
import type { BudoKind, CombatKind } from "./types.ts";
|
|
13
14
|
export type { MBox, MMark, MRange };
|
|
14
15
|
/** The apothem of the Nippon Budokan's arena, an octagon 55 m across the flats (the Budokan's leaflet). */
|
|
15
16
|
export declare const BUDOKAN_ARENA = 27.5;
|
|
@@ -48,11 +49,18 @@ export interface BudoPlan {
|
|
|
48
49
|
sumo?: SumoLayout;
|
|
49
50
|
kyudo?: KyudoLayout;
|
|
50
51
|
dojo?: DojoLayout;
|
|
52
|
+
mma?: CageLayout;
|
|
51
53
|
}
|
|
52
54
|
/** The sports of the budō family. */
|
|
53
55
|
export declare const BUDO_SPORTS: readonly BudoKind[];
|
|
54
56
|
/** True for a sport of the budō family. */
|
|
55
|
-
export declare const isBudoSport: (sport: string) => sport is BudoKind
|
|
57
|
+
export declare const isBudoSport: (sport: string) => sport is Exclude<BudoKind, CombatKind>;
|
|
58
|
+
/** The combat sports the engine of the budō also draws: the MMA cage. */
|
|
59
|
+
export declare const COMBAT_SPORTS: readonly CombatKind[];
|
|
60
|
+
/** True for a combat sport (the MMA cage). */
|
|
61
|
+
export declare const isCombatSport: (sport: string) => sport is CombatKind;
|
|
62
|
+
/** True for a sport this engine draws: a sport of the budō or a combat sport. */
|
|
63
|
+
export declare const isMatSport: (sport: string) => sport is BudoKind;
|
|
56
64
|
/** The league a set of options asks for: a rulebook's, else the sport's own. */
|
|
57
65
|
export declare function budoLeague(o: Pick<SurfaceOptions, "sport" | "league" | "budo" | "dojo">): BudoLeague;
|
|
58
66
|
/** The octagon of the Budokan's arena as a path, centred on (cx, cy). */
|
package/dist/budo/plan.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { chooseLeague } from "../leagues.js";
|
|
2
2
|
import { BUDO_LEAGUES, DOJO_LEAGUES, JUDO_LEAGUES, KARATE_LEAGUES, KENDO_LEAGUES, KYUDO_LEAGUES, SUMO_LEAGUES } from "../leagues/budo.js";
|
|
3
|
+
import { MMA_LEAGUES } from "../leagues/combat.js";
|
|
3
4
|
import { dojoLayout, dojoLeague, dojoSpecOf } from "./dojo.js";
|
|
4
5
|
import { contestOf, gridOf, judoParts, matOf, safetyOf, snapTo } from "./judo.js";
|
|
5
6
|
import { karateParts } from "./karate.js";
|
|
6
7
|
import { kendoParts, kendoSide } from "./kendo.js";
|
|
7
8
|
import { kyudoParts, shootersOf } from "./kyudo.js";
|
|
8
9
|
import { boxD } from "./kit.js";
|
|
10
|
+
import { cageHeight, cageParts, cageWidth, fenceHeight } from "./cage.js";
|
|
9
11
|
import { emptyParts, grow, union } from "./parts.js";
|
|
10
12
|
import { dohyoHeight, sumoParts } from "./sumo.js";
|
|
11
13
|
import { lookOf } from "./looks.js";
|
|
@@ -16,7 +18,13 @@ const isBudoLeague = (l) => typeof l === "object" && l !== null && BUDO_LEAGUES.
|
|
|
16
18
|
export const BUDO_SPORTS = Object.freeze(["judo", "karate", "kendo", "sumo", "kyudo", "dojo"]);
|
|
17
19
|
/** True for a sport of the budō family. */
|
|
18
20
|
export const isBudoSport = (sport) => BUDO_SPORTS.includes(sport);
|
|
19
|
-
|
|
21
|
+
/** The combat sports the engine of the budō also draws: the MMA cage. */
|
|
22
|
+
export const COMBAT_SPORTS = Object.freeze(["mma"]);
|
|
23
|
+
/** True for a combat sport (the MMA cage). */
|
|
24
|
+
export const isCombatSport = (sport) => COMBAT_SPORTS.includes(sport);
|
|
25
|
+
/** True for a sport this engine draws: a sport of the budō or a combat sport. */
|
|
26
|
+
export const isMatSport = (sport) => isBudoSport(sport) || isCombatSport(sport);
|
|
27
|
+
const OWN = { judo: JUDO_LEAGUES, karate: KARATE_LEAGUES, kendo: KENDO_LEAGUES, sumo: SUMO_LEAGUES, kyudo: KYUDO_LEAGUES, dojo: DOJO_LEAGUES, mma: MMA_LEAGUES };
|
|
20
28
|
/** What `budo.style` asks of a judo area: true for a kata area, false for a contest area, undefined for neither said. @throws TypeError for a value that is not `shiai` or `kata`. */
|
|
21
29
|
function kataOf(style) {
|
|
22
30
|
if (style === undefined)
|
|
@@ -118,6 +126,12 @@ export function budoPlan(o) {
|
|
|
118
126
|
const ranges = { shajo: L.shajo, yamichi: L.yamichi, azuchi: grow(L.azuchi, 0.8) };
|
|
119
127
|
return finish({ box: L.range, extent: L.extent, areas: L.parts.areas, shapes: L.parts.shapes, lineWidth: 0.05, ranges, marks: L.marks, centre: { x: (L.shajo.x0 + L.shajo.x1) / 2, y: (L.shajo.y0 + L.shajo.y1) / 2, r: 1.5 }, kyudo: L });
|
|
120
128
|
}
|
|
129
|
+
case "mma": {
|
|
130
|
+
const f = fig;
|
|
131
|
+
const L = cageParts(f, { width: cageWidth(style.size, f), height: cageHeight(style.height, f), fence: fenceHeight(style.fence, f), gates: flag(style.gates, true, "budo.gates"), steps: flag(style.steps, true, "budo.steps") });
|
|
132
|
+
const ranges = { ...L.ranges, half: halves(L.platform) };
|
|
133
|
+
return finish({ box: L.platform, extent: L.extent, areas: L.parts.areas, shapes: L.parts.shapes, lineWidth: f.post.diameter, ranges, marks: L.marks, centre: { x: L.centre[0], y: L.centre[1], r: L.apothem * 0.35 }, mma: L });
|
|
134
|
+
}
|
|
121
135
|
default: {
|
|
122
136
|
const L = dojoLayout(o.dojo ?? {}, dojoLeague(league.id));
|
|
123
137
|
const f = L.floor;
|