組合せアルゴリズム(combination.py)
| 優先度 | 制約内容 |
|---|---|
| 1(必須) | 2回連続休憩禁止(MIN_REST_INTERVAL=3未満の再休憩を禁止) |
| 2(必須) | 完全一致禁止(同じ休憩者+同じ組合せの繰り返しを禁止) |
| 3(必須) | 新規参加者は必ず出場(過去ラウンドに登場していないメンバー) |
| 4(最適化) | 休憩間隔を最大化(直近に休んだ人を避ける) |
| 5(最適化) | ペア重複を最小化(同じペアになった回数が少ない組合せを優先) |
| 6(ランダム) | 同スコアの候補からrandom.choiceでランダム選択 |
1. メンバー管理 (/tennis/members)
・ メンバー追加・編集(名前・性別・表示順)・削除
・ 性別:男性=黒文字、女性=赤文字で表示
・ 表示順(sort_order)でセッション作成時の選択画面に反映
2. セッション管理
・ セッション作成:日付・コート数(自動/1面/2面/3面)・参加メンバー選択(4〜12名)
・ 8名以上で自動2面設定(コート数手動指定も可)
・ 途中参加・離脱:「編集」ボタンでセッション中のメンバー変更が可能
・ 新規追加されたメンバーは次のラウンドで必ず出場
3. 組合せ生成
「組合」ボタンでパネルを開き、以下の方式で生成:
・ 次の1ラウンド生成:制約を守りながら1ラウンド分を生成
・ 全ラウンド一括生成(6〜10R):まとめて生成(既存ラウンドを削除して再生成)
・ 手動追加:「手動」ボタンから任意の組合せを入力(過去データ入力用)
4. スコア入力
・ 「入力」ボタンタップでモーダル表示
・ ペア名表示 実際の名前
・ 4ゲーム連動モード(デフォルトON):片方を変えると自動的に4-入力値が設定
・ チェックを外すと独立入力(5ゲーム以上・引き分けも対応)
・ 合計ゲーム数をリアルタイム表示
5. 当日成績表
・ セッション詳細画面の上部に固定表示
・ スコア入力後にリロードで自動更新
・ 勝点・負点・ゲーム数・勝率を表示
6. 年間成績 (/tennis/stats)
・ 勝率順にランキング表示(同率は参加回数割り勝点)
・ 未参加者・ゲーム数0の人は非表示
・ 表示項目:参加回数・勝点・負点・ゲーム数・勝率・参加割勝点
7. 分析 (/tennis/analysis)
・ 🤝 相性表:ペアを組んだ時の勝率マトリックス(60%以上=赤、40%以下=青)
・ ⚔️ 対戦履歴:直接対決の勝点率マトリックス
・ 🔥 連勝記録:現在の連勝/連敗中・過去最高記録
・ 📅 月間MVP:月別勝点ランキング
・ PC版は画面幅いっぱいに表示(max-width: 100%)
8. シミュレーター (/tennis/simulator)
・ メンバー名なし、数字(1〜20)で組合せをシミュレート
・ 参加人数・ラウンド数・コート数を設定
・ 各試合にチェックボタン(完了マーク)
・ 全ラウンド完了時にバッジ表示
・ 性別:男性=黒文字、女性=赤文字で表示
・ 表示順(sort_order)でセッション作成時の選択画面に反映
2. セッション管理
・ セッション作成:日付・コート数(自動/1面/2面/3面)・参加メンバー選択(4〜12名)
・ 8名以上で自動2面設定(コート数手動指定も可)
・ 途中参加・離脱:「編集」ボタンでセッション中のメンバー変更が可能
・ 新規追加されたメンバーは次のラウンドで必ず出場
3. 組合せ生成
「組合」ボタンでパネルを開き、以下の方式で生成:
・ 次の1ラウンド生成:制約を守りながら1ラウンド分を生成
・ 全ラウンド一括生成(6〜10R):まとめて生成(既存ラウンドを削除して再生成)
・ 手動追加:「手動」ボタンから任意の組合せを入力(過去データ入力用)
4. スコア入力
・ 「入力」ボタンタップでモーダル表示
・ ペア名表示 実際の名前
・ 4ゲーム連動モード(デフォルトON):片方を変えると自動的に4-入力値が設定
・ チェックを外すと独立入力(5ゲーム以上・引き分けも対応)
・ 合計ゲーム数をリアルタイム表示
5. 当日成績表
・ セッション詳細画面の上部に固定表示
・ スコア入力後にリロードで自動更新
・ 勝点・負点・ゲーム数・勝率を表示
6. 年間成績 (/tennis/stats)
・ 勝率順にランキング表示(同率は参加回数割り勝点)
・ 未参加者・ゲーム数0の人は非表示
・ 表示項目:参加回数・勝点・負点・ゲーム数・勝率・参加割勝点
7. 分析 (/tennis/analysis)
・ 🤝 相性表:ペアを組んだ時の勝率マトリックス(60%以上=赤、40%以下=青)
・ ⚔️ 対戦履歴:直接対決の勝点率マトリックス
・ 🔥 連勝記録:現在の連勝/連敗中・過去最高記録
・ 📅 月間MVP:月別勝点ランキング
・ PC版は画面幅いっぱいに表示(max-width: 100%)
8. シミュレーター (/tennis/simulator)
・ メンバー名なし、数字(1〜20)で組合せをシミュレート
・ 参加人数・ラウンド数・コート数を設定
・ 各試合にチェックボタン(完了マーク)
・ 全ラウンド完了時にバッジ表示
・バックエンド:Python / Flask / SQLite
・フロントエンド:HTML / CSS / JavaScript / Chart.js
・インフラ:Docker / Docker Compose / Apache / Tailscale
・Android:TWA(Trusted Web Activity)/ Bubblewrap
・フロントエンド:HTML / CSS / JavaScript / Chart.js
・インフラ:Docker / Docker Compose / Apache / Tailscale
・Android:TWA(Trusted Web Activity)/ Bubblewrap
ディレクトリ構成
/mnt/data/docker/tennis_app/
├── app.py # Flaskエントリポイント(port 5002)
├── tennis_bp.py # Blueprintルート一式
├── combination.py # 制約付き組合せ生成ロジック
├── database.py # SQLite初期化
├── tennis.db # データベース
├── Dockerfile
├── docker-compose.yml
├── requirements.txt # flask
├── templates/tennis/
│ ├── base.html # 共通レイアウト
│ ├── sessions.html # セッション一覧
│ ├── session_new.html # セッション作成
│ ├── session_detail.html # セッション詳細(メイン画面)
│ ├── members.html # メンバー管理
│ ├── stats.html # 年間成績
│ ├── analysis.html # 分析(相性表・対戦・連勝・月間MVP)
│ └── simulator.html # 組合せシミュレーター
└── static/tennis/
├── css/tennis.css
├── js/tennis.js
├── favicon.png
└── manifest.json # TWA用PWAマニフェスト
├── app.py # Flaskエントリポイント(port 5002)
├── tennis_bp.py # Blueprintルート一式
├── combination.py # 制約付き組合せ生成ロジック
├── database.py # SQLite初期化
├── tennis.db # データベース
├── Dockerfile
├── docker-compose.yml
├── requirements.txt # flask
├── templates/tennis/
│ ├── base.html # 共通レイアウト
│ ├── sessions.html # セッション一覧
│ ├── session_new.html # セッション作成
│ ├── session_detail.html # セッション詳細(メイン画面)
│ ├── members.html # メンバー管理
│ ├── stats.html # 年間成績
│ ├── analysis.html # 分析(相性表・対戦・連勝・月間MVP)
│ └── simulator.html # 組合せシミュレーター
└── static/tennis/
├── css/tennis.css
├── js/tennis.js
├── favicon.png
└── manifest.json # TWA用PWAマニフェスト
DBスキーマ設計主要テーブル構成:
| members | メンバー(名前・性別・表示順・有効フラグ) |
| sessions | 1日の試合セッション(日付・コート数・ラウンド数) |
| session_members | セッションと参加メンバーの中間テーブル |
| rounds | 1ラウンドの試合(セッションID・ラウンド番号・コート・4名のメンバーID・スコア) |
| rest_players | 各ラウンドの休憩者 |