@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/heat.zones.js
CHANGED
|
@@ -15,6 +15,7 @@ import { WATER_POLO } from "./pool.figures.js";
|
|
|
15
15
|
import { swimPlan } from "./pool.js";
|
|
16
16
|
import { athleticsLanes, athleticsLeague } from "./athletics/plan.js";
|
|
17
17
|
import { skatingPlan } from "./skating/plan.js";
|
|
18
|
+
import { budoPlan } from "./budo/plan.js";
|
|
18
19
|
import { laneEdges } from "./skating/track.js";
|
|
19
20
|
import { iceRadius } from "./skating/long.js";
|
|
20
21
|
import { LEAGUES, chooseLeague, cricketOf } from "./leagues.js";
|
|
@@ -36,6 +37,7 @@ export const ZONE_SETS = Object.freeze({
|
|
|
36
37
|
"pool-lanes": { sports: ["swimming"], title: "Lanes: each lane of the pool, the whole length of it", source: "docs/sources.md#zone-sets" },
|
|
37
38
|
"water-polo-areas": { sports: ["waterpolo"], title: "The goal area, the ground from 2 to 6 m, and the rest of the field, at each end", source: "docs/sources.md#zone-sets" },
|
|
38
39
|
"pool-thirds": { sports: ["diving", "artisticswimming"], title: "Thirds along the pool, from the wall the boards or the judges stand at", source: "docs/sources.md#zone-sets" },
|
|
40
|
+
"budo-areas": { sports: ["judo", "karate", "kendo", "sumo", "kyudo", "dojo"], title: "The surface in its areas: the contest and the safety areas, the boundary band, the clay and the ring of a dohyō, the shajō, the yamichi and the azuchi, a dojo's floor", source: "docs/sources.md#zone-sets" },
|
|
39
41
|
"field-thirds": { sports: ["lacrosse", "rugby", "afl", "gaelic", "fieldhockey", "handball", "netball"], title: "Thirds: defensive, middle and attacking", source: "docs/sources.md#zone-sets" },
|
|
40
42
|
"skating-track": { sports: ["skating"], title: "The rink in parts: the finish straight, the first curve, the crossing straight, the second curve and the infield (a figure skating rink in thirds)", source: "docs/sources.md#zone-sets" },
|
|
41
43
|
"athletics-track": { sports: ["athletics"], title: "The track in parts: the finish straight, the first bend, the back straight, the second bend, and the infield", source: "docs/sources.md#zone-sets" },
|
|
@@ -197,7 +199,7 @@ function nhlZones(id, ctx) {
|
|
|
197
199
|
return out;
|
|
198
200
|
}
|
|
199
201
|
/** The distance from home plate along a ray at `angle` (degrees, 0 straight out to centre field, negative to left) to the edge of the infield: the arc 95 feet round the pitcher's plate. */
|
|
200
|
-
function infieldReach(angle) {
|
|
202
|
+
export function infieldReach(angle) {
|
|
201
203
|
const a = (angle * Math.PI) / 180;
|
|
202
204
|
const along = MLB.pitcher * Math.cos(a);
|
|
203
205
|
return along + Math.sqrt(along * along + MLB.skinRadius * MLB.skinRadius - MLB.pitcher * MLB.pitcher);
|
|
@@ -463,7 +465,7 @@ function poolLanes(ctx) {
|
|
|
463
465
|
}
|
|
464
466
|
/**
|
|
465
467
|
* A water polo field at each end: the goal area (to the 2 m line), the ground from 2 to 6 m (where the penalty foul applies), and the rest, split at the half distance line. The marks are the rules' (Part Six,
|
|
466
|
-
* Appendix 4); the zones are ours.
|
|
468
|
+
* Article 21.7, February 2026; Appendix 4, 20.4.1.5 in the June 2025 edition); the zones are ours.
|
|
467
469
|
*/
|
|
468
470
|
function waterPoloAreas(ctx) {
|
|
469
471
|
const { box } = ctx.outline;
|
|
@@ -556,6 +558,56 @@ function skatingZones(ctx) {
|
|
|
556
558
|
{ id: "second-curve", name: w.secondCurve, d: west, label: [cx - (S / 2 + (R + Ro) / 2) * k, cy], room: [(Ro - R) * k, R * k], has: (x, y) => { const [u, v] = m(x, y); return onIce(u, v) && u < -S / 2; } },
|
|
557
559
|
];
|
|
558
560
|
}
|
|
561
|
+
/**
|
|
562
|
+
* The budō surface in its areas, each as the plan lays it out (budo/plan.ts): a judo or karate area's mats by the colour they are laid in (the safety area under, the contest area, and for karate the boundary band, over
|
|
563
|
+
* it); a dohyō's clay, the jano-me and the ring; a kyūdōjō's shajō, yamichi and azuchi; a kendo floor and a dojo's in two parts (a dojo's kamiza end and the rest). The zones are ours: no rule names them.
|
|
564
|
+
*/
|
|
565
|
+
function budoZones(ctx) {
|
|
566
|
+
const plan = budoPlan({ sport: ctx.o.sport, league: ctx.o.league, budo: ctx.o.budo, dojo: ctx.o.dojo });
|
|
567
|
+
const k = FEET_PER_METRE;
|
|
568
|
+
const ox = plan.box.x0;
|
|
569
|
+
const oy = plan.box.y0;
|
|
570
|
+
const w = ctx.words;
|
|
571
|
+
const box = (b) => [(b.x0 - ox) * k, (b.y0 - oy) * k, (b.x1 - ox) * k, (b.y1 - oy) * k];
|
|
572
|
+
const one = (id, name, b) => {
|
|
573
|
+
const [x0, y0, x1, y1] = box(b);
|
|
574
|
+
return rect(id, name, x0, y0, x1, y1, true, true);
|
|
575
|
+
};
|
|
576
|
+
const whole = one("surface", w.budoSafety, plan.box);
|
|
577
|
+
// The zones do not overlap: a zone is what is in it and in none of the zones laid over it.
|
|
578
|
+
const inBox = (b, x, y) => x >= (b.x0 - ox) * k - 1e-9 && x <= (b.x1 - ox) * k + 1e-9 && y >= (b.y0 - oy) * k - 1e-9 && y <= (b.y1 - oy) * k + 1e-9;
|
|
579
|
+
const without = (z, over) => ({ ...z, has: (x, y) => z.has(x, y) && !over.some((b) => inBox(b, x, y)) });
|
|
580
|
+
if (plan.judo !== undefined)
|
|
581
|
+
return [without(one("safety-area", w.budoSafety, plan.judo.tatami), plan.judo.contests), ...plan.judo.contests.map((c, i) => one(`contest-area-${i + 1}`, w.budoContest, c))];
|
|
582
|
+
if (plan.karate !== undefined)
|
|
583
|
+
return [without(one("safety-area", w.budoSafety, plan.karate.mats), plan.karate.areas), ...plan.karate.areas.map((c, i) => without(one(`boundary-band-${i + 1}`, w.budoBand, c), plan.karate.inner)), ...plan.karate.inner.map((c, i) => one(`contest-area-${i + 1}`, w.budoContest, c))];
|
|
584
|
+
if (plan.sumo !== undefined) {
|
|
585
|
+
const L = plan.sumo;
|
|
586
|
+
const [cx, cy] = [(L.centre[0] - ox) * k, (L.centre[1] - oy) * k];
|
|
587
|
+
const ring = (r) => `M${num(cx - r * k)} ${num(cy)}A${num(r * k)} ${num(r * k)} 0 1 0 ${num(cx + r * k)} ${num(cy)}A${num(r * k)} ${num(r * k)} 0 1 0 ${num(cx - r * k)} ${num(cy)}Z`;
|
|
588
|
+
const jano = L.outer + plan.figures.jano;
|
|
589
|
+
const dist = (x, y) => Math.hypot(x - cx, y - cy) / k;
|
|
590
|
+
const base = one("clay", w.budoClay, L.platform);
|
|
591
|
+
const inner = L.ring + plan.figures.bale.width;
|
|
592
|
+
return [
|
|
593
|
+
{ ...base, has: (x, y) => base.has(x, y) && dist(x, y) > jano },
|
|
594
|
+
{ id: "jano-me", name: w.budoJano, d: ring(jano), label: [cx, cy - ((L.outer + jano) / 2) * k], room: [(jano - L.outer) * k, (jano - L.outer) * k], has: (x, y) => dist(x, y) <= jano && dist(x, y) > inner },
|
|
595
|
+
{ id: "ring", name: w.budoRing, d: ring(L.ring), label: [cx, cy - L.ring * 0.5 * k], room: [L.ring * k, L.ring * k * 0.4], has: (x, y) => dist(x, y) <= inner },
|
|
596
|
+
];
|
|
597
|
+
}
|
|
598
|
+
if (plan.kyudo !== undefined) {
|
|
599
|
+
const parts = [plan.kyudo.shajo, plan.kyudo.yamichi, plan.kyudo.azuchi];
|
|
600
|
+
return [without({ ...whole, id: "range", name: w.budoRest }, parts), one("shajo", w.budoShajo, plan.kyudo.shajo), without(one("yamichi", w.budoYamichi, plan.kyudo.yamichi), [plan.kyudo.shajo, plan.kyudo.azuchi]), without(one("azuchi", w.budoAzuchi, plan.kyudo.azuchi), [plan.kyudo.shajo, plan.kyudo.yamichi])];
|
|
601
|
+
}
|
|
602
|
+
const ranges = plan.ranges;
|
|
603
|
+
const kamiza = ranges.kamiza;
|
|
604
|
+
if (plan.dojo !== undefined && kamiza !== undefined && !("left" in kamiza))
|
|
605
|
+
return [without({ ...whole, id: "floor", name: w.budoRest }, [kamiza]), one("kamiza", w.budoKamiza, kamiza)];
|
|
606
|
+
const halves = ranges.half;
|
|
607
|
+
if (halves !== undefined && "left" in halves)
|
|
608
|
+
return [one("left", w.endLeft, halves.left), without(one("right", w.endRight, halves.right), [halves.left])];
|
|
609
|
+
return [whole];
|
|
610
|
+
}
|
|
559
611
|
/** The zones of a set on the surface the context describes. Throws for a set that is not for the surface's sport. */
|
|
560
612
|
export function buildZoneSet(id, ctx) {
|
|
561
613
|
if (!Object.prototype.hasOwnProperty.call(ZONE_SETS, id))
|
|
@@ -567,6 +619,6 @@ export function buildZoneSet(id, ctx) {
|
|
|
567
619
|
const { zones, which } = retrosheetZones(ctx);
|
|
568
620
|
return { id, zones, which };
|
|
569
621
|
}
|
|
570
|
-
const zones = id === "skating-track" ? skatingZones(ctx) : id === "athletics-track" ? athleticsZones(ctx) : id === "field-thirds" ? fieldThirds(ctx) : id === "cricket-ground" ? cricketZones(ctx) : id.startsWith("soccer") ? soccerZones(id, ctx) : id === "nba-shot" ? nbaZones(ctx) : id.startsWith("nhl") ? nhlZones(id, ctx) : id === "baseball-spray" ? baseballSpray(ctx) : id === "curling-house" ? curlingZones(ctx) : id === "net-court" ? netZones(ctx) : id === "wall-court" ? wallZones(ctx) : id === "roundnet-rings" ? roundnetZones(ctx) : id === "pool-lanes" ? poolLanes(ctx) : id === "water-polo-areas" ? waterPoloAreas(ctx) : id === "pool-thirds" ? poolThirds(ctx) : footballPass(ctx);
|
|
622
|
+
const zones = id === "budo-areas" ? budoZones(ctx) : id === "skating-track" ? skatingZones(ctx) : id === "athletics-track" ? athleticsZones(ctx) : id === "field-thirds" ? fieldThirds(ctx) : id === "cricket-ground" ? cricketZones(ctx) : id.startsWith("soccer") ? soccerZones(id, ctx) : id === "nba-shot" ? nbaZones(ctx) : id.startsWith("nhl") ? nhlZones(id, ctx) : id === "baseball-spray" ? baseballSpray(ctx) : id === "curling-house" ? curlingZones(ctx) : id === "net-court" ? netZones(ctx) : id === "wall-court" ? wallZones(ctx) : id === "roundnet-rings" ? roundnetZones(ctx) : id === "pool-lanes" ? poolLanes(ctx) : id === "water-polo-areas" ? waterPoloAreas(ctx) : id === "pool-thirds" ? poolThirds(ctx) : footballPass(ctx);
|
|
571
623
|
return { id, zones, which: lastWins(zones) };
|
|
572
624
|
}
|
package/dist/homeside.js
CHANGED
|
@@ -42,6 +42,13 @@ export const HOME_FIRST = Object.freeze({
|
|
|
42
42
|
athletics: false,
|
|
43
43
|
// A skating race has no home and away.
|
|
44
44
|
skating: false,
|
|
45
|
+
// A budō contest is between the first contestant called and the second (judo: blue to the referee's right, white to his left; karate: aka and ao; kendo: aka and shiro; sumo: east and west): no home side.
|
|
46
|
+
judo: false,
|
|
47
|
+
karate: false,
|
|
48
|
+
kendo: false,
|
|
49
|
+
sumo: false,
|
|
50
|
+
kyudo: false,
|
|
51
|
+
dojo: false,
|
|
45
52
|
});
|
|
46
53
|
/** The leagues whose convention is not their sport's: the international federation's lacrosse lists the home team first. */
|
|
47
54
|
export const HOME_FIRST_LEAGUES = Object.freeze({
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export { COLOR_PROPERTIES, SPORTS, crowdStands, describe, drawBadge, drawKyogijo, drawScore, drawSurface, isPortrait, statusLabel, statusText, winnerOf } from "./draw.ts";
|
|
2
2
|
export { HOME_FIRST, HOME_FIRST_LEAGUES, homeSideFor } from "./homeside.ts";
|
|
3
|
-
export { inkOn, luminance, rgbOf, safeColour,
|
|
3
|
+
export { inkOn, luminance, rgbOf, safeColour, safePicture } from "./colour.ts";
|
|
4
|
+
export { safeLogo } from "./logo.ts";
|
|
5
|
+
export { useEmblems } from "./emblems-source.ts";
|
|
6
|
+
export type { EmblemDrawOptions, EmblemId, EmblemRef, EmblemRenderer, EmblemStyleName } from "./emblems-source.ts";
|
|
4
7
|
export { OUTCOMES, drawLayers, layerTable } from "./layers.ts";
|
|
5
8
|
export { RANGES } from "./ranges.names.ts";
|
|
6
9
|
export { BACKGROUND_OPACITY, BACKGROUND_PATTERNS, KYOGIJO_BACKGROUND_STYLE } from "./background.ts";
|
|
@@ -14,6 +17,10 @@ export type { Area as FieldArea, FieldPlan, GoalPlan as FieldGoalPlan, Outline a
|
|
|
14
17
|
export { KYOGIJO_FIELDS_STYLE } from "./fields.style.ts";
|
|
15
18
|
export { KYOGIJO_ATHLETICS_STYLE, KYOGIJO_TRACK_STYLE } from "./athletics.style.ts";
|
|
16
19
|
export { KYOGIJO_SKATING_STYLE } from "./skating.style.ts";
|
|
20
|
+
export { KYOGIJO_BUDO_STYLE } from "./budo.style.ts";
|
|
21
|
+
export { dojo, drawDojo } from "./budo/dojo.api.ts";
|
|
22
|
+
export type { Dojo, Tatami } from "./budo/dojo.api.ts";
|
|
23
|
+
export type { BudoScore, BudoStyle, DojoSpec } from "./budo/types.ts";
|
|
17
24
|
export type { SkatingDiscipline, SkatingFurniture, SkatingInfield, SkatingRace, SkatingStyle } from "./skating/types.ts";
|
|
18
25
|
export type { AthleticsFieldEvent, AthleticsInfield, AthleticsRace, AthleticsStyle, AthleticsTrackLook, WaterJump } from "./athletics/types.ts";
|
|
19
26
|
export type { RangeInfo } from "./ranges.names.ts";
|
|
@@ -30,6 +37,9 @@ export { KYOGIJO_CROWD_STYLE } from "./crowd.draw.ts";
|
|
|
30
37
|
export { GRIDIRON_GROUNDS, WALL_SEATS, outlinePath, outlinePoints } from "./crowd.ts";
|
|
31
38
|
export type { CrowdStands, StandGap, StandRing, StandSector, Outline as StandOutline } from "./crowd.ts";
|
|
32
39
|
export { KYOGIJO_MARK_STYLE } from "./mark.ts";
|
|
40
|
+
export { DRIVE_CODES, readSituation, situationText } from "./situation.ts";
|
|
41
|
+
export type { BaseballSituation, DriveLeg, DriveResult, FootballSituation, HockeySituation, ShootoutAttempt, ShootoutRound, Situation, SituationContext, SituationRead, SituationTeam, HockeyRead, BaseballRead, FootballRead, DriveRead } from "./situation.ts";
|
|
42
|
+
export { KYOGIJO_SITUATION_STYLE } from "./situation.style.ts";
|
|
33
43
|
export { KYOGIJO_PAGEANT_MOTION, KYOGIJO_PAGEANT_STYLE } from "./pageant.style.ts";
|
|
34
44
|
export { KYOGIJO_POOL_STYLE } from "./pool.style.ts";
|
|
35
45
|
export { KYOGIJO_CURLING_STYLE, KYOGIJO_HEAT_STYLE, KYOGIJO_NOTE_STYLE, KYOGIJO_STYLE, KYOGIJO_TEAM_STYLE, KYOGIJO_WALLS_STYLE } from "./style.ts";
|
|
@@ -37,7 +47,7 @@ export { KYOGIJO_LOOK_STYLE, LOOKS, LOOK_NAMES, LOOK_PAIRS, contrastOf, groupOf,
|
|
|
37
47
|
export type { Group as LookGroup, Look, Palette as LookPalette, PaletteKey as LookPaletteKey } from "./look.ts";
|
|
38
48
|
export { FEATURES, FEATURE_INFO, KYOGIJO_FEATURE_STYLE } from "./features.ts";
|
|
39
49
|
export type { Feature } from "./features.ts";
|
|
40
|
-
export type { DelaunayLayer, FlowLayer, Formation, FormationLayer, FormationPlayer, FormationPosition, FormationSport, HullLayer, MoveDatum, NetworkLayer, NetworkNode, PassDatum, PlayerDatum, SonarLayer, VoronoiLayer } from "./team.types.ts";
|
|
50
|
+
export type { DelaunayLayer, FlowLayer, Formation, FormationLayer, FormationPlayer, FormationPosition, FormationSport, HullLayer, LineupLayer, LineupPlayer, MoveDatum, NetworkLayer, NetworkNode, PassDatum, PlayerDatum, SonarLayer, VoronoiLayer } from "./team.types.ts";
|
|
41
51
|
export { COURT_THEMES } from "./themes.ts";
|
|
42
52
|
export { abbreviate, capitals, fitLines, textWidth } from "./text.ts";
|
|
43
53
|
export type { FittedLines } from "./text.ts";
|
|
@@ -47,6 +57,8 @@ export type { PlaceAlias, PlaceNameKind } from "./names.ts";
|
|
|
47
57
|
export type { CoverQuirk, DugoutSide, HillQuirk, OverhangQuirk, Park, ParkData, ParkDugouts, ParkPeriod, ParkPeriodData, ParkQuirk, ParkSource, ParkWall, ParkWallData, PointQuirk, QuirkKind, WallPlace } from "./parks.ts";
|
|
48
58
|
export { ERA_CURRENT, ERA_SOURCES, ERA_SPORTS, eraChanges, eraRange, eraStates, footballIn, rulesFor, seasonLabel } from "./eras.ts";
|
|
49
59
|
export type { EraChange, EraRules, EraRulesOf, EraSource, EraSpan, EraSport, FootballRules, MlbRules, NbaRules, NhlRules } from "./eras.ts";
|
|
60
|
+
export { ARENA_IDS, ARENAS, arenaById, arenaByName, arenaByWikidata, arenaCourtIn, arenaNameIn, arenaOfficialName, arenaRinkIn, arenaSourceUrl, arenasByName } from "./arenas.ts";
|
|
61
|
+
export type { Arena, ArenaCapacity, ArenaData, ArenaName, ArenaSize, ArenaSource } from "./arenas.ts";
|
|
50
62
|
export { GROUND_IDS, GROUNDS, groundById, groundByName, groundByWikidata, groundNameIn, groundOfficialName, groundSourceUrl, groundsByName, groundsHosting } from "./grounds.ts";
|
|
51
63
|
export type { Ground, GroundCompetition, GroundData, GroundName, GroundSource, GroundTournament } from "./grounds.ts";
|
|
52
64
|
export { AFL_GROUNDS, FAMILY_OF, LEAGUES, LEAGUE_SOURCES, VARIANTS, chooseLeague, hasHistory, leagueAt, leagueById, leagueChanges, leagueFigures, leagueIds, leagueSeason, leagueSize } from "./leagues.ts";
|
|
@@ -58,4 +70,4 @@ export type { SoccerPitchClass, SoccerPitchId, SoccerSize, SoccerSpec } from "./
|
|
|
58
70
|
export { SOCCER_PROVIDER_IDS, SOCCER_PROVIDERS, frameMatrix, rescale, soccerFrame, soccerLandmarks } from "./surfaces/soccer-providers.ts";
|
|
59
71
|
export type { Rescaler, SoccerFrame, SoccerProvider, SoccerProviderId } from "./surfaces/soccer-providers.ts";
|
|
60
72
|
export { VERSION } from "./version.ts";
|
|
61
|
-
export type { AxesOptions, Box, Colors, CourtStyle, CrowdOptions, CrowdShape, Detail, DirectionOptions, FieldSport, FieldStyle, Fence, GoalInfo, GoalStyle, HardwoodOptions, Language, NetStyle, LineDash, LineWidth, LookName, Orientation, PoolSport, PoolStyle, QuirkName, QuirkOptions, RangeBox, PageantOptions, PageantStyle, RangeName, RangeNamed, ScoreOptions, Side, Size, Sport, StatusWord, StripePattern, SurfaceOptions, Team, TeamMark, Theme, WallOptions, } from "./types.ts";
|
|
73
|
+
export type { AxesOptions, Box, Colors, CourtStyle, CrowdOptions, CrowdShape, Detail, DirectionOptions, BudoSport, FieldSport, FieldStyle, Fence, GoalInfo, GoalStyle, HardwoodOptions, Language, NetStyle, LineDash, LineWidth, LookName, Orientation, PoolSport, PoolStyle, QuirkName, QuirkOptions, RangeBox, PageantOptions, PageantStyle, RangeName, RangeNamed, ScoreOptions, Side, Size, Sport, StatusWord, StripePattern, SurfaceOptions, Team, TeamMark, Theme, WallOptions, } from "./types.ts";
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// Kyogijo Stadiums 競技場: sports surfaces as SVG, drawn to scale, with the teams and the score on them.
|
|
2
2
|
export { COLOR_PROPERTIES, SPORTS, crowdStands, describe, drawBadge, drawKyogijo, drawScore, drawSurface, isPortrait, statusLabel, statusText, winnerOf } from "./draw.js";
|
|
3
3
|
export { HOME_FIRST, HOME_FIRST_LEAGUES, homeSideFor } from "./homeside.js";
|
|
4
|
-
export { inkOn, luminance, rgbOf, safeColour,
|
|
4
|
+
export { inkOn, luminance, rgbOf, safeColour, safePicture } from "./colour.js";
|
|
5
|
+
export { safeLogo } from "./logo.js";
|
|
6
|
+
export { useEmblems } from "./emblems-source.js";
|
|
5
7
|
export { OUTCOMES, drawLayers, layerTable } from "./layers.js";
|
|
6
8
|
export { RANGES } from "./ranges.names.js";
|
|
7
9
|
export { BACKGROUND_OPACITY, BACKGROUND_PATTERNS, KYOGIJO_BACKGROUND_STYLE } from "./background.js";
|
|
@@ -11,6 +13,8 @@ export { formatTime, parseTime } from "./pool.race.js";
|
|
|
11
13
|
export { KYOGIJO_FIELDS_STYLE } from "./fields.style.js";
|
|
12
14
|
export { KYOGIJO_ATHLETICS_STYLE, KYOGIJO_TRACK_STYLE } from "./athletics.style.js";
|
|
13
15
|
export { KYOGIJO_SKATING_STYLE } from "./skating.style.js";
|
|
16
|
+
export { KYOGIJO_BUDO_STYLE } from "./budo.style.js";
|
|
17
|
+
export { dojo, drawDojo } from "./budo/dojo.api.js";
|
|
14
18
|
export { rampColour } from "./layers.marks.js";
|
|
15
19
|
export { HEAT_RAMPS, HEAT_RAMP_NAMES } from "./heat.colour.js";
|
|
16
20
|
export { ZONE_SETS, ZONE_SET_IDS } from "./heat.zones.js";
|
|
@@ -20,6 +24,8 @@ export { HARDWOOD_SMALL, KYOGIJO_HARDWOOD_STYLE } from "./hardwood.js";
|
|
|
20
24
|
export { KYOGIJO_CROWD_STYLE } from "./crowd.draw.js";
|
|
21
25
|
export { GRIDIRON_GROUNDS, WALL_SEATS, outlinePath, outlinePoints } from "./crowd.js";
|
|
22
26
|
export { KYOGIJO_MARK_STYLE } from "./mark.js";
|
|
27
|
+
export { DRIVE_CODES, readSituation, situationText } from "./situation.js";
|
|
28
|
+
export { KYOGIJO_SITUATION_STYLE } from "./situation.style.js";
|
|
23
29
|
export { KYOGIJO_PAGEANT_MOTION, KYOGIJO_PAGEANT_STYLE } from "./pageant.style.js";
|
|
24
30
|
export { KYOGIJO_POOL_STYLE } from "./pool.style.js";
|
|
25
31
|
export { KYOGIJO_CURLING_STYLE, KYOGIJO_HEAT_STYLE, KYOGIJO_NOTE_STYLE, KYOGIJO_STYLE, KYOGIJO_TEAM_STYLE, KYOGIJO_WALLS_STYLE } from "./style.js";
|
|
@@ -30,6 +36,7 @@ export { abbreviate, capitals, fitLines, textWidth } from "./text.js";
|
|
|
30
36
|
export { PARKS, PARK_IDS, fenceFor, parkById, parkByName, parkByWikidata, parkNameIn, parkOfficialName, parkPointsIn, parkQuirksIn, parkSourceUrl, parkUnit, parkWallsIn, parksByName } from "./parks.js";
|
|
31
37
|
export { officialName, plainName } from "./names.js";
|
|
32
38
|
export { ERA_CURRENT, ERA_SOURCES, ERA_SPORTS, eraChanges, eraRange, eraStates, footballIn, rulesFor, seasonLabel } from "./eras.js";
|
|
39
|
+
export { ARENA_IDS, ARENAS, arenaById, arenaByName, arenaByWikidata, arenaCourtIn, arenaNameIn, arenaOfficialName, arenaRinkIn, arenaSourceUrl, arenasByName } from "./arenas.js";
|
|
33
40
|
export { GROUND_IDS, GROUNDS, groundById, groundByName, groundByWikidata, groundNameIn, groundOfficialName, groundSourceUrl, groundsByName, groundsHosting } from "./grounds.js";
|
|
34
41
|
export { AFL_GROUNDS, FAMILY_OF, LEAGUES, LEAGUE_SOURCES, VARIANTS, chooseLeague, hasHistory, leagueAt, leagueById, leagueChanges, leagueFigures, leagueIds, leagueSeason, leagueSize } from "./leagues.js";
|
|
35
42
|
export { SURFACE_UNITS, UNITS, convertLength, isUnit } from "./units.js";
|
package/dist/layers-entry.d.ts
CHANGED
|
@@ -13,7 +13,8 @@ export { KYOGIJO_HEAT_STYLE } from "./style.ts";
|
|
|
13
13
|
export type { ArrowsLayer, Comet, Layer, LayerBase, LayerKind, LayerTeam, LineDatum, LineStyle, LinesLayer, MarkDatum, MarkShape, OutcomeStyle, Paint, PointDatum, PointStyle, PointsLayer, Scale, TableOptions, TextDatum, TextLayer, TextStyle } from "./layers.types.ts";
|
|
14
14
|
export { KYOGIJO_TEAM_STYLE } from "./style.ts";
|
|
15
15
|
export { FORMATIONS, FORMATION_IDS, POSITION_NAMES, formationById, formationsOf, positionName } from "./formations.ts";
|
|
16
|
+
export { LINEUP_CODES } from "./lineup.codes.ts";
|
|
16
17
|
export type { Named } from "./formations.ts";
|
|
17
18
|
export { clipNearer, convexHull, delaunay, neighbours, polygonArea, polygonCentroid, triangulationEdges, voronoiCells } from "./team.geometry.ts";
|
|
18
19
|
export type { Pt, Triangulation } from "./team.geometry.ts";
|
|
19
|
-
export type { DelaunayLayer, FlowLayer, Formation, FormationLayer, FormationPlayer, FormationPosition, FormationSport, HullLayer, MoveDatum, NetworkLayer, NetworkNode, PassDatum, PlayerDatum, SonarLayer, VoronoiLayer } from "./team.types.ts";
|
|
20
|
+
export type { DelaunayLayer, FlowLayer, Formation, FormationLayer, FormationPlayer, FormationPosition, FormationSport, HullLayer, LineupLayer, LineupPlayer, MoveDatum, NetworkLayer, NetworkNode, PassDatum, PlayerDatum, SonarLayer, VoronoiLayer } from "./team.types.ts";
|
package/dist/layers-entry.js
CHANGED
|
@@ -8,4 +8,5 @@ export { ZONE_SETS, ZONE_SET_IDS, buildZoneSet } from "./heat.zones.js";
|
|
|
8
8
|
export { KYOGIJO_HEAT_STYLE } from "./style.js";
|
|
9
9
|
export { KYOGIJO_TEAM_STYLE } from "./style.js";
|
|
10
10
|
export { FORMATIONS, FORMATION_IDS, POSITION_NAMES, formationById, formationsOf, positionName } from "./formations.js";
|
|
11
|
+
export { LINEUP_CODES } from "./lineup.codes.js";
|
|
11
12
|
export { clipNearer, convexHull, delaunay, neighbours, polygonArea, polygonCentroid, triangulationEdges, voronoiCells } from "./team.geometry.js";
|
package/dist/layers.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Env } from "./layers.env.ts";
|
|
1
2
|
import type { Layer, OutcomeStyle, TableOptions } from "./layers.types.ts";
|
|
2
3
|
import type { Box, ScoreOptions, SurfaceOptions } from "./types.ts";
|
|
3
4
|
/**
|
|
@@ -11,7 +12,7 @@ export interface RenderedLayers {
|
|
|
11
12
|
summaries: string[];
|
|
12
13
|
}
|
|
13
14
|
/** The layers of a drawing as markup, and a sentence for each. `turned` says whether the surface group is turned a quarter. */
|
|
14
|
-
export declare function renderLayers(o: SurfaceOptions | ScoreOptions, layers: readonly Layer[] | undefined, turned?: boolean, range?: Box, upright?: number): RenderedLayers;
|
|
15
|
+
export declare function renderLayers(o: SurfaceOptions | ScoreOptions, layers: readonly Layer[] | undefined, turned?: boolean, range?: Box, upright?: number, zone?: Env["zone"]): RenderedLayers;
|
|
15
16
|
/**
|
|
16
17
|
* The layers of a drawing as one SVG group, in the surface's own frame, for a caller who composes the drawing's parts. Put it inside the
|
|
17
18
|
* surface's group (the one with the quarter turn, when the drawing is tall) and the marks lie on the surface, cut to its outline, with
|
package/dist/layers.env.d.ts
CHANGED
|
@@ -32,7 +32,16 @@ export interface Env {
|
|
|
32
32
|
home?: string;
|
|
33
33
|
away?: string;
|
|
34
34
|
};
|
|
35
|
+
/** Whether the layer being drawn writes `data-mark-id`, `data-index` and `data-zone` on its marks: set for each layer by `renderLayers`. */
|
|
36
|
+
marks: boolean;
|
|
37
|
+
/** The finest zone of the surface a place (feet, the drawing's wide frame) lies in, by id: what a mark carries as `data-zone`. `undefined` where the sport has none there. */
|
|
38
|
+
zone: (x: number, y: number) => string | undefined;
|
|
35
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* The data attributes every mark carries, so that one listener on the drawing can link a mark to a table: `data-mark-id` (the id the caller gave the datum, else its index),
|
|
42
|
+
* `data-index` (its place in the layer's data) and `data-zone` (the zone it lies in, from `zoneAt`'s rules). The place is in feet in the drawing's wide frame.
|
|
43
|
+
*/
|
|
44
|
+
export declare function markAttrs(env: Env, id: unknown, index: number, at?: readonly [number, number], name?: string): string;
|
|
36
45
|
/** What a layer made. */
|
|
37
46
|
export interface Made {
|
|
38
47
|
/** The elements of the layer, and its gradients as `defs`. */
|
|
@@ -71,4 +80,4 @@ export declare function place(layer: LayerBase, env: Env, points: readonly P[],
|
|
|
71
80
|
/** The inverse of `place`: places on the surface, in feet, as the layer's own coordinates (its frame and unit). */
|
|
72
81
|
export declare function placeBack(layer: LayerBase, env: Env, points: readonly P[], unit: Unit): P[];
|
|
73
82
|
export declare function newMade(): Made;
|
|
74
|
-
export declare function envFor(o: SurfaceOptions | ScoreOptions, turned: boolean | undefined, range?: Box, upright?: number): Env;
|
|
83
|
+
export declare function envFor(o: SurfaceOptions | ScoreOptions, turned: boolean | undefined, range?: Box, upright?: number, zone?: Env["zone"]): Env;
|
package/dist/layers.env.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// What every kind of data layer is drawn against: the drawing's id, its unit and outline, the words, and what a layer made. Kept apart
|
|
2
2
|
// from layers.ts so that the heat maps, which are written in files of their own, can use it without importing the file that imports them.
|
|
3
|
-
import { safeLogo } from "./
|
|
3
|
+
import { safeLogo } from "./logo.js";
|
|
4
|
+
import { esc } from "./format.js";
|
|
4
5
|
import { drawingId, isPortrait, lengthUnit } from "./common.js";
|
|
5
6
|
import { fromSurface, toSurface } from "./frames.js";
|
|
7
|
+
import { zoneResolver } from "./rules.js";
|
|
6
8
|
import "./frames.providers.js";
|
|
7
9
|
import { chooseLeague } from "./leagues.js";
|
|
8
10
|
import { frameSizeOf, outlineOf } from "./outline.js";
|
|
@@ -12,6 +14,32 @@ export const isNum = (value) => typeof value === "number" && Number.isFinite(val
|
|
|
12
14
|
export const clamp01 = (value) => Math.max(0, Math.min(1, value));
|
|
13
15
|
export const own = (table, key) => Object.prototype.hasOwnProperty.call(table, key);
|
|
14
16
|
export const opacityOf = (value) => (isNum(value) ? clamp01(value) : undefined);
|
|
17
|
+
/** The zone of a drawing's marks, made when the first mark asks: a surface the rules cannot be made for (a special game) has none. */
|
|
18
|
+
function zonesOf(o) {
|
|
19
|
+
let resolver;
|
|
20
|
+
return (x, y) => {
|
|
21
|
+
if (resolver === undefined) {
|
|
22
|
+
try {
|
|
23
|
+
resolver = o.host !== undefined ? () => undefined : zoneResolver(o.sport, o);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
resolver = () => undefined;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return resolver(x, y);
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The data attributes every mark carries, so that one listener on the drawing can link a mark to a table: `data-mark-id` (the id the caller gave the datum, else its index),
|
|
34
|
+
* `data-index` (its place in the layer's data) and `data-zone` (the zone it lies in, from `zoneAt`'s rules). The place is in feet in the drawing's wide frame.
|
|
35
|
+
*/
|
|
36
|
+
export function markAttrs(env, id, index, at, name = "data-zone") {
|
|
37
|
+
if (!env.marks)
|
|
38
|
+
return "";
|
|
39
|
+
const given = typeof id === "string" && id !== "" ? id : typeof id === "number" && Number.isFinite(id) ? String(id) : String(index);
|
|
40
|
+
const zone = at === undefined ? undefined : env.zone(at[0], at[1]);
|
|
41
|
+
return ` data-mark-id="${esc(given)}" data-index="${index}"${zone === undefined ? "" : ` ${name}="${esc(zone)}"`}`;
|
|
42
|
+
}
|
|
15
43
|
export const toArray = (value, what) => {
|
|
16
44
|
if (!Array.isArray(value))
|
|
17
45
|
throw new TypeError(`${what} needs data: a list of marks`);
|
|
@@ -60,7 +88,7 @@ export function placeBack(layer, env, points, unit) {
|
|
|
60
88
|
export function newMade() {
|
|
61
89
|
return { marks: "", defs: "", style: "", attr: "", opacity: undefined, drawn: 0, skipped: 0, outcomes: new Map(), teams: new Map(), low: Infinity, high: -Infinity };
|
|
62
90
|
}
|
|
63
|
-
export function envFor(o, turned, range, upright) {
|
|
91
|
+
export function envFor(o, turned, range, upright, zone) {
|
|
64
92
|
const language = o.language === "ja" ? "ja" : "en";
|
|
65
93
|
const outline = outlineOf(o);
|
|
66
94
|
const teams = o;
|
|
@@ -76,6 +104,8 @@ export function envFor(o, turned, range, upright) {
|
|
|
76
104
|
cropped: range !== undefined,
|
|
77
105
|
base: Math.max((range ?? outline.box).w, (range ?? outline.box).h) * 0.013,
|
|
78
106
|
words: KYOGIJO_STRINGS[language],
|
|
79
|
-
logos: { home: safeLogo(teams.home?.logo), away: safeLogo(teams.away?.logo) },
|
|
107
|
+
logos: { home: safeLogo(teams.home?.logo, { color: teams.home?.color, accent: teams.home?.textColor }), away: safeLogo(teams.away?.logo, { color: teams.away?.color, accent: teams.away?.textColor }) },
|
|
108
|
+
marks: o.marks === true || o.pointer === true,
|
|
109
|
+
zone: zone ?? zonesOf(o),
|
|
80
110
|
};
|
|
81
111
|
}
|
package/dist/layers.js
CHANGED
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
// table that stands for the drawing. Every mark is a plain SVG element in the drawing's own frame, so the same options always give
|
|
4
4
|
// the same string. Written for this package; mplsoccer and hockey_rink were read for the list of charts to match, and nothing of
|
|
5
5
|
// either is used.
|
|
6
|
-
import { safeColour
|
|
6
|
+
import { safeColour } from "./colour.js";
|
|
7
|
+
import { withEmblems } from "./emblems-source.js";
|
|
8
|
+
import { safeLogo } from "./logo.js";
|
|
7
9
|
import { FRAMES } from "./frames.js";
|
|
8
10
|
import { KYOGIJO_HEAT_STYLE, KYOGIJO_TEAM_STYLE } from "./style.js";
|
|
9
11
|
import { drawTeam, isTeamLayer, teamTables } from "./team.layers.js";
|
|
10
12
|
import { drawHeat, drawLegend, heatTable } from "./heat.js";
|
|
11
|
-
import { clamp01, envFor, isNum, newMade, opacityOf, own, place, toArray, unitOfLayer } from "./layers.env.js";
|
|
13
|
+
import { clamp01, envFor, isNum, markAttrs, newMade, opacityOf, own, place, toArray, unitOfLayer } from "./layers.env.js";
|
|
12
14
|
import { safeClass } from "./common.js";
|
|
13
15
|
import { esc, num } from "./format.js";
|
|
14
16
|
import { curveBetween, curvePath, headPath, isPolygon, polylinePath, rampColour, shapePath, taperPath, wavePath, } from "./layers.marks.js";
|
|
@@ -136,7 +138,7 @@ function drawPoints(layer, env) {
|
|
|
136
138
|
const w = (isNum(d.size) && d.size > 0 ? d.size * k : sizeFn === undefined ? fixed : Math.max(0.05, sizeFn(d.value) * k)) * (outcome.scale ?? 1);
|
|
137
139
|
const { cls, css } = colourAttrs(colourFor(style.fill, d, NEUTRAL, domain), layerExpr, NEUTRAL);
|
|
138
140
|
const classes = `${cls}${outcome.hollow === true ? `${cls === "" ? "" : " "}ky-hol` : ""}`;
|
|
139
|
-
const open = attrs(classes, css, opacityOf(d.opacity));
|
|
141
|
+
const open = attrs(classes, css, opacityOf(d.opacity)) + markAttrs(env, d.id, i, [x, y]);
|
|
140
142
|
const role = d.team === "home" ? "home" : d.team === "away" ? "away" : undefined;
|
|
141
143
|
const logo = shape === "logo" ? safeLogo(d.logo) ?? (role === undefined ? undefined : safeLogo(style.logos?.[role]) ?? env.logos[role]) : undefined;
|
|
142
144
|
if (logo !== undefined) {
|
|
@@ -258,13 +260,15 @@ function drawLines(layer, env, index) {
|
|
|
258
260
|
const headEl = head === "" ? "" : `<path class="${headKind === "open" ? "ky-ln" : "ky-ah"}" d="${head}"${headKind === "open" ? ` stroke-width="${num(w)}"` : ""}/>`;
|
|
259
261
|
const title = typeof d.title === "string" && d.title !== "" ? `<title>${esc(d.title)}</title>` : "";
|
|
260
262
|
const opacity = opacityOf(d.opacity);
|
|
263
|
+
// Where it starts is its zone; where it ends is `data-zone-end`.
|
|
264
|
+
const marks = env.marks ? markAttrs(env, d.id, i, first) + (env.zone(last[0], last[1]) === undefined ? "" : ` data-zone-end="${esc(env.zone(last[0], last[1]))}"`) : "";
|
|
261
265
|
// A line with a head is a group (its colour and opacity on the group); a line alone carries them itself.
|
|
262
266
|
const wrap = headEl !== "";
|
|
263
267
|
const pathClass = [shaftClass, wrap ? "" : cls].filter((c) => c !== "").join(" ");
|
|
264
268
|
const pathStyle = [wrap ? "" : css, gradient].filter((c) => c !== "").join(";");
|
|
265
|
-
const pathOpen = `${attrs(pathClass, pathStyle, wrap ? undefined : opacity)} d="${shaft}"${tapered === undefined ? strokeWidth + dashes : ""}`;
|
|
269
|
+
const pathOpen = `${attrs(pathClass, pathStyle, wrap ? undefined : opacity)}${wrap ? "" : marks} d="${shaft}"${tapered === undefined ? strokeWidth + dashes : ""}`;
|
|
266
270
|
if (wrap)
|
|
267
|
-
out.push(`<g${attrs(cls, css, opacity)}>${title}<path${pathOpen}/>${headEl}</g>`);
|
|
271
|
+
out.push(`<g${attrs(cls, css, opacity)}${marks}>${title}<path${pathOpen}/>${headEl}</g>`);
|
|
268
272
|
else
|
|
269
273
|
out.push(title === "" ? `<path${pathOpen}/>` : `<path${pathOpen}>${title}</path>`);
|
|
270
274
|
});
|
|
@@ -309,12 +313,17 @@ function drawText(layer, env) {
|
|
|
309
313
|
// The letters are turned back by the quarter the surface was turned, so that they read upright, and by the caller's own turn on top.
|
|
310
314
|
const angle = env.back + (isNum(d.rotate) ? d.rotate : 0);
|
|
311
315
|
const classes = ["ky-lt", style.halo === false ? "ky-nh" : "", cls].filter((c) => c !== "").join(" ");
|
|
312
|
-
const open = `${attrs(classes, `${s === size ? "" : `font-size:${num(s)}px`}${s !== size && css !== "" ? ";" : ""}${css}`, opacityOf(d.opacity))}${anchor === base ? "" : ` text-anchor="${anchor}"`} x="${num(x)}" y="${num(y + s * 0.36)}"${angle === 0 ? "" : ` transform="rotate(${num(angle)} ${num(x)} ${num(y)})"`}`;
|
|
316
|
+
const open = `${attrs(classes, `${s === size ? "" : `font-size:${num(s)}px`}${s !== size && css !== "" ? ";" : ""}${css}`, opacityOf(d.opacity))}${markAttrs(env, d.id, i, [x, y])}${anchor === base ? "" : ` text-anchor="${anchor}"`} x="${num(x)}" y="${num(y + s * 0.36)}"${angle === 0 ? "" : ` transform="rotate(${num(angle)} ${num(x)} ${num(y)})"`}`;
|
|
313
317
|
out.push(`<text${open}>${esc(String(d.text))}${typeof d.title === "string" && d.title !== "" ? `<title>${esc(d.title)}</title>` : ""}</text>`);
|
|
314
318
|
});
|
|
315
319
|
made.marks = out.join("");
|
|
316
320
|
return made;
|
|
317
321
|
}
|
|
322
|
+
/**
|
|
323
|
+
* True when a datum of the layer has an `id`: the caller means to find its marks again. Not for the team layers, whose data have always had an `id` of their own (the player's, for a label and a table),
|
|
324
|
+
* so that a drawing made before the marks had ids is the same text now.
|
|
325
|
+
*/
|
|
326
|
+
const hasIds = (layer) => !isTeamLayer(layer) && Array.isArray(layer.data) && (layer.data).some((d) => typeof d === "object" && d !== null && d.id !== undefined);
|
|
318
327
|
const plural = (words, kind, n) => words[`${kind === "lines" ? "line" : kind === "arrows" ? "arrow" : kind === "text" ? "text" : "point"}${n === 1 ? "One" : "Many"}`];
|
|
319
328
|
const tidy = (text) => text.replace(/[.。]\s*$/, "");
|
|
320
329
|
/** A list of counts, `goal 3, shot 21`, the most first. */
|
|
@@ -348,12 +357,16 @@ function summarise(layer, made, words, stop, gap) {
|
|
|
348
357
|
return { title, description: parts.join(gap) };
|
|
349
358
|
}
|
|
350
359
|
/** The layers of a drawing as markup, and a sentence for each. `turned` says whether the surface group is turned a quarter. */
|
|
351
|
-
export function renderLayers(o, layers, turned, range, upright) {
|
|
360
|
+
export function renderLayers(o, layers, turned, range, upright, zone) {
|
|
361
|
+
return withEmblems(o.emblems, () => renderedLayers(o, layers, turned, range, upright, zone));
|
|
362
|
+
}
|
|
363
|
+
function renderedLayers(o, layers, turned, range, upright, zone) {
|
|
352
364
|
if (layers === undefined || layers.length === 0)
|
|
353
365
|
return { svg: "", summaries: [] };
|
|
354
366
|
if (!Array.isArray(layers))
|
|
355
367
|
throw new TypeError("layers is a list of layers");
|
|
356
|
-
const env = envFor(o, turned, range, upright);
|
|
368
|
+
const env = envFor(o, turned, range, upright, zone);
|
|
369
|
+
const markedBy = env.marks;
|
|
357
370
|
const clipId = `${env.id}-lc`;
|
|
358
371
|
const { stop, gap } = env.words.said;
|
|
359
372
|
const said = [];
|
|
@@ -366,6 +379,8 @@ export function renderLayers(o, layers, turned, range, upright) {
|
|
|
366
379
|
layers.forEach((layer, index) => {
|
|
367
380
|
if (typeof layer !== "object" || layer === null)
|
|
368
381
|
throw new TypeError(`layer ${index} is not a layer`);
|
|
382
|
+
// The marks are written with their ids, indexes and zones when the layer or the drawing asks, or when the caller gave a datum an id of its own.
|
|
383
|
+
env.marks = typeof layer.marks === "boolean" ? layer.marks : markedBy || hasIds(layer);
|
|
369
384
|
const name = safeClass(layer.id).replace(/ /g, "-");
|
|
370
385
|
const gid = name === "" ? `${env.id}-l${index}` : `${env.id}-${name}`;
|
|
371
386
|
const finish = (made) => {
|
|
@@ -375,7 +390,8 @@ export function renderLayers(o, layers, turned, range, upright) {
|
|
|
375
390
|
return;
|
|
376
391
|
const { title, description } = summarise(layer, made, env.words.layers, stop, gap);
|
|
377
392
|
said[index] = description === "" ? `${tidy(title)}${stop}` : `${tidy(title)}${stop}${gap}${description}`;
|
|
378
|
-
|
|
393
|
+
// A lineup is not cut to the outline unless it is asked to be: a fielder at the foul line or a catcher behind the plate would lose half a jersey.
|
|
394
|
+
const clip = layer.kind !== "legend" && (layer.clip === "surface" || (layer.clip !== "none" && layer.kind !== "lineup"));
|
|
379
395
|
clipped = clipped || clip;
|
|
380
396
|
const cls = made.cls ?? (layer.kind === "points" ? "ky-pts" : layer.kind === "text" ? "ky-txt" : "ky-lns");
|
|
381
397
|
// Cropped to a range, a clipped layer is also cut to the range: its group is held by a group with the range's clip.
|
|
@@ -403,6 +419,7 @@ export function renderLayers(o, layers, turned, range, upright) {
|
|
|
403
419
|
return;
|
|
404
420
|
case "network":
|
|
405
421
|
case "formation":
|
|
422
|
+
case "lineup":
|
|
406
423
|
case "voronoi":
|
|
407
424
|
case "delaunay":
|
|
408
425
|
case "hull":
|
|
@@ -415,7 +432,7 @@ export function renderLayers(o, layers, turned, range, upright) {
|
|
|
415
432
|
slots[index] = () => finish(drawLegend(layer, env, gid, known));
|
|
416
433
|
return;
|
|
417
434
|
default:
|
|
418
|
-
throw new TypeError(`layer ${index} has the kind "${String(layer.kind)}": use points, lines, arrows, text, network, formation, voronoi, delaunay, hull, flow, sonar, heatmap, hexbin, zones, contour or legend`);
|
|
435
|
+
throw new TypeError(`layer ${index} has the kind "${String(layer.kind)}": use points, lines, arrows, text, network, formation, lineup, voronoi, delaunay, hull, flow, sonar, heatmap, hexbin, zones, contour or legend`);
|
|
419
436
|
}
|
|
420
437
|
});
|
|
421
438
|
slots.forEach((later) => later?.());
|
|
@@ -491,7 +508,7 @@ export function layerTable(layers, options = {}) {
|
|
|
491
508
|
return render(heatTable(layer, surfaceEnv), layer.kind);
|
|
492
509
|
if (surfaceEnv !== undefined && isTeamLayer(layer))
|
|
493
510
|
return teamTables(layer, surfaceEnv).map((t) => render(t, layer.kind)).join("");
|
|
494
|
-
const data = layer.kind === "formation" ? (layer.data ?? []) : toArray(layer.data, `layer ${index}`);
|
|
511
|
+
const data = layer.kind === "formation" ? (layer.data ?? []) : layer.kind === "lineup" ? (layer.players ?? []) : toArray(layer.data, `layer ${index}`);
|
|
495
512
|
const columns = [];
|
|
496
513
|
const has = (key) => data.some((d) => typeof d === "object" && d !== null && d[key] !== undefined && d[key] !== null);
|
|
497
514
|
const t = words.team;
|
|
@@ -501,6 +518,8 @@ export function layerTable(layers, options = {}) {
|
|
|
501
518
|
columns.push([t.tableFrom, "from", (d) => d.from], [t.tableTo, "to", (d) => d.to]);
|
|
502
519
|
if (layer.kind === "formation")
|
|
503
520
|
columns.push([t.tablePosition, "position", (d) => d.position], [t.tableNumber, "number", (d) => d.number], [t.tableName, "name", (d) => d.name]);
|
|
521
|
+
else if (layer.kind === "lineup")
|
|
522
|
+
columns.push([t.tablePosition, "pos", (d) => d.pos], [t.tableNumber, "number", (d) => d.number], [t.tableName, "name", (d) => d.name]);
|
|
504
523
|
else {
|
|
505
524
|
columns.push([w.tableX, "x", (d) => d.x]);
|
|
506
525
|
columns.push([w.tableY, "y", (d) => d.y]);
|
package/dist/layers.types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ScoreOptions, SurfaceOptions } from "./types.ts";
|
|
2
2
|
import type { Frame, Attacking, Landmark, SurfaceSize } from "./frames.ts";
|
|
3
3
|
import type { ContourLayer, HeatmapLayer, HexbinLayer, LegendLayer, ZonesLayer } from "./heat.types.ts";
|
|
4
|
-
import type { DelaunayLayer, FlowLayer, FormationLayer, HullLayer, NetworkLayer, SonarLayer, VoronoiLayer } from "./team.types.ts";
|
|
4
|
+
import type { DelaunayLayer, FlowLayer, FormationLayer, HullLayer, LineupLayer, NetworkLayer, SonarLayer, VoronoiLayer } from "./team.types.ts";
|
|
5
5
|
import type { Unit } from "./units.ts";
|
|
6
6
|
/** The shapes a point can be drawn as. A team's logo is `logo`. */
|
|
7
7
|
export type MarkShape = "circle" | "square" | "triangle" | "diamond" | "cross" | "x" | "star";
|
|
@@ -45,6 +45,8 @@ export interface OutcomeStyle {
|
|
|
45
45
|
}
|
|
46
46
|
/** What every mark can carry. */
|
|
47
47
|
export interface MarkDatum {
|
|
48
|
+
/** Your id for the mark: written on it as `data-mark-id`, so that a listener can link it to a row of your table. The mark's index is written when there is none. */
|
|
49
|
+
id?: string | number;
|
|
48
50
|
/** The tooltip, and what a screen reader reads for the mark. */
|
|
49
51
|
title?: string;
|
|
50
52
|
/** `home`, `away` or another team. */
|
|
@@ -189,6 +191,11 @@ export interface LayerBase {
|
|
|
189
191
|
clip?: "surface" | "none";
|
|
190
192
|
/** Hide the layer. It is still in `layerTable`. */
|
|
191
193
|
hidden?: boolean;
|
|
194
|
+
/**
|
|
195
|
+
* Write `data-mark-id`, `data-index` and `data-zone` on every mark of the layer (and draw each cell of a heat map or hexbin as a path of its own), so that one listener can link a mark to a table.
|
|
196
|
+
* Off by default, to keep a drawing compact; on by itself when a datum has an `id`, and when the drawing is made with `marks: true` or `pointer: true`. `false` turns it off for this layer.
|
|
197
|
+
*/
|
|
198
|
+
marks?: boolean;
|
|
192
199
|
}
|
|
193
200
|
export interface PointsLayer extends LayerBase {
|
|
194
201
|
kind: "points";
|
|
@@ -211,7 +218,7 @@ export interface TextLayer extends LayerBase {
|
|
|
211
218
|
style?: TextStyle;
|
|
212
219
|
}
|
|
213
220
|
/** A layer of data on a surface. */
|
|
214
|
-
export type Layer = PointsLayer | LinesLayer | ArrowsLayer | TextLayer | HeatmapLayer | HexbinLayer | ZonesLayer | ContourLayer | LegendLayer | NetworkLayer | FormationLayer | VoronoiLayer | DelaunayLayer | HullLayer | FlowLayer | SonarLayer;
|
|
221
|
+
export type Layer = PointsLayer | LinesLayer | ArrowsLayer | TextLayer | HeatmapLayer | HexbinLayer | ZonesLayer | ContourLayer | LegendLayer | NetworkLayer | FormationLayer | LineupLayer | VoronoiLayer | DelaunayLayer | HullLayer | FlowLayer | SonarLayer;
|
|
215
222
|
/** The kinds of layer. */
|
|
216
223
|
export type LayerKind = Layer["kind"];
|
|
217
224
|
/** What `layerTable` takes. */
|