@johnmorrisdotca/kyogijo-stadiums 0.0.0-stage → 0.4.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 +129 -0
- package/LICENSE +21 -0
- package/NOTICE.md +293 -0
- package/README.md +600 -2
- package/dist/annotate.d.ts +47 -0
- package/dist/annotate.js +349 -0
- package/dist/atlas-entry.d.ts +4 -0
- package/dist/atlas-entry.js +3 -0
- package/dist/atlas.d.ts +131 -0
- package/dist/atlas.js +149 -0
- package/dist/background.d.ts +56 -0
- package/dist/background.js +127 -0
- package/dist/ballpark.d.ts +48 -0
- package/dist/ballpark.js +129 -0
- package/dist/canvas-entry.d.ts +2 -0
- package/dist/canvas-entry.js +2 -0
- package/dist/canvas.d.ts +85 -0
- package/dist/canvas.js +279 -0
- package/dist/charts-entry.d.ts +10 -0
- package/dist/charts-entry.js +8 -0
- package/dist/charts.baseball.d.ts +30 -0
- package/dist/charts.baseball.js +152 -0
- package/dist/charts.curling.d.ts +52 -0
- package/dist/charts.curling.js +196 -0
- package/dist/charts.d.ts +172 -0
- package/dist/charts.js +508 -0
- package/dist/charts.network.d.ts +66 -0
- package/dist/charts.network.js +64 -0
- package/dist/charts.soccer.d.ts +43 -0
- package/dist/charts.soccer.js +191 -0
- package/dist/charts.types.d.ts +396 -0
- package/dist/charts.types.js +1 -0
- package/dist/colour.d.ts +29 -0
- package/dist/colour.js +97 -0
- package/dist/common.d.ts +14 -0
- package/dist/common.js +32 -0
- package/dist/court.d.ts +89 -0
- package/dist/court.js +248 -0
- package/dist/courts.style.d.ts +20 -0
- package/dist/courts.style.js +54 -0
- package/dist/cricket.board.d.ts +18 -0
- package/dist/cricket.board.js +67 -0
- package/dist/curling.board.d.ts +24 -0
- package/dist/curling.board.js +147 -0
- package/dist/d3-entry.d.ts +3 -0
- package/dist/d3-entry.js +2 -0
- package/dist/d3.d.ts +45 -0
- package/dist/d3.js +56 -0
- package/dist/draw.d.ts +52 -0
- package/dist/draw.js +705 -0
- package/dist/element-define.d.ts +2 -0
- package/dist/element-define.js +4 -0
- package/dist/element-entry.d.ts +1 -0
- package/dist/element-entry.js +2 -0
- package/dist/element.d.ts +39 -0
- package/dist/element.js +321 -0
- package/dist/eras-entry.d.ts +2 -0
- package/dist/eras-entry.js +2 -0
- package/dist/eras.d.ts +204 -0
- package/dist/eras.js +396 -0
- package/dist/events-entry.d.ts +3 -0
- package/dist/events-entry.js +3 -0
- package/dist/events.d.ts +54 -0
- package/dist/events.data.d.ts +59 -0
- package/dist/events.data.js +297 -0
- package/dist/events.js +127 -0
- package/dist/features.d.ts +31 -0
- package/dist/features.js +284 -0
- package/dist/field.score.d.ts +5 -0
- package/dist/field.score.js +33 -0
- package/dist/fields/afl.d.ts +11 -0
- package/dist/fields/afl.js +103 -0
- package/dist/fields/cricket.d.ts +9 -0
- package/dist/fields/cricket.js +81 -0
- package/dist/fields/fieldhockey.d.ts +6 -0
- package/dist/fields/fieldhockey.js +81 -0
- package/dist/fields/gaelic.d.ts +10 -0
- package/dist/fields/gaelic.js +86 -0
- package/dist/fields/handball.d.ts +6 -0
- package/dist/fields/handball.js +85 -0
- package/dist/fields/lacrosse.d.ts +17 -0
- package/dist/fields/lacrosse.js +169 -0
- package/dist/fields/rugby.d.ts +10 -0
- package/dist/fields/rugby.js +130 -0
- package/dist/fields.d.ts +12 -0
- package/dist/fields.js +44 -0
- package/dist/fields.kit.d.ts +63 -0
- package/dist/fields.kit.js +108 -0
- package/dist/fields.style.d.ts +4 -0
- package/dist/fields.style.js +19 -0
- package/dist/fields.types.d.ts +155 -0
- package/dist/fields.types.js +1 -0
- package/dist/format.d.ts +10 -0
- package/dist/format.js +28 -0
- package/dist/formations.d.ts +18 -0
- package/dist/formations.js +211 -0
- package/dist/frames-entry.d.ts +8 -0
- package/dist/frames-entry.js +7 -0
- package/dist/frames.d.ts +199 -0
- package/dist/frames.js +271 -0
- package/dist/frames.providers.d.ts +16 -0
- package/dist/frames.providers.js +302 -0
- package/dist/geojson-entry.d.ts +2 -0
- package/dist/geojson-entry.js +2 -0
- package/dist/geojson.d.ts +79 -0
- package/dist/geojson.js +147 -0
- package/dist/geometry-entry.d.ts +7 -0
- package/dist/geometry-entry.js +5 -0
- package/dist/geometry.d.ts +295 -0
- package/dist/geometry.js +361 -0
- package/dist/grounds-entry.d.ts +4 -0
- package/dist/grounds-entry.js +3 -0
- package/dist/grounds.d.ts +134 -0
- package/dist/grounds.data.d.ts +2 -0
- package/dist/grounds.data.js +1849 -0
- package/dist/grounds.js +74 -0
- package/dist/heat.colour.d.ts +37 -0
- package/dist/heat.colour.js +54 -0
- package/dist/heat.d.ts +43 -0
- package/dist/heat.js +614 -0
- package/dist/heat.stats.d.ts +123 -0
- package/dist/heat.stats.js +413 -0
- package/dist/heat.types.d.ts +145 -0
- package/dist/heat.types.js +1 -0
- package/dist/heat.zones.d.ts +54 -0
- package/dist/heat.zones.js +424 -0
- package/dist/homeside.d.ts +16 -0
- package/dist/homeside.js +43 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +29 -0
- package/dist/layers-entry.d.ts +19 -0
- package/dist/layers-entry.js +11 -0
- package/dist/layers.d.ts +41 -0
- package/dist/layers.env.d.ts +72 -0
- package/dist/layers.env.js +79 -0
- package/dist/layers.js +533 -0
- package/dist/layers.marks.d.ts +45 -0
- package/dist/layers.marks.js +168 -0
- package/dist/layers.types.d.ts +226 -0
- package/dist/layers.types.js +1 -0
- package/dist/layout.d.ts +97 -0
- package/dist/layout.js +381 -0
- package/dist/layout.style.d.ts +6 -0
- package/dist/layout.style.js +17 -0
- package/dist/layouts-entry.d.ts +5 -0
- package/dist/layouts-entry.js +4 -0
- package/dist/leagues/aussie.d.ts +57 -0
- package/dist/leagues/aussie.js +36 -0
- package/dist/leagues/baseball.d.ts +58 -0
- package/dist/leagues/baseball.js +171 -0
- package/dist/leagues/basketball.d.ts +67 -0
- package/dist/leagues/basketball.js +128 -0
- package/dist/leagues/courts.d.ts +212 -0
- package/dist/leagues/courts.js +114 -0
- package/dist/leagues/cricket.d.ts +45 -0
- package/dist/leagues/cricket.js +34 -0
- package/dist/leagues/curling.d.ts +64 -0
- package/dist/leagues/curling.js +53 -0
- package/dist/leagues/fieldhockey.d.ts +48 -0
- package/dist/leagues/fieldhockey.js +29 -0
- package/dist/leagues/fields.d.ts +10 -0
- package/dist/leagues/fields.js +6 -0
- package/dist/leagues/football.d.ts +8 -0
- package/dist/leagues/football.js +82 -0
- package/dist/leagues/gaelic.d.ts +50 -0
- package/dist/leagues/gaelic.js +29 -0
- package/dist/leagues/handball.d.ts +45 -0
- package/dist/leagues/handball.js +32 -0
- package/dist/leagues/hockey.d.ts +63 -0
- package/dist/leagues/hockey.js +166 -0
- package/dist/leagues/lacrosse.d.ts +103 -0
- package/dist/leagues/lacrosse.js +175 -0
- package/dist/leagues/rugby.d.ts +59 -0
- package/dist/leagues/rugby.js +72 -0
- package/dist/leagues/sources.d.ts +18 -0
- package/dist/leagues/sources.js +95 -0
- package/dist/leagues/types.d.ts +43 -0
- package/dist/leagues/types.js +5 -0
- package/dist/leagues-entry.d.ts +23 -0
- package/dist/leagues-entry.js +15 -0
- package/dist/leagues.d.ts +172 -0
- package/dist/leagues.js +462 -0
- package/dist/look.d.ts +50 -0
- package/dist/look.js +186 -0
- package/dist/mark.d.ts +35 -0
- package/dist/mark.js +59 -0
- package/dist/mount-entry.d.ts +2 -0
- package/dist/mount-entry.js +2 -0
- package/dist/mount.d.ts +63 -0
- package/dist/mount.js +167 -0
- package/dist/mow.d.ts +36 -0
- package/dist/mow.js +111 -0
- package/dist/names.d.ts +77 -0
- package/dist/names.js +97 -0
- package/dist/outline.d.ts +25 -0
- package/dist/outline.js +112 -0
- package/dist/parks-entry.d.ts +4 -0
- package/dist/parks-entry.js +3 -0
- package/dist/parks.d.ts +200 -0
- package/dist/parks.data.d.ts +2 -0
- package/dist/parks.data.js +4489 -0
- package/dist/parks.js +92 -0
- package/dist/plot-entry.d.ts +2 -0
- package/dist/plot-entry.js +2 -0
- package/dist/plot.d.ts +74 -0
- package/dist/plot.js +68 -0
- package/dist/png-entry.d.ts +2 -0
- package/dist/png-entry.js +2 -0
- package/dist/png.d.ts +26 -0
- package/dist/png.js +46 -0
- package/dist/ranges.d.ts +33 -0
- package/dist/ranges.js +178 -0
- package/dist/ranges.names.d.ts +31 -0
- package/dist/ranges.names.js +65 -0
- package/dist/react-entry.d.ts +2 -0
- package/dist/react-entry.js +2 -0
- package/dist/react.d.ts +53 -0
- package/dist/react.js +58 -0
- package/dist/replay-entry.d.ts +5 -0
- package/dist/replay-entry.js +4 -0
- package/dist/replay.control.d.ts +47 -0
- package/dist/replay.control.js +184 -0
- package/dist/replay.d.ts +170 -0
- package/dist/replay.dom.d.ts +21 -0
- package/dist/replay.dom.js +388 -0
- package/dist/replay.js +579 -0
- package/dist/replay.types.d.ts +152 -0
- package/dist/replay.types.js +1 -0
- package/dist/restyle.d.ts +21 -0
- package/dist/restyle.js +70 -0
- package/dist/road.d.ts +26 -0
- package/dist/road.draw.d.ts +6 -0
- package/dist/road.draw.js +269 -0
- package/dist/road.js +59 -0
- package/dist/road.model.d.ts +63 -0
- package/dist/road.model.js +215 -0
- package/dist/road.style.d.ts +7 -0
- package/dist/road.style.js +26 -0
- package/dist/road.types.d.ts +122 -0
- package/dist/road.types.js +1 -0
- package/dist/scene-entry.d.ts +7 -0
- package/dist/scene-entry.js +5 -0
- package/dist/scene.css.d.ts +44 -0
- package/dist/scene.css.js +296 -0
- package/dist/scene.d.ts +27 -0
- package/dist/scene.fit.d.ts +12 -0
- package/dist/scene.fit.js +18 -0
- package/dist/scene.flat.d.ts +38 -0
- package/dist/scene.flat.js +167 -0
- package/dist/scene.js +420 -0
- package/dist/scene.path.d.ts +40 -0
- package/dist/scene.path.js +357 -0
- package/dist/scene.types.d.ts +172 -0
- package/dist/scene.types.js +1 -0
- package/dist/scene.xml.d.ts +31 -0
- package/dist/scene.xml.js +81 -0
- package/dist/score.d.ts +70 -0
- package/dist/score.js +212 -0
- package/dist/sets.board.d.ts +22 -0
- package/dist/sets.board.js +89 -0
- package/dist/sheet.d.ts +18 -0
- package/dist/sheet.js +38 -0
- package/dist/special.d.ts +44 -0
- package/dist/special.js +204 -0
- package/dist/special.style.d.ts +8 -0
- package/dist/special.style.js +36 -0
- package/dist/strings.d.ts +581 -0
- package/dist/strings.js +411 -0
- package/dist/style.d.ts +35 -0
- package/dist/style.js +177 -0
- package/dist/surfaces/baseball.d.ts +33 -0
- package/dist/surfaces/baseball.js +208 -0
- package/dist/surfaces/baseball.walls.d.ts +16 -0
- package/dist/surfaces/baseball.walls.js +150 -0
- package/dist/surfaces/basketball.d.ts +8 -0
- package/dist/surfaces/basketball.js +199 -0
- package/dist/surfaces/curling.d.ts +23 -0
- package/dist/surfaces/curling.js +128 -0
- package/dist/surfaces/field.d.ts +12 -0
- package/dist/surfaces/field.js +163 -0
- package/dist/surfaces/football.d.ts +12 -0
- package/dist/surfaces/football.js +208 -0
- package/dist/surfaces/hockey.d.ts +10 -0
- package/dist/surfaces/hockey.js +166 -0
- package/dist/surfaces/net.d.ts +7 -0
- package/dist/surfaces/net.js +151 -0
- package/dist/surfaces/soccer-providers.d.ts +124 -0
- package/dist/surfaces/soccer-providers.js +334 -0
- package/dist/surfaces/soccer-spec.d.ts +138 -0
- package/dist/surfaces/soccer-spec.js +175 -0
- package/dist/surfaces/soccer.d.ts +25 -0
- package/dist/surfaces/soccer.js +270 -0
- package/dist/surfaces/surface.d.ts +180 -0
- package/dist/surfaces/surface.js +49 -0
- package/dist/team.common.d.ts +75 -0
- package/dist/team.common.js +97 -0
- package/dist/team.formation.d.ts +24 -0
- package/dist/team.formation.js +121 -0
- package/dist/team.geometry.d.ts +66 -0
- package/dist/team.geometry.js +304 -0
- package/dist/team.layers.d.ts +16 -0
- package/dist/team.layers.js +32 -0
- package/dist/team.motion.d.ts +9 -0
- package/dist/team.motion.js +325 -0
- package/dist/team.network.d.ts +43 -0
- package/dist/team.network.js +215 -0
- package/dist/team.shape.d.ts +12 -0
- package/dist/team.shape.js +217 -0
- package/dist/team.types.d.ts +189 -0
- package/dist/team.types.js +1 -0
- package/dist/text.d.ts +31 -0
- package/dist/text.js +88 -0
- package/dist/themes.d.ts +14 -0
- package/dist/themes.js +24 -0
- package/dist/types.d.ts +565 -0
- package/dist/types.js +1 -0
- package/dist/units.d.ts +45 -0
- package/dist/units.js +90 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +2 -0
- package/package.json +234 -4
package/dist/leagues.js
ADDED
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
// The leagues: for each family of surface (basketball, hockey, football, baseball and softball) the variants a rulebook marks
|
|
2
|
+
// differently, each with the figures of its own rulebook in its own unit, its name in English and Japanese, the sources that say so
|
|
3
|
+
// and, where a source dates it, the markings it had in earlier seasons. `league` in the options picks one; `sport` names the family
|
|
4
|
+
// (`nba` for basketball, `nhl` for hockey, `nfl`, `cfl` and `ifaf` for football, `mlb` for baseball and softball).
|
|
5
|
+
// Nothing here draws.
|
|
6
|
+
import { BASEBALL_LEAGUES, diamondInFeet } from "./leagues/baseball.js";
|
|
7
|
+
import { BASKETBALL_LEAGUES, courtInFeet } from "./leagues/basketball.js";
|
|
8
|
+
import { FOOTBALL_LEAGUES } from "./leagues/football.js";
|
|
9
|
+
import { HOCKEY_LEAGUES, rinkInFeet } from "./leagues/hockey.js";
|
|
10
|
+
import { CURLING_LEAGUES, sheetInFeet } from "./leagues/curling.js";
|
|
11
|
+
import { BADMINTON_LEAGUES, PICKLEBALL_LEAGUES, TABLE_TENNIS_LEAGUES, TENNIS_LEAGUES, VOLLEYBALL_LEAGUES, netInFeet } from "./leagues/courts.js";
|
|
12
|
+
import { AFL_LEAGUES, aflInFeet } from "./leagues/aussie.js";
|
|
13
|
+
import { CRICKET_LEAGUES, cricketInFeet } from "./leagues/cricket.js";
|
|
14
|
+
import { FIELD_HOCKEY_LEAGUES, fieldHockeyInFeet } from "./leagues/fieldhockey.js";
|
|
15
|
+
import { GAELIC_LEAGUES, gaelicInFeet } from "./leagues/gaelic.js";
|
|
16
|
+
import { HANDBALL_LEAGUES, handballInFeet } from "./leagues/handball.js";
|
|
17
|
+
import { LACROSSE_LEAGUES, lacrosseInFeet } from "./leagues/lacrosse.js";
|
|
18
|
+
import { RUGBY_LEAGUES, rugbyInFeet } from "./leagues/rugby.js";
|
|
19
|
+
import { LEAGUE_SOURCES } from "./leagues/sources.js";
|
|
20
|
+
import { inFeet } from "./leagues/types.js";
|
|
21
|
+
import { convertLength } from "./units.js";
|
|
22
|
+
export { LEAGUE_SOURCES };
|
|
23
|
+
export { AFL_GROUNDS } from "./leagues/aussie.js";
|
|
24
|
+
/** The family of surface each sport draws; soccer's variants are its pitches (`pitch`), not leagues. */
|
|
25
|
+
export const FAMILY_OF = Object.freeze({ nfl: "football", cfl: "football", ifaf: "football", nhl: "hockey", nba: "basketball", mlb: "baseball", soccer: undefined, curling: "curling", tennis: "tennis", volleyball: "volleyball", badminton: "badminton", pickleball: "pickleball", tabletennis: "tabletennis", lacrosse: "lacrosse", rugby: "rugby", afl: "afl", gaelic: "gaelic", cricket: "cricket", fieldhockey: "fieldhockey", handball: "handball" });
|
|
26
|
+
/**
|
|
27
|
+
* The leagues each sport can draw, in the order a menu lists them, the sport's own first (the three football sports share their
|
|
28
|
+
* list, the football leagues). Soccer has none.
|
|
29
|
+
*/
|
|
30
|
+
export const LEAGUES = Object.freeze({
|
|
31
|
+
nba: BASKETBALL_LEAGUES,
|
|
32
|
+
nhl: HOCKEY_LEAGUES,
|
|
33
|
+
nfl: FOOTBALL_LEAGUES,
|
|
34
|
+
cfl: FOOTBALL_LEAGUES,
|
|
35
|
+
ifaf: FOOTBALL_LEAGUES,
|
|
36
|
+
mlb: BASEBALL_LEAGUES,
|
|
37
|
+
soccer: [],
|
|
38
|
+
curling: CURLING_LEAGUES,
|
|
39
|
+
tennis: TENNIS_LEAGUES,
|
|
40
|
+
volleyball: VOLLEYBALL_LEAGUES,
|
|
41
|
+
badminton: BADMINTON_LEAGUES,
|
|
42
|
+
pickleball: PICKLEBALL_LEAGUES,
|
|
43
|
+
tabletennis: TABLE_TENNIS_LEAGUES,
|
|
44
|
+
lacrosse: LACROSSE_LEAGUES,
|
|
45
|
+
rugby: RUGBY_LEAGUES,
|
|
46
|
+
afl: AFL_LEAGUES,
|
|
47
|
+
gaelic: GAELIC_LEAGUES,
|
|
48
|
+
cricket: CRICKET_LEAGUES,
|
|
49
|
+
fieldhockey: FIELD_HOCKEY_LEAGUES,
|
|
50
|
+
handball: HANDBALL_LEAGUES,
|
|
51
|
+
});
|
|
52
|
+
/** Every league of every family, once each. */
|
|
53
|
+
export const VARIANTS = Object.freeze([...BASKETBALL_LEAGUES, ...HOCKEY_LEAGUES, ...FOOTBALL_LEAGUES, ...BASEBALL_LEAGUES, ...CURLING_LEAGUES, ...TENNIS_LEAGUES, ...VOLLEYBALL_LEAGUES, ...BADMINTON_LEAGUES, ...PICKLEBALL_LEAGUES, ...TABLE_TENNIS_LEAGUES, ...LACROSSE_LEAGUES, ...RUGBY_LEAGUES, ...AFL_LEAGUES, ...GAELIC_LEAGUES, ...CRICKET_LEAGUES, ...FIELD_HOCKEY_LEAGUES, ...HANDBALL_LEAGUES]);
|
|
54
|
+
/** The ids of a sport's leagues. */
|
|
55
|
+
export const leagueIds = (sport) => LEAGUES[sport].map((league) => league.id);
|
|
56
|
+
/** A league by its sport and id, or `undefined`. */
|
|
57
|
+
export function leagueById(sport, id) {
|
|
58
|
+
return LEAGUES[sport].find((league) => league.id === id);
|
|
59
|
+
}
|
|
60
|
+
/** The unit a league's figures are kept in. */
|
|
61
|
+
const figuresUnit = (league) => league.figuresUnit ?? league.unit;
|
|
62
|
+
/**
|
|
63
|
+
* Which league the options ask for: the league, and the sport it is drawn as. No `league` is the sport's own. A league the sport's
|
|
64
|
+
* own (`nba` for `nba`) is the sport as it is drawn without one; one of the football leagues that is a sport of its own (`cfl`) is that
|
|
65
|
+
* sport. A league of another family, or one that does not exist, is an error that says what to use.
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* import { chooseLeague } from "@johnmorrisdotca/kyogijo-stadiums/leagues";
|
|
69
|
+
* console.log(chooseLeague({ sport: "nba", league: "fiba" }).league?.name.en, chooseLeague({ sport: "nfl", league: "cfl" }).sport);
|
|
70
|
+
* // FIBA basketball court cfl
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export function chooseLeague(o) {
|
|
74
|
+
if (o.league === undefined || o.league === "")
|
|
75
|
+
return { sport: o.sport, league: undefined };
|
|
76
|
+
const id = String(o.league);
|
|
77
|
+
const family = FAMILY_OF[o.sport];
|
|
78
|
+
if (family === undefined)
|
|
79
|
+
throw new Error(`"${String(o.sport)}" has no leagues: a soccer pitch is chosen with pitch`);
|
|
80
|
+
const found = leagueById(o.sport, id);
|
|
81
|
+
if (found === undefined) {
|
|
82
|
+
const elsewhere = Object.keys(FAMILY_OF).find((sport) => FAMILY_OF[sport] !== family && FAMILY_OF[sport] !== undefined && leagueById(sport, id) !== undefined);
|
|
83
|
+
throw new Error(elsewhere === undefined ? `Unknown league "${id}" for "${o.sport}": use one of ${leagueIds(o.sport).join(", ")}` : `"${id}" is a ${FAMILY_OF[elsewhere]} league: use sport "${elsewhere}" for it`);
|
|
84
|
+
}
|
|
85
|
+
if (found.builtIn === true)
|
|
86
|
+
return { sport: found.family === "football" ? found.id : o.sport, league: undefined };
|
|
87
|
+
return { sport: o.sport, league: found };
|
|
88
|
+
}
|
|
89
|
+
const historyOf = (league) => Object.entries(league.history ?? {});
|
|
90
|
+
/**
|
|
91
|
+
* Every change a source dates in a league's markings, in season order, each with a sentence in English and in Japanese and its
|
|
92
|
+
* sources. A league with no cited history has none (a drawing with a `year` is then the league's rulebook as it is now).
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* import { leagueChanges } from "@johnmorrisdotca/kyogijo-stadiums/leagues";
|
|
96
|
+
* console.log(leagueChanges("nba", "ncaa-men").map((change) => change.id));
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export function leagueChanges(sport, id) {
|
|
100
|
+
const league = leagueById(sport, id);
|
|
101
|
+
if (league === undefined)
|
|
102
|
+
throw new Error(`Unknown league "${id}" for "${String(sport)}"`);
|
|
103
|
+
return historyOf(league)
|
|
104
|
+
.flatMap(([feature, spans]) => spans.map((span) => ({ id: `${league.id}.${feature}.${span.from === null ? "start" : span.from}`, league: league.id, feature, from: span.from, value: span.value, what: span.what, ja: span.ja, sources: span.sources })))
|
|
105
|
+
.sort((a, b) => (a.from ?? -Infinity) - (b.from ?? -Infinity) || a.id.localeCompare(b.id));
|
|
106
|
+
}
|
|
107
|
+
/** True when a league has markings a source dates, so that `year` changes its drawing. */
|
|
108
|
+
export const hasHistory = (league) => league !== undefined && historyOf(league).length > 0;
|
|
109
|
+
/** The markings that hold in a season: the last span that began by then, else the first (a gap). */
|
|
110
|
+
function spanIn(spans, year) {
|
|
111
|
+
let found;
|
|
112
|
+
for (const span of spans)
|
|
113
|
+
if (span.from === null || span.from <= year)
|
|
114
|
+
found = span;
|
|
115
|
+
return found === undefined ? { span: spans[0], gap: true } : { span: found, gap: false };
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* A league's figures as they were in a season. Without a year, or for a league with no dated history, they are the rulebook's as
|
|
119
|
+
* it is now.
|
|
120
|
+
* @example
|
|
121
|
+
* ```ts
|
|
122
|
+
* import { leagueAt } from "@johnmorrisdotca/kyogijo-stadiums/leagues";
|
|
123
|
+
* console.log(leagueAt("nba", "ncaa-men", 2010).differences.map((change) => change.id));
|
|
124
|
+
* // [ 'ncaa-men.restricted.start' ]
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
export function leagueAt(sport, id, year) {
|
|
128
|
+
const league = leagueById(sport, id);
|
|
129
|
+
if (league === undefined)
|
|
130
|
+
throw new Error(`Unknown league "${id}" for "${String(sport)}"`);
|
|
131
|
+
return leagueAtOf(league, year);
|
|
132
|
+
}
|
|
133
|
+
/** `leagueAt` for a league already in hand. */
|
|
134
|
+
export function leagueAtOf(league, year) {
|
|
135
|
+
const asked = typeof year === "number" && Number.isFinite(year) ? Math.floor(year) : undefined;
|
|
136
|
+
const figures = { ...league.dimensions };
|
|
137
|
+
const differences = [];
|
|
138
|
+
const gaps = [];
|
|
139
|
+
if (asked !== undefined) {
|
|
140
|
+
for (const [feature, spans] of historyOf(league)) {
|
|
141
|
+
const { span, gap } = spanIn(spans, asked);
|
|
142
|
+
figures[feature] = span.value;
|
|
143
|
+
if (gap)
|
|
144
|
+
gaps.push(feature);
|
|
145
|
+
else if (JSON.stringify(span.value) !== JSON.stringify(league.dimensions[feature])) {
|
|
146
|
+
differences.push({ id: `${league.id}.${feature}.${span.from === null ? "start" : span.from}`, league: league.id, feature, from: span.from, value: span.value, what: span.what, ja: span.ja, sources: span.sources });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return { league, year: asked, figures: figures, differences, gaps };
|
|
151
|
+
}
|
|
152
|
+
/** The name of a season as the family writes it: `1979–80` for basketball and hockey, which play across the new year, else `1979`. */
|
|
153
|
+
export function leagueSeason(family, year) {
|
|
154
|
+
const y = Math.floor(year);
|
|
155
|
+
return family === "basketball" || family === "hockey" ? `${y}–${String((y + 1) % 100).padStart(2, "0")}` : String(y);
|
|
156
|
+
}
|
|
157
|
+
/** A basketball court of a league in a season, in feet. */
|
|
158
|
+
export const courtOf = (league, year) => courtInFeet(leagueAtOf(league, year).figures, figuresUnit(league));
|
|
159
|
+
/** An ice rink of a league in a season, in feet. */
|
|
160
|
+
export const rinkOf = (league, year) => rinkInFeet(leagueAtOf(league, year).figures, figuresUnit(league));
|
|
161
|
+
/** A curling sheet of a league, in feet. A sheet has no history; a year is ignored. */
|
|
162
|
+
export const sheetOf = (league = CURLING_LEAGUES[0]) => sheetInFeet(league.dimensions, league.figuresUnit ?? league.unit);
|
|
163
|
+
/** A net sport's court of a league (tennis, volleyball and beach volleyball, badminton, pickleball, table tennis), in feet. These courts have no history; a year is ignored. */
|
|
164
|
+
export const netOf = (league) => netInFeet(league.dimensions, figuresUnit(league));
|
|
165
|
+
/** A lacrosse surface of a league, in feet (the box floor, or a field). These have no history; a year is ignored. */
|
|
166
|
+
export const lacrosseOf = (league) => lacrosseInFeet(league.dimensions, figuresUnit(league));
|
|
167
|
+
/** A rugby field of a league, in feet. */
|
|
168
|
+
export const rugbyOf = (league) => rugbyInFeet(league.dimensions, figuresUnit(league));
|
|
169
|
+
/** The Australian football ground, in feet. */
|
|
170
|
+
export const aflOf = (league) => aflInFeet(league.dimensions, figuresUnit(league));
|
|
171
|
+
/** A Gaelic games field of a league (football or hurling), in feet. */
|
|
172
|
+
export const gaelicOf = (league) => gaelicInFeet(league.dimensions, figuresUnit(league));
|
|
173
|
+
/** A cricket ground of a league, in feet. */
|
|
174
|
+
export const cricketOf = (league) => cricketInFeet(league.dimensions, figuresUnit(league));
|
|
175
|
+
/** A field hockey pitch, in feet. */
|
|
176
|
+
export const fieldHockeyOf = (league) => fieldHockeyInFeet(league.dimensions, figuresUnit(league));
|
|
177
|
+
/** A handball court, in feet. */
|
|
178
|
+
export const handballOf = (league) => handballInFeet(league.dimensions, figuresUnit(league));
|
|
179
|
+
/** A football field of a league in a season: the spec, in feet. */
|
|
180
|
+
export const fieldOf = (league, year) => inFeet(leagueAtOf(league, year).figures, figuresUnit(league));
|
|
181
|
+
/** A diamond of a league in a season, in feet. */
|
|
182
|
+
export const diamondOf = (league, year) => diamondInFeet(leagueAtOf(league, year).figures, figuresUnit(league));
|
|
183
|
+
/**
|
|
184
|
+
* The length and the width of a league's surface in a unit (the league's own when none is given): a football field with its end
|
|
185
|
+
* zones, end line to end line. A diamond has no fixed size, its fence is its size.
|
|
186
|
+
* @example
|
|
187
|
+
* ```ts
|
|
188
|
+
* import { leagueSize } from "@johnmorrisdotca/kyogijo-stadiums/leagues";
|
|
189
|
+
* console.log(leagueSize("nba", "nba"));
|
|
190
|
+
* // { length: 94, width: 50, unit: 'ft' }
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
export function leagueSize(sport, id, unit) {
|
|
194
|
+
const league = leagueById(sport, id);
|
|
195
|
+
if (league === undefined)
|
|
196
|
+
throw new Error(`Unknown league "${id}" for "${String(sport)}"`);
|
|
197
|
+
const to = unit ?? league.unit;
|
|
198
|
+
let feet;
|
|
199
|
+
switch (league.family) {
|
|
200
|
+
case "basketball":
|
|
201
|
+
feet = courtOf(league);
|
|
202
|
+
break;
|
|
203
|
+
case "hockey":
|
|
204
|
+
feet = rinkOf(league);
|
|
205
|
+
break;
|
|
206
|
+
case "curling":
|
|
207
|
+
feet = sheetOf(league);
|
|
208
|
+
break;
|
|
209
|
+
case "tennis": {
|
|
210
|
+
const t = netOf(league);
|
|
211
|
+
feet = { length: t.length, width: t.widthDoubles };
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
case "volleyball":
|
|
215
|
+
case "badminton":
|
|
216
|
+
case "pickleball":
|
|
217
|
+
case "tabletennis":
|
|
218
|
+
feet = netOf(league);
|
|
219
|
+
break;
|
|
220
|
+
case "football": {
|
|
221
|
+
const field = fieldOf(league);
|
|
222
|
+
feet = { length: field.length + 2 * field.endZone, width: field.width };
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
case "lacrosse": {
|
|
226
|
+
const f = lacrosseOf(league);
|
|
227
|
+
feet = { length: f.length.drawn, width: f.width.drawn };
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
case "rugby": {
|
|
231
|
+
const f = rugbyOf(league);
|
|
232
|
+
feet = { length: f.length.drawn + 2 * f.inGoal.drawn, width: f.width.drawn };
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
case "afl":
|
|
236
|
+
case "gaelic":
|
|
237
|
+
case "fieldhockey":
|
|
238
|
+
case "handball": {
|
|
239
|
+
const f = league.family === "afl" ? aflOf(league) : league.family === "gaelic" ? gaelicOf(league) : league.family === "fieldhockey" ? fieldHockeyOf(league) : handballOf(league);
|
|
240
|
+
feet = { length: f.length.drawn, width: f.width.drawn };
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
case "cricket": {
|
|
244
|
+
const f = cricketOf(league);
|
|
245
|
+
feet = { length: 2 * f.boundary.drawn, width: 2 * f.boundary.drawn };
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
default:
|
|
249
|
+
throw new Error(`No fixed size for the ${league.family} league "${id}": a diamond's size is its fence`);
|
|
250
|
+
}
|
|
251
|
+
return { length: convertLength(feet.length, "ft", to), width: convertLength(feet.width, "ft", to), unit: to };
|
|
252
|
+
}
|
|
253
|
+
/** A length in feet written in a unit: metres to two places, feet and inches (`22 ft 1.75 in`), yards to two places. */
|
|
254
|
+
function written(feet, unit) {
|
|
255
|
+
const trim = (n, places) => String(Math.round(n * 10 ** places) / 10 ** places);
|
|
256
|
+
if (unit === "m")
|
|
257
|
+
return `${trim(convertLength(feet, "ft", "m"), 3)} m`;
|
|
258
|
+
if (unit === "yd")
|
|
259
|
+
return `${trim(feet / 3, 2)} yd`;
|
|
260
|
+
const whole = Math.floor(feet + 1e-9);
|
|
261
|
+
const inches = Math.round((feet - whole) * 12 * 100) / 100;
|
|
262
|
+
return inches === 0 ? `${whole} ft` : whole === 0 ? `${trim(inches, 2)} in` : `${whole} ft ${trim(inches, 2)} in`;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* The key figures of a league in words, each in the unit its rulebook uses: for a table of the leagues (docs/variants.md) and for a
|
|
266
|
+
* test that holds the drawing to the rulebook.
|
|
267
|
+
* @example
|
|
268
|
+
* ```ts
|
|
269
|
+
* import { LEAGUES, leagueFigures } from "@johnmorrisdotca/kyogijo-stadiums/leagues";
|
|
270
|
+
* const fiba = LEAGUES.nba.find((league) => league.id === "fiba")!;
|
|
271
|
+
* console.log(leagueFigures(fiba).slice(0, 2).map(([name, value]) => `${name}: ${value}`).join("; "));
|
|
272
|
+
* // court: 28 m by 15 m; lane: 4.9 m wide
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
export function leagueFigures(league) {
|
|
276
|
+
const u = league.unit;
|
|
277
|
+
const w = (feet) => written(feet, u);
|
|
278
|
+
switch (league.family) {
|
|
279
|
+
case "basketball": {
|
|
280
|
+
const c = courtOf(league);
|
|
281
|
+
return [
|
|
282
|
+
["court", `${w(c.length)} by ${w(c.width)}`],
|
|
283
|
+
["lane", `${w(c.laneWidth)} wide`],
|
|
284
|
+
["free-throw line", `${w(c.freeThrowLine)} from the baseline`],
|
|
285
|
+
["three-point line", c.threePoint === null ? "none" : `${w(c.threePoint.radius)} arc, straights ${w(c.threePoint.sideInset)} from the sidelines`],
|
|
286
|
+
["restricted area", c.restricted === null ? "none" : `${w(c.restricted)} arc`],
|
|
287
|
+
];
|
|
288
|
+
}
|
|
289
|
+
case "hockey": {
|
|
290
|
+
const r = rinkOf(league);
|
|
291
|
+
return [
|
|
292
|
+
["rink", `${w(r.length)} by ${w(r.width)}`],
|
|
293
|
+
["corner radius", w(r.cornerRadius)],
|
|
294
|
+
["goal line", `${w(r.goalLine)} from the end boards`],
|
|
295
|
+
["blue line", `${w(r.blueLine)} from the end boards`],
|
|
296
|
+
["face-off circle", `${w(r.circleRadius)} radius`],
|
|
297
|
+
["trapezoid", r.trapezoid === null ? "none" : `${w(r.trapezoid.atGoalLine)} at the goal line, ${w(r.trapezoid.atBoards)} at the boards`],
|
|
298
|
+
];
|
|
299
|
+
}
|
|
300
|
+
case "curling": {
|
|
301
|
+
const s = sheetOf(league);
|
|
302
|
+
const [twelve, eight, four, button] = s.rings;
|
|
303
|
+
return [
|
|
304
|
+
["sheet", `${w(s.length)} by ${w(s.width)}`],
|
|
305
|
+
["least sheet", `${w(s.lengthMin)} by ${w(s.widthMin)}`],
|
|
306
|
+
["tee to tee", `${w(2 * s.teeFromMiddle)}`],
|
|
307
|
+
["back line", `${w(s.backLine)} from the tee`],
|
|
308
|
+
["hog line", `${w(s.hogLine)} from the tee`],
|
|
309
|
+
["house", `circles of ${w(twelve)}, ${w(eight)} and ${w(four)} radius, a button of ${w(button)}`],
|
|
310
|
+
["courtesy line", s.courtesy === null ? "none" : `${w(s.courtesy.outsideHog)} outside each hog line`],
|
|
311
|
+
];
|
|
312
|
+
}
|
|
313
|
+
case "tennis": {
|
|
314
|
+
const t = netOf(league);
|
|
315
|
+
return [
|
|
316
|
+
["court", `${w(t.length)} by ${w(t.widthDoubles)} (singles ${w(t.widthSingles)} wide)`],
|
|
317
|
+
["service line", `${w(t.serviceLine)} from the net`],
|
|
318
|
+
["net", `${w(t.net.heightPosts)} at the posts, ${w(t.net.heightCentre)} at the centre`],
|
|
319
|
+
["net posts", `${w(t.net.postsOutside)} outside the doubles court`],
|
|
320
|
+
["free zone", t.free.official === null ? "none" : `${w(t.free.official.end)} behind the baselines, ${w(t.free.official.side)} beside the sidelines`],
|
|
321
|
+
];
|
|
322
|
+
}
|
|
323
|
+
case "volleyball": {
|
|
324
|
+
const v = netOf(league);
|
|
325
|
+
return [
|
|
326
|
+
["court", `${w(v.length)} by ${w(v.width)}`],
|
|
327
|
+
["attack line", v.attackLine === null ? "none" : `${w(v.attackLine)} from the centre line`],
|
|
328
|
+
["net", `${w(v.net.length)} long, ${w(v.net.heightMen)} high (women's ${w(v.net.heightWomen)})`],
|
|
329
|
+
["posts", `${w(v.net.postsOutside)} outside the side lines`],
|
|
330
|
+
["free zone", v.free.official === null ? "none" : `${w(v.free.official.end)} behind the end lines, ${w(v.free.official.side)} beside the side lines`],
|
|
331
|
+
];
|
|
332
|
+
}
|
|
333
|
+
case "badminton": {
|
|
334
|
+
const b = netOf(league);
|
|
335
|
+
return [
|
|
336
|
+
["court", `${w(b.length)} by ${w(b.width)} (singles ${w(b.width - 2 * b.singlesInset)} wide)`],
|
|
337
|
+
["short service line", `${w(b.shortServiceLine)} from the net`],
|
|
338
|
+
["doubles long service line", `${w(b.doublesLongServiceInset)} inside the back boundary`],
|
|
339
|
+
["net", `${w(b.net.heightCentre)} at the centre, ${w(b.net.heightSides)} over the side lines`],
|
|
340
|
+
];
|
|
341
|
+
}
|
|
342
|
+
case "pickleball": {
|
|
343
|
+
const p = netOf(league);
|
|
344
|
+
return [
|
|
345
|
+
["court", `${w(p.length)} by ${w(p.width)}`],
|
|
346
|
+
["non-volley zone", `${w(p.nonVolley)} from the net`],
|
|
347
|
+
["net", `${w(p.net.heightSides)} at the sidelines, ${w(p.net.heightCentre)} at the centre`],
|
|
348
|
+
["playing surface", p.free.least === null ? "none" : `at least ${w(p.width + 2 * p.free.least.side)} by ${w(p.length + 2 * p.free.least.end)}`],
|
|
349
|
+
];
|
|
350
|
+
}
|
|
351
|
+
case "tabletennis": {
|
|
352
|
+
const t = netOf(league);
|
|
353
|
+
return [
|
|
354
|
+
["table", `${w(t.length)} by ${w(t.width)}, ${w(t.height)} high`],
|
|
355
|
+
["net", `${w(t.net.height)} above the playing surface`],
|
|
356
|
+
["lines", `${w(t.edgeLine)} at the edges, a ${w(t.centreLine)} centre line`],
|
|
357
|
+
];
|
|
358
|
+
}
|
|
359
|
+
case "football": {
|
|
360
|
+
const f = fieldOf(league);
|
|
361
|
+
return [
|
|
362
|
+
["goal lines", `${written(f.length, "yd")} apart`],
|
|
363
|
+
["end zones", written(f.endZone, "yd")],
|
|
364
|
+
["width", written(f.width, "yd")],
|
|
365
|
+
["hash marks", `${written(f.hash, "ft")} from each sideline`],
|
|
366
|
+
["goal posts", `${written(f.postWidth ?? 18.5, "ft")} apart, on the ${f.posts === "end-line" ? "end line" : "goal line"}`],
|
|
367
|
+
];
|
|
368
|
+
}
|
|
369
|
+
case "rugby": {
|
|
370
|
+
const f = rugbyOf(league);
|
|
371
|
+
const r = (x) => (x.min === x.max ? w(x.max) : `${w(x.min)} to ${w(x.max)}`);
|
|
372
|
+
return [
|
|
373
|
+
["field of play", `${r(f.length)} by ${r(f.width)}`],
|
|
374
|
+
["in-goal", `${r(f.inGoal)} deep`],
|
|
375
|
+
["goal posts", `${w(f.postsApart)} apart, the crossbar ${w(f.crossbar)} up`],
|
|
376
|
+
f.code === "union" ? ["22-metre line", `${w(f.twentyTwo)} from the try line`] : ["lines across", `every ${w(f.step)} from each goal line`],
|
|
377
|
+
];
|
|
378
|
+
}
|
|
379
|
+
case "lacrosse": {
|
|
380
|
+
const f = lacrosseOf(league);
|
|
381
|
+
const r = (x) => (x.min === x.max ? w(x.max) : `${w(x.min)} to ${w(x.max)}`);
|
|
382
|
+
const out = [
|
|
383
|
+
[f.kind === "box" ? "floor" : "field", `${r(f.length)} by ${r(f.width)}`],
|
|
384
|
+
["goal", `${w(f.goalWidth)} wide and ${w(f.goalHeight)} high, its line ${w(f.goalLine)} from the end ${f.kind === "box" ? "boards" : "line"}`],
|
|
385
|
+
];
|
|
386
|
+
if (f.crease !== null)
|
|
387
|
+
out.push(["crease", `a circle of ${w(f.crease)} radius`]);
|
|
388
|
+
if (f.goalCircle !== null)
|
|
389
|
+
out.push(["goal circle", `${w(f.goalCircle)} radius`]);
|
|
390
|
+
if (f.restraining !== null)
|
|
391
|
+
out.push(["restraining line", `${w(f.restraining)} from the goal line`]);
|
|
392
|
+
if (f.restrainingFromCentre !== null)
|
|
393
|
+
out.push(["restraining line", `${w(f.restrainingFromCentre)} from the centre line`]);
|
|
394
|
+
if (f.twoPoint !== null)
|
|
395
|
+
out.push(["two-point arc", `${w(f.twoPoint.gle)} from the goal at the goal line extended, then an arc of ${w(f.twoPoint.radius)}`]);
|
|
396
|
+
return out;
|
|
397
|
+
}
|
|
398
|
+
case "afl": {
|
|
399
|
+
const f = aflOf(league);
|
|
400
|
+
const r = (x) => `${w(x.min)} to ${w(x.max)}`;
|
|
401
|
+
return [
|
|
402
|
+
["ground", `an oval ${r(f.length)} long and ${r(f.width)} wide`],
|
|
403
|
+
["goal posts", `${w(f.goalPosts)} apart, behind posts ${w(f.behindPosts)} either side`],
|
|
404
|
+
["goal square", `${w(f.goalSquareDepth)} deep`],
|
|
405
|
+
["centre square", `${w(f.centreSquare)} by ${w(f.centreSquare)}`],
|
|
406
|
+
["fifty metre arc", `${w(f.fiftyArc)} from the middle of the goal line`],
|
|
407
|
+
];
|
|
408
|
+
}
|
|
409
|
+
case "gaelic": {
|
|
410
|
+
const f = gaelicOf(league);
|
|
411
|
+
const r = (x) => `${w(x.min)} to ${w(x.max)}`;
|
|
412
|
+
return [
|
|
413
|
+
["field", `${r(f.length)} by ${r(f.width)}`],
|
|
414
|
+
["lines across", f.lines.map((line) => w(line)).join(", ")],
|
|
415
|
+
["goalposts", `${w(f.postsApart)} apart, the crossbar ${w(f.crossbar)} up`],
|
|
416
|
+
["rectangles", `${w(f.small.depth)} deep and ${w(f.large.depth)} deep`],
|
|
417
|
+
];
|
|
418
|
+
}
|
|
419
|
+
case "cricket": {
|
|
420
|
+
const f = cricketOf(league);
|
|
421
|
+
// The Laws print yards for the pitch's length and the boundary and feet and inches for the rest.
|
|
422
|
+
const ft = (feet) => written(feet, "ft");
|
|
423
|
+
return [
|
|
424
|
+
["pitch", `${w(f.pitchLength)} by ${ft(f.pitchWidth)}`],
|
|
425
|
+
["bowling crease", `${ft(f.bowlingCrease)} long`],
|
|
426
|
+
["popping crease", `${ft(f.poppingCrease)} in front of the bowling crease, marked ${ft(f.poppingEach)} either side of the middle stumps at least`],
|
|
427
|
+
["return creases", `${ft(f.returnOutside)} either side of the middle stumps, marked ${ft(f.returnBehind)} behind the popping crease`],
|
|
428
|
+
["wickets", `${ft(f.wicket)} wide`],
|
|
429
|
+
["boundary", Number.isFinite(f.boundary.max) ? `${w(f.boundary.min)} to ${w(f.boundary.max)} from the centre of the pitch` : "no size given"],
|
|
430
|
+
["circle", f.circle === null ? "none" : `${w(f.circle)} radius about each middle stump`],
|
|
431
|
+
];
|
|
432
|
+
}
|
|
433
|
+
case "fieldhockey": {
|
|
434
|
+
const f = fieldHockeyOf(league);
|
|
435
|
+
return [
|
|
436
|
+
["pitch", `${w(f.length.max)} by ${w(f.width.max)}`],
|
|
437
|
+
["23-metre lines", `${w(f.twentyThree)} from each back-line`],
|
|
438
|
+
["circle", `${w(f.circleRadius)} from the back-line`],
|
|
439
|
+
["goal", `${w(f.goalWidth)} wide and ${w(f.goalHeight)} high`],
|
|
440
|
+
];
|
|
441
|
+
}
|
|
442
|
+
case "handball": {
|
|
443
|
+
const f = handballOf(league);
|
|
444
|
+
return [
|
|
445
|
+
["court", `${w(f.length.max)} by ${w(f.width.max)}`],
|
|
446
|
+
["goal area line", `${w(f.areaDistance)} from the goal line`],
|
|
447
|
+
["free-throw line", `${w(f.areaDistance + f.freeThrowOutside)} from the goal line`],
|
|
448
|
+
["goal", `${w(f.goalWidth)} wide and ${w(f.goalHeight)} high`],
|
|
449
|
+
];
|
|
450
|
+
}
|
|
451
|
+
default: {
|
|
452
|
+
const d = diamondOf(league);
|
|
453
|
+
const f = d.fence;
|
|
454
|
+
const fence = [f.left, f.center].filter((n) => n !== undefined);
|
|
455
|
+
return [
|
|
456
|
+
["bases", `${written(d.base, "ft")} apart`],
|
|
457
|
+
["pitching distance", written(d.pitcher, "ft")],
|
|
458
|
+
["fence", f.left === undefined ? "none given" : f.center === undefined || f.center === f.left ? `${written(f.left, "ft")}` : `${written(fence[0], "ft")} at the lines, ${written(fence[1], "ft")} in the middle`],
|
|
459
|
+
];
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
package/dist/look.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { LookName, Sport } from "./types.ts";
|
|
2
|
+
/** The parts of a palette, each a custom property of the stylesheet. */
|
|
3
|
+
export type PaletteKey = "ink" | "line" | "apron" | "surface" | "alt" | "zone" | "boards" | "red" | "blue" | "dirt" | "foul" | "infield" | "crease" | "key" | "court" | "post" | "pylon" | "rgo" | "rgm" | "rgi" | "rgb" | "hog" | "hack" | "fgz" | "pebble" | "free" | "net" | "area";
|
|
4
|
+
/** Colours by part. */
|
|
5
|
+
export type Palette = Partial<Record<PaletteKey, string>>;
|
|
6
|
+
/** The surfaces that are painted alike: football's three fields are one. */
|
|
7
|
+
export type Group = "football" | "nhl" | "nba" | "mlb" | "soccer" | "curling" | "net";
|
|
8
|
+
/** One mode of a look: a palette for every sport, and what a group of sports changes in it. */
|
|
9
|
+
export interface Mode {
|
|
10
|
+
base: Palette;
|
|
11
|
+
groups?: Partial<Record<Group, Palette>>;
|
|
12
|
+
}
|
|
13
|
+
/** A named look. */
|
|
14
|
+
export interface Look {
|
|
15
|
+
/** What it is for, in a sentence. */
|
|
16
|
+
about: string;
|
|
17
|
+
light: Mode;
|
|
18
|
+
dark: Mode;
|
|
19
|
+
}
|
|
20
|
+
/** The group a sport is painted with, or `undefined` for a surface with no palette of its own (it takes the look's base). */
|
|
21
|
+
export declare const groupOf: (sport: Sport | string) => Group | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* The named looks. Each is a light and a dark palette for every sport, as custom properties on `.kyogijo[data-palette="<name>"]`; pass one as `look`.
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* import { LOOKS, drawKyogijo } from "@johnmorrisdotca/kyogijo-stadiums";
|
|
27
|
+
* const svg = drawKyogijo({ sport: "nhl", look: "chalkboard" });
|
|
28
|
+
* console.log(Object.keys(LOOKS).length, svg.includes('data-palette="chalkboard"'));
|
|
29
|
+
* // 7 true
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare const LOOKS: Readonly<Record<LookName, Look>>;
|
|
33
|
+
/** The names of the looks, in the order a menu lists them. */
|
|
34
|
+
export declare const LOOK_NAMES: readonly LookName[];
|
|
35
|
+
/** True when a value names a look. */
|
|
36
|
+
export declare const isLook: (value: unknown) => value is LookName;
|
|
37
|
+
/** A look's palette for a sport in one mode: the look's base with what the sport's group changes. */
|
|
38
|
+
export declare function lookPalette(look: LookName, mode: "light" | "dark", sport: Sport | string): Palette;
|
|
39
|
+
/**
|
|
40
|
+
* The pairs of a palette that must read: what is painted on what, as `[ink, ground, least contrast]` (WCAG 2.2's 3:1 for a line, 4.5:1 for text). The words
|
|
41
|
+
* of the drawing are on the apron; a line is on the surface and, where its sport paints them under it, on the second tone of the mowing or planks, the key,
|
|
42
|
+
* the dirt, the infield and the foul ground.
|
|
43
|
+
*/
|
|
44
|
+
export declare const LOOK_PAIRS: Readonly<Record<Group | "all", readonly (readonly [PaletteKey, PaletteKey, number])[]>>;
|
|
45
|
+
/** The contrast ratio of two colours (WCAG 2.2): 1 to 21, or `undefined` when a colour cannot be read without a browser. */
|
|
46
|
+
export declare function contrastOf(a: string | undefined, b: string | undefined): number | undefined;
|
|
47
|
+
/** The stylesheet of one look, light and dark, at no weight. A drawing with a `look` carries its look's. */
|
|
48
|
+
export declare function lookStyle(name: LookName): string;
|
|
49
|
+
/** The stylesheet of every look, for a page that draws with `style: "none"`. */
|
|
50
|
+
export declare const KYOGIJO_LOOK_STYLE: string;
|