﻿# Rozwiązanie zadania 4: Synchronizacja jednostek - termometr
# Używamy języka angielskiego w kodzie, ale polskich komentarzy z szerokimi wyjaśnieniami.

class Thermometer:
    """
    Klasa symulująca termometr. 
    Demonstruje potężne możliwości @property polegające na synchronizowaniu 
    wartości dwóch teoretycznie różnych "zmiennych" (Celsius i Fahrenheit),
    będących odzwierciedleniem jednego stanu wewnętrznego (_celsius).
    """

    def __init__(self, temp_celsius=0.0):
        """
        Termometr wewnętrznie przechowuje temperaturę zawsze tylko w Celsjuszach.
        To nasz bazowy format (Single Source of Truth).
        """
        # Ustawiamy stan początkowy by móc przejść przez walidację settera
        self._celsius = 0.0
        # Od razu przekazujemy wartość do zwalidowania i ustawienia
        self.celsius = temp_celsius

    @property
    def celsius(self):
        """Getter temperatury w skali Celsjusza."""
        return self._celsius

    @celsius.setter
    def celsius(self, value):
        """
        Setter dla Celsjusza z uwzględnieniem praw fizyki. 
        Zero bezwzględne to -273.15. Nic nie może być zimniejsze.
        """
        if value >= -273.15:
            self._celsius = value
        else:
            print("Error: Temperature cannot be below absolute zero (-273.15 °C)!")

    @property
    def fahrenheit(self):
        """
        Getter odczytujący temperaturę w Fahrenheitach.
        W obiekcie nie ma zmiennej _fahrenheit. Kiedy ktos prosi o odczyt,
        system natychmiastowo bierze _celsius i po prostu podmienia wzorem
        matematycznym na wymaganą jednostkę.
        """
        return (self.celsius * 1.8) + 32.0

    @fahrenheit.setter
    def fahrenheit(self, value):
        """
        Setter dla Fahrenheita. 
        Jeśli użytkownik podaje wartość w Fahrenheitach (np. t.fahrenheit = 100), 
        system przelicza ją na Celsjusze i zapisuje bezpośrednio do 'self.celsius'.
        Dzięki takiemu zapisowi (korzystamy z self.celsius, a nie self._celsius), 
        automatycznie używamy walidacji zera bezwzględnego wbudowanej w klasę!
        """
        # (F - 32) / 1.8 = C
        celsius_converted = (value - 32.0) / 1.8
        
        # Setter self.celsius sprawdzi czy wyliczona wartość jest dozwolona w fizyce
        self.celsius = celsius_converted

# Blok testowy
if __name__ == '__main__':
    print("--- Utworzenie Termometru (domyślnie 0°C) ---")
    t = Thermometer(0)
    print(f"Temperatura °C: {t.celsius}")
    print(f"Temperatura w °F będzie odczytana jako: {t.fahrenheit}")

    print("\n--- Ustawienie w °Fahrenheita (100°F) ---")
    t.fahrenheit = 100
    print(f"Odczyt w °F: {t.fahrenheit}")
    print(f"Odczyt w °C (zaaktualizowany): {t.celsius:.2f}")

    print("\n--- Próba przekroczenia zera bezwzględnego (Celsjusz) ---")
    t.celsius = -300
    
    print("\n--- Próba przekroczenia zera bezwzględnego (Fahrenheit) ---")
    # -500 F to znacznie poniżej zera bezwzględnego.
    # Wzór pod spodem przeliczy to na Celsjusze (-295.55 C)
    # i przekaże do `self.celsius`, który zablokuje błąd na poziomie -273.15
    t.fahrenheit = -500 

    print("\n--- Sprawdzenie stabilności stanu ---")
    print(f"Stan (Celsjusze): {t.celsius:.2f}")  # Została stara poprawna temperatura (37.78 C z ustawienia 100 F)
