Ростислав обнови решението на 06.11.2011 23:51 (преди около 13 години)
+def get_one_free (product, qty, sum)
+ if (product.promotion[:get_one_free]!=nil && qty>=product.promotion[:get_one_free])
+ sum = sum - (qty/product.promotion[:get_one_free])*product.price
+ end
+ return sum
+end
+def package(product, qty, sum)
+ if (product.promotion[:package]!=nil && qty>=product.promotion[:package].keys[0])
+ key = product.promotion[:package].keys[0]
+ value = product.promotion[:package].values[0]
+ sum = sum - (qty-qty%key)*product.price*(value/100.0)
+ end
+ return sum
+end
+def threshold(product, qty, sum)
+ if (product.promotion[:threshold]!=nil && qty>=product.promotion[:threshold].keys[0])
+ key = product.promotion[:threshold].keys[0]
+ value = product.promotion[:threshold].values[0]
+ sum = sum - (qty-key)*product.price*(value/100.0)
+ end
+ return sum
+end
+def help (key, value)
+ str=""
+ if key.promotion[:get_one_free]!=nil
+ sum = sprintf("%5.2f", get_one_free(key, value, 0))
+ get = key.promotion.values[0]-1
+ str = "| (buy #{get}, get 1 free)"+" "*(27-get.to_s.length)
+ str += "|" + " "*(9-sum.length) + "#{"%5.2f"%sum} |\n"
+ end
+ return str
+end
+def help2 (key, value)
+ str=""
+ if key.promotion[:package]!=nil
+ sum = sprintf("%5.2f", package(key, value, 0))
+ get, num = key.promotion[:package].values[0], key.promotion[:package].keys[0]
+ word_length = get.to_s.length
+ str = "| (get #{get}% off for every #{num})"+" "*(23-word_length-num.to_s.length)
+ str += "|" + " "*(9-sum.length) + "#{"%5.2f"%sum} |\n"
+ end
+ return str
+end
+def ordinalize (number)
+ if (10...20).include?(number)
+ return "#{number}th"
+ else
+ arr = %w{ th st nd rd th th th th th th }
+ return number.to_s+arr[number%10]
+ end
+end
+def help3 (key, value)
+ str=""
+ if key.promotion[:threshold]!=nil
+ sum = sprintf("%5.2f", threshold(key, value, 0))
+ get = key.promotion[:threshold].values[0]
+ th = ordinalize(key.promotion[:threshold].keys[0])
+ str = "| (#{get}% off of every after the #{th})"+" "*(18-get.to_s.length-th.length)
+ str += "|" + " "*(9-sum.length) + "#{"%5.2f"%sum} |\n"
+ end
+ return str
+end
+def gte_zero (number)
+ if number < "0.00".to_d
+ number="0.00".to_d
+ end
+ return number
+end
+class Product
+ require 'bigdecimal'
+ require 'bigdecimal/util'
+ attr_accessor :name, :price, :promotion
+ def initialize(name="", price="0.00", promotion={})
+ @name = name
+ @price = BigDecimal(price)
+ @promotion = promotion
+ end
+end
+class Coupon
+ attr_accessor :name, :type
+ def initialize(name, type)
+ @name = name
+ @type = type
+ end
+end
+class Inventory
+ require 'bigdecimal'
+ require 'bigdecimal/util'
+ attr_accessor :inventory, :coupons
+ def initialize
+ @inventory = []
+ @coupons = []
+ end
+ def register(name, price, promotion={})
+ if name.length>40 || price.to_d<=("0.00").to_d || price.to_d>("999.99").to_d
+ raise "Invalid parameters passed."
+ end
+ self.inventory.each do |n|
+ if n.name == name
+ raise "Invalid parameters passed."
+ end
+ end
+ product = Product.new(name, price, promotion)
+ @inventory << product
+ end
+ def register_coupon(name, type)
+ coupon=Coupon.new(name, type)
+ @coupons << coupon
+ end
+ def new_cart
+ cart = Cart.new(self.inventory, self.coupons)
+ return cart
+ end
+end
+class Cart
+ attr_accessor :inventory, :purchase, :coupons, :coupons_used
+ require 'bigdecimal'
+ require 'bigdecimal/util'
+ def initialize(inventory, coupons)
+ @inventory = inventory
+ @coupons = coupons
+ @purchase = {}
+ @coupons_used = []
+ end
+ def add(name_of_product, quantity=1)
+ raise "Invalid parameters passed." if quantity<=0 || quantity>99
+ product = Product.new("error", "-1")
+ @purchase.each do |key, value|
+ @purchase[key]+=quantity and return if key.name == name_of_product
+ end
+ @inventory.each do |n|
+ product = n if n.name == name_of_product
+ end
+ raise "Invalid parameters passed." if product.price=="-1".to_d
+ @purchase.merge!(product => quantity)
+ end
+ def use(name_of_coupon)
+ coupon = Coupon.new("error", "error")
+ @coupons.each do |iter|
+ if iter.name==name_of_coupon
+ coupon = iter
+ break
+ end
+ end
+ raise "Invalid parameters passed." if coupon.type=="error" || @coupons_used!=[]
+ @coupons_used << coupon
+ end
+ def coupon(sum)
+ return sum if @coupons_used == []
+ type = @coupons_used[0].type
+ sum -= (type.values[0]/100.0)*sum if type.keys[0]==:percent
+ sum -= type.values[0].to_d if type.keys[0]==:amount
+ return sum
+ end
+ def total
+ sum = "0.00".to_d
+ @purchase.each do |key, value|
+ sum += value*key.price
+ sum = get_one_free(key, value, sum)
+ sum = package(key, value, sum)
+ sum = threshold(key, value, sum)
+ end
+ return gte_zero (self.coupon(sum))
+ end
+ def invoice
+ str = "+------------------------------------------------+----------+\n"
+ str1 = "| Name qty | price |\n"
+ total = sprintf("%5.2f", self.total)
+ str2 = "| TOTAL"+" "*42+"|" + " "*(9-total.length)+ "#{total} |\n"
+ return str+str1+str+self.body+self.coupon_percent+self.coupon_amount+str+str2+str
+ end
+ def coupon_percent
+ return "" if @coupons_used == []
+ str = ""
+ name, percent = @coupons_used[0].name, @coupons_used[0].type.values[0]
+ sum=sprintf("%5.2f",-(self.total_without_coupons-coupon(self.total_without_coupons)))
+ if @coupons_used[0].type.keys[0]==:percent
+ str = "| Coupon #{name} - #{percent}% off"+" "*(32-name.length-percent.to_s.length)
+ str += "|" + " "*(9-sum.to_s.length) + "#{"%5.2f"%sum} |\n"
+ end
+ return str
+ end
+ def coupon_amount
+ return "" if @coupons_used == []
+ str = ""
+ name, num = @coupons_used[0].name, @coupons_used[0].type.values[0]
+ sum = sprintf("%5.2f",-(self.total_without_coupons - self.total))
+ if @coupons_used[0].type.keys[0]==:amount
+ str = "| Coupon #{name} - #{"%5.2f"%num} off"+" "*(33-name.length-num.to_s.length)
+ str += "|" + " "*(9-sum.to_s.length) + "#{"%5.2f"%sum} |\n"
+ end
+ return str
+ end
+ def body
+ str=""
+ @purchase.each do |key, value|
+ qty = sprintf("%5.0f", value)
+ val = sprintf("%5.2f", key.price*value)
+ name_length = key.name.length
+ str += "| #{key.name}"+" "*(46-name_length-qty.length)+"#{qty} |"+" "*(9-val.length)
+ str += "#{val} |\n"+help(key, value)+help2(key, value)+help3(key, value)
+ end
+ return str
+ end
+ def total_without_coupons
+ sum = "0.00".to_d
+ @purchase.each do |key, value|
+ sum += value*key.price
+ sum = get_one_free(key, value, sum)
+ sum = package(key, value, sum)
+ sum = threshold(key, value, sum)
+ end
+ return sum
+ end
+end