diff --git a/Kotlin/README.md b/Kotlin/README.md index 0b80bad9..91ebb827 100644 --- a/Kotlin/README.md +++ b/Kotlin/README.md @@ -64,4 +64,16 @@ During refactor I also found README file in a main directory in which algorithm - quality cannot be negative At this point code is readable but not so extensible because all algos are in a single class which might grow to infinity. -The usual way to handle this situation is to go with OO approach - I cannot modify Item class so I will implement new one and its specifications. \ No newline at end of file +The usual way to handle this situation is to go with OO approach - I cannot modify Item class so I will implement new one and its specifications. + +### End result +I didn't modify gliderose in order to be able to execute regression tests that compare my new implementation results with original. +I created a package platinumrose with few subpackages +- simple: is the simpleness, cleaned up implementation, no OO concepts or design-patterns +- mid: is the mid-level implementation with a separate strategies for each type of item +- advanced - is one of possible implementation of production grade code, it involves item extension methods, qualityCalculator factory, and separation of concepts. This is the only impl fuully covered by tests +![img_2.png](img_2.png) + + +### TODO +- I didn't cover extra case described in the main README because of other responsibilities and lack of time \ No newline at end of file diff --git a/Kotlin/img_2.png b/Kotlin/img_2.png new file mode 100644 index 00000000..6266b570 Binary files /dev/null and b/Kotlin/img_2.png differ diff --git a/Kotlin/src/main/kotlin/com/gildedrose/Item.kt b/Kotlin/src/main/kotlin/com/gildedrose/Item.kt index 5059f949..c54f9c91 100644 --- a/Kotlin/src/main/kotlin/com/gildedrose/Item.kt +++ b/Kotlin/src/main/kotlin/com/gildedrose/Item.kt @@ -1,5 +1,6 @@ package com.gildedrose +// NOTE: changes to data class to make comparison (asserts) easier. If rough goblin is against it, I'm ready to die data class Item(var name: String, var sellIn: Int, var quality: Int) { override fun toString(): String { return this.name + ", " + this.sellIn + ", " + this.quality diff --git a/Kotlin/src/main/kotlin/com/gildedrose/ItemExtention.kt b/Kotlin/src/main/kotlin/com/gildedrose/ItemExtention.kt new file mode 100644 index 00000000..88897af0 --- /dev/null +++ b/Kotlin/src/main/kotlin/com/gildedrose/ItemExtention.kt @@ -0,0 +1,2 @@ +package com.gildedrose + diff --git a/Kotlin/src/main/kotlin/com/gildedrose/TestcasesGenerator.kt b/Kotlin/src/main/kotlin/com/gildedrose/TestcasesGenerator.kt index b113f6ba..0d88df4e 100644 --- a/Kotlin/src/main/kotlin/com/gildedrose/TestcasesGenerator.kt +++ b/Kotlin/src/main/kotlin/com/gildedrose/TestcasesGenerator.kt @@ -1,8 +1,6 @@ package com.gildedrose -import com.gildedrose.PlatinumRose.Companion.AGED_BRIE -import com.gildedrose.PlatinumRose.Companion.BACKSTAGE_PASSES -import com.gildedrose.PlatinumRose.Companion.LULFURAS_HAND_OF_RAGNAROK + import java.util.* @@ -20,9 +18,9 @@ fun generateTestCasesInRanger(names: List, sellInRange: IntRange, qualit fun main(args: Array) { val names = listOf( - AGED_BRIE, - BACKSTAGE_PASSES, - LULFURAS_HAND_OF_RAGNAROK, + com.platinumrose.ItemType.AGED_BRIE.name, + com.platinumrose.ItemType.BACKSTAGE_PASSES.name, + com.platinumrose.ItemType.SULFURAS.name, "new none-existing on code name" ) val sellInRange = -100..100 diff --git a/Kotlin/src/main/kotlin/com/platinumrose/ItemConstant.kt b/Kotlin/src/main/kotlin/com/platinumrose/ItemConstant.kt new file mode 100644 index 00000000..2d2d908c --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/ItemConstant.kt @@ -0,0 +1,9 @@ +package com.platinumrose + +class ItemConstant { + companion object { + const val MIN_QUALITY = 0 + const val REGULAR_ITEM_MAX_QUALITY = 50 + const val LEGENDARY_ITEM_MAX_QUALITY = 80 + } +} \ No newline at end of file diff --git a/Kotlin/src/main/kotlin/com/platinumrose/ItemType.kt b/Kotlin/src/main/kotlin/com/platinumrose/ItemType.kt new file mode 100644 index 00000000..f168092f --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/ItemType.kt @@ -0,0 +1,14 @@ +package com.platinumrose + +enum class ItemType(val value: String? = null) { + AGED_BRIE("Aged Brie"), + BACKSTAGE_PASSES("Backstage passes to a TAFKAL80ETC concert"), + SULFURAS("Sulfuras, Hand of Ragnaros"), + REGULAR; + + companion object { + fun fromValue(value: String): com.platinumrose.ItemType { + return entries.find { it.value == value } ?: com.platinumrose.ItemType.REGULAR + } + } +} \ No newline at end of file diff --git a/Kotlin/src/main/kotlin/com/platinumrose/Solution.kt b/Kotlin/src/main/kotlin/com/platinumrose/Solution.kt new file mode 100644 index 00000000..dd34afdd --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/Solution.kt @@ -0,0 +1,8 @@ +package com.platinumrose + +import com.gildedrose.Item + +interface Solution { + fun items(): List + fun updateQuality() +} \ No newline at end of file diff --git a/Kotlin/src/main/kotlin/com/platinumrose/advance/AdvancePlatinumRose.kt b/Kotlin/src/main/kotlin/com/platinumrose/advance/AdvancePlatinumRose.kt new file mode 100644 index 00000000..f012d9d1 --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/advance/AdvancePlatinumRose.kt @@ -0,0 +1,23 @@ +package com.platinumrose.advance + +import com.gildedrose.Item +import com.platinumrose.ItemType.Companion.fromValue +import com.platinumrose.Solution +import com.platinumrose.advance.extention.updateQuality +import com.platinumrose.advance.factory.QualityCalculatorFactory +import com.platinumrose.advance.factory.QualityCalculatorFactoryImpl + +class AdvancePlatinumRose(private val items: List) : Solution { + + private val qualityCalculatorFactory: QualityCalculatorFactory = QualityCalculatorFactoryImpl() + + override fun items(): List { + return items + } + + override fun updateQuality() { + items.forEach { + it.updateQuality(qualityCalculatorFactory.qualityCalculator(fromValue(it.name))) + } + } +} diff --git a/Kotlin/src/main/kotlin/com/platinumrose/advance/extention/ItemExtention.kt b/Kotlin/src/main/kotlin/com/platinumrose/advance/extention/ItemExtention.kt new file mode 100644 index 00000000..79662eef --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/advance/extention/ItemExtention.kt @@ -0,0 +1,28 @@ +package com.platinumrose.advance.extention + +import com.gildedrose.Item +import com.platinumrose.advance.quality.QualityCalculator + + +fun Item.updateQuality(qualityCalculator: QualityCalculator) { + updateQualityBeforeSellInDate(qualityCalculator) + updateQualityAfterSellInDate(qualityCalculator) + coerceQuality(qualityCalculator) +} + +private fun Item.updateQualityBeforeSellInDate(qualityCalculator: QualityCalculator) { + val qualityIncrease = + qualityCalculator.computeQualityIncreaseBeforeSellIn(sellIn, quality) + sellIn += qualityCalculator.computeSellInDecrease(sellIn) + quality += qualityIncrease +} + +private fun Item.updateQualityAfterSellInDate(qualityCalculator: QualityCalculator) { + val qualityIncrease = + if (sellIn >= 0) 0 else qualityCalculator.computeQualityIncreaseAfterSellIn(sellIn, quality) + quality += qualityIncrease +} + +private fun Item.coerceQuality(qualityCalculator: QualityCalculator) { + quality = quality.coerceIn(com.platinumrose.ItemConstant.MIN_QUALITY, qualityCalculator.maxQuality()) +} \ No newline at end of file diff --git a/Kotlin/src/main/kotlin/com/platinumrose/advance/factory/QualityCalculatorFactory.kt b/Kotlin/src/main/kotlin/com/platinumrose/advance/factory/QualityCalculatorFactory.kt new file mode 100644 index 00000000..5607a27f --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/advance/factory/QualityCalculatorFactory.kt @@ -0,0 +1,9 @@ +package com.platinumrose.advance.factory + +import com.platinumrose.ItemType +import com.platinumrose.advance.quality.QualityCalculator + + +interface QualityCalculatorFactory { + fun qualityCalculator(itemType: ItemType): QualityCalculator +} \ No newline at end of file diff --git a/Kotlin/src/main/kotlin/com/platinumrose/advance/factory/QualityCalculatorFactoryImpl.kt b/Kotlin/src/main/kotlin/com/platinumrose/advance/factory/QualityCalculatorFactoryImpl.kt new file mode 100644 index 00000000..06e06068 --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/advance/factory/QualityCalculatorFactoryImpl.kt @@ -0,0 +1,22 @@ +package com.platinumrose.advance.factory + +import com.platinumrose.ItemType +import com.platinumrose.advance.quality.* + + +class QualityCalculatorFactoryImpl : QualityCalculatorFactory { + private val strategies: Map + private val regularItem = RegularItem() + + init { + val agedBrieUpdated = AgedBrie() + val backstagePasses = BackstagePasses() + val sulfuras = Sulfuras() + val strategiesList = listOf(agedBrieUpdated, backstagePasses, sulfuras) + strategies = strategiesList.associateBy { it.type() } + } + + override fun qualityCalculator(itemType: ItemType): QualityCalculator { + return strategies.getOrDefault(itemType, regularItem) + } +} \ No newline at end of file diff --git a/Kotlin/src/main/kotlin/com/platinumrose/advance/quality/AgedBrie.kt b/Kotlin/src/main/kotlin/com/platinumrose/advance/quality/AgedBrie.kt new file mode 100644 index 00000000..c3b4dca5 --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/advance/quality/AgedBrie.kt @@ -0,0 +1,28 @@ +package com.platinumrose.advance.quality + +import com.platinumrose.ItemConstant.Companion.REGULAR_ITEM_MAX_QUALITY +import com.platinumrose.ItemType.AGED_BRIE + + +internal class AgedBrie : QualityCalculator { + + override fun type(): com.platinumrose.ItemType { + return AGED_BRIE + } + + override fun maxQuality(): Int { + return REGULAR_ITEM_MAX_QUALITY + } + + override fun computeSellInDecrease(sellIn: Int): Int { + return -1 + } + + override fun computeQualityIncreaseBeforeSellIn(sellIn: Int, quality: Int): Int { + return 1 + } + + override fun computeQualityIncreaseAfterSellIn(sellIn: Int, quality: Int): Int { + return 1 + } +} \ No newline at end of file diff --git a/Kotlin/src/main/kotlin/com/platinumrose/advance/quality/BackstagePasses.kt b/Kotlin/src/main/kotlin/com/platinumrose/advance/quality/BackstagePasses.kt new file mode 100644 index 00000000..7fcf37ac --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/advance/quality/BackstagePasses.kt @@ -0,0 +1,32 @@ +package com.platinumrose.advance.quality + +import com.platinumrose.ItemConstant.Companion.REGULAR_ITEM_MAX_QUALITY +import com.platinumrose.ItemType.BACKSTAGE_PASSES + + +internal class BackstagePasses : QualityCalculator { + + override fun type(): com.platinumrose.ItemType { + return BACKSTAGE_PASSES + } + + override fun maxQuality(): Int { + return REGULAR_ITEM_MAX_QUALITY + } + + override fun computeSellInDecrease(sellIn: Int): Int { + return -1 + } + + override fun computeQualityIncreaseBeforeSellIn(sellIn: Int, quality: Int): Int { + return when (sellIn) { + in 0..5 -> 3 + in 6..10 -> 2 + else -> 1 + } + } + + override fun computeQualityIncreaseAfterSellIn(sellIn: Int, quality: Int): Int { + return -quality + } +} \ No newline at end of file diff --git a/Kotlin/src/main/kotlin/com/platinumrose/advance/quality/QualityCalculator.kt b/Kotlin/src/main/kotlin/com/platinumrose/advance/quality/QualityCalculator.kt new file mode 100644 index 00000000..32a3d367 --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/advance/quality/QualityCalculator.kt @@ -0,0 +1,11 @@ +package com.platinumrose.advance.quality + +interface QualityCalculator { + + fun type(): com.platinumrose.ItemType + fun maxQuality(): Int + + fun computeQualityIncreaseBeforeSellIn(sellIn: Int, quality: Int): Int; + fun computeSellInDecrease(sellIn: Int): Int + fun computeQualityIncreaseAfterSellIn(sellIn: Int, quality: Int): Int; +} \ No newline at end of file diff --git a/Kotlin/src/main/kotlin/com/platinumrose/advance/quality/RegularItem.kt b/Kotlin/src/main/kotlin/com/platinumrose/advance/quality/RegularItem.kt new file mode 100644 index 00000000..8ae1d5cb --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/advance/quality/RegularItem.kt @@ -0,0 +1,28 @@ +package com.platinumrose.advance.quality + +import com.platinumrose.ItemConstant.Companion.REGULAR_ITEM_MAX_QUALITY +import com.platinumrose.ItemType.REGULAR + + +internal class RegularItem : QualityCalculator { + + override fun type(): com.platinumrose.ItemType { + return REGULAR + } + + override fun maxQuality(): Int { + return REGULAR_ITEM_MAX_QUALITY + } + + override fun computeSellInDecrease(sellIn: Int): Int { + return -1 + } + + override fun computeQualityIncreaseBeforeSellIn(sellIn: Int, quality: Int): Int { + return -1 + } + + override fun computeQualityIncreaseAfterSellIn(sellIn: Int, quality: Int): Int { + return -1 + } +} \ No newline at end of file diff --git a/Kotlin/src/main/kotlin/com/platinumrose/advance/quality/Sulfuras.kt b/Kotlin/src/main/kotlin/com/platinumrose/advance/quality/Sulfuras.kt new file mode 100644 index 00000000..2ce55b1d --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/advance/quality/Sulfuras.kt @@ -0,0 +1,28 @@ +package com.platinumrose.advance.quality + +import com.platinumrose.ItemConstant.Companion.LEGENDARY_ITEM_MAX_QUALITY +import com.platinumrose.ItemType.SULFURAS + + +internal class Sulfuras : QualityCalculator { + + override fun type(): com.platinumrose.ItemType { + return SULFURAS + } + + override fun maxQuality(): Int { + return LEGENDARY_ITEM_MAX_QUALITY + } + + override fun computeSellInDecrease(sellIn: Int): Int { + return 0 + } + + override fun computeQualityIncreaseBeforeSellIn(sellIn: Int, quality: Int): Int { + return 0 + } + + override fun computeQualityIncreaseAfterSellIn(sellIn: Int, quality: Int): Int { + return 0 + } +} diff --git a/Kotlin/src/main/kotlin/com/platinumrose/mid/MidPlatinumRose.kt b/Kotlin/src/main/kotlin/com/platinumrose/mid/MidPlatinumRose.kt new file mode 100644 index 00000000..4e5d04b6 --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/mid/MidPlatinumRose.kt @@ -0,0 +1,36 @@ +package com.platinumrose.mid + +import com.gildedrose.Item +import com.platinumrose.ItemConstant.Companion.MIN_QUALITY +import com.platinumrose.Solution +import com.platinumrose.mid.strategy.* + + +class MidPlatinumRose(var items: List) : Solution { + private val strategies: Map + private val defaultStrategy = DefaultStrategy() + + init { + val agedBrieStrategy = AgedBrieStrategy() + val backstagePassesStrategy = BackstagePassesStrategy() + val sulfurasStrategy = SulfurasStrategy() + val strategiesList = listOf(agedBrieStrategy, backstagePassesStrategy, sulfurasStrategy) + strategies = strategiesList.associateBy { it.type() } + } + + override fun items(): List { + return items + } + + override fun updateQuality() { + for (item in items) { + val strategy = findUpdateQualityStrategy(item) + strategy.updateQuality(item) + item.quality = item.quality.coerceIn(MIN_QUALITY, strategy.maxQuality()) + } + } + + private fun findUpdateQualityStrategy(item: Item): UpdateQualityStrategy { + return strategies.getOrDefault(com.platinumrose.ItemType.fromValue(item.name), defaultStrategy) + } +} \ No newline at end of file diff --git a/Kotlin/src/main/kotlin/com/platinumrose/mid/strategy/AgedBrieStrategy.kt b/Kotlin/src/main/kotlin/com/platinumrose/mid/strategy/AgedBrieStrategy.kt new file mode 100644 index 00000000..f309842e --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/mid/strategy/AgedBrieStrategy.kt @@ -0,0 +1,25 @@ +package com.platinumrose.mid.strategy + +import com.gildedrose.Item +import com.platinumrose.ItemConstant.Companion.REGULAR_ITEM_MAX_QUALITY +import com.platinumrose.ItemType.AGED_BRIE + + +internal class AgedBrieStrategy : UpdateQualityStrategy { + + override fun type(): com.platinumrose.ItemType { + return AGED_BRIE + } + + override fun updateQuality(item: Item) { + item.quality += 1 + item.sellIn -= 1 + if (item.sellIn < 0) { + item.quality += 1 + } + } + + override fun maxQuality(): Int { + return REGULAR_ITEM_MAX_QUALITY + } +} \ No newline at end of file diff --git a/Kotlin/src/main/kotlin/com/platinumrose/mid/strategy/BackstagePassesStrategy.kt b/Kotlin/src/main/kotlin/com/platinumrose/mid/strategy/BackstagePassesStrategy.kt new file mode 100644 index 00000000..41cb418b --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/mid/strategy/BackstagePassesStrategy.kt @@ -0,0 +1,31 @@ +package com.platinumrose.mid.strategy + +import com.gildedrose.Item +import com.platinumrose.ItemConstant.Companion.REGULAR_ITEM_MAX_QUALITY +import com.platinumrose.ItemType.BACKSTAGE_PASSES + + +internal class BackstagePassesStrategy : UpdateQualityStrategy { + + override fun type(): com.platinumrose.ItemType { + return BACKSTAGE_PASSES + } + + override fun updateQuality(item: Item) { + item.quality += 1 + if (item.sellIn < 11) { + item.quality += 1 + } + if (item.sellIn < 6) { + item.quality += 1 + } + item.sellIn -= 1 + if (item.sellIn < 0) { + item.quality = 0 + } + } + + override fun maxQuality(): Int { + return REGULAR_ITEM_MAX_QUALITY + } +} \ No newline at end of file diff --git a/Kotlin/src/main/kotlin/com/platinumrose/mid/strategy/DefaultStrategy.kt b/Kotlin/src/main/kotlin/com/platinumrose/mid/strategy/DefaultStrategy.kt new file mode 100644 index 00000000..ae723516 --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/mid/strategy/DefaultStrategy.kt @@ -0,0 +1,25 @@ +package com.platinumrose.mid.strategy + +import com.gildedrose.Item +import com.platinumrose.ItemConstant.Companion.REGULAR_ITEM_MAX_QUALITY +import com.platinumrose.ItemType.REGULAR + + +internal class DefaultStrategy : UpdateQualityStrategy { + + override fun type(): com.platinumrose.ItemType { + return REGULAR + } + + override fun updateQuality(item: Item) { + item.quality -= 1 + item.sellIn -= 1 + if (item.sellIn < 0) { + item.quality -= 1 + } + } + + override fun maxQuality(): Int { + return REGULAR_ITEM_MAX_QUALITY + } +} \ No newline at end of file diff --git a/Kotlin/src/main/kotlin/com/platinumrose/mid/strategy/SulfurasStrategy.kt b/Kotlin/src/main/kotlin/com/platinumrose/mid/strategy/SulfurasStrategy.kt new file mode 100644 index 00000000..0e20e2ce --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/mid/strategy/SulfurasStrategy.kt @@ -0,0 +1,23 @@ +package com.platinumrose.mid.strategy + +import com.gildedrose.Item +import com.platinumrose.ItemConstant.Companion.LEGENDARY_ITEM_MAX_QUALITY +import com.platinumrose.ItemType.SULFURAS + + +internal class SulfurasStrategy : UpdateQualityStrategy { + + override fun type(): com.platinumrose.ItemType { + return SULFURAS + } + + override fun updateQuality(item: Item) { + // nothing to do here + } + + override fun maxQuality(): Int { + return LEGENDARY_ITEM_MAX_QUALITY + } +} + + diff --git a/Kotlin/src/main/kotlin/com/platinumrose/mid/strategy/UpdateQualityStrategy.kt b/Kotlin/src/main/kotlin/com/platinumrose/mid/strategy/UpdateQualityStrategy.kt new file mode 100644 index 00000000..e0af7073 --- /dev/null +++ b/Kotlin/src/main/kotlin/com/platinumrose/mid/strategy/UpdateQualityStrategy.kt @@ -0,0 +1,9 @@ +package com.platinumrose.mid.strategy + +import com.gildedrose.Item + +interface UpdateQualityStrategy { + fun type(): com.platinumrose.ItemType + fun updateQuality(item: Item) + fun maxQuality(): Int +} \ No newline at end of file diff --git a/Kotlin/src/main/kotlin/com/gildedrose/PlatinumRose.kt b/Kotlin/src/main/kotlin/com/platinumrose/simple/SimplePlatinumRose.kt similarity index 56% rename from Kotlin/src/main/kotlin/com/gildedrose/PlatinumRose.kt rename to Kotlin/src/main/kotlin/com/platinumrose/simple/SimplePlatinumRose.kt index a8e8cd81..e1bddb6d 100644 --- a/Kotlin/src/main/kotlin/com/gildedrose/PlatinumRose.kt +++ b/Kotlin/src/main/kotlin/com/platinumrose/simple/SimplePlatinumRose.kt @@ -1,6 +1,9 @@ -package com.gildedrose +package com.platinumrose.simple -class PlatinumRose(var items: List) { +import com.gildedrose.Item +import com.platinumrose.Solution + +class SimplePlatinumRose(var items: List) : Solution { companion object { const val MIN_QUALITY = 0 @@ -12,15 +15,20 @@ class PlatinumRose(var items: List) { const val LULFURAS_HAND_OF_RAGNAROK = "Sulfuras, Hand of Ragnaros" } - fun updateQuality() { + + override fun items(): List { + return items + } + + + override fun updateQuality() { for (item in items) { when (item.name) { - AGED_BRIE -> updateQualityForAgedBrie(item) - BACKSTAGE_PASSES -> updateQualityForBackstagePasses(item) - LULFURAS_HAND_OF_RAGNAROK -> null + com.platinumrose.ItemType.AGED_BRIE.value -> updateQualityForAgedBrie(item) + com.platinumrose.ItemType.BACKSTAGE_PASSES.value -> updateQualityForBackstagePasses(item) + com.platinumrose.ItemType.SULFURAS.value -> updateQualityForSulfuras(item) else -> updateQuality(item) } - item.quality = item.quality.coerceIn(0, REGULAR_ITEM_MAX_QUALITY) } } @@ -30,6 +38,7 @@ class PlatinumRose(var items: List) { if (item.sellIn < 0) { item.quality -= 1 } + item.quality = item.quality.coerceIn(0, REGULAR_ITEM_MAX_QUALITY) } private fun updateQualityForAgedBrie(item: Item) { @@ -38,6 +47,7 @@ class PlatinumRose(var items: List) { if (item.sellIn < 0) { item.quality += 1 } + item.quality = item.quality.coerceIn(0, REGULAR_ITEM_MAX_QUALITY) } private fun updateQualityForBackstagePasses(item: Item) { @@ -52,5 +62,10 @@ class PlatinumRose(var items: List) { if (item.sellIn < 0) { item.quality = 0 } + item.quality = item.quality.coerceIn(0, REGULAR_ITEM_MAX_QUALITY) + } + + private fun updateQualityForSulfuras(item: Item) { + item.quality = item.quality.coerceIn(0, LEGENDARY_ITEM_MAX_QUALITY) } } \ No newline at end of file diff --git a/Kotlin/src/test/kotlin/com/gildedrose/PlatinumRoseTest.kt b/Kotlin/src/test/kotlin/com/gildedrose/PlatinumRoseTest.kt deleted file mode 100644 index 2d8bea4f..00000000 --- a/Kotlin/src/test/kotlin/com/gildedrose/PlatinumRoseTest.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.gildedrose - -import com.gildedrose.PlatinumRose.Companion.AGED_BRIE -import com.gildedrose.PlatinumRose.Companion.BACKSTAGE_PASSES -import com.gildedrose.PlatinumRose.Companion.LULFURAS_HAND_OF_RAGNAROK -import com.gildedrose.PlatinumRose.Companion.MIN_QUALITY -import com.gildedrose.PlatinumRose.Companion.REGULAR_ITEM_MAX_QUALITY -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import java.util.* - -class PlatinumRoseTest { - - @Test - fun `should update quality for generated test cases and compare with GlidedRose`() { - val names = listOf( - AGED_BRIE, - BACKSTAGE_PASSES, - LULFURAS_HAND_OF_RAGNAROK, - "new none-existing on code name" - ) - val sellInRange = -100..100 - val qualityRange = MIN_QUALITY..REGULAR_ITEM_MAX_QUALITY - val allTestCases = generateTestCasesInRanger(names, sellInRange, qualityRange) - - - for (testCase in allTestCases) { - val platinumRose = PlatinumRose(listOf(Item(testCase.name, testCase.sellIn, testCase.quality))) - val gildedRose = GildedRose(listOf(Item(testCase.name, testCase.sellIn, testCase.quality))) - - platinumRose.updateQuality() - gildedRose.updateQuality() - - assertEquals(gildedRose.items, platinumRose.items) - } - } - - private fun generateTestCasesInRanger( - names: List, - sellInRange: IntRange, - qualityRange: IntRange - ): List { - val items = LinkedList() - for (name in names) { - for (sellIn in sellInRange) { - for (quality in qualityRange) { - items.add(Item(name, sellIn, quality)) - } - } - } - return items - } -} \ No newline at end of file diff --git a/Kotlin/src/test/kotlin/com/platinumrose/PlatinumRoseTestTemplate.kt b/Kotlin/src/test/kotlin/com/platinumrose/PlatinumRoseTestTemplate.kt new file mode 100644 index 00000000..e248623b --- /dev/null +++ b/Kotlin/src/test/kotlin/com/platinumrose/PlatinumRoseTestTemplate.kt @@ -0,0 +1,46 @@ +package com.platinumrose + +import com.gildedrose.GildedRose +import com.gildedrose.Item +import com.platinumrose.ItemConstant.Companion.MIN_QUALITY +import com.platinumrose.ItemConstant.Companion.REGULAR_ITEM_MAX_QUALITY +import org.junit.jupiter.api.Assertions.assertEquals +import java.util.* + +abstract class PlatinumRoseTestTemplate { + private val ITEMS_NAMES = listOf( + com.platinumrose.ItemType.AGED_BRIE.value!!, + com.platinumrose.ItemType.BACKSTAGE_PASSES.value!!, + com.platinumrose.ItemType.SULFURAS.value!!, + "new none-existing on code name" + ) + private val SELLIN_RANGE = -100..100 + private val QUALITY_RANGE = MIN_QUALITY..REGULAR_ITEM_MAX_QUALITY + + + fun generateTestCases(): List { + return generateTestCasesInRanger(ITEMS_NAMES, SELLIN_RANGE, QUALITY_RANGE) + } + + fun updateQualityAndCheckResult(gildedRose: GildedRose, simplePlatinumRose: Solution) { + simplePlatinumRose.updateQuality() + gildedRose.updateQuality() + assertEquals(gildedRose.items, simplePlatinumRose.items()) + } + + private fun generateTestCasesInRanger( + names: List, + sellInRange: IntRange, + qualityRange: IntRange + ): List { + val items = LinkedList() + for (name in names) { + for (sellIn in sellInRange) { + for (quality in qualityRange) { + items.add(Item(name, sellIn, quality)) + } + } + } + return items + } +} \ No newline at end of file diff --git a/Kotlin/src/test/kotlin/com/platinumrose/advance/AdvancePlatinumRoseTest.kt b/Kotlin/src/test/kotlin/com/platinumrose/advance/AdvancePlatinumRoseTest.kt new file mode 100644 index 00000000..24e8497f --- /dev/null +++ b/Kotlin/src/test/kotlin/com/platinumrose/advance/AdvancePlatinumRoseTest.kt @@ -0,0 +1,17 @@ +package com.platinumrose.advance + +import com.gildedrose.GildedRose +import com.gildedrose.Item +import com.platinumrose.PlatinumRoseTestTemplate +import org.junit.jupiter.api.Test + +class AdvancePlatinumRoseTest : PlatinumRoseTestTemplate() { + + @Test + fun `should update quality for generated test cases and compare with GlidedRose`() { + val allTestCases = generateTestCases() + val gildedRose = GildedRose(allTestCases.map { Item(it.name, it.sellIn, it.quality) }) + val simplePlatinumRose = AdvancePlatinumRose(allTestCases.map { Item(it.name, it.sellIn, it.quality) }) + updateQualityAndCheckResult(gildedRose, simplePlatinumRose) + } +} \ No newline at end of file diff --git a/Kotlin/src/test/kotlin/com/platinumrose/advance/factory/QualityCalculatorFactoryImplTest.kt b/Kotlin/src/test/kotlin/com/platinumrose/advance/factory/QualityCalculatorFactoryImplTest.kt new file mode 100644 index 00000000..e4a0435f --- /dev/null +++ b/Kotlin/src/test/kotlin/com/platinumrose/advance/factory/QualityCalculatorFactoryImplTest.kt @@ -0,0 +1,38 @@ +package com.platinumrose.advance.factory + +import com.platinumrose.ItemType +import com.platinumrose.advance.quality.AgedBrie +import com.platinumrose.advance.quality.BackstagePasses +import com.platinumrose.advance.quality.RegularItem +import com.platinumrose.advance.quality.Sulfuras +import org.junit.jupiter.api.Assertions.assertInstanceOf +import org.junit.jupiter.api.Test + +class QualityCalculatorFactoryImplTest { + + private val qualityCalculatorFactory = QualityCalculatorFactoryImpl() + + @Test + fun `should return expected calculator for AGED_BRIE`() { + val qualityCalculator = qualityCalculatorFactory.qualityCalculator(ItemType.AGED_BRIE) + assertInstanceOf(AgedBrie::class.java, qualityCalculator) + } + + @Test + fun `should return expected calculator for BACKSTAGE_PASSES`() { + val qualityCalculator = qualityCalculatorFactory.qualityCalculator(ItemType.BACKSTAGE_PASSES) + assertInstanceOf(BackstagePasses::class.java, qualityCalculator) + } + + @Test + fun `should return expected calculator for SULFURAS`() { + val qualityCalculator = qualityCalculatorFactory.qualityCalculator(ItemType.SULFURAS) + assertInstanceOf(Sulfuras::class.java, qualityCalculator) + } + + @Test + fun `should return expected calculator for any other`() { + val qualityCalculator = qualityCalculatorFactory.qualityCalculator(ItemType.REGULAR) + assertInstanceOf(RegularItem::class.java, qualityCalculator) + } +} \ No newline at end of file diff --git a/Kotlin/src/test/kotlin/com/platinumrose/advance/quality/AgedBrieTest.kt b/Kotlin/src/test/kotlin/com/platinumrose/advance/quality/AgedBrieTest.kt new file mode 100644 index 00000000..36457ce3 --- /dev/null +++ b/Kotlin/src/test/kotlin/com/platinumrose/advance/quality/AgedBrieTest.kt @@ -0,0 +1,38 @@ +package com.platinumrose.advance.quality + +import com.platinumrose.ItemConstant.Companion.REGULAR_ITEM_MAX_QUALITY +import com.platinumrose.ItemType +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import kotlin.random.Random + +class AgedBrieTest { + + private val Random = Random(Int.MAX_VALUE) + private val item = AgedBrie() + + @Test + fun `should return expected type`() { + assertEquals(item.type(), ItemType.AGED_BRIE) + } + + @Test + fun `should return expected max quality`() { + assertEquals(item.maxQuality(), REGULAR_ITEM_MAX_QUALITY) + } + + @Test + fun `should return -1 when calculate sell in decrease`() { + assertEquals(item.computeSellInDecrease(Random.nextInt()), -1) + } + + @Test + fun `should return 1 when calculate quality increase before sell in`() { + assertEquals(item.computeQualityIncreaseBeforeSellIn(Random.nextInt(), Random.nextInt()), 1) + } + + @Test + fun `should return 1 when calculate quality increase after sell in`() { + assertEquals(item.computeQualityIncreaseAfterSellIn(Random.nextInt(), Random.nextInt()), 1) + } +} \ No newline at end of file diff --git a/Kotlin/src/test/kotlin/com/platinumrose/advance/quality/BackstagePassesTest.kt b/Kotlin/src/test/kotlin/com/platinumrose/advance/quality/BackstagePassesTest.kt new file mode 100644 index 00000000..4a212f3e --- /dev/null +++ b/Kotlin/src/test/kotlin/com/platinumrose/advance/quality/BackstagePassesTest.kt @@ -0,0 +1,51 @@ +package com.platinumrose.advance.quality + +import com.platinumrose.ItemConstant.Companion.REGULAR_ITEM_MAX_QUALITY +import com.platinumrose.ItemType.BACKSTAGE_PASSES +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import kotlin.random.Random + +class BackstagePassesTest { + + private val Random = Random(0) + private val item = BackstagePasses() + + @Test + fun `should return expected type`() { + assertEquals(item.type(), BACKSTAGE_PASSES) + } + + @Test + fun `should return expected max quality`() { + assertEquals(item.maxQuality(), REGULAR_ITEM_MAX_QUALITY) + } + + @Test + fun `should return -1 when calculate sell in decrease`() { + assertEquals(item.computeSellInDecrease(Random.nextInt()), -1) + } + + @Test + fun `should return 1 when calculate quality increase before sell in and quality greater than 10`() { + assertEquals(item.computeQualityIncreaseBeforeSellIn(Random.nextInt(12, Int.MAX_VALUE), Random.nextInt()), 1) + } + + @Test + fun `should return 2 when calculate quality increase before sell in and quality between 6 and 10`() { + assertEquals(item.computeQualityIncreaseBeforeSellIn(6, Random.nextInt()), 2) + assertEquals(item.computeQualityIncreaseBeforeSellIn(10, Random.nextInt()), 2) + } + + @Test + fun `should return 3 when calculate quality increase before sell in and quality between 0 and 5`() { + assertEquals(item.computeQualityIncreaseBeforeSellIn(0, Random.nextInt()), 3) + assertEquals(item.computeQualityIncreaseBeforeSellIn(5, Random.nextInt()), 3) + } + + @Test + fun `should return negative quality when calculate quality increase after sell in`() { + val quality = Random.nextInt() + assertEquals(item.computeQualityIncreaseAfterSellIn(Random.nextInt(), quality), -quality) + } +} \ No newline at end of file diff --git a/Kotlin/src/test/kotlin/com/platinumrose/advance/quality/RegularItemTest.kt b/Kotlin/src/test/kotlin/com/platinumrose/advance/quality/RegularItemTest.kt new file mode 100644 index 00000000..cf567075 --- /dev/null +++ b/Kotlin/src/test/kotlin/com/platinumrose/advance/quality/RegularItemTest.kt @@ -0,0 +1,38 @@ +package com.platinumrose.advance.quality + +import com.platinumrose.ItemConstant +import com.platinumrose.ItemType +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import kotlin.random.Random + +class RegularItemTest { + + private val Random = Random(Int.MAX_VALUE) + private val item = RegularItem() + + @Test + fun `should return expected type`() { + assertEquals(item.type(), ItemType.REGULAR) + } + + @Test + fun `should return expected max quality`() { + assertEquals(item.maxQuality(), ItemConstant.REGULAR_ITEM_MAX_QUALITY) + } + + @Test + fun `should return -1 when calculate sell in decrease`() { + assertEquals(item.computeSellInDecrease(Random.nextInt()), -1) + } + + @Test + fun `should return -1 when calculate quality increase before sell in`() { + assertEquals(item.computeQualityIncreaseBeforeSellIn(Random.nextInt(), Random.nextInt()), -1) + } + + @Test + fun `should return -1 when calculate quality increase after sell in`() { + assertEquals(item.computeQualityIncreaseAfterSellIn(Random.nextInt(), Random.nextInt()), -1) + } +} \ No newline at end of file diff --git a/Kotlin/src/test/kotlin/com/platinumrose/advance/quality/SulfurasTest.kt b/Kotlin/src/test/kotlin/com/platinumrose/advance/quality/SulfurasTest.kt new file mode 100644 index 00000000..afe3ed77 --- /dev/null +++ b/Kotlin/src/test/kotlin/com/platinumrose/advance/quality/SulfurasTest.kt @@ -0,0 +1,38 @@ +package com.platinumrose.advance.quality + +import com.platinumrose.ItemConstant +import com.platinumrose.ItemType +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import kotlin.random.Random + +class SulfurasTest { + + private val Random = Random(Int.MAX_VALUE) + private val item = Sulfuras() + + @Test + fun `should return expected type`() { + assertEquals(item.type(), ItemType.SULFURAS) + } + + @Test + fun `should return expected max quality`() { + assertEquals(item.maxQuality(), ItemConstant.LEGENDARY_ITEM_MAX_QUALITY) + } + + @Test + fun `should return 0 when calculate sell in decrease`() { + assertEquals(item.computeSellInDecrease(Random.nextInt()), 0) + } + + @Test + fun `should return 0 when calculate quality increase before sell in`() { + assertEquals(item.computeQualityIncreaseBeforeSellIn(Random.nextInt(), Random.nextInt()), 0) + } + + @Test + fun `should return 0 when calculate quality increase after sell in`() { + assertEquals(item.computeQualityIncreaseAfterSellIn(Random.nextInt(), Random.nextInt()), 0) + } +} \ No newline at end of file diff --git a/Kotlin/src/test/kotlin/com/platinumrose/mid/MidPlatinumRoseTest.kt b/Kotlin/src/test/kotlin/com/platinumrose/mid/MidPlatinumRoseTest.kt new file mode 100644 index 00000000..8cb9ab17 --- /dev/null +++ b/Kotlin/src/test/kotlin/com/platinumrose/mid/MidPlatinumRoseTest.kt @@ -0,0 +1,18 @@ +package com.platinumrose.mid + +import com.gildedrose.GildedRose +import com.gildedrose.Item +import com.platinumrose.PlatinumRoseTestTemplate +import org.junit.jupiter.api.Test + + +class MidPlatinumRoseTest : PlatinumRoseTestTemplate() { + + @Test + fun `should update quality for generated test cases and compare with GlidedRose`() { + val allTestCases = generateTestCases() + val gildedRose = GildedRose(allTestCases.map { Item(it.name, it.sellIn, it.quality) }) + val solution = MidPlatinumRose(allTestCases.map { Item(it.name, it.sellIn, it.quality) }) + updateQualityAndCheckResult(gildedRose, solution) + } +} \ No newline at end of file diff --git a/Kotlin/src/test/kotlin/com/platinumrose/simple/SimplePlatinumRoseTest.kt b/Kotlin/src/test/kotlin/com/platinumrose/simple/SimplePlatinumRoseTest.kt new file mode 100644 index 00000000..f5acf1e9 --- /dev/null +++ b/Kotlin/src/test/kotlin/com/platinumrose/simple/SimplePlatinumRoseTest.kt @@ -0,0 +1,17 @@ +package com.platinumrose.simple + +import com.gildedrose.GildedRose +import com.gildedrose.Item +import com.platinumrose.PlatinumRoseTestTemplate +import org.junit.jupiter.api.Test + +class SimplePlatinumRoseTest : PlatinumRoseTestTemplate() { + + @Test + fun `should update quality for generated test cases and compare with GlidedRose`() { + val allTestCases = generateTestCases() + val gildedRose = GildedRose(allTestCases.map { Item(it.name, it.sellIn, it.quality) }) + val solution = SimplePlatinumRose(allTestCases.map { Item(it.name, it.sellIn, it.quality) }) + updateQualityAndCheckResult(gildedRose, solution) + } +} \ No newline at end of file