feat: Spiele-Empfehlungs-Engine mit Scoring-Algorithmus
Quality Gate / 🛡️ Lint + Type Check + Tests (push) Failing after 11m56s
Quality Gate / 🛡️ Lint + Type Check + Tests (push) Failing after 11m56s
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
"""Spiele-Datenbank fuer die Empfehlungs-Engine."""
|
||||
|
||||
from typing import TypedDict
|
||||
|
||||
|
||||
class SPIEL(TypedDict):
|
||||
"""Struktur einer Spiel-Zeile."""
|
||||
|
||||
name: str
|
||||
min_spieler: int
|
||||
max_spieler: int
|
||||
dauer_min: int
|
||||
komplexitaet: float
|
||||
kategorien: list[str]
|
||||
|
||||
MIN_SPIELER_DEFAULT = 1
|
||||
MAX_SPIELER_DEFAULT = 10
|
||||
|
||||
|
||||
def spiele_laden() -> list[SPIEL]:
|
||||
"""Lädt eine vordefinierte Liste von Brettspielen.
|
||||
|
||||
Returns:
|
||||
Liste von Spiel-Dictionaries mit mindestens 8 Spielen.
|
||||
"""
|
||||
return [
|
||||
{
|
||||
"name": "Catan",
|
||||
"min_spieler": 3,
|
||||
"max_spieler": 4,
|
||||
"dauer_min": 60,
|
||||
"komplexitaet": 2.5,
|
||||
"kategorien": ["Strategie", "Aufbau", "Handel"],
|
||||
},
|
||||
{
|
||||
"name": "Carcassonne",
|
||||
"min_spieler": 2,
|
||||
"max_spieler": 5,
|
||||
"dauer_min": 45,
|
||||
"komplexitaet": 1.5,
|
||||
"kategorien": ["Familienspiel", "Bauen", "Karte"],
|
||||
},
|
||||
{
|
||||
"name": "Pandemic",
|
||||
"min_spieler": 2,
|
||||
"max_spieler": 4,
|
||||
"dauer_min": 45,
|
||||
"komplexitaet": 2.4,
|
||||
"kategorien": ["Strategie", "Kooperativ", "Abenteuer"],
|
||||
},
|
||||
{
|
||||
"name": "Codenames",
|
||||
"min_spieler": 4,
|
||||
"max_spieler": 8,
|
||||
"dauer_min": 15,
|
||||
"komplexitaet": 1.3,
|
||||
"kategorien": ["Partyspiel", "Worte", "Team"],
|
||||
},
|
||||
{
|
||||
"name": "Wunderland",
|
||||
"min_spieler": 2,
|
||||
"max_spieler": 4,
|
||||
"dauer_min": 60,
|
||||
"komplexitaet": 2.5,
|
||||
"kategorien": ["Strategie", "Worte", "Kreativ"],
|
||||
},
|
||||
{
|
||||
"name": "Ticket to Ride",
|
||||
"min_spieler": 2,
|
||||
"max_spieler": 5,
|
||||
"dauer_min": 60,
|
||||
"komplexitaet": 1.8,
|
||||
"kategorien": ["Familienspiel", "Reisen", "Bauen"],
|
||||
},
|
||||
{
|
||||
"name": "Dixit",
|
||||
"min_spieler": 3,
|
||||
"max_spieler": 6,
|
||||
"dauer_min": 30,
|
||||
"komplexitaet": 1.2,
|
||||
"kategorien": ["Partyspiel", "Träume", "Kreativ"],
|
||||
},
|
||||
{
|
||||
"name": "Wingspan",
|
||||
"min_spieler": 1,
|
||||
"max_spieler": 5,
|
||||
"dauer_min": 70,
|
||||
"komplexitaet": 3.1,
|
||||
"kategorien": ["Strategie", "Aufbau", "Natur"],
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def spiele_filtern(
|
||||
spiele: list[SPIEL],
|
||||
spieler_count: int | None = None,
|
||||
kategorien: list[str] | None = None,
|
||||
max_dauer: int | None = None,
|
||||
) -> list[SPIEL]:
|
||||
"""Filtert Spiele nach Spieleranzahl, Kategorien und Dauer.
|
||||
|
||||
Jeder Filter ist optional (None = kein Filter). Nur Spiele,
|
||||
die alle aktiven Filter erfüllen, werden zurückgegeben.
|
||||
|
||||
Args:
|
||||
spiele: Liste aller Spiele, die gefiltert werden sollen.
|
||||
spieler_count: Gesuchte Spieleranzahl.
|
||||
kategorien: Liste der Kategorien, die vorhanden sein müssen.
|
||||
max_dauer: Maximale Spieldauer in Minuten.
|
||||
|
||||
Returns:
|
||||
Gefilterte Liste der Spiele.
|
||||
"""
|
||||
ergebnis: list[SPIEL] = []
|
||||
|
||||
for spiel in spiele:
|
||||
if spieler_count is not None:
|
||||
if not (spiel["min_spieler"] <= spieler_count <= spiel["max_spieler"]):
|
||||
continue
|
||||
|
||||
if kategorien is not None:
|
||||
spiel_kat = spiel.get("kategorien", [])
|
||||
if not any(kat in spiel_kat for kat in kategorien):
|
||||
continue
|
||||
|
||||
if max_dauer is not None:
|
||||
if spiel.get("dauer_min", 999) > max_dauer:
|
||||
continue
|
||||
|
||||
ergebnis.append(spiel)
|
||||
|
||||
return ergebnis
|
||||
Reference in New Issue
Block a user