carolineartz
2/19/2014 - 12:24 AM

Virus Predictor

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