diff --git a/public/host.html b/public/host.html
index cc11385..f34c8ca 100644
--- a/public/host.html
+++ b/public/host.html
@@ -5,7 +5,7 @@
出題者ページ
@@ -31,7 +38,6 @@
-
@@ -42,6 +48,20 @@
+
+
+
手動得点調整
+
+
+
+
+
参加チーム一覧
@@ -75,10 +95,13 @@
const nextBtn = document.getElementById("nextBtn");
const correctBtn = document.getElementById("correctBtn");
const incorrectBtn = document.getElementById("incorrectBtn");
- const teamsTableBody = document.querySelector("#teamsTable tbody");
- // ▼▼▼【追加】ボタン要素の取得 ▼▼▼
const scoreResetBtn = document.getElementById("scoreResetBtn");
-
+ const teamsTableBody = document.querySelector("#teamsTable tbody");
+ // ▼▼▼【追加】得点調整UIの要素を取得 ▼▼▼
+ const adjustGroupSelect = document.getElementById("adjustGroupSelect");
+ const adjustScoreInput = document.getElementById("adjustScoreInput");
+ const adjustScoreBtn = document.getElementById("adjustScoreBtn");
+
let musicFiles = [];
let currentIndex = -1;
@@ -88,43 +111,55 @@
// (fetch, WebSocket接続は変更なし)
fetch(`http://192.168.0.145:8890/music_list.json`)
.then(res => res.json())
- .then(data => {
- musicFiles = data.files.sort((a, b) => (parseInt(a.match(/^\d+/), 10) || 0) - (parseInt(b.match(/^\d+/), 10) || 0));
- });
+ .then(data => { musicFiles = data.files.sort((a, b) => (parseInt(a.match(/^\d+/), 10) || 0) - (parseInt(b.match(/^\d+/), 10) || 0)); });
const conn = new WebSocket(`ws://${location.hostname}:8888`);
-
// (通常のボタンイベントリスナーは変更なし)
playBtn.addEventListener("click", () => { if (currentIndex === -1) return; conn.send(JSON.stringify({ type: "play" })); });
pauseBtn.addEventListener("click", () => conn.send(JSON.stringify({ type: "pause" })));
stopBtn.addEventListener("click", () => conn.send(JSON.stringify({ type: "stop" })));
resetBtn.addEventListener("click", () => conn.send(JSON.stringify({ type: "reset" })));
- prevBtn.addEventListener("click", () => { if (musicFiles.length === 0) return; currentIndex = (currentIndex - 1 + musicFiles.length) % musicFiles.length; const file = musicFiles[currentIndex]; songLabel.textContent = `現在の曲: ${file}`; conn.send(JSON.stringify({ type: "select", file: file })); });
- nextBtn.addEventListener("click", () => { if (musicFiles.length === 0) return; currentIndex = (currentIndex + 1) % musicFiles.length; const file = musicFiles[currentIndex]; songLabel.textContent = `現在の曲: ${file}`; conn.send(JSON.stringify({ type: "select", file: file })); });
correctBtn.addEventListener("click", () => { if (currentIndex === -1) return; conn.send(JSON.stringify({ type: "correct", answer: musicFiles[currentIndex] })); });
incorrectBtn.addEventListener("click", () => conn.send(JSON.stringify({ type: "incorrect" })));
-
- // ▼▼▼【追加】得点リセットボタンの処理 ▼▼▼
+ prevBtn.addEventListener("click", () => { if (musicFiles.length === 0) return; currentIndex = (currentIndex - 1 + musicFiles.length) % musicFiles.length; const file = musicFiles[currentIndex]; songLabel.textContent = `現在の曲: ${file}`; conn.send(JSON.stringify({ type: "select", file: file })); });
+ nextBtn.addEventListener("click", () => { if (musicFiles.length === 0) return; currentIndex = (currentIndex + 1) % musicFiles.length; const file = musicFiles[currentIndex]; songLabel.textContent = `現在の曲: ${file}`; conn.send(JSON.stringify({ type: "select", file: file })); });
scoreResetBtn.addEventListener("click", () => {
- const confirmCode = "1111"; // 確認コード(自由に変更してください)
- const input = prompt(`【得点リセット確認】\n\n誤操作防止のため、確認コード「${confirmCode}」を入力してください。`);
-
+ const confirmCode = "1111";
+ const input = prompt(`【得点リセット確認】\n\n確認コード「${confirmCode}」を入力してください。`);
if (input === confirmCode) {
- if (confirm("本当によろしいですか?\nすべてのチームの得点が0点にリセットされます。この操作は元に戻せません。")) {
+ if (confirm("本当によろしいですか?\nすべてのチームの得点が0点にリセットされます。")) {
conn.send(JSON.stringify({ type: "reset_scores" }));
alert("全チームの得点をリセットしました。");
}
- } else if (input !== null) { // キャンセルではなく、何か入力された場合
- alert("確認コードが違います。得点のリセットはキャンセルされました。");
+ } else if (input !== null) {
+ alert("確認コードが違います。");
}
});
+ // ▼▼▼【追加】手動得点調整ボタンの処理 ▼▼▼
+ adjustScoreBtn.addEventListener("click", () => {
+ const group = adjustGroupSelect.value;
+ const scoreText = adjustScoreInput.value;
+ const score = parseInt(scoreText, 10);
+
+ if (!group) {
+ alert("班を選択してください。");
+ return;
+ }
+ if (isNaN(score) || scoreText.trim() === "") {
+ alert("有効な数値を入力してください。");
+ return;
+ }
+
+ conn.send(JSON.stringify({ type: "adjust_score", group: group, score: score }));
+ console.log(`${group}の得点を${score}点調整します。`);
+ adjustScoreInput.value = ""; // 送信後に入力欄をクリア
+ });
// (onmessageの処理は変更なし)
conn.onmessage = ev => {
let msg;
try { msg = JSON.parse(ev.data); } catch { return; }
-
switch (msg.type) {
case "select":
announce.textContent = "曲選択完了、待機中...";
@@ -145,18 +180,13 @@
const participants = msg.teams || [];
const points = msg.points || {};
const teamMembers = { '1班': [], '2班': [], '3班': [], '4班': [], '5班': [] };
- participants.forEach(p => {
- if (teamMembers[p.group]) { teamMembers[p.group].push(p.name); }
- });
+ participants.forEach(p => { if (teamMembers[p.group]) { teamMembers[p.group].push(p.name); } });
for (let i = 1; i <= 5; i++) {
const groupName = `${i}班`;
const memberCell = document.getElementById(`members-${i}`);
const members = teamMembers[groupName];
- if (members.length > 0) {
- memberCell.innerHTML = members.join('
');
- } else {
- memberCell.textContent = '(まだ誰もいません)';
- }
+ if (members.length > 0) { memberCell.innerHTML = members.join('
'); }
+ else { memberCell.textContent = '(まだ誰もいません)'; }
const pointsCell = document.getElementById(`points-${i}`);
pointsCell.textContent = points[groupName] || 0;
}