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.
- package/dist/analysis/anomaly/common.d.ts +53 -0
- package/dist/analysis/anomaly/common.d.ts.map +1 -0
- package/dist/analysis/anomaly/common.js +69 -0
- package/dist/analysis/anomaly/common.js.map +1 -0
- package/dist/analysis/anomaly/diet.d.ts +8 -0
- package/dist/analysis/anomaly/diet.d.ts.map +1 -0
- package/dist/analysis/anomaly/diet.js +95 -0
- package/dist/analysis/anomaly/diet.js.map +1 -0
- package/dist/analysis/anomaly/exercise.d.ts +9 -0
- package/dist/analysis/anomaly/exercise.d.ts.map +1 -0
- package/dist/analysis/anomaly/exercise.js +116 -0
- package/dist/analysis/anomaly/exercise.js.map +1 -0
- package/dist/analysis/anomaly/index.d.ts +19 -0
- package/dist/analysis/anomaly/index.d.ts.map +1 -0
- package/dist/analysis/anomaly/index.js +51 -0
- package/dist/analysis/anomaly/index.js.map +1 -0
- package/dist/analysis/anomaly/overall.d.ts +13 -0
- package/dist/analysis/anomaly/overall.d.ts.map +1 -0
- package/dist/analysis/anomaly/overall.js +128 -0
- package/dist/analysis/anomaly/overall.js.map +1 -0
- package/dist/analysis/anomaly/overall2.d.ts +5 -0
- package/dist/analysis/anomaly/overall2.d.ts.map +1 -0
- package/dist/analysis/anomaly/overall2.js +94 -0
- package/dist/analysis/anomaly/overall2.js.map +1 -0
- package/dist/analysis/anomaly/weight.d.ts +8 -0
- package/dist/analysis/anomaly/weight.d.ts.map +1 -0
- package/dist/analysis/anomaly/weight.js +106 -0
- package/dist/analysis/anomaly/weight.js.map +1 -0
- package/dist/analysis/anomaly/weight2.d.ts +4 -0
- package/dist/analysis/anomaly/weight2.d.ts.map +1 -0
- package/dist/analysis/anomaly/weight2.js +59 -0
- package/dist/analysis/anomaly/weight2.js.map +1 -0
- package/dist/analysis/contraindications.d.ts +63 -0
- package/dist/analysis/contraindications.d.ts.map +1 -0
- package/dist/analysis/contraindications.js +121 -0
- package/dist/analysis/contraindications.js.map +1 -0
- package/dist/analysis/cross.d.ts +75 -0
- package/dist/analysis/cross.d.ts.map +1 -0
- package/dist/analysis/cross.js +283 -0
- package/dist/analysis/cross.js.map +1 -0
- package/dist/analysis/dashboard.d.ts +18 -0
- package/dist/analysis/dashboard.d.ts.map +1 -0
- package/dist/analysis/dashboard.js +48 -0
- package/dist/analysis/dashboard.js.map +1 -0
- package/dist/analysis/deficit.d.ts +44 -0
- package/dist/analysis/deficit.d.ts.map +1 -0
- package/dist/analysis/deficit.js +54 -0
- package/dist/analysis/deficit.js.map +1 -0
- package/dist/analysis/diet.d.ts +76 -0
- package/dist/analysis/diet.d.ts.map +1 -0
- package/dist/analysis/diet.js +164 -0
- package/dist/analysis/diet.js.map +1 -0
- package/dist/analysis/exercise.d.ts +98 -0
- package/dist/analysis/exercise.d.ts.map +1 -0
- package/dist/analysis/exercise.js +298 -0
- package/dist/analysis/exercise.js.map +1 -0
- package/dist/analysis/exerciseReview.d.ts +36 -0
- package/dist/analysis/exerciseReview.d.ts.map +1 -0
- package/dist/analysis/exerciseReview.js +50 -0
- package/dist/analysis/exerciseReview.js.map +1 -0
- package/dist/analysis/precision.d.ts +15 -0
- package/dist/analysis/precision.d.ts.map +1 -0
- package/dist/analysis/precision.js +38 -0
- package/dist/analysis/precision.js.map +1 -0
- package/dist/analysis/result.d.ts +15 -0
- package/dist/analysis/result.d.ts.map +1 -0
- package/dist/analysis/result.js +13 -0
- package/dist/analysis/result.js.map +1 -0
- package/dist/analysis/review.d.ts +118 -0
- package/dist/analysis/review.d.ts.map +1 -0
- package/dist/analysis/review.js +195 -0
- package/dist/analysis/review.js.map +1 -0
- package/dist/analysis/series.d.ts +42 -0
- package/dist/analysis/series.d.ts.map +1 -0
- package/dist/analysis/series.js +127 -0
- package/dist/analysis/series.js.map +1 -0
- package/dist/analysis/simulate.d.ts +43 -0
- package/dist/analysis/simulate.d.ts.map +1 -0
- package/dist/analysis/simulate.js +109 -0
- package/dist/analysis/simulate.js.map +1 -0
- package/dist/analysis/simulate2.d.ts +65 -0
- package/dist/analysis/simulate2.d.ts.map +1 -0
- package/dist/analysis/simulate2.js +173 -0
- package/dist/analysis/simulate2.js.map +1 -0
- package/dist/analysis/trend.d.ts +39 -0
- package/dist/analysis/trend.d.ts.map +1 -0
- package/dist/analysis/trend.js +48 -0
- package/dist/analysis/trend.js.map +1 -0
- package/dist/analysis/utils.d.ts +17 -0
- package/dist/analysis/utils.d.ts.map +1 -0
- package/dist/analysis/utils.js +52 -0
- package/dist/analysis/utils.js.map +1 -0
- package/dist/analysis/volatility.d.ts +43 -0
- package/dist/analysis/volatility.d.ts.map +1 -0
- package/dist/analysis/volatility.js +96 -0
- package/dist/analysis/volatility.js.map +1 -0
- package/dist/analysis/weight.d.ts +86 -0
- package/dist/analysis/weight.d.ts.map +1 -0
- package/dist/analysis/weight.js +219 -0
- package/dist/analysis/weight.js.map +1 -0
- package/dist/analysis/weightCompare.d.ts +63 -0
- package/dist/analysis/weightCompare.d.ts.map +1 -0
- package/dist/analysis/weightCompare.js +212 -0
- package/dist/analysis/weightCompare.js.map +1 -0
- package/dist/analysis/weightCompare2.d.ts +63 -0
- package/dist/analysis/weightCompare2.d.ts.map +1 -0
- package/dist/analysis/weightCompare2.js +211 -0
- package/dist/analysis/weightCompare2.js.map +1 -0
- package/dist/analysis/weightCompare3.d.ts +13 -0
- package/dist/analysis/weightCompare3.d.ts.map +1 -0
- package/dist/analysis/weightCompare3.js +199 -0
- package/dist/analysis/weightCompare3.js.map +1 -0
- package/dist/cli/cmd_read.d.ts +8 -0
- package/dist/cli/cmd_read.d.ts.map +1 -0
- package/dist/cli/cmd_read.js +719 -0
- package/dist/cli/cmd_read.js.map +1 -0
- package/dist/cli/keys.d.ts +333 -0
- package/dist/cli/keys.d.ts.map +1 -0
- package/dist/cli/keys.js +103 -0
- package/dist/cli/keys.js.map +1 -0
- package/dist/cli/write.d.ts +24 -0
- package/dist/cli/write.d.ts.map +1 -0
- package/dist/cli/write.js +832 -0
- package/dist/cli/write.js.map +1 -0
- package/dist/fetch/audit.d.ts +25 -0
- package/dist/fetch/audit.d.ts.map +1 -0
- package/dist/fetch/audit.js +46 -0
- package/dist/fetch/audit.js.map +1 -0
- package/dist/fetch/batch.d.ts +68 -0
- package/dist/fetch/batch.d.ts.map +1 -0
- package/dist/fetch/batch.js +183 -0
- package/dist/fetch/batch.js.map +1 -0
- package/dist/fetch/body.d.ts +89 -0
- package/dist/fetch/body.d.ts.map +1 -0
- package/dist/fetch/body.js +217 -0
- package/dist/fetch/body.js.map +1 -0
- package/dist/fetch/cli.d.ts +3 -0
- package/dist/fetch/cli.d.ts.map +1 -0
- package/dist/fetch/cli.js +195 -0
- package/dist/fetch/cli.js.map +1 -0
- package/dist/fetch/cross-skill.d.ts +29 -0
- package/dist/fetch/cross-skill.d.ts.map +1 -0
- package/dist/fetch/cross-skill.js +42 -0
- package/dist/fetch/cross-skill.js.map +1 -0
- package/dist/fetch/db.d.ts +5 -0
- package/dist/fetch/db.d.ts.map +1 -0
- package/dist/fetch/db.js +4 -0
- package/dist/fetch/db.js.map +1 -0
- package/dist/fetch/diet.d.ts +174 -0
- package/dist/fetch/diet.d.ts.map +1 -0
- package/dist/fetch/diet.js +239 -0
- package/dist/fetch/diet.js.map +1 -0
- package/dist/fetch/errors.d.ts +5 -0
- package/dist/fetch/errors.d.ts.map +1 -0
- package/dist/fetch/errors.js +8 -0
- package/dist/fetch/errors.js.map +1 -0
- package/dist/fetch/exercise.d.ts +72 -0
- package/dist/fetch/exercise.d.ts.map +1 -0
- package/dist/fetch/exercise.js +270 -0
- package/dist/fetch/exercise.js.map +1 -0
- package/dist/fetch/goal.d.ts +48 -0
- package/dist/fetch/goal.d.ts.map +1 -0
- package/dist/fetch/goal.js +73 -0
- package/dist/fetch/goal.js.map +1 -0
- package/dist/fetch/goalHistory.d.ts +24 -0
- package/dist/fetch/goalHistory.d.ts.map +1 -0
- package/dist/fetch/goalHistory.js +51 -0
- package/dist/fetch/goalHistory.js.map +1 -0
- package/dist/fetch/history.d.ts +28 -0
- package/dist/fetch/history.d.ts.map +1 -0
- package/dist/fetch/history.js +29 -0
- package/dist/fetch/history.js.map +1 -0
- package/dist/fetch/index.d.ts +23 -0
- package/dist/fetch/index.d.ts.map +1 -0
- package/dist/fetch/index.js +16 -0
- package/dist/fetch/index.js.map +1 -0
- package/dist/fetch/nutritionGoal.d.ts +115 -0
- package/dist/fetch/nutritionGoal.d.ts.map +1 -0
- package/dist/fetch/nutritionGoal.js +154 -0
- package/dist/fetch/nutritionGoal.js.map +1 -0
- package/dist/fetch/photos.d.ts +76 -0
- package/dist/fetch/photos.d.ts.map +1 -0
- package/dist/fetch/photos.js +193 -0
- package/dist/fetch/photos.js.map +1 -0
- package/dist/fetch/plan.d.ts +145 -0
- package/dist/fetch/plan.d.ts.map +1 -0
- package/dist/fetch/plan.js +258 -0
- package/dist/fetch/plan.js.map +1 -0
- package/dist/fetch/products.d.ts +62 -0
- package/dist/fetch/products.d.ts.map +1 -0
- package/dist/fetch/products.js +73 -0
- package/dist/fetch/products.js.map +1 -0
- package/dist/fetch/profile.d.ts +46 -0
- package/dist/fetch/profile.d.ts.map +1 -0
- package/dist/fetch/profile.js +105 -0
- package/dist/fetch/profile.js.map +1 -0
- package/dist/fetch/shapes.d.ts +41 -0
- package/dist/fetch/shapes.d.ts.map +1 -0
- package/dist/fetch/shapes.js +38 -0
- package/dist/fetch/shapes.js.map +1 -0
- package/dist/fetch/validate.d.ts +11 -0
- package/dist/fetch/validate.d.ts.map +1 -0
- package/dist/fetch/validate.js +64 -0
- package/dist/fetch/validate.js.map +1 -0
- package/dist/fetch/weight.d.ts +109 -0
- package/dist/fetch/weight.d.ts.map +1 -0
- package/dist/fetch/weight.js +210 -0
- package/dist/fetch/weight.js.map +1 -0
- package/dist/fetch/xunji-catalog.d.ts +17 -0
- package/dist/fetch/xunji-catalog.d.ts.map +1 -0
- package/dist/fetch/xunji-catalog.js +57 -0
- package/dist/fetch/xunji-catalog.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/kcal.d.ts +21 -0
- package/dist/kcal.d.ts.map +1 -0
- package/dist/kcal.js +27 -0
- package/dist/kcal.js.map +1 -0
- package/dist/migrate/migrate.d.ts +71 -0
- package/dist/migrate/migrate.d.ts.map +1 -0
- package/dist/migrate/migrate.js +450 -0
- package/dist/migrate/migrate.js.map +1 -0
- package/dist/paths.d.ts +6 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +34 -0
- package/dist/paths.js.map +1 -0
- package/dist/render/analysisPlate.d.ts +49 -0
- package/dist/render/analysisPlate.d.ts.map +1 -0
- package/dist/render/analysisPlate.js +149 -0
- package/dist/render/analysisPlate.js.map +1 -0
- package/dist/render/bodyPlate.d.ts +55 -0
- package/dist/render/bodyPlate.d.ts.map +1 -0
- package/dist/render/bodyPlate.js +97 -0
- package/dist/render/bodyPlate.js.map +1 -0
- package/dist/render/diet.d.ts +47 -0
- package/dist/render/diet.d.ts.map +1 -0
- package/dist/render/diet.js +94 -0
- package/dist/render/diet.js.map +1 -0
- package/dist/render/envelope.d.ts +60 -0
- package/dist/render/envelope.d.ts.map +1 -0
- package/dist/render/envelope.js +111 -0
- package/dist/render/envelope.js.map +1 -0
- package/dist/render/errors.d.ts +10 -0
- package/dist/render/errors.d.ts.map +1 -0
- package/dist/render/errors.js +9 -0
- package/dist/render/errors.js.map +1 -0
- package/dist/render/exercise.d.ts +20 -0
- package/dist/render/exercise.d.ts.map +1 -0
- package/dist/render/exercise.js +32 -0
- package/dist/render/exercise.js.map +1 -0
- package/dist/render/goal.d.ts +24 -0
- package/dist/render/goal.d.ts.map +1 -0
- package/dist/render/goal.js +23 -0
- package/dist/render/goal.js.map +1 -0
- package/dist/render/goalExtra.d.ts +45 -0
- package/dist/render/goalExtra.d.ts.map +1 -0
- package/dist/render/goalExtra.js +94 -0
- package/dist/render/goalExtra.js.map +1 -0
- package/dist/render/goalPlate.d.ts +66 -0
- package/dist/render/goalPlate.d.ts.map +1 -0
- package/dist/render/goalPlate.js +110 -0
- package/dist/render/goalPlate.js.map +1 -0
- package/dist/render/health.d.ts +21 -0
- package/dist/render/health.d.ts.map +1 -0
- package/dist/render/health.js +41 -0
- package/dist/render/health.js.map +1 -0
- package/dist/render/help.d.ts +18 -0
- package/dist/render/help.d.ts.map +1 -0
- package/dist/render/help.js +58 -0
- package/dist/render/help.js.map +1 -0
- package/dist/render/home.d.ts +30 -0
- package/dist/render/home.d.ts.map +1 -0
- package/dist/render/home.js +73 -0
- package/dist/render/home.js.map +1 -0
- package/dist/render/html.d.ts +66 -0
- package/dist/render/html.d.ts.map +1 -0
- package/dist/render/html.js +510 -0
- package/dist/render/html.js.map +1 -0
- package/dist/render/index.d.ts +47 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +26 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/insightPlate.d.ts +55 -0
- package/dist/render/insightPlate.d.ts.map +1 -0
- package/dist/render/insightPlate.js +97 -0
- package/dist/render/insightPlate.js.map +1 -0
- package/dist/render/library.d.ts +32 -0
- package/dist/render/library.d.ts.map +1 -0
- package/dist/render/library.js +54 -0
- package/dist/render/library.js.map +1 -0
- package/dist/render/photo.d.ts +101 -0
- package/dist/render/photo.d.ts.map +1 -0
- package/dist/render/photo.js +241 -0
- package/dist/render/photo.js.map +1 -0
- package/dist/render/planPlate.d.ts +40 -0
- package/dist/render/planPlate.d.ts.map +1 -0
- package/dist/render/planPlate.js +72 -0
- package/dist/render/planPlate.js.map +1 -0
- package/dist/render/profilePlate.d.ts +17 -0
- package/dist/render/profilePlate.d.ts.map +1 -0
- package/dist/render/profilePlate.js +18 -0
- package/dist/render/profilePlate.js.map +1 -0
- package/dist/render/ranking.d.ts +22 -0
- package/dist/render/ranking.d.ts.map +1 -0
- package/dist/render/ranking.js +63 -0
- package/dist/render/ranking.js.map +1 -0
- package/dist/render/receipt.d.ts +71 -0
- package/dist/render/receipt.d.ts.map +1 -0
- package/dist/render/receipt.js +65 -0
- package/dist/render/receipt.js.map +1 -0
- package/dist/render/weightPlate.d.ts +54 -0
- package/dist/render/weightPlate.d.ts.map +1 -0
- package/dist/render/weightPlate.js +110 -0
- package/dist/render/weightPlate.js.map +1 -0
- package/dist/schema.d.ts +25 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +281 -0
- package/dist/schema.js.map +1 -0
- package/dist/triggers/help-lookup.d.ts +28 -0
- package/dist/triggers/help-lookup.d.ts.map +1 -0
- package/dist/triggers/help-lookup.js +163 -0
- package/dist/triggers/help-lookup.js.map +1 -0
- package/dist/triggers/index.d.ts +24 -0
- package/dist/triggers/index.d.ts.map +1 -0
- package/dist/triggers/index.js +78 -0
- package/dist/triggers/index.js.map +1 -0
- package/dist/triggers/scene-01-home.d.ts +4 -0
- package/dist/triggers/scene-01-home.d.ts.map +1 -0
- package/dist/triggers/scene-01-home.js +13 -0
- package/dist/triggers/scene-01-home.js.map +1 -0
- package/dist/triggers/scene-02-diet.d.ts +4 -0
- package/dist/triggers/scene-02-diet.d.ts.map +1 -0
- package/dist/triggers/scene-02-diet.js +74 -0
- package/dist/triggers/scene-02-diet.js.map +1 -0
- package/dist/triggers/scene-03-weight.d.ts +4 -0
- package/dist/triggers/scene-03-weight.d.ts.map +1 -0
- package/dist/triggers/scene-03-weight.js +62 -0
- package/dist/triggers/scene-03-weight.js.map +1 -0
- package/dist/triggers/scene-04-exercise.d.ts +4 -0
- package/dist/triggers/scene-04-exercise.d.ts.map +1 -0
- package/dist/triggers/scene-04-exercise.js +43 -0
- package/dist/triggers/scene-04-exercise.js.map +1 -0
- package/dist/triggers/scene-05-workout.d.ts +4 -0
- package/dist/triggers/scene-05-workout.d.ts.map +1 -0
- package/dist/triggers/scene-05-workout.js +36 -0
- package/dist/triggers/scene-05-workout.js.map +1 -0
- package/dist/triggers/scene-06-goal.d.ts +4 -0
- package/dist/triggers/scene-06-goal.d.ts.map +1 -0
- package/dist/triggers/scene-06-goal.js +29 -0
- package/dist/triggers/scene-06-goal.js.map +1 -0
- package/dist/triggers/scene-07-profile.d.ts +4 -0
- package/dist/triggers/scene-07-profile.d.ts.map +1 -0
- package/dist/triggers/scene-07-profile.js +8 -0
- package/dist/triggers/scene-07-profile.js.map +1 -0
- package/dist/triggers/scene-08-body.d.ts +4 -0
- package/dist/triggers/scene-08-body.d.ts.map +1 -0
- package/dist/triggers/scene-08-body.js +17 -0
- package/dist/triggers/scene-08-body.js.map +1 -0
- package/dist/triggers/scene-09-photo.d.ts +4 -0
- package/dist/triggers/scene-09-photo.d.ts.map +1 -0
- package/dist/triggers/scene-09-photo.js +14 -0
- package/dist/triggers/scene-09-photo.js.map +1 -0
- package/dist/triggers/scene-10-analysis.d.ts +4 -0
- package/dist/triggers/scene-10-analysis.d.ts.map +1 -0
- package/dist/triggers/scene-10-analysis.js +180 -0
- package/dist/triggers/scene-10-analysis.js.map +1 -0
- package/dist/triggers/types.d.ts +66 -0
- package/dist/triggers/types.d.ts.map +1 -0
- package/dist/triggers/types.js +3 -0
- package/dist/triggers/types.js.map +1 -0
- package/package.json +35 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { base, daysBetween, degrade, MIN_DAYS, PRED_MIN, round, seriesAvg, seriesDelta, weightVals } from './common.js';
|
|
2
|
+
function commonOverall(series, kind, title) {
|
|
3
|
+
const out = base(series, kind, title);
|
|
4
|
+
const wv = weightVals(series);
|
|
5
|
+
const delta = seriesDelta(series, 'weightKg');
|
|
6
|
+
out.findings.push({
|
|
7
|
+
cause: '体重',
|
|
8
|
+
evidence: wv.length >= 2 ? wv[0] + '→' + wv[wv.length - 1] + ' kg(Δ' + (delta !== null && delta !== undefined && delta >= 0 ? '+' : '') + (delta ?? 0).toFixed(2) + ')' : '体重样本不足',
|
|
9
|
+
confidence: wv.length >= 2 ? '中' : '低',
|
|
10
|
+
action: '',
|
|
11
|
+
});
|
|
12
|
+
const avgCal = seriesAvg(series, 'calories');
|
|
13
|
+
const goal = series[0]?.calorieGoal;
|
|
14
|
+
if (avgCal) {
|
|
15
|
+
out.findings.push({ cause: '摄入', evidence: '日均 ' + avgCal + ' 卡 vs 目标 ' + goal + ' 卡(Δ' + (avgCal - (goal ?? 0) >= 0 ? '+' : '') + round(avgCal - (goal ?? 0)) + ')', confidence: '中', action: '' });
|
|
16
|
+
}
|
|
17
|
+
const ex = seriesAvg(series, 'exerciseKcal');
|
|
18
|
+
if (ex)
|
|
19
|
+
out.findings.push({ cause: '运动', evidence: '日均消耗 ' + ex + ' 卡', confidence: '中', action: '' });
|
|
20
|
+
const df = seriesAvg(series, 'deficit');
|
|
21
|
+
if (df)
|
|
22
|
+
out.findings.push({ cause: '缺口', evidence: '日均缺口 ' + (df >= 0 ? '+' : '') + round(df) + ' 卡(减重需要每日 +300~+500)', confidence: '中', action: '' });
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
function weeklyRate(series, out) {
|
|
26
|
+
const total = seriesDelta(series, 'weightKg') ?? 0;
|
|
27
|
+
const days = daysBetween(out.start, out.end) || 1;
|
|
28
|
+
return (total / days) * 7;
|
|
29
|
+
}
|
|
30
|
+
export function diagWhyNotLosing(series) {
|
|
31
|
+
const out = commonOverall(series, 'why_not_losing', '为什么我没瘦');
|
|
32
|
+
if (weightVals(series).length < MIN_DAYS)
|
|
33
|
+
return degrade(out, '体重数据不足,先连续记录 1 周以上再诊断。');
|
|
34
|
+
const df = seriesAvg(series, 'deficit');
|
|
35
|
+
if (df === null || df === undefined || df < 100) {
|
|
36
|
+
out.findings.push({ cause: '缺口不足或为负', evidence: '日均缺口 ' + (df !== null && df !== undefined && df >= 0 ? '+' : '') + round(df ?? 0) + ' 卡(减重需 +300~+500)', confidence: '高', action: '先恢复缺口:(TDEE + 运动) − 摄入 ≥ 300 卡。常见偷吃:液体热量/酱料/坚果' });
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
out.findings.push({ cause: '缺口存在但体重不动', evidence: '日均缺口 +' + round(df) + ' 卡', confidence: '中', action: '缺口存在仍不动:检查称重条件是否统一、是否在平台期(14 天 ±0.5kg)、是否水肿(高钠/经期)' });
|
|
40
|
+
}
|
|
41
|
+
out.findings.push({ cause: '优先级', evidence: '缺口 > 蛋白 > 运动 > 睡眠', confidence: '高', action: '按优先级逐项排查,别同时改 5 个变量' });
|
|
42
|
+
out.insight = '核心先看日均缺口是否真的为正;缺口为正仍不动再看平台期/水分。';
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
export function diagWhyLosingFast(series) {
|
|
46
|
+
const out = commonOverall(series, 'why_losing_fast', '为什么我瘦太快');
|
|
47
|
+
const wv = weightVals(series);
|
|
48
|
+
if (wv.length < PRED_MIN)
|
|
49
|
+
return degrade(out, '体重数据不足 14 天,无法评估速度。');
|
|
50
|
+
const rate = weeklyRate(series, out);
|
|
51
|
+
const mag = -rate;
|
|
52
|
+
out.findings.push({
|
|
53
|
+
cause: '减重速度',
|
|
54
|
+
evidence: (rate >= 0 ? '+' : '') + rate.toFixed(2) + ' kg/周(健康范围 0.5-1.0;>1.5 为过快)',
|
|
55
|
+
confidence: '高',
|
|
56
|
+
action: mag > 1.5 ? '⚠️ 每周 >1.5kg:多来自水分/肌肉流失,尽快上调摄入 200-300 卡,保蛋白 1.6g/kg' : '速度在健康范围,不必担心',
|
|
57
|
+
});
|
|
58
|
+
const avgCal = seriesAvg(series, 'calories');
|
|
59
|
+
const tdee = series[0].tdee;
|
|
60
|
+
if (avgCal && tdee && avgCal < tdee * 0.6) {
|
|
61
|
+
out.findings.push({ cause: '摄入过低', evidence: '日均摄入 ' + avgCal + ' 卡,仅为 TDEE(' + tdee + ')的 ' + round((avgCal / tdee) * 100) + '%', confidence: '中', action: '摄入低于 TDEE 60% 会掉代谢:逐步加回,每周 +100 卡' });
|
|
62
|
+
}
|
|
63
|
+
out.insight = '速度 ' + (rate >= 0 ? '+' : '') + rate.toFixed(2) + ' kg/周,' + (mag > 1.5 ? '过快,需要立即调整。' : '正常。');
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
export function diagRateReasonable(series) {
|
|
67
|
+
const out = commonOverall(series, 'rate_reasonable', '我的减重速度合理吗');
|
|
68
|
+
const wv = weightVals(series);
|
|
69
|
+
if (wv.length < PRED_MIN)
|
|
70
|
+
return degrade(out, '体重数据不足 14 天,无法评估速度。');
|
|
71
|
+
const rate = weeklyRate(series, out);
|
|
72
|
+
const mag = -rate;
|
|
73
|
+
const verdict = mag > 1.0 ? '偏快' : mag >= 0.5 ? '健康范围' : '偏慢';
|
|
74
|
+
const action = verdict === '偏快' ? '适当上调摄入,优先保住肌肉' : verdict === '健康范围' ? '保持当前节奏,规律记录即可' : '检查缺口是否 ≥300 卡,是否漏记了加餐';
|
|
75
|
+
out.findings.push({ cause: '速度判定', evidence: (rate >= 0 ? '+' : '') + rate.toFixed(2) + ' kg/周 → ' + verdict + '(健康范围 0.5-1.0 kg/周)', confidence: '高', action });
|
|
76
|
+
out.insight = '当前速度 ' + (rate >= 0 ? '+' : '') + rate.toFixed(2) + ' kg/周,判定为「' + verdict + '」。';
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
export function diagStrategyCheck(series) {
|
|
80
|
+
const out = commonOverall(series, 'strategy_check', '我的减肥策略对吗');
|
|
81
|
+
const wv = weightVals(series);
|
|
82
|
+
if (wv.length < PRED_MIN)
|
|
83
|
+
return degrade(out, '数据不足 14 天,策略评估先积累数据。');
|
|
84
|
+
const df = seriesAvg(series, 'deficit');
|
|
85
|
+
const p = seriesAvg(series, 'protein');
|
|
86
|
+
const ex = seriesAvg(series, 'exerciseKcal');
|
|
87
|
+
const checks = [];
|
|
88
|
+
if (df !== null && df !== undefined && df >= 100 && df <= 500)
|
|
89
|
+
checks.push('缺口策略合理');
|
|
90
|
+
else if (df !== null && df !== undefined && df > 800)
|
|
91
|
+
checks.push('⚠️ 缺口过大(>800 卡):可持续性差');
|
|
92
|
+
else
|
|
93
|
+
checks.push('⚠️ 缺口不足(需 +300~+500 卡)');
|
|
94
|
+
const weight = wv[wv.length - 1];
|
|
95
|
+
if (p && weight)
|
|
96
|
+
checks.push(p >= weight * 1.2 ? '蛋白达标' : '⚠️ 蛋白不足(建议 ≥1.2g/kg)');
|
|
97
|
+
checks.push(ex && ex > 0 ? '运动有贡献' : '⚠️ 纯靠饮食,建议加力量');
|
|
98
|
+
out.findings.push({ cause: '策略体检', evidence: checks.join(';'), confidence: '中', action: '对 ⚠️ 项逐一修正;减脂期最稳的公式:TDEE 以下 300-500 卡 + 蛋白足量 + 每周 2-3 次力量' });
|
|
99
|
+
const bad = checks.filter((c) => c.includes('⚠️')).map((c) => c.split('⚠️ ')[1]);
|
|
100
|
+
out.insight = bad.length === 0 ? '策略总体合理' : '存在 ' + bad.join('、') + ' 问题。';
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
export function diagGapToGoal(db, series) {
|
|
104
|
+
const out = commonOverall(series, 'gap_to_goal', '我距离目标还差什么');
|
|
105
|
+
const g = db.prepare('SELECT weight_goal, goal_deadline FROM daily_goal WHERE id = 1').get();
|
|
106
|
+
const wv = weightVals(series);
|
|
107
|
+
if (!g || g.weight_goal === null || g.weight_goal === undefined) {
|
|
108
|
+
out.findings.push({ cause: '目标未设置', evidence: '还没有体重目标', confidence: '高', action: '先定一个目标体重(建议先设最近 1-2 个月可达到的小目标)' });
|
|
109
|
+
out.insight = '先设置目标体重,再谈差距。';
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
112
|
+
const current = wv.length > 0 ? wv[wv.length - 1] : null;
|
|
113
|
+
if (current === null)
|
|
114
|
+
return degrade(out, '缺少近期体重记录。');
|
|
115
|
+
const gap = round((current - g.weight_goal) * 10) / 10;
|
|
116
|
+
const rate = weeklyRate(series, out);
|
|
117
|
+
// 有意偏离老家(同上):老家 `gap / weekly if weekly > 0` 在正常减重时恒回 None;此处减重中按 gap/|rate| 估算。
|
|
118
|
+
const weeksLeft = gap > 0 && rate < 0 ? gap / -rate : null;
|
|
119
|
+
out.findings.push({
|
|
120
|
+
cause: '目标差距',
|
|
121
|
+
evidence: '当前 ' + current + ' kg vs 目标 ' + g.weight_goal + ' kg,还差 ' + (gap >= 0 ? '+' : '') + gap.toFixed(1) + ' kg' + (weeksLeft ? ',按当前速度约需 ' + round(weeksLeft) + ' 周' : ',当前速度无法估算'),
|
|
122
|
+
confidence: '高',
|
|
123
|
+
action: '把大目标拆成每周 0.5kg 的小里程碑,每周只盯一个小目标',
|
|
124
|
+
});
|
|
125
|
+
out.insight = '距目标还差 ' + Math.abs(gap).toFixed(1) + ' kg。';
|
|
126
|
+
return out;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=overall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overall.js","sourceRoot":"","sources":["../../../src/analysis/anomaly/overall.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { DaySeries, Diagnosis } from './common.js';
|
|
2
|
+
export declare function diagMonthHighlights(series: DaySeries[]): Diagnosis;
|
|
3
|
+
export declare function diagMonthImprove(series: DaySeries[]): Diagnosis;
|
|
4
|
+
export declare function diagOverall(series: DaySeries[]): Diagnosis;
|
|
5
|
+
//# sourceMappingURL=overall2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overall2.d.ts","sourceRoot":"","sources":["../../../src/analysis/anomaly/overall2.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAuBxD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAgBlE;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAc/D;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAyB1D"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/** T5 #24 · 综合诊断续(月度亮点/改进/总体评估,对照老家 anomaly.py)。 */
|
|
2
|
+
import { base, MIN_DAYS, round, seriesAvg, seriesDelta, weightVals } from './common.js';
|
|
3
|
+
function commonOverall(series, kind, title) {
|
|
4
|
+
const out = base(series, kind, title);
|
|
5
|
+
const wv = weightVals(series);
|
|
6
|
+
const delta = seriesDelta(series, 'weightKg');
|
|
7
|
+
out.findings.push({
|
|
8
|
+
cause: '体重',
|
|
9
|
+
evidence: wv.length >= 2 ? wv[0] + '→' + wv[wv.length - 1] + ' kg(Δ' + (delta !== null && delta !== undefined && delta >= 0 ? '+' : '') + (delta ?? 0).toFixed(2) + ')' : '体重样本不足',
|
|
10
|
+
confidence: wv.length >= 2 ? '中' : '低',
|
|
11
|
+
action: '',
|
|
12
|
+
});
|
|
13
|
+
const avgCal = seriesAvg(series, 'calories');
|
|
14
|
+
const goal = series[0]?.calorieGoal;
|
|
15
|
+
if (avgCal) {
|
|
16
|
+
out.findings.push({ cause: '摄入', evidence: '日均 ' + avgCal + ' 卡 vs 目标 ' + goal + ' 卡(Δ' + (avgCal - (goal ?? 0) >= 0 ? '+' : '') + round(avgCal - (goal ?? 0)) + ')', confidence: '中', action: '' });
|
|
17
|
+
}
|
|
18
|
+
const ex = seriesAvg(series, 'exerciseKcal');
|
|
19
|
+
if (ex)
|
|
20
|
+
out.findings.push({ cause: '运动', evidence: '日均消耗 ' + ex + ' 卡', confidence: '中', action: '' });
|
|
21
|
+
const df = seriesAvg(series, 'deficit');
|
|
22
|
+
if (df)
|
|
23
|
+
out.findings.push({ cause: '缺口', evidence: '日均缺口 ' + (df >= 0 ? '+' : '') + round(df) + ' 卡(减重需要每日 +300~+500)', confidence: '中', action: '' });
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
export function diagMonthHighlights(series) {
|
|
27
|
+
const out = base(series, 'month_highlights', '我这个月做得好的');
|
|
28
|
+
const wv = weightVals(series);
|
|
29
|
+
const items = [];
|
|
30
|
+
if (wv.length >= 2 && (seriesDelta(series, 'weightKg') ?? 0) < 0) {
|
|
31
|
+
items.push('体重下降 ' + Math.abs(seriesDelta(series, 'weightKg') ?? 0).toFixed(2) + ' kg');
|
|
32
|
+
}
|
|
33
|
+
const daysWith = series.filter((s) => (s.exerciseKcal ?? 0) > 0).length;
|
|
34
|
+
if (daysWith >= 8)
|
|
35
|
+
items.push('运动 ' + daysWith + ' 天');
|
|
36
|
+
const goal = series[0]?.calorieGoal ?? 1800;
|
|
37
|
+
const under = series.filter((s) => s.calories !== null && s.calories !== undefined && s.calories <= goal).length;
|
|
38
|
+
if (under >= 15)
|
|
39
|
+
items.push(under + ' 天摄入在目标内');
|
|
40
|
+
if (items.length === 0)
|
|
41
|
+
items.push('本月暂无亮点,从记录完整度开始(连续记录本身就该表扬)');
|
|
42
|
+
out.findings.push({ cause: '本月亮点', evidence: items.join(';'), confidence: '中', action: '把做得好的行为固定成习惯(时间/场景/频率),下月复制' });
|
|
43
|
+
out.insight = '本月亮点:' + items.join('、') + '。';
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
export function diagMonthImprove(series) {
|
|
47
|
+
const out = base(series, 'month_improve', '我这个月需要改的');
|
|
48
|
+
const goal = series[0]?.calorieGoal ?? 1800;
|
|
49
|
+
const over = series.filter((s) => s.calories !== null && s.calories !== undefined && s.calories > goal * 1.1).length;
|
|
50
|
+
const exDays = series.filter((s) => (s.exerciseKcal ?? 0) > 0).length;
|
|
51
|
+
const items = [];
|
|
52
|
+
if (over >= 5)
|
|
53
|
+
items.push('超标日 ' + over + ' 天');
|
|
54
|
+
if (exDays < 8)
|
|
55
|
+
items.push('运动仅 ' + exDays + ' 天');
|
|
56
|
+
const water = series.map((s) => s.waterMl).filter((v) => v !== null && v !== undefined);
|
|
57
|
+
if (water.length > 0 && water.filter((w) => w < 1500).length >= 10)
|
|
58
|
+
items.push('饮水量偏少');
|
|
59
|
+
if (items.length === 0)
|
|
60
|
+
items.push('各项指标均正常,下月可挑战更高目标');
|
|
61
|
+
out.findings.push({ cause: '待改进项', evidence: items.join(';'), confidence: '中', action: '挑 1 个最影响结果的先改,改稳了再动下一个' });
|
|
62
|
+
out.insight = '下月改进:' + items.join('、') + '。';
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
export function diagOverall(series) {
|
|
66
|
+
const out = commonOverall(series, 'overall', '综合健康评估');
|
|
67
|
+
const wv = weightVals(series);
|
|
68
|
+
if (wv.length < MIN_DAYS) {
|
|
69
|
+
out.degraded = true;
|
|
70
|
+
out.degradeMsg = '数据不足:至少需要 7 天体重 + 任意摄入/运动记录。';
|
|
71
|
+
out.insight = out.degradeMsg;
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
const total = seriesDelta(series, 'weightKg') ?? 0;
|
|
75
|
+
const df = seriesAvg(series, 'deficit');
|
|
76
|
+
const ex = seriesAvg(series, 'exerciseKcal') ?? 0;
|
|
77
|
+
const scores = [];
|
|
78
|
+
if (total <= -0.3)
|
|
79
|
+
scores.push('体重维度 ✅ 在下降');
|
|
80
|
+
else if (total >= 0.3)
|
|
81
|
+
scores.push('体重维度 ⚠️ 在上升');
|
|
82
|
+
else
|
|
83
|
+
scores.push('体重维度 ➖ 基本持平');
|
|
84
|
+
scores.push((df ?? 0) > 0 ? '缺口维度 ✅ 在缺口' : '缺口维度 ⚠️ 无缺口');
|
|
85
|
+
scores.push(ex >= 50 ? '运动维度 ✅ 有规律运动' : '运动维度 ⚠️ 运动偏少');
|
|
86
|
+
const p = seriesAvg(series, 'protein');
|
|
87
|
+
scores.push(p && p >= 70 ? '蛋白维度 ✅ 充足' : '蛋白维度 ⚠️ 偏低');
|
|
88
|
+
out.findings.push({ cause: '八维体检', evidence: scores.join(';'), confidence: '中', action: '按 ⚠️ 维度优先改进,每个周期只改 1-2 项' });
|
|
89
|
+
const pri = scores.filter((f) => f.includes('⚠️')).map((f) => f.split('维度')[0]);
|
|
90
|
+
out.findings.push({ cause: '优先级', evidence: pri.length > 0 ? pri.join('>') : '无短板', confidence: '中', action: '先补缺口,再补运动,最后补蛋白' });
|
|
91
|
+
out.insight = '综合评估:' + scores.join(';') + '。';
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=overall2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overall2.js","sourceRoot":"","sources":["../../../src/analysis/anomaly/overall2.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DaySeries, Diagnosis } from './common.js';
|
|
2
|
+
export declare function diagWeightVolatility(series: DaySeries[]): Diagnosis;
|
|
3
|
+
export declare function diagWeightPlateau(series: DaySeries[]): Diagnosis;
|
|
4
|
+
export declare function diagWeightRebound(series: DaySeries[]): Diagnosis;
|
|
5
|
+
/** 有意偏离老家:老家 `healthy = 0.5 <= rate <= 1.0` 未对减重负速率取负,恒判“偏慢”
|
|
6
|
+
*(why_losing_fast/rate_reasonable 同式)。此处按 -rate 落健康区间,待口径裁决(T7)。 */
|
|
7
|
+
export declare function diagWeightLossCause(series: DaySeries[]): Diagnosis;
|
|
8
|
+
//# sourceMappingURL=weight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weight.d.ts","sourceRoot":"","sources":["../../../src/analysis/anomaly/weight.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAKxD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAwBnE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAuBhE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAoBhE;AAED;oEACoE;AACpE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAyBlE"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { base, daysBetween, degrade, MIN_DAYS, PRED_MIN, round, round2, seriesAvg, seriesDelta, std, weightVals } from './common.js';
|
|
2
|
+
import { FetchError } from '../../fetch/errors.js';
|
|
3
|
+
void FetchError;
|
|
4
|
+
export function diagWeightVolatility(series) {
|
|
5
|
+
const out = base(series, 'weight_volatility', '诊断体重波动原因');
|
|
6
|
+
const wv = weightVals(series);
|
|
7
|
+
if (wv.length < MIN_DAYS)
|
|
8
|
+
return degrade(out, '可用体重数据 ' + wv.length + ' 天,不足 ' + MIN_DAYS + ' 天,无法诊断波动。');
|
|
9
|
+
const s = std(wv);
|
|
10
|
+
const avg = round2(wv.reduce((a, b) => a + b, 0) / wv.length);
|
|
11
|
+
out.findings.push({
|
|
12
|
+
cause: '波动幅度评估',
|
|
13
|
+
evidence: '窗口内 ' + wv.length + ' 个体重值,均值 ' + avg + ' kg,标准差 ' + s + ' kg',
|
|
14
|
+
confidence: s > 0.6 ? '高' : '中',
|
|
15
|
+
action: s > 0.6 ? '波动明显(σ>0.6):优先看水分/盐分/进食时间影响,固定晨起空腹同一条件称重' : '波动在正常范围:每日 ±0.3kg 内多为水分波动,不必逐日焦虑',
|
|
16
|
+
});
|
|
17
|
+
const sodium = series.map((x) => x.sodiumMg).filter((v) => v !== null && v !== undefined);
|
|
18
|
+
if (sodium.length > 0) {
|
|
19
|
+
const naAvg = sodium.reduce((a, b) => a + b, 0) / sodium.length;
|
|
20
|
+
out.findings.push({ cause: '钠摄入过高(水分滞留)', evidence: '日均钠 ' + round(naAvg) + ' mg(参考 ≤2000 mg),高钠日次日起体重易虚高', confidence: '中', action: '控制高盐加工食品(火锅/卤味/腌制品),高钠日多喝水排钠' });
|
|
21
|
+
}
|
|
22
|
+
const avgCal = seriesAvg(series, 'calories');
|
|
23
|
+
if (avgCal) {
|
|
24
|
+
const goal = series[0].calorieGoal;
|
|
25
|
+
out.findings.push({ cause: '摄入波动', evidence: '日均摄入 ' + avgCal + ' 卡,偏离目标 ' + goal + ' 卡达 ' + Math.abs(avgCal - goal).toFixed(0) + ' 卡', confidence: '中', action: '周末/聚餐日摄入波动最大,可对每周 1-2 个高卡日单独复盘' });
|
|
26
|
+
}
|
|
27
|
+
out.insight = '波动以' + (s > 0.6 ? '明显' : '正常') + '为主(σ=' + s + '),建议统一称重条件后继续观察。';
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
export function diagWeightPlateau(series) {
|
|
31
|
+
const out = base(series, 'weight_plateau', '诊断体重停滞(含平台期判断)');
|
|
32
|
+
const wv = weightVals(series);
|
|
33
|
+
if (wv.length < PRED_MIN)
|
|
34
|
+
return degrade(out, '可用体重数据 ' + wv.length + ' 天,不足 ' + PRED_MIN + ' 天,无法判断平台期。');
|
|
35
|
+
const recent = wv.slice(-14);
|
|
36
|
+
const span = recent.length >= 14 ? Math.max(...recent) - Math.min(...recent) : 99;
|
|
37
|
+
const plateau = recent.length >= 14 && span <= 0.5;
|
|
38
|
+
out.findings.push({
|
|
39
|
+
cause: '平台期判断',
|
|
40
|
+
evidence: recent.length >= 14 ? '最近 14 天体重的最高-最低差 ' + span.toFixed(2) + ' kg(≤0.5 kg 判平台期)' : '最近体重样本 ' + recent.length + ' 天,不足 14 天',
|
|
41
|
+
confidence: plateau ? '高' : '中',
|
|
42
|
+
action: plateau ? '当前处于平台期:体重保护机制启动,可尝试碳水循环/增加力量训练/调整缺口 10-15%' : '尚未进入平台期,保持当前节奏',
|
|
43
|
+
});
|
|
44
|
+
const recentAvg = round2(recent.reduce((a, b) => a + b, 0) / recent.length);
|
|
45
|
+
const calAvg = seriesAvg(series.slice(-14), 'calories');
|
|
46
|
+
out.findings.push({
|
|
47
|
+
cause: '摄入是否仍在缺口',
|
|
48
|
+
evidence: '近 14 天日均摄入 ' + (calAvg ?? '—') + ' 卡 vs 目标 ' + series[0].calorieGoal + ' 卡,体重均值 ' + recentAvg + ' kg',
|
|
49
|
+
confidence: '中',
|
|
50
|
+
action: '若摄入已悄悄回到维持水平,先恢复缺口再谈平台期',
|
|
51
|
+
});
|
|
52
|
+
out.insight = plateau ? '⚠️ 已持续 14 天体重不变(±0.5kg 内),符合平台期特征。' : '体重仍在小幅波动,暂未达到平台期标准。';
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
export function diagWeightRebound(series) {
|
|
56
|
+
const out = base(series, 'weight_rebound', '诊断体重反弹');
|
|
57
|
+
const wv = weightVals(series);
|
|
58
|
+
if (wv.length < MIN_DAYS)
|
|
59
|
+
return degrade(out, '可用体重数据 ' + wv.length + ' 天,不足 ' + MIN_DAYS + ' 天,无法诊断反弹。');
|
|
60
|
+
const recent = wv.slice(-7);
|
|
61
|
+
const delta = recent.length >= 2 ? round2(recent[recent.length - 1] - recent[0]) : null;
|
|
62
|
+
const rebound = delta !== null && delta > 0.5;
|
|
63
|
+
out.findings.push({
|
|
64
|
+
cause: '反弹程度',
|
|
65
|
+
evidence: '最近 7 天体重从 ' + recent[0] + ' → ' + recent[recent.length - 1] + ' kg,变化 ' + (delta !== null && delta >= 0 ? '+' : '') + delta + ' kg',
|
|
66
|
+
confidence: rebound ? '高' : '中',
|
|
67
|
+
action: rebound ? '反弹超过 0.5 kg:回看近 1 周摄入/饮水/盐分/压力睡眠,区分真反弹与水分滞留' : '近 7 天变化在正常波动内',
|
|
68
|
+
});
|
|
69
|
+
const calNow = seriesAvg(series.slice(-7), 'calories');
|
|
70
|
+
const calBefore = seriesAvg(series.slice(-14, -7), 'calories');
|
|
71
|
+
if (calNow && calBefore) {
|
|
72
|
+
out.findings.push({ cause: '摄入变化', evidence: '反弹期日均摄入 ' + calNow + ' 卡 vs 前 7 天 ' + calBefore + ' 卡(Δ' + (calNow - calBefore >= 0 ? '+' : '') + round(calNow - calBefore) + ')', confidence: '中', action: '若摄入明显上升,反弹来自热量盈余;若摄入持平,先考虑水分/盐分' });
|
|
73
|
+
}
|
|
74
|
+
out.insight = rebound ? '⚠️ 近 7 天反弹 +' + delta.toFixed(2) + ' kg,需区分真反弹与水分。' : '近 7 天无实质反弹。';
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
/** 有意偏离老家:老家 `healthy = 0.5 <= rate <= 1.0` 未对减重负速率取负,恒判“偏慢”
|
|
78
|
+
*(why_losing_fast/rate_reasonable 同式)。此处按 -rate 落健康区间,待口径裁决(T7)。 */
|
|
79
|
+
export function diagWeightLossCause(series) {
|
|
80
|
+
const out = base(series, 'weight_loss_cause', '诊断体重下降原因');
|
|
81
|
+
const wv = weightVals(series);
|
|
82
|
+
if (wv.length < PRED_MIN)
|
|
83
|
+
return degrade(out, '可用体重数据 ' + wv.length + ' 天,不足 ' + PRED_MIN + ' 天,无法评估速度。');
|
|
84
|
+
const totalDelta = seriesDelta(series, 'weightKg') ?? 0;
|
|
85
|
+
const days = daysBetween(out.start, out.end) || 1;
|
|
86
|
+
const rate = (totalDelta / days) * 7;
|
|
87
|
+
const healthy = rate >= -1.0 && rate <= -0.5;
|
|
88
|
+
out.findings.push({
|
|
89
|
+
cause: '减重速度',
|
|
90
|
+
evidence: '窗口内体重净变化 ' + (totalDelta >= 0 ? '+' : '') + totalDelta.toFixed(2) + ' kg,折合 ' + (rate >= 0 ? '+' : '') + rate.toFixed(2) + ' kg/周(健康范围 0.5-1.0)',
|
|
91
|
+
confidence: '高',
|
|
92
|
+
action: healthy ? '速度在健康范围' : rate > -0.5 ? '速度偏慢:缺口不足或摄入估算偏高' : '⚠️ 速度过快:可能肌肉流失/摄入过低',
|
|
93
|
+
});
|
|
94
|
+
const avgCal = seriesAvg(series, 'calories');
|
|
95
|
+
const deficit = seriesAvg(series, 'deficit');
|
|
96
|
+
if (avgCal) {
|
|
97
|
+
out.findings.push({ cause: '摄入端', evidence: '日均摄入 ' + avgCal + ' 卡,日均缺口 ' + (deficit !== null && deficit !== undefined ? (deficit >= 0 ? '+' : '') + round(deficit) : '0') + ' 卡', confidence: '中', action: '缺口主要来自饮食控制,注意蛋白 ≥ 1.2 g/kg 保护肌肉' });
|
|
98
|
+
}
|
|
99
|
+
const exAvg = seriesAvg(series, 'exerciseKcal');
|
|
100
|
+
if (exAvg) {
|
|
101
|
+
out.findings.push({ cause: '运动端', evidence: '日均运动消耗 ' + exAvg + ' 卡', confidence: '中', action: '运动贡献占比较小时,减重主要靠饮食缺口' });
|
|
102
|
+
}
|
|
103
|
+
out.insight = '减重速度 ' + (rate >= 0 ? '+' : '') + rate.toFixed(2) + ' kg/周,' + (healthy ? '处于健康范围。' : rate > -0.5 ? '偏慢,建议检查实际缺口。' : '偏快,建议上调摄入保护肌肉。');
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=weight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weight.js","sourceRoot":"","sources":["../../../src/analysis/anomaly/weight.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weight2.d.ts","sourceRoot":"","sources":["../../../src/analysis/anomaly/weight2.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAyBhE;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAyBnE"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/** T5 #24 · 体重诊断续(异常点/背离,对照老家 anomaly.py)。 */
|
|
2
|
+
import { base, degrade, MIN_DAYS, round, seriesDelta, std, weightVals } from './common.js';
|
|
3
|
+
export function diagWeightAnomaly(series) {
|
|
4
|
+
const out = base(series, 'weight_anomaly', '诊断体重异常点');
|
|
5
|
+
const wv = weightVals(series);
|
|
6
|
+
if (wv.length < MIN_DAYS)
|
|
7
|
+
return degrade(out, '可用体重数据 ' + wv.length + ' 天,不足 ' + MIN_DAYS + ' 天,无法找异常点。');
|
|
8
|
+
const avg = wv.reduce((a, b) => a + b, 0) / wv.length;
|
|
9
|
+
const s = std(wv);
|
|
10
|
+
const points = [];
|
|
11
|
+
for (const x of series) {
|
|
12
|
+
if (x.weightKg === null || x.weightKg === undefined)
|
|
13
|
+
continue;
|
|
14
|
+
const z = s ? (x.weightKg - avg) / s : 0;
|
|
15
|
+
if (Math.abs(z) > 1.5)
|
|
16
|
+
points.push({ date: x.date, weight: x.weightKg, z: Math.round(z * 100) / 100, guess: z > 0 ? '偏高' : '偏低' });
|
|
17
|
+
}
|
|
18
|
+
out.findings.push({
|
|
19
|
+
cause: '异常点检测(偏离均值 >1.5σ)',
|
|
20
|
+
evidence: points.length > 0
|
|
21
|
+
? '窗口内均值 ' + round(avg * 100) / 100 + ' kg,σ=' + s + ',检出 ' + points.length + ' 个异常点'
|
|
22
|
+
: '窗口内均值 ' + round(avg * 100) / 100 + ' kg,σ=' + s + ',无显著异常点',
|
|
23
|
+
confidence: '中',
|
|
24
|
+
action: '异常点先核对当日是否有聚餐/饮酒/腹泻/称重时间不同,勿当作趋势信号',
|
|
25
|
+
});
|
|
26
|
+
for (const p of points.slice(0, 5)) {
|
|
27
|
+
out.findings.push({ cause: '异常点 ' + p.date, evidence: p.weight + ' kg(偏离 ' + p.z + 'σ,' + p.guess + ')', confidence: '中', action: '回看当天饮食/饮水/盐分记录确认成因' });
|
|
28
|
+
}
|
|
29
|
+
out.insight = points.length > 0 ? '共检出 ' + points.length + ' 个异常点' : '未发现显著异常体重点。';
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
export function diagWeightDivergence(series) {
|
|
33
|
+
const out = base(series, 'weight_divergence', '诊断体重 vs 体脂围度背离');
|
|
34
|
+
const wv = weightVals(series);
|
|
35
|
+
const bf = series.map((s) => s.bodyFatPct).filter((v) => v !== null && v !== undefined);
|
|
36
|
+
const wa = series.map((s) => s.waistCm).filter((v) => v !== null && v !== undefined);
|
|
37
|
+
if (wv.length < MIN_DAYS || (bf.length < 2 && wa.length < 2))
|
|
38
|
+
return degrade(out, '需要 ≥2 个体脂或围度样本才能做背离检测。');
|
|
39
|
+
const wDelta = seriesDelta(series, 'weightKg');
|
|
40
|
+
if (bf.length >= 2) {
|
|
41
|
+
const bfDelta = round((bf[bf.length - 1] - bf[0]) * 100) / 100;
|
|
42
|
+
const divergence = wDelta !== null && wDelta !== undefined && wDelta < -0.3 && bfDelta > -0.5;
|
|
43
|
+
out.findings.push({
|
|
44
|
+
cause: '体重 vs 体脂',
|
|
45
|
+
evidence: '体重 ' + (wDelta !== null && wDelta !== undefined && wDelta >= 0 ? '+' : '') + (wDelta ?? 0).toFixed(2) + ' kg,体脂率 ' + (bfDelta >= 0 ? '+' : '') + bfDelta.toFixed(2) + ' 个百分点(' + bf[0] + '% → ' + bf[bf.length - 1] + '%)',
|
|
46
|
+
confidence: '中',
|
|
47
|
+
action: divergence ? '⚠️ 体重降但体脂未同步降:可能在流失水分/肌肉,检查蛋白摄入与力量训练' : '体重与体脂同向变化,脂肪确实在减少',
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
if (wa.length >= 2) {
|
|
51
|
+
const waDelta = round((wa[wa.length - 1] - wa[0]) * 100) / 100;
|
|
52
|
+
out.findings.push({ cause: '体重 vs 腰围', evidence: '腰围 ' + (waDelta >= 0 ? '+' : '') + waDelta.toFixed(2) + ' cm(' + wa[0] + ' → ' + wa[wa.length - 1] + ' cm)', confidence: '中', action: '腰围下降 = 内脏脂肪减少,即使体重波动也值得肯定' });
|
|
53
|
+
}
|
|
54
|
+
out.insight = out.findings.every((f) => !f.cause.startsWith('⚠️')) && out.findings.every((f) => !f.action.startsWith('⚠️'))
|
|
55
|
+
? '体重与体脂围度基本同步'
|
|
56
|
+
: '存在体重与体脂围度背离信号。';
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=weight2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weight2.js","sourceRoot":"","sources":["../../../src/analysis/anomaly/weight2.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** T5 #24 · 禁忌扫描(对照老家 scripts/contraindications/{soft_rules,validators,scanner}.py)。
|
|
2
|
+
*
|
|
3
|
+
* 心法层(规则数据:腰/膝/肩 + SAFE_VARIANTS 白名单)+ 硬规则层(子串匹配,
|
|
4
|
+
* 英文大小写不敏感,级别不可降级)+ 编排层(读 workout_plans → 汇总 Hit →
|
|
5
|
+
* by_severity → summary_status ok/warn/fail + 替代建议)。DB 由调用方传入
|
|
6
|
+
* (显式路径;缺失由 openDb 侧阻断,不在此静默)。
|
|
7
|
+
*/
|
|
8
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
9
|
+
export type Severity = 'info' | 'warn' | 'error';
|
|
10
|
+
export type ContraPart = '腰' | '膝' | '肩';
|
|
11
|
+
export declare const CONTRA_PARTS: ContraPart[];
|
|
12
|
+
export declare const SAFE_VARIANTS: string[];
|
|
13
|
+
export declare function isSafeVariant(name: string): boolean;
|
|
14
|
+
export interface ContraRule {
|
|
15
|
+
part: ContraPart;
|
|
16
|
+
name: string;
|
|
17
|
+
reason: string;
|
|
18
|
+
keywords: string[];
|
|
19
|
+
severity: Severity;
|
|
20
|
+
}
|
|
21
|
+
export declare const ALL_RULES: Record<ContraPart, ContraRule[]>;
|
|
22
|
+
export declare function rulesFor(part: string): ContraRule[];
|
|
23
|
+
export interface Hit {
|
|
24
|
+
movementName: string;
|
|
25
|
+
part: string;
|
|
26
|
+
ruleName: string;
|
|
27
|
+
severity: Severity;
|
|
28
|
+
reason: string;
|
|
29
|
+
usedIn: string[];
|
|
30
|
+
safeVariant: boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare function matchOne(name: string, rule: ContraRule): boolean;
|
|
33
|
+
/** 单动作扫描:每部位一个 slot(无命中为空数组,顺序稳定)。 */
|
|
34
|
+
export declare function scanMovement(name: string, parts?: string[]): ContraRule[][];
|
|
35
|
+
export declare function worstSeverity(rules: ContraRule[]): Severity | null;
|
|
36
|
+
export declare function scanAllMovements(movements: Array<{
|
|
37
|
+
name?: string;
|
|
38
|
+
}>, parts?: string[]): Hit[];
|
|
39
|
+
export interface PlanScan {
|
|
40
|
+
scannedSessions: number;
|
|
41
|
+
scannedMovements: number;
|
|
42
|
+
scannedParts: string[];
|
|
43
|
+
safeSkipped: number;
|
|
44
|
+
hits: Hit[];
|
|
45
|
+
byMovement: Record<string, {
|
|
46
|
+
count: number;
|
|
47
|
+
severity: Severity;
|
|
48
|
+
rules: string[];
|
|
49
|
+
usedIn: string[];
|
|
50
|
+
parts: string[];
|
|
51
|
+
}>;
|
|
52
|
+
bySeverity: Record<Severity, number>;
|
|
53
|
+
summaryStatus: 'ok' | 'warn' | 'fail';
|
|
54
|
+
suggestions: Array<{
|
|
55
|
+
movement: string;
|
|
56
|
+
rule: string;
|
|
57
|
+
reason: string;
|
|
58
|
+
replace: string;
|
|
59
|
+
safeExamples: string[];
|
|
60
|
+
}>;
|
|
61
|
+
}
|
|
62
|
+
export declare function scanPlan(db: DatabaseSync, part?: string): PlanScan;
|
|
63
|
+
//# sourceMappingURL=contraindications.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contraindications.d.ts","sourceRoot":"","sources":["../../src/analysis/contraindications.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AACjD,MAAM,MAAM,UAAU,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACzC,eAAO,MAAM,YAAY,EAAE,UAAU,EAAoB,CAAC;AAE1D,eAAO,MAAM,aAAa,EAAE,MAAM,EAA8B,CAAC;AAEjE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE;AAsBtH,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,UAAU,EAAE,CAA6C,CAAC;AAErG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,CAEnD;AAED,MAAM,WAAW,GAAG;IAAG,YAAY,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE;AAMzJ,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAEhE;AAED,sCAAsC;AACtC,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAM,EAAsB,GAAG,UAAU,EAAE,EAAE,CAE9F;AAID,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,QAAQ,GAAG,IAAI,CAGlE;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,KAAK,GAAE,MAAM,EAAsB,GAAG,GAAG,EAAE,CAahH;AAED,MAAM,WAAW,QAAQ;IAAG,eAAe,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,GAAG,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAAC,aAAa,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAAC,WAAW,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAA;CAAE;AAE9b,wBAAgB,QAAQ,CAAC,EAAE,EAAE,YAAY,EAAE,IAAI,GAAE,MAAc,GAAG,QAAQ,CA2DzE"}
|