143 lines
5.3 KiB
Python
143 lines
5.3 KiB
Python
"""
|
|
Kapitel 13: Datei-Persistenz (JSON & CSV) 💾📁
|
|
==============================================
|
|
Musterlösung für JSON- und CSV-Persistenz in Python OOP.
|
|
"""
|
|
|
|
import json
|
|
import csv
|
|
from pathlib import Path
|
|
from typing import List, Optional, Dict, Any
|
|
|
|
|
|
# ==============================================================================
|
|
# 1. Klasse Spieler mit to_dict / from_dict
|
|
# ==============================================================================
|
|
class Spieler:
|
|
def __init__(self, name: str, level: int, punkte: int, inventar: Optional[List[str]] = None):
|
|
"""Initialisiert ein Spieler-Objekt."""
|
|
self.name: str = name
|
|
self.level: int = int(level)
|
|
self.punkte: int = int(punkte)
|
|
self.inventar: List[str] = list(inventar) if inventar is not None else []
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
"""Konvertiert das Objekt in ein speicherbares Dictionary."""
|
|
return {
|
|
"name": self.name,
|
|
"level": self.level,
|
|
"punkte": self.punkte,
|
|
"inventar": self.inventar,
|
|
}
|
|
|
|
@classmethod
|
|
def from_dict(cls, daten: Dict[str, Any]) -> "Spieler":
|
|
"""Erstellt ein neues Spieler-Objekt aus einem Dictionary."""
|
|
return cls(
|
|
name=daten["name"],
|
|
level=int(daten["level"]),
|
|
punkte=int(daten["punkte"]),
|
|
inventar=list(daten.get("inventar", [])),
|
|
)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"Spieler(name='{self.name}', level={self.level}, punkte={self.punkte}, inventar={self.inventar})"
|
|
|
|
def __eq__(self, other: object) -> bool:
|
|
if not isinstance(other, Spieler):
|
|
return False
|
|
return (
|
|
self.name == other.name
|
|
and self.level == other.level
|
|
and self.punkte == other.punkte
|
|
and self.inventar == other.inventar
|
|
)
|
|
|
|
|
|
# ==============================================================================
|
|
# 2. Klasse Spielstand mit JSON & CSV Persistenz
|
|
# ==============================================================================
|
|
class Spielstand:
|
|
def __init__(self, titel: str = "Neuer Spielstand"):
|
|
"""Initialisiert einen Spielstand mit Titel und leerer Spielerliste."""
|
|
self.titel: str = titel
|
|
self.spieler_liste: List[Spieler] = []
|
|
|
|
def spieler_hinzufuegen(self, spieler: Spieler) -> None:
|
|
"""Fügt einen Spieler hinzu."""
|
|
self.spieler_liste.append(spieler)
|
|
|
|
def spieler_suchen(self, name: str) -> Optional[Spieler]:
|
|
"""Findet einen Spieler anhand seines Namens."""
|
|
for s in self.spieler_liste:
|
|
if s.name == name:
|
|
return s
|
|
return None
|
|
|
|
def bester_spieler(self) -> Optional[Spieler]:
|
|
"""Gibt den Spieler mit der höchsten Punktzahl zurück."""
|
|
if not self.spieler_liste:
|
|
return None
|
|
return max(self.spieler_liste, key=lambda s: s.punkte)
|
|
|
|
def speichern_als_json(self, dateipfad: str | Path) -> None:
|
|
"""Speichert den gesamten Zustand als JSON auf der Festplatte."""
|
|
pfad = Path(dateipfad)
|
|
daten = {
|
|
"titel": self.titel,
|
|
"spieler": [s.to_dict() for s in self.spieler_liste],
|
|
}
|
|
with open(pfad, "w", encoding="utf-8") as f:
|
|
json.dump(daten, f, indent=4, ensure_ascii=False)
|
|
|
|
def laden_aus_json(self, dateipfad: str | Path) -> None:
|
|
"""Lädt den Spielstand aus einer JSON-Datei."""
|
|
pfad = Path(dateipfad)
|
|
with open(pfad, "r", encoding="utf-8") as f:
|
|
daten = json.load(f)
|
|
|
|
self.titel = daten.get("titel", self.titel)
|
|
spieler_rohdaten = daten.get("spieler", [])
|
|
self.spieler_liste = [Spieler.from_dict(d) for d in spieler_rohdaten]
|
|
|
|
def exportiere_als_csv(self, dateipfad: str | Path) -> None:
|
|
"""Exportiert eine tabellarische Zusammenfassung als CSV-Datei."""
|
|
pfad = Path(dateipfad)
|
|
feldnamen = ["name", "level", "punkte", "inventar_anzahl"]
|
|
|
|
with open(pfad, "w", newline="", encoding="utf-8") as f:
|
|
writer = csv.DictWriter(f, fieldnames=feldnamen)
|
|
writer.writeheader()
|
|
for s in self.spieler_liste:
|
|
writer.writerow({
|
|
"name": s.name,
|
|
"level": s.level,
|
|
"punkte": s.punkte,
|
|
"inventar_anzahl": len(s.inventar),
|
|
})
|
|
|
|
def importiere_aus_csv(self, dateipfad: str | Path) -> int:
|
|
"""Importiert Spieler aus einer CSV-Datei."""
|
|
pfad = Path(dateipfad)
|
|
importierte_anzahl = 0
|
|
|
|
with open(pfad, "r", newline="", encoding="utf-8") as f:
|
|
reader = csv.DictReader(f)
|
|
for zeile in reader:
|
|
neuer_spieler = Spieler(
|
|
name=zeile["name"],
|
|
level=int(zeile["level"]),
|
|
punkte=int(zeile["punkte"]),
|
|
inventar=[]
|
|
)
|
|
self.spieler_hinzufuegen(neuer_spieler)
|
|
importierte_anzahl += 1
|
|
|
|
return importierte_anzahl
|
|
|
|
|
|
if __name__ == "__main__":
|
|
spielstand = Spielstand("Musterloesung Spielstand")
|
|
spielstand.spieler_hinzufuegen(Spieler("Gandalf", 99, 99999, ["Stab", "Ring"]))
|
|
spielstand.speichern_als_json("test_muster.json")
|
|
print("Erfolgreich ausgeführt!")
|