最近面试,要求解决如下小问题 模拟超市收银台的工作流程,商品价格可以单价和 package 价格例如:
A | $2.00 each or 4 for $7.00 B | $12.00 C | $1.25 or $6 for a six pack D | $0.15 实现工作流如下: terminal.setPricing(...) terminal.scan("A") terminal.scan("C") ... etc. result = terminal.total 显示结果: Scan these items in this order: ABCDABAA; Verify the total price is $32.40. Scan these items in this order: CCCCCCC; Verify the total price is $7.25. Scan these items in this order: ABCD; Verify the total price is $15.40. 我的代码如下:
class Terminal
attr_accessor :item_types, :item_sequence
def initialize
self.item_types = []
self.item_sequence = []
end
#input product name and price.
#can be only unit price or both unit price and volume price
#
#@terminal.set_price 'A', 3.00
#@terminal.set_price 'A', 3.00, 5, 13.00
def set_price p_code, *price
p_class = item_exists?(p_code) ? eval("#{p_code}") : create_item(p_code)
p_class.send :unit_price=, price[0]
p_class.send :volume_price=, {amount: price[1], v_price: price[2]} unless price[1].nil? || price[2].nil?
end
def scan p_code
eval "#{p_code}.new"
self.item_sequence << p_code
end
def total_cost
self.item_types.inject(0.0){|sum,item| sum += Item.cost(item)}
end
private
def create_item p_code
Object.const_set p_code, Class.new( Item )
p_class = eval "#{p_code}"
p_class.amount = 0
p_class.scaned_items = []
self.item_types << p_class
p_class
end
def item_exists? p_name
eval "defined?(#{p_name}) && #{p_name}.is_a?(Class)"
end
end
class Item
class << self; attr_accessor :unit_price, :volume_price, :amount, :scaned_items; end
attr_accessor :item_name
def initialize
self.class.amount += 1
self.class.scaned_items << self
self.item_name = "#{self.class}_#{self.class.amount}"
end
protected
def self.cost item
return 0 if item.amount == 0
if item.volume_price.nil?
item.amount * item.unit_price
else
item.unit_price * (item.amount % item.volume_price[:amount]) +
item.volume_price[:v_price] * (item.amount / item.volume_price[:amount]).to_i
end
end
end