Replaced all quality modification rules with a new enum rule based on a protocol

This commit is contained in:
Lucas van Dongen 2020-11-23 17:05:35 +01:00
parent 6323c90d96
commit 8f15db659d
5 changed files with 175 additions and 43 deletions

View File

@ -7,53 +7,29 @@ public class GildedRose {
public func updateQuality() {
for i in 0..<items.count {
if (items[i].name != "Aged Brie" && 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 {
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
// }
// }
// }
}
}
}

View File

@ -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
}
}

View File

@ -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)
}
}

View File

@ -13,6 +13,6 @@ extension Item {
let system = GildedRose(items: [self])
system.updateQuality()
return self.quality == quality
return system.items.first?.quality == quality
}
}

View File

@ -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() {
}
}