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 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'
@@ -0,0 +1,2 @@
1
+ module FAA::Airport
2
+ end
@@ -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,2 @@
1
+ class FAA::Delay::GeneralArrival < FAA::Delay::General
2
+ end
@@ -0,0 +1,2 @@
1
+ class FAA::Delay::GeneralDeparture < FAA::Delay::General
2
+ 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>
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'fakeweb'
4
+
5
+ $: << File.join(File.dirname(__FILE__), '..', 'lib')
6
+
7
+ require 'faa'
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
+