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