GildedRose-Refactoring-Kata/swift/Sources/GildedRose/Rules/QualityModificationRules.swift
2020-11-23 17:31:19 +01:00

107 lines
3.1 KiB
Swift

//
// 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,
conjured,
qualityIncreasesFasterBeforeExpireThenDropsToZero,
legendary
static func rule(for item: Item) -> RuleType {
if item.name.lowercased().contains("conjured") {
return .conjured
}
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 {
let newQuality: Int
switch self {
case .regular:
newQuality = regularRuleQuality(for: item)
case .increasesQuality:
newQuality = increasesQualityQuality(for: item)
case .qualityIncreasesFasterBeforeExpireThenDropsToZero:
newQuality = increasesFasterBeforeExpireThenDropsToZeroQuality(for: item)
case .legendary:
return item // Unmodified
case .conjured:
newQuality = conjuredRuleQuality(for: item)
}
return Self.modify(item: item, with: newQuality)
}
private func regularRuleQuality(for item: Item) -> Int {
let modification = Self.isRegularItemExpired(sellIn: item.sellIn) ? -2 : -1
return item.quality + modification
}
private func increasesQualityQuality(for item: Item) -> Int {
return item.quality + 1
}
private func increasesFasterBeforeExpireThenDropsToZeroQuality(for item: Item) -> Int {
switch item.sellIn {
case ...0:
return 0
case 0...5:
return item.quality + 3
case 5...10:
return item.quality + 2
case 10...:
return item.quality + 1
default:
fatalError("All values of `sellIn` should be covered")
}
}
private func conjuredRuleQuality(for item: Item) -> Int {
let modification = Self.isRegularItemExpired(sellIn: item.sellIn) ? -4 : -2
return item.quality + modification
}
public static func modify(item: Item, with newQuality: Int) -> Item {
let correctedQuality = applyQualityThresholds(to: newQuality)
return Item(name: item.name, sellIn: item.sellIn, quality: correctedQuality)
}
public static func applyQualityThresholds(to quality: Int) -> Int {
switch quality {
case ...0:
return 0
case 0...50:
return quality
case 50...:
return 50
default:
fatalError("All values of `quality` should be covered")
}
}
public static func isRegularItemExpired(sellIn: Int) -> Bool {
return sellIn <= 0
}
}