flightstats 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +23 -0
- data/Rakefile +30 -0
- data/lib/flightstats.rb +50 -0
- data/lib/flightstats/airline.rb +5 -0
- data/lib/flightstats/airport.rb +5 -0
- data/lib/flightstats/data_feed.rb +73 -0
- data/lib/flightstats/data_feed/file.rb +31 -0
- data/lib/flightstats/data_feed/file/flight_update.rb +5 -0
- data/lib/flightstats/data_feed/file/sax_parser.rb +138 -0
- data/lib/flightstats/data_feed/sax_parser.rb +27 -0
- data/lib/flightstats/flight.rb +58 -0
- data/lib/flightstats/flight/codeshare.rb +7 -0
- data/test/flightstats/data_feed/file_test.rb +146 -0
- data/test/flightstats/data_feed_test.rb +23 -0
- data/test/flightstats_test.rb +20 -0
- data/test/responses/error.xml +37 -0
- data/test/responses/feed_file_list.xml +2 -0
- data/test/responses/test1.gz +0 -0
- data/test/responses/test2.gz +0 -0
- data/test/test_helper.rb +9 -0
- metadata +94 -0
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
|
data/lib/flightstats.rb
ADDED
@@ -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,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,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,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
|
data/test/test_helper.rb
ADDED
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
|
+
|