Kyogijo Stadiums競技場

Guides, the reference, a gallery of every picture it can draw, and how it compares: the pages are made from the package's own files when the site is built.

About the name

The pages are in English; this contents, the search and the buttons are in Japanese.

Zones and the rules

zoneAt(sport, point, options) says where a point lies in the sport's own terms: the zone (the offensive zone, the frontcourt, the attacking third, the infield, the red zone), the finer area in it (the crease, the paint, the six-yard box, the warning track, between the hashes), and every other area that holds, each by an id that is the same in every language and a name in English or Japanese. It is in its own entry, @johnmorrisdotca/kyogijo-stadiums/zones. (The frames entry has a zoneAt of its own, for Retrosheet's hit-location sectors; this one is for every sport.)

The geometry is the package's own: a rink's blue lines, goal lines, creases, trapezoids and face-off circles from the rink of a league and a season; a court's lane, restricted area and three-point line from the league's court and the season's rules (the NBA's arc was 22 feet from 1994 to 1997); a pitch's boxes from the Laws and the pitch's size; a ballpark's fence from the park, in the season; a field's end zones and hash marks from the league. Where a rule has no figure of its own (the slot, the half-spaces) the package's zone sets are used, and a test holds the two to the same answer on a grid. A sport that has no rules of its own here answers in its zone sets.

import { zoneAt } from "@johnmorrisdotca/kyogijo-stadiums/zones";

// The right end-zone face-off dot: the offensive zone, inside a face-off circle.
const dot = zoneAt("nhl", [69, 22], { frame: "nhl-api" });
console.log(dot.zone, dot.subzone, dot.names["faceoff-circle"]);
// offensive-zone faceoff-circle Face-off circle

// A shot from 25 feet out in the middle, in the NBA stats' tenths of a foot.
const arc = zoneAt("nba", [0, 250], { frame: "nba-stats" });
console.log(arc.zone, arc.subzone, arc.zones.includes("three-point"));
// frontcourt above-the-break true

// Opta's (95, 50): the six-yard box, and the penalty area it is in.
const box = zoneAt("soccer", [95, 50], { frame: "opta" });
console.log(box.zone, box.subzone, box.zones.join(" "));
// attacking-third six-yard-box attacking-third six-yard-box penalty-area central-corridor

The point#

A point is [x, y] or { x, y }. frame says what it is in: a frame's name (nhl-api, nba-stats, opta, statsbomb, retrosheet, mlbam, nfl-tracking and every other), a frame of your own, or nothing, for the drawing's own numbers in feet (or units). size gives the surface's size for a frame that fits any. The surface's options (league, year, park, pitch, fence) say which rink, court, park or pitch: a league's blue line is its own (the IIHF's are 22.5 m from the end boards).

The team is taken to attack the right end, as the surface is drawn wide. attacking: "left" says the numbers are a team's that attacks the left; they are turned a half turn first, as the data layers turn them, so the same point is a team's own end (the defensive zone, own-six-yard-box) or the one it attacks. Left and right are the attacker's: facing the right end, left is the top of the drawing.

A point off the surface (on the apron, in the stands) is in no zone: inBounds is false and zone, subzone and zones are empty. A ballpark is the exception, because foul ground and the stands beyond the fence are zones of baseball.

What each sport answers#

SportZoneFiner areas and flags
Hockeydefensive-zone, neutral-zone, offensive-zone (the blue lines)crease, trapezoid, behind-goal-line, inner-slot, outer-slot, slot, faceoff-circle, centre-circle
Basketballfrontcourt, backcourt (of the basket attacked)restricted-area, paint, mid-range, corner-three-left, corner-three-right, above-the-break, and the flag three-point
Soccerdefensive-third, middle-third, attacking-thirdsix-yard-box, penalty-area, penalty-arc (the D), each also as own- at the end the team defends; wing-left, half-space-left, central-corridor, half-space-right, wing-right
Baseballinfield, outfield, foul-territory, over-the-wallfair-territory, warning-track, left-field, centre-field, right-field, third-base-side, middle-infield, first-base-side
Footballown-end-zone, own-half, opponent-half, red-zone, opponent-end-zoneend-zone, between-the-hashes, outside-hashes-left, outside-hashes-right
Every other sportthe first of its zone sets that the point is inthe rest, and sets has the zone of each set

Names by league. The restricted area is worded by the rule book of the league: in the NBA and the leagues that follow its words it is the restricted area (リストリクテッドエリア in Japanese); FIBA's rule book calls it the no-charge semicircle, and the Japan Basketball Association, which follows FIBA, ノーチャージセミサークル. A court of league: "fiba" is named in FIBA's words (No-charge semicircle, ノーチャージセミサークル), every other court in the NBA's; the id is restricted-area in both, and zoneName(id, language, league) gives the word for a league. The package has no Japanese league of its own: a court played under the JBA's rules is league: "fiba".

The paint flag holds for the whole key, the restricted area included, so inPaint is the key as a rulebook draws it; subzone is restricted-area there, as the NBA's shot zones have it. The slot is the package's definition (the zone sets' nhl-slot), because the NHL's rules do not define one. The red zone is the 20 yards before the opponent's goal line. The three-point test is the line's own geometry: the straight lines 3 feet from the sidelines (22 feet from the basket), the arc beyond.

Yes or no#

import { inCrease, inPenaltyArea, inSlot, isFair, isThreePointer, onWarningTrack, overWall } from "@johnmorrisdotca/kyogijo-stadiums/zones";

console.log(isThreePointer([0, 240], { frame: "nba-stats" }), isThreePointer([0, 230], { frame: "nba-stats" }));
console.log(inSlot([80, 0], { frame: "nhl-api" }), inCrease([85, 3.9], { frame: "nhl-api" }), inPenaltyArea([88, 50], { frame: "opta" }));
console.log(isFair([101, 100], { frame: "retrosheet" }), onWarningTrack([0, 380], { frame: "retrosheet", park: "fenway-park" }), overWall([0, 395], { frame: "retrosheet", park: "fenway-park" }));
// true false
// true true true
// false true true

isThreePointer, inPaint, inRestrictedArea, inSlot, inCrease, inPenaltyArea, inSixYardBox, inRedZone, betweenHashes, isFair, overWall and onWarningTrack each take a point and the same options. zoneResolver(sport, options) is the function of a surface place (feet) to the finest zone that the marks of a drawing use for their data-zone.

Home runs, from the park's own fence and wall#

homeRun(park, point, { frame, height }) decides from the park's fence distance at the bearing and, when the height of the ball where it crossed the fence is given, the height of the wall there. A ball in fair territory that came down beyond the fence is a home run; one under the wall's height struck it. isHomeRun is the yes or no.

import { PARKS_WITHOUT_WALL_HEIGHTS, homeRun, isHomeRun } from "@johnmorrisdotca/kyogijo-stadiums/zones";

// Fenway Park's Green Monster is 37 feet 2 inches high, 310 feet down the line.
const left = [-250, 250] as const;
console.log(homeRun("fenway-park", left, { frame: "retrosheet", height: 30 }).reason, isHomeRun("fenway-park", left, { frame: "retrosheet", height: 40 }));
// struck-wall true
console.log(PARKS_WITHOUT_WALL_HEIGHTS.length, "of 94 parks hold no wall height");
// 59 of 94 parks hold no wall height

Where the park's article gives no wall height for the bearing, a decision that needs one is homeRun: undefined with reason: "unknown-wall" and wallData false: never a guess. PARKS_WITHOUT_WALL_HEIGHTS lists the parks (59 of the 94 hold none at all), and wallHeightAt(park, angle, year) is the height at a bearing, or null. Without height, a fair ball beyond the fence is a home run whatever the wall.

Marks carry their zone#

Add marks: true to a drawing and every mark of its data layers (and of a chart) is written with data-mark-id, data-index and data-zone, the zone being this engine's finest, so that one listener can tie a mark to a table: see data layers. A layer whose data has an id, and a drawing made with pointer: true, have them without asking.

Edit this page on GitHub