diff --git a/README.md b/README.md index 7080c93..03b1dea 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,19 @@ # painel-debate -Painel para gerência de tempo e perguntas em debates para eleições. Você poderá utilizar como fonte para transmissões com OBS. + +Painel para gerência de tempo em debates para eleições. O sistema fornece links para uso múltiplo, que permite compartilhar o painel para outros usuários ou até mesmo utilizar como fonte para transmissões com OBS. ## Requisitos - + - um servidor Web com suporte a PHP ativo (pode ser Apache HTTP Server, nginx etc.); - suporte a SQLite no PHP; -- sistema operacional compatível (nos testes foram usados Windows e Linux); -- caso você deseje compartilhar os recursos de usuários externos, seu servidor Web deve estar com firewall configurado para ser acessível externamente. +- caso você deseje compartilhar os recursos de usuários externos, seu servidor Web deve estar acessível externamente (verifique seu firewall). ## Instalação -- Baixe os arquivos para seu diretório Web (`git clone https://github.com/TiagoDGomes/painel-debate.git`); +- Clone o projeto usando `git clone https://github.com/TiagoDGomes/painel-debate.git` em seu diretório Web (ou baixe [aqui](https://github.com/TiagoDGomes/painel-debate/releases/latest) a última versão); - Copie o arquivo `config.php-default` como `config.php`; -- Abra o arquivo `config.php` e configure a seu gosto: -- verifique se há permissões de escrita para a pasta "database" no arquivo de configuração (ex.: `chown -R www-data:www-data databases`); +- Edite o arquivo `config.php` e configure a seu gosto: +- Verifique se há permissões de escrita para a pasta "database" no arquivo de configuração (ex.: `chown -R www-data:www-data databases`); - Abra o navegador e navegue em http://seu-servidor/painel-debate/. ## Créditos diff --git a/core/core.php b/core/core.php index 4bff866..806aa69 100644 --- a/core/core.php +++ b/core/core.php @@ -1,13 +1,26 @@ - ⏸️ +
diff --git a/media/button.css b/media/button.css index 3570a2e..f3b6544 100644 --- a/media/button.css +++ b/media/button.css @@ -82,10 +82,10 @@ button.big .shadow { button.big .edge { position: absolute; - top: 0; + top: 2px; left: 0; width: 100%; - height: 100%; + height: 95%; border-radius: 12px; background: linear-gradient(to left, #202020 0%, @@ -99,7 +99,7 @@ button.big .edge { button.big .front { display: block; position: relative; - padding: 12px 27px; + padding: 14px 27px; border-radius: 12px; font-size: 1.1rem; color: white; diff --git a/media/default.css b/media/default.css index 7d037fd..3b03927 100644 --- a/media/default.css +++ b/media/default.css @@ -8,6 +8,7 @@ --status-error-color: rgb(204, 0, 255); --status-color: rgba(87, 86, 86, 0.25); --status-font-color: rgba(255, 255, 255, 0.75); + --timer-sync-error-color: red; } a { @@ -55,6 +56,12 @@ body.timer-ending .container-timer { background-color: var(--timer-ending-color); } + +body.user.timer-sync.timer-sync-error, +body.timer-sync.timer-sync-error .container-timer{ + background-color: var(--timer-sync-error-color); +} + body.user.timer-semaphore.set, body.user.timer-ending.timer-alert, body.timer-semaphore.set .container-timer, @@ -161,6 +168,12 @@ i.icon { opacity: .5; } +button i.icon{ + width: 1em; + height: 1em; + opacity: 1; +} + i.icon:hover { opacity: 1; } @@ -171,4 +184,7 @@ i.icon.full-screen { i.icon.qrcode { background-image: url(qrcode.png); +} +i.icon.pause { + background-image: url(pause.svg); } \ No newline at end of file diff --git a/media/pause.svg b/media/pause.svg new file mode 100644 index 0000000..692fd37 --- /dev/null +++ b/media/pause.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + diff --git a/scripts/classes.js b/scripts/classes.js index 8968929..efdb776 100644 --- a/scripts/classes.js +++ b/scripts/classes.js @@ -1,5 +1,6 @@ var Timer = { localTime: 0, + localTimeMillis: 0, serverTimeMillis: 0, _syncing: false, pingCount: SYNC_PING_COUNT, @@ -9,6 +10,7 @@ var Timer = { endTime: null, preparedTime: null, updateFailed: false, + isSyncing: function () { return Timer._syncing; }, @@ -39,71 +41,92 @@ var Timer = { Timer.preparedTime = 0; Timer.startTime = 0; Timer.endTime = 0; - Timer.localTime = 0; Timer.serverTime = 0; + Timer.localTimeMillis = 0; Timer.serverTimeMillis = 0; Timer._syncCount = 0; Timer._diffServer = 0; Timer._diffSum = 0; Timer.setText(''); - Timer._syncTicTacLoop(function () { - - }); + Timer._syncTicTacLoop(function (resultSuccess) { }); }, - _syncTicTacLoop: function (callback_sync) { - HTTPRequest.getJSON('?timer=1&syncCount=' + Timer._syncCount + "&localTime=" + Timer.localTime, function (data) { - var diff = data['diff']; - Timer.serverTimeMillis = data['serverTimeMillis']; - if (diff != Timer.serverTimeMillis) { - Timer._diffSum += diff; - } - var diffToZero = Timer.serverTimeMillis % 1000; - Timer.localTime = Timer.serverTimeMillis; - Timer._syncCount++; - var nextTimeout = 1000 - diffToZero; - console.log("Timer._syncCount,diff, diffToZero, nextTimeout", Timer._syncCount, diff, diffToZero, nextTimeout); - setTimeout(function () { - if (Timer._syncCount >= Timer.pingCount) { - var avgDiff = Timer._diffSum / Timer._syncCount; - var miliRounded = Math.floor(avgDiff / 1000) * 1000; - Timer.localTime += miliRounded; - setTimeout(function () { - Timer.initTicTac(); - try { - callback_sync(); - } catch (e) { - console.error(e); - } - }, miliRounded - avgDiff * 2) - } else { - Timer._syncTicTacLoop(callback_sync); + _syncTicTacLoop: function (callback_result_success) { + HTTPRequest.getJSON('?timer=1&syncCount=' + Timer._syncCount + "&localTime=" + Timer.localTimeMillis, function (data) { + if (data === null){ + // console.error("Sincronização falhou."); + Timer._syncTicTacLoop(callback_result_success); + } else { + + var diff = data['diff']; + Timer.serverTimeMillis = data['serverTimeMillis']; + if (diff != Timer.serverTimeMillis) { + Timer._diffSum += diff; } - }, nextTimeout); + var diffToZero = Timer.serverTimeMillis % 1000; + Timer.localTimeMillis = Timer.serverTimeMillis + 1000; + Timer._syncCount++; + var nextTimeout = 1000 - diffToZero; + console.log("_syncCount ", Timer._syncCount, + "\ndiff ", diff, + "\ndiffToZero ", diffToZero, + "\n_diffSum ", Timer._diffSum, + "\nnextTimeout ", nextTimeout, + "\nserverTimeMillis ", Timer.serverTimeMillis, + "\nlocalTimeMillis ", Timer.localTimeMillis, + ); + + setTimeout(function () { + var requireNewPing = Timer._syncCount >= Timer.pingCount; + if (requireNewPing) { + var avgDiff = Timer._diffSum / Timer._syncCount; + var miliRounded = Math.floor(avgDiff / 1000) * 1000; + Timer.localTimeMillis += miliRounded; + setTimeout(function () { + Timer.initTicTac(); + try { + callback_result_success(true); + } catch (e) { + console.error(e); + } + }, miliRounded - avgDiff * 2) + } else { + Timer._syncTicTacLoop(callback_result_success); + } + }, nextTimeout); + } }); }, initTicTac: function () { - console.log('Timer.initTicTac'); + console.log("initTicTac:", + "\nTimer.localTime: ", Timer.localTime, + "\nTimer.serverTime: ", Timer.serverTime); Timer.setSyncing(false); delete Timer._syncCount; delete Timer._diffServer; delete Timer._diffSum; delete Timer.serverTimeMillis; - Timer.localTime = Math.round(Timer.localTime / 1000); - Timer._interval1s = setInterval(function () { - Timer.localTime += 1; - }, 1000); - Timer._interval1sUpdate = setInterval(function () { - Timer.updateData(); - Timer.refreshInterface(); - Status.setDebugMessage('L: ' + Timer.localTime + '\nS: ' + Timer.serverTime); - if (!Timer.isRunning() || !Timer.updateFailed) { - if (Math.abs(Timer.serverTime - Timer.localTime) >= 1.5 || Timer.localTime > Timer.serverTime) { - Timer.syncTicTac(); - } - } - }, 500); + Timer.localTime = Math.round(Timer.localTimeMillis / 1000); + Timer._interval1s = setInterval(Timer.tic, 1000); + Timer._interval1sUpdate = setInterval(Timer.updateTicTac, 500); Timer.updateData(Timer.refreshInterface); }, + tic: function(){ + Timer.localTime += 1; + Status.setDebugMessage('L: ' + Timer.localTime + '\nS: ' + Timer.serverTime); + }, + updateTicTac: function(){ + Timer.updateData(); + Timer.refreshInterface(); + if (Timer.isRunning()) { + //console.log('Timer is Running!'); + } else { + //console.log('Timer is not Running!'); + //console.log("Timer.serverTime: ", Timer.serverTime, "\nTimer.localTime: ", Timer.localTime) + if (Math.abs(Timer.serverTime - Timer.localTime) >= 1.5 || Timer.localTime > Timer.serverTime) { + Timer.syncTicTac(); + } + } + }, updateData: function (callback) { Property.getAll(function (data) { if (data) { @@ -113,7 +136,7 @@ var Timer = { Timer.serverTime = data['serverTimeMillis'] / 1000; Timer.updateFailed = false; } else { - Timer.updateFailed = true; + Timer.updateFailed = true; document.body.classList.add('timer-sync-error'); if (!Timer.isRunning) { Timer.syncTicTac(); @@ -234,8 +257,8 @@ var Timer = { return seconds >= 0 && seconds < 10; }, isRunning: function () { - seconds = Timer.getRemainingSeconds(); - return seconds > 0 && seconds < 86400; + seconds = Timer.getRemainingSecondsDiff(); + return seconds > -3 && seconds < 86400; }, isPrepared: function () { return Timer.endTime <= 0; @@ -261,6 +284,8 @@ var Timer = { } } +Timer.localTimeMillis = (new Date()).getTime(); + var Property = { getAll: function (callbackdata) { HTTPRequest.getJSON('?up=1', function (data) { @@ -302,7 +327,7 @@ var HTTPRequest = { var r = JSON.parse(xhr.responseText); callback_func(r); } catch (e) { - console.info(url, '\n', e, xhr.responseText); + //console.info(url, '\n', e, xhr.responseText); callback_func(null); } }