Решение на Трета задача от Ивайло Сачански

Обратно към всички решения

Към профила на Ивайло Сачански

Резултати

  • 4 точки от тестове
  • 0 бонус точки
  • 4 точки общо
  • 12 успешни тест(а)
  • 7 неуспешни тест(а)

Код

require 'bigdecimal'
require 'bigdecimal/util'
class PromotionFactory
def PromotionFactory.make_promotion promotion
type = promotion.keys[0]
arguments = promotion.values[0]
case type
when :get_one_free
return GetOneFreePromotion.new arguments
when :package
return PackagePromotion.new arguments
when :threshold
return ThresholdPromotion.new arguments
end
end
end
class AbstractPromotion
def get_discount count, price
raise "Unimplemented method exception."
end
end
class GetOneFreePromotion < AbstractPromotion
def initialize number
@number_per_free = number
end
def get_discount count, price
(count / @number_per_free) * price.to_d
end
end
class PackagePromotion < AbstractPromotion
def initialize discount
@discount_per_number = discount
end
def get_discount count, price
(count - count.remainder(@discount_per_number.keys[0])) *
((price.to_d * @discount_per_number.values[0] ) / 100)
end
end
class ThresholdPromotion < AbstractPromotion
def initialize discount
@discount_after_number = discount
end
def get_discount count, price
p count
p Float(@discount_after_number.keys[0])
p Float (@discount_after_number.values[0])
p price
if count > @discount_after_number.keys[0]
return (count - @discount_after_number.keys[0]) *
((price.to_d * @discount_after_number.values[0])/ 100)
end
return 0
end
end
class Product
attr_accessor :name
attr_accessor :price
attr_accessor :promotion
def initialize product, price, promotion
@name = product
@price = price
if promotion
@promotion = PromotionFactory.make_promotion promotion
end
end
def == other
@name == other
end
def calculate_price count
if promotion
count * @price.to_d - (@promotion.get_discount count, @price)
else
count * @price.to_d
end
end
end
class Inventory
def initialize
@products = []
@coupons = {}
end
def register product, price, promotion = nil
float_price = Float price
if (@products.include? product) || float_price < 0.01 ||
float_price > 999.99 || product.size > 40
raise "Illegal argument exception."
end
@products << (Product.new product, price, promotion)
end
def register_coupon name, data
@coupons[name] = data
end
def new_cart
@cart = Cart.new @products, @coupons
end
end
class Cart
def initialize products, coupons
@items = {}
@has_coupon = false
@available_products = products
@coupons = coupons
@invoice = ""
end
def add product, count = 1
if (!@available_products.include? product) || (!(0..99).include? count)
raise "Illegal argument exception."
end
@items[product] = count + (@items.fetch product, 0)
end
def use coupon
if @coupons[coupon]
@has_coupon = true
@coupon = @coupons[coupon]
end
end
def total
result = 0
@items.each do |k, v|
result += @available_products[@available_products.index k].calculate_price v
end
if @has_coupon
result = use_coupon @coupon, result
end
if result < 0 then result = 0 end
result
end
def invoice
"Did not have time for this :("
end
private
def use_coupon coupon, price
if coupon.keys[0] == :percent
return price = (price * (100 - coupon.values[0])) / 100
elsif coupon.keys[0] == :amount
return price -= coupon.values[0].to_d
end
end
end

Лог от изпълнението

..F..F..F8
5.0
10.0
"2.00"
.8
10.0
20.0
"1.00"
10
10.0
20.0
"1.00"
15
10.0
20.0
"1.00"
.F..F..FF

Failures:

  1) Inventory with no discounts can print an invoice
     Failure/Error: cart.invoice.should eq <<INVOICE
       
       expected: "+------------------------------------------------+----------+\n| Name                                       qty |    price |\n+------------------------------------------------+----------+\n| Green Tea                                    1 |     0.79 |\n| Earl Grey                                    3 |     2.97 |\n| Black Coffee                                 2 |     3.98 |\n+------------------------------------------------+----------+\n| TOTAL                                          |     7.74 |\n+------------------------------------------------+----------+\n"
            got: "Did not have time for this :("
       
       (compared using ==)
       
       Diff:
       @@ -1,10 +1,2 @@
       -+------------------------------------------------+----------+
       -| Name                                       qty |    price |
       -+------------------------------------------------+----------+
       -| Green Tea                                    1 |     0.79 |
       -| Earl Grey                                    3 |     2.97 |
       -| Black Coffee                                 2 |     3.98 |
       -+------------------------------------------------+----------+
       -| TOTAL                                          |     7.74 |
       -+------------------------------------------------+----------+
       +Did not have time for this :(
     # /tmp/d20111115-5847-15w9ycu/spec.rb:73:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) Inventory with a 'buy X, get one free' promotion shows the discount in the invoice
     Failure/Error: cart.invoice.should eq <<INVOICE
       
       expected: "+------------------------------------------------+----------+\n| Name                                       qty |    price |\n+------------------------------------------------+----------+\n| Green Tea                                    3 |     3.00 |\n|   (buy 2, get 1 free)                          |    -1.00 |\n| Red Tea                                      8 |    16.00 |\n|   (buy 4, get 1 free)                          |    -2.00 |\n+------------------------------------------------+----------+\n| TOTAL                                          |    16.00 |\n+------------------------------------------------+----------+\n"
            got: "Did not have time for this :("
       
       (compared using ==)
       
       Diff:
       @@ -1,11 +1,2 @@
       -+------------------------------------------------+----------+
       -| Name                                       qty |    price |
       -+------------------------------------------------+----------+
       -| Green Tea                                    3 |     3.00 |
       -|   (buy 2, get 1 free)                          |    -1.00 |
       -| Red Tea                                      8 |    16.00 |
       -|   (buy 4, get 1 free)                          |    -2.00 |
       -+------------------------------------------------+----------+
       -| TOTAL                                          |    16.00 |
       -+------------------------------------------------+----------+
       +Did not have time for this :(
     # /tmp/d20111115-5847-15w9ycu/spec.rb:111:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) Inventory with a '% off for every n' promotion shows the discount in the invoice
     Failure/Error: cart.invoice.should eq <<INVOICE
       
       expected: "+------------------------------------------------+----------+\n| Name                                       qty |    price |\n+------------------------------------------------+----------+\n| Green Tea                                    4 |     4.00 |\n|   (get 10% off for every 4)                    |    -0.40 |\n| Red Tea                                      8 |    16.00 |\n|   (get 20% off for every 5)                    |    -2.00 |\n+------------------------------------------------+----------+\n| TOTAL                                          |    17.60 |\n+------------------------------------------------+----------+\n"
            got: "Did not have time for this :("
       
       (compared using ==)
       
       Diff:
       @@ -1,11 +1,2 @@
       -+------------------------------------------------+----------+
       -| Name                                       qty |    price |
       -+------------------------------------------------+----------+
       -| Green Tea                                    4 |     4.00 |
       -|   (get 10% off for every 4)                    |    -0.40 |
       -| Red Tea                                      8 |    16.00 |
       -|   (get 20% off for every 5)                    |    -2.00 |
       -+------------------------------------------------+----------+
       -| TOTAL                                          |    17.60 |
       -+------------------------------------------------+----------+
       +Did not have time for this :(
     # /tmp/d20111115-5847-15w9ycu/spec.rb:154:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) Inventory with a '% off of every item after the nth' promotion shows the discount in the ivnoice
     Failure/Error: cart.invoice.should eq <<INVOICE
       
       expected: "+------------------------------------------------+----------+\n| Name                                       qty |    price |\n+------------------------------------------------+----------+\n| Green Tea                                   12 |    12.00 |\n|   (10% off of every after the 10th)            |    -0.20 |\n| Red Tea                                     20 |    40.00 |\n|   (20% off of every after the 15th)            |    -2.00 |\n+------------------------------------------------+----------+\n| TOTAL                                          |    49.80 |\n+------------------------------------------------+----------+\n"
            got: "Did not have time for this :("
       
       (compared using ==)
       
       Diff:
       @@ -1,11 +1,2 @@
       -+------------------------------------------------+----------+
       -| Name                                       qty |    price |
       -+------------------------------------------------+----------+
       -| Green Tea                                   12 |    12.00 |
       -|   (10% off of every after the 10th)            |    -0.20 |
       -| Red Tea                                     20 |    40.00 |
       -|   (20% off of every after the 15th)            |    -2.00 |
       -+------------------------------------------------+----------+
       -| TOTAL                                          |    49.80 |
       -+------------------------------------------------+----------+
       +Did not have time for this :(
     # /tmp/d20111115-5847-15w9ycu/spec.rb:197:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  5) Inventory with a '% off' coupon shows the discount in the invoice
     Failure/Error: cart.invoice.should eq <<INVOICE
       
       expected: "+------------------------------------------------+----------+\n| Name                                       qty |    price |\n+------------------------------------------------+----------+\n| Green Tea                                   10 |    10.00 |\n| Coupon TEA-TIME - 20% off                      |    -2.00 |\n+------------------------------------------------+----------+\n| TOTAL                                          |     8.00 |\n+------------------------------------------------+----------+\n"
            got: "Did not have time for this :("
       
       (compared using ==)
       
       Diff:
       @@ -1,9 +1,2 @@
       -+------------------------------------------------+----------+
       -| Name                                       qty |    price |
       -+------------------------------------------------+----------+
       -| Green Tea                                   10 |    10.00 |
       -| Coupon TEA-TIME - 20% off                      |    -2.00 |
       -+------------------------------------------------+----------+
       -| TOTAL                                          |     8.00 |
       -+------------------------------------------------+----------+
       +Did not have time for this :(
     # /tmp/d20111115-5847-15w9ycu/spec.rb:240:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  6) Inventory with an 'amount off' coupon shows the discount in the invoice
     Failure/Error: cart.invoice.should eq <<INVOICE
       
       expected: "+------------------------------------------------+----------+\n| Name                                       qty |    price |\n+------------------------------------------------+----------+\n| Green Tea                                    5 |     5.00 |\n| Coupon TEA-TIME - 10.00 off                    |    -5.00 |\n+------------------------------------------------+----------+\n| TOTAL                                          |     0.00 |\n+------------------------------------------------+----------+\n"
            got: "Did not have time for this :("
       
       (compared using ==)
       
       Diff:
       @@ -1,9 +1,2 @@
       -+------------------------------------------------+----------+
       -| Name                                       qty |    price |
       -+------------------------------------------------+----------+
       -| Green Tea                                    5 |     5.00 |
       -| Coupon TEA-TIME - 10.00 off                    |    -5.00 |
       -+------------------------------------------------+----------+
       -| TOTAL                                          |     0.00 |
       -+------------------------------------------------+----------+
       +Did not have time for this :(
     # /tmp/d20111115-5847-15w9ycu/spec.rb:281:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  7) Inventory with multiple discounts can print an invoice
     Failure/Error: cart.invoice.should eq <<INVOICE
       
       expected: "+------------------------------------------------+----------+\n| Name                                       qty |    price |\n+------------------------------------------------+----------+\n| Green Tea                                    8 |    22.32 |\n|   (buy 1, get 1 free)                          |   -11.16 |\n| Black Coffee                                 5 |    14.95 |\n|   (get 20% off for every 2)                    |    -2.39 |\n| Milk                                         5 |     8.95 |\n|   (30% off of every after the 3rd)             |    -1.07 |\n| Cereal                                       3 |     7.47 |\n| Coupon BREAKFAST - 10% off                     |    -3.91 |\n+------------------------------------------------+----------+\n| TOTAL                                          |    35.16 |\n+------------------------------------------------+----------+\n"
            got: "Did not have time for this :("
       
       (compared using ==)
       
       Diff:
       @@ -1,15 +1,2 @@
       -+------------------------------------------------+----------+
       -| Name                                       qty |    price |
       -+------------------------------------------------+----------+
       -| Green Tea                                    8 |    22.32 |
       -|   (buy 1, get 1 free)                          |   -11.16 |
       -| Black Coffee                                 5 |    14.95 |
       -|   (get 20% off for every 2)                    |    -2.39 |
       -| Milk                                         5 |     8.95 |
       -|   (30% off of every after the 3rd)             |    -1.07 |
       -| Cereal                                       3 |     7.47 |
       -| Coupon BREAKFAST - 10% off                     |    -3.91 |
       -+------------------------------------------------+----------+
       -| TOTAL                                          |    35.16 |
       -+------------------------------------------------+----------+
       +Did not have time for this :(
     # /tmp/d20111115-5847-15w9ycu/spec.rb:309:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.5721 seconds
19 examples, 7 failures

Failed examples:

rspec /tmp/d20111115-5847-15w9ycu/spec.rb:64 # Inventory with no discounts can print an invoice
rspec /tmp/d20111115-5847-15w9ycu/spec.rb:104 # Inventory with a 'buy X, get one free' promotion shows the discount in the invoice
rspec /tmp/d20111115-5847-15w9ycu/spec.rb:147 # Inventory with a '% off for every n' promotion shows the discount in the invoice
rspec /tmp/d20111115-5847-15w9ycu/spec.rb:190 # Inventory with a '% off of every item after the nth' promotion shows the discount in the ivnoice
rspec /tmp/d20111115-5847-15w9ycu/spec.rb:233 # Inventory with a '% off' coupon shows the discount in the invoice
rspec /tmp/d20111115-5847-15w9ycu/spec.rb:274 # Inventory with an 'amount off' coupon shows the discount in the invoice
rspec /tmp/d20111115-5847-15w9ycu/spec.rb:295 # Inventory with multiple discounts can print an invoice

История (1 версия и 0 коментара)

Ивайло обнови решението на 07.11.2011 16:49 (преди около 13 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class PromotionFactory
+ def PromotionFactory.make_promotion promotion
+ type = promotion.keys[0]
+ arguments = promotion.values[0]
+ case type
+ when :get_one_free
+ return GetOneFreePromotion.new arguments
+ when :package
+ return PackagePromotion.new arguments
+ when :threshold
+ return ThresholdPromotion.new arguments
+ end
+ end
+end
+
+class AbstractPromotion
+ def get_discount count, price
+ raise "Unimplemented method exception."
+ end
+end
+
+class GetOneFreePromotion < AbstractPromotion
+ def initialize number
+ @number_per_free = number
+ end
+
+ def get_discount count, price
+ (count / @number_per_free) * price.to_d
+ end
+end
+
+class PackagePromotion < AbstractPromotion
+ def initialize discount
+ @discount_per_number = discount
+ end
+
+ def get_discount count, price
+ (count - count.remainder(@discount_per_number.keys[0])) *
+ ((price.to_d * @discount_per_number.values[0] ) / 100)
+ end
+end
+
+class ThresholdPromotion < AbstractPromotion
+ def initialize discount
+ @discount_after_number = discount
+ end
+
+ def get_discount count, price
+ p count
+ p Float(@discount_after_number.keys[0])
+ p Float (@discount_after_number.values[0])
+ p price
+ if count > @discount_after_number.keys[0]
+ return (count - @discount_after_number.keys[0]) *
+ ((price.to_d * @discount_after_number.values[0])/ 100)
+ end
+ return 0
+ end
+end
+
+class Product
+ attr_accessor :name
+ attr_accessor :price
+ attr_accessor :promotion
+
+ def initialize product, price, promotion
+ @name = product
+ @price = price
+ if promotion
+ @promotion = PromotionFactory.make_promotion promotion
+ end
+ end
+
+ def == other
+ @name == other
+ end
+
+ def calculate_price count
+ if promotion
+ count * @price.to_d - (@promotion.get_discount count, @price)
+ else
+ count * @price.to_d
+ end
+ end
+end
+
+class Inventory
+ def initialize
+ @products = []
+ @coupons = {}
+ end
+
+ def register product, price, promotion = nil
+ float_price = Float price
+ if (@products.include? product) || float_price < 0.01 ||
+ float_price > 999.99 || product.size > 40
+ raise "Illegal argument exception."
+ end
+ @products << (Product.new product, price, promotion)
+ end
+
+ def register_coupon name, data
+ @coupons[name] = data
+ end
+
+ def new_cart
+ @cart = Cart.new @products, @coupons
+ end
+end
+
+class Cart
+ def initialize products, coupons
+ @items = {}
+ @has_coupon = false
+ @available_products = products
+ @coupons = coupons
+ @invoice = ""
+ end
+
+ def add product, count = 1
+ if (!@available_products.include? product) || (!(0..99).include? count)
+ raise "Illegal argument exception."
+ end
+
+ @items[product] = count + (@items.fetch product, 0)
+ end
+
+ def use coupon
+ if @coupons[coupon]
+ @has_coupon = true
+ @coupon = @coupons[coupon]
+ end
+ end
+
+ def total
+ result = 0
+
+ @items.each do |k, v|
+ result += @available_products[@available_products.index k].calculate_price v
+ end
+ if @has_coupon
+ result = use_coupon @coupon, result
+ end
+ if result < 0 then result = 0 end
+ result
+ end
+
+ def invoice
+ "Did not have time for this :("
+ end
+
+ private
+
+ def use_coupon coupon, price
+ if coupon.keys[0] == :percent
+ return price = (price * (100 - coupon.values[0])) / 100
+ elsif coupon.keys[0] == :amount
+ return price -= coupon.values[0].to_d
+ end
+ end
+end