﻿"""
Zadanie 3: Niezmienne punkty i ranking (frozen i order)
Scenariusz: Klasy Immutable oraz automatyczne generowanie operatorów porównania do sortowania danych.
"""

from dataclasses import dataclass

# Parametr frozen=True sprawia, że instancje tej klasy stają się "tylko do odczytu".
# Po utworzeniu obiektu, jakakolwiek próba modyfikacji atrybutów rzuci wyjątek FrozenInstanceError.
# Dzięki temu obiekty są bezpieczne w środowiskach wielowątkowych i mogą służyć np. jako klucze w słownikach.
@dataclass(frozen=True)
class Punkt3D:
    """Klasa reprezentująca niemutowalny punkt w przestrzeni trójwymiarowej."""
    x: float
    y: float
    z: float

# Parametr order=True automatycznie generuje metody służące do porównywania obiektów (__, <, >, <=, >=).
# Obiekty są porównywane pole po polu, w kolejności ich definicji (od góry do dołu).
# W tym przypadku kluczowym elementem sortowania będą punkty gracza, więc to pole musi być pierwsze.
@dataclass(order=True)
class Wynik:
    """Klasa reprezentująca wynik gracza w systemie rankingowym."""
    # Definiujemy punkty jako pierwsze, by sortowanie odbywało się na ich podstawie
    punkty: int
    gracz: str

if __name__ == "__main__":
    print(">>> p = Punkt3D(1, 2, 3)")
    p = Punkt3D(1, 2, 3)
    
    print(">>> p.x = 5")
    # Próba modyfikacji rzuci FrozenInstanceError
    try:
        p.x = 5
    except Exception as e:
        # Wypisujemy wyjątek zgodnie ze wzorcem w scenariuszu
        print(f"dataclasses.{type(e).__name__}")


    w1 = Wynik(100, "Adam")
    w2 = Wynik(150, "Ewa")
    
    print(">>> w1 = Wynik(100, \"Adam\")")
    print(">>> w2 = Wynik(150, \"Ewa\")")
    print(">>> print(w1 < w2)")
    print(w1 < w2)

    # Sortowanie listy
    # Korzystamy z wbudowanej w listę metody .sort()
    # Metody porównujące (__lt__, __gt__) zostały wygenerowane automatycznie.
    lista_wynikow = [w2, Wynik(50, "Kasia"), w1]
    lista_wynikow.sort(reverse=True) # Sortujemy malejąco
    print("\n[Dodatkowy test] Wyniki po posortowaniu (malejąco):")
    for w in lista_wynikow:
        print(w)
