diff --git a/src/main/kotlin/ru/otus/cars/Car.kt b/src/main/kotlin/ru/otus/cars/Car.kt index 559978c..3da1b07 100644 --- a/src/main/kotlin/ru/otus/cars/Car.kt +++ b/src/main/kotlin/ru/otus/cars/Car.kt @@ -19,6 +19,11 @@ interface Car : CarInput { */ val carOutput: CarOutput + /** + * Топливная горловина + */ + val tankMouth: TankMouth + /** * Получить оборудование */ diff --git a/src/main/kotlin/ru/otus/cars/CarFactory.kt b/src/main/kotlin/ru/otus/cars/CarFactory.kt index 3b8f03e..84233ae 100644 --- a/src/main/kotlin/ru/otus/cars/CarFactory.kt +++ b/src/main/kotlin/ru/otus/cars/CarFactory.kt @@ -18,7 +18,7 @@ object Togliatti : CarFactory { println("Запил ${Vaz2107.MODEL} в Тольятти...") val vaz = Vaz2107.build(plates) println("Проверяем тачку...") - Vaz2107.test(vaz) + Vaz2107.test(vaz as Vaz2107) vaz.drdrdrdrdr() return vaz } @@ -27,7 +27,7 @@ object Togliatti : CarFactory { println("Запил ${Vaz2108.MODEL} в Тольятти...") val vaz = Vaz2108.build(plates) println("Сход-развал...") - Vaz2108.alignWheels(vaz) + Vaz2108.alignWheels(vaz as Vaz2108) vaz.zhzhzhzh() return vaz } diff --git a/src/main/kotlin/ru/otus/cars/CarOutput.kt b/src/main/kotlin/ru/otus/cars/CarOutput.kt index 875339f..000e217 100644 --- a/src/main/kotlin/ru/otus/cars/CarOutput.kt +++ b/src/main/kotlin/ru/otus/cars/CarOutput.kt @@ -8,4 +8,5 @@ interface CarOutput { * Скажи текущую скорость */ fun getCurrentSpeed(): Int + fun getTankContents(): Int } \ No newline at end of file diff --git a/src/main/kotlin/ru/otus/cars/FuelStation.kt b/src/main/kotlin/ru/otus/cars/FuelStation.kt new file mode 100644 index 0000000..ba16507 --- /dev/null +++ b/src/main/kotlin/ru/otus/cars/FuelStation.kt @@ -0,0 +1,30 @@ +package ru.otus.cars + +interface FuelStationInterface { + fun refuel(tankMouth: TankMouth, volume: Int): RefuelResult +} + +enum class RefuelResult { + DONE, + ERROR +} + +class FuelStation : FuelStationInterface { + override fun refuel(tankMouth: TankMouth, volume: Int): RefuelResult { + try { + tankMouth.open() + when (tankMouth) { + is TankMouth.LpgTankMouth -> tankMouth.fuelLpg(volume) + is TankMouth.PetrolTankMouth -> tankMouth.fuelPetrol(volume) + } + tankMouth.close() + return RefuelResult.DONE + } catch (e: TankMouthException) { + println(e.message) + return RefuelResult.ERROR + } catch (e: Throwable) { + println("Что-то не так. Прекратили все работы.") + return RefuelResult.ERROR + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/ru/otus/cars/Tank.kt b/src/main/kotlin/ru/otus/cars/Tank.kt new file mode 100644 index 0000000..debdbdb --- /dev/null +++ b/src/main/kotlin/ru/otus/cars/Tank.kt @@ -0,0 +1,44 @@ +package ru.otus.cars + +open class Tank(val initialVolume: Int) : TankInterface { + + private var volume: Int = initialVolume + get() { + if (field <= 0) throw Exception("Tank volume should be more than zero") + return field + } + set(value) { + if (value <= 0) throw Exception("Tank volume should be more than zero") + field = value + } + + private var fuelBalance: Int = 0 + + override fun getContents(): Int = fuelBalance + + override fun receiveFuel(liters: Int) { + when { + liters < 0 -> throw TankException("Liters can't be negative") + liters + fuelBalance > volume -> { + fuelBalance = volume + throw TankException("Tank full") + } + + liters + fuelBalance <= volume -> fuelBalance += liters + } + } + + override fun toString(): String { + return "Tank(volume=$volume, fuelBalance=$fuelBalance)" + } + + +} + + +interface TankInterface { + fun getContents(): Int + fun receiveFuel(liters: Int) +} + +class TankException(message: String) : Exception(message) \ No newline at end of file diff --git a/src/main/kotlin/ru/otus/cars/TankMouth.kt b/src/main/kotlin/ru/otus/cars/TankMouth.kt new file mode 100644 index 0000000..e346e9c --- /dev/null +++ b/src/main/kotlin/ru/otus/cars/TankMouth.kt @@ -0,0 +1,68 @@ +package ru.otus.cars + + +interface TankMouthInterface { + fun open() + fun close() +} + +sealed class TankMouth : TankMouthInterface { + protected lateinit var tank: TankInterface + + protected fun buildWithTank(tank: TankInterface): TankMouth { + this.tank = tank + return this + } + + protected fun receiveFuel(liters: Int) { + try { + tank.receiveFuel(liters) + } catch (e: TankException) { + throw TankMouthException(e.message ?: "Tank mouth error") + } + } + + fun getContents() : Int = tank.getContents() + + enum class TankMouthState { OPEN, CLOSED } + + private var state: TankMouthState = TankMouthState.CLOSED + override fun open() { + state = TankMouthState.OPEN + } + + override fun close() { + state = TankMouthState.CLOSED + } + + class PetrolTankMouth private constructor(): TankMouth() { + companion object { + fun build(tank: TankInterface) : TankMouth { + return PetrolTankMouth().buildWithTank(tank) + } + } + + fun fuelPetrol(liters: Int) = super.receiveFuel(liters) + + override fun toString(): String { + return "PetrolTankMouth($tank)" + } + } + + class LpgTankMouth private constructor(): TankMouth() { + companion object { + fun build(tank: TankInterface) : TankMouth { + return LpgTankMouth().buildWithTank(tank) + } + } + fun fuelLpg(liters: Int) = super.receiveFuel(liters) + + override fun toString(): String { + return "LpgTankMouth($tank)" + } + } +} + + + +class TankMouthException(message: String) : Exception(message) \ No newline at end of file diff --git a/src/main/kotlin/ru/otus/cars/Taz.kt b/src/main/kotlin/ru/otus/cars/Taz.kt index 49df937..f04f0e6 100644 --- a/src/main/kotlin/ru/otus/cars/Taz.kt +++ b/src/main/kotlin/ru/otus/cars/Taz.kt @@ -18,10 +18,19 @@ object Taz: Car { override val carOutput: CarOutput get() = throw NotImplementedError("Приборов нет") + + class TazTank: Tank(initialVolume = 20) { + override fun receiveFuel(liters: Int) { + throw NotImplementedError("Bang!!") + } + } + /** * Получить оборудование */ override fun getEquipment(): String = "Крыса" + override val tankMouth: TankMouth + get() = TankMouth.PetrolTankMouth.build(TazTank()) /** * Руль вправо на [degrees] градусов diff --git a/src/main/kotlin/ru/otus/cars/Vaz2107.kt b/src/main/kotlin/ru/otus/cars/Vaz2107.kt index be857d2..38358ff 100644 --- a/src/main/kotlin/ru/otus/cars/Vaz2107.kt +++ b/src/main/kotlin/ru/otus/cars/Vaz2107.kt @@ -17,9 +17,10 @@ class Vaz2107 private constructor(color: String) : VazPlatform(color) { } } - override fun build(plates: Car.Plates): Vaz2107 = Vaz2107("Зеленый").apply { + override fun build(plates: Car.Plates): Car = Vaz2107("Зеленый").apply { this.engine = getRandomEngine() this.plates = plates + this.tankMouth = TankMouth.LpgTankMouth.build(Tank(50)) } /** @@ -40,6 +41,9 @@ class Vaz2107 private constructor(color: String) : VazPlatform(color) { override lateinit var engine: VazEngine private set + override lateinit var tankMouth: TankMouth + private set + /** * Семерка едет так */ @@ -59,7 +63,7 @@ class Vaz2107 private constructor(color: String) : VazPlatform(color) { // Выводим состояние машины override fun toString(): String { - return "Vaz2107(plates=$plates, wheelAngle=$wheelAngle, currentSpeed=$currentSpeed)" + return "Vaz2107(plates=$plates, wheelAngle=$wheelAngle, currentSpeed=$currentSpeed, tankMouth=$tankMouth)" } /** @@ -74,5 +78,9 @@ class Vaz2107 private constructor(color: String) : VazPlatform(color) { override fun getCurrentSpeed(): Int { return this@Vaz2107.currentSpeed } + + override fun getTankContents(): Int { + return this@Vaz2107.tankMouth.getContents() + } } } \ No newline at end of file diff --git a/src/main/kotlin/ru/otus/cars/Vaz2108.kt b/src/main/kotlin/ru/otus/cars/Vaz2108.kt index 27b83b8..2fb91ba 100644 --- a/src/main/kotlin/ru/otus/cars/Vaz2108.kt +++ b/src/main/kotlin/ru/otus/cars/Vaz2108.kt @@ -18,9 +18,10 @@ class Vaz2108 private constructor(color: String) : VazPlatform(color) { } } - override fun build(plates: Car.Plates): Vaz2108 = Vaz2108("Красный").apply { + override fun build(plates: Car.Plates): Car = Vaz2108("Красный").apply { this.engine = getRandomEngine() this.plates = plates + this.tankMouth = TankMouth.PetrolTankMouth.build(Tank(65)) } fun alignWheels(vaz2108: Vaz2108) { @@ -38,6 +39,9 @@ class Vaz2108 private constructor(color: String) : VazPlatform(color) { override lateinit var engine: VazEngine private set + override lateinit var tankMouth: TankMouth + private set + /** * Восьмерка едет так */ @@ -63,7 +67,7 @@ class Vaz2108 private constructor(color: String) : VazPlatform(color) { // Выводим состояние машины override fun toString(): String { - return "Vaz2108(plates=$plates, wheelAngle=$wheelAngle, currentSpeed=$currentSpeed)" + return "Vaz2108(plates=$plates, wheelAngle=$wheelAngle, currentSpeed=$currentSpeed, tankMouth=$tankMouth)" } /** @@ -78,5 +82,9 @@ class Vaz2108 private constructor(color: String) : VazPlatform(color) { override fun getCurrentSpeed(): Int { return this@Vaz2108.currentSpeed } + + override fun getTankContents(): Int { + return this@Vaz2108.tankMouth.getContents() + } } } \ No newline at end of file diff --git a/src/main/kotlin/ru/otus/cars/main.kt b/src/main/kotlin/ru/otus/cars/main.kt index 978d0ef..0d477bc 100644 --- a/src/main/kotlin/ru/otus/cars/main.kt +++ b/src/main/kotlin/ru/otus/cars/main.kt @@ -16,6 +16,7 @@ fun main() { techChecks() println("\n===> Taz...") println(Taz.color) + refuelCars() } fun driveCars() { @@ -31,7 +32,7 @@ fun driveCars() { fun innerNestedCheck() { val vaz = Vaz2107.build(Car.Plates("123", 77)) - val output = vaz.VazOutput() // Создаем новый объект ИЗ ЭКЗЕМПЛЯРА МАШИНЫ + val output = (vaz as Vaz2107).VazOutput() // Создаем новый объект ИЗ ЭКЗЕМПЛЯРА МАШИНЫ println("Скорость до проверки: ${output.getCurrentSpeed()}") // Выводит 0 Vaz2107.test(vaz) // Газуем... @@ -78,8 +79,8 @@ fun techChecks() { val vaz1 = Vaz2107.build(Car.Plates("123", 77)) val vaz2 = Vaz2108.build(Car.Plates("321", 78)) - repairEngine(vaz1) - repairEngine(vaz2) + repairEngine(vaz1 as VazPlatform) + repairEngine(vaz2 as VazPlatform) } fun repairEngine(car: VazPlatform) { @@ -90,4 +91,26 @@ fun repairEngine(car: VazPlatform) { is VazEngine.LADA_2107 -> println("Чистка карбюратора у двигателя объемом ${car.engine.volume} куб.см у машины $car") is VazEngine.SAMARA_2108 -> println("Угол зажигания у двигателя объемом ${car.engine.volume} куб.см у машины $car") } +} + +fun refuelCars() { + val cars: List = listOf( + Vaz2107.build(Car.Plates("123", 77)), + Vaz2108.build(Car.Plates("321", 78)), + Taz + ) + + val station = FuelStation() + + for (car in cars) { + println("Собираемся заправить $car, Кол-во топлива: ${car.tankMouth.getContents()}") + val refuelResult = station.refuel(car.tankMouth, 10) + println("Результат заправки $refuelResult, Кол-во топлива: ${car.tankMouth.getContents()}, Машина: $car") + } + + for (car in cars) { + println("Собираемся заправить $car, Кол-во топлива: ${car.tankMouth.getContents()}") + val refuelResult = station.refuel(car.tankMouth, 15) + println("Результат заправки $refuelResult, Кол-во топлива: ${car.tankMouth.getContents()}, Машина: $car") + } } \ No newline at end of file