Решение на Трета задача от Георги Лозев

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

Към профила на Георги Лозев

Резултати

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

Код

require 'bigdecimal'
require 'bigdecimal/util'
class Inventory
MinPrice = BigDecimal('0.01')
MaxPrice = BigDecimal('999.99')
attr_reader :goods_in_stock, :coupons, :goods_in_promotion
def initialize
@goods_in_stock = {}
@goods_in_promotion = {}
@coupons = {}
end
def register(goods_name, price, promotion=nil)
decimal_price = BigDecimal(price)
if goods_name.length > 40 || !decimal_price.between?(MinPrice, MaxPrice)
raise 'Invalid parameters passed.'
elsif @goods_in_stock.has_key?(goods_name)
raise 'Already exist in the inventory.'
end
@goods_in_stock[goods_name] = decimal_price
if promotion != nil
@goods_in_promotion[goods_name] = Promotions.create_promotion(promotion)
end
end
def register_coupon(name, type)
@coupons[name] = type
end
def new_cart
Cart.new(@goods_in_stock, @goods_in_promotion, @coupons)
end
end
class Cart
def initialize(goods_in_stock, goods_in_promotion, coupons)
@items = Hash.new(0)
@goods_in_stock = goods_in_stock
@goods_in_promotion = goods_in_promotion
@coupons = coupons
@total = BigDecimal('0')
@used_coupon = nil
end
def total
calculate_total_without_coupons()
calculate_total_with_coupons() if @used_coupon != nil
@total
end
def add(goods_name, quantity=1)
raise 'Not in the inventory.' if !@goods_in_stock.has_key?(goods_name)
raise 'Invalid quantity. ' if !quantity.between?(1, 99)
@items[goods_name] += quantity
end
def invoice
Receipt.new(self).print()
end
def use(name)
@used_coupon = name if @used_coupon == nil
end
private
def calculate_total_without_coupons
@total, item_tot = BigDecimal('0'), BigDecimal('0')
@items.each do |name, qty|
if @goods_in_promotion.include?(name)
item_tot= @goods_in_promotion[name].calculate_subtotal(qty, @goods_in_stock[name])
else
item_tot = (qty * @goods_in_stock[name])
end
@total += item_tot
end
end
def calculate_total_with_coupons
case @coupons[@used_coupon].keys.first
when :amount then
discount = @coupons[@used_coupon][:amount].to_d
@total = (discount <= @total)? (@total - discount): '0.00'.to_d
when :percent then
@total -= (@coupons[@used_coupon][:percent] / '100.00'.to_d) * @total
end
end
end
class Receipt
def initialize(cart)
end
def print
end
end
class Promotions
def Promotions.create_promotion(promo)
promotion = case promo.keys.first
when :get_one_free then GetOneFreePromo.new(promo[:get_one_free])
when :package then PackagePromo.new(promo[:package])
when :threshold then ThresholdPromo.new(promo[:threshold])
end
promotion
end
end
class GetOneFreePromo
def initialize(condition)
@condition = condition
end
def calculate_subtotal(qty, item_price)
subtotal = BigDecimal('0')
subtotal = qty * item_price
if qty >= @condition
subtotal -= ((qty / @condition) * item_price)
end
subtotal
end
end
class PackagePromo
def initialize(condition)
@number_of_items = condition.keys.first
@percent_discount = condition.values.first
end
def calculate_subtotal(qty, item_price)
subtotal = BigDecimal('0')
subtotal = qty * item_price
if qty >= @number_of_items
items_in_promo, coeff = qty / @number_of_items, (@percent_discount / '100.00'.to_d)
subtotal -= (items_in_promo * (coeff * (@number_of_items * item_price)))
end
subtotal
end
end
class ThresholdPromo
def initialize(condition)
@number_of_items = condition.keys.first
@percent_discount = condition.values.first
end
def calculate_subtotal(qty, item_price)
subtotal = BigDecimal('0')
subtotal = qty * item_price
if qty >= @number_of_items
items_in_prom, coeff = (qty - @number_of_items), (@percent_discount / '100.00'.to_d)
subtotal -= (items_in_prom * coeff * (item_price))
end
subtotal
end
end

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

..F..F..F..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: nil
       
       (compared using ==)
     # /tmp/d20111115-5847-1toskxy/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: nil
       
       (compared using ==)
     # /tmp/d20111115-5847-1toskxy/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: nil
       
       (compared using ==)
     # /tmp/d20111115-5847-1toskxy/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: nil
       
       (compared using ==)
     # /tmp/d20111115-5847-1toskxy/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: nil
       
       (compared using ==)
     # /tmp/d20111115-5847-1toskxy/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: nil
       
       (compared using ==)
     # /tmp/d20111115-5847-1toskxy/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: nil
       
       (compared using ==)
     # /tmp/d20111115-5847-1toskxy/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.56409 seconds
19 examples, 7 failures

Failed examples:

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

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

Георги обнови решението на 07.11.2011 11:50 (преди над 12 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class Inventory
+ MinPrice = BigDecimal('0.01')
+ MaxPrice = BigDecimal('999.99')
+
+ attr_reader :goods_in_stock, :coupons, :goods_in_promotion
+
+ def initialize
+ @goods_in_stock = {}
+ @goods_in_promotion = {}
+ @coupons = {}
+ end
+
+ def register(goods_name, price, promotion=nil)
+ decimal_price = BigDecimal(price)
+ if goods_name.length > 40 || !decimal_price.between?(MinPrice, MaxPrice)
+ raise 'Invalid parameters passed.'
+ elsif @goods_in_stock.has_key?(goods_name)
+ raise 'Already exist in the inventory.'
+ end
+ @goods_in_stock[goods_name] = decimal_price
+ if promotion != nil
+ @goods_in_promotion[goods_name] = Promotions.create_promotion(promotion)
+ end
+ end
+
+ def register_coupon(name, type)
+ @coupons[name] = type
+ end
+
+ def new_cart
+ Cart.new(@goods_in_stock, @goods_in_promotion, @coupons)
+ end
+end
+
+class Cart
+ def initialize(goods_in_stock, goods_in_promotion, coupons)
+ @items = Hash.new(0)
+ @goods_in_stock = goods_in_stock
+ @goods_in_promotion = goods_in_promotion
+ @coupons = coupons
+ @total = BigDecimal('0')
+ @used_coupon = nil
+ end
+
+ def total
+ calculate_total_without_coupons()
+ calculate_total_with_coupons() if @used_coupon != nil
+ @total
+ end
+
+ def add(goods_name, quantity=1)
+ raise 'Not in the inventory.' if !@goods_in_stock.has_key?(goods_name)
+ raise 'Invalid quantity. ' if !quantity.between?(1, 99)
+ @items[goods_name] += quantity
+ end
+
+ def invoice
+ Receipt.new(self).print()
+ end
+
+ def use(name)
+ @used_coupon = name if @used_coupon == nil
+ end
+
+ private
+ def calculate_total_without_coupons
+ @total, item_tot = BigDecimal('0'), BigDecimal('0')
+ @items.each do |name, qty|
+ if @goods_in_promotion.include?(name)
+ item_tot= @goods_in_promotion[name].calculate_subtotal(qty, @goods_in_stock[name])
+ else
+ item_tot = (qty * @goods_in_stock[name])
+ end
+ @total += item_tot
+ end
+ end
+
+ def calculate_total_with_coupons
+ case @coupons[@used_coupon].keys.first
+ when :amount then
+ discount = @coupons[@used_coupon][:amount].to_d
+ @total = (discount <= @total)? (@total - discount): '0.00'.to_d
+ when :percent then
+ @total -= (@coupons[@used_coupon][:percent] / '100.00'.to_d) * @total
+ end
+ end
+end
+
+class Receipt
+ def initialize(cart)
+
+ end
+
+ def print
+
+ end
+end
+
+class Promotions
+ def Promotions.create_promotion(promo)
+ promotion = case promo.keys.first
+ when :get_one_free then GetOneFreePromo.new(promo[:get_one_free])
+ when :package then PackagePromo.new(promo[:package])
+ when :threshold then ThresholdPromo.new(promo[:threshold])
+ end
+ promotion
+ end
+end
+
+class GetOneFreePromo
+ def initialize(condition)
+ @condition = condition
+ end
+
+ def calculate_subtotal(qty, item_price)
+ subtotal = BigDecimal('0')
+ subtotal = qty * item_price
+ if qty >= @condition
+ subtotal -= ((qty / @condition) * item_price)
+ end
+ subtotal
+ end
+end
+
+class PackagePromo
+ def initialize(condition)
+ @number_of_items = condition.keys.first
+ @percent_discount = condition.values.first
+ end
+
+ def calculate_subtotal(qty, item_price)
+ subtotal = BigDecimal('0')
+ subtotal = qty * item_price
+ if qty >= @number_of_items
+ items_in_promo, coeff = qty / @number_of_items, (@percent_discount / '100.00'.to_d)
+ subtotal -= (items_in_promo * (coeff * (@number_of_items * item_price)))
+ end
+ subtotal
+ end
+end
+
+class ThresholdPromo
+ def initialize(condition)
+ @number_of_items = condition.keys.first
+ @percent_discount = condition.values.first
+ end
+
+ def calculate_subtotal(qty, item_price)
+ subtotal = BigDecimal('0')
+ subtotal = qty * item_price
+ if qty >= @number_of_items
+ items_in_prom, coeff = (qty - @number_of_items), (@percent_discount / '100.00'.to_d)
+ subtotal -= (items_in_prom * coeff * (item_price))
+ end
+ subtotal
+ end
+end