基于鸿蒙os开发跑步管理系统(七)-跑步建议算法
跑步建议算法
算法概述
RunAdvisorService 是应用的核心算法服务,根据用户个人信息和天气状况生成三种不同强度的跑步建议方案。算法综合考虑 BMI 体质指数、年龄和天气适宜性三个维度,动态调整距离、配速和心率区间。
三种跑步方案
| 方案 | runType | 颜色 | 强度 | 定位 |
|---|---|---|---|---|
| 轻松跑 | easy | #4CAF50 (绿) | 低 | 适合初学者和恢复训练 |
| 标准跑 | standard | #2196F3 (蓝) | 中 | 适合日常锻炼 |
| 耐力跑 | endurance | #FF9800 (橙) | 高 | 适合进阶跑者 |
九步算法详解
第一步:计算基础参数
从 UserProfile 中提取 BMI 和最大心率:
const bmi: number = profile.getBMI();
const maxHR: number = profile.getMaxHR();
BMI 计算公式:weight / (height/100)^2
最大心率公式:220 - age
第二步:判断天气适宜性
const isGoodWeather: boolean =
weather !== undefined ? weather.isGoodForRunning() : true;
天气不适宜的条件(任一满足即判定为不宜):
- 温度 < -10C 或 > 35C
- 风速 > 15 m/s
- 湿度 > 90%
第三步:计算心率区间
基于最大心率,按不同比例划分三个训练区间:
const easyHRMin: number = Math.round(maxHR * 0.60);
const easyHRMax: number = Math.round(maxHR * 0.65);
const stdHRMin: number = Math.round(maxHR * 0.65);
const stdHRMax: number = Math.round(maxHR * 0.70);
const endHRMin: number = Math.round(maxHR * 0.70);
const endHRMax: number = Math.round(maxHR * 0.80);
心率区间对照表:
| 方案 | 心率下限 | 心率上限 | 最大心率占比 |
|---|---|---|---|
| 轻松跑 | 60% HRmax | 65% HRmax | 0.60 - 0.65 |
| 标准跑 | 65% HRmax | 70% HRmax | 0.65 - 0.70 |
| 耐力跑 | 70% HRmax | 80% HRmax | 0.70 - 0.80 |
示例:30 岁用户 (maxHR = 190)
| 方案 | 心率区间 |
|---|---|
| 轻松跑 | 114 - 123 bpm |
| 标准跑 | 123 - 133 bpm |
| 耐力跑 | 133 - 152 bpm |
第四步:设置基础距离与配速
为三种方案设定默认距离和配速:
let easyDist: number = 3;
let easyPaceMin: number = 7;
let easyPaceSec: number = 30;
let stdDist: number = 5;
let stdPaceMin: number = 6;
let stdPaceSec: number = 0;
let endDist: number = 10;
let endPaceMin: number = 5;
let endPaceSec: number = 30;
基础方案参数:
| 方案 | 默认距离 | 默认配速 | 含义 |
|---|---|---|---|
| 轻松跑 | 3 km | 7’30"/km | 慢跑恢复 |
| 标准跑 | 5 km | 6’00"/km | 中等有氧 |
| 耐力跑 | 10 km | 5’30"/km | 节奏跑 |
第五步:BMI 调整
根据 BMI 分类调整距离和配速,BMI 越高运动难度越大:
if (bmi > 28) {
easyDist = 2; easyPaceMin = 8; easyPaceSec = 0;
stdDist = 3; stdPaceMin = 7; stdPaceSec = 0;
endDist = 5; endPaceMin = 6; endPaceSec = 30;
} else if (bmi < 18.5) {
easyDist = 4; easyPaceMin = 6; easyPaceSec = 30;
stdDist = 6; stdPaceMin = 5; stdPaceSec = 30;
endDist = 12; endPaceMin = 5; endPaceSec = 0;
}
BMI 调整对照表:
| BMI 范围 | 分类 | 轻松跑距离 | 标准跑距离 | 耐力跑距离 |
|---|---|---|---|---|
| < 18.5 | 偏瘦 | 4 km | 6 km | 12 km |
| 18.5 - 28 | 正常/偏胖 | 3 km | 5 km | 10 km |
| > 28 | 肥胖 | 2 km | 3 km | 5 km |
第六步:年龄调整
根据年龄段微调配速和距离:
if (profile.age > 50) {
easyPaceMin += 1;
stdPaceMin += 1;
endPaceMin += 1;
easyDist = Math.max(2, easyDist - 1);
stdDist = Math.max(3, stdDist - 1);
endDist = Math.max(5, endDist - 2);
} else if (profile.age < 25) {
easyPaceMin = Math.max(6, easyPaceMin - 1);
stdPaceMin = Math.max(5, stdPaceMin - 1);
}
年龄调整逻辑:
| 年龄段 | 配速调整 | 距离调整 | 说明 |
|---|---|---|---|
| < 25 岁 | 配速加快 1 min/km | 不变 | 年轻体能好 |
| 25 - 50 岁 | 不变 | 不变 | 基准区间 |
| > 50 岁 | 配速减慢 1 min/km | 距离缩短 1-2km | 安全优先 |
注意:距离调整使用 Math.max() 保证下限值,防止减至不合理数值。
第七步:天气调整
天气不适宜时缩短运动距离:
if (!isGoodWeather) {
easyDist = Math.max(2, easyDist - 1);
stdDist = Math.max(3, stdDist - 1);
endDist = Math.max(4, endDist - 2);
}
| 方案 | 正常距离缩减 | 最小保障距离 |
|---|---|---|
| 轻松跑 | -1 km | 2 km |
| 标准跑 | -1 km | 3 km |
| 耐力跑 | -2 km | 4 km |
第八步:计算时长与建议
根据调整后的距离和配速计算预计运动时长:
const easyDuration: number = Math.round(
easyDist * easyPaceMin + easyDist * easyPaceSec / 60
);
const stdDuration: number = Math.round(
stdDist * stdPaceMin + stdDist * stdPaceSec / 60
);
const endDuration: number = Math.round(
endDist * endPaceMin + endDist * endPaceSec / 60
);
时长计算公式:距离 x 配速分钟 + 距离 x 配速秒 / 60
同时生成基础建议文本:
let easyTips: string = '轻松跑是恢复和基础训练的好方式,保持均匀呼吸';
let stdTips: string = '标准跑适合日常锻炼,注意心率不要过高';
let endTips: string = '耐力跑挑战较大,确保充分热身和补水';
如果天气数据可用,在建议前拼接天气提示:
if (weather !== undefined) {
easyTips = weather.getWeatherAdvice() + '。' + easyTips;
stdTips = weather.getWeatherAdvice() + '。' + stdTips;
endTips = weather.getWeatherAdvice() + '。' + endTips;
}
第九步:生成 RunAdvice 对象
将所有计算结果封装为三个 RunAdvice 对象返回:
advices.push(RunAdvice.create(
Constants.RUN_EASY, Constants.RUN_EASY_NAME, easyDist,
easyPaceMin, easyPaceSec, easyHRMin, easyHRMax,
easyDuration, 5, 5, easyTips, '低',
Constants.RUN_EASY_COLOR,
'适合初学者和恢复训练,低心率轻松跑'
));
advices.push(RunAdvice.create(
Constants.RUN_STANDARD, Constants.RUN_STANDARD_NAME, stdDist,
stdPaceMin, stdPaceSec, stdHRMin, stdHRMax,
stdDuration, 8, 5, stdTips, '中',
Constants.RUN_STANDARD_COLOR,
'适合日常锻炼,中等强度有氧跑'
));
advices.push(RunAdvice.create(
Constants.RUN_ENDURANCE, Constants.RUN_ENDURANCE_NAME, endDist,
endPaceMin, endPaceSec, endHRMin, endHRMax,
endDuration, 10, 8, endTips, '高',
Constants.RUN_ENDURANCE_COLOR,
'适合进阶跑者,长距离耐力训练'
));
热身和放松时长预设值:
| 方案 | 热身 | 放松 |
|---|---|---|
| 轻松跑 | 5 分钟 | 5 分钟 |
| 标准跑 | 8 分钟 | 5 分钟 |
| 耐力跑 | 10 分钟 | 8 分钟 |
算法示例
示例 1:正常体型青年
用户:体重 65kg,身高 175cm,年龄 25 岁,男性,天气晴好
BMI = 65 / 1.75^2 = 21.2 (正常)
maxHR = 220 - 25 = 195
轻松跑: 3km, 6'30"/km, HR 117-127, 20min
标准跑: 5km, 5'00"/km, HR 127-137, 25min
耐力跑: 10km, 5'30"/km, HR 137-156, 55min
示例 2:肥胖中年,天气不佳
用户:体重 95kg,身高 170cm,年龄 55 岁,男性,高温 36C
BMI = 95 / 1.70^2 = 32.9 (肥胖)
maxHR = 220 - 55 = 165
BMI调整: easy 2km/8'00", std 3km/7'00", end 5km/6'30"
年龄调整: +1 min/km 配速,距离缩短
天气调整: 距离再缩短
轻松跑: 2km, 9'00"/km, HR 99-107, 18min
标准跑: 3km, 8'00"/km, HR 107-116, 24min
耐力跑: 4km, 7'30"/km, HR 116-132, 30min
Tips: 高温预警,避免户外跑步,注意防暑。...
示例 3:偏瘦年轻人
用户:体重 50kg,身高 168cm,年龄 22 岁,女性,天气适宜
BMI = 50 / 1.68^2 = 17.7 (偏瘦)
maxHR = 220 - 22 = 198
BMI调整: easy 4km/6'30", std 6km/5'30", end 12km/5'00"
年龄调整: 配速减1 (5'30"->4'30" 但 max(6,6-1)=5 for easy)
轻松跑: 4km, 6'30"/km, HR 119-129, 26min
标准跑: 6km, 5'30"/km, HR 129-139, 33min
耐力跑: 12km, 5'00"/km, HR 139-158, 60min
建议页面展示
页面结构
+----------------------------------+
| 跑步建议 |
| |
| +------------------------------+ |
| | 轻松跑 | |
| | 适合初学者和恢复训练... | |
| | 3km | |
| | 7'30"/km | |
| | 目标心率: 114-123 bpm | |
| | 预计时长: 23分钟 | |
| | 热身5分钟 | 放松5分钟 | |
| | 天气适宜跑步... | |
| | [查看路线] | |
| +------------------------------+ |
| |
| +------------------------------+ |
| | 标准跑 | |
| | ... | |
| | [查看路线] | |
| +------------------------------+ |
| |
| +------------------------------+ |
| | 耐力跑 | |
| | ... | |
| | [查看路线] | |
| +------------------------------+ |
+----------------------------------+
查看路线跳转
点击"查看路线"按钮跳转到对应路线的地图详情页:
Button('查看路线')
.backgroundColor(advice.color)
.onClick(() => {
this.navStack.pushPath({
name: 'MapRoute',
param: advice.runType // 'easy' | 'standard' | 'endurance'
});
})
算法优化方向
- 引入跑步历史数据,基于用户实际配速动态调整
- 加入风向因素,逆风时增加配速建议
- 考虑海拔变化对配速的影响
- 引入心率变异性 (HRV) 判断恢复状态
- 基于天气预报提供未来几天训练计划
算法设计哲学
渐进安全原则
跑步建议算法的核心设计原则是"渐进安全"(Progressive Safety):宁可建议偏保守,也不能让用户冒险。这一原则体现在多个设计决策中:
- 距离调整使用 Math.max() 设置下限,确保缩减后仍为合理值
- 天气不适宜时一律缩短距离,不做"虽然高温但可以坚持"的判断
- 年龄超过 50 岁时配速和距离双重缩减,而非仅调整其一
- 心率区间基于最大心率百分比,而非绝对值,自动适配不同年龄
多维度交叉影响
算法的三个输入维度(BMI、年龄、天气)不是简单的加权叠加,而是按顺序逐层调整,每层的调整基于前一层的输出。这种串行调整模式确保了各维度的影响不会相互抵消:
基础参数 -> BMI调整 -> 年龄调整 -> 天气调整 -> 最终结果
例如,一个肥胖且年长的用户在恶劣天气下,三个维度的缩减会叠加,最终建议会非常保守(如轻松跑仅 2km、9’00"/km),这正是渐进安全原则的体现。
为什么提供三种方案
提供轻松跑、标准跑、耐力跑三种方案而非单一建议,基于以下考量:
- 用户状态每日不同(恢复日选轻松跑,状态好选耐力跑)
- 单一建议容易产生"要么跑要么不跑"的二元决策压力
- 三种方案覆盖了 60%-80% 最大心率区间,对应不同的训练效果
- 与三条预置路线(easy/standard/endurance)一一对应,实现建议到行动的闭环
BMI 分类与运动建议关系
BMI 分类标准
本应用采用中国肥胖问题工作组 (WGCPN) 的 BMI 分类标准,与 WHO 标准略有差异:
| 分类 | BMI 范围 (中国标准) | BMI 范围 (WHO标准) | 差异说明 |
|---|---|---|---|
| 偏瘦 | < 18.5 | < 18.5 | 一致 |
| 正常 | 18.5 - 23.9 | 18.5 - 24.9 | 中国标准更严格 |
| 偏胖 | 24.0 - 27.9 | 25.0 - 29.9 | 更低的阈值 |
| 肥胖 | >= 28.0 | >= 30.0 | 更低的阈值 |
中国标准对超重和肥胖的判定阈值低于 WHO,反映了亚洲人体脂分布特点(相同 BMI 下亚洲人内脏脂肪比例更高,健康风险更大)。
BMI 对跑步建议的影响机制
BMI 通过影响距离和配速两个维度作用于建议:
| BMI 分类 | 距离调整 | 配速调整 | 生理依据 |
|---|---|---|---|
| 偏瘦 (< 18.5) | 增加 1-2km | 加快 1 min/km | 体重轻,关节负荷小,可承受更大运动量 |
| 正常 (18.5-28) | 保持默认 | 保持默认 | 标准体质,适用默认参数 |
| 肥胖 (> 28) | 减少 1-5km | 减慢 0.5-1.5 min/km | 体重增加关节冲击,心肺负荷大 |
偏瘦用户的特殊考虑
BMI < 18.5 的用户被建议增加运动距离和加快配速,但这并不意味着偏瘦人群应该大量运动。偏瘦用户通常需要的是增肌增重,而过量有氧运动反而会消耗更多热量。当前算法的建议更偏向"以运动促进食欲"的思路,未来可引入"增肌期建议减少有氧、增加力量训练"的提示。
年龄调整的科学依据
最大心率公式
本应用采用 220 - age 公式计算最大心率。这是最广泛使用的估算公式,由 Fox 等人于 1971 年提出。需要注意的是,该公式是统计平均值,个体差异可达 ±10 bpm。更精确的公式包括:
| 公式 | 计算 | 适用人群 |
|---|---|---|
| Fox (1971) | 220 - age | 通用(本应用采用) |
| Tanaka (2001) | 208 - 0.7 * age | 中老年人更准确 |
| Gellish (2007) | 207 - 0.7 * age | 活跃人群 |
当前选择 Fox 公式是因为其计算简单、认知度高。未来可考虑增加用户自测最大心率输入,绕过估算公式。
年龄分段阈值
| 年龄段 | 配速调整 | 距离调整 | 科学依据 |
|---|---|---|---|
| < 25 岁 | 加快 1 min/km | 不变 | VO2max 峰值期,恢复能力强 |
| 25-50 岁 | 不变 | 不变 | 基准区间,运动能力稳定 |
| > 50 岁 | 减慢 1 min/km | 减少 1-2km | 最大心率下降,关节退变风险增加 |
50 岁为调整阈值,基于以下医学考量:50 岁后最大心率平均每年下降约 1 bpm,肌肉量每十年减少约 8%,关节软骨磨损累积。适度降低运动强度有助于安全锻炼。
Math.max 下限保护
年龄调整中,距离缩减使用 Math.max 保证下限值:
easyDist = Math.max(2, easyDist - 1);
stdDist = Math.max(3, stdDist - 1);
endDist = Math.max(5, endDist - 2);
各方案的下限值不同:轻松跑最低 2km(约 15 分钟),标准跑最低 3km(约 20 分钟),耐力跑最低 5km(约 30 分钟)。这些下限值确保了即使多重缩减叠加,每种方案仍具有最低限度的运动量,避免出现"建议跑 0km"的无意义结果。
天气调整的运动生理学基础
高温对跑步的影响
气温超过 35C 时,人体核心体温上升,皮肤血管扩张以增加散热,导致流向肌肉的血液减少,运动能力下降。此外,大量出汗导致电解质流失,增加抽筋和中暑风险。因此高温天气下必须缩短运动距离。
低温对跑步的影响
气温低于 -10C 时,吸入的冷空气刺激气道,可能诱发运动性哮喘。肌肉在低温下黏滞性增加,弹性和收缩力下降,拉伤风险显著升高。关节滑液变稠,灵活性降低。
风速的影响
风速 > 15 m/s(约 7 级风)时,跑步姿态受影响,平衡控制困难,尤其对中老年跑者构成安全风险。逆风跑步时,空气阻力与速度的平方成正比,能耗大幅增加。
湿度的影响
湿度 > 90% 时,汗液蒸发几乎停止,人体主要散热机制失效。即使气温不高,高湿度也会导致核心体温快速上升,产生闷热不适感。
天气调整的保守策略
当天气判定为不适宜时,算法不是完全禁止跑步(isGoodForRunning 仅影响距离,不阻止建议生成),而是缩短距离保留运动机会。这符合"有运动总比没有好"的公共健康原则,同时通过 tips 文本提醒用户注意风险。
配速与时长的数学关系
时长计算公式
时长(分钟) = 距离(km) * 配速分钟 + 距离(km) * 配速秒 / 60
以标准跑(5km, 6’00"/km)为例:
- 时长 = 5 * 6 + 5 * 0 / 60 = 30 分钟
以轻松跑(3km, 7’30"/km)为例:
- 时长 = 3 * 7 + 3 * 30 / 60 = 21 + 1.5 = 22.5 -> Math.round = 23 分钟
配速与速度的换算
配速是"每公里所需时间",与速度互为倒数关系:
| 配速 | 速度 | 说明 |
|---|---|---|
| 5’00"/km | 12 km/h | 跑者水平 |
| 6’00"/km | 10 km/h | 慢跑 |
| 7’00"/km | 8.57 km/h | 轻松跑 |
| 7’30"/km | 8 km/h | 入门跑 |
| 8’00"/km | 7.5 km/h | 快走/慢跑过渡 |
| 9’00"/km | 6.67 km/h | 快走 |
心率训练区间详解
三个心率区间的训练效果
| 区间 | 心率范围 | 主要能量来源 | 训练效果 |
|---|---|---|---|
| 轻松区 (60-65%) | 有氧区 | 脂肪为主 | 基础耐力、恢复、脂肪代谢 |
| 标准区 (65-70%) | 有氧-无氧过渡 | 糖原+脂肪 | 心肺功能、有氧耐力 |
| 耐力区 (70-80%) | 无氧阈附近 | 糖原为主 | 乳酸阈值提升、速度耐力 |
心率区间的实际应用
轻松跑(60-65% HRmax):这个区间的跑步应该可以轻松交谈,不会气喘。它是建立有氧基础的关键训练,也是恢复日的最佳选择。长期坚持轻松跑可以增加线粒体密度,提高脂肪氧化能力。
标准跑(65-70% HRmax):这个区间是日常训练的主力,呼吸明显加快但仍可断续说话。有效提升心脏泵血能力和毛细血管密度。
耐力跑(70-80% HRmax):这个区间接近乳酸阈值,说话困难,只能说出短句。训练效果是提升乳酸阈值,使跑者能在更高速度下维持更久。
心率区间计算示例
30 岁用户 (maxHR = 190 bpm):
| 方案 | 下限计算 | 上限计算 | 结果区间 |
|---|---|---|---|
| 轻松跑 | 190 * 0.60 = 114 | 190 * 0.65 = 123.5 -> 124 | 114-124 |
| 标准跑 | 190 * 0.65 = 123.5 -> 124 | 190 * 0.70 = 133 | 124-133 |
| 耐力跑 | 190 * 0.70 = 133 | 190 * 0.80 = 152 | 133-152 |
注意 Math.round 导致的边界重叠(124 同时是轻松跑上限和标准跑下限),在实际使用中这不构成问题,因为心率本身就有波动。
热身与放松时长设定
时长设定依据
| 方案 | 热身时长 | 放松时长 | 依据 |
|---|---|---|---|
| 轻松跑 | 5 分钟 | 5 分钟 | 低强度运动,短热身即可 |
| 标准跑 | 8 分钟 | 5 分钟 | 中强度需更充分热身 |
| 耐力跑 | 10 分钟 | 8 分钟 | 高强度需充分热身和较长放松 |
热身的作用是逐步提高心率和肌肉温度,增加关节灵活性,预防运动损伤。放松的作用是逐步降低心率,促进乳酸代谢,减少运动后延迟性肌肉酸痛 (DOMS)。
热身内容建议
当前算法仅提供热身时长,未提供具体动作建议。未来可扩展为:
- 轻松跑热身:5 分钟快走 + 动态拉伸
- 标准跑热身:5 分钟慢跑 + 动态拉伸 + 2 组跨步跑
- 耐力跑热身:8 分钟渐进跑 + 动态拉伸 + 3 组跨步跑 + 2 组加速跑
建议文本生成策略
基础建议文本
三种方案各有一句基础建议:
轻松跑: "轻松跑是恢复和基础训练的好方式,保持均匀呼吸"
标准跑: "标准跑适合日常锻炼,注意心率不要过高"
耐力跑: "耐力跑挑战较大,确保充分热身和补水"
天气提示拼接
如果天气数据可用,在基础建议前拼接 getWeatherAdvice() 的结果:
天气适宜: "天气适宜跑步,享受运动吧!轻松跑是恢复和基础训练的好方式,保持均匀呼吸"
高温天气: "高温预警,避免户外跑步,注意防暑。轻松跑是恢复和基础训练的好方式,保持均匀呼吸"
大风天气: "风力较大,跑步时逆风会较吃力。标准跑适合日常锻炼,注意心率不要过高"
这种拼接方式确保了即使基础建议不变,天气提示也能为用户提供当日特定的运动指导。
算法边界情况分析
极端 BMI 值
| BMI | 分类 | 算法行为 |
|---|---|---|
| 15 | 严重偏瘦 | 偏瘦分支:距离增加,配速加快 |
| 18.4 | 临界偏瘦 | 偏瘦分支 |
| 18.5 | 正常下限 | 正常分支:默认参数 |
| 27.9 | 临界肥胖 | 正常分支 |
| 28.0 | 肥胖下限 | 肥胖分支:距离缩短,配速减慢 |
| 40+ | 重度肥胖 | 肥胖分支(与BMI 28相同调整) |
当前算法在 BMI > 28 后没有进一步分级。重度肥胖(BMI > 35)用户可能需要更保守的建议,如将轻松跑距离降至 1km 或建议步行替代。这是未来优化方向。
极端年龄值
| 年龄 | 算法行为 |
|---|---|
| < 18 | 未成年,配速加快但无特殊警告 |
| 22 | 年轻分支:配速加快 1 min/km |
| 25 | 基准区间开始 |
| 50 | 基准区间结束 |
| 51 | 年长分支:配速减慢,距离缩短 |
| 80+ | 年长分支(与51岁相同调整) |
算法没有对未成年人和极高龄人群做特殊处理。未成年人正在发育期,运动建议应考虑骨骼发育状况;80 岁以上用户可能存在心血管疾病风险,需要更保守的参数。这些边界情况在当前版本中未覆盖。
天气数据缺失
当 weather 参数为 undefined 时,算法按天气适宜处理(isGoodWeather = true)。这确保了网络不可用时仍能生成合理建议,只是缺少天气调整维度。
const isGoodWeather: boolean =
weather !== undefined ? weather.isGoodForRunning() : true;
建议页面的路线联动
runType 到路线的映射
建议页面的"查看路线"按钮通过 advice.runType 传递参数,与 RouteService 的路线类型一一对应:
| runType | 建议 | 路线 |
|---|---|---|
| easy | 轻松跑 | route_easy (3.5km, 入门) |
| standard | 标准跑 | route_standard (5.8km, 中等) |
| endurance | 耐力跑 | route_endurance (10.2km, 挑战) |
地图页面参数传递
Button('查看路线')
.backgroundColor(advice.color)
.onClick(() => {
this.navStack.pushPath({
name: 'MapRoute',
param: advice.runType
});
})
MapRoutePageNav 接收 param 后调用 RouteService.getRouteByType(param as string) 获取路线数据。这种参数传递方式简洁高效,避免了序列化整个 RouteInfo 对象。
算法完整流程图
getAdvice(profile, weather)
|
+-- 1. 计算 BMI 和 maxHR
| bmi = weight / (height/100)^2
| maxHR = 220 - age
|
+-- 2. 判断天气适宜性
| isGoodWeather = weather?.isGoodForRunning() ?? true
|
+-- 3. 计算心率区间
| easy: 60%-65% maxHR
| standard: 65%-70% maxHR
| endurance: 70%-80% maxHR
|
+-- 4. 设置基础距离与配速
| easy: 3km, 7'30"/km
| standard: 5km, 6'00"/km
| endurance: 10km, 5'30"/km
|
+-- 5. BMI 调整
| bmi>28: 减距离+减配速
| bmi<18.5: 增距离+增配速
|
+-- 6. 年龄调整
| age>50: 减距离+减配速
| age<25: 增配速
|
+-- 7. 天气调整
| !isGoodWeather: 减距离
|
+-- 8. 计算时长与生成建议文本
| duration = distance * pace
| tips = weatherAdvice + baseTips
|
+-- 9. 封装 RunAdvice 对象
返回 [easyAdvice, standardAdvice, enduranceAdvice]
更多推荐


所有评论(0)