@johnmorrisdotca/kyogijo-stadiums 0.5.0 → 0.6.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 +58 -0
- package/NOTICE.md +179 -3
- package/README.md +43 -11
- package/dist/arenas-entry.d.ts +4 -0
- package/dist/arenas-entry.js +3 -0
- package/dist/arenas.d.ts +125 -0
- package/dist/arenas.data.d.ts +2 -0
- package/dist/arenas.data.js +3763 -0
- package/dist/arenas.js +72 -0
- package/dist/atlas-entry.d.ts +3 -1
- package/dist/atlas-entry.js +3 -2
- package/dist/atlas.d.ts +37 -19
- package/dist/atlas.js +92 -7
- package/dist/background.js +2 -1
- package/dist/budo/describe.d.ts +13 -0
- package/dist/budo/describe.js +120 -0
- package/dist/budo/dojo.api.d.ts +64 -0
- package/dist/budo/dojo.api.js +46 -0
- package/dist/budo/dojo.d.ts +72 -0
- package/dist/budo/dojo.js +300 -0
- package/dist/budo/judo.d.ts +61 -0
- package/dist/budo/judo.js +109 -0
- package/dist/budo/karate.d.ts +29 -0
- package/dist/budo/karate.js +80 -0
- package/dist/budo/kendo.d.ts +18 -0
- package/dist/budo/kendo.js +44 -0
- package/dist/budo/kimarite.d.ts +19 -0
- package/dist/budo/kimarite.js +33 -0
- package/dist/budo/kit.d.ts +16 -0
- package/dist/budo/kit.js +24 -0
- package/dist/budo/kyudo.d.ts +28 -0
- package/dist/budo/kyudo.js +66 -0
- package/dist/budo/looks.d.ts +28 -0
- package/dist/budo/looks.js +58 -0
- package/dist/budo/parts.d.ts +32 -0
- package/dist/budo/parts.js +10 -0
- package/dist/budo/plan.d.ts +64 -0
- package/dist/budo/plan.js +139 -0
- package/dist/budo/room.d.ts +133 -0
- package/dist/budo/room.js +111 -0
- package/dist/budo/sumo.d.ts +31 -0
- package/dist/budo/sumo.js +71 -0
- package/dist/budo/tatami.d.ts +55 -0
- package/dist/budo/tatami.js +156 -0
- package/dist/budo/types.d.ts +192 -0
- package/dist/budo/types.js +2 -0
- package/dist/budo-entry.d.ts +22 -0
- package/dist/budo-entry.js +13 -0
- package/dist/budo.board.d.ts +28 -0
- package/dist/budo.board.js +81 -0
- package/dist/budo.score.d.ts +18 -0
- package/dist/budo.score.js +52 -0
- package/dist/budo.style.d.ts +6 -0
- package/dist/budo.style.js +67 -0
- package/dist/charts.baseball.js +1 -1
- package/dist/charts.js +4 -4
- package/dist/charts.soccer.js +3 -3
- package/dist/charts.types.d.ts +10 -0
- package/dist/colour.d.ts +4 -4
- package/dist/colour.js +4 -4
- package/dist/crowd.d.ts +11 -1
- package/dist/crowd.draw.js +15 -9
- package/dist/crowd.js +17 -2
- package/dist/draw.js +156 -31
- package/dist/element-entry.d.ts +2 -0
- package/dist/element-entry.js +1 -0
- package/dist/element.d.ts +2 -2
- package/dist/element.js +2 -1
- package/dist/emblems-source.d.ts +50 -0
- package/dist/emblems-source.js +56 -0
- package/dist/eras.d.ts +3 -1
- package/dist/eras.js +8 -3
- package/dist/features.js +73 -0
- package/dist/field.data.d.ts +16 -0
- package/dist/field.data.js +50 -0
- package/dist/fields.kit.d.ts +2 -2
- package/dist/fields.types.d.ts +9 -3
- package/dist/formations.js +18 -7
- package/dist/formations.sports.d.ts +8 -0
- package/dist/formations.sports.js +251 -0
- package/dist/frames.providers.js +9 -1
- package/dist/halls.d.ts +65 -0
- package/dist/halls.js +122 -0
- package/dist/heat.js +17 -10
- package/dist/heat.zones.d.ts +4 -2
- package/dist/heat.zones.js +55 -3
- package/dist/homeside.js +7 -0
- package/dist/index.d.ts +15 -3
- package/dist/index.js +8 -1
- package/dist/layers-entry.d.ts +2 -1
- package/dist/layers-entry.js +1 -0
- package/dist/layers.d.ts +2 -1
- package/dist/layers.env.d.ts +10 -1
- package/dist/layers.env.js +33 -3
- package/dist/layers.js +30 -11
- package/dist/layers.types.d.ts +9 -2
- package/dist/leagues/budo.d.ts +196 -0
- package/dist/leagues/budo.js +105 -0
- package/dist/leagues/hockey.js +41 -19
- package/dist/leagues/sources.js +21 -0
- package/dist/leagues/types.d.ts +1 -1
- package/dist/leagues.d.ts +4 -1
- package/dist/leagues.js +102 -2
- package/dist/lineup.codes.d.ts +23 -0
- package/dist/lineup.codes.js +122 -0
- package/dist/logo.d.ts +25 -0
- package/dist/logo.js +47 -0
- package/dist/outline.d.ts +1 -1
- package/dist/outline.js +17 -3
- package/dist/pageant.js +7 -3
- package/dist/pointer-entry.d.ts +2 -0
- package/dist/pointer-entry.js +2 -0
- package/dist/pointer.d.ts +113 -0
- package/dist/pointer.js +151 -0
- package/dist/pool.d.ts +7 -7
- package/dist/pool.figures.d.ts +57 -55
- package/dist/pool.figures.js +59 -55
- package/dist/pool.js +7 -7
- package/dist/pool.labels.js +2 -1
- package/dist/ranges.names.js +6 -0
- package/dist/road.draw.js +3 -2
- package/dist/road.js +2 -1
- package/dist/road.types.d.ts +3 -0
- package/dist/rules.d.ts +138 -0
- package/dist/rules.js +511 -0
- package/dist/rules.types.d.ts +4 -0
- package/dist/rules.types.js +64 -0
- package/dist/score.d.ts +3 -0
- package/dist/score.js +23 -1
- package/dist/situation.d.ts +135 -0
- package/dist/situation.draw.d.ts +34 -0
- package/dist/situation.draw.js +202 -0
- package/dist/situation.js +337 -0
- package/dist/situation.style.d.ts +2 -0
- package/dist/situation.style.js +45 -0
- package/dist/situation.types.d.ts +77 -0
- package/dist/situation.types.js +3 -0
- package/dist/situation.widgets.d.ts +39 -0
- package/dist/situation.widgets.js +129 -0
- package/dist/strings.d.ts +175 -1
- package/dist/strings.js +364 -20
- package/dist/style.js +9 -2
- package/dist/surfaces/artistic.d.ts +3 -3
- package/dist/surfaces/artistic.js +3 -3
- package/dist/surfaces/baseball.js +2 -0
- package/dist/surfaces/basketball.js +1 -1
- package/dist/surfaces/budo.d.ts +6 -0
- package/dist/surfaces/budo.js +104 -0
- package/dist/surfaces/dive.d.ts +3 -3
- package/dist/surfaces/dive.js +3 -3
- package/dist/surfaces/football.js +7 -0
- package/dist/surfaces/hockey.js +3 -2
- package/dist/surfaces/polo.d.ts +4 -4
- package/dist/surfaces/polo.js +5 -5
- package/dist/surfaces/pool.d.ts +1 -1
- package/dist/surfaces/pool.js +3 -3
- package/dist/surfaces/surface.d.ts +32 -0
- package/dist/surfaces/venue.d.ts +1 -1
- package/dist/surfaces/venue.js +1 -1
- package/dist/target-entry.d.ts +2 -0
- package/dist/target-entry.js +2 -0
- package/dist/target.d.ts +200 -0
- package/dist/target.js +525 -0
- package/dist/team.common.d.ts +1 -1
- package/dist/team.common.js +3 -3
- package/dist/team.formation.d.ts +3 -1
- package/dist/team.formation.js +3 -3
- package/dist/team.layers.d.ts +2 -2
- package/dist/team.layers.js +4 -1
- package/dist/team.lineup.d.ts +27 -0
- package/dist/team.lineup.js +207 -0
- package/dist/team.network.js +6 -5
- package/dist/team.shape.js +5 -5
- package/dist/team.types.d.ts +40 -1
- package/dist/tenants.data.js +848 -0
- package/dist/turn-entry.d.ts +2 -2
- package/dist/turn-entry.js +1 -1
- package/dist/turn.camera.d.ts +12 -1
- package/dist/turn.camera.js +18 -2
- package/dist/turn.dom.js +11 -9
- package/dist/turn.kit.d.ts +2 -2
- package/dist/turn.style.js +4 -3
- package/dist/types.d.ts +43 -7
- package/dist/units.js +7 -0
- package/dist/uprights.budo.d.ts +17 -0
- package/dist/uprights.budo.js +87 -0
- package/dist/uprights.js +10 -1
- package/dist/uprights.pools.js +4 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/zones-entry.d.ts +2 -0
- package/dist/zones-entry.js +2 -0
- package/package.json +39 -3
package/dist/arenas.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { ARENA_DATA } from "./arenas.data.js";
|
|
2
|
+
import { officialName, placesNamed } from "./names.js";
|
|
3
|
+
const FEET_PER_METRE = 1 / 0.3048;
|
|
4
|
+
const tenth = (feet) => Math.round(feet * 10) / 10;
|
|
5
|
+
const inFeet = (size) => {
|
|
6
|
+
const k = size.unit === "m" ? FEET_PER_METRE : 1;
|
|
7
|
+
return { length: tenth(size.length * k), width: tenth(size.width * k) };
|
|
8
|
+
};
|
|
9
|
+
/** The size that held in a year: the one whose years cover it, else (with no year) the latest. */
|
|
10
|
+
const sizeIn = (sizes, year) => {
|
|
11
|
+
if (sizes === undefined || sizes.length === 0)
|
|
12
|
+
return undefined;
|
|
13
|
+
if (year === undefined || !Number.isFinite(year))
|
|
14
|
+
return inFeet(sizes.find((size) => size.to === undefined) ?? sizes[sizes.length - 1]);
|
|
15
|
+
const found = sizes.find((size) => (size.from === undefined || size.from <= year) && (size.to === undefined || year <= size.to));
|
|
16
|
+
return found === undefined ? undefined : inFeet(found);
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* The size of an arena's rink in feet, in a year or today (the latest), when the sources publish one that differs from the NHL's; else `undefined` and the NHL's 200 by 85 feet
|
|
20
|
+
* is the rink.
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { arenaById, arenaRinkIn } from "@johnmorrisdotca/kyogijo-stadiums/arenas";
|
|
24
|
+
* console.log(arenaRinkIn(arenaById("boston-garden")!), arenaRinkIn(arenaById("matthews-arena")!, 1926), arenaRinkIn(arenaById("td-garden")!));
|
|
25
|
+
* // { length: 190.9, width: 83 } { length: 220, width: 90 } undefined
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export const arenaRinkIn = (arena, year) => sizeIn(arena?.rink, year);
|
|
29
|
+
/** The size of an arena's court in feet, in a year or today, when the sources publish one that differs from the NBA's 94 by 50 feet; else `undefined`. */
|
|
30
|
+
export const arenaCourtIn = (arena, year) => sizeIn(arena?.court, year);
|
|
31
|
+
/**
|
|
32
|
+
* Every arena by its key: the homes of the NHL's, the NBA's, the WNBA's and the PWHL's clubs, today's and the old ones, each with where it stands, when it was in use, its names,
|
|
33
|
+
* its seats for each sport and, where the sources publish one that differs from the league's, the size of its rink or its court.
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* import { ARENAS } from "@johnmorrisdotca/kyogijo-stadiums/arenas";
|
|
37
|
+
* const garden = ARENAS["boston-garden"];
|
|
38
|
+
* console.log(garden.name, garden.city, garden.from, garden.to, garden.capacity?.hockey);
|
|
39
|
+
* // Boston Garden Boston 1928 1995 14448
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export const ARENAS = Object.freeze(Object.fromEntries(ARENA_DATA.map((data) => [data.id, data])));
|
|
43
|
+
/** The keys of `ARENAS`, in the order of the data: the arenas in use first, then those of the past. */
|
|
44
|
+
export const ARENA_IDS = Object.freeze(ARENA_DATA.map((data) => data.id));
|
|
45
|
+
/** The arena with a key, or `undefined`. */
|
|
46
|
+
export const arenaById = (id) => (id !== undefined && Object.prototype.hasOwnProperty.call(ARENAS, id) ? ARENAS[id] : undefined);
|
|
47
|
+
/** The arenas that answer to a name, best match first (see `placesByName`): the everyday names, then the official and cited names, then the former names and the nicknames. */
|
|
48
|
+
export const arenasByName = (name) => placesNamed(Object.values(ARENAS), name);
|
|
49
|
+
/** The arena a name belongs to (the best match when several answer to it), or `undefined`. */
|
|
50
|
+
export const arenaByName = (name) => arenasByName(name)[0];
|
|
51
|
+
/** The arena whose Wikidata item is `Q894567`, or `undefined`. */
|
|
52
|
+
export const arenaByWikidata = (wikidata) => Object.values(ARENAS).find((arena) => arena.wikidata === wikidata);
|
|
53
|
+
/** The name an arena had in a year (the name of the time in English; in Japanese there is one name for every year). */
|
|
54
|
+
export function arenaNameIn(arena, year, language = "en") {
|
|
55
|
+
if (language === "ja")
|
|
56
|
+
return arena.nameJa;
|
|
57
|
+
if (year === undefined || !Number.isFinite(year))
|
|
58
|
+
return arena.name;
|
|
59
|
+
const periods = (arena.names ?? []).filter((period) => period.from <= year && year <= period.to);
|
|
60
|
+
return periods.length === 0 ? arena.name : periods[periods.length - 1].name;
|
|
61
|
+
}
|
|
62
|
+
/** The name an arena officially has in a language, when it is not the everyday name; else `undefined`. */
|
|
63
|
+
export function arenaOfficialName(arena, language = "en", year) {
|
|
64
|
+
const shown = arenaNameIn(arena, year, language);
|
|
65
|
+
if (year !== undefined && Number.isFinite(year) && language === "en" && shown !== arena.name)
|
|
66
|
+
return undefined;
|
|
67
|
+
return officialName(arena, language, shown, Number.isFinite(year) ? year : undefined);
|
|
68
|
+
}
|
|
69
|
+
/** The address of the revision of an article that an arena's facts were read from. */
|
|
70
|
+
export function arenaSourceUrl(source, language = "en") {
|
|
71
|
+
return `https://${language}.wikipedia.org/w/index.php?title=${encodeURIComponent(source.title.replace(/ /g, "_"))}&oldid=${source.revision}`;
|
|
72
|
+
}
|
package/dist/atlas-entry.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export { PLACES, atlasFacets, placeById, placeByName, placesBy, placesByClub, placesByName, surfaceOf, surfacesOf, tenantsOf } from "./atlas.ts";
|
|
1
|
+
export { PLACES, atlasFacets, hallSurfaces, placeById, placeByName, placesBy, placesByClub, placesByName, surfaceOf, surfacesOf, tenantsOf } from "./atlas.ts";
|
|
2
|
+
export { HALLS } from "./halls.ts";
|
|
3
|
+
export type { Hall, HallBasis, HallSurface } from "./halls.ts";
|
|
2
4
|
export { officialName, plainName } from "./names.ts";
|
|
3
5
|
export { TENANTS, TENANT_JAPANESE_NAMES, nameJaOf } from "./tenants.ts";
|
|
4
6
|
export type { PlaceAlias, PlaceNameKind } from "./names.ts";
|
package/dist/atlas-entry.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
// The atlas: every ballpark
|
|
2
|
-
export { PLACES, atlasFacets, placeById, placeByName, placesBy, placesByClub, placesByName, surfaceOf, surfacesOf, tenantsOf } from "./atlas.js";
|
|
1
|
+
// The atlas: every ballpark, soccer ground and hockey and basketball arena, and the famous halls of the budō, with where it stands, when it was in use and the clubs that played there, and the filters over them.
|
|
2
|
+
export { PLACES, atlasFacets, hallSurfaces, placeById, placeByName, placesBy, placesByClub, placesByName, surfaceOf, surfacesOf, tenantsOf } from "./atlas.js";
|
|
3
|
+
export { HALLS } from "./halls.js";
|
|
3
4
|
export { officialName, plainName } from "./names.js";
|
|
4
5
|
export { TENANTS, TENANT_JAPANESE_NAMES, nameJaOf } from "./tenants.js";
|
package/dist/atlas.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { type Hall, type HallSurface } from "./halls.ts";
|
|
1
2
|
import type { PlaceAlias } from "./names.ts";
|
|
3
|
+
import type { BudoSport, BudoStyle, DojoSpec } from "./types.ts";
|
|
2
4
|
import type { Tenant, TenantSport } from "./tenants.ts";
|
|
3
|
-
/** What a place is: a ballpark (of `PARKS`)
|
|
4
|
-
export type PlaceKind = "park" | "ground";
|
|
5
|
-
/** The sport a place is drawn for: baseball parks have a fence, soccer grounds a pitch. */
|
|
6
|
-
export type PlaceSport = "baseball" | "soccer";
|
|
5
|
+
/** What a place is: a ballpark (of `PARKS`), a soccer ground (of `GROUNDS`), a hall of the budō (of `HALLS`: a dojo, an arena, a sumo hall) or a hockey and basketball arena (of `ARENAS`). */
|
|
6
|
+
export type PlaceKind = "park" | "ground" | "hall" | "arena";
|
|
7
|
+
/** The sport a place is drawn for: baseball parks have a fence, soccer grounds a pitch, the halls of the budō (`budo`) the mats, the dohyō or the range of their sports, and arenas an ice rink (`hockey`) and a court (`basketball`). */
|
|
8
|
+
export type PlaceSport = "baseball" | "soccer" | "budo" | "hockey" | "basketball";
|
|
7
9
|
/** `current` is a ground a club or a competition uses today, `past` one it has left, closed or pulled down. */
|
|
8
10
|
export type PlaceStatus = "current" | "past";
|
|
9
11
|
/** One place on the atlas: a ballpark or a soccer ground, with where it is and when it was in use. */
|
|
@@ -28,7 +30,10 @@ export interface Place {
|
|
|
28
30
|
from: number;
|
|
29
31
|
to: number;
|
|
30
32
|
}[];
|
|
33
|
+
/** The sport it is first drawn for: a park's is baseball, a ground's soccer, an arena's hockey where an ice hockey club played there, else basketball. */
|
|
31
34
|
sport: PlaceSport;
|
|
35
|
+
/** Every sport it is drawn for: a park's and a ground's is its `sport` alone, an arena's is `hockey`, `basketball` or both (`TD Garden`), by the clubs that played there. */
|
|
36
|
+
sports: readonly PlaceSport[];
|
|
32
37
|
/** The leagues and competitions it is known for: the leagues of the park's club and of every club that has played its home matches there (`CFL` and `MLS` for BC Place, `MLB` and `CFL` for Montreal's Olympic Stadium), then the World Cups it staged (`FIFA World Cup`, `FIFA Women's World Cup`). A ground with no tenant that staged none has none. */
|
|
33
38
|
leagues: readonly string[];
|
|
34
39
|
/** The clubs that play, or played, their home matches there, with the league and the years of each (see `tenantsOf`): the current ones first. A place no club is known to have called home has none. */
|
|
@@ -36,7 +41,7 @@ export interface Place {
|
|
|
36
41
|
/** ISO 3166-1 alpha-2: `US`. */
|
|
37
42
|
country: string;
|
|
38
43
|
city: string;
|
|
39
|
-
/** The club that plays in a park (`Boston Red Sox`); soccer grounds have none (see `tenants`). */
|
|
44
|
+
/** The club that plays in a park (`Boston Red Sox`); soccer grounds and arenas have none (see `tenants`). */
|
|
40
45
|
team?: string;
|
|
41
46
|
/** Wikidata's coordinates (P625, CC0), in degrees. */
|
|
42
47
|
lat: number;
|
|
@@ -48,11 +53,14 @@ export interface Place {
|
|
|
48
53
|
to?: number;
|
|
49
54
|
/** The Wikidata item (`Q49136`): the key to join a place to other data. */
|
|
50
55
|
wikidata: string;
|
|
56
|
+
/** A hall of the budō (`kind: "hall"`): what it holds, how it came to be and the surfaces it offers (see `HALLS`). */
|
|
57
|
+
hall?: Hall;
|
|
51
58
|
/** True where Wikidata lists athletics among the sports of a soccer ground: a running track lies round its pitch (`drawKyogijo({ sport: "athletics", ground })`). Absent where Wikidata says nothing of it. */
|
|
52
59
|
track?: boolean;
|
|
53
60
|
}
|
|
54
61
|
/** What `placesBy` keeps: every field given must match. A list matches any of its members. */
|
|
55
62
|
export interface PlaceFilter {
|
|
63
|
+
/** A sport a place is drawn for: an arena is found by `hockey` and by `basketball` if clubs of both played there. */
|
|
56
64
|
sport?: PlaceSport | readonly PlaceSport[];
|
|
57
65
|
kind?: PlaceKind | readonly PlaceKind[];
|
|
58
66
|
/** A league or competition from `Place.leagues`: a tenant's league (`CFL`) or a tournament. */
|
|
@@ -65,17 +73,6 @@ export interface PlaceFilter {
|
|
|
65
73
|
/** Words to find in any name (the everyday names, the aliases, the readings), the city or the club, or the name of a club that plays or played there (in English or in Japanese), ignoring case, accents, width and, in Japanese, hiragana or katakana; every word must be found. */
|
|
66
74
|
text?: string;
|
|
67
75
|
}
|
|
68
|
-
/**
|
|
69
|
-
* Every place the package draws, parks first and then grounds, each in the order of its own list: the ballparks of
|
|
70
|
-
* `PARKS` and the soccer grounds of `GROUNDS`, with where each stands.
|
|
71
|
-
* @example
|
|
72
|
-
* ```ts
|
|
73
|
-
* import { PLACES } from "@johnmorrisdotca/kyogijo-stadiums/atlas";
|
|
74
|
-
* const fenway = PLACES.find((place) => place.id === "fenway-park");
|
|
75
|
-
* console.log(fenway?.name, fenway?.lat, fenway?.lon, fenway?.country);
|
|
76
|
-
* // Fenway Park 42.34639 -71.0975 US
|
|
77
|
-
* ```
|
|
78
|
-
*/
|
|
79
76
|
export declare const PLACES: readonly Place[];
|
|
80
77
|
/** The place with a key, or `undefined`. */
|
|
81
78
|
export declare const placeById: (id: string | undefined) => Place | undefined;
|
|
@@ -122,25 +119,43 @@ export interface AtlasFacets {
|
|
|
122
119
|
* import { atlasFacets } from "@johnmorrisdotca/kyogijo-stadiums/atlas";
|
|
123
120
|
* const { sports, leagues, countries, years } = atlasFacets();
|
|
124
121
|
* console.log(sports.join(), leagues.length, leagues.includes("CFL"), countries.length, years.min);
|
|
125
|
-
* // baseball,soccer
|
|
122
|
+
* // baseball,basketball,budo,hockey,soccer 90 true 23 1877
|
|
126
123
|
* ```
|
|
127
124
|
*/
|
|
128
125
|
export declare function atlasFacets(): AtlasFacets;
|
|
129
126
|
/** The options `drawKyogijo` takes to draw a surface a place offers. */
|
|
130
127
|
export type PlaceSurface = {
|
|
128
|
+
sport: BudoSport;
|
|
129
|
+
league?: string;
|
|
130
|
+
budo?: BudoStyle;
|
|
131
|
+
dojo?: DojoSpec;
|
|
132
|
+
} | {
|
|
131
133
|
sport: "mlb";
|
|
132
134
|
park: string;
|
|
133
135
|
} | {
|
|
134
136
|
sport: "soccer";
|
|
135
137
|
ground?: string;
|
|
136
138
|
} | {
|
|
137
|
-
sport: "
|
|
139
|
+
sport: "nhl" | "nba";
|
|
140
|
+
arena?: string;
|
|
141
|
+
} | {
|
|
142
|
+
sport: "nfl" | "cfl" | "afl" | "cricket";
|
|
138
143
|
} | {
|
|
139
144
|
sport: "rugby";
|
|
140
145
|
league?: "nrl";
|
|
141
146
|
};
|
|
142
147
|
/** The sports `surfaceOf` can be asked for. */
|
|
143
148
|
export type SurfaceSport = PlaceSurface["sport"];
|
|
149
|
+
/**
|
|
150
|
+
* Every surface a hall of the budō offers, each with its name, how much of it is documented (`basis`) and the options that draw it, in the order of the hall's own list. A place that is not a hall has none.
|
|
151
|
+
* @example
|
|
152
|
+
* ```ts
|
|
153
|
+
* import { hallSurfaces, placeById } from "@johnmorrisdotca/kyogijo-stadiums/atlas";
|
|
154
|
+
* console.log(hallSurfaces(placeById("kodokan")!).map((surface) => `${surface.id} ${surface.mats}`).join());
|
|
155
|
+
* // main-dojo 420,main-dojo-earlier 420,school-dojo 240,international-dojo 192,womens-dojo 240,boys-dojo 114
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export declare const hallSurfaces: (place: Place) => readonly HallSurface[];
|
|
144
159
|
/**
|
|
145
160
|
* Every surface a place offers, the place's own first: a park's fence (`mlb` with the park) or a ground's pitch at its size (`soccer` with the ground), then one for each
|
|
146
161
|
* sport a tenant plays that the package draws (a CFL field for BC Place, an NFL field for MetLife Stadium, the rugby league field for Stadium Australia), each once. A ground
|
|
@@ -171,7 +186,10 @@ export declare function surfaceOf(place: Place): {
|
|
|
171
186
|
} | {
|
|
172
187
|
sport: "soccer";
|
|
173
188
|
ground: string;
|
|
174
|
-
}
|
|
189
|
+
} | {
|
|
190
|
+
sport: "nhl" | "nba";
|
|
191
|
+
arena: string;
|
|
192
|
+
} | PlaceSurface;
|
|
175
193
|
export declare function surfaceOf(place: Place, sport: SurfaceSport): PlaceSurface | undefined;
|
|
176
194
|
/** What `tenantsOf` keeps: every field given must match. */
|
|
177
195
|
export interface TenantFilter {
|
package/dist/atlas.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { ARENAS, ARENA_IDS } from "./arenas.js";
|
|
1
2
|
import { GROUNDS, GROUND_IDS } from "./grounds.js";
|
|
3
|
+
import { HALLS } from "./halls.js";
|
|
2
4
|
import { nameContainsAll, placesNamed, plainName } from "./names.js";
|
|
3
5
|
import { PARKS, PARK_IDS } from "./parks.js";
|
|
4
6
|
import { SURFACE_OF_SPORT, TENANTS, hasSurface, leaguesOf, playedIn } from "./tenants.js";
|
|
@@ -24,6 +26,7 @@ const fromPark = (park) => {
|
|
|
24
26
|
...(park.localName === undefined ? {} : { localName: park.localName, localLanguage: park.localLanguage }),
|
|
25
27
|
aliases: park.aliases ?? [],
|
|
26
28
|
sport: "baseball",
|
|
29
|
+
sports: ["baseball"],
|
|
27
30
|
leagues: withoutRepeats([park.league], leaguesOf(tenants)),
|
|
28
31
|
tenants,
|
|
29
32
|
country: park.country,
|
|
@@ -48,6 +51,7 @@ const fromGround = (ground) => ({
|
|
|
48
51
|
aliases: ground.aliases ?? [],
|
|
49
52
|
...(ground.names === undefined ? {} : { names: ground.names }),
|
|
50
53
|
sport: "soccer",
|
|
54
|
+
sports: ["soccer"],
|
|
51
55
|
leagues: withoutRepeats(leaguesOf(TENANTS[ground.id] ?? []), leaguesOfGround(ground)),
|
|
52
56
|
tenants: TENANTS[ground.id] ?? [],
|
|
53
57
|
country: ground.country,
|
|
@@ -60,9 +64,44 @@ const fromGround = (ground) => ({
|
|
|
60
64
|
wikidata: ground.wikidata,
|
|
61
65
|
...(ground.track === true ? { track: true } : {}),
|
|
62
66
|
});
|
|
67
|
+
/** The sports an arena is drawn for, by the clubs that played there: hockey first when any ice hockey club did. */
|
|
68
|
+
const sportsOfArena = (tenants) => {
|
|
69
|
+
const out = [];
|
|
70
|
+
if (tenants.some((tenant) => tenant.sport === "ice-hockey" && hasSurface(tenant)))
|
|
71
|
+
out.push("hockey");
|
|
72
|
+
if (tenants.some((tenant) => tenant.sport === "basketball" && hasSurface(tenant)))
|
|
73
|
+
out.push("basketball");
|
|
74
|
+
return out;
|
|
75
|
+
};
|
|
76
|
+
const fromArena = (arena) => {
|
|
77
|
+
const tenants = TENANTS[arena.id] ?? [];
|
|
78
|
+
const sports = sportsOfArena(tenants);
|
|
79
|
+
return {
|
|
80
|
+
id: arena.id,
|
|
81
|
+
kind: "arena",
|
|
82
|
+
name: arena.name,
|
|
83
|
+
nameJa: arena.nameJa,
|
|
84
|
+
...(arena.readingJa === undefined ? {} : { readingJa: arena.readingJa }),
|
|
85
|
+
...(arena.localName === undefined ? {} : { localName: arena.localName, localLanguage: arena.localLanguage }),
|
|
86
|
+
aliases: arena.aliases ?? [],
|
|
87
|
+
...(arena.names === undefined ? {} : { names: arena.names }),
|
|
88
|
+
sport: sports[0] ?? "hockey",
|
|
89
|
+
sports: sports.length === 0 ? ["hockey"] : sports,
|
|
90
|
+
leagues: leaguesOf(tenants),
|
|
91
|
+
tenants,
|
|
92
|
+
country: arena.country,
|
|
93
|
+
city: arena.city,
|
|
94
|
+
lat: arena.lat,
|
|
95
|
+
lon: arena.lon,
|
|
96
|
+
status: arena.status,
|
|
97
|
+
...(arena.from === undefined ? {} : { from: arena.from }),
|
|
98
|
+
...(arena.status === "past" && arena.to !== undefined ? { to: arena.to } : {}),
|
|
99
|
+
wikidata: arena.wikidata,
|
|
100
|
+
};
|
|
101
|
+
};
|
|
63
102
|
/**
|
|
64
|
-
* Every place the package draws, parks first
|
|
65
|
-
* `PARKS` and the
|
|
103
|
+
* Every place the package draws, parks first, then grounds, then arenas, each in the order of its own list: the ballparks of
|
|
104
|
+
* `PARKS`, the soccer grounds of `GROUNDS` and the hockey and basketball arenas of `ARENAS`, with where each stands.
|
|
66
105
|
* @example
|
|
67
106
|
* ```ts
|
|
68
107
|
* import { PLACES } from "@johnmorrisdotca/kyogijo-stadiums/atlas";
|
|
@@ -71,7 +110,27 @@ const fromGround = (ground) => ({
|
|
|
71
110
|
* // Fenway Park 42.34639 -71.0975 US
|
|
72
111
|
* ```
|
|
73
112
|
*/
|
|
74
|
-
|
|
113
|
+
const fromHall = (hall) => ({
|
|
114
|
+
id: hall.id,
|
|
115
|
+
kind: "hall",
|
|
116
|
+
name: hall.name,
|
|
117
|
+
nameJa: hall.nameJa,
|
|
118
|
+
...(hall.readingJa === undefined ? {} : { readingJa: hall.readingJa }),
|
|
119
|
+
aliases: hall.aliases,
|
|
120
|
+
sport: "budo",
|
|
121
|
+
sports: ["budo"],
|
|
122
|
+
leagues: hall.leagues,
|
|
123
|
+
tenants: [],
|
|
124
|
+
country: hall.country,
|
|
125
|
+
city: hall.city,
|
|
126
|
+
lat: hall.lat,
|
|
127
|
+
lon: hall.lon,
|
|
128
|
+
status: "current",
|
|
129
|
+
from: hall.from,
|
|
130
|
+
wikidata: hall.wikidata,
|
|
131
|
+
hall,
|
|
132
|
+
});
|
|
133
|
+
export const PLACES = Object.freeze([...PARK_IDS.map((id) => fromPark(PARKS[id])), ...GROUND_IDS.map((id) => fromGround(GROUNDS[id])), ...HALLS.map(fromHall), ...ARENA_IDS.map((id) => fromArena(ARENAS[id]))]);
|
|
75
134
|
const BY_ID = new Map(PLACES.map((place) => [place.id, place]));
|
|
76
135
|
/** The place with a key, or `undefined`. */
|
|
77
136
|
export const placeById = (id) => (id === undefined ? undefined : BY_ID.get(id));
|
|
@@ -110,7 +169,7 @@ export function placesBy(filter = {}) {
|
|
|
110
169
|
const year = filter.year !== undefined && Number.isFinite(filter.year) ? filter.year : undefined;
|
|
111
170
|
const words = filter.text === undefined ? [] : filter.text.split(/\s+/).map(plain).filter(Boolean);
|
|
112
171
|
return PLACES.filter((place) => {
|
|
113
|
-
if (sports !== undefined && !sports.includes(
|
|
172
|
+
if (sports !== undefined && !place.sports.some((sport) => sports.includes(sport)))
|
|
114
173
|
return false;
|
|
115
174
|
if (kinds !== undefined && !kinds.includes(place.kind))
|
|
116
175
|
return false;
|
|
@@ -139,7 +198,7 @@ export function placesBy(filter = {}) {
|
|
|
139
198
|
* import { atlasFacets } from "@johnmorrisdotca/kyogijo-stadiums/atlas";
|
|
140
199
|
* const { sports, leagues, countries, years } = atlasFacets();
|
|
141
200
|
* console.log(sports.join(), leagues.length, leagues.includes("CFL"), countries.length, years.min);
|
|
142
|
-
* // baseball,soccer
|
|
201
|
+
* // baseball,basketball,budo,hockey,soccer 90 true 23 1877
|
|
143
202
|
* ```
|
|
144
203
|
*/
|
|
145
204
|
export function atlasFacets() {
|
|
@@ -151,6 +210,20 @@ export function atlasFacets() {
|
|
|
151
210
|
years: { min: Math.min(...years), max: Math.max(...years) },
|
|
152
211
|
};
|
|
153
212
|
}
|
|
213
|
+
/** The rink (`hockey`) or the court (`basketball`) of an arena, drawn at the arena's own size where the data has one. */
|
|
214
|
+
const arenaSurface = (place, sport) => ({ sport: sport === "basketball" ? "nba" : "nhl", arena: place.id });
|
|
215
|
+
/** The options that draw a surface of a hall. */
|
|
216
|
+
const hallOptions = (surface) => ({ sport: surface.sport, ...surface.options });
|
|
217
|
+
/**
|
|
218
|
+
* Every surface a hall of the budō offers, each with its name, how much of it is documented (`basis`) and the options that draw it, in the order of the hall's own list. A place that is not a hall has none.
|
|
219
|
+
* @example
|
|
220
|
+
* ```ts
|
|
221
|
+
* import { hallSurfaces, placeById } from "@johnmorrisdotca/kyogijo-stadiums/atlas";
|
|
222
|
+
* console.log(hallSurfaces(placeById("kodokan")!).map((surface) => `${surface.id} ${surface.mats}`).join());
|
|
223
|
+
* // main-dojo 420,main-dojo-earlier 420,school-dojo 240,international-dojo 192,womens-dojo 240,boys-dojo 114
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
export const hallSurfaces = (place) => (place.kind === "hall" ? (place.hall?.surfaces ?? []) : []);
|
|
154
227
|
/**
|
|
155
228
|
* Every surface a place offers, the place's own first: a park's fence (`mlb` with the park) or a ground's pitch at its size (`soccer` with the ground), then one for each
|
|
156
229
|
* sport a tenant plays that the package draws (a CFL field for BC Place, an NFL field for MetLife Stadium, the rugby league field for Stadium Australia), each once. A ground
|
|
@@ -163,8 +236,15 @@ export function atlasFacets() {
|
|
|
163
236
|
* ```
|
|
164
237
|
*/
|
|
165
238
|
export function surfacesOf(place) {
|
|
166
|
-
|
|
239
|
+
if (place.kind === "hall")
|
|
240
|
+
return (place.hall?.surfaces ?? []).map(hallOptions);
|
|
241
|
+
// An arena's surfaces are its rink and its court, each at the arena's own size where the sources publish one.
|
|
242
|
+
const own = place.kind === "park" ? { sport: "mlb", park: place.id } : place.kind === "arena" ? arenaSurface(place, place.sport) : { sport: "soccer", ground: place.id };
|
|
167
243
|
const out = [own];
|
|
244
|
+
if (place.kind === "arena")
|
|
245
|
+
for (const sport of place.sports)
|
|
246
|
+
if (sport !== place.sport)
|
|
247
|
+
out.push(arenaSurface(place, sport));
|
|
168
248
|
for (const tenant of place.tenants) {
|
|
169
249
|
const drawn = SURFACE_OF_SPORT[tenant.sport];
|
|
170
250
|
if (drawn === undefined || !hasSurface(tenant))
|
|
@@ -172,6 +252,9 @@ export function surfacesOf(place) {
|
|
|
172
252
|
// A baseball club's fence is a park's: a ground has none to draw.
|
|
173
253
|
if (drawn.sport === "mlb")
|
|
174
254
|
continue;
|
|
255
|
+
// An arena's rink and court are already offered, at its size.
|
|
256
|
+
if (place.kind === "arena" && (drawn.sport === "nhl" || drawn.sport === "nba"))
|
|
257
|
+
continue;
|
|
175
258
|
const surface = drawn.sport === "soccer" ? { sport: "soccer" } : drawn.sport === "rugby" ? { sport: "rugby", ...(drawn.league === undefined ? {} : { league: drawn.league }) } : { sport: drawn.sport };
|
|
176
259
|
if (out.some((have) => have.sport === surface.sport && (have.sport !== "rugby" || have.league === surface.league)))
|
|
177
260
|
continue;
|
|
@@ -180,8 +263,10 @@ export function surfacesOf(place) {
|
|
|
180
263
|
return out;
|
|
181
264
|
}
|
|
182
265
|
export function surfaceOf(place, sport) {
|
|
266
|
+
if (place.kind === "hall")
|
|
267
|
+
return sport === undefined ? surfacesOf(place)[0] : surfacesOf(place).find((surface) => surface.sport === sport);
|
|
183
268
|
if (sport === undefined)
|
|
184
|
-
return place.kind === "park" ? { sport: "mlb", park: place.id } : { sport: "soccer", ground: place.id };
|
|
269
|
+
return place.kind === "park" ? { sport: "mlb", park: place.id } : place.kind === "arena" ? arenaSurface(place, place.sport) : { sport: "soccer", ground: place.id };
|
|
185
270
|
return surfacesOf(place).find((surface) => surface.sport === sport);
|
|
186
271
|
}
|
|
187
272
|
/**
|
package/dist/background.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// The ground behind a drawing: a subtle pattern drawn in SVG (felt, grass, wood, ice, paper, a grid, dots) and, when the caller has one, a photograph at an opacity. It is
|
|
2
2
|
// written once here for the drawing (`background` in the options, laid on the apron under the surface) and for a grid of drawings (`drawGrid`, laid under all of them).
|
|
3
3
|
// Every pattern is a few shapes in a tile, with no random number, in the ink or the line colour of the drawing at a low opacity, so that it follows light and dark.
|
|
4
|
-
import { safeColour
|
|
4
|
+
import { safeColour } from "./colour.js";
|
|
5
|
+
import { safeLogo } from "./logo.js";
|
|
5
6
|
import { el, num } from "./format.js";
|
|
6
7
|
/** The patterns, in the order a menu lists them. */
|
|
7
8
|
export const BACKGROUND_PATTERNS = ["felt", "grass", "wood", "ice", "paper", "grid", "dots"];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Language, SurfaceOptions, Team } from "../types.ts";
|
|
2
|
+
import type { DojoFigures } from "../leagues/budo.ts";
|
|
3
|
+
import { type BudoPlan } from "./plan.ts";
|
|
4
|
+
type Opt = Pick<SurfaceOptions, "sport" | "league" | "budo" | "dojo" | "range" | "detail">;
|
|
5
|
+
/** The sentence about the surface, as a fragment: "a judo contest area of 10 by 10 metres in a safety area 4 metres wide...". */
|
|
6
|
+
export declare function budoAbout(o: Opt, language: Language, plan?: BudoPlan): string;
|
|
7
|
+
/** The sentences that follow it: what the options mark. Each starts after a gap. */
|
|
8
|
+
export declare function budoSentences(o: Opt, language: Language, plan?: BudoPlan): string;
|
|
9
|
+
/** The mat of a dojo league, for a caller that wants its size in words. */
|
|
10
|
+
export declare const dojoMat: (f: DojoFigures) => string;
|
|
11
|
+
/** What each side scored, in sentences, for a judo, karate, kendo or sumo score: the counts the board shows. Each starts after a gap. */
|
|
12
|
+
export declare function budoScoreSentences(sport: string, order: readonly Pick<Team, "name" | "budo">[], language: Language): string;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// What a budō drawing says of itself: its sentence about the surface, and what the options mark on it. Built from the plan, so that the words and the drawing agree.
|
|
2
|
+
import { fill, KYOGIJO_STRINGS } from "../strings.js";
|
|
3
|
+
import { budoView } from "../budo.score.js";
|
|
4
|
+
import { kimariteName } from "./kimarite.js";
|
|
5
|
+
import { budoPlan } from "./plan.js";
|
|
6
|
+
const trim = (n) => String(Math.round(n * 100) / 100);
|
|
7
|
+
const cm = (n) => String(Math.round(n * 1000) / 10);
|
|
8
|
+
/** The sentence about the surface, as a fragment: "a judo contest area of 10 by 10 metres in a safety area 4 metres wide...". */
|
|
9
|
+
export function budoAbout(o, language, plan = budoPlan(o)) {
|
|
10
|
+
const words = KYOGIJO_STRINGS[language].budo;
|
|
11
|
+
const mat = (m) => fill(words.tatami, { length: trim(m.length), width: trim(m.width) });
|
|
12
|
+
if (plan.judo !== undefined) {
|
|
13
|
+
const L = plan.judo;
|
|
14
|
+
const c = L.contests[0];
|
|
15
|
+
const contest = trim(c.x1 - c.x0);
|
|
16
|
+
const safety = trim(c.x0);
|
|
17
|
+
const tatami = mat(L.mat);
|
|
18
|
+
if (plan.league === "ijf-kata")
|
|
19
|
+
return fill(words.judoKata, { contest, safety, tatami });
|
|
20
|
+
return L.contests.length > 1 ? fill(words.judoMany, { areas: L.contests.length, contest, safety, gap: trim(L.gap), tatami }) : fill(words.judo, { contest, safety, tatami });
|
|
21
|
+
}
|
|
22
|
+
if (plan.karate !== undefined) {
|
|
23
|
+
const L = plan.karate;
|
|
24
|
+
const area = trim(L.areas[0].x1 - L.areas[0].x0);
|
|
25
|
+
const safety = trim(L.areas[0].x0);
|
|
26
|
+
if (plan.league === "wkf-kata")
|
|
27
|
+
return fill(words.karateKata, { area, safety });
|
|
28
|
+
return L.areas.length > 1 ? fill(words.karateMany, { areas: L.areas.length, area, gap: trim(L.gap), safety }) : fill(words.karate, { area, safety });
|
|
29
|
+
}
|
|
30
|
+
if (plan.kendo !== undefined)
|
|
31
|
+
return fill(words.kendo, { side: trim(plan.kendo.side) });
|
|
32
|
+
if (plan.sumo !== undefined) {
|
|
33
|
+
const L = plan.sumo;
|
|
34
|
+
const fig = plan.figures;
|
|
35
|
+
const bare = !L.parts.areas.some((a) => a.id === "tawara");
|
|
36
|
+
return fill(bare ? words.sumoBare : words.sumo, { platform: trim(fig.platform), height: cm(L.height), circle: trim(fig.circle), count: fig.tawara.count });
|
|
37
|
+
}
|
|
38
|
+
if (plan.kyudo !== undefined) {
|
|
39
|
+
const L = plan.kyudo;
|
|
40
|
+
const fig = plan.figures;
|
|
41
|
+
return fill(plan.league === "enteki" ? words.kyudoEnteki : words.kyudo, { n: L.shooters, distance: trim(fig.distance) });
|
|
42
|
+
}
|
|
43
|
+
const L = plan.dojo;
|
|
44
|
+
if (L === undefined)
|
|
45
|
+
return "";
|
|
46
|
+
const template = L.pattern === "competition" ? words.dojoCompetition : L.pattern === "checker" ? words.dojoChecker : L.pattern === "border" ? words.dojoBorder : words.dojoTraditional;
|
|
47
|
+
return fill(template, { jo: trim(L.jo), width: trim(L.width), length: trim(L.length), mat: fill(words.tatami, { length: trim(L.mat.length), width: trim(L.mat.width) }) });
|
|
48
|
+
}
|
|
49
|
+
/** The sentences that follow it: what the options mark. Each starts after a gap. */
|
|
50
|
+
export function budoSentences(o, language, plan = budoPlan(o)) {
|
|
51
|
+
const words = KYOGIJO_STRINGS[language].budo;
|
|
52
|
+
const { gap } = KYOGIJO_STRINGS[language].said;
|
|
53
|
+
const out = [];
|
|
54
|
+
if (plan.judo !== undefined) {
|
|
55
|
+
const L = plan.judo;
|
|
56
|
+
const fig = plan.figures;
|
|
57
|
+
if (L.danger > 0)
|
|
58
|
+
out.push(words.danger);
|
|
59
|
+
if (o.budo?.platform === true)
|
|
60
|
+
out.push(words.platform);
|
|
61
|
+
if (plan.shapes.some((s) => s.kind === "bar" && s.feature.startsWith("start")) && fig.marks !== null)
|
|
62
|
+
out.push(fill(words.start, { apart: trim(2 * fig.marks.fromCentre) }));
|
|
63
|
+
if (o.budo?.officials === true)
|
|
64
|
+
out.push(words.officials);
|
|
65
|
+
}
|
|
66
|
+
if (plan.karate !== undefined && plan.areas.some((a) => a.feature === "judges" || a.feature === "referee"))
|
|
67
|
+
out.push(words.karateOfficials);
|
|
68
|
+
if (plan.sumo !== undefined && plan.areas.some((a) => a.feature === "tassels"))
|
|
69
|
+
out.push(words.tassels);
|
|
70
|
+
if (plan.dojo !== undefined) {
|
|
71
|
+
const L = plan.dojo;
|
|
72
|
+
out.push(fill(words.dojoKamiza, { side: words.sides[L.kamiza] }));
|
|
73
|
+
if (L.dais !== undefined)
|
|
74
|
+
out.push(words.dojoDais);
|
|
75
|
+
if (L.banner !== undefined)
|
|
76
|
+
out.push(words.dojoBanner);
|
|
77
|
+
if (L.shrine !== undefined)
|
|
78
|
+
out.push(words.dojoShinzen);
|
|
79
|
+
if (L.contests.length > 0)
|
|
80
|
+
out.push(fill(words.dojoAreas, { n: L.contests.length }));
|
|
81
|
+
}
|
|
82
|
+
return out.map((t) => `${gap}${t}`).join("");
|
|
83
|
+
}
|
|
84
|
+
/** The mat of a dojo league, for a caller that wants its size in words. */
|
|
85
|
+
export const dojoMat = (f) => `${trim(f.mat.length)} × ${trim(f.mat.width)} m`;
|
|
86
|
+
/** What each side scored, in sentences, for a judo, karate, kendo or sumo score: the counts the board shows. Each starts after a gap. */
|
|
87
|
+
export function budoScoreSentences(sport, order, language) {
|
|
88
|
+
const words = KYOGIJO_STRINGS[language].budo;
|
|
89
|
+
const { gap } = KYOGIJO_STRINGS[language].said;
|
|
90
|
+
const sep = KYOGIJO_STRINGS[language].layers.listSep;
|
|
91
|
+
const out = [];
|
|
92
|
+
for (const team of order) {
|
|
93
|
+
const v = budoView(team.budo);
|
|
94
|
+
if (v === undefined)
|
|
95
|
+
continue;
|
|
96
|
+
const list = [];
|
|
97
|
+
const count = (n, label) => {
|
|
98
|
+
if (n !== undefined && n > 0)
|
|
99
|
+
list.push(language === "ja" ? `${label}${n}` : `${n} ${label.toLowerCase()}`);
|
|
100
|
+
};
|
|
101
|
+
if (sport === "judo" || sport === "karate") {
|
|
102
|
+
count(v.ippon, words.board.ippon);
|
|
103
|
+
count(v.wazaari, words.board.wazaari);
|
|
104
|
+
count(v.yuko, words.board.yuko);
|
|
105
|
+
count(v.shido, sport === "judo" ? words.board.shido : words.board.chui);
|
|
106
|
+
if (v.senshu === true)
|
|
107
|
+
list.push(words.board.senshu);
|
|
108
|
+
if (list.length > 0)
|
|
109
|
+
out.push(fill(sport === "judo" ? words.board.judoScore : words.board.karateScore, { name: team.name, list: list.join(sep) }));
|
|
110
|
+
}
|
|
111
|
+
else if (sport === "kendo" && v.techniques !== undefined) {
|
|
112
|
+
const named = v.techniques.map((t) => words.board.techniques[t] ?? t);
|
|
113
|
+
out.push(fill(words.board.kendoScore, { name: team.name, list: named.join(sep) }));
|
|
114
|
+
}
|
|
115
|
+
else if (sport === "sumo" && v.kimarite !== undefined) {
|
|
116
|
+
out.push(fill(words.board.sumoScore, { name: team.name, kimarite: kimariteName(v.kimarite, language) }));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return out.map((t) => `${gap}${t}`).join("");
|
|
120
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { SurfaceOptions } from "../types.ts";
|
|
2
|
+
import type { MBox } from "./parts.ts";
|
|
3
|
+
import type { Piece } from "./tatami.ts";
|
|
4
|
+
import type { Compass, DojoPattern, DojoSpec } from "./types.ts";
|
|
5
|
+
/** One mat of a dojo's floor, or a part of one, in metres from the floor's top left corner. */
|
|
6
|
+
export type Tatami = Piece;
|
|
7
|
+
/** A dojo made from a spec: the floor as data. */
|
|
8
|
+
export interface Dojo {
|
|
9
|
+
/** The spec it was made from. */
|
|
10
|
+
spec: DojoSpec;
|
|
11
|
+
/** The mat standard: a league of the `dojo` sport (`chukyoma`, `kyoma`, `edoma`, `danchima`, `judo-2x1`) and the mat's size in metres. */
|
|
12
|
+
standard: string;
|
|
13
|
+
mat: {
|
|
14
|
+
length: number;
|
|
15
|
+
width: number;
|
|
16
|
+
};
|
|
17
|
+
/** The floor in metres: its width (x, the longer side) and its length (y). */
|
|
18
|
+
width: number;
|
|
19
|
+
length: number;
|
|
20
|
+
/** The floor's area in jō: the area over the area of a mat, a half mat counting a half. */
|
|
21
|
+
jo: number;
|
|
22
|
+
/** How many whole mats, half mats (hanjō) and cut pieces the floor holds. */
|
|
23
|
+
counts: {
|
|
24
|
+
full: number;
|
|
25
|
+
half: number;
|
|
26
|
+
cut: number;
|
|
27
|
+
};
|
|
28
|
+
pattern: DojoPattern;
|
|
29
|
+
/** Every mat, in metres, with the tone it is painted in (1, 2 or 3). */
|
|
30
|
+
mats: readonly Tatami[];
|
|
31
|
+
/** The seat of honour's wall, and the doors and windows with where each is. */
|
|
32
|
+
kamiza: Compass;
|
|
33
|
+
entrances: readonly {
|
|
34
|
+
wall: Compass;
|
|
35
|
+
box: MBox;
|
|
36
|
+
}[];
|
|
37
|
+
windows: readonly {
|
|
38
|
+
wall: Compass;
|
|
39
|
+
box: MBox;
|
|
40
|
+
}[];
|
|
41
|
+
shrine: MBox | undefined;
|
|
42
|
+
/** The thickness of the walls round the floor, 0 for none. */
|
|
43
|
+
wall: number;
|
|
44
|
+
/** The contest areas laid on the floor, in metres. */
|
|
45
|
+
contests: readonly MBox[];
|
|
46
|
+
/** The options that draw it: `drawKyogijo(dojo.options)`. */
|
|
47
|
+
options: SurfaceOptions;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A dojo (道場): the floor in mats, laid as real tatami units, with the walls, doors, windows, shrine and kamiza. `mats` is the floor: a number is its area in jō (8, 12, 20, 50, 100 and 200 give the usual shapes), `[across, along]`
|
|
51
|
+
* the whole mats across and along, `{ width, length, unit }` a size in metres, feet, mats or jō; `pattern` is how it is laid (`traditional`: no four corners meet; `competition`, `checker`, `border`).
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { dojo } from "@johnmorrisdotca/kyogijo-stadiums/budo";
|
|
55
|
+
* const d = dojo({ jo: 20 });
|
|
56
|
+
* console.log(d.jo, d.width.toFixed(2), d.length.toFixed(2), d.counts.full, d.counts.half, d.pattern);
|
|
57
|
+
* // 20 7.28 4.55 18 4 traditional
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function dojo(spec?: DojoSpec): Dojo;
|
|
61
|
+
/** Draw a dojo: `drawKyogijo` with the spec as the options' `dojo`, and any other option the caller gives. */
|
|
62
|
+
export declare function drawDojo(spec?: DojoSpec, more?: Partial<SurfaceOptions>): string;
|
|
63
|
+
/** The mat standards a dojo can be laid with. */
|
|
64
|
+
export declare const DOJO_STANDARDS: readonly string[];
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// The dojo builder's public face: `dojo(spec)` lays a floor of tatami out as real units and returns it as plain data (every mat, the floor in metres and in jō, where the kamiza, the doors and the windows are),
|
|
2
|
+
// and `drawDojo(spec)` draws it. The same spec always gives the same floor.
|
|
3
|
+
import { drawKyogijo } from "../draw.js";
|
|
4
|
+
import { DOJO_LEAGUES } from "../leagues/budo.js";
|
|
5
|
+
import { dojoLayout, dojoLeague } from "./dojo.js";
|
|
6
|
+
/**
|
|
7
|
+
* A dojo (道場): the floor in mats, laid as real tatami units, with the walls, doors, windows, shrine and kamiza. `mats` is the floor: a number is its area in jō (8, 12, 20, 50, 100 and 200 give the usual shapes), `[across, along]`
|
|
8
|
+
* the whole mats across and along, `{ width, length, unit }` a size in metres, feet, mats or jō; `pattern` is how it is laid (`traditional`: no four corners meet; `competition`, `checker`, `border`).
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { dojo } from "@johnmorrisdotca/kyogijo-stadiums/budo";
|
|
12
|
+
* const d = dojo({ jo: 20 });
|
|
13
|
+
* console.log(d.jo, d.width.toFixed(2), d.length.toFixed(2), d.counts.full, d.counts.half, d.pattern);
|
|
14
|
+
* // 20 7.28 4.55 18 4 traditional
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export function dojo(spec = {}) {
|
|
18
|
+
const standard = spec.standard ?? "chukyoma";
|
|
19
|
+
const league = dojoLeague(standard);
|
|
20
|
+
const L = dojoLayout(spec, league);
|
|
21
|
+
return {
|
|
22
|
+
spec,
|
|
23
|
+
standard,
|
|
24
|
+
mat: { length: L.mat.length, width: L.mat.width },
|
|
25
|
+
width: L.width,
|
|
26
|
+
length: L.length,
|
|
27
|
+
jo: L.jo,
|
|
28
|
+
counts: L.counts,
|
|
29
|
+
pattern: L.pattern,
|
|
30
|
+
mats: L.pieces,
|
|
31
|
+
kamiza: L.kamiza,
|
|
32
|
+
entrances: L.entrances,
|
|
33
|
+
windows: L.windows,
|
|
34
|
+
shrine: L.shrine,
|
|
35
|
+
wall: L.wall,
|
|
36
|
+
contests: L.contests,
|
|
37
|
+
options: { sport: "dojo", ...(standard === "chukyoma" ? {} : { league: standard }), dojo: spec },
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** Draw a dojo: `drawKyogijo` with the spec as the options' `dojo`, and any other option the caller gives. */
|
|
41
|
+
export function drawDojo(spec = {}, more = {}) {
|
|
42
|
+
const d = dojo(spec);
|
|
43
|
+
return drawKyogijo({ ...d.options, ...more, sport: "dojo", dojo: spec });
|
|
44
|
+
}
|
|
45
|
+
/** The mat standards a dojo can be laid with. */
|
|
46
|
+
export const DOJO_STANDARDS = DOJO_LEAGUES.map((l) => l.id);
|