Virus Predictor
#population density is number of people per square mile as of 2012
#this data is updated every year with estimates from a 10 year census
STATE_DATA = { "Alabama" => {population_density: 94.65, population: 4822023, region: 5, regional_spread: 3},
"Alaska" => {population_density: 1.26, population: 731449, region: 10, regional_spread: 9},
"Arizona" => {population_density: 57.05, population: 6553255, region: 8, regional_spread: 8},
"Arkansas" => {population_density: 56.43, population: 2949131, region: 7, regional_spread: 5},
"California" => {population_density: 244.2, population: 38041430, region: 9, regional_spread: 8},
"Colorado" => {population_density: 49.33, population: 5187582, region: 8, regional_spread: 6},
"Connecticut" => {population_density: 741.4, population: 3590347, region: 1, regional_spread: 2},
"Deleware" => {population_density: 470.7, population: 917092, region: 3, regional_spread: 2},
"Florida" => {population_density: 360.2, population: 19317568, region: 3, regional_spread: 5},
"Georgia" => {population_density: 172.5, population: 9919945, region: 3, regional_spread: 5},
"Hawaii" => {population_density: 216.8, population: 1392313, region: 11, regional_spread: 9},
"Idaho" => {population_density: 19.15, population: 1595728, region: 8, regional_spread: 9},
"Illinois" => {population_density: 231.9, population: 12875255, region: 4, regional_spread: 6},
"Indiana" => {population_density: 182.5, population: 6537334, region: 4, regional_spread: 5},
"Iowa" => {population_density: 54.81, population: 3074186, region: 6, regional_spread: 4},
"Kansas" => {population_density: 35.09, population: 2885905, region: 6, regional_spread: 7},
"Kentucky" => {population_density: 110.0, population: 4380415, region: 5, regional_spread: 4},
"Louisiana" => {population_density: 105.0, population: 4601893, region: 7, regional_spread: 5},
"Maine" => {population_density: 43.04, population: 1329192, region: 1, regional_spread: 2},
"Maryland" => {population_density: 606.2, population: 5884563, region: 3, regional_spread: 2},
"Massachusetts" => {population_density: 852.1, population: 6646144, region: 1, regional_spread: 2},
"Michigan" => {population_density: 174.8, population: 9883360, region: 4, regional_spread: 2},
"Minnesota" => {population_density: 67.14, population: 5379139, region: 6, regional_spread: 4},
"Mississippi" => {population_density: 63.50, population: 2984926, region: 5, regional_spread: 7},
"Missouri" => {population_density: 87.26, population: 6021988, region: 6, regional_spread: 4},
"Montana" => {population_density: 6.86, population: 1005141, region: 8, regional_spread: 9},
"Nebraska" => {population_density: 23.97, population: 1855525, region: 6, regional_spread: 8},
"Nevada" => {population_density: 24.8, population: 2758931, region: 8, regional_spread: 9},
"New Hampshire" => {population_density: 147.0, population: 1320718, region: 1, region: 1, regional_spread: 2},
"New Jersey" => {population_density: 1205, population: 8864590, region: 2, regional_spread: 3},
"New Mexico" => {population_density: 17.16, population: 2085538, region: 8, regional_spread: 7},
"New York" => {population_density: 415.3, population: 19570261, region: 2, regional_spread: 1},
"North Carolina" => {population_density: 200.6, population: 9752073, region: 3, regional_spread: 5},
"North Dakota" => {population_density: 9.92, population: 699628, region: 6, regional_spread: 8},
"Ohio" => {population_density: 282.5, population: 11544225, region: 4, regional_spread: 2},
"Oklahoma" => {population_density: 55.22, population: 3814820, region: 7, regional_spread: 6},
"Oregon" => {population_density: 40.33, population: 3899353, region: 9, regional_spread: 8},
"Pennsylvania" => {population_density: 285.3, population: 12763536, region: 2, regional_spread: 3},
"Rhode Island" => {population_density: 1016, population: 1050292, region: 1, regional_spread: 2},
"South Carolina" => {population_density: 157.1, population: 4723723, region: 3, regional_spread: 5},
"South Dakota" => {population_density: 10.86, population: 833354, region: 6, regional_spread: 8},
"Tennessee" => {population_density: 156.6, population: 6456243, region: 5, regional_spread: 3},
"Texas" => {population_density: 98.07, population: 26059203, region: 7, regional_spread: 3},
"Utah" => {population_density: 34.3, population: 2855287, region: 8, regional_spread: 9},
"Vermont" => {population_density: 67.73, population: 626011, region: 1, regional_spread: 2},
"Virginia" => {population_density: 207.3, population: 8185867, region: 3, regional_spread: 2},
"Washington" => {population_density: 102.6, population: 6724540, region: 9, regional_spread: 8},
"Washington,D.C."=> {population_density: 10357, population: 632323, region: 3, regional_spread: 2},
"West Virginia" => {population_density: 77.06, population: 1855413, region: 3, regional_spread: 4},
"Wisconsin" => {population_density: 105.2, population: 5726398, region: 4, regional_spread: 6},
"Wyoming" => {population_density: 5.851, population: 576412, region: 8, regional_spread: 6}
}
# When you are finished with this challenge you should be able to:
# Explain what "require_relative" does and why you would use it
# Demonstrate how to iterate through a hash
# Easily recognize and refactor repetitive code
# Objectives
# 1) Run the code. Look at the output. Look at the input (it's in the other file). Explain what the program is doing.
# 2) Write a comment explaining the require_relative statement below
# 3) Comment each method and define it's responsibility
# 4) New Feature: create a report for all 50 states, not just the 4 listed below. Is there a DRY way of doing this?
# 5) Refactor the virus_effects method. (HINT: what is the scope of instance variables?)
# 6) What is the purpose of "private". What happens if you move it elsewhere in the class?
# 7) Refactor the private methods predicted_deaths and speed_of_spread. How can you make them more DRY?
# 8) BONUS: Access the population by calling it on the instance.
# YOUR NAMES: 1) 2)
# EXPLANATION OF require_relative
#
#
require_relative 'state_data'
class VirusPredictor
def initialize(state_of_origin, population_density, population, region, regional_spread)
@state = state_of_origin
@population = population
@population_density = population_density
@region = region
@next_region = regional_spread
end
def virus_effects
predicted_deaths(@population_density, @population, @state)
speed_of_spread(@population_density, @state)
end
private #what is this? what happens if it were cut and pasted above the virus_effects method
def predicted_deaths(population_density, population, state)
if @population_density >= 200
number_of_deaths = (@population * 0.4).floor
elsif @population_density >= 150
number_of_deaths = (@population * 0.3).floor
elsif @population_density >= 100
number_of_deaths = (@population * 0.2).floor
elsif @population_density >= 50
number_of_deaths = (@population * 0.1).floor
else
number_of_deaths = (@population * 0.05).floor
end
print "#{@state} will lose #{number_of_deaths} people in this outbreak"
end
def speed_of_spread(population_density, state) #in months
speed = 0.0
if @population_density >= 200
speed += 0.5
elsif @population_density >= 150
speed += 1
elsif @population_density >= 100
speed += 1.5
elsif @population_density >= 50
speed += 2
else
speed += 2.5
end
puts " and will spread across the state in #{speed} months.\n\n"
end
end
#=======================================================================
# DRIVER CODE
# initialize VirusPredictor for each state
alabama = VirusPredictor.new("Alabama", STATE_DATA["Alabama"][:population_density], STATE_DATA["Alabama"][:population], STATE_DATA["Alabama"][:region], STATE_DATA["Alabama"][:regional_spread])
alabama.virus_effects
jersey = VirusPredictor.new("New Jersey", STATE_DATA["New Jersey"][:population_density], STATE_DATA["New Jersey"][:population], STATE_DATA["New Jersey"][:region], STATE_DATA["New Jersey"][:regional_spread])
jersey.virus_effects
california = VirusPredictor.new("California", STATE_DATA["California"][:population_density], STATE_DATA["California"][:population], STATE_DATA["California"][:region], STATE_DATA["California"][:regional_spread])
california.virus_effects
alaska = VirusPredictor.new("Alaska", STATE_DATA["Alaska"][:population_density], STATE_DATA["Alaska"][:population], STATE_DATA["Alaska"][:region], STATE_DATA["Alaska"][:regional_spread])
alaska.virus_effects
# YOUR NAMES: Caroline Artz (Went solo, didn't have an opportunity for a GPS for this)
require_relative 'state_data' #requires (links) the content of the file state_data (here its in the same directory)
class VirusPredictor
attr_reader :population #for bonus
def self.state_report(data)
data.each do |state, state_data|
VirusPredictor.new(state, state_data).virus_effects
end
end
def initialize(state_of_origin, state_data)
@state = state_of_origin
@population = state_data[:population]
@population_density = state_data[:population_density]
end
#OBJECTIVE: Refactor the virus_effects method
#calls the two methods below, providing reading access to their output from outside the VirusPredictor class
def virus_effects
predicted_deaths
speed_of_spread
end
#OBJECTIVE: What is the purpose of "private". What happens if you move it elsewhere in the class?
# if this was above the virus_effects method, it would make the virus_predictor method also unavailable for
# access outside the VirusPredictor class, and thus make all but the instance vars inaccessible. Private methods
# can help protect from unwanted behavior elicited outside the class, but care must be taken to ensure public
# access to private method returns/output is made possible via getters.
private
#private method determines/outputs state death impact based on input population density
#OBJECTIVE: Refactor the private method predicted_deaths
def predicted_deaths
calculate = -> m { (@population * m).floor }
number_of_deaths = case @population_density
when 0...50 then calculate.call(0.05)
when 50...100 then calculate.call(0.1)
when 100...150 then calculate.call(0.2)
when 150...200 then calculate.call(0.3)
else calculate.call(0.4)
end
print "#{@state} will lose #{number_of_deaths} people in this outbreak"
end
#private method determines/outputs disease spread speed based on input state population density
#OBJECTIVE: Refactor the private method speed_of_spread.
def speed_of_spread #in months
speed = case @population_density
when 0...50 then 2.5
when 50...100 then 2
when 100...150 then 1.5
when 150...200 then 1
else 0.5
end
puts " and will spread across the state in #{speed} months.\n\n"
end
end
#=======================================================================
# OBJECTIVE: create a report for all 50 states, not just the 4 listed below.
VirusPredictor.state_report(STATE_DATA) #=> FOR ALL STATES, print: "<state> will lose <quantity> people in this outbreak and
# will spread across the state in <time> months"
#OBJECTIVE: BONUS: Access the population by calling it on the instance.
p VirusPredictor.new('Michigan', STATE_DATA['Michigan']).population #=> 9883360
p VirusPredictor.new('Illinois', STATE_DATA['Illinois']).population #=> 12875255