我有一个静态的json文件,其中包含:
{
"homes": {
"person_a": "windows+tables",
"person_b": "lights+tables",
"person_c": "doors+curtains"
}
}
对于每个请求,应用程序都应计算3家保险公司的报价。业务需求如下:
如果匹配2个封面,则报价为费率的10%;如果仅匹配1个封面且报价为最大,则报价为20%;如果是第二个封面,则为25%;如果是第三个封面,则为30%。 / p>
来自用户的请求如下
{:curtains=>20, :tables=>30, :windows=>50}
如果该值为零(0),则系统不应返回引号
然后,应用程序将计算以下报价:
person_a: 8 (10% of 80 (two matches on windows and tables))
person_b: 7.5 (25% of 30 (one match on contents, the 2nd biggest cover))
insurer_c: 6 (30% of 20 (one match on curtains, the 3rd biggest cover)
这是我的解决方案:
require_relative './rules'
module Coverage
class CalculateQuotes
def initialize(quotes)
@quotes = quotes
end
def get_rates
result = []
@insurer = Coverage::Rules.parse_file ## which will give {
#"insurer_rates": {
#"person_a": "windows+tables",
# "person_b": "lights+tables",
#"person_c": "doors+curtains"
# }}
@insurer[:insurer_rates].each do |k, v|
@match_covers = match_cover(v.split("+"))
result << [k, calculate_rate ]
end
end
def match_cover(covers)
covers = covers.map { |x| x.to_sym }
@quotes.select { |k,v| covers.include?(k) }
end
def calculate_rate
premium = 0.0
persentage = get_percentage_by_match_covers
@match_covers.values.each do |v|
premium += v * persentage
end
premium == 0 ? nil : premium
end
def get_percentage_by_match_covers
if @match_covers.size == 2
0.1
elsif @match_covers.size == 1
only_1_match_covers
else
0
end
end
def only_1_match_covers
index = position_of_customer_request
case index
when 0
0.2
when 1
0.25
when 2
0.3
else
raise StandardError
end
end
def position_of_customer_request
(@quotes.to_a.reverse).index(@match_covers.to_a.flatten)
end
end
end
request = {:windows=>50, :contents=>30, :engine=>20}
Coverage::CalculateQuotes.new(request).get_rates
请帮助我了解如何使用SOLID红宝石原理更好地进行计算和编码?
答案 0 :(得分:1)
数据
double_quote_rate = 0.1
single_quote_rate = [0.3, 0.25, 0.2]
request = {:curtains=>20, :tables=>30, :windows=>50}
代码
关键是创建一个将产品集映射到其计算值的哈希。
第一步是创建键值对,其中键是包含单个产品的集合:
require 'set'
h = single_quote_rate.zip(request.sort_by(&:last)).
each_with_object({}) { |(rate, (product, score)),h|
h[[product].to_set] = rate*score }
#=> {#<Set: {:curtains}>=>6.0, #<Set: {:tables}>=>7.5,
# #<Set: {:windows}>=>10.0}
请注意,single_quote_rate
中的值按从大到小的顺序排列。中间计算如下:
single_quote_rate.zip(request.sort_by(&:last))
#=> [[0.3, [:curtains, 20]], [0.25, [:tables, 30]],
# [0.2, [:windows, 50]]]
现在添加两种产品的所有组合:
request.to_a.combination(2).each { |(product1, score1),(product2,score2)|
h[[product1,product2].to_set] = double_quote_rate*(score1+score2) }
h #=> {#<Set: {:curtains}>=>6.0,
# #<Set: {:tables}>=>7.5,
# #<Set: {:windows}>=>10.0,
# #<Set: {:curtains, :tables}>=>5.0,
# #<Set: {:curtains, :windows}>=>7.0,
# #<Set: {:tables, :windows}>=>8.0}
第一个计算如下:
enum = request.to_a.combination(2)
#=> #<Enumerator: [[:curtains, 20], [:tables, 30],
# [:windows, 50]]:combination(2)>
我们可以将此枚举器转换为数组,以查看将传递给该块的三个元素(数组)。
enum.to_a
#=> [[[:curtains, 20], [:tables, 30]],
# [[:curtains, 20], [:windows, 50]],
# [[:tables, 30], [:windows, 50]]]
块变量分配如下:
(product1, score1),(product2,score2) = enum.next
#=> [[:curtains, 20], [:tables, 30]]
product1
#=> :curtains
score1
#=> 20
product2
#=> :tables
score2
#=> 30
将数组分解成其组成元素称为array decompostion。
为方便起见,将request
的键分配给变量:
keys = request.keys
#=> [:curtains, :tables, :windows]
示例
hash = { "homes": { "person_a": "windows+tables",
"person_b": "lights+tables",
"person_c": "doors+curtains" } }
hash[:"homes"].transform_values do |s|
h[s.split('+').map(&:to_sym).select { |s| keys.include?(s) }.to_set]
end
#=> {:person_a=>8.0, :person_b=>7.5, :person_c=>6.0}
用于获得h
的期望值的密钥的示例计算如下:
s = "lights+tables"
a = s.split('+')
#=> ["lights", "tables"]
b = a.map(&:to_sym)
#=> [:lights, :tables]
c = b.select { |s| keys.include?(s) }
#=> [:tables]
d = c.to_set
#=> #<Set: {:tables}>
h[d]
#=> 7.5