Runde wird automatisch aus der Tabelle ermittelt

This commit is contained in:
2026-05-24 15:42:17 +02:00
parent 82e37fb9bf
commit 08ec14bd63

View File

@@ -17,19 +17,25 @@ import json
import re
from datetime import datetime
CURRENT_ROUND = int(os.environ.get("CURRENT_ROUND", 2))
PGN_URL = f"https://www.deutsche-schachjugend.de/2026/odjm-d/partien/{CURRENT_ROUND}.pgn"
STANDINGS_URL = "https://www.deutsche-schachjugend.de/2026/odjm-d/tabelle/"
PORT = int(os.environ.get("PORT", 8111))
CACHE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "cache")
CACHE_FILE = os.path.join(CACHE_DIR, f"runde-{CURRENT_ROUND}.pgn")
STANDINGS_CACHE_FILE = os.path.join(CACHE_DIR, "standings.json")
CACHE_TTL = int(os.environ.get("CACHE_TTL", 31)) # Sekunden
CACHE_TTL = int(os.environ.get("CACHE_TTL", 31))
os.makedirs(CACHE_DIR, exist_ok=True)
last_fetch_time = None
last_standings_fetch_time = None
current_round = 0 # wird aus der Tabelle ermittelt
def get_pgn_url():
return f"https://www.deutsche-schachjugend.de/2026/odjm-d/partien/{current_round}.pgn"
def get_cache_file():
return os.path.join(CACHE_DIR, f"runde-{current_round}.pgn")
def fetch_pgn():
@@ -37,11 +43,14 @@ def fetch_pgn():
Nutzt If-Modified-Since gibt (data, changed) zurück.
changed=False bedeutet 304 Not Modified (keine neuen Daten)."""
global last_fetch_time
if current_round == 0:
return None, False
url = get_pgn_url()
try:
headers = {"User-Agent": "Mozilla/5.0"}
if last_fetch_time:
headers["If-Modified-Since"] = datetime.utcfromtimestamp(last_fetch_time).strftime("%a, %d %b %Y %H:%M:%S GMT")
req = urllib.request.Request(PGN_URL, headers=headers)
req = urllib.request.Request(url, headers=headers)
with urllib.request.urlopen(req, timeout=31) as response:
data = response.read()
last_fetch_time = time.time()
@@ -60,33 +69,35 @@ def get_pgn_content_longpoll(since=0):
"""Long-Poll: Blockiert, bis sich die PGN-Datei tatsächlich ändert.
Antwortet nur bei neuen Daten, nie mit unverändertem Stand."""
while True:
if os.path.exists(CACHE_FILE):
mtime = os.path.getmtime(CACHE_FILE)
cache_file = get_cache_file()
if os.path.exists(cache_file):
mtime = os.path.getmtime(cache_file)
if mtime > since:
with open(CACHE_FILE, "rb") as f:
with open(cache_file, "rb") as f:
return f.read(), mtime
age = time.time() - mtime
if age >= CACHE_TTL:
content, changed = fetch_pgn()
if changed and content is not None:
with open(CACHE_FILE, "wb") as f:
with open(cache_file, "wb") as f:
f.write(content)
new_mtime = os.path.getmtime(CACHE_FILE)
new_mtime = os.path.getmtime(cache_file)
print(f"[{datetime.now().strftime('%H:%M:%S')}] PGN via Long-Poll aktualisiert ({len(content)} Bytes)")
return content, new_mtime
else:
content, changed = fetch_pgn()
if changed and content is not None:
with open(CACHE_FILE, "wb") as f:
with open(cache_file, "wb") as f:
f.write(content)
return content, os.path.getmtime(CACHE_FILE)
return content, os.path.getmtime(cache_file)
time.sleep(5)
def fetch_standings():
"""Lädt die Tabellenseite und parst Laras Platzierung."""
global last_standings_fetch_time
"""Lädt die Tabellenseite und parst Laras Platzierung.
Ermittelt dabei auch die aktuelle Runde."""
global last_standings_fetch_time, current_round
try:
headers = {"User-Agent": "Mozilla/5.0"}
if last_standings_fetch_time:
@@ -96,13 +107,16 @@ def fetch_standings():
html = response.read().decode("utf-8", errors="replace")
last_standings_fetch_time = time.time()
# Rundeninfo extrahieren
round_info = ""
m = re.search(r"Tabellenstand\s+nach\s+der\s+(\d+)\.\s*Runde", html)
if m:
detected = int(m.group(1))
if detected != current_round:
old = current_round
current_round = detected
print(f"[{datetime.now().strftime('%H:%M:%S')}] Runde erkannt: {current_round} (war {old})")
round_info = f"nach der {m.group(1)}. Runde"
# Tabellenzeilen suchen
rows = re.findall(r"<tr[^>]*>(.*?)</tr>", html, re.DOTALL | re.IGNORECASE)
for row in rows:
if "Lara Kiesewetter" not in row:
@@ -238,9 +252,10 @@ def background_refresh():
while True:
time.sleep(CACHE_TTL)
try:
content = fetch_pgn()
if content:
with open(CACHE_FILE, "wb") as f:
content, changed = fetch_pgn()
if changed and content is not None:
cache_file = get_cache_file()
with open(cache_file, "wb") as f:
f.write(content)
except Exception as e:
print(f"[{datetime.now().strftime('%H:%M:%S')}] Hintergrund-Refresh Fehler: {e}")
@@ -254,10 +269,18 @@ def main():
print(f" Drücke Ctrl+C zum Beenden")
print("=" * 50)
# Initialer Ladeversuch
content = fetch_pgn()
if content:
with open(CACHE_FILE, "wb") as f:
# Runde aus Tabelle ermitteln
standings = fetch_standings()
if standings and current_round > 0:
print(f"[OK] Aktuelle Runde: {current_round}")
else:
current_round = 1
print("[INFO] Starte mit Runde 1 (Tabelle noch nicht verfügbar)")
content, changed = fetch_pgn()
if changed and content is not None:
cache_file = get_cache_file()
with open(cache_file, "wb") as f:
f.write(content)
print(f"[OK] PGN geladen ({len(content)} Bytes)")
else: