diff --git a/build.gradle b/build.gradle index dcb6872..df07d71 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'org.jetbrains.kotlin.jvm' version '2.2.10' + id 'org.jetbrains.kotlin.jvm' version '2.0.21' } kotlin { diff --git a/src/main/kotlin/ru/otus/cars/Car.kt b/src/main/kotlin/ru/otus/cars/Car.kt deleted file mode 100644 index 559978c..0000000 --- a/src/main/kotlin/ru/otus/cars/Car.kt +++ /dev/null @@ -1,31 +0,0 @@ -package ru.otus.cars - -/** - * Машина целиком - */ -interface Car : CarInput { - /** - * Номерной знак - */ - val plates: Plates - - /** - * Цвет машины - */ - val color: String - - /** - * Следит за машиной - */ - val carOutput: CarOutput - - /** - * Получить оборудование - */ - fun getEquipment(): String - - /** - * Внутренний статический класс - номерой знак - */ - data class Plates(val number: String, val region: Int) -} \ No newline at end of file diff --git a/src/main/kotlin/ru/otus/cars/VazPlatform.kt b/src/main/kotlin/ru/otus/home_work5/VazPlatform.kt similarity index 79% rename from src/main/kotlin/ru/otus/cars/VazPlatform.kt rename to src/main/kotlin/ru/otus/home_work5/VazPlatform.kt index 079c2da..6c6f411 100644 --- a/src/main/kotlin/ru/otus/cars/VazPlatform.kt +++ b/src/main/kotlin/ru/otus/home_work5/VazPlatform.kt @@ -1,13 +1,20 @@ -package ru.otus.cars +package ru.otus.home_work5 + +import ru.otus.home_work5.carfacory.car.Car abstract class VazPlatform(override val color: String) : Car { // Положение руля. Доступно только внутри класса и наследникам protected var wheelAngle: Int = 0 // Положение руля // Реализация интерфейса CarInput - override fun wheelToRight(degrees: Int) { wheelAngle += degrees } + override fun wheelToRight(degrees: Int) { + wheelAngle += degrees + } + // Реализация интерфейса CarInput - override fun wheelToLeft(degrees: Int) { wheelAngle -= degrees } + override fun wheelToLeft(degrees: Int) { + wheelAngle -= degrees + } // Получить оборудование override fun getEquipment(): String = "Кузов, колеса, движок" diff --git a/src/main/kotlin/ru/otus/home_work5/carfacory/car/AbstractCarBuilder.kt b/src/main/kotlin/ru/otus/home_work5/carfacory/car/AbstractCarBuilder.kt new file mode 100644 index 0000000..af089ee --- /dev/null +++ b/src/main/kotlin/ru/otus/home_work5/carfacory/car/AbstractCarBuilder.kt @@ -0,0 +1,15 @@ +package ru.otus.home_work5.carfacory.car + +import ru.otus.home_work5.carfacory.tank_system.LpgMouth +import ru.otus.home_work5.carfacory.tank_system.PetrolMouth +import ru.otus.home_work5.carfacory.tank_system.TankMouth +import kotlin.random.Random.Default.nextInt + +sealed class AbstractCarBuilder : CarBuilder { + protected fun getRandomTankMount(): TankMouth { + return when (nextInt(2)) { + 0 -> PetrolMouth() + else -> LpgMouth() + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/ru/otus/home_work5/carfacory/car/Car.kt b/src/main/kotlin/ru/otus/home_work5/carfacory/car/Car.kt new file mode 100644 index 0000000..93faa83 --- /dev/null +++ b/src/main/kotlin/ru/otus/home_work5/carfacory/car/Car.kt @@ -0,0 +1,48 @@ +package ru.otus.home_work5.carfacory.car + +import ru.otus.home_work5.carfacory.tank_system.TankMouth + +/** + * Машина целиком + */ +interface Car : CarInput { + /** + * Номерной знак + */ + val plates: Plates + + /** + * Цвет машины + */ + val color: String + + /** + * Следит за машиной + */ + val carOutput: CarOutput + + /** + * Горловина авто для залива топлива + */ + val tankMouth: TankMouth + + /** + * Получить оборудование + */ + fun getEquipment(): String + + /** + * Внутренний статический класс - номерной знак + */ + data class Plates( + /** + * Регистрационный номер + */ + val number: String, + + /** + * Код региона регистрации + */ + val region: Int + ) +} \ No newline at end of file diff --git a/src/main/kotlin/ru/otus/cars/CarBuilder.kt b/src/main/kotlin/ru/otus/home_work5/carfacory/car/CarBuilder.kt similarity index 78% rename from src/main/kotlin/ru/otus/cars/CarBuilder.kt rename to src/main/kotlin/ru/otus/home_work5/carfacory/car/CarBuilder.kt index 224f46d..f694695 100644 --- a/src/main/kotlin/ru/otus/cars/CarBuilder.kt +++ b/src/main/kotlin/ru/otus/home_work5/carfacory/car/CarBuilder.kt @@ -1,4 +1,4 @@ -package ru.otus.cars +package ru.otus.home_work5.carfacory.car /** * Сборщик машины @@ -8,4 +8,5 @@ sealed interface CarBuilder { * Собери машину */ fun build(plates: Car.Plates): Car -} \ No newline at end of file +} + diff --git a/src/main/kotlin/ru/otus/cars/CarFactory.kt b/src/main/kotlin/ru/otus/home_work5/carfacory/car/CarFactory.kt similarity index 96% rename from src/main/kotlin/ru/otus/cars/CarFactory.kt rename to src/main/kotlin/ru/otus/home_work5/carfacory/car/CarFactory.kt index 3b8f03e..7375a21 100644 --- a/src/main/kotlin/ru/otus/cars/CarFactory.kt +++ b/src/main/kotlin/ru/otus/home_work5/carfacory/car/CarFactory.kt @@ -1,4 +1,4 @@ -package ru.otus.cars +package ru.otus.home_work5.carfacory.car /** * Автозавод diff --git a/src/main/kotlin/ru/otus/cars/CarInput.kt b/src/main/kotlin/ru/otus/home_work5/carfacory/car/CarInput.kt similarity index 87% rename from src/main/kotlin/ru/otus/cars/CarInput.kt rename to src/main/kotlin/ru/otus/home_work5/carfacory/car/CarInput.kt index fc2478e..9f9fd28 100644 --- a/src/main/kotlin/ru/otus/cars/CarInput.kt +++ b/src/main/kotlin/ru/otus/home_work5/carfacory/car/CarInput.kt @@ -1,4 +1,4 @@ -package ru.otus.cars +package ru.otus.home_work5.carfacory.car /** * Рулит машиной diff --git a/src/main/kotlin/ru/otus/cars/CarOutput.kt b/src/main/kotlin/ru/otus/home_work5/carfacory/car/CarOutput.kt similarity index 56% rename from src/main/kotlin/ru/otus/cars/CarOutput.kt rename to src/main/kotlin/ru/otus/home_work5/carfacory/car/CarOutput.kt index 875339f..a6d4d64 100644 --- a/src/main/kotlin/ru/otus/cars/CarOutput.kt +++ b/src/main/kotlin/ru/otus/home_work5/carfacory/car/CarOutput.kt @@ -1,4 +1,4 @@ -package ru.otus.cars +package ru.otus.home_work5.carfacory.car /** * Следит за машиной @@ -8,4 +8,9 @@ interface CarOutput { * Скажи текущую скорость */ fun getCurrentSpeed(): Int + + /** + * Остаток топлива + */ + fun getFuelReserve(): Int } \ No newline at end of file diff --git a/src/main/kotlin/ru/otus/cars/Taz.kt b/src/main/kotlin/ru/otus/home_work5/carfacory/car/Taz.kt similarity index 78% rename from src/main/kotlin/ru/otus/cars/Taz.kt rename to src/main/kotlin/ru/otus/home_work5/carfacory/car/Taz.kt index 49df937..f06c4d1 100644 --- a/src/main/kotlin/ru/otus/cars/Taz.kt +++ b/src/main/kotlin/ru/otus/home_work5/carfacory/car/Taz.kt @@ -1,6 +1,8 @@ -package ru.otus.cars +package ru.otus.home_work5.carfacory.car -object Taz: Car { +import ru.otus.home_work5.carfacory.tank_system.TankMouth + +object Taz : Car { /** * Номерной знак */ @@ -18,6 +20,9 @@ object Taz: Car { override val carOutput: CarOutput get() = throw NotImplementedError("Приборов нет") + override val tankMouth: TankMouth + get() = throw NotImplementedError("Взрыв топливной системы!") + /** * Получить оборудование */ diff --git a/src/main/kotlin/ru/otus/cars/Vaz2107.kt b/src/main/kotlin/ru/otus/home_work5/carfacory/car/Vaz2107.kt similarity index 82% rename from src/main/kotlin/ru/otus/cars/Vaz2107.kt rename to src/main/kotlin/ru/otus/home_work5/carfacory/car/Vaz2107.kt index be857d2..8c7bca4 100644 --- a/src/main/kotlin/ru/otus/cars/Vaz2107.kt +++ b/src/main/kotlin/ru/otus/home_work5/carfacory/car/Vaz2107.kt @@ -1,5 +1,8 @@ -package ru.otus.cars +package ru.otus.home_work5.carfacory.car +import ru.otus.home_work5.VazEngine +import ru.otus.home_work5.VazPlatform +import ru.otus.home_work5.carfacory.tank_system.TankMouth import kotlin.random.Random /** @@ -9,7 +12,7 @@ class Vaz2107 private constructor(color: String) : VazPlatform(color) { /** * Сам-себе-сборщик ВАЗ 2107. */ - companion object : CarBuilder { + companion object : AbstractCarBuilder() { private fun getRandomEngine(): VazEngine { return when (Random.nextInt(0, 2)) { 0 -> VazEngine.LADA_2107(1300) @@ -20,6 +23,7 @@ class Vaz2107 private constructor(color: String) : VazPlatform(color) { override fun build(plates: Car.Plates): Vaz2107 = Vaz2107("Зеленый").apply { this.engine = getRandomEngine() this.plates = plates + this.tankMouth = getRandomTankMount() } /** @@ -40,6 +44,8 @@ class Vaz2107 private constructor(color: String) : VazPlatform(color) { override lateinit var engine: VazEngine private set + override lateinit var tankMouth: TankMouth + private set /** * Семерка едет так */ @@ -74,5 +80,9 @@ class Vaz2107 private constructor(color: String) : VazPlatform(color) { override fun getCurrentSpeed(): Int { return this@Vaz2107.currentSpeed } + + override fun getFuelReserve(): Int { + return this@Vaz2107.tankMouth.tankFreeSpace() + } } } \ No newline at end of file diff --git a/src/main/kotlin/ru/otus/cars/Vaz2108.kt b/src/main/kotlin/ru/otus/home_work5/carfacory/car/Vaz2108.kt similarity index 83% rename from src/main/kotlin/ru/otus/cars/Vaz2108.kt rename to src/main/kotlin/ru/otus/home_work5/carfacory/car/Vaz2108.kt index 27b83b8..501faa8 100644 --- a/src/main/kotlin/ru/otus/cars/Vaz2108.kt +++ b/src/main/kotlin/ru/otus/home_work5/carfacory/car/Vaz2108.kt @@ -1,5 +1,8 @@ -package ru.otus.cars +package ru.otus.home_work5.carfacory.car +import ru.otus.home_work5.VazEngine +import ru.otus.home_work5.VazPlatform +import ru.otus.home_work5.carfacory.tank_system.TankMouth import kotlin.random.Random /** @@ -9,7 +12,7 @@ class Vaz2108 private constructor(color: String) : VazPlatform(color) { /** * Сам-себе-сборщик ВАЗ 2108. */ - companion object : CarBuilder { + companion object : AbstractCarBuilder() { private fun getRandomEngine(): VazEngine { return when (Random.nextInt(0, 3)) { 0 -> VazEngine.SAMARA_2108(1100) @@ -21,6 +24,7 @@ class Vaz2108 private constructor(color: String) : VazPlatform(color) { override fun build(plates: Car.Plates): Vaz2108 = Vaz2108("Красный").apply { this.engine = getRandomEngine() this.plates = plates + this.tankMouth = getRandomTankMount() } fun alignWheels(vaz2108: Vaz2108) { @@ -37,6 +41,8 @@ class Vaz2108 private constructor(color: String) : VazPlatform(color) { // Переопределяем свойство родителя override lateinit var engine: VazEngine private set + override lateinit var tankMouth: TankMouth + private set /** * Восьмерка едет так @@ -78,5 +84,9 @@ class Vaz2108 private constructor(color: String) : VazPlatform(color) { override fun getCurrentSpeed(): Int { return this@Vaz2108.currentSpeed } + + override fun getFuelReserve(): Int { + return this@Vaz2108.tankMouth.tankFreeSpace() + } } } \ No newline at end of file diff --git a/src/main/kotlin/ru/otus/home_work5/carfacory/tank_system/Tank.kt b/src/main/kotlin/ru/otus/home_work5/carfacory/tank_system/Tank.kt new file mode 100644 index 0000000..14359ca --- /dev/null +++ b/src/main/kotlin/ru/otus/home_work5/carfacory/tank_system/Tank.kt @@ -0,0 +1,33 @@ +package ru.otus.home_work5.carfacory.tank_system + +/** + * Интерфейс Tank представляет хранилище топлива с возможностью приема и отслеживания текущего уровня топлива. + * + * @author Yuriy Tilman + * @author GigaChat + */ +interface Tank { + /** + * Горловина резервуара, через которую производится прием топлива. + */ + val mouth: TankMouth + + /** + * Возвращает текущее количество топлива в резервуаре. + * + * @return количество топлива в литрах + */ + fun getContents(): Int + + /** + * @return вместимость бака + * */ + fun getCapacity(): Int + + /** + * Производит прием указанного количества топлива в резервуар. + * + * @param liters количество топлива, которое нужно добавить в резервуар + */ + fun receiveFuel(liters: Int) +} \ No newline at end of file diff --git a/src/main/kotlin/ru/otus/home_work5/carfacory/tank_system/TankMouth.kt b/src/main/kotlin/ru/otus/home_work5/carfacory/tank_system/TankMouth.kt new file mode 100644 index 0000000..d0651db --- /dev/null +++ b/src/main/kotlin/ru/otus/home_work5/carfacory/tank_system/TankMouth.kt @@ -0,0 +1,107 @@ +package ru.otus.home_work5.carfacory.tank_system + + +/** + * Общая абстракция горловины автомобиля, которая + * используемую для наполнения топливом разных типов. + * + * @author Yuriy Tilman + * @author GigaChat + */ +sealed class TankMouth { + protected abstract val tank: Tank + + /** + * Открывает горловину автомобиля для возможности заправки. + */ + abstract fun open() + + /** + * Закрывает горловину автомобиля после завершения заправки. + */ + abstract fun close() + + fun tankFreeSpace() = tank.getCapacity() - tank.getContents() + fun receiveFuel(liters: Int) = tank.receiveFuel(liters) +} + +/** + * Реализация бензинового типа горловины автомобиля. + * + * @author Yuriy Tilman + * @author GigaChat + */ +class PetrolMouth : TankMouth() { + override fun open() = println("Горловина бензобака открыта") + + override fun close() = println("Горловина бензобака закрыта") + + override val tank: Tank = object : Tank { + private val capacity: Int = 50 + var currentVolume: Int = 0 + override val mouth: TankMouth = this@PetrolMouth + + override fun getContents(): Int = currentVolume + override fun getCapacity(): Int = capacity + + override fun receiveFuel(liters: Int) { + if (liters > 0) { + currentVolume += liters + println("$liters литров бензина успешно залиты в бак. Текущий объём: $currentVolume л.") + } else { + println("Ошибка: невозможно залить отрицательное количество топлива!") + } + } + } + + /** + * Производит подачу бензина в автомобиль. + * + * @param liters Количество литров бензина, которое должно быть заправлено. + */ + fun fuelPetrol(liters: Int) { + tank.receiveFuel(liters) + println("Заправлен бензин: $liters литров.") + } + +} + +/** + * Реализация газовой горловины автомобиля для сжиженного газа (LPG). + * + * @author Yuriy Tilman + * @author GigaChat + */ +class LpgMouth : TankMouth() { + override fun open() = println("Газовая горловина открыта") + + override fun close() = println("Газовая горловина закрыта") + override val tank = object : Tank { + var currentVolume: Int = 0 + private val capacity: Int = 100 + override val mouth: TankMouth = this@LpgMouth + + override fun getContents(): Int = currentVolume + override fun getCapacity() = capacity + + override fun receiveFuel(liters: Int) { + if (liters > 0) { + currentVolume += liters + println("$liters литров газа успешно залиты в бак. Текущий объём: $currentVolume л.") + } else { + println("Ошибка: невозможно залить отрицательное количество топлива!") + } + } + } + + /** + * Осуществляет подачу сжиженного газа в автомобиль. + * + * @param liters Объем газа в литрах, который будет заполнен. + */ + fun fuelLpg(liters: Int) { + tank.receiveFuel(liters) + println("Заправлен газ: $liters литров.") + } +} + diff --git a/src/main/kotlin/ru/otus/home_work5/gas_station/GasStation.kt b/src/main/kotlin/ru/otus/home_work5/gas_station/GasStation.kt new file mode 100644 index 0000000..467d009 --- /dev/null +++ b/src/main/kotlin/ru/otus/home_work5/gas_station/GasStation.kt @@ -0,0 +1,39 @@ +package ru.otus.home_work5.gas_station + +import ru.otus.home_work5.carfacory.car.Car +import ru.otus.home_work5.carfacory.tank_system.TankMouth + + +/** + * @interface описывает заправку топливом + */ +interface GasStation { + val supportedTankMouth: Set + + /** + * Заправка топливом + * @note отступление от задания. Машина передается не при создании объекта, а при заправке. + * Так как при создании заправки определяется типы топлива, а не конкретные машины. + * @return количество заправленного топлива + * */ + fun refueling(car: Car): Int +} + +class GasStationImpl( + override val supportedTankMouth: Set +) : GasStation { + override fun refueling(car: Car): Int { + runCatching { + car.tankMouth.open() + val freeSpace = car.tankMouth.tankFreeSpace() // умная заправка, узнает сколько топлива в баке без водителя) + car.tankMouth.receiveFuel(freeSpace) + car.tankMouth.close() + return freeSpace + } + .getOrElse { + System.err.println("Произошел взрыв. Возгорание ликвидировано.") + return 0 + } + + } +} diff --git a/src/main/kotlin/ru/otus/cars/main.kt b/src/main/kotlin/ru/otus/home_work5/main.kt similarity index 75% rename from src/main/kotlin/ru/otus/cars/main.kt rename to src/main/kotlin/ru/otus/home_work5/main.kt index 978d0ef..c069995 100644 --- a/src/main/kotlin/ru/otus/cars/main.kt +++ b/src/main/kotlin/ru/otus/home_work5/main.kt @@ -1,4 +1,15 @@ -package ru.otus.cars +package ru.otus.home_work5 + +import ru.otus.home_work5.carfacory.car.Car +import ru.otus.home_work5.carfacory.car.CarBuilder +import ru.otus.home_work5.carfacory.car.CarFactory +import ru.otus.home_work5.carfacory.car.Taz +import ru.otus.home_work5.carfacory.car.Togliatti +import ru.otus.home_work5.carfacory.car.Vaz2107 +import ru.otus.home_work5.carfacory.car.Vaz2108 +import ru.otus.home_work5.carfacory.tank_system.LpgMouth +import ru.otus.home_work5.carfacory.tank_system.PetrolMouth +import ru.otus.home_work5.gas_station.GasStationImpl fun main() { println("\n===> drive cars...") @@ -16,6 +27,20 @@ fun main() { techChecks() println("\n===> Taz...") println(Taz.color) + + fuelCars() +} + +fun fuelCars() { + val vaz2107 = Togliatti.buildCar(Vaz2107, Car.Plates("123", 77)) + val vaz2108 = Togliatti.buildCar(Vaz2108, Car.Plates("321", 78)) + + val gazProm = GasStationImpl(setOf(PetrolMouth(), LpgMouth())) + + gazProm.refueling(vaz2107) + gazProm.refueling(vaz2108) + gazProm.refueling(Taz) + } fun driveCars() { @@ -34,7 +59,7 @@ fun innerNestedCheck() { val output = vaz.VazOutput() // Создаем новый объект ИЗ ЭКЗЕМПЛЯРА МАШИНЫ println("Скорость до проверки: ${output.getCurrentSpeed()}") // Выводит 0 - Vaz2107.test(vaz) // Газуем... + Vaz2107.Companion.test(vaz) // Газуем... println("Скорость после проверки: ${output.getCurrentSpeed()}") // Выводит случайную скорость } @@ -48,7 +73,7 @@ fun garageMake() { } } - val vaz = garage.buildCar(Vaz2107, Car.Plates("500", 50)) + val vaz = garage.buildCar(Vaz2107.Companion, Car.Plates("500", 50)) println(vaz.toString()) } diff --git a/src/main/resources/Car.puml b/src/main/resources/Car.puml new file mode 100644 index 0000000..4a361d6 --- /dev/null +++ b/src/main/resources/Car.puml @@ -0,0 +1,46 @@ +@startuml +'https://plantuml.com/class-diagram +hide empty members + +interface CarInput { + +wheelToRight(degrees: Int) + +wheelToLeft(degrees: Int) +} + +interface CarOutput { + +getCurrentSpeed(): Int + +getFuelContents(): Int +} + +abstract class TankMouth { + +open() + +close() +} +note right of TankMouth + Горловина бензобака +end note + +class PetrolMouth { + +fuelPetrol(liters: Int) +} +PetrolMouth -up-|> TankMouth + +class LpgMouth { + +fuelLpg(liters: Int) +} +LpgMouth -up-|> TankMouth + +interface Car { + +plates: CarPlates + +carOutput: CarOutput + +tankMouth: TankMouth +} +CarInput <|-down- Car +CarOutput -right-* Car +TankMouth -up-* Car + +class CarPlates +CarPlates -left-* Car + + +@enduml \ No newline at end of file diff --git a/src/main/resources/Tank.puml b/src/main/resources/Tank.puml new file mode 100644 index 0000000..2774a4e --- /dev/null +++ b/src/main/resources/Tank.puml @@ -0,0 +1,17 @@ +@startuml +'https://plantuml.com/class-diagram + +hide empty members + +abstract class TankMouth +interface CarOutput + +interface Tank { + +mouth: TankMouth + +getContents(): Int + +receiveFuel(liters: Int) +} +Tank -> CarOutput: запас бензина > +TankMouth -> Tank: пополняет > + +@enduml \ No newline at end of file