Skip to content
Open

ДЗ #75

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/main/kotlin/ru/otus/cars/Car.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ interface Car : CarInput {
*/
val carOutput: CarOutput

/**
* Топливная система
*/
val tank: Tank
val mouth: TankMouth
fun refuel(amount: Double)

/**
* Получить оборудование
*/
Expand Down
5 changes: 5 additions & 0 deletions src/main/kotlin/ru/otus/cars/CarOutput.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,9 @@ interface CarOutput {
* Скажи текущую скорость
*/
fun getCurrentSpeed(): Int

/**
* Скажи сколько топлива
*/
fun getFuelLevel(): Double
}
49 changes: 49 additions & 0 deletions src/main/kotlin/ru/otus/cars/CarRefill.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package ru.otus.cars

class CarRefill {
/**
* Заправить одну машину.
* @param car машина (любая реализация Car)
* @param liters сколько литров лить
*/
fun refuel(car: Car, liters: Double) {
// Определяем тип топлива по горловине
val fuelType = when (car.mouth) {
is GasolineMouth -> "benzin"
is GasMouth -> "gas"
else -> "kakoe-to eshe toplivo"
}
val plateNumber = try { car.plates.number } catch (e: NotImplementedError) { "без номера" }
println("Zapravka: liyem $liters litrov ($fuelType) v mashinu ${car::class.simpleName} nomer $plateNumber")

try {
car.refuel(liters)
println(" → Zapravleno uspesno")
} catch (e: TankOverflowException) {
println(" → Error: ${e.message}")
println(" → Bak polomalsya, no mojno prodoljit s drugimi mashinami")
}
}

/**
* Заправить коллекцию машин
* Если с баком проблема — остальные всё равно заправим.
*/
fun refuelAll(cars: List<Car>, litersPerCar: Double) {
println("\n=== Massovaya zapravka ($litersPerCar litrov kajdoy) ===\n")

for ((index, car) in cars.withIndex()) {
println("[$index] ${car.plates.number}")
refuel(car, litersPerCar)
println()
}

println("=== Itogo ===")
cars.forEach { car ->
val gasoline = car.tank.getGasolineLevel()
val gas = car.tank.getGasLevel()
println("${car.plates.number}: Benzin=$gasoline litrov, Gas=$gas litrov")
}
}

}
93 changes: 93 additions & 0 deletions src/main/kotlin/ru/otus/cars/CarTankSystem.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package ru.otus.cars

/**
* Топливная система
*/
// --- Типы топлива ---
sealed class Fuel {
abstract val amount: Double

data class Gasoline(override val amount: Double) : Fuel()
data class LiquefiedGas(override val amount: Double) : Fuel()
}

// --- Бак (реализация спрятана от пользователя) ---
class Tank private constructor(
private var gasoline: Double = 0.0,
private var gas: Double = 0.0,
private val capacity: Double = 100.0,
) {
override fun toString() : String {
return "currentFuel Gaz = $gas, Benzin = $gasoline)"
}
fun getGasolineLevel(): Double = gasoline
fun getGasLevel(): Double = gas
//Не знаю как сделать исключение и условие в inline
// fun addFuel(fuel: Fuel) {
// when (fuel) {
// is Fuel.Gasoline -> gasoline = (gasoline + fuel.amount).coerceAtMost(capacity)
// is Fuel.LiquefiedGas -> gas = (gas + fuel.amount).coerceAtMost(capacity)
// }
// }

fun addFuel(fuel: Fuel) {
when (fuel) {
is Fuel.Gasoline -> {
// println("Zalivaetsya v bak ${fuel.amount} litrov")
val newAmount = gasoline + fuel.amount
// println("Posle zapravki v bake stanet ${newAmount} litrov")
if (newAmount > capacity) {
println("Bak perepolnen! Zalivaetsya ${fuel.amount}, est benzina $gasoline | gaza $gas, limit $capacity")
}
if (gas > 0) {
throw TankOverflowException(
"V bake est gaz = $gas! Zalivaetsya benzin ${fuel.amount}, popytka zalit oba vida topliva vyzvala iskluchenie!"
)
}
gasoline = (newAmount).coerceAtMost(capacity)
// println("V bake posle zapravki $gasoline litrov gasoline")
}
is Fuel.LiquefiedGas -> {
// println("Zalivaetsya v bak ${fuel.amount} litrov")
val newAmount = gas + fuel.amount
// println("Posle zapravki v bake stanet ${newAmount} litrov")
if (newAmount > capacity) {
println("Bak perepolnen! Zalivaetsya ${fuel.amount}, est benzina $gasoline | gaza $gas, limit $capacity")
}
if (gasoline > 0) {
throw TankOverflowException(
"V bake est benzin = $gasoline! Zalivaetsya gaz ${fuel.amount}, popytka zalit oba vida topliva vyzvala iskluchenie!"
)
}
gas = (newAmount).coerceAtMost(capacity)
// println("V bake posle zapravki $gas litrov gas")
}
}
}

companion object {
fun create(): Tank = Tank()
}
}

// ──────────────────────────────────────────────
// Исключение: с баком проблемы
// ──────────────────────────────────────────────
class TankOverflowException(message: String) : Exception(message)

// --- Горловина бака ---
sealed class TankMouth(protected val tank: Tank) {
abstract fun refuel(amount: Double)
}

class GasolineMouth(tank: Tank) : TankMouth(tank) {
override fun refuel(amount: Double) {
tank.addFuel(Fuel.Gasoline(amount))
}
}

class GasMouth(tank: Tank) : TankMouth(tank) {
override fun refuel(amount: Double) {
tank.addFuel(Fuel.LiquefiedGas(amount))
}
}
22 changes: 21 additions & 1 deletion src/main/kotlin/ru/otus/cars/Taz.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package ru.otus.cars

import kotlin.random.Random

object Taz: Car {
/**
* Номерной знак
Expand All @@ -12,12 +14,30 @@ object Taz: Car {
*/
override val color: String = "Ржавый"

/**
* Топливная система: бак и горловина.
* Бак спрятан — доступ только через горловину и CarOutput.
*/
override val tank: Tank = Tank.create()
// для taz ставим любую горловину
override val mouth: TankMouth = when (Random.nextInt(0, 2)) {
0 -> GasolineMouth(tank)
else -> GasMouth(tank)
}



/**
* Заправка через горловину
*/
override fun refuel(amount: Double) {
mouth.refuel(amount)
}
/**
* Следит за машиной
*/
override val carOutput: CarOutput
get() = throw NotImplementedError("Приборов нет")

/**
* Получить оборудование
*/
Expand Down
25 changes: 24 additions & 1 deletion src/main/kotlin/ru/otus/cars/Vaz2107.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ import kotlin.random.Random
* Семёрочка
*/
class Vaz2107 private constructor(color: String) : VazPlatform(color) {

/**
* Топливная система: бак и горловина.
* Бак спрятан — доступ только через горловину и CarOutput.
*/
override val tank: Tank = Tank.create()
override val mouth: TankMouth = GasMouth(tank)

/**
* Заправка через горловину
*/
override fun refuel(amount: Double) {
mouth.refuel(amount)
}

/**
* Сам-себе-сборщик ВАЗ 2107.
*/
Expand All @@ -20,6 +35,8 @@ class Vaz2107 private constructor(color: String) : VazPlatform(color) {
override fun build(plates: Car.Plates): Vaz2107 = Vaz2107("Зеленый").apply {
this.engine = getRandomEngine()
this.plates = plates
this.tank
this.mouth.refuel(30.0) // Залили топлива при сборке
}

/**
Expand All @@ -28,6 +45,9 @@ class Vaz2107 private constructor(color: String) : VazPlatform(color) {
fun test(vaz2107: Vaz2107) {
println("Проверяем, едет ли ВАЗ 2107...")
vaz2107.currentSpeed = Random.nextInt(0, 60)
vaz2107.refuel(Random.nextDouble(0.0, 60.0)) // долить для теста еще топлива
// println("Lyem toplivo v Vaz2107, itogo ${vaz2107.tank.getGasLevel()} litrov") // не очень понятно почему так работает, ведь tank приватный
println("Zapravili Vaz2107 na ${vaz2107.carOutput.getFuelLevel()} litrov")
}

/**
Expand Down Expand Up @@ -59,7 +79,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, currentFuel=${carOutput.getFuelLevel()})"
}

/**
Expand All @@ -74,5 +94,8 @@ class Vaz2107 private constructor(color: String) : VazPlatform(color) {
override fun getCurrentSpeed(): Int {
return this@Vaz2107.currentSpeed
}
override fun getFuelLevel(): Double {
return this@Vaz2107.tank.getGasLevel()
}
}
}
24 changes: 22 additions & 2 deletions src/main/kotlin/ru/otus/cars/Vaz2108.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ import kotlin.random.Random
* Восьмерка
*/
class Vaz2108 private constructor(color: String) : VazPlatform(color) {
/**
* Топливная система: бак и горловина создаются вместе.
* Бак спрятан — доступ только через горловину и CarOutput.
*/
override val tank: Tank = Tank.create()
override val mouth: TankMouth = GasolineMouth(tank)

/**
* Заправка через горловину
*/
override fun refuel(amount: Double) {
mouth.refuel(amount)
}
/**
* Сам-себе-сборщик ВАЗ 2108.
*/
Expand All @@ -21,11 +34,16 @@ class Vaz2108 private constructor(color: String) : VazPlatform(color) {
override fun build(plates: Car.Plates): Vaz2108 = Vaz2108("Красный").apply {
this.engine = getRandomEngine()
this.plates = plates
this.tank
this.mouth.refuel(10.0) //зальем топлива в первый раз
}

fun alignWheels(vaz2108: Vaz2108) {
println("Ваз 2108 выравнивает колёса... ")
vaz2108.wheelAngle = 0
vaz2108.refuel(Random.nextDouble(70.0, 100.0))
// println("Lyem toplivo v Vaz2108, itogo ${vaz2108.tank.getGasolineLevel()} litrov") // не очень понятно почему так работает, ведь tank приватный
println("Zapravili Vaz2108 na ${vaz2108.carOutput.getFuelLevel()} litrov")
}

/**
Expand Down Expand Up @@ -53,7 +71,6 @@ class Vaz2108 private constructor(color: String) : VazPlatform(color) {
}

private var currentSpeed: Int = 0 // Скока жмёт

/**
* Доступно сборщику
* @see [build]
Expand All @@ -63,7 +80,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, currentFuel=${carOutput.getFuelLevel()})"
}

/**
Expand All @@ -78,5 +95,8 @@ class Vaz2108 private constructor(color: String) : VazPlatform(color) {
override fun getCurrentSpeed(): Int {
return this@Vaz2108.currentSpeed
}
override fun getFuelLevel(): Double {
return this@Vaz2108.tank.getGasolineLevel()
}
}
}
Loading