@johnmorrisdotca/kyogijo-stadiums 0.22.0 → 0.24.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 +20 -0
- package/NOTICE.md +1 -1
- package/README.md +79 -43
- package/dist/budo/describe.js +10 -0
- package/dist/budo/looks.js +8 -5
- package/dist/budo/plan.d.ts +1 -0
- package/dist/budo/plan.js +10 -3
- package/dist/budo/ring.js +7 -4
- package/dist/budo/types.d.ts +1 -1
- package/dist/budo.style.js +2 -2
- package/dist/crowd.js +2 -0
- package/dist/draw.js +16 -3
- package/dist/features.js +8 -0
- package/dist/heat.zones.js +1 -1
- package/dist/homeside.js +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/leagues/combat.d.ts +19 -2
- package/dist/leagues/combat.js +27 -1
- package/dist/leagues/sources.js +3 -0
- package/dist/leagues/types.d.ts +1 -1
- package/dist/leagues.d.ts +1 -1
- package/dist/leagues.js +21 -3
- package/dist/outline.js +1 -0
- package/dist/overlay.d.ts +73 -0
- package/dist/overlay.js +182 -0
- package/dist/ranges.names.js +1 -0
- package/dist/score.js +3 -0
- package/dist/strings.d.ts +4 -0
- package/dist/strings.js +15 -7
- package/dist/turn.dom.js +6 -1
- package/dist/turn.markup.js +2 -1
- package/dist/turn.model.d.ts +3 -0
- package/dist/turn.model.js +4 -0
- package/dist/turn.style.js +2 -0
- package/dist/types.d.ts +8 -1
- package/dist/units.js +2 -0
- package/dist/uprights.budo.js +3 -1
- package/dist/uprights.js +1 -1
- package/dist/uprights.ring.js +2 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -1
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export { OUTCOMES, drawLayers, layerTable } from "./layers.ts";
|
|
|
10
10
|
export { RANGES } from "./ranges.names.ts";
|
|
11
11
|
export { BACKGROUND_OPACITY, BACKGROUND_PATTERNS, KYOGIJO_BACKGROUND_STYLE } from "./background.ts";
|
|
12
12
|
export type { Background, BackgroundFit, BackgroundOptions, BackgroundPattern } from "./background.ts";
|
|
13
|
+
export { BOARD_CLEAR, BOARD_POSITIONS, placeBoard } from "./overlay.ts";
|
|
14
|
+
export type { BoardBox, BoardOptions, BoardPoint, BoardPosition } from "./overlay.ts";
|
|
13
15
|
export { FIELD_SPORTS, fieldPlan, isFieldSport } from "./fields.ts";
|
|
14
16
|
export { POOL_SPORTS, isPoolSport, poolPlan, swimPlan, venueLayout } from "./pool.ts";
|
|
15
17
|
export type { ArtisticPlan, Board, DivePlan, LanePlan, PoloPlan, PoolPlan, Rope, RopeColour, SwimPlan, VenueItem, VenueLayout } from "./pool.ts";
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export { useFlags } from "./flags-source.js";
|
|
|
8
8
|
export { OUTCOMES, drawLayers, layerTable } from "./layers.js";
|
|
9
9
|
export { RANGES } from "./ranges.names.js";
|
|
10
10
|
export { BACKGROUND_OPACITY, BACKGROUND_PATTERNS, KYOGIJO_BACKGROUND_STYLE } from "./background.js";
|
|
11
|
+
export { BOARD_CLEAR, BOARD_POSITIONS, placeBoard } from "./overlay.js";
|
|
11
12
|
export { FIELD_SPORTS, fieldPlan, isFieldSport } from "./fields.js";
|
|
12
13
|
export { POOL_SPORTS, isPoolSport, poolPlan, swimPlan, venueLayout } from "./pool.js";
|
|
13
14
|
export { formatTime, parseTime } from "./pool.race.js";
|
package/dist/leagues/combat.d.ts
CHANGED
|
@@ -79,6 +79,9 @@ export interface RingFigures {
|
|
|
79
79
|
fromRopes: number;
|
|
80
80
|
pad: number;
|
|
81
81
|
};
|
|
82
|
+
/** Whether two ties hold the ropes of a side in line (a boxing ring's; a wrestling ring's ropes are not tethered together), and whether the corners are the two boxers' (red and blue) and two neutral ones. */
|
|
83
|
+
ties: boolean;
|
|
84
|
+
boxerCorners: boolean;
|
|
82
85
|
}
|
|
83
86
|
/** The figures of a boxing ring, in metres. */
|
|
84
87
|
export interface BoxingFigures extends RingFigures {
|
|
@@ -135,9 +138,23 @@ export declare const NCAA_MAT: WrestlingFigures;
|
|
|
135
138
|
export declare const NFHS_MAT: WrestlingFigures;
|
|
136
139
|
/** The wrestling leagues: the UWW's first. */
|
|
137
140
|
export declare const WRESTLING_LEAGUES: readonly WrestlingLeague[];
|
|
141
|
+
/** The figures of a professional wrestling ring, in metres: the same ring as the boxing ring, with three ropes that are not tied together, posts at the corners and steel steps at ringside. No body's rule gives them: they are what rings are made as. */
|
|
142
|
+
export interface ProWrestlingFigures extends RingFigures {
|
|
143
|
+
kind: "prowrestling";
|
|
144
|
+
}
|
|
145
|
+
/** A professional wrestling league: the ring as rings are made. */
|
|
146
|
+
export type ProWrestlingLeague = LeagueBase<"prowrestling", ProWrestlingFigures>;
|
|
147
|
+
/**
|
|
148
|
+
* The professional wrestling ring as it is typically made (no rulebook gives it: every figure is typical, from the sources that describe one, and they differ): most rings measure 14 to 20 feet a side between the ropes, and 20 feet is
|
|
149
|
+
* the large promotions' size (English Wikipedia, "Wrestling ring"); three ropes of 1 to 1.5 inches at about 1, 3 and 5 feet over the mat; a platform 40 inches (3 to 4.5 feet) over the floor; an apron of 1 foot beyond the ropes
|
|
150
|
+
* (dimensions.com, "Professional Wrestling Ring"; a 2012 description of a large promotion's ring). The posts' height over the mat (ours) is 1.7 m, a little over the top rope.
|
|
151
|
+
*/
|
|
152
|
+
export declare const PRO_RING: ProWrestlingFigures;
|
|
153
|
+
/** The professional wrestling league: the ring as it is typically made. */
|
|
154
|
+
export declare const PRO_WRESTLING_LEAGUES: readonly ProWrestlingLeague[];
|
|
138
155
|
/** The figures of a combat league. */
|
|
139
|
-
export type CombatFigures = MmaFigures | BoxingFigures | WrestlingFigures;
|
|
156
|
+
export type CombatFigures = MmaFigures | BoxingFigures | WrestlingFigures | ProWrestlingFigures;
|
|
140
157
|
/** A league with a combat surface of its own. */
|
|
141
|
-
export type CombatLeague = MmaLeague | BoxingLeague | WrestlingLeague;
|
|
158
|
+
export type CombatLeague = MmaLeague | BoxingLeague | WrestlingLeague | ProWrestlingLeague;
|
|
142
159
|
/** Every combat league, once each. */
|
|
143
160
|
export declare const COMBAT_LEAGUES: readonly CombatLeague[];
|
package/dist/leagues/combat.js
CHANGED
|
@@ -33,6 +33,8 @@ export const NRUC_RING = {
|
|
|
33
33
|
foam: span(1 * IN, 1.5 * IN, 1 * IN),
|
|
34
34
|
ropes: { count: 4, heights: [18 * IN, 30 * IN, 42 * IN, 54 * IN], diameter: span(1 * IN, 2 * IN, 1 * IN) },
|
|
35
35
|
post: { height: 58 * IN, diameter: 3 * IN, fromRopes: 18 * IN, pad: 0.3 },
|
|
36
|
+
ties: true,
|
|
37
|
+
boxerCorners: true,
|
|
36
38
|
};
|
|
37
39
|
/** The ring of Wisconsin's rule (SPS 192.38): 16 to 20 feet within the ropes, an apron of at least 18 inches, a platform of at most 4 feet with three sets of steps, ropes at 18, 30, 42 and 54 inches, posts at least 3 inches across and 58 inches high. */
|
|
38
40
|
export const WISCONSIN_RING = {
|
|
@@ -43,6 +45,8 @@ export const WISCONSIN_RING = {
|
|
|
43
45
|
foam: span(1 * IN, 1 * IN, 1 * IN),
|
|
44
46
|
ropes: { count: 4, heights: [18 * IN, 30 * IN, 42 * IN, 54 * IN], diameter: span(1 * IN, 2 * IN, 1 * IN) },
|
|
45
47
|
post: { height: 58 * IN, diameter: 3 * IN, fromRopes: 18 * IN, pad: 0.3 },
|
|
48
|
+
ties: true,
|
|
49
|
+
boxerCorners: true,
|
|
46
50
|
};
|
|
47
51
|
/** The amateur ring of the WBC Amateur rules (Rule 1, 2026): 4.50 to 6.10 m within the ropes, a platform of 0.90 to 1.20 m, an apron of at least 0.50 m, ropes of 3 to 5 cm at 41, 71, 102 and 132 cm, three sets of steps. Ontario's amateur rules agree (4.9 to 6.1 m, ropes at 40, 70, 100 and 130 cm, an apron of at least 45 cm, a platform of at most 1.2 m). */
|
|
48
52
|
export const WBC_AMATEUR_RING = {
|
|
@@ -53,6 +57,8 @@ export const WBC_AMATEUR_RING = {
|
|
|
53
57
|
foam: span(0.01, 0.025, 0.02),
|
|
54
58
|
ropes: { count: 4, heights: [0.41, 0.71, 1.02, 1.32], diameter: span(0.03, 0.05, 0.04) },
|
|
55
59
|
post: { height: 1.5, diameter: 0.076, fromRopes: 0.45, pad: 0.3 },
|
|
60
|
+
ties: true,
|
|
61
|
+
boxerCorners: true,
|
|
56
62
|
};
|
|
57
63
|
/** The boxing leagues: the Nevada commission's first. */
|
|
58
64
|
export const BOXING_LEAGUES = [
|
|
@@ -99,5 +105,25 @@ export const WRESTLING_LEAGUES = [
|
|
|
99
105
|
{ id: "ncaa-wrestling", family: "wrestling", name: { en: "Wrestling mat, NCAA folkstyle", ja: "レスリングのマット(NCAA:フォークスタイル)" }, unit: "ft", figuresUnit: "m", dimensions: NCAA_MAT, sources: ["ncaa-wrestling"] },
|
|
100
106
|
{ id: "nfhs-wrestling", family: "wrestling", name: { en: "Wrestling mat, high school folkstyle (NFHS)", ja: "レスリングのマット(NFHS:アメリカの高校のフォークスタイル)" }, unit: "ft", figuresUnit: "m", dimensions: NFHS_MAT, sources: ["nfhs-wrestling-mat", "ncaa-wrestling"] },
|
|
101
107
|
];
|
|
108
|
+
/**
|
|
109
|
+
* The professional wrestling ring as it is typically made (no rulebook gives it: every figure is typical, from the sources that describe one, and they differ): most rings measure 14 to 20 feet a side between the ropes, and 20 feet is
|
|
110
|
+
* the large promotions' size (English Wikipedia, "Wrestling ring"); three ropes of 1 to 1.5 inches at about 1, 3 and 5 feet over the mat; a platform 40 inches (3 to 4.5 feet) over the floor; an apron of 1 foot beyond the ropes
|
|
111
|
+
* (dimensions.com, "Professional Wrestling Ring"; a 2012 description of a large promotion's ring). The posts' height over the mat (ours) is 1.7 m, a little over the top rope.
|
|
112
|
+
*/
|
|
113
|
+
export const PRO_RING = {
|
|
114
|
+
kind: "prowrestling",
|
|
115
|
+
size: span(14 * FT, 20 * FT, 20 * FT),
|
|
116
|
+
platform: { height: span(0, 6 * FT, 40 * IN), steps: { sets: 2, treads: 3, tread: 0.3, width: 1 } },
|
|
117
|
+
apron: span(1 * FT, 3 * FT, 1 * FT),
|
|
118
|
+
foam: span(1 * IN, 2 * IN, 1 * IN),
|
|
119
|
+
ropes: { count: 3, heights: [1 * FT, 3 * FT, 5 * FT], diameter: span(1 * IN, 1.5 * IN, 1.25 * IN) },
|
|
120
|
+
post: { height: 1.7, diameter: 0.15, fromRopes: 0.12, pad: 0.26 },
|
|
121
|
+
ties: false,
|
|
122
|
+
boxerCorners: false,
|
|
123
|
+
};
|
|
124
|
+
/** The professional wrestling league: the ring as it is typically made. */
|
|
125
|
+
export const PRO_WRESTLING_LEAGUES = [
|
|
126
|
+
{ id: "pro-ring", family: "prowrestling", name: { en: "Professional wrestling ring, as rings are typically made", ja: "プロレスのリング(一般的な寸法)" }, unit: "ft", figuresUnit: "m", dimensions: PRO_RING, sources: ["wp-wrestling-ring", "dimensions-pro-ring", "wwe-ring-2012", "wp-boxing-ring"], builtIn: true },
|
|
127
|
+
];
|
|
102
128
|
/** Every combat league, once each. */
|
|
103
|
-
export const COMBAT_LEAGUES = Object.freeze([...MMA_LEAGUES, ...BOXING_LEAGUES, ...WRESTLING_LEAGUES]);
|
|
129
|
+
export const COMBAT_LEAGUES = Object.freeze([...MMA_LEAGUES, ...BOXING_LEAGUES, ...WRESTLING_LEAGUES, ...PRO_WRESTLING_LEAGUES]);
|
package/dist/leagues/sources.js
CHANGED
|
@@ -137,6 +137,9 @@ export const LEAGUE_SOURCES = Object.freeze(Object.fromEntries([
|
|
|
137
137
|
source({ id: "uww-wrestling-rules", title: "Wrestling Rules, Article 4 The Mat (a 9 m mat with a 1.50 m border of the same thickness; an orange band of 1 m inside the 9 m circle; the central circle of 1 m with a band of 10 cm; the central surface of 7 m; the platform of 0.80 to 1.10 m with at least 1 m round the mat) and Article 45 Passivity Zone", by: "United World Wrestling", edition: "January 2026", url: "https://cdn.uww.org/2026-01/wrestling_rules.pdf", read: COMBAT_READ, note: "the one mat of freestyle, Greco-Roman and women's wrestling; the wrestlers' places (red left, blue right) are not drawn" }),
|
|
138
138
|
source({ id: "ncaa-wrestling", title: "NCAA Wrestling Rules 2025-26 and 2026-27, Rule 1, Section 1 Mats (Art. 1 mat specifications: a competition circle of 32 to 42 feet, a matted area of at least 5 feet round it, the circle's edge a 2 inch line in bounds; Art. 3 mat markings: two 1 inch down-position starting lines 3 feet long and 10 inches apart, closed by a green and a red neutral line) and Diagram 1", by: "NCAA, Men's Wrestling Rules Committee", edition: "August 2025", url: "https://ncaaorg.s3.amazonaws.com/championships/sports/wrestling/rules/PRMWR_RulesBook.pdf", read: COMBAT_READ, note: "the college mat; the NFHS's starting lines are the same size" }),
|
|
139
139
|
source({ id: "nfhs-wrestling-mat", title: "Required Wrestling Mat Area (quoting NFHS Wrestling Rule 2-1-2: a wrestling area of a minimum of 28 feet in diameter with a safety mat area of approximately 5 feet wide round it)", by: "Kentucky High School Athletic Association, notice of 21 November 2014", edition: "2014 notice of the NFHS rule", url: "https://khsaa.org/?p=14520", read: COMBAT_READ, note: "the high school mat's size; the starting lines (1 inch, 3 feet long, 12 inches outside to outside, closed by a red and a green line, front line on the diameter of the 10 foot circle) are quoted from NFHS Rule 2-1-4 on https://info.resilite.com/knowledge/why-are-my-referee-/-starting-lines-not-centered, and the circle of 10 feet became optional in 2024-25 (NFHS 2-1-3 and 2-1-4: NJSIAA, Wrestling Rule Changes 2024-2025, https://njsiaa.org/sites/default/files/documents/2024-10/wrestling-rule-changes-2024-2025.pdf)" }),
|
|
140
|
+
source({ id: "wp-wrestling-ring", title: "Wrestling ring (English Wikipedia): constructed like a boxing ring; three ring ropes (one fewer than a boxing ring) that are not tethered together, held by turnbuckles hung on steel posts; the apron the mat beyond the ropes; steel steps at ringside; most rings 14 to 20 feet on each side, 20 feet for the large promotions and 18 for some others", by: "Wikipedia contributors (CC BY-SA 4.0), read for facts only", edition: "revision 1379090810", url: "https://en.wikipedia.org/w/index.php?title=Wrestling_ring&oldid=1379090810", read: COMBAT_READ, note: "typical, not a rule: the size range, three ropes, no ties, the apron, the steps" }),
|
|
141
|
+
source({ id: "dimensions-pro-ring", title: "Professional Wrestling Ring Dimensions & Drawings: a ring of 20 by 20 feet, the mat 40 inches (1.02 m) over the floor, an apron of 1 foot, ropes of 1 to 1.5 inches, posts 6 inches across", by: "Dimensions.com", edition: "the page as read on the date given (it names no promotion; its figure of an 8 foot top rope is not used)", url: "https://www.dimensions.com/element/professional-wrestling-ring", read: COMBAT_READ, note: "typical, not a rule: the platform's height, the apron, the ropes' thickness" }),
|
|
142
|
+
source({ id: "wwe-ring-2012", title: "WWE Wrestling Ring Dimensions (a blog's description of a large promotion's ring as of 2012: a mat of 20 by 20 feet between the turnbuckles, 21 by 21 feet with the apron, 4 to 6 feet from the floor, three ropes at about 1, 3 and 5 feet over the mat, an apron of 1 foot beyond the ropes)", by: "Abstruse Decapod Games & Fun (a blog)", edition: "posted 15 November 2012", url: "http://abstrusedecapod.blogspot.com/2012/11/wwe-wrestling-ring-dimensions.html", read: COMBAT_READ, note: "typical, not a rule, and the weakest source here: the ropes' heights and the platform's upper range; the blog's own spacing figure is wrong, as a comment on it says, and its post height is not used" }),
|
|
140
143
|
// Baseball and softball.
|
|
141
144
|
source({ id: "obr-2026", title: "Official Baseball Rules, 2.01, 2.03 and 2.04 (the rules Minor League Baseball plays under)", by: "Major League Baseball", edition: "2026", url: "https://mktg.mlbstatic.com/mlb/official-information/2026-official-baseball-rules.pdf", read: READ, note: "bases 18 inches (2.03), the fence at least 325 and 400 feet (2.01 note); Minor League Baseball's own facility standards are not public" }),
|
|
142
145
|
source({ id: "ncaa-baseball", title: "NCAA Baseball Rules, Rule 1, and the field diagram", by: "NCAA", edition: "2027 and 2028 rules book (printed October 2026)", url: "https://ncaaorg.s3.amazonaws.com/championships/sports/baseball/rules/PRMBA_RulesBook.pdf", read: READ, note: "90-foot square (1-2-a), recommended fence 330, 375 and 400 feet (1-2-b), boxes 4 by 6 feet (1-3-a), backstop 45 feet (1-5-b); diagram: PRMBA_Re-imagedFieldDiagrams.pdf" }),
|
package/dist/leagues/types.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export interface Named {
|
|
|
5
5
|
ja: string;
|
|
6
6
|
}
|
|
7
7
|
/** The families of surface a league is a variant of. */
|
|
8
|
-
export type Family = "basketball" | "hockey" | "football" | "baseball" | "curling" | "tennis" | "volleyball" | "badminton" | "pickleball" | "tabletennis" | "padel" | "squash" | "racquetball" | "sepaktakraw" | "teqball" | "roundnet" | "netball" | "lacrosse" | "rugby" | "afl" | "gaelic" | "cricket" | "fieldhockey" | "handball" | "athletics" | "skating" | "judo" | "karate" | "kendo" | "sumo" | "kyudo" | "dojo" | "mma" | "boxing" | "wrestling";
|
|
8
|
+
export type Family = "basketball" | "hockey" | "football" | "baseball" | "curling" | "tennis" | "volleyball" | "badminton" | "pickleball" | "tabletennis" | "padel" | "squash" | "racquetball" | "sepaktakraw" | "teqball" | "roundnet" | "netball" | "lacrosse" | "rugby" | "afl" | "gaelic" | "cricket" | "fieldhockey" | "handball" | "athletics" | "skating" | "judo" | "karate" | "kendo" | "sumo" | "kyudo" | "dojo" | "mma" | "boxing" | "wrestling" | "prowrestling";
|
|
9
9
|
/** The state of one marking from a season on, in a league's own history: the season it began, what it was, and its sources. */
|
|
10
10
|
export interface LeagueSpan<T> {
|
|
11
11
|
/** The first season it was in force, or `null` for the state before the first change that is cited. */
|
package/dist/leagues.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ export { WA_STANDARD_TRACK, WA_SHORT_TRACK, WA_STAGGER_TABLE, WA_SHORT_STAGGER_T
|
|
|
36
36
|
export type { SkatingFigures, SkatingLeague, LongTrackFigures, ShortTrackFigures, FigureRinkFigures } from "./leagues/skating.ts";
|
|
37
37
|
export { ISU_LONG_TRACK, ISU_SHORT_TRACK, ISU_FIGURE_RINK, ISU_LONG_TRACK_TABLE } from "./leagues/skating.ts";
|
|
38
38
|
export type { BudoFigures, BudoLeague, DojoFigures, DojoLeague, JudoFigures, JudoLeague, KarateFigures, KarateLeague, KendoFigures, KendoLeague, KyudoFigures, KyudoLeague, Mat, SumoFigures, SumoLeague } from "./leagues/budo.ts";
|
|
39
|
-
export { BOXING_LEAGUES, IMMAF_CAGE, MMA_LEAGUES, NRUC_CAGE, NCAA_MAT, NFHS_MAT, NRUC_RING, UWW_MAT, WBC_AMATEUR_RING, WISCONSIN_RING, WRESTLING_LEAGUES } from "./leagues/combat.ts";
|
|
39
|
+
export { BOXING_LEAGUES, IMMAF_CAGE, MMA_LEAGUES, NRUC_CAGE, NCAA_MAT, NFHS_MAT, NRUC_RING, PRO_RING, PRO_WRESTLING_LEAGUES, UWW_MAT, WBC_AMATEUR_RING, WISCONSIN_RING, WRESTLING_LEAGUES } from "./leagues/combat.ts";
|
|
40
40
|
export { AJJF_CONTEST, BUDO_LEAGUES, ENTEKI, FIK_SHIAI_JO, IJF_CONTEST, IJF_KATA, JSA_DOHYO, KINTEKI, WKF_KATA, WKF_KUMITE } from "./leagues/budo.ts";
|
|
41
41
|
export type { BadmintonFigures, BadmintonLeague, FreeZone, FreeZones, NetFigures, NetLeague, NetSport, NetballFigures, NetballLeague, PadelFigures, PadelLeague, PickleballFigures, PickleballLeague, RacquetballFigures, RacquetballLeague, RoundnetFigures, RoundnetLeague, SepakTakrawFigures, SepakTakrawLeague, SquashFigures, SquashLeague, TableTennisFigures, TableTennisLeague, TennisFigures, TennisLeague, TeqballFigures, TeqballLeague, VolleyballFigures, VolleyballLeague } from "./leagues/courts.ts";
|
|
42
42
|
export type { CourtFigures, CourtMarks } from "./leagues/basketball.ts";
|
package/dist/leagues.js
CHANGED
|
@@ -15,7 +15,7 @@ import { FIELD_HOCKEY_LEAGUES, fieldHockeyInFeet } from "./leagues/fieldhockey.j
|
|
|
15
15
|
import { ATHLETICS_LEAGUES, athleticsInFeet } from "./leagues/athletics.js";
|
|
16
16
|
import { longOval, outerEdge } from "./skating/track.js";
|
|
17
17
|
import { SKATING_LEAGUES, skatingInFeet } from "./leagues/skating.js";
|
|
18
|
-
import { BOXING_LEAGUES, MMA_LEAGUES, WRESTLING_LEAGUES } from "./leagues/combat.js";
|
|
18
|
+
import { BOXING_LEAGUES, MMA_LEAGUES, PRO_WRESTLING_LEAGUES, WRESTLING_LEAGUES } from "./leagues/combat.js";
|
|
19
19
|
import { BUDO_LEAGUES, DOJO_LEAGUES, JUDO_LEAGUES, KARATE_LEAGUES, KENDO_LEAGUES, KYUDO_LEAGUES, SUMO_LEAGUES } from "./leagues/budo.js";
|
|
20
20
|
import { GAELIC_LEAGUES, gaelicInFeet } from "./leagues/gaelic.js";
|
|
21
21
|
import { HANDBALL_LEAGUES, handballInFeet } from "./leagues/handball.js";
|
|
@@ -28,10 +28,10 @@ export { LEAGUE_SOURCES };
|
|
|
28
28
|
export { AFL_GROUNDS } from "./leagues/aussie.js";
|
|
29
29
|
export { WA_STANDARD_TRACK, WA_SHORT_TRACK, WA_STAGGER_TABLE, WA_SHORT_STAGGER_TABLE } from "./leagues/athletics.js";
|
|
30
30
|
export { ISU_LONG_TRACK, ISU_SHORT_TRACK, ISU_FIGURE_RINK, ISU_LONG_TRACK_TABLE } from "./leagues/skating.js";
|
|
31
|
-
export { BOXING_LEAGUES, IMMAF_CAGE, MMA_LEAGUES, NRUC_CAGE, NCAA_MAT, NFHS_MAT, NRUC_RING, UWW_MAT, WBC_AMATEUR_RING, WISCONSIN_RING, WRESTLING_LEAGUES } from "./leagues/combat.js";
|
|
31
|
+
export { BOXING_LEAGUES, IMMAF_CAGE, MMA_LEAGUES, NRUC_CAGE, NCAA_MAT, NFHS_MAT, NRUC_RING, PRO_RING, PRO_WRESTLING_LEAGUES, UWW_MAT, WBC_AMATEUR_RING, WISCONSIN_RING, WRESTLING_LEAGUES } from "./leagues/combat.js";
|
|
32
32
|
export { AJJF_CONTEST, BUDO_LEAGUES, ENTEKI, FIK_SHIAI_JO, IJF_CONTEST, IJF_KATA, JSA_DOHYO, KINTEKI, WKF_KATA, WKF_KUMITE } from "./leagues/budo.js";
|
|
33
33
|
/** The family of surface each sport draws; soccer's variants are its pitches (`pitch`), not leagues. */
|
|
34
|
-
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", padel: "padel", squash: "squash", racquetball: "racquetball", sepaktakraw: "sepaktakraw", teqball: "teqball", roundnet: "roundnet", netball: "netball", lacrosse: "lacrosse", rugby: "rugby", afl: "afl", gaelic: "gaelic", cricket: "cricket", fieldhockey: "fieldhockey", handball: "handball", swimming: undefined, waterpolo: undefined, diving: undefined, artisticswimming: undefined, athletics: "athletics", skating: "skating", judo: "judo", karate: "karate", kendo: "kendo", sumo: "sumo", kyudo: "kyudo", dojo: "dojo", mma: "mma", boxing: "boxing", wrestling: "wrestling" });
|
|
34
|
+
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", padel: "padel", squash: "squash", racquetball: "racquetball", sepaktakraw: "sepaktakraw", teqball: "teqball", roundnet: "roundnet", netball: "netball", lacrosse: "lacrosse", rugby: "rugby", afl: "afl", gaelic: "gaelic", cricket: "cricket", fieldhockey: "fieldhockey", handball: "handball", swimming: undefined, waterpolo: undefined, diving: undefined, artisticswimming: undefined, athletics: "athletics", skating: "skating", judo: "judo", karate: "karate", kendo: "kendo", sumo: "sumo", kyudo: "kyudo", dojo: "dojo", mma: "mma", boxing: "boxing", wrestling: "wrestling", prowrestling: "prowrestling" });
|
|
35
35
|
/**
|
|
36
36
|
* The leagues each sport can draw, in the order a menu lists them, the sport's own first (the three football sports share their
|
|
37
37
|
* list, the football leagues). Soccer and the pools have none.
|
|
@@ -80,6 +80,7 @@ export const LEAGUES = Object.freeze({
|
|
|
80
80
|
mma: MMA_LEAGUES,
|
|
81
81
|
boxing: BOXING_LEAGUES,
|
|
82
82
|
wrestling: WRESTLING_LEAGUES,
|
|
83
|
+
prowrestling: PRO_WRESTLING_LEAGUES,
|
|
83
84
|
});
|
|
84
85
|
/** Every league of every family, once each. */
|
|
85
86
|
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, ...PADEL_LEAGUES, ...SQUASH_LEAGUES, ...RACQUETBALL_LEAGUES, ...SEPAK_TAKRAW_LEAGUES, ...TEQBALL_LEAGUES, ...ROUNDNET_LEAGUES, ...NETBALL_LEAGUES, ...LACROSSE_LEAGUES, ...RUGBY_LEAGUES, ...AFL_LEAGUES, ...GAELIC_LEAGUES, ...CRICKET_LEAGUES, ...FIELD_HOCKEY_LEAGUES, ...HANDBALL_LEAGUES, ...ATHLETICS_LEAGUES, ...BUDO_LEAGUES]);
|
|
@@ -335,6 +336,13 @@ export function leagueSize(sport, id, unit) {
|
|
|
335
336
|
feet = { length: convertLength(length, "m", "ft"), width: convertLength(frontage, "m", "ft") };
|
|
336
337
|
break;
|
|
337
338
|
}
|
|
339
|
+
case "prowrestling": {
|
|
340
|
+
// The platform: the ring at the size drawn, with its apron.
|
|
341
|
+
const d = league.dimensions;
|
|
342
|
+
const m = d.size.drawn + 2 * Math.max(d.apron.drawn, d.post.fromRopes + d.post.pad / 2 + 0.02);
|
|
343
|
+
feet = { length: convertLength(m, "m", "ft"), width: convertLength(m, "m", "ft") };
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
338
346
|
case "wrestling": {
|
|
339
347
|
// The mat's square: the circle with the matted area round it.
|
|
340
348
|
const d = league.dimensions;
|
|
@@ -710,6 +718,16 @@ export function leagueFigures(league) {
|
|
|
710
718
|
["shajō", `${f.hall.depth} m deep, ${f.hall.side} m from the end shooters to the walls, ceiling ${f.ceiling} m`],
|
|
711
719
|
];
|
|
712
720
|
}
|
|
721
|
+
case "prowrestling": {
|
|
722
|
+
const f = league.dimensions;
|
|
723
|
+
const ft = (m) => `${Math.round((m / 0.3048) * 100) / 100} ft`;
|
|
724
|
+
return [
|
|
725
|
+
["ring", `${ft(f.size.min)} to ${ft(f.size.max)} square between the ropes (typical)`],
|
|
726
|
+
["platform", `${ft(f.platform.height.drawn)} drawn, up to ${ft(f.platform.height.max)}`],
|
|
727
|
+
["ropes", `${f.ropes.count} at ${f.ropes.heights.map((h) => ft(h)).join(", ")}, not tied together`],
|
|
728
|
+
["apron", `${ft(f.apron.drawn)} beyond the ropes`],
|
|
729
|
+
];
|
|
730
|
+
}
|
|
713
731
|
case "wrestling": {
|
|
714
732
|
const f = league.dimensions;
|
|
715
733
|
const ft = (m) => `${Math.round((m / 0.3048) * 100) / 100} ft`;
|
package/dist/outline.js
CHANGED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** Where a board goes. `top` and `bottom` are centred on the drawing's top and bottom edge, `side` is at the right edge, centred, `left` the same at the left, `corner` is the top right corner, and the four corners by their names. */
|
|
2
|
+
export type BoardPosition = "top" | "bottom" | "side" | "left" | "corner" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
3
|
+
/** A place of your own: the board's top left corner (or, with `anchor: "center"`, its middle) at this share of the drawing's width (`x`) and height (`y`), 0 to 1. The board may then cover the middle of the surface: you asked for it. */
|
|
4
|
+
export interface BoardPoint {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
anchor?: "start" | "center";
|
|
8
|
+
}
|
|
9
|
+
/** A board over a drawing. */
|
|
10
|
+
export interface BoardOptions {
|
|
11
|
+
/** The board, as SVG text (`<svg …>…</svg>`): the string `resultsBoard`, `boutBoard` or `broadcastMedalTable` of Taisen Brackets gives. It is written as an image, so nothing in it can run and its styles stay in it. Anything else is ignored. */
|
|
12
|
+
svg: string;
|
|
13
|
+
/** The board's own width and height, the numbers its maker gives (`resultsBoardSize`, `boutBoardSize`, `broadcastMedalSize`): they give its shape. Left out, the `viewBox` of the SVG is read. A board with no size is ignored. */
|
|
14
|
+
width?: number;
|
|
15
|
+
height?: number;
|
|
16
|
+
/** Where it goes: a name (`BOARD_POSITIONS`) or a point of your own. `top` by default. */
|
|
17
|
+
position?: BoardPosition | BoardPoint;
|
|
18
|
+
/** How opaque it is, 0 to 1. 1 by default. */
|
|
19
|
+
opacity?: number;
|
|
20
|
+
/** Its width as a share of the drawing's width, 0.1 to 1. By default 0.5 at the top and the bottom, 0.3 at a side and 0.36 in a corner, and 0.4 at a point; a board is never made larger than the room that keeps the middle of the surface clear. */
|
|
21
|
+
share?: number;
|
|
22
|
+
/** The gap between the board and the edge of the drawing, as a share of the drawing's width, 0 to 0.2. 0.02 by default. */
|
|
23
|
+
margin?: number;
|
|
24
|
+
/** Let a named position cover the middle of the surface, so that the board may be as large as `share` says (it is still kept inside the drawing). Off by default. */
|
|
25
|
+
cover?: boolean;
|
|
26
|
+
/** What the board says, in a sentence, for a reader who cannot see it: its title and who leads, say. Without it the board is hidden from assistive technology (it is a picture of what the page says elsewhere). */
|
|
27
|
+
label?: string;
|
|
28
|
+
}
|
|
29
|
+
/** A board that has been read: sizes and places that can be used, and the picture as an address. */
|
|
30
|
+
export interface ResolvedBoard {
|
|
31
|
+
href: string;
|
|
32
|
+
width: number;
|
|
33
|
+
height: number;
|
|
34
|
+
position: BoardPosition | {
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
anchor: "start" | "center";
|
|
38
|
+
};
|
|
39
|
+
opacity: number;
|
|
40
|
+
share: number;
|
|
41
|
+
margin: number;
|
|
42
|
+
cover: boolean;
|
|
43
|
+
label: string | undefined;
|
|
44
|
+
}
|
|
45
|
+
/** A box: a drawing's viewBox, or the place a board takes in it. */
|
|
46
|
+
export interface BoardBox {
|
|
47
|
+
x: number;
|
|
48
|
+
y: number;
|
|
49
|
+
w: number;
|
|
50
|
+
h: number;
|
|
51
|
+
}
|
|
52
|
+
/** The positions, in the order a menu lists them. */
|
|
53
|
+
export declare const BOARD_POSITIONS: readonly BoardPosition[];
|
|
54
|
+
/** The share of a drawing's width and of its height that is kept clear round its middle: a board placed by name does not reach into it, so the middle of the playing area, where the score's panel stands, is never covered. */
|
|
55
|
+
export declare const BOARD_CLEAR = 0.34;
|
|
56
|
+
/** The shape of the box a 3D view is placed for (16 by 10, the view's own) and the units of it: a board in 3D is placed for this box and keeps its place, as a share of the box, when the box is another shape. */
|
|
57
|
+
export declare const BOARD_TURN_BOX: BoardBox;
|
|
58
|
+
/** The board an option asks for, read: a bad one is `undefined` and the drawing is as it was without it, as a bad `background` image is. */
|
|
59
|
+
export declare function resolveBoard(value: unknown): ResolvedBoard | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* The place a board takes in a box. A named position keeps to its edge and takes the share asked for, unless that would reach into the middle (`BOARD_CLEAR` of the box's width and height, centred): then the board is made smaller, down
|
|
62
|
+
* to nothing in a box too small to hold one, and never moved. `cover` lifts that, and a point of your own is never held to it. The board keeps its own shape, and stays inside the box.
|
|
63
|
+
*/
|
|
64
|
+
export declare function placeBoard(board: ResolvedBoard, view: BoardBox): BoardBox;
|
|
65
|
+
/** The board as markup in a drawing: an image in the box `placeBoard` gave, in the drawing's own units, over everything else. Nothing for a box with no room. */
|
|
66
|
+
export declare function overlayMarkup(board: ResolvedBoard, box: BoardBox): string;
|
|
67
|
+
/**
|
|
68
|
+
* The 3D view's board: a layer over the whole view (not in the scene, so it never turns, tips or zooms with it), and in it the picture at its size as a share of the view's width, its own shape kept (`height:auto`, `object-fit:contain`),
|
|
69
|
+
* placed by flex alignment on the view's edges. Its largest height is what the box `BOARD_TURN_BOX` gives it, so that on a wider view than that it still does not reach into the middle. It never takes the pointer: a drag on it turns the view.
|
|
70
|
+
*/
|
|
71
|
+
export declare function turnBoardMarkup(board: ResolvedBoard): string;
|
|
72
|
+
/** The rules of the 3D view's board layer, written into `KYOGIJO_TURN_STYLE`. */
|
|
73
|
+
export declare const KYOGIJO_TURN_BOARD_STYLE: string;
|
package/dist/overlay.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// A board laid over a drawing: a results board, a bout presentation, a medal table, drawn by anything else as an SVG (Taisen Brackets', say) and placed here, over the surface, in 2D (`board` in the drawing's
|
|
2
|
+
// options) and in 3D (`board` in the options of the 3D view, where it is a screen-space overlay over the view and never a plane that turns). The package takes the board as a string and draws no board of its own and
|
|
3
|
+
// reads nothing from the one it is given but its size: it is written as an image, which cannot run scripts, scaled evenly (its own shape is kept, so no letter is ever stretched), and placed by a named position
|
|
4
|
+
// that keeps the middle of the surface clear, or by a point of the caller's choosing. Pure: the same options always give the same string.
|
|
5
|
+
import { safePicture } from "./colour.js";
|
|
6
|
+
import { el, esc, num } from "./format.js";
|
|
7
|
+
/** The positions, in the order a menu lists them. */
|
|
8
|
+
export const BOARD_POSITIONS = ["top", "bottom", "side", "left", "corner", "top-left", "top-right", "bottom-left", "bottom-right"];
|
|
9
|
+
/** The share of a drawing's width and of its height that is kept clear round its middle: a board placed by name does not reach into it, so the middle of the playing area, where the score's panel stands, is never covered. */
|
|
10
|
+
export const BOARD_CLEAR = 0.34;
|
|
11
|
+
/** The shape of the box a 3D view is placed for (16 by 10, the view's own) and the units of it: a board in 3D is placed for this box and keeps its place, as a share of the box, when the box is another shape. */
|
|
12
|
+
export const BOARD_TURN_BOX = { x: 0, y: 0, w: 1600, h: 1000 };
|
|
13
|
+
const MAX_SIZE = 100000;
|
|
14
|
+
const isPosition = (value) => typeof value === "string" && BOARD_POSITIONS.includes(value);
|
|
15
|
+
const finite = (value) => typeof value === "number" && Number.isFinite(value);
|
|
16
|
+
const between = (value, low, high) => Math.min(high, Math.max(low, value));
|
|
17
|
+
/** The width and height of an SVG document's root, from its `viewBox`. */
|
|
18
|
+
function viewBoxOf(svg) {
|
|
19
|
+
const root = /^\s*(?:<\?xml[^>]*\?>\s*)?(?:<!--[\s\S]*?-->\s*)*<svg\b[^>]*>/i.exec(svg)?.[0];
|
|
20
|
+
const box = root === undefined ? undefined : /\sviewBox\s*=\s*"\s*(-?[\d.]+)[\s,]+(-?[\d.]+)[\s,]+([\d.]+)[\s,]+([\d.]+)\s*"/i.exec(root);
|
|
21
|
+
if (box === undefined || box === null)
|
|
22
|
+
return undefined;
|
|
23
|
+
const [width, height] = [Number(box[3]), Number(box[4])];
|
|
24
|
+
return Number.isFinite(width) && Number.isFinite(height) && width > 0 && height > 0 ? { width, height } : undefined;
|
|
25
|
+
}
|
|
26
|
+
const defaultShare = (position) => {
|
|
27
|
+
if (typeof position === "object")
|
|
28
|
+
return 0.4;
|
|
29
|
+
if (position === "top" || position === "bottom")
|
|
30
|
+
return 0.5;
|
|
31
|
+
if (position === "side" || position === "left")
|
|
32
|
+
return 0.3;
|
|
33
|
+
return 0.36;
|
|
34
|
+
};
|
|
35
|
+
/** The board an option asks for, read: a bad one is `undefined` and the drawing is as it was without it, as a bad `background` image is. */
|
|
36
|
+
export function resolveBoard(value) {
|
|
37
|
+
if (typeof value !== "object" || value === null)
|
|
38
|
+
return undefined;
|
|
39
|
+
const o = value;
|
|
40
|
+
if (typeof o.svg !== "string" || !/^\s*(?:<\?xml|<svg)\b/i.test(o.svg))
|
|
41
|
+
return undefined;
|
|
42
|
+
const href = safePicture(o.svg);
|
|
43
|
+
if (href === undefined)
|
|
44
|
+
return undefined;
|
|
45
|
+
const own = viewBoxOf(o.svg);
|
|
46
|
+
const width = finite(o.width) && o.width > 0 ? o.width : own?.width;
|
|
47
|
+
const height = finite(o.height) && o.height > 0 ? o.height : own?.height;
|
|
48
|
+
if (width === undefined || height === undefined || width > MAX_SIZE || height > MAX_SIZE)
|
|
49
|
+
return undefined;
|
|
50
|
+
let position = "top";
|
|
51
|
+
const asked = o.position;
|
|
52
|
+
if (isPosition(asked))
|
|
53
|
+
position = asked;
|
|
54
|
+
else if (typeof asked === "object" && asked !== null && finite(asked.x) && finite(asked.y)) {
|
|
55
|
+
const point = asked;
|
|
56
|
+
position = { x: between(point.x, 0, 1), y: between(point.y, 0, 1), anchor: point.anchor === "center" ? "center" : "start" };
|
|
57
|
+
}
|
|
58
|
+
const label = typeof o.label === "string" && o.label.trim() !== "" ? o.label.trim().slice(0, 300) : undefined;
|
|
59
|
+
return {
|
|
60
|
+
href,
|
|
61
|
+
width,
|
|
62
|
+
height,
|
|
63
|
+
position,
|
|
64
|
+
opacity: finite(o.opacity) ? between(o.opacity, 0, 1) : 1,
|
|
65
|
+
share: finite(o.share) ? between(o.share, 0.1, 1) : defaultShare(position),
|
|
66
|
+
margin: finite(o.margin) ? between(o.margin, 0, 0.2) : 0.02,
|
|
67
|
+
cover: o.cover === true,
|
|
68
|
+
label,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** Where a named position stands: which edge it keeps to on each axis. */
|
|
72
|
+
function edges(position) {
|
|
73
|
+
switch (position) {
|
|
74
|
+
case "top":
|
|
75
|
+
return { v: "top", h: "centre" };
|
|
76
|
+
case "bottom":
|
|
77
|
+
return { v: "bottom", h: "centre" };
|
|
78
|
+
case "side":
|
|
79
|
+
return { v: "middle", h: "right" };
|
|
80
|
+
case "left":
|
|
81
|
+
return { v: "middle", h: "left" };
|
|
82
|
+
case "corner":
|
|
83
|
+
case "top-right":
|
|
84
|
+
return { v: "top", h: "right" };
|
|
85
|
+
case "top-left":
|
|
86
|
+
return { v: "top", h: "left" };
|
|
87
|
+
case "bottom-left":
|
|
88
|
+
return { v: "bottom", h: "left" };
|
|
89
|
+
case "bottom-right":
|
|
90
|
+
return { v: "bottom", h: "right" };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The place a board takes in a box. A named position keeps to its edge and takes the share asked for, unless that would reach into the middle (`BOARD_CLEAR` of the box's width and height, centred): then the board is made smaller, down
|
|
95
|
+
* to nothing in a box too small to hold one, and never moved. `cover` lifts that, and a point of your own is never held to it. The board keeps its own shape, and stays inside the box.
|
|
96
|
+
*/
|
|
97
|
+
export function placeBoard(board, view) {
|
|
98
|
+
const ratio = board.width / board.height;
|
|
99
|
+
const gap = board.margin * view.w;
|
|
100
|
+
const inner = { x0: view.x + gap, y0: view.y + gap, x1: view.x + view.w - gap, y1: view.y + view.h - gap };
|
|
101
|
+
const innerW = Math.max(0, inner.x1 - inner.x0);
|
|
102
|
+
const innerH = Math.max(0, inner.y1 - inner.y0);
|
|
103
|
+
const wanted = board.share * view.w;
|
|
104
|
+
const point = board.position;
|
|
105
|
+
if (typeof point === "object") {
|
|
106
|
+
const w = Math.max(0, Math.min(wanted, view.w, view.h * ratio));
|
|
107
|
+
const h = w / ratio;
|
|
108
|
+
const x = view.x + point.x * view.w - (point.anchor === "center" ? w / 2 : 0);
|
|
109
|
+
const y = view.y + point.y * view.h - (point.anchor === "center" ? h / 2 : 0);
|
|
110
|
+
return { x: between(x, view.x, view.x + view.w - w), y: between(y, view.y, view.y + view.h - h), w, h };
|
|
111
|
+
}
|
|
112
|
+
const { v, h: side } = edges(point);
|
|
113
|
+
const clear = { x0: view.x + view.w * (0.5 - BOARD_CLEAR / 2), x1: view.x + view.w * (0.5 + BOARD_CLEAR / 2), y0: view.y + view.h * (0.5 - BOARD_CLEAR / 2), y1: view.y + view.h * (0.5 + BOARD_CLEAR / 2) };
|
|
114
|
+
let room = Math.min(innerW, innerH * ratio);
|
|
115
|
+
if (!board.cover) {
|
|
116
|
+
// Beside the middle (to its right, or to its left) and above or below it: how wide the board may be in each.
|
|
117
|
+
const beside = side === "right" ? inner.x1 - (clear.x1 + gap) : side === "left" ? clear.x0 - gap - inner.x0 : 0;
|
|
118
|
+
const above = v === "top" ? clear.y0 - gap - inner.y0 : v === "bottom" ? inner.y1 - (clear.y1 + gap) : 0;
|
|
119
|
+
if (v === "middle")
|
|
120
|
+
room = Math.min(beside, innerH * ratio);
|
|
121
|
+
else if (side === "centre")
|
|
122
|
+
room = Math.min(above * ratio, innerW);
|
|
123
|
+
else
|
|
124
|
+
room = Math.max(Math.min(beside, innerH * ratio), Math.min(above * ratio, innerW));
|
|
125
|
+
}
|
|
126
|
+
const w = Math.max(0, Math.min(wanted, room));
|
|
127
|
+
const h = w / ratio;
|
|
128
|
+
const x = side === "left" ? inner.x0 : side === "right" ? inner.x1 - w : view.x + (view.w - w) / 2;
|
|
129
|
+
const y = v === "top" ? inner.y0 : v === "bottom" ? inner.y1 - h : view.y + (view.h - h) / 2;
|
|
130
|
+
return { x, y, w, h };
|
|
131
|
+
}
|
|
132
|
+
/** The name a position goes by in the markup. */
|
|
133
|
+
const positionName = (board) => (typeof board.position === "object" ? "custom" : board.position);
|
|
134
|
+
/** The board as markup in a drawing: an image in the box `placeBoard` gave, in the drawing's own units, over everything else. Nothing for a box with no room. */
|
|
135
|
+
export function overlayMarkup(board, box) {
|
|
136
|
+
if (!(box.w > 0) || !(box.h > 0))
|
|
137
|
+
return "";
|
|
138
|
+
return el("g", {
|
|
139
|
+
class: "ky-board",
|
|
140
|
+
"data-position": positionName(board),
|
|
141
|
+
opacity: board.opacity < 1 ? board.opacity : undefined,
|
|
142
|
+
"pointer-events": "none",
|
|
143
|
+
role: board.label === undefined ? undefined : "img",
|
|
144
|
+
"aria-label": board.label,
|
|
145
|
+
"aria-hidden": board.label === undefined ? "true" : undefined,
|
|
146
|
+
}, el("image", { class: "ky-board-img", href: board.href, x: box.x, y: box.y, width: box.w, height: box.h, preserveAspectRatio: "xMidYMid meet" }));
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* The 3D view's board: a layer over the whole view (not in the scene, so it never turns, tips or zooms with it), and in it the picture at its size as a share of the view's width, its own shape kept (`height:auto`, `object-fit:contain`),
|
|
150
|
+
* placed by flex alignment on the view's edges. Its largest height is what the box `BOARD_TURN_BOX` gives it, so that on a wider view than that it still does not reach into the middle. It never takes the pointer: a drag on it turns the view.
|
|
151
|
+
*/
|
|
152
|
+
export function turnBoardMarkup(board) {
|
|
153
|
+
const box = placeBoard(board, BOARD_TURN_BOX);
|
|
154
|
+
if (!(box.w > 0))
|
|
155
|
+
return "";
|
|
156
|
+
const percent = (n) => `${num(Math.round(n * 1000) / 10)}%`;
|
|
157
|
+
const style = [`width:${percent(box.w / BOARD_TURN_BOX.w)}`, `max-height:${percent(box.h / BOARD_TURN_BOX.h)}`];
|
|
158
|
+
if (typeof board.position === "object") {
|
|
159
|
+
style.push("position:absolute", `left:${percent(board.position.x)}`, `top:${percent(board.position.y)}`, "margin:0");
|
|
160
|
+
if (board.position.anchor === "center")
|
|
161
|
+
style.push("translate:-50% -50%");
|
|
162
|
+
}
|
|
163
|
+
else
|
|
164
|
+
style.push(`margin:${percent(board.margin)}`);
|
|
165
|
+
if (board.opacity < 1)
|
|
166
|
+
style.push(`opacity:${num(board.opacity)}`);
|
|
167
|
+
const attributes = `class="ky-turn-board" data-position="${positionName(board)}"${board.label === undefined ? ' aria-hidden="true"' : ` role="img" aria-label="${esc(board.label)}"`}`;
|
|
168
|
+
return `<div ${attributes}><img class="ky-turn-board-img" src="${esc(board.href)}" alt="" width="${num(board.width)}" height="${num(board.height)}" style="${style.join(";")}"></div>`;
|
|
169
|
+
}
|
|
170
|
+
/** The rules of the 3D view's board layer, written into `KYOGIJO_TURN_STYLE`. */
|
|
171
|
+
export const KYOGIJO_TURN_BOARD_STYLE = `
|
|
172
|
+
.ky-turn-board{position:absolute;inset:0;z-index:var(--ky-turn-board-z,9999);display:flex;pointer-events:none;overflow:hidden}
|
|
173
|
+
.ky-turn-board-img{display:block;height:auto;object-fit:contain;flex:none;min-width:0}
|
|
174
|
+
.ky-turn-board[data-position=top]{justify-content:center;align-items:flex-start}
|
|
175
|
+
.ky-turn-board[data-position=bottom]{justify-content:center;align-items:flex-end}
|
|
176
|
+
.ky-turn-board[data-position=side]{justify-content:flex-end;align-items:center}
|
|
177
|
+
.ky-turn-board[data-position=left]{justify-content:flex-start;align-items:center}
|
|
178
|
+
.ky-turn-board[data-position=corner],.ky-turn-board[data-position=top-right]{justify-content:flex-end;align-items:flex-start}
|
|
179
|
+
.ky-turn-board[data-position=top-left]{justify-content:flex-start;align-items:flex-start}
|
|
180
|
+
.ky-turn-board[data-position=bottom-left]{justify-content:flex-start;align-items:flex-end}
|
|
181
|
+
.ky-turn-board[data-position=bottom-right]{justify-content:flex-end;align-items:flex-end}
|
|
182
|
+
.ky-turn-board[data-position=custom]{display:block}`.trim();
|
package/dist/ranges.names.js
CHANGED
|
@@ -80,6 +80,7 @@ export const RANGES = Object.freeze({
|
|
|
80
80
|
dojo: Object.freeze([range("kamiza"), range("half", "left")]),
|
|
81
81
|
mma: Object.freeze([range("cage"), range("gate"), range("half", "left")]),
|
|
82
82
|
boxing: Object.freeze([range("ropes"), range("corner"), range("half", "left")]),
|
|
83
|
+
prowrestling: Object.freeze([range("ropes"), range("half", "left")]),
|
|
83
84
|
wrestling: Object.freeze([range("start"), range("passivity", undefined, ["uww"]), range("half", "left")]),
|
|
84
85
|
});
|
|
85
86
|
const isNumber = (value) => typeof value === "number" && Number.isFinite(value);
|
package/dist/score.js
CHANGED
|
@@ -218,6 +218,9 @@ export function glyph(sport) {
|
|
|
218
218
|
case "dojo":
|
|
219
219
|
// A dojo: a floor of mats laid so that no four corners meet.
|
|
220
220
|
return "M-14 -10H14V10H-14ZM-14 0H14M-5 -10V0M5 0V10";
|
|
221
|
+
case "prowrestling":
|
|
222
|
+
// A ring: the platform's square, the three ropes and the four posts.
|
|
223
|
+
return "M-10 -10H10V10H-10ZM-6 -6H6V6H-6ZM-5 -5H5V5H-5ZM-8 -8L-6 -6M8 -8L6 -6M-8 8L-6 6M8 8L6 6";
|
|
221
224
|
case "wrestling":
|
|
222
225
|
// A mat: the square, the circle, the passivity band and the circle in the middle.
|
|
223
226
|
return "M-10 -10H10V10H-10ZM-8 0A8 8 0 1 0 8 0A8 8 0 1 0 -8 0M-5.5 0A5.5 5.5 0 1 0 5.5 0A5.5 5.5 0 1 0 -5.5 0M-1 0A1 1 0 1 0 1 0A1 1 0 1 0 -1 0";
|
package/dist/strings.d.ts
CHANGED
|
@@ -459,6 +459,10 @@ export interface KyogijoWords {
|
|
|
459
459
|
wrestlingFloor: string;
|
|
460
460
|
wrestlingCentre: string;
|
|
461
461
|
wrestlingLines: string;
|
|
462
|
+
/** A professional wrestling ring: the sentence ({size}, {feet}, {apron}, {platform}; the platform parts are the boxing ring's), and the sentences about its ropes and its steps. */
|
|
463
|
+
prowrestling: string;
|
|
464
|
+
prowrestlingRopes: string;
|
|
465
|
+
prowrestlingSteps: string;
|
|
462
466
|
/** The scoreboards: the heads and the sentences that say what each side scored. */
|
|
463
467
|
board: {
|
|
464
468
|
ippon: string;
|