diff --git a/.idea/misc.xml b/.idea/misc.xml index d045e46..ca4614a 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,8 @@ + + \ No newline at end of file diff --git a/forester-game-app/app/custom_loader.py b/forester-game-app/app/custom_loader.py index bd32fe4..311b3be 100644 --- a/forester-game-app/app/custom_loader.py +++ b/forester-game-app/app/custom_loader.py @@ -1,31 +1,29 @@ import os -import sys +import pathlib +from pathlib import Path + from flask import current_app from jinja2 import FileSystemLoader, TemplateNotFound -def get_root_path(): - if getattr(sys, "frozen", False): - # we are running in a bundle - return sys._MEIPASS - else: - # we are running in a normal Python environment - return current_app.config["ROOT_DIR"] - - class CustomLoader(FileSystemLoader): def get_source(self, environment, template): - root_path = get_root_path() if template.startswith("templates/"): - template_path = os.path.join(root_path, "templates", template[10:]) + # {% include 'templates/header.html' %} + if current_app.config.get("LIVE_DATA_USED") and current_app.config.get("LIVE_DATA_FOLDER").exists(): + template_path = pathlib.Path(current_app.config["TEMPLATES_FOLDER_LIVE"]) / template[10:] + else: + template_path = pathlib.Path(current_app.config["TEMPLATES_FOLDER"]) / template[10:] + elif current_app.config.get("LIVE_DATA_USED") and Path(current_app.config["GAMES_FOLDER_LIVE"]).exists(): + template_path = pathlib.Path(current_app.config["GAMES_FOLDER_LIVE"]) / template else: - template_path = os.path.join(root_path, "pages", template) + template_path = pathlib.Path(current_app.config["GAMES_FOLDER"]) / template - if not os.path.exists(template_path): + if not template_path.exists(): raise TemplateNotFound(template) with open( - template_path, "r", encoding="utf-8" + template_path, "r", encoding="utf-8" ) as f: # Specify the encoding here source = f.read() mtime = os.path.getmtime(template_path) diff --git a/forester-game-app/app/database.py b/forester-game-app/app/database.py index 3a3f9d4..927c1c6 100644 --- a/forester-game-app/app/database.py +++ b/forester-game-app/app/database.py @@ -10,20 +10,30 @@ class DatabaseException(Exception): class Database: def __init__(self): + self.directory = None + self.file = None self.path_to_data = None self.data = {} - def init(self, path: str, file_name: str, clear_data: bool = False): - if not path or not os.path.exists(path): + def init(self, directory: str, file_name: str, clear_data: bool = False): + if not directory or not os.path.exists(directory): raise DatabaseException('Path is not provided or does not exist - Database.init()') if not file_name or not file_name.endswith('.json'): raise DatabaseException('File name is not provided or is not a JSON file - Database.init()') - self.path_to_data = os.path.join(path, file_name) + self.directory = directory + self.file = file_name + self.path_to_data = os.path.join(directory, file_name) if clear_data or not os.path.exists(self.path_to_data): self._write_data({}) self.data = self._read_data() + def get_directory(self): + return self.directory + + def get_file(self): + return self.file + def _write_data(self, data): with open(self.path_to_data, 'w') as f: json.dump(data, f) @@ -47,8 +57,8 @@ def overwrite_data_dict(self, new_data: dict): def get_data(self): return self.data - def get_data_key(self, key): - return self.data.get(key) + def get_data_key(self, key, default=None): + return self.data.get(key, default) def set_data_key(self, key, value): self.data[key] = value diff --git a/forester-game-app/app/init.py b/forester-game-app/app/init.py index ed80918..faa82c0 100644 --- a/forester-game-app/app/init.py +++ b/forester-game-app/app/init.py @@ -1,9 +1,8 @@ +from app.custom_loader import CustomLoader +from app.database import Database from flask import Flask from flask_cors import CORS from flask_socketio import SocketIO -from app.custom_loader import CustomLoader -from app.database import Database -import os socketio = SocketIO(cors_allowed_origins="*") db = Database() @@ -19,10 +18,19 @@ def create_app(config_class="config.Config"): db.init(app.config["ROOT_DIR"], app.config["DATAFILE"]) # Set custom Jinja loader - root_path = app.config["ROOT_DIR"] - app.jinja_loader = CustomLoader( - [os.path.join(root_path, "pages"), os.path.join(root_path, "templates")] - ) + + loader_locations = [ + app.config.get("GAMES_FOLDER"), + app.config.get("TEMPLATES_FOLDER"), + app.config.get("ASSETS_FOLDER"), + ] + + if app.config.get("LIVE_DATA_USED"): + loader_locations.append(app.config.get("GAMES_FOLDER_LIVE")) + loader_locations.append(app.config.get("TEMPLATES_FOLDER_LIVE")) + loader_locations.append(app.config.get("ASSETS_FOLDER_LIVE")) + + app.jinja_loader = CustomLoader(loader_locations) # Register Blueprints from app.routes import main as main_blueprint diff --git a/forester-game-app/app/routes.py b/forester-game-app/app/routes.py index d6c82a3..858cd19 100644 --- a/forester-game-app/app/routes.py +++ b/forester-game-app/app/routes.py @@ -1,10 +1,7 @@ -import os - -from flask import Blueprint, render_template, abort, send_from_directory, current_app, jsonify, request -from jinja2 import TemplateNotFound - from app.init import db from app.utils import get_local_ip_address +from flask import Blueprint, render_template, abort, send_from_directory, current_app, jsonify, request +from jinja2 import TemplateNotFound main = Blueprint('main', __name__) @@ -13,6 +10,7 @@ def index(): return render_template('menu/index.html') + @main.route('/download-data') def download_data(): return send_from_directory(current_app.config['ROOT_DIR'], current_app.config['DATAFILE'], as_attachment=True) @@ -34,21 +32,23 @@ def upload_data(): return jsonify({"status": "error", "message": "No selected file"}) allowed_extensions = current_app.config['ALLOWED_EXTENSIONS'] - if file and file.filename.rsplit('.', 1)[1].lower() in allowed_extensions: - print(f'Uploading file {file.filename} that will overwrite the current data') - db.overwrite_data_file(file) - return jsonify({"status": "success"}) - else: + if ( + not file + or file.filename.rsplit('.', 1)[1].lower() not in allowed_extensions + ): return jsonify({"status": "error", "message": f"Invalid file type - allowed extensions: {allowed_extensions}"}) + print(f'Uploading file {file.filename} that will overwrite the current data') + db.overwrite_data_file(file) + return jsonify({"status": "success"}) @main.route('//', defaults={'page': 'index'}) @main.route('//') -def render_page(folder, page): +def render_page(folder: str, page: str): try: # if page contains a dot, it is a file extension - serve as static file if '.' in page: - return send_from_directory(os.path.join(main.root_path, '..', 'pages'), f'{folder}/{page}') + return send_from_directory(current_app.config.get("GAMES_FOLDER"), f'{folder}/{page}') return render_template( f'{folder}/{page}.html', title=f'{folder.capitalize()}', @@ -66,5 +66,5 @@ def render_page(folder, page): # Serve static files @main.route('/assets/') def static_files(filename): - static_path = os.path.join(main.root_path, '..', 'assets') + static_path = current_app.config.get("ASSETS_FOLDER") return send_from_directory(static_path, filename) diff --git a/forester-game-app/app/socketio_events.py b/forester-game-app/app/socketio_events.py index b0daff7..7399c35 100644 --- a/forester-game-app/app/socketio_events.py +++ b/forester-game-app/app/socketio_events.py @@ -28,63 +28,56 @@ def handle_disconnect(): connected_clients -= 1 emit('update_clients', {'count': connected_clients}, broadcast=True) - -@socketio.on('game_start') -def handle_game_start(): +@socketio.on('get_game_status') +def handle_game_status(): global game_status - game_status = 'running' - emit('game_status', game_status, broadcast=True) - + emit('game_status', game_status) -@socketio.on('game_stop') -def handle_game_stop(): - global game_status - game_status = 'stopped' - emit('game_status', game_status, broadcast=True) -@socketio.on('game_pause') -def handle_game_pause(): +@socketio.on('set_game_status') +def handle_set_game_status(status: str): global game_status - game_status = 'paused' + game_status = status emit('game_status', game_status, broadcast=True) -@socketio.on('get_game_status') -def handle_game_status(): - emit('game_status', game_status) - - +@socketio.on('get_all_db') +def handle_get_all_data(data) -> dict: + return {'status': 'ok', 'data': db.get_data()} +@socketio.on('delete_all_db') +def handle_delete_all_data(data) -> dict: + db.overwrite_data_dict({}) + return {'status': 'ok'} +@socketio.on('set_key') +def handle_set_key(json: dict): + key = json.get('key') + value = json.get('value') + db.set_data_key(key, value) + return {'status': 'ok'} -@socketio.on('get_all') -def handle_get_all_data(): - return db.get_data() -@socketio.on('set') -def handle_set(json): +@socketio.on('set_key_broadcast') +def handle_set_key_broadcast(json: dict): key = json.get('key') value = json.get('value') db.set_data_key(key, value) - return {'status': 'success'} + emit(key, value, broadcast=True) + return {'status': 'ok'} -@socketio.on('get') -def handle_get(key): - return {'value': db.get_data_key(key)} +@socketio.on('exists_key') +def handle_exists_key(key: str) -> dict: + return {'status': 'ok', 'exists': db.get_data_key(key) is not None} -@socketio.on('edit_data') -def handle_edit_data(json): - key = json.get('key') - value = json.get('value') - if db.edit_data_key(key, value): - return {'status': 'success'} - return {'status': 'error', 'message': 'Key not found'} +@socketio.on('get_key') +def handle_get_key(key: str, default=None) -> dict: + return {'status': 'ok', 'data': db.get_data_key(key, default)} -@socketio.on('delete_data') -def handle_delete_data(key): - if db.delete_data_key(key): - return {'status': 'success'} - return {'status': 'error', 'message': 'Key not found'} +@socketio.on('delete_key') +def handle_delete_key(key: str) -> dict: + db.delete_data_key(key) + return {'status': 'ok'} diff --git a/forester-game-app/assets/js/foresterLib.js b/forester-game-app/assets/js/forrestHubLib.js similarity index 53% rename from forester-game-app/assets/js/foresterLib.js rename to forester-game-app/assets/js/forrestHubLib.js index cc887a0..f508ce5 100644 --- a/forester-game-app/assets/js/foresterLib.js +++ b/forester-game-app/assets/js/forrestHubLib.js @@ -1,4 +1,4 @@ -class ForesterLib { +class ForrestHubLib { // RUNNING = 1; RUNNING = "running"; PAUSED = "paused"; @@ -8,32 +8,30 @@ class ForesterLib { this.isGameMode = true; this.isAdmin = isAdmin; - if (typeof io === 'undefined') { throw new Error('Socket.io is not loaded.'); } this.socket = io.connect(url); - this.socket.on('connect', () => { + this.addEventListenerKey('connect', () => { console.log('Connected to the server!'); this.socket.emit('get_game_status'); this.removeOverlay(); }); - this.socket.on('disconnect', () => { + this.addEventListenerKey('disconnect', () => { console.log('Disconnected from the server.'); this.showOverlay('Byl jsi odpojen od serveru.
Hra nejspíš skončila nebo nastala neočekávaná chyba.', null, "danger", true); }); - this.socket.on('admin_messages', (message) => { + this.addEventListenerKey('admin_messages', (message) => { this.showOverlay(message, 5000, 'warning'); // Show for 5 seconds }); - this.socket.on('game_status', (status) => { + this.addEventListenerKey('game_status', (status) => { if (status === this.RUNNING) { this.removeOverlay(); if (this.isGameMode) { - // this.showOverlay('Hra spuštěna', 500, 'success'); this.showAlert('success', 'Hra spuštěna', 5000); } } else if (status === this.PAUSED) { @@ -45,27 +43,17 @@ class ForesterLib { } }); - - this.addEventListener("game_status", (data) => { - if (data === this.RUNNING) { - document.querySelectorAll(".game_status").forEach((element) => { - element.innerText = "Běží"; - }); - } else if (data === this.PAUSED) { - document.querySelectorAll(".game_status").forEach((element) => { - element.innerText = "Pozastavena"; - }); - } else if (data === this.STOPPED) { - document.querySelectorAll(".game_status").forEach((element) => { - element.innerText = "Ukončena"; - }); + this.addEventListenerKey('full_screen', async (data) => { + if (data === true) { + await document.documentElement.requestFullscreen(); } else { - document.querySelectorAll(".game_status").forEach((element) => { - element.innerText = "?"; - }); + await document.exitFullscreen(); } }); + this.addEventListenerKey("game_status", (data) => { + this.updateGameStatusUI(data); + }); } setAdmin(isAdmin) { @@ -76,84 +64,101 @@ class ForesterLib { this.isGameMode = isGameMode; } - set(key, value) { + emitWithResponse(event, data) { return new Promise((resolve, reject) => { - this.socket.emit('set', {key: key, value: value}, (response) => { - if (response.status === 'success') { + this.emit(event, data, (response) => { + if (response && response.status === 'ok') { resolve(response); } else { - console.error('Error setting value.'); - this.showOverlay('Nastala chyba při ukládání dat.', null); - reject(new Error('Error setting value')); + const message = `Chyba při zpracování události: ${event}`; + console.error(message); + this.showOverlay(message, null); + reject(new Error(message)); } }); }); } - get(key) { - return new Promise((resolve, reject) => { - this.socket.emit('get', key, (response) => { - if (response) { - resolve(response.value); - } else { - console.error('Error getting value'); - this.showOverlay('Nastala chyba při načítání dat.', null); - reject(new Error('Error getting value')); - } - }); - }); + /** + * Emit event with data and optional callback + * @param event + * @param data + * @param callback + */ + emit(event, data=null, callback = null) { + if (callback) { + this.socket.emit(event, data, callback); + } else { + this.socket.emit(event, data); + } } - getAll() { - return new Promise((resolve, reject) => { - this.socket.emit('get_all', (response) => { - if (response) { - resolve(response); - } else { - console.error('Error getting all data'); - this.showOverlay('Nastala chyba při načítání dat.', null); - reject(new Error('Error getting all data')); - } - }); - }); + /** + * Set key with value and return response + * @param key + * @param value + * @returns {Promise} + */ + async setKey(key, value) { + await this.emitWithResponse('set_key', { key, value }); + } + + async setKeyBroadcast(key, value) { + await this.emitWithResponse('set_key_broadcast', { key, value }); + } + + async getKey(key) { + const response = await this.emitWithResponse('get_key', key); + return response.data; + } + + async existKey(key) { + const response = await this.emitWithResponse('exist_key', key); + return !!response.exists; + } + + async deleteKey(key) { + await this.emitWithResponse('delete_key', key); } - addEventListener(eventKey, callback) { + addEventListenerKey(eventKey, callback) { this.socket.on(eventKey, (data) => { callback(data); }); } - edit(key, newValue) { - return new Promise((resolve, reject) => { - this.socket.emit('edit_data', {key: key, value: newValue}, (response) => { - if (response.status === 'success') { - resolve(response); - } else { - console.error('Error editing value.'); - reject(new Error('Error editing value')); - } - }); - }); + async getAllDatabase() { + const db = await this.emitWithResponse('get_all_db'); + return db.data || {}; } - delete(key) { - return new Promise((resolve, reject) => { - this.socket.emit('delete_data', key, (response) => { - if (response.status === 'success') { - resolve(response); - } else { - console.error('Error deleting value.'); - reject(new Error('Error deleting value')); - } - }); + async deleteAllDatabase() { + await this.emitWithResponse('delete_all_db'); + } + + updateGameStatusUI(status) { + let statusText = ""; + switch (status) { + case this.RUNNING: + statusText = "Běží"; + break; + case this.PAUSED: + statusText = "Pozastavena"; + break; + case this.STOPPED: + statusText = "Ukončena"; + break; + default: + statusText = "?"; + } + document.querySelectorAll(".game_status").forEach((element) => { + element.innerText = statusText; }); } showAlert(type, message, duration = 5000) { const alertDiv = document.createElement('div'); alertDiv.className = `alert alert-${type} alert-dismissible fade show`; - // keep alert on top of the page - allow scrolling alertDiv.style.position = 'fixed'; alertDiv.style.top = '0'; alertDiv.style.left = '50%'; @@ -169,14 +174,12 @@ class ForesterLib { setTimeout(() => alertDiv.remove(), duration); } - showOverlay(text, duration = null, status = 'info', forceShow = false) { - // do not show messages with duration on admin page if (this.isAdmin && !forceShow) { this.showAlert('info', `Zpráva: ${text}`, 5000); return; } - // Create overlay elements + let overlay = document.createElement('div'); let message = document.createElement('div'); let countdown = document.createElement('div'); @@ -214,13 +217,8 @@ class ForesterLib { overlay.appendChild(countdown); document.body.appendChild(overlay); - // if (!duration && !this.isGameMode) { - // duration = 5000; - // } - - // Countdown logic - if (duration) { - let remainingTime = duration / 1000; // convert to seconds + if (duration) { // duration in ms + let remainingTime = duration / 1000; countdown.innerText = `Zbývá ${remainingTime}s`; let countdownInterval = setInterval(() => { @@ -232,24 +230,6 @@ class ForesterLib { this.removeOverlay(); } }, 1000); - } else { - // slowly fade in and out in infinit loop - let opacity = 1; - let fadeIn = false; - let fadeInterval = setInterval(() => { - if (fadeIn) { - opacity += 0.0008; - if (opacity >= 0.96) { - fadeIn = false; - } - } else { - opacity -= 0.0008; - if (opacity <= 0.8) { - fadeIn = true; - } - } - overlay.style.backgroundColor = `rgba(5,5,0,${opacity})`; - }, 20); } } @@ -259,7 +239,4 @@ class ForesterLib { document.body.removeChild(overlay); } } - } - -// let foresterLib = new ForesterLib(); diff --git a/forester-game-app/config.py b/forester-game-app/config.py index c86d114..780d2de 100644 --- a/forester-game-app/config.py +++ b/forester-game-app/config.py @@ -1,29 +1,59 @@ import os import sys from app.utils import get_local_ip_address +import pathlib class Config: + VERSION = "1.1.0" DATAFILE = "data.json" LOG_FOLDER = "ForesterLogs" ALLOWED_EXTENSIONS = ["json"] + TEMPLATES_DIR = "templates" + GAMES_DIR = "games" + ASSETS_DIR = "assets" + + LIVE_DATA_DIR = "forester-live" IP_ADDRESS = get_local_ip_address() - VERSION = "1.1.0" + + DEBUG = True + USE_RELOADER = True if getattr(sys, "frozen", False): - # frozen - ROOT_DIR = os.path.dirname(sys.executable) - TEMP_DIR = sys._MEIPASS - TEMPLATES_DIR = os.path.join(sys._MEIPASS, "templates") - STATIC_DIR = os.path.join(sys._MEIPASS, "static") + FROZEN = True PORT = 80 - DEBUG = False - USE_RELOADER = False + ROOT_DIR = pathlib.Path(sys.executable).parent + DATA_DIR = sys._MEIPASS else: - ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) - TEMP_DIR = "-" - TEMPLATES_DIR = os.path.join(ROOT_DIR, "templates") - STATIC_DIR = os.path.join(ROOT_DIR, "static") + FROZEN = False PORT = 4444 - DEBUG = True - USE_RELOADER = True + ROOT_DIR = pathlib.Path(__file__).parent + DATA_DIR = ROOT_DIR + + # use live data if it exists + LIVE_DATA_FOLDER = pathlib.Path(ROOT_DIR) / LIVE_DATA_DIR + TEMPLATES_FOLDER = pathlib.Path(ROOT_DIR) / TEMPLATES_DIR + GAMES_FOLDER = pathlib.Path(ROOT_DIR) / GAMES_DIR + ASSETS_FOLDER = pathlib.Path(ROOT_DIR) / ASSETS_DIR + LIVE_DATA_USED = False + + if LIVE_DATA_FOLDER.exists(): + LIVE_DATA_USED = True + TEMPLATES_FOLDER_LIVE = pathlib.Path(LIVE_DATA_FOLDER) / TEMPLATES_DIR + GAMES_FOLDER_LIVE = pathlib.Path(LIVE_DATA_FOLDER) / GAMES_DIR + ASSETS_FOLDER_LIVE = pathlib.Path(LIVE_DATA_FOLDER) / ASSETS_DIR + + # Disable debug and reloader when using frozen data with live data - production mode + if not LIVE_DATA_USED and FROZEN: + DEBUG = False + USE_RELOADER = False + +# check if exist TEMPLATES_DIR, STATIC_DIR, ASSETS_DIR + if not TEMPLATES_FOLDER.exists(): + raise FileNotFoundError(f"Templates folder not found: {TEMPLATES_FOLDER}") + + if not GAMES_FOLDER.exists(): + raise FileNotFoundError(f"Games folder not found: {GAMES_FOLDER}") + + if not ASSETS_FOLDER.exists(): + raise FileNotFoundError(f"Assets folder not found: {ASSETS_FOLDER}") diff --git a/forester-game-app/games/admin/index.css b/forester-game-app/games/admin/index.css new file mode 100644 index 0000000..e69de29 diff --git a/forester-game-app/pages/admin/index.html b/forester-game-app/games/admin/index.html similarity index 99% rename from forester-game-app/pages/admin/index.html rename to forester-game-app/games/admin/index.html index 7bea9fe..9e38cda 100644 --- a/forester-game-app/pages/admin/index.html +++ b/forester-game-app/games/admin/index.html @@ -83,7 +83,7 @@
Správa dat hry

Data hry jsou uložena v počítači: {{ config.ROOT_DIR }}/{{ config.DATAFILE }}

Veškerý informace jsou logovány do souboru: {{ config.ROOT_DIR }}/{{ config.LOG_FOLDER }}

Debug: {{ config.DEBUG }}

-

Temp: {{ config.TEMP_DIR }}

+

Root: {{ config.TEMP_DIR }}

diff --git a/forester-game-app/pages/admin/index.js b/forester-game-app/games/admin/index.js similarity index 71% rename from forester-game-app/pages/admin/index.js rename to forester-game-app/games/admin/index.js index 7671572..f42aaae 100644 --- a/forester-game-app/pages/admin/index.js +++ b/forester-game-app/games/admin/index.js @@ -1,25 +1,25 @@ -const foresterLib = new ForesterLib(); +const foresterLib = new ForrestHubLib(); foresterLib.setAdmin(true); foresterLib.setGameMode(false); let globalData = {}; -foresterLib.addEventListener("connect", async () => { +foresterLib.addEventListenerKey("connect", async () => { foresterLib.showAlert('success', 'Připojeno k serveru.'); await loadAndDisplayData(); - foresterLib.socket.emit('get_game_status'); + foresterLib.emit('get_game_status'); }); -setInterval(loadAndDisplayData, 2000); +setInterval(loadAndDisplayData, 1000); async function loadAndDisplayData() { try { - globalData = await foresterLib.getAll(); + globalData = await foresterLib.getAllDatabase(); displayData(); } catch (error) { - showAlert('danger', 'Error loading data: ' + error.message); + foresterLib.showAlert('danger', 'Error loading data: ' + error.message); } } @@ -123,7 +123,7 @@ async function saveData() { } try { - await foresterLib.edit(key, value); + await foresterLib.setKeyBroadcast(key, value); globalData[key] = value; // Update local data displayData(); // Refresh the display foresterLib.showAlert('success', `Value for ${key} updated successfully.`); @@ -134,19 +134,19 @@ async function saveData() { } async function deleteData(key) { - if (confirm(`Are you sure you want to delete ${key}?`)) { + if (confirm(`Opravdu si přeješ smazat data s klíčem: ${key}`)) { try { - await foresterLib.delete(key); + await foresterLib.deleteKey(key); delete globalData[key]; // Remove from local data displayData(); // Refresh the display - foresterLib.showAlert('success', `${key} deleted successfully.`); + foresterLib.showAlert('success', `Klíč '${key}' smazán úspěšně`); } catch (error) { - foresterLib.showAlert('danger', `Error deleting ${key}: ${error}`); + foresterLib.showAlert('danger', `Chyba mazání ${key}: ${error}`); } } } -foresterLib.addEventListener('update_clients', (data) => { +foresterLib.addEventListenerKey('update_clients', (data) => { document.getElementById('connected_clients').innerText = data.count; }); @@ -156,22 +156,22 @@ function sendAdminMessage() { foresterLib.socket.emit('send_admin_message', adminMessage.value); document.getElementById('lastAdminMessage').innerText = adminMessage.value; adminMessage.value = ''; - showAlert('success', 'Message sent successfully.'); + foresterLib.showAlert('success', 'Zpráva odeslána.'); } else { - showAlert('warning', 'Please enter a message before sending.'); + foresterLib.showAlert('warning', 'Napište nejprve zprávu.'); } } document.getElementById("game_start").addEventListener("click", function () { - foresterLib.socket.emit('game_start'); + foresterLib.emit("set_game_status", foresterLib.RUNNING); }); document.getElementById("game_pause").addEventListener("click", function () { - foresterLib.socket.emit('game_pause'); + foresterLib.emit('set_game_status', foresterLib.PAUSED); }); document.getElementById("game_stop").addEventListener("click", function () { - foresterLib.socket.emit('game_stop'); + foresterLib.emit('set_game_status', foresterLib.STOPPED); }); @@ -181,19 +181,7 @@ document.getElementById("download-button").addEventListener("click", function () document.getElementById("clear-button").addEventListener("click", async function () { if (confirm("Are you sure you want to clear all data? This action cannot be undone.")) { - try { - const response = await fetch('/clear-data', {method: 'POST'}); - const data = await response.json(); - if (data.status === "success") { - globalData = {}; // Clear local data - displayData(); // Refresh the display - showAlert('success', "Data successfully cleared."); - } else { - showAlert('danger', "An error occurred while clearing the data."); - } - } catch (error) { - showAlert('danger', "An error occurred while clearing the data."); - } + await foresterLib.deleteAllDatabase(); } }); @@ -206,45 +194,22 @@ document.getElementById("upload-button").addEventListener("click", async functio formData.append("file", file); try { - const response = await fetch("/upload_data", { + const response = await fetch("/upload-data", { method: "POST", body: formData }); const data = await response.json(); if (data.status === "success") { - showAlert('success', "Data successfully uploaded."); + foresterLib.showAlert('success', "Data successfully uploaded."); await loadAndDisplayData(); // Reload and display the new data } else { - showAlert('danger', "An error occurred while uploading the data."); + foresterLib.showAlert('danger', "An error occurred while uploading the data."); } } catch (error) { console.error("Error uploading file:", error); - showAlert('danger', "An error occurred while uploading the file."); + foresterLib.showAlert('danger', "An error occurred while uploading the file."); } } else { - showAlert('warning', "Please select a file to upload."); + foresterLib.showAlert('warning', "Please select a file to upload."); } }); - -function getParameterByName(name, url = window.location.href) { - name = name.replace(/[\[\]]/g, '\\$&'); - const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), - results = regex.exec(url); - if (!results) return null; - if (!results[2]) return ''; - return decodeURIComponent(results[2].replace(/\+/g, ' ')); -} - - - - -// Initialize tooltips -var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')) -var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { - return new bootstrap.Tooltip(tooltipTriggerEl) -}) - -// Load and display data when the page loads -// document.addEventListener('DOMContentLoaded', async () => { -// -// }); \ No newline at end of file diff --git a/forester-game-app/games/demo/decrement.css b/forester-game-app/games/demo/decrement.css new file mode 100644 index 0000000..e69de29 diff --git a/forester-game-app/games/demo/decrement.html b/forester-game-app/games/demo/decrement.html new file mode 100644 index 0000000..c671a11 --- /dev/null +++ b/forester-game-app/games/demo/decrement.html @@ -0,0 +1,12 @@ +{% extends "templates/base.html" %} +{% set game_name = "Demo - Snížení počítadla" %} +{% block content %} +
+

Demo úkázka použití šablony - podstránka

+

Počítadlo: ?

+ + +
+ Zpět na Demo +
+{% endblock %} diff --git a/forester-game-app/games/demo/decrement.js b/forester-game-app/games/demo/decrement.js new file mode 100644 index 0000000..9f20ad5 --- /dev/null +++ b/forester-game-app/games/demo/decrement.js @@ -0,0 +1,30 @@ +const foresterLib = new ForrestHubLib(); + +document.addEventListener('DOMContentLoaded', function () { + const counterElement = document.getElementById('counter'); + const decrementButton = document.getElementById('decrementButton'); + + // Načti počáteční hodnotu počítadla + foresterLib.getKey('my_number').then((value) => { + counterElement.innerText = value || 0; + }).catch((err) => { + console.error('Chyba při načítání počítadla:', err); + }); + + // Zvyšení počítadla po kliknutí + decrementButton.addEventListener('click', () => { + let currentValue = parseInt(counterElement.innerText, 10); + let newValue = currentValue - 1; + + foresterLib.setKeyBroadcast('my_number', newValue).then((response) => { + counterElement.innerText = newValue; + }).catch((err) => { + console.error('Chyba při ukládání počítadla:', err); + }); + }); + + // Automatické načítání změn v hodnotě počítadla + foresterLib.addEventListenerKey('my_number', (data) => { + counterElement.innerText = data || 0; + }); +}); \ No newline at end of file diff --git a/forester-game-app/games/demo/increment.css b/forester-game-app/games/demo/increment.css new file mode 100644 index 0000000..e69de29 diff --git a/forester-game-app/games/demo/increment.html b/forester-game-app/games/demo/increment.html new file mode 100644 index 0000000..43f6b36 --- /dev/null +++ b/forester-game-app/games/demo/increment.html @@ -0,0 +1,44 @@ +{% extends "templates/base.html" %} +{% block content %} +
+

Demo úkázka použití šablony

+

Počítadlo: ?

+ + +
+ Přejít na stránku snížení počítadla +
+ + +{% endblock %} diff --git a/forester-game-app/games/demo/increment.js b/forester-game-app/games/demo/increment.js new file mode 100644 index 0000000..0d14414 --- /dev/null +++ b/forester-game-app/games/demo/increment.js @@ -0,0 +1,30 @@ +// const foresterLib = new ForrestHubLib(); +// +// document.addEventListener('DOMContentLoaded', function () { +// const counterElement = document.getElementById('counter'); +// const incrementButton = document.getElementById('incrementButton'); +// +// // Načti počáteční hodnotu počítadla +// foresterLib.getKey('my_number').then((value) => { +// counterElement.innerText = value || 0; +// }).catch((err) => { +// console.error('Chyba při načítání počítadla:', err); +// }); +// +// // Zvyšení počítadla po kliknutí +// incrementButton.addEventListener('click', () => { +// let currentValue = parseInt(counterElement.innerText, 10); +// let newValue = currentValue + 1; +// +// foresterLib.setKeyBroadcast('my_number', newValue).then((response) => { +// counterElement.innerText = newValue; +// }).catch((err) => { +// console.error('Chyba při ukládání počítadla:', err); +// }); +// }); +// +// // Automatické načítání změn v hodnotě počítadla +// foresterLib.addEventListenerKey('my_number', (data) => { +// counterElement.innerText = data || 0; +// }); +// }); \ No newline at end of file diff --git a/forester-game-app/pages/menu/index.html b/forester-game-app/games/menu/index.html similarity index 100% rename from forester-game-app/pages/menu/index.html rename to forester-game-app/games/menu/index.html diff --git a/forester-game-app/games/posta/index.html b/forester-game-app/games/posta/index.html new file mode 100644 index 0000000..9b00063 --- /dev/null +++ b/forester-game-app/games/posta/index.html @@ -0,0 +1,63 @@ +{% extends "templates/base.html" %} +{% set game_name = "Pořadové číslo a čas" %} +{% block content %} +
+

Odesílání pořadového čísla a času

+

Pořadová čísla a časy:

+
    + +
    + + +{% endblock %} diff --git a/forester-game-app/pages/udavac/index.html b/forester-game-app/games/udavac/index.html similarity index 100% rename from forester-game-app/pages/udavac/index.html rename to forester-game-app/games/udavac/index.html diff --git a/forester-game-app/pages/udavac/kontrolor.css b/forester-game-app/games/udavac/kontrolor.css similarity index 100% rename from forester-game-app/pages/udavac/kontrolor.css rename to forester-game-app/games/udavac/kontrolor.css diff --git a/forester-game-app/pages/udavac/kontrolor.html b/forester-game-app/games/udavac/kontrolor.html similarity index 100% rename from forester-game-app/pages/udavac/kontrolor.html rename to forester-game-app/games/udavac/kontrolor.html diff --git a/forester-game-app/pages/udavac/kontrolor.js b/forester-game-app/games/udavac/kontrolor.js similarity index 97% rename from forester-game-app/pages/udavac/kontrolor.js rename to forester-game-app/games/udavac/kontrolor.js index 311d323..21e35f2 100644 --- a/forester-game-app/pages/udavac/kontrolor.js +++ b/forester-game-app/games/udavac/kontrolor.js @@ -1,4 +1,4 @@ -const foresterLib = new ForesterLib(); +const foresterLib = new ForrestHubLib(); const numberInput = document.querySelector('#number'); const checkButton = document.querySelector('#check'); diff --git a/forester-game-app/pages/udavac/udavac.css b/forester-game-app/games/udavac/udavac.css similarity index 100% rename from forester-game-app/pages/udavac/udavac.css rename to forester-game-app/games/udavac/udavac.css diff --git a/forester-game-app/pages/udavac/udavac.html b/forester-game-app/games/udavac/udavac.html similarity index 100% rename from forester-game-app/pages/udavac/udavac.html rename to forester-game-app/games/udavac/udavac.html diff --git a/forester-game-app/pages/udavac/udavac.js b/forester-game-app/games/udavac/udavac.js similarity index 97% rename from forester-game-app/pages/udavac/udavac.js rename to forester-game-app/games/udavac/udavac.js index b54d9cf..1616eea 100644 --- a/forester-game-app/pages/udavac/udavac.js +++ b/forester-game-app/games/udavac/udavac.js @@ -1,4 +1,4 @@ -const foresterLib = new ForesterLib(); +const foresterLib = new ForrestHubLib(); const numberInput = document.querySelector('#number'); const udavacButton = document.querySelector('#udavac'); diff --git a/forester-game-app/pages/admin/index.css b/forester-game-app/pages/admin/index.css deleted file mode 100644 index 5c3da28..0000000 --- a/forester-game-app/pages/admin/index.css +++ /dev/null @@ -1,7 +0,0 @@ -#alert-container { - position: fixed; - top: 0; - left: 0; - width: 100%; - z-index: 1050; /* Ensure it appears above other content */ -} \ No newline at end of file diff --git a/forester-game-app/pyinstaller.spec b/forester-game-app/pyinstaller.spec index c537906..828ed32 100644 --- a/forester-game-app/pyinstaller.spec +++ b/forester-game-app/pyinstaller.spec @@ -9,7 +9,7 @@ a = Analysis( datas=[ ('templates', 'templates'), ('assets', 'assets'), - ('pages', 'pages'), + ('games', 'games'), ('config.py', '.'), ('app', 'app'), ], diff --git a/forester-game-app/templates/head.html b/forester-game-app/templates/head.html index 94ef505..870e2de 100644 --- a/forester-game-app/templates/head.html +++ b/forester-game-app/templates/head.html @@ -12,3 +12,8 @@ + + + + +{##} diff --git a/forester-game-app/templates/menu.html b/forester-game-app/templates/menu.html index ae82bd7..1c636f0 100644 --- a/forester-game-app/templates/menu.html +++ b/forester-game-app/templates/menu.html @@ -2,6 +2,14 @@ +
    + Pošta +
    + +
    + Demo +
    + diff --git a/forester-game-app/templates/scripts.html b/forester-game-app/templates/scripts.html index 85adeb9..beefad5 100644 --- a/forester-game-app/templates/scripts.html +++ b/forester-game-app/templates/scripts.html @@ -1,5 +1,5 @@ - - - +{##} +{##} +{##} diff --git a/py-server-old/.idea/.gitignore b/py-server-old/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/py-server-old/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/py-server-old/.idea/inspectionProfiles/Project_Default.xml b/py-server-old/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 6a66008..0000000 --- a/py-server-old/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - \ No newline at end of file diff --git a/py-server-old/.idea/inspectionProfiles/profiles_settings.xml b/py-server-old/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/py-server-old/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/py-server-old/.idea/misc.xml b/py-server-old/.idea/misc.xml deleted file mode 100644 index a971a2c..0000000 --- a/py-server-old/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/py-server-old/.idea/modules.xml b/py-server-old/.idea/modules.xml deleted file mode 100644 index 66ad573..0000000 --- a/py-server-old/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/py-server-old/.idea/py-server.iml b/py-server-old/.idea/py-server.iml deleted file mode 100644 index 74d76ae..0000000 --- a/py-server-old/.idea/py-server.iml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/py-server-old/.idea/vcs.xml b/py-server-old/.idea/vcs.xml deleted file mode 100644 index 6c0b863..0000000 --- a/py-server-old/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/py-server-old/.vscode/settings.json b/py-server-old/.vscode/settings.json deleted file mode 100644 index 7826e12..0000000 --- a/py-server-old/.vscode/settings.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "python.languageServer": "Pylance", - "python.linting.pylintEnabled": false, - "python.analysis.diagnosticSeverityOverrides": { - "reportMissingModuleSource": "none" - }, - "python.analysis.extraPaths": [ - "", - "/Users/kuba/.vscode/extensions/joedevivo.vscode-circuitpython-0.1.20-darwin-arm64/stubs", - "/Users/kuba/Library/Application Support/Code/User/globalStorage/joedevivo.vscode-circuitpython/bundle/20230815/adafruit-circuitpython-bundle-py-20230815/lib" - ], - "circuitpython.board.version": null -} \ No newline at end of file diff --git a/py-server-old/components/database.py b/py-server-old/components/database.py deleted file mode 100644 index 984eb40..0000000 --- a/py-server-old/components/database.py +++ /dev/null @@ -1,16 +0,0 @@ -import json - -filename = "data.json" - -def load_data(): - try: - with open(filename, "r") as f: - if f.read() == "": - return {} - return json.load(f) - except FileNotFoundError: - return {} - -def save_data(data): - with open(filename, "w") as f: - json.dump(data, f) \ No newline at end of file diff --git a/py-server-old/components/flask_app.py b/py-server-old/components/flask_app.py deleted file mode 100644 index 0e92305..0000000 --- a/py-server-old/components/flask_app.py +++ /dev/null @@ -1,20 +0,0 @@ -from flask import Flask, render_template -import os - -# Get the absolute path to the root directory -ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) -TEMPLATES_DIR = os.path.join(ROOT_DIR, '..', 'templates') -STATIC_DIR = os.path.join(ROOT_DIR, '..', 'static') - -app = Flask(__name__, template_folder=TEMPLATES_DIR, static_folder=STATIC_DIR) - -@app.route('/') -def index(): - return render_template('index.html') - -@app.route('/game') -def game(): - return render_template('game.html') - -def run_flask_app(): - app.run(host='0.0.0.0', port=5000) diff --git a/py-server-old/components/gui_app.py b/py-server-old/components/gui_app.py deleted file mode 100644 index 9bfb82d..0000000 --- a/py-server-old/components/gui_app.py +++ /dev/null @@ -1,101 +0,0 @@ -import json -import sys - -from PyQt5.QtCore import Qt, QEvent -from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QTextEdit, - QPushButton, QHBoxLayout, QLabel, QSpinBox, - QTreeWidget, QTreeWidgetItem, QMessageBox) - -from .database import save_data -from .ws_lib import WebSocketServer -from .timer_widget import TimerWidget -from .database import load_data, save_data - -class SimpleApp(QWidget): - def __init__(self): - super().__init__() - self.init_ui() - - def init_ui(self): - # Main Layout - self.layout = QVBoxLayout() - - # Timer Configurator - self.timer_widget = TimerWidget() - self.layout.addWidget(self.timer_widget) - self.timer_widget.timeChanged.connect(self.handle_time_change) - - # Data Display - self.data_tree = QTreeWidget(self) - self.data_tree.setHeaderLabels(["Key", "Value"]) - self.data_tree.itemDoubleClicked.connect(self.edit_item) - - self.layout.addWidget(self.data_tree) - self.setLayout(self.layout) - - self.websocket_thread = WebSocketServer() - self.websocket_thread.messageReceived.connect(self.update_data) - self.websocket_thread.start() - - def load_tree_data(self): - store_data = load_data() # Load data from the database - self.update_data(store_data) - - def update_data(self, store_data): - self.data_tree.clear() - for key, value in store_data.items(): - item = QTreeWidgetItem(self.data_tree) - item.setText(0, key) - item.setText(1, str(value)) - item.setFlags(item.flags() | Qt.ItemIsEditable) # make the item editable - - def handle_time_change(self, time: str): - # Here, format the data as required to send over WebSocket - data = { - 'action': 'update_time', - 'payload': time - } - self.websocket_thread.send_data(data) - - def edit_item(self, item, column): - self.data_tree.editItem(item, column) - - # Save the edited data back to the database - store_data = {} - for index in range(self.data_tree.topLevelItemCount()): - item = self.data_tree.topLevelItem(index) - key = item.text(0) - value = item.text(1) - store_data[key] = value - save_data(store_data) - - def remove_selected_item(self): - selected_items = self.data_tree.selectedItems() - for item in selected_items: - index = self.data_tree.indexOfTopLevelItem(item) - self.data_tree.takeTopLevelItem(index) - - # Save the updated data back to the database after deletion - store_data = {} - for index in range(self.data_tree.topLevelItemCount()): - item = self.data_tree.topLevelItem(index) - key = item.text(0) - value = item.text(1) - store_data[key] = value - save_data(store_data) - - def closeEvent(self, event: QEvent): - """ - This method is automatically called when the window is closed. - """ - # Prompt user to confirm closure - reply = QMessageBox.question(self, 'Confirm Exit', - 'Are you sure you want to close the application?', - QMessageBox.Yes | QMessageBox.No, QMessageBox.No) - - if reply == QMessageBox.Yes: - # Close WebSocket thread - self.websocket_thread.terminate() - event.accept() # Confirm the close event - else: - event.ignore() # Ignore the close event \ No newline at end of file diff --git a/py-server-old/components/timer_widget.py b/py-server-old/components/timer_widget.py deleted file mode 100644 index bff5c00..0000000 --- a/py-server-old/components/timer_widget.py +++ /dev/null @@ -1,114 +0,0 @@ -import sys -import asyncio -import websockets -import json -from PyQt5.QtWidgets import QWidget, QVBoxLayout, QSpinBox, QLabel, QPushButton, QHBoxLayout -from PyQt5.QtCore import QTimer, Qt, pyqtSignal - -class TimerWidget(QWidget): - timeChanged = pyqtSignal(str) - - def __init__(self): - super().__init__() - self.init_ui() - self.remaining_seconds = 0 - - def init_ui(self): - self.layout = QVBoxLayout() - - # Time Configurator - self.timer_layout = QHBoxLayout() - self.hours_spin = QSpinBox(self) - self.hours_spin.setMaximum(23) - self.minutes_spin = QSpinBox(self) - self.minutes_spin.setMaximum(59) - self.seconds_spin = QSpinBox(self) - self.seconds_spin.setMaximum(59) - - self.timer_layout.addWidget(self.hours_spin) - self.timer_layout.addWidget(QLabel("H")) - self.timer_layout.addWidget(self.minutes_spin) - self.timer_layout.addWidget(QLabel("M")) - self.timer_layout.addWidget(self.seconds_spin) - self.timer_layout.addWidget(QLabel("S")) - - # Buttons - self.start_btn = QPushButton('Start', self) - self.start_btn.clicked.connect(self.start_timer) - self.pause_btn = QPushButton('Pause', self) - self.pause_btn.clicked.connect(self.pause_timer) - self.end_btn = QPushButton('End Game', self) - self.end_btn.clicked.connect(self.end_timer) - - self.timer_layout.addWidget(self.start_btn) - self.timer_layout.addWidget(self.pause_btn) - self.timer_layout.addWidget(self.end_btn) - - self.layout.addLayout(self.timer_layout) - self.setLayout(self.layout) - - # QTimer for the countdown - self.timer = QTimer(self) - self.timer.timeout.connect(self.update_timer) - - def start_timer(self): - hours = self.hours_spin.value() - minutes = self.minutes_spin.value() - seconds = self.seconds_spin.value() - - self.remaining_seconds = hours * 3600 + minutes * 60 + seconds - - self.hours_spin.setEnabled(False) - self.minutes_spin.setEnabled(False) - self.seconds_spin.setEnabled(False) - - if self.remaining_seconds <= 0: - self.timeChanged.emit("Hra běží") - return - - if not self.timer.isActive(): - self.timer.start(1000) - - def pause_timer(self): - self.timeChanged.emit("Zastaveno") - if self.timer.isActive(): - self.timer.stop() - - - def end_timer(self): - self.timer.stop() - self.remaining_seconds = 0 - self.update_time_display() - self.timeChanged.emit("Konec hry") - - self.hours_spin.setEnabled(True) - self.minutes_spin.setEnabled(True) - self.seconds_spin.setEnabled(True) - - def update_timer(self): - if self.remaining_seconds > 0: - self.remaining_seconds -= 1 - self.update_time_display() - self.send_time_data() # Send the remaining time via WebSocket - - if self.remaining_seconds == 0: - self.timer.stop() - else: - self.timer.stop() - self.end_timer() - - def update_time_display(self): - hours = self.remaining_seconds // 3600 - minutes = (self.remaining_seconds % 3600) // 60 - seconds = self.remaining_seconds % 60 - - self.hours_spin.setValue(hours) - self.minutes_spin.setValue(minutes) - self.seconds_spin.setValue(seconds) - - formatted_time = f"{hours:02}:{minutes:02}:{seconds:02}" - self.timeChanged.emit(formatted_time) - - def send_time_data(self): - data = {"action": "update_time", "time": self.remaining_seconds} - # Implement WebSocket logic here to send the data diff --git a/py-server-old/components/ws_lib.py b/py-server-old/components/ws_lib.py deleted file mode 100644 index a4c4682..0000000 --- a/py-server-old/components/ws_lib.py +++ /dev/null @@ -1,64 +0,0 @@ -import json -import asyncio -import websockets -from PyQt5.QtCore import QThread, pyqtSignal - -from .database import load_data, save_data - -class WebSocketServer(QThread): - messageReceived = pyqtSignal(dict) - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.clients = set() - - async def server(self, websocket, path): - self.clients.add(websocket) - try: - while True: - data = await websocket.recv() - print(f"Received: {data}") - - try: - message = json.loads(data) - action = message.get('action') - payload = message.get('payload', {}) - store_data = load_data() - - if action == "set": - key = payload.get('key') - value = payload.get('value') - store_data[key] = value - save_data(store_data) - response = {"status": "success", "message": f"Key '{key}' set to '{value}'."} - if action == "get": - key = payload.get('key') - value = store_data.get(key) - if value: - response = {"status": "success", "message": f"Value for '{key}' is '{value}'.", "payload": value} - else: - response = {"status": "error", "message": f"Key '{key}' not found."} - # else: - # response = {"status": "error", "message": f"Action '{action}' not found."} - await websocket.send(json.dumps(response)) - # self.messageReceived.emit(store_data) - except json.JSONDecodeError: - await websocket.send(json.dumps({"status": "error", "message": "Invalid JSON format."})) - - finally: - self.clients.remove(websocket) - - async def broadcast(self, message): - if self.clients: - tasks = [asyncio.create_task(client.send(json.dumps(message))) for client in self.clients] - await asyncio.wait(tasks) - - def send_data(self, data): - asyncio.run(self.broadcast(data)) - - def run(self): - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - start_server = websockets.serve(self.server, "0.0.0.0", 8765) - loop.run_until_complete(start_server) - loop.run_forever() diff --git a/py-server-old/data.json b/py-server-old/data.json deleted file mode 100644 index 0a5b5ea..0000000 --- a/py-server-old/data.json +++ /dev/null @@ -1 +0,0 @@ -{"kuba": "and"} \ No newline at end of file diff --git a/py-server-old/main.py b/py-server-old/main.py deleted file mode 100644 index 827e313..0000000 --- a/py-server-old/main.py +++ /dev/null @@ -1,18 +0,0 @@ -import sys -import webbrowser -from PyQt5.QtCore import QTimer -from PyQt5.QtWidgets import QApplication -from threading import Thread - -from components.gui_app import SimpleApp -from components.flask_app import run_flask_app - - -if __name__ == '__main__': - t = Thread(target=run_flask_app) - t.start() - QTimer.singleShot(1000, lambda: webbrowser.open("http://127.0.0.1:5000")) - qt_app = QApplication(sys.argv) - window = SimpleApp() - window.show() - sys.exit(qt_app.exec_()) diff --git a/py-server-old/static/client.js b/py-server-old/static/client.js deleted file mode 100644 index e0f73b6..0000000 --- a/py-server-old/static/client.js +++ /dev/null @@ -1,17 +0,0 @@ -const client = new WSClient(`ws://${window.location.hostname}:8765`); - -client.addEventListener("update_time", (count) => { - document.getElementById("update_time").textContent = "Game timer: " + count; -}); - -function setValue() { - let key = document.getElementById('setKey').value; - let value = document.getElementById('setValue').value; - client.setKeyValue(key, value); -} - -async function getValue() { - let key = document.getElementById('getKey').value; - const resp = await client.getKeyValue(key); - document.getElementById('response').innerHTML = resp; -} diff --git a/py-server-old/static/clientLib.js b/py-server-old/static/clientLib.js deleted file mode 100644 index 1b123b6..0000000 --- a/py-server-old/static/clientLib.js +++ /dev/null @@ -1,73 +0,0 @@ -class WSClient { - constructor(url) { - this.socket = new WebSocket(url); - this.setupListeners(); - this.eventListeners = {}; - } - - setupListeners() { - this.socket.onopen = () => console.log('WebSocket is connected.'); - this.socket.onerror = error => console.error(`WebSocket Error: ${error}`); - this.socket.onmessage = event => { - const responseData = JSON.parse(event.data); - console.log(responseData); - if (responseData.action) { - this.triggerEventListeners(responseData.action, responseData.payload); - } - }; - this.socket.onclose = event => { - if (event.wasClean) { - console.log(`Connection closed cleanly, code=${event.code}, reason=${event.reason}`); - } else { - console.error('Connection died'); - } - }; - } - - addEventListener(key, callback) { - if(!this.eventListeners[key]) { - this.eventListeners[key] = []; - } - this.eventListeners[key].push(callback); - } - - triggerEventListeners(key, data) { - if(this.eventListeners[key]) { - for(let callback of this.eventListeners[key]) { - callback(data); - } - } - } - - send(action, payload) { - return new Promise((resolve, reject) => { - const message = { - action: action, - payload: payload - }; - console.log("Sending message: ", message); - this.socket.send(JSON.stringify(message)); - - this.socket.onmessage = event => { - const responseData = JSON.parse(event.data); - if (responseData.status === 'success') { - resolve(responseData.payload); - } else { - reject(responseData.message); - } - }; - }); - } - - async getKeyValue(key) { - return await this.send("get", { key: key }); - } - - setKeyValue(key, value) { - this.send("set", { key: key, value: value }); - } - - close() { - this.socket.close(); - } -} diff --git a/py-server-old/static/game.js b/py-server-old/static/game.js deleted file mode 100644 index 971b867..0000000 --- a/py-server-old/static/game.js +++ /dev/null @@ -1,47 +0,0 @@ -const client = new WSClient(`ws://${window.location.hostname}:8765`); - -client.addEventListener("update_time", (count) => { - document.getElementById("update_time").textContent = "Herní čas: " + count; -}); - - -const numberInput = document.getElementById('number'); -const checkButton = document.getElementById('check'); -const addButton = document.getElementById('add'); -const resultDiv = document.getElementById('result'); - -checkButton.onclick = (() => { - let number = numberInput.value; - let numbersList = client.getKeyValue('numbersList') || []; - - if(number.length != 5 || isNaN(number)) { - resultDiv.innerHTML = 'Zadej čtyřmístné číslo'; - numberInput.value = ""; - setTimeout(() => { resultDiv.innerHTML = ''; }, 3000); - return; - } - - if (numbersList.includes(number)) { - resultDiv.innerHTML = 'Stůj'; - } else { - resultDiv.innerHTML = 'Můžeš dál'; - } - numberInput.value = ""; - setTimeout(() => { resultDiv.innerHTML = ''; }, 3000); -}); - -addButton.click(() => { - let number = numberInput.value; - let numbersList = client.getKeyValue('numbersList') || []; - - // is it number? - if (number.length == 5 && !isNaN(number)) { - numbersList.push(number); - client.setKeyValue('numbersList', numbersList); - resultDiv.innerHTML = 'Přidáno'; - } else { - resultDiv.innerHTML = 'Zadej čtyřmístné číslo'; - } - numberInput.value = ""; - setTimeout(() => { resultDiv.innerHTML = ''; }, 3000); -}); \ No newline at end of file diff --git a/py-server-old/static/reconnecting-websocket.min.js b/py-server-old/static/reconnecting-websocket.min.js deleted file mode 100644 index a1e2279..0000000 --- a/py-server-old/static/reconnecting-websocket.min.js +++ /dev/null @@ -1,2 +0,0 @@ -// BOOO! -!function(a,b){"function"==typeof define&&define.amd?define([],b):"undefined"!=typeof module&&module.exports?module.exports=b():a.ReconnectingWebSocket=b()}(this,function(){function a(b,c,d){function l(a,b){var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,!1,!1,b),c}var e={debug:!1,automaticOpen:!0,reconnectInterval:1e3,maxReconnectInterval:3e4,reconnectDecay:1.5,timeoutInterval:2e3};d||(d={});for(var f in e)this[f]="undefined"!=typeof d[f]?d[f]:e[f];this.url=b,this.reconnectAttempts=0,this.readyState=WebSocket.CONNECTING,this.protocol=null;var h,g=this,i=!1,j=!1,k=document.createElement("div");k.addEventListener("open",function(a){g.onopen(a)}),k.addEventListener("close",function(a){g.onclose(a)}),k.addEventListener("connecting",function(a){g.onconnecting(a)}),k.addEventListener("message",function(a){g.onmessage(a)}),k.addEventListener("error",function(a){g.onerror(a)}),this.addEventListener=k.addEventListener.bind(k),this.removeEventListener=k.removeEventListener.bind(k),this.dispatchEvent=k.dispatchEvent.bind(k),this.open=function(b){h=new WebSocket(g.url,c||[]),b||k.dispatchEvent(l("connecting")),(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","attempt-connect",g.url);var d=h,e=setTimeout(function(){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","connection-timeout",g.url),j=!0,d.close(),j=!1},g.timeoutInterval);h.onopen=function(){clearTimeout(e),(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onopen",g.url),g.protocol=h.protocol,g.readyState=WebSocket.OPEN,g.reconnectAttempts=0;var d=l("open");d.isReconnect=b,b=!1,k.dispatchEvent(d)},h.onclose=function(c){if(clearTimeout(e),h=null,i)g.readyState=WebSocket.CLOSED,k.dispatchEvent(l("close"));else{g.readyState=WebSocket.CONNECTING;var d=l("connecting");d.code=c.code,d.reason=c.reason,d.wasClean=c.wasClean,k.dispatchEvent(d),b||j||((g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onclose",g.url),k.dispatchEvent(l("close")));var e=g.reconnectInterval*Math.pow(g.reconnectDecay,g.reconnectAttempts);setTimeout(function(){g.reconnectAttempts++,g.open(!0)},e>g.maxReconnectInterval?g.maxReconnectInterval:e)}},h.onmessage=function(b){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onmessage",g.url,b.data);var c=l("message");c.data=b.data,k.dispatchEvent(c)},h.onerror=function(b){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onerror",g.url,b),k.dispatchEvent(l("error"))}},1==this.automaticOpen&&this.open(!1),this.send=function(b){if(h)return(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","send",g.url,b),h.send(b);throw"INVALID_STATE_ERR : Pausing to reconnect websocket"},this.close=function(a,b){"undefined"==typeof a&&(a=1e3),i=!0,h&&h.close(a,b)},this.refresh=function(){h&&h.close()}}return a.prototype.onopen=function(){},a.prototype.onclose=function(){},a.prototype.onconnecting=function(){},a.prototype.onmessage=function(){},a.prototype.onerror=function(){},a.debugAll=!1,a.CONNECTING=WebSocket.CONNECTING,a.OPEN=WebSocket.OPEN,a.CLOSING=WebSocket.CLOSING,a.CLOSED=WebSocket.CLOSED,a}); diff --git a/py-server-old/templates/game.html b/py-server-old/templates/game.html deleted file mode 100644 index 2661c96..0000000 --- a/py-server-old/templates/game.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - Game - - - -

    - - - -
    - - - - - diff --git a/py-server-old/templates/index.html b/py-server-old/templates/index.html deleted file mode 100644 index 93844e5..0000000 --- a/py-server-old/templates/index.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - WebSocket Client - - - - - -

    WebSocket Client

    - -

    Waiting for countdown...

    - -

    Set Key Value

    - Key: - Value: - - -

    Get Key Value

    - Key: - - -

    Response:

    -

    - - - - diff --git a/py-socket-server/.idea/.gitignore b/py-socket-server/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/py-socket-server/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/py-socket-server/.idea/inspectionProfiles/Project_Default.xml b/py-socket-server/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 6a66008..0000000 --- a/py-socket-server/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - \ No newline at end of file diff --git a/py-socket-server/.idea/inspectionProfiles/profiles_settings.xml b/py-socket-server/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/py-socket-server/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/py-socket-server/.idea/misc.xml b/py-socket-server/.idea/misc.xml deleted file mode 100644 index a971a2c..0000000 --- a/py-socket-server/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/py-socket-server/.idea/modules.xml b/py-socket-server/.idea/modules.xml deleted file mode 100644 index 78f230c..0000000 --- a/py-socket-server/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/py-socket-server/.idea/py-socket-server.iml b/py-socket-server/.idea/py-socket-server.iml deleted file mode 100644 index 18e7513..0000000 --- a/py-socket-server/.idea/py-socket-server.iml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/py-socket-server/.idea/vcs.xml b/py-socket-server/.idea/vcs.xml deleted file mode 100644 index 6c0b863..0000000 --- a/py-socket-server/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/py-socket-server/Makefile b/py-socket-server/Makefile deleted file mode 100644 index 6210b72..0000000 --- a/py-socket-server/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -build-window: - pyinstaller --onefile --add-data 'templates;templates' --add-data 'static;static' --icon=static\forester.ico --name="Forester" .\main.py - -build-linux: - pyinstaller --onefile --add-data 'templates:templates' --add-data 'static:static' main.py \ No newline at end of file diff --git a/py-socket-server/data.json b/py-socket-server/data.json deleted file mode 100644 index d932dd9..0000000 --- a/py-socket-server/data.json +++ /dev/null @@ -1 +0,0 @@ -{"numbersList": ["1234", "2352", "7890", "9876", "8765", "5643", "4554"]} \ No newline at end of file diff --git a/py-socket-server/database.py b/py-socket-server/database.py deleted file mode 100644 index 89ad95e..0000000 --- a/py-socket-server/database.py +++ /dev/null @@ -1,30 +0,0 @@ -import json -import os - -from werkzeug.datastructures import FileStorage - - -class Database: - def __init__(self, path: str, file_name: str): - self.pathToData = os.path.join(path, file_name) - if not os.path.exists(self.pathToData): - self._write_data({}) - - def _write_data(self, data): - with open(self.pathToData, 'w') as f: - json.dump(data, f) - - def read_data(self): - with open(self.pathToData, 'r') as f: - try : - data = json.load(f) - except json.decoder.JSONDecodeError: - data = {} - return data - - def write_data(self, new_data): - self._write_data(new_data) - - def save_file(self, file: FileStorage): - file.save(self.pathToData) - return self.read_data() diff --git a/py-socket-server/main.py b/py-socket-server/main.py deleted file mode 100644 index bf5dba9..0000000 --- a/py-socket-server/main.py +++ /dev/null @@ -1,152 +0,0 @@ -# Web-game-engine is a simple web platform allowing you to design multiplayer games that communicate over a local network. -# This is the server-side code that runs on the host computer. This code is written in Python and uses Flask and SocketIO. -# The client-side code is written in JavaScript, and it is served by the server-side code. - -import webbrowser -from werkzeug.utils import secure_filename -from flask import Flask, render_template, jsonify, send_from_directory, request -from flask_socketio import SocketIO, emit -from engineio.async_drivers import gevent -import json -import os -import sys -import socket -from database import Database - -PORT = 80 -DATAFILE = 'data.json' - -ALLOWED_EXTENSIONS = {'json'} - -if getattr(sys, 'frozen', False): - # frozen - ROOT_DIR = os.path.dirname(sys.executable) - TEMPLATES_DIR = os.path.join(sys._MEIPASS, 'templates') - STATIC_DIR = os.path.join(sys._MEIPASS, 'static') - DEBUG = False -else: - ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) - TEMPLATES_DIR = os.path.join(ROOT_DIR, 'templates') - STATIC_DIR = os.path.join(ROOT_DIR, 'static') - DEBUG = True - -app = Flask(__name__, template_folder=TEMPLATES_DIR, static_folder=STATIC_DIR) -socketio = SocketIO(app, cors_allowed_origins="*") - -# Initialize the database -db = Database(ROOT_DIR, DATAFILE) -data_storage = db.read_data() - -# Function to get the local network IP address -def get_local_ip_address(): - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.connect(("8.8.8.8", 80)) - ip_address = s.getsockname()[0] - s.close() - return ip_address - -# Get local IP -local_ip = f'http://{get_local_ip_address()}:{PORT}' - -@app.route('/') -def index(): - return render_template('index.html') - -@app.route('/udavac') -def udavac(): - return render_template('udavac.html') - -@app.route('/admin') -def admin(): - return render_template('admin.html', data=data_storage, ip_address=local_ip) - -@app.route('/download_data') -def download_data(): - return send_from_directory(ROOT_DIR, DATAFILE, as_attachment=True) - -@app.route('/clear_data') -def clear_data(): - global data_storage - data_storage = {} - db.write_data(data_storage) - return jsonify({"status": "success"}) - -def allowed_file(filename): - return '.' in filename and \ - filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS - -@app.route('/upload_data', methods=['POST']) -def upload_data(): - global data_storage - if 'file' not in request.files: - return jsonify({"status": "error", "message": "No file part"}) - file = request.files['file'] - - if file.filename == '': - return jsonify({"status": "error", "message": "No selected file"}) - - if file and allowed_file(file.filename): - print(f'Uploading file {file.filename} that will overwrite the current data') - data_storage= db.save_file(file) - - return jsonify({"status": "success"}) - else: - return jsonify({"status": "error", "message": "Invalid file type"}) - -@socketio.on('send_admin_message') -def handle_admin_message(message): - emit('admin_messages', message, broadcast=True) - -connected_clients = 0 -@socketio.on('connect') -def handle_connect(): - global connected_clients - connected_clients += 1 - emit('update_clients', {'count': connected_clients}, broadcast=True) - -@socketio.on('disconnect') -def handle_disconnect(): - global connected_clients - connected_clients -= 1 - emit('update_clients', {'count': connected_clients}, broadcast=True) - -@socketio.on('set') -def handle_set(json): - key = json.get('key') - value = json.get('value') - data_storage[key] = value - db.write_data(data_storage) - return {'status': 'success'} - -@socketio.on('get') -def handle_get(key): - return {'value': data_storage.get(key)} - -@socketio.on('edit_data') -def handle_edit_data(json): - key = json.get('key') - value = json.get('value') - data_storage[key] = value - db.write_data(data_storage) - return {'status': 'success'} - -@socketio.on('delete_data') -def handle_delete_data(key): - if key in data_storage: - del data_storage[key] - db.write_data(data_storage) - return {'status': 'success'} - return {'status': 'error', 'message': 'Key not found'} - -if __name__ == '__main__': - if not DEBUG: - webbrowser.open(f'http://localhost:{PORT}/admin') - webbrowser.open(f'http://localhost:{PORT}') - - # stop the server with Ctrl-C - try: - print(f'Server started at {local_ip}') - socketio.run(app, debug=DEBUG, host='0.0.0.0', port=PORT) - except KeyboardInterrupt: - print('Server stopped') - sys.exit(0) diff --git a/py-socket-server/requieriments.txt b/py-socket-server/requieriments.txt deleted file mode 100644 index efb7e5d..0000000 --- a/py-socket-server/requieriments.txt +++ /dev/null @@ -1,5 +0,0 @@ -flask==2.3.3 -flask-socketio==5.3.5 -gevent==23.7.0 -gevent-websocket==0.10.1 -greenlet \ No newline at end of file diff --git a/py-socket-server/static/admin/script.js b/py-socket-server/static/admin/script.js deleted file mode 100644 index 50b4ea6..0000000 --- a/py-socket-server/static/admin/script.js +++ /dev/null @@ -1,109 +0,0 @@ -const adminClient = new SocketClient(); - -function editData(key) { - let newValue = prompt("Edit the value:", document.getElementById(key).innerText); - if (newValue != null) { - adminClient.edit(key, newValue); - document.getElementById(key).innerText = newValue; - } -} - -function deleteData(key) { - if (confirm('Are you sure you want to delete this?')) { - adminClient.delete(key); - location.reload(); - } -} - - -// Update the connected devices count when the event is received -adminClient.addEventListener('update_clients', (data) => { - document.getElementById('connected_clients').innerText = data.count; -}); - -function sendAdminMessage() { - const adminMessage = document.getElementById('adminMessage') - adminClient.socket.emit('send_admin_message', adminMessage.value); - document.getElementById('lastAdminMessage').innerText = adminMessage.value; - adminMessage.value = ''; -} - - -document.getElementById("download-button").addEventListener("click", function() { - window.location.href = "/download_data"; -}); - -document.getElementById("clear-button").addEventListener("click", function() { - if (window.confirm("Are you sure you want to clear all data?")) { - // Add AJAX call here to Flask endpoint that clears the data - fetch('/clear_data') - .then(response => response.json()) - .then(data => { - if (data.status === "success") { - alert("Data successfully cleared."); - // You can also add code here to update the UI to reflect the cleared data - } else { - alert("An error occurred while clearing the data."); - } - }); - } -}); - -document.getElementById("upload-button").addEventListener("click", function() { - const fileInput = document.getElementById("uploadFile"); - const file = fileInput.files[0]; - - if (file) { - const formData = new FormData(); - formData.append("file", file); - - fetch("/upload_data", { - method: "POST", - body: formData - }).then(response => response.json()) - .then(data => { - if (data.status === "success") { - alert("Data successfully uploaded."); - // Update the UI here if needed - } else { - alert("An error occurred while uploading the data."); - } - }).catch(error => { - console.error("Error uploading file:", error); - }); - } else { - alert("Please select a file to upload."); - } -}); - - -// Function to get URL parameters -function getParameterByName(name, url = window.location.href) { - name = name.replace(/[\[\]]/g, '\\$&'); - const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), - results = regex.exec(url); - if (!results) return null; - if (!results[2]) return ''; - return decodeURIComponent(results[2].replace(/\+/g, ' ')); -} - -// Add the "reload=true" parameter and reload the page -document.getElementById('startReload').addEventListener('click', function() { - window.location.href = window.location.pathname + '?reload=true'; -}); - -let reloadInterval; - -// Autonomously check for the "reload" parameter in the URL -if (getParameterByName('reload') === 'true') { - reloadInterval = setInterval(function() { - location.reload(); - }, 2000); -} - -// Add an event listener to the stop button to clear the reload interval and remove the URL parameter -document.getElementById('stopReload').addEventListener('click', function() { - clearInterval(reloadInterval); - // Remove the URL parameter - window.location.href = window.location.pathname; -}); diff --git a/py-socket-server/static/clientLib.js b/py-socket-server/static/clientLib.js deleted file mode 100644 index d55da0e..0000000 --- a/py-socket-server/static/clientLib.js +++ /dev/null @@ -1,140 +0,0 @@ -class SocketClient { - constructor(url = `http://${window.location.hostname}:80`) { - if (io === undefined) { - throw new Error('Socket.io is not loaded.'); - } - this.socket = io.connect(url); - - this.socket.on('connect', () => { - console.log('Connected to the server!'); - this.removeOverlay(); - }); - - this.socket.on('disconnect', () => { - console.log('Disconnected from the server.'); - this.showOverlay('Byl jsi odpojen od serveru.
    Hra nejspíš skončila nebo nastala neočekávaná chyba.', null); - }); - - this.socket.on('admin_messages', (message) => { - this.showOverlay(message, 5000); // Show for 5 seconds - }); - } - - set(key, value) { - this.socket.emit('set', { key: key, value: value }, (response) => { - if (response.status !== 'success') { - console.error('Error setting value.'); - this.showOverlay('Nastala chyba při ukládání dat.', null); - } - }); - } - - getCallback(key, callback) { - this.socket.emit('get', key, (response) => { - callback(response.value); - }); - } - - get(key) { - return new Promise((resolve, reject) => { - this.socket.emit('get', key, (response) => { - if (response) { - resolve(response.value); - } else { - reject('Error getting value'); - this.showOverlay('Nastala chyba při načítání dat.', null); - } - }); - }); - } - - addEventListener(eventKey, callback) { - this.socket.on(eventKey, (data) => { - callback(data); - }); - } - - edit(key, newValue) { - this.socket.emit('edit_data', { key: key, value: newValue }, (response) => { - if (response.status !== 'success') { - console.error('Error editing value.'); - } - }); - } - - delete(key) { - this.socket.emit('delete_data', key, (response) => { - if (response.status !== 'success') { - console.error('Error deleting value.'); - } - }); - } - - showOverlay(text, duration = null) { - // do not show messages with duration on admin page - if (window.location.pathname == '/admin' && duration) { - return; - } - // Create overlay elements - let overlay = document.createElement('div'); - let message = document.createElement('div'); - let countdown = document.createElement('div'); - - overlay.id = 'overlay'; - overlay.style.position = 'fixed'; - overlay.style.top = '0'; - overlay.style.left = '0'; - overlay.style.width = '100%'; - overlay.style.height = '100%'; - overlay.style.backgroundColor = 'rgba(5,5,0,0.9)'; - overlay.style.zIndex = '9999'; - - message.id = 'overlay-message'; - message.innerHTML = text; - message.style.position = 'absolute'; - message.style.top = '30%'; - message.style.left = '50%'; - message.style.transform = 'translate(-50%, -50%)'; - message.style.color = 'white'; - message.style.fontFamily = 'sans-serif'; - message.style.fontSize = '32px'; - message.style.textAlign = 'center'; - - countdown.style.position = 'absolute'; - countdown.style.top = '40%'; - countdown.style.left = '50%'; - countdown.style.transform = 'translate(-50%, -50%)'; - countdown.style.color = 'white'; - countdown.style.fontFamily = 'sans-serif'; - countdown.style.fontSize = '24px'; - countdown.style.textAlign = 'center'; - - overlay.appendChild(message); - overlay.appendChild(countdown); - document.body.appendChild(overlay); - - // Countdown logic - if (duration) { - let remainingTime = duration / 1000; // convert to seconds - countdown.innerText = `Zbývá ${remainingTime}s`; - - let countdownInterval = setInterval(() => { - remainingTime -= 1; - countdown.innerText = `Zbývá ${remainingTime}s`; - - if (remainingTime <= 0) { - clearInterval(countdownInterval); - this.removeOverlay(); - } - }, 1000); - } - } - - removeOverlay() { - let overlay = document.getElementById('overlay'); - if (overlay) { - document.body.removeChild(overlay); - } - } - -} diff --git a/py-socket-server/static/crusaders/helceletka.png b/py-socket-server/static/crusaders/helceletka.png deleted file mode 100644 index b7454a0..0000000 Binary files a/py-socket-server/static/crusaders/helceletka.png and /dev/null differ diff --git a/py-socket-server/static/crusaders/script.js b/py-socket-server/static/crusaders/script.js deleted file mode 100644 index 2826ff7..0000000 --- a/py-socket-server/static/crusaders/script.js +++ /dev/null @@ -1,43 +0,0 @@ -const client = new SocketClient(); - -const numberInput = document.querySelector('#number'); -const checkButton = document.querySelector('#check'); -const addButton = document.querySelector('#add'); -const resultDiv = document.querySelector('#result'); - -async function checkNumber(number) { - // let numbersList = JSON.parse(sessionStorage.getItem('numbersList')) || []; - let numbersList = await client.get('numbersList') || []; - - if(number.length != 4 || isNaN(number)) { - resultDiv.innerHTML = 'Zadej čtyřmístné číslo'; - numberInput.value = ""; - setTimeout(() => { resultDiv.innerHTML = ''; }, 3000); - return; - } - - if (numbersList.includes(number)) { - resultDiv.innerHTML = 'Stůj'; - } else { - resultDiv.innerHTML = 'Můžeš dál'; - } - numberInput.value = ""; - setTimeout(() => { resultDiv.innerHTML = ''; }, 3000); -} -checkButton.addEventListener('click', async () => { - let number = numberInput.value; - await checkNumber(number); -}); - -numberInput.addEventListener('keyup', async (event) => { - if (event.key == "Backspace") { - return; - } - - // Check if the pressed key is NOT a number (0-9) - if (!event.key.match(/[0-9]/)) { - event.preventDefault(); - let number = numberInput.value; - await checkNumber(number); - } -}); \ No newline at end of file diff --git a/py-socket-server/static/crusaders/style.css b/py-socket-server/static/crusaders/style.css deleted file mode 100644 index 59bc311..0000000 --- a/py-socket-server/static/crusaders/style.css +++ /dev/null @@ -1,40 +0,0 @@ -html, body { - height: 100%; - margin: 0; - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - font-size: 40px; - font-family: 'sans-serif'; -} -#number { - width: 200px; - height: 60px; - font-size: 40px; -} -button { - margin-top: 20px; - width: 200px; - height: 60px; - font-size: 40px; -} -#result { - margin-top: 20px; - font-size: 45px; -} -.ok { - color: green; -} -.stop { - color: red; -} - -#forester { - width: 10%; - background-size: contain; - position: absolute; - top: 0; - left: 0; - z-index: -1; -} \ No newline at end of file diff --git a/py-socket-server/static/forester.ico b/py-socket-server/static/forester.ico deleted file mode 100644 index bfd1375..0000000 Binary files a/py-socket-server/static/forester.ico and /dev/null differ diff --git a/py-socket-server/static/forester.jpeg b/py-socket-server/static/forester.jpeg deleted file mode 100644 index 817ea3b..0000000 Binary files a/py-socket-server/static/forester.jpeg and /dev/null differ diff --git a/py-socket-server/static/game1/script.js b/py-socket-server/static/game1/script.js deleted file mode 100644 index f4154ed..0000000 --- a/py-socket-server/static/game1/script.js +++ /dev/null @@ -1,48 +0,0 @@ -const client = new SocketClient(); - -const numberInput = document.querySelector('#number'); -const checkButton = document.querySelector('#check'); -const addButton = document.querySelector('#add'); -const resultDiv = document.querySelector('#result'); - -checkButton.addEventListener('click', async () => { - let number = numberInput.value; - // let numbersList = JSON.parse(sessionStorage.getItem('numbersList')) || []; - let numbersList = await client.get('numbersList') || []; - - if(number.length != 4 || isNaN(number)) { - resultDiv.innerHTML = 'Zadej čtyřmístné číslo'; - numberInput.value = ""; - setTimeout(() => { resultDiv.innerHTML = ''; }, 3000); - return; - } - - if (numbersList.includes(number)) { - resultDiv.innerHTML = 'Stůj'; - } else { - resultDiv.innerHTML = 'Můžeš dál'; - } - numberInput.value = ""; - setTimeout(() => { resultDiv.innerHTML = ''; }, 3000); -}); - -addButton.addEventListener('click', async () => { - let number = numberInput.value; - // let numbersList = JSON.parse(sessionStorage.getItem('numbersList')) || []; - let numbersList = await client.get('numbersList') || []; - - - // is it number? - if (number.length == 4 && !isNaN(number)) { - if (!numbersList.includes(number)) { - numbersList.push(number); - } - // sessionStorage.setItem('numbersList', JSON.stringify(numbersList)); - client.set('numbersList', numbersList); - resultDiv.innerHTML = 'Přidáno'; - } else { - resultDiv.innerHTML = 'Zadej čtyřmístné číslo'; - } - numberInput.value = ""; - setTimeout(() => { resultDiv.innerHTML = ''; }, 3000); -}); \ No newline at end of file diff --git a/py-socket-server/static/game1/style.css b/py-socket-server/static/game1/style.css deleted file mode 100644 index 31c93ae..0000000 --- a/py-socket-server/static/game1/style.css +++ /dev/null @@ -1,31 +0,0 @@ -html, body { - height: 100%; - margin: 0; - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - font-size: 40px; - font-family: 'sans-serif'; -} -#number { - width: 200px; - height: 60px; - font-size: 40px; -} -button { - margin-top: 20px; - width: 200px; - height: 60px; - font-size: 40px; -} -#result { - margin-top: 20px; - font-size: 45px; -} -.ok { - color: green; -} -.stop { - color: red; -} \ No newline at end of file diff --git a/py-socket-server/static/qrcode.min.js b/py-socket-server/static/qrcode.min.js deleted file mode 100644 index 993e88f..0000000 --- a/py-socket-server/static/qrcode.min.js +++ /dev/null @@ -1 +0,0 @@ -var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this.parsedData=[];for(var b=[],d=0,e=this.data.length;e>d;d++){var f=this.data.charCodeAt(d);f>65536?(b[0]=240|(1835008&f)>>>18,b[1]=128|(258048&f)>>>12,b[2]=128|(4032&f)>>>6,b[3]=128|63&f):f>2048?(b[0]=224|(61440&f)>>>12,b[1]=128|(4032&f)>>>6,b[2]=128|63&f):f>128?(b[0]=192|(1984&f)>>>6,b[1]=128|63&f):b[0]=f,this.parsedData=this.parsedData.concat(b)}this.parsedData.length!=this.data.length&&(this.parsedData.unshift(191),this.parsedData.unshift(187),this.parsedData.unshift(239))}function b(a,b){this.typeNumber=a,this.errorCorrectLevel=b,this.modules=null,this.moduleCount=0,this.dataCache=null,this.dataList=[]}function i(a,b){if(void 0==a.length)throw new Error(a.length+"/"+b);for(var c=0;c=f;f++){var h=0;switch(b){case d.L:h=l[f][0];break;case d.M:h=l[f][1];break;case d.Q:h=l[f][2];break;case d.H:h=l[f][3]}if(h>=e)break;c++}if(c>l.length)throw new Error("Too long data");return c}function s(a){var b=encodeURI(a).toString().replace(/\%[0-9a-fA-F]{2}/g,"a");return b.length+(b.length!=a?3:0)}a.prototype={getLength:function(){return this.parsedData.length},write:function(a){for(var b=0,c=this.parsedData.length;c>b;b++)a.put(this.parsedData[b],8)}},b.prototype={addData:function(b){var c=new a(b);this.dataList.push(c),this.dataCache=null},isDark:function(a,b){if(0>a||this.moduleCount<=a||0>b||this.moduleCount<=b)throw new Error(a+","+b);return this.modules[a][b]},getModuleCount:function(){return this.moduleCount},make:function(){this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17,this.modules=new Array(this.moduleCount);for(var d=0;d=7&&this.setupTypeNumber(a),null==this.dataCache&&(this.dataCache=b.createData(this.typeNumber,this.errorCorrectLevel,this.dataList)),this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,b){for(var c=-1;7>=c;c++)if(!(-1>=a+c||this.moduleCount<=a+c))for(var d=-1;7>=d;d++)-1>=b+d||this.moduleCount<=b+d||(this.modules[a+c][b+d]=c>=0&&6>=c&&(0==d||6==d)||d>=0&&6>=d&&(0==c||6==c)||c>=2&&4>=c&&d>=2&&4>=d?!0:!1)},getBestMaskPattern:function(){for(var a=0,b=0,c=0;8>c;c++){this.makeImpl(!0,c);var d=f.getLostPoint(this);(0==c||a>d)&&(a=d,b=c)}return b},createMovieClip:function(a,b,c){var d=a.createEmptyMovieClip(b,c),e=1;this.make();for(var f=0;f=g;g++)for(var h=-2;2>=h;h++)this.modules[d+g][e+h]=-2==g||2==g||-2==h||2==h||0==g&&0==h?!0:!1}},setupTypeNumber:function(a){for(var b=f.getBCHTypeNumber(this.typeNumber),c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[Math.floor(c/3)][c%3+this.moduleCount-8-3]=d}for(var c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[c%3+this.moduleCount-8-3][Math.floor(c/3)]=d}},setupTypeInfo:function(a,b){for(var c=this.errorCorrectLevel<<3|b,d=f.getBCHTypeInfo(c),e=0;15>e;e++){var g=!a&&1==(1&d>>e);6>e?this.modules[e][8]=g:8>e?this.modules[e+1][8]=g:this.modules[this.moduleCount-15+e][8]=g}for(var e=0;15>e;e++){var g=!a&&1==(1&d>>e);8>e?this.modules[8][this.moduleCount-e-1]=g:9>e?this.modules[8][15-e-1+1]=g:this.modules[8][15-e-1]=g}this.modules[this.moduleCount-8][8]=!a},mapData:function(a,b){for(var c=-1,d=this.moduleCount-1,e=7,g=0,h=this.moduleCount-1;h>0;h-=2)for(6==h&&h--;;){for(var i=0;2>i;i++)if(null==this.modules[d][h-i]){var j=!1;g>>e));var k=f.getMask(b,d,h-i);k&&(j=!j),this.modules[d][h-i]=j,e--,-1==e&&(g++,e=7)}if(d+=c,0>d||this.moduleCount<=d){d-=c,c=-c;break}}}},b.PAD0=236,b.PAD1=17,b.createData=function(a,c,d){for(var e=j.getRSBlocks(a,c),g=new k,h=0;h8*l)throw new Error("code length overflow. ("+g.getLengthInBits()+">"+8*l+")");for(g.getLengthInBits()+4<=8*l&&g.put(0,4);0!=g.getLengthInBits()%8;)g.putBit(!1);for(;;){if(g.getLengthInBits()>=8*l)break;if(g.put(b.PAD0,8),g.getLengthInBits()>=8*l)break;g.put(b.PAD1,8)}return b.createBytes(g,e)},b.createBytes=function(a,b){for(var c=0,d=0,e=0,g=new Array(b.length),h=new Array(b.length),j=0;j=0?p.get(q):0}}for(var r=0,m=0;mm;m++)for(var j=0;jm;m++)for(var j=0;j=0;)b^=f.G15<=0;)b^=f.G18<>>=1;return b},getPatternPosition:function(a){return f.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,b,c){switch(a){case e.PATTERN000:return 0==(b+c)%2;case e.PATTERN001:return 0==b%2;case e.PATTERN010:return 0==c%3;case e.PATTERN011:return 0==(b+c)%3;case e.PATTERN100:return 0==(Math.floor(b/2)+Math.floor(c/3))%2;case e.PATTERN101:return 0==b*c%2+b*c%3;case e.PATTERN110:return 0==(b*c%2+b*c%3)%2;case e.PATTERN111:return 0==(b*c%3+(b+c)%2)%2;default:throw new Error("bad maskPattern:"+a)}},getErrorCorrectPolynomial:function(a){for(var b=new i([1],0),c=0;a>c;c++)b=b.multiply(new i([1,g.gexp(c)],0));return b},getLengthInBits:function(a,b){if(b>=1&&10>b)switch(a){case c.MODE_NUMBER:return 10;case c.MODE_ALPHA_NUM:return 9;case c.MODE_8BIT_BYTE:return 8;case c.MODE_KANJI:return 8;default:throw new Error("mode:"+a)}else if(27>b)switch(a){case c.MODE_NUMBER:return 12;case c.MODE_ALPHA_NUM:return 11;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 10;default:throw new Error("mode:"+a)}else{if(!(41>b))throw new Error("type:"+b);switch(a){case c.MODE_NUMBER:return 14;case c.MODE_ALPHA_NUM:return 13;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 12;default:throw new Error("mode:"+a)}}},getLostPoint:function(a){for(var b=a.getModuleCount(),c=0,d=0;b>d;d++)for(var e=0;b>e;e++){for(var f=0,g=a.isDark(d,e),h=-1;1>=h;h++)if(!(0>d+h||d+h>=b))for(var i=-1;1>=i;i++)0>e+i||e+i>=b||(0!=h||0!=i)&&g==a.isDark(d+h,e+i)&&f++;f>5&&(c+=3+f-5)}for(var d=0;b-1>d;d++)for(var e=0;b-1>e;e++){var j=0;a.isDark(d,e)&&j++,a.isDark(d+1,e)&&j++,a.isDark(d,e+1)&&j++,a.isDark(d+1,e+1)&&j++,(0==j||4==j)&&(c+=3)}for(var d=0;b>d;d++)for(var e=0;b-6>e;e++)a.isDark(d,e)&&!a.isDark(d,e+1)&&a.isDark(d,e+2)&&a.isDark(d,e+3)&&a.isDark(d,e+4)&&!a.isDark(d,e+5)&&a.isDark(d,e+6)&&(c+=40);for(var e=0;b>e;e++)for(var d=0;b-6>d;d++)a.isDark(d,e)&&!a.isDark(d+1,e)&&a.isDark(d+2,e)&&a.isDark(d+3,e)&&a.isDark(d+4,e)&&!a.isDark(d+5,e)&&a.isDark(d+6,e)&&(c+=40);for(var k=0,e=0;b>e;e++)for(var d=0;b>d;d++)a.isDark(d,e)&&k++;var l=Math.abs(100*k/b/b-50)/5;return c+=10*l}},g={glog:function(a){if(1>a)throw new Error("glog("+a+")");return g.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;a>=256;)a-=255;return g.EXP_TABLE[a]},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)},h=0;8>h;h++)g.EXP_TABLE[h]=1<h;h++)g.EXP_TABLE[h]=g.EXP_TABLE[h-4]^g.EXP_TABLE[h-5]^g.EXP_TABLE[h-6]^g.EXP_TABLE[h-8];for(var h=0;255>h;h++)g.LOG_TABLE[g.EXP_TABLE[h]]=h;i.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var b=new Array(this.getLength()+a.getLength()-1),c=0;cf;f++)for(var g=c[3*f+0],h=c[3*f+1],i=c[3*f+2],k=0;g>k;k++)e.push(new j(h,i));return e},j.getRsBlockTable=function(a,b){switch(b){case d.L:return j.RS_BLOCK_TABLE[4*(a-1)+0];case d.M:return j.RS_BLOCK_TABLE[4*(a-1)+1];case d.Q:return j.RS_BLOCK_TABLE[4*(a-1)+2];case d.H:return j.RS_BLOCK_TABLE[4*(a-1)+3];default:return void 0}},k.prototype={get:function(a){var b=Math.floor(a/8);return 1==(1&this.buffer[b]>>>7-a%8)},put:function(a,b){for(var c=0;b>c;c++)this.putBit(1==(1&a>>>b-c-1))},getLengthInBits:function(){return this.length},putBit:function(a){var b=Math.floor(this.length/8);this.buffer.length<=b&&this.buffer.push(0),a&&(this.buffer[b]|=128>>>this.length%8),this.length++}};var l=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]],o=function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){function g(a,b){var c=document.createElementNS("http://www.w3.org/2000/svg",a);for(var d in b)b.hasOwnProperty(d)&&c.setAttribute(d,b[d]);return c}var b=this._htOption,c=this._el,d=a.getModuleCount();Math.floor(b.width/d),Math.floor(b.height/d),this.clear();var h=g("svg",{viewBox:"0 0 "+String(d)+" "+String(d),width:"100%",height:"100%",fill:b.colorLight});h.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink","http://www.w3.org/1999/xlink"),c.appendChild(h),h.appendChild(g("rect",{fill:b.colorDark,width:"1",height:"1",id:"template"}));for(var i=0;d>i;i++)for(var j=0;d>j;j++)if(a.isDark(i,j)){var k=g("use",{x:String(i),y:String(j)});k.setAttributeNS("http://www.w3.org/1999/xlink","href","#template"),h.appendChild(k)}},a.prototype.clear=function(){for(;this._el.hasChildNodes();)this._el.removeChild(this._el.lastChild)},a}(),p="svg"===document.documentElement.tagName.toLowerCase(),q=p?o:m()?function(){function a(){this._elImage.src=this._elCanvas.toDataURL("image/png"),this._elImage.style.display="block",this._elCanvas.style.display="none"}function d(a,b){var c=this;if(c._fFail=b,c._fSuccess=a,null===c._bSupportDataURI){var d=document.createElement("img"),e=function(){c._bSupportDataURI=!1,c._fFail&&_fFail.call(c)},f=function(){c._bSupportDataURI=!0,c._fSuccess&&c._fSuccess.call(c)};return d.onabort=e,d.onerror=e,d.onload=f,d.src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",void 0}c._bSupportDataURI===!0&&c._fSuccess?c._fSuccess.call(c):c._bSupportDataURI===!1&&c._fFail&&c._fFail.call(c)}if(this._android&&this._android<=2.1){var b=1/window.devicePixelRatio,c=CanvasRenderingContext2D.prototype.drawImage;CanvasRenderingContext2D.prototype.drawImage=function(a,d,e,f,g,h,i,j){if("nodeName"in a&&/img/i.test(a.nodeName))for(var l=arguments.length-1;l>=1;l--)arguments[l]=arguments[l]*b;else"undefined"==typeof j&&(arguments[1]*=b,arguments[2]*=b,arguments[3]*=b,arguments[4]*=b);c.apply(this,arguments)}}var e=function(a,b){this._bIsPainted=!1,this._android=n(),this._htOption=b,this._elCanvas=document.createElement("canvas"),this._elCanvas.width=b.width,this._elCanvas.height=b.height,a.appendChild(this._elCanvas),this._el=a,this._oContext=this._elCanvas.getContext("2d"),this._bIsPainted=!1,this._elImage=document.createElement("img"),this._elImage.style.display="none",this._el.appendChild(this._elImage),this._bSupportDataURI=null};return e.prototype.draw=function(a){var b=this._elImage,c=this._oContext,d=this._htOption,e=a.getModuleCount(),f=d.width/e,g=d.height/e,h=Math.round(f),i=Math.round(g);b.style.display="none",this.clear();for(var j=0;e>j;j++)for(var k=0;e>k;k++){var l=a.isDark(j,k),m=k*f,n=j*g;c.strokeStyle=l?d.colorDark:d.colorLight,c.lineWidth=1,c.fillStyle=l?d.colorDark:d.colorLight,c.fillRect(m,n,f,g),c.strokeRect(Math.floor(m)+.5,Math.floor(n)+.5,h,i),c.strokeRect(Math.ceil(m)-.5,Math.ceil(n)-.5,h,i)}this._bIsPainted=!0},e.prototype.makeImage=function(){this._bIsPainted&&d.call(this,a)},e.prototype.isPainted=function(){return this._bIsPainted},e.prototype.clear=function(){this._oContext.clearRect(0,0,this._elCanvas.width,this._elCanvas.height),this._bIsPainted=!1},e.prototype.round=function(a){return a?Math.floor(1e3*a)/1e3:a},e}():function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){for(var b=this._htOption,c=this._el,d=a.getModuleCount(),e=Math.floor(b.width/d),f=Math.floor(b.height/d),g=[''],h=0;d>h;h++){g.push("");for(var i=0;d>i;i++)g.push('');g.push("")}g.push("
    "),c.innerHTML=g.join("");var j=c.childNodes[0],k=(b.width-j.offsetWidth)/2,l=(b.height-j.offsetHeight)/2;k>0&&l>0&&(j.style.margin=l+"px "+k+"px")},a.prototype.clear=function(){this._el.innerHTML=""},a}();QRCode=function(a,b){if(this._htOption={width:256,height:256,typeNumber:4,colorDark:"#000000",colorLight:"#ffffff",correctLevel:d.H},"string"==typeof b&&(b={text:b}),b)for(var c in b)this._htOption[c]=b[c];"string"==typeof a&&(a=document.getElementById(a)),this._android=n(),this._el=a,this._oQRCode=null,this._oDrawing=new q(this._el,this._htOption),this._htOption.text&&this.makeCode(this._htOption.text)},QRCode.prototype.makeCode=function(a){this._oQRCode=new b(r(a,this._htOption.correctLevel),this._htOption.correctLevel),this._oQRCode.addData(a),this._oQRCode.make(),this._el.title=a,this._oDrawing.draw(this._oQRCode),this.makeImage()},QRCode.prototype.makeImage=function(){"function"==typeof this._oDrawing.makeImage&&(!this._android||this._android>=3)&&this._oDrawing.makeImage()},QRCode.prototype.clear=function(){this._oDrawing.clear()},QRCode.CorrectLevel=d}(); \ No newline at end of file diff --git a/py-socket-server/static/socket.io.min.js b/py-socket-server/static/socket.io.min.js deleted file mode 100644 index f39af5c..0000000 --- a/py-socket-server/static/socket.io.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Socket.IO v4.7.2 - * (c) 2014-2023 Guillermo Rauch - * Released under the MIT License. - */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).io=e()}(this,(function(){"use strict";function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}function e(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function n(t,e){for(var n=0;nt.length)&&(e=t.length);for(var n=0,r=new Array(e);n=t.length?{done:!0}:{done:!1,value:t[r++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==n.return||n.return()}finally{if(a)throw o}}}}var v=Object.create(null);v.open="0",v.close="1",v.ping="2",v.pong="3",v.message="4",v.upgrade="5",v.noop="6";var g=Object.create(null);Object.keys(v).forEach((function(t){g[v[t]]=t}));var m,b={type:"error",data:"parser error"},k="function"==typeof Blob||"undefined"!=typeof Blob&&"[object BlobConstructor]"===Object.prototype.toString.call(Blob),w="function"==typeof ArrayBuffer,_=function(t){return"function"==typeof ArrayBuffer.isView?ArrayBuffer.isView(t):t&&t.buffer instanceof ArrayBuffer},A=function(t,e,n){var r=t.type,i=t.data;return k&&i instanceof Blob?e?n(i):O(i,n):w&&(i instanceof ArrayBuffer||_(i))?e?n(i):O(new Blob([i]),n):n(v[r]+(i||""))},O=function(t,e){var n=new FileReader;return n.onload=function(){var t=n.result.split(",")[1];e("b"+(t||""))},n.readAsDataURL(t)};function E(t){return t instanceof Uint8Array?t:t instanceof ArrayBuffer?new Uint8Array(t):new Uint8Array(t.buffer,t.byteOffset,t.byteLength)}for(var T="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",R="undefined"==typeof Uint8Array?[]:new Uint8Array(256),C=0;C<64;C++)R[T.charCodeAt(C)]=C;var B,S="function"==typeof ArrayBuffer,N=function(t,e){if("string"!=typeof t)return{type:"message",data:x(t,e)};var n=t.charAt(0);return"b"===n?{type:"message",data:L(t.substring(1),e)}:g[n]?t.length>1?{type:g[n],data:t.substring(1)}:{type:g[n]}:b},L=function(t,e){if(S){var n=function(t){var e,n,r,i,o,s=.75*t.length,a=t.length,u=0;"="===t[t.length-1]&&(s--,"="===t[t.length-2]&&s--);var c=new ArrayBuffer(s),h=new Uint8Array(c);for(e=0;e>4,h[u++]=(15&r)<<4|i>>2,h[u++]=(3&i)<<6|63&o;return c}(t);return x(n,e)}return{base64:!0,data:t}},x=function(t,e){return"blob"===e?t instanceof Blob?t:new Blob([t]):t instanceof ArrayBuffer?t:t.buffer},P=String.fromCharCode(30);function q(){return new TransformStream({transform:function(t,e){!function(t,e){k&&t.data instanceof Blob?t.data.arrayBuffer().then(E).then(e):w&&(t.data instanceof ArrayBuffer||_(t.data))?e(E(t.data)):A(t,!1,(function(t){m||(m=new TextEncoder),e(m.encode(t))}))}(t,(function(n){var r,i=n.length;if(i<126)r=new Uint8Array(1),new DataView(r.buffer).setUint8(0,i);else if(i<65536){r=new Uint8Array(3);var o=new DataView(r.buffer);o.setUint8(0,126),o.setUint16(1,i)}else{r=new Uint8Array(9);var s=new DataView(r.buffer);s.setUint8(0,127),s.setBigUint64(1,BigInt(i))}t.data&&"string"!=typeof t.data&&(r[0]|=128),e.enqueue(r),e.enqueue(n)}))}})}function j(t){return t.reduce((function(t,e){return t+e.length}),0)}function D(t,e){if(t[0].length===e)return t.shift();for(var n=new Uint8Array(e),r=0,i=0;i1?e-1:0),r=1;r1&&void 0!==arguments[1]?arguments[1]:{};return t+"://"+this._hostname()+this._port()+this.opts.path+this._query(e)}},{key:"_hostname",value:function(){var t=this.opts.hostname;return-1===t.indexOf(":")?t:"["+t+"]"}},{key:"_port",value:function(){return this.opts.port&&(this.opts.secure&&Number(443!==this.opts.port)||!this.opts.secure&&80!==Number(this.opts.port))?":"+this.opts.port:""}},{key:"_query",value:function(t){var e=function(t){var e="";for(var n in t)t.hasOwnProperty(n)&&(e.length&&(e+="&"),e+=encodeURIComponent(n)+"="+encodeURIComponent(t[n]));return e}(t);return e.length?"?"+e:""}}]),i}(U),z="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_".split(""),J=64,$={},Q=0,X=0;function G(t){var e="";do{e=z[t%J]+e,t=Math.floor(t/J)}while(t>0);return e}function Z(){var t=G(+new Date);return t!==K?(Q=0,K=t):t+"."+G(Q++)}for(;X0&&void 0!==arguments[0]?arguments[0]:{};return i(t,{xd:this.xd,cookieJar:this.cookieJar},this.opts),new st(this.uri(),t)}},{key:"doWrite",value:function(t,e){var n=this,r=this.request({method:"POST",data:t});r.on("success",e),r.on("error",(function(t,e){n.onError("xhr post error",t,e)}))}},{key:"doPoll",value:function(){var t=this,e=this.request();e.on("data",this.onData.bind(this)),e.on("error",(function(e,n){t.onError("xhr poll error",e,n)})),this.pollXhr=e}}]),s}(W),st=function(t){o(i,t);var n=l(i);function i(t,r){var o;return e(this,i),H(f(o=n.call(this)),r),o.opts=r,o.method=r.method||"GET",o.uri=t,o.data=void 0!==r.data?r.data:null,o.create(),o}return r(i,[{key:"create",value:function(){var t,e=this,n=F(this.opts,"agent","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","autoUnref");n.xdomain=!!this.opts.xd;var r=this.xhr=new nt(n);try{r.open(this.method,this.uri,!0);try{if(this.opts.extraHeaders)for(var o in r.setDisableHeaderCheck&&r.setDisableHeaderCheck(!0),this.opts.extraHeaders)this.opts.extraHeaders.hasOwnProperty(o)&&r.setRequestHeader(o,this.opts.extraHeaders[o])}catch(t){}if("POST"===this.method)try{r.setRequestHeader("Content-type","text/plain;charset=UTF-8")}catch(t){}try{r.setRequestHeader("Accept","*/*")}catch(t){}null===(t=this.opts.cookieJar)||void 0===t||t.addCookies(r),"withCredentials"in r&&(r.withCredentials=this.opts.withCredentials),this.opts.requestTimeout&&(r.timeout=this.opts.requestTimeout),r.onreadystatechange=function(){var t;3===r.readyState&&(null===(t=e.opts.cookieJar)||void 0===t||t.parseCookies(r)),4===r.readyState&&(200===r.status||1223===r.status?e.onLoad():e.setTimeoutFn((function(){e.onError("number"==typeof r.status?r.status:0)}),0))},r.send(this.data)}catch(t){return void this.setTimeoutFn((function(){e.onError(t)}),0)}"undefined"!=typeof document&&(this.index=i.requestsCount++,i.requests[this.index]=this)}},{key:"onError",value:function(t){this.emitReserved("error",t,this.xhr),this.cleanup(!0)}},{key:"cleanup",value:function(t){if(void 0!==this.xhr&&null!==this.xhr){if(this.xhr.onreadystatechange=rt,t)try{this.xhr.abort()}catch(t){}"undefined"!=typeof document&&delete i.requests[this.index],this.xhr=null}}},{key:"onLoad",value:function(){var t=this.xhr.responseText;null!==t&&(this.emitReserved("data",t),this.emitReserved("success"),this.cleanup())}},{key:"abort",value:function(){this.cleanup()}}]),i}(U);if(st.requestsCount=0,st.requests={},"undefined"!=typeof document)if("function"==typeof attachEvent)attachEvent("onunload",at);else if("function"==typeof addEventListener){addEventListener("onpagehide"in I?"pagehide":"unload",at,!1)}function at(){for(var t in st.requests)st.requests.hasOwnProperty(t)&&st.requests[t].abort()}var ut="function"==typeof Promise&&"function"==typeof Promise.resolve?function(t){return Promise.resolve().then(t)}:function(t,e){return e(t,0)},ct=I.WebSocket||I.MozWebSocket,ht="undefined"!=typeof navigator&&"string"==typeof navigator.product&&"reactnative"===navigator.product.toLowerCase(),ft=function(t){o(i,t);var n=l(i);function i(t){var r;return e(this,i),(r=n.call(this,t)).supportsBinary=!t.forceBase64,r}return r(i,[{key:"name",get:function(){return"websocket"}},{key:"doOpen",value:function(){if(this.check()){var t=this.uri(),e=this.opts.protocols,n=ht?{}:F(this.opts,"agent","perMessageDeflate","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","localAddress","protocolVersion","origin","maxPayload","family","checkServerIdentity");this.opts.extraHeaders&&(n.headers=this.opts.extraHeaders);try{this.ws=ht?new ct(t,e,n):e?new ct(t,e):new ct(t)}catch(t){return this.emitReserved("error",t)}this.ws.binaryType=this.socket.binaryType,this.addEventListeners()}}},{key:"addEventListeners",value:function(){var t=this;this.ws.onopen=function(){t.opts.autoUnref&&t.ws._socket.unref(),t.onOpen()},this.ws.onclose=function(e){return t.onClose({description:"websocket connection closed",context:e})},this.ws.onmessage=function(e){return t.onData(e.data)},this.ws.onerror=function(e){return t.onError("websocket error",e)}}},{key:"write",value:function(t){var e=this;this.writable=!1;for(var n=function(){var n=t[r],i=r===t.length-1;A(n,e.supportsBinary,(function(t){try{e.ws.send(t)}catch(t){}i&&ut((function(){e.writable=!0,e.emitReserved("drain")}),e.setTimeoutFn)}))},r=0;rMath.pow(2,21)-1){a.enqueue(b);break}i=l*Math.pow(2,32)+f.getUint32(4),r=3}else{if(j(n)t){a.enqueue(b);break}}}})}(Number.MAX_SAFE_INTEGER,t.socket.binaryType),r=e.readable.pipeThrough(n).getReader(),i=q();i.readable.pipeTo(e.writable),t.writer=i.writable.getWriter();!function e(){r.read().then((function(n){var r=n.done,i=n.value;r||(t.onPacket(i),e())})).catch((function(t){}))}();var o={type:"open"};t.query.sid&&(o.data='{"sid":"'.concat(t.query.sid,'"}')),t.writer.write(o).then((function(){return t.onOpen()}))}))})))}},{key:"write",value:function(t){var e=this;this.writable=!1;for(var n=function(){var n=t[r],i=r===t.length-1;e.writer.write(n).then((function(){i&&ut((function(){e.writable=!0,e.emitReserved("drain")}),e.setTimeoutFn)}))},r=0;r1&&void 0!==arguments[1]?arguments[1]:{};return e(this,a),(r=s.call(this)).binaryType="arraybuffer",r.writeBuffer=[],n&&"object"===t(n)&&(o=n,n=null),n?(n=vt(n),o.hostname=n.host,o.secure="https"===n.protocol||"wss"===n.protocol,o.port=n.port,n.query&&(o.query=n.query)):o.host&&(o.hostname=vt(o.host).host),H(f(r),o),r.secure=null!=o.secure?o.secure:"undefined"!=typeof location&&"https:"===location.protocol,o.hostname&&!o.port&&(o.port=r.secure?"443":"80"),r.hostname=o.hostname||("undefined"!=typeof location?location.hostname:"localhost"),r.port=o.port||("undefined"!=typeof location&&location.port?location.port:r.secure?"443":"80"),r.transports=o.transports||["polling","websocket","webtransport"],r.writeBuffer=[],r.prevBufferLen=0,r.opts=i({path:"/engine.io",agent:!1,withCredentials:!1,upgrade:!0,timestampParam:"t",rememberUpgrade:!1,addTrailingSlash:!0,rejectUnauthorized:!0,perMessageDeflate:{threshold:1024},transportOptions:{},closeOnBeforeunload:!1},o),r.opts.path=r.opts.path.replace(/\/$/,"")+(r.opts.addTrailingSlash?"/":""),"string"==typeof r.opts.query&&(r.opts.query=function(t){for(var e={},n=t.split("&"),r=0,i=n.length;r1))return this.writeBuffer;for(var t,e=1,n=0;n=57344?n+=3:(r++,n+=4);return n}(t):Math.ceil(1.33*(t.byteLength||t.size))),n>0&&e>this.maxPayload)return this.writeBuffer.slice(0,n);e+=2}return this.writeBuffer}},{key:"write",value:function(t,e,n){return this.sendPacket("message",t,e,n),this}},{key:"send",value:function(t,e,n){return this.sendPacket("message",t,e,n),this}},{key:"sendPacket",value:function(t,e,n,r){if("function"==typeof e&&(r=e,e=void 0),"function"==typeof n&&(r=n,n=null),"closing"!==this.readyState&&"closed"!==this.readyState){(n=n||{}).compress=!1!==n.compress;var i={type:t,data:e,options:n};this.emitReserved("packetCreate",i),this.writeBuffer.push(i),r&&this.once("flush",r),this.flush()}}},{key:"close",value:function(){var t=this,e=function(){t.onClose("forced close"),t.transport.close()},n=function n(){t.off("upgrade",n),t.off("upgradeError",n),e()},r=function(){t.once("upgrade",n),t.once("upgradeError",n)};return"opening"!==this.readyState&&"open"!==this.readyState||(this.readyState="closing",this.writeBuffer.length?this.once("drain",(function(){t.upgrading?r():e()})):this.upgrading?r():e()),this}},{key:"onError",value:function(t){a.priorWebsocketSuccess=!1,this.emitReserved("error",t),this.onClose("transport error",t)}},{key:"onClose",value:function(t,e){"opening"!==this.readyState&&"open"!==this.readyState&&"closing"!==this.readyState||(this.clearTimeoutFn(this.pingTimeoutTimer),this.transport.removeAllListeners("close"),this.transport.close(),this.transport.removeAllListeners(),"function"==typeof removeEventListener&&(removeEventListener("beforeunload",this.beforeunloadEventListener,!1),removeEventListener("offline",this.offlineEventListener,!1)),this.readyState="closed",this.id=null,this.emitReserved("close",t,e),this.writeBuffer=[],this.prevBufferLen=0)}},{key:"filterUpgrades",value:function(t){for(var e=[],n=0,r=t.length;n=0&&e.num1?e-1:0),r=1;r1?n-1:0),i=1;in._opts.retries&&(n._queue.shift(),e&&e(t));else if(n._queue.shift(),e){for(var i=arguments.length,o=new Array(i>1?i-1:0),s=1;s0&&void 0!==arguments[0]&&arguments[0];if(this.connected&&0!==this._queue.length){var e=this._queue[0];e.pending&&!t||(e.pending=!0,e.tryCount++,this.flags=e.flags,this.emit.apply(this,e.args))}}},{key:"packet",value:function(t){t.nsp=this.nsp,this.io._packet(t)}},{key:"onopen",value:function(){var t=this;"function"==typeof this.auth?this.auth((function(e){t._sendConnectPacket(e)})):this._sendConnectPacket(this.auth)}},{key:"_sendConnectPacket",value:function(t){this.packet({type:Bt.CONNECT,data:this._pid?i({pid:this._pid,offset:this._lastOffset},t):t})}},{key:"onerror",value:function(t){this.connected||this.emitReserved("connect_error",t)}},{key:"onclose",value:function(t,e){this.connected=!1,delete this.id,this.emitReserved("disconnect",t,e)}},{key:"onpacket",value:function(t){if(t.nsp===this.nsp)switch(t.type){case Bt.CONNECT:t.data&&t.data.sid?this.onconnect(t.data.sid,t.data.pid):this.emitReserved("connect_error",new Error("It seems you are trying to reach a Socket.IO server in v2.x with a v3.x client, but they are not compatible (more information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/)"));break;case Bt.EVENT:case Bt.BINARY_EVENT:this.onevent(t);break;case Bt.ACK:case Bt.BINARY_ACK:this.onack(t);break;case Bt.DISCONNECT:this.ondisconnect();break;case Bt.CONNECT_ERROR:this.destroy();var e=new Error(t.data.message);e.data=t.data.data,this.emitReserved("connect_error",e)}}},{key:"onevent",value:function(t){var e=t.data||[];null!=t.id&&e.push(this.ack(t.id)),this.connected?this.emitEvent(e):this.receiveBuffer.push(Object.freeze(e))}},{key:"emitEvent",value:function(t){if(this._anyListeners&&this._anyListeners.length){var e,n=y(this._anyListeners.slice());try{for(n.s();!(e=n.n()).done;){e.value.apply(this,t)}}catch(t){n.e(t)}finally{n.f()}}p(s(a.prototype),"emit",this).apply(this,t),this._pid&&t.length&&"string"==typeof t[t.length-1]&&(this._lastOffset=t[t.length-1])}},{key:"ack",value:function(t){var e=this,n=!1;return function(){if(!n){n=!0;for(var r=arguments.length,i=new Array(r),o=0;o0&&t.jitter<=1?t.jitter:0,this.attempts=0}It.prototype.duration=function(){var t=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var e=Math.random(),n=Math.floor(e*this.jitter*t);t=0==(1&Math.floor(10*e))?t-n:t+n}return 0|Math.min(t,this.max)},It.prototype.reset=function(){this.attempts=0},It.prototype.setMin=function(t){this.ms=t},It.prototype.setMax=function(t){this.max=t},It.prototype.setJitter=function(t){this.jitter=t};var Ft=function(n){o(s,n);var i=l(s);function s(n,r){var o,a;e(this,s),(o=i.call(this)).nsps={},o.subs=[],n&&"object"===t(n)&&(r=n,n=void 0),(r=r||{}).path=r.path||"/socket.io",o.opts=r,H(f(o),r),o.reconnection(!1!==r.reconnection),o.reconnectionAttempts(r.reconnectionAttempts||1/0),o.reconnectionDelay(r.reconnectionDelay||1e3),o.reconnectionDelayMax(r.reconnectionDelayMax||5e3),o.randomizationFactor(null!==(a=r.randomizationFactor)&&void 0!==a?a:.5),o.backoff=new It({min:o.reconnectionDelay(),max:o.reconnectionDelayMax(),jitter:o.randomizationFactor()}),o.timeout(null==r.timeout?2e4:r.timeout),o._readyState="closed",o.uri=n;var u=r.parser||qt;return o.encoder=new u.Encoder,o.decoder=new u.Decoder,o._autoConnect=!1!==r.autoConnect,o._autoConnect&&o.open(),o}return r(s,[{key:"reconnection",value:function(t){return arguments.length?(this._reconnection=!!t,this):this._reconnection}},{key:"reconnectionAttempts",value:function(t){return void 0===t?this._reconnectionAttempts:(this._reconnectionAttempts=t,this)}},{key:"reconnectionDelay",value:function(t){var e;return void 0===t?this._reconnectionDelay:(this._reconnectionDelay=t,null===(e=this.backoff)||void 0===e||e.setMin(t),this)}},{key:"randomizationFactor",value:function(t){var e;return void 0===t?this._randomizationFactor:(this._randomizationFactor=t,null===(e=this.backoff)||void 0===e||e.setJitter(t),this)}},{key:"reconnectionDelayMax",value:function(t){var e;return void 0===t?this._reconnectionDelayMax:(this._reconnectionDelayMax=t,null===(e=this.backoff)||void 0===e||e.setMax(t),this)}},{key:"timeout",value:function(t){return arguments.length?(this._timeout=t,this):this._timeout}},{key:"maybeReconnectOnOpen",value:function(){!this._reconnecting&&this._reconnection&&0===this.backoff.attempts&&this.reconnect()}},{key:"open",value:function(t){var e=this;if(~this._readyState.indexOf("open"))return this;this.engine=new gt(this.uri,this.opts);var n=this.engine,r=this;this._readyState="opening",this.skipReconnect=!1;var i=jt(n,"open",(function(){r.onopen(),t&&t()})),o=function(n){e.cleanup(),e._readyState="closed",e.emitReserved("error",n),t?t(n):e.maybeReconnectOnOpen()},s=jt(n,"error",o);if(!1!==this._timeout){var a=this._timeout,u=this.setTimeoutFn((function(){i(),o(new Error("timeout")),n.close()}),a);this.opts.autoUnref&&u.unref(),this.subs.push((function(){e.clearTimeoutFn(u)}))}return this.subs.push(i),this.subs.push(s),this}},{key:"connect",value:function(t){return this.open(t)}},{key:"onopen",value:function(){this.cleanup(),this._readyState="open",this.emitReserved("open");var t=this.engine;this.subs.push(jt(t,"ping",this.onping.bind(this)),jt(t,"data",this.ondata.bind(this)),jt(t,"error",this.onerror.bind(this)),jt(t,"close",this.onclose.bind(this)),jt(this.decoder,"decoded",this.ondecoded.bind(this)))}},{key:"onping",value:function(){this.emitReserved("ping")}},{key:"ondata",value:function(t){try{this.decoder.add(t)}catch(t){this.onclose("parse error",t)}}},{key:"ondecoded",value:function(t){var e=this;ut((function(){e.emitReserved("packet",t)}),this.setTimeoutFn)}},{key:"onerror",value:function(t){this.emitReserved("error",t)}},{key:"socket",value:function(t,e){var n=this.nsps[t];return n?this._autoConnect&&!n.active&&n.connect():(n=new Ut(this,t,e),this.nsps[t]=n),n}},{key:"_destroy",value:function(t){for(var e=0,n=Object.keys(this.nsps);e=this._reconnectionAttempts)this.backoff.reset(),this.emitReserved("reconnect_failed"),this._reconnecting=!1;else{var n=this.backoff.duration();this._reconnecting=!0;var r=this.setTimeoutFn((function(){e.skipReconnect||(t.emitReserved("reconnect_attempt",e.backoff.attempts),e.skipReconnect||e.open((function(n){n?(e._reconnecting=!1,e.reconnect(),t.emitReserved("reconnect_error",n)):e.onreconnect()})))}),n);this.opts.autoUnref&&r.unref(),this.subs.push((function(){t.clearTimeoutFn(r)}))}}},{key:"onreconnect",value:function(){var t=this.backoff.attempts;this._reconnecting=!1,this.backoff.reset(),this.emitReserved("reconnect",t)}}]),s}(U),Mt={};function Vt(e,n){"object"===t(e)&&(n=e,e=void 0);var r,i=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2?arguments[2]:void 0,r=t;n=n||"undefined"!=typeof location&&location,null==t&&(t=n.protocol+"//"+n.host),"string"==typeof t&&("/"===t.charAt(0)&&(t="/"===t.charAt(1)?n.protocol+t:n.host+t),/^(https?|wss?):\/\//.test(t)||(t=void 0!==n?n.protocol+"//"+t:"https://"+t),r=vt(t)),r.port||(/^(http|ws)$/.test(r.protocol)?r.port="80":/^(http|ws)s$/.test(r.protocol)&&(r.port="443")),r.path=r.path||"/";var i=-1!==r.host.indexOf(":")?"["+r.host+"]":r.host;return r.id=r.protocol+"://"+i+":"+r.port+e,r.href=r.protocol+"://"+i+(n&&n.port===r.port?"":":"+r.port),r}(e,(n=n||{}).path||"/socket.io"),o=i.source,s=i.id,a=i.path,u=Mt[s]&&a in Mt[s].nsps;return n.forceNew||n["force new connection"]||!1===n.multiplex||u?r=new Ft(o,n):(Mt[s]||(Mt[s]=new Ft(o,n)),r=Mt[s]),i.query&&!n.query&&(n.query=i.queryKey),r.socket(i.path,n)}return i(Vt,{Manager:Ft,Socket:Ut,io:Vt,connect:Vt}),Vt})); -//# sourceMappingURL=socket.io.min.js.map diff --git a/py-socket-server/static/udavac/helceletka.png b/py-socket-server/static/udavac/helceletka.png deleted file mode 100644 index b7454a0..0000000 Binary files a/py-socket-server/static/udavac/helceletka.png and /dev/null differ diff --git a/py-socket-server/static/udavac/script.js b/py-socket-server/static/udavac/script.js deleted file mode 100644 index 7c724b8..0000000 --- a/py-socket-server/static/udavac/script.js +++ /dev/null @@ -1,44 +0,0 @@ -const client = new SocketClient(); - -const numberInput = document.querySelector('#number'); -const udavacButton = document.querySelector('#udavac'); -const resultDiv = document.querySelector('#result'); - -async function addNumber(number) { - // let numbersList = JSON.parse(sessionStorage.getItem('numbersList')) || []; - let numbersList = await client.get('numbersList') || []; - - - // is it number? - if (number.length == 4 && !isNaN(number)) { - if (!numbersList.includes(number)) { - numbersList.push(number); - } - // sessionStorage.setItem('numbersList', JSON.stringify(numbersList)); - client.set('numbersList', numbersList); - resultDiv.innerHTML = 'Udáno'; - } else { - resultDiv.innerHTML = 'Zadej čtyřmístné číslo'; - } - numberInput.value = ""; - setTimeout(() => { resultDiv.innerHTML = ''; }, 3000); -} - -udavacButton.addEventListener('click', async () => { - let number = numberInput.value; - await addNumber(number); -}); - -numberInput.addEventListener('keyup', async (event) => { - // if backspace is pressed - if (event.key == "Backspace") { - return; - } - - // Check if the pressed key is NOT a number (0-9) - if (!event.key.match(/[0-9]/)) { - event.preventDefault(); - let number = numberInput.value; - await addNumber(number); - } -}); \ No newline at end of file diff --git a/py-socket-server/static/udavac/style.css b/py-socket-server/static/udavac/style.css deleted file mode 100644 index 6430394..0000000 --- a/py-socket-server/static/udavac/style.css +++ /dev/null @@ -1,40 +0,0 @@ -html, body { - height: 100%; - margin: 0; - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - font-size: 40px; - font-family: 'sans-serif'; -} -#number { - width: 200px; - height: 60px; - font-size: 40px; -} -button { - margin-top: 20px; - width: 200px; - height: 60px; - font-size: 40px; -} -#result { - margin-top: 20px; - font-size: 45px; -} -.ok { - color: green; -} -.stop { - color: red; -} - -#forester { - width: 10%; - background-size: contain; - position: absolute; - top: 0; - right : 0; - z-index: -1; -} \ No newline at end of file diff --git a/py-socket-server/templates/admin.html b/py-socket-server/templates/admin.html deleted file mode 100644 index 3cfcadc..0000000 --- a/py-socket-server/templates/admin.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - Admin Panel - - -

    Admin Panel

    - Home - Udavač -{# #} - -
    - - -
    - -

    Počet připojených zařízení: 0 (ve hře i admin panelu)

    - -

    IP adresa serveru: {{ ip_address }}

    -

    Tuto adresu zadejte do prohlížeče na zařízení, které chcete připojit do hry.

    - -

    Odeslat zprávu do všech zařízení:

    - - -

    Zpráva se odešle všem připojeným zařízením, které jsou v danou chvíli ve hře.

    -

    Poslední odeslaná zpráva: -

    - -

    Upravit data:

    -
      - {% if not data %} -
    • Žádná data
    • - {% endif %} - {% for key, value in data.items() %} -
    • - {{ key }}: {{ value }} - - -
    • - {% endfor %} -
    - - - - -

    Nahrát data:

    - - - -
    -
    - -
    - QR kód pro připojení do hry - - - - - - - diff --git a/py-socket-server/templates/index.html b/py-socket-server/templates/index.html deleted file mode 100644 index 255e34d..0000000 --- a/py-socket-server/templates/index.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - Game - - - - -
    - - -

    Stiskni tlačítko nebo klikni na ENTER

    -
    - - - - - - diff --git a/py-socket-server/templates/udavac.html b/py-socket-server/templates/udavac.html deleted file mode 100644 index 2da8ab9..0000000 --- a/py-socket-server/templates/udavac.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - Game - - -

    Udavač

    - - -
    - - -

    Stiskni tlačítko nebo klikni na ENTER

    -
    - - - - - - diff --git a/py-socket-server/templates/udavacOld.html b/py-socket-server/templates/udavacOld.html deleted file mode 100644 index f0973c7..0000000 --- a/py-socket-server/templates/udavacOld.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - Game - - - - - -
    - - - - - -