atc-tools 1.0.0

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.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/bin/fpv +3 -0
  3. data/doc/ATCTools.html +133 -0
  4. data/doc/ATCTools/Aircraft.html +309 -0
  5. data/doc/ATCTools/Airport.html +634 -0
  6. data/doc/ATCTools/FlightPlan.html +544 -0
  7. data/doc/ATCTools/FlightPlanValidator.html +265 -0
  8. data/doc/ATCTools/HeadingDiscoveryError.html +135 -0
  9. data/doc/ATCTools/HeadingError.html +135 -0
  10. data/doc/ATCTools/NameDiscoveryError.html +135 -0
  11. data/doc/ATCTools/NoAircraftSelectedError.html +135 -0
  12. data/doc/ATCTools/VRC.html +656 -0
  13. data/doc/Aircraft.html +127 -0
  14. data/doc/Airport.html +564 -0
  15. data/doc/FlightPlan.html +127 -0
  16. data/doc/HeadingError.html +127 -0
  17. data/doc/NameDiscoveryError.html +127 -0
  18. data/doc/created.rid +7 -0
  19. data/doc/images/add.png +0 -0
  20. data/doc/images/arrow_up.png +0 -0
  21. data/doc/images/brick.png +0 -0
  22. data/doc/images/brick_link.png +0 -0
  23. data/doc/images/bug.png +0 -0
  24. data/doc/images/bullet_black.png +0 -0
  25. data/doc/images/bullet_toggle_minus.png +0 -0
  26. data/doc/images/bullet_toggle_plus.png +0 -0
  27. data/doc/images/date.png +0 -0
  28. data/doc/images/delete.png +0 -0
  29. data/doc/images/find.png +0 -0
  30. data/doc/images/loadingAnimation.gif +0 -0
  31. data/doc/images/macFFBgHack.png +0 -0
  32. data/doc/images/package.png +0 -0
  33. data/doc/images/page_green.png +0 -0
  34. data/doc/images/page_white_text.png +0 -0
  35. data/doc/images/page_white_width.png +0 -0
  36. data/doc/images/plugin.png +0 -0
  37. data/doc/images/ruby.png +0 -0
  38. data/doc/images/tag_blue.png +0 -0
  39. data/doc/images/tag_green.png +0 -0
  40. data/doc/images/transparent.png +0 -0
  41. data/doc/images/wrench.png +0 -0
  42. data/doc/images/wrench_orange.png +0 -0
  43. data/doc/images/zoom.png +0 -0
  44. data/doc/index.html +87 -0
  45. data/doc/js/darkfish.js +155 -0
  46. data/doc/js/jquery.js +18 -0
  47. data/doc/js/navigation.js +142 -0
  48. data/doc/js/search.js +94 -0
  49. data/doc/js/search_index.js +1 -0
  50. data/doc/js/searcher.js +228 -0
  51. data/doc/rdoc.css +595 -0
  52. data/doc/table_of_contents.html +132 -0
  53. data/lib/atc-tools.rb +1 -0
  54. data/lib/atc-tools/aircraft.rb +36 -0
  55. data/lib/atc-tools/airport.rb +103 -0
  56. data/lib/atc-tools/flight_plan.rb +119 -0
  57. data/lib/atc-tools/script/flight_plan_validator.rb +65 -0
  58. data/lib/atc-tools/vrc.rb +165 -0
  59. data/license.txt +19 -0
  60. metadata +174 -0
@@ -0,0 +1,132 @@
1
+ <!DOCTYPE html>
2
+
3
+ <html>
4
+ <head>
5
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
6
+
7
+ <title>Table of Contents - RDoc Documentation</title>
8
+
9
+ <link type="text/css" media="screen" href="./rdoc.css" rel="stylesheet">
10
+
11
+ <script type="text/javascript">
12
+ var rdoc_rel_prefix = "./";
13
+ </script>
14
+
15
+ <script type="text/javascript" charset="utf-8" src="./js/jquery.js"></script>
16
+ <script type="text/javascript" charset="utf-8" src="./js/navigation.js"></script>
17
+ <script type="text/javascript" charset="utf-8" src="./js/search_index.js"></script>
18
+ <script type="text/javascript" charset="utf-8" src="./js/search.js"></script>
19
+ <script type="text/javascript" charset="utf-8" src="./js/searcher.js"></script>
20
+ <script type="text/javascript" charset="utf-8" src="./js/darkfish.js"></script>
21
+
22
+
23
+ <body class="indexpage">
24
+ <h1>Table of Contents - RDoc Documentation</h1>
25
+
26
+
27
+ <h2 id="classes">Classes/Modules</h2>
28
+ <ul>
29
+ <li class="module">
30
+ <a href="ATCTools.html">ATCTools</a>
31
+ </li>
32
+ <li class="class">
33
+ <a href="ATCTools/Aircraft.html">ATCTools::Aircraft</a>
34
+ </li>
35
+ <li class="class">
36
+ <a href="ATCTools/Airport.html">ATCTools::Airport</a>
37
+ </li>
38
+ <li class="class">
39
+ <a href="ATCTools/FlightPlan.html">ATCTools::FlightPlan</a>
40
+ </li>
41
+ <li class="class">
42
+ <a href="ATCTools/FlightPlanValidator.html">ATCTools::FlightPlanValidator</a>
43
+ </li>
44
+ <li class="class">
45
+ <a href="ATCTools/HeadingDiscoveryError.html">ATCTools::HeadingDiscoveryError</a>
46
+ </li>
47
+ <li class="class">
48
+ <a href="ATCTools/NameDiscoveryError.html">ATCTools::NameDiscoveryError</a>
49
+ </li>
50
+ <li class="class">
51
+ <a href="ATCTools/NoAircraftSelectedError.html">ATCTools::NoAircraftSelectedError</a>
52
+ </li>
53
+ <li class="class">
54
+ <a href="ATCTools/VRC.html">ATCTools::VRC</a>
55
+ </li>
56
+
57
+ </ul>
58
+
59
+ <h2 id="methods">Methods</h2>
60
+ <ul>
61
+
62
+ <li class="method"><a href="ATCTools/FlightPlanValidator.html#method-c-flight_plan">::flight_plan &mdash; ATCTools::FlightPlanValidator</a>
63
+
64
+ <li class="method"><a href="ATCTools/Airport.html#method-c-new">::new &mdash; ATCTools::Airport</a>
65
+
66
+ <li class="method"><a href="ATCTools/VRC.html#method-c-new">::new &mdash; ATCTools::VRC</a>
67
+
68
+ <li class="method"><a href="ATCTools/Aircraft.html#method-c-new">::new &mdash; ATCTools::Aircraft</a>
69
+
70
+ <li class="method"><a href="ATCTools/FlightPlan.html#method-c-new">::new &mdash; ATCTools::FlightPlan</a>
71
+
72
+ <li class="method"><a href="ATCTools/FlightPlanValidator.html#method-c-run">::run &mdash; ATCTools::FlightPlanValidator</a>
73
+
74
+ <li class="method"><a href="ATCTools/VRC.html#method-i-activate_terminal_window-21">#activate_terminal_window! &mdash; ATCTools::VRC</a>
75
+
76
+ <li class="method"><a href="ATCTools/VRC.html#method-i-activate_vrc_window-21">#activate_vrc_window! &mdash; ATCTools::VRC</a>
77
+
78
+ <li class="method"><a href="ATCTools/VRC.html#method-i-aircraft_selected-3F">#aircraft_selected? &mdash; ATCTools::VRC</a>
79
+
80
+ <li class="method"><a href="ATCTools/FlightPlan.html#method-i-altitude_valid-3F">#altitude_valid? &mdash; ATCTools::FlightPlan</a>
81
+
82
+ <li class="method"><a href="ATCTools/VRC.html#method-i-command_line">#command_line &mdash; ATCTools::VRC</a>
83
+
84
+ <li class="method"><a href="ATCTools/Airport.html#method-i-discover_name">#discover_name &mdash; ATCTools::Airport</a>
85
+
86
+ <li class="method"><a href="ATCTools/Airport.html#method-i-discover_variance">#discover_variance &mdash; ATCTools::Airport</a>
87
+
88
+ <li class="method"><a href="ATCTools/VRC.html#method-i-execute_command">#execute_command &mdash; ATCTools::VRC</a>
89
+
90
+ <li class="method"><a href="ATCTools/VRC.html#method-i-execute_command-21">#execute_command! &mdash; ATCTools::VRC</a>
91
+
92
+ <li class="method"><a href="ATCTools/VRC.html#method-i-flight_plan_title">#flight_plan_title &mdash; ATCTools::VRC</a>
93
+
94
+ <li class="method"><a href="ATCTools/FlightPlan.html#method-i-heading">#heading &mdash; ATCTools::FlightPlan</a>
95
+
96
+ <li class="method"><a href="ATCTools/Airport.html#method-i-magnetic_heading_from">#magnetic_heading_from &mdash; ATCTools::Airport</a>
97
+
98
+ <li class="method"><a href="ATCTools/Airport.html#method-i-magnetic_heading_to">#magnetic_heading_to &mdash; ATCTools::Airport</a>
99
+
100
+ <li class="method"><a href="ATCTools/Airport.html#method-i-magnetic_to_true">#magnetic_to_true &mdash; ATCTools::Airport</a>
101
+
102
+ <li class="method"><a href="ATCTools/Airport.html#method-i-name">#name &mdash; ATCTools::Airport</a>
103
+
104
+ <li class="method"><a href="ATCTools/VRC.html#method-i-selected_aircraft">#selected_aircraft &mdash; ATCTools::VRC</a>
105
+
106
+ <li class="method"><a href="ATCTools/VRC.html#method-i-selected_aircraft_info-21">#selected_aircraft_info! &mdash; ATCTools::VRC</a>
107
+
108
+ <li class="method"><a href="ATCTools/VRC.html#method-i-selected_flight_plan-21">#selected_flight_plan! &mdash; ATCTools::VRC</a>
109
+
110
+ <li class="method"><a href="ATCTools/FlightPlan.html#method-i-to_s">#to_s &mdash; ATCTools::FlightPlan</a>
111
+
112
+ <li class="method"><a href="ATCTools/Aircraft.html#method-i-to_s">#to_s &mdash; ATCTools::Aircraft</a>
113
+
114
+ <li class="method"><a href="ATCTools/Airport.html#method-i-to_s">#to_s &mdash; ATCTools::Airport</a>
115
+
116
+ <li class="method"><a href="ATCTools/Airport.html#method-i-true_heading_from">#true_heading_from &mdash; ATCTools::Airport</a>
117
+
118
+ <li class="method"><a href="ATCTools/Airport.html#method-i-true_heading_to">#true_heading_to &mdash; ATCTools::Airport</a>
119
+
120
+ <li class="method"><a href="ATCTools/Airport.html#method-i-true_to_magnetic">#true_to_magnetic &mdash; ATCTools::Airport</a>
121
+
122
+ <li class="method"><a href="ATCTools/FlightPlan.html#method-i-validate">#validate &mdash; ATCTools::FlightPlan</a>
123
+
124
+ </ul>
125
+
126
+
127
+ <footer id="validator-badges">
128
+ <p><a href="http://validator.w3.org/check/referer">[Validate]</a>
129
+ <p>Generated by <a href="https://github.com/rdoc/rdoc">RDoc</a> 4.0.1.
130
+ <p>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish Rdoc Generator</a> 3.
131
+ </footer>
132
+
@@ -0,0 +1 @@
1
+ require 'atc-tools/script/flight_plan_validator'
@@ -0,0 +1,36 @@
1
+ module ATCTools
2
+ class Aircraft
3
+ # Raw data used to initialize the object,
4
+ # typically from the VRC client.
5
+ attr_reader :raw
6
+ # Full aircraft info string.
7
+ attr_accessor :info
8
+ # Aircraft code. The identifier that would be displayed
9
+ # on the radar scope (B732 = Boeing 737-200).
10
+ attr_reader :code
11
+ # Aircraft model number.
12
+ attr_reader :model
13
+ # Aircraft equipment code.
14
+ attr_reader :equipment
15
+
16
+ # Params:
17
+ # :info, :model, :code, :equipment
18
+ # -- See instance variables for descriptions.
19
+ def initialize(aircraft_code = nil, **kvargs)
20
+ @raw = aircraft_code || kvargs.fetch(:code, '')
21
+ @info = kvargs.fetch :info, ''
22
+ @model = kvargs.fetch :model, ''
23
+
24
+ params = @raw.scan(%r{(?:([a-zA-Z]+)/)?(\w+)(?:/([a-zA-Z]+))?}).flatten
25
+
26
+ @code = kvargs.fetch(:code, nil) || params[1] || ''
27
+ @equipment = kvargs.fetch(:equipment, nil) || params[2] || ''
28
+ end
29
+
30
+ # Returns @raw.
31
+ def to_s
32
+ @raw
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,103 @@
1
+ require 'net/http'
2
+
3
+ module ATCTools
4
+ class NameDiscoveryError < StandardError; end
5
+ class HeadingDiscoveryError < StandardError; end
6
+
7
+ class Airport
8
+ # Airport's ICAO code.
9
+ attr_accessor :code
10
+ # Airport's full name.
11
+ attr_writer :name
12
+ # Airport's magnetic variance from true north.
13
+ attr_accessor :variance
14
+
15
+ # URI of the web page used for the last airport name lookup.
16
+ attr_reader :name_uri
17
+ # URI of the web page used for the last heading lookup.
18
+ attr_reader :heading_uri
19
+
20
+ # Params:
21
+ # :code, :name, :variance
22
+ def initialize(code = nil, **kvargs)
23
+ @code = code || (kvargs.fetch :code, '')
24
+ @name = kvargs.fetch :name, ''
25
+ @variance = kvargs.fetch :variance, 17.0 # TODO: Detect this intelligently.
26
+ end
27
+
28
+ # Airport's full name.
29
+ def name
30
+ discover_name if @name.empty?
31
+ @name
32
+ end
33
+
34
+ # Discover the airport's full name based
35
+ # on ICAO code.
36
+ def discover_name
37
+ @name_uri = "http://www.airnav.com/airport/#{@code.to_s.downcase}"
38
+ response = Net::HTTP.get URI name_uri
39
+
40
+ l = response.scan %r{(?i:<title>)(?:AirNav:\s*\w*\s*-\s*)?(.*)(?i:</title>)}
41
+
42
+ raise ATCTools::NameDiscoveryError, "Could not discover name for #{@code.to_s.upcase}" \
43
+ unless l.count > 0
44
+
45
+ @name = l.flatten.first
46
+ end
47
+
48
+ # Discover the airport's magnetic variance
49
+ # based on ICAO code.
50
+ def discover_variance
51
+ end
52
+
53
+ # Calculate the true heading to the specified airport.
54
+ # Takes an ICAO code or Airport object.
55
+ def true_heading_to(arrival)
56
+ @heading_uri = "http://www6.landings.com/cgi-bin/nph-dist_apt?airport1=#{@code.downcase}&airport2=#{arrival.to_s.strip.downcase}"
57
+ response = Net::HTTP.get URI heading_uri
58
+ r = response.scan /(?:heading:)\s*([\d\.]+)\s+/
59
+
60
+ raise ATCTools::HeadingDiscoveryError, "Heading from #{@code.upcase} to #{arrival.to_s.upcase} not found." \
61
+ unless r.count > 0
62
+
63
+ true_hdg = r.flatten.first.to_f
64
+ end
65
+
66
+ # Calculate the true heading from the specified airport.
67
+ # Takes an ICAO code or Airport object.
68
+ def true_heading_from(departure)
69
+ 360.0 - true_heading_to(departure)
70
+ end
71
+
72
+ # Calculate the magnetic heading to the specified airport.
73
+ # Takes an ICAO code or Airport object.
74
+ def magnetic_heading_to(arrival)
75
+ true_to_magnetic true_heading_to(arrival)
76
+ end
77
+
78
+ # Calculate the magnetic heading from the specified airport.
79
+ # Takes an ICAO code or Airport object.
80
+ def magnetic_heading_from(departure)
81
+ true_to_magnetic true_heading_from(departure)
82
+ end
83
+
84
+ # Convert a true heading to magnetic based on the airport's
85
+ # magnetic variance.
86
+ def true_to_magnetic(heading)
87
+ heading - @variance
88
+ end
89
+
90
+ # Convert a magnetic heading to true based on the airport's
91
+ # magnetic variance.
92
+ def magnetic_to_true(heading)
93
+ heading + @variance
94
+ end
95
+
96
+ # Print the Airport ICAO code.
97
+ # Allows the object to act as a direct replacement for string input.
98
+ def to_s
99
+ @code.to_s.upcase
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,119 @@
1
+ require 'atc-tools/aircraft'
2
+ require 'atc-tools/airport'
3
+
4
+ module ATCTools
5
+ class FlightPlan
6
+ # Aircraft callsign.
7
+ attr_accessor :callsign
8
+ # Aircraft type/info.
9
+ attr_accessor :aircraft
10
+ # Flight rules.
11
+ attr_accessor :rules
12
+ # Departure airport.
13
+ attr_accessor :depart
14
+ # Arrival airport.
15
+ attr_accessor :arrive
16
+ # Alternate airport.
17
+ attr_accessor :alternate
18
+ # Cruising altitude.
19
+ attr_accessor :cruise
20
+ # Squawk code.
21
+ attr_accessor :squawk
22
+ # Flight route.
23
+ attr_accessor :route
24
+ # Additional remarks/notes.
25
+ attr_accessor :remarks
26
+ # Scratch pad.
27
+ attr_accessor :scratchpad
28
+
29
+ # Params:
30
+ # :callsign, :aircraft, :rules, :depart, :arrive, :alternate, :cruse,
31
+ # :squawk, :route, :remarks, :scratchpad
32
+ # -- See instance variables for descriptions.
33
+ def initialize(**kvargs)
34
+ @callsign = kvargs.fetch :callsign, ''
35
+ @aircraft = kvargs.fetch :aircraft, ATCTools::Aircraft.new
36
+ @rules = kvargs.fetch :rules, ''
37
+ @depart = kvargs.fetch :depart, ATCTools::Airport.new
38
+ @arrive = kvargs.fetch :arrive, ATCTools::Airport.new
39
+ @alternate = kvargs.fetch :alternate, ATCTools::Airport.new
40
+ @cruise = kvargs.fetch :cruise, 0
41
+ @squawk = kvargs.fetch :squawk, '0000'
42
+ @route = kvargs.fetch :route, ''
43
+ @remarks = kvargs.fetch :remarks, ''
44
+ @scratchpad = kvargs.fetch :scratchpad, ''
45
+
46
+ @heading = nil
47
+ end
48
+
49
+ # Magnetic heading from the departure to arrival airport.
50
+ def heading
51
+ altitude_valid? unless @heading # Run the validator to populate @heading.
52
+ @heading
53
+ end
54
+
55
+ # Validate the cruising altitude given the arrival airport
56
+ # and flight rules.
57
+ def altitude_valid?
58
+ # TODO: This can cause a bug if the destination airport is changed
59
+ # after the heading is calculated. Although a new FlightPlan
60
+ # object should be created in this case, the problem should
61
+ # still be fixed.
62
+ @heading = @depart.magnetic_heading_to @arrive unless @heading
63
+
64
+ # Strip the zeros off of the altitude for even/odd comparison.
65
+ cruise_stripped = @cruise.to_s.gsub(/0/, '').to_i
66
+ is_north_east = (@heading < 180 || @heading >= 360)
67
+
68
+ rules = @rules.upcase.to_sym
69
+ case rules
70
+ when :IFR
71
+ above_fl410 = cruise_stripped > 41
72
+
73
+ if above_fl410
74
+ east_alt = [45, 49, 53, 57, 61]
75
+ west_alt = [43, 47, 51, 55, 59]
76
+
77
+ east_valid = (is_north_east && east_alt.include?(cruise_stripped))
78
+ west_valid = ((not is_north_east) && west_alt.include?(cruise_stripped))
79
+
80
+ return true if east_valid || west_valid
81
+ else
82
+ return true if
83
+ (is_north_east && cruise_stripped.odd?) ||
84
+ ((not is_north_east) && cruise_stripped.even?)
85
+ end
86
+
87
+ when :VFR
88
+ end
89
+
90
+ false
91
+ end
92
+
93
+ # Validate the flight plan.
94
+ def validate
95
+ end
96
+
97
+ # Returns a human-readable version of the flight plan.
98
+ def to_s
99
+ data = <<EOS
100
+ Callsign: #{@callsign}
101
+ A/C Type: #{@aircraft}
102
+ Rules: #{@rules}
103
+
104
+ Depart: #{@depart}
105
+ Arrive: #{@arrive} :: #{@arrive.name}
106
+ Alternate: #{@alternate}
107
+
108
+ Route: #{@route}
109
+
110
+ Cruise: #{@cruise}
111
+ Scratchpad: #{@scratchpad}
112
+ Squawk: #{@squawk}
113
+
114
+ Remarks: #{@remarks}
115
+ EOS
116
+ end
117
+
118
+ end
119
+ end
@@ -0,0 +1,65 @@
1
+ require 'launchy'
2
+ require 'atc-tools/vrc'
3
+ require 'atc-tools/flight_plan'
4
+
5
+ module ATCTools
6
+ # Script that extracts a flight plan from VRC.
7
+ class FlightPlanValidator
8
+ private_class_method :new
9
+
10
+ # The last flight plan returned.
11
+ def self.flight_plan
12
+ @flight_plan
13
+ end
14
+
15
+ # Note: Executing this script will call commands in
16
+ # the VRC client and will interfere with the user.
17
+ def self.run
18
+ vrc = ATCTools::VRC.new
19
+
20
+ begin
21
+ @flight_plan = vrc.selected_flight_plan!
22
+ rescue ATCTools::NoAircraftSelectedError
23
+ return 'No aircraft selected.'
24
+ end
25
+
26
+ vrc.activate_terminal_window!
27
+
28
+ heading_thread = Thread.new do
29
+ begin
30
+ @flight_plan.heading
31
+ rescue ATCTools::HeadingDiscoveryError
32
+ Launchy.open @flight_plan.depart.heading_uri
33
+ end
34
+ end
35
+
36
+ airport_name_thread = Thread.new do
37
+ begin
38
+ @flight_plan.arrive.name
39
+ rescue ATCTools::NameDiscoveryError
40
+ Launchy.open "https://www.google.com/#q=#{@flight_plan.arrive.upcase}+airport"
41
+ end
42
+ end
43
+
44
+ heading_thread.join
45
+ airport_name_thread.join
46
+
47
+ output = []
48
+
49
+ output << '------------------------------------------------------------'
50
+ output << vrc.flight_plan_title
51
+ output << ''
52
+ output << @flight_plan.to_s.split("\n")
53
+ output << ''
54
+ output << ''
55
+ output << "Alt Valid? #{(@flight_plan.altitude_valid?) ? 'Yes' : '-NO-'}"
56
+ output << "Heading: #{@flight_plan.heading} mag :: #{@flight_plan.depart.magnetic_to_true @flight_plan.heading} true"
57
+ output << ''
58
+ output << @flight_plan.aircraft.info.split(' - ').join("\n").strip
59
+ output << '------------------------------------------------------------'
60
+
61
+ text = output.join("\n")
62
+ end
63
+
64
+ end
65
+ end