@johnmorrisdotca/kyogijo-stadiums 0.21.0 → 0.23.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,23 @@ All notable changes to this project are written here. The format follows
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.23.0] - 2026-10-20
11
+
12
+ ### Added
13
+
14
+ - **The professional wrestling ring** (`sport: "prowrestling"`, [the combat sports page](./docs/combat.md)): the boxing ring's engine with three ropes that are not tied together, a canvas with an apron of a foot, a platform of 40 inches, four padded posts and steel steps at two corners. No rulebook gives a wrestling ring's figures, so every one is typical and says so: most rings are 14 to 20 feet a side between the ropes, 20 feet drawn (`budo.size`, 4.27 m to 6.10 m); the ropes are at about 1, 3 and 5 feet; the platform (`budo.height`) is 0 to 6 feet. The sources (English Wikipedia's "Wrestling ring", Dimensions.com and a 2012 description of a large promotion's ring) differ, the page says where, and the figures that cannot be right (an 8 foot top rope, posts of 9 to 10 feet) are not used. The league is `pro-ring`, the looks are the boxing ring's, `RANGES.prowrestling` has `ropes` and `half`, and in 3D the ring stands as the boxing ring does with three ropes and no ties. It is the forty-third sport.
15
+ - **A figure of a ring is now the league's:** `RingFigures` carries whether the ropes are tied and whether the corners are the boxers' (a boxing ring's are, a wrestling ring's are not), and the number of sets of steps.
16
+ - **The demo** has the ring in its sport picker, with its looks, the score and the 3D view.
17
+
18
+
19
+ ## [0.22.0] - 2026-10-20
20
+
21
+ ### Added
22
+
23
+ - **The wrestling mats** (`sport: "wrestling"`, [the combat sports page](./docs/combat.md)): the UWW's mat (freestyle, Greco-Roman and women's wrestling are wrestled on the same one: a circle of 9 m with a protection area of 1.5 m, an orange passivity band of 1 m inside the circle, a central circle of 1 m, a platform of 0.80 to 1.10 m), the NCAA's folkstyle mat (a competition circle of 32 to 42 feet with a 2 inch line, a matted area of at least 5 feet, two starting lines closed by a green and a red line) and the high schools' (a circle of at least 28 feet, a safety mat of about 5 feet, the circle of 10 feet, optional from 2024-25, the same starting lines), to scale. The leagues are `uww`, `ncaa-wrestling` and `nfhs-wrestling`; `budo.size` (the circle), `budo.height` (the platform), `budo.circle` and `budo.start` stay within each league and refuse a number outside it; the looks are `blue-red`, `green-beige` and `yellow-blue`; `RANGES.wrestling` has `start`, `passivity` (the UWW's) and `half`. In 3D the UWW's platform is a solid block with the mat as its top, and a folkstyle mat lies on the floor. A figure that is the rule's, one that is typical and one that is ours are told apart in [Sources](./docs/sources.md#the-combat-sports). It is the forty-second sport.
24
+ - **The demo** has the mats in its sport picker, with their league and looks, the score of a bout and the 3D view.
25
+
26
+
10
27
  ## [0.21.0] - 2026-10-20
11
28
 
12
29
  ### Added
package/NOTICE.md CHANGED
@@ -35,7 +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 and the boxing ring | 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), Wisconsin's SPS 192.38, the WBC Amateur competition rules (2026), Ontario's Amateur combative sport rules: Boxing (Part II), and the English Wikipedia articles "Mixed martial arts cage" (revision 1377260922), "Mixed martial arts" (revision 1381048799) and "Boxing ring" (revision 1370389178), for the sizes that are typical | Facts, CC BY-SA 4.0 for the Wikipedia text read |
38
+ | `leagues`: the MMA cage, the boxing ring the wrestling mats and the professional wrestling ring | 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), Wisconsin's SPS 192.38, the UWW's Wrestling Rules (January 2026), the NCAA's Wrestling Rules (2025-26 and 2026-27), the NFHS's mat rules as the KHSAA, Resilite and the NJSIAA quote them, the WBC Amateur competition rules (2026), Ontario's Amateur combative sport rules: Boxing (Part II), Dimensions.com's professional wrestling ring page, a 2012 blog's description of a large promotion's ring, and the English Wikipedia articles "Wrestling ring" (revision 1379090810), "Mixed martial arts cage" (revision 1377260922), "Mixed martial arts" (revision 1381048799) and "Boxing ring" (revision 1370389178), for the sizes that are typical | Facts, CC BY-SA 4.0 for the Wikipedia text read |
39
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 |
40
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/) |
41
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 surfaces of forty-one sports, from football and curling to the budō and the combat sports, 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, 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>
4
+ The surfaces of forty-three sports, from football and curling to the budō and the combat sports, 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, 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>
@@ -72,41 +72,41 @@ console.log(svg.startsWith("<svg"), svg.includes("USA 3, Canada 2"));
72
72
 
73
73
  ## Features
74
74
 
75
- - **Forty-one 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ō, the MMA cage and the boxing ring. Every figure is cited in [sources](./docs/sources.md). [The surfaces](./docs/surfaces.md).
75
+ - **Forty-three 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ō, the MMA cage, the rings and the wrestling mats. 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
- - **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
- - **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 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
- - **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
- - **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
- - **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).
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, `show: "folded"` for the whole sheet with both houses enlarged beside it. [Curling](./docs/curling.md).
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, 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 50 or 25 m pool with its lanes, ropes, blocks and touch panels; the water polo field; the diving well; the artistic swimming area. A race's lanes carry names, flags, places and times, with a replay. [Pools](./docs/pools.md).
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 runs, wickets and overs. [Field sports](./docs/field-sports.md).
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, with lane draws, results and a race replay. [The athletics stadium](./docs/athletics.md).
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 with its judges' seats; and results, a race replay and the elements of a programme. [The skating rinks](./docs/skating.md).
85
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
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
- - **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
- - **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).
89
+ - **Walls and quirks.** How high the fence stands, stretch by stretch and season by season (the Green Monster at 37 feet 2 inches) (`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
+ - **Special games.** A surface set inside another, to scale: an NHL rink on a ballpark's infield or a football stadium's field or a baseball field laid over a London stadium's pitch. 18 games, each cited. [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).
92
92
  - **Score mode.** Each team's name and logo on its side (the end zones, the ends of the ice, the halves of the court, the dugouts) and the score large in the middle, with the competition, the status and the date, and the winner emphasised; a flag or a crest can be round, in a circle with a ring (`markShape: "round"`). [Score and layout](./docs/score.md#round-marks).
93
93
  - **The situation of a game.** `situation` draws what is happening: hockey's power play or empty net and a shootout; baseball's runners lit on the diamond with a scorebug; football's line of scrimmage, first-down line, red zone and down-and-distance tag, with a drive chart; in the badge and the compact card too. [The situation](./docs/situation.md).
94
- - **Lineups.** A `lineup` layer places a team's players by position code (`GK`, `CB`, `HK`, `C`) with no coordinates: it reads where each stands from a formation (36 of them, in 13 sports), draws a disc or a jersey with the shirt number and the name under it, a captain's C and a flag, and puts the visitors at the other end. [Lineups](./docs/team-shape.md#lineups).
95
- - **A pageant.** Each team's flag or crest laid large over its half of the surface: `pageant: "carpet"` (a flag at its own ratio with a border) or `"stage"` (a crest on a round disc with a gold ring), an emblem or a trophy in the centre circle, the score in the middle or in the strip, with an entrance in CSS for readers who have not asked for less motion. [The pageant](./docs/pageant.md).
96
- - **Trophies, medals, balls and crests, by id.** `useEmblems(renderEmblem)` plugs in the sister package [Dougu Sports](https://johnmorrisdotca.github.io/dougu-sports/) in one line, and an id goes wherever a logo, a flag or a mark is taken: `logo: "crest:shield"`, `pageant: { emblem: "trophy:hockey-cup" }`, `"ball:puck"`. Kyogijo bundles no emblem and keeps zero dependencies. [Emblems](./docs/emblems.md).
97
- - **Country flags, by code.** `useFlags(render)` plugs in the sister package [Hata](https://github.com/johnmorrisdotca/hata) through a small adapter, and a team's `flag: "CA"` is its flag: round in a round mark, at its own proportions on a banner, a badge or a carpet. Kyogijo bundles no flag and keeps zero dependencies. [Flags](./docs/flags.md).
94
+ - **Lineups.** A `lineup` layer places a team's players by position code (`GK`, `CB`, `HK`, `C`) with no coordinates: it reads where each stands from a formation (36 of them, in 13 sports), draws a disc or a jersey with the shirt number and the name under it, a captain's C and a flag. [Lineups](./docs/team-shape.md#lineups).
95
+ - **A pageant.** Each team's flag or crest laid large over its half of the surface: `pageant: "carpet"` (a flag at its own ratio with a border) or `"stage"` (a crest on a round disc with a gold ring), an emblem or a trophy in the centre circle, the score in the middle or in the strip; an entrance in CSS for readers who have not asked for less motion. [The pageant](./docs/pageant.md).
96
+ - **Trophies, medals, balls and crests, by id.** `useEmblems(renderEmblem)` plugs in the sister package [Dougu Sports](https://johnmorrisdotca.github.io/dougu-sports/) in one line, and an id goes wherever a logo, a flag or a mark is taken: `logo: "crest:shield"`, `pageant: { emblem: "trophy:hockey-cup" }`, `"ball:puck"`. [Emblems](./docs/emblems.md).
97
+ - **Country flags, by code.** `useFlags(render)` plugs in the sister package [Hata](https://github.com/johnmorrisdotca/hata) through a small adapter, and a team's `flag: "CA"` is its flag: round in a round mark, at its own proportions on a banner, a badge or a carpet. [Flags](./docs/flags.md).
98
98
  - **Zoom to a part of a surface.** `range: "offensive-zone"` crops a drawing to a rink's zone, a half court, the paint, the red zone, a soccer half, third or penalty area, the infield, a curling house, or a box of your own in any frame, with its data, heat, labels and score following. [Display ranges](./docs/ranges.md).
99
99
  - **Wide, tall or fit the box.** Every surface lies wide or tall: tall turns it a quarter, keeps every word upright and puts the teams top and bottom. With `orientation: "auto"` the browser helpers follow the box.
100
100
  - **Where a point lies, by the rules, and a click as a place.** `zoneAt("nhl", [69, 22], { frame: "nhl-api" })` names the zone and the area in it from the surface's own figures, with `isThreePointer`, `inSlot`, `isFair`, `isHomeRun` and the like; `clientPointToField(svg, x, y, { provider })` is a pointer's place in any of the frames, with the zone. [Zones](./docs/zones.md), [pointing](./docs/pointer.md).
101
- - **Goals, the strike zone and the stumps, end-on.** A goal mouth for six sports with the shots laid on it and its zones, the catcher's view of the strike zone with its pitches numbered, and the wicket from the bowler's end with its line and length zones. [Targets](./docs/targets.md).
102
- - **Data on the surface.** Points, lines, arrows, text, heat maps, hexagons, zone charts and density contours over any surface, in its feet or a data provider's frame, cut to its outline, with a table for each layer; ready-made shot and pass charts. [Data layers](./docs/layers.md), [charts](./docs/charts.md).
103
- - **Small multiples and backgrounds.** `drawGrid` puts many drawings in one SVG, under a title and a subtitle, over a credit line, with a key they share, in a size for a social card, a square post or a phone; `background` lays a quiet pattern (felt, grass, wood, ice, paper, a grid, dots) or a photograph behind a drawing or a grid. [Layouts and backgrounds](./docs/layouts.md).
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).
101
+ - **Goals, the strike zone and the stumps, end-on.** A goal mouth for six sports with the shots laid on it, the catcher's view of the strike zone with its pitches numbered, and the wicket from the bowler's end with its zones. [Targets](./docs/targets.md).
102
+ - **Data on the surface.** Points, lines, arrows, text, heat maps, hexagons, zone charts and density contours over any surface, in its own feet or a provider's frame; ready-made shot and pass charts. [Data layers](./docs/layers.md), [charts](./docs/charts.md).
103
+ - **Small multiples and backgrounds.** `drawGrid` puts many drawings in one SVG, under a title and a subtitle, over a credit line, with a key they share, in a size for a card or a phone; `background` lays a quiet pattern or a photograph behind a drawing or a grid. [Layouts and backgrounds](./docs/layouts.md).
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, and a stadium round it. [Tournament layouts](./docs/multi.md).
105
105
  - **Judging assignments.** Who judges where. [Judging](./docs/judging.md).
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, 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
- - **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
- - **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).
106
+ - **Replay.** Tracking data played on any surface: the players, the ball and its trail, and the passes, shots and goals as they happen, with controls, the keyboard and a live region, and steps for a reader who prefers reduced motion. [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, boards and glass, goals, a fence, a cage's mesh, a ring's ropes) and the venue round it (raked stands, roofs, a dojo's walls). [The 3D view](./docs/turn.md).
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. [Renderers](./docs/renderers.md).
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 one for 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.
111
111
  - **Light and dark**, by the device or the page, and every colour a custom property; eight named looks, colours by feature, line widths and dashes, goal styles and mowing patterns, and arrows, axes and labels for teaching. [Theming](./docs/theming.md), [annotations](./docs/annotations.md).
112
112
  - **Accessible.** Each drawing is an `img` with a title and a description that say the surface and the result, in English or Japanese. [Accessibility](./docs/accessibility.md).
@@ -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 forty-one sports, the 94 ballparks, the court looks. |
122
+ | `SPORTS`, `PARKS`, `PARK_IDS`, `COURT_THEMES` | The forty-three 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. |
@@ -233,7 +233,7 @@ console.log(box(wide), box(tall));
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 forty-one, 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.
236
+ [The surfaces](./docs/surfaces.md) lists the forty-three, 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
 
@@ -615,7 +615,7 @@ A table in the ITTF's playing area, 14 m by 7 m, with surrounds and chairs ([cou
615
615
 
616
616
  ### The combat sports
617
617
 
618
- An MMA cage and a boxing ring ([the combat sports page](./docs/combat.md)).
618
+ An MMA cage, rings and wrestling mats ([the combat sports page](./docs/combat.md)).
619
619
 
620
620
  <p align="center">
621
621
  <picture>
@@ -641,6 +641,22 @@ An MMA cage and a boxing ring ([the combat sports page](./docs/combat.md)).
641
641
  <br><em>The ring in 3D.</em>
642
642
  </p>
643
643
 
644
+ <p align="center">
645
+ <picture>
646
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/wrestling-mat-3d-desk-dark.webp">
647
+ <img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/wrestling-mat-3d-desk-light.webp" alt="The UWW's wrestling mat in 3D on its platform" width="660">
648
+ </picture>
649
+ <br><em>The UWW's mat in 3D.</em>
650
+ </p>
651
+
652
+ <p align="center">
653
+ <picture>
654
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/prowrestling-ring-3d-desk-dark.webp">
655
+ <img src="https://raw.githubusercontent.com/johnmorrisdotca/kyogijo-stadiums/main/docs/images/prowrestling-ring-3d-desk-light.webp" alt="A professional wrestling ring in 3D with three ropes" width="660">
656
+ </picture>
657
+ <br><em>A wrestling ring in 3D.</em>
658
+ </p>
659
+
644
660
  ### The element in a page
645
661
 
646
662
  ```html
@@ -714,7 +730,7 @@ Nothing is branded. The drawing is coloured by custom properties on its `svg`, w
714
730
 
715
731
  ## Limits
716
732
 
717
- Each is held by a test: forty-one 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).
733
+ Each is held by a test: forty-three 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).
718
734
 
719
735
  ## Accessibility
720
736
 
@@ -45,6 +45,19 @@ export function budoAbout(o, language, plan = budoPlan(o)) {
45
45
  const platform = L.height > 0.0005 ? fill(words.boxingPlatform, { height: cm(L.height) }) : words.boxingFloor;
46
46
  return fill(words.boxing, { size: trim(L.size), feet: trim(L.size / 0.3048), apron: cm(L.apron), platform });
47
47
  }
48
+ if (plan.prowrestling !== undefined) {
49
+ const L = plan.prowrestling;
50
+ const platform = L.height > 0.0005 ? fill(words.boxingPlatform, { height: cm(L.height) }) : words.boxingFloor;
51
+ return fill(words.prowrestling, { size: trim(L.size), feet: trim(L.size / 0.3048), apron: cm(L.apron), platform });
52
+ }
53
+ if (plan.wrestling !== undefined) {
54
+ const L = plan.wrestling;
55
+ const fig = plan.figures;
56
+ const platform = L.height > 0.0005 ? fill(words.wrestlingPlatform, { height: trim(L.height) }) : words.wrestlingFloor;
57
+ if (fig.passivity > 0)
58
+ return fill(words.wrestlingUww, { circle: trim(L.circle), border: trim(L.border), band: trim(fig.passivity), platform });
59
+ return fill(words.wrestlingFolk, { feet: trim(L.circle / 0.3048), circle: trim(L.circle), border: trim(L.border / 0.3048), platform });
60
+ }
48
61
  if (plan.kyudo !== undefined) {
49
62
  const L = plan.kyudo;
50
63
  const fig = plan.figures;
@@ -83,6 +96,18 @@ export function budoSentences(o, language, plan = budoPlan(o)) {
83
96
  if (plan.mma.steps.length > 0)
84
97
  out.push(words.mmaSteps);
85
98
  }
99
+ if (plan.prowrestling !== undefined) {
100
+ out.push(words.prowrestlingRopes);
101
+ if (plan.prowrestling.steps.length > 0)
102
+ out.push(words.prowrestlingSteps);
103
+ }
104
+ if (plan.wrestling !== undefined) {
105
+ const fig = plan.figures;
106
+ if (fig.centre !== null && o.budo?.circle !== false)
107
+ out.push(fill(words.wrestlingCentre, { d: trim(fig.centre.diameter) }));
108
+ if (fig.lines !== null && plan.wrestling.start !== undefined)
109
+ out.push(words.wrestlingLines);
110
+ }
86
111
  if (plan.boxing !== undefined) {
87
112
  if (o.budo?.corners !== false)
88
113
  out.push(words.boxingCorners);
@@ -32,6 +32,12 @@ const DOJO_ONLY = {
32
32
  "yellow-green": pair({ ...COMMON, surface: "#e8d98e", alt: "#5f9a52", red: "#c8462a" }),
33
33
  "green-orange": pair({ ...COMMON, surface: "#6fa352", alt: "#69a04f", red: "#d4572a" }),
34
34
  };
35
+ /** The ring's canvas over the dark skirt of its platform: a pale canvas with dark red ropes (the default), a blue one and a black one with white ropes. Ours: the rules do not paint a ring. */
36
+ const RING_LOOKS = {
37
+ white: lifted(pair({ ...COMMON, surface: "#e6e3da", alt: "#d4d0c4", red: "#b32a2f", floor: "#2d3a56", rope: "#b32a2f" }), "#3b4a6e"),
38
+ blue: lifted(pair({ ...COMMON, surface: "#3a68ad", alt: "#2b528d", red: "#b32a2f", floor: "#1f3358", rope: "#f4f1e8" }), "#324a78"),
39
+ black: lifted(pair({ ...COMMON, surface: "#2b2e33", alt: "#1f2226", red: "#b32a2f", floor: "#17191c", rope: "#f4f1e8" }), "#3b3f45"),
40
+ };
35
41
  /** The looks of each sport: the names, the default first, and the colours. */
36
42
  export const BUDO_LOOKS = Object.freeze({
37
43
  judo: MATS,
@@ -53,10 +59,13 @@ export const BUDO_LOOKS = Object.freeze({
53
59
  blue: lifted(pair({ ...COMMON, surface: "#3a68ad", alt: "#2b528d", red: "#b32a2f", floor: "#2c3440" }), "#3a4452"),
54
60
  },
55
61
  // The ring's canvas over the dark skirt of its platform: a pale canvas with dark red ropes (the default), a blue one and a black one with white ropes. Ours: the rules do not paint a ring.
56
- boxing: {
57
- white: lifted(pair({ ...COMMON, surface: "#e6e3da", alt: "#d4d0c4", red: "#b32a2f", floor: "#2d3a56", rope: "#b32a2f" }), "#3b4a6e"),
58
- blue: lifted(pair({ ...COMMON, surface: "#3a68ad", alt: "#2b528d", red: "#b32a2f", floor: "#1f3358", rope: "#f4f1e8" }), "#324a78"),
59
- black: lifted(pair({ ...COMMON, surface: "#2b2e33", alt: "#1f2226", red: "#b32a2f", floor: "#17191c", rope: "#f4f1e8" }), "#3b3f45"),
62
+ boxing: RING_LOOKS,
63
+ prowrestling: RING_LOOKS,
64
+ // The wrestling mat's colours: the circle over the border (a UWW mat's protection area is a different colour from the mat, as its rules say), with the passivity band orange in every look. Ours.
65
+ wrestling: {
66
+ "blue-red": lifted(pair({ ...COMMON, surface: "#2f6db0", alt: "#c0392b", red: "#f07a1a", floor: "#2e3138" }), "#3b3f48"),
67
+ "green-beige": lifted(pair({ ...COMMON, surface: "#4f9560", alt: "#d6c595", red: "#f07a1a", floor: "#2e3138" }), "#3b3f48"),
68
+ "yellow-blue": lifted(pair({ ...COMMON, surface: "#e6c02e", alt: "#2f5fa6", red: "#f07a1a", floor: "#2e3138" }), "#3b3f48"),
60
69
  },
61
70
  kyudo: { wood: pair({ ...COMMON, surface: "#9db57d", alt: "#d8cfb0", red: "#b32a2f", floor: "#b98c58", dirt: "#c9ad7a" }) },
62
71
  });
@@ -0,0 +1,34 @@
1
+ import type { WrestlingFigures } from "../leagues/combat.ts";
2
+ import { type MBox, type MMark, type Parts } from "./parts.ts";
3
+ /** What a wrestling plan is. */
4
+ export interface MatLayout {
5
+ parts: Parts;
6
+ /** The mat's square: the circle and the matted area round it. The surface's own box. */
7
+ mat: MBox;
8
+ /** The platform under the mat (a square a metre wider each side), when there is one. */
9
+ platform: MBox | undefined;
10
+ extent: MBox;
11
+ centre: [number, number];
12
+ /** The wrestling area's diameter, and the middle part of it inside the passivity band (the UWW's). */
13
+ circle: number;
14
+ inner: number;
15
+ /** The matted area's width round the circle. */
16
+ border: number;
17
+ /** The platform's height over the floor of the building, in metres. */
18
+ height: number;
19
+ /** The starting lines: the rectangle they enclose, when drawn. */
20
+ start: MBox | undefined;
21
+ marks: MMark[];
22
+ ranges: Record<string, MBox>;
23
+ }
24
+ /** The circle's diameter the options ask for, held to what the league allows. */
25
+ export declare const matCircle: (asked: number | undefined, fig: WrestlingFigures, rule: string) => number;
26
+ /** The platform's height the options ask for, held to what the league allows. */
27
+ export declare function matHeight(asked: number | undefined, fig: WrestlingFigures, rule: string): number;
28
+ /** The plan of the mat the options ask for. */
29
+ export declare function matParts(fig: WrestlingFigures, o: {
30
+ circle: number;
31
+ height: number;
32
+ centre: boolean;
33
+ lines: boolean;
34
+ }): MatLayout;
@@ -0,0 +1,71 @@
1
+ // A wrestling mat: the wrestling area's circle with the matted area round it, and on the UWW's mat the orange passivity band, the central circle and the platform it stands on; on a folkstyle mat the line that outlines the
2
+ // circle, the circle of 10 feet and the two starting lines closed by a green and a red line. From the UWW's Wrestling Rules (Article 4, January 2026), the NCAA's Wrestling Rules (Rule 1) and the NFHS's (Rule 2-1). In metres,
3
+ // the origin at the top left of the mat's square, north at the top. Nothing here draws SVG.
4
+ import { ring } from "../fields.kit.js";
5
+ import { annulusD, discArea, rectArea, tapeBar, within } from "./kit.js";
6
+ import { emptyParts, grow } from "./parts.js";
7
+ /** The circle's diameter the options ask for, held to what the league allows. */
8
+ export const matCircle = (asked, fig, rule) => (asked === undefined ? fig.circle.drawn : within(asked, fig.circle.min, fig.circle.max, "The wrestling area", rule));
9
+ /** The platform's height the options ask for, held to what the league allows. */
10
+ export function matHeight(asked, fig, rule) {
11
+ if (asked === undefined)
12
+ return fig.platform.height.drawn;
13
+ const h = within(asked, fig.platform.height.min, fig.platform.height.max, "The platform", rule);
14
+ // A platform, when there is one, is at least the league's least (the UWW's 0.80 m); none at all is allowed.
15
+ if (h > 0 && h < fig.platform.least - 1e-9)
16
+ throw new RangeError(`The platform of ${h} m is outside what ${rule} allows: none, or ${fig.platform.least} m to ${fig.platform.height.max} m`);
17
+ return h;
18
+ }
19
+ /** The plan of the mat the options ask for. */
20
+ export function matParts(fig, o) {
21
+ const b = fig.border.drawn;
22
+ const side = o.circle + 2 * b;
23
+ const mat = { x0: 0, y0: 0, x1: side, y1: side };
24
+ const c = side / 2;
25
+ const r = o.circle / 2;
26
+ const parts = emptyParts();
27
+ const platform = o.height > 0 ? grow(mat, fig.platform.around) : undefined;
28
+ if (platform !== undefined)
29
+ parts.areas.push(rectArea("platform", "platform", "ky-bud-platform", platform));
30
+ parts.areas.push(rectArea("border", "border", "ky-bud-t2", mat));
31
+ parts.areas.push(discArea("circle", "circle", "ky-bud-t1", c, c, r));
32
+ const inner = fig.passivity > 0 ? o.circle - 2 * fig.passivity : o.circle;
33
+ if (fig.passivity > 0)
34
+ parts.areas.push({ id: "passivity", feature: "passivity", cls: "ky-bud-t3", d: annulusD(c, c, inner / 2, r), evenodd: true });
35
+ // The line that outlines the circle (folkstyle): part of the wrestling area, in bounds.
36
+ if (fig.rim > 0)
37
+ parts.shapes.push(ring("rim", "rim", c, c, r - fig.rim / 2, r - fig.rim / 2, { w: fig.rim, cls: "ky-bud-line" }));
38
+ // The circle in the middle: a band round a circle of the stated inside diameter.
39
+ if (fig.centre !== null && o.centre)
40
+ parts.shapes.push(ring("centre-circle", "centre-circle", c, c, fig.centre.diameter / 2 + fig.centre.band / 2, fig.centre.diameter / 2 + fig.centre.band / 2, { w: fig.centre.band, cls: "ky-bud-line" }));
41
+ // The starting lines: two parallel lines, closed at their ends by a green line (home, left) and a red line (visitors, right).
42
+ let start;
43
+ if (fig.lines !== null && o.lines) {
44
+ const L = fig.lines;
45
+ const half = L.apart / 2 + L.width;
46
+ start = { x0: c - L.length / 2, y0: c - half, x1: c + L.length / 2, y1: c + half };
47
+ parts.shapes.push(tapeBar("start-line-1", "starting-lines", "ky-bud-white-fill", { x0: start.x0, y0: c - L.apart / 2 - L.width, x1: start.x1, y1: c - L.apart / 2 }));
48
+ parts.shapes.push(tapeBar("start-line-2", "starting-lines", "ky-bud-white-fill", { x0: start.x0, y0: c + L.apart / 2, x1: start.x1, y1: c + L.apart / 2 + L.width }));
49
+ parts.shapes.push(tapeBar("start-green", "starting-lines", "ky-bud-green-fill", { x0: start.x0, y0: start.y0, x1: start.x0 + L.width, y1: start.y1 }));
50
+ parts.shapes.push(tapeBar("start-red", "starting-lines", "ky-bud-red-fill", { x0: start.x1 - L.width, y0: start.y0, x1: start.x1, y1: start.y1 }));
51
+ }
52
+ const extent = grow(platform ?? mat, 0.6);
53
+ const ranges = { start: { x0: c - 1.5, y0: c - 1.5, x1: c + 1.5, y1: c + 1.5 } };
54
+ if (fig.passivity > 0)
55
+ ranges.passivity = { x0: c - r - 0.3, y0: c - r - 0.3, x1: c + r + 0.3, y1: c + r + 0.3 };
56
+ const marks = [
57
+ { id: "mat-circle", x: c - r * 0.72, y: c - r * 0.72, side: "top" },
58
+ { id: "mat-border", x: b / 2, y: c + r * 0.55, side: "bottom" },
59
+ ];
60
+ if (fig.passivity > 0)
61
+ marks.push({ id: "mat-central", x: c - inner / 2 * Math.SQRT1_2, y: c + inner / 2 * Math.SQRT1_2, side: "bottom" });
62
+ if (fig.passivity > 0)
63
+ marks.push({ id: "mat-passivity", x: c + (inner / 2 + fig.passivity / 2) * Math.SQRT1_2, y: c - (inner / 2 + fig.passivity / 2) * Math.SQRT1_2, side: "top" });
64
+ if (fig.centre !== null && o.centre)
65
+ marks.push({ id: "mat-centre-circle", x: c + fig.centre.diameter / 2, y: c + fig.centre.diameter / 2, side: "bottom" });
66
+ if (start !== undefined)
67
+ marks.push({ id: "mat-starting-lines", x: start.x1, y: c, side: "bottom" });
68
+ if (platform !== undefined)
69
+ marks.push({ id: "mat-platform", x: platform.x1 - 0.3, y: platform.y0 + 0.3, side: "top" });
70
+ return { parts, mat, platform, extent, centre: [c, c], circle: o.circle, inner, border: b, height: o.height, start, marks, ranges };
71
+ }
@@ -9,6 +9,7 @@ import { type KyudoLayout } from "./kyudo.ts";
9
9
  import { boxD } from "./kit.ts";
10
10
  import { type CageLayout } from "./cage.ts";
11
11
  import { type RingLayout } from "./ring.ts";
12
+ import { type MatLayout } from "./mat.ts";
12
13
  import { type MBox, type MMark, type MRange } from "./parts.ts";
13
14
  import { type SumoLayout } from "./sumo.ts";
14
15
  import type { BudoKind, CombatKind } from "./types.ts";
@@ -52,6 +53,8 @@ export interface BudoPlan {
52
53
  dojo?: DojoLayout;
53
54
  mma?: CageLayout;
54
55
  boxing?: RingLayout;
56
+ wrestling?: MatLayout;
57
+ prowrestling?: RingLayout;
55
58
  }
56
59
  /** The sports of the budō family. */
57
60
  export declare const BUDO_SPORTS: readonly BudoKind[];
package/dist/budo/plan.js CHANGED
@@ -1,6 +1,6 @@
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 { BOXING_LEAGUES, MMA_LEAGUES } from "../leagues/combat.js";
3
+ import { BOXING_LEAGUES, MMA_LEAGUES, PRO_WRESTLING_LEAGUES, WRESTLING_LEAGUES } from "../leagues/combat.js";
4
4
  import { dojoLayout, dojoLeague, dojoSpecOf } from "./dojo.js";
5
5
  import { contestOf, gridOf, judoParts, matOf, safetyOf, snapTo } from "./judo.js";
6
6
  import { karateParts } from "./karate.js";
@@ -9,6 +9,7 @@ import { kyudoParts, shootersOf } from "./kyudo.js";
9
9
  import { boxD } from "./kit.js";
10
10
  import { cageHeight, cageParts, cageWidth, fenceHeight } from "./cage.js";
11
11
  import { ringHeight, ringParts, ringSize } from "./ring.js";
12
+ import { matCircle, matHeight, matParts } from "./mat.js";
12
13
  import { emptyParts, grow, union } from "./parts.js";
13
14
  import { dohyoHeight, sumoParts } from "./sumo.js";
14
15
  import { lookOf } from "./looks.js";
@@ -20,12 +21,12 @@ export const BUDO_SPORTS = Object.freeze(["judo", "karate", "kendo", "sumo", "ky
20
21
  /** True for a sport of the budō family. */
21
22
  export const isBudoSport = (sport) => BUDO_SPORTS.includes(sport);
22
23
  /** The combat sports the engine of the budō also draws: the MMA cage and the boxing ring. */
23
- export const COMBAT_SPORTS = Object.freeze(["mma", "boxing"]);
24
+ export const COMBAT_SPORTS = Object.freeze(["mma", "boxing", "wrestling", "prowrestling"]);
24
25
  /** True for a combat sport (the MMA cage). */
25
26
  export const isCombatSport = (sport) => COMBAT_SPORTS.includes(sport);
26
27
  /** True for a sport this engine draws: a sport of the budō or a combat sport. */
27
28
  export const isMatSport = (sport) => isBudoSport(sport) || isCombatSport(sport);
28
- const OWN = { judo: JUDO_LEAGUES, karate: KARATE_LEAGUES, kendo: KENDO_LEAGUES, sumo: SUMO_LEAGUES, kyudo: KYUDO_LEAGUES, dojo: DOJO_LEAGUES, mma: MMA_LEAGUES, boxing: BOXING_LEAGUES };
29
+ const OWN = { judo: JUDO_LEAGUES, karate: KARATE_LEAGUES, kendo: KENDO_LEAGUES, sumo: SUMO_LEAGUES, kyudo: KYUDO_LEAGUES, dojo: DOJO_LEAGUES, mma: MMA_LEAGUES, boxing: BOXING_LEAGUES, wrestling: WRESTLING_LEAGUES, prowrestling: PRO_WRESTLING_LEAGUES };
29
30
  /** 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`. */
30
31
  function kataOf(style) {
31
32
  if (style === undefined)
@@ -140,6 +141,20 @@ export function budoPlan(o) {
140
141
  const ranges = { ...L.ranges, half: halves(L.platform) };
141
142
  return finish({ box: L.platform, extent: L.extent, areas: L.parts.areas, shapes: L.parts.shapes, lineWidth: f.ropes.diameter.drawn, ranges, marks: L.marks, centre: { x: L.centre[0], y: L.centre[1], r: L.size * 0.2 }, boxing: L });
142
143
  }
144
+ case "prowrestling": {
145
+ const f = fig;
146
+ const rule = "what rings are typically made as";
147
+ const L = ringParts(f, { size: ringSize(style.size, f, rule), height: ringHeight(style.height, f, rule), steps: flag(style.steps, true, "budo.steps"), corners: flag(style.corners, true, "budo.corners") });
148
+ const ranges = { ropes: L.ranges.ropes, half: halves(L.platform) };
149
+ return finish({ box: L.platform, extent: L.extent, areas: L.parts.areas, shapes: L.parts.shapes, lineWidth: f.ropes.diameter.drawn, ranges, marks: L.marks, centre: { x: L.centre[0], y: L.centre[1], r: L.size * 0.2 }, prowrestling: L });
150
+ }
151
+ case "wrestling": {
152
+ const f = fig;
153
+ const rule = `the rules of ${league.id === "uww" ? "the UWW" : league.id === "ncaa-wrestling" ? "the NCAA" : "the NFHS"}`;
154
+ const L = matParts(f, { circle: matCircle(style.size, f, rule), height: matHeight(style.height, f, rule), centre: flag(style.circle, true, "budo.circle"), lines: flag(style.start, true, "budo.start") });
155
+ const ranges = { ...L.ranges, half: halves(L.mat) };
156
+ return finish({ box: L.mat, extent: L.extent, areas: L.parts.areas, shapes: L.parts.shapes, lineWidth: 0.05, ranges, marks: L.marks, centre: { x: L.centre[0], y: L.centre[1], r: L.circle * 0.2 }, wrestling: L });
157
+ }
143
158
  default: {
144
159
  const L = dojoLayout(o.dojo ?? {}, dojoLeague(league.id));
145
160
  const f = L.floor;
package/dist/budo/ring.js CHANGED
@@ -45,8 +45,8 @@ export function ringParts(fig, o) {
45
45
  parts.areas.push(rectArea(`step-${corner}-${t + 1}`, "steps", "ky-bud-step", { x0: b.x0, y0, x1: b.x1, y1: y0 + s.tread }));
46
46
  }
47
47
  };
48
- // The red corner (bottom left), the blue corner (top right) and the neutral corner nearest the table (bottom right).
49
- for (const corner of [3, 1, 2])
48
+ // The red corner (bottom left), the blue corner (top right) and the neutral corner nearest the table (bottom right); a ring with fewer sets has the first of them.
49
+ for (const corner of [3, 1, 2].slice(0, s.sets))
50
50
  at(corner);
51
51
  }
52
52
  // The ropes seen from above are one line each side; each turns to its post by the extension.
@@ -68,10 +68,13 @@ export function ringParts(fig, o) {
68
68
  { id: "ring-canvas", x: mid - o.size * 0.2, y: mid + o.size * 0.15, side: "bottom" },
69
69
  { id: "ring-ropes", x: ring.x1, y: mid - o.size * 0.2, side: "bottom" },
70
70
  { id: "ring-post", x: corners[0].post[0], y: corners[0].post[1], side: "top" },
71
- { id: "ring-red-corner", x: red.post[0], y: red.post[1], side: "bottom" },
72
- { id: "ring-blue-corner", x: blue.post[0], y: blue.post[1], side: "top" },
73
71
  { id: "ring-apron", x: mid, y: apron / 2, side: "top" },
74
72
  ];
73
+ // A boxing ring's corners are the two boxers' and two neutral ones; a wrestling ring's are not assigned, and its platform is named instead.
74
+ if (fig.boxerCorners)
75
+ marks.push({ id: "ring-red-corner", x: red.post[0], y: red.post[1], side: "bottom" }, { id: "ring-blue-corner", x: blue.post[0], y: blue.post[1], side: "top" });
76
+ else if (o.height > 0)
77
+ marks.push({ id: "ring-platform", x: platform.x1 - 0.2, y: mid + o.size * 0.3, side: "bottom" });
75
78
  if (steps.length > 0) {
76
79
  const last = steps[steps.length - 1];
77
80
  marks.push({ id: "ring-steps", x: (last.box.x0 + last.box.x1) / 2, y: side + (last.box.y1 - last.box.y0) / 2, side: "bottom" });
@@ -1,7 +1,7 @@
1
1
  /** The sports of the budō family. */
2
2
  export type BudoKind = "judo" | "karate" | "kendo" | "sumo" | "kyudo" | "dojo" | CombatKind;
3
3
  /** The combat sports the engine of the budō also draws: the MMA cage. */
4
- export type CombatKind = "mma" | "boxing";
4
+ export type CombatKind = "mma" | "boxing" | "wrestling" | "prowrestling";
5
5
  /** The sides of a hall, as a plan has them: north is the top of the drawing. `top`, `bottom`, `left` and `right` say the same. */
6
6
  export type Compass = "north" | "south" | "east" | "west";
7
7
  export type Side4 = Compass | "top" | "bottom" | "left" | "right";
@@ -21,13 +21,13 @@ export interface BudoStyle {
21
21
  hall?: "budokan";
22
22
  /** Judo: `shiai` (the contest area, the default) or `kata` (the IJF's kata area, `league: "ijf-kata"`: a centre tape, two white tapes 3 m from it either side, a safety area of 2 m; with `officials`, the five judges' seats on the shomen side and the coach's chair opposite). */
23
23
  style?: "shiai" | "kata";
24
- /** Judo: the contest area's side, 8 m to 10 m. Kendo: the shiai-jo's side, 9 m to 11 m. MMA cage: the width across the flats, 6.096 m to 9.754 m (20 to 32 feet), 9.144 m (30 feet) by default; 7.62 m is the smaller cage of 25 feet. Boxing ring: the side inside the ropes, within what the league allows (20 feet for the Nevada rule, 16 to 20 feet for Wisconsin, 4.5 to 6.1 m for the WBC Amateur rules). In metres. */
24
+ /** Judo: the contest area's side, 8 m to 10 m. Kendo: the shiai-jo's side, 9 m to 11 m. MMA cage: the width across the flats, 6.096 m to 9.754 m (20 to 32 feet), 9.144 m (30 feet) by default; 7.62 m is the smaller cage of 25 feet. Boxing ring: the side inside the ropes, within what the league allows (20 feet for the Nevada rule, 16 to 20 feet for Wisconsin, 4.5 to 6.1 m for the WBC Amateur rules). Wrestling: the diameter of the wrestling area (9 m for the UWW, 32 to 42 feet for the NCAA, at least 28 feet for the NFHS). In metres. */
25
25
  size?: number;
26
26
  /** Judo: the width of the safety area, 3 m or more (4 m by default). In metres. */
27
27
  safety?: number;
28
28
  /** Judo: the tatami's size. `2x1` (the IJF's, 2 m by 1 m, the default of an IJF area), `1x1` (the half tatami) or `182x91` (the AJJF's own, the default of an AJJF area). */
29
29
  tatami?: "2x1" | "1x1" | "182x91";
30
- /** Judo: the tape that marks where the contestants start. On by default for the AJJF's area and the kata area, and for the IJF's (the 2020 rules' blue and white tape). */
30
+ /** Wrestling: the starting lines of a folkstyle mat (the UWW's mat has none). On by default. Judo: the tape that marks where the contestants start. On by default for the AJJF's area and the kata area, and for the IJF's (the 2020 rules' blue and white tape). */
31
31
  start?: boolean;
32
32
  /** Judo: a solid platform under the tatami, one metre wider and longer than it. Off by default. */
33
33
  platform?: boolean;
@@ -39,7 +39,7 @@ export interface BudoStyle {
39
39
  texture?: "weave" | "none";
40
40
  /** Karate: the referee's and the judges' places. On by default. */
41
41
  judges?: boolean;
42
- /** Sumo: the height of the clay square in metres, 0.34 to 0.60. 0.55 by default. MMA cage: the platform's height over the floor of the building, 0 to 1.219 m (4 feet), 1.219 m by default. Boxing ring: the same, 0 to what the league allows (5 feet in Nevada, 4 feet in Wisconsin, 1.2 m for the amateurs). Seen in 3D. */
42
+ /** Sumo: the height of the clay square in metres, 0.34 to 0.60. 0.55 by default. MMA cage: the platform's height over the floor of the building, 0 to 1.219 m (4 feet), 1.219 m by default. Boxing ring: the same, 0 to what the league allows (5 feet in Nevada, 4 feet in Wisconsin, 1.2 m for the amateurs). Wrestling: the platform the mat stands on, none or 0.80 to 1.10 m for the UWW's mat (1 m drawn) and 0 to 1.10 m for the others (none drawn). Seen in 3D. */
43
43
  height?: number;
44
44
  /** Sumo: the four tassels of the roof, in the colours of the four quarters (green east, red south, white west, black north). Off by default. */
45
45
  tassels?: boolean;
@@ -51,6 +51,8 @@ export interface BudoStyle {
51
51
  gates?: boolean;
52
52
  /** MMA cage: the steps up to the platform at each gate, three treads. Boxing ring: the three sets of steps, one in each boxer's corner and one in a neutral corner. On by default. */
53
53
  steps?: boolean;
54
+ /** Wrestling: the circle in the middle of the mat (the UWW's central circle, the NFHS's circle of 10 feet; the NCAA has none). On by default. */
55
+ circle?: boolean;
54
56
  /** Boxing ring: the posts and their pads in the corner colours (the red and the blue corner of the boxers, two neutral ones in white). On by default. */
55
57
  corners?: boolean;
56
58
  /** Kyūdō: the number of shooters in a line, 1 to 12 (5 by default). */
@@ -47,8 +47,11 @@ const RING_CLASSES = `
47
47
  .kyogijo .ky-bud-corner-red{fill:var(--ky-red)}
48
48
  .kyogijo .ky-bud-corner-blue{fill:var(--ky-blue,#2a5db0)}
49
49
  .kyogijo .ky-bud-corner-white{fill:#f4f1e8;stroke:var(--ky-ink);stroke-opacity:.45;stroke-width:.03}`.trim();
50
- const COMBAT = ["mma", "boxing"];
51
- const RING = ["boxing"];
50
+ const COMBAT = ["mma", "boxing", "prowrestling"];
51
+ const RING = ["boxing", "prowrestling"];
52
+ /** The rules of a wrestling mat's own class: the green neutral line of a folkstyle mat's starting lines. */
53
+ const WRESTLING_CLASSES = `.kyogijo .ky-bud-green-fill{fill:#2f9e63}`;
54
+ const WRESTLING = ["wrestling"];
52
55
  /** The custom properties of a look. */
53
56
  const vars = (l) => `--ky-surface:${l.surface};--ky-surface-alt:${l.alt};--ky-red:${l.red};--ky-apron:${l.apron};--ky-free:${l.free};--ky-bud-floor:${l.floor};--ky-boards:${l.boards}${l.dirt === undefined ? "" : `;--ky-dirt:${l.dirt}`}${l.sand === undefined ? "" : `;--ky-sand:${l.sand}`}${l.straw === undefined ? "" : `;--ky-bud-straw:${l.straw}`}${l.rope === undefined ? "" : `;--ky-bud-rope:${l.rope}`}`;
54
57
  /** The three rules of one look: light, dark by the device's setting, and dark by the page's `data-theme`. */
@@ -76,7 +79,7 @@ export function budoStyle(sport, look) {
76
79
  const kind = sport;
77
80
  if (BUDO_LOOKS[kind] === undefined)
78
81
  return "";
79
- return `${CLASSES}${COMBAT.includes(sport) ? `\n${COMBAT_CLASSES}` : ""}${RING.includes(sport) ? `\n${RING_CLASSES}` : ""}\n${look === undefined ? lookRules(kind, Object.keys(BUDO_LOOKS[kind])[0]) : lookRules(kind, look)}`;
82
+ return `${CLASSES}${COMBAT.includes(sport) ? `\n${COMBAT_CLASSES}` : ""}${RING.includes(sport) ? `\n${RING_CLASSES}` : ""}${WRESTLING.includes(sport) ? `\n${WRESTLING_CLASSES}` : ""}\n${look === undefined ? lookRules(kind, Object.keys(BUDO_LOOKS[kind])[0]) : lookRules(kind, look)}`;
80
83
  }
81
84
  /** Every budō sport's rules and every look, for a page that draws with `style: "none"` and supplies the stylesheet itself. */
82
- export const KYOGIJO_BUDO_STYLE = `${CLASSES}\n${COMBAT_CLASSES}\n${RING_CLASSES}${KYOGIJO_BUDO_GALLERY_STYLE}\n${Object.keys(BUDO_LOOKS).flatMap((sport) => Object.keys(BUDO_LOOKS[sport]).map((name) => lookRules(sport, name))).join("\n")}`;
85
+ export const KYOGIJO_BUDO_STYLE = `${CLASSES}\n${COMBAT_CLASSES}\n${RING_CLASSES}\n${WRESTLING_CLASSES}${KYOGIJO_BUDO_GALLERY_STYLE}\n${Object.keys(BUDO_LOOKS).flatMap((sport) => Object.keys(BUDO_LOOKS[sport]).map((name) => lookRules(sport, name))).join("\n")}`;
package/dist/crowd.js CHANGED
@@ -104,6 +104,10 @@ const PROFILES = {
104
104
  mma: { shape: "bowl", side: 40, end: 40, bench: 0, corner: 56, tiers: [lower(60, 3, 24), upper(67, 120, 32, 60)], away: "corner" },
105
105
  // A boxing ring stands in the middle of an arena in the same way.
106
106
  boxing: { shape: "bowl", side: 40, end: 40, bench: 0, corner: 56, tiers: [lower(60, 3, 24), upper(67, 120, 32, 60)], away: "corner" },
107
+ // A wrestling mat stands in the middle of a hall in the same way.
108
+ wrestling: { shape: "bowl", side: 36, end: 36, bench: 6, corner: 50, tiers: [lower(60, 3, 24), upper(67, 120, 32, 60)], away: "corner" },
109
+ // A wrestling ring stands in the middle of an arena as a boxing ring does.
110
+ prowrestling: { shape: "bowl", side: 40, end: 40, bench: 0, corner: 56, tiers: [lower(60, 3, 24), upper(67, 120, 32, 60)], away: "corner" },
107
111
  };
108
112
  /** The grounds of the package that are the home of an NFL or a CFL club, where a soccer pitch stands inside a gridiron's stands. From each ground's article. */
109
113
  export const GRIDIRON_GROUNDS = Object.freeze({