Решение на Трета задача от Румен Ангелов

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

Към профила на Румен Ангелов

Резултати

  • 3 точки от тестове
  • 0 бонус точки
  • 3 точки общо
  • 9 успешни тест(а)
  • 10 неуспешни тест(а)

Код

require 'bigdecimal'
require 'bigdecimal/util' # добавя String#to_d
class Inventory
def initialize
@inventory = {}
end
def register(name, price, promo = {})
if name.length > 40 || @inventory[name] != nil ||
price.to_d < '0.01'.to_d || price.to_d > '999.99'.to_d
raise "Invalid parameters passed."
else
@inventory[name] = [price, promo]
end
end
def new_cart
Cart.new(@inventory)
end
end
class Cart
attr_reader :cart, :inventory
def initialize(inventory)
@cart, @inventory = Hash.new(0), inventory
end
def add(name, quantity = 1)
if quantity < 0 || quantity > 99 || @inventory[name] == nil
raise "Invalid parameters passed."
else
@cart[name] += quantity
if @cart[name] > 99
@cart[name] -= quantity
raise "Invalid parameters passed."
end
end
end
def total
@cart.inject(0) do |product, (key, val)|
if @inventory[key][1].has_key? :get_one_free
product + Get_one_free.new(key, val, @inventory).calculate
elsif @inventory[key][1].has_key? :package
product + Package.new(key, val, @inventory).calculate
elsif @inventory[key][1].has_key? :threshold
product + Threshold.new(key, val, @inventory).calculate
else product + @inventory[key][0].to_d * val
end
end
end
def invoice
Receipt.new(@cart, @inventory, self.total).receipt
end
end
class Receipt
attr_reader :receipt
def initialize(cart, inventory, total)
@cart, @inventory, @total = cart, inventory, total
@receipt = "+#{'-'*48}+#{'-'*10}+\n| Name#{' '*39}qty | price |\n"
@receipt += "+#{'-'*48}+#{'-'*10}+\n"
print
@receipt += "+#{'-'*48}+#{'-'*10}+\n"
@receipt += "| TOTAL #{' '*41}|#{' '*(9 - @total.to_f.to_s.size)}#{@total.to_f} |\n"
@receipt += "+#{'-'*48}+#{'-'*10}+\n"
end
def print
@cart.map do |key, val|
hash = @inventory[key][1]
@receipt += "| #{key}#{' '*(46 - key.length - val.to_s.size)}#{val} |" +
"#{' '*(9 - (@inventory[key][0].to_d*val).round(2).to_f.to_s.size)}"+
"#{(@inventory[key][0].to_d*val).round(2).to_f} |\n" +
if hash.has_key? :package then Package.new(key, val, @inventory).print
elsif hash.has_key? :get_one_free then Get_one_free.new(key, val, @inventory).print
elsif hash.has_key? :threshold then Threshold.new(key, val, @inventory).print
else ""
end
end
end
end
class Get_one_free
def initialize(name, quantity, inventory)
@name, @qty, @inventory = name, quantity, inventory
end
def calculate
x = @qty / @inventory[@name][1][:get_one_free]
(@qty - x) * @inventory[@name][0].to_d
end
def print
result = @inventory[@name][0].to_d * @qty - calculate
x = "| (buy #{@qty - 1}, get #{1} free)"
"#{x}#{' '*(49 - x.size)}|#{' '*(8 - result.to_f.to_s.size)}-#{result.to_f} |\n"
end
end
class Package
def initialize(name, quantity, inventory)
@name, @qty, @inventory = name, quantity, inventory
@promo = @inventory[@name][1][:package].flatten
end
def calculate
x = @qty / @promo[0]
cena = @inventory[@name][0].to_d
ostatyk = @qty % @promo[0]
procent = @promo[1] .to_s.to_d/ 100
(x * @promo[0] * cena - x * @promo[0] * cena * procent) + ostatyk * cena
end
def print
result = @inventory[@name][0].to_d * @qty - calculate
x = "| (get #{@promo[1]}% off for every #{@promo[0]})"
"#{x}#{' '*(49 - x.size)}|#{' '*(8 - result.to_f.to_s.size)}-#{result.to_f} |\n"
end
end
class Threshold
def initialize(name, quantity, inventory)
@name, @qty, @inventory = name, quantity, inventory
@promo = @inventory[@name][1][:threshold].flatten
end
def calculate
x = @qty - @promo[0]
cena = @inventory[@name][0].to_d
procent = @promo[1].to_s.to_d / 100
if(@qty > @promo[0])
@promo[0] * cena + (x * cena - x * cena * procent)
else
@qty * cena
end
end
def print
result = @inventory[@name][0].to_d * @qty - calculate
x = "| (#{@promo[1]}% free after #{@promo[0]}" +
case @promo[0]
when 1 then "st)"
when 2 then "nd)"
when 3 then "rd)"
else "th)"
end
"#{x}#{' '*(49 - x.size)}|#{' '*(8 - result.to_f.to_s.size)}-#{result.to_f} |\n"
end
end

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

.....F..F..FFFFFFFF

Failures:

  1) 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: "+------------------------------------------------+----------+\n| Name                                       qty |    price |\n+------------------------------------------------+----------+\n| Green Tea                                    3 |      3.0 |\n|   (buy 2, get 1 free)                          |     -1.0 |\n| Red Tea                                      8 |     16.0 |\n|   (buy 7, get 1 free)                          |     -2.0 |\n+------------------------------------------------+----------+\n| TOTAL                                          |     16.0 |\n+------------------------------------------------+----------+\n"
       
       (compared using ==)
       
       Diff:
       
       @@ -1,11 +1,11 @@
        +------------------------------------------------+----------+
        | 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 |
       +| Green Tea                                    3 |      3.0 |
       +|   (buy 2, get 1 free)                          |     -1.0 |
       +| Red Tea                                      8 |     16.0 |
       +|   (buy 7, get 1 free)                          |     -2.0 |
        +------------------------------------------------+----------+
       -| TOTAL                                          |    16.00 |
       +| TOTAL                                          |     16.0 |
        +------------------------------------------------+----------+
     # /tmp/d20111115-5847-1cv4qpc/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)>'

  2) 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: "+------------------------------------------------+----------+\n| Name                                       qty |    price |\n+------------------------------------------------+----------+\n| Green Tea                                    4 |      4.0 |\n|   (get 10% off for every 4)                    |     -0.4 |\n| Red Tea                                      8 |     16.0 |\n|   (get 20% off for every 5)                    |     -2.0 |\n+------------------------------------------------+----------+\n| TOTAL                                          |     17.6 |\n+------------------------------------------------+----------+\n"
       
       (compared using ==)
       
       Diff:
       
       @@ -1,11 +1,11 @@
        +------------------------------------------------+----------+
        | 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 |
       +| Green Tea                                    4 |      4.0 |
       +|   (get 10% off for every 4)                    |     -0.4 |
       +| Red Tea                                      8 |     16.0 |
       +|   (get 20% off for every 5)                    |     -2.0 |
        +------------------------------------------------+----------+
       -| TOTAL                                          |    17.60 |
       +| TOTAL                                          |     17.6 |
        +------------------------------------------------+----------+
     # /tmp/d20111115-5847-1cv4qpc/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)>'

  3) 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: "+------------------------------------------------+----------+\n| Name                                       qty |    price |\n+------------------------------------------------+----------+\n| Green Tea                                   12 |     12.0 |\n|   (10% free after 10th)                        |     -0.2 |\n| Red Tea                                     20 |     40.0 |\n|   (20% free after 15th)                        |     -2.0 |\n+------------------------------------------------+----------+\n| TOTAL                                          |     49.8 |\n+------------------------------------------------+----------+\n"
       
       (compared using ==)
       
       Diff:
       
       @@ -1,11 +1,11 @@
        +------------------------------------------------+----------+
        | 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 |
       +| Green Tea                                   12 |     12.0 |
       +|   (10% free after 10th)                        |     -0.2 |
       +| Red Tea                                     20 |     40.0 |
       +|   (20% free after 15th)                        |     -2.0 |
        +------------------------------------------------+----------+
       -| TOTAL                                          |    49.80 |
       +| TOTAL                                          |     49.8 |
        +------------------------------------------------+----------+
     # /tmp/d20111115-5847-1cv4qpc/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)>'

  4) Inventory with a '% off' coupon gives % off of the total
     Failure/Error: inventory.register_coupon 'TEATIME', percent: 20
     NoMethodError:
       undefined method `register_coupon' for #<Inventory:0xa59c7e8 @inventory={"Tea"=>["1.00", {}]}>
     # /tmp/d20111115-5847-1cv4qpc/spec.rb:215: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 applies the coupon discount after product promotions
     Failure/Error: inventory.register_coupon 'TEATIME', percent: 10
     NoMethodError:
       undefined method `register_coupon' for #<Inventory:0xa28f9d8>
     # /tmp/d20111115-5847-1cv4qpc/spec.rb:225: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' coupon shows the discount in the invoice
     Failure/Error: inventory.register_coupon 'TEA-TIME', percent: 20
     NoMethodError:
       undefined method `register_coupon' for #<Inventory:0xa28ef88 @inventory={"Green Tea"=>["1.00", {}]}>
     # /tmp/d20111115-5847-1cv4qpc/spec.rb:235: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 an 'amount off' coupon subtracts the amount form the total
     Failure/Error: inventory.register_coupon 'TEATIME', amount: '10.00'.to_d
     NoMethodError:
       undefined method `register_coupon' for #<Inventory:0xa28e2a4 @inventory={"Tea"=>["1.00", {}]}>
     # /tmp/d20111115-5847-1cv4qpc/spec.rb:256: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 an 'amount off' coupon does not result in a negative total
     Failure/Error: inventory.register_coupon 'TEATIME', amount: '10.00'.to_d
     NoMethodError:
       undefined method `register_coupon' for #<Inventory:0xa28d714 @inventory={"Tea"=>["1.00", {}]}>
     # /tmp/d20111115-5847-1cv4qpc/spec.rb:266: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 an 'amount off' coupon shows the discount in the invoice
     Failure/Error: inventory.register_coupon 'TEA-TIME', amount: '10.00'.to_d
     NoMethodError:
       undefined method `register_coupon' for #<Inventory:0xa28cc88 @inventory={"Green Tea"=>["1.00", {}]}>
     # /tmp/d20111115-5847-1cv4qpc/spec.rb:276: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 multiple discounts can print an invoice
     Failure/Error: inventory.register_coupon 'BREAKFAST', percent: 10
     NoMethodError:
       undefined method `register_coupon' for #<Inventory:0xa2b8be4>
     # /tmp/d20111115-5847-1cv4qpc/spec.rb:301: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.60537 seconds
19 examples, 10 failures

Failed examples:

rspec /tmp/d20111115-5847-1cv4qpc/spec.rb:104 # Inventory with a 'buy X, get one free' promotion shows the discount in the invoice
rspec /tmp/d20111115-5847-1cv4qpc/spec.rb:147 # Inventory with a '% off for every n' promotion shows the discount in the invoice
rspec /tmp/d20111115-5847-1cv4qpc/spec.rb:190 # Inventory with a '% off of every item after the nth' promotion shows the discount in the ivnoice
rspec /tmp/d20111115-5847-1cv4qpc/spec.rb:213 # Inventory with a '% off' coupon gives % off of the total
rspec /tmp/d20111115-5847-1cv4qpc/spec.rb:223 # Inventory with a '% off' coupon applies the coupon discount after product promotions
rspec /tmp/d20111115-5847-1cv4qpc/spec.rb:233 # Inventory with a '% off' coupon shows the discount in the invoice
rspec /tmp/d20111115-5847-1cv4qpc/spec.rb:254 # Inventory with an 'amount off' coupon subtracts the amount form the total
rspec /tmp/d20111115-5847-1cv4qpc/spec.rb:264 # Inventory with an 'amount off' coupon does not result in a negative total
rspec /tmp/d20111115-5847-1cv4qpc/spec.rb:274 # Inventory with an 'amount off' coupon shows the discount in the invoice
rspec /tmp/d20111115-5847-1cv4qpc/spec.rb:295 # Inventory with multiple discounts can print an invoice

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

Румен обнови решението на 07.11.2011 16:06 (преди около 13 години)

+require 'bigdecimal'
+require 'bigdecimal/util' # добавя String#to_d
+
+class Inventory
+ def initialize
+ @inventory = {}
+ end
+
+ def register(name, price, promo = {})
+ if name.length > 40 || @inventory[name] != nil ||
+ price.to_d < '0.01'.to_d || price.to_d > '999.99'.to_d
+ raise "Invalid parameters passed."
+ else
+ @inventory[name] = [price, promo]
+ end
+ end
+
+ def new_cart
+ Cart.new(@inventory)
+ end
+end
+
+class Cart
+ attr_reader :cart, :inventory
+
+ def initialize(inventory)
+ @cart, @inventory = Hash.new(0), inventory
+ end
+
+ def add(name, quantity = 1)
+ if quantity < 0 || quantity > 99 || @inventory[name] == nil
+ raise "Invalid parameters passed."
+ else
+ @cart[name] += quantity
+ if @cart[name] > 99
+ @cart[name] -= quantity
+ raise "Invalid parameters passed."
+ end
+ end
+ end
+
+ def total
+ @cart.inject(0) do |product, (key, val)|
+ if @inventory[key][1].has_key? :get_one_free
+ product + Get_one_free.new(key, val, @inventory).calculate
+ elsif @inventory[key][1].has_key? :package
+ product + Package.new(key, val, @inventory).calculate
+ elsif @inventory[key][1].has_key? :threshold
+ product + Threshold.new(key, val, @inventory).calculate
+ else product + @inventory[key][0].to_d * val
+ end
+ end
+ end
+
+ def invoice
+ Receipt.new(@cart, @inventory, self.total).receipt
+ end
+end
+
+class Receipt
+ attr_reader :receipt
+ def initialize(cart, inventory, total)
+ @cart, @inventory, @total = cart, inventory, total
+ @receipt = "+#{'-'*48}+#{'-'*10}+\n| Name#{' '*39}qty | price |\n"
+ @receipt += "+#{'-'*48}+#{'-'*10}+\n"
+ print
+ @receipt += "+#{'-'*48}+#{'-'*10}+\n"
+ @receipt += "| TOTAL #{' '*41}|#{' '*(9 - @total.to_f.to_s.size)}#{@total.to_f} |\n"
+ @receipt += "+#{'-'*48}+#{'-'*10}+\n"
+ end
+
+ def print
+ @cart.map do |key, val|
+ hash = @inventory[key][1]
+ @receipt += "| #{key}#{' '*(46 - key.length - val.to_s.size)}#{val} |" +
+ "#{' '*(9 - (@inventory[key][0].to_d*val).round(2).to_f.to_s.size)}"+
+ "#{(@inventory[key][0].to_d*val).round(2).to_f} |\n" +
+ if hash.has_key? :package then Package.new(key, val, @inventory).print
+ elsif hash.has_key? :get_one_free then Get_one_free.new(key, val, @inventory).print
+ elsif hash.has_key? :threshold then Threshold.new(key, val, @inventory).print
+ else ""
+ end
+ end
+ end
+
+end
+
+class Get_one_free
+ def initialize(name, quantity, inventory)
+ @name, @qty, @inventory = name, quantity, inventory
+ end
+
+ def calculate
+ x = @qty / @inventory[@name][1][:get_one_free]
+ (@qty - x) * @inventory[@name][0].to_d
+ end
+
+ def print
+ result = @inventory[@name][0].to_d * @qty - calculate
+ x = "| (buy #{@qty - 1}, get #{1} free)"
+ "#{x}#{' '*(49 - x.size)}|#{' '*(8 - result.to_f.to_s.size)}-#{result.to_f} |\n"
+ end
+end
+
+class Package
+ def initialize(name, quantity, inventory)
+ @name, @qty, @inventory = name, quantity, inventory
+ @promo = @inventory[@name][1][:package].flatten
+ end
+
+ def calculate
+ x = @qty / @promo[0]
+ cena = @inventory[@name][0].to_d
+ ostatyk = @qty % @promo[0]
+ procent = @promo[1] .to_s.to_d/ 100
+ (x * @promo[0] * cena - x * @promo[0] * cena * procent) + ostatyk * cena
+ end
+
+ def print
+ result = @inventory[@name][0].to_d * @qty - calculate
+ x = "| (get #{@promo[1]}% off for every #{@promo[0]})"
+ "#{x}#{' '*(49 - x.size)}|#{' '*(8 - result.to_f.to_s.size)}-#{result.to_f} |\n"
+ end
+end
+
+class Threshold
+ def initialize(name, quantity, inventory)
+ @name, @qty, @inventory = name, quantity, inventory
+ @promo = @inventory[@name][1][:threshold].flatten
+ end
+
+ def calculate
+ x = @qty - @promo[0]
+ cena = @inventory[@name][0].to_d
+ procent = @promo[1].to_s.to_d / 100
+ if(@qty > @promo[0])
+ @promo[0] * cena + (x * cena - x * cena * procent)
+ else
+ @qty * cena
+ end
+ end
+
+ def print
+ result = @inventory[@name][0].to_d * @qty - calculate
+ x = "| (#{@promo[1]}% free after #{@promo[0]}" +
+ case @promo[0]
+ when 1 then "st)"
+ when 2 then "nd)"
+ when 3 then "rd)"
+ else "th)"
+ end
+ "#{x}#{' '*(49 - x.size)}|#{' '*(8 - result.to_f.to_s.size)}-#{result.to_f} |\n"
+ end
+end