Skip to content

Commit

Permalink
Add live load
Browse files Browse the repository at this point in the history
  • Loading branch information
JakubAndrysek committed Sep 6, 2024
1 parent 3202c53 commit 5784ae8
Show file tree
Hide file tree
Showing 81 changed files with 442 additions and 1,795 deletions.
3 changes: 3 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 13 additions & 15 deletions forester-game-app/app/custom_loader.py
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
20 changes: 15 additions & 5 deletions forester-game-app/app/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
22 changes: 15 additions & 7 deletions forester-game-app/app/init.py
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -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
Expand Down
26 changes: 13 additions & 13 deletions forester-game-app/app/routes.py
Original file line number Diff line number Diff line change
@@ -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__)

Expand All @@ -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)
Expand All @@ -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('/<folder>/', defaults={'page': 'index'})
@main.route('/<folder>/<page>')
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()}',
Expand All @@ -66,5 +66,5 @@ def render_page(folder, page):
# Serve static files
@main.route('/assets/<path:filename>')
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)
73 changes: 33 additions & 40 deletions forester-game-app/app/socketio_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'}
Loading

0 comments on commit 5784ae8

Please sign in to comment.