Решение на Трета задача от Александър Маринов

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

Към профила на Александър Маринов

Резултати

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

Код

class Invoice
def initialize(cart)
@cart_instance = cart
@cart = cart.cart
@promos = cart.promos
@coupons = cart.coupons
@used_coupon = cart.used_coupon
end
def suffix(number)
number = number.to_s
case number
when '1' then number + 'st)'
when '2' then number + 'nd)'
when '3' then number + 'rd)'
else number + 'th)'
end
end
def print_product_mixed(name, count, discount=nil)
if discount
price = sprintf "-%.2f", @cart_instance.determine_product_discount(name)
name = discount
else
price = sprintf "%.2f", @cart_instance.determine_product_price(name)
end
('| ' + name).ljust(48 - count.length) + count + ' |' + price.rjust(9) + " |\n"
end
def print_product_promo(name)
promo = @promos[name].values[0]
case @promos[name].keys[0]
when :get_one_free then opt_str = " (buy #{promo - 1}, get 1 free)"
when :package
opt_str = " (get #{promo.values[0]}% off for every #{promo.keys[0]})"
when :threshold
opt_str = " (#{promo.values[0]}% off of every after the #{suffix(promo.keys[0])}"
end
print_product_mixed(name, '', opt_str)
end
def print_product_invoice
product_invoice = ''
@cart.keys.each do |name|
product_invoice += print_product_mixed(name, @cart[name].to_s)
product_invoice += print_product_promo(name) if @promos[name]
end
product_invoice
end
def print_coupon_invoice
hash = @coupons[@used_coupon]
coupon_discount =
sprintf "%.2f", @cart_instance.determine_coupon_discount(@cart_instance.total false)
str = "| Coupon #{@used_coupon} - #{hash.values[0]} off".ljust(49)
if hash.keys[0] == :percent
str = str.sub(" off ", "% off")
end
str + '|' + "-#{coupon_discount}".rjust(9) + " |\n"
end
def print_footer_invoice
"+------------------------------------------------+----------+\n" +
"| Name qty | price |\n" +
"+------------------------------------------------+----------+\n"
end
def invoice
invoice = print_footer_invoice
invoice += print_product_invoice
invoice += print_coupon_invoice if @used_coupon
invoice += "+------------------------------------------------+----------+\n" +
"| TOTAL |" +
sprintf("%.2f", @cart_instance.total).rjust(9) + " |\n" +
"+------------------------------------------------+----------+\n"
invoice
end
end
class Cart
require 'bigdecimal'
require 'bigdecimal/util'
attr_reader :cart, :promos, :coupons, :used_coupon
def initialize(inventory)
@inventory = inventory.inventory
@cart = {}
@promos = inventory.promos
@coupons = inventory.coupons
@used_coupon = nil
end
def add(name, count = 1)
if not @inventory[name] or not (1..99).include? count
raise "Invalid parameters passed."
end
@cart[name] = (@cart[name] or 0) + count
end
def use(coupon_name)
@used_coupon = coupon_name
end
def determine_product_price(name)
@inventory[name].to_d*@cart[name]
end
def determine_product_discount(name)
promo = @promos[name].values[0]
price = @inventory[name].to_d
count = @cart[name]
case @promos[name].keys[0]
when :get_one_free then price*(count/promo)
when :package then (count/promo.keys[0])*promo.keys[0]*(price*promo.values[0]/100)
when :threshold
(promo.keys[0] < count)?(count-promo.keys[0])*price*promo.values[0]/100:'0'.to_d
end
end
def determine_coupon_discount(total_price)
return BigDecimal('0') if not @used_coupon
case @coupons[@used_coupon].keys[0]
when :percent
total_price*@coupons[@used_coupon].values[0]/100
when :amount
discount = (@coupons[@used_coupon].values[0]).to_d
(discount > total_price)?total_price:discount
end
end
def total(calc_discount = true)
total_price = BigDecimal.new('0')
@cart.keys.each do |name|
total_price += determine_product_price(name)
total_price -= determine_product_discount(name) if @promos[name]
end
coupon_discount = BigDecimal('0') if not calc_discount
coupon_discount = determine_coupon_discount(total_price) if calc_discount
(total_price < coupon_discount)?BigDecimal('0'):total_price - coupon_discount
end
def invoice
Invoice.new(self).invoice
end
end
class Inventory
attr_reader :inventory, :promos, :coupons
def initialize
@inventory = {}
@promos = {}
@coupons = {}
end
def register(name, price, promo = {})
if not (0..40).include? name.length or
not ('0.01'..'999.99').include? price or @inventory[name]
raise "Invalid parameters passed."
end
@inventory[name] = price
@promos[name] = (promo.keys.size == 0)?nil:promo
end
def register_coupon(coupon_name, coupon_discount)
@coupons[coupon_name] = coupon_discount
end
def new_cart
Cart.new self
end
end

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

.................F.

Failures:

  1) 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: "+------------------------------------------------+----------+\n| Name                                       qty |    price |\n+------------------------------------------------+----------+\n| Green Tea                                    5 |     5.00 |\n| Coupon TEA-TIME - 0.1E2 off                    |    -5.00 |\n+------------------------------------------------+----------+\n| TOTAL                                          |     0.00 |\n+------------------------------------------------+----------+\n"
       
       (compared using ==)
       
       Diff:
       @@ -2,7 +2,7 @@
        | Name                                       qty |    price |
        +------------------------------------------------+----------+
        | Green Tea                                    5 |     5.00 |
       -| Coupon TEA-TIME - 10.00 off                    |    -5.00 |
       +| Coupon TEA-TIME - 0.1E2 off                    |    -5.00 |
        +------------------------------------------------+----------+
        | TOTAL                                          |     0.00 |
        +------------------------------------------------+----------+
     # /tmp/d20111115-5847-n4nyn0/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)>'

Finished in 0.92022 seconds
19 examples, 1 failure

Failed examples:

rspec /tmp/d20111115-5847-n4nyn0/spec.rb:274 # Inventory with an 'amount off' coupon shows the discount in the invoice

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

Александър обнови решението на 07.11.2011 03:17 (преди около 13 години)

+class Invoice
+ def initialize(cart)
+ @cart_instance = cart
+ @cart = cart.cart
+ @promos = cart.promos
+ @coupons = cart.coupons
+ @used_coupon = cart.used_coupon
+ end
+
+ def suffix(number)
+ number = number.to_s
+ case number
+ when '1' then number + 'st)'
+ when '2' then number + 'nd)'
+ when '3' then number + 'rd)'
+ else number + 'th)'
+ end
+ end
+
+ def print_product_mixed(name, count, discount=nil)
+ if discount
+ price = sprintf "-%.2f", @cart_instance.determine_product_discount(name)
+ name = discount
+ else
+ price = sprintf "%.2f", @cart_instance.determine_product_price(name)
+ end
+ ('| ' + name).ljust(48 - count.length) + count + ' |' + price.rjust(9) + " |\n"
+ end
+
+ def print_product_promo(name)
+ promo = @promos[name].values[0]
+ case @promos[name].keys[0]
+ when :get_one_free then opt_str = " (buy #{promo - 1}, get 1 free)"
+ when :package
+ opt_str = " (get #{promo.values[0]}% off for every #{promo.keys[0]})"
+ when :threshold
+ opt_str = " (#{promo.values[0]}% off of every after the #{suffix(promo.keys[0])}"
+ end
+ print_product_mixed(name, '', opt_str)
+ end
+
+ def print_product_invoice
+ product_invoice = ''
+ @cart.keys.each do |name|
+ product_invoice += print_product_mixed(name, @cart[name].to_s)
+ product_invoice += print_product_promo(name) if @promos[name]
+ end
+ product_invoice
+ end
+
+ def print_coupon_invoice
+ hash = @coupons[@used_coupon]
+ coupon_discount =
+ sprintf "%.2f", @cart_instance.determine_coupon_discount(@cart_instance.total false)
+ str = "| Coupon #{@used_coupon} - #{hash.values[0]} off".ljust(49)
+ if hash.keys[0] == :percent
+ str = str.sub(" off ", "% off")
+ end
+ str + '|' + "-#{coupon_discount}".rjust(9) + " |\n"
+ end
+
+ def print_footer_invoice
+ "+------------------------------------------------+----------+\n" +
+ "| Name qty | price |\n" +
+ "+------------------------------------------------+----------+\n"
+ end
+
+ def invoice
+ invoice = print_footer_invoice
+ invoice += print_product_invoice
+ invoice += print_coupon_invoice if @used_coupon
+ invoice += "+------------------------------------------------+----------+\n" +
+ "| TOTAL |" +
+ sprintf("%.2f", @cart_instance.total).rjust(9) + " |\n" +
+ "+------------------------------------------------+----------+\n"
+ invoice
+ end
+end
+
+class Cart
+ require 'bigdecimal'
+ require 'bigdecimal/util'
+
+ attr_reader :cart, :promos, :coupons, :used_coupon
+ def initialize(inventory)
+ @inventory = inventory.inventory
+ @cart = {}
+ @promos = inventory.promos
+ @coupons = inventory.coupons
+ @used_coupon = nil
+ end
+
+ def add(name, count = 1)
+ if not @inventory[name] or not (1..99).include? count
+ raise "Invalid parameters passed."
+ end
+ @cart[name] = (@cart[name] or 0) + count
+ end
+
+ def use(coupon_name)
+ @used_coupon = coupon_name
+ end
+
+ def determine_product_price(name)
+ @inventory[name].to_d*@cart[name]
+ end
+
+ def determine_product_discount(name)
+ promo = @promos[name].values[0]
+ price = @inventory[name].to_d
+ count = @cart[name]
+ case @promos[name].keys[0]
+ when :get_one_free then price*(count/promo)
+ when :package then (count/promo.keys[0])*promo.keys[0]*(price*promo.values[0]/100)
+ when :threshold
+ (promo.keys[0] < count)?(count-promo.keys[0])*price*promo.values[0]/100:'0'.to_d
+ end
+ end
+
+ def determine_coupon_discount(total_price)
+ return BigDecimal('0') if not @used_coupon
+ case @coupons[@used_coupon].keys[0]
+ when :percent
+ total_price*@coupons[@used_coupon].values[0]/100
+ when :amount
+ discount = (@coupons[@used_coupon].values[0]).to_d
+ (discount > total_price)?total_price:discount
+ end
+ end
+
+ def total(calc_discount = true)
+ total_price = BigDecimal.new('0')
+ @cart.keys.each do |name|
+ total_price += determine_product_price(name)
+ total_price -= determine_product_discount(name) if @promos[name]
+ end
+ coupon_discount = BigDecimal('0') if not calc_discount
+ coupon_discount = determine_coupon_discount(total_price) if calc_discount
+ (total_price < coupon_discount)?BigDecimal('0'):total_price - coupon_discount
+ end
+
+ def invoice
+ Invoice.new(self).invoice
+ end
+end
+
+class Inventory
+ attr_reader :inventory, :promos, :coupons
+
+ def initialize
+ @inventory = {}
+ @promos = {}
+ @coupons = {}
+ end
+
+ def register(name, price, promo = {})
+ if not (0..40).include? name.length or
+ not ('0.01'..'999.99').include? price or @inventory[name]
+ raise "Invalid parameters passed."
+ end
+ @inventory[name] = price
+ @promos[name] = (promo.keys.size == 0)?nil:promo
+ end
+
+ def register_coupon(coupon_name, coupon_discount)
+ @coupons[coupon_name] = coupon_discount
+ end
+
+ def new_cart
+ Cart.new self
+ end
+end