Please review my code and help on How can I make it better calculation in method and class definition with SOLID ruby principles??
The application has a static JSON file which contains:
{
"homes": {
"person_a": "windows+tables",
"person_b": "lights+tables",
"person_c": "doors+curtains"
}
}
The application should, for each user request, calculate quotes for the 3 insurers. The business requirement is as follows:
The quote is a 10% of the rate if 2 covers are matched or 20% if just 1 cover is matched and that is the biggest requested, 25% if it is the second biggest or 30% if is the third.
the request from user is as follow
{:curtains=>20, :tables=>30, :windows=>50}
The system should not return a quote if the value is zero(0)
For eg: the application will return the result for the above user request
{
person_a: 8 (10% of 80 (two matches on windows and tables))
person_b: 7.5 (25% of 30 (one match on tables, the 2nd biggest cover))
insurer_c: 6 (30% of 20 (one match on curtains, the 3rd biggest cover)
}
This is my solution:
require_relative './rules'
module Coverage
class CalculateQuotes
def initialize(quotes)
@quotes = quotes
end
def calculate_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).calculate_rates
````