skill-calorie 0.1.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 (373) hide show
  1. package/dist/analysis/anomaly/common.d.ts +53 -0
  2. package/dist/analysis/anomaly/common.d.ts.map +1 -0
  3. package/dist/analysis/anomaly/common.js +69 -0
  4. package/dist/analysis/anomaly/common.js.map +1 -0
  5. package/dist/analysis/anomaly/diet.d.ts +8 -0
  6. package/dist/analysis/anomaly/diet.d.ts.map +1 -0
  7. package/dist/analysis/anomaly/diet.js +95 -0
  8. package/dist/analysis/anomaly/diet.js.map +1 -0
  9. package/dist/analysis/anomaly/exercise.d.ts +9 -0
  10. package/dist/analysis/anomaly/exercise.d.ts.map +1 -0
  11. package/dist/analysis/anomaly/exercise.js +116 -0
  12. package/dist/analysis/anomaly/exercise.js.map +1 -0
  13. package/dist/analysis/anomaly/index.d.ts +19 -0
  14. package/dist/analysis/anomaly/index.d.ts.map +1 -0
  15. package/dist/analysis/anomaly/index.js +51 -0
  16. package/dist/analysis/anomaly/index.js.map +1 -0
  17. package/dist/analysis/anomaly/overall.d.ts +13 -0
  18. package/dist/analysis/anomaly/overall.d.ts.map +1 -0
  19. package/dist/analysis/anomaly/overall.js +128 -0
  20. package/dist/analysis/anomaly/overall.js.map +1 -0
  21. package/dist/analysis/anomaly/overall2.d.ts +5 -0
  22. package/dist/analysis/anomaly/overall2.d.ts.map +1 -0
  23. package/dist/analysis/anomaly/overall2.js +94 -0
  24. package/dist/analysis/anomaly/overall2.js.map +1 -0
  25. package/dist/analysis/anomaly/weight.d.ts +8 -0
  26. package/dist/analysis/anomaly/weight.d.ts.map +1 -0
  27. package/dist/analysis/anomaly/weight.js +106 -0
  28. package/dist/analysis/anomaly/weight.js.map +1 -0
  29. package/dist/analysis/anomaly/weight2.d.ts +4 -0
  30. package/dist/analysis/anomaly/weight2.d.ts.map +1 -0
  31. package/dist/analysis/anomaly/weight2.js +59 -0
  32. package/dist/analysis/anomaly/weight2.js.map +1 -0
  33. package/dist/analysis/contraindications.d.ts +63 -0
  34. package/dist/analysis/contraindications.d.ts.map +1 -0
  35. package/dist/analysis/contraindications.js +121 -0
  36. package/dist/analysis/contraindications.js.map +1 -0
  37. package/dist/analysis/cross.d.ts +75 -0
  38. package/dist/analysis/cross.d.ts.map +1 -0
  39. package/dist/analysis/cross.js +283 -0
  40. package/dist/analysis/cross.js.map +1 -0
  41. package/dist/analysis/dashboard.d.ts +18 -0
  42. package/dist/analysis/dashboard.d.ts.map +1 -0
  43. package/dist/analysis/dashboard.js +48 -0
  44. package/dist/analysis/dashboard.js.map +1 -0
  45. package/dist/analysis/deficit.d.ts +44 -0
  46. package/dist/analysis/deficit.d.ts.map +1 -0
  47. package/dist/analysis/deficit.js +54 -0
  48. package/dist/analysis/deficit.js.map +1 -0
  49. package/dist/analysis/diet.d.ts +76 -0
  50. package/dist/analysis/diet.d.ts.map +1 -0
  51. package/dist/analysis/diet.js +164 -0
  52. package/dist/analysis/diet.js.map +1 -0
  53. package/dist/analysis/exercise.d.ts +98 -0
  54. package/dist/analysis/exercise.d.ts.map +1 -0
  55. package/dist/analysis/exercise.js +298 -0
  56. package/dist/analysis/exercise.js.map +1 -0
  57. package/dist/analysis/exerciseReview.d.ts +36 -0
  58. package/dist/analysis/exerciseReview.d.ts.map +1 -0
  59. package/dist/analysis/exerciseReview.js +50 -0
  60. package/dist/analysis/exerciseReview.js.map +1 -0
  61. package/dist/analysis/precision.d.ts +15 -0
  62. package/dist/analysis/precision.d.ts.map +1 -0
  63. package/dist/analysis/precision.js +38 -0
  64. package/dist/analysis/precision.js.map +1 -0
  65. package/dist/analysis/result.d.ts +15 -0
  66. package/dist/analysis/result.d.ts.map +1 -0
  67. package/dist/analysis/result.js +13 -0
  68. package/dist/analysis/result.js.map +1 -0
  69. package/dist/analysis/review.d.ts +118 -0
  70. package/dist/analysis/review.d.ts.map +1 -0
  71. package/dist/analysis/review.js +195 -0
  72. package/dist/analysis/review.js.map +1 -0
  73. package/dist/analysis/series.d.ts +42 -0
  74. package/dist/analysis/series.d.ts.map +1 -0
  75. package/dist/analysis/series.js +127 -0
  76. package/dist/analysis/series.js.map +1 -0
  77. package/dist/analysis/simulate.d.ts +43 -0
  78. package/dist/analysis/simulate.d.ts.map +1 -0
  79. package/dist/analysis/simulate.js +109 -0
  80. package/dist/analysis/simulate.js.map +1 -0
  81. package/dist/analysis/simulate2.d.ts +65 -0
  82. package/dist/analysis/simulate2.d.ts.map +1 -0
  83. package/dist/analysis/simulate2.js +173 -0
  84. package/dist/analysis/simulate2.js.map +1 -0
  85. package/dist/analysis/trend.d.ts +39 -0
  86. package/dist/analysis/trend.d.ts.map +1 -0
  87. package/dist/analysis/trend.js +48 -0
  88. package/dist/analysis/trend.js.map +1 -0
  89. package/dist/analysis/utils.d.ts +17 -0
  90. package/dist/analysis/utils.d.ts.map +1 -0
  91. package/dist/analysis/utils.js +52 -0
  92. package/dist/analysis/utils.js.map +1 -0
  93. package/dist/analysis/volatility.d.ts +43 -0
  94. package/dist/analysis/volatility.d.ts.map +1 -0
  95. package/dist/analysis/volatility.js +96 -0
  96. package/dist/analysis/volatility.js.map +1 -0
  97. package/dist/analysis/weight.d.ts +86 -0
  98. package/dist/analysis/weight.d.ts.map +1 -0
  99. package/dist/analysis/weight.js +219 -0
  100. package/dist/analysis/weight.js.map +1 -0
  101. package/dist/analysis/weightCompare.d.ts +63 -0
  102. package/dist/analysis/weightCompare.d.ts.map +1 -0
  103. package/dist/analysis/weightCompare.js +212 -0
  104. package/dist/analysis/weightCompare.js.map +1 -0
  105. package/dist/analysis/weightCompare2.d.ts +63 -0
  106. package/dist/analysis/weightCompare2.d.ts.map +1 -0
  107. package/dist/analysis/weightCompare2.js +211 -0
  108. package/dist/analysis/weightCompare2.js.map +1 -0
  109. package/dist/analysis/weightCompare3.d.ts +13 -0
  110. package/dist/analysis/weightCompare3.d.ts.map +1 -0
  111. package/dist/analysis/weightCompare3.js +199 -0
  112. package/dist/analysis/weightCompare3.js.map +1 -0
  113. package/dist/cli/cmd_read.d.ts +8 -0
  114. package/dist/cli/cmd_read.d.ts.map +1 -0
  115. package/dist/cli/cmd_read.js +719 -0
  116. package/dist/cli/cmd_read.js.map +1 -0
  117. package/dist/cli/keys.d.ts +333 -0
  118. package/dist/cli/keys.d.ts.map +1 -0
  119. package/dist/cli/keys.js +103 -0
  120. package/dist/cli/keys.js.map +1 -0
  121. package/dist/cli/write.d.ts +24 -0
  122. package/dist/cli/write.d.ts.map +1 -0
  123. package/dist/cli/write.js +832 -0
  124. package/dist/cli/write.js.map +1 -0
  125. package/dist/fetch/audit.d.ts +25 -0
  126. package/dist/fetch/audit.d.ts.map +1 -0
  127. package/dist/fetch/audit.js +46 -0
  128. package/dist/fetch/audit.js.map +1 -0
  129. package/dist/fetch/batch.d.ts +68 -0
  130. package/dist/fetch/batch.d.ts.map +1 -0
  131. package/dist/fetch/batch.js +183 -0
  132. package/dist/fetch/batch.js.map +1 -0
  133. package/dist/fetch/body.d.ts +89 -0
  134. package/dist/fetch/body.d.ts.map +1 -0
  135. package/dist/fetch/body.js +217 -0
  136. package/dist/fetch/body.js.map +1 -0
  137. package/dist/fetch/cli.d.ts +3 -0
  138. package/dist/fetch/cli.d.ts.map +1 -0
  139. package/dist/fetch/cli.js +195 -0
  140. package/dist/fetch/cli.js.map +1 -0
  141. package/dist/fetch/cross-skill.d.ts +29 -0
  142. package/dist/fetch/cross-skill.d.ts.map +1 -0
  143. package/dist/fetch/cross-skill.js +42 -0
  144. package/dist/fetch/cross-skill.js.map +1 -0
  145. package/dist/fetch/db.d.ts +5 -0
  146. package/dist/fetch/db.d.ts.map +1 -0
  147. package/dist/fetch/db.js +4 -0
  148. package/dist/fetch/db.js.map +1 -0
  149. package/dist/fetch/diet.d.ts +174 -0
  150. package/dist/fetch/diet.d.ts.map +1 -0
  151. package/dist/fetch/diet.js +239 -0
  152. package/dist/fetch/diet.js.map +1 -0
  153. package/dist/fetch/errors.d.ts +5 -0
  154. package/dist/fetch/errors.d.ts.map +1 -0
  155. package/dist/fetch/errors.js +8 -0
  156. package/dist/fetch/errors.js.map +1 -0
  157. package/dist/fetch/exercise.d.ts +72 -0
  158. package/dist/fetch/exercise.d.ts.map +1 -0
  159. package/dist/fetch/exercise.js +270 -0
  160. package/dist/fetch/exercise.js.map +1 -0
  161. package/dist/fetch/goal.d.ts +48 -0
  162. package/dist/fetch/goal.d.ts.map +1 -0
  163. package/dist/fetch/goal.js +73 -0
  164. package/dist/fetch/goal.js.map +1 -0
  165. package/dist/fetch/goalHistory.d.ts +24 -0
  166. package/dist/fetch/goalHistory.d.ts.map +1 -0
  167. package/dist/fetch/goalHistory.js +51 -0
  168. package/dist/fetch/goalHistory.js.map +1 -0
  169. package/dist/fetch/history.d.ts +28 -0
  170. package/dist/fetch/history.d.ts.map +1 -0
  171. package/dist/fetch/history.js +29 -0
  172. package/dist/fetch/history.js.map +1 -0
  173. package/dist/fetch/index.d.ts +23 -0
  174. package/dist/fetch/index.d.ts.map +1 -0
  175. package/dist/fetch/index.js +16 -0
  176. package/dist/fetch/index.js.map +1 -0
  177. package/dist/fetch/nutritionGoal.d.ts +115 -0
  178. package/dist/fetch/nutritionGoal.d.ts.map +1 -0
  179. package/dist/fetch/nutritionGoal.js +154 -0
  180. package/dist/fetch/nutritionGoal.js.map +1 -0
  181. package/dist/fetch/photos.d.ts +76 -0
  182. package/dist/fetch/photos.d.ts.map +1 -0
  183. package/dist/fetch/photos.js +193 -0
  184. package/dist/fetch/photos.js.map +1 -0
  185. package/dist/fetch/plan.d.ts +145 -0
  186. package/dist/fetch/plan.d.ts.map +1 -0
  187. package/dist/fetch/plan.js +258 -0
  188. package/dist/fetch/plan.js.map +1 -0
  189. package/dist/fetch/products.d.ts +62 -0
  190. package/dist/fetch/products.d.ts.map +1 -0
  191. package/dist/fetch/products.js +73 -0
  192. package/dist/fetch/products.js.map +1 -0
  193. package/dist/fetch/profile.d.ts +46 -0
  194. package/dist/fetch/profile.d.ts.map +1 -0
  195. package/dist/fetch/profile.js +105 -0
  196. package/dist/fetch/profile.js.map +1 -0
  197. package/dist/fetch/shapes.d.ts +41 -0
  198. package/dist/fetch/shapes.d.ts.map +1 -0
  199. package/dist/fetch/shapes.js +38 -0
  200. package/dist/fetch/shapes.js.map +1 -0
  201. package/dist/fetch/validate.d.ts +11 -0
  202. package/dist/fetch/validate.d.ts.map +1 -0
  203. package/dist/fetch/validate.js +64 -0
  204. package/dist/fetch/validate.js.map +1 -0
  205. package/dist/fetch/weight.d.ts +109 -0
  206. package/dist/fetch/weight.d.ts.map +1 -0
  207. package/dist/fetch/weight.js +210 -0
  208. package/dist/fetch/weight.js.map +1 -0
  209. package/dist/fetch/xunji-catalog.d.ts +17 -0
  210. package/dist/fetch/xunji-catalog.d.ts.map +1 -0
  211. package/dist/fetch/xunji-catalog.js +57 -0
  212. package/dist/fetch/xunji-catalog.js.map +1 -0
  213. package/dist/index.d.ts +17 -0
  214. package/dist/index.d.ts.map +1 -0
  215. package/dist/index.js +12 -0
  216. package/dist/index.js.map +1 -0
  217. package/dist/kcal.d.ts +21 -0
  218. package/dist/kcal.d.ts.map +1 -0
  219. package/dist/kcal.js +27 -0
  220. package/dist/kcal.js.map +1 -0
  221. package/dist/migrate/migrate.d.ts +71 -0
  222. package/dist/migrate/migrate.d.ts.map +1 -0
  223. package/dist/migrate/migrate.js +450 -0
  224. package/dist/migrate/migrate.js.map +1 -0
  225. package/dist/paths.d.ts +6 -0
  226. package/dist/paths.d.ts.map +1 -0
  227. package/dist/paths.js +34 -0
  228. package/dist/paths.js.map +1 -0
  229. package/dist/render/analysisPlate.d.ts +49 -0
  230. package/dist/render/analysisPlate.d.ts.map +1 -0
  231. package/dist/render/analysisPlate.js +149 -0
  232. package/dist/render/analysisPlate.js.map +1 -0
  233. package/dist/render/bodyPlate.d.ts +55 -0
  234. package/dist/render/bodyPlate.d.ts.map +1 -0
  235. package/dist/render/bodyPlate.js +97 -0
  236. package/dist/render/bodyPlate.js.map +1 -0
  237. package/dist/render/diet.d.ts +47 -0
  238. package/dist/render/diet.d.ts.map +1 -0
  239. package/dist/render/diet.js +94 -0
  240. package/dist/render/diet.js.map +1 -0
  241. package/dist/render/envelope.d.ts +60 -0
  242. package/dist/render/envelope.d.ts.map +1 -0
  243. package/dist/render/envelope.js +111 -0
  244. package/dist/render/envelope.js.map +1 -0
  245. package/dist/render/errors.d.ts +10 -0
  246. package/dist/render/errors.d.ts.map +1 -0
  247. package/dist/render/errors.js +9 -0
  248. package/dist/render/errors.js.map +1 -0
  249. package/dist/render/exercise.d.ts +20 -0
  250. package/dist/render/exercise.d.ts.map +1 -0
  251. package/dist/render/exercise.js +32 -0
  252. package/dist/render/exercise.js.map +1 -0
  253. package/dist/render/goal.d.ts +24 -0
  254. package/dist/render/goal.d.ts.map +1 -0
  255. package/dist/render/goal.js +23 -0
  256. package/dist/render/goal.js.map +1 -0
  257. package/dist/render/goalExtra.d.ts +45 -0
  258. package/dist/render/goalExtra.d.ts.map +1 -0
  259. package/dist/render/goalExtra.js +94 -0
  260. package/dist/render/goalExtra.js.map +1 -0
  261. package/dist/render/goalPlate.d.ts +66 -0
  262. package/dist/render/goalPlate.d.ts.map +1 -0
  263. package/dist/render/goalPlate.js +110 -0
  264. package/dist/render/goalPlate.js.map +1 -0
  265. package/dist/render/health.d.ts +21 -0
  266. package/dist/render/health.d.ts.map +1 -0
  267. package/dist/render/health.js +41 -0
  268. package/dist/render/health.js.map +1 -0
  269. package/dist/render/help.d.ts +18 -0
  270. package/dist/render/help.d.ts.map +1 -0
  271. package/dist/render/help.js +58 -0
  272. package/dist/render/help.js.map +1 -0
  273. package/dist/render/home.d.ts +30 -0
  274. package/dist/render/home.d.ts.map +1 -0
  275. package/dist/render/home.js +73 -0
  276. package/dist/render/home.js.map +1 -0
  277. package/dist/render/html.d.ts +66 -0
  278. package/dist/render/html.d.ts.map +1 -0
  279. package/dist/render/html.js +510 -0
  280. package/dist/render/html.js.map +1 -0
  281. package/dist/render/index.d.ts +47 -0
  282. package/dist/render/index.d.ts.map +1 -0
  283. package/dist/render/index.js +26 -0
  284. package/dist/render/index.js.map +1 -0
  285. package/dist/render/insightPlate.d.ts +55 -0
  286. package/dist/render/insightPlate.d.ts.map +1 -0
  287. package/dist/render/insightPlate.js +97 -0
  288. package/dist/render/insightPlate.js.map +1 -0
  289. package/dist/render/library.d.ts +32 -0
  290. package/dist/render/library.d.ts.map +1 -0
  291. package/dist/render/library.js +54 -0
  292. package/dist/render/library.js.map +1 -0
  293. package/dist/render/photo.d.ts +101 -0
  294. package/dist/render/photo.d.ts.map +1 -0
  295. package/dist/render/photo.js +241 -0
  296. package/dist/render/photo.js.map +1 -0
  297. package/dist/render/planPlate.d.ts +40 -0
  298. package/dist/render/planPlate.d.ts.map +1 -0
  299. package/dist/render/planPlate.js +72 -0
  300. package/dist/render/planPlate.js.map +1 -0
  301. package/dist/render/profilePlate.d.ts +17 -0
  302. package/dist/render/profilePlate.d.ts.map +1 -0
  303. package/dist/render/profilePlate.js +18 -0
  304. package/dist/render/profilePlate.js.map +1 -0
  305. package/dist/render/ranking.d.ts +22 -0
  306. package/dist/render/ranking.d.ts.map +1 -0
  307. package/dist/render/ranking.js +63 -0
  308. package/dist/render/ranking.js.map +1 -0
  309. package/dist/render/receipt.d.ts +71 -0
  310. package/dist/render/receipt.d.ts.map +1 -0
  311. package/dist/render/receipt.js +65 -0
  312. package/dist/render/receipt.js.map +1 -0
  313. package/dist/render/weightPlate.d.ts +54 -0
  314. package/dist/render/weightPlate.d.ts.map +1 -0
  315. package/dist/render/weightPlate.js +110 -0
  316. package/dist/render/weightPlate.js.map +1 -0
  317. package/dist/schema.d.ts +25 -0
  318. package/dist/schema.d.ts.map +1 -0
  319. package/dist/schema.js +281 -0
  320. package/dist/schema.js.map +1 -0
  321. package/dist/triggers/help-lookup.d.ts +28 -0
  322. package/dist/triggers/help-lookup.d.ts.map +1 -0
  323. package/dist/triggers/help-lookup.js +163 -0
  324. package/dist/triggers/help-lookup.js.map +1 -0
  325. package/dist/triggers/index.d.ts +24 -0
  326. package/dist/triggers/index.d.ts.map +1 -0
  327. package/dist/triggers/index.js +78 -0
  328. package/dist/triggers/index.js.map +1 -0
  329. package/dist/triggers/scene-01-home.d.ts +4 -0
  330. package/dist/triggers/scene-01-home.d.ts.map +1 -0
  331. package/dist/triggers/scene-01-home.js +13 -0
  332. package/dist/triggers/scene-01-home.js.map +1 -0
  333. package/dist/triggers/scene-02-diet.d.ts +4 -0
  334. package/dist/triggers/scene-02-diet.d.ts.map +1 -0
  335. package/dist/triggers/scene-02-diet.js +74 -0
  336. package/dist/triggers/scene-02-diet.js.map +1 -0
  337. package/dist/triggers/scene-03-weight.d.ts +4 -0
  338. package/dist/triggers/scene-03-weight.d.ts.map +1 -0
  339. package/dist/triggers/scene-03-weight.js +62 -0
  340. package/dist/triggers/scene-03-weight.js.map +1 -0
  341. package/dist/triggers/scene-04-exercise.d.ts +4 -0
  342. package/dist/triggers/scene-04-exercise.d.ts.map +1 -0
  343. package/dist/triggers/scene-04-exercise.js +43 -0
  344. package/dist/triggers/scene-04-exercise.js.map +1 -0
  345. package/dist/triggers/scene-05-workout.d.ts +4 -0
  346. package/dist/triggers/scene-05-workout.d.ts.map +1 -0
  347. package/dist/triggers/scene-05-workout.js +36 -0
  348. package/dist/triggers/scene-05-workout.js.map +1 -0
  349. package/dist/triggers/scene-06-goal.d.ts +4 -0
  350. package/dist/triggers/scene-06-goal.d.ts.map +1 -0
  351. package/dist/triggers/scene-06-goal.js +29 -0
  352. package/dist/triggers/scene-06-goal.js.map +1 -0
  353. package/dist/triggers/scene-07-profile.d.ts +4 -0
  354. package/dist/triggers/scene-07-profile.d.ts.map +1 -0
  355. package/dist/triggers/scene-07-profile.js +8 -0
  356. package/dist/triggers/scene-07-profile.js.map +1 -0
  357. package/dist/triggers/scene-08-body.d.ts +4 -0
  358. package/dist/triggers/scene-08-body.d.ts.map +1 -0
  359. package/dist/triggers/scene-08-body.js +17 -0
  360. package/dist/triggers/scene-08-body.js.map +1 -0
  361. package/dist/triggers/scene-09-photo.d.ts +4 -0
  362. package/dist/triggers/scene-09-photo.d.ts.map +1 -0
  363. package/dist/triggers/scene-09-photo.js +14 -0
  364. package/dist/triggers/scene-09-photo.js.map +1 -0
  365. package/dist/triggers/scene-10-analysis.d.ts +4 -0
  366. package/dist/triggers/scene-10-analysis.d.ts.map +1 -0
  367. package/dist/triggers/scene-10-analysis.js +180 -0
  368. package/dist/triggers/scene-10-analysis.js.map +1 -0
  369. package/dist/triggers/types.d.ts +66 -0
  370. package/dist/triggers/types.d.ts.map +1 -0
  371. package/dist/triggers/types.js +3 -0
  372. package/dist/triggers/types.js.map +1 -0
  373. package/package.json +35 -0
@@ -0,0 +1,298 @@
1
+ import { FetchError } from '../fetch/errors.js';
2
+ import { getActivityFactor, parseDate, shiftISODate } from './utils.js';
3
+ import { ok, rejection } from './result.js';
4
+ const round = (n) => Math.round(n);
5
+ function rangeOf(start, end) {
6
+ const s = parseDate(start);
7
+ if (!s)
8
+ throw new FetchError('起始日期非法: ' + String(start));
9
+ return [s, parseDate(end ?? undefined) ?? s];
10
+ }
11
+ function daysBetween(d1, d2) {
12
+ const a = Date.parse(d1 + 'T12:00:00Z');
13
+ const b = Date.parse(d2 + 'T12:00:00Z');
14
+ if (Number.isNaN(a) || Number.isNaN(b))
15
+ throw new FetchError('日期非法: ' + d1 + ' ~ ' + d2);
16
+ return Math.round((b - a) / 86400000);
17
+ }
18
+ function latestWeightKg(db) {
19
+ const row = db.prepare('SELECT weight_kg FROM weight_log ORDER BY date DESC LIMIT 1').get();
20
+ return row?.weight_kg ?? 70;
21
+ }
22
+ function profileActivityLevel(db) {
23
+ const row = db.prepare('SELECT activity_level FROM user_profile WHERE id = 1').get();
24
+ return row?.activity_level ?? 'moderate';
25
+ }
26
+ export function exerciseTrend(db, startDate, endDate) {
27
+ const [start, end] = rangeOf(startDate, endDate);
28
+ const raw = db.prepare('SELECT date AS d, exercise_type AS t, duration_minutes AS dur, calories_burned AS k FROM exercise_log WHERE date >= ? AND date <= ? ORDER BY date ASC').all(start, end);
29
+ const rows = raw.map((r) => [r.d, r.t, r.dur, r.k]);
30
+ if (rows.length === 0)
31
+ return rejection('无运动记录(' + start + ' ~ ' + end + ')');
32
+ const span = daysBetween(start, end) + 1;
33
+ const dates = [...new Set(rows.map((r) => r[0]))].sort();
34
+ const totalCal = rows.reduce((a, r) => a + (r[3] ?? 0), 0);
35
+ const totalDur = rows.reduce((a, r) => a + (r[2] ?? 0), 0);
36
+ const durationMissing = rows.every((r) => r[2] === null || r[2] === undefined);
37
+ let longestStreak = 1;
38
+ let cur = 1;
39
+ for (let i = 1; i < dates.length; i++) {
40
+ if (daysBetween(dates[i - 1], dates[i]) === 1) {
41
+ cur += 1;
42
+ longestStreak = Math.max(longestStreak, cur);
43
+ }
44
+ else
45
+ cur = 1;
46
+ }
47
+ let maxGap;
48
+ if (dates.length >= 2) {
49
+ maxGap = 0;
50
+ for (let i = 1; i < dates.length; i++)
51
+ maxGap = Math.max(maxGap, daysBetween(dates[i - 1], dates[i]) - 1);
52
+ }
53
+ else
54
+ maxGap = span - 1;
55
+ return ok({
56
+ daysWithExercise: dates.length,
57
+ totalDays: span,
58
+ coveragePct: round((dates.length / span) * 100),
59
+ totalCalories: totalCal,
60
+ totalMinutes: totalDur,
61
+ avgCaloriesPerDay: round(totalCal / span),
62
+ avgMinutesPerDay: durationMissing ? null : round(totalDur / span),
63
+ longestStreakDays: longestStreak,
64
+ longestRestDays: maxGap,
65
+ alert: maxGap >= 7 ? '建议动起来' : null,
66
+ durationMissing,
67
+ }, '运动 ' + dates.length + '/' + span + ' 天,总消耗 ' + totalCal + ' 卡');
68
+ }
69
+ export function exerciseTypeBreakdown(db, startDate, endDate) {
70
+ const [start, end] = rangeOf(startDate, endDate);
71
+ const raw = db.prepare('SELECT exercise_type AS t, SUM(calories_burned) AS k, COUNT(*) AS n, SUM(duration_minutes) AS dur FROM exercise_log WHERE date >= ? AND date <= ? GROUP BY exercise_type ORDER BY SUM(calories_burned) DESC').all(start, end);
72
+ const rows = raw.map((r) => [r.t, r.k, r.n, r.dur]);
73
+ if (rows.length === 0)
74
+ return rejection('无运动记录(' + start + ' ~ ' + end + ')');
75
+ const totalCal = rows.reduce((a, r) => a + (r[1] ?? 0), 0);
76
+ const totalCnt = rows.reduce((a, r) => a + r[2], 0);
77
+ const totalDur = rows.reduce((a, r) => a + (r[3] ?? 0), 0);
78
+ const types = rows.map((r) => ({
79
+ type: r[0],
80
+ calories: r[1] ?? 0,
81
+ count: r[2],
82
+ minutes: r[3] ?? 0,
83
+ calPct: totalCal === 0 ? 0 : round(((r[1] ?? 0) / totalCal) * 100),
84
+ countPct: totalCnt === 0 ? 0 : round((r[2] / totalCnt) * 100),
85
+ minutesPct: totalDur === 0 ? 0 : round(((r[3] ?? 0) / totalDur) * 100),
86
+ }));
87
+ return ok({ totalCalories: totalCal, totalCount: totalCnt, totalMinutes: totalDur, types }, types.length + ' 种运动类型');
88
+ }
89
+ export function exerciseDeficitContribution(db, startDate, endDate) {
90
+ const [start, end] = rangeOf(startDate, endDate);
91
+ const exRow = db.prepare('SELECT SUM(calories_burned) AS v FROM exercise_log WHERE date >= ? AND date <= ?').get(start, end);
92
+ const inRow = db.prepare('SELECT SUM(calories) AS v FROM food_log WHERE date >= ? AND date <= ?').get(start, end);
93
+ const totalEx = exRow.v ?? 0;
94
+ const totalIntake = inRow.v ?? 0;
95
+ const span = daysBetween(start, end) + 1;
96
+ const currentWeight = latestWeightKg(db);
97
+ const bmr = currentWeight * 24 * getActivityFactor(profileActivityLevel(db));
98
+ const dietDeficit = bmr * span - totalIntake;
99
+ const totalDeficit = bmr * span - totalIntake + totalEx;
100
+ let dietPct;
101
+ let exPct;
102
+ if (totalDeficit === 0) {
103
+ dietPct = 50;
104
+ exPct = 50;
105
+ }
106
+ else {
107
+ dietPct = (Math.abs(dietDeficit) / Math.abs(totalDeficit)) * 100;
108
+ exPct = (totalEx / Math.abs(totalDeficit)) * 100;
109
+ }
110
+ const evaluation = exPct < 15 ? '运动贡献偏低,建议增加运动比例' : exPct > 25 ? '运动贡献较高' : '运动贡献适中';
111
+ return ok({
112
+ dietDeficit: round(dietDeficit),
113
+ dietContribPct: round(dietPct),
114
+ exerciseDeficit: round(totalEx),
115
+ exerciseContribPct: round(exPct),
116
+ evaluation,
117
+ bmr: round(bmr),
118
+ currentWeight: Math.round(currentWeight * 10) / 10,
119
+ }, '运动贡献 ' + round(exPct) + '% — ' + evaluation);
120
+ }
121
+ function calcPlanWeek(targetISO, config) {
122
+ if (!config)
123
+ return null;
124
+ const diff = daysBetween(config.start_date, targetISO);
125
+ if (diff < 0)
126
+ return null;
127
+ const realWeek = Math.floor(diff / 7) + 1;
128
+ return ((realWeek - 1) % config.total_weeks) + 1;
129
+ }
130
+ function getDayPlan(db, targetISO) {
131
+ const cfg = db.prepare('SELECT total_weeks, start_date FROM workout_plan_config WHERE id = 1').get();
132
+ const config = cfg ? { total_weeks: cfg.total_weeks, start_date: cfg.start_date } : null;
133
+ const week = calcPlanWeek(targetISO, config);
134
+ const dow = new Date(targetISO + 'T12:00:00Z').getUTCDay();
135
+ const isoDow = dow === 0 ? 7 : dow;
136
+ if (week === null && config !== null) {
137
+ return { plan_week: null, config, sessions: [], unstarted: true };
138
+ }
139
+ const rows = db.prepare('SELECT session_label, time_start, time_end, is_rest_day, total_sets, movements FROM workout_plans WHERE week_number = ? AND day_of_week = ? ORDER BY session_index').all(week, isoDow);
140
+ return {
141
+ plan_week: week,
142
+ config,
143
+ sessions: rows.map((r) => ({ session_label: r[0], total_sets: r[4], movements: JSON.parse(r[5] || '[]') })),
144
+ };
145
+ }
146
+ function isoWeekKey(iso) {
147
+ const d = new Date(iso + 'T12:00:00Z');
148
+ const day = (d.getUTCDay() + 6) % 7;
149
+ const thursday = new Date(d.getTime() + (3 - day) * 86400000);
150
+ const year = thursday.getUTCFullYear();
151
+ const jan4 = new Date(Date.UTC(year, 0, 4));
152
+ const week = 1 + Math.round(((thursday.getTime() - jan4.getTime()) / 86400000 - 3 + ((jan4.getUTCDay() + 6) % 7)) / 7);
153
+ return year + '-W' + String(week).padStart(2, '0');
154
+ }
155
+ function weekLabel(mondayISO) {
156
+ const mon = new Date(mondayISO + 'T12:00:00Z');
157
+ const sun = new Date(mon.getTime() + 6 * 86400000);
158
+ const m1 = mon.getUTCMonth() + 1;
159
+ const d1 = mon.getUTCDate();
160
+ const m2 = sun.getUTCMonth() + 1;
161
+ const d2 = sun.getUTCDate();
162
+ return m1 === m2 ? m1 + '/' + d1 + '~' + d2 : m1 + '/' + d1 + '~' + m2 + '/' + d2;
163
+ }
164
+ export function exerciseReview(db, startDate, endDate) {
165
+ const [start, end] = rangeOf(startDate, endDate);
166
+ const results = new Map();
167
+ const volPlanWeek = new Map();
168
+ const volActualWeek = new Map();
169
+ const volPlanMov = new Map();
170
+ const volActualMov = new Map();
171
+ const volMovTotal = new Map();
172
+ const volWeeks = [];
173
+ const weekMonday = new Map();
174
+ const addVol = (m, k, v) => { m.set(k, (m.get(k) ?? 0) + v); };
175
+ for (let d = start; d <= end; d = shiftISODate(d, 1)) {
176
+ const wk = isoWeekKey(d);
177
+ if (volWeeks[volWeeks.length - 1] !== wk) {
178
+ volWeeks.push(wk);
179
+ weekMonday.set(wk, shiftISODate(d, -(((new Date(d + 'T12:00:00Z').getUTCDay() + 6) % 7))));
180
+ }
181
+ const plan = getDayPlan(db, d);
182
+ const planSessions = plan.sessions;
183
+ const planTotalSets = planSessions.reduce((a, s) => a + (s.total_sets ?? 0), 0);
184
+ const sessionLabels = planSessions.map((s) => s.session_label ?? '');
185
+ for (const s of planSessions) {
186
+ for (const m of s.movements ?? []) {
187
+ const name = m.name ?? '';
188
+ for (const st of m.sets ?? []) {
189
+ const w = Number(st.weight ?? 0);
190
+ const reps = Math.trunc(Number(st.reps ?? 0));
191
+ if (!(w > 0) || !(reps > 0))
192
+ continue;
193
+ const unit = st.unit ?? '';
194
+ if (unit && unit !== 'kg')
195
+ continue;
196
+ const ton = w * reps;
197
+ addVol(volPlanWeek, wk, ton);
198
+ addVol(volPlanMov, wk + '\u0000' + name, ton);
199
+ const t = volMovTotal.get(name) ?? { plan: 0, actual: 0 };
200
+ t.plan += ton;
201
+ volMovTotal.set(name, t);
202
+ }
203
+ }
204
+ }
205
+ const exRaw = db.prepare('SELECT exercise_type AS t, duration_minutes AS dur, calories_burned AS k, reps AS r, load_kg AS l FROM exercise_log WHERE date = ? ORDER BY exercise_type').all(d);
206
+ const exRows = exRaw.map((r) => [r.t, r.dur, r.k, r.r, r.l]);
207
+ const actual = new Map();
208
+ for (const r of exRows) {
209
+ const etype = r[0];
210
+ const a = actual.get(etype) ?? { sets: 0, calories: 0, minutes: 0 };
211
+ a.sets += 1;
212
+ a.calories += r[2] ?? 0;
213
+ a.minutes += r[1] ?? 0;
214
+ actual.set(etype, a);
215
+ const load = r[4] ?? 0;
216
+ const reps = r[3] ?? 0;
217
+ if (load > 0 && reps > 0) {
218
+ const ton = load * reps;
219
+ addVol(volActualWeek, wk, ton);
220
+ addVol(volActualMov, wk + '\u0000' + etype, ton);
221
+ const t = volMovTotal.get(etype) ?? { plan: 0, actual: 0 };
222
+ t.actual += ton;
223
+ volMovTotal.set(etype, t);
224
+ }
225
+ }
226
+ const actualTotalSets = [...actual.values()].reduce((a, v) => a + v.sets, 0);
227
+ const anomalies = [];
228
+ let note = null;
229
+ let completionRate = null;
230
+ if (plan.unstarted) {
231
+ note = '计划尚未开始(起始 ' + plan.config.start_date + ')';
232
+ }
233
+ else if (planTotalSets === 0 && actualTotalSets === 0) {
234
+ note = '休息日 / 无计划无实绩';
235
+ }
236
+ else if (planTotalSets === 0 && actualTotalSets > 0) {
237
+ note = '计划休息但实做了 ' + actualTotalSets + ' 组';
238
+ anomalies.push({ type: 'rest_but_done', msg: '⚠️ ' + note });
239
+ }
240
+ else if (planTotalSets > 0 && actualTotalSets === 0) {
241
+ note = '计划有训练但完全未做';
242
+ completionRate = 0.0;
243
+ anomalies.push({ type: 'no_actual', msg: '❌ ' + note });
244
+ }
245
+ else {
246
+ completionRate = (actualTotalSets / planTotalSets) * 100;
247
+ if (completionRate < 50)
248
+ anomalies.push({ type: 'low_completion', msg: '⚠️ 完成率仅 ' + Math.round(completionRate) + '%(实做 ' + actualTotalSets + '/' + planTotalSets + ' 组数)' });
249
+ else if (completionRate > 130)
250
+ anomalies.push({ type: 'over_completion', msg: '⚠️ 超额完成 (' + Math.round(completionRate) + '%)(' + actualTotalSets + '/' + planTotalSets + ' 组数)' });
251
+ }
252
+ results.set(d, {
253
+ date: d,
254
+ planWeek: plan.plan_week,
255
+ sessions: sessionLabels,
256
+ planTotalSets,
257
+ actualTotalSets,
258
+ caloriesBurned: [...actual.values()].reduce((a, v) => a + v.calories, 0),
259
+ completionRate,
260
+ anomalies,
261
+ note,
262
+ isRestDay: planTotalSets === 0 && actualTotalSets === 0,
263
+ });
264
+ }
265
+ const bySeverityCount = { low_completion: 0, over_completion: 0, no_actual: 0, rest_but_done: 0 };
266
+ for (const r of results.values()) {
267
+ for (const a of r.anomalies) {
268
+ if (a.type in bySeverityCount)
269
+ bySeverityCount[a.type] = bySeverityCount[a.type] + 1;
270
+ }
271
+ }
272
+ const wlabel = (wk) => weekLabel(weekMonday.get(wk));
273
+ const volumeWeeks = volWeeks.map((wk) => ({ week: wk, label: wlabel(wk), plan: round(volPlanWeek.get(wk) ?? 0), actual: round(volActualWeek.get(wk) ?? 0), actualSets: 0 }));
274
+ const topNames = [...volMovTotal.keys()].sort((a, b) => {
275
+ const ta = volMovTotal.get(a);
276
+ const tb = volMovTotal.get(b);
277
+ return tb.plan + tb.actual - (ta.plan + ta.actual);
278
+ }).slice(0, 4);
279
+ const volumeMovements = topNames.map((name) => {
280
+ const t = volMovTotal.get(name);
281
+ return { name, planTotal: round(t.plan), actualTotal: round(t.actual), weeks: volWeeks.map((wk) => ({ week: wk, label: wlabel(wk), plan: round(volPlanMov.get(wk + '\u0000' + name) ?? 0), actual: round(volActualMov.get(wk + '\u0000' + name) ?? 0) })) };
282
+ });
283
+ const totalActualTon = [...volActualWeek.values()].reduce((a, b) => a + b, 0);
284
+ const days = [...results.values()];
285
+ const data = {};
286
+ for (const [k, v] of results)
287
+ data[k] = v;
288
+ data.__meta__ = {
289
+ bySeverityCount,
290
+ totalDays: days.length,
291
+ trainDays: days.filter((r) => !r.isRestDay).length,
292
+ restDays: days.filter((r) => r.isRestDay).length,
293
+ totalCalories: days.reduce((a, r) => a + (r.caloriesBurned ?? 0), 0),
294
+ volume: { weeks: volumeWeeks, movements: volumeMovements, totalPlan: round([...volPlanWeek.values()].reduce((a, b) => a + b, 0)), totalActual: round(totalActualTon), hasActual: totalActualTon > 0 },
295
+ };
296
+ return ok(data, '训练复盘 ' + days.length + ' 天');
297
+ }
298
+ //# sourceMappingURL=exercise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exercise.js","sourceRoot":"","sources":["../../src/analysis/exercise.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG5C,MAAM,KAAK,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnD,SAAS,OAAO,CAAC,KAAa,EAAE,GAAmB;IACjD,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC3B,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,WAAW,CAAC,EAAU,EAAE,EAAU;IACzC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,YAAY,CAAC,CAAC;IACxC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,YAAY,CAAC,CAAC;IACxC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,QAAQ,GAAG,EAAE,GAAG,KAAK,GAAG,EAAE,CAAC,CAAC;IACzF,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,cAAc,CAAC,EAAgB;IACtC,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,6DAA6D,CAAC,CAAC,GAAG,EAA8C,CAAC;IACxI,OAAO,GAAG,EAAE,SAAS,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED,SAAS,oBAAoB,CAAC,EAAgB;IAC5C,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,sDAAsD,CAAC,CAAC,GAAG,EAAmD,CAAC;IACtI,OAAO,GAAG,EAAE,cAAc,IAAI,UAAU,CAAC;AAC3C,CAAC;AAID,MAAM,UAAU,aAAa,CAAC,EAAgB,EAAE,SAAiB,EAAE,OAAuB;IACxF,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CACpB,uJAAuJ,CACxJ,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAqF,CAAC;IACtG,MAAM,IAAI,GAA0D,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3G,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC,QAAQ,GAAG,KAAK,GAAG,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;IAC9E,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3D,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IAC/E,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAW,EAAE,KAAK,CAAC,CAAC,CAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YAAC,GAAG,IAAI,CAAC,CAAC;YAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;QAAC,CAAC;;YACzH,GAAG,GAAG,CAAC,CAAC;IACf,CAAC;IACD,IAAI,MAAc,CAAC;IACnB,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,GAAG,CAAC,CAAC;QACX,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;YAAE,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAW,EAAE,KAAK,CAAC,CAAC,CAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IAChI,CAAC;;QAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC;IACzB,OAAO,EAAE,CAAC;QACR,gBAAgB,EAAE,KAAK,CAAC,MAAM;QAC9B,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC;QAC/C,aAAa,EAAE,QAAQ;QACvB,YAAY,EAAE,QAAQ;QACtB,iBAAiB,EAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;QACzC,gBAAgB,EAAE,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;QACjE,iBAAiB,EAAE,aAAa;QAChC,eAAe,EAAE,MAAM;QACvB,KAAK,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;QACnC,eAAe;KAChB,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,GAAG,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,GAAG,IAAI,CAAC,CAAC;AACtE,CAAC;AAKD,MAAM,UAAU,qBAAqB,CAAC,EAAgB,EAAE,SAAiB,EAAE,OAAuB;IAChG,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CACpB,6MAA6M,CAC9M,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAqF,CAAC;IACtG,MAAM,IAAI,GAA0D,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3G,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC,QAAQ,GAAG,KAAK,GAAG,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;IAC9E,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAuB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACjD,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACV,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACnB,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QACX,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAClB,MAAM,EAAE,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,GAAG,CAAC;QAClE,QAAQ,EAAE,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,GAAG,CAAC;QAC7D,UAAU,EAAE,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,GAAG,CAAC;KACvE,CAAC,CAAC,CAAC;IACJ,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC;AACvH,CAAC;AAID,MAAM,UAAU,2BAA2B,CAAC,EAAgB,EAAE,SAAiB,EAAE,OAAuB;IACtG,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC,kFAAkF,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAyB,CAAC;IACrJ,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC,uEAAuE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAyB,CAAC;IAC1I,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,aAAa,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,aAAa,GAAG,EAAE,GAAG,iBAAiB,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7E,MAAM,WAAW,GAAG,GAAG,GAAG,IAAI,GAAG,WAAW,CAAC;IAC7C,MAAM,YAAY,GAAG,GAAG,GAAG,IAAI,GAAG,WAAW,GAAG,OAAO,CAAC;IACxD,IAAI,OAAe,CAAC;IACpB,IAAI,KAAa,CAAC;IAClB,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;QAAC,KAAK,GAAG,EAAE,CAAC;IAAC,CAAC;SAChD,CAAC;QAAC,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,GAAG,GAAG,CAAC;QAAC,KAAK,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,GAAG,GAAG,CAAC;IAAC,CAAC;IAC5H,MAAM,UAAU,GAAG,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;IACrF,OAAO,EAAE,CAAC;QACR,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC;QAC/B,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC;QAC9B,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC;QAC/B,kBAAkB,EAAE,KAAK,CAAC,KAAK,CAAC;QAChC,UAAU;QACV,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC;QACf,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,EAAE,CAAC,GAAG,EAAE;KACnD,EAAE,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,UAAU,CAAC,CAAC;AACnD,CAAC;AASD,SAAS,YAAY,CAAC,SAAiB,EAAE,MAA0D;IACjG,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACvD,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAC1C,OAAO,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,UAAU,CAAC,EAAgB,EAAE,SAAiB;IACrD,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,sEAAsE,CAAC,CAAC,GAAG,EAErF,CAAC;IACd,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACzF,MAAM,IAAI,GAAG,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,SAAS,GAAG,YAAY,CAAC,CAAC,SAAS,EAAE,CAAC;IAC3D,MAAM,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACnC,IAAI,IAAI,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACrC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACpE,CAAC;IACD,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CACrB,oKAAoK,CACrK,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAmG,CAAC;IACtH,OAAO;QACL,SAAS,EAAE,IAAI;QACf,MAAM;QACN,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAiC,EAAE,CAAC,CAAC;KAC5I,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,GAAG,YAAY,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAG,QAAQ,CAAC,cAAc,EAAE,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,QAAQ,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACvH,OAAO,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,SAAS,CAAC,SAAiB;IAClC,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,SAAS,GAAG,YAAY,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC;IACnD,MAAM,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IACjC,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC;IAC5B,MAAM,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IACjC,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC;IAC5B,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAgB,EAAE,SAAiB,EAAE,OAAuB;IACzF,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC7C,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC9C,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC/C,MAAM,WAAW,GAAG,IAAI,GAAG,EAA4C,CAAC;IACxE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,MAAM,MAAM,GAAG,CAAC,CAAsB,EAAE,CAAS,EAAE,CAAS,EAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1G,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACrD,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;YAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAAC,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;QAC5J,MAAM,IAAI,GAAG,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC;QACnC,MAAM,aAAa,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAChF,MAAM,aAAa,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;QACrE,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;YAC7B,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;gBAClC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;gBAC1B,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;oBAC9B,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;oBACjC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;oBAC9C,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;wBAAE,SAAS;oBACtC,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;oBAC3B,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI;wBAAE,SAAS;oBACpC,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC;oBACrB,MAAM,CAAC,WAAW,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;oBAC7B,MAAM,CAAC,UAAU,EAAE,EAAE,GAAG,QAAQ,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC;oBAC9C,MAAM,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;oBAC1D,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC;oBACd,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;gBAC3B,CAAC;YACH,CAAC;QACH,CAAC;QACD,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,CACtB,2JAA2J,CAC5J,CAAC,GAAG,CAAC,CAAC,CAA8G,CAAC;QACtH,MAAM,MAAM,GAAgF,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1I,MAAM,MAAM,GAAG,IAAI,GAAG,EAA+D,CAAC;QACtF,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACnB,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;YACpE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;YACZ,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACvB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACrB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACvB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACvB,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;gBACxB,MAAM,CAAC,aAAa,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;gBAC/B,MAAM,CAAC,YAAY,EAAE,EAAE,GAAG,QAAQ,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC;gBACjD,MAAM,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;gBAC3D,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC;gBAChB,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QACD,MAAM,eAAe,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC7E,MAAM,SAAS,GAAoB,EAAE,CAAC;QACtC,IAAI,IAAI,GAAkB,IAAI,CAAC;QAC/B,IAAI,cAAc,GAAkB,IAAI,CAAC;QACzC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,IAAI,GAAG,YAAY,GAAI,IAAI,CAAC,MAAiC,CAAC,UAAU,GAAG,GAAG,CAAC;QACjF,CAAC;aAAM,IAAI,aAAa,KAAK,CAAC,IAAI,eAAe,KAAK,CAAC,EAAE,CAAC;YACxD,IAAI,GAAG,cAAc,CAAC;QACxB,CAAC;aAAM,IAAI,aAAa,KAAK,CAAC,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;YACtD,IAAI,GAAG,WAAW,GAAG,eAAe,GAAG,IAAI,CAAC;YAC5C,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,CAAC,CAAC;QAC/D,CAAC;aAAM,IAAI,aAAa,GAAG,CAAC,IAAI,eAAe,KAAK,CAAC,EAAE,CAAC;YACtD,IAAI,GAAG,YAAY,CAAC;YACpB,cAAc,GAAG,GAAG,CAAC;YACrB,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,cAAc,GAAG,CAAC,eAAe,GAAG,aAAa,CAAC,GAAG,GAAG,CAAC;YACzD,IAAI,cAAc,GAAG,EAAE;gBAAE,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,OAAO,GAAG,eAAe,GAAG,GAAG,GAAG,aAAa,GAAG,MAAM,EAAE,CAAC,CAAC;iBACxK,IAAI,cAAc,GAAG,GAAG;gBAAE,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,KAAK,GAAG,eAAe,GAAG,GAAG,GAAG,aAAa,GAAG,MAAM,EAAE,CAAC,CAAC;QACrL,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE;YACb,IAAI,EAAE,CAAC;YACP,QAAQ,EAAE,IAAI,CAAC,SAAS;YACxB,QAAQ,EAAE,aAAa;YACvB,aAAa;YACb,eAAe;YACf,cAAc,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACxE,cAAc;YACd,SAAS;YACT,IAAI;YACJ,SAAS,EAAE,aAAa,KAAK,CAAC,IAAI,eAAe,KAAK,CAAC;SACxD,CAAC,CAAC;IACL,CAAC;IACD,MAAM,eAAe,GAA2B,EAAE,cAAc,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC;IAC1H,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACjC,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;YAC5B,IAAI,CAAC,CAAC,IAAI,IAAI,eAAe;gBAAE,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,GAAI,eAAe,CAAC,CAAC,CAAC,IAAI,CAAY,GAAG,CAAC,CAAC;QACnG,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,CAAC,EAAU,EAAU,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAW,CAAC,CAAC;IAC/E,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7K,MAAM,QAAQ,GAAG,CAAC,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACrD,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAqC,CAAC;QAClE,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAqC,CAAC;QAClE,OAAO,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACf,MAAM,eAAe,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC5C,MAAM,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAqC,CAAC;QACpE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,GAAG,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAC9P,CAAC,CAAC,CAAC;IACH,MAAM,cAAc,GAAG,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9E,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACnC,MAAM,IAAI,GAAuD,EAAE,CAAC;IACpE,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO;QAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACzC,IAAgC,CAAC,QAAQ,GAAG;QAC3C,eAAe;QACf,SAAS,EAAE,IAAI,CAAC,MAAM;QACtB,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM;QAClD,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM;QAChD,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;QACpE,MAAM,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,cAAc,GAAG,CAAC,EAAE;KACtM,CAAC;IACF,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,36 @@
1
+ /** T7 #26 · 运动复核口径(对照老家 exercise_review CLI 范围语义 + T3 取数 + T5 衍生)。
2
+ *
3
+ * 老家 exercise_review.py 仅参数排期外壳,复核计算主体在 review_engine;
4
+ * TS 以 T3 listWindow 为行源、MET 口径为估算源,产出运动复核摘要(T8 渲染消费)。
5
+ * 软删除排除;缺失阻断不返空。
6
+ */
7
+ import type { DatabaseSync } from 'node:sqlite';
8
+ export interface ExerciseTypeStat {
9
+ type: string;
10
+ sessions: number;
11
+ burned: number;
12
+ minutes: number;
13
+ }
14
+ export interface ExerciseReview {
15
+ start: string;
16
+ end: string;
17
+ days: number;
18
+ sessions: number;
19
+ activeDays: number;
20
+ totalBurned: number;
21
+ totalMinutes: number;
22
+ avgBurnedPerSession: number;
23
+ avgBurnedPerDay: number;
24
+ byCategory: Record<string, {
25
+ sessions: number;
26
+ burned: number;
27
+ }>;
28
+ byType: ExerciseTypeStat[];
29
+ estimatedCheck: {
30
+ reported: number;
31
+ estimated: number;
32
+ deviationPct: number | null;
33
+ };
34
+ }
35
+ export declare function buildExerciseReview(db: DatabaseSync, start: string, end: string, bodyWeightKg?: number): ExerciseReview;
36
+ //# sourceMappingURL=exerciseReview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exerciseReview.d.ts","sourceRoot":"","sources":["../../src/analysis/exerciseReview.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAKhD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;CACjE;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IACzC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAC1C,mBAAmB,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IACrD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,cAAc,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CACtF;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,SAAK,GAAG,cAAc,CA4CnH"}
@@ -0,0 +1,50 @@
1
+ import { FetchError } from '../fetch/errors.js';
2
+ import { round2 } from '../kcal.js';
3
+ import { estimateCaloriesMet, inferCategory, listWindow } from '../fetch/exercise.js';
4
+ export function buildExerciseReview(db, start, end, bodyWeightKg = 70) {
5
+ const rows = listWindow(db, start, end);
6
+ if (!rows.length)
7
+ throw new FetchError(`无运动记录:${start} ~ ${end}`);
8
+ const daySet = new Set();
9
+ let totalBurned = 0, totalMinutes = 0;
10
+ const byCategory = {};
11
+ const byType = new Map();
12
+ let estSum = 0;
13
+ for (const r of rows) {
14
+ const date = String(r.date);
15
+ const type = String(r.exercise_type ?? '未知');
16
+ const burned = Number(r.calories_burned ?? 0);
17
+ const minutes = Number(r.duration_minutes ?? 0);
18
+ daySet.add(date);
19
+ totalBurned += burned;
20
+ totalMinutes += minutes;
21
+ const cat = inferCategory(type);
22
+ const c = byCategory[cat] ?? { sessions: 0, burned: 0 };
23
+ c.sessions++;
24
+ c.burned += burned;
25
+ byCategory[cat] = c;
26
+ const t = byType.get(type) ?? { type, sessions: 0, burned: 0, minutes: 0 };
27
+ t.sessions++;
28
+ t.burned += burned;
29
+ t.minutes += minutes;
30
+ byType.set(type, t);
31
+ const [est] = estimateCaloriesMet(type, bodyWeightKg, minutes || undefined, 3);
32
+ estSum += est;
33
+ }
34
+ const sessions = rows.length;
35
+ const days = daySet.size;
36
+ const deviationPct = estSum > 0 ? round2(Math.abs(totalBurned - estSum) / estSum) : null;
37
+ return {
38
+ start, end, days,
39
+ sessions,
40
+ activeDays: days,
41
+ totalBurned: round2(totalBurned),
42
+ totalMinutes,
43
+ avgBurnedPerSession: round2(totalBurned / sessions),
44
+ avgBurnedPerDay: round2(totalBurned / days),
45
+ byCategory,
46
+ byType: [...byType.values()].sort((a, b) => b.burned - a.burned),
47
+ estimatedCheck: { reported: round2(totalBurned), estimated: round2(estSum), deviationPct },
48
+ };
49
+ }
50
+ //# sourceMappingURL=exerciseReview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exerciseReview.js","sourceRoot":"","sources":["../../src/analysis/exerciseReview.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export declare const PRECISION_SUMMARY_FIELDS: string[];
2
+ export declare const PRECISION_SERIES_KEYS: string[];
3
+ export interface LeakReport {
4
+ path: string;
5
+ value: number;
6
+ }
7
+ export declare function findLeaks(data: {
8
+ summary?: Record<string, unknown>;
9
+ series?: Record<string, unknown>[];
10
+ }): LeakReport[];
11
+ export declare function assertNoLeak(data: {
12
+ summary?: Record<string, unknown>;
13
+ series?: Record<string, unknown>[];
14
+ }): void;
15
+ //# sourceMappingURL=precision.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"precision.d.ts","sourceRoot":"","sources":["../../src/analysis/precision.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,wBAAwB,UAIpC,CAAC;AAEF,eAAO,MAAM,qBAAqB,UAAc,CAAC;AAEjD,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAE3D,wBAAgB,SAAS,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;CAAE,GAAG,UAAU,EAAE,CAevH;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;CAAE,GAAG,IAAI,CAOlH"}
@@ -0,0 +1,38 @@
1
+ /** T7 #26 · 精度守卫(对照老家 check_decimal_precision.py 白名单与规则)。
2
+ *
3
+ * 白名单:summary.trend_value/start_avg/end_avg/weekday_avg/weekend_avg/avg/total_calorie/avg_calorie、
4
+ * series[*].calorie/items[*].calorie。规则:round(2) 后差 ≤ 1e-9,否则抛错。
5
+ * T8-T10 渲染序列化前调 assertNoLeak;T1 kcal.isClean 为单值版。
6
+ */
7
+ import { isClean } from '../kcal.js';
8
+ export const PRECISION_SUMMARY_FIELDS = [
9
+ 'trend_value', 'trendValue', 'start_avg', 'startAvg', 'end_avg', 'endAvg',
10
+ 'weekday_avg', 'weekdayAvg', 'weekend_avg', 'weekendAvg', 'weekend_diff', 'weekendDiff',
11
+ 'avg', 'total_calorie', 'totalCalorie', 'avg_calorie', 'avgCalorie',
12
+ ];
13
+ export const PRECISION_SERIES_KEYS = ['calorie'];
14
+ export function findLeaks(data) {
15
+ const leaks = [];
16
+ const summary = data.summary ?? {};
17
+ for (const f of PRECISION_SUMMARY_FIELDS) {
18
+ const v = summary[f];
19
+ if (typeof v === 'number' && !isClean(v))
20
+ leaks.push({ path: `summary.${f}`, value: v });
21
+ }
22
+ for (let i = 0; i < (data.series ?? []).length; i++) {
23
+ const item = data.series[i];
24
+ for (const k of PRECISION_SERIES_KEYS) {
25
+ const v = item[k];
26
+ if (typeof v === 'number' && !isClean(v))
27
+ leaks.push({ path: `series[${i}].${k}`, value: v });
28
+ }
29
+ }
30
+ return leaks;
31
+ }
32
+ export function assertNoLeak(data) {
33
+ const leaks = findLeaks(data);
34
+ if (leaks.length) {
35
+ throw new Error('[calorie] 小数精度泄漏: ' + leaks.map((l) => `${l.path}=${l.value}`).join(', '));
36
+ }
37
+ }
38
+ //# sourceMappingURL=precision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"precision.js","sourceRoot":"","sources":["../../src/analysis/precision.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ;IACzE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa;IACvF,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY;CACpE,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,SAAS,CAAC,CAAC;AAIjD,MAAM,UAAU,SAAS,CAAC,IAA+E;IACvG,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IACnC,KAAK,MAAM,CAAC,IAAI,wBAAwB,EAAE,CAAC;QACzC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3F,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpD,MAAM,IAAI,GAAI,IAAI,CAAC,MAAoC,CAAC,CAAC,CAA4B,CAAC;QACtF,KAAK,MAAM,CAAC,IAAI,qBAAqB,EAAE,CAAC;YACtC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAA+E;IAC1G,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,oBAAoB,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAC3E,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ /** T5 #24 · 分析结果包络(对照老家 as_dict=True 形状)。
2
+ *
3
+ * 有规则口径 → {status:'ok', data, message};无数据 → {status:'error', data:null,
4
+ * message} 明确缺失阻断(验收:无规则 rejection 有明确缺失阻断,不返空)。
5
+ * 输入非法(坏日期/坏枚举)→ 抛 FetchError。L6 开放式分析留 AI,不在此建模。
6
+ */
7
+ export type AnalysisStatus = 'ok' | 'error';
8
+ export interface AnalysisResult<T> {
9
+ status: AnalysisStatus;
10
+ data: T | null;
11
+ message: string;
12
+ }
13
+ export declare function ok<T>(data: T, message: string): AnalysisResult<T>;
14
+ export declare function rejection<T = never>(message: string): AnalysisResult<T>;
15
+ //# sourceMappingURL=result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/analysis/result.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC;AAE5C,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,CAEjE;AAED,wBAAgB,SAAS,CAAC,CAAC,GAAG,KAAK,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,CAEvE"}
@@ -0,0 +1,13 @@
1
+ /** T5 #24 · 分析结果包络(对照老家 as_dict=True 形状)。
2
+ *
3
+ * 有规则口径 → {status:'ok', data, message};无数据 → {status:'error', data:null,
4
+ * message} 明确缺失阻断(验收:无规则 rejection 有明确缺失阻断,不返空)。
5
+ * 输入非法(坏日期/坏枚举)→ 抛 FetchError。L6 开放式分析留 AI,不在此建模。
6
+ */
7
+ export function ok(data, message) {
8
+ return { status: 'ok', data, message };
9
+ }
10
+ export function rejection(message) {
11
+ return { status: 'error', data: null, message };
12
+ }
13
+ //# sourceMappingURL=result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/analysis/result.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,MAAM,UAAU,EAAE,CAAI,IAAO,EAAE,OAAe;IAC5C,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,SAAS,CAAY,OAAe;IAClD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAS,EAAE,OAAO,EAAE,CAAC;AACvD,CAAC"}
@@ -0,0 +1,118 @@
1
+ /** T5 #24 · 周复盘引擎取数+衍生(对照老家 scripts/review_engine.py 数据段)。
2
+ *
3
+ * parseRange / query5dims / derive(含 complete_days 今日污染隔离、缺口、
4
+ * 营养达标率、异常天规则)。_render_weight_trend_svg 与 extract_summary 属
5
+ * 渲染/HTML 层,归 T8-T10,本票 weightTrendSvg 回 null 并在 meta 注明(待裁决)。
6
+ * today 可注入(默认 UTC 日)。
7
+ */
8
+ import type { DatabaseSync } from 'node:sqlite';
9
+ export type RangeType = 'day' | 'week' | 'month' | 'year';
10
+ export declare function parseRange(rangeArg?: string | null, rangeType?: RangeType, today?: string): [string, string];
11
+ export interface DayIntake {
12
+ date: string;
13
+ totalCalorie: number;
14
+ totalProtein: number;
15
+ totalCarbs: number;
16
+ totalFat: number;
17
+ mealCount: number;
18
+ }
19
+ export interface DayBurn {
20
+ date: string;
21
+ totalBurned: number;
22
+ totalMinutes: number | null;
23
+ types: string | null;
24
+ categories: string | null;
25
+ }
26
+ export interface WeightLogPoint {
27
+ date: string;
28
+ weightKg: number;
29
+ }
30
+ export interface FitnessSession {
31
+ date: string;
32
+ weekNumber: number;
33
+ dayOfWeek: number;
34
+ sessionLabel: string;
35
+ isRestDay: number;
36
+ totalSets: number | null;
37
+ movements: unknown[];
38
+ }
39
+ export interface TopFood {
40
+ name: string;
41
+ totalCal: number;
42
+ cnt: number;
43
+ avgCalPerMeal: number;
44
+ }
45
+ export interface FiveDims {
46
+ range: {
47
+ start: string;
48
+ end: string;
49
+ days: number;
50
+ };
51
+ dailyIntake: DayIntake[];
52
+ dailyBurn: DayBurn[];
53
+ weightLogs: WeightLogPoint[];
54
+ fitnessPlan: FitnessSession[] | null;
55
+ userProfile: {
56
+ heightCm: number | null;
57
+ age: number;
58
+ gender: string;
59
+ activityLevel: string;
60
+ };
61
+ nutritionTargets: Record<string, unknown>;
62
+ topFoods: TopFood[];
63
+ }
64
+ export declare function query5dims(db: DatabaseSync, start: string, end: string): FiveDims;
65
+ export interface NutritionMatch {
66
+ daysCount: number;
67
+ matchedDays: number;
68
+ matchRatePct: number;
69
+ summary: string;
70
+ }
71
+ export declare function nutritionMatchRate(dailyIntake: DayIntake[], targets: Record<string, unknown>): NutritionMatch;
72
+ export interface AnomalyDay {
73
+ date: string | null;
74
+ type: string;
75
+ value: number;
76
+ target: number;
77
+ diff: string;
78
+ severity: string;
79
+ }
80
+ export interface DerivedReview extends FiveDims {
81
+ todayPartial: {
82
+ intake: DayIntake | null;
83
+ burn: DayBurn | null;
84
+ };
85
+ completeDaysCount: number;
86
+ tdee: number;
87
+ intakeSummary: {
88
+ daysCount: number;
89
+ isPartial?: boolean;
90
+ avgCalorie: number;
91
+ avgProtein: number;
92
+ avgCarbs: number;
93
+ avgFat: number;
94
+ };
95
+ burnSummary: {
96
+ daysCount: number;
97
+ isPartial?: boolean;
98
+ totalBurned: number;
99
+ avgBurned: number;
100
+ totalMinutes: number;
101
+ };
102
+ macroRatio: {
103
+ proteinPct: number;
104
+ carbsPct: number;
105
+ fatPct: number;
106
+ };
107
+ weeklyDeficit: number;
108
+ avgDailyDeficit: number;
109
+ theoreticalWeightLoss: number;
110
+ nutritionMatch: NutritionMatch;
111
+ weightTrendSvg: null;
112
+ weightTrendMeta: {
113
+ deferred: string;
114
+ };
115
+ anomalyDays: AnomalyDay[];
116
+ }
117
+ export declare function deriveReview(db: DatabaseSync, dims: FiveDims, today?: string): DerivedReview;
118
+ //# sourceMappingURL=review.d.ts.map