aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNat Lasseter <user@4574.co.uk>2022-06-13 20:07:02 +0100
committerNat Lasseter <user@4574.co.uk>2022-06-13 20:07:02 +0100
commitf79f9733ddec5c61ce5886619f91065c07bcbdf6 (patch)
tree5d36e17968b318c1771ecad2a347338b9fe83995
Initial commit
-rw-r--r--Gemfile4
-rw-r--r--Readme.textile5
-rw-r--r--planed.html62
-rw-r--r--planed.ru213
4 files changed, 284 insertions, 0 deletions
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..7909b9a
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,4 @@
+source 'https://rubygems.org'
+
+gem 'rack'
+gem 'thin'
diff --git a/Readme.textile b/Readme.textile
new file mode 100644
index 0000000..ab6d0a8
--- /dev/null
+++ b/Readme.textile
@@ -0,0 +1,5 @@
+h1. Planed
+
+p. As in plane daemon.
+
+p. Generates random ATC instructions and prints them to screen.
diff --git a/planed.html b/planed.html
new file mode 100644
index 0000000..6e685b8
--- /dev/null
+++ b/planed.html
@@ -0,0 +1,62 @@
+<html>
+ <head>
+ <title>
+ Plane
+ </title>
+ <style>
+body {
+ background-color: #111;
+}
+
+div#overlay {
+ background-image: linear-gradient(0deg, #000 75%, #666 25%);
+ background-size: 1em 1em;
+ opacity: 0.1;
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+}
+
+div.msg {
+ margin-bottom: 0.5em;
+ color: #0D0;
+ font-family: monospace;
+ font-size: 2em;
+ font-weight: bold;
+}
+ </style>
+ </head>
+ <body>
+ <div id="overlay"></div>
+ <div id="log"></div>
+ <script>
+ let ws = new WebSocket("ws://localhost:3000");
+ let div = document.getElementById("log");
+ let loglen = 0;
+ const logmax = 18;
+ const timemax = 5000;
+
+ ws.onmessage = function(ev) {
+ loglen += 1;
+ div.innerHTML += "<div class=\"msg\" id=\"msg" + loglen + "\">" + ev.data + "</div>";
+ if (loglen > logmax)
+ document.getElementById("msg" + (loglen - logmax)).remove();
+ };
+
+ function rantime() {
+ return Math.random() * timemax + 1000;
+ }
+
+ function msgloop() {
+ ws.send("any");
+ setTimeout(msgloop, rantime());
+ }
+
+ ws.onopen = function(ev) {
+ setTimeout(msgloop, rantime());
+ }
+ </script>
+ </body>
+</html>
diff --git a/planed.ru b/planed.ru
new file mode 100644
index 0000000..0851968
--- /dev/null
+++ b/planed.ru
@@ -0,0 +1,213 @@
+#!/usr/bin/env ruby
+
+def plane
+ (('A'..'Z').to_a.sample(rand(2) + 2) +
+ (0..9).to_a.sample(rand(2) + 3)).join +
+ (rand(3) == 0 ? " heavy" : "")
+end
+
+def heading
+ "%03d" % (rand(72) * 5)
+end
+
+def level
+ rand(32) + 7
+end
+
+def altitude
+ (rand(6) + 1) * 1000
+end
+
+def please
+ "please #{%w(climb descend).sample} flight level #{level}"
+end
+
+def beacon
+ c = %w(B C D F G H J K L M N P Q R S T V W X Z)
+ v = %w(A E I O U Y)
+
+ case rand(4)
+ when 0
+ c.sample + v.sample + c.sample
+ when 1
+ c.sample + v.sample + c.sample + v.sample + c.sample
+ when 2
+ c.sample + v.sample + c.sample + c.sample + v.sample
+ when 3
+ c.sample + c.sample + v.sample
+ end
+end
+
+def digit?
+ d = rand(5)
+ d = "" if d.zero?
+ d.to_s
+end
+
+def route
+ c = %w(B C D F G H J K L M N P Q R S T V W X Z)
+ v = %w(A E I O U Y)
+
+ case rand(2)
+ when 0
+ c.sample + v.sample + c.sample + v.sample + c.sample + digit?
+ when 1
+ c.sample + v.sample + c.sample + c.sample + v.sample + digit?
+ end
+end
+
+def runway
+ "#{rand(36) + 1}#{%w(_ _ L L L C R R R).sample.gsub(/_/, "")}"
+end
+
+def clearance
+ "cleared to " +
+ case rand(6)
+ when 0
+ "heading #{heading}"
+ when 1
+ "flight level #{level}"
+ when 2
+ "#{altitude} feet"
+ when 3
+ beacon
+ when 4
+ "land runway #{runway}"
+ when 5
+ "take off runway #{runway}"
+ end
+end
+
+def localizer?
+ case rand(3)
+ when 0
+ " until established on the localizer"
+ when 1..2
+ ""
+ end
+end
+
+def maintain
+ "maintain #{altitude} feet#{localizer?}"
+end
+
+def vectors
+ case rand(2)
+ when 0
+ "expect vectors for the #{%w(ILS RNAV).sample} runway #{runway}"
+ when 1
+ "join the localizer runway #{runway}"
+ end
+end
+
+def proceed
+ "#{%w(proceed fly).sample} direct #{beacon}"
+end
+
+def location
+ %w(
+ ground
+ delivery
+ departure
+ arrival
+ tower
+ tracks
+ ).sample
+end
+
+def frequency
+ (rand(13) + 118) +
+ (rand(200) / 200.0)
+end
+
+def contact
+ "contact #{location} on #{frequency}"
+end
+
+def monitor
+ "monitor #{frequency}"
+end
+
+def turn
+ case rand(3)
+ when 0
+ "turn left heading #{heading}#{localizer?}"
+ when 1
+ "turn heading #{heading}#{localizer?}"
+ when 2
+ "turn right heading #{heading}#{localizer?}"
+ end
+end
+
+def radar
+ "radar contact"
+end
+
+def transition?
+ ", #{runway} transition"
+end
+
+def star
+ case rand(3)
+ when 0
+ "descend via #{route}"
+ when 1
+ "join the #{route} arrival"
+ when 2
+ "descend on the #{route} arrival"
+ end
+end
+
+def sid
+ "proceed direct #{beacon}, join the #{route} departure"
+end
+
+def sentence
+ plane + " " +
+ case rand(21)
+ when 0
+ please
+ when 1
+ proceed
+ when 2
+ contact
+ when 3
+ monitor
+ when 4..9
+ clearance
+ when 10..12
+ turn
+ when 13
+ radar
+ when 14..15
+ star
+ when 16..17
+ sid
+ when 18..19
+ vectors
+ when 20
+ maintain
+ end
+end
+
+require 'faye/websocket'
+
+Faye::WebSocket.load_adapter('thin')
+
+webpage = File.read("planed.html")
+
+App = lambda do |env|
+ if Faye::WebSocket.websocket?(env)
+ ws = Faye::WebSocket.new(env)
+
+ ws.on(:message) do |ev|
+ ws.send(sentence)
+ end
+
+ ws.rack_response
+ else
+ [200, { 'Content-Type' => 'text/html' }, [webpage]]
+ end
+end
+
+run App