Хорошо, по твоему коду отвечаю кратко, без воды.
Задание 1 — SRP
Trip хранит только данные и считает расход. TripPrinter отвечает за вывод, TripSaver — за сохранение. Каждый класс имеет одну причину для изменения. Никакой код в Trip не занимается печатью или файлами — это SRP.
Задание 2 — OCP
Чтобы добавить новый способ оплаты (например, CryptoPayment), создаёшь новый класс, наследующий PaymentMethod, и реализуешь pay(). Классы CardPayment, CashPayment, QRPayment не трогаешь. Код открыт для расширения, закрыт для изменений — это OCP.
Задание 3 — LSP
BrokenCar при вызове move() кидает исключение вместо возврата строки. Если подставить BrokenCar вместо Vehicle, программа падает. По LSP потомок должен заменять родителя без изменения корректности работы. Здесь замена невозможна.
Задание 4 — ISP
В коде интерфейсы разделены: EngineRepairer и WiringRepairer. Mechanic реализует только repair_engine(), Electrician — только repair_wiring(). Никто не вынужден реализовывать ненужные методы. Это ISP.
Задание 5 — DIP
Dashboard получает любой датчик через конструктор (абстракция SpeedProvider). Внутри нет SpeedSensor(), нет жёсткой привязки. Меняешь датчик — создаёшь другой объект и передаёшь. DIP позволяет легко заменять источник данных.