Skip to content

Instantly share code, notes, and snippets.

@suzukimilanpaak
Created June 29, 2010 13:37
Show Gist options
  • Save suzukimilanpaak/457229 to your computer and use it in GitHub Desktop.
Save suzukimilanpaak/457229 to your computer and use it in GitHub Desktop.
# This is a code snippet for my exercise on Lambda and Proc.
# Let's say there is a supermarket which sells only three products bellow.
# Product Code | Name | Price
# FR1 | Fruit Tea | £3.11
# SR1 | Strawberries| £5.00
# CF1 | Coffee | £11.23
# - It offers buy-one-get-one-free for fruit tea.
# - It offers strawberries to get a price discount for bulk purchases. If you buy 3 or more strawberries, the price should drop to £4.50.
# - The check-out can scan items in any order, and the pricing rule needs to be flexible regarding responding to changeable demands. Thus, logic for it should be separated from products data source(Item class).
# To test, you just need to run this command; $ spec checkout.rb
# Items
class Item
attr_accessor :product_code, :name, :price, :dropped_price
def initialize(product_code, name, price, dropped_price = nil)
@product_code, @name, @price, @dropped_price = product_code, name, price, dropped_price
end
end
# Pricing rules
rule4fruit_tea = lambda do |items|
if items.length > 1
items[0].price * (items.length / 2) + items[0].price * (items.length % 2)
else
items[0].price * items.length
end
end
rule4strawberries = lambda do |items|
if items.length >= 3
items[0].dropped_price * items.length
else
items[0].price * items.length
end
end
$pricing_rules = {:FR1 => rule4fruit_tea, :SR1 => rule4strawberries}
class Checkout
def initialize(pricing_rules)
@pricing_rules = pricing_rules
@basket = {}
end
# Push an item into an array sorting out by its product code in hash table called @basket.
# Inside of @basket is like this;
# {:FR1=>[#<Item:0x8d6a2b0 @discounted_price=nil, @price=3.11, @product_code="FR1", @name="Fruit tea">,
# #<Item:0x8d6a2b0 @discounted_price=nil, @price=3.11, @product_code="FR1", @name="Fruit tea">],
# :SR1=>[#<Item:0x8d6a224 @discounted_price=nil, @price=5, @product_code="SR1"]}
def scan(item)
(@basket[item.product_code.to_sym] ||= []) << item
end
def total
total = 0
@basket.each do |key, items|
# if a pricing rule is defined for the type of items
if @pricing_rules.key? key
total += @pricing_rules[key].call(items)
else
total += items[0].price * items.length
end
end
total
end
end
#__
fruit_tea = Item.new("FR1", "Fruit tea", 3.11)
strawberries = Item.new("SR1", "Strowberries", 5, 4.5)
coffee = Item.new("CF1", "Coffee", 11.23)
describe Checkout, "when there are 2 fruit teas in a basket" do
before do
@co = Checkout.new($pricing_rules)
[fruit_tea, fruit_tea].each{|item| @co.scan(item)}
end
it "should be £3.11 in total" do
@co.total.should == 3.11
end
after do
@co = nil
end
end
describe Checkout, "when there are 3 fruit teas, 1 pack of strawberries and 1 coffee in a basket" do
before do
@co = Checkout.new($pricing_rules)
[fruit_tea, strawberries, fruit_tea, fruit_tea, coffee].each{|item| @co.scan(item)}
end
it "should be £22.45 in total" do
@co.total.should == 22.45
end
after do
@co = nil
end
end
describe Checkout, "when there are 3 packs of strawberries and 1 fruit tea in a basket" do
before do
@co = Checkout.new($pricing_rules)
[strawberries, strawberries, fruit_tea, strawberries].each{|item| @co.scan(item)}
end
it "should be £16.61 in total" do
@co.total.should == 16.61
end
after do
@co = nil
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment