# 羽球記分板

使用 `Vite + React + TypeScript + Node.js` 製作的羽毛球記分板，支援選隊伍、計分板、歷史戰績、語音播報、PWA 安裝與 Docker / NAS 部署。

## 功能

- 選隊伍
  - 可依指定日期從資料庫讀取分組資料。
  - 若當天沒有資料，可手動輸入 A、B 區名單產生分組。
  - 每組可直接進入記分板，不需額外再點選這組。
- 計分板
  - 設定隊伍彈窗支援逐一選人。
  - 依選取順序自動成隊：`1、2` 一隊，`3、4` 一隊。
  - 右側可快速選擇預設隊伍。
  - 可設定本場幾分獲勝，預設 `21` 分。
  - 需先指定先攻，之後點擊分數即可直接加分。
  - 第一分記錄後，右側 `設定隊伍` 會切成 `上一步`。
  - 可交換上下隊伍位置，也可交換同隊左右球員位置。
  - `比賽結算` 為防誤觸設計，需長按 `1 秒` 才會觸發。
  - 比分仍是 `0:0` 時，不會啟動比賽結算長按。
  - 長按 `比賽結算` 時，按鈕下方會顯示進度條，按鈕本身也會有亮起與下壓的視覺回饋。
  - 手機長按 `比賽結算` 不會再觸發文字選取。
  - 連勝會出現特效提示：
    - `3 連勝`：`大殺特殺`
    - `4 連勝`：`暴走`
    - `5 連勝`：`無人能擋`
    - `6 連勝`：`主宰比賽`
    - `7 連勝`：`像神一般的`
    - `8 連勝`：`成為傳說`
  - 達到目標分數時會顯示獲勝動畫。
  - 內建免費瀏覽器 TTS。
  - 可設定是否播報得分者、是否播報發球者、以及語速。
  - `RURU` 已支援不分大小寫的發音別名，會念成 `嚕嚕`。
- 歷史戰績
  - 直接從資料庫 `history` 表讀取列表。
  - 點擊單筆戰績可開啟得分紀錄彈窗。
  - 彈窗支援右上角 `X` 關閉按鈕。
  - 每筆資料可直接刪除，刪除前會跳一次確認提示。
- PWA
  - 可加入手機主畫面，像 App 一樣開啟。
  - 支援 `manifest`、`service worker`、主畫面 icon。
  - 網頁 favicon 與 PWA icon 已改用 `ICON.png` 產生的 PNG 圖示。
  - 偵測到新版本時，畫面底部會顯示更新提示，可一鍵重新整理套用新版。
  - 前端會定期輪詢 `/api/version`，只要重新部署並重建 app container，就能偵測到新版本。

## 執行環境

### Port

- Client：`3501`
- Server：`8788`

### 安裝

```bash
npm install
```

### 開發模式

```bash
npm run dev
```

啟動後會同時開兩個服務：

- 前端：`http://localhost:3501`
- API：`http://localhost:8788`

### 檢查

```bash
npm run lint
npm run build
```

## 環境變數

請在專案根目錄建立 `.env`：

```env
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=root
DB_PASSWORD=your_password
DB_DATABASE=badminton
DB_TABLE=badminton
DB_HISTORY_TABLE=history
PORT=8788
```

## Docker / NAS 部署

正式部署時目前是雙容器架構：

- App 內部服務：`8788`
- Nginx SSL 對外入口：`3501`

啟動指令：

```bash
sudo docker compose up -d --build
```

部署完成後，對外入口：

```text
https://你的網域或 NAS IP:3501
```

每次執行 `sudo docker compose up -d --build` 重建 app container 時，後端都會帶新的容器啟動版號；前端輪詢發現版號不同後，就會跳出更新提示。

## SSL 憑證目錄

Docker Compose 會直接掛載 NAS 上的憑證目錄：

```text
/volume1/homes/JianMiau/www/certificate/
```

目前預設使用這三個檔名：

- `RSA-cert.pem`
- `RSA-chain.pem`
- `RSA-privkey.pem`

更新憑證時，只要更新上述目錄內的檔案，再重新啟動容器即可。

## history 資料表格式

`history` 表目前使用以下欄位：

- `id`
- `time`
- `dayOfWeek`
- `score`
- `winScore`
- `type`
  - `0`：雙打
  - `1`：單打
- `players`
  - 依 `1 ~ 4` 順序排序的玩家名稱
- `team`
  - `1、2` 一隊
  - `3、4` 一隊
- `scoreList`
  - 格式：`[round, 發球者編號, 連勝次數, 得分隊伍(0 或 1)]`

## Git 中文顯示

若要讓 commit 與 log 正常顯示中文，可設定：

```bash
git config i18n.commitEncoding utf-8
git config i18n.logOutputEncoding utf-8
git config core.quotepath false
```
