Решение на Трета задача от Михаил Илиев

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

Към профила на Михаил Илиев

Резултати

  • 1 точка от тестове
  • 0 бонус точки
  • 1 точка общо
  • 2 успешни тест(а)
  • 17 неуспешни тест(а)

Код

require 'bigdecimal'
require 'bigdecimal/util'
class Inventory
def initialize
@products = {}
@coupons = {}
@promotions = {}
end
def register(name, price, promotion = {} )
if name.length > 40 then raise "Length over 40 symbols." end
if price.to_d > 999.99 or price.to_d < 0.01 then raise "Wrong price." end
if @products[name] then raise "Already in shop" end
@products[name] = price.to_d
@promotions[name] = promotion
end
def register_coupon(name, discount)
@coupons[name] = discount
end
def new_cart
cart = Cart.new(@products, @promotions, @coupons)
end
end
class Cart
def initialize(products, promotions, coupons)
# This shouldn't be like this!
@shop = products
@promotions = promotions
@coupons = coupons
@to_buy = {}
@coupon = ''
end
def add(name, quantity = 1)
raise "Should be more than 0." if quantity<1
# TODO Could it be a one-liner?
if @to_buy[name]
@to_buy[name] = @to_buy[name] + quantity
else
@to_buy[name] = quantity
end
if !@shop[name] or @to_buy[name] > 99 then raise "You can't add it." end
end
def use(coupon)
@coupon = coupon
end
def total
total = 0
@to_buy.each do |product, qty|
total += @shop[product] * qty
# promotions
end
#coupon
total
end
def invoice
end
end

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

..FFFFFFFFFFFFFFFFF

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-v6hnai/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 grants every nth item for free
     Failure/Error: cart.total.should eq '3.00'.to_d
       
       expected: #<BigDecimal:9831e14,'0.3E1',4(8)>
            got: #<BigDecimal:9831e50,'0.4E1',4(12)>
       
       (compared using ==)
     # /tmp/d20111115-5847-v6hnai/spec.rb:93: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 'buy X, get one free' promotion grants 2 items free, when 8 purchased and every 3rd is free
     Failure/Error: cart.total.should eq '6.00'.to_d
       
       expected: #<BigDecimal:9830e24,'0.6E1',4(8)>
            got: #<BigDecimal:9830e60,'0.8E1',4(12)>
       
       (compared using ==)
     # /tmp/d20111115-5847-v6hnai/spec.rb:101: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 '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-v6hnai/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)>'

  5) Inventory with a '% off for every n' promotion gives % off for every group of n
     Failure/Error: cart.total.should eq '3.20'.to_d
       
       expected: #<BigDecimal:982edb8,'0.32E1',8(8)>
            got: #<BigDecimal:982edf4,'0.4E1',4(12)>
       
       (compared using ==)
     # /tmp/d20111115-5847-v6hnai/spec.rb:131: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 a '% off for every n' promotion does not discount for extra items, that don't fit in a group
     Failure/Error: cart.total.should eq '1.80'.to_d
       
       expected: #<BigDecimal:9dacb3c,'0.18E1',8(8)>
            got: #<BigDecimal:9dacb78,'0.2E1',4(12)>
       
       (compared using ==)
     # /tmp/d20111115-5847-v6hnai/spec.rb:141: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 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-v6hnai/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)>'

  8) Inventory with a '% off of every item after the nth' promotion gives a discount for every item after the nth
     Failure/Error: cart.total.should eq '15.40'.to_d
       
       expected: #<BigDecimal:9daaaa8,'0.154E2',8(8)>
            got: #<BigDecimal:9daaae4,'0.16E2',4(12)>
       
       (compared using ==)
     # /tmp/d20111115-5847-v6hnai/spec.rb:174: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)>'

  9) Inventory with a '% off of every item after the nth' promotion does not give a discount if there are no more than n items in the cart
     Failure/Error: cart.total.should eq '14.00'.to_d
       
       expected: #<BigDecimal:9da948c,'0.14E2',4(8)>
            got: #<BigDecimal:9da94c8,'0.15E2',4(12)>
       
       (compared using ==)
     # /tmp/d20111115-5847-v6hnai/spec.rb:187: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)>'

  10) 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-v6hnai/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)>'

  11) Inventory with a '% off' coupon gives % off of the total
     Failure/Error: cart.total.should eq '8.00'.to_d
       
       expected: #<BigDecimal:9dcb064,'0.8E1',4(8)>
            got: #<BigDecimal:9dcb0a0,'0.1E2',4(12)>
       
       (compared using ==)
     # /tmp/d20111115-5847-v6hnai/spec.rb:220: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)>'

  12) Inventory with a '% off' coupon applies the coupon discount after product promotions
     Failure/Error: cart.total.should eq '9.00'.to_d
       
       expected: #<BigDecimal:9dca024,'0.9E1',4(8)>
            got: #<BigDecimal:9dca060,'0.12E2',4(12)>
       
       (compared using ==)
     # /tmp/d20111115-5847-v6hnai/spec.rb:230: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)>'

  13) 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-v6hnai/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)>'

  14) Inventory with an 'amount off' coupon subtracts the amount form the total
     Failure/Error: cart.total.should eq '2.00'.to_d
       
       expected: #<BigDecimal:99a3b44,'0.2E1',4(8)>
            got: #<BigDecimal:99a3b80,'0.12E2',4(12)>
       
       (compared using ==)
     # /tmp/d20111115-5847-v6hnai/spec.rb:261: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)>'

  15) Inventory with an 'amount off' coupon does not result in a negative total
     Failure/Error: cart.total.should eq '0.00'.to_d
       
       expected: #<BigDecimal:99a2ac8,'0.0',4(8)>
            got: #<BigDecimal:99a2b04,'0.8E1',4(12)>
       
       (compared using ==)
     # /tmp/d20111115-5847-v6hnai/spec.rb:271: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)>'

  16) 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-v6hnai/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)>'

  17) 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-v6hnai/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, 17 failures

Failed examples:

rspec /tmp/d20111115-5847-v6hnai/spec.rb:64 # Inventory with no discounts can print an invoice
rspec /tmp/d20111115-5847-v6hnai/spec.rb:88 # Inventory with a 'buy X, get one free' promotion grants every nth item for free
rspec /tmp/d20111115-5847-v6hnai/spec.rb:96 # Inventory with a 'buy X, get one free' promotion grants 2 items free, when 8 purchased and every 3rd is free
rspec /tmp/d20111115-5847-v6hnai/spec.rb:104 # Inventory with a 'buy X, get one free' promotion shows the discount in the invoice
rspec /tmp/d20111115-5847-v6hnai/spec.rb:127 # Inventory with a '% off for every n' promotion gives % off for every group of n
rspec /tmp/d20111115-5847-v6hnai/spec.rb:137 # Inventory with a '% off for every n' promotion does not discount for extra items, that don't fit in a group
rspec /tmp/d20111115-5847-v6hnai/spec.rb:147 # Inventory with a '% off for every n' promotion shows the discount in the invoice
rspec /tmp/d20111115-5847-v6hnai/spec.rb:170 # Inventory with a '% off of every item after the nth' promotion gives a discount for every item after the nth
rspec /tmp/d20111115-5847-v6hnai/spec.rb:177 # Inventory with a '% off of every item after the nth' promotion does not give a discount if there are no more than n items in the cart
rspec /tmp/d20111115-5847-v6hnai/spec.rb:190 # Inventory with a '% off of every item after the nth' promotion shows the discount in the ivnoice
rspec /tmp/d20111115-5847-v6hnai/spec.rb:213 # Inventory with a '% off' coupon gives % off of the total
rspec /tmp/d20111115-5847-v6hnai/spec.rb:223 # Inventory with a '% off' coupon applies the coupon discount after product promotions
rspec /tmp/d20111115-5847-v6hnai/spec.rb:233 # Inventory with a '% off' coupon shows the discount in the invoice
rspec /tmp/d20111115-5847-v6hnai/spec.rb:254 # Inventory with an 'amount off' coupon subtracts the amount form the total
rspec /tmp/d20111115-5847-v6hnai/spec.rb:264 # Inventory with an 'amount off' coupon does not result in a negative total
rspec /tmp/d20111115-5847-v6hnai/spec.rb:274 # Inventory with an 'amount off' coupon shows the discount in the invoice
rspec /tmp/d20111115-5847-v6hnai/spec.rb:295 # Inventory with multiple discounts can print an invoice

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

Михаил обнови решението на 07.11.2011 15:07 (преди над 12 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class Inventory
+ def initialize
+ @products = {}
+ @coupons = {}
+ @promotions = {}
+ end
+
+ def register(name, price, promotion = {} )
+ if name.length > 40 then raise "Length over 40 symbols." end
+ if price.to_d > 999.99 or price.to_d < 0.01 then raise "Wrong price." end
+ if @products[name] then raise "Already in shop" end
+
+ @products[name] = price.to_d
+ @promotions[name] = promotion
+ end
+
+ def register_coupon(name, discount)
+ @coupons[name] = discount
+ end
+
+ def new_cart
+ cart = Cart.new(@products, @promotions, @coupons)
+ end
+end
+
+class Cart
+ def initialize(products, promotions, coupons)
+ # This shouldn't be like this!
+ @shop = products
+ @promotions = promotions
+ @coupons = coupons
+
+ @to_buy = {}
+ @coupon = ''
+ end
+
+ def add(name, quantity = 1)
+ raise "Should be more than 0." if quantity<1
+ # TODO Could it be a one-liner?
+ if @to_buy[name]
+ @to_buy[name] = @to_buy[name] + quantity
+ else
+ @to_buy[name] = quantity
+ end
+
+ if !@shop[name] or @to_buy[name] > 99 then raise "You can't add it." end
+ end
+
+ def use(coupon)
+ @coupon = coupon
+ end
+
+ def total
+ total = 0
+ @to_buy.each do |product, qty|
+ total += @shop[product] * qty
+ # promotions
+ end
+ #coupon
+ total
+ end
+
+ def invoice
+ end
+end

А какво ще кажете за псевдо-"null object pattern"-а от типа:

@to_buy = Hash.new 0 в Cart#initialize

И последващо премахване на разни if-ове :) (т.е.: @to_buy[name] += quantity)

Ако горното ви дразни, идиоматично е следното:

@to_buy[name] ||= 0
@to_buy[name] += quantity