diff --git a/swift/Sources/GildedRose/GildedRose.swift b/swift/Sources/GildedRose/GildedRose.swift index 9b975467..7a95040c 100644 --- a/swift/Sources/GildedRose/GildedRose.swift +++ b/swift/Sources/GildedRose/GildedRose.swift @@ -7,53 +7,29 @@ public class GildedRose { public func updateQuality() { for i in 0.. 0) { - if (items[i].name != "Sulfuras, Hand of Ragnaros") { - items[i].quality = items[i].quality - 1 - } - } - } else { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1 - - if (items[i].name == "Backstage passes to a TAFKAL80ETC concert") { - if (items[i].sellIn < 11) { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1 - } - } - - if (items[i].sellIn < 6) { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1 - } - } - } - } - } + items[i] = QualityModificationRule.process(item: items[i]) if (items[i].name != "Sulfuras, Hand of Ragnaros") { items[i].sellIn = items[i].sellIn - 1 } - if (items[i].sellIn < 0) { - if (items[i].name != "Aged Brie") { - if (items[i].name != "Backstage passes to a TAFKAL80ETC concert") { - if (items[i].quality > 0) { - if (items[i].name != "Sulfuras, Hand of Ragnaros") { - items[i].quality = items[i].quality - 1 - } - } - } else { - items[i].quality = items[i].quality - items[i].quality - } - } else { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1 - } - } - } +// if (items[i].sellIn < 0) { +// if (items[i].name != "Aged Brie") { +// if (items[i].name != "Backstage passes to a TAFKAL80ETC concert") { +// if (items[i].quality > 0) { +// if (items[i].name != "Sulfuras, Hand of Ragnaros") { +// items[i].quality = items[i].quality - 1 +// } +// } +// } else { +// items[i].quality = items[i].quality - items[i].quality +// } +// } else { +// if (items[i].quality < 50) { +// items[i].quality = items[i].quality + 1 +// } +// } +// } } } } diff --git a/swift/Sources/GildedRose/Rules/QualityModificationRules.swift b/swift/Sources/GildedRose/Rules/QualityModificationRules.swift new file mode 100644 index 00000000..180e5b6a --- /dev/null +++ b/swift/Sources/GildedRose/Rules/QualityModificationRules.swift @@ -0,0 +1,95 @@ +// +// QualityModificationRule.swift +// +// +// Created by Lucas van Dongen on 23/11/2020. +// + +import Foundation + +// These rules are really simple, you could handle more complex ones within their own class +enum QualityModificationRule: Rule { + typealias RuleType = Self + + case regular, + increasesQuality, + qualityIncreasesFasterBeforeExpireThenDropsToZero, + legendary + + static func rule(for item: Item) -> RuleType { + switch item.name { + case "Aged Brie": + return .increasesQuality + case "Backstage passes to a TAFKAL80ETC concert": + return .qualityIncreasesFasterBeforeExpireThenDropsToZero + case "Sulfuras, Hand of Ragnaros": + return .legendary + default: + return .regular + } + } + + func apply(to item: Item) -> Item { + switch self { + case .regular: + return applyRegularRule(to: item) + case .increasesQuality: + return applyIncreasesQualityRule(to: item) + case .qualityIncreasesFasterBeforeExpireThenDropsToZero: + return qualityIncreasesFasterBeforeExpireThenDropsToZeroRule(to: item) + case .legendary: + return applyLegendaryRule(to: item) + } + } + + private func applyRegularRule(to item: Item) -> Item { + let modification = Self.isRegularItemExpired(sellIn: item.sellIn) ? -2 : -1 + return Self.applyQualityThresholds(to: item, newQuality: item.quality + modification) + } + + private func applyIncreasesQualityRule(to item: Item) -> Item { + Self.applyQualityThresholds(to: item, newQuality: item.quality + 1) + } + + private func qualityIncreasesFasterBeforeExpireThenDropsToZeroRule(to item: Item) -> Item { + let newQuality: Int + switch item.sellIn { + case ...0: + newQuality = 0 + case 0...5: + newQuality = item.quality + 3 + case 5...10: + newQuality = item.quality + 2 + case 10...: + newQuality = item.quality + 1 + default: + fatalError("All values of `sellIn` should be covered") + } + + return Self.applyQualityThresholds(to: item, newQuality: newQuality) + } + + private func applyLegendaryRule(to item: Item) -> Item { + return item // No change + } + + public static func applyQualityThresholds(to item: Item, newQuality: Int) -> Item { + let correctedQuality: Int + switch newQuality { + case ...0: + correctedQuality = 0 + case 0...50: + correctedQuality = newQuality + case 50...: + correctedQuality = 50 + default: + fatalError("All values of `quality` should be covered") + } + + return Item(name: item.name, sellIn: item.sellIn, quality: correctedQuality) + } + + public static func isRegularItemExpired(sellIn: Int) -> Bool { + return sellIn <= 0 + } +} diff --git a/swift/Sources/GildedRose/Rules/Rule.swift b/swift/Sources/GildedRose/Rules/Rule.swift new file mode 100644 index 00000000..d1e7a739 --- /dev/null +++ b/swift/Sources/GildedRose/Rules/Rule.swift @@ -0,0 +1,23 @@ +// +// File.swift +// +// +// Created by Lucas van Dongen on 23/11/2020. +// + +import Foundation + +protocol Rule { + associatedtype RuleType: Rule + + func apply(to item: Item) -> Item + + static func rule(for item: Item) -> RuleType + static func process(item: Item) -> Item +} + +extension Rule { + static func process(item: Item) -> Item { + return rule(for: item).apply(to: item) + } +} diff --git a/swift/Tests/GildedRoseTests/TestItem.swift b/swift/Tests/GildedRoseTests/TestItem.swift index 5f6c3b2b..169aff0e 100644 --- a/swift/Tests/GildedRoseTests/TestItem.swift +++ b/swift/Tests/GildedRoseTests/TestItem.swift @@ -13,6 +13,6 @@ extension Item { let system = GildedRose(items: [self]) system.updateQuality() - return self.quality == quality + return system.items.first?.quality == quality } } diff --git a/swift/Tests/GildedRoseTests/TestQualityModificationRules.swift b/swift/Tests/GildedRoseTests/TestQualityModificationRules.swift new file mode 100644 index 00000000..211076f4 --- /dev/null +++ b/swift/Tests/GildedRoseTests/TestQualityModificationRules.swift @@ -0,0 +1,38 @@ +// +// TestSellInModificationRule.swift +// GildedRose +// +// Created by Lucas van Dongen on 23/11/2020. +// + +@testable import GildedRose +import XCTest + +class TestSellInModificationRule: XCTestCase { + private let regularItem = Item(name: "Regular Item", sellIn: 1, quality: 5) + private let backstagePassesItem = Item(name: "Backstage passes to a TAFKAL80ETC concert", sellIn: 1, quality: 0) + private let brieItem = Item(name: "Aged Brie", sellIn: 2, quality: 0) + private let sulfuras = Item(name: "Sulfuras, Hand of Ragnaros", sellIn: 0, quality: 50) + + //- All items have a SellIn value which denotes the number of days we have to sell the item + func testRuleSelection() { + XCTAssertEqual(QualityModificationRule.rule(for: regularItem), .regular) + XCTAssertEqual(QualityModificationRule.rule(for: backstagePassesItem), .qualityIncreasesFasterBeforeExpireThenDropsToZero) + XCTAssertEqual(QualityModificationRule.rule(for: brieItem), .increasesQuality) + XCTAssertEqual(QualityModificationRule.rule(for: sulfuras), .legendary) + } + + func testApplyQualityThresholds() { + let tooLow = Item(name: "Too low", sellIn: 0, quality: 0) + let tooHigh = Item(name: "Too high", sellIn: 0, quality: 50) + let unaltered = Item(name: "Too low", sellIn: 0, quality: 25) + + XCTAssertEqual(QualityModificationRule.applyQualityThresholds(to: tooLow, newQuality: -1).quality, 0) + XCTAssertEqual(QualityModificationRule.applyQualityThresholds(to: tooHigh, newQuality: 51).quality, 50) + XCTAssertEqual(QualityModificationRule.applyQualityThresholds(to: unaltered, newQuality: 24).quality, 24) + } + + func testIsRegularItemExpired() { + + } +}