Created
June 29, 2010 13:37
-
-
Save suzukimilanpaak/457229 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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