faa 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +0 -0
- data/Rakefile +33 -0
- data/lib/faa.rb +22 -0
- data/lib/faa/airport.rb +2 -0
- data/lib/faa/airport/closure.rb +28 -0
- data/lib/faa/delay.rb +28 -0
- data/lib/faa/delay/airspace_flow.rb +63 -0
- data/lib/faa/delay/airspace_flow/circle.rb +17 -0
- data/lib/faa/delay/airspace_flow/line.rb +20 -0
- data/lib/faa/delay/airspace_flow/polygon.rb +20 -0
- data/lib/faa/delay/general.rb +71 -0
- data/lib/faa/delay/general_arrival.rb +2 -0
- data/lib/faa/delay/general_departure.rb +2 -0
- data/lib/faa/delay/ground_delay.rb +57 -0
- data/lib/faa/delay/ground_stop.rb +25 -0
- data/lib/faa/delay_feed.rb +45 -0
- data/test/delay_feed_test.rb +109 -0
- data/test/responses/delays_with_icao_code.xml +49 -0
- data/test/responses/no_delays.xml +7 -0
- data/test/responses/various_delays.xml +95 -0
- data/test/responses/various_delays_with_air_flow_program.xml +166 -0
- data/test/test_helper.rb +7 -0
- metadata +86 -0
    
        data/README.rdoc
    ADDED
    
    | 
            File without changes
         | 
    
        data/Rakefile
    ADDED
    
    | @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            require 'rubygems'
         | 
| 2 | 
            +
            require 'rake'
         | 
| 3 | 
            +
            require 'rake/testtask'
         | 
| 4 | 
            +
            require 'metric_fu'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            Rake::TestTask.new(:test) do |t|
         | 
| 9 | 
            +
              t.test_files = FileList['test/*_test.rb']
         | 
| 10 | 
            +
            end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            MetricFu::Configuration.run do |config|
         | 
| 13 | 
            +
                config.metrics  = [:churn, :saikuro, :flog, :flay, :reek, :roodi]
         | 
| 14 | 
            +
                config.flay     = { :dirs_to_flay => ['lib']  } 
         | 
| 15 | 
            +
                config.flog     = { :dirs_to_flog => ['lib']  }
         | 
| 16 | 
            +
                config.reek     = { :dirs_to_reek => ['lib']  }
         | 
| 17 | 
            +
                config.roodi    = { :dirs_to_roodi => ['lib'] }
         | 
| 18 | 
            +
                config.saikuro  = { :output_directory => 'tmp/scratch/saikuro', 
         | 
| 19 | 
            +
                                    :input_directory => ['lib'],
         | 
| 20 | 
            +
                                    :cyclo => "",
         | 
| 21 | 
            +
                                    :filter_cyclo => "0",
         | 
| 22 | 
            +
                                    :warn_cyclo => "5",
         | 
| 23 | 
            +
                                    :error_cyclo => "7",
         | 
| 24 | 
            +
                                    :formater => "text"} #this needs to be set to "text"
         | 
| 25 | 
            +
                config.churn    = { :start_date => "1 year ago", :minimum_churn_count => 10}
         | 
| 26 | 
            +
                config.rcov     = { :test_files => ['spec/*_spec.rb'],
         | 
| 27 | 
            +
                                    :rcov_opts => ["--sort coverage",
         | 
| 28 | 
            +
                                                   "--no-html", 
         | 
| 29 | 
            +
                                                   "--text-coverage",
         | 
| 30 | 
            +
                                                   "--no-color",
         | 
| 31 | 
            +
                                                   "--profile",
         | 
| 32 | 
            +
                                                   "--exclude /gems/,/Library/,spec"]}
         | 
| 33 | 
            +
            end
         | 
    
        data/lib/faa.rb
    ADDED
    
    | @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            require 'libxml'
         | 
| 2 | 
            +
            require 'net/http'
         | 
| 3 | 
            +
            require 'uri'
         | 
| 4 | 
            +
            require 'time'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module FAA
         | 
| 7 | 
            +
              VERSION = '0.0.1'
         | 
| 8 | 
            +
            end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            require 'faa/airport'
         | 
| 11 | 
            +
            require 'faa/airport/closure'
         | 
| 12 | 
            +
            require 'faa/delay'
         | 
| 13 | 
            +
            require 'faa/delay_feed'
         | 
| 14 | 
            +
            require 'faa/delay/general'
         | 
| 15 | 
            +
            require 'faa/delay/general_arrival'
         | 
| 16 | 
            +
            require 'faa/delay/general_departure'
         | 
| 17 | 
            +
            require 'faa/delay/ground_delay'
         | 
| 18 | 
            +
            require 'faa/delay/ground_stop'
         | 
| 19 | 
            +
            require 'faa/delay/airspace_flow'
         | 
| 20 | 
            +
            require 'faa/delay/airspace_flow/line'
         | 
| 21 | 
            +
            require 'faa/delay/airspace_flow/polygon'
         | 
| 22 | 
            +
            require 'faa/delay/airspace_flow/circle'
         | 
    
        data/lib/faa/airport.rb
    ADDED
    
    
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            class FAA::Airport::Closure
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              attr_accessor :airport_id, :reason, :start, :reopen
         | 
| 4 | 
            +
              
         | 
| 5 | 
            +
              
         | 
| 6 | 
            +
              def self.from_xml(root)
         | 
| 7 | 
            +
                closures = []
         | 
| 8 | 
            +
                
         | 
| 9 | 
            +
                root.children.each do |node|
         | 
| 10 | 
            +
                  delay = new
         | 
| 11 | 
            +
                  node.children.each do |child|
         | 
| 12 | 
            +
                    case child.name
         | 
| 13 | 
            +
                    when 'ARPT'
         | 
| 14 | 
            +
                      delay.airport_id = child.content.strip
         | 
| 15 | 
            +
                    when 'Reason'
         | 
| 16 | 
            +
                      delay.reason = child.content.strip
         | 
| 17 | 
            +
                    when 'Start'
         | 
| 18 | 
            +
                      delay.start = child.content.strip
         | 
| 19 | 
            +
                    when 'Reopen'
         | 
| 20 | 
            +
                      delay.reopen = child.content.strip
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                  closures << delay
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
                closures
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
              
         | 
| 28 | 
            +
            end
         | 
    
        data/lib/faa/delay.rb
    ADDED
    
    | @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            class FAA::Delay
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              attr_accessor :airport_id, :reason
         | 
| 4 | 
            +
              
         | 
| 5 | 
            +
              class << self
         | 
| 6 | 
            +
                
         | 
| 7 | 
            +
                def from_xml(node)
         | 
| 8 | 
            +
                  delays = []
         | 
| 9 | 
            +
                  node.children.each do |delay_list|
         | 
| 10 | 
            +
                    case delay_list.name
         | 
| 11 | 
            +
                    when 'Ground_Stop_List'
         | 
| 12 | 
            +
                      delays += FAA::Delay::GroundStop.from_xml(delay_list)
         | 
| 13 | 
            +
                    when 'Ground_Delay_List'
         | 
| 14 | 
            +
                      delays += FAA::Delay::GroundDelay.from_xml(delay_list)
         | 
| 15 | 
            +
                    when 'Airspace_Flow_List'
         | 
| 16 | 
            +
                      delays += FAA::Delay::AirspaceFlow.from_xml(delay_list)
         | 
| 17 | 
            +
                    when 'Arrival_Departure_Delay_List'
         | 
| 18 | 
            +
                      delays += FAA::Delay::General.from_xml(delay_list)
         | 
| 19 | 
            +
                    when 'Airport_Closure_List'
         | 
| 20 | 
            +
                      delays += FAA::Airport::Closure.from_xml(delay_list)
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                  delays
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
                
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
              
         | 
| 28 | 
            +
            end
         | 
| @@ -0,0 +1,63 @@ | |
| 1 | 
            +
            class FAA::Delay::AirspaceFlow
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              attr_accessor :control_element, :reason, :fca_start_time, :fca_end_time,
         | 
| 4 | 
            +
                :afp_start_time, :afp_end_time, :average, :floor, :ceiling
         | 
| 5 | 
            +
              
         | 
| 6 | 
            +
              def self.from_xml(root)
         | 
| 7 | 
            +
                flows = []
         | 
| 8 | 
            +
                
         | 
| 9 | 
            +
                root.children.each do |child_flow|
         | 
| 10 | 
            +
                  flow = case child_flow.children.find { |x| ["Line", "Polygon", "Circle"].include?(x.name) }.name
         | 
| 11 | 
            +
                  when 'Line'
         | 
| 12 | 
            +
                    FAA::Delay::AirspaceFlow::Line.from_xml(child_flow.children.find { |x| x.name == 'Line' })
         | 
| 13 | 
            +
                  when 'Polygon'
         | 
| 14 | 
            +
                    FAA::Delay::AirspaceFlow::Polygon.from_xml(child_flow.children.find { |x| x.name == 'Polygon' })
         | 
| 15 | 
            +
                  when 'Circle'
         | 
| 16 | 
            +
                    FAA::Delay::AirspaceFlow::Circle.from_xml(child_flow.children.find { |x| x.name == 'Circle' })
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                
         | 
| 19 | 
            +
                  child_flow.children.each do |node|
         | 
| 20 | 
            +
                    case node.name
         | 
| 21 | 
            +
                    when 'CTL_Element'
         | 
| 22 | 
            +
                      flow.control_element = node.content.strip
         | 
| 23 | 
            +
                    when 'Reason'
         | 
| 24 | 
            +
                      flow.reason = node.content.strip
         | 
| 25 | 
            +
                    when 'FCA_Start_DateTime'
         | 
| 26 | 
            +
                      flow.fca_start_time = Time.utc(node.content[0..3], node.content[4..5], node.content[6..7], node.content[8..9], node.content[10..11], node.content[12..13])
         | 
| 27 | 
            +
                    when 'FCA_End_DateTime'
         | 
| 28 | 
            +
                      flow.fca_end_time = Time.utc(node.content[0..3], node.content[4..5], node.content[6..7], node.content[8..9], node.content[10..11], node.content[12..13])
         | 
| 29 | 
            +
                    when 'AFP_StartTime'
         | 
| 30 | 
            +
                      flow.afp_start_time = Time.utc(flow.fca_start_time.year, flow.fca_start_time.month, flow.fca_start_time.day, node.content[0..1], node.content[2..3])
         | 
| 31 | 
            +
                      flow.afp_start_time += 86400 if flow.afp_start_time < flow.fca_start_time
         | 
| 32 | 
            +
                    when 'AFP_EndTime'
         | 
| 33 | 
            +
                      flow.afp_end_time = Time.utc(flow.fca_end_time.year, flow.fca_end_time.month, flow.fca_end_time.day, node.content[0..1], node.content[2..3])
         | 
| 34 | 
            +
                      flow.afp_end_time -= 86400 if flow.afp_end_time > flow.fca_end_time
         | 
| 35 | 
            +
                    when 'Avg'
         | 
| 36 | 
            +
                      flow.average = node.content.strip
         | 
| 37 | 
            +
                    when 'Floor'
         | 
| 38 | 
            +
                      flow.floor = node.content.to_i
         | 
| 39 | 
            +
                    when 'Ceiling'
         | 
| 40 | 
            +
                      flow.ceiling = node.content.to_i
         | 
| 41 | 
            +
                    end
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                  flows << flow
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
                flows
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
              
         | 
| 48 | 
            +
              # Accetps either a string like `1 hour 5 min` or an integer representing the minutes
         | 
| 49 | 
            +
              def average=(object)
         | 
| 50 | 
            +
                case object
         | 
| 51 | 
            +
                when Integer
         | 
| 52 | 
            +
                  @average = object
         | 
| 53 | 
            +
                when String
         | 
| 54 | 
            +
                  @average = 0
         | 
| 55 | 
            +
                  @average += $1.to_i if object =~ /([0-9]+) minutes/
         | 
| 56 | 
            +
                  @average += $1.to_i*60 if object =~ /([0-9]+) hour/
         | 
| 57 | 
            +
                  @average += $1.to_i*60*24 if object =~ /([0-9]+) day/
         | 
| 58 | 
            +
                else
         | 
| 59 | 
            +
                  raise ArgumentError, "Must be a string or integer"
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
              
         | 
| 63 | 
            +
            end
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            class FAA::Delay::AirspaceFlow::Circle < FAA::Delay::AirspaceFlow
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              attr_accessor :center, :radius
         | 
| 4 | 
            +
              
         | 
| 5 | 
            +
              def self.from_xml(xml)
         | 
| 6 | 
            +
                circle = new
         | 
| 7 | 
            +
                circle.radius = xml.attributes['Radius'].to_i * 1852
         | 
| 8 | 
            +
                xml.children.each do |child|
         | 
| 9 | 
            +
                  if child.name == "Center"
         | 
| 10 | 
            +
                    circle.center << {'latitude' => child.attributes['Lat'].to_f,
         | 
| 11 | 
            +
                                      'longitude' => child.attributes['Long'].to_f}
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
                circle
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
              
         | 
| 17 | 
            +
            end
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            class FAA::Delay::AirspaceFlow::Line < FAA::Delay::AirspaceFlow
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              attr_accessor :points
         | 
| 4 | 
            +
              
         | 
| 5 | 
            +
              def initialize
         | 
| 6 | 
            +
                @points = []
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
              
         | 
| 9 | 
            +
              def self.from_xml(xml)
         | 
| 10 | 
            +
                line = new
         | 
| 11 | 
            +
                xml.children.each do |child|
         | 
| 12 | 
            +
                  if child.name == "Point"
         | 
| 13 | 
            +
                    line.points << {'latitude' => child.attributes['Lat'].to_f,
         | 
| 14 | 
            +
                                    'longitude' => child.attributes['Long'].to_f}
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
                line
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
              
         | 
| 20 | 
            +
            end
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            class FAA::Delay::AirspaceFlow::Polygon < FAA::Delay::AirspaceFlow
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              attr_accessor :points
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              def initialize
         | 
| 6 | 
            +
                @points = []
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              def self.parse(xml)
         | 
| 10 | 
            +
                poly = new
         | 
| 11 | 
            +
                xml.children.each do |child|
         | 
| 12 | 
            +
                  if child.name == "Point"
         | 
| 13 | 
            +
                    poly.points << {'latitude' => child.attributes['Lat'].to_f,
         | 
| 14 | 
            +
                                    'longitude' => child.attributes['Long'].to_f}
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
                poly
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
              
         | 
| 20 | 
            +
            end
         | 
| @@ -0,0 +1,71 @@ | |
| 1 | 
            +
            class FAA::Delay::General < FAA::Delay
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              attr_accessor :minimum, :maximum, :trend, :reason
         | 
| 4 | 
            +
              
         | 
| 5 | 
            +
              # Blame the F***** FAA for this function, who does their crappy xml?
         | 
| 6 | 
            +
              def self.from_xml(root)
         | 
| 7 | 
            +
                delays = []
         | 
| 8 | 
            +
                
         | 
| 9 | 
            +
                root.children.each do |child|
         | 
| 10 | 
            +
                  delay = case child.children.find { |x| x.name == "Arrival_Departure" }['Type']
         | 
| 11 | 
            +
                  when 'Departure'
         | 
| 12 | 
            +
                    FAA::Delay::GeneralDeparture.new
         | 
| 13 | 
            +
                  when 'Arrival'
         | 
| 14 | 
            +
                    FAA::Delay::GeneralArrival.new
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                  
         | 
| 17 | 
            +
                  child.children.each do |node|
         | 
| 18 | 
            +
                    case node.name
         | 
| 19 | 
            +
                    when 'ARPT'
         | 
| 20 | 
            +
                      delay.airport_id = node.content.strip
         | 
| 21 | 
            +
                    when 'Reason'
         | 
| 22 | 
            +
                      delay.reason = node.content.strip
         | 
| 23 | 
            +
                    when 'Arrival_Departure'
         | 
| 24 | 
            +
                      node.children.each do |child2|
         | 
| 25 | 
            +
                        case child2.name
         | 
| 26 | 
            +
                        when 'Trend'
         | 
| 27 | 
            +
                          delay.trend = child2.content.strip.downcase
         | 
| 28 | 
            +
                        when 'Min'
         | 
| 29 | 
            +
                          delay.minimum = child2.content
         | 
| 30 | 
            +
                        when 'Max'
         | 
| 31 | 
            +
                          delay.maximum = child2.content
         | 
| 32 | 
            +
                        end
         | 
| 33 | 
            +
                      end
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
                  delays << delay
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
                delays
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
              
         | 
| 41 | 
            +
              # Accetps either a string like `1 hour 5 min` or an integer representing the minutes
         | 
| 42 | 
            +
              def maximum=(object)
         | 
| 43 | 
            +
                case object
         | 
| 44 | 
            +
                when Integer
         | 
| 45 | 
            +
                  @maximum = object
         | 
| 46 | 
            +
                when String
         | 
| 47 | 
            +
                  @maximum = 0
         | 
| 48 | 
            +
                  @maximum += $1.to_i if object =~ /([0-9]+) minutes/
         | 
| 49 | 
            +
                  @maximum += $1.to_i*60 if object =~ /([0-9]+) hour/
         | 
| 50 | 
            +
                  @maximum += $1.to_i*60*24 if object =~ /([0-9]+) day/
         | 
| 51 | 
            +
                else
         | 
| 52 | 
            +
                  raise ArgumentError, "Must be a string or integer"
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
              
         | 
| 56 | 
            +
              # Accetps either a string like `1 hour 5 min` or an integer representing the minutes
         | 
| 57 | 
            +
              def minimum=(object)
         | 
| 58 | 
            +
                case object
         | 
| 59 | 
            +
                when Integer
         | 
| 60 | 
            +
                  @minimum = object
         | 
| 61 | 
            +
                when String
         | 
| 62 | 
            +
                  @minimum = 0
         | 
| 63 | 
            +
                  @minimum += $1.to_i if object =~ /([0-9]+) minutes/
         | 
| 64 | 
            +
                  @minimum += $1.to_i*60 if object =~ /([0-9]+) hour/
         | 
| 65 | 
            +
                  @minimum += $1.to_i*60*24 if object =~ /([0-9]+) day/
         | 
| 66 | 
            +
                else
         | 
| 67 | 
            +
                  raise ArgumentError, "Must be a string or integer"
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
              
         | 
| 71 | 
            +
            end
         | 
| @@ -0,0 +1,57 @@ | |
| 1 | 
            +
            class FAA::Delay::GroundDelay < FAA::Delay
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              attr_accessor :average, :maximum
         | 
| 4 | 
            +
              
         | 
| 5 | 
            +
              def self.from_xml(root)
         | 
| 6 | 
            +
                delays = []
         | 
| 7 | 
            +
                
         | 
| 8 | 
            +
                root.children.each do |node|
         | 
| 9 | 
            +
                  delay = new
         | 
| 10 | 
            +
                  node.children.each do |child|
         | 
| 11 | 
            +
                    case child.name
         | 
| 12 | 
            +
                    when 'ARPT'
         | 
| 13 | 
            +
                      delay.airport_id = child.content.strip
         | 
| 14 | 
            +
                    when 'Reason'
         | 
| 15 | 
            +
                      delay.reason = child.content.strip
         | 
| 16 | 
            +
                    when 'Avg'
         | 
| 17 | 
            +
                      delay.average = child.content
         | 
| 18 | 
            +
                    when 'Max'
         | 
| 19 | 
            +
                      delay.maximum = child.content
         | 
| 20 | 
            +
                    end
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                  delays << delay
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
                delays
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
              
         | 
| 27 | 
            +
              # Accetps either a string like `1 hour 5 min` or an integer representing the minutes
         | 
| 28 | 
            +
              def average=(object)
         | 
| 29 | 
            +
                case object
         | 
| 30 | 
            +
                when Integer
         | 
| 31 | 
            +
                  @average = object
         | 
| 32 | 
            +
                when String
         | 
| 33 | 
            +
                  @average = 0
         | 
| 34 | 
            +
                  @average += $1.to_i if object =~ /([0-9]+) minutes/
         | 
| 35 | 
            +
                  @average += $1.to_i*60 if object =~ /([0-9]+) hour/
         | 
| 36 | 
            +
                  @average += $1.to_i*60*24 if object =~ /([0-9]+) day/
         | 
| 37 | 
            +
                else
         | 
| 38 | 
            +
                  raise ArgumentError, "Must be a string or integer"
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
              
         | 
| 42 | 
            +
              # Accetps either a string like `1 hour 5 min` or an integer representing the minutes
         | 
| 43 | 
            +
              def maximum=(object)
         | 
| 44 | 
            +
                case object
         | 
| 45 | 
            +
                when Integer
         | 
| 46 | 
            +
                  @maximum = object
         | 
| 47 | 
            +
                when String
         | 
| 48 | 
            +
                  @maximum = 0
         | 
| 49 | 
            +
                  @maximum += $1.to_i if object =~ /([0-9]+) minutes/
         | 
| 50 | 
            +
                  @maximum += $1.to_i*60 if object =~ /([0-9]+) hour/
         | 
| 51 | 
            +
                  @maximum += $1.to_i*60*24 if object =~ /([0-9]+) day/
         | 
| 52 | 
            +
                else
         | 
| 53 | 
            +
                  raise ArgumentError, "Must be a string or integer"
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
              
         | 
| 57 | 
            +
            end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            class FAA::Delay::GroundStop < FAA::Delay
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              attr_accessor :end_time
         | 
| 4 | 
            +
              
         | 
| 5 | 
            +
              def self.from_xml(xml)
         | 
| 6 | 
            +
                delays = []
         | 
| 7 | 
            +
                
         | 
| 8 | 
            +
                xml.children.each do |node|
         | 
| 9 | 
            +
                  delay = new
         | 
| 10 | 
            +
                  node.children.each do |child|
         | 
| 11 | 
            +
                    case child.name
         | 
| 12 | 
            +
                    when 'ARPT'
         | 
| 13 | 
            +
                      delay.airport_id = child.content.strip
         | 
| 14 | 
            +
                    when 'Reason'
         | 
| 15 | 
            +
                      delay.reason = child.content.strip
         | 
| 16 | 
            +
                    when 'End_Time'
         | 
| 17 | 
            +
                      delay.end_time = Time.parse(child.content)
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                  delays << delay
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
                delays
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
              
         | 
| 25 | 
            +
            end
         | 
| @@ -0,0 +1,45 @@ | |
| 1 | 
            +
            class FAA::DelayFeed
         | 
| 2 | 
            +
              FEED_URI = 'http://www.fly.faa.gov/flyfaa/xmlAirportStatus.jsp'
         | 
| 3 | 
            +
              
         | 
| 4 | 
            +
              attr_reader :updated_at, :delays, :raw
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              def initialize(raw=nil)
         | 
| 7 | 
            +
                @raw = raw ? raw : FAA::DelayFeed.raw_feed.read
         | 
| 8 | 
            +
                @delays = []
         | 
| 9 | 
            +
                parse_xml_feed
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
              
         | 
| 12 | 
            +
              def parse_xml_feed
         | 
| 13 | 
            +
                options = {:options => LibXML::XML::Parser::Options::NOBLANKS}
         | 
| 14 | 
            +
                document = LibXML::XML::Parser.string(@raw, options).parse
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                document.root.children.each do |node|
         | 
| 17 | 
            +
                  case node.name
         | 
| 18 | 
            +
                  when 'Update_Time'
         | 
| 19 | 
            +
                    @updated_at = Time.parse(node.content).utc
         | 
| 20 | 
            +
                  when 'Delay_type'
         | 
| 21 | 
            +
                    @delays += FAA::Delay.from_xml(node)
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
              
         | 
| 26 | 
            +
              
         | 
| 27 | 
            +
              class << self
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                # The URI of the feed.
         | 
| 30 | 
            +
                def uri
         | 
| 31 | 
            +
                  @uri ||= URI.parse(FEED_URI)
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                # A StringIO object with the raw xml feed
         | 
| 35 | 
            +
                def raw_feed
         | 
| 36 | 
            +
                  http = Net::HTTP.new(uri.host, uri.port)
         | 
| 37 | 
            +
                  StringIO.new(http.get(uri.path).body)
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                def current_delays
         | 
| 41 | 
            +
                  self.new.delays
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
                
         | 
| 45 | 
            +
            end
         | 
| @@ -0,0 +1,109 @@ | |
| 1 | 
            +
            require File.dirname(__FILE__) + '/test_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class DelayFeedTest < Test::Unit::TestCase
         | 
| 4 | 
            +
              
         | 
| 5 | 
            +
              def test_should_find_no_delays
         | 
| 6 | 
            +
                FakeWeb.register_uri(:get, "http://www.fly.faa.gov/flyfaa/xmlAirportStatus.jsp",
         | 
| 7 | 
            +
                  :body => File.read("#{File.dirname(__FILE__)}/responses/no_delays.xml"))
         | 
| 8 | 
            +
                assert_equal 0, FAA::DelayFeed.current_delays.size
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
              
         | 
| 11 | 
            +
              def test_should_have_10_delays
         | 
| 12 | 
            +
                FakeWeb.register_uri(:get, "http://www.fly.faa.gov/flyfaa/xmlAirportStatus.jsp",
         | 
| 13 | 
            +
                  :body => File.read("#{File.dirname(__FILE__)}/responses/various_delays.xml"))
         | 
| 14 | 
            +
                assert_equal 10, FAA::DelayFeed.current_delays.size
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
              
         | 
| 17 | 
            +
              def test_should_have_4_ground_delays
         | 
| 18 | 
            +
                FakeWeb.register_uri(:get, "http://www.fly.faa.gov/flyfaa/xmlAirportStatus.jsp",
         | 
| 19 | 
            +
                  :body => File.read("#{File.dirname(__FILE__)}/responses/various_delays.xml"))
         | 
| 20 | 
            +
                delays = FAA::DelayFeed.current_delays.select { |x| x.class == FAA::Delay::GroundDelay }
         | 
| 21 | 
            +
                delay = delays.first
         | 
| 22 | 
            +
                assert_equal 4, delays.size
         | 
| 23 | 
            +
                assert_equal 'BOS', delay.airport_id
         | 
| 24 | 
            +
                assert_equal 'WEATHER / LOW CEILINGS', delay.reason
         | 
| 25 | 
            +
                assert_equal 46, delay.average
         | 
| 26 | 
            +
                assert_equal 0, delay.maximum
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
              
         | 
| 29 | 
            +
              def test_should_have_4_departure_delays
         | 
| 30 | 
            +
                FakeWeb.register_uri(:get, "http://www.fly.faa.gov/flyfaa/xmlAirportStatus.jsp",
         | 
| 31 | 
            +
                  :body => File.read("#{File.dirname(__FILE__)}/responses/various_delays.xml"))
         | 
| 32 | 
            +
                delays = FAA::DelayFeed.current_delays.select { |x| x.class == FAA::Delay::GeneralDeparture }
         | 
| 33 | 
            +
                delay = delays.first
         | 
| 34 | 
            +
                assert_equal 4, delays.size
         | 
| 35 | 
            +
                assert_equal 'CLT', delay.airport_id
         | 
| 36 | 
            +
                assert_equal 'WX:Thunderstorms', delay.reason
         | 
| 37 | 
            +
                assert_equal 16, delay.minimum
         | 
| 38 | 
            +
                assert_equal 30, delay.maximum
         | 
| 39 | 
            +
                assert_equal 'increasing', delay.trend
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
              
         | 
| 42 | 
            +
              def test_should_have_2_arrival_delays
         | 
| 43 | 
            +
                FakeWeb.register_uri(:get, "http://www.fly.faa.gov/flyfaa/xmlAirportStatus.jsp",
         | 
| 44 | 
            +
                  :body => File.read("#{File.dirname(__FILE__)}/responses/various_delays.xml"))
         | 
| 45 | 
            +
                delays = FAA::DelayFeed.current_delays.select { |x| x.class == FAA::Delay::GeneralArrival }
         | 
| 46 | 
            +
                delay = delays.first
         | 
| 47 | 
            +
                assert_equal 2, delays.size
         | 
| 48 | 
            +
                assert_equal 'FLL', delay.airport_id
         | 
| 49 | 
            +
                assert_equal 'WX:Thunderstorms', delay.reason
         | 
| 50 | 
            +
                assert_equal 31, delay.minimum
         | 
| 51 | 
            +
                assert_equal 45, delay.maximum
         | 
| 52 | 
            +
                assert_equal 'increasing', delay.trend
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
              
         | 
| 55 | 
            +
              def test_delay_feed_should_have_3_ground_stops
         | 
| 56 | 
            +
                FakeWeb.register_uri(:get, "http://www.fly.faa.gov/flyfaa/xmlAirportStatus.jsp",
         | 
| 57 | 
            +
                  :body => File.read("#{File.dirname(__FILE__)}/responses/various_delays_with_air_flow_program.xml"))
         | 
| 58 | 
            +
                delays = FAA::DelayFeed.current_delays.select { |x| x.class == FAA::Delay::GroundStop }
         | 
| 59 | 
            +
                assert_equal 3, delays.size
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
              
         | 
| 62 | 
            +
              def test_delay_feed_should_have_4_ground_delays
         | 
| 63 | 
            +
                FakeWeb.register_uri(:get, "http://www.fly.faa.gov/flyfaa/xmlAirportStatus.jsp",
         | 
| 64 | 
            +
                  :body => File.read("#{File.dirname(__FILE__)}/responses/various_delays_with_air_flow_program.xml"))
         | 
| 65 | 
            +
                delays = FAA::DelayFeed.current_delays.select { |x| x.class == FAA::Delay::GroundDelay }
         | 
| 66 | 
            +
                assert_equal 4, delays.size
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
              
         | 
| 69 | 
            +
              def test_delay_feed_should_have_2_air_flow_programs
         | 
| 70 | 
            +
                FakeWeb.register_uri(:get, "http://www.fly.faa.gov/flyfaa/xmlAirportStatus.jsp",
         | 
| 71 | 
            +
                  :body => File.read("#{File.dirname(__FILE__)}/responses/various_delays_with_air_flow_program.xml"))
         | 
| 72 | 
            +
                delays = FAA::DelayFeed.current_delays.select { |x| x.is_a? FAA::Delay::AirspaceFlow }
         | 
| 73 | 
            +
                flow = delays.first
         | 
| 74 | 
            +
                assert_equal 2, delays.size
         | 
| 75 | 
            +
                assert_equal 'FCAA05', flow.control_element
         | 
| 76 | 
            +
                assert_equal 'WEATHER / THUNDERSTORMS', flow.reason
         | 
| 77 | 
            +
                assert_equal Time.parse('Thu May 28 12:00:00 UTC 2009'), flow.fca_start_time
         | 
| 78 | 
            +
                assert_equal Time.parse('Fri May 29 11:00:00 UTC 2009'), flow.fca_end_time
         | 
| 79 | 
            +
                assert_equal Time.parse('Thu May 28 19:00:00 UTC 2009'), flow.afp_start_time
         | 
| 80 | 
            +
                assert_equal Time.parse('Fri May 29 01:59:00 UTC 2009'), flow.afp_end_time
         | 
| 81 | 
            +
                assert_equal 52, flow.average
         | 
| 82 | 
            +
                assert_equal 120, flow.floor
         | 
| 83 | 
            +
                assert_equal 600, flow.ceiling
         | 
| 84 | 
            +
                assert_equal flow.points, [ {'latitude' => 4392, 'longitude' => 8218},
         | 
| 85 | 
            +
                                          {'latitude' => 4392, 'longitude' => 8367},
         | 
| 86 | 
            +
                                          {'latitude' => 4348, 'longitude' => 8500},
         | 
| 87 | 
            +
                                          {'latitude' => 4185, 'longitude' => 8500},
         | 
| 88 | 
            +
                                          {'latitude' => 4187, 'longitude' => 8477},
         | 
| 89 | 
            +
                                          {'latitude' => 4090, 'longitude' => 8470},
         | 
| 90 | 
            +
                                          {'latitude' => 4078, 'longitude' => 8377},
         | 
| 91 | 
            +
                                          {'latitude' => 4073, 'longitude' => 8362},
         | 
| 92 | 
            +
                                          {'latitude' => 4072, 'longitude' => 8345},
         | 
| 93 | 
            +
                                          {'latitude' => 4057, 'longitude' => 8308},
         | 
| 94 | 
            +
                                          {'latitude' => 4055, 'longitude' => 8268},
         | 
| 95 | 
            +
                                          {'latitude' => 4058, 'longitude' => 8177},
         | 
| 96 | 
            +
                                          {'latitude' => 4022, 'longitude' => 8163},
         | 
| 97 | 
            +
                                          {'latitude' => 3975, 'longitude' => 8155},
         | 
| 98 | 
            +
                                          {'latitude' => 3917, 'longitude' => 8048},
         | 
| 99 | 
            +
                                          {'latitude' => 3917, 'longitude' => 8042}]
         | 
| 100 | 
            +
              end
         | 
| 101 | 
            +
              
         | 
| 102 | 
            +
              def test_delay_feed_should_have_6_departure_delays
         | 
| 103 | 
            +
                FakeWeb.register_uri(:get, "http://www.fly.faa.gov/flyfaa/xmlAirportStatus.jsp",
         | 
| 104 | 
            +
                  :body => File.read("#{File.dirname(__FILE__)}/responses/various_delays_with_air_flow_program.xml"))
         | 
| 105 | 
            +
                delays = FAA::DelayFeed.current_delays.select { |x| x.class == FAA::Delay::GeneralDeparture }
         | 
| 106 | 
            +
                assert_equal 6, delays.size
         | 
| 107 | 
            +
              end
         | 
| 108 | 
            +
              
         | 
| 109 | 
            +
            end
         | 
| @@ -0,0 +1,49 @@ | |
| 1 | 
            +
            <?xml version="1.0" encoding="ISO-8859-1"?>
         | 
| 2 | 
            +
            <!DOCTYPE AIRPORT_STATUS_INFORMATION SYSTEM "http://www.fly.faa.gov/AirportStatus.dtd">
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            <AIRPORT_STATUS_INFORMATION>
         | 
| 5 | 
            +
              <Update_Time>Mon Jun 29 20:05:47 2009 GMT+00:00</Update_Time>
         | 
| 6 | 
            +
              <Dtd_File>http://www.fly.faa.gov/AirportStatus.dtd</Dtd_File>
         | 
| 7 | 
            +
              <Delay_type>
         | 
| 8 | 
            +
                <Name>Ground Stop Programs</Name>
         | 
| 9 | 
            +
                <Ground_Stop_List>
         | 
| 10 | 
            +
                  <Program>
         | 
| 11 | 
            +
                    <ARPT>CYYZ</ARPT>
         | 
| 12 | 
            +
                    <Reason>TSTMS</Reason>
         | 
| 13 | 
            +
                    <End_Time>20:15 UTC.</End_Time>
         | 
| 14 | 
            +
                  </Program>
         | 
| 15 | 
            +
                </Ground_Stop_List>
         | 
| 16 | 
            +
              </Delay_type>
         | 
| 17 | 
            +
              <Delay_type>
         | 
| 18 | 
            +
                <Name>General Arrival/Departure Delay Info</Name>
         | 
| 19 | 
            +
                <Arrival_Departure_Delay_List>
         | 
| 20 | 
            +
                  <Delay>
         | 
| 21 | 
            +
                    <ARPT>ATL</ARPT>
         | 
| 22 | 
            +
                    <Reason>VOL:Compacted Demand</Reason>
         | 
| 23 | 
            +
                    <Arrival_Departure Type="Departure">
         | 
| 24 | 
            +
                      <Min>16 minutes</Min>
         | 
| 25 | 
            +
                      <Max>30 minutes</Max>
         | 
| 26 | 
            +
                      <Trend>Increasing</Trend>
         | 
| 27 | 
            +
                    </Arrival_Departure>
         | 
| 28 | 
            +
                  </Delay>
         | 
| 29 | 
            +
                  <Delay>
         | 
| 30 | 
            +
                    <ARPT>DFW</ARPT>
         | 
| 31 | 
            +
                    <Reason>WX:Thunderstorms</Reason>
         | 
| 32 | 
            +
                    <Arrival_Departure Type="Departure">
         | 
| 33 | 
            +
                      <Min>31 minutes</Min>
         | 
| 34 | 
            +
                      <Max>45 minutes</Max>
         | 
| 35 | 
            +
                      <Trend>Increasing</Trend>
         | 
| 36 | 
            +
                    </Arrival_Departure>
         | 
| 37 | 
            +
                  </Delay>
         | 
| 38 | 
            +
                  <Delay>
         | 
| 39 | 
            +
                    <ARPT>JFK</ARPT>
         | 
| 40 | 
            +
                    <Reason>VOL:Volume</Reason>
         | 
| 41 | 
            +
                    <Arrival_Departure Type="Arrival">
         | 
| 42 | 
            +
                      <Min>46 minutes</Min>
         | 
| 43 | 
            +
                      <Max>1 hour</Max>
         | 
| 44 | 
            +
                      <Trend>Increasing</Trend>
         | 
| 45 | 
            +
                    </Arrival_Departure>
         | 
| 46 | 
            +
                  </Delay>
         | 
| 47 | 
            +
                </Arrival_Departure_Delay_List>
         | 
| 48 | 
            +
              </Delay_type>
         | 
| 49 | 
            +
            </AIRPORT_STATUS_INFORMATION>
         | 
| @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            <?xml version="1.0" encoding="ISO-8859-1"?>
         | 
| 2 | 
            +
            <!DOCTYPE AIRPORT_STATUS_INFORMATION SYSTEM "http://www.fly.faa.gov/AirportStatus.dtd">
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            <AIRPORT_STATUS_INFORMATION>
         | 
| 5 | 
            +
              <Update_Time>Mon Jun 1 05:44:10 2009 GMT+00:00</Update_Time>
         | 
| 6 | 
            +
              <Dtd_File>http://www.fly.faa.gov/AirportStatus.dtd</Dtd_File>
         | 
| 7 | 
            +
            </AIRPORT_STATUS_INFORMATION>
         | 
| @@ -0,0 +1,95 @@ | |
| 1 | 
            +
            <?xml version="1.0" encoding="ISO-8859-1"?>
         | 
| 2 | 
            +
            <!DOCTYPE AIRPORT_STATUS_INFORMATION SYSTEM "http://www.fly.faa.gov/AirportStatus.dtd">
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            <AIRPORT_STATUS_INFORMATION>
         | 
| 5 | 
            +
              <Update_Time>Wed May 27 19:50:15 2009 GMT+00:00</Update_Time>
         | 
| 6 | 
            +
              <Dtd_File>http://www.fly.faa.gov/AirportStatus.dtd</Dtd_File>
         | 
| 7 | 
            +
              <Delay_type>
         | 
| 8 | 
            +
                <Name>Ground Delay Programs</Name>
         | 
| 9 | 
            +
                <Ground_Delay_List>
         | 
| 10 | 
            +
                  <Ground_Delay>
         | 
| 11 | 
            +
                    <ARPT>BOS</ARPT>
         | 
| 12 | 
            +
                    <Reason>WEATHER / LOW CEILINGS</Reason>
         | 
| 13 | 
            +
                    <Avg>46 minutes</Avg>
         | 
| 14 | 
            +
                    <Max>0 minutes</Max>
         | 
| 15 | 
            +
                  </Ground_Delay>
         | 
| 16 | 
            +
                  <Ground_Delay>
         | 
| 17 | 
            +
                    <ARPT>EWR</ARPT>
         | 
| 18 | 
            +
                    <Reason>WEATHER / LOW CEILINGS</Reason>
         | 
| 19 | 
            +
                    <Avg>1 hour and 51 minutes</Avg>
         | 
| 20 | 
            +
                    <Max>0 minutes</Max>
         | 
| 21 | 
            +
                  </Ground_Delay>
         | 
| 22 | 
            +
                  <Ground_Delay>
         | 
| 23 | 
            +
                    <ARPT>JFK</ARPT>
         | 
| 24 | 
            +
                    <Reason>WEATHER / WIND</Reason>
         | 
| 25 | 
            +
                    <Avg>1 hour and 8 minutes</Avg>
         | 
| 26 | 
            +
                    <Max>0 minutes</Max>
         | 
| 27 | 
            +
                  </Ground_Delay>
         | 
| 28 | 
            +
                  <Ground_Delay>
         | 
| 29 | 
            +
                    <ARPT>LGA</ARPT>
         | 
| 30 | 
            +
                    <Reason>WEATHER / LOW CEILINGS</Reason>
         | 
| 31 | 
            +
                    <Avg>1 hour and 45 minutes</Avg>
         | 
| 32 | 
            +
                    <Max>0 minutes</Max>
         | 
| 33 | 
            +
                  </Ground_Delay>
         | 
| 34 | 
            +
                </Ground_Delay_List>
         | 
| 35 | 
            +
              </Delay_type>
         | 
| 36 | 
            +
              <Delay_type>
         | 
| 37 | 
            +
                <Name>General Arrival/Departure Delay Info</Name>
         | 
| 38 | 
            +
                <Arrival_Departure_Delay_List>
         | 
| 39 | 
            +
                  <Delay>
         | 
| 40 | 
            +
                    <ARPT>CLT</ARPT>
         | 
| 41 | 
            +
                    <Reason>WX:Thunderstorms</Reason>
         | 
| 42 | 
            +
                    <Arrival_Departure Type="Departure">
         | 
| 43 | 
            +
                      <Min>16 minutes</Min>
         | 
| 44 | 
            +
                      <Max>30 minutes</Max>
         | 
| 45 | 
            +
                      <Trend>Increasing</Trend>
         | 
| 46 | 
            +
                    </Arrival_Departure>
         | 
| 47 | 
            +
                  </Delay>
         | 
| 48 | 
            +
                  <Delay>
         | 
| 49 | 
            +
                    <ARPT>DTW</ARPT>
         | 
| 50 | 
            +
                    <Reason>TM Initiatives:MIT</Reason>
         | 
| 51 | 
            +
                    <Arrival_Departure Type="Departure">
         | 
| 52 | 
            +
                      <Min>16 minutes</Min>
         | 
| 53 | 
            +
                      <Max>30 minutes</Max>
         | 
| 54 | 
            +
                      <Trend>Increasing</Trend>
         | 
| 55 | 
            +
                    </Arrival_Departure>
         | 
| 56 | 
            +
                  </Delay>
         | 
| 57 | 
            +
                  <Delay>
         | 
| 58 | 
            +
                    <ARPT>FLL</ARPT>
         | 
| 59 | 
            +
                    <Reason>WX:Thunderstorms</Reason>
         | 
| 60 | 
            +
                    <Arrival_Departure Type="Departure">
         | 
| 61 | 
            +
                      <Min>1 hour</Min>
         | 
| 62 | 
            +
                      <Max>1 hour and 14 minutes</Max>
         | 
| 63 | 
            +
                      <Trend>Decreasing</Trend>
         | 
| 64 | 
            +
                    </Arrival_Departure>
         | 
| 65 | 
            +
                  </Delay>
         | 
| 66 | 
            +
                  <Delay>
         | 
| 67 | 
            +
                    <ARPT>FLL</ARPT>
         | 
| 68 | 
            +
                    <Reason>WX:Thunderstorms</Reason>
         | 
| 69 | 
            +
                    <Arrival_Departure Type="Arrival">
         | 
| 70 | 
            +
                      <Min>31 minutes</Min>
         | 
| 71 | 
            +
                      <Max>45 minutes</Max>
         | 
| 72 | 
            +
                      <Trend>Increasing</Trend>
         | 
| 73 | 
            +
                    </Arrival_Departure>
         | 
| 74 | 
            +
                  </Delay>
         | 
| 75 | 
            +
                  <Delay>
         | 
| 76 | 
            +
                    <ARPT>LAS</ARPT>
         | 
| 77 | 
            +
                    <Reason>OTHER:VIP Movement</Reason>
         | 
| 78 | 
            +
                    <Arrival_Departure Type="Departure">
         | 
| 79 | 
            +
                      <Min>31 minutes</Min>
         | 
| 80 | 
            +
                      <Max>45 minutes</Max>
         | 
| 81 | 
            +
                      <Trend>Increasing</Trend>
         | 
| 82 | 
            +
                    </Arrival_Departure>
         | 
| 83 | 
            +
                  </Delay>
         | 
| 84 | 
            +
                  <Delay>
         | 
| 85 | 
            +
                    <ARPT>MIA</ARPT>
         | 
| 86 | 
            +
                    <Reason>WX:Thunderstorms</Reason>
         | 
| 87 | 
            +
                    <Arrival_Departure Type="Arrival">
         | 
| 88 | 
            +
                      <Min>16 minutes</Min>
         | 
| 89 | 
            +
                      <Max>30 minutes</Max>
         | 
| 90 | 
            +
                      <Trend>Increasing</Trend>
         | 
| 91 | 
            +
                    </Arrival_Departure>
         | 
| 92 | 
            +
                  </Delay>
         | 
| 93 | 
            +
                </Arrival_Departure_Delay_List>
         | 
| 94 | 
            +
              </Delay_type>
         | 
| 95 | 
            +
            </AIRPORT_STATUS_INFORMATION>
         | 
| @@ -0,0 +1,166 @@ | |
| 1 | 
            +
            <?xml version="1.0" encoding="ISO-8859-1"?>
         | 
| 2 | 
            +
            <!DOCTYPE AIRPORT_STATUS_INFORMATION SYSTEM "http://www.fly.faa.gov/AirportStatus.dtd">
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            <AIRPORT_STATUS_INFORMATION>
         | 
| 5 | 
            +
              <Update_Time>Thu May 28 20:23:09 2009 GMT+00:00</Update_Time>
         | 
| 6 | 
            +
              <Dtd_File>http://www.fly.faa.gov/AirportStatus.dtd</Dtd_File>
         | 
| 7 | 
            +
              <Delay_type>
         | 
| 8 | 
            +
                <Name>Ground Stop Programs</Name>
         | 
| 9 | 
            +
                <Ground_Stop_List>
         | 
| 10 | 
            +
                  <Program>
         | 
| 11 | 
            +
                    <ARPT>BWI</ARPT>
         | 
| 12 | 
            +
                    <Reason>WEATHER / THUNDERSTORMS</Reason>
         | 
| 13 | 
            +
                    <End_Time>4:30 pm EDT.</End_Time>
         | 
| 14 | 
            +
                  </Program>
         | 
| 15 | 
            +
                  <Program>
         | 
| 16 | 
            +
                    <ARPT>DCA</ARPT>
         | 
| 17 | 
            +
                    <Reason>WEATHER / THUNDERSTORMS</Reason>
         | 
| 18 | 
            +
                    <End_Time>4:30 pm EDT.</End_Time>
         | 
| 19 | 
            +
                  </Program>
         | 
| 20 | 
            +
                  <Program>
         | 
| 21 | 
            +
                    <ARPT>IAD</ARPT>
         | 
| 22 | 
            +
                    <Reason>WEATHER / THUNDERSTORMS</Reason>
         | 
| 23 | 
            +
                    <End_Time>4:30 pm EDT.</End_Time>
         | 
| 24 | 
            +
                  </Program>
         | 
| 25 | 
            +
                </Ground_Stop_List>
         | 
| 26 | 
            +
              </Delay_type>
         | 
| 27 | 
            +
              <Delay_type>
         | 
| 28 | 
            +
                <Name>Ground Delay Programs</Name>
         | 
| 29 | 
            +
                <Ground_Delay_List>
         | 
| 30 | 
            +
                  <Ground_Delay>
         | 
| 31 | 
            +
                    <ARPT>BOS</ARPT>
         | 
| 32 | 
            +
                    <Reason>LOW CIGS</Reason>
         | 
| 33 | 
            +
                    <Avg>1 hour and 57 minutes</Avg>
         | 
| 34 | 
            +
                    <Max>0 minutes</Max>
         | 
| 35 | 
            +
                  </Ground_Delay>
         | 
| 36 | 
            +
                  <Ground_Delay>
         | 
| 37 | 
            +
                    <ARPT>EWR</ARPT>
         | 
| 38 | 
            +
                    <Reason>LOW CIGS</Reason>
         | 
| 39 | 
            +
                    <Avg>1 hour and 45 minutes</Avg>
         | 
| 40 | 
            +
                    <Max>0 minutes</Max>
         | 
| 41 | 
            +
                  </Ground_Delay>
         | 
| 42 | 
            +
                  <Ground_Delay>
         | 
| 43 | 
            +
                    <ARPT>JFK</ARPT>
         | 
| 44 | 
            +
                    <Reason>LOW CIGS</Reason>
         | 
| 45 | 
            +
                    <Avg>49 minutes</Avg>
         | 
| 46 | 
            +
                    <Max>0 minutes</Max>
         | 
| 47 | 
            +
                  </Ground_Delay>
         | 
| 48 | 
            +
                  <Ground_Delay>
         | 
| 49 | 
            +
                    <ARPT>LGA</ARPT>
         | 
| 50 | 
            +
                    <Reason>LOW VIS</Reason>
         | 
| 51 | 
            +
                    <Avg>1 hour and 44 minutes</Avg>
         | 
| 52 | 
            +
                    <Max>0 minutes</Max>
         | 
| 53 | 
            +
                  </Ground_Delay>
         | 
| 54 | 
            +
                </Ground_Delay_List>
         | 
| 55 | 
            +
              </Delay_type>
         | 
| 56 | 
            +
              <Delay_type>
         | 
| 57 | 
            +
                <Name>Airspace Flow Programs</Name>
         | 
| 58 | 
            +
                <Airspace_Flow_List>
         | 
| 59 | 
            +
                  <Airspace_Flow>
         | 
| 60 | 
            +
                    <CTL_Element>FCAA05</CTL_Element>
         | 
| 61 | 
            +
                    <Reason>WEATHER / THUNDERSTORMS</Reason>
         | 
| 62 | 
            +
                    <FCA_Start_DateTime>20090528120000</FCA_Start_DateTime>
         | 
| 63 | 
            +
                    <FCA_End_DateTime>20090529110000</FCA_End_DateTime>
         | 
| 64 | 
            +
                    <AFP_StartTime>1900</AFP_StartTime>
         | 
| 65 | 
            +
                    <AFP_EndTime>0159</AFP_EndTime>
         | 
| 66 | 
            +
                    <Line>
         | 
| 67 | 
            +
                      <Point Lat="4392" Long="8218" />
         | 
| 68 | 
            +
                      <Point Lat="4392" Long="8367" />
         | 
| 69 | 
            +
                      <Point Lat="4348" Long="8500" />
         | 
| 70 | 
            +
                      <Point Lat="4185" Long="8500" />
         | 
| 71 | 
            +
                      <Point Lat="4187" Long="8477" />
         | 
| 72 | 
            +
                      <Point Lat="4090" Long="8470" />
         | 
| 73 | 
            +
                      <Point Lat="4078" Long="8377" />
         | 
| 74 | 
            +
                      <Point Lat="4073" Long="8362" />
         | 
| 75 | 
            +
                      <Point Lat="4072" Long="8345" />
         | 
| 76 | 
            +
                      <Point Lat="4057" Long="8308" />
         | 
| 77 | 
            +
                      <Point Lat="4055" Long="8268" />
         | 
| 78 | 
            +
                      <Point Lat="4058" Long="8177" />
         | 
| 79 | 
            +
                      <Point Lat="4022" Long="8163" />
         | 
| 80 | 
            +
                      <Point Lat="3975" Long="8155" />
         | 
| 81 | 
            +
                      <Point Lat="3917" Long="8048" />
         | 
| 82 | 
            +
                      <Point Lat="3917" Long="8042" />
         | 
| 83 | 
            +
                    </Line>
         | 
| 84 | 
            +
                    <Avg>52 minutes</Avg>
         | 
| 85 | 
            +
                    <Floor>120</Floor>
         | 
| 86 | 
            +
                    <Ceiling>600</Ceiling>
         | 
| 87 | 
            +
                  </Airspace_Flow>
         | 
| 88 | 
            +
                  <Airspace_Flow>
         | 
| 89 | 
            +
                    <CTL_Element>FCAA08</CTL_Element>
         | 
| 90 | 
            +
                    <Reason>WEATHER / THUNDERSTORMS</Reason>
         | 
| 91 | 
            +
                    <FCA_Start_DateTime>20090528121500</FCA_Start_DateTime>
         | 
| 92 | 
            +
                    <FCA_End_DateTime>20090529110000</FCA_End_DateTime>
         | 
| 93 | 
            +
                    <AFP_StartTime>1900</AFP_StartTime>
         | 
| 94 | 
            +
                    <AFP_EndTime>0159</AFP_EndTime>
         | 
| 95 | 
            +
                    <Line>
         | 
| 96 | 
            +
                      <Point Lat="3917" Long="8040" />
         | 
| 97 | 
            +
                      <Point Lat="3763" Long="8078" />
         | 
| 98 | 
            +
                      <Point Lat="3758" Long="7732" />
         | 
| 99 | 
            +
                      <Point Lat="3793" Long="7302" />
         | 
| 100 | 
            +
                    </Line>
         | 
| 101 | 
            +
                    <Avg>23 minutes</Avg>
         | 
| 102 | 
            +
                    <Floor>120</Floor>
         | 
| 103 | 
            +
                    <Ceiling>600</Ceiling>
         | 
| 104 | 
            +
                  </Airspace_Flow>
         | 
| 105 | 
            +
                </Airspace_Flow_List>
         | 
| 106 | 
            +
              </Delay_type>
         | 
| 107 | 
            +
              <Delay_type>
         | 
| 108 | 
            +
                <Name>General Arrival/Departure Delay Info</Name>
         | 
| 109 | 
            +
                <Arrival_Departure_Delay_List>
         | 
| 110 | 
            +
                  <Delay>
         | 
| 111 | 
            +
                    <ARPT>BWI</ARPT>
         | 
| 112 | 
            +
                    <Reason>WX:Thunderstorms</Reason>
         | 
| 113 | 
            +
                    <Arrival_Departure Type="Departure">
         | 
| 114 | 
            +
                      <Min>31 minutes</Min>
         | 
| 115 | 
            +
                      <Max>45 minutes</Max>
         | 
| 116 | 
            +
                      <Trend>Increasing</Trend>
         | 
| 117 | 
            +
                    </Arrival_Departure>
         | 
| 118 | 
            +
                  </Delay>
         | 
| 119 | 
            +
                  <Delay>
         | 
| 120 | 
            +
                    <ARPT>DCA</ARPT>
         | 
| 121 | 
            +
                    <Reason>WX:Thunderstorms</Reason>
         | 
| 122 | 
            +
                    <Arrival_Departure Type="Departure">
         | 
| 123 | 
            +
                      <Min>16 minutes</Min>
         | 
| 124 | 
            +
                      <Max>30 minutes</Max>
         | 
| 125 | 
            +
                      <Trend>Increasing</Trend>
         | 
| 126 | 
            +
                    </Arrival_Departure>
         | 
| 127 | 
            +
                  </Delay>
         | 
| 128 | 
            +
                  <Delay>
         | 
| 129 | 
            +
                    <ARPT>IAD</ARPT>
         | 
| 130 | 
            +
                    <Reason>WX:Thunderstorms</Reason>
         | 
| 131 | 
            +
                    <Arrival_Departure Type="Departure">
         | 
| 132 | 
            +
                      <Min>46 minutes</Min>
         | 
| 133 | 
            +
                      <Max>1 hour</Max>
         | 
| 134 | 
            +
                      <Trend>Increasing</Trend>
         | 
| 135 | 
            +
                    </Arrival_Departure>
         | 
| 136 | 
            +
                  </Delay>
         | 
| 137 | 
            +
                  <Delay>
         | 
| 138 | 
            +
                    <ARPT>JFK</ARPT>
         | 
| 139 | 
            +
                    <Reason>TM Initiatives:ASP</Reason>
         | 
| 140 | 
            +
                    <Arrival_Departure Type="Departure">
         | 
| 141 | 
            +
                      <Min>16 minutes</Min>
         | 
| 142 | 
            +
                      <Max>30 minutes</Max>
         | 
| 143 | 
            +
                      <Trend>Increasing</Trend>
         | 
| 144 | 
            +
                    </Arrival_Departure>
         | 
| 145 | 
            +
                  </Delay>
         | 
| 146 | 
            +
                  <Delay>
         | 
| 147 | 
            +
                    <ARPT>LGA</ARPT>
         | 
| 148 | 
            +
                    <Reason>TM Initiatives:SWAP</Reason>
         | 
| 149 | 
            +
                    <Arrival_Departure Type="Departure">
         | 
| 150 | 
            +
                      <Min>16 minutes</Min>
         | 
| 151 | 
            +
                      <Max>30 minutes</Max>
         | 
| 152 | 
            +
                      <Trend>Increasing</Trend>
         | 
| 153 | 
            +
                    </Arrival_Departure>
         | 
| 154 | 
            +
                  </Delay>
         | 
| 155 | 
            +
                  <Delay>
         | 
| 156 | 
            +
                    <ARPT>MIA</ARPT>
         | 
| 157 | 
            +
                    <Reason>WX:Thunderstorms</Reason>
         | 
| 158 | 
            +
                    <Arrival_Departure Type="Departure">
         | 
| 159 | 
            +
                      <Min>16 minutes</Min>
         | 
| 160 | 
            +
                      <Max>30 minutes</Max>
         | 
| 161 | 
            +
                      <Trend>Increasing</Trend>
         | 
| 162 | 
            +
                    </Arrival_Departure>
         | 
| 163 | 
            +
                  </Delay>
         | 
| 164 | 
            +
                </Arrival_Departure_Delay_List>
         | 
| 165 | 
            +
              </Delay_type>
         | 
| 166 | 
            +
            </AIRPORT_STATUS_INFORMATION>
         | 
    
        data/test/test_helper.rb
    ADDED
    
    
    
        metadata
    ADDED
    
    | @@ -0,0 +1,86 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification 
         | 
| 2 | 
            +
            name: faa
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            +
              version: 0.0.1
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors: 
         | 
| 7 | 
            +
            - FlightCaster
         | 
| 8 | 
            +
            - Jon Bracy
         | 
| 9 | 
            +
            autorequire: 
         | 
| 10 | 
            +
            bindir: bin
         | 
| 11 | 
            +
            cert_chain: []
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            date: 2009-12-11 00:00:00 -08:00
         | 
| 14 | 
            +
            default_executable: 
         | 
| 15 | 
            +
            dependencies: 
         | 
| 16 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 17 | 
            +
              name: libxml-ruby
         | 
| 18 | 
            +
              type: :runtime
         | 
| 19 | 
            +
              version_requirement: 
         | 
| 20 | 
            +
              version_requirements: !ruby/object:Gem::Requirement 
         | 
| 21 | 
            +
                requirements: 
         | 
| 22 | 
            +
                - - ">="
         | 
| 23 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 24 | 
            +
                    version: 1.1.3
         | 
| 25 | 
            +
                version: 
         | 
| 26 | 
            +
            description: 
         | 
| 27 | 
            +
            email: dev@flightcaster.com
         | 
| 28 | 
            +
            executables: []
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            extensions: []
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            extra_rdoc_files: []
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            files: 
         | 
| 35 | 
            +
            - Rakefile
         | 
| 36 | 
            +
            - README.rdoc
         | 
| 37 | 
            +
            - lib/faa/airport/closure.rb
         | 
| 38 | 
            +
            - lib/faa/airport.rb
         | 
| 39 | 
            +
            - lib/faa/delay/airspace_flow/circle.rb
         | 
| 40 | 
            +
            - lib/faa/delay/airspace_flow/line.rb
         | 
| 41 | 
            +
            - lib/faa/delay/airspace_flow/polygon.rb
         | 
| 42 | 
            +
            - lib/faa/delay/airspace_flow.rb
         | 
| 43 | 
            +
            - lib/faa/delay/general.rb
         | 
| 44 | 
            +
            - lib/faa/delay/general_arrival.rb
         | 
| 45 | 
            +
            - lib/faa/delay/general_departure.rb
         | 
| 46 | 
            +
            - lib/faa/delay/ground_delay.rb
         | 
| 47 | 
            +
            - lib/faa/delay/ground_stop.rb
         | 
| 48 | 
            +
            - lib/faa/delay.rb
         | 
| 49 | 
            +
            - lib/faa/delay_feed.rb
         | 
| 50 | 
            +
            - lib/faa.rb
         | 
| 51 | 
            +
            - test/delay_feed_test.rb
         | 
| 52 | 
            +
            - test/test_helper.rb
         | 
| 53 | 
            +
            - test/responses/delays_with_icao_code.xml
         | 
| 54 | 
            +
            - test/responses/no_delays.xml
         | 
| 55 | 
            +
            - test/responses/various_delays.xml
         | 
| 56 | 
            +
            - test/responses/various_delays_with_air_flow_program.xml
         | 
| 57 | 
            +
            has_rdoc: true
         | 
| 58 | 
            +
            homepage: http://flightcaster.com/
         | 
| 59 | 
            +
            licenses: []
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            post_install_message: 
         | 
| 62 | 
            +
            rdoc_options: []
         | 
| 63 | 
            +
             | 
| 64 | 
            +
            require_paths: 
         | 
| 65 | 
            +
            - lib
         | 
| 66 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement 
         | 
| 67 | 
            +
              requirements: 
         | 
| 68 | 
            +
              - - ">="
         | 
| 69 | 
            +
                - !ruby/object:Gem::Version 
         | 
| 70 | 
            +
                  version: "0"
         | 
| 71 | 
            +
              version: 
         | 
| 72 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement 
         | 
| 73 | 
            +
              requirements: 
         | 
| 74 | 
            +
              - - ">="
         | 
| 75 | 
            +
                - !ruby/object:Gem::Version 
         | 
| 76 | 
            +
                  version: "0"
         | 
| 77 | 
            +
              version: 
         | 
| 78 | 
            +
            requirements: []
         | 
| 79 | 
            +
             | 
| 80 | 
            +
            rubyforge_project: 
         | 
| 81 | 
            +
            rubygems_version: 1.3.5
         | 
| 82 | 
            +
            signing_key: 
         | 
| 83 | 
            +
            specification_version: 3
         | 
| 84 | 
            +
            summary: A wrapper for the FAA Data Sources
         | 
| 85 | 
            +
            test_files: []
         | 
| 86 | 
            +
             |