Add some mechanical hexid->registration conversions.
This commit is contained in:
parent
08fba4e3b0
commit
e5912c322f
|
@ -16,6 +16,7 @@
|
|||
<script type="text/javascript" src="config.js"></script>
|
||||
<script type="text/javascript" src="markers.js"></script>
|
||||
<script type="text/javascript" src="dbloader.js"></script>
|
||||
<script type="text/javascript" src="registrations.js"></script>
|
||||
<script type="text/javascript" src="planeObject.js"></script>
|
||||
<script type="text/javascript" src="formatter.js"></script>
|
||||
<script type="text/javascript" src="flags.js"></script>
|
||||
|
|
|
@ -44,9 +44,12 @@ function PlaneObject(icao) {
|
|||
this.markerStyleKey = null;
|
||||
this.markerSvgKey = null;
|
||||
|
||||
// request metadata
|
||||
this.registration = null;
|
||||
// start from a computed registration, let the DB override it
|
||||
// if it has something else.
|
||||
this.registration = registration_from_hexid(this.icao);
|
||||
this.icaotype = null;
|
||||
|
||||
// request metadata
|
||||
getAircraftData(this.icao).done(function(data) {
|
||||
if ("r" in data) {
|
||||
this.registration = data.r;
|
||||
|
|
310
public_html/registrations.js
Normal file
310
public_html/registrations.js
Normal file
|
@ -0,0 +1,310 @@
|
|||
// Various reverse-engineered versions of the allocation algorithms
|
||||
// used by different countries to allocate 24-bit ICAO addresses based
|
||||
// on the aircraft registration.
|
||||
//
|
||||
// These were worked out by looking at the allocation patterns and
|
||||
// working backwards to an algorithm that generates that pattern,
|
||||
// spot-checking aircraft to see if it worked.
|
||||
// YMMV.
|
||||
|
||||
registration_from_hexid = (function () {
|
||||
// hide the guts in a closure
|
||||
|
||||
var limited_alphabet = "ABCDEFGHJKLMNPQRSTUVWXYZ"; // 24 chars; no I, O
|
||||
var full_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // 26 chars
|
||||
|
||||
// handles 3-letter suffixes assigned with a regular pattern
|
||||
//
|
||||
// start: first hexid of range
|
||||
// s1: major stride (interval between different first letters)
|
||||
// s2: minor stride (interval between different second letters)
|
||||
// prefix: the registration prefix
|
||||
//
|
||||
// optionally:
|
||||
// alphabet: the alphabet to use (defaults full_alphabet)
|
||||
// first: the suffix to use at the start of the range (default: AAA)
|
||||
// last: the last valid suffix in the range (default: ZZZ)
|
||||
|
||||
var stride_mappings = [
|
||||
{ start: 0x008011, s1: 26*26, s2: 26, prefix: "ZS-" },
|
||||
|
||||
{ start: 0x390000, s1: 1024, s2: 32, prefix: "F-G" },
|
||||
{ start: 0x398000, s1: 1024, s2: 32, prefix: "F-H" },
|
||||
|
||||
{ start: 0x3C4421, s1: 1024, s2: 32, prefix: "D-A", first: 'AAA', last: 'OZZ' },
|
||||
{ start: 0x3C0001, s1: 26*26, s2: 26, prefix: "D-A", first: 'PAA', last: 'ZZZ' },
|
||||
{ start: 0x3C8421, s1: 1024, s2: 32, prefix: "D-B", first: 'AAA', last: 'OZZ' },
|
||||
{ start: 0x3C2001, s1: 26*26, s2: 26, prefix: "D-B", first: 'PAA', last: 'ZZZ' },
|
||||
{ start: 0x3CC000, s1: 26*26, s2: 26, prefix: "D-C" },
|
||||
{ start: 0x3D04A8, s1: 26*26, s2: 26, prefix: "D-E" },
|
||||
{ start: 0x3D4950, s1: 26*26, s2: 26, prefix: "D-F" },
|
||||
{ start: 0x3D8DF8, s1: 26*26, s2: 26, prefix: "D-G" },
|
||||
{ start: 0x3DD2A0, s1: 26*26, s2: 26, prefix: "D-H" },
|
||||
{ start: 0x3E1748, s1: 26*26, s2: 26, prefix: "D-I" },
|
||||
|
||||
{ start: 0x448421, s1: 1024, s2: 32, prefix: "OO-" },
|
||||
{ start: 0x458421, s1: 1024, s2: 32, prefix: "OY-" },
|
||||
{ start: 0x460000, s1: 26*26, s2: 26, prefix: "OH-" },
|
||||
{ start: 0x468421, s1: 1024, s2: 32, prefix: "SX-" },
|
||||
{ start: 0x490421, s1: 1024, s2: 32, prefix: "CS-" },
|
||||
{ start: 0x4A0421, s1: 1024, s2: 32, prefix: "YR-" },
|
||||
{ start: 0x4B8421, s1: 1024, s2: 32, prefix: "TC-" },
|
||||
{ start: 0x740421, s1: 1024, s2: 32, prefix: "JY-" },
|
||||
{ start: 0x760421, s1: 1024, s2: 32, prefix: "AP-" },
|
||||
{ start: 0x768421, s1: 1024, s2: 32, prefix: "9V-" },
|
||||
{ start: 0x778421, s1: 1024, s2: 32, prefix: "YK-" },
|
||||
{ start: 0xC00001, s1: 26*26, s2: 26, prefix: "C-F" },
|
||||
{ start: 0xC044A9, s1: 26*26, s2: 26, prefix: "C-G" },
|
||||
{ start: 0xE01041, s1: 4096, s2: 64, prefix: "LV-" }
|
||||
];
|
||||
|
||||
// numeric registrations
|
||||
// start: start hexid in range
|
||||
// first: first numeric registration
|
||||
// count: number of numeric registrations
|
||||
// template: registration template, trailing characters are replaced with the numeric registration
|
||||
var numeric_mappings = [
|
||||
{ start: 0x140000, first: 0, count: 100000, template: "RA0000" },
|
||||
{ start: 0x0B03E8, first: 1000, count: 1000, template: "CUT0000" }
|
||||
];
|
||||
|
||||
// fill in some derived data
|
||||
for (var i = 0; i < stride_mappings.length; ++i) {
|
||||
var mapping = stride_mappings[i];
|
||||
|
||||
if (!mapping.alphabet) {
|
||||
mapping.alphabet = full_alphabet;
|
||||
}
|
||||
|
||||
if (mapping.first) {
|
||||
var c1 = mapping.alphabet.indexOf(mapping.first.charAt(0));
|
||||
var c2 = mapping.alphabet.indexOf(mapping.first.charAt(1));
|
||||
var c3 = mapping.alphabet.indexOf(mapping.first.charAt(2));
|
||||
mapping.offset = c1 * mapping.s1 + c2 * mapping.s2 + c3;
|
||||
} else {
|
||||
mapping.offset = 0;
|
||||
}
|
||||
|
||||
if (mapping.last) {
|
||||
var c1 = mapping.alphabet.indexOf(mapping.last.charAt(0));
|
||||
var c2 = mapping.alphabet.indexOf(mapping.last.charAt(1));
|
||||
var c3 = mapping.alphabet.indexOf(mapping.last.charAt(2));
|
||||
mapping.end = mapping.start - mapping.offset +
|
||||
c1 * mapping.s1 +
|
||||
c2 * mapping.s2 +
|
||||
c3 - mapping.offset;
|
||||
} else {
|
||||
mapping.end = mapping.start - mapping.offset +
|
||||
(mapping.alphabet.length - 1) * mapping.s1 +
|
||||
(mapping.alphabet.length - 1) * mapping.s2 +
|
||||
(mapping.alphabet.length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < numeric_mappings.length; ++i) {
|
||||
numeric_mappings[i].end = numeric_mappings[i].start + numeric_mappings[i].count - 1;
|
||||
}
|
||||
|
||||
function lookup(hexid) {
|
||||
var hexid = +("0x" + hexid);
|
||||
|
||||
reg = n_reg(hexid);
|
||||
if (reg)
|
||||
return reg;
|
||||
|
||||
reg = ja_reg(hexid);
|
||||
if (reg)
|
||||
return reg;
|
||||
|
||||
reg = hl_reg(hexid);
|
||||
if (reg)
|
||||
return reg;
|
||||
|
||||
reg = numeric_reg(hexid);
|
||||
if (reg)
|
||||
return reg;
|
||||
|
||||
reg = stride_reg(hexid);
|
||||
if (reg)
|
||||
return reg;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function stride_reg(hexid) {
|
||||
// try the mappings in stride_mappings
|
||||
var i;
|
||||
for (i = 0; i < stride_mappings.length; ++i) {
|
||||
var mapping = stride_mappings[i];
|
||||
if (hexid < mapping.start || hexid > mapping.end)
|
||||
continue;
|
||||
|
||||
var offset = hexid - mapping.start + mapping.offset;
|
||||
|
||||
var i1 = Math.floor(offset / mapping.s1);
|
||||
offset = offset % mapping.s1;
|
||||
var i2 = Math.floor(offset / mapping.s2);
|
||||
offset = offset % mapping.s2;
|
||||
var i3 = offset;
|
||||
|
||||
if (i1 < 0 || i1 >= mapping.alphabet.length ||
|
||||
i2 < 0 || i2 >= mapping.alphabet.length ||
|
||||
i3 < 0 || i3 >= mapping.alphabet.length)
|
||||
continue;
|
||||
|
||||
return mapping.prefix + mapping.alphabet.charAt(i1) + mapping.alphabet.charAt(i2) + mapping.alphabet.charAt(i3);
|
||||
}
|
||||
|
||||
// nothing
|
||||
return null;
|
||||
}
|
||||
|
||||
function numeric_reg(hexid) {
|
||||
// try the mappings in numeric_mappings
|
||||
var i;
|
||||
for (i = 0; i < numeric_mappings.length; ++i) {
|
||||
var mapping = numeric_mappings[i];
|
||||
if (hexid < mapping.start || hexid > mapping.end)
|
||||
continue;
|
||||
|
||||
var reg = (hexid - mapping.start + mapping.first) + "";
|
||||
return mapping.template.substring(0, mapping.template.length - reg.length) + reg;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// US N-numbers
|
||||
//
|
||||
|
||||
function n_letters(rem) {
|
||||
if (rem == 0)
|
||||
return "";
|
||||
|
||||
--rem;
|
||||
return limited_alphabet.charAt(Math.floor(rem / 25)) + n_letter(rem % 25);
|
||||
}
|
||||
|
||||
function n_letter(rem) {
|
||||
if (rem == 0)
|
||||
return "";
|
||||
|
||||
--rem;
|
||||
return limited_alphabet.charAt(rem);
|
||||
}
|
||||
|
||||
function n_reg(hexid) {
|
||||
var offset = hexid - 0xA00001;
|
||||
if (offset < 0 || offset >= 915399) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var digit1 = Math.floor(offset / 101711) + 1;
|
||||
var reg = "N" + digit1;
|
||||
offset = offset % 101711;
|
||||
if (offset <= 600) {
|
||||
// Na, NaA .. NaZ, NaAA .. NaZZ
|
||||
return reg + n_letters(offset);
|
||||
}
|
||||
|
||||
// Na0* .. Na9*
|
||||
offset -= 601;
|
||||
|
||||
var digit2 = Math.floor(offset / 10111);
|
||||
reg += digit2;
|
||||
offset = offset % 10111;
|
||||
|
||||
if (offset <= 600) {
|
||||
// Nab, NabA..NabZ, NabAA..NabZZ
|
||||
return reg + n_letters(offset);
|
||||
}
|
||||
|
||||
// Nab0* .. Nab9*
|
||||
offset -= 601;
|
||||
|
||||
var digit3 = Math.floor(offset / 951);
|
||||
reg += digit3;
|
||||
offset = offset % 951;
|
||||
|
||||
if (offset <= 600) {
|
||||
// Nabc, NabcA .. NabcZ, NabcAA .. NabcZZ
|
||||
return reg + n_letters(offset);
|
||||
}
|
||||
|
||||
// Nabc0* .. Nabc9*
|
||||
offset -= 601;
|
||||
|
||||
var digit4 = Math.floor(offset / 35);
|
||||
reg += digit4.toFixed(0);
|
||||
offset = offset % 35;
|
||||
|
||||
if (offset <= 24) {
|
||||
// Nabcd, NabcdA .. NabcdZ
|
||||
return reg + n_letter(offset);
|
||||
}
|
||||
|
||||
// Nabcd0 .. Nabcd9
|
||||
offset -= 25;
|
||||
return reg + offset.toFixed(0);
|
||||
}
|
||||
|
||||
// South Korea
|
||||
function hl_reg(hexid) {
|
||||
if (hexid >= 0x71BA00 && hexid <= 0x71bf99) {
|
||||
return "HL" + (hexid - 0x71BA00 + 0x7200).toString(16);
|
||||
}
|
||||
|
||||
if (hexid >= 0x71C000 && hexid <= 0x71C099) {
|
||||
return "HL" + (hexid - 0x71C000 + 0x8000).toString(16);
|
||||
}
|
||||
|
||||
if (hexid >= 0x71C200 && hexid <= 0x71C299) {
|
||||
return "HL" + (hexid - 0x71C200 + 0x8200).toString(16);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Japan
|
||||
function ja_reg(hexid) {
|
||||
var offset = hexid - 0x840000;
|
||||
if (offset < 0 || offset >= 229840)
|
||||
return null;
|
||||
|
||||
var reg = "JA";
|
||||
|
||||
var digit1 = Math.floor(offset / 22984);
|
||||
if (digit1 < 0 || digit1 > 9)
|
||||
return null;
|
||||
reg += digit1;
|
||||
offset = offset % 22984;
|
||||
|
||||
var digit2 = Math.floor(offset / 916);
|
||||
if (digit2 < 0 || digit2 > 9)
|
||||
return null;
|
||||
reg += digit2;
|
||||
offset = offset % 916;
|
||||
|
||||
if (offset < 340) {
|
||||
// 3rd is a digit, 4th is a digit or letter
|
||||
var digit3 = Math.floor(offset / 34);
|
||||
reg += digit3;
|
||||
offset = offset % 34;
|
||||
|
||||
if (offset < 10) {
|
||||
// 4th is a digit
|
||||
return reg + offset;
|
||||
}
|
||||
|
||||
// 4th is a letter
|
||||
offset -= 10;
|
||||
return reg + limited_alphabet.charAt(offset);
|
||||
}
|
||||
|
||||
// 3rd and 4th are letters
|
||||
offset -= 340;
|
||||
var letter3 = Math.floor(offset / 24);
|
||||
return reg + limited_alphabet.charAt(letter3) + limited_alphabet.charAt(offset % 24);
|
||||
}
|
||||
|
||||
return lookup;
|
||||
})();
|
Loading…
Reference in a new issue