@johnmorrisdotca/kyogijo-stadiums 0.4.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.
Files changed (361) hide show
  1. package/CHANGELOG.md +133 -0
  2. package/NOTICE.md +182 -2
  3. package/README.md +106 -19
  4. package/dist/annotate.js +1 -1
  5. package/dist/arenas-entry.d.ts +4 -0
  6. package/dist/arenas-entry.js +3 -0
  7. package/dist/arenas.d.ts +125 -0
  8. package/dist/arenas.data.d.ts +2 -0
  9. package/dist/arenas.data.js +3763 -0
  10. package/dist/arenas.js +72 -0
  11. package/dist/athletics/describe.d.ts +8 -0
  12. package/dist/athletics/describe.js +41 -0
  13. package/dist/athletics/events.d.ts +17 -0
  14. package/dist/athletics/events.js +48 -0
  15. package/dist/athletics/facilities.d.ts +80 -0
  16. package/dist/athletics/facilities.js +176 -0
  17. package/dist/athletics/infield.d.ts +79 -0
  18. package/dist/athletics/infield.js +166 -0
  19. package/dist/athletics/layout.d.ts +13 -0
  20. package/dist/athletics/layout.js +98 -0
  21. package/dist/athletics/oval.d.ts +57 -0
  22. package/dist/athletics/oval.js +116 -0
  23. package/dist/athletics/plan.d.ts +97 -0
  24. package/dist/athletics/plan.js +355 -0
  25. package/dist/athletics/races.d.ts +102 -0
  26. package/dist/athletics/races.js +355 -0
  27. package/dist/athletics/steeplechase.d.ts +72 -0
  28. package/dist/athletics/steeplechase.js +196 -0
  29. package/dist/athletics/stencil.d.ts +13 -0
  30. package/dist/athletics/stencil.js +85 -0
  31. package/dist/athletics/track.d.ts +54 -0
  32. package/dist/athletics/track.js +105 -0
  33. package/dist/athletics/types.d.ts +77 -0
  34. package/dist/athletics/types.js +1 -0
  35. package/dist/athletics-entry.d.ts +17 -0
  36. package/dist/athletics-entry.js +11 -0
  37. package/dist/athletics.style.d.ts +16 -0
  38. package/dist/athletics.style.js +51 -0
  39. package/dist/atlas-entry.d.ts +6 -2
  40. package/dist/atlas-entry.js +4 -2
  41. package/dist/atlas.d.ts +117 -23
  42. package/dist/atlas.js +197 -12
  43. package/dist/background.js +2 -1
  44. package/dist/budo/describe.d.ts +13 -0
  45. package/dist/budo/describe.js +120 -0
  46. package/dist/budo/dojo.api.d.ts +64 -0
  47. package/dist/budo/dojo.api.js +46 -0
  48. package/dist/budo/dojo.d.ts +72 -0
  49. package/dist/budo/dojo.js +300 -0
  50. package/dist/budo/judo.d.ts +61 -0
  51. package/dist/budo/judo.js +109 -0
  52. package/dist/budo/karate.d.ts +29 -0
  53. package/dist/budo/karate.js +80 -0
  54. package/dist/budo/kendo.d.ts +18 -0
  55. package/dist/budo/kendo.js +44 -0
  56. package/dist/budo/kimarite.d.ts +19 -0
  57. package/dist/budo/kimarite.js +33 -0
  58. package/dist/budo/kit.d.ts +16 -0
  59. package/dist/budo/kit.js +24 -0
  60. package/dist/budo/kyudo.d.ts +28 -0
  61. package/dist/budo/kyudo.js +66 -0
  62. package/dist/budo/looks.d.ts +28 -0
  63. package/dist/budo/looks.js +58 -0
  64. package/dist/budo/parts.d.ts +32 -0
  65. package/dist/budo/parts.js +10 -0
  66. package/dist/budo/plan.d.ts +64 -0
  67. package/dist/budo/plan.js +139 -0
  68. package/dist/budo/room.d.ts +133 -0
  69. package/dist/budo/room.js +111 -0
  70. package/dist/budo/sumo.d.ts +31 -0
  71. package/dist/budo/sumo.js +71 -0
  72. package/dist/budo/tatami.d.ts +55 -0
  73. package/dist/budo/tatami.js +156 -0
  74. package/dist/budo/types.d.ts +192 -0
  75. package/dist/budo/types.js +2 -0
  76. package/dist/budo-entry.d.ts +22 -0
  77. package/dist/budo-entry.js +13 -0
  78. package/dist/budo.board.d.ts +28 -0
  79. package/dist/budo.board.js +81 -0
  80. package/dist/budo.score.d.ts +18 -0
  81. package/dist/budo.score.js +52 -0
  82. package/dist/budo.style.d.ts +6 -0
  83. package/dist/budo.style.js +67 -0
  84. package/dist/charts-entry.d.ts +6 -1
  85. package/dist/charts-entry.js +3 -0
  86. package/dist/charts.athletics.d.ts +183 -0
  87. package/dist/charts.athletics.js +455 -0
  88. package/dist/charts.baseball.js +1 -1
  89. package/dist/charts.curling.heat.d.ts +24 -0
  90. package/dist/charts.curling.heat.js +116 -0
  91. package/dist/charts.curling.js +14 -3
  92. package/dist/charts.js +4 -4
  93. package/dist/charts.pool.d.ts +67 -0
  94. package/dist/charts.pool.js +76 -0
  95. package/dist/charts.skating.d.ts +204 -0
  96. package/dist/charts.skating.js +426 -0
  97. package/dist/charts.soccer.js +3 -3
  98. package/dist/charts.types.d.ts +63 -1
  99. package/dist/colour.d.ts +4 -4
  100. package/dist/colour.js +4 -4
  101. package/dist/court.d.ts +85 -2
  102. package/dist/court.js +102 -7
  103. package/dist/court.more.d.ts +46 -0
  104. package/dist/court.more.js +219 -0
  105. package/dist/courts.style.d.ts +14 -2
  106. package/dist/courts.style.js +51 -4
  107. package/dist/crowd.d.ts +164 -0
  108. package/dist/crowd.draw.d.ts +17 -0
  109. package/dist/crowd.draw.js +204 -0
  110. package/dist/crowd.js +480 -0
  111. package/dist/crowd.park.d.ts +19 -0
  112. package/dist/crowd.park.js +153 -0
  113. package/dist/curling.stats.d.ts +271 -0
  114. package/dist/curling.stats.js +301 -0
  115. package/dist/draw.d.ts +16 -0
  116. package/dist/draw.js +462 -54
  117. package/dist/element-entry.d.ts +3 -1
  118. package/dist/element-entry.js +2 -1
  119. package/dist/element.d.ts +13 -2
  120. package/dist/element.js +79 -4
  121. package/dist/emblems-source.d.ts +50 -0
  122. package/dist/emblems-source.js +56 -0
  123. package/dist/eras.d.ts +3 -1
  124. package/dist/eras.js +8 -3
  125. package/dist/features.js +204 -0
  126. package/dist/field.data.d.ts +16 -0
  127. package/dist/field.data.js +50 -0
  128. package/dist/fields.kit.d.ts +2 -2
  129. package/dist/fields.types.d.ts +24 -4
  130. package/dist/formations.js +18 -7
  131. package/dist/formations.sports.d.ts +8 -0
  132. package/dist/formations.sports.js +251 -0
  133. package/dist/frames.providers.js +71 -8
  134. package/dist/geojson.js +3 -0
  135. package/dist/geometry-entry.d.ts +2 -1
  136. package/dist/geometry-entry.js +2 -1
  137. package/dist/geometry.d.ts +20 -0
  138. package/dist/geometry.js +78 -1
  139. package/dist/grounds.d.ts +4 -0
  140. package/dist/grounds.data.js +12 -0
  141. package/dist/halls.d.ts +65 -0
  142. package/dist/halls.js +122 -0
  143. package/dist/hardwood.d.ts +31 -0
  144. package/dist/hardwood.js +157 -0
  145. package/dist/heat.js +21 -13
  146. package/dist/heat.types.d.ts +5 -0
  147. package/dist/heat.zones.d.ts +4 -2
  148. package/dist/heat.zones.js +207 -7
  149. package/dist/homeside.js +24 -0
  150. package/dist/index.d.ts +30 -4
  151. package/dist/index.js +18 -2
  152. package/dist/layers-entry.d.ts +2 -1
  153. package/dist/layers-entry.js +1 -0
  154. package/dist/layers.d.ts +2 -1
  155. package/dist/layers.env.d.ts +12 -1
  156. package/dist/layers.env.js +36 -4
  157. package/dist/layers.js +32 -13
  158. package/dist/layers.types.d.ts +9 -2
  159. package/dist/leagues/athletics.d.ts +63 -0
  160. package/dist/leagues/athletics.js +87 -0
  161. package/dist/leagues/budo.d.ts +196 -0
  162. package/dist/leagues/budo.js +105 -0
  163. package/dist/leagues/courts.d.ts +269 -4
  164. package/dist/leagues/courts.js +155 -1
  165. package/dist/leagues/hockey.js +41 -19
  166. package/dist/leagues/skating.d.ts +145 -0
  167. package/dist/leagues/skating.js +73 -0
  168. package/dist/leagues/sources.js +41 -0
  169. package/dist/leagues/types.d.ts +1 -1
  170. package/dist/leagues-entry.d.ts +4 -2
  171. package/dist/leagues-entry.js +2 -1
  172. package/dist/leagues.d.ts +17 -4
  173. package/dist/leagues.js +246 -5
  174. package/dist/lineup.codes.d.ts +23 -0
  175. package/dist/lineup.codes.js +122 -0
  176. package/dist/logo.d.ts +25 -0
  177. package/dist/logo.js +47 -0
  178. package/dist/look.d.ts +3 -3
  179. package/dist/look.js +39 -6
  180. package/dist/outline.d.ts +1 -1
  181. package/dist/outline.js +46 -4
  182. package/dist/pageant.d.ts +120 -0
  183. package/dist/pageant.draw.d.ts +21 -0
  184. package/dist/pageant.draw.js +171 -0
  185. package/dist/pageant.js +211 -0
  186. package/dist/pageant.style.d.ts +8 -0
  187. package/dist/pageant.style.js +42 -0
  188. package/dist/png.d.ts +8 -1
  189. package/dist/png.js +21 -1
  190. package/dist/pointer-entry.d.ts +2 -0
  191. package/dist/pointer-entry.js +2 -0
  192. package/dist/pointer.d.ts +113 -0
  193. package/dist/pointer.js +151 -0
  194. package/dist/pool.d.ts +176 -0
  195. package/dist/pool.figures.d.ts +306 -0
  196. package/dist/pool.figures.js +148 -0
  197. package/dist/pool.js +304 -0
  198. package/dist/pool.kit.d.ts +48 -0
  199. package/dist/pool.kit.js +141 -0
  200. package/dist/pool.labels.d.ts +20 -0
  201. package/dist/pool.labels.js +258 -0
  202. package/dist/pool.race.d.ts +65 -0
  203. package/dist/pool.race.js +140 -0
  204. package/dist/pool.replay.d.ts +46 -0
  205. package/dist/pool.replay.js +127 -0
  206. package/dist/pool.section.d.ts +13 -0
  207. package/dist/pool.section.js +83 -0
  208. package/dist/pool.style.d.ts +20 -0
  209. package/dist/pool.style.js +169 -0
  210. package/dist/pool.types.d.ts +145 -0
  211. package/dist/pool.types.js +3 -0
  212. package/dist/pool.words.d.ts +13 -0
  213. package/dist/pool.words.js +101 -0
  214. package/dist/ranges.names.js +53 -3
  215. package/dist/replay-entry.d.ts +3 -0
  216. package/dist/replay-entry.js +2 -0
  217. package/dist/restyle.js +1 -1
  218. package/dist/road.draw.js +3 -2
  219. package/dist/road.js +2 -1
  220. package/dist/road.types.d.ts +3 -0
  221. package/dist/rules.d.ts +138 -0
  222. package/dist/rules.js +511 -0
  223. package/dist/rules.types.d.ts +4 -0
  224. package/dist/rules.types.js +64 -0
  225. package/dist/score.d.ts +3 -0
  226. package/dist/score.js +93 -6
  227. package/dist/sheet.d.ts +3 -0
  228. package/dist/sheet.js +7 -3
  229. package/dist/situation.d.ts +135 -0
  230. package/dist/situation.draw.d.ts +34 -0
  231. package/dist/situation.draw.js +202 -0
  232. package/dist/situation.js +337 -0
  233. package/dist/situation.style.d.ts +2 -0
  234. package/dist/situation.style.js +45 -0
  235. package/dist/situation.types.d.ts +77 -0
  236. package/dist/situation.types.js +3 -0
  237. package/dist/situation.widgets.d.ts +39 -0
  238. package/dist/situation.widgets.js +129 -0
  239. package/dist/skating/describe.d.ts +7 -0
  240. package/dist/skating/describe.js +44 -0
  241. package/dist/skating/events.d.ts +24 -0
  242. package/dist/skating/events.js +47 -0
  243. package/dist/skating/figure.d.ts +24 -0
  244. package/dist/skating/figure.js +37 -0
  245. package/dist/skating/long.d.ts +54 -0
  246. package/dist/skating/long.js +111 -0
  247. package/dist/skating/parts.d.ts +43 -0
  248. package/dist/skating/parts.js +40 -0
  249. package/dist/skating/plan.d.ts +55 -0
  250. package/dist/skating/plan.js +197 -0
  251. package/dist/skating/short.d.ts +47 -0
  252. package/dist/skating/short.js +89 -0
  253. package/dist/skating/track.d.ts +66 -0
  254. package/dist/skating/track.js +94 -0
  255. package/dist/skating/types.d.ts +57 -0
  256. package/dist/skating/types.js +3 -0
  257. package/dist/skating-entry.d.ts +17 -0
  258. package/dist/skating-entry.js +11 -0
  259. package/dist/skating.style.d.ts +4 -0
  260. package/dist/skating.style.js +24 -0
  261. package/dist/strings.d.ts +470 -0
  262. package/dist/strings.js +674 -13
  263. package/dist/style.d.ts +2 -0
  264. package/dist/style.js +19 -2
  265. package/dist/surfaces/artistic.d.ts +9 -0
  266. package/dist/surfaces/artistic.js +94 -0
  267. package/dist/surfaces/athletics.d.ts +16 -0
  268. package/dist/surfaces/athletics.js +132 -0
  269. package/dist/surfaces/baseball.js +17 -0
  270. package/dist/surfaces/basketball.floor.d.ts +27 -0
  271. package/dist/surfaces/basketball.floor.js +83 -0
  272. package/dist/surfaces/basketball.gear.d.ts +27 -0
  273. package/dist/surfaces/basketball.gear.js +90 -0
  274. package/dist/surfaces/basketball.js +44 -22
  275. package/dist/surfaces/budo.d.ts +6 -0
  276. package/dist/surfaces/budo.js +104 -0
  277. package/dist/surfaces/curling.d.ts +16 -0
  278. package/dist/surfaces/curling.fold.d.ts +67 -0
  279. package/dist/surfaces/curling.fold.js +107 -0
  280. package/dist/surfaces/curling.js +37 -3
  281. package/dist/surfaces/dive.d.ts +9 -0
  282. package/dist/surfaces/dive.js +128 -0
  283. package/dist/surfaces/field.d.ts +7 -2
  284. package/dist/surfaces/field.js +15 -9
  285. package/dist/surfaces/football.js +7 -0
  286. package/dist/surfaces/hockey.js +4 -2
  287. package/dist/surfaces/net.d.ts +2 -1
  288. package/dist/surfaces/net.js +160 -15
  289. package/dist/surfaces/polo.d.ts +12 -0
  290. package/dist/surfaces/polo.js +159 -0
  291. package/dist/surfaces/pool.d.ts +27 -0
  292. package/dist/surfaces/pool.js +198 -0
  293. package/dist/surfaces/skating.d.ts +6 -0
  294. package/dist/surfaces/skating.js +62 -0
  295. package/dist/surfaces/soccer.js +2 -1
  296. package/dist/surfaces/surface.d.ts +76 -0
  297. package/dist/surfaces/venue.d.ts +15 -0
  298. package/dist/surfaces/venue.js +95 -0
  299. package/dist/target-entry.d.ts +2 -0
  300. package/dist/target-entry.js +2 -0
  301. package/dist/target.d.ts +200 -0
  302. package/dist/target.js +525 -0
  303. package/dist/team.common.d.ts +1 -1
  304. package/dist/team.common.js +3 -3
  305. package/dist/team.formation.d.ts +3 -1
  306. package/dist/team.formation.js +3 -3
  307. package/dist/team.layers.d.ts +2 -2
  308. package/dist/team.layers.js +4 -1
  309. package/dist/team.lineup.d.ts +27 -0
  310. package/dist/team.lineup.js +207 -0
  311. package/dist/team.network.js +6 -5
  312. package/dist/team.shape.js +5 -5
  313. package/dist/team.types.d.ts +40 -1
  314. package/dist/tenants.d.ts +77 -0
  315. package/dist/tenants.data.d.ts +8 -0
  316. package/dist/tenants.data.js +1793 -0
  317. package/dist/tenants.js +46 -0
  318. package/dist/turn-entry.d.ts +12 -0
  319. package/dist/turn-entry.js +7 -0
  320. package/dist/turn.camera.d.ts +116 -0
  321. package/dist/turn.camera.js +184 -0
  322. package/dist/turn.dom.d.ts +40 -0
  323. package/dist/turn.dom.js +353 -0
  324. package/dist/turn.kit.d.ts +86 -0
  325. package/dist/turn.kit.js +110 -0
  326. package/dist/turn.markup.d.ts +48 -0
  327. package/dist/turn.markup.js +108 -0
  328. package/dist/turn.model.d.ts +78 -0
  329. package/dist/turn.model.js +91 -0
  330. package/dist/turn.style.d.ts +5 -0
  331. package/dist/turn.style.js +56 -0
  332. package/dist/types.d.ts +221 -20
  333. package/dist/units.d.ts +1 -1
  334. package/dist/units.js +22 -1
  335. package/dist/uprights.board.d.ts +17 -0
  336. package/dist/uprights.board.js +59 -0
  337. package/dist/uprights.budo.d.ts +17 -0
  338. package/dist/uprights.budo.js +87 -0
  339. package/dist/uprights.d.ts +37 -0
  340. package/dist/uprights.fields.d.ts +32 -0
  341. package/dist/uprights.fields.js +172 -0
  342. package/dist/uprights.goal.d.ts +49 -0
  343. package/dist/uprights.goal.js +69 -0
  344. package/dist/uprights.js +169 -0
  345. package/dist/uprights.more.d.ts +7 -0
  346. package/dist/uprights.more.js +183 -0
  347. package/dist/uprights.net.d.ts +12 -0
  348. package/dist/uprights.net.js +109 -0
  349. package/dist/uprights.netkit.d.ts +28 -0
  350. package/dist/uprights.netkit.js +67 -0
  351. package/dist/uprights.pools.d.ts +8 -0
  352. package/dist/uprights.pools.js +190 -0
  353. package/dist/uprights.rinks.d.ts +27 -0
  354. package/dist/uprights.rinks.js +106 -0
  355. package/dist/uprights.track.d.ts +50 -0
  356. package/dist/uprights.track.js +246 -0
  357. package/dist/version.d.ts +1 -1
  358. package/dist/version.js +1 -1
  359. package/dist/zones-entry.d.ts +2 -0
  360. package/dist/zones-entry.js +2 -0
  361. package/package.json +56 -3
package/dist/arenas.js ADDED
@@ -0,0 +1,72 @@
1
+ import { ARENA_DATA } from "./arenas.data.js";
2
+ import { officialName, placesNamed } from "./names.js";
3
+ const FEET_PER_METRE = 1 / 0.3048;
4
+ const tenth = (feet) => Math.round(feet * 10) / 10;
5
+ const inFeet = (size) => {
6
+ const k = size.unit === "m" ? FEET_PER_METRE : 1;
7
+ return { length: tenth(size.length * k), width: tenth(size.width * k) };
8
+ };
9
+ /** The size that held in a year: the one whose years cover it, else (with no year) the latest. */
10
+ const sizeIn = (sizes, year) => {
11
+ if (sizes === undefined || sizes.length === 0)
12
+ return undefined;
13
+ if (year === undefined || !Number.isFinite(year))
14
+ return inFeet(sizes.find((size) => size.to === undefined) ?? sizes[sizes.length - 1]);
15
+ const found = sizes.find((size) => (size.from === undefined || size.from <= year) && (size.to === undefined || year <= size.to));
16
+ return found === undefined ? undefined : inFeet(found);
17
+ };
18
+ /**
19
+ * The size of an arena's rink in feet, in a year or today (the latest), when the sources publish one that differs from the NHL's; else `undefined` and the NHL's 200 by 85 feet
20
+ * is the rink.
21
+ * @example
22
+ * ```ts
23
+ * import { arenaById, arenaRinkIn } from "@johnmorrisdotca/kyogijo-stadiums/arenas";
24
+ * console.log(arenaRinkIn(arenaById("boston-garden")!), arenaRinkIn(arenaById("matthews-arena")!, 1926), arenaRinkIn(arenaById("td-garden")!));
25
+ * // { length: 190.9, width: 83 } { length: 220, width: 90 } undefined
26
+ * ```
27
+ */
28
+ export const arenaRinkIn = (arena, year) => sizeIn(arena?.rink, year);
29
+ /** The size of an arena's court in feet, in a year or today, when the sources publish one that differs from the NBA's 94 by 50 feet; else `undefined`. */
30
+ export const arenaCourtIn = (arena, year) => sizeIn(arena?.court, year);
31
+ /**
32
+ * Every arena by its key: the homes of the NHL's, the NBA's, the WNBA's and the PWHL's clubs, today's and the old ones, each with where it stands, when it was in use, its names,
33
+ * its seats for each sport and, where the sources publish one that differs from the league's, the size of its rink or its court.
34
+ * @example
35
+ * ```ts
36
+ * import { ARENAS } from "@johnmorrisdotca/kyogijo-stadiums/arenas";
37
+ * const garden = ARENAS["boston-garden"];
38
+ * console.log(garden.name, garden.city, garden.from, garden.to, garden.capacity?.hockey);
39
+ * // Boston Garden Boston 1928 1995 14448
40
+ * ```
41
+ */
42
+ export const ARENAS = Object.freeze(Object.fromEntries(ARENA_DATA.map((data) => [data.id, data])));
43
+ /** The keys of `ARENAS`, in the order of the data: the arenas in use first, then those of the past. */
44
+ export const ARENA_IDS = Object.freeze(ARENA_DATA.map((data) => data.id));
45
+ /** The arena with a key, or `undefined`. */
46
+ export const arenaById = (id) => (id !== undefined && Object.prototype.hasOwnProperty.call(ARENAS, id) ? ARENAS[id] : undefined);
47
+ /** The arenas that answer to a name, best match first (see `placesByName`): the everyday names, then the official and cited names, then the former names and the nicknames. */
48
+ export const arenasByName = (name) => placesNamed(Object.values(ARENAS), name);
49
+ /** The arena a name belongs to (the best match when several answer to it), or `undefined`. */
50
+ export const arenaByName = (name) => arenasByName(name)[0];
51
+ /** The arena whose Wikidata item is `Q894567`, or `undefined`. */
52
+ export const arenaByWikidata = (wikidata) => Object.values(ARENAS).find((arena) => arena.wikidata === wikidata);
53
+ /** The name an arena had in a year (the name of the time in English; in Japanese there is one name for every year). */
54
+ export function arenaNameIn(arena, year, language = "en") {
55
+ if (language === "ja")
56
+ return arena.nameJa;
57
+ if (year === undefined || !Number.isFinite(year))
58
+ return arena.name;
59
+ const periods = (arena.names ?? []).filter((period) => period.from <= year && year <= period.to);
60
+ return periods.length === 0 ? arena.name : periods[periods.length - 1].name;
61
+ }
62
+ /** The name an arena officially has in a language, when it is not the everyday name; else `undefined`. */
63
+ export function arenaOfficialName(arena, language = "en", year) {
64
+ const shown = arenaNameIn(arena, year, language);
65
+ if (year !== undefined && Number.isFinite(year) && language === "en" && shown !== arena.name)
66
+ return undefined;
67
+ return officialName(arena, language, shown, Number.isFinite(year) ? year : undefined);
68
+ }
69
+ /** The address of the revision of an article that an arena's facts were read from. */
70
+ export function arenaSourceUrl(source, language = "en") {
71
+ return `https://${language}.wikipedia.org/w/index.php?title=${encodeURIComponent(source.title.replace(/ /g, "_"))}&oldid=${source.revision}`;
72
+ }
@@ -0,0 +1,8 @@
1
+ import type { Language, SurfaceOptions } from "../types.ts";
2
+ /** The words of a race or a field event in a language. */
3
+ export declare const raceName: (id: string, language: Language) => string;
4
+ export declare const fieldEventName: (id: string, language: Language) => string;
5
+ /** The sentence about the track, as a fragment: "an athletics track of 400 metres with 8 lanes...". */
6
+ export declare function athleticsAbout(o: Pick<SurfaceOptions, "sport" | "league" | "athletics">, language: Language): string;
7
+ /** The sentences that follow it: the infield, the events and the races marked, the close-up and the layout. Each starts after a gap. */
8
+ export declare function athleticsSentences(o: Pick<SurfaceOptions, "sport" | "league" | "athletics" | "range">, language: Language): string;
@@ -0,0 +1,41 @@
1
+ // What an athletics drawing says of itself: its sentence about the track, and what the options mark on it. Cheap (it reads the options, not the plan), so that a title and a description cost nothing.
2
+ import { fill, KYOGIJO_STRINGS } from "../strings.js";
3
+ import { fieldEventById, raceById } from "./events.js";
4
+ import { athleticsLanes, athleticsLeague, eventsOf, racesOf } from "./plan.js";
5
+ /** The words of a race or a field event in a language. */
6
+ export const raceName = (id, language) => raceById(id)?.name[language] ?? id;
7
+ export const fieldEventName = (id, language) => fieldEventById(id)?.name[language] ?? id;
8
+ /** The sentence about the track, as a fragment: "an athletics track of 400 metres with 8 lanes...". */
9
+ export function athleticsAbout(o, language) {
10
+ const words = KYOGIJO_STRINGS[language].athletics;
11
+ const league = athleticsLeague(o);
12
+ return fill(league.dimensions.banking === null ? words.track400 : words.track200, { lanes: athleticsLanes(o) });
13
+ }
14
+ /** The sentences that follow it: the infield, the events and the races marked, the close-up and the layout. Each starts after a gap. */
15
+ export function athleticsSentences(o, language) {
16
+ const words = KYOGIJO_STRINGS[language].athletics;
17
+ const { gap } = KYOGIJO_STRINGS[language].said;
18
+ const sep = KYOGIJO_STRINGS[language].layers.listSep;
19
+ const style = o.athletics;
20
+ const league = athleticsLeague(o);
21
+ const indoor = league.dimensions.banking !== null;
22
+ const out = [];
23
+ if (style?.layout !== undefined)
24
+ return `${gap}${fill(words.layout, { event: fieldEventName(style.layout, language) })}`;
25
+ const infield = style?.infield ?? (indoor ? "none" : "pitch");
26
+ out.push(infield === "pitch" ? words.infieldPitch : infield === "grass" ? words.infieldGrass : words.infieldNone);
27
+ if (!indoor) {
28
+ const events = eventsOf(style);
29
+ if (events.length > 0)
30
+ out.push(fill(words.events, { list: events.map((e) => fieldEventName(e, language)).join(sep) }));
31
+ }
32
+ const races = racesOf(style, indoor);
33
+ if (races.length > 0)
34
+ out.push(fill(words.races, { list: races.map((r) => r.name[language]).join(sep) }));
35
+ const range = typeof o.range === "string" ? o.range : typeof o.range === "object" && o.range !== null && "name" in o.range ? o.range.name : undefined;
36
+ if (range === "start")
37
+ out.push(fill(words.start, { race: raceName(style?.start ?? "400m", language) }));
38
+ if (range === "finish")
39
+ out.push(words.finish);
40
+ return out.map((t) => `${gap}${t}`).join("");
41
+ }
@@ -0,0 +1,17 @@
1
+ import type { AthleticsFieldEvent, AthleticsRace, FieldEventInfo, RaceInfo } from "./types.ts";
2
+ /**
3
+ * The races, in the order a menu lists them. `kind` says how the start is made: `straight` (the sprints and the sprint hurdles, on the finish straight), `stagger` (the lanes' staggers of Table
4
+ * 2.2.1.6a: `bends` half-turns in lanes), `curved` (a curved start line, the waterfall, for a race run without lanes) and `steeplechase` (the water jump's lap). The breakline (Rule 17.5.1) is the
5
+ * 800 m's and the 4 x 400 m's; the group starts (Rule 17.5.2) are those of the races over 1000 m.
6
+ */
7
+ export declare const RACES: readonly RaceInfo[];
8
+ /** The ids of the races. */
9
+ export declare const RACE_IDS: readonly AthleticsRace[];
10
+ /** A race by its id, or `undefined`. */
11
+ export declare const raceById: (id: unknown) => RaceInfo | undefined;
12
+ /** The field events, in the order a menu lists them: the jumps and then the throws. */
13
+ export declare const FIELD_EVENTS: readonly FieldEventInfo[];
14
+ /** The ids of the field events. */
15
+ export declare const FIELD_EVENT_IDS: readonly AthleticsFieldEvent[];
16
+ /** A field event by its id, or `undefined`. */
17
+ export declare const fieldEventById: (id: unknown) => FieldEventInfo | undefined;
@@ -0,0 +1,48 @@
1
+ const race = (r) => Object.freeze(r);
2
+ /**
3
+ * The races, in the order a menu lists them. `kind` says how the start is made: `straight` (the sprints and the sprint hurdles, on the finish straight), `stagger` (the lanes' staggers of Table
4
+ * 2.2.1.6a: `bends` half-turns in lanes), `curved` (a curved start line, the waterfall, for a race run without lanes) and `steeplechase` (the water jump's lap). The breakline (Rule 17.5.1) is the
5
+ * 800 m's and the 4 x 400 m's; the group starts (Rule 17.5.2) are those of the races over 1000 m.
6
+ */
7
+ export const RACES = Object.freeze([
8
+ race({ id: "60m", distance: 60, kind: "straight", indoor: true, name: { en: "60 m", ja: "60m", fr: "60\u00a0m" } }),
9
+ race({ id: "60m-hurdles", distance: 60, kind: "straight", hurdles: true, indoor: true, name: { en: "60 m hurdles", ja: "60mハードル", fr: "60\u00a0m haies" } }),
10
+ race({ id: "100m", distance: 100, kind: "straight", name: { en: "100 m", ja: "100m", fr: "100\u00a0m" } }),
11
+ race({ id: "100m-hurdles", distance: 100, kind: "straight", hurdles: true, name: { en: "100 m hurdles", ja: "100mハードル", fr: "100\u00a0m haies" } }),
12
+ race({ id: "110m-hurdles", distance: 110, kind: "straight", hurdles: true, name: { en: "110 m hurdles", ja: "110mハードル", fr: "110\u00a0m haies" } }),
13
+ race({ id: "200m", distance: 200, kind: "stagger", bends: 1, name: { en: "200 m", ja: "200m", fr: "200\u00a0m" } }),
14
+ race({ id: "400m", distance: 400, kind: "stagger", bends: 2, name: { en: "400 m", ja: "400m", fr: "400\u00a0m" } }),
15
+ race({ id: "400m-hurdles", distance: 400, kind: "stagger", bends: 2, hurdles: true, name: { en: "400 m hurdles", ja: "400mハードル", fr: "400\u00a0m haies" } }),
16
+ race({ id: "800m", distance: 800, kind: "stagger", bends: 1, breakline: true, name: { en: "800 m", ja: "800m", fr: "800\u00a0m" } }),
17
+ race({ id: "1000m", distance: 1000, kind: "curved", group: true, name: { en: "1000 m", ja: "1000m", fr: "1000\u00a0m" } }),
18
+ race({ id: "1500m", distance: 1500, kind: "curved", name: { en: "1500 m", ja: "1500m", fr: "1500\u00a0m" } }),
19
+ race({ id: "mile", distance: 1609.344, kind: "curved", name: { en: "Mile", ja: "1マイル", fr: "Mile" } }),
20
+ race({ id: "2000m", distance: 2000, kind: "curved", group: true, name: { en: "2000 m", ja: "2000m", fr: "2000\u00a0m" } }),
21
+ race({ id: "3000m", distance: 3000, kind: "curved", group: true, name: { en: "3000 m", ja: "3000m", fr: "3000\u00a0m" } }),
22
+ race({ id: "5000m", distance: 5000, kind: "curved", group: true, name: { en: "5000 m", ja: "5000m", fr: "5000\u00a0m" } }),
23
+ race({ id: "10000m", distance: 10000, kind: "curved", group: true, name: { en: "10,000 m", ja: "10000m", fr: "10\u00a0000\u00a0m" } }),
24
+ race({ id: "2000m-steeplechase", distance: 2000, kind: "steeplechase", name: { en: "2000 m steeplechase", ja: "2000m障害物競走", fr: "2000\u00a0m steeple" } }),
25
+ race({ id: "3000m-steeplechase", distance: 3000, kind: "steeplechase", group: true, name: { en: "3000 m steeplechase", ja: "3000m障害物競走", fr: "3000\u00a0m steeple" } }),
26
+ race({ id: "4x100m", distance: 400, kind: "stagger", bends: 2, legs: [100, 100, 100, 100], name: { en: "4 x 100 m relay", ja: "4×100mリレー", fr: "Relais 4\u00a0×\u00a0100\u00a0m" } }),
27
+ race({ id: "4x400m", distance: 1600, kind: "stagger", bends: 3, breakline: true, legs: [400, 400, 400, 400], name: { en: "4 x 400 m relay", ja: "4×400mリレー", fr: "Relais 4\u00a0×\u00a0400\u00a0m" } }),
28
+ ]);
29
+ /** The ids of the races. */
30
+ export const RACE_IDS = Object.freeze(RACES.map((r) => r.id));
31
+ /** A race by its id, or `undefined`. */
32
+ export const raceById = (id) => RACES.find((r) => r.id === id);
33
+ const field = (f) => Object.freeze(f);
34
+ /** The field events, in the order a menu lists them: the jumps and then the throws. */
35
+ export const FIELD_EVENTS = Object.freeze([
36
+ field({ id: "high-jump", name: { en: "High jump", ja: "走高跳", fr: "Saut en hauteur" } }),
37
+ field({ id: "pole-vault", name: { en: "Pole vault", ja: "棒高跳", fr: "Saut à la perche" } }),
38
+ field({ id: "long-jump", name: { en: "Long jump", ja: "走幅跳", fr: "Saut en longueur" } }),
39
+ field({ id: "triple-jump", name: { en: "Triple jump", ja: "三段跳", fr: "Triple saut" } }),
40
+ field({ id: "shot-put", name: { en: "Shot put", ja: "砲丸投", fr: "Lancer du poids" } }),
41
+ field({ id: "discus-throw", name: { en: "Discus throw", ja: "円盤投", fr: "Lancer du disque" } }),
42
+ field({ id: "hammer-throw", name: { en: "Hammer throw", ja: "ハンマー投", fr: "Lancer du marteau" } }),
43
+ field({ id: "javelin-throw", name: { en: "Javelin throw", ja: "やり投", fr: "Lancer du javelot" } }),
44
+ ]);
45
+ /** The ids of the field events. */
46
+ export const FIELD_EVENT_IDS = Object.freeze(FIELD_EVENTS.map((f) => f.id));
47
+ /** A field event by its id, or `undefined`. */
48
+ export const fieldEventById = (id) => FIELD_EVENTS.find((f) => f.id === id);
@@ -0,0 +1,80 @@
1
+ import type { Area, Shape } from "../fields.types.ts";
2
+ import type { Parts } from "./oval.ts";
3
+ import type { AthleticsFieldEvent } from "./types.ts";
4
+ /** A point in the plan. */
5
+ type Pt = readonly [number, number];
6
+ /** What a facility is, as data: where it stands, which way it throws or jumps, and the figures that say how big it is. */
7
+ export interface Facility {
8
+ id: string;
9
+ event: AthleticsFieldEvent;
10
+ /** The throw's circle centre, the javelin arc's centre point, the high jump's bar centre, the pole vault's box, the jump's take-off board. */
11
+ x: number;
12
+ y: number;
13
+ /** The direction of the throw or the jump, in radians clockwise from the right as the eye sees it. */
14
+ heading: number;
15
+ /** A box round all of it, for the ranges. */
16
+ box: {
17
+ x0: number;
18
+ y0: number;
19
+ x1: number;
20
+ y1: number;
21
+ };
22
+ /** The length of the sector, or the runway, or the run-up. */
23
+ reach?: number;
24
+ }
25
+ /** The angle of a throw's sector: 34.92 degrees (Rule 32, landing sector; Manual 2.4.1.4). Its lines are 12 m apart (the chord) 20 m from the circle's centre, 0.60 m more for each metre further: 2 asin(0.3). */
26
+ export declare const SECTOR_ANGLE: number;
27
+ /** The javelin sector's half angle: the arc's radius is 8 m and the runway 4 m wide, so the lines through the arc's ends make 28.96 degrees (Rule 32, landing sector; Figure 2.4.3.2). */
28
+ export declare const JAVELIN_HALF: number;
29
+ /** A rectangle in the plan, `w` along `heading` and `h` across it, centred at `c`, as an area. */
30
+ export declare function rectArea(id: string, cls: Area["cls"], feature: string, c: Pt, heading: number, w: number, h: number): Area;
31
+ /** The outline of the same rectangle as a line. */
32
+ export declare function rectLine(id: string, feature: string, c: Pt, heading: number, w: number, h: number, wLine: number): Shape;
33
+ /** The sector of a throw: its two lines from the circle's rim to the arc, and the arc, 50 mm wide, the inner edges through the circle's centre (Rule 32, landing sector). */
34
+ export declare function sectorShapes(id: string, feature: string, c: Pt, heading: number, rim: number, reach: number, half?: number): Shape[];
35
+ /** A throwing circle (Rule 32, throwing circle, and 32.8; Manual 2.4.1.2): the concrete inside the rim, the rim, the 0.75 m lines at right angles to the sector's axis, the centre. `d` is the inside diameter. */
36
+ export declare function circleParts(id: string, event: AthleticsFieldEvent, c: Pt, heading: number, d: number, rim?: number): Parts;
37
+ /** The shot put's stop board (Rule 33.2; Manual 2.4.4.3): an arc on the circle's inside edge, 1.21 m long (the chord), 0.112 m wide, centred on the sector's axis. */
38
+ export declare function stopBoard(id: string, c: Pt, heading: number, d: number): Area;
39
+ /**
40
+ * A discus or hammer cage in plan (Rules 35 and 37; Manual 2.4.1.3, Figure 2.4.1.2): U-shaped, its mouth 6 m wide and 7 m in front of the circle's centre, the netting no nearer than 3 m behind it. The
41
+ * mouth and the line the sides take to it are the rules'; the rear is drawn as an arc about the centre, which is ours.
42
+ */
43
+ export declare function cageShapes(id: string, c: Pt, heading: number): Shape[];
44
+ /** The javelin's runway and arc (Rule 32, javelin throw runway; Manual 2.4.3.2 and 2.4.3.3), about the centre point of the arc and the throwing direction `heading` (0 throws right). */
45
+ export declare function javelinParts(id: string, c: Pt, heading: number, runway?: number): {
46
+ parts: Parts;
47
+ facility: Facility;
48
+ };
49
+ /** The box round some points. */
50
+ export declare function bounds(points: readonly Pt[]): {
51
+ x0: number;
52
+ y0: number;
53
+ x1: number;
54
+ y1: number;
55
+ };
56
+ /**
57
+ * A high jump facility (Rule 27; Manual 2.3.3): the uprights 4.02 m apart (Rule 27.6: 4.00 to 4.04 m), the crossbar, the landing mat of 6 m by 4 m at the least (Rule 27, landing area; Manual 2.3.3.4) with the bar's
58
+ * plane 0.5 m inside its front edge, the 50 mm line 3 m outside each upright (Rule 27.2, note) and the run-up: a 16 m wide area, 15 m long (Rule 27.3: 25 m for the major competitions), drawn
59
+ * as a dashed outline cut by the arc of the 15 m radius. `heading` is the way the athlete jumps; the facility is about the bar's middle.
60
+ */
61
+ export declare function highJumpParts(id: string, c: Pt, heading: number, runup?: number): {
62
+ parts: Parts;
63
+ facility: Facility;
64
+ };
65
+ /**
66
+ * A pole vault's box and 0-line at the end of a runway (Rule 28; Manual 2.3.4.2): the box 1.00 m long, 0.60 m wide at the front and 0.15 m at the stop board, set so that the top inside
67
+ * edge of the stop board is on the 0-line, which is 10 mm wide and runs on past the uprights (5.20 m apart at the least). `c` is the middle of the stop board and `heading` the way the athlete
68
+ * runs; the landing mat of 6.00 m by 6.00 m at the least with front pieces 2 m long (Rule 28; Manual 2.3.4.4) lies beyond, its front 0.10 to 0.15 m from the box.
69
+ */
70
+ export declare function poleVaultEnd(id: string, c: Pt, heading: number): {
71
+ parts: Parts;
72
+ facility: Facility;
73
+ };
74
+ /** The runway of a jump: two lines 1.22 m apart (Rule 29; Manual 2.3.1.2) from `from` to `to` along `heading`, as lines. */
75
+ export declare function runwayLines(id: string, event: AthleticsFieldEvent, from: Pt, to: Pt, width?: number): Shape[];
76
+ /** A landing pit (Rule 30; Manual 2.3.1.4): the sand with its white border, `length` long along the jump and `width` across it, centred at `c`. */
77
+ export declare function pitParts(id: string, event: AthleticsFieldEvent, c: Pt, heading: number, length: number, width: number): Parts;
78
+ /** A take-off board (Rule 29, take-off board; Manual 2.3.1.3): 1.22 m by 0.20 m, white, whose edge nearer the pit is the take-off line, `d` metres from the pit's near end. `pitEdge` is that end's middle. */
79
+ export declare function takeOffBoard(id: string, event: AthleticsFieldEvent, pitEdge: Pt, heading: number, d: number): Area;
80
+ export {};
@@ -0,0 +1,176 @@
1
+ // The field events' facilities, each at the size the World Athletics Track and Field Facilities Manual (2019 edition, 2.3 and 2.4, Figures 2.3.1.1a, 2.3.2.1, 2.3.3.1, 2.3.4.1, 2.4.1.1 to 2.4.4.2)
2
+ // and Technical Rules 25 to 38 of Book C2.1 give, in metres, and each made about its own origin and the direction of its throw or its run: a circle, a runway, a pit, a mat, a sector. The standard
3
+ // stadium's places for them (Figure 2.5a and the Marking Plan) are in infield.ts. Nothing here draws SVG.
4
+ import { arc, line, path, poly, ring } from "../fields.kit.js";
5
+ import { num } from "../format.js";
6
+ import { arcD } from "./track.js";
7
+ import { emptyParts } from "./oval.js";
8
+ /** The angle of a throw's sector: 34.92 degrees (Rule 32, landing sector; Manual 2.4.1.4). Its lines are 12 m apart (the chord) 20 m from the circle's centre, 0.60 m more for each metre further: 2 asin(0.3). */
9
+ export const SECTOR_ANGLE = 2 * Math.asin(0.3);
10
+ /** The javelin sector's half angle: the arc's radius is 8 m and the runway 4 m wide, so the lines through the arc's ends make 28.96 degrees (Rule 32, landing sector; Figure 2.4.3.2). */
11
+ export const JAVELIN_HALF = Math.asin(2 / 8);
12
+ const f = (n) => num(n);
13
+ const at = (c, theta, k, side = 0) => [c[0] + k * Math.cos(theta) - side * Math.sin(theta), c[1] + k * Math.sin(theta) + side * Math.cos(theta)];
14
+ /** The path of a closed polygon filled as an area. */
15
+ const polyArea = (id, cls, feature, points) => ({ id, feature, cls, d: `M${points.map(([x, y]) => `${f(x)} ${f(y)}`).join("L")}Z` });
16
+ /** A rectangle in the plan, `w` along `heading` and `h` across it, centred at `c`, as an area. */
17
+ export function rectArea(id, cls, feature, c, heading, w, h) {
18
+ return polyArea(id, cls, feature, [at(c, heading, -w / 2, -h / 2), at(c, heading, w / 2, -h / 2), at(c, heading, w / 2, h / 2), at(c, heading, -w / 2, h / 2)]);
19
+ }
20
+ /** The outline of the same rectangle as a line. */
21
+ export function rectLine(id, feature, c, heading, w, h, wLine) {
22
+ return poly(id, feature, [at(c, heading, -w / 2, -h / 2), at(c, heading, w / 2, -h / 2), at(c, heading, w / 2, h / 2), at(c, heading, -w / 2, h / 2)], { closed: true, w: wLine });
23
+ }
24
+ /** The sector of a throw: its two lines from the circle's rim to the arc, and the arc, 50 mm wide, the inner edges through the circle's centre (Rule 32, landing sector). */
25
+ export function sectorShapes(id, feature, c, heading, rim, reach, half = SECTOR_ANGLE / 2) {
26
+ const a = heading - half;
27
+ const b = heading + half;
28
+ const p0 = at(c, a, rim);
29
+ const p1 = at(c, a, reach);
30
+ const q0 = at(c, b, rim);
31
+ const q1 = at(c, b, reach);
32
+ const thin = { cls: "ky-ath-s", least: 0.07 };
33
+ return [poly(`${id}-sector-line`, feature, [p0, p1], thin), poly(`${id}-sector-line`, feature, [q0, q1], thin), path(`${id}-sector-arc`, feature, arcD(c[0], c[1], reach, a, b), thin)];
34
+ }
35
+ /** A throwing circle (Rule 32, throwing circle, and 32.8; Manual 2.4.1.2): the concrete inside the rim, the rim, the 0.75 m lines at right angles to the sector's axis, the centre. `d` is the inside diameter. */
36
+ export function circleParts(id, event, c, heading, d, rim = 0.06) {
37
+ const parts = emptyParts();
38
+ const r = d / 2;
39
+ parts.areas.push({ id: `${id}-circle`, feature: event, cls: "ky-ath-concrete", d: `M${f(c[0] - r)} ${f(c[1])}A${f(r)} ${f(r)} 0 1 0 ${f(c[0] + r)} ${f(c[1])}A${f(r)} ${f(r)} 0 1 0 ${f(c[0] - r)} ${f(c[1])}Z` });
40
+ parts.shapes.push(ring(`${id}-rim`, event, c[0], c[1], r + rim / 2, r + rim / 2, { w: rim }));
41
+ for (const side of [-1, 1]) {
42
+ const p = at(c, heading, 0, side * (r + rim));
43
+ const q = at(c, heading, 0, side * (r + rim + 0.75));
44
+ parts.shapes.push(line(`${id}-circle-line`, event, p[0], p[1], q[0], q[1], { w: 0.05 }));
45
+ }
46
+ return parts;
47
+ }
48
+ /** The shot put's stop board (Rule 33.2; Manual 2.4.4.3): an arc on the circle's inside edge, 1.21 m long (the chord), 0.112 m wide, centred on the sector's axis. */
49
+ export function stopBoard(id, c, heading, d) {
50
+ const r = d / 2;
51
+ const half = Math.asin(1.21 / 2 / r);
52
+ const inner = r;
53
+ const outer = r + 0.112;
54
+ const p = (k, th) => at(c, th, k);
55
+ const a = heading - half;
56
+ const b = heading + half;
57
+ const [i0, i1, o0, o1] = [p(inner, a), p(inner, b), p(outer, a), p(outer, b)];
58
+ return { id: `${id}-stop-board`, feature: "shot-put", cls: "ky-ath-board", d: `M${f(i0[0])} ${f(i0[1])}A${f(inner)} ${f(inner)} 0 0 1 ${f(i1[0])} ${f(i1[1])}L${f(o1[0])} ${f(o1[1])}A${f(outer)} ${f(outer)} 0 0 0 ${f(o0[0])} ${f(o0[1])}Z` };
59
+ }
60
+ /**
61
+ * A discus or hammer cage in plan (Rules 35 and 37; Manual 2.4.1.3, Figure 2.4.1.2): U-shaped, its mouth 6 m wide and 7 m in front of the circle's centre, the netting no nearer than 3 m behind it. The
62
+ * mouth and the line the sides take to it are the rules'; the rear is drawn as an arc about the centre, which is ours.
63
+ */
64
+ export function cageShapes(id, c, heading) {
65
+ const mouth = [7, 3];
66
+ const wide = 4.4;
67
+ const pts = (u, v) => at(c, heading, u, v);
68
+ const back = 4.4;
69
+ const left = [pts(mouth[0], -mouth[1]), pts(0, -wide)];
70
+ const right = [pts(mouth[0], mouth[1]), pts(0, wide)];
71
+ const a0 = heading - Math.PI / 2;
72
+ const a1 = heading + Math.PI / 2;
73
+ const rear = arcD(c[0], c[1], back, a0 + Math.PI, a1 + Math.PI);
74
+ return [poly(`${id}-cage`, "cage", [left[0], left[1]], { w: 0.12, cls: "ky-ath-k" }), poly(`${id}-cage`, "cage", [right[0], right[1]], { w: 0.12, cls: "ky-ath-k" }), path(`${id}-cage`, "cage", rear, { w: 0.12, cls: "ky-ath-k" })];
75
+ }
76
+ /** The javelin's runway and arc (Rule 32, javelin throw runway; Manual 2.4.3.2 and 2.4.3.3), about the centre point of the arc and the throwing direction `heading` (0 throws right). */
77
+ export function javelinParts(id, c, heading, runway = 36.5) {
78
+ const parts = emptyParts();
79
+ const xe = 8 * Math.cos(JAVELIN_HALF);
80
+ const w = 2;
81
+ // The runway: two lines 4 m apart from the ends of the arc back `runway` metres, the arc, and the 0.75 m lines at right angles to the runway at the arc's ends.
82
+ for (const side of [-1, 1]) {
83
+ const p = at(c, heading, xe, side * w);
84
+ const q = at(c, heading, xe - runway, side * w);
85
+ parts.shapes.push(line(`${id}-runway-line`, "javelin-throw", p[0], p[1], q[0], q[1], { w: 0.05 }));
86
+ const m0 = at(c, heading, xe, side * w);
87
+ const m1 = at(c, heading, xe, side * (w + 0.75));
88
+ parts.shapes.push(line(`${id}-arc-mark`, "javelin-throw", m0[0], m0[1], m1[0], m1[1], { w: 0.07 }));
89
+ // Two white squares of 0.05 m beside the runway, 4 m back from the ends of the arc.
90
+ const sq = at(c, heading, xe - 4, side * (w + 0.12));
91
+ parts.shapes.push(line(`${id}-square`, "javelin-throw", sq[0], sq[1], sq[0], sq[1], { w: 0.05 }));
92
+ }
93
+ parts.shapes.push(arc(`${id}-arc`, "javelin-throw", c[0], c[1], 8, (heading - JAVELIN_HALF) * (180 / Math.PI), (heading + JAVELIN_HALF) * (180 / Math.PI), { w: 0.07 }));
94
+ parts.shapes.push(...sectorShapes(id, "javelin-throw", c, heading, 8, 100, JAVELIN_HALF));
95
+ const end = at(c, heading, xe - runway, 0);
96
+ const box = bounds([end, at(c, heading, 100, -25), at(c, heading, 100, 25), at(c, heading, 0, 0), at(c, heading, 100, 0)]);
97
+ return { parts, facility: { id, event: "javelin-throw", x: c[0], y: c[1], heading, box, reach: 100 } };
98
+ }
99
+ /** The box round some points. */
100
+ export function bounds(points) {
101
+ const xs = points.map((p) => p[0]);
102
+ const ys = points.map((p) => p[1]);
103
+ return { x0: Math.min(...xs), y0: Math.min(...ys), x1: Math.max(...xs), y1: Math.max(...ys) };
104
+ }
105
+ /**
106
+ * A high jump facility (Rule 27; Manual 2.3.3): the uprights 4.02 m apart (Rule 27.6: 4.00 to 4.04 m), the crossbar, the landing mat of 6 m by 4 m at the least (Rule 27, landing area; Manual 2.3.3.4) with the bar's
107
+ * plane 0.5 m inside its front edge, the 50 mm line 3 m outside each upright (Rule 27.2, note) and the run-up: a 16 m wide area, 15 m long (Rule 27.3: 25 m for the major competitions), drawn
108
+ * as a dashed outline cut by the arc of the 15 m radius. `heading` is the way the athlete jumps; the facility is about the bar's middle.
109
+ */
110
+ export function highJumpParts(id, c, heading, runup = 15) {
111
+ const parts = emptyParts();
112
+ parts.areas.push(rectArea(`${id}-mat`, "ky-ath-mat", "high-jump", at(c, heading, 1.5), heading, 4, 6));
113
+ parts.shapes.push(rectLine(`${id}-mat-edge`, "high-jump", at(c, heading, 1.5), heading, 4, 6, 0.05));
114
+ const a = at(c, heading, 0, -5.01);
115
+ const b = at(c, heading, 0, 5.01);
116
+ parts.shapes.push(line(`${id}-take-off-line`, "high-jump", a[0], a[1], b[0], b[1], { w: 0.05 }));
117
+ const bar0 = at(c, heading, 0, -2.01);
118
+ const bar1 = at(c, heading, 0, 2.01);
119
+ parts.shapes.push(line(`${id}-crossbar`, "high-jump", bar0[0], bar0[1], bar1[0], bar1[1], { w: 0.04, cls: "ky-ath-k" }));
120
+ for (const side of [-1, 1]) {
121
+ const p = at(c, heading, 0, side * 2.01);
122
+ parts.shapes.push({ kind: "dot", id: `${id}-upright`, feature: "high-jump", cx: p[0], cy: p[1], r: 0.1, paint: "post" });
123
+ }
124
+ // The run-up: 8 m either side of the middle of the bar, to 15 m back, rounded by the arc of 15 m about the bar's middle.
125
+ const half = 8;
126
+ const x = Math.sqrt(runup * runup - half * half);
127
+ const [p0, p1] = [at(c, heading, 0, -half), at(c, heading, -x, -half)];
128
+ const [q0, q1] = [at(c, heading, -x, half), at(c, heading, 0, half)];
129
+ const sweep = 0;
130
+ const d = `M${f(p0[0])} ${f(p0[1])}L${f(p1[0])} ${f(p1[1])}A${f(runup)} ${f(runup)} 0 0 ${sweep} ${f(q0[0])} ${f(q0[1])}L${f(q1[0])} ${f(q1[1])}`;
131
+ parts.shapes.push(path(`${id}-run-up`, "high-jump", d, { w: 0.04, dash: [0.6, 0.6], least: 0.04 }));
132
+ const box = bounds([at(c, heading, 4.5, -3.2), at(c, heading, 4.5, 3.2), at(c, heading, -runup, -half), at(c, heading, -runup, half)]);
133
+ return { parts, facility: { id, event: "high-jump", x: c[0], y: c[1], heading, box, reach: runup } };
134
+ }
135
+ /**
136
+ * A pole vault's box and 0-line at the end of a runway (Rule 28; Manual 2.3.4.2): the box 1.00 m long, 0.60 m wide at the front and 0.15 m at the stop board, set so that the top inside
137
+ * edge of the stop board is on the 0-line, which is 10 mm wide and runs on past the uprights (5.20 m apart at the least). `c` is the middle of the stop board and `heading` the way the athlete
138
+ * runs; the landing mat of 6.00 m by 6.00 m at the least with front pieces 2 m long (Rule 28; Manual 2.3.4.4) lies beyond, its front 0.10 to 0.15 m from the box.
139
+ */
140
+ export function poleVaultEnd(id, c, heading) {
141
+ const parts = emptyParts();
142
+ parts.areas.push(polyArea(`${id}-box`, "ky-ath-pad", "pole-vault", [at(c, heading, -1, -0.3), at(c, heading, 0, -0.075), at(c, heading, 0, 0.075), at(c, heading, -1, 0.3)]));
143
+ parts.areas.push(rectArea(`${id}-mat`, "ky-ath-mat", "pole-vault", at(c, heading, 0.15 + 4), heading, 8, 6));
144
+ parts.shapes.push(rectLine(`${id}-mat-edge`, "pole-vault", at(c, heading, 0.15 + 4), heading, 8, 6, 0.05));
145
+ const a = at(c, heading, 0, -2.8);
146
+ const b = at(c, heading, 0, 2.8);
147
+ parts.shapes.push(line(`${id}-zero-line`, "pole-vault", a[0], a[1], b[0], b[1], { w: 0.03, least: 0.08, cls: "ky-ath-r" }));
148
+ for (const side of [-1, 1]) {
149
+ const p = at(c, heading, 0.1, side * 2.6);
150
+ parts.shapes.push({ kind: "dot", id: `${id}-upright`, feature: "pole-vault", cx: p[0], cy: p[1], r: 0.1, paint: "post" });
151
+ }
152
+ const box = bounds([at(c, heading, -45, -0.7), at(c, heading, -45, 0.7), at(c, heading, 8.2, -3), at(c, heading, 8.2, 3)]);
153
+ return { parts, facility: { id, event: "pole-vault", x: c[0], y: c[1], heading, box, reach: 45 } };
154
+ }
155
+ /** The runway of a jump: two lines 1.22 m apart (Rule 29; Manual 2.3.1.2) from `from` to `to` along `heading`, as lines. */
156
+ export function runwayLines(id, event, from, to, width = 1.22) {
157
+ const heading = Math.atan2(to[1] - from[1], to[0] - from[0]);
158
+ return [-1, 1].map((side) => {
159
+ const a = at(from, heading, 0, (side * width) / 2);
160
+ const b = at(to, heading, 0, (side * width) / 2);
161
+ return line(`${id}-runway-line`, event, a[0], a[1], b[0], b[1], { w: 0.05 });
162
+ });
163
+ }
164
+ /** A landing pit (Rule 30; Manual 2.3.1.4): the sand with its white border, `length` long along the jump and `width` across it, centred at `c`. */
165
+ export function pitParts(id, event, c, heading, length, width) {
166
+ const parts = emptyParts();
167
+ parts.areas.push(rectArea(`${id}-pit`, "ky-ath-sand", event, c, heading, length, width));
168
+ parts.shapes.push(rectLine(`${id}-pit-border`, event, c, heading, length, width, 0.05));
169
+ return parts;
170
+ }
171
+ /** A take-off board (Rule 29, take-off board; Manual 2.3.1.3): 1.22 m by 0.20 m, white, whose edge nearer the pit is the take-off line, `d` metres from the pit's near end. `pitEdge` is that end's middle. */
172
+ export function takeOffBoard(id, event, pitEdge, heading, d) {
173
+ // The board lies behind the take-off line, away from the pit: along the run, `d` from the pit's near end is the line and the board is the 0.20 m before it.
174
+ const line0 = at(pitEdge, heading, -d);
175
+ return rectArea(id, "ky-ath-board", event, at(line0, heading, -0.1), heading, 0.2, 1.22);
176
+ }
@@ -0,0 +1,79 @@
1
+ import type { Shape } from "../fields.types.ts";
2
+ import { type Facility } from "./facilities.ts";
3
+ import { type Parts } from "./oval.ts";
4
+ import type { Oval } from "./track.ts";
5
+ import type { AthleticsFieldEvent } from "./types.ts";
6
+ /** The sectors' lengths (Manual 2.1.1.3 and Figures 2.4.1.1, 2.4.2.1, 2.4.3.1, 2.4.4.1): the shot's 25 m, the discus's 80 m, the hammer's 90 m, the javelin's 100 m. */
7
+ export declare const SECTOR_REACH: {
8
+ readonly "shot-put": 25;
9
+ readonly "discus-throw": 80;
10
+ readonly "hammer-throw": 90;
11
+ readonly "javelin-throw": 100;
12
+ };
13
+ /** Where the standard stadium puts each facility, in metres from the centre of the semicircle of its segment (CP1 at the left, CP2 at the right), read from the Marking Plan. */
14
+ export declare const ARENA: {
15
+ /** The synthetic surface of a segment ends, and the turf of the infield begins, this far from the semicircle's centre along the straights' axis (Marking Plan; 108.39 m of turf between: a 105 m pitch fits). */
16
+ readonly turf: 12;
17
+ /** The javelin arc's apex is this far beyond the segment's centre; the centre point is 8 m behind it. */
18
+ readonly javelinApex: number;
19
+ /** The shot put circles: from the segment's centre outward along the axis, and the distance up or down. */
20
+ readonly shotWest: {
21
+ readonly out: 13.5;
22
+ readonly across: 18.15;
23
+ };
24
+ readonly shotEast: {
25
+ readonly out: 14.2;
26
+ readonly across: 18.5;
27
+ };
28
+ /** The combined discus and hammer circle of the second segment. */
29
+ readonly discus: {
30
+ readonly out: 20.4;
31
+ readonly across: -24.1;
32
+ readonly heading: number;
33
+ };
34
+ /** The two pole vault runways of the first segment: their middle lines, the boxes' places and the length, from the axis. */
35
+ readonly vaultA: {
36
+ readonly out: 23.26;
37
+ readonly box: 16.5;
38
+ };
39
+ readonly vaultB: {
40
+ readonly out: 15.82;
41
+ readonly box: 20.7;
42
+ };
43
+ readonly vaultReach: 26;
44
+ /** The high jumps: the bar's distance beyond the segment's centre and the distance of each from the axis (the spacing of two sets of uprights is 12 to 15 m: 13.5 m). */
45
+ readonly highJump: {
46
+ readonly out: 15;
47
+ readonly across: 6.75;
48
+ };
49
+ /** The long and triple jump beyond the back straight (Figure 2.5a, Marking Plan): the strip, the two runways' middle lines, and the pits' places along the straight. */
50
+ readonly strip: {
51
+ readonly x0: -45.6;
52
+ readonly x1: 46.2;
53
+ readonly y0: -56.6;
54
+ };
55
+ readonly rows: readonly [{
56
+ readonly y: -54.2;
57
+ readonly west: readonly [-39.7, -31.7];
58
+ readonly east: readonly [23, 31.1];
59
+ }, {
60
+ readonly y: -50.4;
61
+ readonly west: readonly [-30.9, -22.9];
62
+ readonly east: readonly [31.9, 40];
63
+ }];
64
+ };
65
+ /** What the infield is made of: shapes and areas, the facilities as data, and the box of what lies beyond the oval. */
66
+ export interface Infield {
67
+ parts: Parts;
68
+ facilities: Facility[];
69
+ }
70
+ /** The standard stadium's field events, those asked for. */
71
+ export declare function infieldParts(o: Oval, events: ReadonlySet<AthleticsFieldEvent>): Infield;
72
+ /** The strip beyond the back straight where the long and the triple jumps are, as a box, when they are drawn. */
73
+ export declare const jumpStrip: () => {
74
+ x0: number;
75
+ y0: number;
76
+ x1: number;
77
+ y1: number;
78
+ };
79
+ export type { Shape };