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

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

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

Резултати

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

Код

require 'bigdecimal'
require 'bigdecimal/util'
class Product
attr_accessor :name, :price, :promo
def initialize(name, price, *promo)
@name = name
@price = price.to_d
@promo = (promo == [] ? nil : promo[0])
end
end
class Coupon
attr_accessor :name, :type
def initialize(name, type)
@name = name
@type = type
end
end
class Promo_compute
def self.ending(num)
case num
when 1 then "1st"
when 2 then "2nd"
when 3 then "3rd"
else num.to_s + "th"
end
end
def self.kv(k, v)
start = "| " + k
start + " " * ((v > 9 ? 46 : 47) - start.length) + v.to_s + " |"
end
def self.invoice_string(promo, save)
if promo == []
return ""
end
k = promo.keys[0]
v = promo[k]
if v.kind_of? Hash
v1 = v.keys[0]
v2 = v[v1]
end
u = "% off of every after the "
case k
when :get_one_free then e = "| (buy " + (v - 1).to_s + ", get 1 free)"
when :package then e = "| (get " + v2.to_s + "% off for every " + v1.to_s + ")"
when :threshold then e = "| (" + v2.to_s + u + self.ending(v1) + ")"
end
e + " " * (49 - e.length) + "|" + sprintf("%9.2f", -save) + " |\n"
end
def self.invoice_sc(name, coupon, save)
k = coupon.keys[0]
v = coupon[k]
start = "| Coupon " + name + " - " + v.to_s
if k == :percent
start << "%"
end
start << " off"
start + " " * (49 - start.length) + "|" + sprintf("%9.2f", -save) + " |\n"
end
def self.calc_promo(k, v, count, perc, v1, v2, price)
case k
when :get_one_free then price * (count - count / v)
when :package then price * ((count - count % v1) * perc + (count % v1))
when :threshold then price * ([v1, count].min + perc * [(count - v1), 0].max)
end
end
def self.invoice_end(q, total)
ret = q + "| " + sprintf("%s %41s", "TOTAL", "") + "|"
ret << sprintf("%9.2f", total) + " |"+ "\n" + q
end
end
class Cart
attr_accessor :contents, :products, :using, :coupons
def initialize(products, coupons)
@contents = {}
@products = products
@coupons = coupons
end
def add(name, *count_opt)
count = (count_opt == [] ? 1 : count_opt[0])
if @products.collect {|p| p.name == name}.count(true) == 0 || count < 1
raise "Invalid parameters passed."
end
if !contents.has_key?(name)
contents[name] = 0
end
contents[name] += count
if contents[name] > 99
raise "Invalid parameters passed."
end
end
def use(coupon)
@using = coupon
end
def get_ptc(item, count)
product = @products.select {|p| p.name == item} [0]
if product.promo == []
return product.price * count
end
k, v = product.promo.keys[0], product.promo.values[0]
if v.kind_of? Hash
v1, v2 = v.keys[0], v.values[0]
perc = BigDecimal(((100.0 - v2) / 100.0).to_s)
end
Promo_compute.calc_promo(k, v, count, perc, v1, v2, product.price)
end
def get_cd(sum)
if @using != nil
k = @coupons[@using].keys[0]
v = BigDecimal(@coupons[@using][k].to_s)
case k
when :percent then sum - (sum * (100 - v) / 100)
when :amount then [v, sum].min
end
else
0
end
end
def tot_wc
sum = BigDecimal('0')
@contents.each do |k, v|
sum += get_ptc(k, v)
end
sum
end
def total
tot_wc - get_cd(tot_wc)
end
def get_p(item)
@products.select {|p| p.name == item} [0].price
end
def get_promo(item)
@products.select {|p| p.name == item} [0].promo
end
def invoice
q = "+------------------------------------------------+----------+\n"
result = q + "| Name qty | price |\n" + q
@contents.each do |k, v|
result << Promo_compute.kv(k, v) + sprintf("%9.2f", get_p(k) * v) + " |\n"
result << Promo_compute.invoice_string(get_promo(k), get_p(k) * v - get_ptc(k, v))
end
if @using != nil
result << Promo_compute.invoice_sc(@using, @coupons[@using], get_cd(tot_wc))
end
result << Promo_compute.invoice_end(q, total)
end
end
class Inventory
attr_accessor :products, :coupons
def initialize
@products = []
@coupons = {}
end
def check_register_data(name, price)
if (!name.kind_of? String) or (!price.kind_of? String)
raise "Invalid parameters passed."
end
if name.length > 40 or price.to_d < 0.01 or price.to_d > 999.99
raise "Invalid parameters passed."
end
if @products.collect {|p| p.name == name}.count(true) > 0
raise "Invalid parameters passed."
end
end
def register(name, price, *promo)
check_register_data(name, price)
@products << Product.new(name, price, (promo == [] ? [] : promo[0]))
end
def register_coupon(name, type)
@coupons[name] = type
end
def new_cart
Cart.new(@products, @coupons)
end
end

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

.................F.

Failures:

  1) Inventory with an 'amount off' coupon shows the discount in the invoice
     Failure/Error: cart.invoice.should eq <<INVOICE
       
       expected: "+------------------------------------------------+----------+\n| Name                                       qty |    price |\n+------------------------------------------------+----------+\n| Green Tea                                    5 |     5.00 |\n| Coupon TEA-TIME - 10.00 off                    |    -5.00 |\n+------------------------------------------------+----------+\n| TOTAL                                          |     0.00 |\n+------------------------------------------------+----------+\n"
            got: "+------------------------------------------------+----------+\n| Name                                       qty |    price |\n+------------------------------------------------+----------+\n| Green Tea                                    5 |     5.00 |\n| Coupon TEA-TIME - 0.1E2 off                    |    -5.00 |\n+------------------------------------------------+----------+\n| TOTAL                                          |     0.00 |\n+------------------------------------------------+----------+\n"
       
       (compared using ==)
       
       Diff:
       @@ -2,7 +2,7 @@
        | Name                                       qty |    price |
        +------------------------------------------------+----------+
        | Green Tea                                    5 |     5.00 |
       -| Coupon TEA-TIME - 10.00 off                    |    -5.00 |
       +| Coupon TEA-TIME - 0.1E2 off                    |    -5.00 |
        +------------------------------------------------+----------+
        | TOTAL                                          |     0.00 |
        +------------------------------------------------+----------+
     # /tmp/d20111115-5847-ka0hz7/spec.rb:281:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.5676 seconds
19 examples, 1 failure

Failed examples:

rspec /tmp/d20111115-5847-ka0hz7/spec.rb:274 # Inventory with an 'amount off' coupon shows the discount in the invoice

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

Георги обнови решението на 06.11.2011 20:43 (преди около 13 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class Product
+ attr_accessor :name, :price, :promo
+
+ def initialize(name, price, *promo)
+ @name = name
+ @price = price.to_d
+ @promo = (promo == [] ? nil : promo[0])
+ end
+
+end
+
+class Coupon
+ attr_accessor :name, :type
+
+ def initialize(name, type)
+ @name = name
+ @type = type
+ end
+
+end
+
+class Promo_compute
+
+ def self.ending(num)
+ case num
+ when 1 then "1st"
+ when 2 then "2nd"
+ when 3 then "3rd"
+ else num.to_s + "th"
+ end
+ end
+
+ def self.kv(k, v)
+ start = "| " + k
+ start + " " * ((v > 9 ? 46 : 47) - start.length) + v.to_s + " |"
+ end
+
+ def self.invoice_string(promo, save)
+ if promo == []
+ return ""
+ end
+ k = promo.keys[0]
+ v = promo[k]
+ if v.kind_of? Hash
+ v1 = v.keys[0]
+ v2 = v[v1]
+ end
+ u = "% off of every after the "
+ case k
+ when :get_one_free then e = "| (buy " + (v - 1).to_s + ", get 1 free)"
+ when :package then e = "| (get " + v2.to_s + "% off for every " + v1.to_s + ")"
+ when :threshold then e = "| (" + v2.to_s + u + self.ending(v1) + ")"
+ end
+ e + " " * (49 - e.length) + "|" + sprintf("%9.2f", -save) + " |\n"
+ end
+
+ def self.invoice_sc(name, coupon, save)
+ k = coupon.keys[0]
+ v = coupon[k]
+ start = "| Coupon " + name + " - " + v.to_s
+ if k == :percent
+ start << "%"
+ end
+ start << " off"
+ start + " " * (49 - start.length) + "|" + sprintf("%9.2f", -save) + " |\n"
+ end
+
+ def self.calc_promo(k, v, count, perc, v1, v2, price)
+ case k
+ when :get_one_free then price * (count - count / v)
+ when :package then price * ((count - count % v1) * perc + (count % v1))
+ when :threshold then price * ([v1, count].min + perc * [(count - v1), 0].max)
+ end
+ end
+
+ def self.invoice_end(q, total)
+ ret = q + "| " + sprintf("%s %41s", "TOTAL", "") + "|"
+ ret << sprintf("%9.2f", total) + " |"+ "\n" + q
+ end
+end
+
+class Cart
+ attr_accessor :contents, :products, :using, :coupons
+
+ def initialize(products, coupons)
+ @contents = {}
+ @products = products
+ @coupons = coupons
+ end
+
+ def add(name, *count_opt)
+ count = (count_opt == [] ? 1 : count_opt[0])
+ if @products.collect {|p| p.name == name}.count(true) == 0 || count < 1
+ raise "Invalid parameters passed."
+ end
+ if !contents.has_key?(name)
+ contents[name] = 0
+ end
+ contents[name] += count
+ if contents[name] > 99
+ raise "Invalid parameters passed."
+ end
+ end
+
+ def use(coupon)
+ @using = coupon
+ end
+
+ def get_ptc(item, count)
+ product = @products.select {|p| p.name == item} [0]
+ if product.promo == []
+ return product.price * count
+ end
+ k, v = product.promo.keys[0], product.promo.values[0]
+ if v.kind_of? Hash
+ v1, v2 = v.keys[0], v.values[0]
+ perc = BigDecimal(((100.0 - v2) / 100.0).to_s)
+ end
+ Promo_compute.calc_promo(k, v, count, perc, v1, v2, product.price)
+ end
+
+ def get_cd(sum)
+ if @using != nil
+ k = @coupons[@using].keys[0]
+ v = BigDecimal(@coupons[@using][k].to_s)
+ case k
+ when :percent then sum - (sum * (100 - v) / 100)
+ when :amount then [v, sum].min
+ end
+ else
+ 0
+ end
+ end
+
+ def tot_wc
+ sum = BigDecimal('0')
+ @contents.each do |k, v|
+ sum += get_ptc(k, v)
+ end
+ sum
+ end
+
+ def total
+ tot_wc - get_cd(tot_wc)
+ end
+
+ def get_p(item)
+ @products.select {|p| p.name == item} [0].price
+ end
+
+ def get_promo(item)
+ @products.select {|p| p.name == item} [0].promo
+ end
+
+ def invoice
+ q = "+------------------------------------------------+----------+\n"
+ result = q + "| Name qty | price |\n" + q
+ @contents.each do |k, v|
+ result << Promo_compute.kv(k, v) + sprintf("%9.2f", get_p(k) * v) + " |\n"
+ result << Promo_compute.invoice_string(get_promo(k), get_p(k) * v - get_ptc(k, v))
+ end
+ if @using != nil
+ result << Promo_compute.invoice_sc(@using, @coupons[@using], get_cd(tot_wc))
+ end
+ result << Promo_compute.invoice_end(q, total)
+ end
+
+end
+
+class Inventory
+ attr_accessor :products, :coupons
+
+ def initialize
+ @products = []
+ @coupons = {}
+ end
+
+ def check_register_data(name, price)
+ if (!name.kind_of? String) or (!price.kind_of? String)
+ raise "Invalid parameters passed."
+ end
+ if name.length > 40 or price.to_d < 0.01 or price.to_d > 999.99
+ raise "Invalid parameters passed."
+ end
+ if @products.collect {|p| p.name == name}.count(true) > 0
+ raise "Invalid parameters passed."
+ end
+ end
+
+ def register(name, price, *promo)
+ check_register_data(name, price)
+ @products << Product.new(name, price, (promo == [] ? [] : promo[0]))
+ end
+
+ def register_coupon(name, type)
+ @coupons[name] = type
+ end
+
+ def new_cart
+ Cart.new(@products, @coupons)
+ end
+
+ end