class WxAlert::Alert
Class containing an individual alert. Each alert has 3 variables: alert - The hash containing the alert itself fixed - If the alert has been fixed and processed full - If the alert is the complete CAP alert versus
what's pulled from the index.
TODO: full - If the alert is the complete CAP alert
Constants
- HVTEC_ERR
Empty H-VETCS appear as this in the index
- NONE
String constants
Attributes
Class getters
Class getters
Class getters
Public Class Methods
Takes a hash and converts each string key into a symbol. Since some values in an alert hash are hashes themselves, this method will convert the keys of all sub hashes as well as the parent hash.
# File lib/WxAlert/alert.rb, line 52 def self.hash_str_key_to_sym(hash) # Map through each hash hash.map do |key, value| # If the value is a hash, recurse through it if value.is_a? Hash # Recurse and replace sub hashes temp = hash_str_key_to_sym(value) value.replace(temp.pop) end # Convert each key to a symbol {str_to_sym(key) => value} end end
Sets up new alert taking two parameters, a hash containing a raw alert and a boolean if the alert has already been fixed.
# File lib/WxAlert/alert.rb, line 24 def initialize(alert, fixed = false) @alert = alert @fixed = fixed @full = false fix unless fixed self end
Extremely clever function that converts strings to symbols for the purpose of making raw NWS alerts into slightly prettier Ruby hashes.
# File lib/WxAlert/alert.rb, line 35 def self.str_to_sym(str) # Make sure str is actually a string and symbol-able # This is mostly to catch keys that are already symbols if str.respond_to?('gsub') && str.respond_to?('to_sym') # EXTREMELY CLEVER PROGRAMMING (please hire me) str.gsub(/\s+/, '_').downcase.to_sym else # Return whatever was passed in str end end
Public Instance Methods
Fix the ugly, raw alert. Turns keys to symbols, and extracts various data elements. TODO: Deal with this one-level-nested hashes. Probs flatten them.
# File lib/WxAlert/alert.rb, line 77 def fix # Don't fix a fixed alert return @alert if @fixed # Change keys to symbols and flatten the hash. @alert.replace( Alert.hash_str_key_to_sym(@alert).reduce({}, :merge)) # Run the fixing methods if a valid alert. apply_fixes unless not_alert? @fixed = true # Return the alert hash @alert end
Takes a hash key and value, returns true if the Alert's alert hash has a matching key and value. If the key corresponds to an array, if any element in the array matches the value. TODO: Check sub hashes
# File lib/WxAlert/alert.rb, line 98 def match?(hash_key, value) # real_value = @alert[hash_key] # Check the contents of any arrays if @alert[hash_key].is_a? Array @alert[hash_key].map { |str| str.include? value }.include? true else @alert[hash_key].include? value end end
Return true if the Alert
object is actually not an alert. That is, it is the no alerts message from NWS.
# File lib/WxAlert/alert.rb, line 69 def not_alert? true if @alert[:title] == 'There are no active watches'\ ', warnings or advisories' end
Retrieve the entire CAP alert. Specifically retrieves the entire description text, and the timemotloc code. TODO: Do something else with the timemotloc code TODO: Get Instructions
# File lib/WxAlert/alert.rb, line 113 def retrieve_full return self if @full || not_alert? full = Downloader.get(@alert[:id])['alert']['info'] @alert[:summary] = full['description'] @alert[:timemotloc] = full['parameter'].last[:value] @alert[:timemotloc] ||= NONE @full = true self end
Protected Instance Methods
Clever way to appease Rubocop and take advantage of a neat Ruby feature. Also easy to add more stuff.
# File lib/WxAlert/alert.rb, line 130 def apply_fixes fix_methods = [:fix_vtec, :fix_geocode, :fix_polygon, :fix_areadesc, :fix_nested_hashes] fix_methods.each { |method| send(method) } # Add the empty timemotloc key @alert[:timemotloc] = NONE end
Split up human readable location descriptions into an array.
# File lib/WxAlert/alert.rb, line 262 def fix_areadesc @alert[:areadesc] = @alert[:areadesc].split(/;\s/) end
Split up the FIPS codes and put them in an array.
# File lib/WxAlert/alert.rb, line 221 def fix_fips(geocodes) if geocodes.respond_to?('split') @alert[:fips] = geocodes.split else @alert[:fips] = [NONE] end end
Clean up the geocodes, that is, split up the FIPS and UGC codes, and put them into array.
# File lib/WxAlert/alert.rb, line 204 def fix_geocode bad_geocodes = @alert[:geocode][:value] # Some alerts don't have geocodes if bad_geocodes.is_a?(Array) && bad_geocodes.length == 2 fix_fips(bad_geocodes[0]) fix_ugc(bad_geocodes[1]) else return end # Get rid of the old geocode key @alert.delete(:geocode) end
Flatten unneeded sub-hashes, that is, keys that map to a hash with exactly one key-value pair.
# File lib/WxAlert/alert.rb, line 140 def fix_nested_hashes @alert.each do |key, val| if val.is_a?(Hash) && val.length == 1 @alert[key] = val.first[1] end end end
Split up each set of coordinates and put each set as a two element array, and each of those arrays in an array. TODO: Convert the number string to a float
# File lib/WxAlert/alert.rb, line 246 def fix_polygon polygon = @alert[:polygon] # If there is a polygon, convert it to an # array of coordinates. if polygon.respond_to?('split') @alert[:polygon] = polygon.split.map do |pnt| pnt.split(',').map { |coord| coord.to_f } end else @alert[:polygon] = NONE end end
Split up the UGC codes and put them in an array. NOTE: As far as I can tell, in the indexes every UGC code is listed, and are not abbreviated like in 'full' CAP alerts.
# File lib/WxAlert/alert.rb, line 234 def fix_ugc(geocodes) if geocodes.respond_to?('split') @alert[:ugc] = geocodes.split else @alert[:ugc] = [NONE] end end
VTECs come in funky. Sometimes only one is present, when both are, they are separated by a newline.
# File lib/WxAlert/alert.rb, line 150 def fix_vtec # Split up the VTECs, which come in the specified location # for some reason I'm not sure of. if @alert[:parameter][:value].respond_to?('length') # Split up the VTECs pvtec, hvtec = split_vtec @alert[:parameter][:value] else # If there isn't any VTECs assign NONE to both pvtec, hvtec = NONE, NONE end # By the way, RuboCop needs to just chill the hell out. # When I clean this up it is getting configured SO HARD @alert[:pvtec], @alert[:hvtec] = pvtec.to_s, hvtec.to_s # Delete the weirdly named ex-home of the VTEC(s) @alert.delete(:parameter) end
Split up the raw VTEC string depending on which VTECs are present. Takes the raw vtec string returns pvtec, hvtec
# File lib/WxAlert/alert.rb, line 174 def split_vtec(vtec) # Get rid of the newline, if it exists. vtec = vtec.split("\n") vtec_str = vtec.join # I'LL TAKE THE CASE! # Assigns VTECs depending on which exist. case vtec_str.length when 48 # P-VTECs are 48 characters return vtec_str, NONE when 54 # H-VTECs are 54 characters # Change any 'error' hvtecs to NONE (vtec_str == HVTEC_ERR) ? hvtec = NONE : hvtec = vtec_str return NONE, hvtec else # Both codes exist, or something is super borked. # pvtec, hvtec if vtec.length == 2 return vtec[0], vtec[1] else return NONE, NONE end end end