@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.
Files changed (244) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/NOTICE.md +4 -0
  3. package/README.md +71 -16
  4. package/dist/annotate.js +1 -1
  5. package/dist/athletics/describe.d.ts +8 -0
  6. package/dist/athletics/describe.js +41 -0
  7. package/dist/athletics/events.d.ts +17 -0
  8. package/dist/athletics/events.js +48 -0
  9. package/dist/athletics/facilities.d.ts +80 -0
  10. package/dist/athletics/facilities.js +176 -0
  11. package/dist/athletics/infield.d.ts +79 -0
  12. package/dist/athletics/infield.js +166 -0
  13. package/dist/athletics/layout.d.ts +13 -0
  14. package/dist/athletics/layout.js +98 -0
  15. package/dist/athletics/oval.d.ts +57 -0
  16. package/dist/athletics/oval.js +116 -0
  17. package/dist/athletics/plan.d.ts +97 -0
  18. package/dist/athletics/plan.js +355 -0
  19. package/dist/athletics/races.d.ts +102 -0
  20. package/dist/athletics/races.js +355 -0
  21. package/dist/athletics/steeplechase.d.ts +72 -0
  22. package/dist/athletics/steeplechase.js +196 -0
  23. package/dist/athletics/stencil.d.ts +13 -0
  24. package/dist/athletics/stencil.js +85 -0
  25. package/dist/athletics/track.d.ts +54 -0
  26. package/dist/athletics/track.js +105 -0
  27. package/dist/athletics/types.d.ts +77 -0
  28. package/dist/athletics/types.js +1 -0
  29. package/dist/athletics-entry.d.ts +17 -0
  30. package/dist/athletics-entry.js +11 -0
  31. package/dist/athletics.style.d.ts +16 -0
  32. package/dist/athletics.style.js +51 -0
  33. package/dist/atlas-entry.d.ts +4 -2
  34. package/dist/atlas-entry.js +3 -2
  35. package/dist/atlas.d.ts +83 -7
  36. package/dist/atlas.js +108 -8
  37. package/dist/charts-entry.d.ts +6 -1
  38. package/dist/charts-entry.js +3 -0
  39. package/dist/charts.athletics.d.ts +183 -0
  40. package/dist/charts.athletics.js +455 -0
  41. package/dist/charts.curling.heat.d.ts +24 -0
  42. package/dist/charts.curling.heat.js +116 -0
  43. package/dist/charts.curling.js +14 -3
  44. package/dist/charts.pool.d.ts +67 -0
  45. package/dist/charts.pool.js +76 -0
  46. package/dist/charts.skating.d.ts +204 -0
  47. package/dist/charts.skating.js +426 -0
  48. package/dist/charts.types.d.ts +53 -1
  49. package/dist/court.d.ts +85 -2
  50. package/dist/court.js +102 -7
  51. package/dist/court.more.d.ts +46 -0
  52. package/dist/court.more.js +219 -0
  53. package/dist/courts.style.d.ts +14 -2
  54. package/dist/courts.style.js +51 -4
  55. package/dist/crowd.d.ts +154 -0
  56. package/dist/crowd.draw.d.ts +17 -0
  57. package/dist/crowd.draw.js +198 -0
  58. package/dist/crowd.js +465 -0
  59. package/dist/crowd.park.d.ts +19 -0
  60. package/dist/crowd.park.js +153 -0
  61. package/dist/curling.stats.d.ts +271 -0
  62. package/dist/curling.stats.js +301 -0
  63. package/dist/draw.d.ts +16 -0
  64. package/dist/draw.js +318 -35
  65. package/dist/element-entry.d.ts +1 -1
  66. package/dist/element-entry.js +1 -1
  67. package/dist/element.d.ts +13 -2
  68. package/dist/element.js +77 -3
  69. package/dist/features.js +131 -0
  70. package/dist/fields.kit.d.ts +2 -2
  71. package/dist/fields.types.d.ts +18 -4
  72. package/dist/frames.providers.js +63 -8
  73. package/dist/geojson.js +3 -0
  74. package/dist/geometry-entry.d.ts +2 -1
  75. package/dist/geometry-entry.js +2 -1
  76. package/dist/geometry.d.ts +20 -0
  77. package/dist/geometry.js +78 -1
  78. package/dist/grounds.d.ts +4 -0
  79. package/dist/grounds.data.js +12 -0
  80. package/dist/hardwood.d.ts +31 -0
  81. package/dist/hardwood.js +157 -0
  82. package/dist/heat.js +4 -3
  83. package/dist/heat.types.d.ts +5 -0
  84. package/dist/heat.zones.d.ts +2 -2
  85. package/dist/heat.zones.js +154 -6
  86. package/dist/homeside.js +17 -0
  87. package/dist/index.d.ts +16 -2
  88. package/dist/index.js +10 -1
  89. package/dist/layers.d.ts +1 -1
  90. package/dist/layers.env.d.ts +3 -1
  91. package/dist/layers.env.js +4 -2
  92. package/dist/layers.js +4 -4
  93. package/dist/leagues/athletics.d.ts +63 -0
  94. package/dist/leagues/athletics.js +87 -0
  95. package/dist/leagues/courts.d.ts +269 -4
  96. package/dist/leagues/courts.js +155 -1
  97. package/dist/leagues/skating.d.ts +145 -0
  98. package/dist/leagues/skating.js +73 -0
  99. package/dist/leagues/sources.js +20 -0
  100. package/dist/leagues/types.d.ts +1 -1
  101. package/dist/leagues-entry.d.ts +4 -2
  102. package/dist/leagues-entry.js +2 -1
  103. package/dist/leagues.d.ts +14 -4
  104. package/dist/leagues.js +146 -5
  105. package/dist/look.d.ts +3 -3
  106. package/dist/look.js +39 -6
  107. package/dist/outline.d.ts +1 -1
  108. package/dist/outline.js +30 -2
  109. package/dist/pageant.d.ts +120 -0
  110. package/dist/pageant.draw.d.ts +21 -0
  111. package/dist/pageant.draw.js +171 -0
  112. package/dist/pageant.js +207 -0
  113. package/dist/pageant.style.d.ts +8 -0
  114. package/dist/pageant.style.js +42 -0
  115. package/dist/png.d.ts +8 -1
  116. package/dist/png.js +21 -1
  117. package/dist/pool.d.ts +176 -0
  118. package/dist/pool.figures.d.ts +304 -0
  119. package/dist/pool.figures.js +144 -0
  120. package/dist/pool.js +304 -0
  121. package/dist/pool.kit.d.ts +48 -0
  122. package/dist/pool.kit.js +141 -0
  123. package/dist/pool.labels.d.ts +20 -0
  124. package/dist/pool.labels.js +257 -0
  125. package/dist/pool.race.d.ts +65 -0
  126. package/dist/pool.race.js +140 -0
  127. package/dist/pool.replay.d.ts +46 -0
  128. package/dist/pool.replay.js +127 -0
  129. package/dist/pool.section.d.ts +13 -0
  130. package/dist/pool.section.js +83 -0
  131. package/dist/pool.style.d.ts +20 -0
  132. package/dist/pool.style.js +169 -0
  133. package/dist/pool.types.d.ts +145 -0
  134. package/dist/pool.types.js +3 -0
  135. package/dist/pool.words.d.ts +13 -0
  136. package/dist/pool.words.js +101 -0
  137. package/dist/ranges.names.js +47 -3
  138. package/dist/replay-entry.d.ts +3 -0
  139. package/dist/replay-entry.js +2 -0
  140. package/dist/restyle.js +1 -1
  141. package/dist/score.js +70 -5
  142. package/dist/sheet.d.ts +3 -0
  143. package/dist/sheet.js +7 -3
  144. package/dist/skating/describe.d.ts +7 -0
  145. package/dist/skating/describe.js +44 -0
  146. package/dist/skating/events.d.ts +24 -0
  147. package/dist/skating/events.js +47 -0
  148. package/dist/skating/figure.d.ts +24 -0
  149. package/dist/skating/figure.js +37 -0
  150. package/dist/skating/long.d.ts +54 -0
  151. package/dist/skating/long.js +111 -0
  152. package/dist/skating/parts.d.ts +43 -0
  153. package/dist/skating/parts.js +40 -0
  154. package/dist/skating/plan.d.ts +55 -0
  155. package/dist/skating/plan.js +197 -0
  156. package/dist/skating/short.d.ts +47 -0
  157. package/dist/skating/short.js +89 -0
  158. package/dist/skating/track.d.ts +66 -0
  159. package/dist/skating/track.js +94 -0
  160. package/dist/skating/types.d.ts +57 -0
  161. package/dist/skating/types.js +3 -0
  162. package/dist/skating-entry.d.ts +17 -0
  163. package/dist/skating-entry.js +11 -0
  164. package/dist/skating.style.d.ts +4 -0
  165. package/dist/skating.style.js +24 -0
  166. package/dist/strings.d.ts +296 -0
  167. package/dist/strings.js +328 -11
  168. package/dist/style.d.ts +2 -0
  169. package/dist/style.js +11 -1
  170. package/dist/surfaces/artistic.d.ts +9 -0
  171. package/dist/surfaces/artistic.js +94 -0
  172. package/dist/surfaces/athletics.d.ts +16 -0
  173. package/dist/surfaces/athletics.js +132 -0
  174. package/dist/surfaces/baseball.js +15 -0
  175. package/dist/surfaces/basketball.floor.d.ts +27 -0
  176. package/dist/surfaces/basketball.floor.js +83 -0
  177. package/dist/surfaces/basketball.gear.d.ts +27 -0
  178. package/dist/surfaces/basketball.gear.js +90 -0
  179. package/dist/surfaces/basketball.js +43 -21
  180. package/dist/surfaces/curling.d.ts +16 -0
  181. package/dist/surfaces/curling.fold.d.ts +67 -0
  182. package/dist/surfaces/curling.fold.js +107 -0
  183. package/dist/surfaces/curling.js +37 -3
  184. package/dist/surfaces/dive.d.ts +9 -0
  185. package/dist/surfaces/dive.js +128 -0
  186. package/dist/surfaces/field.d.ts +7 -2
  187. package/dist/surfaces/field.js +15 -9
  188. package/dist/surfaces/hockey.js +1 -0
  189. package/dist/surfaces/net.d.ts +2 -1
  190. package/dist/surfaces/net.js +160 -15
  191. package/dist/surfaces/polo.d.ts +12 -0
  192. package/dist/surfaces/polo.js +159 -0
  193. package/dist/surfaces/pool.d.ts +27 -0
  194. package/dist/surfaces/pool.js +198 -0
  195. package/dist/surfaces/skating.d.ts +6 -0
  196. package/dist/surfaces/skating.js +62 -0
  197. package/dist/surfaces/soccer.js +2 -1
  198. package/dist/surfaces/surface.d.ts +44 -0
  199. package/dist/surfaces/venue.d.ts +15 -0
  200. package/dist/surfaces/venue.js +95 -0
  201. package/dist/tenants.d.ts +77 -0
  202. package/dist/tenants.data.d.ts +8 -0
  203. package/dist/tenants.data.js +945 -0
  204. package/dist/tenants.js +46 -0
  205. package/dist/turn-entry.d.ts +12 -0
  206. package/dist/turn-entry.js +7 -0
  207. package/dist/turn.camera.d.ts +105 -0
  208. package/dist/turn.camera.js +168 -0
  209. package/dist/turn.dom.d.ts +40 -0
  210. package/dist/turn.dom.js +351 -0
  211. package/dist/turn.kit.d.ts +86 -0
  212. package/dist/turn.kit.js +110 -0
  213. package/dist/turn.markup.d.ts +48 -0
  214. package/dist/turn.markup.js +108 -0
  215. package/dist/turn.model.d.ts +78 -0
  216. package/dist/turn.model.js +91 -0
  217. package/dist/turn.style.d.ts +5 -0
  218. package/dist/turn.style.js +55 -0
  219. package/dist/types.d.ts +183 -18
  220. package/dist/units.d.ts +1 -1
  221. package/dist/units.js +15 -1
  222. package/dist/uprights.board.d.ts +17 -0
  223. package/dist/uprights.board.js +59 -0
  224. package/dist/uprights.d.ts +37 -0
  225. package/dist/uprights.fields.d.ts +32 -0
  226. package/dist/uprights.fields.js +172 -0
  227. package/dist/uprights.goal.d.ts +49 -0
  228. package/dist/uprights.goal.js +69 -0
  229. package/dist/uprights.js +160 -0
  230. package/dist/uprights.more.d.ts +7 -0
  231. package/dist/uprights.more.js +183 -0
  232. package/dist/uprights.net.d.ts +12 -0
  233. package/dist/uprights.net.js +109 -0
  234. package/dist/uprights.netkit.d.ts +28 -0
  235. package/dist/uprights.netkit.js +67 -0
  236. package/dist/uprights.pools.d.ts +8 -0
  237. package/dist/uprights.pools.js +190 -0
  238. package/dist/uprights.rinks.d.ts +27 -0
  239. package/dist/uprights.rinks.js +106 -0
  240. package/dist/uprights.track.d.ts +50 -0
  241. package/dist/uprights.track.js +246 -0
  242. package/dist/version.d.ts +1 -1
  243. package/dist/version.js +1 -1
  244. package/package.json +19 -2
@@ -5,6 +5,7 @@ import { ICC_MEN_GROUND } from "./leagues/cricket.ts";
5
5
  import { FIH_PITCH } from "./leagues/fieldhockey.ts";
6
6
  import { GAA_FOOTBALL_FIELD } from "./leagues/gaelic.ts";
7
7
  import { IHF_COURT } from "./leagues/handball.ts";
8
+ import { ARTISTIC, DIVING, SWIMMING, WATER_POLO } from "./pool.figures.ts";
8
9
  import { WORLD_MEN_FIELD } from "./leagues/lacrosse.ts";
9
10
  import { WORLD_RUGBY_FIELD } from "./leagues/rugby.ts";
10
11
  import type { Sport } from "./types.ts";
@@ -185,6 +186,14 @@ export declare const BEACH_VOLLEYBALL: import("./leagues.ts").VolleyballFigures;
185
186
  export declare const BADMINTON: import("./leagues.ts").BadmintonFigures;
186
187
  export declare const PICKLEBALL: import("./leagues.ts").PickleballFigures;
187
188
  export declare const TABLE_TENNIS: import("./leagues.ts").TableTennisFigures;
189
+ export declare const SITTING_VOLLEYBALL: import("./leagues.ts").VolleyballFigures;
190
+ export declare const PADEL: import("./leagues.ts").PadelFigures;
191
+ export declare const SQUASH: import("./leagues.ts").SquashFigures;
192
+ export declare const RACQUETBALL: import("./leagues.ts").RacquetballFigures;
193
+ export declare const SEPAK_TAKRAW: import("./leagues.ts").SepakTakrawFigures;
194
+ export declare const TEQBALL: import("./leagues.ts").TeqballFigures;
195
+ export declare const ROUNDNET: import("./leagues.ts").RoundnetFigures;
196
+ export declare const NETBALL: import("./leagues.ts").NetballFigures;
188
197
  /** The baseball field, from rules 2.01 to 2.05 of the Official Baseball Rules. */
189
198
  export declare const MLB: {
190
199
  readonly base: 90;
@@ -283,6 +292,13 @@ export declare function dimensionsOf(sport: "volleyball", unit?: Unit): Scaled<t
283
292
  export declare function dimensionsOf(sport: "badminton", unit?: Unit): Scaled<typeof BADMINTON>;
284
293
  export declare function dimensionsOf(sport: "pickleball", unit?: Unit): Scaled<typeof PICKLEBALL>;
285
294
  export declare function dimensionsOf(sport: "tabletennis", unit?: Unit): Scaled<typeof TABLE_TENNIS>;
295
+ export declare function dimensionsOf(sport: "padel", unit?: Unit): Scaled<typeof PADEL>;
296
+ export declare function dimensionsOf(sport: "squash", unit?: Unit): Scaled<typeof SQUASH>;
297
+ export declare function dimensionsOf(sport: "racquetball", unit?: Unit): Scaled<typeof RACQUETBALL>;
298
+ export declare function dimensionsOf(sport: "sepaktakraw", unit?: Unit): Scaled<typeof SEPAK_TAKRAW>;
299
+ export declare function dimensionsOf(sport: "teqball", unit?: Unit): Scaled<typeof TEQBALL>;
300
+ export declare function dimensionsOf(sport: "roundnet", unit?: Unit): Scaled<typeof ROUNDNET>;
301
+ export declare function dimensionsOf(sport: "netball", unit?: Unit): Scaled<typeof NETBALL>;
286
302
  export declare function dimensionsOf(sport: "lacrosse", unit?: Unit): Scaled<typeof WORLD_MEN_FIELD>;
287
303
  export declare function dimensionsOf(sport: "rugby", unit?: Unit): Scaled<typeof WORLD_RUGBY_FIELD>;
288
304
  export declare function dimensionsOf(sport: "afl", unit?: Unit): Scaled<typeof AFL_GROUND>;
@@ -290,6 +306,10 @@ export declare function dimensionsOf(sport: "gaelic", unit?: Unit): Scaled<typeo
290
306
  export declare function dimensionsOf(sport: "cricket", unit?: Unit): Scaled<typeof ICC_MEN_GROUND>;
291
307
  export declare function dimensionsOf(sport: "fieldhockey", unit?: Unit): Scaled<typeof FIH_PITCH>;
292
308
  export declare function dimensionsOf(sport: "handball", unit?: Unit): Scaled<typeof IHF_COURT>;
309
+ export declare function dimensionsOf(sport: "swimming", unit?: Unit): Scaled<typeof SWIMMING>;
310
+ export declare function dimensionsOf(sport: "waterpolo", unit?: Unit): Scaled<typeof WATER_POLO>;
311
+ export declare function dimensionsOf(sport: "diving", unit?: Unit): Scaled<typeof DIVING>;
312
+ export declare function dimensionsOf(sport: "artisticswimming", unit?: Unit): Scaled<typeof ARTISTIC>;
293
313
  export declare function dimensionsOf(sport: Sport, unit?: Unit): unknown;
294
314
  /** A fence's points with each distance in another unit; the angles stay as they are. Feet are the default for `from`. */
295
315
  export declare function fenceIn(points: readonly FencePoint[], to: Unit, from?: Unit): FencePoint[];
package/dist/geometry.js CHANGED
@@ -3,12 +3,13 @@
3
3
  // hold a key distance to the rulebook.
4
4
  import { SURFACE_UNITS, convertLength, lengthsIn } from "./units.js";
5
5
  import { SOCCER, soccerSpec } from "./surfaces/soccer-spec.js";
6
- import { BWF_BADMINTON, FIVB_BEACH, FIVB_INDOOR, ITF_TENNIS, ITTF_TABLE, USAP_PICKLEBALL, netInFeet } from "./leagues/courts.js";
6
+ import { BWF_BADMINTON, FIP_PADEL, FITEQ_TEQBALL, FIVB_BEACH, FIVB_INDOOR, IRF_RACQUETBALL, IRF_ROUNDNET, ISTAF_SEPAK_TAKRAW, ITF_TENNIS, ITTF_TABLE, USAP_PICKLEBALL, WN_NETBALL, WPV_SITTING, WSF_SQUASH, netInFeet } from "./leagues/courts.js";
7
7
  import { AFL_GROUND } from "./leagues/aussie.js";
8
8
  import { ICC_MEN_GROUND } from "./leagues/cricket.js";
9
9
  import { FIH_PITCH } from "./leagues/fieldhockey.js";
10
10
  import { GAA_FOOTBALL_FIELD } from "./leagues/gaelic.js";
11
11
  import { IHF_COURT } from "./leagues/handball.js";
12
+ import { ARTISTIC, DIVING, SWIMMING, SWIMMING_WIDTHS, WATER_POLO } from "./pool.figures.js";
12
13
  import { WORLD_MEN_FIELD } from "./leagues/lacrosse.js";
13
14
  import { WORLD_RUGBY_FIELD } from "./leagues/rugby.js";
14
15
  export const FEET_PER_YARD = 3;
@@ -126,6 +127,14 @@ export const BEACH_VOLLEYBALL = netInFeet(FIVB_BEACH, "m");
126
127
  export const BADMINTON = netInFeet(BWF_BADMINTON, "m");
127
128
  export const PICKLEBALL = netInFeet(USAP_PICKLEBALL, "ft");
128
129
  export const TABLE_TENNIS = netInFeet(ITTF_TABLE, "m");
130
+ export const SITTING_VOLLEYBALL = netInFeet(WPV_SITTING, "m");
131
+ export const PADEL = netInFeet(FIP_PADEL, "m");
132
+ export const SQUASH = netInFeet(WSF_SQUASH, "m");
133
+ export const RACQUETBALL = netInFeet(IRF_RACQUETBALL, "ft");
134
+ export const SEPAK_TAKRAW = netInFeet(ISTAF_SEPAK_TAKRAW, "m");
135
+ export const TEQBALL = netInFeet(FITEQ_TEQBALL, "m");
136
+ export const ROUNDNET = netInFeet(IRF_ROUNDNET, "m");
137
+ export const NETBALL = netInFeet(WN_NETBALL, "m");
129
138
  /** The baseball field, from rules 2.01 to 2.05 of the Official Baseball Rules. */
130
139
  export const MLB = {
131
140
  base: 90,
@@ -274,6 +283,34 @@ export function surfaceSize(sport, unit = SURFACE_UNITS[sport]) {
274
283
  length = TABLE_TENNIS.length;
275
284
  width = TABLE_TENNIS.width;
276
285
  break;
286
+ case "padel":
287
+ length = PADEL.length;
288
+ width = PADEL.width;
289
+ break;
290
+ case "squash":
291
+ length = SQUASH.length;
292
+ width = SQUASH.width;
293
+ break;
294
+ case "racquetball":
295
+ length = RACQUETBALL.length;
296
+ width = RACQUETBALL.width;
297
+ break;
298
+ case "sepaktakraw":
299
+ length = SEPAK_TAKRAW.length;
300
+ width = SEPAK_TAKRAW.width;
301
+ break;
302
+ case "teqball":
303
+ length = TEQBALL.length;
304
+ width = TEQBALL.width;
305
+ break;
306
+ case "roundnet":
307
+ length = ROUNDNET.length;
308
+ width = ROUNDNET.width;
309
+ break;
310
+ case "netball":
311
+ length = NETBALL.length;
312
+ width = NETBALL.width;
313
+ break;
277
314
  case "lacrosse":
278
315
  length = convertLength(WORLD_MEN_FIELD.length.drawn, "m", "ft");
279
316
  width = convertLength(WORLD_MEN_FIELD.width.drawn, "m", "ft");
@@ -304,6 +341,23 @@ export function surfaceSize(sport, unit = SURFACE_UNITS[sport]) {
304
341
  length = convertLength(IHF_COURT.length.drawn, "m", "ft");
305
342
  width = convertLength(IHF_COURT.width.drawn, "m", "ft");
306
343
  break;
344
+ // The pools, as drawn without options: the 50 by 25 m pool of eight lanes, the water polo pool (the field and the 0.30 m behind each goal line), a diving well and the Olympic artistic swimming area.
345
+ case "swimming":
346
+ length = convertLength(SWIMMING.longCourse, "m", "ft");
347
+ width = convertLength(SWIMMING_WIDTHS.permanent, "m", "ft");
348
+ break;
349
+ case "waterpolo":
350
+ length = convertLength(WATER_POLO.length + 2 * WATER_POLO.goal.netClear, "m", "ft");
351
+ width = convertLength(WATER_POLO.width, "m", "ft");
352
+ break;
353
+ case "diving":
354
+ length = convertLength(DIVING.well.length, "m", "ft");
355
+ width = convertLength(DIVING.well.width, "m", "ft");
356
+ break;
357
+ case "artisticswimming":
358
+ length = convertLength(ARTISTIC.olympic.length, "m", "ft");
359
+ width = convertLength(ARTISTIC.olympic.width, "m", "ft");
360
+ break;
307
361
  default:
308
362
  throw new Error(`No fixed size for "${String(sport)}": a ballpark's size is its fence`);
309
363
  }
@@ -336,6 +390,20 @@ export function dimensionsOf(sport, unit = SURFACE_UNITS[sport]) {
336
390
  return lengthsIn(PICKLEBALL, unit);
337
391
  case "tabletennis":
338
392
  return lengthsIn(TABLE_TENNIS, unit);
393
+ case "padel":
394
+ return lengthsIn(PADEL, unit);
395
+ case "squash":
396
+ return lengthsIn(SQUASH, unit);
397
+ case "racquetball":
398
+ return lengthsIn(RACQUETBALL, unit);
399
+ case "sepaktakraw":
400
+ return lengthsIn(SEPAK_TAKRAW, unit);
401
+ case "teqball":
402
+ return lengthsIn(TEQBALL, unit);
403
+ case "roundnet":
404
+ return lengthsIn(ROUNDNET, unit);
405
+ case "netball":
406
+ return lengthsIn(NETBALL, unit);
339
407
  // The field sports: the figures of the league a drawing has without a `league` (`LEAGUES` has the others), kept in the unit their rulebook prints them in.
340
408
  case "lacrosse":
341
409
  return lengthsIn(WORLD_MEN_FIELD, unit, "m");
@@ -351,6 +419,15 @@ export function dimensionsOf(sport, unit = SURFACE_UNITS[sport]) {
351
419
  return lengthsIn(FIH_PITCH, unit, "m");
352
420
  case "handball":
353
421
  return lengthsIn(IHF_COURT, unit, "m");
422
+ // The pools' figures, kept in metres as World Aquatics prints them.
423
+ case "swimming":
424
+ return lengthsIn(SWIMMING, unit, "m");
425
+ case "waterpolo":
426
+ return lengthsIn(WATER_POLO, unit, "m");
427
+ case "diving":
428
+ return lengthsIn(DIVING, unit, "m");
429
+ case "artisticswimming":
430
+ return lengthsIn(ARTISTIC, unit, "m");
354
431
  default:
355
432
  throw new Error(`Unknown sport "${String(sport)}"`);
356
433
  }
package/dist/grounds.d.ts CHANGED
@@ -54,6 +54,10 @@ export interface GroundData {
54
54
  /** The year it opened, and for a past ground the year it closed. */
55
55
  from?: number;
56
56
  to?: number;
57
+ /** True where Wikidata lists athletics among the ground's sports (property P641): a running track lies round the pitch, which `drawKyogijo({ sport: "athletics", ground })` draws. Absent for a ground Wikidata says nothing of, which may still have one. */
58
+ track?: boolean;
59
+ /** Where `track` was read. */
60
+ trackSource?: string;
57
61
  /** The first capacity the article's infobox gives, when it gives a number. */
58
62
  capacity?: number;
59
63
  /** `published` when the article gives the pitch's length and width, `default` when it does not: the ground is then drawn at the international 105 by 68 m. */
@@ -298,6 +298,8 @@ export const GROUND_DATA = [
298
298
  {
299
299
  "id": "olympiastadion-munich",
300
300
  "wikidata": "Q131610",
301
+ "track": true,
302
+ "trackSource": "Wikidata, property P641 (sport) lists athletics",
301
303
  "name": "Munich Olympic Stadium",
302
304
  "nameJa": "ミュンヘン・オリンピアシュタディオン",
303
305
  "localName": "Olympiastadion München",
@@ -391,6 +393,8 @@ export const GROUND_DATA = [
391
393
  {
392
394
  "id": "stadio-olimpico-rome",
393
395
  "wikidata": "Q159884",
396
+ "track": true,
397
+ "trackSource": "Wikidata, property P641 (sport) lists athletics",
394
398
  "name": "Stadio Olimpico",
395
399
  "names": [
396
400
  { "name": "Stadio dei Cipressi", "from": 1928, "to": 1953 },
@@ -450,6 +454,8 @@ export const GROUND_DATA = [
450
454
  {
451
455
  "id": "stade-de-france",
452
456
  "wikidata": "Q13205",
457
+ "track": true,
458
+ "trackSource": "Wikidata, property P641 (sport) lists athletics",
453
459
  "name": "Stade de France",
454
460
  "nameJa": "スタッド・ド・フランス",
455
461
  "localName": "Stade de France",
@@ -476,6 +482,8 @@ export const GROUND_DATA = [
476
482
  {
477
483
  "id": "nissan-stadium-yokohama",
478
484
  "wikidata": "Q116601",
485
+ "track": true,
486
+ "trackSource": "Wikidata, property P641 (sport) lists athletics",
479
487
  "name": "Nissan Stadium",
480
488
  "names": [
481
489
  { "name": "International Stadium Yokohama", "from": 1998, "to": 2004 }
@@ -570,6 +578,8 @@ export const GROUND_DATA = [
570
578
  {
571
579
  "id": "luzhniki",
572
580
  "wikidata": "Q202163",
581
+ "track": true,
582
+ "trackSource": "Wikidata, property P641 (sport) lists athletics",
573
583
  "name": "Luzhniki Stadium",
574
584
  "names": [
575
585
  { "name": "Central Lenin Stadium", "from": 1956, "to": 1992 }
@@ -1092,6 +1102,8 @@ export const GROUND_DATA = [
1092
1102
  {
1093
1103
  "id": "dignity-health-sports-park",
1094
1104
  "wikidata": "Q200684",
1105
+ "track": true,
1106
+ "trackSource": "Wikidata, property P641 (sport) lists athletics",
1095
1107
  "name": "Dignity Health Sports Park",
1096
1108
  "names": [
1097
1109
  { "name": "Home Depot Center", "from": 2003, "to": 2013 },
@@ -0,0 +1,31 @@
1
+ import type { CourtStyle } from "./types.ts";
2
+ /** The options of a hardwood floor, read: every part has its value. */
3
+ export interface Hardwood {
4
+ seed: number;
5
+ /** True for the seams, ends, grain, soft shadows, table and benches; false for broad boards and one shadow. */
6
+ fine: boolean;
7
+ /** The width of a board, in feet. */
8
+ board: number;
9
+ stain: number;
10
+ sheen: number;
11
+ hoops: boolean;
12
+ bench: boolean;
13
+ }
14
+ /** The width of a drawing in pixels when the options say it (`480` or `"480px"`), else `undefined` (a percentage or an em says nothing of the screen). */
15
+ export declare function pixelWidth(width: unknown): number | undefined;
16
+ /** The width in pixels under which a drawing is a thumbnail, and its boards a blur: the `auto` detail is `plain` below it. */
17
+ export declare const HARDWOOD_SMALL = 480;
18
+ /** The hardwood the options ask for, or `undefined` for the usual clean floor. `simple` is the drawing's `detail: "simple"`; `width` its `width` option. */
19
+ export declare function resolveHardwood(court: CourtStyle | undefined, simple: boolean, width: unknown): Hardwood | undefined;
20
+ /** A small, fast generator (mulberry32): the same seed gives the same numbers on every machine. */
21
+ export declare function generator(seed: number): () => number;
22
+ /** The width of a tile, in feet: longer than any court of the package, so that the boards do not repeat along it. */
23
+ export declare const TILE = 96;
24
+ /** The two tiles of a floor and the size they are laid at: the tones and grain (under the paint) and the seams and ends (over it). */
25
+ export declare function floorTiles(h: Hardwood): {
26
+ height: number;
27
+ under: string;
28
+ over: string;
29
+ };
30
+ /** The rules of the hardwood floor's classes, written into a drawing that has one (and in `KYOGIJO_STYLE`, for a page that supplies the stylesheet). */
31
+ export declare const KYOGIJO_HARDWOOD_STYLE: string;
@@ -0,0 +1,157 @@
1
+ // The realistic basketball floor (`court.hardwood`): the options read once, and the boards. A maple strip floor is laid in boards of one width that run the length of the
2
+ // court, each row's boards ending at different places so that no two neighbours' ends line up; each board has a tone of its own and a little grain. All of it is made here
3
+ // from a seed with a small generator of our own (no `Math.random`), so the same options give the same floor, and it is written as two tiles of a pattern (the tones and
4
+ // grain under the paint, the seams and ends over it), so that the SVG holds a few shapes however large the court is. Written for this package from the way a strip floor
5
+ // is laid; no photograph or other drawing was copied.
6
+ import { el, num } from "./format.js";
7
+ const finite = (value) => typeof value === "number" && Number.isFinite(value);
8
+ const clamp = (value, low, high) => Math.min(high, Math.max(low, value));
9
+ /** The width of a drawing in pixels when the options say it (`480` or `"480px"`), else `undefined` (a percentage or an em says nothing of the screen). */
10
+ export function pixelWidth(width) {
11
+ if (finite(width))
12
+ return width > 0 ? width : undefined;
13
+ const match = typeof width === "string" ? /^\s*(\d+(?:\.\d+)?)(?:px)?\s*$/.exec(width) : null;
14
+ return match === null ? undefined : Number(match[1]);
15
+ }
16
+ /** The width in pixels under which a drawing is a thumbnail, and its boards a blur: the `auto` detail is `plain` below it. */
17
+ export const HARDWOOD_SMALL = 480;
18
+ /** The hardwood the options ask for, or `undefined` for the usual clean floor. `simple` is the drawing's `detail: "simple"`; `width` its `width` option. */
19
+ export function resolveHardwood(court, simple, width) {
20
+ const given = court?.hardwood;
21
+ if (given === undefined || given === false)
22
+ return undefined;
23
+ const o = given === true ? {} : given;
24
+ const px = pixelWidth(width);
25
+ const fine = o.detail === "fine" || (o.detail !== "plain" && !simple && (px === undefined || px >= HARDWOOD_SMALL));
26
+ return {
27
+ seed: finite(o.seed) ? Math.trunc(o.seed) : 1,
28
+ fine,
29
+ board: clamp(finite(o.board) ? o.board : 2.25, 1.5, 6) / 12,
30
+ stain: clamp(finite(o.stain) ? o.stain : 0.82, 0.3, 1),
31
+ sheen: clamp(finite(o.sheen) ? o.sheen : 1, 0, 1.5),
32
+ hoops: o.hoops !== false,
33
+ bench: o.bench !== false && fine,
34
+ };
35
+ }
36
+ /** A small, fast generator (mulberry32): the same seed gives the same numbers on every machine. */
37
+ export function generator(seed) {
38
+ let a = seed >>> 0;
39
+ return () => {
40
+ a = (a + 0x6d2b79f5) >>> 0;
41
+ let t = a;
42
+ t = Math.imul(t ^ (t >>> 15), t | 1);
43
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
44
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
45
+ };
46
+ }
47
+ /** The width of a tile, in feet: longer than any court of the package, so that the boards do not repeat along it. */
48
+ export const TILE = 96;
49
+ const WARM = "#fff0c4";
50
+ const DEEP = "#4a280b";
51
+ const TONES = [
52
+ { colour: WARM, opacity: 0.19, upTo: 90 },
53
+ { colour: WARM, opacity: 0.1, upTo: 310 },
54
+ { colour: DEEP, opacity: 0.1, upTo: 520 },
55
+ { colour: DEEP, opacity: 0.2, upTo: 640 },
56
+ ];
57
+ /** The least two ends of boards in neighbouring rows come to one another, in feet. */
58
+ const APART = 1.2;
59
+ /** True when an end at `x` is within `APART` of any end of the rows given, going round the tile. */
60
+ const near = (x, rows) => rows.some((row) => row?.some((end) => {
61
+ const d = Math.abs(x - end) % TILE;
62
+ return Math.min(d, TILE - d) < APART;
63
+ }) === true);
64
+ /** An end moved on, a little at a time, until it is clear of the ends of the rows next to it (and of its own row's, `own`). */
65
+ function clear(x, rows, own, least) {
66
+ let at = x;
67
+ for (let tries = 0; tries < 40 && (near(at, rows) || own.some((end) => Math.abs(at - end) < least)); tries += 1)
68
+ at += 0.6;
69
+ return at;
70
+ }
71
+ /**
72
+ * The rows of boards of a tile: for each row the places its boards end, going round the tile. A row's ends are at random distances apart, between `lengths`, and are
73
+ * moved on until none is within a foot of an end in the row above or the one above that, as boards are laid so that no joint lines up with a neighbour's.
74
+ */
75
+ function rows(count, lengths, next) {
76
+ const [low, high] = lengths;
77
+ const made = [];
78
+ for (let r = 0; r < count; r += 1) {
79
+ // The rows next to it: the two above, and for the last rows the first ones, which lie under them when the tile repeats.
80
+ const above = [made[r - 1], made[r - 2], ...(r >= count - 2 ? made.slice(0, r === count - 1 ? 2 : 1) : [])];
81
+ const start = next() * high;
82
+ const ends = [clear(start, above, [], low)];
83
+ for (let at = ends[0] + low + next() * (high - low); at < start + TILE - low * 0.6; at += low + next() * (high - low)) {
84
+ const placed = clear(at, above, ends, low * 0.6);
85
+ ends.push(placed);
86
+ at = placed;
87
+ }
88
+ made.push(ends.map((end) => end % TILE).sort((x, y) => x - y));
89
+ }
90
+ return made;
91
+ }
92
+ /** A number for a path: one decimal, no leading zero's loss (`.5`), never `-0`. */
93
+ const n1 = (value) => {
94
+ const text = (Math.round(value * 10) / 10).toString();
95
+ return text === "-0" ? "0" : text;
96
+ };
97
+ /** The pieces of one row's board between two ends, going round the tile: one piece, or two when the board crosses its edge. */
98
+ function spans(from, to) {
99
+ return to > from ? [[from, to]] : [[from, TILE], [0, to]];
100
+ }
101
+ /** The two tiles of a floor and the size they are laid at: the tones and grain (under the paint) and the seams and ends (over it). */
102
+ export function floorTiles(h) {
103
+ const next = generator(h.seed);
104
+ const pitch = h.fine ? h.board : h.board * 4;
105
+ const count = Math.max(4, Math.round(6 / pitch));
106
+ const height = count * pitch;
107
+ const ends = rows(count, h.fine ? [5, 12] : [10, 26], next);
108
+ // Each board's tone: a stroke across the whole width of its row, so that the rows meet with no gap.
109
+ const byTone = TONES.map(() => []);
110
+ ends.forEach((row, r) => {
111
+ const y = num((r + 0.5) * pitch);
112
+ for (let i = 0; i < row.length; i += 1) {
113
+ const pick = next() * 1000;
114
+ const tone = TONES.findIndex((t) => pick < t.upTo);
115
+ if (tone < 0)
116
+ continue;
117
+ for (const [a, b] of spans(row[i], row[(i + 1) % row.length]))
118
+ byTone[tone].push(`M${n1(a)} ${y}h${n1(b - a)}`);
119
+ }
120
+ });
121
+ let under = "";
122
+ TONES.forEach((tone, i) => {
123
+ if (byTone[i].length > 0)
124
+ under += el("path", { d: byTone[i].join(""), stroke: tone.colour, "stroke-opacity": tone.opacity, "stroke-width": num(pitch + 0.004), fill: "none" });
125
+ });
126
+ if (!h.fine)
127
+ return { height, under, over: "" };
128
+ // The grain: fine streaks along the boards, short and faint, a few of them bowed.
129
+ const grain = [];
130
+ for (let i = 0; i < 70; i += 1) {
131
+ const x = next() * TILE;
132
+ const y = (Math.floor(next() * count) + 0.15 + next() * 0.7) * pitch;
133
+ const length = 1.2 + next() * 5.5;
134
+ const bow = (next() - 0.5) * pitch * 0.5;
135
+ grain.push(i % 4 === 0 ? `M${n1(x)} ${num(y)}q${n1(length / 2)} ${num(bow)} ${n1(length)} 0` : `M${n1(x)} ${num(y)}h${n1(length)}`);
136
+ }
137
+ under += el("path", { d: grain.join(""), stroke: DEEP, "stroke-opacity": 0.2, "stroke-width": num(pitch * 0.09), fill: "none", "stroke-linecap": "round" });
138
+ // The seams between the boards and the butt joints where they end.
139
+ const seam = [];
140
+ for (let r = 0; r < count; r += 1)
141
+ seam.push(`M0 ${num(r * pitch)}H${TILE}`);
142
+ ends.forEach((row, r) => {
143
+ for (const x of row)
144
+ seam.push(`M${n1(x)} ${num(r * pitch)}v${num(pitch)}`);
145
+ });
146
+ const over = el("path", { d: seam.join(""), stroke: "#2a1506", "stroke-opacity": 0.3, "stroke-width": num(pitch * 0.17), fill: "none" });
147
+ return { height, under, over };
148
+ }
149
+ /** The rules of the hardwood floor's classes, written into a drawing that has one (and in `KYOGIJO_STYLE`, for a page that supplies the stylesheet). */
150
+ export const KYOGIJO_HARDWOOD_STYLE = `
151
+ .kyogijo .ky-hw-end-l{fill:var(--ky-hw-end-left,var(--ky-boards))}
152
+ .kyogijo .ky-hw-end-r{fill:var(--ky-hw-end-right,var(--ky-boards))}
153
+ .kyogijo .ky-hw-pad{fill:var(--ky-hw-pad,#2c333c);stroke:#fff;stroke-opacity:.2;stroke-width:.1}
154
+ .kyogijo .ky-hw-arm{fill:var(--ky-hw-arm,#454d58);stroke:#fff;stroke-opacity:.15;stroke-width:.06}
155
+ .kyogijo .ky-hw-glass{fill:#eef4f8;stroke:#7d8791;stroke-width:.06}
156
+ .kyogijo .ky-hw-net{fill:none;stroke:#fff;stroke-opacity:.7}
157
+ .kyogijo .ky-hw-furniture{fill:#7b838c;fill-opacity:.35;stroke:#7b838c;stroke-opacity:.35;stroke-width:.18;stroke-linejoin:round}`.trim();
package/dist/heat.js CHANGED
@@ -330,8 +330,8 @@ function formatter(percent, decimals) {
330
330
  }
331
331
  /** The legend's marks: a plate, the heading, the steps as a bar and the ticks. Laid out as the eye sees it, then placed on the surface and turned back when the surface is turned. */
332
332
  function legendMarks(env, spec) {
333
- const box = env.shown;
334
- const b = env.base;
333
+ const box = spec.region ?? env.shown;
334
+ const b = spec.region === undefined ? env.base : Math.max(box.w, box.h) * 0.013;
335
335
  const fs = b * 1.1;
336
336
  const barH = b * 1.3;
337
337
  const pad = b * 1;
@@ -518,6 +518,7 @@ export function drawHeat(layer, env, gid, known) {
518
518
  title: legend.title ?? c.stat,
519
519
  ticks: legend.ticks ?? 5,
520
520
  position: legend.position ?? (env.o.sport === "mlb" ? "bottom-right" : "bottom"),
521
+ region: legend.region,
521
522
  format: formatter(c.percent, undefined),
522
523
  at: contour === undefined || contour.levels.length > 6 ? undefined : contour.levels.map((l) => 100 * l.label),
523
524
  }));
@@ -566,7 +567,7 @@ export function drawLegend(layer, env, gid, known) {
566
567
  const title = typeof layer.name === "string" && layer.name.trim() !== "" ? layer.name.trim() : target?.stat ?? words.stat.custom;
567
568
  made.cls = "ky-hm";
568
569
  made.opacity = opacityOf(layer.opacity);
569
- made.marks = legendMarks(env, { colours, title, ticks: layer.ticks ?? 5, position: layer.position ?? (env.o.sport === "mlb" ? "bottom-right" : "bottom"), format: formatter(percent, undefined) });
570
+ made.marks = legendMarks(env, { colours, title, ticks: layer.ticks ?? 5, position: layer.position ?? (env.o.sport === "mlb" ? "bottom-right" : "bottom"), region: layer.region, format: formatter(percent, undefined) });
570
571
  made.css = darkRules(colours, [gid]);
571
572
  made.title = fill(words.legendTitle, { name: title });
572
573
  made.text = fill(words.range, { min: formatter(percent, undefined)(colours.domain[0]), max: formatter(percent, undefined)(colours.domain[1]) });
@@ -2,6 +2,7 @@ import type { HeatRamp } from "./heat.colour.ts";
2
2
  import type { HexOrientation, Reducer, StatisticName } from "./heat.stats.ts";
3
3
  import type { ZoneSetId } from "./heat.zones.ts";
4
4
  import type { LayerBase, MarkDatum } from "./layers.types.ts";
5
+ import type { Box } from "./types.ts";
5
6
  export type { HeatRamp, HeatRampName } from "./heat.colour.ts";
6
7
  export type { HexOrientation, Reducer, StatisticName } from "./heat.stats.ts";
7
8
  export type { ZoneSetId } from "./heat.zones.ts";
@@ -33,6 +34,8 @@ export interface HeatLegend {
33
34
  ticks?: number;
34
35
  /** The opacity of the legend, 0 to 1. */
35
36
  opacity?: number;
37
+ /** Size and place the legend against this part of the surface, in feet in the drawing's frame (x along the surface, y across it), instead of the whole of what is shown: the half of a curling sheet that is drawn, say. */
38
+ region?: Box;
36
39
  }
37
40
  /** What the heat layers take beyond a layer's places. */
38
41
  export interface HeatBase extends LayerBase {
@@ -142,4 +145,6 @@ export interface LegendLayer extends Omit<LayerBase, "from" | "attacking" | "sur
142
145
  ticks?: number;
143
146
  /** The opacity of the legend, 0 to 1. */
144
147
  opacity?: number;
148
+ /** Size and place the legend against this part of the surface, as `HeatLegend.region` does. */
149
+ region?: Box;
145
150
  }
@@ -2,7 +2,7 @@ import type { Outline } from "./outline.ts";
2
2
  import type { KyogijoWords } from "./strings.ts";
3
3
  import type { Sport, SurfaceOptions } from "./types.ts";
4
4
  /** The zone sets. */
5
- export type ZoneSetId = "field-thirds" | "cricket-ground" | "soccer-positional" | "soccer-thirds" | "soccer-channels" | "soccer-18" | "nba-shot" | "nhl-slot" | "nhl-home-plate" | "baseball-spray" | "baseball-retrosheet" | "football-pass" | "curling-house" | "net-court";
5
+ export type ZoneSetId = "field-thirds" | "cricket-ground" | "soccer-positional" | "soccer-thirds" | "soccer-channels" | "soccer-18" | "nba-shot" | "nhl-slot" | "nhl-home-plate" | "baseball-spray" | "baseball-retrosheet" | "football-pass" | "athletics-track" | "skating-track" | "curling-house" | "net-court" | "wall-court" | "roundnet-rings" | "pool-lanes" | "water-polo-areas" | "pool-thirds";
6
6
  type Pt = readonly [number, number];
7
7
  /** One zone: its shape on the surface and whether a point lies in it. */
8
8
  export interface ZoneShape {
@@ -30,7 +30,7 @@ export interface ZoneSet {
30
30
  }
31
31
  /** What a zone set needs to know about the drawing and the layer. */
32
32
  export interface ZoneContext {
33
- o: Pick<SurfaceOptions, "sport" | "pitch" | "units"> & Partial<Pick<SurfaceOptions, "league" | "net" | "field">>;
33
+ o: Pick<SurfaceOptions, "sport" | "pitch" | "units"> & Partial<Pick<SurfaceOptions, "league" | "net" | "field" | "pool" | "athletics" | "skating">>;
34
34
  outline: Outline;
35
35
  /** The way the team attacks as the surface is drawn wide: names the sides and counts the bands from the team's own end. `right` by default. */
36
36
  direction: "left" | "right";