运行计划负载检查器 - 训练计划审查的AI技能
来自 Wikiprompt,自由的提示词百科全书
运行计划负载检查器 - 训练计划审查的AI技能 一个完整的AI技能,用于制定和审查跑步训练计划,包括一个Python脚本,用于检查风险负荷跳跃,以及一个详细的工作流程。
提示词内容收藏
🌐
---
name: running-plan-load-checker
description: 构建并审查针对5K、10K、半程马拉松和马拉松目标的跑步训练计划,,使用经过测试的脚本检查每周跑量跳跃、长跑占比与进展、高强度日与连续高强度训练、休息周与减量周、峰值时机以及赛前减量,然后用通俗语言解释风险并提出更安全的逐周计划。当跑者分享计划或询问“这个计划是否强度过大?”、“帮我制定一个12周半程马拉松计划”或“我应该如何增加跑量?”时使用。
---
# 跑步计划负荷检查器
你帮助普通跑者健康地到达比赛日。你构建循序渐进进展的计划,并审查现有计划中导致大多数过度使用损伤的负荷错误:做得太多、太快、恢复太少。
你是教练助理,不是医生。疼痛、疾病和医疗状况应交给专业人士(参见 `references/safety-and-red-flags.md`)。
## 本技能中的文件
- `scripts/check_plan.py` - 解析计划表格(Markdown或CSV)并逐周检查负荷进展(仅使用Python 3标准库)
- `references/training-principles.md` - 进展、强度平衡、长跑、减量周、峰值和赛前减量
- `references/safety-and-red-flags.md` - 何时停止、就医或调整计划
- `templates/training-plan.md` - 脚本读取的计划表格格式,以及审查布局
- `examples/example-half-marathon-review.md` - 一份草稿计划的审查与修正
## 工作流程
### 1. 获取跑者的背景信息
用一条简短消息询问或确认:
- 目标比赛、距离和日期(或可用周数)。
- 当前跑步情况:过去4周的每周公里数、每周跑步次数、最近最长跑距离。
- 经验水平以及过去一年的受伤史。
- 可用天数,以及必须空闲的任何一天。
- 目标:舒适完赛,还是时间目标。
如果跑者有健康问题、正在从伤病中恢复、怀孕或刚开始运动,建议在遵循任何计划前咨询医生。
### 2. 将计划放入表格格式
使用 `templates/training-plan.md`:每个训练课一行,包含 `week`、`day`、`type` 和 `km`。使用脚本识别的类型词(easy、recovery、long、tempo、intervals、hills、fartlek、race、cross、strength、rest)。
### 3. 运行检查器
```bash
python3 scripts/check_plan.py plan.md --race half --level intermediate --current-km 20
python3 scripts/check_plan.py plan.csv --race marathon --level beginner --current-km 30 --json
```
每周表格显示公里数、跑步次数、非跑步天数、长跑距离、长跑占比、高强度天数,以及与前三周最高值的对比变化。发现项为HIGH(使用计划前必须修复)或WARN(需审查并说明理由)。退出码1表示至少有一个HIGH发现项。
如果无法运行脚本,请使用 `references/training-principles.md` 手动应用相同检查,并说明情况。
### 4. 修复并解释
对于每个发现项,修改计划而不仅仅是描述问题:平滑跳跃、插入减量周、将高强度训练分开、调整峰值、缩短比赛周。再次运行检查器,直到没有HIGH发现项,并且仅在有理由的情况下保留任何剩余的WARN(例如经验丰富的跑者恢复到熟悉的跑量)。
### 5. 报告
使用 `templates/training-plan.md` 中的审查布局,如 `examples/example-half-marathon-review.md` 所示:更改了什么及原因、最终计划、生活变化时如何调整,以及安全注意事项。
## 规则
- 距离使用公里,除非跑者使用英里;一个计划中绝不混用单位。
- 大多数跑步应感觉轻松(可对话)。用体感和说话测试描述强度,而不仅仅用配速。
- 不规定饮食、补剂或药物。
- 绝不让跑者带着尖锐、加重或导致跛行的疼痛继续训练。
- 错过一周是正常的:重复上一周而不是跳进。
FILE:references/training-principles.md
# 检查器使用的训练原则
这些是休闲跑者的保守经验法则。它们是识别风险的指南,不是法律;经验丰富的跑者可以证明例外情况。
## 每周跑量进展
- 将每周与**前三周的最高值**进行比较,而不仅仅是前一周,这样从减量周恢复到之前的跑量不会受到惩罚。
- 典型安全增幅:初学者约10%,中级跑者12%,高级跑者15%。脚本超过这些值会发出警告,并将超过25%、30%或35%的跳跃评为HIGH。
- 小的绝对变化(3公里或更少)被忽略,因为15公里周的10%太小,无关紧要。
- 第1周应从接近跑者当前水平开始。从远高于当前跑量开始是最常见的计划错误。
## 减量周
- 每3到4周的建设期,减少约20%到30%的跑量一周,并缩短长跑。
- 脚本在连续五周建设期没有至少15%的下降时发出警告(减量周除外)。
## 长跑
- 长跑建立耐力,但不应主导一周。使用的占比限制:每周低于30公里时50%,低于60公里时45%,以上时40%。比赛周除外。
- 长跑每次增加约1到3公里。脚本在增长超过3公里且超过之前最佳值20%时发出警告。
- 比赛周前的最长跑最低要求:5K为6公里,10K为10公里,半程马拉松为16公里,马拉松为28公里(初学者马拉松计划通常峰值在30到32公里)。
## 强度平衡
- 约80%的跑步时间为轻松跑,20%为中等或高强度。
- 高强度训练:节奏跑或阈值跑、间歇跑、山坡跑、法特莱克跑、渐进跑、比赛。每周最大高强度天数:初学者1天,中级2天,高级3天。
- 除非跑者经验丰富且有意为之,否则不要将高强度训练或高强度训练与长跑安排在连续两天(脚本会发出警告)。
- 跨步跑(轻松跑后的短距离放松加速)计为轻松跑。
## 休息
- 初学者和中级跑者每周至少需要一天非跑步日;3到4次跑步计划通常有2到3天休息。交叉训练和力量训练在表格中计为非跑步日。
## 峰值与赛前减量
- 半程马拉松和马拉松:最大周应在比赛周前2到3周(脚本将最后两周内的峰值标记为HIGH)。
- 赛前减量:在最后1到3周逐渐减少跑量,同时保持一些短而快的跑步。在比赛周,除比赛本身外,目标约为峰值的40%到60%(脚本超过60%会发出警告)。
## 单位
- 1英里 = 1.609公里。检查前转换整个计划;脚本只读取公里。
FILE:references/safety-and-red-flags.md
# 安全与危险信号
在构建或审查计划时使用此列表。如有疑问,建议跑者去看医生、物理治疗师或运动医学专业人士。不要诊断。
## 立即停止跑步并寻求医疗帮助
- 胸痛、压迫感或紧绷感;晕厥或近乎晕厥;异常气短;心跳过快或不规律。
- 热病迹象:意识混乱、停止出汗、恶心或呕吐、体温极高。
## 停止本次训练并休息,如果持续则就医
- 尖锐、局限于骨骼某一点的疼痛,或导致跛行的疼痛。
- 跑步时加重,或次日早晨更严重的疼痛。
- 肿胀、麻木或夜间疼痛。
- 休息几天后仍持续的疼痛。
## 减少或调整计划
- 异常疲劳持续几天以上、睡眠差、易怒,或静息心率明显高于正常:增加额外轻松日。
- 颈部以上轻度疾病(流鼻涕:轻松跑可能没问题;颈部以下疾病(发烧、胸闷、胃病)或发烧:休息。
- 错过一周:重复最后完成的周。错过两周或更长时间:将跑量退回两周前。
- 炎热、高海拔和山坡:按体感而非配速跑步,并在非常热的日子缩短训练。
## 开始计划前要求进行医疗检查
- 刚开始运动、长时间休息后恢复,或超过40岁且之前不活跃。
- 已知心脏、肺部或代谢疾病,或心源性猝死家族史。
- 怀孕或近期分娩。
- 近期受伤,尤其是骨应力性损伤。
## 补给与补水(仅一般性建议)
- 对于超过约75到90分钟的跑步,在训练中练习携带水和一些碳水化合物,而不是在比赛日第一次尝试。
- 具体的营养、补剂或体重建议属于注册营养师或医生的职责。
## 如何表达
要清晰且友善:“那种疼痛是停止并检查后再进行下一次跑步的理由。计划会等待;我们可以调整之后的几周。”
FILE:templates/training-plan.md
# 训练计划表格(scripts/check_plan.py 的输入)
每个训练课一行。休息日可以列为类型 `rest` 和公里数 `0`,或省略。
| week | day | type | km | notes |
|---|---|---|---|---|
| 1 | Tue | easy | 5 | conversational pace |
| 1 | Thu | tempo | 6 | 2x8 min comfortably hard, 2 min jog between |
| 1 | Sat | long | 10 | easy, practice drinking |
| 1 | Sun | cross | 0 | bike or swim30 to45 min, optional |
列:
- `week`:1、2、3 ...
- `day`:Mon到Sun(或1到7)
- `type`:easy、recovery、long、tempo、threshold、intervals、hills、fartlek、progression、race、cross、strength、rest
- `km`:以公里为单位的距离(rest、cross、strength为0)
- `notes`:可选;训练细节
运行:`python3 scripts/check_plan.py plan.md --race <5k|10k|half|marathon> --level <beginner|intermediate|advanced> --current-km <km>`
---
# 计划审查:<runner> - <race> 于 <date>
**跑者:** <当前每周公里数、每周跑步次数、最近最长跑、水平、受伤史>
**目标:** <完赛 / 时间目标> **周数:** <n> **可用天数:** <days>
## 检查器结果(之前)
<HIGH和WARN发现项,简短>
## 我更改了什么及原因
1. <更改> - 修复 <发现项>;<一行原因>
## 最终计划
<上述格式的表格>
## 检查器结果(之后)
<“0个发现项”或剩余的WARN及其可接受的理由>
## 生活变化时如何调整
- 错过一次跑步:<规则>
- 错过一周:<规则>
- 感觉疲惫:<规则>
## 安全注意事项
- <来自 references/safety-and-red-flags.md 的相关要点>
FILE:examples/example-half-marathon-review.md
# 示例:审查一份10周半程马拉松草稿
**跑者:** “我每周跑约20公里,3次跑步,最长跑9公里。我在网上找到了这个10周半程马拉松计划。可以吗?”中级,过去一年无受伤,目标是强劲完赛。可用时间:周二、周三、周四、周六、周日。
**草稿计划(摘要):** 第1到9周从24公里增加到44公里,长跑每周增加1公里从12公里增至20公里,每周有节奏跑或间歇跑(第2周额外增加间歇跑,第6周增加山坡跑),没有减量周,第10周周日比赛。
**命令:**
```bash
python3 scripts/check_plan.py draft.md --race half --level intermediate --current-km20
```
**输出:**
```
WEEK KM RUNS REST LONG LONG% HARD CHANGE
1 24 3 4 12 50% 1 -
2 31 4 3 13 42% 2 +29%
3 28 3 4 14 50% 1 -10%
4 34 4 3 15 44% 1 +10%
5 37 4 3 16 43% 1 +9%
6 39 4 3 17 44% 2 +5%
7 40 4 3 18 45% 1 +3%
8 42 4 3 19 45% 1 +5%
9 44 4 3 20 45% 1 +5%
10 40.1 4 3 21.1 53% 2 -9%
发现项: 6
[HIGH] 第9周:峰值跑量(44公里)落在第9周,距离比赛周第10周太近;峰值应在2到3周前
[WARN] 第1周:第1周为24公里,而当前每周20公里
[WARN] 第2周:跑量31公里比近期最大值24公里高29%(目标为12%或更少)
[WARN] 第2周:连续两天有高强度或长跑训练:3-4
[WARN] 第5周:连续五周没有减量周(每3到4周减少20%到30%的跑量)
[WARN] 第6周:连续两天有高强度或长跑训练:4-5、5-6
```
---
# 计划审查:12周半程马拉松
**跑者:** 每周20公里,3次跑步,最近最长跑9公里,中级,近期无受伤
**目标:** 强劲完赛 **周数:** 12(比赛移至第12周,提前两周开始) **可用天数:** 周二、周三、周四、周六、周日
## 检查器结果(之前)
1个HIGH(峰值在比赛前一周,因此没有减量)和5个WARN(起始过高、第2周29%的跳跃、第2周和第6周连续高强度日、没有减量周)。
## 我更改了什么及原因
1. 第1周从21公里开始 - 接近当前20公里,因此身体在第1周不会受到冲击。
2. 每周增加约2公里(6%到10%) - 消除了第2周的跳跃。
3. 第4周和第8周设置减量周(减少约20%,长跑回到10公里) - 让身体吸收训练。
4. 每周四进行一次质量训练,绝不在长跑前一天或后一天 - 修复了连续高强度日。
5. 峰值(36公里,长跑16公里)在第10周,然后是减量周(26公里)和轻松的比赛周 - 比赛时状态新鲜。
6. 从第2周起在周三增加第四次短距离轻松跑 - 在不加重长跑负担的情况下增加跑量。
## 最终计划
| week | km | Tue | Wed | Thu | Sat | Sun |
|---|---|---|---|---|---|---|
| 1 | 21 | easy5 | - | easy6 + strides | long10 | - |
| 2 | 23 | easy5 | easy3 | tempo5(2x8 min) | long10 | - |
| 3 | 25 | easy6 | easy3 | tempo5(2x10 min) | long11 | - |
| 4 | 20 | easy5 | - | easy5 | long10 | - |
| 5 | 27 | easy6 | easy4 | intervals6(5x1 km) | long11 | - |
| 6 | 29 | easy6 | easy4 | tempo7(3x10 min) | long12 | - |
| 7 | 31 | easy6 | easy5 | intervals7(6x1 km) | long13 | - |
| 8 | 25 | easy6 | easy4 | easy5 | long10 | - |
| 9 | 34 | easy7 | easy5 | tempo7(2x15 min) | long15 | - |
| 10 | 36 | easy7 | easy6 | intervals7(5x1.6 km) | long16 | - |
| 11 | 26 | easy6 | easy4 | tempo5(20 min at goal pace) | long11 | - |
| 12 | 30.1 | easy5 + strides | - | easy4 | - | RACE21.1 |
第5周周一还有可选的40分钟自行车骑行。
## 检查器结果(之后)
`python3 scripts/check_plan.py revised.md --race half --level intermediate --current-km20` -> `发现项: 0`,退出码0。
## 生活变化时如何调整
- 错过一次跑步:跳过;不要将其挤入第二天。
- 错过一周:重复你完成的最后一周,然后继续。
- 感觉疲惫或酸痛超过两天:将质量训练替换为轻松跑或休息。
## 安全注意事项
- 对于尖锐、单点或导致跛行的疼痛,或次日早晨更严重的疼痛,停止并就医。
- 从第9周开始在长跑中练习饮水(和少量碳水化合物零食),这样比赛日不会有意外。
FILE:scripts/check_plan.py
#!/usr/bin/env python3
"""检查跑步训练计划是否存在危险的负荷跳跃和结构缺失。
用法:
python3 check_plan.py plan.md [--race5k|10k|half|marathon] [--level beginner|intermediate|advanced]
[--current-km20] [--json]
python3 check_plan.py plan.csv ...
cat plan.md | python3 check_plan.py - ...
计划是Markdown表格或CSV,表头行至少包含
week、day、type和km(也接受:distance、dist。可选列
被忽略。每个训练课一行;休息日可以列出或省略。
day: Mon..Sun、Monday..Sunday或1..7
type: easy、recovery、long、tempo、threshold、intervals、hills、fartlek、
progression、race、cross、strength、rest (其他任何内容计为easy)
km: 数字(rest、cross和strength使用0)
每周检查:与前三周最高值相比的跑量增加、长跑占周跑量的比例(低于30公里时限制50%,低于60公里时45%,以上时40%;比赛周除外)、长跑跳跃、高强度天数、连续两天的高强度或长跑训练、休息日,以及减量周。
计划级检查:第一周与当前每周跑量的对比、最长跑与比赛距离的对比、峰值周距离比赛日太近,以及减量。
退出码:0无HIGH发现项,1至少一个HIGH发现项,2用法或输入错误。
仅使用标准库。
"""
import csv
import io
import json
import re
import sys
DAYS = {"mon":1, "tue":2, "wed":3, "thu":4, "fri":5, "sat":6, "sun":7}
HARD = {"tempo", "threshold", "intervals", "interval", "hills", "hill", "fartlek", "progression", "race", "speed", "track"}
NON_RUN = {"rest", "cross", "strength", "off", "yoga", "bike", "swim"}
RACE_KM = {"5k":5.0, "10k":10.0, "half":21.1, "marathon":42.2}
MIN_LONG = {"5k":6, "10k":10, "half":16, "marathon":28}
LIMITS = { # 每周增加警告、每周增加HIGH、最大高强度天数
"beginner":(0.10, 0.25, 1),
"intermediate":(0.12, 0.30, 2),
"advanced":(0.15, 0.35, 3),
}
def long_share_limit(week_km):
"""低跑量周自然会有更大的长跑占比。"""
return 0.50 if week_km <30 else 0.45 if week_km <60 else 0.40
def usage(msg):
print(f"error: {msg}\n", file=sys.stderr)
print(__doc__.strip().split("\n\n")[1], file=sys.stderr)
sys.exit(2)
def read_rows(text):
lines = [ln for ln in text.splitlines() if ln.strip()]
if not lines:
return []
if lines[0].lstrip().startswith("|") or sum(ln.count("|") >=3 for ln in lines) > len(lines) /2:
rows = []
for ln in lines:
if "|" not in ln or re.match(r"^\s*\|?\s*:?-{2,}", ln):
continue
rows.append([c.strip() for c in ln.strip().strip("|").split("|")])
else:
rows = list(csv.reader(io.StringIO("\n".join(lines))))
header = [h.strip().lower() for h in rows[0]]
out = []
for r in rows[1:]:
out.append({header[i]: (r[i].strip() if i < len(r) else "") for i in range(len(header))})
return out
def num(value):
m = re.search(r"\d+(?:[.,]\d+)?", value or "")
return float(m.group(0).replace(",", ".") if m else 0.0)
def parse(rows):
if not rows:
raise ValueError("no table rows found")
keys = rows[0].keys()
kcol = next((k for k in ("km", "distance", "dist", "distance_km") if k in keys), None)
for need, col in (("week", "week" in keys), ("day", "day" in keys), ("type", "type" in keys), ("km", kcol)):
if not col:
raise ValueError(f"missing column '{need}' (found: {', '.join(keys)})")
sessions = []
for i, r in enumerate(rows,2):
w = num(r["week"])
d = r["day"].strip().lower()
day = DAYS.get(d[:3]) if d[:3] in DAYS else (int(d) if d.isdigit() and 1 <= int(d) <=7 else None)
if not w or day is None:
raise ValueError(f"row {i}: cannot read week/day from {r['week']!r}/{r['day']!r}")
t = (r["type"].strip().lower().split() or ["easy"])[0]
km = num(r[kcol])
sessions.append({"week": int(w), "day": day, "type": t, "km":0.0 if t in NON_RUN else km})
return sessions
def analyze(sessions, race, level, current_km):
warn_up, high_up, max_hard = LIMITS[level]
weeks = {}
for s in sessions:
weeks.setdefault(s["week"], []).append(s)
findings, table = [], []
def add(sev, week, msg):
findings.append({"severity": sev, "week": week, "message": msg})
prev_long = []
week_nums = sorted(weeks)
for idx, w in enumerate(week_nums):
ss = sorted(weeks[w], key=lambda s: s["day"])
runs = [s for s in ss if s["km"] >0]
total = round(sum(s["km"] for s in runs),1)
run_days = sorted({s["day"] for s in runs})
longest = max((s["km"] for s in runs), default=0.0)
hard_days = sorted({s["day"] for s in runs if s["type"] in HARD})
stress_days = sorted({s["day"] for s in runs if s["type"] in HARD or s["type"] == "long"})
ref = max((r["km"] for r in table[-3:]), default=None)
change = None if not ref else (total - ref) / ref
row = {"week": w, "km": total, "runs": len(runs), "rest_days":7 - len(run_days), "long_km": longest,
"long_share": round(longest / total,2) if total else 0.0, "hard_days": len(hard_days),
"change_vs_recent_max": None if change is None else round(change *100)}
table.append(row)
if change is not None and total - ref >3:
if change > high_up:
add("HIGH", w, f"volume {total:g} km is {change:.0%} above the recent max of {ref:g} km (limit {high_up:.0%})")
elif change > warn_up:
add("WARN", w, f"volume {total:g} km is {change:.0%} above the recent max of {ref:g} km (aim for {warn_up:.0%} or less)")
is_race_week = bool(race) and idx == len(week_nums) -1
long_share = long_share_limit(total)
share = round(longest / total,2) if total else 0.0
if total >=15 and not is_race_week and share > long_share:
sev = "HIGH" if share > long_share +0.15 else "WARN"
add(sev, w, f"long run {longest:g} km is {share:.0%} of the week's {total:g} km (aim for {long_share:.0%} or less)")
if prev_long and longest > max(prev_long) +3 and longest > max(prev_long) *1.2 and not is_race_week:
add("WARN", w, f"longest run jumps to {longest:g} km from a previous best of {max(prev_long):g} km (add1 to3 km at a time)")
prev_long.append(longest)
if len(hard_days) > max_hard:
add("WARN", w, f"{len(hard_days)} hard days (days {', '.join(map(str, hard_days))}); {level} plans usually have at most {max_hard}")
b2b = [(a, b) for a, b in zip(stress_days, stress_days[1:]) if b - a ==1]
if b2b:
add("WARN", w, "hard or long sessions on back-to-back days: " + ", ".join(f"{a}-{b}" for a, b in b2b))
if len(run_days) ==7 and level != "advanced":
add("WARN", w, "no rest day this week")
# 减量周:在任何连续5周的建设期中,期望至少有一周比前一周低15%
build = [r for r in table]
if race and len(build) >=3:
build = build[:-2] # 将减量周排除在外
streak =0
for i, r in enumerate(build):
if i and build[i -1]["km"] and r["km"] <= build[i -1]["km"] *0.85:
streak =0
else:
streak +=1
if streak ==5:
add("WARN", r["week"], "five weeks in a row without a cutback week (drop volume20 to30% every3 to4 weeks)")
streak =0
if current_km is not None and table:
first = table[0]["km"]
if current_km ==0 and first >10:
add("HIGH", table[0]["week"], f"week1 starts at {first:g} km from no running; begin with run-walk sessions")
elif current_km and (first - current_km) / current_km > high_up and first - current_km >3:
add("HIGH", table[0]["week"], f"week1 is {first:g} km but current volume is {current_km:g} km/week ({(first - current_km) / current_km:.0%} jump)")
elif current_km and (first - current_km) / current_km > warn_up and first - current_km >3:
add("WARN", table[0]["week"], f"week1 is {first:g} km versus current {current_km:g} km/week")
if race and table:
peak = max(table, key=lambda r: r["km"])
last = table[-1]["week"]
race_rows = [s for s in sessions if s["type"] == "race"]
if not race_rows:
add("INFO", last, "no session with type 'race'; the last week is treated as race week")
build_long = max((r["long_km"] for r in table[:-1]), default=0)
if build_long < MIN_LONG[race]:
add("HIGH" if race in ("half", "marathon") else "WARN", None,
f"longest training run before race week is {build_long:g} km; for a {race} aim for at least {MIN_LONG[race]} km")
if len(table) >=3 and race in ("half", "marathon") and peak["week"] >= last -1:
add("HIGH", peak["week"], f"peak volume ({peak['km']:g} km) falls in week {peak['week']}, too close to race week {last}; peak2 to3 weeks out")
if len(table) >=2:
race_km = sum(s["km"] for s in sessions if s["type"] == "race")
race_week_other = table[-1]["km"] - race_km
if peak["km"] and race_week_other >0.6 * peak["km"]:
add("WARN", last, f"race week has {race_week_other:g} km beside the race ({race_week_other / peak['km']:.0%} of peak); taper to about40 to60%")
return table, findings
def main(argv):
opts = {"race": None, "level": "intermediate", "current": None, "json": False}
paths = []
it = iter(argv)
for a in it:
if a == "--race":
opts["race"] = (next(it, "") or "").lower()
if opts["race"] not in RACE_KM:
usage("--race must be 5k, 10k, half or marathon")
elif a == "--level":
opts["level"] = (next(it, "") or "").lower()
if opts["level"] not in LIMITS:
usage("--level must be beginner, intermediate or advanced")
elif a == "--current-km":
v = next(it, "")
try:
opts["current"] = float(v)
except ValueError:
usage("--current-km needs a number")
elif a == "--json":
opts["json"] = True
elif a.startswith("--"):
usage(f"unknown option {a}")
else:
paths.append(a)
if len(paths) !=1:
usage("give exactly one plan file, or - for stdin")
try:
text = sys.stdin.read() if paths[0] == "-" else open(paths[0], encoding="utf-8").read()
sessions = parse(read_rows(text))
except (OSError, ValueError) as e:
print(f"error: {e}", file=sys.stderr)
return2
table, findings = analyze(sessions, opts["race"], opts["level"], opts["current"])
order = {"HIGH":0, "WARN":1, "INFO":2}
findings.sort(key=lambda f: (order[f["severity"]], f["week"] or0))
if opts["json"]:
print(json.dumps({"weeks": table, "findings": findings}, indent=2))
else:
print(f"Plan: {len(table)} weeks, {sum(r['km'] for r in table):g} km total | level={opts['level']}"
f" race={opts['race'] or '-'} current={opts['current'] if opts['current'] is not None else '-'} km/week")
print(f"\n{'WEEK':>4} {'KM':>6} {'RUNS':>4} {'REST':>4} {'LONG':>5} {'LONG%':>5} {'HARD':>4} {'CHANGE':>7}")
for r in table:
ch = "-" if r["change_vs_recent_max"] is None else f"{r['change_vs_recent_max']:+d}%"
print(f"{r['week']:>4} {r['km']:>6g} {r['runs']:>4} {r['rest_days']:>4} {r['long_km']:>5g} "
f"{r['long_share']:>5.0%} {r['hard_days']:>4} {ch:>7}")
print(f"\nFindings: {len(findings)}")
for f in findings:
where = f"week {f['week']}" if f["week"] else "plan"
print(f" [{f['severity']}] {where}: {f['message']}")
if not findings:
print(" none - load progression looks reasonable")
return1 if any(f["severity"] == "HIGH" for f in findings) else0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
用法
此提示词专为 productivity 设计。复制上方内容并粘贴到你常用的 AI 工具中。
为获得最佳效果,可将占位符(方括号或大写字母标示)替换为你的具体需求。
讨论
0 条评论