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,121 @@
1
+ export const CONTRA_PARTS = ['腰', '膝', '肩'];
2
+ export const SAFE_VARIANTS = ['支撑式', '俯卧', '仰卧', '高位'];
3
+ export function isSafeVariant(name) {
4
+ return SAFE_VARIANTS.some((v) => name.includes(v));
5
+ }
6
+ const LUMBAR = [
7
+ { part: '腰', name: '髋铰链轴向压力', reason: '硬拉/罗马尼亚硬拉/早安式弯腰会让腰椎承受巨大轴向压力,突出节段受挤压加重', keywords: ['硬拉', '罗马尼亚', '早安', 'good morning', '臀桥'], severity: 'error' },
8
+ { part: '腰', name: '俯身/弯腰划船类', reason: '俯身角度超过 45° 时腰部竖脊肌持续等长收缩 + 腰椎剪切力,T-bar 划船最危险', keywords: ['俯身', 't-bar', 'tbar', 't bar', '杠铃划船'], severity: 'warn' },
9
+ { part: '腰', name: '腿举/倒蹬类', reason: '倒蹬器械在膝屈曲 + 髋屈曲时腰椎屈曲代偿,突出节段受压(用户已主动删除器械倒蹬)', keywords: ['倒蹬', '腿举', 'smith 机深蹲'], severity: 'error' },
10
+ { part: '腰', name: '坐姿腿弯举', reason: '腘绳肌在屈膝时收缩牵拉坐骨结节,导致骨盆前倾 + 腰椎屈曲,加重突出', keywords: ['腿弯举', '坐姿腿弯举', '俯卧腿弯举'], severity: 'error' },
11
+ ];
12
+ const KNEE = [
13
+ { part: '膝', name: '大重量深蹲/全蹲', reason: '超过 90° 深度 + 大重量会让髌股关节压力激增,半月板承受剪切', keywords: ['深蹲', '全蹲', '高杠深蹲', '低杠深蹲', '前蹲'], severity: 'warn' },
14
+ { part: '膝', name: '跳跃/冲击类', reason: '跳跃落地时膝关节承受 5-7 倍体重冲击,半月板/韧带风险高', keywords: ['跳箱', 'box jump', '跳跃', '冲刺跑'], severity: 'warn' },
15
+ { part: '膝', name: '开链伸膝大重量', reason: '坐姿腿屈伸(开链)大重量时髌腱张力极高,易诱发髌腱炎', keywords: ['腿屈伸', 'leg extension'], severity: 'info' },
16
+ ];
17
+ const SHOULDER = [
18
+ { part: '肩', name: '颈后推举', reason: '颈后推举时肩关节外旋 + 极度外展,肩峰下撞击综合征风险极高', keywords: ['颈后推举', '颈后推', 'behind neck press'], severity: 'error' },
19
+ { part: '肩', name: '大重量直立划船', reason: '直立划船到顶端时肩关节内旋 + 外展,肩峰撞击 + 肩袖肌群挤压', keywords: ['直立划船', 'upright row'], severity: 'warn' },
20
+ { part: '肩', name: '过头推举大重量', reason: '过头推举超过头部时肱骨大结节与肩峰撞击,肩袖肌群受压', keywords: ['过头推举', 'overhead press', '推举过头'], severity: 'warn' },
21
+ { part: '肩', name: '大幅度侧平举', reason: '侧平举超过 90° 时肩峰下空间消失,冈上肌撞击', keywords: ['侧平举', 'lateral raise'], severity: 'info' },
22
+ ];
23
+ export const ALL_RULES = { '腰': LUMBAR, '膝': KNEE, '肩': SHOULDER };
24
+ export function rulesFor(part) {
25
+ return ALL_RULES[part] ?? [];
26
+ }
27
+ function matches(name, keyword) {
28
+ return name.toLowerCase().includes(keyword.toLowerCase());
29
+ }
30
+ export function matchOne(name, rule) {
31
+ return rule.keywords.some((kw) => matches(name, kw));
32
+ }
33
+ /** 单动作扫描:每部位一个 slot(无命中为空数组,顺序稳定)。 */
34
+ export function scanMovement(name, parts = [...CONTRA_PARTS]) {
35
+ return parts.map((part) => rulesFor(part).filter((r) => matchOne(name, r)));
36
+ }
37
+ const SEV_ORDER = { error: 3, warn: 2, info: 1 };
38
+ export function worstSeverity(rules) {
39
+ if (rules.length === 0)
40
+ return null;
41
+ return rules.reduce((a, b) => (SEV_ORDER[b.severity] > SEV_ORDER[a.severity] ? b : a)).severity;
42
+ }
43
+ export function scanAllMovements(movements, parts = [...CONTRA_PARTS]) {
44
+ const hits = [];
45
+ for (const m of movements) {
46
+ const name = m.name ?? '';
47
+ const safe = isSafeVariant(name);
48
+ for (const [i, part] of parts.entries()) {
49
+ void i;
50
+ for (const rule of scanMovement(name, parts)[parts.indexOf(part)]) {
51
+ hits.push({ movementName: name, part, ruleName: rule.name, severity: rule.severity, reason: rule.reason, usedIn: [], safeVariant: safe });
52
+ }
53
+ }
54
+ }
55
+ return hits;
56
+ }
57
+ export function scanPlan(db, part = 'all') {
58
+ const parts = part === 'all' ? [...CONTRA_PARTS] : [part];
59
+ const plansRaw = db.prepare('SELECT week_number AS wn, day_of_week AS dow, session_index AS si, session_label AS label, movements AS movs FROM workout_plans ORDER BY week_number, day_of_week, session_index').all();
60
+ const plans = plansRaw.map((r) => [r.wn, r.dow, r.si, r.label, r.movs]);
61
+ const hits = [];
62
+ const byMovement = new Map();
63
+ let movementCount = 0;
64
+ let safeSkipped = 0;
65
+ for (const p of plans) {
66
+ const movements = JSON.parse(p[4] || '[]');
67
+ const usage = 'W' + p[0] + 'D' + p[1] + '(' + p[3] + ')';
68
+ for (const m of movements) {
69
+ movementCount += 1;
70
+ const name = m.name ?? '';
71
+ const safe = isSafeVariant(name);
72
+ for (const [pi, ppart] of parts.entries()) {
73
+ void pi;
74
+ for (const rule of scanMovement(name, parts)[parts.indexOf(ppart)]) {
75
+ const hit = { movementName: name, part: ppart, ruleName: rule.name, severity: rule.severity, reason: rule.reason, usedIn: [usage], safeVariant: safe };
76
+ if (hit.safeVariant) {
77
+ safeSkipped += 1;
78
+ continue;
79
+ }
80
+ hits.push(hit);
81
+ if (!byMovement.has(name))
82
+ byMovement.set(name, []);
83
+ byMovement.get(name).push(hit);
84
+ }
85
+ }
86
+ }
87
+ }
88
+ const bySeverity = { error: 0, warn: 0, info: 0 };
89
+ for (const h of hits)
90
+ bySeverity[h.severity] += 1;
91
+ const byMovementSummary = {};
92
+ for (const [name, list] of byMovement) {
93
+ const usedIn = [...new Set(list.flatMap((h) => h.usedIn))].sort();
94
+ const rules = [...new Set(list.map((h) => h.ruleName))].sort();
95
+ const sevList = list.map((h) => ({ severity: h.severity }));
96
+ byMovementSummary[name] = {
97
+ count: list.length,
98
+ severity: (worstSeverity(sevList) ?? 'info'),
99
+ rules,
100
+ usedIn,
101
+ parts: [...new Set(list.map((h) => h.part))].sort(),
102
+ };
103
+ }
104
+ const status = bySeverity.error > 0 ? 'fail' : bySeverity.warn > 0 ? 'warn' : 'ok';
105
+ const suggestions = [];
106
+ const seen = new Set();
107
+ for (const hit of hits) {
108
+ if (seen.has(hit.movementName) || hit.safeVariant)
109
+ continue;
110
+ seen.add(hit.movementName);
111
+ suggestions.push({
112
+ movement: hit.movementName,
113
+ rule: hit.ruleName,
114
+ reason: hit.reason,
115
+ replace: '用含 ' + SAFE_VARIANTS.slice(0, 3).join('/') + ' 等关键字的安全变体',
116
+ safeExamples: SAFE_VARIANTS.slice(0, 4),
117
+ });
118
+ }
119
+ return { scannedSessions: plans.length, scannedMovements: movementCount, scannedParts: parts, safeSkipped, hits, byMovement: byMovementSummary, bySeverity, summaryStatus: status, suggestions };
120
+ }
121
+ //# sourceMappingURL=contraindications.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contraindications.js","sourceRoot":"","sources":["../../src/analysis/contraindications.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /** T5 #24 · 跨表组合分析(对照老家 scripts/analysis/cross.py A1/A5)。
2
+ *
3
+ * analyzePair(series, pair, db?):11 配对(PAIRS 表原样);db 仅 exercise/waist
4
+ * 分层取证用(不传则 extra 记不可用,不断言空)。pair 非法即抛。
5
+ * 系列键为 DaySeries 驼峰(_strat 的 a/b 字段名做映射)。
6
+ */
7
+ import type { DatabaseSync } from 'node:sqlite';
8
+ import type { DaySeries } from './series.js';
9
+ export declare const PAIRS: Record<string, [string, string, string, string, string]>;
10
+ export type PairName = keyof typeof PAIRS;
11
+ export declare function pearson(pairs: Array<[number, number]>): number | null;
12
+ export declare function linearRegression(pairs: Array<[number, number]>): {
13
+ slope: number;
14
+ intercept: number;
15
+ n: number;
16
+ } | null;
17
+ export interface StratRow {
18
+ label: string;
19
+ days: number;
20
+ aDelta: number | null;
21
+ bAvg: number | null;
22
+ note: string;
23
+ }
24
+ export interface Strat {
25
+ rows: StratRow[];
26
+ extra: string[];
27
+ }
28
+ export interface PairAnalysis {
29
+ pair: string;
30
+ labels: {
31
+ a: string;
32
+ b: string;
33
+ };
34
+ window: string;
35
+ start: string | null;
36
+ end: string | null;
37
+ days: number;
38
+ aAvg: number | null;
39
+ bAvg: number | null;
40
+ aDelta: number | null;
41
+ bDelta: number | null;
42
+ aCount: number;
43
+ bCount: number;
44
+ line: Array<{
45
+ date: string;
46
+ a: number | null;
47
+ b: number | null;
48
+ }>;
49
+ scatter: Array<{
50
+ x: number;
51
+ y: number;
52
+ }>;
53
+ overLimitDays: string[];
54
+ deficitBuckets: Array<{
55
+ label: string;
56
+ days: number;
57
+ }>;
58
+ correlation: {
59
+ r: number | null;
60
+ n: number;
61
+ };
62
+ regression: {
63
+ slope: number;
64
+ intercept: number;
65
+ n: number;
66
+ } | null;
67
+ lag: Array<{
68
+ lag: number;
69
+ r: number | null;
70
+ }>;
71
+ strat: Strat;
72
+ insight: string;
73
+ }
74
+ export declare function analyzePair(series: DaySeries[], pair: string, db?: DatabaseSync, window?: string): PairAnalysis;
75
+ //# sourceMappingURL=cross.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross.d.ts","sourceRoot":"","sources":["../../src/analysis/cross.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,283 @@
1
+ import { FetchError } from '../fetch/errors.js';
2
+ const round = (n) => Math.round(n);
3
+ const round2 = (n) => Math.round(n * 100) / 100;
4
+ const round3 = (n) => Math.round(n * 1000) / 1000;
5
+ const round4 = (n) => Math.round(n * 10000) / 10000;
6
+ export const PAIRS = {
7
+ weight_calorie: ['weightKg', 'calories', '体重(kg)', '摄入(卡)', 'weekday'],
8
+ weight_exercise: ['weightKg', 'exerciseKcal', '体重(kg)', '运动消耗(卡)', 'exercise'],
9
+ weight_protein: ['weightKg', 'protein', '体重(kg)', '蛋白摄入(g)', 'protein'],
10
+ weight_deficit: ['weightKg', 'deficit', '体重(kg)', '热量缺口(卡)', 'deficit'],
11
+ calorie_exercise: ['calories', 'exerciseKcal', '摄入(卡)', '运动消耗(卡)', 'deficit_src'],
12
+ weight_bodyfat: ['weightKg', 'bodyFatPct', '体重(kg)', '体脂率(%)', 'divergence'],
13
+ weight_waist: ['weightKg', 'waistCm', '体重(kg)', '腰围(cm)', 'waist_divergence'],
14
+ water_weight: ['waterMl', 'weightKg', '饮水(ml)', '体重(kg)', 'water'],
15
+ protein_carbs: ['protein', 'carbs', '蛋白(g)', '碳水(g)', 'ratio'],
16
+ protein_fat: ['protein', 'fat', '蛋白(g)', '脂肪(g)', 'ratio'],
17
+ carbs_fat: ['carbs', 'fat', '碳水(g)', '脂肪(g)', 'ratio'],
18
+ };
19
+ export function pearson(pairs) {
20
+ const n = pairs.length;
21
+ if (n < 2)
22
+ return null;
23
+ let sx = 0, sy = 0, sxy = 0, sx2 = 0, sy2 = 0;
24
+ for (const [x, y] of pairs) {
25
+ sx += x;
26
+ sy += y;
27
+ sxy += x * y;
28
+ sx2 += x * x;
29
+ sy2 += y * y;
30
+ }
31
+ const denom = Math.sqrt((n * sx2 - sx * sx) * (n * sy2 - sy * sy));
32
+ if (denom === 0)
33
+ return null;
34
+ return round3(Math.max(-1, Math.min(1, (n * sxy - sx * sy) / denom)));
35
+ }
36
+ export function linearRegression(pairs) {
37
+ const n = pairs.length;
38
+ if (n < 2)
39
+ return null;
40
+ let sx = 0, sy = 0, sxy = 0, sx2 = 0;
41
+ for (const [x, y] of pairs) {
42
+ sx += x;
43
+ sy += y;
44
+ sxy += x * y;
45
+ sx2 += x * x;
46
+ }
47
+ const denom = n * sx2 - sx * sx;
48
+ if (denom === 0)
49
+ return null;
50
+ const slope = (n * sxy - sx * sy) / denom;
51
+ return { slope: round4(slope), intercept: round2((sy - slope * sx) / n), n };
52
+ }
53
+ function val(s, f) {
54
+ const v = s[f];
55
+ return typeof v === 'number' ? v : null;
56
+ }
57
+ function delta(vals) {
58
+ if (vals.length < 2)
59
+ return null;
60
+ return round2(vals[vals.length - 1] - vals[0]);
61
+ }
62
+ function weekdayOf(iso) {
63
+ return new Date(iso + 'T12:00:00Z').getUTCDay();
64
+ }
65
+ function strat(series, mode, a, b, db) {
66
+ const rows = [];
67
+ const extra = [];
68
+ const mk = (label, rowsIn) => {
69
+ const av = rowsIn.map((s) => val(s, a)).filter((v) => v !== null);
70
+ const bv = rowsIn.map((s) => val(s, b)).filter((v) => v !== null);
71
+ return { label, days: rowsIn.length, aDelta: delta(av), bAvg: bv.length > 0 ? round1(bv.reduce((x, y) => x + y, 0) / bv.length) : null, note: '' };
72
+ };
73
+ const round1 = (n) => Math.round(n * 10) / 10;
74
+ if (mode === 'weekday' || mode === 'exercise' || mode === 'protein' || mode === 'deficit' || mode === 'water') {
75
+ const cond = [];
76
+ const non = [];
77
+ for (const s of series) {
78
+ let isCond = false;
79
+ if (mode === 'weekday')
80
+ isCond = weekdayOf(s.date) >= 1 && weekdayOf(s.date) <= 5;
81
+ else if (mode === 'exercise')
82
+ isCond = (s.exerciseKcal ?? 0) > 0;
83
+ else if (mode === 'protein')
84
+ isCond = (s.protein ?? 0) >= ((s.calorieGoal ?? 0) / 10) * 0.4;
85
+ else if (mode === 'deficit')
86
+ isCond = (s.deficit ?? 0) > 0;
87
+ else if (mode === 'water')
88
+ isCond = (s.waterMl ?? 0) >= (s.waterGoal ?? 2000);
89
+ if (val(s, a) === null)
90
+ continue;
91
+ (isCond ? cond : non).push(s);
92
+ }
93
+ const labels = { weekday: ['工作日', '周末'], exercise: ['运动日', '休息日'], protein: ['蛋白达标日', '未达标日'], deficit: ['有缺口日', '无缺口日'], water: ['饮水达标日', '未达标日'] };
94
+ const [l0, l1] = labels[mode];
95
+ rows.push(mk(l0, cond), mk(l1, non));
96
+ const d1 = rows[0]?.aDelta ?? 0;
97
+ const d2 = rows[1]?.aDelta ?? 0;
98
+ if ((rows[0]?.days ?? 0) > 0 && (rows[1]?.days ?? 0) > 0 && Math.abs(d1 - d2) > 0.2) {
99
+ rows[0].note = 'Δ差异 ' + (d1 - d2 >= 0 ? '+' : '') + round2(d1 - d2).toFixed(2);
100
+ rows[1].note = 'Δ差异 ' + (d2 - d1 >= 0 ? '+' : '') + round2(d2 - d1).toFixed(2);
101
+ }
102
+ if (mode === 'exercise') {
103
+ if (db && series.length > 0) {
104
+ try {
105
+ const start = series[0].date;
106
+ const end = series[series.length - 1].date;
107
+ const st = db.prepare("SELECT SUM(calories_burned) AS v FROM exercise_log WHERE date BETWEEN ? AND ? AND category = '力量'").get(start, end);
108
+ const ca = db.prepare("SELECT SUM(calories_burned) AS v FROM exercise_log WHERE date BETWEEN ? AND ? AND category = '有氧'").get(start, end);
109
+ extra.push('力量消耗合计 ' + round(st.v ?? 0) + ' 卡 vs 有氧 ' + round(ca.v ?? 0) + ' 卡');
110
+ }
111
+ catch (e) {
112
+ extra.push('力量/有氧分层不可用: ' + e.message);
113
+ }
114
+ }
115
+ else
116
+ extra.push('力量/有氧分层不可用: 缺 db');
117
+ }
118
+ }
119
+ else if (mode === 'deficit_src') {
120
+ const cal = series.map((s) => s.calories).filter((v) => v !== null && v !== undefined);
121
+ const ex = series.map((s) => s.exerciseKcal).filter((v) => v !== null && v !== undefined);
122
+ const tdee = series.length > 0 ? series[0].tdee : null;
123
+ const calAvg = cal.length > 0 ? round1(cal.reduce((x, y) => x + y, 0) / cal.length) : null;
124
+ const exAvg = ex.length > 0 ? round1(ex.reduce((x, y) => x + y, 0) / ex.length) : null;
125
+ rows.push({ label: '日均摄入', days: cal.length, aDelta: null, bAvg: calAvg, note: '' });
126
+ rows.push({ label: '日均运动', days: ex.length, aDelta: null, bAvg: exAvg, note: '' });
127
+ if (calAvg !== null && tdee !== null && tdee !== undefined) {
128
+ extra.push('缺口构成:(TDEE ' + tdee + ' + 运动 ' + (exAvg ?? 0) + ') − 摄入 ' + calAvg + ' = 日均缺口 ' + (tdee + (exAvg ?? 0) - calAvg >= 0 ? '+' : '') + round(tdee + (exAvg ?? 0) - calAvg) + ' 卡');
129
+ }
130
+ }
131
+ else if (mode === 'divergence') {
132
+ const wv = series.map((s) => s.weightKg).filter((v) => v !== null && v !== undefined);
133
+ const bv = series.map((s) => s.bodyFatPct).filter((v) => v !== null && v !== undefined);
134
+ const wDelta = delta(wv);
135
+ const bDelta = delta(bv);
136
+ extra.push(wDelta !== null && bDelta !== null ? '体重净变化 ' + (wDelta >= 0 ? '+' : '') + wDelta.toFixed(2) + ' kg;体脂净变化 ' + (bDelta >= 0 ? '+' : '') + bDelta.toFixed(2) + ' 个百分点' : '体重/体脂样本不足,无法背离检测');
137
+ if (wDelta !== null && bDelta !== null) {
138
+ extra.push(wDelta < -0.3 && bDelta > -0.5 ? '⚠️ 背离:体重降但体脂未同步降,警惕肌肉流失' : '体重与体脂同向变化,脂肪确实在减少');
139
+ }
140
+ }
141
+ else if (mode === 'waist_divergence') {
142
+ const wv = series.map((s) => s.weightKg).filter((v) => v !== null && v !== undefined);
143
+ const wDelta = delta(wv);
144
+ extra.push(wDelta !== null ? '体重净变化 ' + (wDelta >= 0 ? '+' : '') + wDelta.toFixed(2) + ' kg' : '体重样本不足');
145
+ const cols = [['chest_cm', '胸围'], ['waist_cm', '腰围'], ['abdomen_cm', '腹围'], ['hip_cm', '臀围'], ['shoulder_cm', '肩围'], ['left_thigh_cm', '左大腿'], ['right_thigh_cm', '右大腿'], ['left_calf_cm', '左小腿'], ['right_calf_cm', '右小腿'], ['left_arm_cm', '左上臂'], ['right_arm_cm', '右上臂'], ['left_forearm_cm', '左前臂'], ['right_forearm_cm', '右前臂']];
146
+ if (db && series.length > 0) {
147
+ try {
148
+ const start = series[0].date;
149
+ const end = series[series.length - 1].date;
150
+ const deltas = [];
151
+ for (const [col, label] of cols) {
152
+ const first = db.prepare('SELECT ' + col + ' AS v FROM body_measurements WHERE date BETWEEN ? AND ? AND ' + col + ' IS NOT NULL AND is_deprecated = 0 ORDER BY date, id LIMIT 1').get(start, end);
153
+ const last = db.prepare('SELECT ' + col + ' AS v FROM body_measurements WHERE date BETWEEN ? AND ? AND ' + col + ' IS NOT NULL AND is_deprecated = 0 ORDER BY date DESC, id DESC LIMIT 1').get(start, end);
154
+ if (first?.v !== null && first?.v !== undefined && last?.v !== null && last?.v !== undefined) {
155
+ deltas.push([label, round1(last.v - first.v)]);
156
+ }
157
+ }
158
+ deltas.sort((a, b) => Math.abs(b[1]) - Math.abs(a[1]));
159
+ extra.push('各部位变化 TOP:' + (deltas.length > 0 ? deltas.slice(0, 3).map(([n, d]) => n + ' ' + (d >= 0 ? '+' : '') + d.toFixed(1) + 'cm').join('、') : '窗口内无围度数据'));
160
+ }
161
+ catch (e) {
162
+ extra.push('围度明细不可用: ' + e.message);
163
+ }
164
+ }
165
+ else
166
+ extra.push('围度明细不可用: 缺 db');
167
+ }
168
+ else if (mode === 'ratio') {
169
+ const ab = series.filter((s) => s.protein !== null || s.carbs !== null || s.fat !== null).map((s) => [s.protein ?? 0, s.carbs ?? 0, s.fat ?? 0]);
170
+ if (ab.length >= 4) {
171
+ const half = Math.floor(ab.length / 2);
172
+ const ratio = (rowsIn) => {
173
+ const p = rowsIn.reduce((a, r) => a + r[0], 0) || 1;
174
+ return '蛋白' + round(rowsIn.reduce((a, r) => a + r[0], 0) / p * 100) + '% 碳水' + round(rowsIn.reduce((a, r) => a + r[1], 0) / p * 100) + '% 脂肪' + round(rowsIn.reduce((a, r) => a + r[2], 0) / p * 100) + '%';
175
+ };
176
+ extra.push('前段占比:' + ratio(ab.slice(0, half)));
177
+ extra.push('后段占比:' + ratio(ab.slice(half)));
178
+ }
179
+ }
180
+ return { rows, extra };
181
+ }
182
+ function insight(pair, r, lag, st, days) {
183
+ const bLabel = PAIRS[pair][3];
184
+ if (r === null)
185
+ return '数据不足,无法判断“' + bLabel + '”与目标指标的关联。';
186
+ const strength = Math.abs(r) >= 0.5 ? '强' : Math.abs(r) >= 0.3 ? '中' : '弱';
187
+ const direction = r > 0 ? '正相关' : '负相关';
188
+ let line = strength + direction + '(r=' + (r >= 0 ? '+' : '') + r.toFixed(2) + ')';
189
+ if (pair === 'weight_calorie' && lag.length > 0) {
190
+ const best = lag.reduce((a, b) => Math.abs(b.r ?? 0) > Math.abs(a.r ?? 0) ? b : a);
191
+ if (best.r !== null && Math.abs(best.r) > Math.abs(r)) {
192
+ line += ';滞后 ' + best.lag + ' 天相关性更强(r=' + (best.r >= 0 ? '+' : '') + best.r.toFixed(2) + ')';
193
+ }
194
+ }
195
+ const ext = st.extra.join('\n');
196
+ if (ext.includes('背离'))
197
+ line += ';⚠️ 体重与体脂/围度存在背离信号';
198
+ if (ext.includes('⚠️ 背离'))
199
+ line += ';⚠️ 体重降但体脂未同步降,警惕肌肉流失';
200
+ return '窗口内共 ' + days + ' 天,' + bLabel + '与目标指标呈' + line + '。';
201
+ }
202
+ export function analyzePair(series, pair, db, window = '30d') {
203
+ if (!(pair in PAIRS))
204
+ throw new FetchError('未知配对 ' + pair + ',可选: ' + Object.keys(PAIRS).join(', '));
205
+ const [fa, fb, la, lb, mode] = PAIRS[pair];
206
+ const line = series.filter((s) => val(s, fa) !== null || val(s, fb) !== null).map((s) => ({ date: s.date, a: val(s, fa), b: val(s, fb) }));
207
+ const alignedPairs = [];
208
+ for (const s of series) {
209
+ const a = val(s, fa);
210
+ const b = val(s, fb);
211
+ if (a !== null && b !== null)
212
+ alignedPairs.push([a, b]);
213
+ }
214
+ const r = pearson(alignedPairs);
215
+ const reg = linearRegression(alignedPairs);
216
+ const lag = [];
217
+ if (pair === 'weight_calorie' || pair === 'weight_exercise' || pair === 'weight_protein') {
218
+ for (const l of [1, 2, 3]) {
219
+ const pairs = [];
220
+ for (let i = l; i < series.length; i++) {
221
+ const a = val(series[i], fa);
222
+ const b = val(series[i - l], fb);
223
+ if (a !== null && b !== null)
224
+ pairs.push([a, b]);
225
+ }
226
+ lag.push({ lag: l, r: pearson(pairs) });
227
+ }
228
+ }
229
+ const st = strat(series, mode, fa, fb, db);
230
+ let overLimitDays = [];
231
+ if (pair === 'weight_calorie' && series.length > 0) {
232
+ const goal = series[0].calorieGoal ?? 1800;
233
+ overLimitDays = series.filter((s) => s.calories !== null && s.calories !== undefined && s.calories > goal * 1.3).map((s) => s.date);
234
+ }
235
+ const deficitBuckets = [];
236
+ if (pair === 'weight_deficit') {
237
+ const buckets = { '深缺口(>500卡)': 0, '标准缺口(100~500)': 0, '小幅盈余(-100~100)': 0, '盈余(<-100)': 0 };
238
+ for (const s of series) {
239
+ const d = s.deficit;
240
+ if (d === null || d === undefined)
241
+ continue;
242
+ if (d > 500)
243
+ buckets['深缺口(>500卡)'] = buckets['深缺口(>500卡)'] + 1;
244
+ else if (d > 100)
245
+ buckets['标准缺口(100~500)'] = buckets['标准缺口(100~500)'] + 1;
246
+ else if (d >= -100)
247
+ buckets['小幅盈余(-100~100)'] = buckets['小幅盈余(-100~100)'] + 1;
248
+ else
249
+ buckets['盈余(<-100)'] = buckets['盈余(<-100)'] + 1;
250
+ }
251
+ for (const [label, days] of Object.entries(buckets)) {
252
+ if (days > 0)
253
+ deficitBuckets.push({ label, days });
254
+ }
255
+ }
256
+ const av = series.map((s) => val(s, fa)).filter((v) => v !== null);
257
+ const bv = series.map((s) => val(s, fb)).filter((v) => v !== null);
258
+ const avg = (xs) => xs.length > 0 ? round2(xs.reduce((a, b) => a + b, 0) / xs.length) : null;
259
+ return {
260
+ pair,
261
+ labels: { a: la, b: lb },
262
+ window,
263
+ start: series.length > 0 ? series[0].date : null,
264
+ end: series.length > 0 ? series[series.length - 1].date : null,
265
+ days: series.length,
266
+ aAvg: avg(av),
267
+ bAvg: avg(bv),
268
+ aDelta: delta(av),
269
+ bDelta: delta(bv),
270
+ aCount: av.length,
271
+ bCount: bv.length,
272
+ line,
273
+ scatter: alignedPairs.map(([x, y]) => ({ x, y })),
274
+ overLimitDays,
275
+ deficitBuckets,
276
+ correlation: { r, n: alignedPairs.length },
277
+ regression: reg,
278
+ lag,
279
+ strat: st,
280
+ insight: insight(pair, r, lag, st, series.length),
281
+ };
282
+ }
283
+ //# sourceMappingURL=cross.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross.js","sourceRoot":"","sources":["../../src/analysis/cross.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /** T5 #24 · 综合健康报告 4 维度(对照老家 scripts/analysis/dashboard.py)。
2
+ *
3
+ * weight/calorie/exercise/deficit 四维独立 try/except(单维失败记 error 不
4
+ * 掀整单);任一 error → 总 status warn。单日 dashboard 时 weight.changeKg
5
+ * 改取“今日首条 − 昨日首条”(老家 2026-07-31 fix,原同日首尾差误导)。
6
+ */
7
+ import type { DatabaseSync } from 'node:sqlite';
8
+ import type { AnalysisResult } from './result.js';
9
+ export interface HealthDashboard {
10
+ start: string;
11
+ end: string;
12
+ weight: unknown;
13
+ calorie: unknown;
14
+ exercise: unknown;
15
+ deficit: unknown;
16
+ }
17
+ export declare function healthDashboard(db: DatabaseSync, startDate: string, endDate?: string | null): AnalysisResult<HealthDashboard>;
18
+ //# sourceMappingURL=dashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/analysis/dashboard.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAMhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAUD,wBAAgB,eAAe,CAAC,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAAC,eAAe,CAAC,CAgC7H"}
@@ -0,0 +1,48 @@
1
+ import { dietCalorieTrend, dietDeficitAnalysis } from './diet.js';
2
+ import { exerciseTrend } from './exercise.js';
3
+ import { weightTrend } from './weight.js';
4
+ import { parseDate, shiftISODate } from './utils.js';
5
+ import { FetchError } from '../fetch/errors.js';
6
+ function safe(fn) {
7
+ try {
8
+ return fn();
9
+ }
10
+ catch (e) {
11
+ return { status: 'error', data: null, message: e instanceof Error ? e.message : String(e) };
12
+ }
13
+ }
14
+ export function healthDashboard(db, startDate, endDate) {
15
+ const start = parseDate(startDate);
16
+ if (!start)
17
+ throw new FetchError('起始日期非法: ' + String(startDate));
18
+ const end = parseDate(endDate ?? undefined) ?? start;
19
+ const dims = {
20
+ weight: safe(() => weightTrend(db, start, end)),
21
+ calorie: safe(() => dietCalorieTrend(db, start, end)),
22
+ exercise: safe(() => exerciseTrend(db, start, end)),
23
+ deficit: safe(() => dietDeficitAnalysis(db, start, end)),
24
+ };
25
+ const weight = dims['weight'];
26
+ if (start === end && weight.status === 'ok' && weight.data && weight.data.firstWeight !== null && weight.data.firstWeight !== undefined) {
27
+ const yesterday = shiftISODate(start, -1);
28
+ const yest = safe(() => weightTrend(db, yesterday, yesterday));
29
+ const ydata = yest.data;
30
+ if (yest.status === 'ok' && ydata && ydata.firstWeight !== null && ydata.firstWeight !== undefined) {
31
+ weight.data.changeKg = Math.round((weight.data.firstWeight - ydata.firstWeight) * 10) / 10;
32
+ }
33
+ }
34
+ const overall = Object.values(dims).some((d) => d.status === 'error') ? 'warn' : 'ok';
35
+ return {
36
+ status: overall,
37
+ data: {
38
+ start,
39
+ end,
40
+ weight: dims['weight'].data,
41
+ calorie: dims['calorie'].data,
42
+ exercise: dims['exercise'].data,
43
+ deficit: dims['deficit'].data,
44
+ },
45
+ message: '健康报告 ' + start + ' ~ ' + end,
46
+ };
47
+ }
48
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/analysis/dashboard.ts"],"names":[],"mappings":"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"}