From 6534de38112511a992bb3151564c5a01a01aab6c Mon Sep 17 00:00:00 2001 From: Vexure Date: Fri, 19 Jul 2024 19:18:16 +0300 Subject: [PATCH] reciever update + server-side top form --- client.css | 220 +++++++++++++++++++ client.js | 547 ++++++++++++++++++++++++++++++++++++++++++++++ dRec.php | 28 +++ data_reciever.php | 17 -- top.htm | 13 ++ 5 files changed, 808 insertions(+), 17 deletions(-) create mode 100644 client.css create mode 100644 client.js create mode 100644 dRec.php delete mode 100644 data_reciever.php create mode 100644 top.htm diff --git a/client.css b/client.css new file mode 100644 index 0000000..037b71d --- /dev/null +++ b/client.css @@ -0,0 +1,220 @@ +body { + text-align: center; +} + + #client-container { + min-width: 300px; + max-width: 326px; + min-height: 80px; + width: fit-content; + height: fit-content; + + border: 1px solid #112; + border-radius : 12px; + + font-family: ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji; + + display: block; + position: fixed; + z-index: 999; + } + + #client-top-header-game-date, #client-top-header-caption, #update-data-button { + padding: 3px; + padding-top: 6px; + padding-bottom: 2px; + display: block; + + font-size: 16px; + font-weight: 700; + } + + #client-top-header { + width: 100%; + margin-left: -1px; + margin-right: -1px; + margin-bottom: 6px; + border-radius: 12px 12px 0 0; + border-bottom: 1px solid #224; + + display: flex; + overflow: hidden; + z-index: 15; + } + + #client-top-header-game-date { + padding: 6px 6px 0px 12px; + font-size: 14px; + z-index: 8; + } + + #client-top-header-caption { + min-width: 150px; + margin-left: auto; + margin-right: auto; + font-size: 14px; + + order: 1; + + text-align: center; + } + + #update-data-button { + float: right; + margin-left: auto; + margin-right: -4px; + height: 32px; + width: 50px; + min-width: 32px; + order: 2; + + border-radius: 0 12px 0 0; + } + + #client-top-table { + min-width: 250px; + min-height: 60px; + padding: 6px 6px 1px 6px; + } + + .client-top-string { + padding-left: 9px; + padding-right: 9px; + min-height: 45px; + + font-weight: 800; + font-size: 21px; + border-radius : 6px; + margin-bottom: -12px; + + align-items: center; + display: flex; + } + + .client-top-string-place, .client-top-string-names, .client-top-string-score { + padding: 10; + overflow: hidden; + + display: inline-block; + + vertical-align: top; + justify-content: center; + } + + .client-top-string-place { + min-width: 36px; + + height: auto; + order: 0; + } + + + .client-top-string-names { + min-width: 200px; + max-width: 320px; + margin-left: auto; + order: 1; + } + + .client-top-string-score { + float: right; + min-width: 36px; + margin-left: auto; + order: 2; + } + + + + #client-extra-panel { + display: none; + position: absolute; + + width: 300px; + height: fit-content; + + background: gray; + + left: -310px; + top: 5px; + + z-index: 100; + border-radius: 5px; + } + + #client-extra-button { + width: 22px; + height: 24px; + left: -19px; + top: 5px; + position: absolute; + background-color: gray; + + font-weight: 700; + font-size: 21px; + + border-radius: 5px 0 0 5px; + z-index: 200; + } + + #client-select-colorSheme { + margin: 8px; + width: 140px; + height: 40px; + background-color: #224; + } + + #client-extra-textarea-messages { + width: 96%; + min-height: 50px; + height: 200px; + + margin-top: 5px; + + font-size: 13px; + background-color: #224; + } + + + #client-update-progress-bar { + width: 100%; + height: 5px; + } + + + #client-bottom-block { + width: 100%; + max-height: 32px; + border-radius: 0 0 12px 12px; + + font-weight: 700; + font-size: 12px; + + display: flex; + overflow: hidden; + z-index: 15; + } + + #client-bottom-block-update-time { + padding: 6px 6px 6px 10px; + z-index: 8; + } + + #client-bottom-block-last-message { + min-width: 100px; + margin-left: auto; + padding: 6px; + order: 1; + + text-align: center; + } + + #client-bottom-block-video-adress { + float: right; + margin-left: auto; + margin-right: -4px; + height: 32px; + max-width: 120px; + padding: 6px 10px 6px 6px; + text-align: right; + order: 2; + } \ No newline at end of file diff --git a/client.js b/client.js new file mode 100644 index 0000000..0f84a33 --- /dev/null +++ b/client.js @@ -0,0 +1,547 @@ + +// стартовые параметры формы +const initColorSheme = 'w2g-dark'; //'twilight'; +const autoUpdatingEnabled = false; +const setDefaultPositionOnResize = true; + +const topDataPath = './curgame'; +//const topDataPath = 'http://x96101uy.beget.tech/qclp/data'; + +var topData = {}; + +// Основной объект формы, содержит настройки и функцию смены цветовой схемы +// поля, содержащие ссылки на элементы формы, добавляются в initTopWindow() +var topWindow = { + colorScheme: initColorSheme, + autoUpdating: autoUpdatingEnabled, + setDefaultPositionOnResize: setDefaultPositionOnResize, + + addLogMessage : function (lMessage) { + this.messagesTextarea.value = "[" + getTimeNow() + "] " + lMessage + "\r" + this.messagesTextarea.value; + let bottomMessageBlock = document.querySelector("#client-bottom-block-last-message"); + if (bottomMessageBlock) bottomMessageBlock.innerHTML = lMessage; + }, + changeColorScheme : function (cShemeName) { + + if (cShemeName == 'twilight') { + this.colorScheme = 'twilight'; + topWindow.colorShemeSelect.value = this.colorScheme; + + let element = document.querySelector('body'); + element.style.backgroundColor = '#112'; + + element = document.querySelector('#client-container'); + element.style.backgroundColor = '#335'; + element.style.color = '#DDF'; + + element = document.querySelector('#client-extra-button'); + element.style.backgroundColor = '#232342'; + + element = document.querySelector('#client-extra-textarea-messages'); + element.style.backgroundColor = '#122332'; + element.style.color = '#DDF'; + + element = document.querySelector('#client-select-colorSheme'); + element.style.backgroundColor = '#122332'; + element.style.color = '#DDF'; + + element = document.querySelector('#client-extra-panel'); + element.style.backgroundColor = '#335'; + + element = document.querySelector('#client-top-header'); + element.style.backgroundColor = '#232342'; + element.style.borderBottom = '1px solid #224'; + + element = document.querySelector('#client-update-progress-bar'); + element.style.backgroundColor = '#2d3d63'; + + element = document.querySelector('#update-data-button'); + element.style.backgroundColor = '#335'; + + element = document.querySelector('#client-bottom-block'); + element.style.backgroundColor = '#232342'; + element.style.borderBottom = '1px solid #224'; + + element = document.querySelectorAll('.client-top-string').forEach(e => e.style.backgroundColor = '#557'); + } + + if (cShemeName == 'light') { + this.colorScheme = 'light'; + topWindow.colorShemeSelect.value = this.colorScheme; + + let element = document.querySelector('body'); + element.style.backgroundColor = '#FFFDFF'; + + element = document.querySelector('#client-container'); + element.style.backgroundColor = '#edf5ed'; + element.style.color = '#635'; + + element = document.querySelector('#client-extra-button'); + element.style.backgroundColor = '#ffebe1'; + element = document.querySelector('#client-extra-panel'); + element.style.backgroundColor = '#ffebe1'; + + element = document.querySelector('#client-extra-panel'); + element.style.backgroundColor = '#edf5ed'; + + element = document.querySelector('#client-extra-textarea-messages'); + element.style.backgroundColor = '#FFFDFF'; + element.style.color = '#635'; + + element = document.querySelector('#client-select-colorSheme'); + element.style.backgroundColor = '#FFFDFF'; + element.style.color = '#635'; + + element = document.querySelector('#client-top-header'); + element.style.backgroundColor = '#ffebe1'; + element.style.borderBottom = '1px solid #CCA'; + + element = document.querySelector('#client-update-progress-bar'); + element.style.backgroundColor = '#CdBdA3'; + + element = document.querySelector('#update-data-button'); + element.style.backgroundColor = '#edf5ed'; + + element = document.querySelector('#client-bottom-block'); + element.style.backgroundColor = '#ffebe1'; + element.style.borderBottom = '1px solid #CCA'; + + element = document.querySelectorAll('.client-top-string').forEach(e => { + e.style.backgroundColor = '#FAFAD5'; + }); + + } + + if (cShemeName == 'w2g-dark') { + this.colorScheme = 'w2g-dark'; + topWindow.colorShemeSelect.value = this.colorScheme; + + let element = document.querySelector('body'); + element.style.backgroundColor = '#112'; + + element = document.querySelector('#client-container'); + element.style.backgroundColor = '#3a4759'; + element.style.color = '#DDF'; + + element = document.querySelector('#client-extra-button'); + element.style.backgroundColor = '#283240'; + + element = document.querySelector('#client-extra-panel'); + element.style.backgroundColor = '#303d51'; + + element = document.querySelector('#client-extra-textarea-messages'); + element.style.backgroundColor = '#283240'; + element.style.color = '#DDF'; + + element = document.querySelector('#client-select-colorSheme'); + element.style.backgroundColor = '#283240'; + element.style.color = '#DDF'; + + element = document.querySelector('#client-top-header'); + element.style.backgroundColor = '#283240'; + element.style.borderBottom = '1px solid #224'; + + element = document.querySelector('#client-update-progress-bar'); + element.style.backgroundColor = '#2d3d63'; + + element = document.querySelector('#update-data-button'); + element.style.backgroundColor = '#293446'; + + element = document.querySelector('#client-bottom-block'); + element.style.backgroundColor = '#283240'; + element.style.borderBottom = '1px solid #224'; + + element = document.querySelectorAll('.client-top-string').forEach(e => e.style.backgroundColor = '#557'); + } + } +}; + + +// Объект для контроля обновлений +var updater = { + delay: 15000, + tick: 32, + counter: 1000, + check: function () { + if (this.counter > 0) { + this.counter -= this.tick; + } else { + loadTopData(topDataPath); + this.counter = this.delay; + topWindow.uBlock.style.width = '0%'; + } + + if (this.counter === 0) { topWindow.uBlock.style.width ='0%'; } + else { + topWindow.uBlock.style.width = 100 - (100 * (this.counter/this.delay)) + '%'; + } + + if (topWindow.autoUpdating) setTimeout(()=>{updater.check();}, this.tick); + } +}; + + +// Получаем время в формате "24:60:60" +var getTimeNow = function () { + var dNow = new Date(); + + let tnHours = dNow.getHours().toString(); + if (tnHours.length < 2) { tnHours = '0'+tnHours; } + let tnMinutes = dNow.getMinutes().toString(); + if (tnMinutes.length < 2) { tnMinutes = '0'+tnMinutes; } + let tnSeconds = dNow.getSeconds().toString(); + if (tnSeconds.length < 2) { tnSeconds = '0'+tnSeconds; } + + return tnHours + ":" + tnMinutes + ":" + tnSeconds; +}; + + +// ====================== НАЧАЛО initTopWindow ========================= +// ========= Инициализируем (встраиваем) основную форму топа =========== +var initTopWindow = function () { + var hBlock = document.querySelector('head'); + var bBlock = document.querySelector('body'); + + topWindow.cBlock = document.createElement('div'); + topWindow.cBlock.id = 'client-container'; + topWindow.cBlock.innerHTML = + "
" + +"
<
" + +"
"; + + topWindow.extraPanel = document.createElement('div'); + topWindow.extraPanel.id = 'client-extra-panel'; + topWindow.cBlock.appendChild(topWindow.extraPanel); + + topWindow.autoUpdateCheckbox = document.createElement('input'); + topWindow.autoUpdateCheckbox.id = 'client-auto-update-checkbox'; + topWindow.autoUpdateCheckbox.type = 'checkbox'; + topWindow.autoUpdateCheckbox.checked = topWindow.autoUpdating; + topWindow.autoUpdateCheckbox.addEventListener('change', () => { + if (topWindow.autoUpdateCheckbox.checked) { + topWindow.autoUpdating = true; + topWindow.addLogMessage("автообн. запущено"); + updater.check(); + } else { + topWindow.autoUpdating = false; + topWindow.addLogMessage("автообн. остановлено"); + } + }); + var AUcheckboxContainer = document.createElement('div'); + AUcheckboxContainer.id = "autoUpdateCheckboxContainer"; + AUcheckboxContainer.innerHTML += "AU  "; + AUcheckboxContainer.style.display = "inline-block"; + AUcheckboxContainer.appendChild(topWindow.autoUpdateCheckbox); + topWindow.extraPanel.appendChild(AUcheckboxContainer); + + topWindow.colorShemeSelect = document.createElement('select'); + topWindow.colorShemeSelect.id = 'client-select-colorSheme'; + topWindow.colorShemeSelect.value = initColorSheme; + topWindow.colorShemeSelect.setAttribute("list","colorSchemes"); + topWindow.colorShemeSelect.innerHTML = + "" + +"" + +"" + +"" + +""; + topWindow.colorShemeSelect.addEventListener('change', () => { + topWindow.changeColorScheme(topWindow.colorShemeSelect.value); + }); + topWindow.extraPanel.appendChild(topWindow.colorShemeSelect); + + topWindow.bottomPanelCheckbox = document.createElement('input'); + topWindow.bottomPanelCheckbox.id = 'client-show-bottom-panel-checkbox'; + topWindow.bottomPanelCheckbox.type = 'checkbox'; + topWindow.bottomPanelCheckbox.checked = true; + topWindow.bottomPanelCheckbox.addEventListener('change', () => { + if (topWindow.bottomPanelCheckbox.checked) { + topWindow.bottomBlock.style.display = "flex"; + } else { + topWindow.bottomBlock.style.display = "none"; + } + }); + var BPcheckboxContainer = document.createElement('div'); + BPcheckboxContainer.id = "bottomPanelCheckboxContainer"; + BPcheckboxContainer.style.display = "inline-block"; + BPcheckboxContainer.innerHTML += "  BP"; + BPcheckboxContainer.prepend(topWindow.bottomPanelCheckbox); + topWindow.extraPanel.appendChild(BPcheckboxContainer); + + topWindow.messagesTextarea = document.createElement('textarea'); + topWindow.messagesTextarea.id = 'client-extra-textarea-messages'; + topWindow.messagesTextarea.readOnly = true; + topWindow.extraPanel.appendChild(topWindow.messagesTextarea); + + bBlock.appendChild(topWindow.cBlock); + topWindow.eBtnText = document.querySelector('#client-extra-button-text'); + + topWindow.eBlockBtn = document.querySelector('#client-extra-button').addEventListener('click', (eBtn) => { + topWindow.ePanel = document.querySelector('#client-extra-panel'); + if (topWindow.ePanel.style.display == 'none') { + topWindow.ePanel.style.display = 'block'; + + topWindow.eBtnText.innerHTML = '>'; + } else { + topWindow.ePanel.style.display = 'none'; + topWindow.eBtnText.innerHTML = '<'; + } + }); + + topWindow.headerBlock = document.createElement('div'); + topWindow.headerBlock.id = 'client-top-header'; + topWindow.headerBlock.innerHTML = + "
32.13.46
" + +"
[Название]
" + +""; + topWindow.cBlock.appendChild(topWindow.headerBlock); + + topWindow.topBlock = document.createElement('div'); + topWindow.topBlock.id = 'client-top-table'; + topWindow.topBlock.innerHTML = ' ТОП '; + topWindow.cBlock.appendChild(topWindow.topBlock); + + topWindow.updateBlock = document.createElement('div'); + topWindow.updateBlock.innerHTML = + "
" + +"
" + +"
"; + topWindow.cBlock.appendChild(topWindow.updateBlock); + + topWindow.bottomBlock = document.createElement('div'); + topWindow.bottomBlock.id = 'client-bottom-block'; + topWindow.bottomBlock.innerHTML = + "
00.00.00
" + +"
" + +"
yt~dsfg4DF
"; + topWindow.cBlock.appendChild(topWindow.bottomBlock); + + topWindow.uBlock = document.querySelector('#client-update-progress-bar'); + + topWindow.w2gRightBlock = document.querySelector("#w2g-at-right"); + + document.querySelector('#client-bottom-block-update-time').innerHTML = '00:00:00'; + + document.querySelector('#update-data-button').addEventListener('click', () => { + loadTopData(topDataPath); + + updater.counter = updater.delay; + + }); + + topWindow.changeColorScheme(topWindow.colorScheme); + + makeDraggable(topWindow.cBlock); + + topWindow.setDefaultPositionOnResize = setDefaultPositionOnResize; + topWindow.setDefaultPosition(); + + topWindow.addLogMessage("окно инициализировано"); + + if (topWindow.autoUpdating) { + updater.check(); + topWindow.addLogMessage("автообн. запущено"); + } +}; +// ==================================================================== +// ====================== КОНЕЦ initTopWindow ========================== + + +// Сокрашаем полный адрес ютуб-видео до "yt~XXXXXXXX" +var getShortYTAdress = function(adress) { + let shortAdress = adress; + if (adress.search('youtube')>0) { + shortAdress = "yt~"+adress.split("?v=")[1]; + } + + return shortAdress; +} + + +// Импортируем полученные данные +var importData = function (tData) { + console.log('import start'); + var parsedData = JSON.parse(decodeURIComponent(escape(atob(tData)))); + + if (!parsedData.name) { + console.log('importing string not valid'); + } else { + console.log(parsedData); + topData = parsedData; + + updateTopTable(); + } +}; + + +// Подгружаем с сервера свежие данные +var loadTopData = function (tdPath) { + var XHR = new XMLHttpRequest(); + XHR.open('GET', tdPath); + XHR.setRequestHeader('Cache-Control', 'no-cache, no-store, max-age=8'); + XHR.onreadystatechange = function() { + if (XHR.readyState === XMLHttpRequest.DONE) { + let rText = XHR.responseText; + rText = JSON.parse(decodeURIComponent(escape(atob(rText)))); + + topData = rText; + + if (!topData.players) { + topWindow.addLogMessage("неверные данные"); + return; + } + + updateTopTable(); + + var dNow = new Date(); + let tnHours = dNow.getHours().toString(); + if (tnHours.length < 2) { tnHours = '0'+tnHours; } + let tnMinutes = dNow.getMinutes().toString(); + if (tnMinutes.length < 2) { tnMinutes = '0'+tnMinutes; } + let tnSeconds = dNow.getSeconds().toString(); + if (tnSeconds.length < 2) { tnSeconds = '0'+tnSeconds; } + + var tNow = getTimeNow(); + document.querySelector('#client-bottom-block-update-time').innerHTML = tNow; + document.querySelector('#client-top-header-caption').innerHTML = topData.name; + document.querySelector('#client-bottom-block-last-message').innerHTML = 'обновлено успешно'; + document.querySelector('#client-top-header-game-date').innerHTML = topData.date; + document.querySelector('#client-bottom-block-video-adress').innerHTML = getShortYTAdress(topData.videoAdress); + + topWindow.changeColorScheme(topWindow.colorScheme); + + if (topData.stopped) { + if (topData.stopped == true) { + topWindow.autoUpdating = false; + topWindow.autoUpdateCheckbox.checked = false; + topWindow.addLogMessage("остановлено хостом"); + } else topWindow.addLogMessage("счёт обновлен"); + } else topWindow.addLogMessage("счёт обновлен"); + } + }; + XHR.send(); +}; + + +// Перестраиваем таблицу топа с актуальной информацией +var updateTopTable = function() { + const sortFn = (a, b) => { + if (a.points < b.points) { return 1; + } else if (a.points > b.points) { return -1; } + return 0; + }; + + topData.players.sort(sortFn); + + topTable = document.querySelector("#client-top-table"); + topTable.innerHTML = ""; + + var placeN = 1; + for (let i = 0; i < topData.players.length; i++) { + + pString = "  "+placeN + " "; + if (placeN == 1) { pString = "🏆"; } + if (placeN == 2) { pString = "🥈"; } + if (placeN == 3) { pString = "🥉"; } + + topTable.innerHTML += + "
" + +"
"+pString+"
" + +"
" + +"
" + +"

"; + tpNameElement = document.querySelector("#top"+placeN+"-player-names"); + tpScoreElement = document.querySelector("#top"+placeN+"-score"); + + tpNameElement.innerHTML = topData.players[i].name; + tpScoreElement.innerHTML = topData.players[i].points; + + for (let j = i+1; j < topData.players.length; j++) { + if (topData.players[j].points >= topData.players[i].points) { + tpNameElement.innerHTML += " " + topData.players[j].name; + i = i+1; + } + } + placeN += 1; + } + + if (document.URL.search("w2g.tv")>0) { + topWindow.curColorSchemeName = 'w2g-dark'; + } + + topWindow.changeColorScheme(topWindow.curColorSchemeName); +}; + + +function makeDraggable (element) { + // Make an element draggable (or if it has a .window-top class, drag based on the .window-top element) + let currentPosX = 0, currentPosY = 0, previousPosX = 0, previousPosY = 0; + + // If there is a window-top classed element, attach to that element instead of full window + if (element.querySelector('#client-top-header')) { + // If present, the window-top element is where you move the parent element from + element.querySelector('#client-top-header').onmousedown = dragMouseDown; + } + else { + // Otherwise, move the element itself + element.onmousedown = dragMouseDown; + } + + function dragMouseDown (e) { + // Prevent any default action on this element (you can remove if you need this element to perform its default action) + e.preventDefault(); + // Get the mouse cursor position and set the initial previous positions to begin + previousPosX = e.clientX; + previousPosY = e.clientY; + // When the mouse is let go, call the closing event + document.onmouseup = closeDragElement; + // call a function whenever the cursor moves + document.onmousemove = elementDrag; + } + + function elementDrag (e) { + // Prevent any default action on this element (you can remove if you need this element to perform its default action) + e.preventDefault(); + // Calculate the new cursor position by using the previous x and y positions of the mouse + currentPosX = previousPosX - e.clientX; + currentPosY = previousPosY - e.clientY; + // Replace the previous positions with the new x and y positions of the mouse + previousPosX = e.clientX; + previousPosY = e.clientY; + // Set the element's new position + element.style.top = (element.offsetTop - currentPosY) + 'px'; + element.style.left = (element.offsetLeft - currentPosX) + 'px'; + } + + function closeDragElement () { + // Stop moving when mouse button is released and release events + document.onmouseup = null; + document.onmousemove = null; + } +} + + +// Выравниваем форму по центру, либо по блоку w2g-at-right, если он есть +topWindow.setDefaultPosition = function() { + if (topWindow.setDefaultPositionOnResize) { + if (topWindow.w2gRightBlock != null) { + let bClientRect = topWindow.w2gRightBlock.getBoundingClientRect(); + topWindow.cBlock.style.left = (6+bClientRect.left).toString()+'px'; + topWindow.cBlock.style.top = (6+bClientRect.top).toString()+'px'; + } else { + topWindow.cBlock.style.left = (window.innerWidth/2 - topWindow.cBlock.offsetWidth/2) + 'px'; + topWindow.cBlock.style.top = (window.innerHeight/2 - topWindow.cBlock.offsetHeight/2) + 'px'; + } + } +} + + +window.addEventListener('load', () => { + // Запускаем ету шарманку + initTopWindow(); +}); + + +// Выравниваем форму по центру при ресайзе окна браузера +window.addEventListener('resize', () => { + topWindow.setDefaultPosition(); +}); \ No newline at end of file diff --git a/dRec.php b/dRec.php new file mode 100644 index 0000000..d8fa9a6 --- /dev/null +++ b/dRec.php @@ -0,0 +1,28 @@ +saveMark)) { + if ($data->type == "videos") { $savePath = "./vlist"; } + if ($data->type == "games") { $savePath = "./glist"; } + if ($data->type == "curgame") { $savePath = "./curgame"; } + + if ($savePath != "") { + file_put_contents($savePath, $data->data); + file_put_contents($savePath . "-sm", json_encode($data->saveMark)); + } + } else { + if ((strlen($data) > 10) && (strlen($data) < 500000)) file_put_contents("./data", $data); + } +} +catch(Throwable $ex) { + echo "ЕГГОГ"; +} + +?> \ No newline at end of file diff --git a/data_reciever.php b/data_reciever.php deleted file mode 100644 index 7d176f1..0000000 --- a/data_reciever.php +++ /dev/null @@ -1,17 +0,0 @@ - \ No newline at end of file diff --git a/top.htm b/top.htm new file mode 100644 index 0000000..604b5be --- /dev/null +++ b/top.htm @@ -0,0 +1,13 @@ + + + + + + + TOP + + + + + + \ No newline at end of file