@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/style.d.ts CHANGED
@@ -15,6 +15,8 @@ export declare const KYOGIJO_HEAT_STYLE: string;
15
15
  * them: a curling drawing writes them in after the base rules, and `KYOGIJO_STYLE` has them for a page.
16
16
  */
17
17
  export declare const KYOGIJO_CURLING_STYLE: string;
18
+ /** The rules of a folded curling sheet: the fan that joins each enlarged house to the part of the strip it shows, the frames and the labels. Written in only by a folded sheet, and in `KYOGIJO_STYLE`. */
19
+ export declare const KYOGIJO_FOLD_STYLE: string;
18
20
  /**
19
21
  * The rules of a ballpark's walls and quirks (`walls` and `quirks`): the four shades of the wall bands (`--ky-wall-1` to `-4`, from under 10 feet to 30 and over), the hill, the
20
22
  * overhang, the ivy, the poles and bullpens, the backstop's bar, the dugouts, the names and the legend. Kept apart so that a drawing without them does not carry them: a drawing
package/dist/style.js CHANGED
@@ -1,11 +1,19 @@
1
1
  import { KYOGIJO_BACKGROUND_STYLE } from "./background.js";
2
2
  import { KYOGIJO_COURTS_STYLE } from "./courts.style.js";
3
+ import { KYOGIJO_CROWD_STYLE } from "./crowd.draw.js";
3
4
  import { KYOGIJO_FIELDS_STYLE } from "./fields.style.js";
5
+ import { KYOGIJO_HARDWOOD_STYLE } from "./hardwood.js";
6
+ import { KYOGIJO_ATHLETICS_STYLE, KYOGIJO_TRACK_STYLE } from "./athletics.style.js";
7
+ import { KYOGIJO_SKATING_STYLE } from "./skating.style.js";
8
+ import { KYOGIJO_BUDO_STYLE } from "./budo.style.js";
4
9
  import { KYOGIJO_FEATURE_STYLE } from "./features.js";
5
10
  import { KYOGIJO_GRID_STYLE } from "./layout.style.js";
6
11
  import { KYOGIJO_LOOK_STYLE } from "./look.js";
7
12
  import { KYOGIJO_MARK_STYLE } from "./mark.js";
13
+ import { KYOGIJO_PAGEANT_MOTION, KYOGIJO_PAGEANT_STYLE } from "./pageant.style.js";
14
+ import { KYOGIJO_POOL_STYLE } from "./pool.style.js";
8
15
  import { KYOGIJO_ROAD_STYLE } from "./road.style.js";
16
+ import { KYOGIJO_SITUATION_STYLE } from "./situation.style.js";
9
17
  import { KYOGIJO_SPECIAL_STYLE } from "./special.style.js";
10
18
  /**
11
19
  * The drawing's stylesheet, without the heat layers' rules: custom properties for every colour, in light and dark, and the rule of each class. It is
@@ -127,6 +135,10 @@ export const KYOGIJO_CURLING_STYLE = `
127
135
  .kyogijo .ky-hog{fill:var(--ky-hog)}.kyogijo .ky-hack{fill:var(--ky-hack)}.kyogijo .ky-fgz{fill:var(--ky-fgz)}.kyogijo pattern circle{fill:var(--ky-pebble)}
128
136
  .kyogijo .ky-hammer{fill:var(--ky-plate-ink)}.kyogijo .ky-hammer-in{fill:var(--ky-plate)}.kyogijo .ky-grid{stroke:var(--ky-plate-ink);opacity:.22}
129
137
  .kyogijo .ky-badge-hammer-left .ky-hammer{fill:var(--ky-left-ink)}.kyogijo .ky-badge-hammer-left .ky-hammer-in{fill:var(--ky-left)}.kyogijo .ky-badge-hammer-right .ky-hammer{fill:var(--ky-right-ink)}.kyogijo .ky-badge-hammer-right .ky-hammer-in{fill:var(--ky-right)}`.trim();
138
+ /** The rules of a folded curling sheet: the fan that joins each enlarged house to the part of the strip it shows, the frames and the labels. Written in only by a folded sheet, and in `KYOGIJO_STYLE`. */
139
+ export const KYOGIJO_FOLD_STYLE = `
140
+ .kyogijo .ky-fold-link{fill:var(--ky-line);fill-opacity:.07}.kyogijo .ky-fold-edge{fill:none;stroke:var(--ky-line);stroke-opacity:.4;stroke-width:.3}.kyogijo .ky-fold-hl{fill:var(--ky-line);fill-opacity:.08;stroke:var(--ky-line);stroke-opacity:.7;stroke-width:.35}
141
+ .kyogijo .ky-fold-frame{fill:none;stroke:var(--ky-boards);stroke-width:.6}.kyogijo .ky-fold-pill{fill:var(--ky-plate);fill-opacity:.92;stroke:var(--ky-boards);stroke-width:.2}.kyogijo .ky-fold-t{fill:var(--ky-plate-ink)}`.trim();
130
142
  /**
131
143
  * The rules of a ballpark's walls and quirks (`walls` and `quirks`): the four shades of the wall bands (`--ky-wall-1` to `-4`, from under 10 feet to 30 and over), the hill, the
132
144
  * overhang, the ivy, the poles and bullpens, the backstop's bar, the dugouts, the names and the legend. Kept apart so that a drawing without them does not carry them: a drawing
@@ -160,7 +172,12 @@ export const KYOGIJO_TEAM_STYLE = `
160
172
  .kyogijo .ky-ro{fill:var(--c,var(--ky-layer));fill-opacity:.7;stroke:var(--ky-layer-edge);stroke-width:calc(var(--w,.3)*1px);stroke-linejoin:round}
161
173
  .kyogijo .ky-ro-r{fill:none;stroke:var(--c,var(--ky-layer));stroke-opacity:.45;stroke-dasharray:calc(var(--w,.3)*3px) calc(var(--w,.3)*3px);stroke-width:calc(var(--w,.3)*1px)}
162
174
  .kyogijo .ky-fm>*{fill:var(--c,var(--ky-layer));stroke:var(--ky-layer-edge);stroke-width:calc(var(--w,.3)*1px)}
163
- .kyogijo .ky-fm>.ky-e{fill:var(--ky-layer-hollow);stroke:var(--c,var(--ky-layer));stroke-width:calc(var(--w,.3)*2.2px)}`.trim();
175
+ .kyogijo .ky-fm>.ky-e{fill:var(--ky-layer-hollow);stroke:var(--c,var(--ky-layer));stroke-width:calc(var(--w,.3)*2.2px)}
176
+ .kyogijo .ky-fm>path{stroke-linejoin:round}
177
+ .kyogijo .ky-nm{fill:var(--ky-plate-ink);stroke:var(--ky-plate);stroke-width:.14em;paint-order:stroke;stroke-linejoin:round;font-family:var(--ky-font);font-weight:700;font-variant-numeric:tabular-nums}
178
+ .kyogijo .ky-lc{fill:var(--ky-post);stroke:var(--ky-layer-edge);stroke-width:calc(var(--w,.3)*1px)}
179
+ .kyogijo .ky-cl{fill:var(--ky-plate);stroke:none;font-family:var(--ky-font);font-weight:700}
180
+ .kyogijo .ky-lf{fill:none;stroke:var(--ky-layer-edge);stroke-width:calc(var(--w,.3)*1px)}`.trim();
164
181
  /**
165
182
  * The rules of the annotations (the arrows of `direction`, the axes of `axes` and the labels and leaders of `landmarks`): words in the ink of the page with an outline in the
166
183
  * apron's colour, thin leaders, and the arrows in the home and away colours. A drawing that has an annotation writes them in; `KYOGIJO_STYLE` has them for a page.
@@ -174,4 +191,4 @@ export const KYOGIJO_NOTE_STYLE = `
174
191
  .kyogijo .ky-an-ar{stroke:var(--c);fill:none}
175
192
  .kyogijo .ky-an-hd{fill:var(--c)}`.trim();
176
193
  /** Every rule of the package, for a page that draws with `style: "none"` and supplies the stylesheet itself. */
177
- export const KYOGIJO_STYLE = `${KYOGIJO_BASE_STYLE}\n${KYOGIJO_HEAT_STYLE}\n${KYOGIJO_TEAM_STYLE}\n${KYOGIJO_CURLING_STYLE}\n${KYOGIJO_WALLS_STYLE}\n${KYOGIJO_COURTS_STYLE}\n${KYOGIJO_FIELDS_STYLE}\n${KYOGIJO_LOOK_STYLE}\n${KYOGIJO_FEATURE_STYLE}\n${KYOGIJO_NOTE_STYLE}\n${KYOGIJO_SPECIAL_STYLE}\n${KYOGIJO_BACKGROUND_STYLE}\n${KYOGIJO_GRID_STYLE}\n${KYOGIJO_MARK_STYLE}\n${KYOGIJO_ROAD_STYLE}`;
194
+ export const KYOGIJO_STYLE = `${KYOGIJO_BASE_STYLE}\n${KYOGIJO_HEAT_STYLE}\n${KYOGIJO_TEAM_STYLE}\n${KYOGIJO_CURLING_STYLE}\n${KYOGIJO_FOLD_STYLE}\n${KYOGIJO_WALLS_STYLE}\n${KYOGIJO_COURTS_STYLE}\n${KYOGIJO_FIELDS_STYLE}\n${KYOGIJO_POOL_STYLE}\n${KYOGIJO_ATHLETICS_STYLE}\n${KYOGIJO_SKATING_STYLE}\n${KYOGIJO_BUDO_STYLE}\n${KYOGIJO_LOOK_STYLE}\n${KYOGIJO_HARDWOOD_STYLE}\n${KYOGIJO_TRACK_STYLE}\n${KYOGIJO_FEATURE_STYLE}\n${KYOGIJO_NOTE_STYLE}\n${KYOGIJO_SPECIAL_STYLE}\n${KYOGIJO_BACKGROUND_STYLE}\n${KYOGIJO_CROWD_STYLE}\n${KYOGIJO_GRID_STYLE}\n${KYOGIJO_MARK_STYLE}\n${KYOGIJO_PAGEANT_STYLE}\n${KYOGIJO_PAGEANT_MOTION}\n${KYOGIJO_SITUATION_STYLE}\n${KYOGIJO_ROAD_STYLE}`;
@@ -0,0 +1,9 @@
1
+ import type { ArtisticPlan } from "../pool.ts";
2
+ import { type PoolCtx } from "../pool.kit.ts";
3
+ import { type BuildOptions, type Surface } from "./surface.ts";
4
+ /**
5
+ * An artistic swimming area lying wide, from World Aquatics' rules (Part Seven, Article 12): 30 by 20 m for the Olympic Games and the World Championships (12.2.2), or the least, 25 by 15 m of which 12 by 12 m is the
6
+ * deep part (12.1.1), the floor marked with contrasting lines in one direction along its length (12.1.3), the judges' (Technical Officials') platform not more than 2 m from the pool's edge (12.2.5) and the starting platform at centre
7
+ * stage (12.1.7). The sizes of the two platforms are ours: the rules give their heights.
8
+ */
9
+ export declare function artistic(o: BuildOptions, plan: ArtisticPlan, ctx?: PoolCtx): Surface;
@@ -0,0 +1,94 @@
1
+ import { el, num } from "../format.js";
2
+ import { feet } from "../pool.js";
3
+ import { box, deckMarkup, leastWidth, paintDefs, poolIds, waterMarkup } from "../pool.kit.js";
4
+ import { ARTISTIC, SWIMMING } from "../pool.figures.js";
5
+ import { GUTTER } from "./pool.js";
6
+ import { atEnds, edges, ft, quarterTurn, textOn } from "./surface.js";
7
+ /**
8
+ * An artistic swimming area lying wide, from World Aquatics' rules (Part Seven, Article 12): 30 by 20 m for the Olympic Games and the World Championships (12.2.2), or the least, 25 by 15 m of which 12 by 12 m is the
9
+ * deep part (12.1.1), the floor marked with contrasting lines in one direction along its length (12.1.3), the judges' (Technical Officials') platform not more than 2 m from the pool's edge (12.2.5) and the starting platform at centre
10
+ * stage (12.1.7). The sizes of the two platforms are ours: the rules give their heights.
11
+ */
12
+ export function artistic(o, plan, ctx = {}) {
13
+ const L = plan.length;
14
+ const W = plan.width;
15
+ const ids = ctx.ids ?? poolIds(o.id);
16
+ const full = o.detail === "full";
17
+ const m = ctx.bare === true ? 0 : (o.margin ?? feet(ARTISTIC.drawn.deck));
18
+ const judges = ARTISTIC.drawn.judges;
19
+ const start = ARTISTIC.drawn.start;
20
+ let base = box(o, "gutter", "ky-boards", -GUTTER, -GUTTER, L + GUTTER, W + GUTTER);
21
+ base += waterMarkup(o, ids, plan.look, 0, 0, L, W);
22
+ if (plan.deep !== undefined) {
23
+ const d = plan.deep;
24
+ base += el("rect", { class: ft(o, "deep-part", "ky-pl-dp"), x: feet(d.x), y: feet(d.y), width: feet(d.length), height: feet(d.width) });
25
+ }
26
+ // Lines in one direction along the pool, 2.5 m apart, ending 2 m short of the walls in a cross line, as the lane markings of a swimming pool do.
27
+ const lw = leastWidth(o, ARTISTIC.line, 0.32);
28
+ const count = Math.floor(W / SWIMMING.lane);
29
+ const gap = SWIMMING.laneLine.endGap;
30
+ const half = SWIMMING.laneLine.cross / 2;
31
+ let d = "";
32
+ for (let k = 0; k < count; k += 1) {
33
+ const y = (W - (count - 1) * SWIMMING.lane) / 2 + k * SWIMMING.lane;
34
+ d += `M${num(feet(gap))} ${num(feet(y))}H${num(feet(L - gap))}M${num(feet(gap))} ${num(feet(y - half))}V${num(feet(y + half))}M${num(feet(L - gap))} ${num(feet(y - half))}V${num(feet(y + half))}`;
35
+ }
36
+ let lines = el("path", { class: ft(o, "floor-lines", "ky-line"), d, "stroke-width": lw, fill: "none" });
37
+ if (plan.deep !== undefined) {
38
+ const dp = plan.deep;
39
+ lines += el("rect", { class: "ky-line ky-pl-dpl", x: feet(dp.x), y: feet(dp.y), width: feet(dp.length), height: feet(dp.width), "stroke-width": lw * 0.6, "stroke-dasharray": `${num(feet(0.8))} ${num(feet(0.5))}`, fill: "none" });
40
+ lines += textOn(o.portrait, feet(dp.x + dp.length / 2), feet(dp.y + dp.width / 2) + 1, `${ARTISTIC.minimum.deepDepth} m`, { size: feet(1.1), anchor: "middle", cls: "ky-pl-sx", weight: 800 });
41
+ }
42
+ // The judges' platform along the top side, close to the pool's edge, with its chairs; the starting platform at centre stage on the other side.
43
+ let deck = "";
44
+ const jy = -GUTTER - 1 - judges.depth;
45
+ deck += el("rect", { class: ft(o, "judges-platform", "ky-pl-jp"), x: feet(L / 2 - judges.length / 2), y: feet(jy), width: feet(judges.length), height: feet(judges.depth), rx: feet(0.12) });
46
+ if (full) {
47
+ const chairs = 7;
48
+ for (let i = 0; i < chairs; i += 1)
49
+ deck += el("rect", { class: "ky-pl-ch", x: feet(L / 2 - judges.length / 2 + 0.5 + i * ((judges.length - 1) / chairs)), y: feet(jy + 0.3), width: feet(0.75), height: feet(0.75), rx: feet(0.1) });
50
+ }
51
+ const sx = L / 2 - start.length / 2;
52
+ const sy = W + GUTTER + 0.4;
53
+ deck += el("rect", { class: ft(o, "starting-platform", "ky-pl-sp2"), x: feet(sx), y: feet(sy), width: feet(start.length), height: feet(start.depth), rx: feet(0.12) });
54
+ const marks = [];
55
+ if (o.landmarks === true) {
56
+ marks.push({ id: "floor-lines", x: feet(L * 0.3), y: feet(W / 2), side: "bottom" }, { id: "floor-lines", x: feet(L * 0.7), y: feet(W / 2), side: "top" }, { id: "judges-platform", x: feet(L / 2), y: feet(jy), side: "top" }, { id: "starting-platform", x: feet(L / 2), y: feet(sy + start.depth), side: "bottom" }, { id: "gutter", x: feet(L * 0.8), y: feet(-GUTTER / 2), side: "top" }, { id: "gutter", x: feet(L * 0.2), y: feet(W + GUTTER / 2), side: "bottom" });
57
+ if (plan.deep !== undefined)
58
+ marks.push({ id: "deep-part", x: feet(plan.deep.x + 1), y: feet(plan.deep.y), side: "top" });
59
+ }
60
+ const top = -jy + 0.4;
61
+ const bottom = sy + start.depth + 0.4 - W;
62
+ const view0 = { x: -m, y: -feet(top) - m * 0.4, w: feet(L) + 2 * m, h: feet(W) + feet(top + bottom) + m * 0.8 };
63
+ base = (ctx.bare === true ? "" : deckMarkup(o, ids, plan.deck, view0.x, view0.y, view0.w, view0.h)) + base + deck;
64
+ const Lf = feet(L);
65
+ const Wf = feet(W);
66
+ const cy = Wf / 2;
67
+ const turned = o.portrait;
68
+ const surface = {
69
+ sport: "artisticswimming",
70
+ view: view0,
71
+ base,
72
+ lines,
73
+ defs: ctx.bare === true ? "" : paintDefs(ids, plan.look, plan.deck, plan.seed),
74
+ left: { cx: -m / 2, cy, w: Wf, h: m, rot: -90 },
75
+ right: { cx: Lf + m / 2, cy, w: Wf, h: m, rot: 90 },
76
+ plate: turned ? { cx: Lf / 2, cy, w: Wf * 0.9, h: Lf * 0.34 } : { cx: Lf / 2, cy, w: Lf * 0.34, h: Wf * 0.55 },
77
+ turned,
78
+ };
79
+ surface.box = { x: 0, y: 0, w: Lf, h: Wf };
80
+ surface.lineRef = { width: lw, feet: 1 };
81
+ surface.ranges = {
82
+ half: atEnds((end) => (end === "left" ? edges(0, 0, Lf / 2, Wf) : edges(Lf / 2, 0, Lf, Wf))),
83
+ // The middle third of the pool, where the athletes enter at centre stage and the routine is usually swum.
84
+ "centre-stage": edges(Lf / 3, 0, (2 * Lf) / 3, Wf),
85
+ };
86
+ if (o.landmarks === true)
87
+ surface.marks = marks;
88
+ if (turned) {
89
+ const t = quarterTurn(view0);
90
+ surface.view = t.view;
91
+ surface.turn = t.turn;
92
+ }
93
+ return surface;
94
+ }
@@ -0,0 +1,16 @@
1
+ import type { AthleticsPlan } from "../athletics/plan.ts";
2
+ import { type BuildOptions, type Surface } from "./surface.ts";
3
+ /** Feet in a metre. */
4
+ export declare const K: number;
5
+ /** The embedded soccer pitch's markup, as the soccer builder wrote it: the ground and the lines, in a group that scales metres to feet. */
6
+ export interface Embedded {
7
+ base: string;
8
+ lines: string;
9
+ defs: string;
10
+ }
11
+ /** The part of a soccer builder's `base` that is the pitch: what follows its apron. */
12
+ export declare function pitchGroup(base: string): string;
13
+ /**
14
+ * The surface of the plan lying wide. `margin` is the ground round what is drawn, in feet. The soccer pitch `embedded` is laid inside the track where the plan has one.
15
+ */
16
+ export declare function athleticsSurface(o: BuildOptions, plan: AthleticsPlan, embedded: Embedded | undefined, margin: number): Surface;
@@ -0,0 +1,132 @@
1
+ // The athletics stadium's surface lying wide, from its plan (athletics/plan.ts): the track between its kerb and its edge, the segments' synthetic surface, the mown turf and the soccer pitch inside, the
2
+ // field events' areas, every painted line, the coloured marks and the lane numbers. The plan is in metres; the drawing is in feet, as every surface lies, so the whole is drawn inside a group
3
+ // that scales metres to feet and moves the stadium's box to the origin.
4
+ import { el, num } from "../format.js";
5
+ import { areaD, marks, strokes } from "./field.js";
6
+ import { strokeWidth, digitsD } from "../athletics/stencil.js";
7
+ import { atEnds, edges, ft, quarterTurn } from "./surface.js";
8
+ /** Feet in a metre. */
9
+ export const K = 1 / 0.3048;
10
+ /** The part of a soccer builder's `base` that is the pitch: what follows its apron. */
11
+ export function pitchGroup(base) {
12
+ const i = base.indexOf('<g class="ky-pitch');
13
+ return i < 0 ? "" : base.slice(i);
14
+ }
15
+ const feetBox = (b, ox, oy) => edges((b.x0 - ox) * K, (b.y0 - oy) * K, (b.x1 - ox) * K, (b.y1 - oy) * K);
16
+ /** A plan's named range in feet, as a surface lists them. */
17
+ function rangeOf(r, ox, oy) {
18
+ return "left" in r ? atEnds((end) => feetBox(end === "left" ? r.left : r.right, ox, oy)) : feetBox(r, ox, oy);
19
+ }
20
+ /**
21
+ * The surface of the plan lying wide. `margin` is the ground round what is drawn, in feet. The soccer pitch `embedded` is laid inside the track where the plan has one.
22
+ */
23
+ export function athleticsSurface(o, plan, embedded, margin) {
24
+ const ox = plan.box.x0;
25
+ const oy = plan.box.y0;
26
+ const full = o.detail === "full";
27
+ // A close-up of a start is turned so that the athletes run to the right (or, in portrait, up the page): the whole drawing is moved and turned about the start's pivot, and data in the stadium's own frame
28
+ // is carried there by `frame`. Every other view is the stadium as it lies, wide, and turned a quarter in portrait.
29
+ const sv = plan.startView;
30
+ const turn = sv === undefined ? 0 : (o.portrait ? -Math.PI / 2 : 0) - sv.pivot.heading;
31
+ const deg = (turn * 180) / Math.PI;
32
+ let view0 = { x: (plan.extent.x0 - ox) * K - margin, y: (plan.extent.y0 - oy) * K - margin, w: (plan.extent.x1 - plan.extent.x0) * K + 2 * margin, h: (plan.extent.y1 - plan.extent.y0) * K + 2 * margin };
33
+ if (sv !== undefined) {
34
+ const w = sv.window;
35
+ const quarter = o.portrait;
36
+ const [x0, x1, y0, y1] = quarter ? [w.y0, w.y1, -w.x1, -w.x0] : [w.x0, w.x1, w.y0, w.y1];
37
+ view0 = { x: x0 * K, y: y0 * K, w: (x1 - x0) * K, h: (y1 - y0) * K };
38
+ }
39
+ const place = sv === undefined ? `scale(${K.toFixed(6)}) translate(${num(-ox)} ${num(-oy)})` : `scale(${K.toFixed(6)}) rotate(${num(deg)}) translate(${num(-sv.pivot.x)} ${num(-sv.pivot.y)})`;
40
+ const group = (inner, cls) => el("g", { class: cls, transform: place }, inner);
41
+ const turned = sv === undefined && o.portrait;
42
+ const upright = sv === undefined ? (o.portrait ? -90 : 0) : -deg;
43
+ const toK = (v) => (v * K).toFixed(4);
44
+ void toK;
45
+ let defs = embedded?.defs ?? "";
46
+ // Under everything: the apron, the track's surfaces, the turf and its bands, the pitch, then the field events' areas.
47
+ let base = el("rect", { class: ft(o, "apron", "ky-apron"), x: view0.x, y: view0.y, width: view0.w, height: view0.h });
48
+ let ground = "";
49
+ for (const a of plan.areas)
50
+ if (a.cls === "ky-ath-track")
51
+ ground += el("path", { class: ft(o, a.feature, a.cls), d: areaD(a), "fill-rule": a.evenodd === true ? "evenodd" : undefined });
52
+ if (plan.turf !== undefined) {
53
+ ground += el("path", { class: ft(o, "infield", "ky-ath-grass"), d: plan.turf.d });
54
+ if (o.stripes && o.mow !== "none" && plan.turf.stripes !== "") {
55
+ defs += el("clipPath", { id: `${o.id}-ath-turf` }, el("path", { d: plan.turf.d }));
56
+ ground += el("path", { class: ft(o, "mowing", "ky-stripe"), d: plan.turf.stripes, "clip-path": `url(#${o.id}-ath-turf)` });
57
+ }
58
+ }
59
+ const pitchAt = plan.pitch === undefined || embedded === undefined ? undefined : `translate(${num(plan.pitch.x)} ${num(plan.pitch.y)}) scale(${(1 / K).toFixed(6)})`;
60
+ if (pitchAt !== undefined && embedded !== undefined)
61
+ ground += el("g", { transform: pitchAt }, embedded.base);
62
+ for (const a of plan.areas)
63
+ if (a.cls !== "ky-ath-track")
64
+ ground += el("path", { class: ft(o, a.feature, a.cls), d: areaD(a), "fill-rule": a.evenodd === true ? "evenodd" : undefined });
65
+ base += group(ground, "ky-ath-ground");
66
+ // The lines: the painted lines and marks of the plan, the lane numbers, the pitch's lines.
67
+ const thick = o.exact ? plan.lineWidth : plan.drawnLine;
68
+ let lines = strokes(plan, o) + marks(plan, o);
69
+ if (pitchAt !== undefined && embedded !== undefined)
70
+ lines += el("g", { transform: pitchAt }, embedded.lines);
71
+ for (const d of plan.digits) {
72
+ const h = d.h;
73
+ if (d.tag === true)
74
+ lines += el("circle", { class: "ky-ath-tag", cx: d.x, cy: d.y, r: h * 0.78 });
75
+ lines += el("path", {
76
+ class: ft(o, d.feature, d.tag === true ? "ky-ath-tagnum" : "ky-ath-num"),
77
+ d: digitsD(d.text, h, d.x, d.y),
78
+ "stroke-width": String(Math.round(strokeWidth(h) * 10000) / 10000),
79
+ transform: upright === 0 ? undefined : `rotate(${num(upright)} ${num(d.x)} ${num(d.y)})`,
80
+ });
81
+ }
82
+ const linesGroup = group(lines, "ky-ath-lines");
83
+ const W = (plan.box.x1 - plan.box.x0) * K;
84
+ const H = (plan.box.y1 - plan.box.y0) * K;
85
+ const surface = {
86
+ sport: "athletics",
87
+ view: view0,
88
+ base,
89
+ lines: linesGroup,
90
+ defs,
91
+ // A team's name, in a score, is written on the grass either side of the middle: a track meeting between teams.
92
+ left: { cx: W * 0.27, cy: H / 2, w: W * 0.2, h: H * 0.11, rot: 0 },
93
+ right: { cx: W * 0.73, cy: H / 2, w: W * 0.2, h: H * 0.11, rot: 0 },
94
+ plate: { cx: W / 2, cy: H / 2, w: Math.min(W * 0.34, 140), h: Math.min(W * 0.34, 140) * 0.52 },
95
+ turned,
96
+ bannersOver: true,
97
+ onColour: false,
98
+ };
99
+ surface.box = { x: 0, y: 0, w: W, h: H };
100
+ surface.lineRef = { width: thick, feet: K };
101
+ const ranges = {};
102
+ for (const [name, r] of Object.entries(plan.ranges))
103
+ ranges[name] = rangeOf(r, ox, oy);
104
+ surface.ranges = ranges;
105
+ if (o.landmarks === true) {
106
+ const m = plan.marks.map((p) => ({ id: p.id, x: (p.x - ox) * K, y: (p.y - oy) * K, side: p.side }));
107
+ surface.marks = full ? m : m.filter((p) => !p.id.startsWith("~"));
108
+ }
109
+ if (sv !== undefined) {
110
+ // The stadium's own frame (feet from its box's corner) to the close-up's: moved so that the pivot is the origin, then turned.
111
+ const qx = (sv.pivot.x - ox) * K;
112
+ const qy = (sv.pivot.y - oy) * K;
113
+ surface.frame = `rotate(${num(deg)}) translate(${num(-qx)} ${num(-qy)})`;
114
+ surface.upright = -deg;
115
+ // In the stadium's own frame the part shown is the box round the close-up's window, and the whole is the stadium: data is cut to the first, as it is for any range.
116
+ const c = Math.cos(sv.pivot.heading);
117
+ const sn = Math.sin(sv.pivot.heading);
118
+ const own = [[sv.window.x0, sv.window.y0], [sv.window.x1, sv.window.y0], [sv.window.x1, sv.window.y1], [sv.window.x0, sv.window.y1]].map(([x, y]) => [(sv.pivot.x + x * c - y * sn - ox) * K, (sv.pivot.y + x * sn + y * c - oy) * K]);
119
+ const bx0 = Math.min(...own.map((p) => p[0]));
120
+ const by0 = Math.min(...own.map((p) => p[1]));
121
+ surface.whole = { x: 0, y: 0, w: W, h: H };
122
+ surface.box = { x: bx0, y: by0, w: Math.max(...own.map((p) => p[0])) - bx0, h: Math.max(...own.map((p) => p[1])) - by0 };
123
+ surface.ranges = {};
124
+ surface.marks = undefined;
125
+ }
126
+ if (turned) {
127
+ const t = quarterTurn(view0);
128
+ surface.view = t.view;
129
+ surface.turn = t.turn;
130
+ }
131
+ return surface;
132
+ }
@@ -179,6 +179,23 @@ export function baseball(points, o, era, diamond = MLB_DIAMOND) {
179
179
  Object.assign(right, { cx: (umax + m - 6 + 62) / 2, cy, w, h: 58 });
180
180
  }
181
181
  const surface = { sport: "mlb", view, base, lines, defs: clip, left, right, plate: { cx: 0, cy: -Math.round(vmax * 0.42), w: 150, h: 62 }, turned: false, lineRef: { width: thin, feet: 1 }, box: { x: umin, y: -vmax, w: umax - umin, h: vmax } };
182
+ // The bases as drawn (first, second, third) for a situation to light.
183
+ surface.anchors = { kind: "baseball", bases: bases.map(([u, v]) => [u, -v]), half: h, backstop };
184
+ // A pageant: the home team's picture on the infield, the visitors' in the outfield beyond the plate, and the emblem on the mound.
185
+ {
186
+ const inW = 2 * centreV * 0.6 * 0.95;
187
+ const inH = 2 * centreV * 0.4 * 0.95;
188
+ const plateTop = Math.round(vmax * 0.42) + 31;
189
+ const v0 = plateTop + 10;
190
+ const v1 = vmax - (b?.track ?? MLB.warningTrack) - 8;
191
+ const outH = Math.min(v1 - v0, inH * 1.9);
192
+ surface.pageant = {
193
+ byRole: true,
194
+ left: { cx: 0, cy: -(v0 + v1) / 2, w: Math.min(inW * 1.9, (umax - umin) * 0.5), h: outH },
195
+ right: { cx: 0, cy: -centreV, w: inW, h: inH },
196
+ centre: { cx: 0, cy: -d.moundCentre, r: 15 },
197
+ };
198
+ }
182
199
  // The infield: the dirt out to the arc round the mound, with the ground behind home plate; the outfield: the fence in to just short of second base.
183
200
  surface.ranges = {
184
201
  infield: edges(-(ua + 15), -(d.pitcher + skin + 12), ua + 15, 0),
@@ -0,0 +1,27 @@
1
+ import { type Hardwood } from "../hardwood.ts";
2
+ import { type BuildOptions } from "./surface.ts";
3
+ /** Where the floor stands: the court's length and width, the border's width, and the prefix of the ids. */
4
+ export interface FloorGeo {
5
+ L: number;
6
+ W: number;
7
+ bw: number;
8
+ /** The ground drawn beyond the court's lines. */
9
+ margin: number;
10
+ id: string;
11
+ }
12
+ /** The floor in layers: the defs (the tiles and the sheen), what lies under the paint, and what lies over it. */
13
+ export interface Floor {
14
+ defs: string;
15
+ under: string;
16
+ over: string;
17
+ }
18
+ /**
19
+ * The wood, the boards and the border, under the paint, and the seams and the sheen over it. The border is stain over the same wood: its sides in the border's colour,
20
+ * and the strip behind each baseline in the colour of the team that defends it (the `--ky-hw-end-left` and `-right` of the drawing, else the border's).
21
+ */
22
+ export declare function hardwoodFloor(h: Hardwood, g: FloorGeo, o: BuildOptions): Floor;
23
+ /**
24
+ * The words of a hardwood floor, each centred in its strip: the baseline words behind each baseline and the sideline words in the border's sides. Where the drawing is
25
+ * turned a quarter to lie tall, the baseline words are turned back to read left to right, and the sideline words run along their strips, the bottom one up the page.
26
+ */
27
+ export declare function hardwoodWords(o: BuildOptions, g: FloorGeo, turned: boolean, sidelines: [string, string] | undefined): string;
@@ -0,0 +1,83 @@
1
+ // The layers of a realistic (`hardwood`) basketball floor: the wood and its boards under the paint, the stained border, and over the paint the seams and the satin sheen.
2
+ // The paint of the keys and the circle is laid between the two by the court's builder, translucent, so the boards show through it as they do through a stained key.
3
+ import { el, num } from "../format.js";
4
+ import { floorTiles } from "../hardwood.js";
5
+ import { ft } from "./surface.js";
6
+ const stop = (offset, colour, opacity, strength) => el("stop", { offset, "stop-color": colour, "stop-opacity": num(Math.min(1, opacity * strength)) });
7
+ /** A gradient laid out in the drawing's own feet from `(x1, y1)` to `(x2, y2)`; its stops are `[offset, colour, opacity]`. */
8
+ function gradient(id, from, to, stops, strength) {
9
+ return el("linearGradient", { id, gradientUnits: "userSpaceOnUse", x1: from[0], y1: from[1], x2: to[0], y2: to[1] }, stops.map(([offset, colour, opacity]) => stop(offset, colour, opacity, strength)).join(""));
10
+ }
11
+ /**
12
+ * The wood, the boards and the border, under the paint, and the seams and the sheen over it. The border is stain over the same wood: its sides in the border's colour,
13
+ * and the strip behind each baseline in the colour of the team that defends it (the `--ky-hw-end-left` and `-right` of the drawing, else the border's).
14
+ */
15
+ export function hardwoodFloor(h, g, o) {
16
+ const { L, W, bw, id, margin } = g;
17
+ const all = { x: -bw, y: -bw, width: L + 2 * bw, height: W + 2 * bw };
18
+ const tiles = floorTiles(h);
19
+ const pattern = (suffix, body) => el("pattern", { id: `${id}-hw-${suffix}`, width: 96, height: num(tiles.height), patternUnits: "userSpaceOnUse" }, body);
20
+ // Where the floor meets the ground round it, a soft shade a few feet deep, as a floor lit from above falls off at its edge.
21
+ const reach = h.fine ? Math.min(2.2, Math.max(0, margin - bw)) : 0;
22
+ const fade = (suffix, from, to) => gradient(`${id}-hw-${suffix}`, from, to, [[0, "#000", 0.16], [0.35, "#000", 0.05], [1, "#000", 0]], 1);
23
+ const strip = (suffix, x, y, width, height) => el("rect", { class: "ky-hw", x: num(x), y: num(y), width: num(width), height: num(height), fill: `url(#${id}-hw-${suffix})` });
24
+ const wide = L + 2 * margin;
25
+ const defs = pattern("a", tiles.under) +
26
+ (tiles.over === "" ? "" : pattern("b", tiles.over)) +
27
+ (reach <= 0 ? "" : fade("e1", [0, -bw], [0, -bw - reach]) + fade("e2", [0, W + bw], [0, W + bw + reach]) + fade("e3", [-bw, 0], [-bw - reach, 0]) + fade("e4", [L + bw, 0], [L + bw + reach, 0]));
28
+ let under = reach <= 0 ? "" : strip("e1", -margin, -bw - reach, wide, reach) + strip("e2", -margin, W + bw, wide, reach) + strip("e3", -bw - reach, -bw, reach, W + 2 * bw) + strip("e4", L + bw, -bw, reach, W + 2 * bw);
29
+ under += el("rect", { class: ft(o, "floor", "ky-surface"), ...all });
30
+ under += el("rect", { class: "ky-hw", ...all, fill: `url(#${id}-hw-a)` });
31
+ // The border: sides, then the strip behind each baseline, stained so that the boards show through.
32
+ const sides = `M0 ${-bw}H${num(L)}V0H0ZM0 ${num(W)}H${num(L)}V${num(W + bw)}H0Z`;
33
+ under += el("path", { class: ft(o, "border", "ky-boards"), d: sides, "fill-opacity": num(h.stain) });
34
+ under += el("path", { class: ft(o, "border", "ky-boards ky-hw-end-l"), d: `M${-bw} ${-bw}H0V${num(W + bw)}H${-bw}Z`, "fill-opacity": num(h.stain) });
35
+ under += el("path", { class: ft(o, "border", "ky-boards ky-hw-end-r"), d: `M${num(L)} ${-bw}H${num(L + bw)}V${num(W + bw)}H${num(L)}Z`, "fill-opacity": num(h.stain) });
36
+ let over = tiles.over === "" ? "" : el("rect", { class: "ky-hw", ...all, fill: `url(#${id}-hw-b)` });
37
+ // The sheen: light along the middle and a darker fall-off at the edges, and a few broad diagonal glints, as a lacquered floor shows under the lights.
38
+ if (h.sheen > 0) {
39
+ const s = h.sheen;
40
+ const names = h.fine ? ["s1", "s2", "s3"] : ["s1", "s2"];
41
+ const defsOf = [
42
+ gradient(`${id}-hw-s1`, [0, -bw], [0, W + bw], [[0, "#000", 0.22], [0.16, "#000", 0.03], [0.3, "#000", 0], [0.5, "#fff", 0.1], [0.7, "#fff", 0], [0.86, "#000", 0.02], [1, "#000", 0.24]], s),
43
+ gradient(`${id}-hw-s2`, [-bw, 0], [L + bw, 0], [[0, "#000", 0.18], [0.1, "#000", 0], [0.5, "#fff", 0.05], [0.9, "#000", 0], [1, "#000", 0.18]], s),
44
+ ...(h.fine ? [gradient(`${id}-hw-s3`, [0, -bw], [L * 0.55, W + bw], [[0, "#fff", 0], [0.17, "#fff", 0], [0.21, "#fff", 0.06], [0.25, "#fff", 0], [0.46, "#fff", 0], [0.5, "#fff", 0.075], [0.54, "#fff", 0], [0.75, "#fff", 0], [0.8, "#fff", 0.05], [0.84, "#fff", 0], [1, "#fff", 0]], s)] : []),
45
+ ];
46
+ over += names.map((n) => el("rect", { class: "ky-hw", ...all, fill: `url(#${id}-hw-${n})` })).join("");
47
+ return { defs: defs + defsOf.join(""), under, over };
48
+ }
49
+ return { defs, under, over };
50
+ }
51
+ /** A word centred on `(x, y)`, turned `angle` degrees in the court's own frame (the drawing's turn to lie tall comes on top of it). */
52
+ function word(o, x, y, text, size, angle, weight, spacing) {
53
+ return el("text", {
54
+ class: `ky-text ${ft(o, "baseline-text", "ky-baseline")}`,
55
+ x: num(x),
56
+ y: num(y + size * 0.36),
57
+ "font-size": size,
58
+ "font-weight": weight,
59
+ "letter-spacing": spacing,
60
+ "text-anchor": "middle",
61
+ transform: angle === 0 ? undefined : `rotate(${num(angle)} ${num(x)} ${num(y)})`,
62
+ }, text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"));
63
+ }
64
+ /**
65
+ * The words of a hardwood floor, each centred in its strip: the baseline words behind each baseline and the sideline words in the border's sides. Where the drawing is
66
+ * turned a quarter to lie tall, the baseline words are turned back to read left to right, and the sideline words run along their strips, the bottom one up the page.
67
+ */
68
+ export function hardwoodWords(o, g, turned, sidelines) {
69
+ const { L, W, bw } = g;
70
+ const cy = W / 2;
71
+ let out = "";
72
+ const base = o.court?.baselineText;
73
+ if (base !== undefined) {
74
+ // Off the middle, where the stanchion's arm crosses the border: the far side from the arm, each end opposite the other as a painted floor is.
75
+ out += word(o, -bw / 2, cy + W * 0.27, base[0], 1.9, -90, 800, 0.4);
76
+ out += word(o, L + bw / 2, cy - W * 0.27, base[1], 1.9, turned ? -90 : 90, 800, 0.4);
77
+ }
78
+ if (sidelines !== undefined) {
79
+ out += word(o, L / 2, -bw / 2, sidelines[0], 1.5, 0, 700, 0.35);
80
+ out += word(o, L / 2, W + bw / 2, sidelines[1], 1.5, turned ? 180 : 0, 700, 0.35);
81
+ }
82
+ return out;
83
+ }
@@ -0,0 +1,27 @@
1
+ import type { Hardwood } from "../hardwood.ts";
2
+ import type { CourtSpec } from "../leagues/basketball.ts";
3
+ import { type BuildOptions } from "./surface.ts";
4
+ /** What `basket` needs of the court, in feet. */
5
+ export interface HoopGeo {
6
+ L: number;
7
+ W: number;
8
+ /** The border's width. */
9
+ bw: number;
10
+ }
11
+ /**
12
+ * Both baskets from above, with their shadows. The backboard is where the court's figures put it (`court.backboard`), the rim in its place and size; the stanchion
13
+ * stands behind the baseline in the border and the ground beyond, with its padded base on the floor.
14
+ */
15
+ export declare function hoops(o: BuildOptions, h: Hardwood, court: CourtSpec, g: HoopGeo): string;
16
+ /** What the bench side needs of the court. */
17
+ export interface BenchGeo extends HoopGeo {
18
+ /** Where the coaching box ends along the sideline, from the baseline. */
19
+ box: number;
20
+ /** The thickness of a line. */
21
+ thin: number;
22
+ }
23
+ /**
24
+ * The coaching box's two lines across the border of the bottom sideline, the scorers' table in the middle of it, and a bench either side. They are drawn only when the
25
+ * ground beyond the border is deep enough to hold them.
26
+ */
27
+ export declare function bench(o: BuildOptions, g: BenchGeo, room: number): string;
@@ -0,0 +1,90 @@
1
+ // What stands on a realistic (`hardwood`) basketball floor, seen from above: each basket with its stanchion and its soft shadow, and along the bottom sideline the
2
+ // coaching box's lines, the scorers' table and the two benches. The shadows are stacked translucent shapes (a blur is not in every renderer), laid as if the light came
3
+ // from the top left: a thing 10 feet up throws its shadow farther than one on the floor. The stanchion's and the benches' places are drawn to look right, not measured
4
+ // from a rulebook: only the court's own figures (the board's width and place, the rim) are.
5
+ import { el, num } from "../format.js";
6
+ import { ft } from "./surface.js";
7
+ /** The shadow of a thing that stands this high (feet): how far it falls to the right and down the drawing. */
8
+ const fall = (height) => [height * 0.14, height * 0.1];
9
+ /** The soft shadow of a set of things: a few layers, each one path of every shadow grown by a few inches, so that its edge fades; one layer in the plain detail. */
10
+ function shadows(things, h) {
11
+ const layers = h.fine ? [[0.7, 0.025], [0.55, 0.03], [0.4, 0.03], [0.25, 0.035], [0.1, 0.04], [0, 0.04]] : [[0.15, 0.14]];
12
+ return layers
13
+ .map(([grow, opacity]) => {
14
+ const d = things.map(([[x0, y0, x1, y1], height]) => {
15
+ const [dx, dy] = fall(height);
16
+ return `M${num(x0 + dx - grow)} ${num(y0 + dy - grow)}H${num(x1 + dx + grow)}V${num(y1 + dy + grow)}H${num(x0 + dx - grow)}Z`;
17
+ });
18
+ return el("path", { class: "ky-hw-shade", d: d.join(""), fill: "#000", "fill-opacity": opacity });
19
+ })
20
+ .join("");
21
+ }
22
+ /**
23
+ * Both baskets from above, with their shadows. The backboard is where the court's figures put it (`court.backboard`), the rim in its place and size; the stanchion
24
+ * stands behind the baseline in the border and the ground beyond, with its padded base on the floor.
25
+ */
26
+ export function hoops(o, h, court, g) {
27
+ const { L, W } = g;
28
+ const cy = W / 2;
29
+ const half = court.backboard.width / 2;
30
+ const back = court.backboard.fromBaseline;
31
+ const pole = -(g.bw + 1.1);
32
+ const cast = [];
33
+ let rims = "";
34
+ let solid = "";
35
+ for (const end of [0, 1]) {
36
+ // A box in the left end's own feet, as the world's: mirrored about the court's middle at the right end.
37
+ const at = (x0, y0, x1, y1) => (end === 0 ? [x0, y0, x1, y1] : [L - x1, y0, L - x0, y1]);
38
+ const x = (v) => (end === 0 ? v : L - v);
39
+ const pad = at(pole - 1.2, cy - 2.6, pole + 1.2, cy + 2.6);
40
+ const arm = at(pole, cy - 0.38, back, cy + 0.38);
41
+ const top = at(pole - 0.7, cy - 0.7, pole + 0.7, cy + 0.7);
42
+ const board = at(back - 0.19, cy - half, back + 0.19, cy + half);
43
+ const bracket = at(back + 0.19, cy - 0.17, court.basket - court.rim, cy + 0.17);
44
+ const by = fall(10);
45
+ cast.push([pad, 0.6], [arm, 10], [top, 10], [board, 10]);
46
+ rims += el("circle", { class: "ky-hw-shade", cx: num(x(court.basket) + by[0]), cy: num(cy + by[1]), r: num(court.rim + 0.1), fill: "none", stroke: "#000", "stroke-opacity": h.fine ? 0.1 : 0.16, "stroke-width": num(h.fine ? 0.42 : 0.3) });
47
+ if (h.fine)
48
+ rims += el("circle", { class: "ky-hw-shade", cx: num(x(court.basket) + by[0]), cy: num(cy + by[1]), r: num(court.rim * 0.8), fill: "#000", "fill-opacity": 0.05 });
49
+ const rect = (cls, b, round) => el("rect", { class: cls, x: num(b[0]), y: num(b[1]), width: num(b[2] - b[0]), height: num(b[3] - b[1]), rx: num(round) || undefined });
50
+ solid += rect("ky-hw-pad", pad, 0.5) + rect("ky-hw-arm", arm, 0.1) + rect("ky-hw-arm", top, 0.25) + rect("ky-hw-arm", bracket, 0.05) + rect("ky-hw-glass", board, 0.06);
51
+ if (h.fine) {
52
+ solid += el("circle", { class: "ky-hw-net", cx: num(x(court.basket)), cy, r: num(court.rim * 0.8), "stroke-width": 0.04, "fill-opacity": 0, fill: "#fff" });
53
+ solid += el("circle", { class: "ky-hw-net", cx: num(x(court.basket)), cy, r: num(court.rim * 0.5), "stroke-width": 0.04, "stroke-opacity": 0.5 });
54
+ }
55
+ solid += el("circle", { class: ft(o, "rims", "ky-rim"), cx: num(x(court.basket)), cy, r: court.rim, "stroke-width": h.fine ? 0.17 : 0.2, fill: "none" });
56
+ }
57
+ return shadows(cast, h) + rims + solid;
58
+ }
59
+ /**
60
+ * The coaching box's two lines across the border of the bottom sideline, the scorers' table in the middle of it, and a bench either side. They are drawn only when the
61
+ * ground beyond the border is deep enough to hold them.
62
+ */
63
+ export function bench(o, g, room) {
64
+ const { L, W, bw } = g;
65
+ if (room < bw + 3.7)
66
+ return "";
67
+ let out = "";
68
+ const lines = [g.box, L - g.box].map((x) => `M${num(x)} ${num(W)}V${num(W + bw + 1.3)}`).join("");
69
+ out += el("path", { class: ft(o, "court-marks", "ky-line"), d: lines, "stroke-width": num(g.thin * 0.8), fill: "none" });
70
+ // The table is a long low box with a row of chairs behind it; each bench is a row of seats facing the court. All of it is one path.
71
+ const table = 8;
72
+ const parts = [];
73
+ const box = (x0, x1, y0, y1) => {
74
+ parts.push(`M${num(x0)} ${num(y0)}H${num(x1)}V${num(y1)}H${num(x0)}Z`);
75
+ };
76
+ const seats = (x0, x1, y, size) => {
77
+ const count = Math.max(1, Math.floor((x1 - x0) / (size * 1.45)));
78
+ const step = (x1 - x0) / count;
79
+ for (let i = 0; i < count; i += 1)
80
+ box(x0 + i * step + (step - size) / 2, x0 + i * step + (step + size) / 2, y, y + size);
81
+ };
82
+ const front = W + bw + 0.7;
83
+ box(L / 2 - table, L / 2 + table, front, front + 1.5);
84
+ seats(L / 2 - table + 0.5, L / 2 + table - 0.5, front + 1.9, 0.9);
85
+ for (const [a, b] of [[g.box + 1, L / 2 - table - 1], [L / 2 + table + 1, L - g.box - 1]])
86
+ if (b - a > 3)
87
+ seats(a, b, front + 0.2, 1.3);
88
+ out += el("path", { class: "ky-hw-furniture", d: parts.join("") });
89
+ return out;
90
+ }