import { type Attacking, type Frame, type SurfaceSize } from "./frames.ts"; import "./frames.providers.ts"; import "./surfaces/soccer-providers.ts"; import { type Park } from "./parks.ts"; import type { Language, Sport, SurfaceOptions } from "./types.ts"; export { RULE_IDS } from "./rules.types.ts"; export type { RuleId } from "./rules.types.ts"; /** A place: `[x, y]` or `{ x, y }`. */ export type PlaceLike = readonly [number, number] | { readonly x: number; readonly y: number; }; /** What `zoneAt` and the predicates take besides the point: the surface's own options (the league, the season, the park, the pitch) and the frame the point is in. */ export interface ZoneOptions extends Partial> { /** The frame the point is in: the name of a frame (`nhl-api`, `opta`), a frame, or nothing for the drawing's own (feet, or `units`). */ frame?: Frame | string; /** The size of the surface when the frame is a variable one, in place of the drawing's own. */ size?: SurfaceSize; /** The end the point's team attacks, as the surface is drawn wide; `left` turns the numbers a half turn so that the team attacks right. */ attacking?: Attacking; } /** What the rules say of a point. */ export interface ZoneAnswer { sport: Sport; /** The point on the surface, in feet in the drawing's wide frame, the team attacking the right. */ at: [number, number]; /** True when the point is on the surface, or on its edge. Off it, `zone`, `subzone` and `zones` are empty (a ballpark is the exception: its foul ground and the stands beyond the fence are zones). */ inBounds: boolean; /** The zone the point is in: one of a partition of the surface, such as `offensive-zone`. */ zone: string | undefined; /** The finer area in the zone, when there is one: `crease`, `paint`, `six-yard-box`, `warning-track`. */ subzone: string | undefined; /** Every id that holds, the zone and the subzone first. */ zones: string[]; /** The zone of each of the package's zone sets for the sport (`ZONE_SETS`) that the point is in. */ sets: Record; /** The name of each id in `zones`, in the language asked for. */ names: Record; } /** The wall height at a bearing: the stretch of the park's fence that covers it in the season, in feet, or `null` where the park's data holds none. */ export declare function wallHeightAt(park: Park, angle: number, year?: number): number | null; /** * Where a point lies by the rules of a sport: the zone, the area in it and every other area that holds, each by id and name. Hockey answers in the * offensive, neutral and defensive zones with the crease, the trapezoid, the slot, the face-off circles and behind the goal line; basketball in the * frontcourt and backcourt with the restricted area, the paint, the mid-range, the corner threes and the arc; soccer in thirds with the six-yard box, * the penalty area, the D, the half-spaces and the wings; baseball in the infield, the outfield, foul territory, the warning track and over the * wall by the park's own fence; football in the end zones, the halves, the red zone and between the hashes. Every other sport answers in its zone sets. * @example * ```ts * import { zoneAt } from "@johnmorrisdotca/kyogijo-stadiums/zones"; * // The NHL API's (69, 22) is the face-off dot in the right end zone: the offensive zone, inside a face-off circle. * const dot = zoneAt("nhl", [69, 22], { frame: "nhl-api" }); * console.log(dot.zone, dot.subzone, dot.zones.includes("faceoff-circle")); * // offensive-zone faceoff-circle true * ``` */ export declare function zoneAt(sport: Sport, point: PlaceLike, options?: ZoneOptions): ZoneAnswer; /** `zoneAt` for a place already on the surface: feet in the drawing's wide frame, the team attacking the right. What a drawing's click is asked with (pointer.ts). */ export declare function zoneAtSurface(sport: Sport, at: readonly [number, number], options?: ZoneOptions): ZoneAnswer; /** * A function from a place on the surface (feet, the drawing's wide frame, the team attacking the right) to the id of the finest zone it lies in: what a data * layer's marks carry as `data-zone`. Built once for the options of a drawing; `undefined` where the sport has no zone there. */ export declare function zoneResolver(sport: Sport, options?: ZoneOptions): (x: number, y: number) => string | undefined; /** * The name of a zone id in a language: the rules engine's own ids have words in both; any other id (a zone set's) comes back as it is. A court of `league: "fiba"` has the words of FIBA's rule book, which the * Japan Basketball Association follows: the restricted area is the no-charge semicircle (ノーチャージセミサークル); in the NBA and the leagues that follow its words it is the restricted area (リストリクテッドエリア). */ export declare const zoneName: (id: string, language?: Language, league?: string) => string; /** True when a shot from the place would count three: beyond the three-point line (the arc, or past the straight lines at the sidelines), at the basket the team attacks. */ export declare const isThreePointer: (point: PlaceLike, options?: ZoneOptions) => boolean; /** True when the place is in the paint (the free-throw lane, the key), outside the restricted area. */ export declare const inPaint: (point: PlaceLike, options?: ZoneOptions) => boolean; /** True when the place is in the restricted area under the basket. */ export declare const inRestrictedArea: (point: PlaceLike, options?: ZoneOptions) => boolean; /** True when the place is in the slot (the package's definition: the inner and outer slot in front of the net, between the face-off circles), at either end. */ export declare const inSlot: (point: PlaceLike, options?: ZoneOptions) => boolean; /** True when the place is in a goal crease. */ export declare const inCrease: (point: PlaceLike, options?: ZoneOptions) => boolean; /** True when the place is in a penalty area, at the end the team attacks or the one it defends. */ export declare const inPenaltyArea: (point: PlaceLike, options?: ZoneOptions) => boolean; /** True when the place is in a goal area (the six-yard box), at either end. */ export declare const inSixYardBox: (point: PlaceLike, options?: ZoneOptions) => boolean; /** True when the place is in the red zone: inside the opponent's 20-yard line. */ export declare const inRedZone: (point: PlaceLike, options?: ZoneOptions) => boolean; /** True when the place is between the hash marks. */ export declare const betweenHashes: (point: PlaceLike, options?: ZoneOptions) => boolean; /** True when the place is in fair territory: between the foul lines, which are fair themselves. */ export declare const isFair: (point: PlaceLike, options?: ZoneOptions) => boolean; /** True when the place, in fair territory, lies beyond the park's fence: where a ball came down over the wall. `park` is a key of `PARKS`. */ export declare const overWall: (point: PlaceLike, options?: ZoneOptions) => boolean; /** True when the place is on the warning track. */ export declare const onWarningTrack: (point: PlaceLike, options?: ZoneOptions) => boolean; /** What a home-run decision rests on. */ export interface HomeRunVerdict { /** True: a home run. False: in play or foul. `undefined`: it cannot be told, because the ball was over the fence and its height was given but the park holds no wall height there. */ homeRun: boolean | undefined; /** The place is in fair territory. */ fair: boolean; /** How far from home plate, and the fence's distance in that direction (at the bearing), in feet. */ distance: number; fence: number; /** The bearing from dead centre, in degrees (negative to left field). */ angle: number; /** The wall's height at the bearing in feet, or `null` where the park's data holds none. */ wall: number | null; /** True when the park has wall heights at all; `isHomeRun` reports it so that a caller can say the data is missing. */ wallData: boolean; /** Why, in a word: `foul`, `short` (the ball came down inside the fence), `over` (beyond the fence), `cleared` or `struck-wall` (the given height did not clear the wall), `unknown-wall`. */ reason: "foul" | "short" | "over" | "cleared" | "struck-wall" | "unknown-wall"; } /** What a caller can give about the ball. */ export interface HomeRunOptions extends ZoneOptions { /** The height of the ball in feet as it crossed the fence's line. Without it, a ball that came down beyond the fence in fair territory is a home run. */ height?: number; } /** * The ballparks whose wall heights the package holds nowhere in their fence: of the 94 parks, the 35 whose article gives heights have them for some stretch, * and for the rest the height is not known here, so a decision that needs it is undecided (`homeRun: undefined`), never guessed. */ export declare const PARKS_WITHOUT_WALL_HEIGHTS: readonly string[]; /** * Whether a ball is a home run, from the park's own fence: the fence's distance at the bearing and, when the height of the ball is given, the wall's height there * (`wall` data of the park: the stretches of fence with their heights). A ball in fair territory that came down beyond the fence is a home run; one that was * lower than the wall where it crossed struck the wall and is in play. Where the park holds no height for the bearing the answer to a question that needs it * is `homeRun: undefined`, and `wallData` says whether the park has any heights at all. `park` is a key of `PARKS` (or a park); the place is in the frame of `options.frame` * (`retrosheet` and `mlbam` are the usual) or the drawing's own. * @example * ```ts * import { homeRun } from "@johnmorrisdotca/kyogijo-stadiums/zones"; * // Fenway Park's Green Monster is 37 feet 2 inches high, 310 feet down the line in left. * console.log(homeRun("fenway-park", [-250, 250], { frame: "retrosheet", height: 30 }).reason, homeRun("fenway-park", [-250, 250], { frame: "retrosheet", height: 40 }).reason); * // struck-wall cleared * ``` */ export declare function homeRun(park: string | Park, point: PlaceLike, options?: HomeRunOptions): HomeRunVerdict; /** `homeRun` as a yes or no: `true` for a home run, `false` for foul, in play or the wall struck, `undefined` where the park's wall height is missing and the decision needs it. */ export declare const isHomeRun: (park: string | Park, point: PlaceLike, options?: HomeRunOptions) => boolean | undefined;