新增 V2 場地排程頁面與實力權重系統
根本原因: V1 三輪配對制不符合實際打球流程:實際是 2、3 號場地各打 8 局雙打、 每局換搭檔輪休;且配對完全沒考慮成員實力,會出現強強同隊的失衡對戰。 影響: - 首頁改為 V2 場地排程:每局從全員挑 8 人分兩場地打雙打,其餘自動輪休, 搭檔組合在全部輪過一遍之前不重複,每人上場局數落差最多 1 局 - tg_members 新增 skill 欄位(1~10,預設 1),attendance API 一併帶出實力, 新增 GET /api/skills 供頁面開啟時載入全體實力表(載完才能產生賽程) - V2 依實力排點:搭檔強弱互補、每局兩隊實力總和盡量接近, 滑鼠停在隊伍上會浮出實力泡泡;讀取指定日期可回填已上傳的 V2 賽程 - V1 完整保留於 /v1,讀取出席名單改為依實力自動分 A / B 區 - V2 推送 LINE 固定走測試目標(LINE_TARGET_ID_LOCAL),不碰正式群組, 訊息改用綠底標題+斑馬紋對戰列的新版 Flex 卡片 - 上傳沿用 badminton 表,battlecombination 改以場地為 key 存 16 組搭檔 修法: App.tsx 拆為路由(/ 進 AppV2、/v1 進 AppV1);AppV2 排程演算法以 105 種 完美配對窮舉搭配重試 40 次,取「重複最少、總實力差最小」的一份賽程; server 新增 /api/skills、LINE V2 Flex 訊息與 target 覆寫,attendance 查詢 LEFT JOIN tg_members 取得 skill(user_id 優先、nickname 備援、預設 1)。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,24 @@
|
||||
# 羽毛球分組配對器
|
||||
|
||||
這是一個使用 `React + Vite + TypeScript` 製作的網頁應用程式,用來將 A 區與 B 區成員配成羽毛球隊伍。
|
||||
這是一個使用 `React + Vite + TypeScript` 製作的網頁應用程式,用來排羽毛球場地賽程與隊伍配對。
|
||||
|
||||
## 功能說明
|
||||
- 首頁(`/`)是 V2:2、3 號場地各排 8 局雙打
|
||||
- `/v1` 保留舊版:A / B 區三輪配對
|
||||
|
||||
## V2 功能說明(首頁)
|
||||
|
||||
- 輸入或用 `讀取出席名單` 載入出席成員(來源同 V1 的 attendance API)
|
||||
- 每局從全部成員中挑 8 人上場(2、3 號場地各 4 人打雙打),其他人休息
|
||||
- 成員不固定場地,每局重新分配;系統會讓每個人上場局數盡量平均(落差最多 1 局)
|
||||
- 搭檔組合在全部組合輪完一遍之前不會重複;對手組合也會盡量錯開
|
||||
- 頁面載入時會先透過 `GET /api/skills` 抓 `tg_members` 的實力表,載入完成前不能產生賽程
|
||||
- 依實力權重排點:在不重複的前提下,搭檔盡量強弱互補、每局兩隊實力總和盡量接近(查不到的人權重當 1);對戰表平常只顯示名字,滑鼠停在隊伍上會浮出實力泡泡(例如 `阿志 1、蓉蓉 4(合計 5)`)
|
||||
- 人數 4~7 人時只排 2 號場地 8 局;未滿 4 人無法排賽程
|
||||
- `讀取指定日期` 可把之前上傳的 V2 賽程從資料庫回填到畫面;該日還沒賽程時會自動改載入出席名單(V1 格式的舊資料請到 `/v1` 讀取)
|
||||
- 上傳沿用原本的 `badminton` 表:`personnel` 存全部出席者、`battlecombination` 的 `"0"` / `"1"` 分別存 2、3 號場地的 16 組搭檔(依序每 2 組為一局的對戰雙方)
|
||||
- `推送到 LINE` 固定推到測試群組(`LINE_TARGET_ID_LOCAL`),不會推到正式羽球群;一樣要按兩次確認
|
||||
|
||||
## V1 功能說明(`/v1`)
|
||||
|
||||
- 分別輸入 A 區與 B 區名單
|
||||
- 可指定要寫入資料庫的目標日期
|
||||
@@ -14,18 +30,19 @@
|
||||
- 產生配對後可用按鈕手動上傳資料到資料庫
|
||||
- 若指定日期已經有資料,上傳前會先詢問是否覆蓋
|
||||
- 可讀取指定日期的資料庫內容並回填到畫面
|
||||
- 若指定日期還沒有配對資料,`讀取指定日期` 會自動改抓 Telegram bot 的出席名單帶入 A 區
|
||||
- 也可直接按 `讀取今日出席`,把出席名單帶進 A 區後再自行分配到 B 區
|
||||
- 若指定日期還沒有配對資料,`讀取指定日期` 會自動改抓 Telegram bot 的出席名單
|
||||
- 也可直接按 `讀取今日出席` 帶入出席名單
|
||||
- 載入出席名單時會依 `tg_members.skill` 實力權重自動分區:實力強的一半放 A 區、弱的一半放 B 區(可再手動調整)
|
||||
- 兩邊都沒有資料時,畫面會顯示對應的錯誤訊息
|
||||
- 組隊結果產生後可一鍵主動推播到指定 LINE 對話(需按兩次確認)
|
||||
- 支援換行、半形逗號、全形逗號與頓號輸入
|
||||
- 會自動去除空白與重複名稱
|
||||
|
||||
## 操作流程
|
||||
## V1 操作流程
|
||||
|
||||
1. 選擇 `目標日期`
|
||||
2. 按 `讀取今日出席` 帶入 Telegram 報名名單(或手動輸入 A 區與 B 區名單)
|
||||
3. 把 A 區的人自行搬一部分到 B 區
|
||||
3. 系統會依實力權重自動分好 A / B 區,需要時再手動微調
|
||||
4. 按下 `產生三組配對`
|
||||
5. 按下 `上傳資料` 將資料寫入 DB
|
||||
6. 若需要,可按 `讀取指定日期` 載回既有資料;該日還沒配對時會自動改載入出席名單
|
||||
@@ -36,9 +53,10 @@
|
||||
出席名單來自 Node-RED 的 Telegram bot「建喵打羽球」:群組成員按「參加」後會寫進同一個資料庫的 `attendance` 表,按「不參加」則直接刪除,所以表裡的就是當天出席名單。
|
||||
|
||||
- 使用現有的 `DB_HOST / DB_PORT / DB_USER / DB_PASSWORD / DB_DATABASE` 連線,不需要新的環境變數
|
||||
- API:`GET /api/attendance/:time`(`time` 為 `YYYYMMDD`),回傳 `{ ok: true, data: { time, names: [...] } }`;沒資料回 404
|
||||
- `attendance` 表沒有 A / B 區資訊,載入後所有人會先放在 A 區,請自行分配到 B 區
|
||||
- 載入時會沿用名單去重邏輯,並清空 B 區與既有配對結果
|
||||
- API:`GET /api/attendance/:time`(`time` 為 `YYYYMMDD`),回傳 `{ ok: true, data: { time, names: [...], members: [{ name, skill }] } }`;沒資料回 404
|
||||
- 每個人的 `skill` 來自 `tg_members.skill`(優先用 `user_id` 對應,對不到再用 `nickname` 對應),查不到就當 1
|
||||
- 載入後依 `skill` 由高到低排序,前一半(無條件進位)放 A 區、後一半放 B 區;同分時維持報名順序
|
||||
- 載入時會沿用名單去重邏輯,並清空既有配對結果
|
||||
|
||||
`attendance` 表結構:
|
||||
|
||||
@@ -53,7 +71,15 @@ CREATE TABLE attendance (
|
||||
) CHARSET utf8mb4;
|
||||
```
|
||||
|
||||
bot 另外還有 `tg_poll`(報名訊息 id)與 `tg_members`(暱稱記憶)兩張表,這個專案不會讀寫。
|
||||
### 實力權重
|
||||
|
||||
`tg_members` 表加了 `skill` 欄位(`TINYINT UNSIGNED NOT NULL DEFAULT 1`,範圍 1~10,10 最強),這個專案只會讀取、不會寫入:
|
||||
|
||||
```sql
|
||||
UPDATE tg_members SET skill = 8 WHERE nickname = '柏威';
|
||||
```
|
||||
|
||||
bot 另外還有 `tg_poll`(報名訊息 id)表,這個專案不會讀寫;`tg_members` 也只讀 `skill` 與 `nickname` 對應,不會修改。
|
||||
|
||||
## 使用方式
|
||||
|
||||
|
||||
Reference in New Issue
Block a user