diff --git a/www/html/Game/public/js/play.js b/www/html/Game/public/js/play.js index 432a8c2..64dc4e7 100644 --- a/www/html/Game/public/js/play.js +++ b/www/html/Game/public/js/play.js @@ -784,6 +784,8 @@ let quizCarrySessionEnded = false; /** หลัง timeup บนโต๊ะ (embed): รอ 5s แล้วโชว์ result-complete / result-gameover */ let quizCarryResultEndTimer = null; + /** หลังโชว์ result-end (embed preview): รอ 5s แล้วกลับ room-lobby — ใช้ร่วม quiz_carry + crown */ + let embedPreviewLobbyReturnTimer = null; /** embed พรีวิว: รอ Ready / START ของโฮสต์ก่อนนับ 3–2–1 */ let quizCarryPregameActive = false; let playHostId = null; @@ -3547,11 +3549,29 @@ return ranks.slice(0, 5); } + function cancelEmbedPreviewLobbyReturnTimer() { + if (embedPreviewLobbyReturnTimer != null) { + clearTimeout(embedPreviewLobbyReturnTimer); + embedPreviewLobbyReturnTimer = null; + } + } + function cancelQuizCarryResultEndAfterTimeup() { if (quizCarryResultEndTimer != null) { clearTimeout(quizCarryResultEndTimer); quizCarryResultEndTimer = null; } + cancelEmbedPreviewLobbyReturnTimer(); + } + + /** หลังภาพ result-complete / gameover (editor embed + preview): รอ 5s แล้วไปล็อบบี้ห้องพรีวิว */ + function scheduleEmbedPreviewReturnToLobbyAfterResultEnd() { + cancelEmbedPreviewLobbyReturnTimer(); + if (!(previewMode && editorEmbedReturn)) return; + embedPreviewLobbyReturnTimer = setTimeout(function () { + embedPreviewLobbyReturnTimer = null; + window.location.href = 'room-lobby.html?space=' + encodeURIComponent(spaceId) + '&nick=' + encodeURIComponent(nick); + }, 5000); } /** มีผู้เล่นอย่างน้อยหนึ่งคนได้คะแนน > 0 (= ส่งคำตอบถูกที่ฮับอย่างน้อย 1 ครั้ง; คะแนนต่อข้อคงที่ QUIZ_CARRY_POINTS_PER_CORRECT) */ @@ -3565,6 +3585,7 @@ } function hideQuizCarryResultEndLayer() { + cancelEmbedPreviewLobbyReturnTimer(); const el = document.getElementById('quiz-carry-result-end-layer'); if (!el) return; el.classList.add('is-hidden'); @@ -3581,15 +3602,22 @@ el.setAttribute('aria-hidden', 'false'); } - /** หลังแสดง timeup บนโต๊ะ (embed): รอ 5 วินาที แล้วโชว์ mock จบตามว่ามีคนตอบถูกหรือไม่ */ - function scheduleQuizCarryResultEndAfterTimeup() { + /** Embed editor: หลัง timeup บนโต๊ะ — รอ 5 วิ แล้วโชว์ result-complete / result-gameover (ใช้ร่วม quiz_carry + crown) */ + function scheduleEmbedDeskResultAfterDelay(okResolver) { cancelQuizCarryResultEndAfterTimeup(); hideQuizCarryResultEndLayer(); + const resolve = typeof okResolver === 'function' ? okResolver : function () { return !!okResolver; }; quizCarryResultEndTimer = setTimeout(function () { quizCarryResultEndTimer = null; - const anyOk = quizCarryAnyPlayerHasCorrectAnswer(); + let anyOk = false; + try { + anyOk = !!resolve(); + } catch (e) { + anyOk = false; + } hideQuizCarryTimeupOnDeskLayer(); showQuizCarryResultEndLayer(anyOk); + scheduleEmbedPreviewReturnToLobbyAfterResultEnd(); }, 5000); } @@ -3608,8 +3636,9 @@ el.setAttribute('aria-hidden', 'true'); } - /** หลังกดรับหลักฐาน (embed preview) — แสดง timeup-txt กลางโต๊ะบนแคนวาส แยกจากป๊อปสรุปคะแนน */ - function showQuizCarryTimeupOnDeskLayer() { + /** หลังกดรับหลักฐาน (embed preview) — แสดง timeup-txt กลางโต๊ะบนแคนวาส แยกจากป๊อปสรุปคะแนน + * @param {function():boolean} [embedResultOkFn] — ถ้าไม่ส่ง = ใช้คะแนน quiz_carry (คนตอบถูก); ส่งเมื่อ crown เพื่อเลือก complete vs gameover */ + function showQuizCarryTimeupOnDeskLayer(embedResultOkFn) { const el = document.getElementById('quiz-carry-timeup-desk-layer'); if (!el) return; const img = document.getElementById('quiz-carry-timeup-txt-img'); @@ -3622,7 +3651,7 @@ syncQuizCarryTimeupDeskLayerPosition(); } catch (e) { /* ignore */ } if (previewMode && editorEmbedReturn) { - scheduleQuizCarryResultEndAfterTimeup(); + scheduleEmbedDeskResultAfterDelay(embedResultOkFn || quizCarryAnyPlayerHasCorrectAnswer); } } @@ -5346,6 +5375,13 @@ updateGauntletCrownHowtoHud(); } + /** Editor embed: เกรด F = ภาพจบแบบ gameover — เหมือน logic สรุป quiz_carry mission */ + function gauntletCrownEmbedMissionAnyOk(mission) { + if (!mission) return false; + const g = String(mission.grade || '').trim().toUpperCase().charAt(0); + return g !== 'F'; + } + function showGauntletCrownMissionOverlay(mission) { const ov = document.getElementById('gauntlet-crown-mission-overlay'); const rowEl = document.getElementById('gcm-rank-row'); @@ -5451,8 +5487,12 @@ } if (btn) { btn.onclick = function () { - if (previewMode && editorEmbedReturn) ov.classList.add('is-hidden'); - else goLobby(); + if (previewMode && editorEmbedReturn) { + ov.classList.add('is-hidden'); + showQuizCarryTimeupOnDeskLayer(function () { return gauntletCrownEmbedMissionAnyOk(mission); }); + } else { + goLobby(); + } }; } } @@ -8225,6 +8265,7 @@ }); socket.on('gauntlet-ended', (data) => { + cancelQuizCarryResultEndAfterTimeup(); gauntletEndsAtMs = null; gauntletCrownRunHeldRemote = false; gauntletCrownPregamePhase = null; diff --git a/www/html/Game/public/js/version.js b/www/html/Game/public/js/version.js index e06f1ae..0d40f06 100644 --- a/www/html/Game/public/js/version.js +++ b/www/html/Game/public/js/version.js @@ -1,6 +1,6 @@ // ทุกครั้งที่มีการเพิ่มหรือเปลี่ยน ให้เพิ่ม v +0.0001 // หลังแก้ค่าแล้วต้อง copy ไป path ที่ Nginx ชี้ (หรือรัน copy-frogger-files-only.sh) ถึงจะเห็นบนเว็บ -window.APP_VERSION = '0.0172'; +window.APP_VERSION = '0.0174'; document.addEventListener('DOMContentLoaded', function () { var t = document.querySelector('.version-tag'); if (t) t.textContent = 'v ' + window.APP_VERSION; diff --git a/www/html/Game/public/play.html b/www/html/Game/public/play.html index 32a84a1..d538aba 100644 --- a/www/html/Game/public/play.html +++ b/www/html/Game/public/play.html @@ -1858,8 +1858,8 @@ - - + +
v —
diff --git a/www/html/Game/public/play.js b/www/html/Game/public/play.js index 432a8c2..64dc4e7 100644 --- a/www/html/Game/public/play.js +++ b/www/html/Game/public/play.js @@ -784,6 +784,8 @@ let quizCarrySessionEnded = false; /** หลัง timeup บนโต๊ะ (embed): รอ 5s แล้วโชว์ result-complete / result-gameover */ let quizCarryResultEndTimer = null; + /** หลังโชว์ result-end (embed preview): รอ 5s แล้วกลับ room-lobby — ใช้ร่วม quiz_carry + crown */ + let embedPreviewLobbyReturnTimer = null; /** embed พรีวิว: รอ Ready / START ของโฮสต์ก่อนนับ 3–2–1 */ let quizCarryPregameActive = false; let playHostId = null; @@ -3547,11 +3549,29 @@ return ranks.slice(0, 5); } + function cancelEmbedPreviewLobbyReturnTimer() { + if (embedPreviewLobbyReturnTimer != null) { + clearTimeout(embedPreviewLobbyReturnTimer); + embedPreviewLobbyReturnTimer = null; + } + } + function cancelQuizCarryResultEndAfterTimeup() { if (quizCarryResultEndTimer != null) { clearTimeout(quizCarryResultEndTimer); quizCarryResultEndTimer = null; } + cancelEmbedPreviewLobbyReturnTimer(); + } + + /** หลังภาพ result-complete / gameover (editor embed + preview): รอ 5s แล้วไปล็อบบี้ห้องพรีวิว */ + function scheduleEmbedPreviewReturnToLobbyAfterResultEnd() { + cancelEmbedPreviewLobbyReturnTimer(); + if (!(previewMode && editorEmbedReturn)) return; + embedPreviewLobbyReturnTimer = setTimeout(function () { + embedPreviewLobbyReturnTimer = null; + window.location.href = 'room-lobby.html?space=' + encodeURIComponent(spaceId) + '&nick=' + encodeURIComponent(nick); + }, 5000); } /** มีผู้เล่นอย่างน้อยหนึ่งคนได้คะแนน > 0 (= ส่งคำตอบถูกที่ฮับอย่างน้อย 1 ครั้ง; คะแนนต่อข้อคงที่ QUIZ_CARRY_POINTS_PER_CORRECT) */ @@ -3565,6 +3585,7 @@ } function hideQuizCarryResultEndLayer() { + cancelEmbedPreviewLobbyReturnTimer(); const el = document.getElementById('quiz-carry-result-end-layer'); if (!el) return; el.classList.add('is-hidden'); @@ -3581,15 +3602,22 @@ el.setAttribute('aria-hidden', 'false'); } - /** หลังแสดง timeup บนโต๊ะ (embed): รอ 5 วินาที แล้วโชว์ mock จบตามว่ามีคนตอบถูกหรือไม่ */ - function scheduleQuizCarryResultEndAfterTimeup() { + /** Embed editor: หลัง timeup บนโต๊ะ — รอ 5 วิ แล้วโชว์ result-complete / result-gameover (ใช้ร่วม quiz_carry + crown) */ + function scheduleEmbedDeskResultAfterDelay(okResolver) { cancelQuizCarryResultEndAfterTimeup(); hideQuizCarryResultEndLayer(); + const resolve = typeof okResolver === 'function' ? okResolver : function () { return !!okResolver; }; quizCarryResultEndTimer = setTimeout(function () { quizCarryResultEndTimer = null; - const anyOk = quizCarryAnyPlayerHasCorrectAnswer(); + let anyOk = false; + try { + anyOk = !!resolve(); + } catch (e) { + anyOk = false; + } hideQuizCarryTimeupOnDeskLayer(); showQuizCarryResultEndLayer(anyOk); + scheduleEmbedPreviewReturnToLobbyAfterResultEnd(); }, 5000); } @@ -3608,8 +3636,9 @@ el.setAttribute('aria-hidden', 'true'); } - /** หลังกดรับหลักฐาน (embed preview) — แสดง timeup-txt กลางโต๊ะบนแคนวาส แยกจากป๊อปสรุปคะแนน */ - function showQuizCarryTimeupOnDeskLayer() { + /** หลังกดรับหลักฐาน (embed preview) — แสดง timeup-txt กลางโต๊ะบนแคนวาส แยกจากป๊อปสรุปคะแนน + * @param {function():boolean} [embedResultOkFn] — ถ้าไม่ส่ง = ใช้คะแนน quiz_carry (คนตอบถูก); ส่งเมื่อ crown เพื่อเลือก complete vs gameover */ + function showQuizCarryTimeupOnDeskLayer(embedResultOkFn) { const el = document.getElementById('quiz-carry-timeup-desk-layer'); if (!el) return; const img = document.getElementById('quiz-carry-timeup-txt-img'); @@ -3622,7 +3651,7 @@ syncQuizCarryTimeupDeskLayerPosition(); } catch (e) { /* ignore */ } if (previewMode && editorEmbedReturn) { - scheduleQuizCarryResultEndAfterTimeup(); + scheduleEmbedDeskResultAfterDelay(embedResultOkFn || quizCarryAnyPlayerHasCorrectAnswer); } } @@ -5346,6 +5375,13 @@ updateGauntletCrownHowtoHud(); } + /** Editor embed: เกรด F = ภาพจบแบบ gameover — เหมือน logic สรุป quiz_carry mission */ + function gauntletCrownEmbedMissionAnyOk(mission) { + if (!mission) return false; + const g = String(mission.grade || '').trim().toUpperCase().charAt(0); + return g !== 'F'; + } + function showGauntletCrownMissionOverlay(mission) { const ov = document.getElementById('gauntlet-crown-mission-overlay'); const rowEl = document.getElementById('gcm-rank-row'); @@ -5451,8 +5487,12 @@ } if (btn) { btn.onclick = function () { - if (previewMode && editorEmbedReturn) ov.classList.add('is-hidden'); - else goLobby(); + if (previewMode && editorEmbedReturn) { + ov.classList.add('is-hidden'); + showQuizCarryTimeupOnDeskLayer(function () { return gauntletCrownEmbedMissionAnyOk(mission); }); + } else { + goLobby(); + } }; } } @@ -8225,6 +8265,7 @@ }); socket.on('gauntlet-ended', (data) => { + cancelQuizCarryResultEndAfterTimeup(); gauntletEndsAtMs = null; gauntletCrownRunHeldRemote = false; gauntletCrownPregamePhase = null;