Files
BSN-Chatsystem/bgg-scrape/build_report.py
T

102 lines
5.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import xml.etree.ElementTree as ET
import json
# Game descriptions mapping (manual descriptions based on known games)
game_descriptions = {
"400366": "Wondrous Creatures Ein Worker-Placement-Spiel mit fantastischen Kreaturen und innovativem Ressourcen-Management von Bad Comet.",
"472021": "Medico Medizinisches Themen-Brettspiel (2026). Neu in der Hotness Details noch spärlich.",
"403150": "World Order Geopolitisches Area-Control-Strategiespiel von Hegemonic Project Games (2026).",
"434172": "Excalibur Artus-Sagen-Themenbrettspiel (2026) mit epischen Quests und Schwert-in-Stein-Mechanik.",
"425549": "Moon Colony Bloodbath Kartenspiel mit Sci-Fi-Horror-Thema von Donald X. Vaccarino (Dominion-Autor).",
"415848": "Lands of Evershade Fantasy-Rollenspiel-inspiriertes Brettspiel mit Kampagnen-Modus (2026).",
"436217": "The Lord of the Rings: Fate of the Fellowship Kooperatives Herr-der-Ringe-Abenteuerspiel (2025).",
"457008": "Friendly Fishing Familienfreundliches Angel-Brettspiel (2026), zugänglich und schnell.",
"357873": "The Old King's Crown Strategisches Kartenspiel mit mittelalterlichem Thronfolge-Thema (2025).",
"418059": "SETI: Search for Extraterrestrial Intelligence Wissenschaftsbasiertes Eurogame zur Suche nach außerirdischem Leben.",
"417197": "Rebirth Reiner Knizia's Wiederaufbau-Strategiespiel mit Plättchenlege-Mechanik.",
"432456": "dnup Kartenspiel mit Wendemechanik und abstraktem Thema (2025).",
"454103": "Magical Athlete Fantasie-Sport-Brettspiel mit magischen Fähigkeiten (2025).",
"381248": "Nemesis: Retaliation Semi-kooperatives Sci-Fi-Horror-Spiel, neuester Teil der Nemesis-Reihe von Awaken Realms.",
"342942": "Ark Nova Aufbau eines modernen Zoos als tiefes strategisches Kartenspiel. Aktuell #4 der BGG-Rangliste."
}
# Fetch the actual descriptions from XMLs
descriptions = {}
for gid in game_descriptions:
try:
tree = ET.parse(f'/home/hermes/workspace/bgg-scrape/game_{gid}.xml')
root = tree.getroot()
for item in root.findall('item'):
desc_elem = item.find('description')
if desc_elem is not None and desc_elem.text:
desc_text = desc_elem.text[:300].strip()
descriptions[gid] = desc_text
# Get year
year_elem = item.find('yearpublished')
if year_elem is not None:
year = year_elem.get('value', '')
# Get stats
stats = item.find("statistics/ratings")
if stats is not None:
avg = stats.find("average")
avg_rating = avg.get('value', 'N/A') if avg is not None else 'N/A'
ranks = stats.find("ranks")
bgg_rank = 'N/A'
if ranks is not None:
for r in ranks.findall('rank'):
if r.get('name') == 'boardgame':
bgg_rank = r.get('value', 'N/A')
descriptions[gid + '_stats'] = f"{avg_rating} | BGG Rank: {bgg_rank}"
except Exception as e:
descriptions[gid] = f"Error: {e}"
# Print report
print("=" * 70)
print(" BOARDGAMEGEEK HOTNESS TOP 15 (6.-7. Juni 2026)")
print("=" * 70)
print()
items = [
("1", "Wondrous Creatures", "400366"),
("2", "Medico", "472021"),
("3", "World Order", "403150"),
("4", "Excalibur", "434172"),
("5", "Moon Colony Bloodbath", "425549"),
("6", "Lands of Evershade", "415848"),
("7", "The Lord of the Rings: Fate of the Fellowship", "436217"),
("8", "Friendly Fishing", "457008"),
("9", "The Old King's Crown", "357873"),
("10", "SETI: Search for Extraterrestrial Intelligence", "418059"),
("11", "Rebirth", "417197"),
("12", "dnup", "432456"),
("13", "Magical Athlete", "454103"),
("14", "Nemesis: Retaliation", "381248"),
("15", "Ark Nova", "342942"),
]
for i, (rank, name, gid) in enumerate(items, 1):
print(f"#{rank} {name}")
print(f" ID: {gid}")
stats = descriptions.get(gid + '_stats', 'Stats: N/A')
print(f" {stats}")
desc = descriptions.get(gid, game_descriptions.get(gid, ''))
if desc:
# Strip HTML and truncate
import re
clean = re.sub(r'<[^>]+>', '', desc)
clean = re.sub(r'&#?\w+;', ' ', clean)
clean = re.sub(r'\s+', ' ', clean).strip()
if len(clean) > 280:
clean = clean[:277] + '...'
print(f" Beschreibung: {clean}")
else:
print(f" Beschreibung: {game_descriptions.get(gid, 'Keine Beschreibung verfügbar.')}")
print(f" Relevanz: {'HOTTEST' if i <= 3 else '🔥 Hoch' if i <= 7 else '★ Mittel' if i <= 12 else '· Stabil'}")
print()
print("\n---")
print("Datenquelle: BGG XML API v2 (de3b01db-9be3-4c80-bd80-d47e071b320e)")
print("User-Agent: BSN-OpenClaw/1.0")
print("Abrufdatum: 6. Juni 2026")
print("Hinweis: BGG-News-Forum (ID=27) war unter CloudFlare-Schutz HTML-Scraping nicht möglich. Forum-ID=1 (News) nur 1 Thread (2009). Hotness via API erfolgreich.")