prographs 0.12.0 → 0.13.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 (269) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/README.md +6 -4
  3. package/dist/AutoGraph-PDPEAIXL.cjs +145 -0
  4. package/dist/GraphType.js +19 -0
  5. package/dist/autograph/chartIndex.js +521 -0
  6. package/dist/autograph/chartModules.js +2 -1
  7. package/dist/autograph/index.cjs +98 -93
  8. package/dist/catalog-DI4XZ46L.cjs +142 -0
  9. package/dist/catalog.js +2 -1
  10. package/dist/charts/biologycharts/BiologySamples.js +59 -0
  11. package/dist/charts/biologycharts/PunnettSquare.js +342 -0
  12. package/dist/charts/biologycharts/biologyEnums.js +22 -1
  13. package/dist/charts/biologycharts/index.js +5 -3
  14. package/dist/charts/doecharts/DoeSamples.js +78 -0
  15. package/dist/charts/doecharts/SipocDiagram.js +453 -0
  16. package/dist/charts/doecharts/index.js +4 -2
  17. package/dist/charts/fieldcharts/SpeciesAccumulationCurve.js +350 -0
  18. package/dist/charts/fieldcharts/fieldEnums.js +8 -1
  19. package/dist/charts/fieldcharts/index.js +5 -3
  20. package/dist/charts/signals/AntennaPatternChart.js +492 -0
  21. package/dist/charts/signals/SignalSamples.js +17 -0
  22. package/dist/charts/signals/index.js +5 -3
  23. package/dist/charts/softwarediagrams/ComponentDiagram.js +504 -0
  24. package/dist/charts/softwarediagrams/DeploymentDiagram.js +419 -0
  25. package/dist/charts/softwarediagrams/SoftwareSamples.js +283 -1
  26. package/dist/charts/softwarediagrams/index.js +7 -3
  27. package/dist/charts/softwarediagrams/softwareEnums.js +45 -1
  28. package/dist/charts/sportscharts/PowerDurationCurve.js +301 -0
  29. package/dist/charts/sportscharts/SportsSamples.js +102 -0
  30. package/dist/charts/sportscharts/TrainingLoadChart.js +325 -0
  31. package/dist/charts/sportscharts/index.js +6 -2
  32. package/dist/charts/strategycharts/BassDiffusionChart.js +362 -0
  33. package/dist/charts/strategycharts/BassModel.js +96 -0
  34. package/dist/charts/strategycharts/BurnRunwayChart.js +284 -0
  35. package/dist/charts/strategycharts/CapTableChart.js +366 -0
  36. package/dist/charts/strategycharts/KanbanBoard.js +324 -0
  37. package/dist/charts/strategycharts/OkrTree.js +339 -0
  38. package/dist/charts/strategycharts/StrategyPane.js +27 -0
  39. package/dist/charts/strategycharts/StrategySamples.js +251 -0
  40. package/dist/charts/strategycharts/index.js +15 -3
  41. package/dist/charts/threefields/BsfcMap3DChart.js +231 -0
  42. package/dist/charts/threefields/CompressorMap3DChart.js +217 -0
  43. package/dist/charts/threefields/FieldGrid.js +50 -0
  44. package/dist/charts/threefields/LossLandscape3DChart.js +201 -0
  45. package/dist/charts/threefields/MapSheet.js +77 -0
  46. package/dist/charts/threefields/TerrainRoute3DChart.js +201 -0
  47. package/dist/charts/threefields/TerrainRouteMath.js +40 -0
  48. package/dist/charts/threefields/ThreeFieldBase.js +117 -0
  49. package/dist/charts/threefields/ThreeFieldsSamples.js +80 -0
  50. package/dist/charts/threefields/WaferMap3DChart.js +218 -0
  51. package/dist/charts/threefields/index.js +19 -0
  52. package/dist/charts/threesurfaces/index.js +2 -2
  53. package/dist/charts/tradingcharts/KeltnerChannelChart.js +171 -0
  54. package/dist/charts/tradingcharts/TradingMath.js +20 -0
  55. package/dist/charts/tradingcharts/index.js +4 -2
  56. package/dist/{chunk-ZL6XDXMK.cjs → chunk-26PSLEP4.cjs} +8 -8
  57. package/dist/{chunk-W3US6EFP.cjs → chunk-2BO5DZUP.cjs} +12 -12
  58. package/dist/{chunk-5DP7OUSE.cjs → chunk-2GG5YYSC.cjs} +6 -6
  59. package/dist/{chunk-7FG4JSVO.cjs → chunk-2GL2VNJU.cjs} +253 -33
  60. package/dist/{chunk-LCWMRCLF.cjs → chunk-2PYOI7OY.cjs} +21 -21
  61. package/dist/{chunk-JFWJAEBD.cjs → chunk-3U4MCSKI.cjs} +4 -4
  62. package/dist/{chunk-CUPLHZRR.cjs → chunk-3ZMM3FSK.cjs} +4 -4
  63. package/dist/{chunk-L2AV62DP.cjs → chunk-4767WQJ7.cjs} +6 -6
  64. package/dist/{chunk-DA2EYIIP.cjs → chunk-4E7FSSBF.cjs} +1210 -168
  65. package/dist/{chunk-VS5LQEZB.cjs → chunk-526STI2S.cjs} +5 -5
  66. package/dist/{chunk-RXIMEK6C.cjs → chunk-55767YPI.cjs} +20 -20
  67. package/dist/{chunk-JXLSKIUV.cjs → chunk-5FBQOMMT.cjs} +26 -26
  68. package/dist/{chunk-27PZV5BR.cjs → chunk-5N4Z7MTS.cjs} +4 -4
  69. package/dist/{chunk-KEWCUIQA.cjs → chunk-5WEV6YWA.cjs} +22 -22
  70. package/dist/chunk-5XOVVC5X.cjs +3281 -0
  71. package/dist/{chunk-HK5J7Q2W.cjs → chunk-6HLXVWXU.cjs} +9 -9
  72. package/dist/{chunk-7JG47RW4.cjs → chunk-6LQT4WJ5.cjs} +25 -25
  73. package/dist/{chunk-OCVTI6X4.cjs → chunk-6YTWOUFD.cjs} +329 -36
  74. package/dist/{chunk-W7IQCAVN.cjs → chunk-7F6W6HKL.cjs} +11 -11
  75. package/dist/{chunk-F2DCJXDM.cjs → chunk-7L6KYU5A.cjs} +21 -21
  76. package/dist/{chunk-GTGR6LPR.cjs → chunk-A4GIN4FE.cjs} +17 -17
  77. package/dist/{chunk-B2CETSR6.cjs → chunk-A4US7SA7.cjs} +5 -5
  78. package/dist/{chunk-3DIF2YYW.cjs → chunk-AOXPBLPW.cjs} +10 -10
  79. package/dist/{chunk-7TTR4UF5.cjs → chunk-ATI45Z4M.cjs} +2 -2
  80. package/dist/{chunk-5BFCIX2V.cjs → chunk-CPPMO4IQ.cjs} +434 -148
  81. package/dist/{chunk-AYZZQ6AC.cjs → chunk-CZ5KGF6Q.cjs} +9 -9
  82. package/dist/{chunk-7THJ3ZBK.cjs → chunk-D4I35MCE.cjs} +2 -2
  83. package/dist/{chunk-MCPPFRLN.cjs → chunk-DCGAAN3Z.cjs} +2 -2
  84. package/dist/{chunk-VABL6CVX.cjs → chunk-DEY36N37.cjs} +21 -21
  85. package/dist/{chunk-RNCKGJCC.cjs → chunk-DXHXD3DK.cjs} +3 -3
  86. package/dist/{chunk-A56ZGMVZ.cjs → chunk-E7B45DBZ.cjs} +11 -11
  87. package/dist/{chunk-DOR6L4MT.cjs → chunk-EJC6EAC5.cjs} +18 -18
  88. package/dist/{chunk-UPGNM7MA.cjs → chunk-EULJOOMA.cjs} +11 -11
  89. package/dist/{chunk-G4AZL4GO.cjs → chunk-EYM6LEIF.cjs} +474 -70
  90. package/dist/{chunk-NJ4X6XGV.cjs → chunk-EZTYX2GH.cjs} +5 -5
  91. package/dist/chunk-FDD4UP73.cjs +521 -0
  92. package/dist/{chunk-WJ3VH2Q4.cjs → chunk-GEAIGM3J.cjs} +110 -615
  93. package/dist/{chunk-P3SBHF43.cjs → chunk-GRUYVXTS.cjs} +2 -2
  94. package/dist/{chunk-NX4Z5LMS.cjs → chunk-H3SZXND5.cjs} +5 -5
  95. package/dist/{chunk-EE4S4TOE.cjs → chunk-HS45TOFJ.cjs} +21 -21
  96. package/dist/chunk-INGOG6OV.cjs +899 -0
  97. package/dist/{chunk-UDKA6DGT.cjs → chunk-J3CDXZHF.cjs} +4 -4
  98. package/dist/{chunk-YO6G7TKI.cjs → chunk-JAU5ADEU.cjs} +11 -11
  99. package/dist/{chunk-22LBK4GA.cjs → chunk-JQEBSHX3.cjs} +4 -4
  100. package/dist/{chunk-RXX3U7VQ.cjs → chunk-KLXGLMFU.cjs} +10 -10
  101. package/dist/chunk-KVOX36J3.cjs +327 -0
  102. package/dist/chunk-L6BGNHFL.cjs +139 -0
  103. package/dist/{chunk-GMER35L3.cjs → chunk-L7TB7PU5.cjs} +20 -20
  104. package/dist/{chunk-AFXYNBL2.cjs → chunk-LBTRYEM2.cjs} +4 -4
  105. package/dist/{chunk-WYYCKIOD.cjs → chunk-LLULNJSP.cjs} +11 -11
  106. package/dist/{chunk-J27XOSLP.cjs → chunk-LSO46AFV.cjs} +8 -8
  107. package/dist/{chunk-5XJO45ES.cjs → chunk-LZ2KJ7ZX.cjs} +11 -11
  108. package/dist/chunk-M4IQ5LIZ.cjs +422 -0
  109. package/dist/{chunk-Y2KIUKJF.cjs → chunk-MPDHDKYZ.cjs} +11 -11
  110. package/dist/{chunk-4EMPKRZU.cjs → chunk-MRQ42ZJE.cjs} +3 -3
  111. package/dist/{chunk-EU5D2MF4.cjs → chunk-MYV4KZWP.cjs} +9 -9
  112. package/dist/{chunk-XD7KN4UN.cjs → chunk-MZXVLC24.cjs} +6 -6
  113. package/dist/{chunk-PPSONARU.cjs → chunk-NLBVDFIR.cjs} +41 -2
  114. package/dist/{chunk-L3PEGMGM.cjs → chunk-NY3TBZY4.cjs} +33 -33
  115. package/dist/{chunk-6YNYXXB6.cjs → chunk-OGVVSFAR.cjs} +3 -3
  116. package/dist/{chunk-MLV7QLB6.cjs → chunk-OMTQIQMN.cjs} +6 -6
  117. package/dist/{chunk-BEEOSNK7.cjs → chunk-PEJJ6TXJ.cjs} +15 -144
  118. package/dist/{chunk-SOKOWUF5.cjs → chunk-PPGWHIU7.cjs} +2 -2
  119. package/dist/{chunk-IELWOM2J.cjs → chunk-PPO6SDAN.cjs} +6 -6
  120. package/dist/{chunk-6JTZZCSL.cjs → chunk-PUMKX5F2.cjs} +3 -3
  121. package/dist/{chunk-RFOXFY2U.cjs → chunk-PXBYWCNB.cjs} +190 -799
  122. package/dist/{chunk-3BYXOISI.cjs → chunk-Q3HB3IX6.cjs} +4 -4
  123. package/dist/{chunk-RXCOVONX.cjs → chunk-RBMUOIXE.cjs} +289 -34
  124. package/dist/{chunk-MSBNHCSE.cjs → chunk-RJHGCUUD.cjs} +6 -6
  125. package/dist/{chunk-I6VG7F6Z.cjs → chunk-RSONDMYW.cjs} +708 -141
  126. package/dist/{chunk-GZDNPHMT.cjs → chunk-SHMPFCUE.cjs} +19 -19
  127. package/dist/{chunk-ZIBVCOW6.cjs → chunk-SN4FCXFC.cjs} +19 -19
  128. package/dist/{chunk-7KM52NMN.cjs → chunk-SN5T7WYO.cjs} +2 -2
  129. package/dist/{chunk-7MSZR65Z.cjs → chunk-SQJZGVDR.cjs} +7 -7
  130. package/dist/chunk-SYABFMD7.cjs +633 -0
  131. package/dist/{chunk-2RRFEYFH.cjs → chunk-TICB3MAC.cjs} +16 -16
  132. package/dist/{chunk-AOOKHUV5.cjs → chunk-U7Z7XYR2.cjs} +5 -5
  133. package/dist/{chunk-JEWQAXVG.cjs → chunk-UA2THQFV.cjs} +6 -6
  134. package/dist/{chunk-LHZPAHU3.cjs → chunk-VIK4L2YF.cjs} +112 -521
  135. package/dist/{chunk-4YWMAQ4J.cjs → chunk-VM2Y6BDY.cjs} +4 -4
  136. package/dist/{chunk-IRRKE2ZE.cjs → chunk-VMS3KWYI.cjs} +21 -21
  137. package/dist/{chunk-4SLARW6F.cjs → chunk-VU5NUD46.cjs} +17 -17
  138. package/dist/{chunk-XHY6TVYG.cjs → chunk-VV5CVOF7.cjs} +13 -13
  139. package/dist/{chunk-CCIBPGPZ.cjs → chunk-VYSAWPSS.cjs} +57 -57
  140. package/dist/{chunk-TTNEMQ2A.cjs → chunk-W7YRWEWQ.cjs} +22 -22
  141. package/dist/{chunk-C7MUOGEW.cjs → chunk-X7R5SY62.cjs} +6 -6
  142. package/dist/{chunk-ILR5KBMB.cjs → chunk-XOK3KTSS.cjs} +6 -6
  143. package/dist/{chunk-2CZM2I3T.cjs → chunk-XUIX45VU.cjs} +19 -19
  144. package/dist/{chunk-TGRMPS3A.cjs → chunk-XWH46PVJ.cjs} +165 -43
  145. package/dist/{chunk-WQYXXECR.cjs → chunk-Y5XVMK3K.cjs} +6 -6
  146. package/dist/{chunk-AK4TX2WG.cjs → chunk-YCNKEDTG.cjs} +13 -13
  147. package/dist/{chunk-PJJB24DU.cjs → chunk-YEF7SE3X.cjs} +20 -20
  148. package/dist/{chunk-RVLV4XW6.cjs → chunk-YMTVPMU3.cjs} +22 -22
  149. package/dist/data/index.cjs +2 -2
  150. package/dist/entries/autograph-lazy.cjs +2 -2
  151. package/dist/entries/charts/acoustictransport.cjs +3 -3
  152. package/dist/entries/charts/analysischarts.cjs +3 -3
  153. package/dist/entries/charts/astrocharts.cjs +3 -3
  154. package/dist/entries/charts/bars.cjs +3 -3
  155. package/dist/entries/charts/bayesiancharts.cjs +3 -3
  156. package/dist/entries/charts/biocharts.cjs +3 -3
  157. package/dist/entries/charts/biologycharts.cjs +11 -3
  158. package/dist/entries/charts/biologycharts.d.ts +1 -1
  159. package/dist/entries/charts/biologycharts.js +3 -2
  160. package/dist/entries/charts/business.cjs +3 -3
  161. package/dist/entries/charts/carecharts.cjs +3 -3
  162. package/dist/entries/charts/chemistrycharts.cjs +3 -3
  163. package/dist/entries/charts/civicscharts.cjs +3 -3
  164. package/dist/entries/charts/clinicalcharts.cjs +3 -3
  165. package/dist/entries/charts/comparison.cjs +3 -3
  166. package/dist/entries/charts/demography.cjs +3 -3
  167. package/dist/entries/charts/density.cjs +3 -3
  168. package/dist/entries/charts/diagrams.cjs +3 -3
  169. package/dist/entries/charts/distribution.cjs +3 -3
  170. package/dist/entries/charts/doecharts.cjs +13 -3
  171. package/dist/entries/charts/doecharts.d.ts +1 -1
  172. package/dist/entries/charts/doecharts.js +2 -1
  173. package/dist/entries/charts/earthscience.cjs +3 -3
  174. package/dist/entries/charts/economicscharts.cjs +3 -3
  175. package/dist/entries/charts/energycharts.cjs +3 -3
  176. package/dist/entries/charts/engineering.cjs +3 -3
  177. package/dist/entries/charts/fieldcharts.cjs +7 -3
  178. package/dist/entries/charts/fieldcharts.d.ts +1 -1
  179. package/dist/entries/charts/fieldcharts.js +3 -2
  180. package/dist/entries/charts/financial.cjs +3 -3
  181. package/dist/entries/charts/flow.cjs +3 -3
  182. package/dist/entries/charts/frameworks.cjs +3 -3
  183. package/dist/entries/charts/genomics.cjs +3 -3
  184. package/dist/entries/charts/geoflows.cjs +3 -3
  185. package/dist/entries/charts/geomaps.cjs +3 -3
  186. package/dist/entries/charts/geosciencecharts.cjs +3 -3
  187. package/dist/entries/charts/hierarchy.cjs +3 -3
  188. package/dist/entries/charts/indicators.cjs +3 -3
  189. package/dist/entries/charts/inferencecharts.cjs +3 -3
  190. package/dist/entries/charts/layoutcharts.cjs +3 -3
  191. package/dist/entries/charts/lifescience.cjs +4 -4
  192. package/dist/entries/charts/linesareas.cjs +3 -3
  193. package/dist/entries/charts/logisticscharts.cjs +3 -3
  194. package/dist/entries/charts/machinecharts.cjs +7 -3
  195. package/dist/entries/charts/machinecharts.d.ts +1 -1
  196. package/dist/entries/charts/machinecharts.js +2 -1
  197. package/dist/entries/charts/massive.cjs +3 -3
  198. package/dist/entries/charts/mathematical.cjs +3 -3
  199. package/dist/entries/charts/matrix.cjs +3 -3
  200. package/dist/entries/charts/medicalcharts.cjs +4 -4
  201. package/dist/entries/charts/mlcharts.cjs +4 -4
  202. package/dist/entries/charts/modelcharts.cjs +6 -5
  203. package/dist/entries/charts/multivariate.cjs +3 -3
  204. package/dist/entries/charts/musiccharts.cjs +3 -3
  205. package/dist/entries/charts/network.cjs +3 -3
  206. package/dist/entries/charts/physicscharts.cjs +3 -3
  207. package/dist/entries/charts/pictorial.cjs +4 -4
  208. package/dist/entries/charts/portfoliocharts.cjs +3 -3
  209. package/dist/entries/charts/productcharts.cjs +3 -3
  210. package/dist/entries/charts/proportion.cjs +3 -3
  211. package/dist/entries/charts/qualitycharts.cjs +3 -3
  212. package/dist/entries/charts/radial.cjs +3 -3
  213. package/dist/entries/charts/reliabilitycharts.cjs +5 -3
  214. package/dist/entries/charts/scatter.cjs +3 -3
  215. package/dist/entries/charts/scientific.cjs +3 -3
  216. package/dist/entries/charts/seriescharts.cjs +3 -3
  217. package/dist/entries/charts/signals.cjs +7 -3
  218. package/dist/entries/charts/signals.d.ts +1 -1
  219. package/dist/entries/charts/signals.js +2 -1
  220. package/dist/entries/charts/softwarediagrams.cjs +21 -3
  221. package/dist/entries/charts/softwarediagrams.d.ts +1 -1
  222. package/dist/entries/charts/softwarediagrams.js +4 -2
  223. package/dist/entries/charts/sportscharts.cjs +13 -3
  224. package/dist/entries/charts/sportscharts.d.ts +1 -1
  225. package/dist/entries/charts/sportscharts.js +3 -1
  226. package/dist/entries/charts/statistics.cjs +6 -6
  227. package/dist/entries/charts/strategycharts.cjs +30 -3
  228. package/dist/entries/charts/strategycharts.d.ts +1 -1
  229. package/dist/entries/charts/strategycharts.js +6 -1
  230. package/dist/entries/charts/structure.cjs +3 -3
  231. package/dist/entries/charts/surveycharts.cjs +3 -3
  232. package/dist/entries/charts/systemscharts.cjs +3 -3
  233. package/dist/entries/charts/textcharts.cjs +5 -5
  234. package/dist/entries/charts/thematicmaps.cjs +4 -4
  235. package/dist/entries/charts/threebars.cjs +3 -3
  236. package/dist/entries/charts/threefields.cjs +53 -0
  237. package/dist/entries/charts/threefields.d.ts +1 -0
  238. package/dist/entries/charts/threefields.js +6 -0
  239. package/dist/entries/charts/threeglobe.cjs +3 -3
  240. package/dist/entries/charts/threenetwork.cjs +3 -3
  241. package/dist/entries/charts/threestrata.cjs +3 -3
  242. package/dist/entries/charts/threesurfaces.cjs +7 -3
  243. package/dist/entries/charts/threesurfaces.d.ts +1 -1
  244. package/dist/entries/charts/threesurfaces.js +2 -1
  245. package/dist/entries/charts/threevolume.cjs +4 -4
  246. package/dist/entries/charts/timeline.cjs +3 -3
  247. package/dist/entries/charts/tracecharts.cjs +3 -3
  248. package/dist/entries/charts/trackscharts.cjs +3 -3
  249. package/dist/entries/charts/tradingcharts.cjs +6 -4
  250. package/dist/entries/charts/tradingcharts.d.ts +1 -1
  251. package/dist/entries/charts/tradingcharts.js +2 -1
  252. package/dist/entries/three.cjs +60 -20
  253. package/dist/entries/three.d.ts +1 -1
  254. package/dist/entries/three.js +7 -1
  255. package/dist/index.cjs +258 -97
  256. package/dist/index.d.cts +1953 -10
  257. package/dist/index.d.ts +1953 -10
  258. package/dist/index.js +26 -5
  259. package/dist/page/index.cjs +2 -2
  260. package/dist/react/components.js +58 -1
  261. package/dist/react/index.cjs +135 -92
  262. package/dist/react/index.d.ts +1 -1
  263. package/dist/react/index.js +2 -2
  264. package/package.json +1 -1
  265. package/dist/AutoGraph-XLBJQDRB.cjs +0 -140
  266. package/dist/catalog-O7XGDD2H.cjs +0 -137
  267. package/dist/chunk-77K2HTRC.cjs +0 -3220
  268. package/dist/chunk-XEK47TVD.cjs +0 -323
  269. /package/dist/{chunk-UMEKIIHJ.cjs → chunk-LNWTC72Y.cjs} +0 -0
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10; var _class11; var _class12; var _class13; var _class14; var _class15; var _class16;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10; var _class11; var _class12; var _class13; var _class14; var _class15; var _class16; var _class17; var _class18;
2
2
 
3
3
  var _chunkXX2YTCORcjs = require('./chunk-XX2YTCOR.cjs');
4
4
 
@@ -10,7 +10,7 @@ var _chunkEEF5WRRZcjs = require('./chunk-EEF5WRRZ.cjs');
10
10
  var _chunkPY4R3IFFcjs = require('./chunk-PY4R3IFF.cjs');
11
11
 
12
12
 
13
- var _chunkUMEKIIHJcjs = require('./chunk-UMEKIIHJ.cjs');
13
+ var _chunkLNWTC72Ycjs = require('./chunk-LNWTC72Y.cjs');
14
14
 
15
15
  // src/charts/sportscharts/FootballPitch.ts
16
16
  var PitchCoordinates = /* @__PURE__ */ ((PitchCoordinates2) => {
@@ -80,7 +80,7 @@ var FootballPitch = (_class = class {
80
80
  { key: "corner-a", points: circle(LENGTH, 0, 1, Math.PI / 2, Math.PI) },
81
81
  { key: "corner-b", points: circle(LENGTH, WIDTH, 1, Math.PI, Math.PI * 1.5) }
82
82
  ];
83
- return lines.map((line4) => ({ ...line4, key: `${key}-${line4.key}`, points: flip ? line4.points.map((point) => this.flip(point)) : line4.points }));
83
+ return lines.map((line6) => ({ ...line6, key: `${key}-${line6.key}`, points: flip ? line6.points.map((point) => this.flip(point)) : line6.points }));
84
84
  }
85
85
  /** The markings a view shows, in pitch metres. */
86
86
  static markings(view) {
@@ -142,7 +142,7 @@ var SportsFieldChart = class extends _chunkEEF5WRRZcjs.Chart2D {
142
142
  }
143
143
  /** Paints field lines in a frame group, which `chartStyle` leaves alone. */
144
144
  fieldLines(ctx, name, lines, frame) {
145
- ctx.marks(`axis-${name}`, "path", lines, (line4) => line4.key).attr("d", (line4) => this.trace(line4.points, frame, line4.filled)).attr("fill", (line4) => line4.filled ? ctx.theme.grid : "none").attr("fill-opacity", (line4) => line4.filled ? 0.5 : null).attr("stroke", (line4) => line4.filled ? "none" : line4.strong ? ctx.theme.inkMuted : ctx.theme.axis).attr("stroke-width", 1.25).attr("stroke-dasharray", (line4) => line4.dashed ? "5 4" : null);
145
+ ctx.marks(`axis-${name}`, "path", lines, (line6) => line6.key).attr("d", (line6) => this.trace(line6.points, frame, line6.filled)).attr("fill", (line6) => line6.filled ? ctx.theme.grid : "none").attr("fill-opacity", (line6) => line6.filled ? 0.5 : null).attr("stroke", (line6) => line6.filled ? "none" : line6.strong ? ctx.theme.inkMuted : ctx.theme.axis).attr("stroke-width", 1.25).attr("stroke-dasharray", (line6) => line6.dashed ? "5 4" : null);
146
146
  }
147
147
  /** Text that never takes a series colour, cut to the room left in the plot. */
148
148
  captions(ctx, name, items) {
@@ -204,6 +204,11 @@ var GOLF_BAG = [
204
204
  { club: "8 iron", target: 150, long: 6, wide: 7, bias: -2 },
205
205
  { club: "Wedge", target: 105, long: 4.5, wide: 4.5, bias: 0 }
206
206
  ];
207
+ var RIDERS = ["Ines Halvard", "Tomas Rehn", "Mirela Stanek", "Jonah Averill"];
208
+ var POWER_PERIODS = ["This season", "Last season", "Two seasons ago"];
209
+ var POWER_DURATIONS = [1, 2, 3, 5, 8, 10, 15, 20, 30, 45, 60, 90, 120, 180, 240, 300, 420, 600, 900, 1200, 1800, 2700, 3600, 5400, 7200, 10800, 14400, 18e3];
210
+ var TRAINING_WEEK = [0, 85, 60, 95, 0, 150, 110];
211
+ var TRAINING_BLOCK = [0.85, 1, 1.2, 0.55];
207
212
  var weighted = (items, roll) => {
208
213
  let pick = roll * items.reduce((sum, item) => sum + (_nullishCoalesce(_nullishCoalesce(item.weight, () => ( item.share)), () => ( 1))), 0);
209
214
  for (const item of items) {
@@ -219,7 +224,7 @@ var SportsSamples = class _SportsSamples {
219
224
  }
220
225
  /** `{ team, player, minute, x, y, xg, outcome }`, in metres, every team attacking the right-hand goal. */
221
226
  static shots(seed) {
222
- const { u, n } = _chunkUMEKIIHJcjs.SampleData.rng(seed), { LENGTH, WIDTH, GOAL_WIDTH } = FootballPitch;
227
+ const { u, n } = _chunkLNWTC72Ycjs.SampleData.rng(seed), { LENGTH, WIDTH, GOAL_WIDTH } = FootballPitch;
223
228
  const shot = (team, names) => {
224
229
  const depth = clamp(6 + Math.abs(n()) * 11, 3, 33), wide = clamp(n() * (3 + depth * 0.6), -26, 26);
225
230
  const distance = Math.hypot(depth, wide);
@@ -234,7 +239,7 @@ var SportsSamples = class _SportsSamples {
234
239
  }
235
240
  /** `{ passer, receiver, shirt, x, y, endX, endY }`, one row per completed pass, in metres, attacking right. */
236
241
  static passes(seed) {
237
- const { u, n } = _chunkUMEKIIHJcjs.SampleData.rng(seed);
242
+ const { u, n } = _chunkLNWTC72Ycjs.SampleData.rng(seed);
238
243
  const reach = LINEUP.map((a) => LINEUP.map((b) => a === b || a.shirt === 1 && b.x > 40 ? 0 : Math.exp(-Math.hypot(a.x - b.x, a.y - b.y) / 14) * (b.x > 70 ? 0.75 : 1)));
239
244
  return Array.from({ length: 420 }, () => {
240
245
  const from = clamp(Math.floor(u() ** 1.2 * LINEUP.length * 0.9 + u() * 1.4), 0, LINEUP.length - 1), a = LINEUP[from], weights = reach[from];
@@ -246,7 +251,7 @@ var SportsSamples = class _SportsSamples {
246
251
  }
247
252
  /** `{ angle, distance, trajectory, result }`: spray angle in degrees, negative toward left field, and feet from the plate. */
248
253
  static battedBalls(seed, lines = 330, centre = 400) {
249
- const { u, n } = _chunkUMEKIIHJcjs.SampleData.rng(seed);
254
+ const { u, n } = _chunkLNWTC72Ycjs.SampleData.rng(seed);
250
255
  return Array.from({ length: 150 }, () => {
251
256
  const kind = u(), angle = clamp(n() * 22 - 4, -44, 44), wall = lines + (centre - lines) * Math.cos(2 * angle * Math.PI / 180);
252
257
  if (kind < 0.44) {
@@ -264,7 +269,7 @@ var SportsSamples = class _SportsSamples {
264
269
  }
265
270
  /** `{ ball, angle, distance, runs }`, one row per legal ball: angle in degrees from straight, positive to the off side, and metres from the striker. */
266
271
  static deliveries(seed) {
267
- const { u, n } = _chunkUMEKIIHJcjs.SampleData.rng(seed);
272
+ const { u, n } = _chunkLNWTC72Ycjs.SampleData.rng(seed);
268
273
  const zones = [{ at: 35, spread: 20, weight: 0.34 }, { at: 100, spread: 18, weight: 0.14 }, { at: -60, spread: 24, weight: 0.3 }, { at: -125, spread: 22, weight: 0.12 }, { at: -8, spread: 12, weight: 0.1 }];
269
274
  return Array.from({ length: 72 }, (_, i) => {
270
275
  const roll = u(), runs = roll < 0.38 ? 0 : roll < 0.72 ? 1 : roll < 0.8 ? 2 : roll < 0.82 ? 3 : roll < 0.95 ? 4 : 6;
@@ -277,7 +282,7 @@ var SportsSamples = class _SportsSamples {
277
282
  }
278
283
  /** `{ serve, x, y, rally, won }`: metres across from the centre line, left negative from behind the server, and metres past the net. */
279
284
  static serves(seed) {
280
- const { u, n } = _chunkUMEKIIHJcjs.SampleData.rng(seed);
285
+ const { u, n } = _chunkLNWTC72Ycjs.SampleData.rng(seed);
281
286
  return Array.from({ length: 140 }, () => {
282
287
  const serve = u() < 0.64 ? 1 : 2, deuce = u() < 0.5, aim = u();
283
288
  const lane = serve === 1 ? aim < 0.42 ? 0.86 : aim < 0.86 ? 0.14 : 0.5 : aim < 0.2 ? 0.8 : aim < 0.5 ? 0.2 : 0.5;
@@ -290,7 +295,7 @@ var SportsSamples = class _SportsSamples {
290
295
  }
291
296
  /** `{ minute, team, probability, leverage, event }`, a row for each side each minute of an 80 minute match in which the side behind scores a little more often. `leverage` is the swing a converted try either way would cause. */
292
297
  static winProbability(seed) {
293
- const { u, n } = _chunkUMEKIIHJcjs.SampleData.rng(seed), edge = (u() - 0.5) * 4;
298
+ const { u, n } = _chunkLNWTC72Ycjs.SampleData.rng(seed), edge = (u() - 0.5) * 4;
294
299
  const chance = (lead2, minute) => {
295
300
  const left = Math.max(0, 80 - minute) / 80;
296
301
  if (!left) return lead2 > 0 ? 1 : lead2 < 0 ? 0 : 0.5;
@@ -311,7 +316,7 @@ var SportsSamples = class _SportsSamples {
311
316
  }
312
317
  /** `{ over, team, runs, wickets }`: what each over of a 20 over innings added, the second side stopping once it passes the first. */
313
318
  static overs(seed) {
314
- const { u, n } = _chunkUMEKIIHJcjs.SampleData.rng(seed);
319
+ const { u, n } = _chunkLNWTC72Ycjs.SampleData.rng(seed);
315
320
  const innings = (team, target) => {
316
321
  const rows = [];
317
322
  for (let over = 1, total = 0, out = 0; over <= 20 && out < 10 && total <= target; over++) {
@@ -328,7 +333,7 @@ var SportsSamples = class _SportsSamples {
328
333
  }
329
334
  /** `{ player, category, metric, value, percentile }`: per 90 figures of two midfielders and where each ranks among players in the position. */
330
335
  static percentiles(seed) {
331
- const { n } = _chunkUMEKIIHJcjs.SampleData.rng(seed);
336
+ const { n } = _chunkLNWTC72Ycjs.SampleData.rng(seed);
332
337
  return ["Lund", "Sousa"].flatMap((player, p) => PIZZA_METRICS.map(([category, metric, low, high, digits]) => {
333
338
  const lean = category === "Attacking" ? 14 : category === "Defending" ? -12 : 6;
334
339
  const percentile = clamp(Math.round(52 + (p ? -lean : lean) + n() * 20), 2, 99);
@@ -337,7 +342,7 @@ var SportsSamples = class _SportsSamples {
337
342
  }
338
343
  /** `{ x, z, pitch, speed, result }`: feet across from the middle of the plate as the catcher sees it, feet above the ground, and miles an hour. */
339
344
  static pitches(seed) {
340
- const { u, n } = _chunkUMEKIIHJcjs.SampleData.rng(seed);
345
+ const { u, n } = _chunkLNWTC72Ycjs.SampleData.rng(seed);
341
346
  return Array.from({ length: 96 }, () => {
342
347
  const kind = weighted(PITCH_MIX, u());
343
348
  const x = round(kind.x + n() * kind.spread), z = round(clamp(kind.z + n() * kind.spread * 1.1, 0.2, 4.8));
@@ -351,7 +356,7 @@ var SportsSamples = class _SportsSamples {
351
356
  * `event` reads `Pit` on an in-lap and `Retired` on a car's last lap, and `flag` names a neutralised lap.
352
357
  */
353
358
  static raceLaps(seed, laps = 30) {
354
- const { u, n } = _chunkUMEKIIHJcjs.SampleData.rng(seed), caution = 11 + Math.floor(u() * 6);
359
+ const { u, n } = _chunkLNWTC72Ycjs.SampleData.rng(seed), caution = 11 + Math.floor(u() * 6);
355
360
  const quitters = /* @__PURE__ */ new Map([[2 + Math.floor(u() * 4), 8 + Math.floor(u() * 6)], [6 + Math.floor(u() * 4), 18 + Math.floor(u() * 8)]]);
356
361
  const cars = RACE_GRID.map(([driver, team], index) => {
357
362
  const two = u() < 0.4, hard = u() < 0.5;
@@ -397,7 +402,7 @@ var SportsSamples = class _SportsSamples {
397
402
  }
398
403
  /** `{ player, type, x, y }`: where one wide player touched the ball, in metres, attacking right. */
399
404
  static touches(seed) {
400
- const { u, n } = _chunkUMEKIIHJcjs.SampleData.rng(seed);
405
+ const { u, n } = _chunkLNWTC72Ycjs.SampleData.rng(seed);
401
406
  return Array.from({ length: 360 }, () => {
402
407
  const spot = weighted(TOUCH_SPOTS, u());
403
408
  return { player: "Amadi", type: TOUCH_KINDS[Math.floor(u() * TOUCH_KINDS.length)], x: round(clamp(spot.x + n() * spot.sx, 0, 105), 1), y: round(clamp(spot.y + n() * spot.sy, 0, 68), 1) };
@@ -405,7 +410,7 @@ var SportsSamples = class _SportsSamples {
405
410
  }
406
411
  /** `{ team, player, period, x, y, result }`: feet from centre ice, the first team shooting at the goal on the right. */
407
412
  static rinkShots(seed) {
408
- const { u, n } = _chunkUMEKIIHJcjs.SampleData.rng(seed);
413
+ const { u, n } = _chunkLNWTC72Ycjs.SampleData.rng(seed);
409
414
  const shot = (team, names, side) => {
410
415
  const distance = clamp(8 + Math.abs(n()) * 22, 5, 62), angle = clamp(n() * 0.75, -1.35, 1.35);
411
416
  const quality = 0.34 * Math.exp(-distance / 18) * Math.cos(angle), roll = u();
@@ -417,12 +422,42 @@ var SportsSamples = class _SportsSamples {
417
422
  }
418
423
  /** `{ club, target, carry, offline }` in yards: the distance aimed for, the distance flown, and how far right of the target line the ball landed. */
419
424
  static golfShots(seed) {
420
- const { n } = _chunkUMEKIIHJcjs.SampleData.rng(seed);
425
+ const { n } = _chunkLNWTC72Ycjs.SampleData.rng(seed);
421
426
  return GOLF_BAG.flatMap(({ club, target, long, wide, bias }) => Array.from({ length: 18 }, () => {
422
427
  const side = n(), depth = n();
423
428
  return { club, target, carry: round(target - 2 + depth * long - Math.abs(side) * long * 0.45, 1), offline: round(bias + side * wide, 1) };
424
429
  }));
425
430
  }
431
+ /**
432
+ * `{ athlete, period, duration, power, weight }`: one rider's best mean power in watts for efforts of a second to five hours,
433
+ * this season and the two before, with body weight in kilograms. Power follows a three-parameter critical power curve that fades past half an hour.
434
+ */
435
+ static powerCurve(seed) {
436
+ const { u, n } = _chunkLNWTC72Ycjs.SampleData.rng(seed);
437
+ const athlete = RIDERS[Math.floor(u() * RIDERS.length)], cp = 250 + u() * 55, reserve = 17e3 + u() * 8e3, sprint = 950 + u() * 350, mass = 62 + u() * 14;
438
+ return POWER_PERIODS.flatMap((period, back) => {
439
+ const steady = cp * (1 - back * (0.03 + u() * 0.02)), burst = reserve * (1 - back * 0.06), top = sprint * [1, 1.04, 0.97][back];
440
+ const weight = round(mass + back * 0.9 + n() * 0.3, 1);
441
+ let best = Infinity;
442
+ return POWER_DURATIONS.map((duration) => {
443
+ const fade = duration > 1800 ? 1 - 0.06 * Math.log(duration / 1800) : 1;
444
+ best = Math.min(best, Math.round((steady + burst / (duration + burst / (top - steady))) * fade * (1 + n() * 8e-3)));
445
+ return { athlete, period, duration, power: best, weight };
446
+ });
447
+ });
448
+ }
449
+ /** `{ date, athlete, load }`: a training stress score for each session of 20 weeks in four week blocks, ending in a taper and a race. Rest days and missed sessions have no row. */
450
+ static trainingLoad(seed, weeks = 20) {
451
+ const { u, n } = _chunkLNWTC72Ycjs.SampleData.rng(seed);
452
+ const athlete = RIDERS[Math.floor(u() * RIDERS.length)], start = Date.UTC(2025, 1, 3 + 7 * (seed % 4)), last = weeks * 7 - 1;
453
+ return Array.from({ length: weeks * 7 }, (_, day) => {
454
+ const week = Math.floor(day / 7), left = weeks - 1 - week;
455
+ const share = left === 0 ? 0.45 : left === 1 ? 0.7 : TRAINING_BLOCK[week % 4] * (0.7 + week * 0.035);
456
+ const planned = day === last ? 240 : TRAINING_WEEK[day % 7] * share;
457
+ if (!planned || day !== last && u() < 0.06) return [];
458
+ return [{ date: new Date(start + day * 864e5).toISOString().slice(0, 10), athlete, load: Math.max(10, Math.round(planned * (1 + n() * 0.12))) }];
459
+ }).flat();
460
+ }
426
461
  };
427
462
 
428
463
  // src/charts/sportscharts/BaseballSprayChart.ts
@@ -573,7 +608,7 @@ var BaseballSprayChart = (_class2 = class extends SportsFieldChart {
573
608
  for (const name of HITS) if (balls.some((ball) => ball.result === name)) ctx.palette.color(name);
574
609
  }
575
610
  this.#drawSectors(ctx, sectors ? this.sectorsOf(balls) : [], frame);
576
- this.fieldLines(ctx, "field", this.#field(reach).filter((line4) => !(sectors && line4.key === "turf")), frame);
611
+ this.fieldLines(ctx, "field", this.#field(reach).filter((line6) => !(sectors && line6.key === "turf")), frame);
577
612
  const rings = [100, 200, 300, 400, 500].filter((ring2) => ring2 < reach);
578
613
  this.captions(ctx, "rings", rings.map((ring2) => {
579
614
  const [x, y] = ground(-FAIR, ring2);
@@ -724,9 +759,9 @@ var CricketWagonWheel = (_class3 = class extends SportsFieldChart {
724
759
  const zoned = marks === "zones" /* Zones */;
725
760
  const reach = boundary * 1.02;
726
761
  const frame = this.frame({ x: 0, y: 0, width: ctx.plot.width, height: ctx.plot.height - FOOT2 }, [-reach, reach], [-reach, reach]);
727
- this.fieldLines(ctx, "ground", this.#ground().filter((line4) => !(zoned && line4.key === "outfield")), frame);
762
+ this.fieldLines(ctx, "ground", this.#ground().filter((line6) => !(zoned && line6.key === "outfield")), frame);
728
763
  this.#drawZones(ctx, zoned ? this.zonesOf(balls) : [], frame);
729
- this.fieldLines(ctx, "pitch-top", zoned ? this.#ground().filter((line4) => line4.key !== "outfield") : [], frame);
764
+ this.fieldLines(ctx, "pitch-top", zoned ? this.#ground().filter((line6) => line6.key !== "outfield") : [], frame);
730
765
  this.#drawRays(ctx, zoned ? [] : this.#shown(balls), frame);
731
766
  const right = hand === "right" /* Right */;
732
767
  this.captions(ctx, "sides", [
@@ -949,7 +984,7 @@ var HockeyRink = (_class5 = class {
949
984
  { key: `neutral${side}`, points: arc(NEUTRAL_SPOT, side * SPOT_Y, 1, 0, Math.PI * 2, 8), filled: true }
950
985
  ])
951
986
  ];
952
- return lines.map((line4) => ({ ...line4, key: `${key}-${line4.key}`, points: flip ? line4.points.map((point) => this.flip(point)) : line4.points }));
987
+ return lines.map((line6) => ({ ...line6, key: `${key}-${line6.key}`, points: flip ? line6.points.map((point) => this.flip(point)) : line6.points }));
953
988
  }
954
989
  /** The lines, circles and creases a view shows, in rink feet. */
955
990
  static markings(view) {
@@ -1108,7 +1143,7 @@ var HockeyRinkShotMap = (_class6 = class _HockeyRinkShotMap extends SportsFieldC
1108
1143
  const frame = this.frame({ x: 0, y: 0, width: ctx.plot.width, height: ctx.plot.height - FOOT4 }, wide, tall);
1109
1144
  const seen = (point) => HockeyRink.project(view, point);
1110
1145
  this.#drawBins(ctx, binned ? this.binsOf(attempts) : [], seen, frame);
1111
- this.fieldLines(ctx, "rink", HockeyRink.markings(view).map((line4) => ({ ...line4, points: line4.points.map(seen) })), frame);
1146
+ this.fieldLines(ctx, "rink", HockeyRink.markings(view).map((line6) => ({ ...line6, points: line6.points.map(seen) })), frame);
1112
1147
  this.#drawShots(ctx, binned ? [] : attempts, (shot) => {
1113
1148
  const [x, y] = seen(shot.at);
1114
1149
  return [frame.x(x), frame.y(y)];
@@ -1218,7 +1253,7 @@ var PassingNetworkPitch = (_class7 = class extends SportsFieldChart {
1218
1253
  const [x, y] = seen([node.x, node.y]);
1219
1254
  return [frame.x(x), frame.y(y)];
1220
1255
  };
1221
- this.fieldLines(ctx, "pitch", FootballPitch.markings(view).map((line4) => ({ ...line4, points: line4.points.map(seen) })), frame);
1256
+ this.fieldLines(ctx, "pitch", FootballPitch.markings(view).map((line6) => ({ ...line6, points: line6.points.map(seen) })), frame);
1222
1257
  const busiest = Math.max(1, ...nodes.map((node) => node.passes + node.received));
1223
1258
  const radius = (node) => Math.max(MIN_RADIUS, MAX_RADIUS * Math.sqrt((node.passes + node.received) / busiest));
1224
1259
  const peak = Math.max(1, ...links.map((link) => link.passes));
@@ -1377,7 +1412,7 @@ var PitchHeatmap = (_class8 = class extends SportsFieldChart {
1377
1412
  const cells = bins === "grid" /* Grid */ ? this.gridCells(events) : bins === "hex" /* Hex */ ? this.hexCells(events) : [];
1378
1413
  this.#drawCells(ctx, cells, seen, frame, Math.max(1, events.length));
1379
1414
  this.#drawContours(ctx, bins === "contour" /* Contour */ ? events : [], seen, frame);
1380
- this.fieldLines(ctx, "pitch", FootballPitch.markings(view).map((line4) => ({ ...line4, points: line4.points.map(seen) })), frame);
1415
+ this.fieldLines(ctx, "pitch", FootballPitch.markings(view).map((line6) => ({ ...line6, points: line6.points.map(seen) })), frame);
1381
1416
  const note = events.length ? `${events.length} events, attacking ${upright ? "up" : "right"}. Tone: events in the area` : "No events on the pitch";
1382
1417
  this.captions(ctx, "note", [{ key: "note", text: note, x: 0, y: ctx.plot.height - 3, tone: "muted" }]);
1383
1418
  }
@@ -1498,7 +1533,7 @@ var PizzaChart = (_class9 = class extends SportsFieldChart {
1498
1533
  }
1499
1534
  }, _class9.__initStatic30(), _class9);
1500
1535
 
1501
- // src/charts/sportscharts/RaceLapChart.ts
1536
+ // src/charts/sportscharts/PowerDurationCurve.ts
1502
1537
 
1503
1538
 
1504
1539
  // src/charts/sportscharts/SportsTimelineChart.ts
@@ -1522,14 +1557,212 @@ var SportsTimelineChart = class extends _chunkXX2YTCORcjs.CartesianChart {
1522
1557
  }
1523
1558
  };
1524
1559
 
1560
+ // src/charts/sportscharts/PowerDurationCurve.ts
1561
+ var PowerDurationUnit = /* @__PURE__ */ ((PowerDurationUnit2) => {
1562
+ PowerDurationUnit2["Watts"] = "watts";
1563
+ PowerDurationUnit2["PerKilogram"] = "watts-per-kg";
1564
+ return PowerDurationUnit2;
1565
+ })(PowerDurationUnit || {});
1566
+ var STANDARD = [5, 60, 300, 1200, 3600];
1567
+ var ROUND = [1, 18e3, 10, 30, 600, 1800, 7200, 36e3, 86400, 2, 15, 120, 10800];
1568
+ var TICK_GAP = 40;
1569
+ var DOT2 = 4.5;
1570
+ var CHAR4 = 6.2;
1571
+ var PowerDurationCurve = (_class10 = class _PowerDurationCurve extends SportsTimelineChart {
1572
+ static __initStatic31() {this.meta = {
1573
+ id: "power-duration-curve",
1574
+ name: "Power-duration curve",
1575
+ family: "trend" /* Trend */,
1576
+ dimension: 2 /* Two */,
1577
+ shape: "table" /* Table */,
1578
+ description: "Plots an athlete's best mean power against effort duration on a log axis, with the fitted critical power model, earlier periods for reference and the standard durations marked, in watts or watts per kilogram. The sample rider is invented.",
1579
+ tags: ["sports", "cycling", "critical power", "mean maximal power", "W prime", "power profile"],
1580
+ sample: (seed) => SportsSamples.powerCurve(seed),
1581
+ variants: {
1582
+ unit: ["watts" /* Watts */, "watts-per-kg" /* PerKilogram */],
1583
+ model: [true, false],
1584
+ references: [true, false],
1585
+ markers: [true, false]
1586
+ }
1587
+ }}
1588
+ #periods = [];
1589
+ #fit = null;
1590
+ #who = "";
1591
+ #timeAxis = null;
1592
+ #powerAxis = null;
1593
+ defaults() {
1594
+ return {
1595
+ x: "duration",
1596
+ y: "power",
1597
+ period: "period",
1598
+ weight: "weight",
1599
+ athlete: "athlete",
1600
+ unit: "watts" /* Watts */,
1601
+ model: true,
1602
+ fitWindow: [120, 1800],
1603
+ references: true,
1604
+ markers: true
1605
+ };
1606
+ }
1607
+ get #perKilo() {
1608
+ return this.options.unit === "watts-per-kg" /* PerKilogram */;
1609
+ }
1610
+ get #unit() {
1611
+ return this.#perKilo ? "W/kg" : "W";
1612
+ }
1613
+ #value(power) {
1614
+ return this.#perKilo ? power.toFixed(power < 10 ? 2 : 1) : Math.round(power).toLocaleString("en");
1615
+ }
1616
+ /** A duration in the largest units that keep it whole: `5 s`, `20 min`, `1 h 30 min`. */
1617
+ static span(seconds) {
1618
+ if (seconds < 60) return `${+seconds.toFixed(1)} s`;
1619
+ const whole = Math.round(seconds), minutes = Math.round(whole / 60);
1620
+ if (whole < 3600) return whole % 60 ? `${Math.floor(whole / 60)} min ${whole % 60} s` : `${whole / 60} min`;
1621
+ return minutes % 60 ? `${Math.floor(minutes / 60)} h ${minutes % 60} min` : `${minutes / 60} h`;
1622
+ }
1623
+ /**
1624
+ * Least squares fit of P = CP + W'/t to the readings inside `window`, as a straight line of power against 1/t.
1625
+ * `null` with fewer than two durations there, or when the line gives a critical power or W' at or below zero.
1626
+ */
1627
+ static fit(points, [from, to]) {
1628
+ const used = points.filter((point) => point.t >= from && point.t <= to), n = used.length;
1629
+ let sx = 0, sy = 0, sxx = 0, sxy = 0;
1630
+ for (const { t, p } of used) {
1631
+ sx += 1 / t;
1632
+ sy += p;
1633
+ sxx += 1 / (t * t);
1634
+ sxy += p / t;
1635
+ }
1636
+ const spread = n * sxx - sx * sx;
1637
+ if (n < 2 || spread <= 1e-15) return null;
1638
+ const wPrime = (n * sxy - sx * sy) / spread, cp = (sy - wPrime * sx) / n;
1639
+ return cp > 0 && wPrime > 0 ? { cp, wPrime } : null;
1640
+ }
1641
+ /** Power at `t` seconds, read between the two nearest durations along log time. `null` outside the curve. */
1642
+ static at(points, t) {
1643
+ const after = points.findIndex((point) => point.t >= t), b = points[after];
1644
+ if (!b) return null;
1645
+ if (b.t === t) return b.p;
1646
+ const a = points[after - 1];
1647
+ return a ? a.p + (b.p - a.p) * Math.log(t / a.t) / Math.log(b.t / a.t) : null;
1648
+ }
1649
+ /** Axis ticks at round durations at least `gap` px apart, the standard test durations first. */
1650
+ static ticks(scale, gap = TICK_GAP) {
1651
+ const [low, high] = scale.domain(), kept = [];
1652
+ for (const tick of [...STANDARD, ...ROUND]) if (tick >= low && tick <= high && kept.every((other) => Math.abs(scale(other) - scale(tick)) >= gap)) kept.push(tick);
1653
+ return kept.sort((a, b) => a - b);
1654
+ }
1655
+ /** The first athlete's curves, the current period first, each with one reading per duration in rising order. */
1656
+ get curves() {
1657
+ const { x, y, period, weight, athlete, current } = this.options, rows = this.rows(), perKilo = this.#perKilo;
1658
+ const who = this.#who = _nullishCoalesce(rows.map((row) => this.word(row[athlete])).find(Boolean), () => ( ""));
1659
+ const best = /* @__PURE__ */ new Map();
1660
+ for (const row of rows) {
1661
+ const t = this.number(row[x]), watts = this.number(row[y]), mass = this.number(row[weight]);
1662
+ if (this.word(row[athlete], who) !== who || t === null || t <= 0 || watts === null || perKilo && !(mass !== null && mass > 0)) continue;
1663
+ const name = this.word(row[period], "Power"), held = _nullishCoalesce(best.get(name), () => ( best.set(name, /* @__PURE__ */ new Map()).get(name)));
1664
+ held.set(t, Math.max(_nullishCoalesce(held.get(t), () => ( -Infinity)), perKilo ? watts / mass : watts));
1665
+ }
1666
+ const curves = [...best].map(([name, held]) => ({ period: name, points: [...held].sort((a, b) => a[0] - b[0]).map(([t, p]) => ({ t, p })) }));
1667
+ const lead = curves.findIndex((curve) => curve.period === current);
1668
+ return lead > 0 ? [curves[lead], ...curves.filter((_, i) => i !== lead)] : curves;
1669
+ }
1670
+ scales(ctx) {
1671
+ const { width, height } = ctx.plot, { references, model, fitWindow } = this.options;
1672
+ const periods = this.#periods = references ? this.curves : this.curves.slice(0, 1);
1673
+ this.#fit = model && periods[0] ? _PowerDurationCurve.fit(periods[0].points, fitWindow) : null;
1674
+ const points = periods.flatMap((curve) => curve.points), times = points.map((point) => point.t), powers = points.map((point) => point.p);
1675
+ let [low, high] = points.length ? [Math.min(...times), Math.max(...times)] : [1, 3600];
1676
+ if (low === high) [low, high] = [low / 2, high * 2];
1677
+ const top = Math.max(0, ...powers), bottom = Math.min(0, ...powers);
1678
+ const x = _d3.scaleLog.call(void 0, [low, high], [0, width]), y = this.#powerAxis = _d3.scaleLinear.call(void 0, [bottom, top > bottom ? top * 1.04 : bottom + 1], [height, 0]).nice();
1679
+ this.#timeAxis = Object.assign(x, { ticks: () => _PowerDurationCurve.ticks(x) });
1680
+ return { x, y };
1681
+ }
1682
+ /** Time ticks name their duration, and the top power tick carries the unit. */
1683
+ tickFormat(scale) {
1684
+ if (scale === this.#timeAxis) return (value) => _PowerDurationCurve.span(+value);
1685
+ const plain = super.tickFormat(scale);
1686
+ if (scale !== this.#powerAxis || !plain) return plain;
1687
+ const top = Math.max(...this.#powerAxis.ticks(this.yTicks()));
1688
+ return (value) => +value === top ? `${plain(value)} ${this.#unit}` : plain(value);
1689
+ }
1690
+ plotMarks(ctx, { x, y }) {
1691
+ const { markers, fitWindow } = this.options, periods = this.#periods, fit = this.#fit, lead = periods[0], unit = this.#unit;
1692
+ const color = (name) => ctx.palette.color(name);
1693
+ for (const curve of periods) color(curve.period);
1694
+ const [low, high] = x.domain(), top = y.domain()[1], { width, height } = ctx.plot;
1695
+ const reading = (power) => `${this.#value(power)} ${unit}`;
1696
+ const asymptote = ctx.marks("axis-critical", "line", fit ? [fit] : []).attr("stroke", ctx.theme.axis).attr("stroke-width", 1).attr("stroke-dasharray", "2 3");
1697
+ ctx.set(asymptote, { x1: 0, x2: width, y1: (d) => y(d.cp), y2: (d) => y(d.cp) });
1698
+ const marked = markers && lead ? STANDARD.flatMap((t) => {
1699
+ const p = _PowerDurationCurve.at(lead.points, t);
1700
+ return p === null || t < low || t > high ? [] : [{ t, p }];
1701
+ }) : [];
1702
+ const drops = ctx.marks("axis-standard", "line", marked, (d) => d.t).attr("stroke", ctx.theme.axis).attr("stroke-width", 1).attr("stroke-dasharray", "1 3");
1703
+ ctx.set(drops, { x1: (d) => x(d.t), x2: (d) => x(d.t), y1: (d) => y(d.p), y2: height });
1704
+ const trace = _d3.line.call(void 0, ).curve(_chunkPY4R3IFFcjs.Scales.curve()).x((d) => x(d.t)).y((d) => y(d.p));
1705
+ const drawn = [...periods].reverse();
1706
+ const paths = ctx.marks("curves", "path", drawn.filter((curve) => curve.points.length > 1), (d) => d.period).attr("fill", "none").attr("stroke", (d) => color(d.period)).attr("stroke-width", (d) => d === lead ? 2 : 1.5).attr("stroke-opacity", (d) => d === lead ? 1 : 0.7).attr("stroke-linejoin", "round").attr("stroke-linecap", "round");
1707
+ ctx.set(paths, { d: (d) => _nullishCoalesce(trace(d.points), () => ( "")) });
1708
+ ctx.drawOn(paths);
1709
+ ctx.hover(paths, (d) => ({
1710
+ title: d.period,
1711
+ color: color(d.period),
1712
+ rows: STANDARD.flatMap((t) => {
1713
+ const p = _PowerDurationCurve.at(d.points, t);
1714
+ return p === null ? [] : [[_PowerDurationCurve.span(t), reading(p)]];
1715
+ })
1716
+ }));
1717
+ const lone = ctx.marks("single", "circle", drawn.filter((curve) => curve.points.length === 1), (d) => d.period).attr("fill", (d) => color(d.period)).attr("stroke", ctx.theme.surface).attr("stroke-width", 2);
1718
+ ctx.set(lone, { cx: (d) => x(d.points[0].t), cy: (d) => y(d.points[0].p), r: DOT2 }, { r: 0 });
1719
+ ctx.hover(lone, (d) => ({ title: d.period, color: color(d.period), rows: [[_PowerDurationCurve.span(d.points[0].t), reading(d.points[0].p)]] }));
1720
+ const start = fit ? Math.max(low, fit.wPrime / Math.max(1e-9, top - fit.cp)) : high;
1721
+ const steps = start < high ? Array.from({ length: 64 }, (_, i) => start * (high / start) ** (i / 63)) : [];
1722
+ const fitted = ctx.marks("model", "path", fit && steps.length ? [fit] : []).attr("fill", "none").attr("stroke", ctx.theme.ink).attr("stroke-width", 1.5).attr("stroke-dasharray", "5 4");
1723
+ ctx.set(fitted, { d: (d) => _nullishCoalesce(_d3.line.call(void 0, ).x((t) => x(t)).y((t) => y(d.cp + d.wPrime / t))(steps), () => ( "")) });
1724
+ ctx.hover(fitted, (d) => ({
1725
+ title: "Critical power model",
1726
+ rows: [["Critical power", reading(d.cp)], ["W'", this.#work(d.wPrime)], ["Fitted over", `${_PowerDurationCurve.span(fitWindow[0])} to ${_PowerDurationCurve.span(fitWindow[1])}`]]
1727
+ }));
1728
+ const dots = ctx.marks("standard", "circle", marked, (d) => d.t).attr("fill", lead ? color(lead.period) : null).attr("stroke", ctx.theme.surface).attr("stroke-width", 2);
1729
+ ctx.set(dots, { cx: (d) => x(d.t), cy: (d) => y(d.p), r: DOT2 }, { r: 0 }, 30);
1730
+ ctx.hover(dots, (d) => ({
1731
+ title: `Best ${_PowerDurationCurve.span(d.t)}`,
1732
+ color: lead ? color(lead.period) : void 0,
1733
+ rows: [[_nullishCoalesce(_optionalChain([lead, 'optionalAccess', _14 => _14.period]), () => ( "")), reading(d.p)], ...fit ? [["Model", reading(fit.cp + fit.wPrime / d.t)]] : []]
1734
+ }));
1735
+ let edge = -Infinity;
1736
+ const values = marked.flatMap((d) => {
1737
+ const text = this.#value(d.p), wide = text.length * CHAR4, flip = x(d.t) + 7 + wide > width, left = flip ? x(d.t) - 7 - wide : x(d.t) + 7;
1738
+ if (left < edge + 4 || y(d.p) < 18) return [];
1739
+ edge = left + wide;
1740
+ return [{ key: `value-${d.t}`, text, x: flip ? x(d.t) - 7 : x(d.t) + 7, y: y(d.p) - 7, anchor: flip ? "end" : "start", tone: "ink" }];
1741
+ });
1742
+ const summary = !lead ? [{ key: "empty", text: this.#perKilo && this.rows().length ? "No body weight to divide by" : "No power readings", x: 4, y: 12, tone: "muted" }] : [
1743
+ ...this.#who ? [{ key: "who", text: this.#who, x: width - 4, y: 12, anchor: "end", tone: "ink" }] : [],
1744
+ ...fit ? [
1745
+ { key: "fit", text: `CP ${reading(fit.cp)}, W' ${this.#work(fit.wPrime)}`, x: width - 4, y: this.#who ? 26 : 12, anchor: "end" },
1746
+ { key: "critical", text: "CP", x: 4, y: y(fit.cp) - 5, tone: "muted", size: 10 }
1747
+ ] : []
1748
+ ];
1749
+ this.notes(ctx, "notes", [...values, ...summary]);
1750
+ }
1751
+ /** W' in kilojoules, or in joules per kilogram when power is per kilogram. */
1752
+ #work(wPrime) {
1753
+ return this.#perKilo ? `${Math.round(wPrime)} J/kg` : `${(wPrime / 1e3).toFixed(1)} kJ`;
1754
+ }
1755
+ }, _class10.__initStatic31(), _class10);
1756
+
1525
1757
  // src/charts/sportscharts/RaceLapChart.ts
1758
+
1526
1759
  var PIT = /pit|stop|box/i;
1527
1760
  var OUT2 = /ret|dnf|out|crash|accident/i;
1528
- var CHAR4 = 6.2;
1761
+ var CHAR5 = 6.2;
1529
1762
  var NAME_MAX = 78;
1530
1763
  var cross = _nullishCoalesce(_d3.symbol.call(void 0, _d3.symbolCross, 64)(), () => ( ""));
1531
- var RaceLapChart = (_class10 = class extends SportsTimelineChart {
1532
- static __initStatic31() {this.meta = {
1764
+ var RaceLapChart = (_class11 = class extends SportsTimelineChart {
1765
+ static __initStatic32() {this.meta = {
1533
1766
  id: "race-lap-chart",
1534
1767
  name: "Lap chart",
1535
1768
  family: "trend" /* Trend */,
@@ -1584,7 +1817,7 @@ var RaceLapChart = (_class10 = class extends SportsTimelineChart {
1584
1817
  }
1585
1818
  /** Px kept right of the last lap for the finishers' names. */
1586
1819
  #nameRoom(width, cars) {
1587
- const longest = Math.max(0, ...cars.map((car) => _chunkEEF5WRRZcjs.TextFit.width(car.driver, CHAR4)));
1820
+ const longest = Math.max(0, ...cars.map((car) => _chunkEEF5WRRZcjs.TextFit.width(car.driver, CHAR5)));
1588
1821
  return width < 220 || !cars.length ? 0 : Math.min(NAME_MAX, width * 0.26, longest + 12);
1589
1822
  }
1590
1823
  tickFormat(scale) {
@@ -1615,7 +1848,7 @@ var RaceLapChart = (_class10 = class extends SportsTimelineChart {
1615
1848
  ctx.set(crosses, { transform: (car) => `translate(${x(end(car).lap).toFixed(2)},${y(end(car).position).toFixed(2)}) rotate(45)` }, { "fill-opacity": 0 });
1616
1849
  ctx.hover(crosses, (car) => ({ title: `${car.driver} retired`, color: color(car), rows: [["Lap", end(car).lap], ["Position", end(car).position]] }));
1617
1850
  const room = this.#nameRoom(ctx.plot.width, cars), edge = x.range()[1];
1618
- const finishers = room ? cars.filter((car) => !car.retired && car.points.length).map((car) => ({ key: car.driver, text: _chunkEEF5WRRZcjs.TextFit.fit(car.driver, room - 8, CHAR4), x: edge + 8, y: y(end(car).position) + 4 })) : [];
1851
+ const finishers = room ? cars.filter((car) => !car.retired && car.points.length).map((car) => ({ key: car.driver, text: _chunkEEF5WRRZcjs.TextFit.fit(car.driver, room - 8, CHAR5), x: edge + 8, y: y(end(car).position) + 4 })) : [];
1619
1852
  const taken = /* @__PURE__ */ new Set();
1620
1853
  const named = finishers.filter((label) => {
1621
1854
  const slot = Math.round(label.y / 11);
@@ -1624,7 +1857,7 @@ var RaceLapChart = (_class10 = class extends SportsTimelineChart {
1624
1857
  const quit = gone.map((car) => ({ key: `out-${car.driver}`, text: car.driver, x: x(end(car).lap) + 8, y: y(end(car).position) + 4, size: 10, tone: "ink" })).filter((label) => label.x + _chunkEEF5WRRZcjs.TextFit.width(label.text, 5.6) < edge);
1625
1858
  this.notes(ctx, "names", [...named, ...quit, ...cars.length ? [] : [{ key: "empty", text: "No laps", x: 4, y: 12, tone: "muted" }]]);
1626
1859
  }
1627
- }, _class10.__initStatic31(), _class10);
1860
+ }, _class11.__initStatic32(), _class11);
1628
1861
 
1629
1862
  // src/charts/sportscharts/ScoreWormChart.ts
1630
1863
 
@@ -1634,8 +1867,8 @@ var WormMeasure = /* @__PURE__ */ ((WormMeasure2) => {
1634
1867
  return WormMeasure2;
1635
1868
  })(WormMeasure || {});
1636
1869
  var END_ROOM = 34;
1637
- var ScoreWormChart = (_class11 = class _ScoreWormChart extends SportsTimelineChart {
1638
- static __initStatic32() {this.meta = {
1870
+ var ScoreWormChart = (_class12 = class _ScoreWormChart extends SportsTimelineChart {
1871
+ static __initStatic33() {this.meta = {
1639
1872
  id: "score-worm",
1640
1873
  name: "Worm chart",
1641
1874
  family: "trend" /* Trend */,
@@ -1676,8 +1909,8 @@ var ScoreWormChart = (_class11 = class _ScoreWormChart extends SportsTimelineCha
1676
1909
  }
1677
1910
  /** The first side's lead over `other` at every period either side has, up to where the shorter of the two ends. */
1678
1911
  static margin(first, other) {
1679
- const end = Math.min(_nullishCoalesce(_optionalChain([first, 'access', _14 => _14.points, 'access', _15 => _15.at, 'call', _16 => _16(-1), 'optionalAccess', _17 => _17.x]), () => ( 0)), _nullishCoalesce(_optionalChain([other, 'access', _18 => _18.points, 'access', _19 => _19.at, 'call', _20 => _20(-1), 'optionalAccess', _21 => _21.x]), () => ( 0)));
1680
- const at = (side, x) => _nullishCoalesce(_optionalChain([side, 'access', _22 => _22.points, 'access', _23 => _23.findLast, 'call', _24 => _24((point) => point.x <= x), 'optionalAccess', _25 => _25.value]), () => ( 0));
1912
+ const end = Math.min(_nullishCoalesce(_optionalChain([first, 'access', _15 => _15.points, 'access', _16 => _16.at, 'call', _17 => _17(-1), 'optionalAccess', _18 => _18.x]), () => ( 0)), _nullishCoalesce(_optionalChain([other, 'access', _19 => _19.points, 'access', _20 => _20.at, 'call', _21 => _21(-1), 'optionalAccess', _22 => _22.x]), () => ( 0)));
1913
+ const at = (side, x) => _nullishCoalesce(_optionalChain([side, 'access', _23 => _23.points, 'access', _24 => _24.findLast, 'call', _25 => _25((point) => point.x <= x), 'optionalAccess', _26 => _26.value]), () => ( 0));
1681
1914
  const periods = [...new Set([...first.points, ...other.points].map((point) => point.x))].filter((x) => x <= end).sort((a, b) => a - b);
1682
1915
  return periods.map((x) => ({ x, value: at(first, x) - at(other, x), added: 0, events: 0 }));
1683
1916
  }
@@ -1707,7 +1940,7 @@ var ScoreWormChart = (_class11 = class _ScoreWormChart extends SportsTimelineCha
1707
1940
  const { curve, markers } = this.options, lines = this.#lines, sides = this.#sides, margin = this.#margin;
1708
1941
  const color = (team) => ctx.palette.color(team);
1709
1942
  for (const side of sides) color(side.team);
1710
- const first = _nullishCoalesce(_optionalChain([sides, 'access', _26 => _26[0], 'optionalAccess', _27 => _27.team]), () => ( "")), duel = margin && lines.length === 1;
1943
+ const first = _nullishCoalesce(_optionalChain([sides, 'access', _27 => _27[0], 'optionalAccess', _28 => _28.team]), () => ( "")), duel = margin && lines.length === 1;
1711
1944
  const zero = ctx.marks("axis-zero", "line", margin && lines.length ? [0] : []).attr("stroke", ctx.theme.axis).attr("stroke-width", 1);
1712
1945
  ctx.set(zero, { x1: 0, x2: ctx.plot.width, y1: y(0), y2: y(0) });
1713
1946
  const outline = duel ? curve === "linear" /* Linear */ ? _ScoreWormChart.zeroCrossings(lines[0].points) : lines[0].points : [];
@@ -1719,14 +1952,14 @@ var ScoreWormChart = (_class11 = class _ScoreWormChart extends SportsTimelineCha
1719
1952
  const worms = ctx.marks("worms", "path", duel ? [] : lines.filter((entry) => entry.points.length > 1), (d) => d.key).attr("fill", "none").attr("stroke", (d) => color(d.team)).attr("stroke-width", 2).attr("stroke-linejoin", "round").attr("stroke-linecap", "round");
1720
1953
  ctx.set(worms, { d: (d) => _nullishCoalesce(trace(d.points), () => ( "")) });
1721
1954
  ctx.drawOn(worms);
1722
- ctx.hover(worms, (d) => ({ title: margin ? `${first} against ${d.team}` : d.team, color: color(d.team), rows: [[margin ? "Final lead" : "Total", _nullishCoalesce(_optionalChain([d, 'access', _28 => _28.points, 'access', _29 => _29.at, 'call', _30 => _30(-1), 'optionalAccess', _31 => _31.value]), () => ( 0))]] }));
1955
+ ctx.hover(worms, (d) => ({ title: margin ? `${first} against ${d.team}` : d.team, color: color(d.team), rows: [[margin ? "Final lead" : "Total", _nullishCoalesce(_optionalChain([d, 'access', _29 => _29.points, 'access', _30 => _30.at, 'call', _31 => _31(-1), 'optionalAccess', _32 => _32.value]), () => ( 0))]] }));
1723
1956
  const height = (team, at) => {
1724
1957
  const track = margin ? _nullishCoalesce(lines.find((entry) => entry.team === team), () => ( lines[0])) : lines.find((entry) => entry.team === team);
1725
- return _nullishCoalesce(_optionalChain([track, 'optionalAccess', _32 => _32.points, 'access', _33 => _33.findLast, 'call', _34 => _34((point) => point.x <= at), 'optionalAccess', _35 => _35.value]), () => ( null));
1958
+ return _nullishCoalesce(_optionalChain([track, 'optionalAccess', _33 => _33.points, 'access', _34 => _34.findLast, 'call', _35 => _35((point) => point.x <= at), 'optionalAccess', _36 => _36.value]), () => ( null));
1726
1959
  };
1727
1960
  const marks = (markers ? sides : []).flatMap((side) => side.points.flatMap((point) => {
1728
1961
  const value = point.events > 0 ? height(side.team, point.x) : null;
1729
- const reach = margin ? _nullishCoalesce(_optionalChain([(_nullishCoalesce(lines.find((entry) => entry.team === side.team), () => ( lines[0]))), 'optionalAccess', _36 => _36.points, 'access', _37 => _37.at, 'call', _38 => _38(-1), 'optionalAccess', _39 => _39.x]), () => ( -Infinity)) : Infinity;
1962
+ const reach = margin ? _nullishCoalesce(_optionalChain([(_nullishCoalesce(lines.find((entry) => entry.team === side.team), () => ( lines[0]))), 'optionalAccess', _37 => _37.points, 'access', _38 => _38.at, 'call', _39 => _39(-1), 'optionalAccess', _40 => _40.x]), () => ( -Infinity)) : Infinity;
1730
1963
  return value === null || point.x > reach ? [] : [{ key: `${side.team}/${point.x}`, team: side.team, x: point.x, value, events: point.events, total: point.value }];
1731
1964
  }));
1732
1965
  const dots = ctx.marks("events", "circle", marks, (d) => d.key).attr("fill", (d) => color(d.team)).attr("stroke", ctx.theme.surface).attr("stroke-width", 2);
@@ -1745,7 +1978,7 @@ var ScoreWormChart = (_class11 = class _ScoreWormChart extends SportsTimelineCha
1745
1978
  ] : margin ? [{ key: "first", text: `Lead of ${first}`, x: 4, y: 12, tone: "muted" }] : [];
1746
1979
  this.notes(ctx, "notes", [...ends, ...corners]);
1747
1980
  }
1748
- }, _class11.__initStatic32(), _class11);
1981
+ }, _class12.__initStatic33(), _class12);
1749
1982
 
1750
1983
  // src/charts/sportscharts/StrikeZonePlot.ts
1751
1984
 
@@ -1770,8 +2003,8 @@ var FOOT8 = 18;
1770
2003
  var NAMES = ["Low", "Middle", "High"];
1771
2004
  var SIDES = ["left", "middle", "right"];
1772
2005
  var clips2 = 0;
1773
- var StrikeZonePlot = (_class12 = class extends SportsFieldChart {
1774
- static __initStatic33() {this.meta = {
2006
+ var StrikeZonePlot = (_class13 = class extends SportsFieldChart {
2007
+ static __initStatic34() {this.meta = {
1775
2008
  id: "strike-zone-plot",
1776
2009
  name: "Strike zone plot",
1777
2010
  family: "pictorial" /* Pictorial */,
@@ -1812,13 +2045,13 @@ var StrikeZonePlot = (_class12 = class extends SportsFieldChart {
1812
2045
  }));
1813
2046
  const far = HALF_PLATE + CHASE, floor = low - CHASE, roof = high + CHASE;
1814
2047
  const outer = this.options.zones === 13 ? [[-1, -1, "Below left"], [1, -1, "Below right"], [-1, 1, "Above left"], [1, 1, "Above right"]].map(([sx, sz, name]) => {
1815
- const side = sx, up = sz, edge = up > 0 ? roof : floor, line4 = up > 0 ? high : low;
2048
+ const side = sx, up = sz, edge = up > 0 ? roof : floor, line6 = up > 0 ? high : low;
1816
2049
  return {
1817
2050
  key: `out-${side}-${up}`,
1818
2051
  name,
1819
2052
  count: 0,
1820
2053
  at: [side * (HALF_PLATE + CHASE / 2), edge - up * CHASE / 2],
1821
- corners: [[0, edge], [side * far, edge], [side * far, mid], [side * HALF_PLATE, mid], [side * HALF_PLATE, line4], [0, line4]]
2054
+ corners: [[0, edge], [side * far, edge], [side * far, mid], [side * HALF_PLATE, mid], [side * HALF_PLATE, line6], [0, line6]]
1822
2055
  };
1823
2056
  }) : [];
1824
2057
  for (const pitch of pitches) {
@@ -1884,14 +2117,14 @@ var StrikeZonePlot = (_class12 = class extends SportsFieldChart {
1884
2117
  const lines = this.#frameLines();
1885
2118
  this.#drawZones(ctx, marks === "zone-grid" /* Grid */ ? this.zonesOf(pitches) : [], frame, Math.max(1, pitches.length));
1886
2119
  this.#drawContours(ctx, marks === "contour" /* Contour */ ? pitches : [], frame);
1887
- this.fieldLines(ctx, "zone", marks === "zone-grid" /* Grid */ ? lines.filter((line4) => !line4.dashed) : lines, frame);
2120
+ this.fieldLines(ctx, "zone", marks === "zone-grid" /* Grid */ ? lines.filter((line6) => !line6.dashed) : lines, frame);
1888
2121
  this.#drawPitches(ctx, marks === "pitches" /* Pitches */ ? pitches : [], frame);
1889
2122
  const inside = pitches.filter((pitch) => Math.abs(pitch.x) <= HALF_PLATE + BALL && pitch.z >= low - BALL && pitch.z <= high + BALL).length;
1890
2123
  const seat = view === "pitcher" /* Pitcher */ ? "pitcher's view" : "catcher's view";
1891
2124
  const note = pitches.length ? `${pitches.length} pitches, ${Math.round(inside / pitches.length * 100)}% in the zone, ${seat}` : "No pitches";
1892
2125
  this.captions(ctx, "note", [{ key: "note", text: note, x: 0, y: ctx.plot.height - 3, tone: "muted" }]);
1893
2126
  }
1894
- }, _class12.__initStatic33(), _class12);
2127
+ }, _class13.__initStatic34(), _class13);
1895
2128
 
1896
2129
  // src/charts/sportscharts/TennisServePlacement.ts
1897
2130
  var ServeMarks = /* @__PURE__ */ ((ServeMarks2) => {
@@ -1930,8 +2163,8 @@ var BANDS = [
1930
2163
  { label: "5-8", low: 5, high: 8, tone: 0.7 },
1931
2164
  { label: "9+", low: 9, high: Infinity, tone: 1 }
1932
2165
  ];
1933
- var TennisServePlacement = (_class13 = class extends SportsFieldChart {
1934
- static __initStatic34() {this.meta = {
2166
+ var TennisServePlacement = (_class14 = class extends SportsFieldChart {
2167
+ static __initStatic35() {this.meta = {
1935
2168
  id: "tennis-serve-placement",
1936
2169
  name: "Serve placement",
1937
2170
  family: "pictorial" /* Pictorial */,
@@ -2080,9 +2313,9 @@ var TennisServePlacement = (_class13 = class extends SportsFieldChart {
2080
2313
  const room = { x: 0, y: 0, width: ctx.plot.width - panel, height: ctx.plot.height - FOOT9 - BOX_LABEL };
2081
2314
  const frame = this.frame(room, [-DOUBLES - MARGIN, DOUBLES + MARGIN], [0, top + (view === "half-court" /* HalfCourt */ ? MARGIN : 2)]);
2082
2315
  const court = this.#court(view);
2083
- this.fieldLines(ctx, "floor", court.filter((line4) => line4.key === "floor" && !zoned), frame);
2316
+ this.fieldLines(ctx, "floor", court.filter((line6) => line6.key === "floor" && !zoned), frame);
2084
2317
  this.#drawZones(ctx, zoned ? this.zonesOf(bounces) : [], frame);
2085
- this.fieldLines(ctx, "court", court.filter((line4) => line4.key !== "floor"), frame);
2318
+ this.fieldLines(ctx, "court", court.filter((line6) => line6.key !== "floor"), frame);
2086
2319
  this.captions(ctx, "boxes", [
2087
2320
  { key: "deuce", text: "Deuce", x: frame.x(-SINGLES / 2), y: frame.y(0) + 14, anchor: "middle", tone: "muted" },
2088
2321
  { key: "ad", text: "Ad", x: frame.x(SINGLES / 2), y: frame.y(0) + 14, anchor: "middle", tone: "muted" }
@@ -2092,7 +2325,171 @@ var TennisServePlacement = (_class13 = class extends SportsFieldChart {
2092
2325
  const note = !bounces.length ? "No serves" : zoned ? `${bounces.length} serves. Tone: share of serves` : `${bounces.length} serves. Filled: point won`;
2093
2326
  this.captions(ctx, "note", [{ key: "note", text: note, x: 0, y: ctx.plot.height - 3, tone: "muted" }]);
2094
2327
  }
2095
- }, _class13.__initStatic34(), _class13);
2328
+ }, _class14.__initStatic35(), _class14);
2329
+
2330
+ // src/charts/sportscharts/TrainingLoadChart.ts
2331
+
2332
+ var TrainingLoadForm = /* @__PURE__ */ ((TrainingLoadForm2) => {
2333
+ TrainingLoadForm2["Band"] = "band";
2334
+ TrainingLoadForm2["Line"] = "line";
2335
+ return TrainingLoadForm2;
2336
+ })(TrainingLoadForm || {});
2337
+ var TrainingLoadLayout = /* @__PURE__ */ ((TrainingLoadLayout2) => {
2338
+ TrainingLoadLayout2["Split"] = "split";
2339
+ TrainingLoadLayout2["Overlay"] = "overlay";
2340
+ return TrainingLoadLayout2;
2341
+ })(TrainingLoadLayout || {});
2342
+ var DAY = 864e5;
2343
+ var MOST_DAYS = 3660;
2344
+ var END_ROOM2 = 34;
2345
+ var PANEL_GAP = 12;
2346
+ var ZONES2 = [
2347
+ { name: "Transition", from: 25, to: Infinity, token: "warning" },
2348
+ { name: "Fresh", from: 5, to: 25, token: "grid" },
2349
+ { name: "Neutral", from: -10, to: 5, token: null },
2350
+ { name: "Productive", from: -30, to: -10, token: "good" },
2351
+ { name: "Overreaching", from: -Infinity, to: -30, token: "critical" }
2352
+ ];
2353
+ var TrainingLoadChart = (_class15 = class _TrainingLoadChart extends SportsTimelineChart {
2354
+ static __initStatic36() {this.meta = {
2355
+ id: "training-load",
2356
+ name: "Training load chart",
2357
+ family: "trend" /* Trend */,
2358
+ dimension: 2 /* Two */,
2359
+ shape: "table" /* Table */,
2360
+ description: "Draws daily training stress as bars with fitness (a 42 day exponentially weighted average), fatigue (7 day) and form (fitness less fatigue) as a line or a filled band over its zones. The sample athlete is invented.",
2361
+ tags: ["sports", "performance management", "fitness", "fatigue", "form", "training stress", "endurance"],
2362
+ sample: (seed) => SportsSamples.trainingLoad(seed),
2363
+ variants: {
2364
+ form: ["band" /* Band */, "line" /* Line */],
2365
+ layout: ["split" /* Split */, "overlay" /* Overlay */],
2366
+ loadBars: [true, false],
2367
+ zones: [true, false]
2368
+ }
2369
+ }}
2370
+ #days = [];
2371
+ #dated = false;
2372
+ #who = "";
2373
+ #formAxis = _d3.scaleLinear.call(void 0, );
2374
+ defaults() {
2375
+ return { x: "date", y: "load", athlete: "athlete", fitnessDays: 42, fatigueDays: 7, form: "band" /* Band */, layout: "split" /* Split */, loadBars: true, zones: true };
2376
+ }
2377
+ /** The form panel has an axis of its own, so only time zooms. */
2378
+ zoomAxes() {
2379
+ return "x" /* X */;
2380
+ }
2381
+ legendItems() {
2382
+ const items = super.legendItems();
2383
+ return this.options.loadBars && items.length ? [{ key: "Daily load", color: this.theme.inkMuted }, ...items] : items;
2384
+ }
2385
+ /**
2386
+ * Fitness, fatigue and form for a run of daily loads. Each average moves toward the day's load by 1 - exp(-1 / days) of the gap,
2387
+ * and form is the day's fitness less its fatigue. Both averages start at `baseline`, or at the mean of the first `fitnessDays` loads.
2388
+ */
2389
+ static model(loads, fitnessDays, fatigueDays, baseline) {
2390
+ const gain = (days) => days > 0 ? 1 - Math.exp(-1 / days) : 1, slow = gain(fitnessDays), fast = gain(fatigueDays);
2391
+ const early = loads.slice(0, Math.max(1, Math.ceil(fitnessDays) || 1));
2392
+ let fitness = _nullishCoalesce(baseline, () => ( (early.length ? early.reduce((sum, load) => sum + load, 0) / early.length : 0))), fatigue = fitness;
2393
+ return loads.map((load) => {
2394
+ fitness += (load - fitness) * slow;
2395
+ fatigue += (load - fatigue) * fast;
2396
+ return { load, fitness, fatigue, form: fitness - fatigue };
2397
+ });
2398
+ }
2399
+ /** Every day from the first athlete's first session to the last, with the sessions of a day added up and rest days at zero. */
2400
+ get days() {
2401
+ const { x, y, athlete, fitnessDays, fatigueDays, baseline } = this.options, rows = this.rows();
2402
+ const who = this.#who = _nullishCoalesce(rows.map((row) => this.word(row[athlete])).find(Boolean), () => ( ""));
2403
+ const totals = /* @__PURE__ */ new Map();
2404
+ let dated = false;
2405
+ for (const row of rows) {
2406
+ const cell = row[x], load = this.number(row[y]), numbered = this.number(cell);
2407
+ const stamp = numbered !== null ? NaN : cell instanceof Date ? cell.getTime() : typeof cell === "string" ? Date.parse(cell) : NaN;
2408
+ const day = numbered !== null ? Math.floor(numbered) : Number.isFinite(stamp) ? Math.floor(stamp / DAY) : null;
2409
+ if (this.word(row[athlete], who) !== who || day === null || load === null) continue;
2410
+ dated ||= numbered === null;
2411
+ totals.set(day, (_nullishCoalesce(totals.get(day), () => ( 0))) + Math.max(0, load));
2412
+ }
2413
+ this.#dated = dated;
2414
+ if (!totals.size) return [];
2415
+ const last = Math.max(...totals.keys()), first = Math.max(Math.min(...totals.keys()), last - MOST_DAYS + 1);
2416
+ const loads = Array.from({ length: last - first + 1 }, (_, i) => _nullishCoalesce(totals.get(first + i), () => ( 0)));
2417
+ return _TrainingLoadChart.model(loads, fitnessDays, fatigueDays, baseline).map((entry, i) => ({ day: first + i, ...entry }));
2418
+ }
2419
+ get #split() {
2420
+ return this.options.layout === "split" /* Split */;
2421
+ }
2422
+ /** The range of form the zones are drawn over: wide enough to show the three middle zones whole. */
2423
+ #reach(days) {
2424
+ const forms = days.map((entry) => entry.form);
2425
+ return [Math.min(-30, ...forms) - 6, Math.max(25, ...forms) + 6];
2426
+ }
2427
+ scales(ctx) {
2428
+ const { width, height } = ctx.plot, { loadBars } = this.options, days = this.#days = this.days, split = this.#split;
2429
+ const first = _nullishCoalesce(_optionalChain([days, 'access', _41 => _41[0], 'optionalAccess', _42 => _42.day]), () => ( 0)), last = _nullishCoalesce(_optionalChain([days, 'access', _43 => _43.at, 'call', _44 => _44(-1), 'optionalAccess', _45 => _45.day]), () => ( first)), range = [0, Math.max(10, width - END_ROOM2)];
2430
+ const x = this.#dated ? _d3.scaleUtc.call(void 0, [new Date((first - 0.5) * DAY), new Date((last + 0.5) * DAY)], range) : _d3.scaleLinear.call(void 0, [first - 0.5, last + 0.5], range);
2431
+ const panel = split ? Math.max(36, Math.min(110, height * 0.3)) : 0, main = Math.max(10, height - (split ? panel + PANEL_GAP : 0));
2432
+ const top = Math.max(1, ...days.flatMap((entry) => [loadBars ? entry.load : 0, entry.fitness, entry.fatigue]));
2433
+ const y = _d3.scaleLinear.call(void 0, [0, top], [main, 0]).nice(), deepest = split ? 0 : Math.min(0, ...days.map((entry) => entry.form));
2434
+ if (deepest < 0) y.domain([deepest * 1.1, y.domain()[1]]);
2435
+ this.#formAxis = split ? _d3.scaleLinear.call(void 0, this.#reach(days), [height, height - panel]) : y;
2436
+ return { x, y };
2437
+ }
2438
+ plotMarks(ctx, { x, y }) {
2439
+ const { form, loadBars, zones, fitnessDays, fatigueDays } = this.options, days = this.#days, split = this.#split, formY = this.#formAxis, { theme } = ctx;
2440
+ const at = (day) => x(this.#dated ? new Date(day * DAY) : day);
2441
+ const named = (day) => this.#dated ? new Date(day * DAY).toISOString().slice(0, 10) : `Day ${day}`;
2442
+ const whole = (value) => `${Math.round(value)}`;
2443
+ const series = [
2444
+ { key: "Fitness", value: (entry) => entry.fitness, scale: y, days: fitnessDays },
2445
+ { key: "Fatigue", value: (entry) => entry.fatigue, scale: y, days: fatigueDays }
2446
+ ];
2447
+ const color = (key) => ctx.palette.color(key);
2448
+ if (days.length) for (const key of ["Fitness", "Fatigue", "Form"]) color(key);
2449
+ const right = at((_nullishCoalesce(_optionalChain([days, 'access', _46 => _46.at, 'call', _47 => _47(-1), 'optionalAccess', _48 => _48.day]), () => ( 0))) + 0.5), [low, high] = this.#reach(days);
2450
+ const shaded = zones && days.length ? ZONES2.flatMap((zone) => {
2451
+ const y0 = formY(Math.min(high, zone.to)), y1 = formY(Math.max(low, zone.from));
2452
+ return y1 - y0 > 0.5 ? [{ ...zone, y0, y1 }] : [];
2453
+ }) : [];
2454
+ const strips = ctx.marks("axis-zones", "rect", shaded.filter((zone) => zone.token), (d) => d.name).attr("fill", (d) => theme[d.token]).attr("fill-opacity", (d) => d.token === "grid" ? 0.6 : 0.14);
2455
+ ctx.set(strips, { x: 0, width: Math.max(0, right), y: (d) => d.y0, height: (d) => d.y1 - d.y0 });
2456
+ const step = Math.abs(at(1) - at(0)), wide = Math.max(1, step - (step > 4 ? 2 : step > 2.5 ? 1 : 0));
2457
+ const bars = ctx.marks("loads", "rect", loadBars ? days.filter((entry) => entry.load > 0) : [], (d) => d.day).attr("fill", theme.inkMuted).attr("fill-opacity", 0.45);
2458
+ ctx.set(bars, { x: (d) => at(d.day) - wide / 2, width: wide, y: (d) => y(d.load), height: (d) => Math.max(0, y(0) - y(d.load)) }, { y: y(0), height: 0 });
2459
+ ctx.hover(bars, (d) => ({ title: named(d.day), rows: [["Load", whole(d.load)], ["Fitness", whole(d.fitness)], ["Fatigue", whole(d.fatigue)], ["Form", whole(d.form)]] }));
2460
+ const zero = ctx.marks("axis-form-zero", "line", days.length && (split || y.domain()[0] < 0) ? [0] : []).attr("stroke", theme.axis).attr("stroke-width", 1);
2461
+ ctx.set(zero, { x1: 0, x2: ctx.plot.width, y1: formY(0), y2: formY(0) });
2462
+ if (split) {
2463
+ const axis = ctx.group("axis-form").call(_d3.axisLeft.call(void 0, formY).ticks(3).tickSize(0).tickFormat((value) => whole(+value)));
2464
+ axis.select(".domain").attr("stroke", "none");
2465
+ axis.selectAll("text").attr("fill", theme.inkSecondary).attr("font-size", 11).attr("font-family", theme.fontFamily);
2466
+ } else ctx.group("axis-form").selectAll("*").remove();
2467
+ const joined = days.length > 1 ? days : [];
2468
+ const latest = days.at(-1);
2469
+ const tell = (key, value, span) => ({ title: key, color: color(key), rows: [["Latest", whole(value)], ...span ? [["Time constant", `${span} days`]] : []] });
2470
+ const fill = _d3.area.call(void 0, ).curve(_chunkPY4R3IFFcjs.Scales.curve()).x((d) => at(d.day)).y0(formY(0));
2471
+ const bands = ctx.marks("form-band", "path", form === "band" /* Band */ && joined.length ? [joined] : []).attr("fill", color("Form")).attr("fill-opacity", 0.7);
2472
+ ctx.set(bands, { d: (d) => _nullishCoalesce(fill.y1((entry) => formY(entry.form))(d), () => ( "")) }, { d: (d) => _nullishCoalesce(fill.y1(formY(0))(d), () => ( "")) });
2473
+ ctx.hover(bands, () => tell("Form", _nullishCoalesce(_optionalChain([latest, 'optionalAccess', _49 => _49.form]), () => ( 0))));
2474
+ const trace = (value, scale) => _d3.line.call(void 0, ).curve(_chunkPY4R3IFFcjs.Scales.curve()).x((d) => at(d.day)).y((d) => scale(value(d)));
2475
+ const traced = [...series, ...form === "line" /* Line */ ? [{ key: "Form", value: (entry) => entry.form, scale: formY, days: 0 }] : []];
2476
+ const lines = ctx.marks("lines", "path", joined.length ? traced : [], (d) => d.key).attr("fill", "none").attr("stroke", (d) => color(d.key)).attr("stroke-width", 2).attr("stroke-linejoin", "round").attr("stroke-linecap", "round");
2477
+ ctx.set(lines, { d: (d) => _nullishCoalesce(trace(d.value, d.scale)(joined), () => ( "")) });
2478
+ ctx.drawOn(lines);
2479
+ ctx.hover(lines, (d) => tell(d.key, latest ? d.value(latest) : 0, d.days));
2480
+ const ends = !latest ? [] : [
2481
+ { key: "fitness", text: whole(latest.fitness), x: right + 5, y: y(latest.fitness) + 4, tone: "ink" },
2482
+ { key: "fatigue", text: whole(latest.fatigue), x: right + 5, y: y(latest.fatigue) + 4, tone: "ink" },
2483
+ { key: "form", text: whole(latest.form), x: right + 5, y: formY(latest.form) + 4, tone: "ink" }
2484
+ ].sort((a, b) => a.y - b.y);
2485
+ ends.forEach((label, i) => {
2486
+ if (i && label.y - ends[i - 1].y < 12) label.y = ends[i - 1].y + 12;
2487
+ });
2488
+ const zoneNames = shaded.filter((zone) => zone.y1 - zone.y0 >= 11).map((zone) => ({ key: `zone-${zone.name}`, text: zone.name, x: 4, y: (zone.y0 + zone.y1) / 2 + 3.5, tone: "muted", size: 10 }));
2489
+ const corner = !days.length ? [{ key: "empty", text: "No training load", x: 4, y: 12, tone: "muted" }] : this.#who ? [{ key: "who", text: this.#who, x: 4, y: 12, tone: "muted" }] : [];
2490
+ this.notes(ctx, "notes", [...zoneNames, ...ends, ...corner]);
2491
+ }
2492
+ }, _class15.__initStatic36(), _class15);
2096
2493
 
2097
2494
  // src/charts/sportscharts/TyreStrategyChart.ts
2098
2495
 
@@ -2105,9 +2502,9 @@ var TyreStrategyOrder = /* @__PURE__ */ ((TyreStrategyOrder2) => {
2105
2502
  var PIT2 = /pit|stop|box/i;
2106
2503
  var RACING = /^(green|clear|none)?$/i;
2107
2504
  var HEAD2 = 14;
2108
- var CHAR5 = 5.6;
2109
- var TyreStrategyChart = (_class14 = class extends SportsTimelineChart {
2110
- static __initStatic35() {this.meta = {
2505
+ var CHAR6 = 5.6;
2506
+ var TyreStrategyChart = (_class16 = class extends SportsTimelineChart {
2507
+ static __initStatic37() {this.meta = {
2111
2508
  id: "tyre-strategy",
2112
2509
  name: "Tyre strategy chart",
2113
2510
  family: "temporal" /* Temporal */,
@@ -2186,7 +2583,7 @@ var TyreStrategyChart = (_class14 = class extends SportsTimelineChart {
2186
2583
  }));
2187
2584
  const text = (stint) => {
2188
2585
  const range = stint.from === stint.to ? `${stint.from}` : `${stint.from}-${stint.to}`, count = `${stint.to - stint.from + 1}`;
2189
- return _nullishCoalesce([range, count].find((label) => _chunkEEF5WRRZcjs.TextFit.width(label, CHAR5) + 8 <= wide(stint)), () => ( ""));
2586
+ return _nullishCoalesce([range, count].find((label) => _chunkEEF5WRRZcjs.TextFit.width(label, CHAR6) + 8 <= wide(stint)), () => ( ""));
2190
2587
  };
2191
2588
  const named = labels && thick >= 12 ? stints.filter(text) : [];
2192
2589
  const captions = ctx.text(ctx.marks("stint-labels", "text", named, (stint) => stint.key), 10).attr("text-anchor", "middle").attr("fill", (stint) => ctx.palette.inkOn(color(stint))).style("pointer-events", "none").text(text);
@@ -2194,13 +2591,13 @@ var TyreStrategyChart = (_class14 = class extends SportsTimelineChart {
2194
2591
  const pauses = this.#shaded, start = (pause) => x(pause.from - 1), span = (pause) => Math.max(1, x(pause.to) - x(pause.from - 1));
2195
2592
  const shades = ctx.marks("axis-neutral", "rect", pauses, (pause) => pause.key).attr("fill", ctx.theme.ink).attr("fill-opacity", 0.16).style("pointer-events", "none");
2196
2593
  ctx.set(shades, { x: start, y: HEAD2, width: span, height: Math.max(0, ctx.plot.height - HEAD2) });
2197
- const short = (name) => name.split(/\s+/).map((word) => _nullishCoalesce(_optionalChain([word, 'access', _40 => _40[0], 'optionalAccess', _41 => _41.toUpperCase, 'call', _42 => _42()]), () => ( ""))).join("");
2594
+ const short = (name) => name.split(/\s+/).map((word) => _nullishCoalesce(_optionalChain([word, 'access', _50 => _50[0], 'optionalAccess', _51 => _51.toUpperCase, 'call', _52 => _52()]), () => ( ""))).join("");
2198
2595
  this.notes(ctx, "neutral-names", [
2199
2596
  ...pauses.map((pause) => ({ key: pause.key, text: _chunkEEF5WRRZcjs.TextFit.width(pause.name, 5.6) <= span(pause) + 24 ? pause.name : short(pause.name), x: start(pause) + span(pause) / 2, y: 10, anchor: "middle", tone: "muted", size: 10 })),
2200
2597
  ...cars.length ? [] : [{ key: "empty", text: "No laps", x: 4, y: 12, tone: "muted" }]
2201
2598
  ]);
2202
2599
  }
2203
- }, _class14.__initStatic35(), _class14);
2600
+ }, _class16.__initStatic37(), _class16);
2204
2601
 
2205
2602
  // src/charts/sportscharts/WinProbabilityChart.ts
2206
2603
 
@@ -2210,11 +2607,11 @@ var WinProbabilityForm = /* @__PURE__ */ ((WinProbabilityForm2) => {
2210
2607
  return WinProbabilityForm2;
2211
2608
  })(WinProbabilityForm || {});
2212
2609
  var EVEN = 0.5;
2213
- var DOT2 = 4.5;
2610
+ var DOT3 = 4.5;
2214
2611
  var LABELS = 3;
2215
2612
  var STRIP_GAP = 16;
2216
- var WinProbabilityChart = (_class15 = class _WinProbabilityChart extends SportsTimelineChart {
2217
- static __initStatic36() {this.meta = {
2613
+ var WinProbabilityChart = (_class17 = class _WinProbabilityChart extends SportsTimelineChart {
2614
+ static __initStatic38() {this.meta = {
2218
2615
  id: "win-probability",
2219
2616
  name: "Win probability chart",
2220
2617
  family: "trend" /* Trend */,
@@ -2324,7 +2721,7 @@ var WinProbabilityChart = (_class15 = class _WinProbabilityChart extends SportsT
2324
2721
  ctx.hover(bars, (d) => ({ title: `${d.time}`, color: tone(d), rows: [["Leverage", +d.leverage.toFixed(3)], [sideName, `${Math.round(d.p * 100)}%`]] }));
2325
2722
  const shown = marked ? events : [];
2326
2723
  const dots = ctx.marks("events", "circle", shown, (d) => d.key).attr("fill", (d) => color(d.team)).attr("stroke", ctx.theme.surface).attr("stroke-width", 2);
2327
- ctx.set(dots, { cx: (d) => x(d.time), cy: (d) => y(d.p), r: DOT2 }, { r: 0 }, 20);
2724
+ ctx.set(dots, { cx: (d) => x(d.time), cy: (d) => y(d.p), r: DOT3 }, { r: 0 }, 20);
2328
2725
  ctx.hover(dots, (d) => ({
2329
2726
  title: d.text,
2330
2727
  color: color(d.team),
@@ -2332,7 +2729,7 @@ var WinProbabilityChart = (_class15 = class _WinProbabilityChart extends SportsT
2332
2729
  }));
2333
2730
  const placed = [];
2334
2731
  const named = [...shown].sort((a, b) => Math.abs(b.swing) - Math.abs(a.swing)).flatMap((d) => {
2335
- const px = x(d.time), up = d.p >= EVEN, py = y(d.p) + (up ? -DOT2 - 5 : DOT2 + 13), half = d.text.length * 3.1 + 4;
2732
+ const px = x(d.time), up = d.p >= EVEN, py = y(d.p) + (up ? -DOT3 - 5 : DOT3 + 13), half = d.text.length * 3.1 + 4;
2336
2733
  if (placed.length >= LABELS || px - half < 0 || px + half > ctx.plot.width || py < 10 || py > y(0) - 2) return [];
2337
2734
  if (placed.some(([qx, qy, qh]) => Math.abs(qy - py) < 13 && Math.abs(qx - px) < half + qh)) return [];
2338
2735
  placed.push([px, py, half]);
@@ -2345,7 +2742,7 @@ var WinProbabilityChart = (_class15 = class _WinProbabilityChart extends SportsT
2345
2742
  const strips = leverageBars && points.length ? [{ key: "leverage", text: "Leverage", x: 4, y: ctx.plot.height - strip - 4, tone: "muted", size: 10 }] : [];
2346
2743
  this.notes(ctx, "notes", [...corners, ...strips, ...named]);
2347
2744
  }
2348
- }, _class15.__initStatic36(), _class15);
2745
+ }, _class17.__initStatic38(), _class17);
2349
2746
 
2350
2747
  // src/charts/sportscharts/XgShotMap.ts
2351
2748
  var XgMarks = /* @__PURE__ */ ((XgMarks2) => {
@@ -2363,8 +2760,8 @@ var FOOT10 = 18;
2363
2760
  var KEY = [0.5, 0.2, 0.05];
2364
2761
  var LANES = [0, 13.84, 24.84, 43.16, 54.16, 68];
2365
2762
  var BANDS2 = [52.5, 70, 88.5, 99.5, 105];
2366
- var XgShotMap = (_class16 = class _XgShotMap extends SportsFieldChart {
2367
- static __initStatic37() {this.meta = {
2763
+ var XgShotMap = (_class18 = class _XgShotMap extends SportsFieldChart {
2764
+ static __initStatic39() {this.meta = {
2368
2765
  id: "xg-shot-map",
2369
2766
  name: "xG shot map",
2370
2767
  family: "pictorial" /* Pictorial */,
@@ -2506,16 +2903,16 @@ var XgShotMap = (_class16 = class _XgShotMap extends SportsFieldChart {
2506
2903
  };
2507
2904
  const radius = (xg) => Math.max(MIN_RADIUS2, Math.sqrt(xg) * FULL_XG * frame.scale);
2508
2905
  this.#drawZones(ctx, zoned ? this.#zones(shots) : [], seen, frame);
2509
- this.fieldLines(ctx, "pitch", FootballPitch.markings(view).map((line4) => ({ ...line4, points: line4.points.map(seen) })), frame);
2906
+ this.fieldLines(ctx, "pitch", FootballPitch.markings(view).map((line6) => ({ ...line6, points: line6.points.map(seen) })), frame);
2510
2907
  this.#drawShots(ctx, zoned ? [] : shots, (shot) => px(shot.at), radius);
2511
2908
  if (rail) this.#drawRail(ctx, shots, frame.right + 16, rail - 16, radius, room.height);
2512
2909
  else this.#drawRail(ctx, [], 0, 0, radius, 0);
2513
2910
  const totals = _XgShotMap.#totals(shots).slice(0, 2).map(({ team, xg }) => `${team} ${xg.toFixed(2)} xG`).join(", ");
2514
2911
  const key = zoned ? "Figures show xG by zone" : "Area shows xG. Filled: goal";
2515
- const note = !_optionalChain([data, 'optionalAccess', _43 => _43.length]) || !shots.length ? "No shots" : rail ? key : `${totals}. ${key}`;
2912
+ const note = !_optionalChain([data, 'optionalAccess', _53 => _53.length]) || !shots.length ? "No shots" : rail ? key : `${totals}. ${key}`;
2516
2913
  this.captions(ctx, "note", [{ key: "note", text: note, x: rail ? frame.left : 0, y: ctx.plot.height - 3, tone: "muted" }]);
2517
2914
  }
2518
- }, _class16.__initStatic37(), _class16);
2915
+ }, _class18.__initStatic39(), _class18);
2519
2916
 
2520
2917
  // src/charts/sportscharts/index.ts
2521
2918
  var sportschartsCatalog = [
@@ -2532,7 +2929,9 @@ var sportschartsCatalog = [
2532
2929
  TyreStrategyChart,
2533
2930
  PitchHeatmap,
2534
2931
  HockeyRinkShotMap,
2535
- GolfShotDispersion
2932
+ GolfShotDispersion,
2933
+ PowerDurationCurve,
2934
+ TrainingLoadChart
2536
2935
  ];
2537
2936
 
2538
2937
 
@@ -2575,4 +2974,9 @@ var sportschartsCatalog = [
2575
2974
 
2576
2975
 
2577
2976
 
2578
- exports.PitchCoordinates = PitchCoordinates; exports.PitchView = PitchView; exports.SprayMarks = SprayMarks; exports.BaseballSprayChart = BaseballSprayChart; exports.WagonMarks = WagonMarks; exports.BatterHand = BatterHand; exports.WagonShots = WagonShots; exports.CricketWagonWheel = CricketWagonWheel; exports.GolfDispersionView = GolfDispersionView; exports.GolfShotDispersion = GolfShotDispersion; exports.HockeyRinkView = HockeyRinkView; exports.HockeyRinkMarks = HockeyRinkMarks; exports.HockeyRinkShots = HockeyRinkShots; exports.HockeyShotResult = HockeyShotResult; exports.HockeyRinkShotMap = HockeyRinkShotMap; exports.PassLinkMode = PassLinkMode; exports.PassPositionBasis = PassPositionBasis; exports.PassingNetworkPitch = PassingNetworkPitch; exports.PitchHeatBins = PitchHeatBins; exports.PitchHeatmap = PitchHeatmap; exports.PizzaSort = PizzaSort; exports.PizzaChart = PizzaChart; exports.RaceLapChart = RaceLapChart; exports.WormMeasure = WormMeasure; exports.ScoreWormChart = ScoreWormChart; exports.StrikeZoneMarks = StrikeZoneMarks; exports.StrikeZoneView = StrikeZoneView; exports.StrikeZonePlot = StrikeZonePlot; exports.ServeMarks = ServeMarks; exports.ServeView = ServeView; exports.ServeFilter = ServeFilter; exports.TennisServePlacement = TennisServePlacement; exports.TyreStrategyOrder = TyreStrategyOrder; exports.TyreStrategyChart = TyreStrategyChart; exports.WinProbabilityForm = WinProbabilityForm; exports.WinProbabilityChart = WinProbabilityChart; exports.XgMarks = XgMarks; exports.XgShotMap = XgShotMap; exports.sportschartsCatalog = sportschartsCatalog;
2977
+
2978
+
2979
+
2980
+
2981
+
2982
+ exports.PitchCoordinates = PitchCoordinates; exports.PitchView = PitchView; exports.SprayMarks = SprayMarks; exports.BaseballSprayChart = BaseballSprayChart; exports.WagonMarks = WagonMarks; exports.BatterHand = BatterHand; exports.WagonShots = WagonShots; exports.CricketWagonWheel = CricketWagonWheel; exports.GolfDispersionView = GolfDispersionView; exports.GolfShotDispersion = GolfShotDispersion; exports.HockeyRinkView = HockeyRinkView; exports.HockeyRinkMarks = HockeyRinkMarks; exports.HockeyRinkShots = HockeyRinkShots; exports.HockeyShotResult = HockeyShotResult; exports.HockeyRinkShotMap = HockeyRinkShotMap; exports.PassLinkMode = PassLinkMode; exports.PassPositionBasis = PassPositionBasis; exports.PassingNetworkPitch = PassingNetworkPitch; exports.PitchHeatBins = PitchHeatBins; exports.PitchHeatmap = PitchHeatmap; exports.PizzaSort = PizzaSort; exports.PizzaChart = PizzaChart; exports.PowerDurationUnit = PowerDurationUnit; exports.PowerDurationCurve = PowerDurationCurve; exports.RaceLapChart = RaceLapChart; exports.WormMeasure = WormMeasure; exports.ScoreWormChart = ScoreWormChart; exports.StrikeZoneMarks = StrikeZoneMarks; exports.StrikeZoneView = StrikeZoneView; exports.StrikeZonePlot = StrikeZonePlot; exports.ServeMarks = ServeMarks; exports.ServeView = ServeView; exports.ServeFilter = ServeFilter; exports.TennisServePlacement = TennisServePlacement; exports.TrainingLoadForm = TrainingLoadForm; exports.TrainingLoadLayout = TrainingLoadLayout; exports.TrainingLoadChart = TrainingLoadChart; exports.TyreStrategyOrder = TyreStrategyOrder; exports.TyreStrategyChart = TyreStrategyChart; exports.WinProbabilityForm = WinProbabilityForm; exports.WinProbabilityChart = WinProbabilityChart; exports.XgMarks = XgMarks; exports.XgShotMap = XgShotMap; exports.sportschartsCatalog = sportschartsCatalog;