@johnmorrisdotca/kyogijo-stadiums 0.4.0 → 0.5.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 +75 -0
- package/NOTICE.md +4 -0
- package/README.md +71 -16
- package/dist/annotate.js +1 -1
- package/dist/athletics/describe.d.ts +8 -0
- package/dist/athletics/describe.js +41 -0
- package/dist/athletics/events.d.ts +17 -0
- package/dist/athletics/events.js +48 -0
- package/dist/athletics/facilities.d.ts +80 -0
- package/dist/athletics/facilities.js +176 -0
- package/dist/athletics/infield.d.ts +79 -0
- package/dist/athletics/infield.js +166 -0
- package/dist/athletics/layout.d.ts +13 -0
- package/dist/athletics/layout.js +98 -0
- package/dist/athletics/oval.d.ts +57 -0
- package/dist/athletics/oval.js +116 -0
- package/dist/athletics/plan.d.ts +97 -0
- package/dist/athletics/plan.js +355 -0
- package/dist/athletics/races.d.ts +102 -0
- package/dist/athletics/races.js +355 -0
- package/dist/athletics/steeplechase.d.ts +72 -0
- package/dist/athletics/steeplechase.js +196 -0
- package/dist/athletics/stencil.d.ts +13 -0
- package/dist/athletics/stencil.js +85 -0
- package/dist/athletics/track.d.ts +54 -0
- package/dist/athletics/track.js +105 -0
- package/dist/athletics/types.d.ts +77 -0
- package/dist/athletics/types.js +1 -0
- package/dist/athletics-entry.d.ts +17 -0
- package/dist/athletics-entry.js +11 -0
- package/dist/athletics.style.d.ts +16 -0
- package/dist/athletics.style.js +51 -0
- package/dist/atlas-entry.d.ts +4 -2
- package/dist/atlas-entry.js +3 -2
- package/dist/atlas.d.ts +83 -7
- package/dist/atlas.js +108 -8
- package/dist/charts-entry.d.ts +6 -1
- package/dist/charts-entry.js +3 -0
- package/dist/charts.athletics.d.ts +183 -0
- package/dist/charts.athletics.js +455 -0
- package/dist/charts.curling.heat.d.ts +24 -0
- package/dist/charts.curling.heat.js +116 -0
- package/dist/charts.curling.js +14 -3
- package/dist/charts.pool.d.ts +67 -0
- package/dist/charts.pool.js +76 -0
- package/dist/charts.skating.d.ts +204 -0
- package/dist/charts.skating.js +426 -0
- package/dist/charts.types.d.ts +53 -1
- package/dist/court.d.ts +85 -2
- package/dist/court.js +102 -7
- package/dist/court.more.d.ts +46 -0
- package/dist/court.more.js +219 -0
- package/dist/courts.style.d.ts +14 -2
- package/dist/courts.style.js +51 -4
- package/dist/crowd.d.ts +154 -0
- package/dist/crowd.draw.d.ts +17 -0
- package/dist/crowd.draw.js +198 -0
- package/dist/crowd.js +465 -0
- package/dist/crowd.park.d.ts +19 -0
- package/dist/crowd.park.js +153 -0
- package/dist/curling.stats.d.ts +271 -0
- package/dist/curling.stats.js +301 -0
- package/dist/draw.d.ts +16 -0
- package/dist/draw.js +318 -35
- package/dist/element-entry.d.ts +1 -1
- package/dist/element-entry.js +1 -1
- package/dist/element.d.ts +13 -2
- package/dist/element.js +77 -3
- package/dist/features.js +131 -0
- package/dist/fields.kit.d.ts +2 -2
- package/dist/fields.types.d.ts +18 -4
- package/dist/frames.providers.js +63 -8
- package/dist/geojson.js +3 -0
- package/dist/geometry-entry.d.ts +2 -1
- package/dist/geometry-entry.js +2 -1
- package/dist/geometry.d.ts +20 -0
- package/dist/geometry.js +78 -1
- package/dist/grounds.d.ts +4 -0
- package/dist/grounds.data.js +12 -0
- package/dist/hardwood.d.ts +31 -0
- package/dist/hardwood.js +157 -0
- package/dist/heat.js +4 -3
- package/dist/heat.types.d.ts +5 -0
- package/dist/heat.zones.d.ts +2 -2
- package/dist/heat.zones.js +154 -6
- package/dist/homeside.js +17 -0
- package/dist/index.d.ts +16 -2
- package/dist/index.js +10 -1
- package/dist/layers.d.ts +1 -1
- package/dist/layers.env.d.ts +3 -1
- package/dist/layers.env.js +4 -2
- package/dist/layers.js +4 -4
- package/dist/leagues/athletics.d.ts +63 -0
- package/dist/leagues/athletics.js +87 -0
- package/dist/leagues/courts.d.ts +269 -4
- package/dist/leagues/courts.js +155 -1
- package/dist/leagues/skating.d.ts +145 -0
- package/dist/leagues/skating.js +73 -0
- package/dist/leagues/sources.js +20 -0
- package/dist/leagues/types.d.ts +1 -1
- package/dist/leagues-entry.d.ts +4 -2
- package/dist/leagues-entry.js +2 -1
- package/dist/leagues.d.ts +14 -4
- package/dist/leagues.js +146 -5
- package/dist/look.d.ts +3 -3
- package/dist/look.js +39 -6
- package/dist/outline.d.ts +1 -1
- package/dist/outline.js +30 -2
- package/dist/pageant.d.ts +120 -0
- package/dist/pageant.draw.d.ts +21 -0
- package/dist/pageant.draw.js +171 -0
- package/dist/pageant.js +207 -0
- package/dist/pageant.style.d.ts +8 -0
- package/dist/pageant.style.js +42 -0
- package/dist/png.d.ts +8 -1
- package/dist/png.js +21 -1
- package/dist/pool.d.ts +176 -0
- package/dist/pool.figures.d.ts +304 -0
- package/dist/pool.figures.js +144 -0
- package/dist/pool.js +304 -0
- package/dist/pool.kit.d.ts +48 -0
- package/dist/pool.kit.js +141 -0
- package/dist/pool.labels.d.ts +20 -0
- package/dist/pool.labels.js +257 -0
- package/dist/pool.race.d.ts +65 -0
- package/dist/pool.race.js +140 -0
- package/dist/pool.replay.d.ts +46 -0
- package/dist/pool.replay.js +127 -0
- package/dist/pool.section.d.ts +13 -0
- package/dist/pool.section.js +83 -0
- package/dist/pool.style.d.ts +20 -0
- package/dist/pool.style.js +169 -0
- package/dist/pool.types.d.ts +145 -0
- package/dist/pool.types.js +3 -0
- package/dist/pool.words.d.ts +13 -0
- package/dist/pool.words.js +101 -0
- package/dist/ranges.names.js +47 -3
- package/dist/replay-entry.d.ts +3 -0
- package/dist/replay-entry.js +2 -0
- package/dist/restyle.js +1 -1
- package/dist/score.js +70 -5
- package/dist/sheet.d.ts +3 -0
- package/dist/sheet.js +7 -3
- package/dist/skating/describe.d.ts +7 -0
- package/dist/skating/describe.js +44 -0
- package/dist/skating/events.d.ts +24 -0
- package/dist/skating/events.js +47 -0
- package/dist/skating/figure.d.ts +24 -0
- package/dist/skating/figure.js +37 -0
- package/dist/skating/long.d.ts +54 -0
- package/dist/skating/long.js +111 -0
- package/dist/skating/parts.d.ts +43 -0
- package/dist/skating/parts.js +40 -0
- package/dist/skating/plan.d.ts +55 -0
- package/dist/skating/plan.js +197 -0
- package/dist/skating/short.d.ts +47 -0
- package/dist/skating/short.js +89 -0
- package/dist/skating/track.d.ts +66 -0
- package/dist/skating/track.js +94 -0
- package/dist/skating/types.d.ts +57 -0
- package/dist/skating/types.js +3 -0
- package/dist/skating-entry.d.ts +17 -0
- package/dist/skating-entry.js +11 -0
- package/dist/skating.style.d.ts +4 -0
- package/dist/skating.style.js +24 -0
- package/dist/strings.d.ts +296 -0
- package/dist/strings.js +328 -11
- package/dist/style.d.ts +2 -0
- package/dist/style.js +11 -1
- package/dist/surfaces/artistic.d.ts +9 -0
- package/dist/surfaces/artistic.js +94 -0
- package/dist/surfaces/athletics.d.ts +16 -0
- package/dist/surfaces/athletics.js +132 -0
- package/dist/surfaces/baseball.js +15 -0
- package/dist/surfaces/basketball.floor.d.ts +27 -0
- package/dist/surfaces/basketball.floor.js +83 -0
- package/dist/surfaces/basketball.gear.d.ts +27 -0
- package/dist/surfaces/basketball.gear.js +90 -0
- package/dist/surfaces/basketball.js +43 -21
- package/dist/surfaces/curling.d.ts +16 -0
- package/dist/surfaces/curling.fold.d.ts +67 -0
- package/dist/surfaces/curling.fold.js +107 -0
- package/dist/surfaces/curling.js +37 -3
- package/dist/surfaces/dive.d.ts +9 -0
- package/dist/surfaces/dive.js +128 -0
- package/dist/surfaces/field.d.ts +7 -2
- package/dist/surfaces/field.js +15 -9
- package/dist/surfaces/hockey.js +1 -0
- package/dist/surfaces/net.d.ts +2 -1
- package/dist/surfaces/net.js +160 -15
- package/dist/surfaces/polo.d.ts +12 -0
- package/dist/surfaces/polo.js +159 -0
- package/dist/surfaces/pool.d.ts +27 -0
- package/dist/surfaces/pool.js +198 -0
- package/dist/surfaces/skating.d.ts +6 -0
- package/dist/surfaces/skating.js +62 -0
- package/dist/surfaces/soccer.js +2 -1
- package/dist/surfaces/surface.d.ts +44 -0
- package/dist/surfaces/venue.d.ts +15 -0
- package/dist/surfaces/venue.js +95 -0
- package/dist/tenants.d.ts +77 -0
- package/dist/tenants.data.d.ts +8 -0
- package/dist/tenants.data.js +945 -0
- package/dist/tenants.js +46 -0
- package/dist/turn-entry.d.ts +12 -0
- package/dist/turn-entry.js +7 -0
- package/dist/turn.camera.d.ts +105 -0
- package/dist/turn.camera.js +168 -0
- package/dist/turn.dom.d.ts +40 -0
- package/dist/turn.dom.js +351 -0
- package/dist/turn.kit.d.ts +86 -0
- package/dist/turn.kit.js +110 -0
- package/dist/turn.markup.d.ts +48 -0
- package/dist/turn.markup.js +108 -0
- package/dist/turn.model.d.ts +78 -0
- package/dist/turn.model.js +91 -0
- package/dist/turn.style.d.ts +5 -0
- package/dist/turn.style.js +55 -0
- package/dist/types.d.ts +183 -18
- package/dist/units.d.ts +1 -1
- package/dist/units.js +15 -1
- package/dist/uprights.board.d.ts +17 -0
- package/dist/uprights.board.js +59 -0
- package/dist/uprights.d.ts +37 -0
- package/dist/uprights.fields.d.ts +32 -0
- package/dist/uprights.fields.js +172 -0
- package/dist/uprights.goal.d.ts +49 -0
- package/dist/uprights.goal.js +69 -0
- package/dist/uprights.js +160 -0
- package/dist/uprights.more.d.ts +7 -0
- package/dist/uprights.more.js +183 -0
- package/dist/uprights.net.d.ts +12 -0
- package/dist/uprights.net.js +109 -0
- package/dist/uprights.netkit.d.ts +28 -0
- package/dist/uprights.netkit.js +67 -0
- package/dist/uprights.pools.d.ts +8 -0
- package/dist/uprights.pools.js +190 -0
- package/dist/uprights.rinks.d.ts +27 -0
- package/dist/uprights.rinks.js +106 -0
- package/dist/uprights.track.d.ts +50 -0
- package/dist/uprights.track.js +246 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +19 -2
package/dist/heat.zones.js
CHANGED
|
@@ -11,6 +11,12 @@ import { fill } from "./strings.js";
|
|
|
11
11
|
import { lengthUnit } from "./common.js";
|
|
12
12
|
import { courtFor, courtSize } from "./court.js";
|
|
13
13
|
import { fieldPlan } from "./fields.js";
|
|
14
|
+
import { WATER_POLO } from "./pool.figures.js";
|
|
15
|
+
import { swimPlan } from "./pool.js";
|
|
16
|
+
import { athleticsLanes, athleticsLeague } from "./athletics/plan.js";
|
|
17
|
+
import { skatingPlan } from "./skating/plan.js";
|
|
18
|
+
import { laneEdges } from "./skating/track.js";
|
|
19
|
+
import { iceRadius } from "./skating/long.js";
|
|
14
20
|
import { LEAGUES, chooseLeague, cricketOf } from "./leagues.js";
|
|
15
21
|
/** Every zone set, with the sports it is for, the source of its definition and its title. */
|
|
16
22
|
export const ZONE_SETS = Object.freeze({
|
|
@@ -24,8 +30,15 @@ export const ZONE_SETS = Object.freeze({
|
|
|
24
30
|
"baseball-spray": { sports: ["mlb"], title: "Spray zones: pull, centre, opposite by infield and outfield", source: "docs/sources.md#zone-sets" },
|
|
25
31
|
"baseball-retrosheet": { sports: ["mlb"], title: "Retrosheet hit locations as the nearest sector", source: "https://www.retrosheet.org/location.htm" },
|
|
26
32
|
"curling-house": { sports: ["curling"], title: "The house: the button, the 4-, 8- and 12-foot rings, and the free guard zone", source: "docs/sources.md#zone-sets" },
|
|
27
|
-
"net-court": { sports: ["tennis", "volleyball", "badminton", "pickleball", "tabletennis"], title: "Each side of the net: the front court and the back court, split by the court's own line", source: "docs/sources.md#zone-sets" },
|
|
28
|
-
"
|
|
33
|
+
"net-court": { sports: ["tennis", "volleyball", "badminton", "pickleball", "tabletennis", "padel", "sepaktakraw", "teqball"], title: "Each side of the net: the front court and the back court, split by the court's own line", source: "docs/sources.md#zone-sets" },
|
|
34
|
+
"wall-court": { sports: ["squash", "racquetball"], title: "The front court and the back court, split by the short line", source: "docs/sources.md#zone-sets" },
|
|
35
|
+
"roundnet-rings": { sports: ["roundnet"], title: "The no hit zone, the ring out to the serving line, and the rest of the court", source: "docs/sources.md#zone-sets" },
|
|
36
|
+
"pool-lanes": { sports: ["swimming"], title: "Lanes: each lane of the pool, the whole length of it", source: "docs/sources.md#zone-sets" },
|
|
37
|
+
"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
|
+
"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" },
|
|
39
|
+
"field-thirds": { sports: ["lacrosse", "rugby", "afl", "gaelic", "fieldhockey", "handball", "netball"], title: "Thirds: defensive, middle and attacking", source: "docs/sources.md#zone-sets" },
|
|
40
|
+
"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
|
+
"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" },
|
|
29
42
|
"cricket-ground": { sports: ["cricket"], title: "The pitch, the ground inside the fielding circle, and the outfield", source: "docs/sources.md#zone-sets" },
|
|
30
43
|
"football-pass": { sports: ["nfl", "cfl", "ifaf"], title: "Pass grid: short and deep by left, middle and right", source: "https://nflreadr.nflverse.com/articles/dictionary_pbp.html" },
|
|
31
44
|
});
|
|
@@ -346,14 +359,15 @@ function curlingZones(ctx) {
|
|
|
346
359
|
}
|
|
347
360
|
/**
|
|
348
361
|
* The court of a net sport on each side of the net: the front court, between the net and the line that the sport's own rules draw there, and the back court behind it.
|
|
349
|
-
* That line is tennis's service line (21 ft), volleyball's attack line (3 m), badminton's short service line (1.98 m)
|
|
350
|
-
*
|
|
362
|
+
* That line is tennis's service line (21 ft), volleyball's attack line (3 m; sitting volleyball's 2 m), badminton's short service line (1.98 m), pickleball's non-volley zone
|
|
363
|
+
* line (7 ft), padel's service line (6.95 m) and teqball's service line (3.5 m); beach volleyball, table tennis and sepak takraw have none, so each side is one zone. The
|
|
364
|
+
* zones are ours: the rules name the lines, not the areas.
|
|
351
365
|
*/
|
|
352
366
|
function netZones(ctx) {
|
|
353
367
|
const plan = courtFor({ sport: ctx.o.sport, league: ctx.o.league, net: ctx.o.net });
|
|
354
368
|
const { length: L, width: W } = courtSize(plan);
|
|
355
369
|
const w = ctx.words;
|
|
356
|
-
const front = plan.sport === "tennis" ? plan.figures.serviceLine : plan.sport === "volleyball" ? plan.figures.attackLine : plan.sport === "badminton" ? plan.figures.shortServiceLine : plan.sport === "pickleball" ? plan.figures.nonVolley : null;
|
|
370
|
+
const front = plan.sport === "tennis" || plan.sport === "padel" || plan.sport === "teqball" ? plan.figures.serviceLine : plan.sport === "volleyball" ? plan.figures.attackLine : plan.sport === "badminton" ? plan.figures.shortServiceLine : plan.sport === "pickleball" ? plan.figures.nonVolley : null;
|
|
357
371
|
const cx = L / 2;
|
|
358
372
|
const both = ctx.end === "both";
|
|
359
373
|
const ends = ctx.end === "both" ? ["left", "right"] : [ctx.end];
|
|
@@ -375,6 +389,37 @@ function netZones(ctx) {
|
|
|
375
389
|
}
|
|
376
390
|
return out;
|
|
377
391
|
}
|
|
392
|
+
/**
|
|
393
|
+
* A squash or racquetball court in two: the front court, from the front wall to the short line, and the back court behind it. The split is the short line's axis. The zones are
|
|
394
|
+
* ours: the rules name the lines, not the areas.
|
|
395
|
+
*/
|
|
396
|
+
function wallZones(ctx) {
|
|
397
|
+
const plan = courtFor({ sport: ctx.o.sport, league: ctx.o.league, net: ctx.o.net });
|
|
398
|
+
const { length: L, width: W } = courtSize(plan);
|
|
399
|
+
const w = ctx.words;
|
|
400
|
+
const split = plan.sport === "squash" || plan.sport === "racquetball" ? L - plan.figures.shortLine - plan.figures.lineWidth / 2 : L / 2;
|
|
401
|
+
return [rect("front-court", w.frontCourt, 0, 0, split, W, false, true), rect("back-court", w.backCourt, split, 0, L, W, true, true)];
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* A roundnet court in three: the no hit zone (the circle of 0.9 m), the ring from it out to the serving line (the circle of 2.6 m), and the rest of the court. The zones are ours:
|
|
405
|
+
* the rules name the lines, not the areas.
|
|
406
|
+
*/
|
|
407
|
+
function roundnetZones(ctx) {
|
|
408
|
+
const plan = courtFor({ sport: "roundnet", league: ctx.o.league, net: ctx.o.net });
|
|
409
|
+
const { length: L, width: W } = courtSize(plan);
|
|
410
|
+
if (plan.sport !== "roundnet")
|
|
411
|
+
return [];
|
|
412
|
+
const [cx, cy] = [L / 2, W / 2];
|
|
413
|
+
const { noHitRadius: n, servingRadius: R } = plan.figures;
|
|
414
|
+
const w = ctx.words;
|
|
415
|
+
const circle = (r) => `M${num(cx - r)} ${num(cy)}a${num(r)} ${num(r)} 0 1 0 ${num(2 * r)} 0a${num(r)} ${num(r)} 0 1 0 ${num(-2 * r)} 0Z`;
|
|
416
|
+
const dist = (x, y) => Math.hypot(x - cx, y - cy);
|
|
417
|
+
return [
|
|
418
|
+
{ id: "outside-circles", name: w.outsideCircles, d: rectPath(0, 0, L, W) + circle(R), label: [cx, (cy + R + W) / 2], room: [L * 0.8, W / 2 - R], has: (x, y) => x >= 0 && x <= L && y >= 0 && y <= W && dist(x, y) > R },
|
|
419
|
+
{ id: "serving-ring", name: w.servingRing, d: circle(R) + circle(n), label: [cx, cy - (R + n) / 2], room: [R - n, R - n], has: (x, y) => dist(x, y) > n && dist(x, y) <= R },
|
|
420
|
+
{ id: "no-hit-zone", name: w.noHitZone, d: circle(n), label: [cx, cy], room: [2 * n, 2 * n], has: (x, y) => dist(x, y) <= n },
|
|
421
|
+
];
|
|
422
|
+
}
|
|
378
423
|
/** The surface in thirds along it, counted from the team's own end: the same for every field sport with ends. */
|
|
379
424
|
function fieldThirds(ctx) {
|
|
380
425
|
const { box } = ctx.outline;
|
|
@@ -408,6 +453,109 @@ function cricketZones(ctx) {
|
|
|
408
453
|
out.push({ id: "pitch", name: w.pitchZone, d: rectPath(px0, py0, px1, py1), label: [cx, cy], room: [px1 - px0, py1 - py0], has: inPitch });
|
|
409
454
|
return out;
|
|
410
455
|
}
|
|
456
|
+
/** A swimming pool in lanes: each lane across the whole length of the pool, from the top of the drawing down. The lane's edges are the ropes'. */
|
|
457
|
+
function poolLanes(ctx) {
|
|
458
|
+
const plan = swimPlan({ sport: "swimming", pool: ctx.o.pool });
|
|
459
|
+
const L = ctx.outline.box.w;
|
|
460
|
+
const per = FEET_PER_METRE;
|
|
461
|
+
const lanes = plan.lanes;
|
|
462
|
+
return lanes.map((lane, i) => rect(`lane-${lane.number}`, fill(ctx.words.poolLane, { n: lane.number }), 0, i === 0 ? 0 : lane.top * per, L, i === lanes.length - 1 ? ctx.outline.box.h : lane.bottom * per, true, i === lanes.length - 1));
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* 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.
|
|
467
|
+
*/
|
|
468
|
+
function waterPoloAreas(ctx) {
|
|
469
|
+
const { box } = ctx.outline;
|
|
470
|
+
const L = box.w;
|
|
471
|
+
const W = box.h;
|
|
472
|
+
const w = ctx.words;
|
|
473
|
+
const post = WATER_POLO.goal.netClear * FEET_PER_METRE;
|
|
474
|
+
const two = WATER_POLO.twoMetre * FEET_PER_METRE;
|
|
475
|
+
const six = WATER_POLO.sixMetre * FEET_PER_METRE;
|
|
476
|
+
const goalLeft = post;
|
|
477
|
+
const goalRight = L - post;
|
|
478
|
+
return [
|
|
479
|
+
rect("goal-area-left", `${w.poloGoalArea} (${w.endLeft})`, 0, 0, goalLeft + two, W, false, true),
|
|
480
|
+
rect("two-to-six-left", `${w.poloTwoToSix} (${w.endLeft})`, goalLeft + two, 0, goalLeft + six, W, false, true),
|
|
481
|
+
rect("beyond-six-left", `${w.poloBeyondSix} (${w.endLeft})`, goalLeft + six, 0, L / 2, W, false, true),
|
|
482
|
+
rect("beyond-six-right", `${w.poloBeyondSix} (${w.endRight})`, L / 2, 0, goalRight - six, W, false, true),
|
|
483
|
+
rect("two-to-six-right", `${w.poloTwoToSix} (${w.endRight})`, goalRight - six, 0, goalRight - two, W, false, true),
|
|
484
|
+
rect("goal-area-right", `${w.poloGoalArea} (${w.endRight})`, goalRight - two, 0, L, W, true, true),
|
|
485
|
+
];
|
|
486
|
+
}
|
|
487
|
+
/** The pool in thirds along its length. */
|
|
488
|
+
function poolThirds(ctx) {
|
|
489
|
+
const { box } = ctx.outline;
|
|
490
|
+
const w = ctx.words;
|
|
491
|
+
return [w.poolNear, w.poolMiddle, w.poolFar].map((name, i) => rect(["near", "middle", "far"][i] + "-third", name, (box.w * i) / 3, 0, (box.w * (i + 1)) / 3, box.h, i === 2, true));
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* The athletics track in parts, each a part of the oval as the Manual lays it out (2.2.1.1): the finish straight and the back straight between the centres of the semicircles, the first bend (the right-hand one, which
|
|
495
|
+
* the athletes enter from the finish line) and the second, and the infield inside the kerb. The zones are ours: the rules name no area of the track. Lane by lane is the lane lines' business, not a zone's.
|
|
496
|
+
*/
|
|
497
|
+
function athleticsZones(ctx) {
|
|
498
|
+
const league = athleticsLeague({ sport: "athletics", league: ctx.o.league });
|
|
499
|
+
const fig = league.dimensions;
|
|
500
|
+
const lanes = athleticsLanes({ sport: "athletics", league: ctx.o.league, athletics: ctx.o.athletics });
|
|
501
|
+
const k = FEET_PER_METRE;
|
|
502
|
+
const { box } = ctx.outline;
|
|
503
|
+
const cx = box.w / 2;
|
|
504
|
+
const cy = box.h / 2;
|
|
505
|
+
const S = fig.straight;
|
|
506
|
+
const R = fig.radius;
|
|
507
|
+
const Ro = R + lanes * fig.lane;
|
|
508
|
+
const w = ctx.words;
|
|
509
|
+
const p = (u, v) => `${num(cx + u * k)} ${num(cy + v * k)}`;
|
|
510
|
+
const arc = (r, sweep) => `A${num(r * k)} ${num(r * k)} 0 0 ${sweep}`;
|
|
511
|
+
const inside = (u, v, r) => Math.abs(v) <= r && (Math.abs(u) <= S / 2 || Math.hypot(Math.abs(u) - S / 2, v) <= r);
|
|
512
|
+
const m = (x, y) => [(x - cx) / k, (y - cy) / k];
|
|
513
|
+
const onTrack = (u, v) => inside(u, v, Ro) && !inside(u, v, R);
|
|
514
|
+
const stadium = (r) => `M${p(-S / 2, -r)}H${num(cx + (S / 2) * k)}${arc(r, 1)} ${p(S / 2, r)}H${num(cx - (S / 2) * k)}${arc(r, 1)} ${p(-S / 2, -r)}Z`;
|
|
515
|
+
const east = `M${p(S / 2, -Ro)}${arc(Ro, 1)} ${p(S / 2, Ro)}V${num(cy + R * k)}${arc(R, 0)} ${p(S / 2, -R)}Z`;
|
|
516
|
+
const west = `M${p(-S / 2, Ro)}${arc(Ro, 1)} ${p(-S / 2, -Ro)}V${num(cy - R * k)}${arc(R, 0)} ${p(-S / 2, R)}Z`;
|
|
517
|
+
return [
|
|
518
|
+
{ id: "infield", name: w.trackInfield, d: stadium(R), label: [cx, cy], room: [S * k, R * k], has: (x, y) => { const [u, v] = m(x, y); return inside(u, v, R); } },
|
|
519
|
+
{ id: "home-straight", name: w.homeStraight, d: `M${p(-S / 2, R)}H${num(cx + (S / 2) * k)}V${num(cy + Ro * k)}H${num(cx - (S / 2) * k)}Z`, label: [cx, cy + ((R + Ro) / 2) * k], room: [S * k, (Ro - R) * k], has: (x, y) => { const [u, v] = m(x, y); return onTrack(u, v) && Math.abs(u) <= S / 2 && v > 0; } },
|
|
520
|
+
{ id: "first-bend", name: w.firstBend, d: east, 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 onTrack(u, v) && u > S / 2; } },
|
|
521
|
+
{ id: "back-straight", name: w.backStraight, d: `M${p(-S / 2, -Ro)}H${num(cx + (S / 2) * k)}V${num(cy - R * k)}H${num(cx - (S / 2) * k)}Z`, label: [cx, cy - ((R + Ro) / 2) * k], room: [S * k, (Ro - R) * k], has: (x, y) => { const [u, v] = m(x, y); return onTrack(u, v) && Math.abs(u) <= S / 2 && v < 0; } },
|
|
522
|
+
{ id: "second-bend", name: w.secondBend, 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 onTrack(u, v) && u < -S / 2; } },
|
|
523
|
+
];
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* The skating rink in parts: for a track, the infield inside the inner edge, the finish straight, the first curve, the crossing straight and the second curve between the centres of the curves, each as the
|
|
527
|
+
* plan lays it out (the long track's ice out to its padding, the short track's rink); for a figure skating rink, its length in thirds. The zones are ours: the Rules name no area of the ice.
|
|
528
|
+
*/
|
|
529
|
+
function skatingZones(ctx) {
|
|
530
|
+
const plan = skatingPlan({ sport: "skating", league: ctx.o.league, skating: ctx.o.skating });
|
|
531
|
+
const k = FEET_PER_METRE;
|
|
532
|
+
const { box } = ctx.outline;
|
|
533
|
+
const w = ctx.words;
|
|
534
|
+
const cx = box.w / 2;
|
|
535
|
+
const cy = box.h / 2;
|
|
536
|
+
if (plan.discipline === "figure") {
|
|
537
|
+
const part = (i, id, name) => rect(id, name, (box.w * i) / 3, 0, (box.w * (i + 1)) / 3, box.h, i === 2, true);
|
|
538
|
+
return [part(0, "left", w.rinkLeft), part(1, "middle", w.rinkMiddle), part(2, "right", w.rinkRight)];
|
|
539
|
+
}
|
|
540
|
+
const S = plan.oval === undefined ? plan.short.straight : plan.oval.straight;
|
|
541
|
+
const R = plan.oval === undefined ? plan.short.blocks : laneEdges(plan.oval, 0).inner;
|
|
542
|
+
const Ro = plan.oval === undefined ? plan.short.width / 2 : iceRadius(plan.oval);
|
|
543
|
+
const p = (u, v) => `${num(cx + u * k)} ${num(cy + v * k)}`;
|
|
544
|
+
const arc = (r, sweep) => `A${num(r * k)} ${num(r * k)} 0 0 ${sweep}`;
|
|
545
|
+
const inside = (u, v, r) => Math.abs(v) <= r && (Math.abs(u) <= S / 2 || Math.hypot(Math.abs(u) - S / 2, v) <= r);
|
|
546
|
+
const m = (x, y) => [(x - cx) / k, (y - cy) / k];
|
|
547
|
+
const onIce = (u, v) => inside(u, v, Ro) && !inside(u, v, R);
|
|
548
|
+
const stadium = (r) => `M${p(-S / 2, -r)}H${num(cx + (S / 2) * k)}${arc(r, 1)} ${p(S / 2, r)}H${num(cx - (S / 2) * k)}${arc(r, 1)} ${p(-S / 2, -r)}Z`;
|
|
549
|
+
const east = `M${p(S / 2, -Ro)}${arc(Ro, 1)} ${p(S / 2, Ro)}V${num(cy + R * k)}${arc(R, 0)} ${p(S / 2, -R)}Z`;
|
|
550
|
+
const west = `M${p(-S / 2, Ro)}${arc(Ro, 1)} ${p(-S / 2, -Ro)}V${num(cy - R * k)}${arc(R, 0)} ${p(-S / 2, R)}Z`;
|
|
551
|
+
return [
|
|
552
|
+
{ id: "infield", name: w.trackInfield, d: stadium(R), label: [cx, cy], room: [S * k, R * k], has: (x, y) => { const [u, v] = m(x, y); return inside(u, v, R); } },
|
|
553
|
+
{ id: "home-straight", name: w.finishStraight, d: `M${p(-S / 2, R)}H${num(cx + (S / 2) * k)}V${num(cy + Ro * k)}H${num(cx - (S / 2) * k)}Z`, label: [cx, cy + ((R + Ro) / 2) * k], room: [S * k, (Ro - R) * k], has: (x, y) => { const [u, v] = m(x, y); return onIce(u, v) && Math.abs(u) <= S / 2 && v > 0; } },
|
|
554
|
+
{ id: "first-curve", name: w.firstCurve, d: east, 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; } },
|
|
555
|
+
{ id: "crossing-straight", name: w.crossingStraight, d: `M${p(-S / 2, -Ro)}H${num(cx + (S / 2) * k)}V${num(cy - R * k)}H${num(cx - (S / 2) * k)}Z`, label: [cx, cy - ((R + Ro) / 2) * k], room: [S * k, (Ro - R) * k], has: (x, y) => { const [u, v] = m(x, y); return onIce(u, v) && Math.abs(u) <= S / 2 && v < 0; } },
|
|
556
|
+
{ 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
|
+
];
|
|
558
|
+
}
|
|
411
559
|
/** The zones of a set on the surface the context describes. Throws for a set that is not for the surface's sport. */
|
|
412
560
|
export function buildZoneSet(id, ctx) {
|
|
413
561
|
if (!Object.prototype.hasOwnProperty.call(ZONE_SETS, id))
|
|
@@ -419,6 +567,6 @@ export function buildZoneSet(id, ctx) {
|
|
|
419
567
|
const { zones, which } = retrosheetZones(ctx);
|
|
420
568
|
return { id, zones, which };
|
|
421
569
|
}
|
|
422
|
-
const zones = 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) : footballPass(ctx);
|
|
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);
|
|
423
571
|
return { id, zones, which: lastWins(zones) };
|
|
424
572
|
}
|
package/dist/homeside.js
CHANGED
|
@@ -10,6 +10,11 @@ export const HOME_FIRST = Object.freeze({
|
|
|
10
10
|
fieldhockey: true,
|
|
11
11
|
handball: true,
|
|
12
12
|
cricket: true,
|
|
13
|
+
// Water polo lists the home team first. A swimming, diving or artistic swimming dual meet follows the North American convention: the visitor is listed first.
|
|
14
|
+
waterpolo: true,
|
|
15
|
+
swimming: false,
|
|
16
|
+
diving: false,
|
|
17
|
+
artisticswimming: false,
|
|
13
18
|
// North American professional and college leagues, and the leagues that follow them: the visitor is listed first.
|
|
14
19
|
lacrosse: false,
|
|
15
20
|
nfl: false,
|
|
@@ -25,6 +30,18 @@ export const HOME_FIRST = Object.freeze({
|
|
|
25
30
|
badminton: false,
|
|
26
31
|
pickleball: false,
|
|
27
32
|
tabletennis: false,
|
|
33
|
+
padel: false,
|
|
34
|
+
squash: false,
|
|
35
|
+
racquetball: false,
|
|
36
|
+
sepaktakraw: false,
|
|
37
|
+
teqball: false,
|
|
38
|
+
roundnet: false,
|
|
39
|
+
// Netball is scored as a goals sport, not in sets, and is listed "home v away" in the Commonwealth countries where it is played most: the home team is first, on the left.
|
|
40
|
+
netball: true,
|
|
41
|
+
// A track meeting has no home and away.
|
|
42
|
+
athletics: false,
|
|
43
|
+
// A skating race has no home and away.
|
|
44
|
+
skating: false,
|
|
28
45
|
});
|
|
29
46
|
/** The leagues whose convention is not their sport's: the international federation's lacrosse lists the home team first. */
|
|
30
47
|
export const HOME_FIRST_LEAGUES = Object.freeze({
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { COLOR_PROPERTIES, SPORTS, describe, drawBadge, drawKyogijo, drawScore, drawSurface, isPortrait, statusLabel, statusText, winnerOf } from "./draw.ts";
|
|
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
3
|
export { inkOn, luminance, rgbOf, safeColour, safeLogo } from "./colour.ts";
|
|
4
4
|
export { OUTCOMES, drawLayers, layerTable } from "./layers.ts";
|
|
@@ -6,8 +6,16 @@ export { RANGES } from "./ranges.names.ts";
|
|
|
6
6
|
export { BACKGROUND_OPACITY, BACKGROUND_PATTERNS, KYOGIJO_BACKGROUND_STYLE } from "./background.ts";
|
|
7
7
|
export type { Background, BackgroundFit, BackgroundOptions, BackgroundPattern } from "./background.ts";
|
|
8
8
|
export { FIELD_SPORTS, fieldPlan, isFieldSport } from "./fields.ts";
|
|
9
|
+
export { POOL_SPORTS, isPoolSport, poolPlan, swimPlan, venueLayout } from "./pool.ts";
|
|
10
|
+
export type { ArtisticPlan, Board, DivePlan, LanePlan, PoloPlan, PoolPlan, Rope, RopeColour, SwimPlan, VenueItem, VenueLayout } from "./pool.ts";
|
|
11
|
+
export { formatTime, parseTime } from "./pool.race.ts";
|
|
12
|
+
export type { DeckLook, DivingPlatform, PaceOptions, PoolKind, PoolLook, PoolRace, PoolSection, RaceShow, Swimmer, SwimmerStatus, VenueOptions, VenuePool } from "./pool.types.ts";
|
|
9
13
|
export type { Area as FieldArea, FieldPlan, GoalPlan as FieldGoalPlan, Outline as FieldOutline, Shape as FieldShape } from "./fields.types.ts";
|
|
10
14
|
export { KYOGIJO_FIELDS_STYLE } from "./fields.style.ts";
|
|
15
|
+
export { KYOGIJO_ATHLETICS_STYLE, KYOGIJO_TRACK_STYLE } from "./athletics.style.ts";
|
|
16
|
+
export { KYOGIJO_SKATING_STYLE } from "./skating.style.ts";
|
|
17
|
+
export type { SkatingDiscipline, SkatingFurniture, SkatingInfield, SkatingRace, SkatingStyle } from "./skating/types.ts";
|
|
18
|
+
export type { AthleticsFieldEvent, AthleticsInfield, AthleticsRace, AthleticsStyle, AthleticsTrackLook, WaterJump } from "./athletics/types.ts";
|
|
11
19
|
export type { RangeInfo } from "./ranges.names.ts";
|
|
12
20
|
export { rampColour } from "./layers.marks.ts";
|
|
13
21
|
export { HEAT_RAMPS, HEAT_RAMP_NAMES } from "./heat.colour.ts";
|
|
@@ -17,7 +25,13 @@ export type { ArrowsLayer, Comet, Layer, LayerBase, LayerKind, LayerTeam, LineDa
|
|
|
17
25
|
export { KYOGIJO_STRINGS } from "./strings.ts";
|
|
18
26
|
export type { KyogijoWords } from "./strings.ts";
|
|
19
27
|
export { KYOGIJO_COURTS_STYLE } from "./courts.style.ts";
|
|
28
|
+
export { HARDWOOD_SMALL, KYOGIJO_HARDWOOD_STYLE } from "./hardwood.ts";
|
|
29
|
+
export { KYOGIJO_CROWD_STYLE } from "./crowd.draw.ts";
|
|
30
|
+
export { GRIDIRON_GROUNDS, WALL_SEATS, outlinePath, outlinePoints } from "./crowd.ts";
|
|
31
|
+
export type { CrowdStands, StandGap, StandRing, StandSector, Outline as StandOutline } from "./crowd.ts";
|
|
20
32
|
export { KYOGIJO_MARK_STYLE } from "./mark.ts";
|
|
33
|
+
export { KYOGIJO_PAGEANT_MOTION, KYOGIJO_PAGEANT_STYLE } from "./pageant.style.ts";
|
|
34
|
+
export { KYOGIJO_POOL_STYLE } from "./pool.style.ts";
|
|
21
35
|
export { KYOGIJO_CURLING_STYLE, KYOGIJO_HEAT_STYLE, KYOGIJO_NOTE_STYLE, KYOGIJO_STYLE, KYOGIJO_TEAM_STYLE, KYOGIJO_WALLS_STYLE } from "./style.ts";
|
|
22
36
|
export { KYOGIJO_LOOK_STYLE, LOOKS, LOOK_NAMES, LOOK_PAIRS, contrastOf, groupOf, lookPalette, lookStyle } from "./look.ts";
|
|
23
37
|
export type { Group as LookGroup, Look, Palette as LookPalette, PaletteKey as LookPaletteKey } from "./look.ts";
|
|
@@ -44,4 +58,4 @@ export type { SoccerPitchClass, SoccerPitchId, SoccerSize, SoccerSpec } from "./
|
|
|
44
58
|
export { SOCCER_PROVIDER_IDS, SOCCER_PROVIDERS, frameMatrix, rescale, soccerFrame, soccerLandmarks } from "./surfaces/soccer-providers.ts";
|
|
45
59
|
export type { Rescaler, SoccerFrame, SoccerProvider, SoccerProviderId } from "./surfaces/soccer-providers.ts";
|
|
46
60
|
export { VERSION } from "./version.ts";
|
|
47
|
-
export type { AxesOptions, Box, Colors, CourtStyle, Detail, DirectionOptions, FieldSport, FieldStyle, Fence, GoalInfo, GoalStyle, Language, NetStyle, LineDash, LineWidth, LookName, Orientation, QuirkName, QuirkOptions, RangeBox, RangeName, RangeNamed, ScoreOptions, Side, Size, Sport, StatusWord, StripePattern, SurfaceOptions, Team, TeamMark, Theme, WallOptions, } from "./types.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";
|
package/dist/index.js
CHANGED
|
@@ -1,18 +1,27 @@
|
|
|
1
1
|
// Kyogijo Stadiums 競技場: sports surfaces as SVG, drawn to scale, with the teams and the score on them.
|
|
2
|
-
export { COLOR_PROPERTIES, SPORTS, describe, drawBadge, drawKyogijo, drawScore, drawSurface, isPortrait, statusLabel, statusText, winnerOf } from "./draw.js";
|
|
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
4
|
export { inkOn, luminance, rgbOf, safeColour, safeLogo } from "./colour.js";
|
|
5
5
|
export { OUTCOMES, drawLayers, layerTable } from "./layers.js";
|
|
6
6
|
export { RANGES } from "./ranges.names.js";
|
|
7
7
|
export { BACKGROUND_OPACITY, BACKGROUND_PATTERNS, KYOGIJO_BACKGROUND_STYLE } from "./background.js";
|
|
8
8
|
export { FIELD_SPORTS, fieldPlan, isFieldSport } from "./fields.js";
|
|
9
|
+
export { POOL_SPORTS, isPoolSport, poolPlan, swimPlan, venueLayout } from "./pool.js";
|
|
10
|
+
export { formatTime, parseTime } from "./pool.race.js";
|
|
9
11
|
export { KYOGIJO_FIELDS_STYLE } from "./fields.style.js";
|
|
12
|
+
export { KYOGIJO_ATHLETICS_STYLE, KYOGIJO_TRACK_STYLE } from "./athletics.style.js";
|
|
13
|
+
export { KYOGIJO_SKATING_STYLE } from "./skating.style.js";
|
|
10
14
|
export { rampColour } from "./layers.marks.js";
|
|
11
15
|
export { HEAT_RAMPS, HEAT_RAMP_NAMES } from "./heat.colour.js";
|
|
12
16
|
export { ZONE_SETS, ZONE_SET_IDS } from "./heat.zones.js";
|
|
13
17
|
export { KYOGIJO_STRINGS } from "./strings.js";
|
|
14
18
|
export { KYOGIJO_COURTS_STYLE } from "./courts.style.js";
|
|
19
|
+
export { HARDWOOD_SMALL, KYOGIJO_HARDWOOD_STYLE } from "./hardwood.js";
|
|
20
|
+
export { KYOGIJO_CROWD_STYLE } from "./crowd.draw.js";
|
|
21
|
+
export { GRIDIRON_GROUNDS, WALL_SEATS, outlinePath, outlinePoints } from "./crowd.js";
|
|
15
22
|
export { KYOGIJO_MARK_STYLE } from "./mark.js";
|
|
23
|
+
export { KYOGIJO_PAGEANT_MOTION, KYOGIJO_PAGEANT_STYLE } from "./pageant.style.js";
|
|
24
|
+
export { KYOGIJO_POOL_STYLE } from "./pool.style.js";
|
|
16
25
|
export { KYOGIJO_CURLING_STYLE, KYOGIJO_HEAT_STYLE, KYOGIJO_NOTE_STYLE, KYOGIJO_STYLE, KYOGIJO_TEAM_STYLE, KYOGIJO_WALLS_STYLE } from "./style.js";
|
|
17
26
|
export { KYOGIJO_LOOK_STYLE, LOOKS, LOOK_NAMES, LOOK_PAIRS, contrastOf, groupOf, lookPalette, lookStyle } from "./look.js";
|
|
18
27
|
export { FEATURES, FEATURE_INFO, KYOGIJO_FEATURE_STYLE } from "./features.js";
|
package/dist/layers.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export interface RenderedLayers {
|
|
|
11
11
|
summaries: string[];
|
|
12
12
|
}
|
|
13
13
|
/** 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): RenderedLayers;
|
|
14
|
+
export declare function renderLayers(o: SurfaceOptions | ScoreOptions, layers: readonly Layer[] | undefined, turned?: boolean, range?: Box, upright?: number): RenderedLayers;
|
|
15
15
|
/**
|
|
16
16
|
* 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
17
|
* 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
|
@@ -14,6 +14,8 @@ export interface Env {
|
|
|
14
14
|
o: SurfaceOptions | ScoreOptions;
|
|
15
15
|
id: string;
|
|
16
16
|
turned: boolean;
|
|
17
|
+
/** The turn, in degrees, that texts and logos are given to read upright: the quarter back (-90) when the surface is turned a quarter, else 0, or the surface's own (a close-up of an athletics start is turned to any angle). */
|
|
18
|
+
back: number;
|
|
17
19
|
unit: Unit;
|
|
18
20
|
outline: Outline;
|
|
19
21
|
/**
|
|
@@ -69,4 +71,4 @@ export declare function place(layer: LayerBase, env: Env, points: readonly P[],
|
|
|
69
71
|
/** The inverse of `place`: places on the surface, in feet, as the layer's own coordinates (its frame and unit). */
|
|
70
72
|
export declare function placeBack(layer: LayerBase, env: Env, points: readonly P[], unit: Unit): P[];
|
|
71
73
|
export declare function newMade(): Made;
|
|
72
|
-
export declare function envFor(o: SurfaceOptions | ScoreOptions, turned: boolean | undefined, range?: Box): Env;
|
|
74
|
+
export declare function envFor(o: SurfaceOptions | ScoreOptions, turned: boolean | undefined, range?: Box, upright?: number): Env;
|
package/dist/layers.env.js
CHANGED
|
@@ -60,14 +60,16 @@ export function placeBack(layer, env, points, unit) {
|
|
|
60
60
|
export function newMade() {
|
|
61
61
|
return { marks: "", defs: "", style: "", attr: "", opacity: undefined, drawn: 0, skipped: 0, outcomes: new Map(), teams: new Map(), low: Infinity, high: -Infinity };
|
|
62
62
|
}
|
|
63
|
-
export function envFor(o, turned, range) {
|
|
63
|
+
export function envFor(o, turned, range, upright) {
|
|
64
64
|
const language = o.language === "ja" ? "ja" : "en";
|
|
65
65
|
const outline = outlineOf(o);
|
|
66
66
|
const teams = o;
|
|
67
|
+
const quarter = turned ?? (isPortrait(o) && o.sport !== "mlb");
|
|
67
68
|
return {
|
|
68
69
|
o,
|
|
69
70
|
id: drawingId(o),
|
|
70
|
-
turned:
|
|
71
|
+
turned: quarter,
|
|
72
|
+
back: upright ?? (quarter ? -90 : 0),
|
|
71
73
|
unit: lengthUnit(o),
|
|
72
74
|
outline,
|
|
73
75
|
shown: range ?? outline.box,
|
package/dist/layers.js
CHANGED
|
@@ -141,7 +141,7 @@ function drawPoints(layer, env) {
|
|
|
141
141
|
const logo = shape === "logo" ? safeLogo(d.logo) ?? (role === undefined ? undefined : safeLogo(style.logos?.[role]) ?? env.logos[role]) : undefined;
|
|
142
142
|
if (logo !== undefined) {
|
|
143
143
|
const side = w * 1.8;
|
|
144
|
-
out.push(titled("image", `${open} href="${esc(logo)}" x="${num(x - side / 2)}" y="${num(y - side / 2)}" width="${num(side)}" height="${num(side)}" preserveAspectRatio="xMidYMid meet"${env.
|
|
144
|
+
out.push(titled("image", `${open} href="${esc(logo)}" x="${num(x - side / 2)}" y="${num(y - side / 2)}" width="${num(side)}" height="${num(side)}" preserveAspectRatio="xMidYMid meet"${env.back !== 0 ? ` transform="rotate(${num(env.back)} ${num(x)} ${num(y)})"` : ""}`, d.title));
|
|
145
145
|
}
|
|
146
146
|
else if (shape !== "logo" && isPolygon(shape))
|
|
147
147
|
out.push(titled("path", `${open} d="${shapePath(shape, x, y, w, env.turned)}"`, d.title));
|
|
@@ -307,7 +307,7 @@ function drawText(layer, env) {
|
|
|
307
307
|
const { cls, css } = colourAttrs(colourFor(style.color, d, INK, domain), layerExpr, INK);
|
|
308
308
|
const anchor = d.anchor === "start" || d.anchor === "middle" || d.anchor === "end" ? d.anchor : base;
|
|
309
309
|
// 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
|
-
const angle =
|
|
310
|
+
const angle = env.back + (isNum(d.rotate) ? d.rotate : 0);
|
|
311
311
|
const classes = ["ky-lt", style.halo === false ? "ky-nh" : "", cls].filter((c) => c !== "").join(" ");
|
|
312
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)})"`}`;
|
|
313
313
|
out.push(`<text${open}>${esc(String(d.text))}${typeof d.title === "string" && d.title !== "" ? `<title>${esc(d.title)}</title>` : ""}</text>`);
|
|
@@ -348,12 +348,12 @@ function summarise(layer, made, words, stop, gap) {
|
|
|
348
348
|
return { title, description: parts.join(gap) };
|
|
349
349
|
}
|
|
350
350
|
/** 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) {
|
|
351
|
+
export function renderLayers(o, layers, turned, range, upright) {
|
|
352
352
|
if (layers === undefined || layers.length === 0)
|
|
353
353
|
return { svg: "", summaries: [] };
|
|
354
354
|
if (!Array.isArray(layers))
|
|
355
355
|
throw new TypeError("layers is a list of layers");
|
|
356
|
-
const env = envFor(o, turned, range);
|
|
356
|
+
const env = envFor(o, turned, range, upright);
|
|
357
357
|
const clipId = `${env.id}-lc`;
|
|
358
358
|
const { stop, gap } = env.words.said;
|
|
359
359
|
const said = [];
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type Unit } from "../units.ts";
|
|
2
|
+
import type { LeagueBase } from "./types.ts";
|
|
3
|
+
/** The figures of an oval track, in metres. */
|
|
4
|
+
export interface AthleticsFigures {
|
|
5
|
+
/** The length of each straight (the distance between the centres of the semicircles, for the outdoor track's). */
|
|
6
|
+
straight: number;
|
|
7
|
+
/** The radius of each bend at the inside of the track, where the kerb is. */
|
|
8
|
+
radius: number;
|
|
9
|
+
/** The width of a lane, the line on its right included. */
|
|
10
|
+
lane: number;
|
|
11
|
+
/** The least, the most and the drawn number of lanes of the oval. */
|
|
12
|
+
lanes: {
|
|
13
|
+
min: number;
|
|
14
|
+
max: number;
|
|
15
|
+
drawn: number;
|
|
16
|
+
};
|
|
17
|
+
/** The width of the painted lines. */
|
|
18
|
+
line: number;
|
|
19
|
+
/** The width of the kerb, as it is drawn (the rules allow 50 to 250 mm). */
|
|
20
|
+
kerb: number;
|
|
21
|
+
/** Where the running line is measured: from the kerb in lane 1, from the line on the left in the other lanes. */
|
|
22
|
+
inner: number;
|
|
23
|
+
outer: number;
|
|
24
|
+
/** The obstacle-free zone inside the kerb and outside the track, at least. */
|
|
25
|
+
safety: number;
|
|
26
|
+
/** The lane width of the straight that runs on beyond the oval's. */
|
|
27
|
+
straightLane: number;
|
|
28
|
+
/** The least and the most lanes of that straight, and the lengths round it: the starting area and the run-out. */
|
|
29
|
+
straightLanes: {
|
|
30
|
+
min: number;
|
|
31
|
+
max: number;
|
|
32
|
+
};
|
|
33
|
+
startArea: number;
|
|
34
|
+
runOut: number;
|
|
35
|
+
/** True for a covered track: its bends are banked, at this angle in degrees. */
|
|
36
|
+
banking: number | null;
|
|
37
|
+
}
|
|
38
|
+
/** The figures in feet, as the drawing's units are: the lengths only, not the counts of lanes or the angle of the banking. */
|
|
39
|
+
export declare function athleticsInFeet(figures: AthleticsFigures, unit: Unit): AthleticsFigures;
|
|
40
|
+
/** A league with an athletics track of its own. */
|
|
41
|
+
export type AthleticsLeague = LeagueBase<"athletics", AthleticsFigures>;
|
|
42
|
+
/**
|
|
43
|
+
* The 400 m Standard Track (Manual 2.2.1.1, Table 2.2.1.1): two semicircles of 36.50 m radius at the kerb joined by two straights of 84.39 m, lanes 1.22 m wide including the 50 mm line on the
|
|
44
|
+
* right (Rule 14.4), the running line 0.30 m outside the kerb in lane 1 and 0.20 m outside the line on the left in every other lane (Rule 14.2), eight lanes at least for the big competitions (Rule
|
|
45
|
+
* 14.5) and nine at the most (Manual 2.2.1.1). A straight of at least six lanes runs on beyond the oval's with a starting area of 3 m and a run-out of 17 m (Manual 2.2.2.1), and has no most (2.2.2.1).
|
|
46
|
+
* The safety zones are 1.00 m wide (2.2.1.5). The kerb is drawn 0.05 m wide, the narrowest the rules allow (Rule 14.1: 50 to 250 mm).
|
|
47
|
+
*/
|
|
48
|
+
export declare const WA_STANDARD_TRACK: AthleticsFigures;
|
|
49
|
+
/**
|
|
50
|
+
* The 200 m Standard Short Track (Marking Plan for the World Athletics Standard Short Track, 1 January 2026; Rules 41 to 44): the bends have a construction radius of 17.205 m at the kerb and the
|
|
51
|
+
* centres of the banked bends are 44.983 m apart; lanes are 1.000 m wide on the oval and 1.220 m on the infield straight, four to six of them (Rule 43: 0.90 to 1.22 m, a minimum of four lanes and
|
|
52
|
+
* a maximum of six); the bends are banked at 10.000 degrees. The plan's own transitions (the ascending and descending sections) are drawn here as one circular bend of the same radius, which is ours.
|
|
53
|
+
*/
|
|
54
|
+
export declare const WA_SHORT_TRACK: AthleticsFigures;
|
|
55
|
+
/** The staggers of the lanes of the 400 m Standard Track as the Manual prints them (Table 2.2.1.6a), in metres on the running line, for lanes 2 to 8: 200 m, 400 m, 800 m and 4 x 400 m. */
|
|
56
|
+
export declare const WA_STAGGER_TABLE: Readonly<Record<"200m" | "400m" | "800m" | "4x400m", readonly number[]>>;
|
|
57
|
+
/**
|
|
58
|
+
* The staggers of the lanes of the 200 m Standard Short Track (Marking Plan, 1 January 2026), in metres measured 0.20 m out from the lane line, for lanes 2 to 6. The first row serves the 200 m, 400 m,
|
|
59
|
+
* 800 m, 4 x 400 m and 4 x 800 m (two bends in lanes), the second the 4 x 200 m (three bends in lanes), the third the second leg of the 4 x 200 m (one bend).
|
|
60
|
+
*/
|
|
61
|
+
export declare const WA_SHORT_STAGGER_TABLE: Readonly<Record<"two-bends" | "three-bends" | "one-bend", readonly number[]>>;
|
|
62
|
+
/** The athletics leagues: the outdoor track (the sport's own) and the covered one. */
|
|
63
|
+
export declare const ATHLETICS_LEAGUES: readonly AthleticsLeague[];
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// The athletics track: World Athletics' 400 m Standard Track (Track and Field Facilities Manual, 2019 edition, 2.2.1, and Technical Rule 14 of Book C2.1) and its 200 m Standard Short Track
|
|
2
|
+
// for covered stadia (Technical Rules 41 to 44, and the Marking Plan for the Standard Short Track of 1 January 2026), with the figures of each in metres. Nothing here draws.
|
|
3
|
+
import { convertLength } from "../units.js";
|
|
4
|
+
/** The figures in feet, as the drawing's units are: the lengths only, not the counts of lanes or the angle of the banking. */
|
|
5
|
+
export function athleticsInFeet(figures, unit) {
|
|
6
|
+
const k = (v) => convertLength(v, unit, "ft");
|
|
7
|
+
return {
|
|
8
|
+
straight: k(figures.straight),
|
|
9
|
+
radius: k(figures.radius),
|
|
10
|
+
lane: k(figures.lane),
|
|
11
|
+
lanes: { ...figures.lanes },
|
|
12
|
+
line: k(figures.line),
|
|
13
|
+
kerb: k(figures.kerb),
|
|
14
|
+
inner: k(figures.inner),
|
|
15
|
+
outer: k(figures.outer),
|
|
16
|
+
safety: k(figures.safety),
|
|
17
|
+
straightLane: k(figures.straightLane),
|
|
18
|
+
straightLanes: { ...figures.straightLanes },
|
|
19
|
+
startArea: k(figures.startArea),
|
|
20
|
+
runOut: k(figures.runOut),
|
|
21
|
+
banking: figures.banking,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The 400 m Standard Track (Manual 2.2.1.1, Table 2.2.1.1): two semicircles of 36.50 m radius at the kerb joined by two straights of 84.39 m, lanes 1.22 m wide including the 50 mm line on the
|
|
26
|
+
* right (Rule 14.4), the running line 0.30 m outside the kerb in lane 1 and 0.20 m outside the line on the left in every other lane (Rule 14.2), eight lanes at least for the big competitions (Rule
|
|
27
|
+
* 14.5) and nine at the most (Manual 2.2.1.1). A straight of at least six lanes runs on beyond the oval's with a starting area of 3 m and a run-out of 17 m (Manual 2.2.2.1), and has no most (2.2.2.1).
|
|
28
|
+
* The safety zones are 1.00 m wide (2.2.1.5). The kerb is drawn 0.05 m wide, the narrowest the rules allow (Rule 14.1: 50 to 250 mm).
|
|
29
|
+
*/
|
|
30
|
+
export const WA_STANDARD_TRACK = {
|
|
31
|
+
straight: 84.39,
|
|
32
|
+
radius: 36.5,
|
|
33
|
+
lane: 1.22,
|
|
34
|
+
lanes: { min: 4, max: 9, drawn: 8 },
|
|
35
|
+
line: 0.05,
|
|
36
|
+
kerb: 0.05,
|
|
37
|
+
inner: 0.3,
|
|
38
|
+
outer: 0.2,
|
|
39
|
+
safety: 1,
|
|
40
|
+
straightLane: 1.22,
|
|
41
|
+
straightLanes: { min: 6, max: 10 },
|
|
42
|
+
startArea: 3,
|
|
43
|
+
runOut: 17,
|
|
44
|
+
banking: null,
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* The 200 m Standard Short Track (Marking Plan for the World Athletics Standard Short Track, 1 January 2026; Rules 41 to 44): the bends have a construction radius of 17.205 m at the kerb and the
|
|
48
|
+
* centres of the banked bends are 44.983 m apart; lanes are 1.000 m wide on the oval and 1.220 m on the infield straight, four to six of them (Rule 43: 0.90 to 1.22 m, a minimum of four lanes and
|
|
49
|
+
* a maximum of six); the bends are banked at 10.000 degrees. The plan's own transitions (the ascending and descending sections) are drawn here as one circular bend of the same radius, which is ours.
|
|
50
|
+
*/
|
|
51
|
+
export const WA_SHORT_TRACK = {
|
|
52
|
+
straight: 44.983,
|
|
53
|
+
radius: 17.205,
|
|
54
|
+
lane: 1,
|
|
55
|
+
lanes: { min: 4, max: 6, drawn: 6 },
|
|
56
|
+
line: 0.05,
|
|
57
|
+
kerb: 0.05,
|
|
58
|
+
inner: 0.3,
|
|
59
|
+
outer: 0.2,
|
|
60
|
+
safety: 1,
|
|
61
|
+
straightLane: 1.22,
|
|
62
|
+
straightLanes: { min: 4, max: 6 },
|
|
63
|
+
startArea: 3,
|
|
64
|
+
runOut: 10,
|
|
65
|
+
banking: 10,
|
|
66
|
+
};
|
|
67
|
+
/** The staggers of the lanes of the 400 m Standard Track as the Manual prints them (Table 2.2.1.6a), in metres on the running line, for lanes 2 to 8: 200 m, 400 m, 800 m and 4 x 400 m. */
|
|
68
|
+
export const WA_STAGGER_TABLE = Object.freeze({
|
|
69
|
+
"200m": [3.519, 7.351, 11.184, 15.017, 18.85, 22.682, 26.515],
|
|
70
|
+
"400m": [7.037, 14.703, 22.368, 30.034, 37.699, 45.365, 53.03],
|
|
71
|
+
"800m": [3.526, 7.384, 11.259, 15.151, 19.06, 22.987, 26.93],
|
|
72
|
+
"4x400m": [10.563, 22.086, 33.627, 45.185, 56.76, 68.352, 79.96],
|
|
73
|
+
});
|
|
74
|
+
/**
|
|
75
|
+
* The staggers of the lanes of the 200 m Standard Short Track (Marking Plan, 1 January 2026), in metres measured 0.20 m out from the lane line, for lanes 2 to 6. The first row serves the 200 m, 400 m,
|
|
76
|
+
* 800 m, 4 x 400 m and 4 x 800 m (two bends in lanes), the second the 4 x 200 m (three bends in lanes), the third the second leg of the 4 x 200 m (one bend).
|
|
77
|
+
*/
|
|
78
|
+
export const WA_SHORT_STAGGER_TABLE = Object.freeze({
|
|
79
|
+
"two-bends": [5.597, 11.821, 18.051, 24.285, 30.523],
|
|
80
|
+
"three-bends": [8.407, 17.781, 27.188, 36.626, 46.092],
|
|
81
|
+
"one-bend": [2.81, 5.959, 9.137, 12.341, 15.57],
|
|
82
|
+
});
|
|
83
|
+
/** The athletics leagues: the outdoor track (the sport's own) and the covered one. */
|
|
84
|
+
export const ATHLETICS_LEAGUES = [
|
|
85
|
+
{ id: "world-athletics", family: "athletics", name: { en: "World Athletics 400 m standard track", ja: "ワールドアスレティックスの400m標準トラック" }, unit: "m", dimensions: WA_STANDARD_TRACK, sources: ["wa-facilities-manual", "wa-technical-rules"], builtIn: true },
|
|
86
|
+
{ id: "world-athletics-short", family: "athletics", name: { en: "World Athletics 200 m standard short track", ja: "ワールドアスレティックスの200m標準トラック(ショート・トラック)" }, unit: "m", dimensions: WA_SHORT_TRACK, sources: ["wa-short-track-plan", "wa-technical-rules"] },
|
|
87
|
+
];
|