faa 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+