Загрузка данных


from abc import ABC, abstractmethod

# ==========================================
# Задание 1: SRP (Single Responsibility)
# ==========================================
class Trip:
    def __init__(self, distance: float, fuel: float):
        self.distance = distance  # Дистанция в км [cite: 6]
        self.fuel = fuel          # Топливо в литрах [cite: 6]

    def calculate_consumption(self) -> float:
        """Вычисляет средний расход топлива [cite: 8]"""
        return (self.fuel / self.distance) * 100 if self.distance else 0.0

class TripPrinter:
    def print_trip(self, trip: Trip):
        """Выводит информацию на экран [cite: 13]"""
        print(f"[SRP] Дистанция: {trip.distance} км, Расход: {trip.calculate_consumption():.2f} л/100км")

class TripSaver:
    def save_trip(self, trip: Trip):
        """Сохраняет данные в файл [cite: 14]"""
        print(f"[SRP] Данные поездки ({trip.distance} км) успешно сохранены.")


# ==========================================
# Задание 2: OCP (Open/Closed)
# ==========================================
class PaymentMethod(ABC):
    @abstractmethod
    def pay(self):  # Базовый метод оплаты [cite: 23]
        pass

class CardPayment(PaymentMethod):
    def pay(self):  # Оплата картой [cite: 26, 29]
        print("[OCP] Оплата успешно проведена картой.")

class CashPayment(PaymentMethod):
    def pay(self):  # Оплата наличными [cite: 27, 29]
        print("[OCP] Принята оплата наличными через купюроприемник.")

class QRPayment(PaymentMethod):
    def pay(self):  # Оплата по QR [cite: 28, 29]
        print("[OCP] Оплата получена через QR-код.")


# ==========================================
# Задание 3: LSP (Liskov Substitution)
# ==========================================
class Vehicle:
    def move(self) -> str:  # Базовый метод движения [cite: 40]
        return "Транспортное средство движется"

class Car(Vehicle):
    def move(self) -> str:  # Переопределение для машины [cite: 44]
        return "Машина едет по дороге"

class Bicycle(Vehicle):
    def move(self) -> str:  # Переопределение для велосипеда [cite: 44]
        return "Велосипед едет по дорожке"

class BrokenCar(Vehicle):
    def move(self):
        # Нарушение LSP — вместо движения выбрасывает ошибку [cite: 47, 49]
        raise RuntimeError("Критическая ошибка: машина сломана и не может ехать!")


# ==========================================
# Задание 4: ISP (Interface Segregation)
# ==========================================
class EngineRepairer(ABC):
    @abstractmethod
    def repair_engine(self):  # Выделенный интерфейс для моториста [cite: 58]
        pass

class WiringRepairer(ABC):
    @abstractmethod
    def repair_wiring(self):  # Выделенный интерфейс для электрика [cite: 58]
        pass

class Mechanic(EngineRepairer):
    def repair_engine(self):  # Механик чинит только мотор [cite: 60, 63]
        print("[ISP] Механик успешно отремонтировал двигатель.")

class Electrician(WiringRepairer):
    def repair_wiring(self):  # Электрик чинит только проводку [cite: 61, 63]
        print("[ISP] Электрик успешно починил проводку.")


# ==========================================
# Задание 5: DIP (Dependency Inversion)
# ==========================================
class SpeedProvider(ABC):
    @abstractmethod
    def get_speed(self) -> float:  # Абстракция для получения скорости [cite: 76]
        pass

class SpeedSensor(SpeedProvider):
    def get_speed(self) -> float:  # Датчик колеса [cite: 73, 76]
        return 60.0

class GPSSensor(SpeedProvider):
    def get_speed(self) -> float:  # GPS-датчик [cite: 74, 76]
        return 58.5

class Dashboard:
    def __init__(self, sensor: SpeedProvider):
        # Зависимость передается через интерфейс, а не создается внутри [cite: 77, 79]
        self.sensor = sensor

    def show_speed(self):  # Вывод скорости на экран [cite: 71]
        print(f"[DIP] Скорость на приборной панели: {self.sensor.get_speed()} км/ч")


# ==========================================
# Общая функция main для демонстрации работы
# ==========================================
def main():
    print("--- Проверка Задания 1 (SRP) ---")
    trip = Trip(250, 20)
    printer = TripPrinter()
    saver = TripSaver()
    printer.print_trip(trip)
    saver.save_trip(trip)

    print("\n--- Проверка Задания 2 (OCP) ---")
    parking_payments = [CardPayment(), CashPayment(), QRPayment()]
    for payment in parking_payments:
        payment.pay()

    print("\n--- Проверка Задания 3 (LSP) ---")
    vehicles = [Car(), Bicycle()]
    for v in vehicles:
        print(f"[LSP] {v.move()}")
    
    # Показываем, как ломается программа из-за BrokenCar
    broken_car = BrokenCar()
    try:
        broken_car.move()
    except RuntimeError as e:
        print(f"[LSP Нарушение] Логика упала: {e}")

    print("\n--- Проверка Задания 4 (ISP) ---")
    mechanic = Mechanic()
    electrician = Electrician()
    mechanic.repair_engine()
    electrician.repair_wiring()

    print("\n--- Проверка Задания 5 (DIP) ---")
    dashboard_with_wheel_sensor = Dashboard(SpeedSensor())
    dashboard_with_gps_sensor = Dashboard(GPSSensor())
    
    dashboard_with_wheel_sensor.show_speed()
    dashboard_with_gps_sensor.show_speed()

if __name__ == "__main__":
    main()