Stanice - Voda
?
QR Kód s aktuální adresou
Zalévací stanice
Zadej tajný kód své květiny:
Vymazat
Doplňování vody
Drž tlačítko a opatrně zalévej!
0 %
DRŽ MĚ
Zrušit a odejít
Hotovo!
Tvoje kytka má radost.
Připravuji stanici pro dalšího hráče...
Upravit obsah stránky
{% extends "templates/base.html" %} {% set game_name = "Stanice - Voda" %} {% block content %} <div id="appContainer" class="full-screen-app bg-light"> <button id="fsBtn" class="btn btn-outline-secondary position-absolute top-0 end-0 m-3 shadow" style="z-index: 10050;" onclick="toggleFullscreen()"> <i class="fa-solid fa-expand fa-2x"></i> </button> <div id="pinScreen" class="container d-flex flex-column justify-content-center align-items-center h-100"> <h1 class="mb-4 text-center text-primary"><i class="fa-solid fa-faucet-drip"></i> Zalévací stanice</h1> <h4 class="mb-4 text-center">Zadej tajný kód své květiny:</h4> <div class="d-flex justify-content-center gap-3 mb-4" id="pinDisplay"> <div class="pin-slot border rounded-circle shadow-sm bg-white" style="width: 80px; height: 80px;"></div> <div class="pin-slot border rounded-circle shadow-sm bg-white" style="width: 80px; height: 80px;"></div> <div class="pin-slot border rounded-circle shadow-sm bg-white" style="width: 80px; height: 80px;"></div> </div> <div class="d-flex flex-wrap justify-content-center gap-3 mb-4" style="max-width: 400px;"> <button class="btn color-btn" style="background-color: red;" onclick="addPinColor('red')"></button> <button class="btn color-btn" style="background-color: blue;" onclick="addPinColor('blue')"></button> <button class="btn color-btn" style="background-color: green;" onclick="addPinColor('green')"></button> <button class="btn color-btn" style="background-color: yellow;" onclick="addPinColor('yellow')"></button> <button class="btn color-btn" style="background-color: purple;" onclick="addPinColor('purple')"></button> <button class="btn color-btn" style="background-color: orange;" onclick="addPinColor('orange')"></button> </div> <button class="btn btn-outline-danger btn-lg mt-2 px-4" onclick="clearPin()">Vymazat</button> </div> <div id="waterScreen" class="container py-4 flex-column h-100 d-none justify-content-center align-items-center" style="position: relative;"> <h1 class="text-primary mb-3"><i class="fa-solid fa-droplet"></i> Doplňování vody</h1> <h4 class="mb-5 text-secondary">Drž tlačítko a opatrně zalévej!</h4> <div class="progress shadow-lg mb-5 w-100" style="height: 60px; max-width: 500px; border: 4px solid #0d6efd; border-radius: 20px;"> <div id="waterProgressBar" class="progress-bar progress-bar-striped progress-bar-animated bg-primary fs-3 fw-bold" role="progressbar" style="width: 0%;">0 %</div> </div> <button id="waterBtn" class="btn btn-primary shadow-lg rounded-circle d-flex align-items-center justify-content-center action-btn" style="width: 250px; height: 250px; user-select: none;"> <div class="text-center"> <i id="wateringCan" class="fa-solid fa-fill-drip can-idle" style="font-size: 5rem;"></i> <h3 id="btnText" class="mt-3 fw-bold">DRŽ MĚ</h3> </div> </button> <button class="btn btn-outline-secondary mt-5" onclick="cancelWatering()"><i class="fa-solid fa-arrow-left"></i> Zrušit a odejít</button> </div> <div id="resultScreen" class="container py-4 flex-column h-100 d-none justify-content-center align-items-center text-center"> <i id="resultIcon" class="fa-solid fa-circle-check text-success" style="font-size: 8rem;"></i> <h1 id="resultTitle" class="mt-4 display-4 fw-bold">Hotovo!</h1> <h3 id="resultMessage" class="mt-3 text-secondary">Tvoje kytka má radost.</h3> <div class="spinner-border text-secondary mt-5" role="status"></div> <p class="mt-2 text-muted">Připravuji stanici pro dalšího hráče...</p> </div> </div> <style> .full-screen-app { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: 9999; display: flex; flex-direction: column; overflow: hidden; } body { user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; } .color-btn { width: 90px; height: 90px; border-radius: 25px; border: 4px solid rgba(0,0,0,0.1); transition: transform 0.1s; } .color-btn:active { transform: scale(0.9); } .bg-danger-flash { background-color: #dc3545 !important; transition: background-color 0.2s; } .action-btn { transition: transform 0.2s ease, background-color 0.2s ease; } .action-btn:active { transform: scale(1.05); } .can-idle { transform: rotate(0deg); transition: transform 0.3s ease-in-out; } .can-tilt { transform: rotate(45deg); transition: transform 0.3s ease-in-out; } </style> <script> forrestHubLib = ForrestHubLib.getInstance(false); const varPrefix = "flower_"; let currentPin = []; let targetFlowerId = ""; let targetFlowerData = null; let wateringInterval; let isWatering = false; let localWaterLevel = 0; let inactivityTimer = null; // Hlídač neaktivity function toggleFullscreen() { const el = document.documentElement; if (!document.fullscreenElement) { if (el.requestFullscreen) el.requestFullscreen(); else if (el.webkitRequestFullscreen) el.webkitRequestFullscreen(); else if (el.msRequestFullscreen) el.msRequestFullscreen(); } } document.addEventListener('fullscreenchange', () => { document.getElementById('fsBtn').style.display = document.fullscreenElement ? 'none' : 'block'; }); function addPinColor(color) { if (currentPin.length < 3) { currentPin.push(color); updatePinDisplay(); if (currentPin.length === 3) checkPinInDatabase(); } } function clearPin() { currentPin = []; updatePinDisplay(); } function updatePinDisplay() { const slots = document.querySelectorAll('.pin-slot'); slots.forEach((slot, index) => { if (currentPin[index]) { slot.style.backgroundColor = currentPin[index]; slot.classList.remove('bg-white'); } else { slot.style.backgroundColor = ''; slot.classList.add('bg-white'); } }); } async function checkPinInDatabase() { targetFlowerId = varPrefix + currentPin.join('_'); try { let exists = await forrestHubLib.dbVarKeyExists(targetFlowerId); if (exists) { targetFlowerData = await forrestHubLib.dbVarGetKey(targetFlowerId); if (targetFlowerData.status === "sick") { forrestHubLib.uiShowAlert('warning', 'Tvoje kytka je nemocná! Běž do Záchranné stanice.', 4000); setTimeout(clearPin, 2000); return; } // --- NOVÉ: OKAMŽITÉ ZABLOKOVÁNÍ TABLETU --- targetFlowerData.status = "busy"; await forrestHubLib.dbVarSetKey(targetFlowerId, targetFlowerData); prepareWateringScreen(); } else { forrestHubLib.uiShowAlert('danger', 'Tento kód neexistuje. Zkus to znovu.', 3000); setTimeout(clearPin, 1000); } } catch (error) { console.error(error); forrestHubLib.uiShowAlert('danger', 'Chyba serveru při ověřování PINu.', 3000); clearPin(); } } function resetInactivityTimer() { clearTimeout(inactivityTimer); // Pokud do 30 vteřin od posledního pohybu/začátku dítě nezalije nebo nezruší akci, zrušíme to automaticky inactivityTimer = setTimeout(cancelWatering, 30000); } function prepareWateringScreen() { localWaterLevel = targetFlowerData.water; updateProgressBar(); document.getElementById('waterProgressBar').classList.replace('bg-danger', 'bg-primary'); document.getElementById('pinScreen').classList.replace('d-flex', 'd-none'); document.getElementById('waterScreen').classList.replace('d-none', 'd-flex'); document.getElementById('wateringCan').className = "fa-solid fa-fill-drip can-idle"; document.getElementById('btnText').innerText = "DRŽ MĚ"; resetInactivityTimer(); } function updateProgressBar() { const bar = document.getElementById('waterProgressBar'); bar.style.width = `${Math.min(100, localWaterLevel)}%`; bar.innerText = `${localWaterLevel} %`; if (localWaterLevel > 100) bar.classList.replace('bg-primary', 'bg-danger'); } const waterBtn = document.getElementById('waterBtn'); waterBtn.addEventListener('contextmenu', e => e.preventDefault()); waterBtn.addEventListener('pointerdown', (e) => { e.preventDefault(); if (isWatering) return; isWatering = true; clearTimeout(inactivityTimer); // Přerušení odpočtu při držení tlačítka waterBtn.classList.replace('btn-primary', 'btn-info'); document.getElementById('wateringCan').classList.replace('can-idle', 'can-tilt'); document.getElementById('btnText').innerText = "ZALÉVÁM..."; wateringInterval = setInterval(() => { localWaterLevel += 1; updateProgressBar(); if (localWaterLevel >= 110) stopWatering(); }, 100); }); waterBtn.addEventListener('pointerup', stopWatering); waterBtn.addEventListener('pointerleave', stopWatering); waterBtn.addEventListener('pointercancel', stopWatering); async function stopWatering() { if (!isWatering) return; isWatering = false; clearInterval(wateringInterval); waterBtn.classList.replace('btn-info', 'btn-primary'); document.getElementById('wateringCan').classList.replace('can-tilt', 'can-idle'); document.getElementById('btnText').innerText = "DRŽ MĚ"; finalizeWatering(); } async function finalizeWatering() { targetFlowerData.water = localWaterLevel; let isOverwatered = false; // --- ZRUŠENÍ BLOKACE a PŘÍPADNÉ PŘELITÍ --- if (localWaterLevel > 100) { targetFlowerData.status = "sick"; isOverwatered = true; } else { targetFlowerData.status = "ok"; // Kytka už není busy } try { await forrestHubLib.dbVarSetKey(targetFlowerId, targetFlowerData); showResultScreen(isOverwatered); } catch (error) { forrestHubLib.uiShowAlert('danger', 'Chyba při ukládání vody.', 3000); cancelWatering(); // Záchranná brzda } } // --- MANUÁLNÍ / AUTOMATICKÉ ZRUŠENÍ (Uvolní tablet) --- async function cancelWatering() { clearTimeout(inactivityTimer); if (targetFlowerData) { targetFlowerData.status = "ok"; // Zpět do normálu await forrestHubLib.dbVarSetKey(targetFlowerId, targetFlowerData); } resetStation(); } function showResultScreen(isOverwatered) { document.getElementById('waterScreen').classList.replace('d-flex', 'd-none'); const resScreen = document.getElementById('resultScreen'); const icon = document.getElementById('resultIcon'); const title = document.getElementById('resultTitle'); const msg = document.getElementById('resultMessage'); resScreen.classList.replace('d-none', 'd-flex'); if (isOverwatered) { icon.className = "fa-solid fa-skull-crossbones text-danger"; title.innerText = "Přelito!"; title.className = "mt-4 display-4 fw-bold text-danger"; msg.innerText = "Rychle běž do Záchranné stanice, kytka se topí!"; appContainer.classList.add('bg-danger-flash'); } else { icon.className = "fa-solid fa-circle-check text-success"; title.innerText = "Zalito!"; title.className = "mt-4 display-4 fw-bold text-success"; msg.innerText = `Květina má teď ${localWaterLevel} % vody.`; } setTimeout(() => { appContainer.classList.remove('bg-danger-flash'); resetStation(); }, 4000); } function resetStation() { clearPin(); targetFlowerId = ""; targetFlowerData = null; localWaterLevel = 0; document.getElementById('resultScreen').classList.replace('d-flex', 'd-none'); document.getElementById('waterScreen').classList.replace('d-flex', 'd-none'); document.getElementById('pinScreen').classList.replace('d-none', 'd-flex'); } </script> {% endblock %}