Skip to content

Instantly share code, notes, and snippets.

@gxespino
Last active December 8, 2016 07:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gxespino/9062f4d059666a1541663880e2073f0a to your computer and use it in GitHub Desktop.
Save gxespino/9062f4d059666a1541663880e2073f0a to your computer and use it in GitHub Desktop.
class CheckoutMachine
PRODUCT_LIST = {
123 => { product: :chips, price: 200 },
456 => { product: :salsa, price: 100 },
789 => { product: :wine, price: 1000 },
111 => { product: :cigarettes, price: 550 },
000 => { product: :bonus_card, price: nil }
}
def initialize
@balance ||= Balance.new
@counter ||= Counter.new
end
def scan(sku)
price = Scanner.scan(sku)
balance.add(price)
counter.increment(sku)
Discounter.apply_any_discounts(
sku: sku,
counter: counter,
balance: balance
)
end
def total
balance.total
end
private
attr_reader :balance, :counter, :discounter
end
# Scans items and returns item price from PriceList
class Scanner
def self.scan(sku)
CheckoutMachine::PRODUCT_LIST[sku][:price]
end
end
# Keeps track of what has been scanned
class Counter
def increment(sku)
products_and_counts[sku_to_product(sku)] += 1
end
def product_count(product)
@products_and_counts[product]
end
private
def products_and_counts
@products_and_counts ||= CheckoutMachine::PRODUCT_LIST
.each_with_object({}) { |product, memo| memo[product[1][:product]] = 0 }
end
def sku_to_product(sku)
CheckoutMachine::PRODUCT_LIST[sku][:product]
end
end
# Maintains state of total
class Balance
attr_accessor :total
def initialize
@total = 0
end
def add(amount)
self.total += amount.to_i
end
def subtract(amount)
self.total -= amount.to_i
end
end
class Discounter
def self.apply_any_discounts(sku:, counter:, balance:)
@@sku, @@counter, @@balance = sku, counter, balance
apply_bonus_card_discounts if bonus_card_scanned?
end
private
def self.apply_bonus_card_discounts
@@balance.subtract(salsa_discount)
@@balance.subtract(chips_discount)
end
def self.salsa_discount
50 * @@counter.product_count(:salsa)
end
def self.chips_discount
200 * (@@counter.product_count(:chips)/3).floor
end
def self.bonus_card_scanned?
CheckoutMachine::PRODUCT_LIST[@@sku][:product] == :bonus_card
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment