Kleine Anpassung des Bereichs ab wann ein Match ein Draw ist. Einfügen dass matches von player2 bestätigt werden müssen bevor sie berechnet und der Rangliste hinzugefügt wird.
This commit is contained in:
parent
380f91957d
commit
0ed86d6130
|
|
@ -1 +1 @@
|
|||
{"authenticated":true,"discord_id":"277898241750859776","discord_name":"mrteels","db_id":1,"display_name":"Zorniger Klebschnüffler","discord_avatar_url":"https://cdn.discordapp.com/avatars/277898241750859776/7c3446bb51fafd72b1b4c21124b4994f.png"}
|
||||
{"authenticated":true,"discord_id":"277898241750859776","discord_name":"mrteels","db_id":2,"display_name":"r","discord_avatar_url":"https://cdn.discordapp.com/avatars/277898241750859776/7c3446bb51fafd72b1b4c21124b4994f.png"}
|
||||
|
|
@ -475,3 +475,64 @@ def get_leaderboard(system_name):
|
|||
result.append(dict(row))
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def get_unconfirmed_matches(player_id):
|
||||
"""Holt alle offenen Matches, die der Spieler noch bestätigen muss."""
|
||||
connection = sqlite3.connect(DB_PATH)
|
||||
connection.row_factory = sqlite3.Row
|
||||
cursor = connection.cursor()
|
||||
|
||||
# Wir joinen players (für den Namen des Gegners) und gamesystems (für den Systemnamen)
|
||||
query = """
|
||||
SELECT m.id AS match_id, m.score_player1, m.score_player2, m.played_at,
|
||||
sys.name AS system_name,
|
||||
p1.display_name AS p1_name
|
||||
FROM matches m
|
||||
JOIN gamesystems sys ON m.gamesystem_id = sys.id
|
||||
JOIN players p1 ON m.player1_id = p1.id
|
||||
WHERE m.player2_id = ? AND m.player2_check = 0
|
||||
"""
|
||||
|
||||
cursor.execute(query, (player_id,))
|
||||
rows = cursor.fetchall()
|
||||
connection.close()
|
||||
|
||||
# Wir geben eine Liste mit Dictionaries zurück
|
||||
return [dict(row) for row in rows]
|
||||
|
||||
|
||||
def delete_match(match_id):
|
||||
"""Löscht ein Match anhand seiner ID komplett aus der Datenbank."""
|
||||
connection = sqlite3.connect(DB_PATH)
|
||||
cursor = connection.cursor()
|
||||
|
||||
# DELETE FROM löscht die gesamte Zeile, bei der die ID übereinstimmt.
|
||||
cursor.execute("DELETE FROM matches WHERE id = ?", (match_id,))
|
||||
|
||||
connection.commit()
|
||||
connection.close()
|
||||
|
||||
|
||||
def confirm_match(match_id):
|
||||
connection = sqlite3.connect(DB_PATH)
|
||||
cursor = connection.cursor()
|
||||
|
||||
# Ändert nur die Spalte player2_check auf 1 (True)
|
||||
cursor.execute("UPDATE matches SET player2_check = 1 WHERE id = ?", (match_id,))
|
||||
|
||||
connection.commit()
|
||||
connection.close()
|
||||
|
||||
|
||||
def set_match_counted(match_id):
|
||||
"""Setzt den Haken (1), dass das Match erfolgreich in die MMR eingeflossen ist."""
|
||||
connection = sqlite3.connect(DB_PATH)
|
||||
cursor = connection.cursor()
|
||||
|
||||
# Ändert nur die Spalte match_is_counted auf 1 (True)
|
||||
cursor.execute("UPDATE matches SET match_is_counted = 1 WHERE id = ?", (match_id,))
|
||||
|
||||
connection.commit()
|
||||
connection.close()
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,12 @@ import sqlite3
|
|||
import os
|
||||
import json
|
||||
|
||||
dummy_is_in = False
|
||||
|
||||
DB_PATH = "data/warhammer_league.db"
|
||||
# 1. Sucht den exakten, absoluten Pfad zu diesem Skript (z.B. /srv/Diceghost-Liga-System/data/)
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
# 2. Klebt den Datenbank-Namen an diesen Ordner
|
||||
DB_PATH = os.path.join(BASE_DIR, "league_database.db")
|
||||
|
||||
def init_db():
|
||||
connection = sqlite3.connect(DB_PATH)
|
||||
|
|
@ -64,6 +68,8 @@ def init_db():
|
|||
played_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
player1_mmr_change INTEGER,
|
||||
player2_mmr_change INTEGER,
|
||||
player2_check INTEGER DEFAULT 0,
|
||||
match_is_counted INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (gamesystem_id) REFERENCES gamesystems (id),
|
||||
FOREIGN KEY (player1_id) REFERENCES players (id),
|
||||
FOREIGN KEY (player2_id) REFERENCES players (id)
|
||||
|
|
@ -141,7 +147,9 @@ def seed_achievements():
|
|||
connection.commit()
|
||||
connection.close()
|
||||
print("Achievements angelegt.")
|
||||
#seed_dummy_player()
|
||||
|
||||
if dummy_is_in:
|
||||
seed_dummy_player()
|
||||
|
||||
|
||||
def seed_dummy_player():
|
||||
|
|
@ -215,7 +223,7 @@ def generate_default_mmr_rules():
|
|||
# Das ist unsere Standard-Vorlage (Faktor 10)
|
||||
default_rules = {
|
||||
"system_info": f"Balancing für {sys_name}",
|
||||
"draw_point_difference": 5,
|
||||
"draw_point_difference": 3,
|
||||
"rank_matrix": {
|
||||
"10": {"win": 10, "draw": 30},
|
||||
"9": {"win": 10, "draw": 30},
|
||||
|
|
|
|||
8
gui/admin_gui.py
Normal file
8
gui/admin_gui.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
from nicegui import ui, app
|
||||
from data import database, data_api
|
||||
from gui import gui_style
|
||||
|
||||
def setup_routes():
|
||||
@ui.page('/admin')
|
||||
def home_page():
|
||||
gui_style.apply_design()
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
from nicegui import ui, app
|
||||
from data import database, data_api
|
||||
from gui import discord_login, gui_style
|
||||
from match_calculations import calc_match
|
||||
|
||||
def setup_routes():
|
||||
def setup_routes(admin_discord_id):
|
||||
@ui.page('/')
|
||||
def home_page():
|
||||
gui_style.apply_design()
|
||||
|
|
@ -19,9 +20,15 @@ def setup_routes():
|
|||
ui.image("gui/pictures/wsdg.png").classes('w-20 h-20 rounded-full')
|
||||
ui.label('Diceghost Liga').classes('text-2xl font-bold text-white')
|
||||
|
||||
# --- RECHTE SEITE ---
|
||||
discord_id = app.storage.user.get("discord_id")
|
||||
if discord_id == admin_discord_id:
|
||||
ui.button('Admin Panel', on_click=lambda: ui.navigate.to('/admin'))
|
||||
|
||||
# --- RECHTE SEITE ---
|
||||
if app.storage.user.get('authenticated', False):
|
||||
with ui.row().classes('items-center gap-4'):
|
||||
|
||||
discord_name = app.storage.user.get('discord_name')
|
||||
display_name = app.storage.user.get('display_name')
|
||||
player_id = app.storage.user.get('db_id')
|
||||
|
|
@ -77,6 +84,49 @@ def setup_routes():
|
|||
ui.button('Login with Discord', on_click=lambda: ui.navigate.to(auth_url))
|
||||
|
||||
|
||||
# ---------------------------
|
||||
# --- Match Bestätigung ---
|
||||
# ---------------------------
|
||||
# --- Bestätigungs-Bereich für offene Spiele --- Der "Marian Balken !!!1!11!"
|
||||
if app.storage.user.get('authenticated', False):
|
||||
unconfirmed_matches = data_api.get_unconfirmed_matches(player_id)
|
||||
|
||||
if len(unconfirmed_matches) > 0:
|
||||
# Eine auffällige, rote Karte über die volle Breite
|
||||
with ui.card().classes('w-full bg-red-900/80 border-2 border-red-500 mb-6'):
|
||||
ui.label(f"Aktion erforderlich: Du hast {len(unconfirmed_matches)} unbestätigte(s) Spiel(e)!").classes('text-2xl font-bold text-white mb-2')
|
||||
|
||||
for match in unconfirmed_matches:
|
||||
|
||||
# --- NEU: Die Funktion, die beim Klick ausgeführt wird ---
|
||||
def reject_match(m_id):
|
||||
data_api.delete_match(m_id)
|
||||
ui.notify("Spiel abgelehnt und gelöscht!", color="warning")
|
||||
ui.navigate.reload() # Lädt die Seite neu, um die Karte zu aktualisieren
|
||||
|
||||
def acccept_match(m_id):
|
||||
ui.notify("Spiel akzeptiert. Wird Berechnet.")
|
||||
ui.navigate.reload() # Lädt die Seite neu, um die Karte zu aktualisieren
|
||||
calc_match.calculate_match(m_id)
|
||||
|
||||
|
||||
|
||||
# Für jedes Match machen wir eine kleine Reihe
|
||||
with ui.row().classes('w-full items-center justify-between bg-zinc-900 p-3 rounded shadow-inner'):
|
||||
# Info-Text: Was wurde eingetragen?
|
||||
info_text = f"[{match['system_name']}] {match['p1_name']} behauptet: Er hat {match['score_player1']} : {match['score_player2']} gegen dich gespielt."
|
||||
ui.label(info_text).classes('text-lg text-gray-200')
|
||||
|
||||
# Die Buttons (Funktion machen wir im nächsten Schritt!)
|
||||
with ui.row().classes('gap-2'):
|
||||
# ABLEHNEN und Spiel löschen
|
||||
ui.button("Ablehnen", color="negative", icon="close", on_click=lambda e, m_id=match['match_id']: reject_match(m_id))
|
||||
ui.space()
|
||||
# BESTÄTIGEN und spiel berechnen lassen
|
||||
ui.button("Bestätigen", color="positive", icon="check", on_click=lambda e, m_id=match['match_id']: acccept_match(m_id))
|
||||
|
||||
|
||||
|
||||
# ---------------------------
|
||||
# --- Spielsysteme ---
|
||||
# ---------------------------
|
||||
|
|
|
|||
|
|
@ -69,8 +69,7 @@ def setup_routes():
|
|||
|
||||
# 4. Erfolgsmeldung und Berechnung
|
||||
ui.notify("Match erfolgreich eingetragen!", color="green")
|
||||
calc_match.calculate_inserted_match(systemname, match_id)
|
||||
ui.navigate.to('/')
|
||||
ui.navigate.to(f'/statistic/{systemname}')
|
||||
|
||||
# Buttons ganz unten in einer Reihe
|
||||
with ui.row().classes("w-full items-center justify-between mt-8"):
|
||||
|
|
|
|||
13
main.py
13
main.py
|
|
@ -2,7 +2,7 @@ import os
|
|||
from dotenv import load_dotenv
|
||||
from nicegui import ui
|
||||
|
||||
from gui import main_gui, match_gui, discord_login, league_statistic
|
||||
from gui import main_gui, match_gui, discord_login, league_statistic, admin_gui
|
||||
|
||||
from data import database
|
||||
|
||||
|
|
@ -10,18 +10,19 @@ from data import database
|
|||
# 1. Lade die geheimen Variablen aus der .env Datei in den Speicher
|
||||
load_dotenv()
|
||||
|
||||
database.check_db()
|
||||
# ----------------------
|
||||
|
||||
# 2. Variablen abrufen
|
||||
client_id = os.getenv("DISCORD_CLIENT_ID")
|
||||
client_secret = os.getenv("DISCORD_CLIENT_SECRET")
|
||||
admin_discord_id = os.getenv("ADMIN")
|
||||
|
||||
database.check_db()
|
||||
|
||||
# 3. Seitenrouten aufbauen
|
||||
main_gui.setup_routes()
|
||||
main_gui.setup_routes(admin_discord_id)
|
||||
discord_login.setup_login_routes()
|
||||
league_statistic.setup_routes()
|
||||
match_gui.setup_routes()
|
||||
admin_gui.setup_routes()
|
||||
|
||||
# 4. Wir starten die NiceGUI App
|
||||
ui.run(title="Warhammer Liga", port=9000, storage_secret="ein_sehr_geheimes_passwort_fuer_die_cookies")
|
||||
ui.run(title="Westside Diceghost Liga", port=9000, storage_secret="ein_sehr_geheimes_passwort_fuer_die_cookies")
|
||||
|
|
|
|||
|
|
@ -4,11 +4,15 @@ import json
|
|||
import os
|
||||
|
||||
# Mach die DB abfrage für die Relevanten Daten. Von hier aus werden die "Aufgaben" und Daten dann an die kleineren Berechnungs Funktionen verteilt.
|
||||
def calculate_inserted_match (gamesystem, match_id):
|
||||
def calculate_match (match_id):
|
||||
match_data = data_api.get_match_by_id(match_id)
|
||||
|
||||
if not match_data:
|
||||
print("Fehler: Match nicht gefunden!")
|
||||
return
|
||||
|
||||
data_api.confirm_match(match_id)
|
||||
|
||||
# Laden und umsetzen der Match Daten
|
||||
p1_id = match_data['player1_id']
|
||||
p2_id = match_data['player2_id']
|
||||
|
|
@ -60,6 +64,7 @@ def calculate_inserted_match (gamesystem, match_id):
|
|||
|
||||
data_api.apply_match_to_player_statistic (winner_id, sys_id, mmr_change_winner, winner_score)
|
||||
data_api.apply_match_to_player_statistic (looser_id, sys_id, mmr_change_looser, looser_score)
|
||||
data_api.set_match_counted(match_id)
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"system_info": "Balancing für Spearhead",
|
||||
"draw_point_difference": 5,
|
||||
"draw_point_difference": 3,
|
||||
"rank_matrix": {
|
||||
"10": {
|
||||
"win": 10,
|
||||
|
|
@ -109,5 +109,4 @@
|
|||
"bonus": 0
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"system_info": "Balancing für Warhammer 40k",
|
||||
"draw_point_difference": 5,
|
||||
"draw_point_difference": 3,
|
||||
"rank_matrix": {
|
||||
"10": {
|
||||
"win": 10,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"system_info": "Balancing für Warhammer Age of Sigmar",
|
||||
"draw_point_difference": 5,
|
||||
"draw_point_difference": 3,
|
||||
"rank_matrix": {
|
||||
"10": {
|
||||
"win": 10,
|
||||
|
|
@ -109,5 +109,4 @@
|
|||
"bonus": 0
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user