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

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

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

Резултати

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

Код

require 'bigdecimal'
require 'bigdecimal/util'
class Inventory
attr_accessor :products, :promo, :coupons
def initialize
@products = {}
@promo = {}
@coupons = {}
end
def available?(pr_name)
@products.has_key? pr_name
end
def check_product(pr_name, pr_price)
if pr_name.length > 40
raise "Product name too long. Only 40 symbols allowed."
end
if pr_price.to_d < 0.01 or pr_price.to_d > 999.99
raise "Product not in the available price range."
end
if available?(pr_name)
raise "Product already in inventory. You cannot add it twice."
end
end
def fst_key hash
hash.first[1].keys[0]
end
def fst_val hash
hash.first[1].values[0]
end
def register(pr_name, pr_price, prom = {})
check_product(pr_name, pr_price)
@products[pr_name] = pr_price.to_d
@promo[pr_name] = case prom.keys[0]
when :get_one_free then Get_nth_free.new(prom.values[0], pr_price)
when :package then N_pack.new(fst_key(prom), fst_val(prom), pr_price)
when :threshold then Aft_n.new(fst_key(prom), fst_val(prom), pr_price)
else nil
end
end
def new_cart
Cart.new(self)
end
def register_coupon name, type
@coupons[name] = case type.keys[0]
when :percent then Coupon_percent.new(name, type.values[0])
when :amount then Coupon_amount.new(name, type.values[0])
end
end
end
class Cart
attr_accessor :inv_reff, :prod_counts
def initialize inventory
@inv_reff, @prod_counts = inventory, {}
@coupon = nil
end
def valid_params(pr_name, pr_count)
unless @inv_reff.available? pr_name
raise "Product not available in inventory."
end
if pr_count <= 0 or (@prod_counts[pr_name] + pr_count) > 99
raise "Invalid quantity number. It should be between 1 and 99."
end
end
def add(pr_name, pr_count = nil)
pr_count = pr_count == nil ? 1 : pr_count
unless @prod_counts.has_key? pr_name
@prod_counts[pr_name] = 0
end
valid_params(pr_name, pr_count)
@prod_counts[pr_name] += pr_count.to_s.to_d
end
def prod_total pr_name
pr_tot = @inv_reff.products[pr_name] * @prod_counts[pr_name]
if @inv_reff.promo[pr_name] != nil
pr_tot -= @inv_reff.promo[pr_name].discount(@prod_counts[pr_name])
end
pr_tot
end
def total
tot = '0'.to_d
@prod_counts.each_key do |elem|
tot += prod_total(elem)
end
@coupon == nil ? tot : (tot - @coupon.discount(tot))
end
def prom_inf name, count
str = ""
if @inv_reff.promo[name] != nil
desc = @inv_reff.promo[name].description
disc_val = "%.2f" % (-@inv_reff.promo[name].discount(count))
str += "| #{desc}#{' ' * (45 - desc.length)}|"
str += "#{' ' * (9 - disc_val.length)}#{disc_val} |\n"
end
str
end
def prod_inf str = ""
@prod_counts.each_key do |elem|
str += "| #{elem + ' ' * (42 - elem.length)}"
str += "#{' ' * (4 - @prod_counts[elem].to_i.to_s.length)}"
str += "#{@prod_counts[elem].to_i} | "
prod_pr = "%.2f" % (@prod_counts[elem] * @inv_reff.products[elem])
str += "#{' ' * (8 - prod_pr.length)}#{prod_pr} |\n"
str += prom_inf(elem, @prod_counts[elem])
end
str
end
def coupon_inf str = ""
unless @coupon == nil
str += "| #{@coupon.description}#{' ' * (47 - @coupon.description.length)}|"
dsc = "%.2f" % (total - @coupon.before_disc)
str += "#{' ' * (9 - dsc.length)}#{dsc} |\n"
end
str
end
def invoice
str = "+#{'-' * 48}+#{'-' * 10}+\n| Name#{' ' * 39}qty |#{' '* 4 }price |"
str += "\n+#{'-' * 48}+#{'-' * 10}+\n" + prod_inf + coupon_inf
str += "+#{'-' * 48}+#{'-' * 10}+\n| TOTAL#{' ' * 42}|"
tot = "%.2f" % total
str += "#{' ' * (9 - tot.length)}#{tot} |\n"
str += "+#{'-' * 48}+#{'-' * 10}+\n"
end
def use coup_name
unless @inv_reff.coupons.has_key? coup_name
raise "Coupon not registered."
end
@coupon = @inv_reff.coupons[coup_name]
end
end
class Get_nth_free
def initialize prom_n, each_price
@prom_n, @each_price, = prom_n.to_s.to_d, each_price.to_s.to_d
end
def discount pr_count
(pr_count.to_s.to_d / @prom_n).to_i.to_s.to_d * @each_price
end
def description
"(buy #{@prom_n.to_i - 1}, get 1 free)"
end
end
class N_pack
def initialize prom_n, prom_perc, each_price
@prom_n, @prom_perc = prom_n.to_s.to_d, prom_perc.to_s.to_d
@each_price = each_price.to_s.to_d
@pack_discount = (@prom_n * @each_price) * '0.01'.to_d * @prom_perc
end
def discount pr_count
(pr_count / @prom_n).to_i.to_s.to_d * @pack_discount
end
def description
"(get #{@prom_perc.to_i}% off for every #{@prom_n.to_i})"
end
end
class Aft_n
def initialize prom_n, prom_perc, each_price
@prom_n, @prom_perc = prom_n.to_s.to_d, prom_perc.to_s.to_d
@each_price = each_price.to_s.to_d
@each_disc = @each_price * '0.01'.to_d * @prom_perc
end
def discount pr_count
if pr_count.to_s.to_d < @prom_n
return '0'.to_d
end
(pr_count.to_s.to_d - @prom_n) * @each_disc
end
def description
prom_n_str = case @prom_n.to_f
when 1.00 then "1st"
when 2.00 then "2nd"
when 3.00 then "3rd"
else "#{@prom_n.to_i}th"
end
"(#{@prom_perc.to_i}% off of every after the #{prom_n_str})"
end
end
class Coupon_percent
def initialize name, perc
@name, @perc, @before_disc = name, perc.to_s.to_d, '0'.to_d
end
def before_disc
@before_disc
end
def discount total
@before_disc = total
total.to_s.to_d * '0.01'.to_d * @perc
end
def description
"Coupon #{@name} - #{@perc.to_i}% off"
end
end
class Coupon_amount
def initialize name, price
@name, @price, @before_disc = name, price.to_s.to_d, '0'.to_d
end
def before_disc
@before_disc
end
def discount total
@before_disc = total
total.to_s.to_d > @price ? @price : total.to_s.to_d
end
def description
"Coupon #{@name} - #{"%.2f" % @price} off"
end
end

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

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

Finished in 0.5692 seconds
19 examples, 0 failures

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

Константин обнови решението на 07.11.2011 14:40 (преди над 12 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class Inventory
+attr_accessor :products, :promo, :coupons
+
+def initialize
+ @products = {}
+ @promo = {}
+ @coupons = {}
+end
+
+def available?(pr_name)
+ @products.has_key? pr_name
+end
+
+def check_product(pr_name, pr_price)
+ if pr_name.length > 40
+ raise "Product name too long. Only 40 symbols allowed."
+ end
+ if pr_price.to_d < 0.01 or pr_price.to_d > 999.99
+ raise "Product not in the available price range."
+ end
+ if available?(pr_name)
+ raise "Product already in inventory. You cannot add it twice."
+ end
+end
+
+def fst_key hash
+ hash.first[1].keys[0]
+end
+
+def fst_val hash
+ hash.first[1].values[0]
+end
+
+def register(pr_name, pr_price, prom = {})
+ check_product(pr_name, pr_price)
+ @products[pr_name] = pr_price.to_d
+ @promo[pr_name] = case prom.keys[0]
+ when :get_one_free then Get_nth_free.new(prom.values[0], pr_price)
+ when :package then N_pack.new(fst_key(prom), fst_val(prom), pr_price)
+ when :threshold then Aft_n.new(fst_key(prom), fst_val(prom), pr_price)
+ else nil
+ end
+end
+
+def new_cart
+ Cart.new(self)
+end
+
+def register_coupon name, type
+ @coupons[name] = case type.keys[0]
+ when :percent then Coupon_percent.new(name, type.values[0])
+ when :amount then Coupon_amount.new(name, type.values[0])
+ end
+end
+
+end
+
+class Cart
+attr_accessor :inv_reff, :prod_counts
+
+def initialize inventory
+ @inv_reff, @prod_counts = inventory, {}
+ @coupon = nil
+end
+
+def valid_params(pr_name, pr_count)
+ unless @inv_reff.available? pr_name
+ raise "Product not available in inventory."
+ end
+ if pr_count <= 0 or (@prod_counts[pr_name] + pr_count) > 99
+ raise "Invalid quantity number. It should be between 1 and 99."
+ end
+end
+
+def add(pr_name, pr_count = nil)
+ pr_count = pr_count == nil ? 1 : pr_count
+ unless @prod_counts.has_key? pr_name
+ @prod_counts[pr_name] = 0
+ end
+ valid_params(pr_name, pr_count)
+ @prod_counts[pr_name] += pr_count.to_s.to_d
+end
+
+def prod_total pr_name
+ pr_tot = @inv_reff.products[pr_name] * @prod_counts[pr_name]
+ if @inv_reff.promo[pr_name] != nil
+ pr_tot -= @inv_reff.promo[pr_name].discount(@prod_counts[pr_name])
+ end
+ pr_tot
+end
+
+def total
+ tot = '0'.to_d
+ @prod_counts.each_key do |elem|
+ tot += prod_total(elem)
+ end
+ @coupon == nil ? tot : (tot - @coupon.discount(tot))
+end
+
+def prom_inf name, count
+ str = ""
+ if @inv_reff.promo[name] != nil
+ desc = @inv_reff.promo[name].description
+ disc_val = "%.2f" % (-@inv_reff.promo[name].discount(count))
+ str += "| #{desc}#{' ' * (45 - desc.length)}|"
+ str += "#{' ' * (9 - disc_val.length)}#{disc_val} |\n"
+ end
+ str
+end
+
+def prod_inf str = ""
+ @prod_counts.each_key do |elem|
+ str += "| #{elem + ' ' * (42 - elem.length)}"
+ str += "#{' ' * (4 - @prod_counts[elem].to_i.to_s.length)}"
+ str += "#{@prod_counts[elem].to_i} | "
+ prod_pr = "%.2f" % (@prod_counts[elem] * @inv_reff.products[elem])
+ str += "#{' ' * (8 - prod_pr.length)}#{prod_pr} |\n"
+ str += prom_inf(elem, @prod_counts[elem])
+ end
+ str
+end
+
+def coupon_inf str = ""
+ unless @coupon == nil
+ str += "| #{@coupon.description}#{' ' * (47 - @coupon.description.length)}|"
+ dsc = "%.2f" % (total - @coupon.before_disc)
+ str += "#{' ' * (9 - dsc.length)}#{dsc} |\n"
+ end
+ str
+end
+
+def invoice
+ str = "+#{'-' * 48}+#{'-' * 10}+\n| Name#{' ' * 39}qty |#{' '* 4 }price |"
+ str += "\n+#{'-' * 48}+#{'-' * 10}+\n" + prod_inf + coupon_inf
+ str += "+#{'-' * 48}+#{'-' * 10}+\n| TOTAL#{' ' * 42}|"
+ tot = "%.2f" % total
+ str += "#{' ' * (9 - tot.length)}#{tot} |\n"
+ str += "+#{'-' * 48}+#{'-' * 10}+\n"
+end
+
+def use coup_name
+ unless @inv_reff.coupons.has_key? coup_name
+ raise "Coupon not registered."
+ end
+ @coupon = @inv_reff.coupons[coup_name]
+end
+
+end
+
+class Get_nth_free
+def initialize prom_n, each_price
+ @prom_n, @each_price, = prom_n.to_s.to_d, each_price.to_s.to_d
+end
+
+def discount pr_count
+ (pr_count.to_s.to_d / @prom_n).to_i.to_s.to_d * @each_price
+end
+
+def description
+ "(buy #{@prom_n.to_i - 1}, get 1 free)"
+end
+
+end
+
+class N_pack
+def initialize prom_n, prom_perc, each_price
+ @prom_n, @prom_perc = prom_n.to_s.to_d, prom_perc.to_s.to_d
+ @each_price = each_price.to_s.to_d
+ @pack_discount = (@prom_n * @each_price) * '0.01'.to_d * @prom_perc
+end
+
+def discount pr_count
+ (pr_count / @prom_n).to_i.to_s.to_d * @pack_discount
+end
+
+def description
+ "(get #{@prom_perc.to_i}% off for every #{@prom_n.to_i})"
+end
+
+end
+
+class Aft_n
+def initialize prom_n, prom_perc, each_price
+ @prom_n, @prom_perc = prom_n.to_s.to_d, prom_perc.to_s.to_d
+ @each_price = each_price.to_s.to_d
+ @each_disc = @each_price * '0.01'.to_d * @prom_perc
+end
+
+def discount pr_count
+ if pr_count.to_s.to_d < @prom_n
+ return '0'.to_d
+ end
+ (pr_count.to_s.to_d - @prom_n) * @each_disc
+end
+
+def description
+ prom_n_str = case @prom_n.to_f
+ when 1.00 then "1st"
+ when 2.00 then "2nd"
+ when 3.00 then "3rd"
+ else "#{@prom_n.to_i}th"
+ end
+ "(#{@prom_perc.to_i}% off of every after the #{prom_n_str})"
+end
+
+end
+
+class Coupon_percent
+def initialize name, perc
+ @name, @perc, @before_disc = name, perc.to_s.to_d, '0'.to_d
+end
+
+def before_disc
+ @before_disc
+end
+
+def discount total
+ @before_disc = total
+ total.to_s.to_d * '0.01'.to_d * @perc
+end
+
+def description
+ "Coupon #{@name} - #{@perc.to_i}% off"
+end
+
+end
+
+class Coupon_amount
+def initialize name, price
+ @name, @price, @before_disc = name, price.to_s.to_d, '0'.to_d
+end
+
+def before_disc
+ @before_disc
+end
+
+def discount total
+ @before_disc = total
+ total.to_s.to_d > @price ? @price : total.to_s.to_d
+end
+
+def description
+ "Coupon #{@name} - #{"%.2f" % @price} off"
+end
+
+end