Commit Graph
38 Commits
Author SHA1 Message Date
JianMiauandClaude Fable 5 6ae1eda7e2 功能:選隊面板新增「同步今日場次」,從 history 表撈今天資料覆蓋本機場次
摘要:
- 選隊伍面板新增「同步今日場次」按鈕,按下後把每個人的今日場次更新成 DB 的數字
- 後端新增 GET /api/history/play-counts?from=&to=,回傳區間內每人上場場數與比賽數
- 按鈕上方顯示同步結果或錯誤訊息;手機版同步按鈕獨占一列

根本原因:
- 今日場次只存在本機 localStorage,跨裝置記分時其他裝置上傳的場次本機看不到,
  自動選擇與「今日 N 場」提示就不準

影響:
- 任一裝置按同步後,今日場次會與 DB history 表一致(以 DB 為準,覆蓋本機)
- 輪空/那個等佔位字不計場次

修法:
- server.mjs 新增 play-counts 端點,依 time 區間查 history.players 累計
- api.ts 新增 loadHistoryPlayCounts;App.tsx 以本機時區當天 00:00 起算 24 小時區間並 setPlayCounts
- ScoreboardPage 加入同步狀態與按鈕,App.css 調整按鈕列為三欄、≤720px 改兩列

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 11:33:54 +08:00
JianMiauandClaude Fable 5 d53ebbd3a8 功能:出席率統計改以 attendance 表(TG 報名名單)為資料來源
摘要:
- 出席統計改讀 attendance 表(每天每人一列),依 poll_date 分組後餵給原本的統計函式
- 新增 DB_ATTENDANCE_TABLE 環境變數,預設 attendance;沒有此表時退回 badminton 分組名單
- 前端說明文字與 README 更新來源說明

根本原因:
- 原本用 badminton 表的每日分組名單,只有名單存進 DB 的日子才有資料,
  當天報名還沒存名單就統計不到,名字寫法也要靠別名表修補

影響:
- 統計天數 121 → 126 天,含當天報名尚未分組的場次
- 名字寫法在 attendance 表已統一,別名合併(卡森→景涵 等)仍生效

修法:
- server.mjs 新增 loadAttendanceDays(),buildAttendanceStats() 改吃 [{ time, names }]
- .env.example / docker-compose.yml / README 補上 DB_ATTENDANCE_TABLE

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 13:50:59 +08:00
JianMiauandClaude Opus 4.8 641e51c887 功能:手動分組改為跨區平衡配對,偶數總人數不再補輪空
根本原因:
原本配對只以人數多的一區為基準,缺額全部補「輪空」。例如 A 區 7 人、B 區 5 人會補 2 個輪空,但總人數 12 是偶數,其實可以讓 A 區 1 人跨區支援就湊滿 6 隊真人對打。

影響:
兩區差距 2 以上時,每輪自動抽「差距÷2」人跨區支援,且每輪輪替不同人,跨區負擔平均分攤;只有總人數為奇數時才會補 1 個輪空。等人數時行為不變,三輪之間照舊旋轉配對讓搭檔不同。

修法:
自 badminton-match-hub 8cc0518 移植 balanceZones / pickCrossMembers,buildManualGroups 改為每輪先平衡兩區再建隊伍,補位改在平衡後只補至多 1 個。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-10 15:47:38 +08:00
JianMiauandClaude Opus 4.8 37fa1446af 功能:首頁新增其他區名單,可在記分板臨時選上場但不參與配對
根本原因:
現場常有臨時來打球的人,不屬於 A、B 區的正規輪替名單;原本要讓他們上場只能把名字塞進 A 或 B 區,但這樣會被排進對戰組合,打亂正規配對。

影響:
首頁 A、B 區下方新增跨整行的「其他區名單」輸入框,內容存 localStorage 且不會被資料庫載入蓋掉;分組配對完全不使用其他區。記分板選隊伍時,其他區的人排在清單最後、名字旁掛「其他區」徽章,可手動勾選上場(含與正規名單混搭),今日場次照計;「自動選擇」不會選到他們,自動輪替仍以正規名單為準。

修法:
App 新增 areaOtherInput 狀態與 localStorage 持久化,parseRoster 後以 extraPlayers 傳入 ScoreboardPage;selectablePlayers 併入其他區人選並用 extraPlayerSet 標記,autoPickDraftPlayers 過濾掉其他區,TeamPickerModal 依標記顯示徽章;TeamSelectionPage 新增第三個輸入欄位與說明文字。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-10 15:22:17 +08:00
JianMiauandClaude Opus 4.8 710d04bffe 功能:新增出席率統計,含每日人數分析分頁與名字別名合併
根本原因:
歷史戰績只有逐場比賽紀錄,看不出每個人長期的出席狀況,也不知道每天平均來幾個人;且名單上同一人有多種寫法(大小寫、錯字),直接統計會被拆成多個人而失真。

影響:
歷史戰績頁新增「出席率統計」按鈕,彈窗含兩個分頁——「出席排行」顯示每人出席場次、全期/加入後出席率長條與最近 12 場到場數;「每日人數」顯示全期與最近平均、單場最多最少、年度平均人數、人數分佈與最近 12 場逐日人數。名字自動正規化:英文大小寫視為同一人,中文錯字用別名表合併(景函、卡森→景涵,振華→振驊,阿翔→昱翔),佔位字(輪空、那個、隨機)不列入統計,平均每場人數也一併排除佔位字。

修法:
後端新增 GET /api/attendance,從 badminton 表的每日分組名單統計(history 表只有記分場次會漏算出席),buildAttendanceStats 輸出球員列表、dailyCounts 與含年度平均的 yearTotals;前端 HistoryPage 新增 AttendanceModal 與分頁切換,App.css 補上排行長條與每日分析的樣式。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-10 15:21:37 +08:00
JianMiauandClaude Opus 4.8 68618a8e04 功能:記分板側欄新增得分紀錄清單,並讓左右兩欄底部切齊
根本原因:
計分時只能看到當前比分,沒有逐球紀錄可回顧;且右側欄在「比賽結算」下方留有大片閒置空間。原本 .scoreboard-screen 用 align-items: start,記分板維持自然高度、側欄卻撐滿,導致兩欄底部不齊。

影響:
計分頁右側欄在比賽結算按鈕下方顯示逐球得分表:每列一球,得分隊亮綠標記並顯示當下比分,最新在最上、可上下捲動看舊資料;記分板與側欄底部切齊、不超出畫面,多出的高度分配給上下分數面板,中間橫幅維持原高度。

修法:
App 把既有 pointLog 傳入 ScoreboardPage,新增 pointHistoryRows 反序累計比分並渲染 rail-history 清單;CSS 將 .scoreboard-screen 改 align-items: stretch(配合 align-self: start + min-height 100% 讓內容過高時可自然長高不重疊),.scoreboard-court 以 minmax(min-content, 1fr) 把撐高空間讓給隊伍區與分數面板;行動版清單改跨滿整行並以 32dvh 限高。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 14:11:22 +08:00
JianMiauandClaude Fable 5 540050a991 功能:自動選隊排除「那個」、選隊面板顯示每人今日場次
摘要:
- 記分板「自動選擇」時排除名字為「那個」的球員,手動仍可勾選
- 結算完成(上傳或不上傳)時幫上場 4 人各記一場,輪空不計
- 選球員面板每位球員名字旁顯示「今日 N 場」徽章

根本原因:
- 名單裡的「那個」是佔位用名字,自動選擇會把它當一般球員排進場
- 現場排下一場時沒有依據看誰打得多、誰打得少,容易分配不均

影響:
- src/App.tsx:新增 playCounts state 與 localStorage 持久化(跨日自動歸零)、recordPlayedMatch() 於 skipUpload 與 uploadSettledMatch 成功時計數、傳 playCounts 給記分板
- src/pages/ScoreboardPage.tsx:新增 AUTO_PICK_EXCLUDED_NAMES 常數過濾自動選擇、選隊 modal 每列加「今日 N 場」徽章
- src/App.css:徽章樣式與選項改三欄 grid(含手機版縮小字級)

修法:
- 自動選擇先以排除名單過濾 selectablePlayers 再洗牌取 4 位
- 場次以 {date, counts} 存 localStorage,載入時日期非當天即歸零
- 計數以 activeMatchup 兩隊為準,isPlaceholder 的輪空欄位跳過

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 11:18:44 +08:00
JianMiauandClaude Fable 5 1bc42f5bf6 功能:SSL 憑證過期偵測與提醒、歷史戰績改為分頁載入
根本原因:
1. 憑證過期時瀏覽器只回 Failed to fetch,前端無法辨識原因,使用者誤以為是 DB 連不上(本次 7/1 憑證過期即是如此)。
2. 歷史戰績一次撈出全部資料(400+ 筆、逾 100KB),筆數持續成長會越來越慢。

影響:所有 API 的連線錯誤訊息、歷史戰績頁載入速度、Docker 憑證掛載路徑與檔名。

修法:
- 後端讀取 cert.pem 到期日(60 秒快取),由 /api/version 與 /api/health 回傳 certNotAfter
- 前端把到期日存進 localStorage;fetch 失敗時依離線、憑證已過期、其他連線問題分別顯示明確訊息
- 憑證到期前 7 天於頁面跳出「SSL 憑證提醒」通知,可手動關閉
- /api/history 支援 page/pageSize(預設 20 筆、上限 100),回傳 total 與 totalPages
- 歷史戰績頁加入分頁控制列(上一頁/頁碼含省略號/下一頁/總筆數),刪除後自動重新載入並修正超出範圍的頁碼
- 憑證掛載目錄改為 /volume1/docker/certs,檔名改為 cert.pem / chain.pem / privkey.pem,app 容器同步掛載以讀取到期日

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 15:44:44 +08:00
JianMiauandClaude Opus 4.8 40cb2f01d7 功能:新增更新紀錄分頁、勝利後鎖記分與結算後自動選隊、報分語音改唸個位數
摘要:
- 新增「更新紀錄」分頁,依 git commit 自動產生日誌(scripts/generate-changelog.mjs → src/data/changelog.json)
- 比賽分出勝負後鎖住記分按鈕,需先結算才能開下一場
- 結算(上傳或不上傳)完成後自動打開選隊伍面板並清空已選,方便直接排下一場
- 得分播報只唸個位數(10→0、19→9、20→0),同分改唸「N 平」

根本原因:
- 想在 App 內直接看到版本更新內容,原本沒有頁面
- 勝利後仍可繼續點加分,容易誤觸超過該局比分
- 一場打完要手動回去重設下一場對戰,流程多一步
- 報分連十位數一起唸(十九、二十)冗長,現場聽不直覺

影響:
- 新增 scripts/generate-changelog.mjs、src/pages/ChangelogPage.tsx;package.json 加 predev/prebuild/gen:changelog;tsconfig.app.json 開 resolveJsonModule;.gitignore 排除產生的 changelog.json
- src/types.ts 新增 ChangelogEntry/ChangelogData;src/App.tsx 加導覽與路由、結算後發 nextMatchSignal、recordPoint 加勝負防呆
- src/lib/match.ts 將 hasWonGame 抽出並 export 供記分板共用
- src/pages/ScoreboardPage.tsx:勝負時 canScore=false、收到 nextMatchSignal 自動清空並打開選隊 picker、報分組字改個位數與「平」
- src/App.css 新增更新紀錄卡片樣式

修法:
- changelog 於 dev/build 前自動產生,正式版讀打包後的 JSON 顯示
- hasWonGame 統一判斷(達標分/Deuce 領先 2 分/30 分上限),App 與記分板共用
- 結算成功才遞增 nextMatchSignal,記分板以「render 期間依 prop 變化調整 state」開啟選隊面板
- 報分以 servingScore % 10 / opponentScore % 10 組字,同分輸出「N 平」

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 12:15:28 +08:00
JianMiauandClaude Opus 4.8 304bcaeedd 修正:dev 環境改善(vite 對網路磁碟啟用 polling、Service Worker 僅正式版註冊)
摘要:
- vite dev server 啟用 watch.usePolling,讓 W: 網路磁碟(RaiDrive)的檔案變更能觸發 HMR
- Service Worker 改為僅在正式版(import.meta.env.PROD)才註冊,dev 不再註冊

根本原因:
- 專案放在 RaiDrive 掛載的網路磁碟,不會發出 fs 事件,vite 預設的檔案監看抓不到變更,HMR 失效
- dev 也註冊 SW 會用快取卡住舊版 bundle,改了程式看不到效果

影響:
- vite.config.ts:server.watch 加上 usePolling 與 interval
- src/main.tsx:SW 註冊條件加上 import.meta.env.PROD

修法:
- 開發時靠 polling 監看檔案;SW 只在 build 後的正式環境啟用

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 17:42:22 +08:00
JianMiauandClaude Opus 4.8 9eb60baa37 功能:記分板語音改為報比分、發球區、賽末點與獲勝隊伍
摘要:
- 得分播報改為「比分(發球方先報)+ 發球者左右發球區」
- 發球方到賽末點(再得 1 分即獲勝)時,比分後加唸「賽末點」
- 賽末點得分獲勝時,整段改播「<獲勝隊伍> 贏得比賽」
- 發球區左右一律用實際球場方向,取消上方隊伍鏡像;畫面「發球區」顯示同步改為不鏡像,與語音一致

根本原因:
- 現場記分需要即時聽到比分與發球位置,原本只唸「誰得分、誰發球」較不直覺
- 先前發球區對上方隊伍做鏡像,導致語音與實際球場方向相反

影響:
- src/App.tsx:recordPoint 計算發球方比分、發球區、賽末點與獲勝隊伍,重整 voiceAnnouncement 欄位
- src/pages/ScoreboardPage.tsx:語音組字改為「X比Y(賽末點)」「OO左/右邊發球」、獲勝改播「贏得比賽」;發球區顯示移除鏡像;語音設定「播報誰得分」更名「播報比分」

修法:
- 發球方分數先報;賽末點僅在發球方再得 1 分就獲勝時觸發;發球區統一用 getServiceCourt 實際方向

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 17:42:05 +08:00
JianMiauandClaude Opus 4.8 091e654bdb 功能:首頁日期預設當天、記分板語音改為報比分與發球區
摘要:
- 首頁「指定日期」每次進入都預設為當天
- 記分板語音得分播報改為「比分(發球方先)+ 發球者左右發球區」,賽末點獲勝時整段改播「贏得比賽」

根本原因:
- 日期原本從 localStorage 讀上次選的值,重開會停在舊日期
- 語音原本只唸「誰得分、誰發球」,現場較不直覺,球敘想聽到即時比分與發球位置

影響:
- src/App.tsx:targetDate 改為直接用當天、移除日期的 localStorage 記憶;recordPoint 算出發球方比分與發球區,重整 voiceAnnouncement 欄位
- src/pages/ScoreboardPage.tsx:語音組字改為「X比Y」「OO左/右邊發球」,獲勝時改播「贏得比賽」;語音設定「播報誰得分」更名「播報比分」

修法:
- 發球方分數先報;上方(左側)隊伍發球區做左右鏡像以對齊畫面,下方隊伍不鏡像

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 15:33:22 +08:00
JianMiau 3677162747 修正記分板在 iPad 尺寸的版面與修復 dev server 啟動問題 2026-05-18 17:40:58 +08:00
JianMiau 30a8e1a44c 調整記分板手機滿版模式並更新說明 2026-04-28 18:17:41 +08:00
JianMiau f3e51ea83d 調整發球鏡像規則並更新說明文件 2026-04-28 08:52:47 +08:00
JianMiau edab74f125 強化房間清理與比賽中分頁限制 2026-04-19 18:05:33 +08:00
JianMiau 2d1ad0600e 補上房間關閉通知與列表重取 2026-04-19 13:02:00 +08:00
JianMiau ab3647587e 調整結算通知與全站防選字 2026-04-19 12:54:18 +08:00
JianMiau 896c24547b 新增即時觀戰房間並整理 README 2026-04-19 12:46:59 +08:00
JianMiau c097ceb9ad 更新圖示與部署更新機制並整理 README 2026-04-16 20:35:31 +08:00
JianMiau 36a39f0b8f 調整比賽結算長按回饋並更新 README 2026-04-16 20:06:26 +08:00
JianMiau 975732017f 新增 PWA 更新提示並整理 README 2026-04-16 19:57:08 +08:00
JianMiau 0cfcdc3b0a 調整歷史戰績刪除提示並更新 README 2026-04-16 18:14:56 +08:00
JianMiau d5fee1d299 補上歷史戰績刪除二次確認 2026-04-16 17:22:23 +08:00
JianMiau b2494fff17 調整語音設定介面並更新 README 2026-04-16 17:11:11 +08:00
JianMiau 860e7adc0e 新增連勝與獲勝特效並更新 README 2026-04-16 16:54:59 +08:00
JianMiau b3809b5d4f 補上先攻勾選顯示並更新 README 2026-04-16 16:49:02 +08:00
JianMiau af7ebda9f4 新增歷史戰績關閉按鈕並更新 README 2026-04-16 15:23:09 +08:00
JianMiau f50b11600e 調整分組卡片版面並更新 README 2026-04-16 14:37:32 +08:00
JianMiau 4a66f37e1f 調整選隊伍頁操作並更新 README 2026-04-16 12:37:38 +08:00
JianMiau 98c289ea5b 精簡選隊伍頁提示並更新 README 2026-04-16 10:55:41 +08:00
JianMiau bbedb70e7e 新增歷史戰績刪除功能並更新 README 2026-04-16 10:26:58 +08:00
JianMiau 31168e830b 整理設定隊伍介面並更新 README 2026-04-16 10:19:23 +08:00
JianMiau a1e0e0f16e 調整設定隊伍流程並支援勝利分數設定 2026-04-16 08:53:05 +08:00
JianMiau e903d3ae52 調整歷史戰績彈窗顯示文字 2026-04-16 07:48:15 +08:00
JianMiau b0908b4d3c 補上歷史戰績列表與 NAS 部署說明 2026-04-15 23:04:16 +08:00
JianMiau 7fc8e2698b Refine scoreboard flow and update ports 2026-04-15 22:56:50 +08:00
JianMiau 8f4411d97e chore: initialize Vite React TypeScript app 2026-04-15 16:55:54 +08:00