Решение на Трета задача от Ростислав Георгиев

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

Към профила на Ростислав Георгиев

Резултати

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

Код

require 'bigdecimal'
require 'bigdecimal/util'
module InvoiceGenerator
def gen_line(name, price, quantity = nil)
if quantity
"| %-40s %5d | %8.2f |\n" % [name, quantity, price]
else
"| %-46s | %8.2f |\n" % [name, price]
end
end
def border_row
"+------------------------------------------------+----------+\n"
end
def invoice_header
border_row <<
"| Name qty | price |\n" <<
border_row
end
def invoice_footer(total)
border_row <<
gen_line("TOTAL", total) <<
border_row
end
end
class Promotion_get_one_free
include InvoiceGenerator
def initialize(commodity, nth_free)
@commodity = commodity
@nth_free = nth_free
end
def discount(qty)
-1 * @commodity.price * (qty / @nth_free)
end
def to_invoice(qty)
gen_line " (buy #{@nth_free-1}, get 1 free)", discount(qty)
end
end
class Promotion_package
include InvoiceGenerator
def initialize(commodity, package)
@commodity = commodity
flat_pack = package.flatten
@quantity = flat_pack[0]
@percentage = flat_pack[1]
end
def discount(qty)
-1 * (qty / @quantity) * @quantity * (@percentage / '100'.to_d) * @commodity.price
end
def to_invoice(qty)
gen_line " (get #{@percentage}% off for every #{@quantity})", discount(qty)
end
end
class Promotion_threshold
include InvoiceGenerator
def initialize(commodity, threshold)
@commodity = commodity
flat_threshold = threshold.flatten
@quantity = flat_threshold[0]
@percentage = flat_threshold[1]
end
def discount(qty)
if qty > @quantity
-1 * (qty - @quantity) * (@percentage / '100'.to_d) * @commodity.price
else
0
end
end
def to_invoice(qty)
ords = ["th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"] * 10
ords[11] = ords[12] = ords[13] = "th"
ordinized = "#{@quantity}#{ords[@quantity % 100]}"
gen_line " (#{@percentage}% off of every after the #{ordinized})", discount(qty)
end
end
class Coupon_percent
include InvoiceGenerator
def initialize(name, percent)
@name = name
@percent = percent
end
def discount(price)
-1 * price * (@percent / '100'.to_d)
end
def to_invoice(price)
gen_line "Coupon #{@name} - #{@percent}% off", discount(price)
end
end
class Coupon_amount
include InvoiceGenerator
def initialize(name, amount)
@name = name
@amount = amount.to_s.to_d
end
def discount(price)
price - @amount > 0.00 ? -@amount : -price
end
def to_invoice(price)
gen_line "Coupon %s - %.2f off" % [@name, @amount], discount(price)
end
end
class Commodity
include InvoiceGenerator
attr_reader :name, :price
def initialize(name, price, promo_hash = {})
raise "Name too long!" if name.length > 40
raise "Price out of bounds!" if price.to_d < 0.01 or price.to_d > 999.99
@name = name
@price = price.to_d
promo_arr = promo_hash.flatten
unless promo_arr == []
class_name = "Promotion_" + promo_arr[0].to_s
@promotion = Object.const_get(class_name).new(self, promo_arr[1])
end
end
def eql?(other)
other.name == name
end
def price_for(quantity)
result = @price * quantity
result += @promotion.discount(quantity) if @promotion
result
end
def to_invoice(quantity)
result = gen_line @name, @price * quantity, quantity
result << @promotion.to_invoice(quantity) if @promotion
result
end
end
class Cart
include InvoiceGenerator
def initialize(inventory)
@inventory = inventory
@coupon = nil
@commodities = Hash.new(0)
end
def add(com_name, quantity = 1)
commodity = @inventory.get_commodity com_name
raise "Unknown commodity \"#{com_name}\"" unless commodity
qty = @commodities[commodity] + quantity
raise "Bad quantity in shopping cart!" if qty <= 0 or qty > 99
@commodities[commodity] = qty
end
def use(coupon_name)
@coupon = @inventory.get_coupon coupon_name
end
def total
result = '0'.to_d
@commodities.each_pair { |com, qty| result += com.price_for qty }
result += @coupon.discount result if @coupon
result
end
def invoice
result = invoice_header
tot = '0'.to_d
@commodities.each_pair do |com, qty|
result << com.to_invoice(qty)
tot += com.price_for qty
end
result << @coupon.to_invoice(tot) if @coupon
result << invoice_footer(total)
result
end
end
class Inventory
def initialize
@commodities = {}
@coupons = {}
end
def register(name, *args)
raise "Commodity already registered!" if @commodities.key? name
@commodities[name] = Commodity.new name, *args
end
def register_coupon(name, type)
type_arr = type.flatten
class_name = "Coupon_" + type_arr[0].to_s
@coupons[name] = Object.const_get(class_name).new(name, type_arr[1])
end
def new_cart
Cart.new self
end
def get_commodity(name)
@commodities[name]
end
def get_coupon(name)
@coupons[name]
end
end

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

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

Finished in 0.57167 seconds
19 examples, 0 failures

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

Ростислав обнови решението на 05.11.2011 21:24 (преди над 12 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+module InvoiceGenerator
+
+ def gen_line(name, price, quantity = nil)
+ if quantity
+ "| %-40s %5d | %8.2f |\n" % [name, quantity, price]
+ else
+ "| %-46s | %8.2f |\n" % [name, price]
+ end
+ end
+
+ def border_row
+ "+------------------------------------------------+----------+\n"
+ end
+
+ def invoice_header
+ border_row <<
+ "| Name qty | price |\n" <<
+ border_row
+ end
+
+ def invoice_footer(total)
+ border_row <<
+ gen_line("TOTAL", total) <<
+ border_row
+ end
+end
+
+class Promotion_get_one_free
+ include InvoiceGenerator
+
+ def initialize(commodity, nth_free)
+ @commodity = commodity
+ @nth_free = nth_free
+ end
+
+ def discount(qty)
+ -1 * @commodity.price * (qty / @nth_free)
+ end
+
+ def to_invoice(qty)
+ gen_line " (buy #{@nth_free-1}, get 1 free)", discount(qty)
+ end
+end
+
+class Promotion_package
+ include InvoiceGenerator
+
+ def initialize(commodity, package)
+ @commodity = commodity
+ flat_pack = package.flatten
+ @quantity = flat_pack[0]
+ @percentage = flat_pack[1]
+ end
+
+ def discount(qty)
+ -1 * (qty / @quantity) * @quantity * (@percentage / '100'.to_d) * @commodity.price
+ end
+
+ def to_invoice(qty)
+ gen_line " (get #{@percentage}% off for every #{@quantity})", discount(qty)
+ end
+end
+
+class Promotion_threshold
+ include InvoiceGenerator
+
+ def initialize(commodity, threshold)
+ @commodity = commodity
+ flat_threshold = threshold.flatten
+ @quantity = flat_threshold[0]
+ @percentage = flat_threshold[1]
+ end
+
+ def discount(qty)
+ if qty > @quantity
+ -1 * (qty - @quantity) * (@percentage / '100'.to_d) * @commodity.price
+ else
+ 0
+ end
+ end
+
+ def to_invoice(qty)
+ ords = ["th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"] * 10
+ ords[11] = ords[12] = ords[13] = "th"
+ ordinized = "#{@quantity}#{ords[@quantity % 100]}"
+ gen_line " (#{@percentage}% off of every after the #{ordinized})", discount(qty)
+ end
+end
+
+class Coupon_percent
+ include InvoiceGenerator
+
+ def initialize(name, percent)
+ @name = name
+ @percent = percent
+ end
+
+ def discount(price)
+ -1 * price * (@percent / '100'.to_d)
+ end
+
+ def to_invoice(price)
+ gen_line "Coupon #{@name} - #{@percent}% off", discount(price)
+ end
+end
+
+class Coupon_amount
+ include InvoiceGenerator
+
+ def initialize(name, amount)
+ @name = name
+ @amount = amount.to_s.to_d
+ end
+
+ def discount(price)
+ price - @amount > 0.00 ? -@amount : -price
+ end
+
+ def to_invoice(price)
+ gen_line "Coupon %s - %.2f off" % [@name, @amount], discount(price)
+ end
+end
+
+class Commodity
+ include InvoiceGenerator
+
+ attr_reader :name, :price
+
+ def initialize(name, price, promo_hash = {})
+ raise "Name too long!" if name.length > 40
+ raise "Price out of bounds!" if price.to_d < 0.01 or price.to_d > 999.99
+ @name = name
+ @price = price.to_d
+ promo_arr = promo_hash.flatten
+ unless promo_arr == []
+ class_name = "Promotion_" + promo_arr[0].to_s
+ @promotion = Object.const_get(class_name).new(self, promo_arr[1])
+ end
+ end
+
+ def eql?(other)
+ other.name == name
+ end
+
+ def price_for(quantity)
+ result = @price * quantity
+ result += @promotion.discount(quantity) if @promotion
+ result
+ end
+
+ def to_invoice(quantity)
+ result = gen_line @name, @price * quantity, quantity
+ result << @promotion.to_invoice(quantity) if @promotion
+ result
+ end
+end
+
+class Cart
+ include InvoiceGenerator
+
+ def initialize(inventory)
+ @inventory = inventory
+ @coupon = nil
+ @commodities = Hash.new(0)
+ end
+
+ def add(com_name, quantity = 1)
+ commodity = @inventory.get_commodity com_name
+ raise "Unknown commodity \"#{com_name}\"" unless commodity
+
+ qty = @commodities[commodity] + quantity
+ raise "Bad quantity in shopping cart!" if qty <= 0 or qty > 99
+ @commodities[commodity] = qty
+ end
+
+ def use(coupon_name)
+ @coupon = @inventory.get_coupon coupon_name
+ end
+
+ def total
+ result = '0'.to_d
+ @commodities.each_pair { |com, qty| result += com.price_for qty }
+ result += @coupon.discount result if @coupon
+ result
+ end
+
+ def invoice
+ result = invoice_header
+ tot = '0'.to_d
+ @commodities.each_pair do |com, qty|
+ result << com.to_invoice(qty)
+ tot += com.price_for qty
+ end
+ result << @coupon.to_invoice(tot) if @coupon
+ result << invoice_footer(total)
+ result
+ end
+end
+
+class Inventory
+ def initialize
+ @commodities = {}
+ @coupons = {}
+ end
+
+ def register(name, *args)
+ raise "Commodity already registered!" if @commodities.key? name
+ @commodities[name] = Commodity.new name, *args
+ end
+
+ def register_coupon(name, type)
+ type_arr = type.flatten
+ class_name = "Coupon_" + type_arr[0].to_s
+ @coupons[name] = Object.const_get(class_name).new(name, type_arr[1])
+ end
+
+ def new_cart
+ Cart.new self
+ end
+
+ def get_commodity(name)
+ @commodities[name]
+ end
+
+ def get_coupon(name)
+ @coupons[name]
+ end
+end