@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
@@ -0,0 +1,156 @@
1
+ import { num } from "../format.js";
2
+ import { path } from "../fields.kit.js";
3
+ const EPS = 1e-6;
4
+ const close = (a, b, tol = 1e-4) => Math.abs(a - b) <= tol;
5
+ const r4 = (v) => Math.round(v * 10000) / 10000;
6
+ /** The kind of a piece of a floor laid with mats of a size. */
7
+ export function kindOf(w, h, mat, along) {
8
+ const long = along === "y" ? h : w;
9
+ const short = along === "y" ? w : h;
10
+ if (close(short, mat.width) && close(long, mat.length))
11
+ return "full";
12
+ if (close(short, mat.width) && close(long, mat.length / 2))
13
+ return "half";
14
+ return "cut";
15
+ }
16
+ /**
17
+ * Lay a rectangle with mats whose long sides run along `along`, in columns the width of a mat. With `stagger` every second column is set off by half a mat, so that no four
18
+ * corners meet (the traditional lay); without it the mats make a grid. The floor's ends and sides are cut to fit where its size is not a whole number of mats; a column that is
19
+ * set off begins and ends with half a mat.
20
+ */
21
+ export function lay(rect, mat, along, stagger) {
22
+ const out = [];
23
+ const acrossLen = along === "y" ? rect.x1 - rect.x0 : rect.y1 - rect.y0;
24
+ const alongLen = along === "y" ? rect.y1 - rect.y0 : rect.x1 - rect.x0;
25
+ const columns = Math.max(0, Math.ceil(acrossLen / mat.width - EPS));
26
+ for (let c = 0; c < columns; c += 1) {
27
+ const a0 = c * mat.width;
28
+ const a1 = Math.min(a0 + mat.width, acrossLen);
29
+ const offset = stagger && c % 2 === 1 ? mat.length / 2 : 0;
30
+ let b = 0;
31
+ if (offset > 0) {
32
+ const e = Math.min(offset, alongLen);
33
+ push(out, rect, along, a0, a1, 0, e, mat);
34
+ b = e;
35
+ }
36
+ while (b < alongLen - EPS) {
37
+ const e = Math.min(b + mat.length, alongLen);
38
+ push(out, rect, along, a0, a1, b, e, mat);
39
+ b = e;
40
+ }
41
+ }
42
+ return out;
43
+ }
44
+ function push(out, rect, along, a0, a1, b0, b1, mat) {
45
+ const x0 = along === "y" ? rect.x0 + a0 : rect.x0 + b0;
46
+ const x1 = along === "y" ? rect.x0 + a1 : rect.x0 + b1;
47
+ const y0 = along === "y" ? rect.y0 + b0 : rect.y0 + a0;
48
+ const y1 = along === "y" ? rect.y0 + b1 : rect.y0 + a1;
49
+ out.push({ x0: r4(x0), y0: r4(y0), x1: r4(x1), y1: r4(y1), kind: kindOf(x1 - x0, y1 - y0, mat, along), along, tone: 1 });
50
+ }
51
+ /** The part of a piece inside a box, and the parts of it outside, each a piece of its own (a mat cut where a colour changes). */
52
+ export function cutBy(piece, box, mat) {
53
+ const ix0 = Math.max(piece.x0, box.x0);
54
+ const iy0 = Math.max(piece.y0, box.y0);
55
+ const ix1 = Math.min(piece.x1, box.x1);
56
+ const iy1 = Math.min(piece.y1, box.y1);
57
+ const mk = (x0, y0, x1, y1) => ({ x0: r4(x0), y0: r4(y0), x1: r4(x1), y1: r4(y1), along: piece.along, tone: piece.tone, kind: kindOf(x1 - x0, y1 - y0, mat, piece.along) });
58
+ if (ix1 - ix0 <= EPS || iy1 - iy0 <= EPS)
59
+ return { inside: undefined, outside: [piece] };
60
+ const outside = [];
61
+ if (iy0 - piece.y0 > EPS)
62
+ outside.push(mk(piece.x0, piece.y0, piece.x1, iy0));
63
+ if (piece.y1 - iy1 > EPS)
64
+ outside.push(mk(piece.x0, iy1, piece.x1, piece.y1));
65
+ if (ix0 - piece.x0 > EPS)
66
+ outside.push(mk(piece.x0, iy0, ix0, iy1));
67
+ if (piece.x1 - ix1 > EPS)
68
+ outside.push(mk(ix1, iy0, piece.x1, iy1));
69
+ return { inside: mk(ix0, iy0, ix1, iy1), outside };
70
+ }
71
+ /**
72
+ * Give every piece the tone of the zone it lies in: the first of `zones` that holds it, else `rest`. A mat that a boundary runs through is cut there, each part
73
+ * taking its own zone's tone.
74
+ */
75
+ export function tint(pieces, zones, rest, mat) {
76
+ let left = pieces.map((p) => ({ ...p, tone: rest }));
77
+ const out = [];
78
+ for (const zone of zones) {
79
+ const next = [];
80
+ for (const p of left) {
81
+ const cut = cutBy(p, zone.box, mat);
82
+ if (cut.inside !== undefined)
83
+ out.push({ ...cut.inside, tone: zone.tone });
84
+ next.push(...cut.outside);
85
+ }
86
+ left = next;
87
+ }
88
+ return [...out, ...left].sort((a, b) => a.y0 - b.y0 || a.x0 - b.x0);
89
+ }
90
+ /** The mats of a checker floor: the tone alternates from one mat to the next, as the squares of a chessboard do. */
91
+ export function checker(pieces, rect, mat) {
92
+ return pieces.map((p) => {
93
+ const col = Math.round((p.along === "y" ? p.x0 - rect.x0 : p.y0 - rect.y0) / mat.width);
94
+ const row = Math.round((p.along === "y" ? p.y0 - rect.y0 : p.x0 - rect.x0) / mat.length);
95
+ return { ...p, tone: ((col + row) % 2 === 0 ? 1 : 2) };
96
+ });
97
+ }
98
+ /**
99
+ * How many points are a corner of four pieces or more: where four mats meet. A floor laid in the traditional way has none. Pieces that only touch along a side are not counted (a T is a point
100
+ * where one piece's side runs past the corners of two others, not a corner of three).
101
+ */
102
+ export function fourCorners(pieces) {
103
+ const count = new Map();
104
+ const key = (x, y) => `${Math.round(x * 1000)},${Math.round(y * 1000)}`;
105
+ for (const p of pieces) {
106
+ for (const [x, y] of [[p.x0, p.y0], [p.x1, p.y0], [p.x0, p.y1], [p.x1, p.y1]])
107
+ count.set(key(x, y), (count.get(key(x, y)) ?? 0) + 1);
108
+ }
109
+ let meets = 0;
110
+ for (const n of count.values())
111
+ if (n >= 4)
112
+ meets += 1;
113
+ return meets;
114
+ }
115
+ /** The floor's area in square metres. */
116
+ export const areaOf = (pieces) => pieces.reduce((sum, p) => sum + (p.x1 - p.x0) * (p.y1 - p.y0), 0);
117
+ /** The number of mats a floor holds, counted as the mats' own area: a half mat is a half, a cut piece the share of a mat it covers. */
118
+ export const matCount = (pieces, mat) => areaOf(pieces) / (mat.length * mat.width);
119
+ const rectD = (b) => `M${num(b.x0)} ${num(b.y0)}H${num(b.x1)}V${num(b.y1)}H${num(b.x0)}Z`;
120
+ /** The painted areas of a floor of mats: one path for each tone, in the class the look gives it. */
121
+ export function tatamiAreas(id, pieces, classes, feature) {
122
+ const out = [];
123
+ for (const tone of [1, 2, 3]) {
124
+ const of = pieces.filter((p) => p.tone === tone);
125
+ if (of.length > 0)
126
+ out.push({ id: `${id}-t${tone}`, feature: feature[tone], cls: classes[tone], d: of.map(rectD).join("") });
127
+ }
128
+ return out;
129
+ }
130
+ /** The seams: the outline of every piece, as one line. */
131
+ export function seams(id, pieces, width) {
132
+ if (pieces.length === 0)
133
+ return [];
134
+ return [path(`${id}-seams`, "seams", pieces.map(rectD).join(""), { w: width, cls: "ky-bud-seam", least: 0 })];
135
+ }
136
+ /** The heri (畳縁), the cloth along the two long sides of a traditional mat, as filled strips inside the mat. Cut pieces and the thin ends of a floor have none. */
137
+ export function heri(id, pieces, width, mat) {
138
+ const strips = [];
139
+ for (const p of pieces) {
140
+ if (p.kind === "cut")
141
+ continue;
142
+ const w = p.x1 - p.x0;
143
+ const h = p.y1 - p.y0;
144
+ if (p.along === "y") {
145
+ if (w < mat.width * 0.9 || h < mat.length * 0.45)
146
+ continue;
147
+ strips.push(rectD({ x0: p.x0, y0: p.y0, x1: p.x0 + width, y1: p.y1 }), rectD({ x0: p.x1 - width, y0: p.y0, x1: p.x1, y1: p.y1 }));
148
+ }
149
+ else {
150
+ if (h < mat.width * 0.9 || w < mat.length * 0.45)
151
+ continue;
152
+ strips.push(rectD({ x0: p.x0, y0: p.y0, x1: p.x1, y1: p.y0 + width }), rectD({ x0: p.x0, y0: p.y1 - width, x1: p.x1, y1: p.y1 }));
153
+ }
154
+ }
155
+ return strips.length === 0 ? [] : [{ id: `${id}-heri`, feature: "heri", cls: "ky-bud-heri", d: strips.join("") }];
156
+ }
@@ -0,0 +1,192 @@
1
+ /** The sports of the budō family. */
2
+ export type BudoKind = "judo" | "karate" | "kendo" | "sumo" | "kyudo" | "dojo";
3
+ /** The sides of a hall, as a plan has them: north is the top of the drawing. `top`, `bottom`, `left` and `right` say the same. */
4
+ export type Compass = "north" | "south" | "east" | "west";
5
+ export type Side4 = Compass | "top" | "bottom" | "left" | "right";
6
+ /**
7
+ * What a budō drawing takes beyond a surface. Every part is optional: a judo contest area is the IJF's of 10 m with a safety area of 4 m, a karate area the WKF's kumite square, a kendo
8
+ * shiai-jo of 10 m, a dohyō of the Japan Sumo Association and a kyūdōjō of 28 m with five shooters, drawn without any.
9
+ */
10
+ export interface BudoStyle {
11
+ /** A named look: the colours of the mats and of the floor. Judo: `yellow-red` (the IJF's own, the default), `yellow-blue`, `blue-grey`, `green-beige` (the traditional tatami), `green-red` (green mats with a red danger zone) and `black-red`. Karate: `blue-red` (the default), `blue-black`, `green-beige`. Kendo: `wood` (the default), `blond`. Sumo: `clay`. Kyūdō: `wood`. Dojo: `green-beige` (the default), `yellow-red`, `yellow-blue`, `blue-grey`, `black-red`, `green-red`. */
12
+ look?: string;
13
+ /** Judo and karate: how many competition areas lie side by side, 1 to 6 (1 by default), or `{ across, down }` for a block of them. They are as far apart as the rules ask, the common safety area. */
14
+ areas?: number | {
15
+ across: number;
16
+ down: number;
17
+ };
18
+ /** Judo, karate and kendo: the arena floor under the surface. `budokan` is the Nippon Budokan's, an octagon 55 m across the flats (the Budokan's leaflet), with the surface in the middle; it must fit. */
19
+ hall?: "budokan";
20
+ /** Judo: the contest area's side, 8 m to 10 m. Kendo: the shiai-jo's side, 9 m to 11 m. In metres. */
21
+ size?: number;
22
+ /** Judo: the width of the safety area, 3 m or more (4 m by default). In metres. */
23
+ safety?: number;
24
+ /** Judo: the tatami's size. `2x1` (the IJF's, 2 m by 1 m, the default of an IJF area), `1x1` (the half tatami) or `182x91` (the AJJF's own, the default of an AJJF area). */
25
+ tatami?: "2x1" | "1x1" | "182x91";
26
+ /** Judo: the tape that marks where the contestants start. On by default for the AJJF's area and the kata area, and for the IJF's (the 2020 rules' blue and white tape). */
27
+ start?: boolean;
28
+ /** Judo: a solid platform under the tatami, one metre wider and longer than it. Off by default. */
29
+ platform?: boolean;
30
+ /** Judo and karate: the technical table, the officials' seats and the judges, outside the safety area. Off by default. */
31
+ officials?: boolean;
32
+ /** Judo: draw the lines of the mats (the seams between them). On by default. */
33
+ seams?: boolean;
34
+ /** Judo and dojo: `weave` draws the rice-straw weave of a mat as fine ridges along each mat's long side (they turn a quarter where a mat does), with a faint highlight on the mat edges; `none` leaves the mats plain. A traditional dojo has it by default, a judo area has none. It drops away at the simple detail. */
35
+ texture?: "weave" | "none";
36
+ /** Karate: the referee's and the judges' places. On by default. */
37
+ judges?: boolean;
38
+ /** Sumo: the height of the clay square in metres, 0.34 to 0.60. 0.55 by default. Seen in 3D. */
39
+ height?: number;
40
+ /** Sumo: the four tassels of the roof, in the colours of the four quarters (green east, red south, white west, black north). Off by default. */
41
+ tassels?: boolean;
42
+ /** Sumo: the tawara, the shikiri-sen and the sand of the jano-me. On by default. */
43
+ tawara?: boolean;
44
+ /** Kyūdō: the number of shooters in a line, 1 to 12 (5 by default). */
45
+ shooters?: number;
46
+ /** Kyūdō: the kind of range, `kinteki` (28 m, the default) or `enteki` (60 m); `league` says it too. */
47
+ range?: "kinteki" | "enteki";
48
+ /** Kyūdō: the target of each shooter at the azuchi. On by default. */
49
+ targets?: boolean;
50
+ /** Kyūdō: the roof of the shajō. On by default. */
51
+ roof?: boolean;
52
+ }
53
+ /** What each team has scored, as the sport counts it. Every part is optional; what is not given is left out of the board. */
54
+ export interface BudoScore {
55
+ /** Judo, karate: the number of ippon (judo: 1 ends the contest; the IJF's scoreboard writes 100). */
56
+ ippon?: number;
57
+ /** Judo (10 on the scoreboard), karate (2 points). Two waza-ari are ippon in judo. */
58
+ wazaari?: number;
59
+ /** Judo (1 on the scoreboard), karate (1 point). */
60
+ yuko?: number;
61
+ /** Judo: the shido, three of which are hansoku-make. Karate: the warnings (chui), up to three. */
62
+ shido?: number;
63
+ /** Karate: the first unopposed score, senshu (先取). */
64
+ senshu?: boolean;
65
+ /** Kendo: the points of the match, each by the target struck: `men`, `kote`, `do` or `tsuki`, or `hansoku` for the point a foul gave the other side. */
66
+ techniques?: readonly string[];
67
+ /** Sumo: the kimarite that decided the bout, by its key (`yorikiri`) or its name (寄り切り). Only the winner's. */
68
+ kimarite?: string;
69
+ }
70
+ /** A door of a dojo: the wall it is in, where along it (0 to 1, the middle by default) and how wide (1.8 m by default). */
71
+ export interface Entrance {
72
+ wall: Side4;
73
+ at?: number;
74
+ width?: number;
75
+ }
76
+ /** A window of a dojo: the wall, where along it (0 to 1, the middle by default) and how wide (1.8 m by default). */
77
+ export interface DojoWindow {
78
+ wall: Side4;
79
+ at?: number;
80
+ width?: number;
81
+ }
82
+ /** The size of a dojo's floor: the mats across and along, or a size with a unit, or the area in jō. */
83
+ export type DojoSize = number | readonly [number, number] | {
84
+ width?: number;
85
+ length?: number;
86
+ unit?: "m" | "ft" | "mat" | "jo";
87
+ jo?: number;
88
+ };
89
+ /** The ways a dojo's mats are laid. */
90
+ export type DojoPattern = "traditional" | "competition" | "checker" | "border";
91
+ /** One look of a dojo's floor in its history. */
92
+ export interface DojoEra {
93
+ /** The era's name, as `era` asks for it (`earlier`, `current`). */
94
+ name: string;
95
+ nameJa?: string;
96
+ /** The first and the last year it lasted, `null` where no source gives the year (an era with no years is picked by name, or as the last). */
97
+ from?: number | null;
98
+ to?: number | null;
99
+ look?: string;
100
+ colours?: DojoColours;
101
+ pattern?: DojoPattern;
102
+ areas?: number | {
103
+ across: number;
104
+ down: number;
105
+ };
106
+ areaSize?: number;
107
+ outline?: boolean;
108
+ }
109
+ /** The colours a dojo may be given, each a CSS colour. */
110
+ export interface DojoColours {
111
+ /** The mats. */
112
+ mat?: string;
113
+ /** The second tone: the other mats of a `checker` floor, the worn side of a mat, the border of a `border` floor. */
114
+ alt?: string;
115
+ /** The border of a `border` floor (a danger zone). */
116
+ border?: string;
117
+ /** The heri (畳縁), the cloth edge along a traditional mat's long sides. */
118
+ heri?: string;
119
+ /** The wood of the floor outside the mats, and of the walls' base. */
120
+ floor?: string;
121
+ /** The walls. */
122
+ wall?: string;
123
+ }
124
+ /**
125
+ * A dojo (道場): the floor in mats, laid out as real tatami units, and what stands round it. Every part is optional: 20 jō of traditional mats with the kamiza at the north, no walls.
126
+ * `dojo()` makes its plan, and `drawKyogijo({ sport: "dojo", dojo })` draws it.
127
+ */
128
+ export interface DojoSpec {
129
+ /**
130
+ * The floor. A number is its area in jō (畳): 8, 12, 20, 50, 100 or 200 give the usual shapes. `[across, along]` is the number of whole mats across the floor and along it
131
+ * (`[5, 4]` is 20 jō). `{ width, length, unit }` is a size in metres (the default), feet, `mat` (as the array) or `jo`. 20 jō by default.
132
+ */
133
+ mats?: DojoSize;
134
+ /** The area in jō, as `mats: 20` says it. */
135
+ jo?: number;
136
+ /** `traditional` (the default): mats laid so that no four corners meet, with a heri along the long sides. `competition`: the same lay, with the contest areas' colours. `checker`: the mats' tones alternate. `border`: a band of another colour round the floor. */
137
+ pattern?: DojoPattern;
138
+ /** The colours. A named look in `look` sets all of them. */
139
+ colours?: DojoColours;
140
+ colors?: DojoColours;
141
+ /** A named look: `green-beige` (the default), `yellow-red`, `yellow-blue`, `blue-grey`, `black-red`, `green-red`. */
142
+ look?: string;
143
+ /** The wall the kamiza (上座), the seat of honour, is at. North (the top of the drawing) by default. The shōmen is that wall. */
144
+ kamiza?: Side4;
145
+ /** The doors. One in the middle of the wall opposite the kamiza by default. */
146
+ entrances?: readonly Entrance[];
147
+ /** The walls round the floor. On by default; `false` for the floor alone. */
148
+ walls?: boolean | {
149
+ thickness?: number;
150
+ };
151
+ /** The windows: a list, or a number of them spread along the long walls. None by default. */
152
+ windows?: readonly DojoWindow[] | number;
153
+ /** The shinzen (神前), a shrine at the middle of the kamiza wall. Off by default. */
154
+ shinzen?: boolean;
155
+ /** The dojo's name, for the title and the description. */
156
+ label?: string;
157
+ labelJa?: string;
158
+ /** Judo contest areas laid on the floor: 1 to 6 in a row (none by default), or `{ across, down }` for a block (`{ across: 2, down: 2 }` is four), of 8 m with a safety area where they fit. */
159
+ areas?: number | {
160
+ across: number;
161
+ down: number;
162
+ };
163
+ /** The side of a contest area laid on the floor, 8 m to 10 m (the IJF's, 8 m by default). In metres. */
164
+ areaSize?: number;
165
+ /** A band one mat wide round each contest area in the third colour (the border mats that outline an area on a floor of one colour). Off by default. */
166
+ outline?: boolean;
167
+ /** `weave` or `none`: the rice-straw weave of the mats (on by default for the traditional and border lays). */
168
+ texture?: "weave" | "none";
169
+ /** The wood round the mats, between them and the walls, in metres (none by default; the Kodokan's main dojo has a polished wood surround). */
170
+ surround?: number;
171
+ /** A spectators' balcony above the floor, as `dojoRoom()` gives it (it is not part of the plan's drawing; `crowd` draws the stands): `true` for all four sides, or the sides, depth in metres (3 by default), seat rows (5) and height above the mats (4 m). */
172
+ balcony?: boolean | {
173
+ sides?: readonly Side4[];
174
+ depth?: number;
175
+ rows?: number;
176
+ height?: number;
177
+ };
178
+ /** The seat of honour's platform: a raised wooden dais at the middle of the kamiza wall (a chair stands on it in the Kodokan's main dojo). Off by default. */
179
+ dais?: boolean;
180
+ /** A plain dark vertical banner on the kamiza wall, over the dais or the shrine (a drawing of a banner, never any emblem). Off by default. */
181
+ banner?: boolean;
182
+ /**
183
+ * The history of the floor: the looks it has had, oldest first. Each era names itself and may say the years it lasted (`from` and `to`, both inclusive, `null` where the years are not known),
184
+ * and any of `look`, `colours`, `pattern`, `areas`, `areaSize` and `outline` it changes. `era` picks one by name; `year` picks the one that holds the year (the first whose years hold it);
185
+ * with neither, the last (the floor as it is now) is drawn.
186
+ */
187
+ eras?: readonly DojoEra[];
188
+ era?: string;
189
+ year?: number;
190
+ /** The mat standard: a league of the `dojo` sport: `chukyoma` (the default), `kyoma`, `edoma`, `danchima` or `judo-2x1`; `league` says it too. */
191
+ standard?: string;
192
+ }
@@ -0,0 +1,2 @@
1
+ // The types of the budō (武道) surfaces: judo and karate contest areas, the kendo shiai-jo, the sumo dohyō, the kyūdōjō, and a dojo of tatami, and the options that say what is drawn. Plain data only.
2
+ export {};
@@ -0,0 +1,22 @@
1
+ export { DOJO_STANDARDS, dojo, drawDojo } from "./budo/dojo.api.ts";
2
+ export type { Dojo, Tatami } from "./budo/dojo.api.ts";
3
+ export { DOJO_SIZES, floorOf, shapeOfJo } from "./budo/dojo.ts";
4
+ export { dojoGallery, dojoRoom, ROOM_HEIGHTS } from "./budo/room.ts";
5
+ export type { DojoGallery, DojoRoom, RoomBalcony, RoomBasis, RoomOpening, RoomWall } from "./budo/room.ts";
6
+ export { budoLeague, budoPlan, BUDO_SPORTS, BUDOKAN_ARENA, isBudoSport } from "./budo/plan.ts";
7
+ export type { BudoPlan, MBox, MMark, MRange } from "./budo/plan.ts";
8
+ export { checker, fourCorners, kindOf, lay, matCount, tint } from "./budo/tatami.ts";
9
+ export type { MatSize, Piece, PieceKind } from "./budo/tatami.ts";
10
+ export { TATAMI } from "./budo/judo.ts";
11
+ export { KIMARITE, KIMARITE_COUNT, KIMARITE_OTHERS, kimariteName, kimariteOf } from "./budo/kimarite.ts";
12
+ export type { Kimarite, KimariteGroup } from "./budo/kimarite.ts";
13
+ export { BUDO_LOOKS, lookNames } from "./budo/looks.ts";
14
+ export type { BudoLook } from "./budo/looks.ts";
15
+ export { budoScoreText, budoView } from "./budo.score.ts";
16
+ export type { BudoView } from "./budo.score.ts";
17
+ export { KYOGIJO_BUDO_STYLE } from "./budo.style.ts";
18
+ export { AJJF_CONTEST, BUDO_LEAGUES, DOJO_LEAGUES, ENTEKI, FIK_SHIAI_JO, IJF_CONTEST, IJF_KATA, JSA_DOHYO, JUDO_LEAGUES, KARATE_LEAGUES, KENDO_LEAGUES, KINTEKI, KYUDO_LEAGUES, SUMO_LEAGUES } from "./leagues/budo.ts";
19
+ export type { BudoFigures, BudoLeague, DojoFigures, DojoLeague, JudoFigures, JudoLeague, KarateFigures, KarateLeague, KendoFigures, KendoLeague, KyudoFigures, KyudoLeague, Mat, SumoFigures, SumoLeague } from "./leagues/budo.ts";
20
+ export { HALLS } from "./halls.ts";
21
+ export type { Hall, HallBasis, HallSurface } from "./halls.ts";
22
+ export type { BudoKind, BudoScore, BudoStyle, Compass, DojoColours, DojoEra, DojoPattern, DojoSize, DojoSpec, DojoWindow, Entrance, Side4 } from "./budo/types.ts";
@@ -0,0 +1,13 @@
1
+ // The budō (武道): judo and karate competition areas, the kendo shiai-jo, the sumo dohyō, the kyūdōjō and the dojo builder, with their plans, the tatami layout, the kimarite, the looks and the stylesheet.
2
+ export { DOJO_STANDARDS, dojo, drawDojo } from "./budo/dojo.api.js";
3
+ export { DOJO_SIZES, floorOf, shapeOfJo } from "./budo/dojo.js";
4
+ export { dojoGallery, dojoRoom, ROOM_HEIGHTS } from "./budo/room.js";
5
+ export { budoLeague, budoPlan, BUDO_SPORTS, BUDOKAN_ARENA, isBudoSport } from "./budo/plan.js";
6
+ export { checker, fourCorners, kindOf, lay, matCount, tint } from "./budo/tatami.js";
7
+ export { TATAMI } from "./budo/judo.js";
8
+ export { KIMARITE, KIMARITE_COUNT, KIMARITE_OTHERS, kimariteName, kimariteOf } from "./budo/kimarite.js";
9
+ export { BUDO_LOOKS, lookNames } from "./budo/looks.js";
10
+ export { budoScoreText, budoView } from "./budo.score.js";
11
+ export { KYOGIJO_BUDO_STYLE } from "./budo.style.js";
12
+ export { AJJF_CONTEST, BUDO_LEAGUES, DOJO_LEAGUES, ENTEKI, FIK_SHIAI_JO, IJF_CONTEST, IJF_KATA, JSA_DOHYO, JUDO_LEAGUES, KARATE_LEAGUES, KENDO_LEAGUES, KINTEKI, KYUDO_LEAGUES, SUMO_LEAGUES } from "./leagues/budo.js";
13
+ export { HALLS } from "./halls.js";
@@ -0,0 +1,28 @@
1
+ import type { BudoView } from "./budo.score.ts";
2
+ import type { TeamView } from "./score.ts";
3
+ import type { PlateSpot } from "./surfaces/surface.ts";
4
+ /** The words of a board. */
5
+ export interface BudoBoardWords {
6
+ competition?: string;
7
+ foot?: string;
8
+ wazaari: string;
9
+ yuko: string;
10
+ shido: string;
11
+ senshu: string;
12
+ chui: string;
13
+ kimarite: string;
14
+ /** The first letter or character of each technique's name, for a kendo point. */
15
+ techniques: Record<string, string>;
16
+ /** What the winner's kimarite is called, already in the language. */
17
+ kimariteName: (key: string) => string;
18
+ }
19
+ type Sport = "judo" | "karate" | "kendo" | "sumo";
20
+ /** A team as the board reads it. */
21
+ export type BoardTeam = TeamView & {
22
+ budo?: BudoView;
23
+ };
24
+ /** The board as a group centred on the origin. `spot` is the room it has; it takes only what its rows and columns need. */
25
+ export declare function budoBoardMarkup(sport: Sport, spot: PlateSpot, left: BoardTeam, right: BoardTeam, words: BudoBoardWords, o: {
26
+ parts: boolean;
27
+ }): string;
28
+ export {};
@@ -0,0 +1,81 @@
1
+ // The budō scoreboards: judo's (the waza-ari, the yuko and the shido of each side beside its score), karate's (the points, the senshu and the warnings), kendo's (the techniques of its points, as the
2
+ // letters of their targets) and sumo's (the result and the kimarite). Drawn on the surface, in the frame the eye sees; the caller turns it back when the surface is turned.
3
+ import { el, esc } from "./format.js";
4
+ import { fitLines, textWidth } from "./text.js";
5
+ const text = (x, cy, value, size, cls, extra = {}) => el("text", { class: `ky-text ${cls}`, x, y: cy + size * 0.36, "font-size": size, "text-anchor": "middle", ...extra }, esc(value));
6
+ const fit = (value, room, ceiling) => Math.max(0.1, Math.min(ceiling, room / Math.max(1, textWidth(value))));
7
+ const num = (v) => (v === undefined ? "" : String(v));
8
+ /** The columns of a sport's board, between the name and the total. */
9
+ function columns(sport, w) {
10
+ switch (sport) {
11
+ case "judo":
12
+ return [
13
+ { head: w.wazaari, width: 1.7, cell: (t) => num(t.budo?.wazaari) },
14
+ { head: w.yuko, width: 1.3, cell: (t) => num(t.budo?.yuko) },
15
+ { head: w.shido, width: 1.3, cell: (t) => num(t.budo?.shido) },
16
+ ];
17
+ case "karate":
18
+ return [
19
+ { head: w.chui, width: 1.3, cell: (t) => num(t.budo?.shido) },
20
+ { head: w.senshu, width: 1.5, cell: (t) => (t.budo?.senshu === true ? "●" : "") },
21
+ ];
22
+ case "kendo":
23
+ return [0, 1].map((k) => ({ head: String(k + 1), width: 1.2, cell: (t) => { const v = t.budo?.techniques?.[k]; return v === undefined ? "" : (w.techniques[v] ?? v).slice(0, 1).toUpperCase(); } }));
24
+ case "sumo":
25
+ return [{ head: w.kimarite, width: 4.2, cell: (t) => (t.budo?.kimarite === undefined || t.state !== "win" ? "" : w.kimariteName(t.budo.kimarite)) }];
26
+ }
27
+ }
28
+ /** The board as a group centred on the origin. `spot` is the room it has; it takes only what its rows and columns need. */
29
+ export function budoBoardMarkup(sport, spot, left, right, words, o) {
30
+ const cols = columns(sport, words);
31
+ const team = [left, right];
32
+ const total = cols.reduce((sum, c) => sum + c.width, 0);
33
+ const units = 3 + total + 1.9;
34
+ const extra = (words.competition ? 0.8 : 0) + (words.foot ? 0.8 : 0);
35
+ const rows = 3 + extra;
36
+ const colU = Math.min(spot.w / units, spot.h / rows / 0.72);
37
+ const rowH = Math.min(spot.h / rows, colU * 0.72);
38
+ const w = colU * units;
39
+ const h = rowH * rows;
40
+ const x0 = -w / 2;
41
+ let y = -h / 2;
42
+ const parts = (names) => (o.parts ? names : undefined);
43
+ let inner = el("rect", { class: "ky-plate-bg", x: -w / 2, y: -h / 2, width: w, height: h, rx: Math.min(rowH * 0.5, w * 0.04) });
44
+ const band = (value, cls) => {
45
+ const bandH = rowH * 0.8;
46
+ inner += text(0, y + bandH / 2, value, fit(value, w * 0.92, bandH * 0.62), cls);
47
+ y += bandH;
48
+ };
49
+ if (words.competition)
50
+ band(words.competition, "ky-comp");
51
+ const nameW = colU * 3;
52
+ let cx = x0 + nameW;
53
+ const centres = [];
54
+ for (const c of cols) {
55
+ centres.push(cx + (c.width * colU) / 2);
56
+ inner += text(centres[centres.length - 1], y + rowH / 2, c.head, fit(c.head, c.width * colU * 0.9, rowH * 0.42), "ky-foot");
57
+ cx += c.width * colU;
58
+ }
59
+ const totalX = cx + colU * 0.95;
60
+ y += rowH;
61
+ for (const t of team) {
62
+ inner += el("rect", { class: `ky-panel-${t.side}`, x: x0 + 0.1 * colU, y: y + rowH * 0.06, width: nameW - 0.2 * colU, height: rowH * 0.88, rx: rowH * 0.2 });
63
+ const name = fitLines(t.name, (nameW - 0.3 * colU) * 0.92, rowH * 0.8, rowH * 0.5);
64
+ name.lines.forEach((line, k) => {
65
+ inner += text(x0 + 0.1 * colU + (nameW - 0.2 * colU) / 2, y + rowH / 2 + (k - (name.lines.length - 1) / 2) * name.size * 1.1, line, name.size, `ky-ink-${t.side}`);
66
+ });
67
+ cols.forEach((c, k) => {
68
+ const v = c.cell(t);
69
+ if (v !== "")
70
+ inner += text(centres[k], y + rowH / 2, v, fit(v, c.width * colU * 0.92, rowH * 0.56), "ky-score");
71
+ });
72
+ const size = fit(t.score, colU * 1.8, rowH * 0.76);
73
+ inner += el("g", { class: `ky-total ky-${t.state}`, part: parts(`score ${t.role}-score`) }, text(totalX, y + rowH / 2, t.score, size, "ky-score"));
74
+ if (t.state === "win")
75
+ inner += el("rect", { class: `ky-winbar ky-winbar-${t.side}`, x: totalX - (textWidth(t.score) * size) / 2, y: y + rowH / 2 + size * 0.5, width: textWidth(t.score) * size, height: Math.max(0.05, size * 0.06) });
76
+ y += rowH;
77
+ }
78
+ if (words.foot)
79
+ band(words.foot, "ky-foot");
80
+ return el("g", { class: "ky-plate ky-scoreboard", part: parts("plate") }, inner);
81
+ }
@@ -0,0 +1,18 @@
1
+ import type { BudoScore, Sport, Team } from "./types.ts";
2
+ /** The budō score of a team, cleaned: each count a whole number held to what the sport allows. */
3
+ export interface BudoView {
4
+ ippon?: number;
5
+ wazaari?: number;
6
+ yuko?: number;
7
+ shido?: number;
8
+ senshu?: boolean;
9
+ techniques?: string[];
10
+ kimarite?: string;
11
+ }
12
+ /** Read a team's `budo`. */
13
+ export declare function budoView(score: BudoScore | undefined): BudoView | undefined;
14
+ /**
15
+ * The total of a side as its sport counts it, when the side gave no `score` of its own. Judo's scoreboard writes ippon (and two waza-ari, waza-ari-awasete-ippon) as 100, a waza-ari as 10 and a yuko as 1 (IJF
16
+ * SOR 2.5.5.1 and the scoreboard's notes); karate's points are yuko 1, waza-ari 2 and ippon 3 (WKF Kumite 8.6); kendo's is the number of its points (the techniques that are not hansoku).
17
+ */
18
+ export declare function budoScoreText(sport: Sport, team: Pick<Team, "budo" | "score">): string | undefined;
@@ -0,0 +1,52 @@
1
+ const whole = (v, hi) => (typeof v === "number" && Number.isFinite(v) && v >= 0 ? Math.min(hi, Math.floor(v)) : undefined);
2
+ /** Read a team's `budo`. */
3
+ export function budoView(score) {
4
+ if (score === undefined || score === null || typeof score !== "object")
5
+ return undefined;
6
+ const out = {};
7
+ const ippon = whole(score.ippon, 9);
8
+ const wazaari = whole(score.wazaari, 9);
9
+ const yuko = whole(score.yuko, 99);
10
+ const shido = whole(score.shido, 9);
11
+ if (ippon !== undefined)
12
+ out.ippon = ippon;
13
+ if (wazaari !== undefined)
14
+ out.wazaari = wazaari;
15
+ if (yuko !== undefined)
16
+ out.yuko = yuko;
17
+ if (shido !== undefined)
18
+ out.shido = shido;
19
+ if (score.senshu === true)
20
+ out.senshu = true;
21
+ if (Array.isArray(score.techniques))
22
+ out.techniques = score.techniques.filter((t) => typeof t === "string").map((t) => t.trim().toLowerCase().slice(0, 12)).filter((t) => t !== "").slice(0, 3);
23
+ if (typeof score.kimarite === "string" && score.kimarite.trim() !== "")
24
+ out.kimarite = score.kimarite.trim().slice(0, 40);
25
+ return Object.keys(out).length === 0 ? undefined : out;
26
+ }
27
+ /**
28
+ * The total of a side as its sport counts it, when the side gave no `score` of its own. Judo's scoreboard writes ippon (and two waza-ari, waza-ari-awasete-ippon) as 100, a waza-ari as 10 and a yuko as 1 (IJF
29
+ * SOR 2.5.5.1 and the scoreboard's notes); karate's points are yuko 1, waza-ari 2 and ippon 3 (WKF Kumite 8.6); kendo's is the number of its points (the techniques that are not hansoku).
30
+ */
31
+ export function budoScoreText(sport, team) {
32
+ if (team.score !== undefined && team.score !== null && String(team.score).trim() !== "")
33
+ return undefined;
34
+ const v = budoView(team.budo);
35
+ if (v === undefined)
36
+ return undefined;
37
+ if (sport === "judo") {
38
+ if ((v.ippon ?? 0) > 0 || (v.wazaari ?? 0) >= 2)
39
+ return "100";
40
+ if (v.wazaari === undefined && v.yuko === undefined)
41
+ return undefined;
42
+ return String((v.wazaari ?? 0) * 10 + (v.yuko ?? 0));
43
+ }
44
+ if (sport === "karate") {
45
+ if (v.ippon === undefined && v.wazaari === undefined && v.yuko === undefined)
46
+ return undefined;
47
+ return String((v.ippon ?? 0) * 3 + (v.wazaari ?? 0) * 2 + (v.yuko ?? 0));
48
+ }
49
+ if (sport === "kendo")
50
+ return v.techniques === undefined ? undefined : String(v.techniques.filter((t) => t !== "hansoku").length);
51
+ return undefined;
52
+ }
@@ -0,0 +1,6 @@
1
+ /** The rules of a dojo's gallery, the stands of a crowd in a dojo: brown seats and a rail, a few neutral people. */
2
+ export declare const KYOGIJO_BUDO_GALLERY_STYLE = "\n.kyogijo .ky-bud-gbed.ky-bud-gbed{fill:var(--ky-bud-gal,#7a5a3c)}\n.kyogijo .ky-bud-gblk.ky-bud-gblk{fill:var(--ky-bud-gpeople,#a89a86)}\n.kyogijo .ky-bud-gseat.ky-bud-gseat{stroke:var(--ky-bud-grail,#3a2c1f);stroke-opacity:.3}\n.kyogijo .ky-bud-rail{stroke:var(--ky-bud-grail,#3a2c1f);stroke-width:1.6;stroke-opacity:.85}\n";
3
+ /** The rules of a drawing of a budō sport in a look: the shared rules and the look's colours. Nothing for another sport. */
4
+ export declare function budoStyle(sport: string, look?: string): string;
5
+ /** Every budō sport's rules and every look, for a page that draws with `style: "none"` and supplies the stylesheet itself. */
6
+ export declare const KYOGIJO_BUDO_STYLE: string;
@@ -0,0 +1,67 @@
1
+ // The stylesheet of a budō drawing: the rules of its classes (the mats in three tones, the heri, the floor, the walls, the clay, the sand, the straw, the azuchi, the tape) in the sheet's own custom
2
+ // properties, so that a named look, the options' `colors` and a page's own rule all win; and the colours of each budō look, in light and dark. See looks.ts for where the colours come from.
3
+ import { BUDO_LOOKS } from "./budo/looks.js";
4
+ const CLASSES = `
5
+ .kyogijo .ky-bud-t1{fill:var(--ky-surface)}
6
+ .kyogijo .ky-bud-t2{fill:var(--ky-surface-alt,var(--ky-surface))}
7
+ .kyogijo .ky-bud-t3{fill:var(--ky-red)}
8
+ .kyogijo .ky-bud-heri{fill:var(--ky-bud-heri,var(--ky-ink));fill-opacity:.82}
9
+ .kyogijo .ky-bud-seam{stroke:var(--ky-ink);stroke-opacity:.26;fill:none;stroke-linejoin:round}
10
+ .kyogijo .ky-bud-line{stroke:var(--ky-line);fill:none}
11
+ .kyogijo .ky-bud-ink{stroke:var(--ky-ink);fill:none}
12
+ .kyogijo .ky-bud-floor{fill:var(--ky-bud-floor,var(--ky-boards))}
13
+ .kyogijo .ky-bud-wall{fill:var(--ky-boards)}
14
+ .kyogijo .ky-bud-window{fill:var(--ky-blue,#2a5db0);fill-opacity:.55}
15
+ .kyogijo .ky-bud-door{fill:var(--ky-apron)}
16
+ .kyogijo .ky-bud-platform{fill:var(--ky-bud-floor,var(--ky-boards))}
17
+ .kyogijo .ky-bud-free{fill:var(--ky-free,var(--ky-apron))}
18
+ .kyogijo .ky-bud-desk{fill:var(--ky-ink);fill-opacity:.55}
19
+ .kyogijo .ky-bud-seat{fill:var(--ky-ink);fill-opacity:.42}
20
+ .kyogijo .ky-bud-shrine{fill:var(--ky-red)}
21
+ .kyogijo .ky-bud-edge{stroke:#fff;stroke-opacity:.2;stroke-width:.03;fill:none}
22
+ .kyogijo .ky-bud-dais{fill:var(--ky-bud-floor,var(--ky-boards));stroke:var(--ky-ink);stroke-opacity:.5;stroke-width:.04}
23
+ .kyogijo .ky-bud-banner{fill:var(--ky-ink);fill-opacity:.85}
24
+ .kyogijo .ky-bud-clay{fill:var(--ky-dirt)}
25
+ .kyogijo .ky-bud-sand{fill:var(--ky-sand,#e8dcc2)}
26
+ .kyogijo .ky-bud-tawara{fill:var(--ky-bud-straw,#c8a45c);stroke:var(--ky-ink);stroke-opacity:.45;stroke-width:.03}
27
+ .kyogijo .ky-bud-azuchi{fill:var(--ky-dirt)}
28
+ .kyogijo .ky-bud-yamichi{fill:var(--ky-surface)}
29
+ .kyogijo .ky-bud-lane{fill:var(--ky-surface-alt,var(--ky-surface))}
30
+ .kyogijo .ky-bud-mato{fill:var(--ky-line);stroke:var(--ky-ink);stroke-width:.04}
31
+ .kyogijo .ky-bud-roof{fill:var(--ky-ink);fill-opacity:.12}
32
+ .kyogijo .ky-bud-blue-fill{fill:var(--ky-blue,#2a5db0)}
33
+ .kyogijo .ky-bud-white-fill{fill:var(--ky-line)}
34
+ .kyogijo .ky-bud-red-fill{fill:var(--ky-red)}
35
+ .kyogijo .ky-bud-ink-fill{fill:var(--ky-ink)}
36
+ .kyogijo .ky-bud-tassel-e{fill:#2f9e63;stroke:var(--ky-ink);stroke-opacity:.5;stroke-width:.03}
37
+ .kyogijo .ky-bud-tassel-s{fill:#d23b32;stroke:var(--ky-ink);stroke-opacity:.5;stroke-width:.03}
38
+ .kyogijo .ky-bud-tassel-w{fill:#f4f1e8;stroke:var(--ky-ink);stroke-opacity:.5;stroke-width:.03}
39
+ .kyogijo .ky-bud-tassel-n{fill:#232323;stroke:var(--ky-ink);stroke-opacity:.5;stroke-width:.03}`.trim();
40
+ /** The custom properties of a look. */
41
+ const vars = (l) => `--ky-surface:${l.surface};--ky-surface-alt:${l.alt};--ky-red:${l.red};--ky-apron:${l.apron};--ky-free:${l.free};--ky-bud-floor:${l.floor};--ky-boards:${l.boards}${l.dirt === undefined ? "" : `;--ky-dirt:${l.dirt}`}${l.sand === undefined ? "" : `;--ky-sand:${l.sand}`}${l.straw === undefined ? "" : `;--ky-bud-straw:${l.straw}`}`;
42
+ /** The three rules of one look: light, dark by the device's setting, and dark by the page's `data-theme`. */
43
+ function lookRules(sport, name) {
44
+ const pair = BUDO_LOOKS[sport][name];
45
+ const at = `[data-sport=${sport}][data-look=${name}]`;
46
+ return [
47
+ `:where(.kyogijo${at}){${vars(pair.light)}}`,
48
+ `@media (prefers-color-scheme:dark){:where(html:not([data-theme=light]) .kyogijo${at}:not([data-theme=light])){${vars(pair.dark)}}}`,
49
+ `:where(html[data-theme=dark] .kyogijo${at},.kyogijo[data-theme=dark]${at}){${vars(pair.dark)}}`,
50
+ ].join("\n");
51
+ }
52
+ /** The rules of a dojo's gallery, the stands of a crowd in a dojo: brown seats and a rail, a few neutral people. */
53
+ export const KYOGIJO_BUDO_GALLERY_STYLE = `
54
+ .kyogijo .ky-bud-gbed.ky-bud-gbed{fill:var(--ky-bud-gal,#7a5a3c)}
55
+ .kyogijo .ky-bud-gblk.ky-bud-gblk{fill:var(--ky-bud-gpeople,#a89a86)}
56
+ .kyogijo .ky-bud-gseat.ky-bud-gseat{stroke:var(--ky-bud-grail,#3a2c1f);stroke-opacity:.3}
57
+ .kyogijo .ky-bud-rail{stroke:var(--ky-bud-grail,#3a2c1f);stroke-width:1.6;stroke-opacity:.85}
58
+ `;
59
+ /** The rules of a drawing of a budō sport in a look: the shared rules and the look's colours. Nothing for another sport. */
60
+ export function budoStyle(sport, look) {
61
+ const kind = sport;
62
+ if (BUDO_LOOKS[kind] === undefined)
63
+ return "";
64
+ return `${CLASSES}\n${look === undefined ? lookRules(kind, Object.keys(BUDO_LOOKS[kind])[0]) : lookRules(kind, look)}`;
65
+ }
66
+ /** Every budō sport's rules and every look, for a page that draws with `style: "none"` and supplies the stylesheet itself. */
67
+ export const KYOGIJO_BUDO_STYLE = `${CLASSES}${KYOGIJO_BUDO_GALLERY_STYLE}\n${Object.keys(BUDO_LOOKS).flatMap((sport) => Object.keys(BUDO_LOOKS[sport]).map((name) => lookRules(sport, name))).join("\n")}`;