# Calculate the percentage of sum of hash values

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
persentage = get_percentage_by_match_covers
@match_covers.values.each do |v|
end
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
$$$$


## Ruby Hash

Rather than using a verbose case statement:

 case index
when 0
0.2
when 1
0.25
when 2
0.3


You could use a Hash:

rates = {0 => 0.2, 1 => 0.25, 2 => 0.3}


And the case can be replaced with:

rates[index]


## Rubocop Report

Use symbols as procs when possible.

covers = covers.map { |x| x.to_sym }


This is a compact alternative:

covers = covers.map(&:to_sym)


Identify unused block arguments.

@quotes.select { |k,v| covers.include?(k) }


Use an underscore to identify unused block arguments:

@quotes.select { |k, _v| covers.include?(k) }


Numeric predicates should use predicate methods instead of comparison operators if possible

premium == 0 ? nil : premium


Use the predicate method zero instead:

premium.zero? ? nil : premium

• Thanks rubocop changes I will do finally when my code gets finalize. I am looking strong ruby code review which will calculate the percentage in a different way and some refactor to my class definition Aug 15, 2019 at 21:58