Решение на Трета задача от Деян Камбуров

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

Към профила на Деян Камбуров

Резултати

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

Код

require 'bigdecimal'
require 'bigdecimal/util'
class Inventory
attr_accessor :wares
def initialize
@wares = []
@coupons = []
end
def register(name, price, *promotion)
if(name.length > 40 or price.to_d < 0.01 or price.to_d > 999.99)
raise "Invalid parameters passed."
end
if(@wares.select{|x| x.name == name} != [] and @wares != [])
raise "Product already exist."
end
@wares << Ware.new(name, price, promotion)
end
def new_cart
ShopingCart.new(@wares, @coupons)
end
def register_coupon(name, hash)
@coupons << Coupon.new(name, hash)
end
end
class Coupon
attr_accessor :name, :type
def initialize(name, hash)
@name = name
@type = hash
end
end
class Ware
attr_accessor :name, :price, :promotion
def initialize(name, price, promotion)
@name = name
@price = price
@promotion = promotion
end
end
class ShopingCart
def initialize(wares, coupons)
@wares = wares
@coupons = coupons
@purchases = []
@coupon_discount = 0
@coupon_type
@coupon_name
end
def add(name,*quantity)
qty = quantity == [] ? 1 : quantity[0]
unless (@wares.map{|n| n.name}.include? name)
raise "Unexisiting product."
end
if (qty < 1 or qty > 99)
raise "Invalid parameters passed."
end
unless (@purchases.index{|x| x.name == name}.nil?)
@purchases[@purchases.index{|x| x.name == name}].quantity += qty
else
@purchases << Purchase.new(name, qty, @wares.find{|x| x.name == name}.price)
end
end
def promotion_price(purchase)
promo = @wares.find{|x| x.name == purchase.name}.promotion[0]
if(promo.nil? or @wares.find{|x| x.name == purchase.name}.promotion == [])
purchase.new_price = purchase.price.to_d * purchase.quantity
else
case promo.first.first
when :get_one_free then purchase.new_price = promo_get_one_free(purchase,promo)
when :threshold then purchase.new_price = promo_treshold(purchase,promo)
when :package then purchase.new_price = promo_package(purchase,promo)
end
end
end
def promo_get_one_free(purchase,promo)
purchase.price.to_d * (purchase.quantity - purchase.quantity / promo[:get_one_free])
end
def promo_treshold(purchase,promo)
key, value = promo[:threshold].first
qty = purchase.quantity
purchase.quantity > key ?
purchase.price.to_d * (qty - (qty - key) * value / 100.00)
: purchase.price.to_d * qty
end
def promo_package(purchase,promo)
key, value = promo[:package].first
pack = purchase.quantity / key
purchase.price.to_d * ((100 - value) / 100.00) * (key * pack) +
(purchase.quantity - (key * pack)) * purchase.price.to_d
end
def total
unless (@coupons == [])
use_coupon(@coupon_name)
end
result = @purchases.map{|x| promotion_price(x)}.inject(&:+) - @coupon_discount
sprintf("%.2f", result).to_d
end
def use_coupon(name_coupon)
if (@coupon_discount != 0) then raise "One coupon per cart available."
end
sum = @purchases.map{|x| promotion_price(x)}.inject(&:+)
@coupon_type = @coupons.find{|x| x.name == name_coupon}.type
@coupon_discount = case @coupon_type.first.first
when :percent
sum * (@coupon_type.first.last / 100.00)
when :amount
(sum - @coupon_type.first.last.to_d) < 0 ? sum : @coupon_type.first.last.to_d
end
end
def use(coupon_name)
@coupon_name = coupon_name
end
def invoice
total
r = Reciept.new(@purchases,@wares,@coupon_discount,@coupon_type,@coupon_name)
r.print_it
end
end
class Purchase
attr_accessor :name, :quantity, :price, :new_price
def initialize(name, quantity, price)
@name = name
@quantity = quantity
@price = price
@new_price
end
end
class Reciept
def initialize(purchases,wares,coupon_discount,coupon_type,coupon_name)
@purchases = purchases
@wares = wares
@coupon_discount = coupon_discount
@coupon_type = coupon_type
@coupon_name = coupon_name
end
def head_lines
lines = "+------------------------------------------------+----------+\n"
lines << "| Name qty | price |\n"
lines << "+------------------------------------------------+----------+\n"
lines
end
def product_lines(name,qty,price)
cost = price.to_d * qty
lines = "| #{sprintf("%-44s", name)}#{sprintf("%2d", qty)}"
lines << " |#{sprintf("%9.2f", cost)} |\n"
if (@wares.find{|n| n.name == name}.promotion[0].nil?) then lines << ""
else
case @wares.find{|n| n.name == name}.promotion[0].first.first
when :get_one_free then lines << line_get_one_free(name)
when :threshold then lines << line_threshold(name)
when :package then lines << line_package(name)
end
end
end
def line_get_one_free(name)
n = @wares.find{|n| n.name == name}.promotion[0][:get_one_free]
purchase = @purchases.find{|n| n.name == name}
discount = -(purchase.price.to_d * purchase.quantity - purchase.new_price)
txt ="(buy#{sprintf("%2d", n-1)}, get 1 free)"
"| #{sprintf("%-45s", txt)}|#{sprintf("%9.2f", discount)} |\n"
end
def line_threshold(name)
n = @wares.find{|n| n.name == name}.promotion[0][:threshold]
key, value = @wares.find{|n| n.name == name}.promotion[0][:threshold].first
purchase = @purchases.find{|n| n.name == name}
discount = -(purchase.price.to_d * purchase.quantity - purchase.new_price)
txt = "(#{sprintf("%2d", value)}% off of every after the#{print_count(key)})"
"| #{sprintf("%-45s", txt)}|#{sprintf("%9.2f", discount)} |\n"
end
def print_count(key)
case key
when 1 then "#{sprintf("%2d",key)}st"
when 2 then "#{sprintf("%2d",key)}nd"
when 3 then "#{sprintf("%2d",key)}rd"
when 4..9 then "#{sprintf("%2d",key)}th"
else "#{sprintf("%3d",key)}th"
end
end
def line_package(name)
n = @wares.find{|n| n.name == name}.promotion[0][:package]
key, value = @wares.find{|n| n.name == name}.promotion[0][:package].first
purchase = @purchases.find{|n| n.name == name}
discount = -(purchase.price.to_d * purchase.quantity - purchase.new_price.to_d)
txt ="(get#{sprintf("%3d", value)}% off for every#{sprintf("%2d", key)})"
"| #{sprintf("%-45s", txt)}|#{sprintf("%9.2f", discount)} |\n"
end
def total_line
result = (@purchases.map{|x| x.new_price}.inject(&:+) - @coupon_discount).to_s
lines = "+------------------------------------------------+----------+\n"
lines << "| #{sprintf("%-47s", "TOTAL")}|#{sprintf("%9.2f", result)} |\n"
lines << "+------------------------------------------------+----------+\n"
lines
end
def coupon_line
if (@coupon_discount == 0)
""
elsif (@coupon_type.first.first == :percent)
txt = "#{@coupon_name} -#{sprintf("%3d", @coupon_type.first.last)}% off"
"| Coupon #{sprintf("%-40s", txt)}|#{sprintf("%9.2f", -@coupon_discount)} |\n"
elsif (@coupon_type.first.first == :amount)
txt = "#{@coupon_name} -#{sprintf("%6.2f", @coupon_type.first.last.to_d)} off"
"| Coupon #{sprintf("%-40s", txt)}|#{sprintf("%9.2f", -@coupon_discount)} |\n"
end
end
def print_it
reciep = ''
reciep<<head_lines
@purchases.each do |n|
reciep<<product_lines(n.name, n.quantity, n.price)
end
reciep<<coupon_line
reciep<<total_line
reciep
end
end

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

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

Finished in 0.57641 seconds
19 examples, 0 failures

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

Деян обнови решението на 07.11.2011 14:13 (преди около 13 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class Inventory
+ attr_accessor :wares
+
+ def initialize
+ @wares = []
+ @coupons = []
+ end
+
+ def register(name, price, *promotion)
+ if(name.length > 40 or price.to_d < 0.01 or price.to_d > 999.99)
+ raise "Invalid parameters passed."
+ end
+ if(@wares.select{|x| x.name == name} != [] and @wares != [])
+ raise "Product already exist."
+ end
+ @wares << Ware.new(name, price, promotion)
+ end
+
+ def new_cart
+ ShopingCart.new(@wares, @coupons)
+ end
+
+ def register_coupon(name, hash)
+ @coupons << Coupon.new(name, hash)
+ end
+end
+
+class Coupon
+ attr_accessor :name, :type
+
+ def initialize(name, hash)
+ @name = name
+ @type = hash
+ end
+end
+
+class Ware
+ attr_accessor :name, :price, :promotion
+
+ def initialize(name, price, promotion)
+ @name = name
+ @price = price
+ @promotion = promotion
+ end
+end
+
+class ShopingCart
+ def initialize(wares, coupons)
+ @wares = wares
+ @coupons = coupons
+ @purchases = []
+ @coupon_discount = 0
+ @coupon_type
+ @coupon_name
+ end
+
+ def add(name,*quantity)
+ qty = quantity == [] ? 1 : quantity[0]
+ unless (@wares.map{|n| n.name}.include? name)
+ raise "Unexisiting product."
+ end
+ if (qty < 1 or qty > 99)
+ raise "Invalid parameters passed."
+ end
+ unless (@purchases.index{|x| x.name == name}.nil?)
+ @purchases[@purchases.index{|x| x.name == name}].quantity += qty
+ else
+ @purchases << Purchase.new(name, qty, @wares.find{|x| x.name == name}.price)
+ end
+ end
+
+ def promotion_price(purchase)
+ promo = @wares.find{|x| x.name == purchase.name}.promotion[0]
+ if(promo.nil? or @wares.find{|x| x.name == purchase.name}.promotion == [])
+ purchase.new_price = purchase.price.to_d * purchase.quantity
+ else
+ case promo.first.first
+ when :get_one_free then purchase.new_price = promo_get_one_free(purchase,promo)
+ when :threshold then purchase.new_price = promo_treshold(purchase,promo)
+ when :package then purchase.new_price = promo_package(purchase,promo)
+ end
+ end
+ end
+
+ def promo_get_one_free(purchase,promo)
+ purchase.price.to_d * (purchase.quantity - purchase.quantity / promo[:get_one_free])
+ end
+
+ def promo_treshold(purchase,promo)
+ key, value = promo[:threshold].first
+ qty = purchase.quantity
+ purchase.quantity > key ?
+ purchase.price.to_d * (qty - (qty - key) * value / 100.00)
+ : purchase.price.to_d * qty
+ end
+
+ def promo_package(purchase,promo)
+ key, value = promo[:package].first
+ pack = purchase.quantity / key
+ purchase.price.to_d * ((100 - value) / 100.00) * (key * pack) +
+ (purchase.quantity - (key * pack)) * purchase.price.to_d
+ end
+
+ def total
+ unless (@coupons == [])
+ use_coupon(@coupon_name)
+ end
+ result = @purchases.map{|x| promotion_price(x)}.inject(&:+) - @coupon_discount
+ sprintf("%.2f", result).to_d
+ end
+
+ def use_coupon(name_coupon)
+ if (@coupon_discount != 0) then raise "One coupon per cart available."
+ end
+ sum = @purchases.map{|x| promotion_price(x)}.inject(&:+)
+ @coupon_type = @coupons.find{|x| x.name == name_coupon}.type
+ @coupon_discount = case @coupon_type.first.first
+ when :percent
+ sum * (@coupon_type.first.last / 100.00)
+ when :amount
+ (sum - @coupon_type.first.last.to_d) < 0 ? sum : @coupon_type.first.last.to_d
+ end
+ end
+
+ def use(coupon_name)
+ @coupon_name = coupon_name
+ end
+
+ def invoice
+ total
+ r = Reciept.new(@purchases,@wares,@coupon_discount,@coupon_type,@coupon_name)
+ r.print_it
+ end
+end
+
+class Purchase
+ attr_accessor :name, :quantity, :price, :new_price
+
+ def initialize(name, quantity, price)
+ @name = name
+ @quantity = quantity
+ @price = price
+ @new_price
+ end
+end
+
+class Reciept
+ def initialize(purchases,wares,coupon_discount,coupon_type,coupon_name)
+ @purchases = purchases
+ @wares = wares
+ @coupon_discount = coupon_discount
+ @coupon_type = coupon_type
+ @coupon_name = coupon_name
+ end
+
+ def head_lines
+ lines = "+------------------------------------------------+----------+\n"
+ lines << "| Name qty | price |\n"
+ lines << "+------------------------------------------------+----------+\n"
+ lines
+ end
+
+ def product_lines(name,qty,price)
+ cost = price.to_d * qty
+ lines = "| #{sprintf("%-44s", name)}#{sprintf("%2d", qty)}"
+ lines << " |#{sprintf("%9.2f", cost)} |\n"
+ if (@wares.find{|n| n.name == name}.promotion[0].nil?) then lines << ""
+ else
+ case @wares.find{|n| n.name == name}.promotion[0].first.first
+ when :get_one_free then lines << line_get_one_free(name)
+ when :threshold then lines << line_threshold(name)
+ when :package then lines << line_package(name)
+ end
+ end
+ end
+
+ def line_get_one_free(name)
+ n = @wares.find{|n| n.name == name}.promotion[0][:get_one_free]
+ purchase = @purchases.find{|n| n.name == name}
+ discount = -(purchase.price.to_d * purchase.quantity - purchase.new_price)
+ txt ="(buy#{sprintf("%2d", n-1)}, get 1 free)"
+ "| #{sprintf("%-45s", txt)}|#{sprintf("%9.2f", discount)} |\n"
+ end
+
+ def line_threshold(name)
+ n = @wares.find{|n| n.name == name}.promotion[0][:threshold]
+ key, value = @wares.find{|n| n.name == name}.promotion[0][:threshold].first
+ purchase = @purchases.find{|n| n.name == name}
+ discount = -(purchase.price.to_d * purchase.quantity - purchase.new_price)
+ txt = "(#{sprintf("%2d", value)}% off of every after the#{print_count(key)})"
+ "| #{sprintf("%-45s", txt)}|#{sprintf("%9.2f", discount)} |\n"
+ end
+
+ def print_count(key)
+ case key
+ when 1 then "#{sprintf("%2d",key)}st"
+ when 2 then "#{sprintf("%2d",key)}nd"
+ when 3 then "#{sprintf("%2d",key)}rd"
+ when 4..9 then "#{sprintf("%2d",key)}th"
+ else "#{sprintf("%3d",key)}th"
+ end
+ end
+
+ def line_package(name)
+ n = @wares.find{|n| n.name == name}.promotion[0][:package]
+ key, value = @wares.find{|n| n.name == name}.promotion[0][:package].first
+ purchase = @purchases.find{|n| n.name == name}
+ discount = -(purchase.price.to_d * purchase.quantity - purchase.new_price.to_d)
+ txt ="(get#{sprintf("%3d", value)}% off for every#{sprintf("%2d", key)})"
+ "| #{sprintf("%-45s", txt)}|#{sprintf("%9.2f", discount)} |\n"
+ end
+
+ def total_line
+ result = (@purchases.map{|x| x.new_price}.inject(&:+) - @coupon_discount).to_s
+ lines = "+------------------------------------------------+----------+\n"
+ lines << "| #{sprintf("%-47s", "TOTAL")}|#{sprintf("%9.2f", result)} |\n"
+ lines << "+------------------------------------------------+----------+\n"
+ lines
+ end
+
+ def coupon_line
+ if (@coupon_discount == 0)
+ ""
+ elsif (@coupon_type.first.first == :percent)
+ txt = "#{@coupon_name} -#{sprintf("%3d", @coupon_type.first.last)}% off"
+ "| Coupon #{sprintf("%-40s", txt)}|#{sprintf("%9.2f", -@coupon_discount)} |\n"
+ elsif (@coupon_type.first.first == :amount)
+ txt = "#{@coupon_name} -#{sprintf("%6.2f", @coupon_type.first.last.to_d)} off"
+ "| Coupon #{sprintf("%-40s", txt)}|#{sprintf("%9.2f", -@coupon_discount)} |\n"
+ end
+ end
+
+ def print_it
+ reciep = ''
+ reciep<<head_lines
+ @purchases.each do |n|
+ reciep<<product_lines(n.name, n.quantity, n.price)
+ end
+ reciep<<coupon_line
+ reciep<<total_line
+ reciep
+ end
+end