Skip to content
Open
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
5 changes: 5 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,11 @@ interface Car : CarInput {
*/
val carOutput: CarOutput

/**
* Горловина бака
*/
val tankMouth: TankMouth

/**
* Получить оборудование
*/
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(): Int
}
55 changes: 55 additions & 0 deletions src/main/kotlin/ru/otus/cars/FuelSystem.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package ru.otus.cars

/**
* Бак машины.
*/
internal interface Tank {
/**
* Горловина, установленная на бак.
*/
val mouth: TankMouth

/**
* Содержимое бака в литрах.
*/
fun getContents(): Int

/**
* Принять топливо.
*/
fun receiveFuel(liters: Int)
}

/**
* Горловина бака определяет, какое топливо можно заливать в машину.
*/
sealed class TankMouth protected constructor(private val tank: Tank) {
internal fun fill(liters: Int) {
tank.receiveFuel(liters)
}

class Petrol internal constructor(tank: Tank) : TankMouth(tank)

class Gas internal constructor(tank: Tank) : TankMouth(tank)
}

internal class SimpleTank(
private val capacity: Int = 50,
mouthFactory: (Tank) -> TankMouth,
) : Tank {
override val mouth: TankMouth = mouthFactory(this)

private var fuelLevel: Int = 0

override fun getContents(): Int {
return fuelLevel
}

override fun receiveFuel(liters: Int) {
require(liters > 0) { "Количество топлива должно быть положительным" }

fuelLevel = (fuelLevel + liters).coerceAtMost(capacity)
}
}

class BrokenTankException(message: String) : RuntimeException(message)
25 changes: 25 additions & 0 deletions src/main/kotlin/ru/otus/cars/GasStation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ru.otus.cars

/**
* Заправка.
*/
object GasStation {
fun fill(car: Car, liters: Int) {
try {
when (val mouth = car.tankMouth) {
is TankMouth.Gas -> fillGas(mouth, liters)
is TankMouth.Petrol -> fillPetrol(mouth, liters)
}
} catch (e: BrokenTankException) {
println("Заправка безопасно остановлена: ${e.message}")
}
}

private fun fillGas(mouth: TankMouth.Gas, liters: Int) {
mouth.fill(liters)
}

private fun fillPetrol(mouth: TankMouth.Petrol, liters: Int) {
mouth.fill(liters)
}
}
32 changes: 30 additions & 2 deletions src/main/kotlin/ru/otus/cars/Taz.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
package ru.otus.cars

object Taz: Car {
private object ExplodingTank : Tank {
override val mouth: TankMouth = TankMouth.Petrol(this)

override fun getContents(): Int {
return 0
}

override fun receiveFuel(liters: Int) {
throw BrokenTankException("Бак ТАЗа взорвался")
}
}

/**
* Номерной знак
*/
Expand All @@ -15,8 +27,20 @@ object Taz: Car {
/**
* Следит за машиной
*/
override val carOutput: CarOutput
get() = throw NotImplementedError("Приборов нет")
override val carOutput: CarOutput = object : CarOutput {
override fun getCurrentSpeed(): Int {
return 0
}

override fun getFuelLevel(): Int {
return ExplodingTank.getContents()
}
}

/**
* Горловина бака
*/
override val tankMouth: TankMouth = ExplodingTank.mouth

/**
* Получить оборудование
Expand All @@ -36,4 +60,8 @@ object Taz: Car {
override fun wheelToLeft(degrees: Int) {
throw NotImplementedError("Руля нет")
}

override fun toString(): String {
return "Taz(color=$color, fuelLevel=${carOutput.getFuelLevel()})"
}
}
21 changes: 18 additions & 3 deletions src/main/kotlin/ru/otus/cars/Vaz2107.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import kotlin.random.Random
/**
* Семёрочка
*/
class Vaz2107 private constructor(color: String) : VazPlatform(color) {
class Vaz2107 private constructor(
color: String,
private val tank: Tank,
) : VazPlatform(color) {
/**
* Сам-себе-сборщик ВАЗ 2107.
*/
Expand All @@ -17,7 +20,10 @@ class Vaz2107 private constructor(color: String) : VazPlatform(color) {
}
}

override fun build(plates: Car.Plates): Vaz2107 = Vaz2107("Зеленый").apply {
override fun build(plates: Car.Plates): Vaz2107 = Vaz2107(
color = "Зеленый",
tank = SimpleTank { TankMouth.Gas(it) },
).apply {
this.engine = getRandomEngine()
this.plates = plates
}
Expand Down Expand Up @@ -50,6 +56,11 @@ class Vaz2107 private constructor(color: String) : VazPlatform(color) {

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

/**
* Семерка ездит на газу.
*/
override val tankMouth: TankMouth = tank.mouth

/**
* Доступно сборщику
* @see [build]
Expand All @@ -59,7 +70,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, fuelLevel=${tank.getContents()})"
}

/**
Expand All @@ -74,5 +85,9 @@ class Vaz2107 private constructor(color: String) : VazPlatform(color) {
override fun getCurrentSpeed(): Int {
return this@Vaz2107.currentSpeed
}

override fun getFuelLevel(): Int {
return this@Vaz2107.tank.getContents()
}
}
}
21 changes: 18 additions & 3 deletions src/main/kotlin/ru/otus/cars/Vaz2108.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import kotlin.random.Random
/**
* Восьмерка
*/
class Vaz2108 private constructor(color: String) : VazPlatform(color) {
class Vaz2108 private constructor(
color: String,
private val tank: Tank,
) : VazPlatform(color) {
/**
* Сам-себе-сборщик ВАЗ 2108.
*/
Expand All @@ -18,7 +21,10 @@ class Vaz2108 private constructor(color: String) : VazPlatform(color) {
}
}

override fun build(plates: Car.Plates): Vaz2108 = Vaz2108("Красный").apply {
override fun build(plates: Car.Plates): Vaz2108 = Vaz2108(
color = "Красный",
tank = SimpleTank { TankMouth.Petrol(it) },
).apply {
this.engine = getRandomEngine()
this.plates = plates
}
Expand Down Expand Up @@ -54,6 +60,11 @@ class Vaz2108 private constructor(color: String) : VazPlatform(color) {

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

/**
* Восьмерка ездит на бензине.
*/
override val tankMouth: TankMouth = tank.mouth

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

/**
Expand All @@ -78,5 +89,9 @@ class Vaz2108 private constructor(color: String) : VazPlatform(color) {
override fun getCurrentSpeed(): Int {
return this@Vaz2108.currentSpeed
}

override fun getFuelLevel(): Int {
return this@Vaz2108.tank.getContents()
}
}
}
24 changes: 24 additions & 0 deletions src/main/kotlin/ru/otus/cars/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ fun main() {
techChecks()
println("\n===> Taz...")
println(Taz.color)
println("\n===> fill cars...")
fillCars()
}

fun driveCars() {
Expand Down Expand Up @@ -90,4 +92,26 @@ fun repairEngine(car: VazPlatform) {
is VazEngine.LADA_2107 -> println("Чистка карбюратора у двигателя объемом ${car.engine.volume} куб.см у машины $car")
is VazEngine.SAMARA_2108 -> println("Угол зажигания у двигателя объемом ${car.engine.volume} куб.см у машины $car")
}
}

fun fillCars() {
val cars = listOf(
Togliatti.buildCar(Vaz2107, Car.Plates("777", 77)),
Togliatti.buildCar(Vaz2108, Car.Plates("888", 78)),
Taz,
)

println("До заправки:")
cars.forEach { car ->
println(car)
}

cars.forEach { car ->
GasStation.fill(car, liters = 30)
}

println("После заправки:")
cars.forEach { car ->
println(car)
}
}