flightstats 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
@@ -0,0 +1,23 @@
1
+ = Copyright
2
+
3
+ Copyright (c) FlightCaster 2009
4
+
5
+ = Description
6
+
7
+ FlightStats is a gem that provides a wraper over the FlightStats Web Services
8
+ API, specifed at https://www.flightstats.com/developers/bin/view/Web+Services/web_services_directory
9
+
10
+ = Usage
11
+
12
+ require 'flightstats'
13
+
14
+ FLIGHTSTATS_ACCOUNT_ID = 'my_id'
15
+ FLIGHTSTATS_USER_ID = "12345"
16
+ FLIGHTSTATS_PASSWORD = "*****"
17
+
18
+ # Displays the flight numbers of all the arriving flights
19
+ boston = FlightStats.find_by_icao_code("KBOS")
20
+ boston.arrivals.each do |flight|
21
+ puts flight.number
22
+ end
23
+
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ require 'rubygems'
2
+ require 'metric_fu'
3
+ require 'rake/testtask'
4
+
5
+ MetricFu::Configuration.run do |config|
6
+ config.metrics = [:churn, :saikuro, :flog, :flay, :reek, :roodi, :rcov]
7
+ config.flay = { :dirs_to_flay => ['lib'] }
8
+ config.flog = { :dirs_to_flog => ['lib'] }
9
+ config.reek = { :dirs_to_reek => ['lib'] }
10
+ config.roodi = { :dirs_to_roodi => ['lib'] }
11
+ config.saikuro = { :output_directory => 'tmp/scratch/saikuro',
12
+ :input_directory => ['lib'],
13
+ :cyclo => "",
14
+ :filter_cyclo => "0",
15
+ :warn_cyclo => "5",
16
+ :error_cyclo => "7",
17
+ :formater => "text"} #this needs to be set to "text"
18
+ config.churn = { :start_date => "1 year ago", :minimum_churn_count => 10}
19
+ config.rcov = { :test_files => ['test/*_test.rb','test/*_test.rb'],
20
+ :rcov_opts => ["--sort coverage",
21
+ "--no-html",
22
+ "--text-coverage",
23
+ "--no-color",
24
+ "--profile",
25
+ "--exclude /gems/,/Library/,spec"]}
26
+ end
27
+
28
+ Rake::TestTask.new(:test) do |t|
29
+ t.test_files = FileList['test/**/*_test.rb']
30
+ end
@@ -0,0 +1,50 @@
1
+ require 'uri'
2
+ require 'net/https'
3
+ require 'zlib'
4
+ require 'libxml'
5
+ require 'time'
6
+ require 'tzinfo'
7
+
8
+ module FlightStats
9
+ SERVER = "https://www.pathfinder-xml.com"
10
+ PATH = "/development/xml"
11
+
12
+ class << self
13
+ def authentication_token
14
+ {'login.guid' => FLIGHTSTATS_GUID}
15
+ end
16
+
17
+ def uri(params, path = nil)
18
+ params.merge!(authentication_token)
19
+ URI.parse(SERVER + (path || PATH) + '?' + params.collect{ |k,v| "#{k}=#{v}"}.join('&'))
20
+ end
21
+
22
+ def query(params, path = nil)
23
+ url = uri(params, path)
24
+ http = Net::HTTP.new(url.host, url.port)
25
+ http.use_ssl = true
26
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
27
+ body = http.request_get(url.path+'?'+url.query) { |response|
28
+ if response.is_a?(Net::HTTPSuccess)
29
+ return StringIO.new(response.read_body)
30
+ else
31
+ raise StandardError, response.read_body
32
+ end
33
+ }
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ require 'flightstats/airline'
40
+
41
+ require 'flightstats/airport'
42
+
43
+ require 'flightstats/flight'
44
+ require 'flightstats/flight/codeshare'
45
+
46
+ require 'flightstats/data_feed'
47
+ require 'flightstats/data_feed/sax_parser'
48
+ require 'flightstats/data_feed/file'
49
+ require 'flightstats/data_feed/file/sax_parser'
50
+ require 'flightstats/data_feed/file/flight_update'
@@ -0,0 +1,5 @@
1
+ class FlightStats::Airline
2
+
3
+ attr_accessor :code, :iata_code, :icao_code, :faa_code, :name
4
+
5
+ end
@@ -0,0 +1,5 @@
1
+ class FlightStats::Airport
2
+
3
+ attr_accessor :code, :iata_code, :icao_code, :faa_code, :name
4
+
5
+ end
@@ -0,0 +1,73 @@
1
+ class FlightStats::DataFeed
2
+
3
+ PATH = '/development/feed'
4
+
5
+ attr_reader :last_accessed_at
6
+
7
+ def initialize(time=nil)
8
+ @last_accessed_at = (time || Time.now.utc)
9
+ end
10
+
11
+ def files(&block)
12
+ params = {:lastAccessed => @last_accessed_at.utc.strftime("%Y-%m-%dT%H:%M"), :useUTC => true}
13
+ parser = LibXML::XML::SaxParser.io(FlightStats.query(params, PATH))
14
+
15
+ if block_given?
16
+ parser.callbacks = SaxParser.new(&block)
17
+ parser.parse
18
+ else
19
+ files = []
20
+ parser.callbacks = SaxParser.new { |file| files << file }
21
+ parser.parse
22
+ files
23
+ end
24
+ end
25
+
26
+ # def self.get_gz_file(id)
27
+ # id = id['id'] if id.class == Hash
28
+ # FlightStats::raw_query({:file=>id}, '/development/feed')
29
+ # end
30
+ #
31
+ # def self.get_file(id)
32
+ # Zlib::GzipReader.new(FlightStats::DataFeed.get_gz_file(id))
33
+ # end
34
+ #
35
+ # # passes each file to a block,
36
+ # # each file is the raw gzipped file from flightstats, StringIO object
37
+ # def each_gz_file(&block)
38
+ # if block.arity == 1
39
+ # @files.each{ |f| block.call(FlightStats::DataFeed.get_gz_file(f)) }
40
+ # elsif block.arity == 2
41
+ # @files.each { |f|
42
+ # block.call(FlightStats::DataFeed.get_gz_file(f), f['timestamp'])
43
+ # }
44
+ # end
45
+ # end
46
+ #
47
+ # # passes each file to a block, each file is a Zlib::GzipReader instance
48
+ # def each_file(&block)
49
+ # if block.arity == 1
50
+ # @files.each{ |f| block.call(FlightStats::DataFeed.get_file(f)) }
51
+ # elsif block.arity == 2
52
+ # @files.each { |f|
53
+ # block.call(FlightStats::DataFeed.get_file(f), f['timestamp'])
54
+ # }
55
+ # end
56
+ # end
57
+ #
58
+ # # passes each update to a block, each update is an instance of FlightStats::Flight
59
+ # def each(&block)
60
+ # each_file { |file| FlightStats::DataFeed.process_file(file, &block) }
61
+ # end
62
+ #
63
+ # def self.process_file(file, &block)
64
+ # xml = LibXML::XML::Parser.string(file.read, PARSER_OPTIONS).parse.root
65
+ # xml.children.each do |node|
66
+ # flight = FlightStats::Flight.new(node.children[0])
67
+ # time_updated = Time.parse(node.attributes['DateTimeRecorded'][0..18] + ' PT')
68
+ # flight.attributes['updated_at'] = time_updated.utc
69
+ # block.call(flight)
70
+ # end
71
+ # end
72
+ #
73
+ end
@@ -0,0 +1,31 @@
1
+ class FlightStats::DataFeed::File
2
+
3
+ attr_accessor :id, :message_count, :bytes, :timestamp
4
+ alias :size :bytes
5
+
6
+ def initialize(content = nil)
7
+ @content = content
8
+ end
9
+
10
+ def content
11
+ if @content.nil?
12
+ @content = FlightStats.query({:file => @id}, FlightStats::DataFeed::PATH)
13
+ end
14
+ @content
15
+ end
16
+
17
+ def updates(&block)
18
+ parser = LibXML::XML::SaxParser.io(Zlib::GzipReader.new(content))
19
+
20
+ if block_given?
21
+ parser.callbacks = SaxParser.new(&block)
22
+ parser.parse
23
+ else
24
+ updates = []
25
+ parser.callbacks = SaxParser.new { |update| updates << update }
26
+ parser.parse
27
+ updates
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,5 @@
1
+ class FlightStats::DataFeed::File::FlightUpdate
2
+
3
+ attr_accessor :timestamp, :source, :event, :data_updated, :flight
4
+
5
+ end
@@ -0,0 +1,138 @@
1
+ class FlightStats::DataFeed::File::SaxParser
2
+
3
+ include LibXML::XML::SaxParser::Callbacks
4
+
5
+ def initialize(&on_update_block)
6
+ @stack = []
7
+ @on_update_block = on_update_block
8
+ end
9
+
10
+ def to_time(string)
11
+ return nil if string.nil?
12
+ Time.utc(string[0..3],string[5..6],string[8..9],
13
+ string[11..12],string[14..15],string[17..18],string[20..22])
14
+ end
15
+
16
+ def on_start_element_ns(name, attributes, prefix, uri, namespaces)
17
+ @stack.push(name)
18
+ attributes = attributes.delete_if{ |k,v| v.strip.empty? }
19
+
20
+ case name
21
+ when 'FlightHistoryEvent'
22
+ @update = FlightStats::DataFeed::File::FlightUpdate.new
23
+ @update.source = attributes['DataSource']
24
+ @update.event = attributes['Event']
25
+ @update.data_updated = attributes['DataUpdated']
26
+ tz = TZInfo::Timezone.get('America/Los_Angeles')
27
+ @update.timestamp = tz.local_to_utc(to_time(attributes['DateTimeRecorded']))
28
+ when 'FlightHistory'
29
+ @flight = FlightStats::Flight.new
30
+ @flight.id = attributes['FlightHistoryId']
31
+ @flight.number = attributes['FlightNumber']
32
+ @flight.tail_number = attributes['TailNumber']
33
+ @flight.status = attributes['Status']
34
+ @flight.status_code = attributes['StatusCode']
35
+ @flight.creator_code = attributes['CreatorCode']
36
+ @flight.published_local_departure_time = to_time(attributes['PublishedDepartureDate'])
37
+ @flight.published_local_arrival_time = to_time(attributes['PublishedArrivalDate'])
38
+ @flight.local_arrival_time = to_time(attributes['PublishedArrivalDate'])
39
+ @flight.scheduled_local_gate_departure_time = to_time(attributes['ScheduledGateDepartureDate'])
40
+ @flight.estimated_local_gate_departure_time = to_time(attributes['EstimatedGateDepartureDate'])
41
+ @flight.actual_local_gate_departure_time = to_time(attributes['ActualGateDepartureDate'])
42
+ @flight.scheduled_local_gate_arrival_time = to_time(attributes['ScheduledGateArrivalDate'])
43
+ @flight.estimated_local_gate_arrival_time = to_time(attributes['EstimatedGateArrivalDate'])
44
+ @flight.actual_local_gate_arrival_time = to_time(attributes['ActualGateArrivalDate'])
45
+ @flight.scheduled_local_runway_departure_time = to_time(attributes['ScheduledRunwayDepartureDate'])
46
+ @flight.estimated_local_runway_departure_time = to_time(attributes['EstimatedRunwayDepartureDate'])
47
+ @flight.actual_local_runway_departure_time = to_time(attributes['ActualRunwayDepartureDate'])
48
+ @flight.scheduled_local_runway_arrival_time = to_time(attributes['ScheduledRunwayArrivalDate'])
49
+ @flight.estimated_local_runway_arrival_time = to_time(attributes['EstimatedRunwayArrivalDate'])
50
+ @flight.actual_local_runway_arrival_time = to_time(attributes['ActualRunwayArrivalDate'])
51
+ @flight.scheduled_air_time = attributes['ScheduledAirTime'].to_i if attributes['ScheduledAirTime']
52
+ @flight.actual_air_time = attributes['ActualAirTime'].to_i if attributes['ActualAirTime']
53
+ @flight.scheduled_block_time = attributes['ScheduledBlockTime'].to_i if attributes['ScheduledBlockTime']
54
+ @flight.actual_block_time = attributes['ActualBlockTime'].to_i if attributes['ActualBlockTime']
55
+ @flight.departure_airport_timezone_offset = attributes['DepartureAirportTimeZoneOffset'].to_f if attributes['DepartureAirportTimeZoneOffset']
56
+ @flight.arrival_airport_timezone_offset = attributes['ArrivalAirportTimeZoneOffset'].to_f if attributes['ArrivalAirportTimeZoneOffset']
57
+ @flight.diverted_airport_timezone_offset = attributes['DivertedAirportTimeZoneOffset'].to_f if attributes['DivertedAirportTimeZoneOffset']
58
+ @flight.local_departure_time = to_time(attributes['DepartureDate'])
59
+ @flight.local_arrival_time = to_time(attributes['ArrivalDate'])
60
+ @flight.scheduled_aircraft_type = attributes['ScheduledAircraftType']
61
+ @flight.actual_aircraft_type = attributes['ActualAircraftType']
62
+ @flight.departure_gate = attributes['DepartureGate']
63
+ @flight.departure_terminal = attributes['DepartureTerminal']
64
+ @flight.arrival_gate = attributes['ArrivalGate']
65
+ @flight.arrival_terminal = attributes['ArrivalTerminal']
66
+ @flight.baggage_claim = attributes['BaggageClaim']
67
+ when 'FlightHistoryCodeshare', 'CodeshareEntry'
68
+ @codeshare = FlightStats::Flight::Codeshare.new
69
+ @codeshare.id = attributes['FlightHistoryCodeshareId']
70
+ @codeshare.number = attributes['FlightNumber']
71
+ @codeshare.tail_number = attributes['TailNumber']
72
+ @codeshare.published_local_departure_time = to_time(attributes['PublishedDepartureDate'])
73
+ @codeshare.published_local_arrival_time = to_time(attributes['PublishedArrivalDate'])
74
+ @codeshare.designator = attributes['Designator']
75
+ when 'Airline'
76
+ @airline = FlightStats::Airline.new
77
+ @airline.code = attributes['AirlineCode']
78
+ @airline.name = attributes['Name']
79
+ @airline.iata_code = attributes['IATACode']
80
+ @airline.icao_code = attributes['ICAOCode']
81
+ @airline.faa_code = attributes['FAACode']
82
+ when 'Origin'
83
+ @origin = FlightStats::Airport.new
84
+ @origin.code = attributes['AirportCode']
85
+ @origin.iata_code = attributes['IATACode']
86
+ @origin.icao_code = attributes['ICAOCode']
87
+ @origin.faa_code = attributes['FAACode']
88
+ @origin.name = attributes['Name']
89
+ when 'Destination'
90
+ @destination = FlightStats::Airport.new
91
+ @destination.code = attributes['AirportCode']
92
+ @destination.iata_code = attributes['IATACode']
93
+ @destination.icao_code = attributes['ICAOCode']
94
+ @destination.faa_code = attributes['FAACode']
95
+ @destination.name = attributes['Name']
96
+ when 'Diverted'
97
+ @diverted = FlightStats::Airport.new
98
+ @diverted.code = attributes['AirportCode']
99
+ @diverted.iata_code = attributes['IATACode']
100
+ @diverted.icao_code = attributes['ICAOCode']
101
+ @diverted.faa_code = attributes['FAACode']
102
+ @diverted.name = attributes['Name']
103
+ end
104
+ end
105
+
106
+ def on_end_element_ns (name, prefix, uri)
107
+ raise 'Unclosed entity' if @stack.pop != name
108
+
109
+ case name
110
+ when 'FlightHistoryEvent'
111
+ @on_update_block.call(@update)
112
+ @update = nil
113
+ when 'FlightHistory'
114
+ @update.flight = @flight if @stack.last == 'FlightHistoryEvent'
115
+ @flight = nil
116
+ when 'FlightHistoryCodeshare', 'CodeshareEntry'
117
+ @flight.codeshares << @codeshare if @stack.last == 'FlightHistory'
118
+ @codeshare = nil
119
+ when 'Airline'
120
+ case @stack.last
121
+ when 'FlightHistory'
122
+ @flight.airline = @airline
123
+ when 'FlightHistoryCodeshare', 'CodeshareEntry'
124
+ @codeshare.airline = @airline
125
+ end
126
+ @airline = nil
127
+ when 'Origin'
128
+ @flight.origin = @origin if @stack.last == 'FlightHistory'
129
+ @origin = nil
130
+ when 'Destination'
131
+ @flight.destination = @destination if @stack.last == 'FlightHistory'
132
+ @destination = nil
133
+ when 'Diverted'
134
+ @flight.diverted = @diverted if @stack.last == 'FlightHistory'
135
+ @diverted = nil
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,27 @@
1
+ class FlightStats::DataFeed::SaxParser
2
+
3
+ include LibXML::XML::SaxParser::Callbacks
4
+
5
+ def initialize(&on_file_block)
6
+ @on_file_block = on_file_block
7
+ end
8
+
9
+ def on_start_element_ns(name, attributes, prefix, uri, namespaces)
10
+ case name
11
+ when 'File'
12
+ file = FlightStats::DataFeed::File.new
13
+ file.id = attributes['ID']
14
+ file.message_count = attributes['Messages'].to_i
15
+ file.bytes = attributes['Bytes'].to_i
16
+ file.timestamp = Time.utc( attributes['DateTimeUTC'][0..3],
17
+ attributes['DateTimeUTC'][5..6],
18
+ attributes['DateTimeUTC'][8..9],
19
+ attributes['DateTimeUTC'][11..12],
20
+ attributes['DateTimeUTC'][14..15],
21
+ attributes['DateTimeUTC'][17..18],
22
+ attributes['DateTimeUTC'][20..22])
23
+ @on_file_block.call(file)
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,58 @@
1
+ class FlightStats::Flight
2
+
3
+ def initialize
4
+ @codeshares = []
5
+ end
6
+
7
+ attr_accessor :id,
8
+ :airline,
9
+ :number,
10
+ :tail_number,
11
+ :codeshares,
12
+
13
+ :origin,
14
+ :destination,
15
+ :diverted,
16
+
17
+ :status,
18
+ :status_code,
19
+ :creator_code,
20
+
21
+ :scheduled_aircraft_type,
22
+ :actual_aircraft_type,
23
+ :scheduled_air_time,
24
+ :actual_air_time,
25
+ :scheduled_block_time,
26
+ :actual_block_time,
27
+
28
+ :departure_gate,
29
+ :departure_terminal,
30
+
31
+ :local_departure_time,
32
+ :published_local_departure_time,
33
+ :scheduled_local_gate_departure_time,
34
+ :estimated_local_gate_departure_time,
35
+ :actual_local_gate_departure_time,
36
+ :scheduled_local_runway_departure_time,
37
+ :estimated_local_runway_departure_time,
38
+ :actual_local_runway_departure_time,
39
+
40
+ :arrival_gate,
41
+ :arrival_terminal,
42
+ :baggage_claim,
43
+
44
+ :local_arrival_time,
45
+ :published_local_arrival_time,
46
+ :scheduled_local_gate_arrival_time,
47
+ :estimated_local_gate_arrival_time,
48
+ :actual_local_gate_arrival_time,
49
+ :scheduled_local_runway_arrival_time,
50
+ :estimated_local_runway_arrival_time,
51
+ :actual_local_runway_arrival_time,
52
+
53
+
54
+ :departure_airport_timezone_offset,
55
+ :arrival_airport_timezone_offset,
56
+ :diverted_airport_timezone_offset
57
+
58
+ end
@@ -0,0 +1,7 @@
1
+ class FlightStats::Flight::Codeshare
2
+
3
+ attr_accessor :id, :airline, :number, :tail_number,
4
+ :published_local_departure_time, :published_local_arrival_time,
5
+ :designator
6
+
7
+ end
@@ -0,0 +1,146 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper'
2
+
3
+ class FlightStats::DataFeed::FileTest < Test::Unit::TestCase
4
+
5
+ def test_should_find_ten_updates
6
+ FakeWeb.register_uri(:get, "https://www.pathfinder-xml.com/development/feed?login.guid=test&useUTC=true&lastAccessed=#{Time.now.utc.strftime("%Y-%m-%dT%H:%M")}",
7
+ :body => File.read("#{File.dirname(__FILE__)}/../../responses/feed_file_list.xml"))
8
+ FakeWeb.register_uri(:get, "https://www.pathfinder-xml.com/development/feed?login.guid=test&file=4551477",
9
+ :body => File.read("#{File.dirname(__FILE__)}/../../responses/test1.gz"))
10
+ FakeWeb.register_uri(:get, "https://www.pathfinder-xml.com/development/feed?login.guid=test&file=4551480",
11
+ :body => File.read("#{File.dirname(__FILE__)}/../../responses/test2.gz"))
12
+
13
+ count = 0
14
+ FlightStats::DataFeed.new.files do |file|
15
+ file.updates do |update|
16
+ count += 1
17
+ end
18
+ end
19
+ assert_equal 11, count
20
+ end
21
+
22
+ def test_should_find_5_updates_when_reading_file
23
+ data_file = File.new("#{File.dirname(__FILE__)}/../../responses/test1.gz")
24
+ file = FlightStats::DataFeed::File.new(data_file)
25
+ count = 0
26
+ file.updates do |update|
27
+ count += 1
28
+ end
29
+ assert_equal(5, count)
30
+ end
31
+
32
+ def test_should_check_correctness_of_data
33
+ FakeWeb.register_uri(:get, "https://www.pathfinder-xml.com/development/feed?login.guid=test&useUTC=true&lastAccessed=#{Time.now.utc.strftime("%Y-%m-%dT%H:%M")}",
34
+ :body => File.read("#{File.dirname(__FILE__)}/../../responses/feed_file_list.xml"))
35
+ FakeWeb.register_uri(:get, "https://www.pathfinder-xml.com/development/feed?login.guid=test&file=4551477",
36
+ :body => File.read("#{File.dirname(__FILE__)}/../../responses/test1.gz"))
37
+ FakeWeb.register_uri(:get, "https://www.pathfinder-xml.com/development/feed?login.guid=test&file=4551480",
38
+ :body => File.read("#{File.dirname(__FILE__)}/../../responses/test2.gz"))
39
+
40
+ changes = Array.new
41
+ FlightStats::DataFeed.new.files do |file|
42
+ file.updates do |update|
43
+ changes << update
44
+ end
45
+ end
46
+ update = changes[0]
47
+ assert_equal(Time.utc(2009,6,8,20,30,0,43), update.timestamp)
48
+ assert_equal('ASDI', update.source)
49
+ assert_equal('STATUS-Active', update.event)
50
+ assert_equal('ARD- New=06/08/09 16:24, ERD- Old=06/08/09 16:26 New=06/08/09 16:24, ERA- Old=06/08/09 17:45 New=06/08/09 17:42, STATUS- Old=S New=A', update.data_updated)
51
+
52
+ assert_equal('162197049', update.flight.id)
53
+ assert_equal('753', update.flight.number)
54
+ assert_equal(Time.utc(2009,6,8,16,26), update.flight.scheduled_local_runway_departure_time)
55
+ assert_equal(Time.utc(2009,6,8,16,24), update.flight.estimated_local_runway_departure_time)
56
+ assert_equal(Time.utc(2009,6,8,16,24,52), update.flight.actual_local_runway_departure_time)
57
+ assert_equal(Time.utc(2009,6,8,17,45), update.flight.scheduled_local_runway_arrival_time)
58
+ assert_equal(Time.utc(2009,6,8,17,42), update.flight.estimated_local_runway_arrival_time)
59
+ assert_equal('A', update.flight.creator_code)
60
+ assert_equal('A', update.flight.status_code)
61
+ assert_equal(79, update.flight.scheduled_air_time)
62
+ assert_equal(-4, update.flight.departure_airport_timezone_offset)
63
+ assert_equal(-4, update.flight.arrival_airport_timezone_offset)
64
+ assert_equal(Time.utc(2009,6,8,16,26), update.flight.local_departure_time)
65
+ assert_equal(Time.utc(2009,6,8,17,45), update.flight.local_arrival_time)
66
+
67
+ assert_equal('G4', update.flight.airline.code)
68
+ assert_equal('AAY', update.flight.airline.icao_code)
69
+ assert_nil(update.flight.airline.iata_code)
70
+ assert_nil(update.flight.airline.faa_code)
71
+ assert_nil(update.flight.airline.name)
72
+
73
+ assert_equal('SFB', update.flight.origin.code)
74
+ assert_equal('KSFB', update.flight.origin.icao_code)
75
+ assert_nil(update.flight.origin.iata_code)
76
+ assert_nil(update.flight.origin.faa_code)
77
+ assert_nil(update.flight.origin.name)
78
+
79
+ assert_equal('GSO', update.flight.destination.code)
80
+ assert_equal('KGSO', update.flight.destination.icao_code)
81
+ assert_nil(update.flight.destination.iata_code)
82
+ assert_nil(update.flight.destination.faa_code)
83
+ assert_nil(update.flight.destination.name)
84
+
85
+ assert_equal([], update.flight.codeshares)
86
+
87
+ update = changes[6]
88
+ assert_equal(Time.utc(2009,6,8,20,27,1,110), update.timestamp)
89
+ assert_equal('Airline (CO)', update.source)
90
+ assert_equal('Time Adjustment', update.event)
91
+ assert_equal('EGD- New=06/08/09 19:35, EGA- New=06/08/09 23:35, DGATE- New=C-30', update.data_updated)
92
+
93
+ assert_equal('161861862', update.flight.id)
94
+ assert_equal('1417', update.flight.number)
95
+ assert_equal(Time.utc(2009,6,8,19,35), update.flight.published_local_departure_time)
96
+ assert_equal(Time.utc(2009,6,8,23,35), update.flight.published_local_arrival_time)
97
+ assert_equal(Time.utc(2009,6,8,19,35), update.flight.scheduled_local_gate_departure_time)
98
+ assert_equal(Time.utc(2009,6,8,19,35), update.flight.estimated_local_gate_departure_time)
99
+ assert_equal(Time.utc(2009,6,8,23,35), update.flight.scheduled_local_gate_arrival_time)
100
+ assert_equal(Time.utc(2009,6,8,23,35), update.flight.estimated_local_gate_arrival_time)
101
+ assert_equal(Time.utc(2009,6,8,19,56), update.flight.scheduled_local_runway_departure_time)
102
+ assert_equal(Time.utc(2009,6,8,19,56), update.flight.estimated_local_runway_departure_time)
103
+ assert_equal(Time.utc(2009,6,8,23,21), update.flight.scheduled_local_runway_arrival_time)
104
+ assert_equal(Time.utc(2009,6,8,23,21), update.flight.estimated_local_runway_arrival_time)
105
+ assert_nil(update.flight.actual_local_runway_departure_time)
106
+ assert_equal('O', update.flight.creator_code)
107
+ assert_equal('S', update.flight.status_code)
108
+ assert_equal(145, update.flight.scheduled_air_time)
109
+ assert_equal(180, update.flight.scheduled_block_time)
110
+ assert_equal(-5, update.flight.departure_airport_timezone_offset)
111
+ assert_equal(-4, update.flight.arrival_airport_timezone_offset)
112
+ assert_equal(Time.utc(2009,6,8,19,35), update.flight.local_departure_time)
113
+ assert_equal(Time.utc(2009,6,8,23,35), update.flight.local_arrival_time)
114
+ assert_equal('735', update.flight.scheduled_aircraft_type)
115
+ assert_equal('C-30', update.flight.departure_gate)
116
+ assert_equal('C', update.flight.departure_terminal)
117
+ assert_nil(update.flight.arrival_terminal)
118
+
119
+ assert_equal('CO', update.flight.airline.code)
120
+ assert_equal('COA', update.flight.airline.icao_code)
121
+ assert_nil(update.flight.airline.iata_code)
122
+ assert_nil(update.flight.airline.faa_code)
123
+ assert_nil(update.flight.airline.name)
124
+
125
+ assert_equal('IAH', update.flight.origin.code)
126
+ assert_equal('KIAH', update.flight.origin.icao_code)
127
+ assert_nil(update.flight.origin.iata_code)
128
+ assert_nil(update.flight.origin.faa_code)
129
+ assert_nil(update.flight.origin.name)
130
+
131
+ assert_equal('PIT', update.flight.destination.code)
132
+ assert_equal('KPIT', update.flight.destination.icao_code)
133
+ assert_nil(update.flight.destination.iata_code)
134
+ assert_nil(update.flight.destination.faa_code)
135
+ assert_nil(update.flight.destination.name)
136
+
137
+ assert_equal(1, update.flight.codeshares.size)
138
+ assert_equal('109977276', update.flight.codeshares.first.id)
139
+ assert_equal('2317', update.flight.codeshares.first.number)
140
+ assert_equal('L', update.flight.codeshares.first.designator)
141
+ assert_equal(Time.utc(2009,6,8,19,35), update.flight.codeshares.first.published_local_departure_time)
142
+ assert_equal(Time.utc(2009,6,8,23,35), update.flight.codeshares.first.published_local_arrival_time)
143
+ assert_equal('CM', update.flight.codeshares.first.airline.code)
144
+ assert_equal('CM', update.flight.codeshares.first.airline.iata_code)
145
+ end
146
+ end
@@ -0,0 +1,23 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class DelayFeedTest < Test::Unit::TestCase
4
+
5
+ def test_should_set_last_accessed_time
6
+ df = FlightStats::DataFeed.new(Time.utc(2009,9,9,9,9))
7
+ assert_equal(Time.utc(2009,9,9,9,9), df.last_accessed_at)
8
+ end
9
+
10
+ def test_should_find_two_files
11
+ FakeWeb.register_uri(:get, "https://www.pathfinder-xml.com/development/feed?login.guid=test&useUTC=true&lastAccessed=#{Time.now.utc.strftime("%Y-%m-%dT%H:%M")}",
12
+ :body => File.read("#{File.dirname(__FILE__)}/../responses/feed_file_list.xml"))
13
+
14
+ files = FlightStats::DataFeed.new.files
15
+ assert_equal 2, files.size
16
+
17
+ assert_equal(265293, files[0].size)
18
+ assert_equal(Time.utc(2009,6,8,21,37), files[0].timestamp)
19
+ assert_equal('4551477', files[0].id)
20
+ assert_equal(1760, files[0].message_count)
21
+ end
22
+
23
+ end
@@ -0,0 +1,20 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class FlightStatsTest < Test::Unit::TestCase
4
+
5
+ def test_flightstats_query
6
+ FakeWeb.register_uri(:get, "https://www.pathfinder-xml.com/development/xml?param=1&login.guid=test",
7
+ :body => "Example")
8
+ assert_equal "Example", FlightStats.query({:param => '1'}).read
9
+ end
10
+
11
+ def test_throw_error_when_error_in_response
12
+ FakeWeb.register_uri(:get, "https://www.pathfinder-xml.com/development/xml?param=2&login.guid=test",
13
+ :body => File.read("#{File.dirname(__FILE__)}/responses/error.xml"),
14
+ :status => ["401", "HTTPUnauthorized"])
15
+ assert_raise StandardError do
16
+ FlightStats.query({:param => '2'})
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,37 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <FlightHistoryEventFeedResponse xmlns="http://pathfinder-xml/FlightHistoryEventFeedService.xsd"><Error MajorCode="1" MinorCode="1"><Message>The guid is not valid.</Message><StackTrace>com.conducivetech.pathfinder.common.util.PathfinderException: The guid is not valid.
3
+ at com.conducivetech.pathfinder.services.ServiceHandler.authenticate(ServiceHandler.java:682)
4
+ at com.conducivetech.pathfinder.services.ServiceHandler.doServiceXML(ServiceHandler.java:372)
5
+ at com.conducivetech.pathfinder.delegates.LocalServiceDelegate.doServiceXML(LocalServiceDelegate.java:83)
6
+ at com.conducivetech.pathfinder.xml.FlightHistoryFeedServlet.invokeServiceXML(FlightHistoryFeedServlet.java:245)
7
+ at com.conducivetech.pathfinder.xml.FlightHistoryFeedServlet.getFilesNewerThanAsXML(FlightHistoryFeedServlet.java:395)
8
+ at com.conducivetech.pathfinder.xml.FlightHistoryFeedServlet.doGet(FlightHistoryFeedServlet.java:172)
9
+ at javax.servlet.http.HttpServlet.service(HttpServlet.java:697)
10
+ at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
11
+ at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
12
+ at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
13
+ at com.conducivetech.pathfinder.webcommon.UTF8EncodingFilter.doFilter(UTF8EncodingFilter.java:38)
14
+ at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
15
+ at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
16
+ at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
17
+ at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
18
+ at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
19
+ at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
20
+ at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
21
+ at org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrincipalValve.java:54)
22
+ at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:174)
23
+ at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432)
24
+ at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
25
+ at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
26
+ at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
27
+ at org.apache.catalina.valves.FastCommonAccessLogValve.invoke(FastCommonAccessLogValve.java:495)
28
+ at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
29
+ at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
30
+ at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:199)
31
+ at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:282)
32
+ at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:754)
33
+ at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:684)
34
+ at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:876)
35
+ at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
36
+ at java.lang.Thread.run(Thread.java:595)
37
+ </StackTrace></Error></FlightHistoryEventFeedResponse>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <FlightHistoryEventFeedResponse xmlns="http://pathfinder-xml/FlightHistoryEventFeedService.xsd"><File Bytes="265293" DateTime="2009-06-08T14:37:00.000" DateTimeUTC="2009-06-08T21:37:00.000" ID="4551477" Messages="1760"/><File Bytes="231618" DateTime="2009-06-08T14:38:00.000" DateTimeUTC="2009-06-08T21:38:00.000" ID="4551480" Messages="1505"/></FlightHistoryEventFeedResponse>
Binary file
Binary file
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'fakeweb'
4
+
5
+ FLIGHTSTATS_GUID = 'test'
6
+
7
+ $: << File.join(File.dirname(__FILE__), '..', 'lib')
8
+
9
+ require 'flightstats'
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flightstats
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-09-24 00:00:00 -07: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
+ - !ruby/object:Gem::Dependency
27
+ name: tzinfo
28
+ type: :runtime
29
+ version_requirement:
30
+ version_requirements: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 0.3.14
35
+ version:
36
+ description:
37
+ email: dev@flightcaster.com
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files: []
43
+
44
+ files:
45
+ - Rakefile
46
+ - README.rdoc
47
+ - lib/flightstats/airline.rb
48
+ - lib/flightstats/airport.rb
49
+ - lib/flightstats/data_feed/file/flight_update.rb
50
+ - lib/flightstats/data_feed/file/sax_parser.rb
51
+ - lib/flightstats/data_feed/file.rb
52
+ - lib/flightstats/data_feed/sax_parser.rb
53
+ - lib/flightstats/data_feed.rb
54
+ - lib/flightstats/flight/codeshare.rb
55
+ - lib/flightstats/flight.rb
56
+ - lib/flightstats.rb
57
+ - test/flightstats/data_feed/file_test.rb
58
+ - test/flightstats/data_feed_test.rb
59
+ - test/flightstats_test.rb
60
+ - test/test_helper.rb
61
+ - test/responses/test1.gz
62
+ - test/responses/test2.gz
63
+ - test/responses/error.xml
64
+ - test/responses/feed_file_list.xml
65
+ has_rdoc: true
66
+ homepage: http://flightcaster.com/
67
+ licenses: []
68
+
69
+ post_install_message:
70
+ rdoc_options: []
71
+
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ version:
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: "0"
85
+ version:
86
+ requirements: []
87
+
88
+ rubyforge_project:
89
+ rubygems_version: 1.3.5
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: FlightStats wrapper
93
+ test_files: []
94
+