Решение на Трета задача от Николай Беличев

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

Към профила на Николай Беличев

Резултати

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

Код

require 'bigdecimal'
require 'bigdecimal/util'
class Inventory
attr_accessor :products, :promotions_gof, :promotions_p, :promotions_t, :coupons
def initialize
@products = {}
@promotions_gof = {}
@promotions_p = {}
@promotions_t = {}
@coupons = {}
end
def register(product, price, promotion = {})
price = BigDecimal(price)
if @products.has_key?(product) || product.size > 40 || !price.between?(0.01, 999.99)
raise "Invalid parameters passed."
else
@products[product] = price
register_promotion(product, promotion)
end
end
def register_promotion(product, promotion)
if(promotion.has_key?(:get_one_free))
@promotions_gof[product] = promotion[:get_one_free]
elsif(promotion.has_key?(:package))
promotion[:package].each { |key, value| @promotions_p[product] = [key,value] }
elsif(promotion.has_key?(:threshold))
promotion[:threshold].each { |key, value| @promotions_t[product] = [key,value] }
end
end
def register_coupon(name, discount)
if discount[:percent]
@coupons[name] = discount[:percent]
else
@coupons[name] = -BigDecimal(discount[:amount])
end
end
def new_cart
Cart.new(self)
end
end
class Cart
def initialize(inventory)
@products = {}
@inventory = inventory
@final_prices = {}
@coupon = 0
@coupon_name = ''
@total_before_coupon = 0
end
def add(product, quantity = 1)
if !@inventory.products.has_key?(product) || !quantity.between?(1, 99)
raise "Invalid parameters passed."
elsif @products.has_key?(product)
@products[product] += quantity
else
@products[product] = quantity
end
@final_prices[product] = @products[product] * @inventory.products[product]
end
def total
discount = 0
@products.each do |prod, qty|
discount += print_or_discount(prod, 'discount')
end
total = @final_prices.values.inject(:+) - discount
@total_before_coupon = total
@coupon > 0 ? total = total * (100 - @coupon) / 100 : 0
@coupon < 0 ? total = total > -@coupon ? total + @coupon : 0 : 0
total
end
def invoice
d = delimiter = "+------------------------------------------------+----------+\n"
invoice = d + "| " + "Name".ljust(43) + "qty | price |\n" + d
@products.each do |prod, qty|
invoice += "| " + prod.ljust(40) + " " + qty.to_s.rjust(2) + " | "
invoice += sprintf("%8.2f", @final_prices[prod]) + " |\n" + print_or_discount(prod)
end
invoice += print_coupon
invoice + d + "| " + "TOTAL".ljust(47) + "| " + sprintf("%8.2f", total) + " |\n" + d
end
def print_or_discount(prod, choose = 'print')
if(@inventory.promotions_gof.has_key?(prod))
choose == 'print' ? gof_promotion(prod)[1] : gof_promotion(prod)[0]
elsif(@inventory.promotions_p.has_key?(prod))
choose == 'print' ? p_promotion(prod)[1] : p_promotion(prod)[0]
elsif(@inventory.promotions_t.has_key?(prod))
choose == 'print' ? t_promotion(prod)[1] : t_promotion(prod)[0]
else
choose == 'print' ? "" : 0
end
end
def gof_promotion(prod)
gof_promotion = @inventory.promotions_gof[prod]
discount = @products[prod] / gof_promotion * @inventory.products[prod]
promotion = "| (buy " + (gof_promotion - 1).to_s + ", get 1 free)"
promotion = promotion.ljust(49) + "| " + sprintf("%8.2f", -discount) + " |\n"
[discount, promotion]
end
def p_promotion(prod)
p_promotion = @inventory.promotions_p[prod]
discount = @products[prod] / p_promotion[0] * @inventory.products[prod]
discount = discount * p_promotion[0] * p_promotion[1] / 100
promotion = "| (get " + p_promotion[1].to_s
promotion += "% off for every " + p_promotion[0].to_s + ")"
promotion = promotion.ljust(49) + "| " + sprintf("%8.2f", -discount) + " |\n"
[discount, promotion]
end
def t_promotion(prod)
t_promotion = @inventory.promotions_t[prod]
@products[prod] > t_promotion[0] ? discount = 1 : discount = 0
discount *= @products[prod] - t_promotion[0]
discount *= @inventory.products[prod] * t_promotion[1] / 100
promotion = "| (" + t_promotion[1].to_s
promotion += "% off of every after the " + Ord.new.to_ord(t_promotion[0].to_s) + ")"
promotion = promotion.ljust(49) + "| " + sprintf("%8.2f", -discount) + " |\n"
[discount, promotion]
end
def use(coupon_name)
@coupon = @inventory.coupons[coupon_name]
@coupon_name = coupon_name
end
def print_coupon
coupon_str = "| Coupon " + @coupon_name + " - "
if @coupon != 0
coupon_str += @coupon > 0 ? @coupon.to_s + "%" : sprintf("%5.2f", -@coupon)
coupon_str = (coupon_str + " off").ljust(49) + "| "
coupon_str += sprintf("%8.2f", total - @total_before_coupon) + " |\n"
else
""
end
end
end
class Ord
#http://snippets.dzone.com/posts/show/593
def to_ord(num)
num = num.to_i
if (10...20) === num
"#{num}th"
else
g = %w{ th st nd rd th th th th th th }
a = num.to_s
c = a[-1..-1].to_i
a + g[c]
end
end
end

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

...................

Finished in 0.58695 seconds
19 examples, 0 failures

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

Николай обнови решението на 07.11.2011 03:31 (преди над 12 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class Inventory
+ attr_accessor :products, :promotions_gof, :promotions_p, :promotions_t, :coupons
+ def initialize
+ @products = {}
+ @promotions_gof = {}
+ @promotions_p = {}
+ @promotions_t = {}
+ @coupons = {}
+ end
+ def register(product, price, promotion = {})
+ price = BigDecimal(price)
+ if @products.has_key?(product) || product.size > 40 || !price.between?(0.01, 999.99)
+ raise "Invalid parameters passed."
+ else
+ @products[product] = price
+ register_promotion(product, promotion)
+ end
+ end
+ def register_promotion(product, promotion)
+ if(promotion.has_key?(:get_one_free))
+ @promotions_gof[product] = promotion[:get_one_free]
+ elsif(promotion.has_key?(:package))
+ promotion[:package].each { |key, value| @promotions_p[product] = [key,value] }
+ elsif(promotion.has_key?(:threshold))
+ promotion[:threshold].each { |key, value| @promotions_t[product] = [key,value] }
+ end
+ end
+ def register_coupon(name, discount)
+ if discount[:percent]
+ @coupons[name] = discount[:percent]
+ else
+ @coupons[name] = -BigDecimal(discount[:amount])
+ end
+ end
+ def new_cart
+ Cart.new(self)
+ end
+end
+
+class Cart
+ def initialize(inventory)
+ @products = {}
+ @inventory = inventory
+ @final_prices = {}
+ @coupon = 0
+ @coupon_name = ''
+ @total_before_coupon = 0
+ end
+ def add(product, quantity = 1)
+ if !@inventory.products.has_key?(product) || !quantity.between?(1, 99)
+ raise "Invalid parameters passed."
+ elsif @products.has_key?(product)
+ @products[product] += quantity
+ else
+ @products[product] = quantity
+ end
+ @final_prices[product] = @products[product] * @inventory.products[product]
+ end
+ def total
+ discount = 0
+ @products.each do |prod, qty|
+ discount += print_or_discount(prod, 'discount')
+ end
+ total = @final_prices.values.inject(:+) - discount
+ @total_before_coupon = total
+ @coupon > 0 ? total = total * (100 - @coupon) / 100 : 0
+ @coupon < 0 ? total = total > -@coupon ? total + @coupon : 0 : 0
+ total
+ end
+ def invoice
+ d = delimiter = "+------------------------------------------------+----------+\n"
+ invoice = d + "| " + "Name".ljust(43) + "qty | price |\n" + d
+ @products.each do |prod, qty|
+ invoice += "| " + prod.ljust(40) + " " + qty.to_s.rjust(2) + " | "
+ invoice += sprintf("%8.2f", @final_prices[prod]) + " |\n" + print_or_discount(prod)
+ end
+ invoice += print_coupon
+ invoice + d + "| " + "TOTAL".ljust(47) + "| " + sprintf("%8.2f", total) + " |\n" + d
+ end
+ def print_or_discount(prod, choose = 'print')
+ if(@inventory.promotions_gof.has_key?(prod))
+ choose == 'print' ? gof_promotion(prod)[1] : gof_promotion(prod)[0]
+ elsif(@inventory.promotions_p.has_key?(prod))
+ choose == 'print' ? p_promotion(prod)[1] : p_promotion(prod)[0]
+ elsif(@inventory.promotions_t.has_key?(prod))
+ choose == 'print' ? t_promotion(prod)[1] : t_promotion(prod)[0]
+ else
+ choose == 'print' ? "" : 0
+ end
+ end
+ def gof_promotion(prod)
+ gof_promotion = @inventory.promotions_gof[prod]
+ discount = @products[prod] / gof_promotion * @inventory.products[prod]
+ promotion = "| (buy " + (gof_promotion - 1).to_s + ", get 1 free)"
+ promotion = promotion.ljust(49) + "| " + sprintf("%8.2f", -discount) + " |\n"
+ [discount, promotion]
+ end
+ def p_promotion(prod)
+ p_promotion = @inventory.promotions_p[prod]
+ discount = @products[prod] / p_promotion[0] * @inventory.products[prod]
+ discount = discount * p_promotion[0] * p_promotion[1] / 100
+ promotion = "| (get " + p_promotion[1].to_s
+ promotion += "% off for every " + p_promotion[0].to_s + ")"
+ promotion = promotion.ljust(49) + "| " + sprintf("%8.2f", -discount) + " |\n"
+ [discount, promotion]
+ end
+ def t_promotion(prod)
+ t_promotion = @inventory.promotions_t[prod]
+ @products[prod] > t_promotion[0] ? discount = 1 : discount = 0
+ discount *= @products[prod] - t_promotion[0]
+ discount *= @inventory.products[prod] * t_promotion[1] / 100
+ promotion = "| (" + t_promotion[1].to_s
+ promotion += "% off of every after the " + Ord.new.to_ord(t_promotion[0].to_s) + ")"
+ promotion = promotion.ljust(49) + "| " + sprintf("%8.2f", -discount) + " |\n"
+ [discount, promotion]
+ end
+ def use(coupon_name)
+ @coupon = @inventory.coupons[coupon_name]
+ @coupon_name = coupon_name
+ end
+ def print_coupon
+ coupon_str = "| Coupon " + @coupon_name + " - "
+ if @coupon != 0
+ coupon_str += @coupon > 0 ? @coupon.to_s + "%" : sprintf("%5.2f", -@coupon)
+ coupon_str = (coupon_str + " off").ljust(49) + "| "
+ coupon_str += sprintf("%8.2f", total - @total_before_coupon) + " |\n"
+ else
+ ""
+ end
+ end
+end
+
+class Ord
+#http://snippets.dzone.com/posts/show/593
+ def to_ord(num)
+ num = num.to_i
+ if (10...20) === num
+ "#{num}th"
+ else
+ g = %w{ th st nd rd th th th th th th }
+ a = num.to_s
+ c = a[-1..-1].to_i
+ a + g[c]
+ end
+ end
+end