flightstats 0.0.1

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