From f713443c201ea0d1692610bc758b2f98b4a3840e Mon Sep 17 00:00:00 2001 From: David Rodenkirchen Date: Wed, 4 Feb 2026 20:23:57 +0100 Subject: [PATCH 1/9] Add easteregg --- src/EzggLanManager.py | 5 ++ src/ezgg_lan_manager/pages/ConwayPage.py | 83 ++++++++++++++++++++++++ src/ezgg_lan_manager/pages/__init__.py | 1 + 3 files changed, 89 insertions(+) create mode 100644 src/ezgg_lan_manager/pages/ConwayPage.py diff --git a/src/EzggLanManager.py b/src/EzggLanManager.py index 0779eca..82d5146 100644 --- a/src/EzggLanManager.py +++ b/src/EzggLanManager.py @@ -171,6 +171,11 @@ if __name__ == "__main__": name="TournamentRulesPage", url_segment="tournament-rules", build=pages.TournamentRulesPage, + ), + ComponentPage( + name="ConwaysGameOfLife", + url_segment="conway", + build=pages.ConwayPage, ) ], theme=theme, diff --git a/src/ezgg_lan_manager/pages/ConwayPage.py b/src/ezgg_lan_manager/pages/ConwayPage.py new file mode 100644 index 0000000..fba7f3c --- /dev/null +++ b/src/ezgg_lan_manager/pages/ConwayPage.py @@ -0,0 +1,83 @@ +from __future__ import annotations + +from copy import deepcopy +from random import randint +from typing import * # type: ignore + +from rio import Component, event, Column, Row, Color, Rectangle + + + +class ConwayPage(Component): + """ + This is an Easter egg. + """ + + active_generation: list[list] = [] + rows: int = 36 + cols: int = 20 + + @event.periodic(1) + async def calc_next_gen(self) -> None: + self.create_next_grid() + + @event.on_populate + def prepare(self) -> None: + self.active_generation = self.create_initial_grid() + + def create_initial_grid(self) -> list[list]: + grid = [] + for row in range(self.rows): + grid_rows = [] + for col in range(self.cols): + if randint(0, 7) == 0: + grid_rows += [1] + else: + grid_rows += [0] + grid += [grid_rows] + return grid + + def create_next_grid(self) -> None: + next_grid = deepcopy(self.active_generation) + + for row in range(self.rows): + for col in range(self.cols): + live_neighbors = self.get_live_neighbors(row, col, self.active_generation) + + if live_neighbors < 2 or live_neighbors > 3: + next_grid[row][col] = 0 + elif live_neighbors == 3 and self.active_generation[row][col] == 0: + next_grid[row][col] = 1 + else: + next_grid[row][col] = self.active_generation[row][col] + + self.active_generation = next_grid + + def get_live_neighbors(self, row: int, col: int, grid: list[list]) -> int: + life_sum = 0 + for i in range(-1, 2): + for j in range(-1, 2): + if not (i == 0 and j == 0): + life_sum += grid[((row + i) % self.rows)][((col + j) % self.cols)] + return life_sum + + def grid_changing(self, next_grid: list[list]) -> bool: + for row in range(self.rows): + for col in range(self.cols): + if not self.active_generation[row][col] == next_grid[row][col]: + return True + return False + + def build(self) -> Component: + rows = [] + + for row in self.active_generation: + rectangles = [] + + for cell in row: + color = Color.WHITE if cell == 1 else Color.BLACK + rectangles.append(Rectangle(fill=color, transition_time=0.3)) + + rows.append(Row(*rectangles)) + + return Column(*rows) diff --git a/src/ezgg_lan_manager/pages/__init__.py b/src/ezgg_lan_manager/pages/__init__.py index d20bffc..8bb9e24 100644 --- a/src/ezgg_lan_manager/pages/__init__.py +++ b/src/ezgg_lan_manager/pages/__init__.py @@ -22,3 +22,4 @@ from .ManageTournamentsPage import ManageTournamentsPage from .OverviewPage import OverviewPage from .TournamentDetailsPage import TournamentDetailsPage from .TournamentRulesPage import TournamentRulesPage +from .ConwayPage import ConwayPage From aa3691a59f799a3898ded912bd8f855388bf27f8 Mon Sep 17 00:00:00 2001 From: David Rodenkirchen Date: Sun, 8 Feb 2026 01:26:55 +0100 Subject: [PATCH 2/9] Fix bug where users without ticket could register for tournament --- .../pages/TournamentDetailsPage.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/ezgg_lan_manager/pages/TournamentDetailsPage.py b/src/ezgg_lan_manager/pages/TournamentDetailsPage.py index 042d907..8e3f3e6 100644 --- a/src/ezgg_lan_manager/pages/TournamentDetailsPage.py +++ b/src/ezgg_lan_manager/pages/TournamentDetailsPage.py @@ -4,7 +4,7 @@ from from_root import from_root from rio import Column, Component, event, TextStyle, Text, Row, Image, Spacer, ProgressCircle, Button, Checkbox, ThemeContextSwitcher, Link, Revealer, PointerEventListener, \ PointerEvent, Rectangle, Color -from src.ezgg_lan_manager import ConfigurationService, TournamentService, UserService +from src.ezgg_lan_manager import ConfigurationService, TournamentService, UserService, TicketingService from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox from src.ezgg_lan_manager.components.TournamentDetailsInfoRow import TournamentDetailsInfoRow from src.ezgg_lan_manager.types.DateUtil import weekday_to_display_text @@ -53,13 +53,18 @@ class TournamentDetailsPage(Component): if not self.user: return - try: - await self.session[TournamentService].register_user_for_tournament(self.user.user_id, self.tournament.id) - self.is_success = True - self.message = f"Erfolgreich angemeldet!" - except Exception as e: + user_ticket = await self.session[TicketingService].get_user_ticket(self.user.user_id) + if user_ticket is None: self.is_success = False - self.message = f"Fehler: {e}" + self.message = "Turnieranmeldung nur mit Ticket" + else: + try: + await self.session[TournamentService].register_user_for_tournament(self.user.user_id, self.tournament.id) + self.is_success = True + self.message = f"Erfolgreich angemeldet!" + except Exception as e: + self.is_success = False + self.message = f"Fehler: {e}" self.loading = False await self.on_populate() From baaa438e5eaf3798224c72880f546aed1ada4d66 Mon Sep 17 00:00:00 2001 From: tcprod Date: Sun, 8 Feb 2026 01:24:49 +0100 Subject: [PATCH 3/9] fix formatting balance bug in email --- src/ezgg_lan_manager/services/MailingService.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ezgg_lan_manager/services/MailingService.py b/src/ezgg_lan_manager/services/MailingService.py index 8636c68..b2d5492 100644 --- a/src/ezgg_lan_manager/services/MailingService.py +++ b/src/ezgg_lan_manager/services/MailingService.py @@ -45,7 +45,7 @@ class MailingService: return f""" Hallo {user.user_name}, - deinem Account wurden {added_balance} € hinzugefügt. Dein neues Guthaben beträgt nun {total_balance} €. + deinem Account wurden {added_balance:.2f} € hinzugefügt. Dein neues Guthaben beträgt nun {total_balance} €. Wenn du zu dieser Aufladung Fragen hast, stehen wir dir in unserem Discord Server oder per Mail an {self._configuration_service.get_lan_info().organizer_mail} zur Verfügung. From c73755f3b5398b67f81d25cf0098f48e4ad4b91a Mon Sep 17 00:00:00 2001 From: tcprod Date: Sun, 8 Feb 2026 01:28:27 +0100 Subject: [PATCH 4/9] fix formatting total balance bug in email --- src/ezgg_lan_manager/services/MailingService.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ezgg_lan_manager/services/MailingService.py b/src/ezgg_lan_manager/services/MailingService.py index b2d5492..cb3121f 100644 --- a/src/ezgg_lan_manager/services/MailingService.py +++ b/src/ezgg_lan_manager/services/MailingService.py @@ -45,7 +45,7 @@ class MailingService: return f""" Hallo {user.user_name}, - deinem Account wurden {added_balance:.2f} € hinzugefügt. Dein neues Guthaben beträgt nun {total_balance} €. + deinem Account wurden {added_balance:.2f} € hinzugefügt. Dein neues Guthaben beträgt nun {total_balance:.2f} €. Wenn du zu dieser Aufladung Fragen hast, stehen wir dir in unserem Discord Server oder per Mail an {self._configuration_service.get_lan_info().organizer_mail} zur Verfügung. From 24866966f40fd486ca00ad99f5153272398eb918 Mon Sep 17 00:00:00 2001 From: David Rodenkirchen Date: Sun, 8 Feb 2026 01:42:42 +0100 Subject: [PATCH 5/9] bump to version 0.2.1 --- README.md | 3 ++- VERSION | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 60f6d00..9d70fae 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ This repository contains the code for the EZGG LAN Manager. ### Step 1: Preparing Database -To prepare the database, apply the SQL file located in `sql/create_database.sql` to your database server. This is easily accomplished with the MYSQL Workbench, but it can be also done by pipeing the file into the mariadb-server executable. +To prepare the database, apply the SQL file located in `sql/create_database.sql` followed by `sql/tournament_patch.sql` to your database server. This is easily accomplished with the MYSQL Workbench, but it can be also done by pipeing the file into the mariadb-server executable. Optionally, you can now execute the script `create_demo_database_content.py`, found in `src/ezgg_lan_manager/helpers`. Be aware that it can be buggy sometimes, especially if you overwrite existing data. @@ -43,3 +43,4 @@ FLUSH PRIVILEGES; ``` 3. Make sure to **NOT** use the default passwords! 4. Apply the `create_database.sql` when starting the MariaDB container for the first time. +5. Apply the `tournament_patch.sql` when starting the MariaDB container for the first time. diff --git a/VERSION b/VERSION index 341cf11..7dff5b8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.0 \ No newline at end of file +0.2.1 \ No newline at end of file From 5a45af4465e1574e058d9e8ee080a76b0cbe50f2 Mon Sep 17 00:00:00 2001 From: tcprod Date: Sun, 8 Feb 2026 02:56:04 +0100 Subject: [PATCH 6/9] fix reset password --- sql/users_patch.sql | 3 +++ src/ezgg_lan_manager/pages/ForgotPassword.py | 2 +- .../services/DatabaseService.py | 25 ++++++++++--------- src/ezgg_lan_manager/services/UserService.py | 2 ++ src/ezgg_lan_manager/types/User.py | 1 + 5 files changed, 20 insertions(+), 13 deletions(-) create mode 100644 sql/users_patch.sql diff --git a/sql/users_patch.sql b/sql/users_patch.sql new file mode 100644 index 0000000..4aea0b3 --- /dev/null +++ b/sql/users_patch.sql @@ -0,0 +1,3 @@ +ALTER TABLE users +ADD COLUMN user_fallback_password VARCHAR(255) DEFAULT NULL +AFTER user_password; \ No newline at end of file diff --git a/src/ezgg_lan_manager/pages/ForgotPassword.py b/src/ezgg_lan_manager/pages/ForgotPassword.py index 9804a4a..b9b69bb 100644 --- a/src/ezgg_lan_manager/pages/ForgotPassword.py +++ b/src/ezgg_lan_manager/pages/ForgotPassword.py @@ -27,7 +27,7 @@ class ForgotPasswordPage(Component): user = await user_service.get_user(self.email_input.text.strip()) if user is not None: new_password = "".join(choices(user_service.ALLOWED_USER_NAME_SYMBOLS, k=16)) - user.user_password = sha256(new_password.encode(encoding="utf-8")).hexdigest() + user.user_fallback_password = sha256(new_password.encode(encoding="utf-8")).hexdigest() await user_service.update_user(user) await mailing_service.send_email( subject=f"Dein neues Passwort für {lan_info.name}", diff --git a/src/ezgg_lan_manager/services/DatabaseService.py b/src/ezgg_lan_manager/services/DatabaseService.py index ccbbfc1..977ea6b 100644 --- a/src/ezgg_lan_manager/services/DatabaseService.py +++ b/src/ezgg_lan_manager/services/DatabaseService.py @@ -75,14 +75,15 @@ class DatabaseService: user_name=data[1], user_mail=data[2], user_password=data[3], - user_first_name=data[4], - user_last_name=data[5], - user_birth_day=data[6], - is_active=bool(data[7]), - is_team_member=bool(data[8]), - is_admin=bool(data[9]), - created_at=data[10], - last_updated_at=data[11] + user_fallback_password=data[4], + user_first_name=data[5], + user_last_name=data[6], + user_birth_day=data[7], + is_active=bool(data[8]), + is_team_member=bool(data[9]), + is_admin=bool(data[10]), + created_at=data[11], + last_updated_at=data[12] ) @staticmethod @@ -185,10 +186,10 @@ class DatabaseService: async with conn.cursor(aiomysql.Cursor) as cursor: try: await cursor.execute( - "UPDATE users SET user_name=%s, user_mail=%s, user_password=%s, user_first_name=%s, " - "user_last_name=%s, user_birth_date=%s, is_active=%s, is_team_member=%s, is_admin=%s " - "WHERE (user_id=%s)", - (user.user_name, user.user_mail.lower(), user.user_password, + "UPDATE users SET user_name=%s, user_mail=%s, user_password=%s, user_fallback_password=%s," + "user_first_name=%s, user_last_name=%s, user_birth_date=%s, is_active=%s, is_team_member=%s," + " is_admin=%s WHERE (user_id=%s)", + (user.user_name, user.user_mail.lower(), user.user_password, user.user_fallback_password, user.user_first_name, user.user_last_name, user.user_birth_day, user.is_active, user.is_team_member, user.is_admin, user.user_id) diff --git a/src/ezgg_lan_manager/services/UserService.py b/src/ezgg_lan_manager/services/UserService.py index d341b51..7295683 100644 --- a/src/ezgg_lan_manager/services/UserService.py +++ b/src/ezgg_lan_manager/services/UserService.py @@ -61,6 +61,8 @@ class UserService: user = await self.get_user(user_name_or_mail) if not user: return False + if user.user_fallback_password: + user.user_fallback_password == sha256(password_clear_text.encode(encoding="utf-8")).hexdigest() return user.user_password == sha256(password_clear_text.encode(encoding="utf-8")).hexdigest() diff --git a/src/ezgg_lan_manager/types/User.py b/src/ezgg_lan_manager/types/User.py index a397962..9f9cece 100644 --- a/src/ezgg_lan_manager/types/User.py +++ b/src/ezgg_lan_manager/types/User.py @@ -9,6 +9,7 @@ class User: user_name: str user_mail: str user_password: str + user_fallback_password: Optional[str] user_first_name: Optional[str] user_last_name: Optional[str] user_birth_day: Optional[date] From 0b9c073900460615be457f29eb4e7f58fea428e5 Mon Sep 17 00:00:00 2001 From: tcprod Date: Tue, 10 Feb 2026 22:27:32 +0100 Subject: [PATCH 7/9] fix reset password --- src/ezgg_lan_manager/services/UserService.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ezgg_lan_manager/services/UserService.py b/src/ezgg_lan_manager/services/UserService.py index 7295683..54d4505 100644 --- a/src/ezgg_lan_manager/services/UserService.py +++ b/src/ezgg_lan_manager/services/UserService.py @@ -59,11 +59,13 @@ class UserService: async def is_login_valid(self, user_name_or_mail: str, password_clear_text: str) -> bool: user = await self.get_user(user_name_or_mail) + user_password_hash = sha256(password_clear_text.encode(encoding="utf-8")).hexdigest() if not user: return False - if user.user_fallback_password: - user.user_fallback_password == sha256(password_clear_text.encode(encoding="utf-8")).hexdigest() - return user.user_password == sha256(password_clear_text.encode(encoding="utf-8")).hexdigest() + if user.user_fallback_password and user.user_fallback_password == user_password_hash: + return True + return user.user_password == user_password_hash + def _check_for_disallowed_char(self, name: str) -> Optional[str]: From ca58f9d74c9a573e211dbb970300e142ffcf6250 Mon Sep 17 00:00:00 2001 From: tcprod Date: Tue, 10 Feb 2026 22:28:17 +0100 Subject: [PATCH 8/9] fix reset password --- src/ezgg_lan_manager/services/UserService.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ezgg_lan_manager/services/UserService.py b/src/ezgg_lan_manager/services/UserService.py index 54d4505..3721d7b 100644 --- a/src/ezgg_lan_manager/services/UserService.py +++ b/src/ezgg_lan_manager/services/UserService.py @@ -67,7 +67,6 @@ class UserService: return user.user_password == user_password_hash - def _check_for_disallowed_char(self, name: str) -> Optional[str]: for c in name: if c not in self.ALLOWED_USER_NAME_SYMBOLS: From 81671f8ab25e108b06f95efc064f6b08793c10ca Mon Sep 17 00:00:00 2001 From: tcprod Date: Thu, 12 Feb 2026 17:37:46 +0100 Subject: [PATCH 9/9] add patches to README.md and comment to patch --- README.md | 4 ++-- sql/users_patch.sql | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9d70fae..d683277 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ This repository contains the code for the EZGG LAN Manager. ### Step 1: Preparing Database -To prepare the database, apply the SQL file located in `sql/create_database.sql` followed by `sql/tournament_patch.sql` to your database server. This is easily accomplished with the MYSQL Workbench, but it can be also done by pipeing the file into the mariadb-server executable. +To prepare the database, apply the SQL file located in `sql/create_database.sql` to your database server. This is easily accomplished with the MYSQL Workbench, but it can be also done by pipeing the file into the mariadb-server executable. +After the database is created, apply the SQL patches located in `sql/*patch.sql` to support the fallback password- and tournament functionality. Optionally, you can now execute the script `create_demo_database_content.py`, found in `src/ezgg_lan_manager/helpers`. Be aware that it can be buggy sometimes, especially if you overwrite existing data. @@ -43,4 +44,3 @@ FLUSH PRIVILEGES; ``` 3. Make sure to **NOT** use the default passwords! 4. Apply the `create_database.sql` when starting the MariaDB container for the first time. -5. Apply the `tournament_patch.sql` when starting the MariaDB container for the first time. diff --git a/sql/users_patch.sql b/sql/users_patch.sql index 4aea0b3..e397ba3 100644 --- a/sql/users_patch.sql +++ b/sql/users_patch.sql @@ -1,3 +1,5 @@ +-- Apply this patch after using create_database.sql to extend the schema to support fallback passwords + ALTER TABLE users ADD COLUMN user_fallback_password VARCHAR(255) DEFAULT NULL AFTER user_password; \ No newline at end of file