Решение на Трета задача от Николай Стоицев

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

Към профила на Николай Стоицев

Резултати

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

Код

require 'bigdecimal'
require 'bigdecimal/util'
class Inventory
def initialize()
@@products_list = {}
@@coupon_list = {}
end
def register(product_name, product_price = nil, promotion = nil)
validate_name(product_name)
validate_price(product_price)
@@products_list[product_name] = Product.new(product_price.to_d, promotion)
end
def new_cart()
Cart.new()
end
def register_coupon(name, coupon_type)
type = coupon_type.keys.first.to_s
if type == "percent"
@@coupon_list[name] = PercentsCoupon.new(coupon_type.values.first, name)
elsif type == "amount"
@@coupon_list[name] = AmountCoupon.new(coupon_type.values.first, name)
end
end
def self.get_product(name)
@@products_list[name]
end
def self.get_coupon(name)
@@coupon_list[name]
end
private
def validate_name(product_name)
if @@products_list.has_key? product_name
raise "Product already registered."
end
if product_name.length > 40
raise "Name is too long. Should be 40 characters max."
end
end
def validate_price(product_price)
if product_price == nil
raise "Specify product price."
end
if product_price.to_d < 0.01 || product_price.to_d > 999.99
raise "Incorrect price."
end
end
end
class Product
def initialize(product_price, promotion)
@price = product_price
if promotion != nil
@promotion = add_promotion(promotion.keys.first, promotion.values.first)
else
@promotion = nil
end
end
def price
@price
end
def get_price(number_of_products)
if @promotion.nil?
total = number_of_products * @price
else
total = @promotion.calc_price(@price, number_of_products)
end
total
end
def get_promo
@promotion
end
def has_promotion?
not @promotion.nil?
end
def add_promotion(promotion_name, params)
if promotion_name.to_s == "get_one_free"
promotion_object = GetOneFreePromotion.new(params)
elsif promotion_name.to_s == "package"
promotion_object = PackagePromotion.new(params)
elsif promotion_name.to_s == "threshold"
promotion_object = ThresholdPromotion.new(params)
end
promotion_object
end
end
class Cart
def initialize()
@basket = {}
@coupon = nil
end
def add(product_name, num_of_products = 1)
validate_product_name(product_name)
validate_num_of_products(num_of_products)
if @basket.has_key? product_name
@basket[product_name] += num_of_products
else
@basket[product_name] = num_of_products
end
end
def use(coupon_name)
@coupon = Inventory.get_coupon(coupon_name)
end
def total()
sum = BigDecimal('0')
@basket.each { |product_name, num_of_products|
sum += Inventory.get_product(product_name).get_price(num_of_products)
}
if @coupon != nil
sum -= @coupon.total(sum)
end
sum
end
def invoice()
invoice = Invoice.new
out = invoice.print_head + "\n"
@basket.each { |name, prod_num|
prod = Inventory.get_product(name)
out << invoice.print_row(name, prod_num, prod.price, prod.get_promo) + "\n"
}
out << invoice.print_footer(total(), @coupon) + "\n"
out
end
private
def validate_product_name(product_name)
if Inventory.get_product(product_name) == nil
raise "Product not registered."
end
end
def validate_num_of_products(num_of_products)
if num_of_products < 1 || num_of_products > 99
raise "Incorecr number of products."
end
end
end
class Invoice
def print_head()
output = "+------------------------------------------------+----------+\n"
output << "| Name qty | price |\n"
output << "+------------------------------------------------+----------+"
output
end
def print_row(product_name, num_of_products, product_price, product_promo = nil)
output = '| ' + product_name.to_s.ljust(44) + num_of_products.to_s.rjust(2) + ' | '
output << ("%.2f" % (product_price * num_of_products)).to_s.rjust(8) + ' |'
if not product_promo.nil?
product_promo.calc_price(product_price, num_of_products)
output << "\n| " + product_promo.to_s.ljust(44) + ' | '
output << ('-' + ("%.2f" % product_promo.get_discount).to_s).rjust(8) + ' |'
end
output
end
def print_footer(total, coupon)
output = ''
if coupon != nil
output << "| " + coupon.to_s.ljust(46) + ' | '
output << ('-' + ("%.2f" % coupon.get_discount).to_s).rjust(8) + " |\n"
end
output + print_total(total)
end
def print_total(total)
output = "+------------------------------------------------+----------+\n"
output << "| TOTAL |"
output << ("%.2f" % total).to_s.rjust(9)
output << " |\n+------------------------------------------------+----------+"
output
end
end
class GetOneFreePromotion
def initialize(free_after_each)
@free_each = free_after_each
@discount = nil
end
def calc_price(price, num_of_products)
free_products = num_of_products / @free_each
@discount = free_products * price
return price * (num_of_products - free_products)
end
def get_discount
@discount
end
def to_s
"(buy #{@free_each - 1}, get 1 free)"
end
end
class PackagePromotion
def initialize(discount)
@products_needed = discount.keys.first
@percents_discount = discount.values.first
@discount = 0
end
def calc_price(price, num_of_products)
discounted = num_of_products / @products_needed
not_discounted = num_of_products % @products_needed
sum = (1 - (@percents_discount.to_f / 100)) * (price * discounted * @products_needed)
sum += (not_discounted * price)
@discount = (price * num_of_products) - sum
sum.to_d
end
def get_discount
@discount
end
def to_s
"(get #{@percents_discount}% off for every #{@products_needed})"
end
end
class ThresholdPromotion
def initialize(discount)
@discount_after = discount.keys.first
@percents_discount = discount.values.first
@discount = 0
end
def calc_price(price, num_of_products)
discounted = num_of_products - @discount_after
if discounted <= 0
return price * num_of_products
end
sum = num_of_products * price
@discount = discounted * price * (@percents_discount.to_f / 100)
sum - @discount
end
def get_discount
@discount
end
def to_s
if @discount_after == 2
@ext = 'nd'
elsif @discount_after == 3
@ext = 'rd'
else
@ext = 'th'
end
"(#{@percents_discount}% off of every after the #{@discount_after.to_s + @ext})"
end
end
class PercentsCoupon
def initialize(percents, name)
@name = name
@percents = percents
@total = 0
end
def total(sum)
@total = sum * (@percents.to_f / 100)
end
def get_discount()
@total
end
def to_s()
"Coupon #{@name} - #{@percents}% off"
end
end
class AmountCoupon
def initialize(amount, name)
@amount = amount.to_d
@name = name
@discount = 0
end
def total(sum)
if sum <= @amount
return @discount = sum
else
return @discount = @amount
end
end
def get_discount()
@discount
end
def to_s()
"Coupon #{@name} - #{"%.2f" % @amount.to_f} off"
end
end

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

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

Finished in 0.57459 seconds
19 examples, 0 failures

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

Николай обнови решението на 04.11.2011 14:25 (преди над 12 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class Inventory
+
+ def initialize()
+ @@products_list = {}
+ @@coupon_list = {}
+ end
+
+ def register(product_name, product_price = nil, promotion = nil)
+ validate_name(product_name)
+ validate_price(product_price)
+ @@products_list[product_name] = Product.new(product_price.to_d, promotion)
+ end
+
+ def new_cart()
+ Cart.new()
+ end
+
+ def register_coupon(name, coupon_type)
+ type = coupon_type.keys.first.to_s
+ if type == "percent"
+ @@coupon_list[name] = PercentsCoupon.new(coupon_type.values.first, name)
+ elsif type == "amount"
+ @@coupon_list[name] = AmountCoupon.new(coupon_type.values.first, name)
+ end
+ end
+
+ def self.get_product(name)
+ @@products_list[name]
+ end
+
+ def self.get_coupon(name)
+ @@coupon_list[name]
+ end
+
+ private
+
+ def validate_name(product_name)
+ if @@products_list.has_key? product_name
+ raise "Product already registered."
+ end
+ if product_name.length > 40
+ raise "Name is too long. Should be 40 characters max."
+ end
+ end
+
+ def validate_price(product_price)
+ if product_price == nil
+ raise "Specify product price."
+ end
+ if product_price.to_d < 0.01 || product_price.to_d > 999.99
+ raise "Incorrect price."
+ end
+ end
+
+end
+
+class Product
+
+ def initialize(product_price, promotion)
+ @price = product_price
+ if promotion != nil
+ @promotion = add_promotion(promotion.keys.first, promotion.values.first)
+ else
+ @promotion = nil
+ end
+ end
+
+ def price
+ @price
+ end
+
+ def get_price(number_of_products)
+ if @promotion.nil?
+ total = number_of_products * @price
+ else
+ total = @promotion.calc_price(@price, number_of_products)
+ end
+ total
+ end
+
+ def get_promo
+ @promotion
+ end
+
+ def has_promotion?
+ not @promotion.nil?
+ end
+
+ def add_promotion(promotion_name, params)
+ if promotion_name.to_s == "get_one_free"
+ promotion_object = GetOneFreePromotion.new(params)
+ elsif promotion_name.to_s == "package"
+ promotion_object = PackagePromotion.new(params)
+ elsif promotion_name.to_s == "threshold"
+ promotion_object = ThresholdPromotion.new(params)
+ end
+ promotion_object
+ end
+
+end
+
+class Cart
+
+ def initialize()
+ @basket = {}
+ @coupon = nil
+ end
+
+ def add(product_name, num_of_products = 1)
+ validate_product_name(product_name)
+ validate_num_of_products(num_of_products)
+ if @basket.has_key? product_name
+ @basket[product_name] += num_of_products
+ else
+ @basket[product_name] = num_of_products
+ end
+ end
+
+ def use(coupon_name)
+ @coupon = Inventory.get_coupon(coupon_name)
+ end
+
+ def total()
+ sum = BigDecimal('0')
+ @basket.each { |product_name, num_of_products|
+ sum += Inventory.get_product(product_name).get_price(num_of_products)
+ }
+ if @coupon != nil
+ sum -= @coupon.total(sum)
+ end
+ sum
+ end
+
+ def invoice()
+ invoice = Invoice.new
+ out = invoice.print_head + "\n"
+ @basket.each { |name, prod_num|
+ prod = Inventory.get_product(name)
+ out << invoice.print_row(name, prod_num, prod.price, prod.get_promo) + "\n"
+ }
+ out << invoice.print_footer(total(), @coupon) + "\n"
+ out
+ end
+
+ private
+
+ def validate_product_name(product_name)
+ if Inventory.get_product(product_name) == nil
+ raise "Product not registered."
+ end
+ end
+
+ def validate_num_of_products(num_of_products)
+ if num_of_products < 1 || num_of_products > 99
+ raise "Incorecr number of products."
+ end
+ end
+
+end
+
+class Invoice
+
+ def print_head()
+ output = "+------------------------------------------------+----------+\n"
+ output << "| Name qty | price |\n"
+ output << "+------------------------------------------------+----------+"
+ output
+ end
+
+ def print_row(product_name, num_of_products, product_price, product_promo = nil)
+ output = '| ' + product_name.to_s.ljust(44) + num_of_products.to_s.rjust(2) + ' | '
+ output << ("%.2f" % (product_price * num_of_products)).to_s.rjust(8) + ' |'
+ if not product_promo.nil?
+ product_promo.calc_price(product_price, num_of_products)
+ output << "\n| " + product_promo.to_s.ljust(44) + ' | '
+ output << ('-' + ("%.2f" % product_promo.get_discount).to_s).rjust(8) + ' |'
+ end
+ output
+ end
+
+ def print_footer(total, coupon)
+ output = ''
+ if coupon != nil
+ output << "| " + coupon.to_s.ljust(46) + ' | '
+ output << ('-' + ("%.2f" % coupon.get_discount).to_s).rjust(8) + " |\n"
+ end
+ output + print_total(total)
+ end
+
+ def print_total(total)
+ output = "+------------------------------------------------+----------+\n"
+ output << "| TOTAL |"
+ output << ("%.2f" % total).to_s.rjust(9)
+ output << " |\n+------------------------------------------------+----------+"
+ output
+ end
+
+end
+
+class GetOneFreePromotion
+
+ def initialize(free_after_each)
+ @free_each = free_after_each
+ @discount = nil
+ end
+
+ def calc_price(price, num_of_products)
+ free_products = num_of_products / @free_each
+ @discount = free_products * price
+ return price * (num_of_products - free_products)
+ end
+
+ def get_discount
+ @discount
+ end
+
+ def to_s
+ "(buy #{@free_each - 1}, get 1 free)"
+ end
+
+end
+
+class PackagePromotion
+
+ def initialize(discount)
+ @products_needed = discount.keys.first
+ @percents_discount = discount.values.first
+ @discount = 0
+ end
+
+ def calc_price(price, num_of_products)
+ discounted = num_of_products / @products_needed
+ not_discounted = num_of_products % @products_needed
+ sum = (1 - (@percents_discount.to_f / 100)) * (price * discounted * @products_needed)
+ sum += (not_discounted * price)
+ @discount = (price * num_of_products) - sum
+ sum.to_d
+ end
+
+ def get_discount
+ @discount
+ end
+
+ def to_s
+ "(get #{@percents_discount}% off for every #{@products_needed})"
+ end
+
+end
+
+class ThresholdPromotion
+
+ def initialize(discount)
+ @discount_after = discount.keys.first
+ @percents_discount = discount.values.first
+ @discount = 0
+ end
+
+ def calc_price(price, num_of_products)
+ discounted = num_of_products - @discount_after
+ if discounted <= 0
+ return price * num_of_products
+ end
+ sum = num_of_products * price
+ @discount = discounted * price * (@percents_discount.to_f / 100)
+ sum - @discount
+ end
+
+ def get_discount
+ @discount
+ end
+
+ def to_s
+ if @discount_after == 2
+ @ext = 'nd'
+ elsif @discount_after == 3
+ @ext = 'rd'
+ else
+ @ext = 'th'
+ end
+ "(#{@percents_discount}% off of every after the #{@discount_after.to_s + @ext})"
+ end
+
+end
+
+class PercentsCoupon
+
+ def initialize(percents, name)
+ @name = name
+ @percents = percents
+ @total = 0
+ end
+
+ def total(sum)
+ @total = sum * (@percents.to_f / 100)
+ end
+
+ def get_discount()
+ @total
+ end
+
+ def to_s()
+ "Coupon #{@name} - #{@percents}% off"
+ end
+
+end
+
+class AmountCoupon
+
+ def initialize(amount, name)
+ @amount = amount.to_d
+ @name = name
+ @discount = 0
+ end
+
+ def total(sum)
+ if sum <= @amount
+ return @discount = sum
+ else
+ return @discount = @amount
+ end
+ end
+
+ def get_discount()
+ @discount
+ end
+
+ def to_s()
+ "Coupon #{@name} - #{"%.2f" % @amount.to_f} off"
+ end
+
+end