Skip to content

Instantly share code, notes, and snippets.

@thexande
Created April 10, 2020 22:15
Show Gist options
  • Save thexande/33a91ee42dc2e07ed5ada6001fabc7ba to your computer and use it in GitHub Desktop.
Save thexande/33a91ee42dc2e07ed5ada6001fabc7ba to your computer and use it in GitHub Desktop.
A coffee machine implementation using swift.
protocol ResourcesContaining {
var beans: Double { get set }
var milk: Double { get set }
var water: Double { get set }
func hasRequiredResources(for resourceSet: [Resource]) -> Bool
}
extension ResourcesContaining {
func hasRequiredResources(for resourceSet: [Resource]) -> Bool {
var currentBeans = self.beans
var currentMilk = self.milk
var currentWater = self.milk
resourceSet.forEach {
switch $0 {
case .beans(let ounces):
currentBeans -= ounces
case .milk(let ounces):
currentMilk -= ounces
case .water(let ounces):
currentWater -= ounces
}
}
return currentBeans > 0 && currentMilk > 0 && currentWater > 0
}
}
enum MachineState {
case ready
case vending
case requiresResources
}
protocol MachineStateProviding {
var resourceStore: ResourcesContaining { get set }
var state: MachineState { get set }
}
final class ResourceStore: ResourcesContaining {
var beans: Double = 0
var milk: Double = 0
var water: Double = 0
}
enum Size: Double {
case small = 8
case medium = 12
case large = 16
}
enum Style {
case espresso
case coffee
case late
}
struct Recipie {
let resources: [Resource]
let style: Style
let size: Size
}
struct Drink {
let ounces: Double
let style: Style
let size: Size
}
enum Resource {
case milk(ounces: Double)
case beans(ounces: Double)
case water(ounces: Double)
}
final class Machine: MachineStateProviding {
var resourceStore: ResourcesContaining = ResourceStore()
var state: MachineState = .ready
}
protocol DrinkProducing {
func make(recipie: Recipie) -> Drink
}
enum DrinkError: Error {
case notEnoughResources
}
extension DrinkProducing where Self: MachineStateProviding {
mutating func make(recipie: Recipie) -> Result<Drink, DrinkError> {
state = .vending
guard resourceStore.hasRequiredResources(for: recipie.resources) else {
return .failure(.notEnoughResources)
}
var totalOunces: Double = 0
for resource in recipie.resources {
switch resource {
case .milk(let ounces):
resourceStore.milk -= ounces
totalOunces += ounces
case .beans(let ounces):
resourceStore.beans -= ounces
totalOunces += ounces
case .water(let ounces):
resourceStore.water -= ounces
totalOunces += ounces
}
}
return .success(.init(ounces: totalOunces,
style: recipie.style,
size: recipie.size))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment