mirror of
https://github.com/magicbug/Cloudlog
synced 2026-08-13 17:49:35 -04:00
Add/adjust known FT8/FT4 spot frequencies and tighten band mode detection ranges. New FT8/FT4 frequencies were added across multiple bands (160m, 80m, 30m, 20m, 17m, 15m, 12m, 10m, 6m, etc.). Mode boundary logic was refined for 160m, 80m, 60m (added), 40m, 6m, 4m, 2m and 70cm to better reflect common CW/DIGI/SSB allocations and specific FT8 spots. These changes improve automatic mode detection from frequency values.
193 lines
8 KiB
JavaScript
193 lines
8 KiB
JavaScript
/**
|
|
* DX Cluster shared utility functions.
|
|
* Used by the DX Cluster page (dxcluster/index.php) and the
|
|
* QSO entry DX Cluster tab (qso/index.php).
|
|
*
|
|
* Exposed as: DXCluster.isRbnSpot(), DXCluster.getBandFromFrequency(),
|
|
* DXCluster.detectModeFromFrequency(), DXCluster.detectMode()
|
|
*/
|
|
var DXCluster = (function () {
|
|
'use strict';
|
|
|
|
/**
|
|
* Returns true if the spotter callsign is an RBN (Reverse Beacon Network) skimmer.
|
|
* RBN skimmers always end with -# (literal hash character).
|
|
*/
|
|
function isRbnSpot(spotter) {
|
|
if (!spotter) return false;
|
|
return /\-#+$/.test(spotter.toString().trim());
|
|
}
|
|
|
|
/**
|
|
* Returns the amateur band name for a given frequency in kHz,
|
|
* or 'unknown' if it falls outside any recognised band.
|
|
*/
|
|
function getBandFromFrequency(freqKhz) {
|
|
var freq = parseFloat(freqKhz);
|
|
if (freq >= 1800 && freq <= 2000) return '160m';
|
|
if (freq >= 3500 && freq <= 4000) return '80m';
|
|
if (freq >= 5250 && freq <= 5450) return '60m';
|
|
if (freq >= 7000 && freq <= 7300) return '40m';
|
|
if (freq >= 10100 && freq <= 10150) return '30m';
|
|
if (freq >= 14000 && freq <= 14350) return '20m';
|
|
if (freq >= 18068 && freq <= 18168) return '17m';
|
|
if (freq >= 21000 && freq <= 21450) return '15m';
|
|
if (freq >= 24890 && freq <= 24990) return '12m';
|
|
if (freq >= 28000 && freq <= 29700) return '10m';
|
|
if (freq >= 50000 && freq <= 54000) return '6m';
|
|
if (freq >= 70000 && freq <= 71000) return '4m';
|
|
if (freq >= 144000 && freq <= 148000) return '2m';
|
|
if (freq >= 420000 && freq <= 450000) return '70cm';
|
|
if (freq >= 1240000 && freq <= 1300000) return '23cm';
|
|
if (freq >= 1300000) return 'ghz';
|
|
return 'unknown';
|
|
}
|
|
|
|
/**
|
|
* Estimates the operating mode from a frequency in kHz using:
|
|
* 1. Known FT8/FT4 spot frequencies (±2 kHz tolerance)
|
|
* 2. IARU Region 1 band-plan segments
|
|
* Returns 'cw', 'digi', or 'ssb'.
|
|
*/
|
|
function detectModeFromFrequency(freqKhz) {
|
|
// Known FT8 / FT4 spot frequencies (kHz)
|
|
var ft8ft4Freqs = [
|
|
1836, // FT8 160m
|
|
1840, // FT8 160m
|
|
1844, // FT4 160m
|
|
3567, // FT8 80m
|
|
3573, // FT8 80m
|
|
3575.5, // FT4 80m
|
|
5357, // FT8 60m
|
|
7047.5, // FT4 40m
|
|
7074, // FT8 40m
|
|
10130, // FT8 30m
|
|
10136, // FT8 30m
|
|
10140, // FT8 30m
|
|
14074, // FT8 20m
|
|
14080, // FT4 20m
|
|
14090, // FT8 20m
|
|
18095, // FT8 17m
|
|
18100, // FT8 17m
|
|
18104, // FT4 17m
|
|
21074, // FT8 15m
|
|
21090, // FT8 15m
|
|
21140, // FT4 15m
|
|
24911, // FT8 12m
|
|
24915, // FT8 12m
|
|
24919, // FT4 12m
|
|
28074, // FT8 10m
|
|
28090, // FT8 10m
|
|
28095, // FT8 10m
|
|
28180, // FT4 10m
|
|
50313, // FT8 6m
|
|
50318, // FT4 6m
|
|
50323, // FT8 6m
|
|
70154, // FT8 4m
|
|
144174, // FT8 2m
|
|
144170, // FT4 2m
|
|
432174 // FT8 70cm
|
|
];
|
|
var tolerance = 2; // kHz
|
|
for (var i = 0; i < ft8ft4Freqs.length; i++) {
|
|
if (Math.abs(freqKhz - ft8ft4Freqs[i]) <= tolerance) return 'digi';
|
|
}
|
|
|
|
// 160m
|
|
if (freqKhz >= 1800 && freqKhz < 1840) return 'cw';
|
|
if (freqKhz >= 1840 && freqKhz < 1843) return 'digi';
|
|
if (freqKhz >= 1843 && freqKhz <= 2000) return 'ssb';
|
|
// 80m
|
|
if (freqKhz >= 3500 && freqKhz < 3570) return 'cw';
|
|
if (freqKhz >= 3570 && freqKhz < 3600) return 'digi';
|
|
if (freqKhz >= 3600 && freqKhz <= 4000) return 'ssb';
|
|
// 60m
|
|
if (freqKhz >= 5351 && freqKhz < 5354) return 'cw';
|
|
if (freqKhz >= 5354 && freqKhz < 5358) return 'digi';
|
|
if (freqKhz >= 5358 && freqKhz <= 5366) return 'ssb';
|
|
// 40m
|
|
if (freqKhz >= 7000 && freqKhz < 7040) return 'cw';
|
|
if (freqKhz >= 7040 && freqKhz < 7060) return 'digi';
|
|
if (freqKhz >= 7060 && freqKhz <= 7300) return 'ssb';
|
|
// 30m — CW + digi only
|
|
if (freqKhz >= 10100 && freqKhz < 10130) return 'cw';
|
|
if (freqKhz >= 10130 && freqKhz <= 10150) return 'digi';
|
|
// 20m
|
|
if (freqKhz >= 14000 && freqKhz < 14070) return 'cw';
|
|
if (freqKhz >= 14070 && freqKhz < 14112) return 'digi';
|
|
if (freqKhz >= 14112 && freqKhz <= 14350) return 'ssb';
|
|
// 17m
|
|
if (freqKhz >= 18068 && freqKhz < 18095) return 'cw';
|
|
if (freqKhz >= 18095 && freqKhz < 18110) return 'digi';
|
|
if (freqKhz >= 18110 && freqKhz <= 18168) return 'ssb';
|
|
// 15m
|
|
if (freqKhz >= 21000 && freqKhz < 21070) return 'cw';
|
|
if (freqKhz >= 21070 && freqKhz < 21151) return 'digi';
|
|
if (freqKhz >= 21151 && freqKhz <= 21450) return 'ssb';
|
|
// 12m
|
|
if (freqKhz >= 24890 && freqKhz < 24915) return 'cw';
|
|
if (freqKhz >= 24915 && freqKhz < 24930) return 'digi';
|
|
if (freqKhz >= 24930 && freqKhz <= 24990) return 'ssb';
|
|
// 10m
|
|
if (freqKhz >= 28000 && freqKhz < 28070) return 'cw';
|
|
if (freqKhz >= 28070 && freqKhz < 28190) return 'digi';
|
|
if (freqKhz >= 28190 && freqKhz <= 29700) return 'ssb';
|
|
// 6m
|
|
if (freqKhz >= 50000 && freqKhz < 50100) return 'cw';
|
|
if (freqKhz >= 50100 && freqKhz < 50300) return 'ssb';
|
|
if (freqKhz >= 50300 && freqKhz <= 50500) return 'digi';
|
|
if (freqKhz > 50500 && freqKhz <= 54000) return 'ssb';
|
|
// 4m
|
|
if (freqKhz >= 70000 && freqKhz < 70100) return 'cw';
|
|
if (freqKhz >= 70100 && freqKhz < 70200) return 'digi';
|
|
if (freqKhz >= 70200 && freqKhz <= 70500) return 'ssb';
|
|
// 2m
|
|
if (freqKhz >= 144000 && freqKhz < 144173) return 'cw';
|
|
if (freqKhz >= 144170 && freqKhz < 144176) return 'digi';
|
|
if (freqKhz >= 144176 && freqKhz <= 148000) return 'ssb';
|
|
// 70cm
|
|
if (freqKhz >= 432000 && freqKhz < 432170) return 'cw';
|
|
if (freqKhz >= 432170 && freqKhz < 432175) return 'digi';
|
|
if (freqKhz >= 432175 && freqKhz <= 450000) return 'ssb';
|
|
// Other VHF/UHF/SHF — default to SSB
|
|
return 'ssb';
|
|
}
|
|
|
|
/**
|
|
* Detects the mode of a DX cluster spot.
|
|
* Priority: comment keywords → RBN skimmer → frequency band-plan.
|
|
* Returns 'cw', 'digi', or 'ssb'.
|
|
*/
|
|
function detectMode(spot) {
|
|
var comment = ((spot.comment || '') + '').toUpperCase();
|
|
|
|
// Digital modes — checked first so RTTY/FT8 etc. are not misclassified as CW/SSB
|
|
var digiKeywords = ['FT8', 'FT4', 'JS8CALL', 'JS8', 'WSPR', 'JT65', 'JT9',
|
|
'PSK31', 'PSK63', 'PSK', 'RTTY', 'BPSK', 'QPSK',
|
|
'OLIVIA', 'MFSK', 'MT63', 'FREEDV', 'WINLINK', 'VARA',
|
|
'PACKET', 'APRS', 'SSTV', 'DIGI', 'DIGITAL'];
|
|
for (var i = 0; i < digiKeywords.length; i++) {
|
|
if (comment.indexOf(digiKeywords[i]) !== -1) return 'digi';
|
|
}
|
|
|
|
if (comment.indexOf('CW') !== -1 || comment.indexOf('MORSE') !== -1) return 'cw';
|
|
|
|
if (comment.indexOf('SSB') !== -1 || comment.indexOf('LSB') !== -1 ||
|
|
comment.indexOf('USB') !== -1 || comment.indexOf(' AM ') !== -1 ||
|
|
comment.indexOf('PHONE') !== -1 || comment.indexOf('FM ') !== -1 ||
|
|
comment.indexOf(' FM') !== -1) return 'ssb';
|
|
|
|
// RBN skimmer spots are always CW
|
|
if (isRbnSpot(spot.spotter)) return 'cw';
|
|
|
|
// Fall back to frequency band-plan detection
|
|
return detectModeFromFrequency(parseFloat(spot.frequency));
|
|
}
|
|
|
|
return {
|
|
isRbnSpot: isRbnSpot,
|
|
getBandFromFrequency: getBandFromFrequency,
|
|
detectModeFromFrequency: detectModeFromFrequency,
|
|
detectMode: detectMode
|
|
};
|
|
}());
|