前面十七天做的東西,都只有自己看得到。
儀表板跑在 localhost:5173,訓練紀錄在我的 markdown 檔裡,負荷曲線在 load.json。這系列叫「教練看不到的那六天」,而到今天為止,教練確實還是什麼都看不到^0^。
今天要把週報交出去。
直覺做法是在儀表板加一個 /report 路由,把網址傳給教練。
但這樣有個語意問題:週報是快照,儀表板是即時的。
9/3 傳給他一個網址,他 9/10 才點開—看到的會是下週的資料,上週的週報就看不到了。
而且還有一串現實問題:儀表板沒有部署、資料檔全部 gitignore、教練不會為了看我的訓練去裝什麼東西。
所以改成產出一個單一 HTML 檔:
report-2026-08-24.html 5.7 KB
吃同一個html檔案,用 LINE 或 mail 傳過去,教練即可查看當週資料。

大綱原本寫「AI 自動產出一頁式訓練摘要」,但 Day 16 才提及 AI 產出的代價—規則寫在 markdown 是引導,不是保證。
自己的產出寫錯了能看得出來,但給別人看的東西寫錯了,就會是用錯的資訊去做判斷。
所以拆開:
| 誰產生 | 為什麼 | |
|---|---|---|
| 達成率、趟數、TRIMP | 程式 | 從紀錄推出來,可以重跑驗證 |
| 「我當天說的」 | 我 | 對話裡打的原話,沒有改寫 |
| 摘要 | 助教 | 需要敘事,但可能出錯 |
而且這三種在頁面上分開標:
<div class="note">
<b>這一頁的數字從哪來</b><br>
達成率、趟數、TRIMP 由程式從訓練紀錄算出來,可以重跑驗證;
「我當天說的」是我在對話裡打的原話,沒有改寫;助教摘要是 LLM 產生的。
三種東西可信度不一樣,所以分開標。
</div>
助教摘要那節底下還單獨掛一句:
這段是 LLM 寫的,可能有誤。上面的數字才是程式算的。
這不是為了嚴謹好看, 教練拿到一頁報告,必須知悉哪一行是機器算的,哪一行是我講的—因為他會根據這些評估我之後的訓練。
大綱寫「教練是用手機看的」,所以排版上會以小螢幕友善。
他是在 LINE 裡點開的,所以直接單欄:
body{max-width:640px;margin-inline:auto;
font:16px/1.7 -apple-system,"PingFang TC","Noto Sans TC",sans-serif;
-webkit-text-size-adjust:100%}
幾個細節:
-webkit-text-size-adjust:100% —iOS Safari 在橫轉直的時候會自己放大字,加這行擋掉。
font-variant-numeric: tabular-nums —數字等寬,這樣配速和 TRIMP 上下對得齊,表格裡的數字沒對齊,看起來就不是很專業。
卡片而不是表格—逐日那段本來想做成表格,但七欄在手機上一定要橫捲,改成每天一張卡片,單欄堆下去,滑就好。
這算是突發奇想,教練帶學生在田徑場,手機在口袋裡不方便看,想 old school 地印出來^0^。
@media print{
/* 教練可能想印出來帶去田徑場。去掉底色、避免卡片被切成兩頁 */
body{padding:0;max-width:none;font-size:12px}
.day,.stat,.note{break-inside:avoid;page-break-inside:avoid}
.said{background:none}
}
break-inside: avoid 那行是重點—沒有它的話,某一天的卡片會被切成兩半跨頁,上半頁寫課表、下半頁寫實際做的。
去底色也是:螢幕上淺藍色的自述區塊很好認,印出來是一塊灰。
跑出來的是 8/24 到 8/30:
5 天有訓練、跑步 3、重訓 2、總負荷 TRIMP 342.2
二 08-25 間歇 4區 1000m ×5~6 → [達標]
四 08-27 間歇 3區 2000m ×2~3 → [達標]
六 08-29 節奏跑 2區 6km ×2 → [部分達標]
而這一週剛好有兩個 Day 15 講過的例子:
8/25 那天課表開 1000m×5~6,我跑到第三趟吃不消,後三趟自己改成 800m。報告上除了「達標」之外,還有這一行:
我當天說的 課表開 1000m×5~6,跑到第三趟覺得吃不消,後三趟自己改成 800m。
8/29 判定是「部分達標」,但底下標著:
判定 趟數 2/2、配速對 1A 0/2(當天跑 1B 的配速)

這兩行才是這份報告存在的理由。 只看「達標/部分達標」,教練會以為我一週練得普通;看到那兩行,他知道的是「這個人這週狀態不好,自己做了兩次調整」。
那正是他看不到的六天裡發生的事。
load.json 的 TRIMP 不含重訓(Day 17 講過,沒戴錶就沒有心率)。
而這一週五天有訓練,其中兩天是重訓。所以「總負荷 TRIMP 342.2」這個數字,涵蓋的是五天裡的三天。
報告上我標了:
TRIMP 只計入有心率的活動,重訓不在裡面(沒戴錶)。
但這句話在一個「總負荷」的大數字旁邊,說服力有限。教練看到 342.2 會直覺以為那是整週。
比較誠實的做法是把重訓那兩天的 TRIMP 顯示成「—」而不是 0—0 表示「做了但負荷是零」,「—」表示「這個模型看不到」。這兩件事不一樣,而我現在的版本混在一起。
之後也許可以做個調整。

東西交出去了,但還有一個問題沒處理。
這份報告是我主動整理給教練的,而助教平常在 Telegram 裡,是我問什麼它答什麼。
明天要測的是:它有沒有什麼是不該答的。