Skip to content

Instantly share code, notes, and snippets.

@krishofmans
Created May 24, 2025 08:22
Show Gist options
  • Select an option

  • Save krishofmans/10d86bb46444e7bae92872bc3d7e3ba8 to your computer and use it in GitHub Desktop.

Select an option

Save krishofmans/10d86bb46444e7bae92872bc3d7e3ba8 to your computer and use it in GitHub Desktop.
My solution so far for the inventory kata
package io.tripled.backtothefuture
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import java.time.LocalDateTime
import java.time.temporal.ChronoUnit
class InventoryKata : FunSpec( {
val today = LocalDateTime.now()
val yesterday = today.minus(1, ChronoUnit.DAYS)
val tomorrow = today.plus(1, ChronoUnit.DAYS)
test("adding things to the inventory through time") {
val inventory = Inventory()
inventory.add(today, "🍌")
inventory.add(today, "πŸ₯")
inventory.add(tomorrow, "🍊")
inventory.project(yesterday) shouldBe ""
inventory.project(today) shouldBe "🍌πŸ₯"
inventory.project(tomorrow) shouldBe "🍌πŸ₯πŸŠ"
}
test("removing things impacts the inventory"){
val inventory = Inventory()
inventory.add(today, "🍌");
inventory.add(today, "πŸ₯");
inventory.remove(tomorrow, "🍌");
inventory.project(yesterday) shouldBe ""
inventory.project(today) shouldBe "🍌πŸ₯"
inventory.project(tomorrow) shouldBe "πŸ₯"
}
test("grouping items"){
val inventory = Inventory()
val future = tomorrow
inventory.add(today, "🍌");
inventory.add(today, "πŸ₯");
inventory.add(today, "🍊");
inventory.add(today, "🍎");
inventory.project(future) shouldBe "🍌πŸ₯πŸŠπŸŽ"
inventory.group(tomorrow, listOf("πŸ₯", "🍊"));
inventory.project(future) shouldBe "🍌|πŸ₯πŸŠ|🍎"
}
})
class Inventory {
private val inventory = mutableListOf<InventoryEvent>()
fun add(momentInTime: LocalDateTime, product: String) {
inventory.add(InventoryEventAdded(momentInTime, SingleItem(product)))
}
fun project(momentInTime: LocalDateTime): String {
val finalState = mutableListOf<Item>()
inventory.sortBy { it.momentInTime }
val eventsSoFar =
inventory.filter { beforeOrAtTheSameTime(it, momentInTime) }.toList()
for (event in eventsSoFar) {
when (event) {
is InventoryEventAdded -> {
finalState.add(event.item)
}
is InventoryEventRemoved -> {
finalState.remove(event.item)
}
is InventoryGroupAdded -> {
finalState.add(event.item)
//finalState.removeAll(event.item.presentation.split(""))
}
}
}
return finalState.joinToString("") { it.presentation }
}
private fun beforeOrAtTheSameTime(
event: InventoryEvent,
momentInTime: LocalDateTime,
): Boolean = event.momentInTime.isBefore(momentInTime) || momentInTime == event.momentInTime
fun remove(momentInTime: LocalDateTime, product: String) {
inventory.add(InventoryEventRemoved(momentInTime, SingleItem(product)))
}
fun group(momentInTime: LocalDateTime, groupOfProducts: List<String>) {
inventory.add(InventoryGroupAdded(momentInTime, GroupedItem(groupOfProducts)))
}
sealed interface InventoryEvent {
val momentInTime: LocalDateTime
val item: Item
}
class InventoryEventAdded(override val momentInTime: LocalDateTime, override val item: Item) : InventoryEvent
class InventoryEventRemoved(override val momentInTime: LocalDateTime, override val item: Item) : InventoryEvent
class InventoryGroupAdded(
override val momentInTime: LocalDateTime,
override val item: Item,
) : InventoryEvent
sealed interface Item {
val presentation: String
}
data class SingleItem(val product: String) : Item {
override val presentation: String
get() = product
}
data class GroupedItem(val groupOfProducts: List<String>) : Item {
override val presentation: String
get() = "|${groupOfProducts.joinToString("" ) { it }}|"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment