Решение на Трета задача от Димо Станев

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

Към профила на Димо Станев

Резултати

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

Код

require 'bigdecimal'
require 'bigdecimal/util'
class PercentCoupon
attr_accessor :name, :percent
def initialize(name, coupon)
@name = name
@percent = coupon.values[0].to_s.to_d / 100
end
def calc(price)
[price - price * @percent, 0].max
end
end
class AmountCoupon
attr_accessor :name, :amount
def initialize(name, amount)
@name = name
@amount = amount.values[0].class == String ? amount.values[0].to_d : amount.values[0]
end
def calc(price)
[price - amount, 0].max
end
end
class Inventory
attr_accessor :products, :coupons
def initialize
@products = {}
@coupons = {}
end
def register(name, price, promo = {})
if @products.key? name or name.size > 40 or price.to_d < 0.01 or price.to_d > 999.99
raise "Invalid parameters passed."
end
case promo.keys[0]
when :get_one_free then @products[name] = GetOneFreeProduct.new(name,price,promo)
when :package then @products[name] = PackageDiscountProduct.new(name,price,promo)
when :threshold then @products[name] = ThresHoldProduct.new(name,price,promo)
else @products[name] = Product.new(name, price)
end
end
def register_coupon(name,coupon)
case coupon.keys[0]
when :percent then @coupons[name] = PercentCoupon.new(name,coupon)
when :amount then @coupons[name] = AmountCoupon.new(name,coupon)
end
end
def new_cart
Cart.new(@products, @coupons)
end
end
class Printer
def print(product, quantity)
if(product.class == Product)
return print_product(product, quantity)
end
if(product.class == GetOneFreeProduct)
return print_one_free_product(product, quantity)
end
if(product.class == PackageDiscountProduct)
return print_package_discount_product(product, quantity)
end
if(product.class == ThresHoldProduct)
return print_thres_hold_product(product, quantity)
end
end
def print_product(product, qty)
tmp = 46 - qty.to_s.size
price = ("%4.2f" % (product.price * qty) ) + " |"
"| " + product.name.ljust(tmp) + qty.to_s + " |" + price.rjust(11) + "\n"
end
def print_one_free_product(product, qty)
p = print_product(product, qty)
tmp = ("| (buy " + (product.number - 1).to_s + ", get 1 free)").ljust(49) + "|"
p + tmp + ("%4.2f" % (product.get_discount(qty).to_f).to_s + " |").rjust(11) + "\n"
end
def print_package_discount_product(product, qty)
p = print_product(product, qty)
k, v = product.package.keys[0], product.package.values[0]
tmp = ("| (get " + v.to_s + "% off for every " + k.to_s + ")").ljust(49) + "|"
p + tmp + ("%4.2f" % (product.get_discount(qty).to_f).to_s + " |").rjust(11) + "\n"
end
def print_thres_hold_product(product, qty)
p = print_product(product, qty)
k, v = product.threshold.keys[0], product.threshold.values[0]
tmp = ("| (" + v.to_s + "% off of every after the " + suf(k) + ")").ljust(49) + "|"
p + tmp + ("%4.2f" % (product.get_discount(qty).to_f).to_s + " |").rjust(11) + "\n"
end
def suf(number)
if(number >= 4 and number <= 20)
return number.to_s + "th"
end
case number % 10
when 1 then number.to_s + "st"
when 2 then number.to_s + "nd"
when 3 then number.to_s + "rd"
else number.to_s + "th"
end
end
def print_total(sum)
line = "+------------------------------------------------+----------+\n"
total = "| TOTAL |"
line + total + (("%4.2f" % sum.to_f).to_s + " |").rjust(11) + "\n" + line
end
def print_coupon(coupon, price)
if(coupon.class == AmountCoupon)
print_amount_coupon(coupon,price)
else
print_percent_coupon(coupon,price)
end
end
def print_percent_coupon(coupon, price)
percent = (coupon.percent * 100).to_f.round(0).to_s
tmp = ("| Coupon " + coupon.name + " - " + percent + "% off").ljust(49) + "|"
tmp + ("-" + ("%4.2f" % price.to_f).to_s + " |").rjust(11) + "\n"
end
def print_amount_coupon(coupon, price)
amount = ("%4.2f" % coupon.amount.to_f).to_s
tmp = ("| Coupon " + coupon.name + " - " + amount + " off").ljust(49) + "|"
tmp + ("-" + ("%4.2f" % price.to_f).to_s + " |").rjust(11) + "\n"
end
end
class Cart
attr_accessor :products, :inventary, :coupons, :used_c
def initialize(inventary, coupons)
@products = {}
@inventary = inventary
@coupons = coupons
@used_c = nil
end
def add(product, quantity = 1)
if not @inventary.key? product or quantity > 99 or quantity <= 0
raise "Invalid parameters passed."
end
if @products.key? product
@products[product] += quantity
else
@products[product] = quantity
end
end
def use(name)
if not @coupons.key? name
raise "Invalid parameters passed."
end
if @used_c != nil
return
end
@used_c = @coupons[name]
end
def total
price = @products.to_a.inject(0) { |a, b| a + @inventary[b[0]].calc_price(b[1]) }
if @used_c != nil
price = @used_c.calc(price)
end
price
end
def get_discount
@products.to_a.inject(0) { |a, b| a + @inventary[b[0]].calc_price(b[1]) } - total
end
def invoice
start = "+------------------------------------------------+----------+
| Name qty | price |
+------------------------------------------------+----------+\n"
p = Printer.new
tmp = @products.to_a.inject(start) { |a, b| a + p.print(@inventary[b[0]], b[1]) }
if @used_c != nil
tmp += p.print_coupon(@used_c, get_discount)
end
tmp + p.print_total(total)
end
end
class Product
attr_accessor :name, :price
def initialize(name, price)
@name = name
@price = price.to_d
end
def calc_price(quantity)
quantity * @price
end
def get_discount(quantity)
- (quantity * @price - calc_price(quantity))
end
end
class GetOneFreeProduct < Product
attr_accessor :number
def initialize(name, price, promotion)
super(name, price)
@number = promotion[:get_one_free]
end
def calc_price(quantity)
(quantity - (quantity / @number)) * @price
end
end
class PackageDiscountProduct < Product
attr_accessor :package
def initialize(name, price, promotion)
super(name, price)
@package = promotion[:package]
end
def calc_price(quantity)
number = @package.keys[0]
percent = (@package.values[0] / 100.0).to_s.to_d
quantity * @price - ((quantity / number) * @price * percent * number)
end
end
class ThresHoldProduct < Product
attr_accessor :threshold
def initialize(name, price, promotion)
super(name, price)
@threshold = promotion[:threshold]
end
def calc_price(quantity)
number = @threshold.keys[0]
percent = (@threshold.values[0] / 100.0).to_s.to_d
if quantity <= number
quantity * @price
else
quantity * @price - ((quantity - number) * @price * percent)
end
end
end

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

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

Finished in 0.58446 seconds
19 examples, 0 failures

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

Димо обнови решението на 04.11.2011 17:14 (преди над 12 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class PercentCoupon
+
+ attr_accessor :name, :percent
+
+ def initialize(name, coupon)
+ @name = name
+ @percent = coupon.values[0].to_s.to_d / 100
+ end
+
+ def calc(price)
+ [price - price * @percent, 0].max
+ end
+end
+
+class AmountCoupon
+
+ attr_accessor :name, :amount
+
+ def initialize(name, amount)
+ @name = name
+ @amount = amount.values[0].class == String ? amount.values[0].to_d : amount.values[0]
+ end
+
+ def calc(price)
+ [price - amount, 0].max
+ end
+end
+
+class Inventory
+
+ attr_accessor :products, :coupons
+
+ def initialize
+ @products = {}
+ @coupons = {}
+ end
+
+ def register(name, price, promo = {})
+ if @products.key? name or name.size > 40 or price.to_d < 0.01 or price.to_d > 999.99
+ raise "Invalid parameters passed."
+ end
+ case promo.keys[0]
+ when :get_one_free then @products[name] = GetOneFreeProduct.new(name,price,promo)
+ when :package then @products[name] = PackageDiscountProduct.new(name,price,promo)
+ when :threshold then @products[name] = ThresHoldProduct.new(name,price,promo)
+ else @products[name] = Product.new(name, price)
+ end
+ end
+
+ def register_coupon(name,coupon)
+ case coupon.keys[0]
+ when :percent then @coupons[name] = PercentCoupon.new(name,coupon)
+ when :amount then @coupons[name] = AmountCoupon.new(name,coupon)
+ end
+ end
+
+ def new_cart
+ Cart.new(@products, @coupons)
+ end
+end
+
+class Printer
+
+ def print(product, quantity)
+ if(product.class == Product)
+ return print_product(product, quantity)
+ end
+ if(product.class == GetOneFreeProduct)
+ return print_one_free_product(product, quantity)
+ end
+ if(product.class == PackageDiscountProduct)
+ return print_package_discount_product(product, quantity)
+ end
+ if(product.class == ThresHoldProduct)
+ return print_thres_hold_product(product, quantity)
+ end
+end
+
+ def print_product(product, qty)
+ tmp = 46 - qty.to_s.size
+ price = ("%4.2f" % (product.price * qty) ) + " |"
+
+ "| " + product.name.ljust(tmp) + qty.to_s + " |" + price.rjust(11) + "\n"
+ end
+
+ def print_one_free_product(product, qty)
+ p = print_product(product, qty)
+ tmp = ("| (buy " + (product.number - 1).to_s + ", get 1 free)").ljust(49) + "|"
+ p + tmp + ("%4.2f" % (product.get_discount(qty).to_f).to_s + " |").rjust(11) + "\n"
+ end
+
+ def print_package_discount_product(product, qty)
+ p = print_product(product, qty)
+ k, v = product.package.keys[0], product.package.values[0]
+ tmp = ("| (get " + v.to_s + "% off for every " + k.to_s + ")").ljust(49) + "|"
+ p + tmp + ("%4.2f" % (product.get_discount(qty).to_f).to_s + " |").rjust(11) + "\n"
+ end
+
+ def print_thres_hold_product(product, qty)
+ p = print_product(product, qty)
+ k, v = product.threshold.keys[0], product.threshold.values[0]
+ tmp = ("| (" + v.to_s + "% off of every after the " + suf(k) + ")").ljust(49) + "|"
+ p + tmp + ("%4.2f" % (product.get_discount(qty).to_f).to_s + " |").rjust(11) + "\n"
+ end
+
+ def suf(number)
+ if(number >= 4 and number <= 20)
+ return number.to_s + "th"
+ end
+ case number % 10
+ when 1 then number.to_s + "st"
+ when 2 then number.to_s + "nd"
+ when 3 then number.to_s + "rd"
+ else number.to_s + "th"
+ end
+ end
+
+ def print_total(sum)
+ line = "+------------------------------------------------+----------+\n"
+ total = "| TOTAL |"
+ line + total + (("%4.2f" % sum.to_f).to_s + " |").rjust(11) + "\n" + line
+ end
+
+ def print_coupon(coupon, price)
+ if(coupon.class == AmountCoupon)
+ print_amount_coupon(coupon,price)
+ else
+ print_percent_coupon(coupon,price)
+ end
+ end
+
+ def print_percent_coupon(coupon, price)
+ percent = (coupon.percent * 100).to_f.round(0).to_s
+ tmp = ("| Coupon " + coupon.name + " - " + percent + "% off").ljust(49) + "|"
+ tmp + ("-" + ("%4.2f" % price.to_f).to_s + " |").rjust(11) + "\n"
+ end
+
+ def print_amount_coupon(coupon, price)
+ amount = ("%4.2f" % coupon.amount.to_f).to_s
+ tmp = ("| Coupon " + coupon.name + " - " + amount + " off").ljust(49) + "|"
+ tmp + ("-" + ("%4.2f" % price.to_f).to_s + " |").rjust(11) + "\n"
+ end
+end
+
+class Cart
+
+ attr_accessor :products, :inventary, :coupons, :used_c
+
+ def initialize(inventary, coupons)
+ @products = {}
+ @inventary = inventary
+ @coupons = coupons
+ @used_c = nil
+ end
+
+ def add(product, quantity = 1)
+ if not @inventary.key? product or quantity > 99 or quantity <= 0
+ raise "Invalid parameters passed."
+ end
+ if @products.key? product
+ @products[product] += quantity
+ else
+ @products[product] = quantity
+ end
+ end
+
+ def use(name)
+ if not @coupons.key? name
+ raise "Invalid parameters passed."
+ end
+ if @used_c != nil
+ return
+ end
+ @used_c = @coupons[name]
+ end
+
+ def total
+ price = @products.to_a.inject(0) { |a, b| a + @inventary[b[0]].calc_price(b[1]) }
+ if @used_c != nil
+ price = @used_c.calc(price)
+ end
+ price
+ end
+
+ def get_discount
+ @products.to_a.inject(0) { |a, b| a + @inventary[b[0]].calc_price(b[1]) } - total
+ end
+
+ def invoice
+ start = "+------------------------------------------------+----------+
+| Name qty | price |
++------------------------------------------------+----------+\n"
+ p = Printer.new
+ tmp = @products.to_a.inject(start) { |a, b| a + p.print(@inventary[b[0]], b[1]) }
+ if @used_c != nil
+ tmp += p.print_coupon(@used_c, get_discount)
+ end
+ tmp + p.print_total(total)
+ end
+end
+
+class Product
+
+ attr_accessor :name, :price
+
+ def initialize(name, price)
+ @name = name
+ @price = price.to_d
+ end
+
+ def calc_price(quantity)
+ quantity * @price
+ end
+ def get_discount(quantity)
+ - (quantity * @price - calc_price(quantity))
+ end
+end
+
+class GetOneFreeProduct < Product
+
+ attr_accessor :number
+
+ def initialize(name, price, promotion)
+ super(name, price)
+ @number = promotion[:get_one_free]
+ end
+
+ def calc_price(quantity)
+ (quantity - (quantity / @number)) * @price
+ end
+end
+
+class PackageDiscountProduct < Product
+
+ attr_accessor :package
+
+ def initialize(name, price, promotion)
+ super(name, price)
+ @package = promotion[:package]
+ end
+
+ def calc_price(quantity)
+ number = @package.keys[0]
+ percent = (@package.values[0] / 100.0).to_s.to_d
+ quantity * @price - ((quantity / number) * @price * percent * number)
+ end
+end
+
+class ThresHoldProduct < Product
+
+ attr_accessor :threshold
+
+ def initialize(name, price, promotion)
+ super(name, price)
+ @threshold = promotion[:threshold]
+ end
+
+ def calc_price(quantity)
+ number = @threshold.keys[0]
+ percent = (@threshold.values[0] / 100.0).to_s.to_d
+ if quantity <= number
+ quantity * @price
+ else
+ quantity * @price - ((quantity - number) * @price * percent)
+ end
+ end
+end