gridtracker/package.nw/lib/gt.js

14077 wiersze
407 KiB
JavaScript

// GridTracker ©2020 GridTracker.org
// All rights reserved.
// See LICENSE for more information.
var pjson = require("./package.json");
var gtVersion = parseInt(pjson.version.replace(/\./g, ""));
var gtBeta = pjson.betaVersion;
var g_startVersion = 0;
if (typeof localStorage.currentVersion != "undefined")
g_startVersion = localStorage.currentVersion;
if (
typeof localStorage.currentVersion == "undefined" ||
localStorage.currentVersion != String(gtVersion)
) {
localStorage.currentVersion = String(gtVersion);
var gui = require("nw.gui");
gui.App.clearCache();
}
var vers = String(gtVersion);
var gtShortVersion =
"v" +
vers.substr(0, 1) +
"." +
vers.substr(1, 2) +
"." +
vers.substr(3, 4) +
" " +
gtBeta;
var gtVersionString = "GridTracker " + gtShortVersion;
var g_windowName = "GT-main";
var os = require("os");
var fs = require("fs");
var g_platform = os.platform();
if (g_platform.indexOf("win") == 0 || g_platform.indexOf("Win") == 0) {
g_platform = "windows";
}
if (g_platform.indexOf("inux") > -1) g_platform = "linux";
if (g_platform.indexOf("darwin") > -1) g_platform = "mac";
var g_dirSeperator = "/";
if (g_platform == "windows") g_dirSeperator = "\\";
var gui = require("nw.gui");
var win = gui.Window.get();
var g_developerMode = process.versions["nw-flavor"] == "sdk";
var g_popupWindowHandle = null;
var g_callRosterWindowHandle = null;
var g_conditionsWindowHandle = null;
var g_chatWindowHandle = null;
var g_statsWindowHandle = null;
var g_lookupWindowHandle = null;
var g_baWindowHandle = null;
var g_appSettings = {};
var g_mapSettings = {};
var g_adifLogSettings = {};
var g_msgSettings = {};
var g_receptionSettings = {};
var g_receptionReports = {};
var g_N1MMSettings = {};
var g_log4OMSettings = {};
var g_dxkLogSettings = {};
var g_HRDLogbookLogSettings = {};
var g_acLogSettings = {};
var g_trustedQslSettings = {};
var g_callsignLookups = {};
var g_startupLogs = [];
var g_mapMemory = [];
var g_callsignDatabaseDXCC = {
291: true,
1: true,
6: true,
110: true,
202: true,
};
var g_callsignDatabaseUS = {
291: true,
6: true,
110: true,
};
var g_callsignDatabaseUSplus = {
291: true,
6: true,
110: true,
202: true,
};
function loadAllSettings() {
for (var x in localStorage) {
if (!validSettings.includes(x) && typeof localStorage[x] == "string") {
delete localStorage[x];
}
}
g_appSettings = loadDefaultsAndMerge("appSettings", def_appSettings);
g_mapSettings = loadDefaultsAndMerge("mapSettings", def_mapSettings);
g_adifLogSettings = loadDefaultsAndMerge(
"adifLogSettings",
def_adifLogSettings
);
g_msgSettings = loadDefaultsAndMerge("msgSettings", def_msgSettings);
g_receptionSettings = loadDefaultsAndMerge(
"receptionSettings",
def_receptionSettings
);
g_N1MMSettings = loadDefaultsAndMerge("N1MMSettings", def_N1MMSettings);
g_log4OMSettings = loadDefaultsAndMerge("log4OMSettings", def_log4OMSettings);
g_dxkLogSettings = loadDefaultsAndMerge("dxkLogSettings", def_dxkLogSettings);
g_HRDLogbookLogSettings = loadDefaultsAndMerge(
"HRDLogbookLogSettings",
def_HRDLogbookLogSettings
);
g_acLogSettings = loadDefaultsAndMerge("acLogSettings", def_acLogSettings);
g_trustedQslSettings = loadDefaultsAndMerge(
"trustedQslSettings",
def_trustedQslSettings
);
g_callsignLookups = loadDefaultsAndMerge(
"callsignLookups",
def_callsignLookups
);
g_bandActivity = loadDefaultsAndMerge("bandActivity", def_bandActivity);
g_startupLogs = loadArrayIfExists("startupLogs");
g_mapMemory = loadArrayIfExists("mapMemory");
if (g_mapMemory.length != 7) {
g_mapMemory = [];
for (var x = 0; x < 7; x++) {
g_mapMemory[x] = {};
g_mapMemory[x].zoom = -1;
g_mapMemory[x].LoLa = [0, 0];
}
g_appSettings.mapMemory = JSON.stringify(g_mapMemory);
}
}
loadAllSettings();
var myDEcall = g_appSettings.myDEcall;
var myDEGrid = g_appSettings.myDEGrid;
var myMode = g_appSettings.myMode;
var myBand = g_appSettings.myBand;
var myRawFreq = g_appSettings.myRawFreq;
var myRawCall = g_appSettings.myRawCall;
var myRawGrid = g_appSettings.myRawGrid;
var g_flightDuration = 30;
var g_crScript = g_appSettings.crScript;
var g_spotsEnabled = g_appSettings.spotsEnabled;
var g_heatEnabled = g_appSettings.heatEnabled;
var g_myLat = g_mapSettings.latitude;
var g_myLon = g_mapSettings.longitude;
function loadDefaultsAndMerge(key, def) {
var settings = {};
if (typeof localStorage[key] != "undefined") {
settings = JSON.parse(localStorage[key]);
}
var merged = deepmerge(def, settings);
for (var x in merged) {
if (!(x in def)) {
delete merged[x];
}
}
localStorage[key] = JSON.stringify(merged);
return merged;
}
function loadArrayIfExists(key) {
var data = [];
if (typeof localStorage[key] != "undefined") {
data = JSON.parse(localStorage[key]);
}
return data;
}
function loadObjectIfExists(key) {
var data = {};
if (typeof localStorage[key] != "undefined") {
data = JSON.parse(localStorage[key]);
}
return data;
}
function saveAppSettings() {
localStorage.appSettings = JSON.stringify(g_appSettings);
}
function saveMapSettings() {
localStorage.mapSettings = JSON.stringify(g_mapSettings);
}
function saveStartupLogs() {
localStorage.startupLogs = JSON.stringify(g_startupLogs);
}
function saveLogSettings() {
localStorage.adifLogSettings = JSON.stringify(g_adifLogSettings);
localStorage.N1MMSettings = JSON.stringify(g_N1MMSettings);
localStorage.log4OMSettings = JSON.stringify(g_log4OMSettings);
localStorage.dxkLogSettings = JSON.stringify(g_dxkLogSettings);
localStorage.HRDLogbookLogSettings = JSON.stringify(g_HRDLogbookLogSettings);
localStorage.acLogSettings = JSON.stringify(g_acLogSettings);
localStorage.trustedQslSettings = JSON.stringify(g_trustedQslSettings);
}
function saveAndCloseApp() {
g_closing = true;
saveReceptionReports();
try {
var data = {};
data.tracker = g_tracker;
for (var key in g_QSOhash) g_QSOhash[key].rect = null;
data.g_QSOhash = g_QSOhash;
data.version = gtVersion;
fs.writeFileSync(g_NWappData + "internal_qso.json", JSON.stringify(data));
} catch (e) {
console.log(e);
}
if (g_map) {
mapMemory(6, true, true);
g_mapSettings.zoom = g_map.getView().getZoom();
saveMapSettings();
}
if (g_wsjtUdpServer != null) {
try {
if (multicastEnable.checked == true && g_appSettings.wsjtIP != "") {
g_wsjtUdpServer.dropMembership(g_appSettings.wsjtIP);
}
g_wsjtUdpServer.close();
} catch (e) {
console.log(e);
}
}
if (g_forwardUdpServer != null) {
g_forwardUdpServer.close();
}
saveAppSettings();
saveMapSettings();
try {
if (g_callRosterWindowHandle) {
g_callRosterWindowHandle.window.writeRosterSettings();
}
if (g_popupWindowHandle != null) g_popupWindowHandle.window.close(true);
g_conditionsWindowHandle.window.close(true);
g_chatWindowHandle.window.close(true);
g_statsWindowHandle.window.close(true);
g_lookupWindowHandle.window.close(true);
g_baWindowHandle.window.close(true);
g_callRosterWindowHandle.window.close(true);
} catch (e) {}
nw.App.quit();
}
function clearAndReload() {
g_closing = true;
if (g_wsjtUdpServer != null) {
g_wsjtUdpServer.close();
g_wsjtUdpServer = null;
}
localStorage.clear();
chrome.runtime.reload();
}
{
win.hide();
win.on("close", function () {
saveAndCloseApp();
});
win.show();
win.setMinimumSize(200, 600);
}
var g_wsjtxProcessRunning = false;
var g_jtdxProcessRunning = false;
var g_wsjtxIni = Array();
var g_jtdxIni = Array();
var g_setNewUdpPortTimeoutHandle = null;
var g_map = null;
var g_menuShowing = true;
var g_closing = false;
var g_liveGrids = {};
var g_qsoGrids = {};
var g_liveCallsigns = {};
var g_lastCallsignCount = 0;
var g_flightPaths = Array();
var g_flightPathOffset = 0;
var g_flightPathLineDash = [9, 3, 3];
var g_flightPathTotal = (9 + 3 + 3) * 2;
var g_lastMessages = Array();
var g_lastTraffic = Array();
var g_showAllGrids = false;
var g_maps = Array();
var g_modes = {};
var g_modes_phone = {};
var g_colorBands = [
"OOB",
"4000m",
"2200m",
"630m",
"160m",
"80m",
"60m",
"40m",
"30m",
"20m",
"17m",
"15m",
"12m",
"11m",
"10m",
"6m",
"4m",
"2m",
"1.25m",
"70cm",
"23cm",
];
var g_pathIgnore = {};
g_pathIgnore["RU"] = true;
g_pathIgnore["FTRU"] = true;
g_pathIgnore["FD"] = true;
g_pathIgnore["TEST"] = true;
g_pathIgnore["DX"] = true;
g_pathIgnore["CQ"] = true;
var g_replaceCQ = {};
g_replaceCQ["ASIA"] = "AS";
var g_searchBand = "dummy";
var g_myDXCC = -1;
var g_QSOhash = {};
var g_QSLcount = 0;
var g_QSOcount = 0;
var g_ignoreMessages = 0;
var g_lastTimeSinceMessageInSeconds = timeNowSec();
var g_loadQSOs = false;
var g_fromDirectCallNoFileDialog = false;
var g_qsoWorkedBorderColor = "#222222FF";
var g_pushPinMode = false;
var g_pskBandActivityTimerHandle = null;
var g_workingIniPath = "";
var g_worldGeoData = {};
var g_prefixToMap = {};
var g_directCallToDXCC = {};
var g_dxccToAltName = {};
var g_dxccToADIFName = {};
var g_dxccToGeoData = {};
var g_gridToDXCC = {};
var g_gridToCQZone = {};
var g_gridToITUZone = {};
var g_gridToState = {};
var g_StateData = {};
var g_cqZones = {};
var g_wacZones = {};
var g_wasZones = {};
var g_ituZones = {};
var g_dxccCount = {};
var g_tracker = {};
initQSOdata();
function initQSOdata() {
g_tracker.worked = {};
g_tracker.confirmed = {};
g_tracker.worked.band = {};
g_tracker.worked.call = {};
g_tracker.worked.grid = {};
g_tracker.worked.dxcc = {};
g_tracker.worked.cqz = {};
g_tracker.worked.ituz = {};
g_tracker.worked.state = {};
g_tracker.worked.px = {};
g_tracker.worked.cnty = {};
g_tracker.worked.cont = {};
g_tracker.confirmed.band = {};
g_tracker.confirmed.call = {};
g_tracker.confirmed.grid = {};
g_tracker.confirmed.dxcc = {};
g_tracker.confirmed.cqz = {};
g_tracker.confirmed.ituz = {};
g_tracker.confirmed.state = {};
g_tracker.confirmed.px = {};
g_tracker.confirmed.cnty = {};
g_tracker.confirmed.cont = {};
}
var g_offlineLayer = null;
var g_mapsLayer = Array();
var g_tileLayer = null;
var g_mapControl = null;
var g_mapView = null;
var g_layerSources = {};
var g_layerVectors = {};
var g_scaleLine = null;
var g_scaleUnits = {};
g_scaleUnits["MI"] = "us";
g_scaleUnits["KM"] = "metric";
g_scaleUnits["NM"] = "nautical";
g_scaleUnits["DG"] = "degrees";
var g_passingToolTipTableString = "";
var g_mouseX = 0;
var g_mouseY = 0;
var g_appData = "";
var g_jsonDir = "";
var g_NWappData = "";
var g_screenshotDir = "";
var g_scriptDir = "";
var g_qsoLogFile = "";
var g_mediaDir = "";
var g_localeString = navigator.language;
var g_shapeFile = "./data/shapes.json";
var g_mapsFile = "./data/maps.json";
var g_voices = null;
var g_shapeData = {};
var g_countyData = {};
var g_zipToCounty = {};
var g_stateToCounty = {};
var g_cntyToCounty = {};
var g_us48Data = {};
var g_startupFunctions = Array();
var g_pskColors = {};
g_pskColors["OOB"] = "888888";
g_pskColors["4000m"] = "45E0FF";
g_pskColors["2200m"] = "FF4500";
g_pskColors["630m"] = "1E90FF";
g_pskColors["160m"] = "7CFC00";
g_pskColors["80m"] = "E550E5";
g_pskColors["60m"] = "0000FF";
g_pskColors["40m"] = "4949FF";
g_pskColors["30m"] = "62FF62";
g_pskColors["20m"] = "FFC40C";
g_pskColors["17m"] = "F2F261";
g_pskColors["15m"] = "CCA166";
g_pskColors["12m"] = "B22222";
g_pskColors["11m"] = "00FF00";
g_pskColors["10m"] = "FF69B4";
g_pskColors["6m"] = "FF0000";
g_pskColors["4m"] = "CC0044";
g_pskColors["2m"] = "FF1493";
g_pskColors["1.25m"] = "CCFF00";
g_pskColors["70cm"] = "999900";
g_pskColors["33cm"] = "009999";
g_pskColors["23cm"] = "5AB8C7";
var g_bandToColor = {};
var g_colorLeafletPins = {};
var g_colorLeafletQPins = {};
var g_UTCoptions = {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
timeZone: "UTC",
timeZoneName: "short",
};
var g_LocalOptions = {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
timeZoneName: "short",
};
var g_earthShadowImageArray = Array();
g_earthShadowImageArray[0] = "./img/shadow_on_32.png";
g_earthShadowImageArray[1] = "./img/shadow_off_32.png";
var g_gtFlagImageArray = Array();
g_gtFlagImageArray[2] = "./img/flag_on_freq.png";
g_gtFlagImageArray[1] = "./img/flag_on.png";
g_gtFlagImageArray[0] = "./img/flag_off.png";
var g_gtShareFlagImageArray = Array();
g_gtShareFlagImageArray[1] = "./img/share-on.png";
g_gtShareFlagImageArray[0] = "./img/share-off.png";
var g_mapImageArray = Array();
g_mapImageArray[1] = "./img/online_map.svg";
g_mapImageArray[0] = "./img/offline_map.svg";
var g_pinImageArray = Array();
g_pinImageArray[1] = "./img/red_pin_32.png";
g_pinImageArray[0] = "./img/gt_grid.png";
var g_qsoLockImageArray = Array();
g_qsoLockImageArray[0] = "./img/qso_unlocked_32.png";
g_qsoLockImageArray[1] = "./img/qso_locked_32.png";
var g_qslLockImageArray = Array();
g_qslLockImageArray[0] = "./img/qsl_unlocked_32.png";
g_qslLockImageArray[1] = "./img/qsl_locked_32.png";
var g_alertImageArray = Array();
g_alertImageArray[0] = "./img/unmuted-button.svg";
g_alertImageArray[1] = "./img/muted-button.svg";
var g_maidenheadModeImageArray = Array();
g_maidenheadModeImageArray[0] = "./img/mh4_32.png";
g_maidenheadModeImageArray[1] = "./img/mh6_32.png";
var g_gridViewArray = Array();
g_gridViewArray[1] = "Live";
g_gridViewArray[2] = "Logbook";
g_gridViewArray[3] = "Logbook &amp; Live";
var g_trophyImageArray = Array();
g_trophyImageArray[0] = "./img/blank_trophy.png";
g_trophyImageArray[1] = "./img/cq_trophy.png";
g_trophyImageArray[2] = "./img/itu_trophy.png";
g_trophyImageArray[3] = "./img/wac_trophy.png";
g_trophyImageArray[4] = "./img/was_trophy.png";
g_trophyImageArray[5] = "./img/dxcc_trophy.png";
g_trophyImageArray[6] = "./img/usc_trophy.png";
g_trophyImageArray[7] = "./img/us48_trophy.png";
var g_viewInfo = {};
g_viewInfo[0] = ["g_qsoGrids", "Grids", 0, 0, 0];
g_viewInfo[1] = ["g_cqZones", "CQ Zones", 0, 0, 40];
g_viewInfo[2] = ["g_ituZones", "ITU Zones", 0, 0, 90];
g_viewInfo[3] = ["g_wacZones", "Continents", 0, 0, 7];
g_viewInfo[4] = ["g_wasZones", "US States", 0, 0, 50];
g_viewInfo[5] = ["g_worldGeoData", "DXCCs", 0, 0, 340];
g_viewInfo[6] = ["g_countyData", "US Counties", 0, 0, 3220];
g_viewInfo[7] = ["g_us48Data", "US Continental Grids", 0, 0, 488];
var g_soundCard = g_appSettings.soundCard;
var g_gridAlpha = "88";
if (typeof g_mapMemory[6] == "undefined") g_mapMemory[6] = g_mapMemory[0];
function qsoBackupFileInit() {
var adifHeader = "GridTracker v" + gtVersion + " <EOH>\r\n";
if (!fs.existsSync(g_qsoLogFile)) {
fs.writeFileSync(g_qsoLogFile, adifHeader);
}
}
function gtBandFilterChanged(selector) {
g_appSettings.gtBandFilter = selector.value;
removePaths();
redrawGrids();
redrawSpots();
}
function gtModeFilterChanged(selector) {
g_appSettings.gtModeFilter = selector.value;
redrawGrids();
redrawSpots();
}
function gtPropFilterChanged(selector) {
g_appSettings.gtPropFilter = selector.value;
redrawGrids();
redrawSpots();
}
function setBandAndModeToAuto() {
g_appSettings.gtModeFilter = g_appSettings.gtBandFilter = gtBandFilter.value = gtModeFilter.value =
"auto";
redrawGrids();
redrawSpots();
}
function hideLiveGrid(i) {
if (g_layerSources["live"].hasFeature(g_liveGrids[i].rectangle)) {
g_layerSources["live"].removeFeature(g_liveGrids[i].rectangle);
}
}
function liveTriangleGrid(i) {
if (g_liveGrids[i].isTriangle == false) {
if (g_layerSources["live"].hasFeature(g_liveGrids[i].rectangle)) {
g_layerSources["live"].removeFeature(g_liveGrids[i].rectangle);
}
gridToTriangle(i, g_liveGrids[i].rectangle, false);
g_liveGrids[i].isTriangle = true;
g_layerSources["live"].addFeature(g_liveGrids[i].rectangle);
}
}
function qsoTriangleGrid(i) {
if (g_qsoGrids[i].isTriangle == false) {
if (g_layerSources["qso"].hasFeature(g_qsoGrids[i].rectangle)) {
g_layerSources["qso"].removeFeature(g_qsoGrids[i].rectangle);
}
gridToTriangle(i, g_qsoGrids[i].rectangle, true);
g_qsoGrids[i].isTriangle = true;
g_layerSources["qso"].addFeature(g_qsoGrids[i].rectangle);
}
}
function setGridViewMode(mode) {
g_appSettings.gridViewMode = mode;
gridViewButton.innerHTML = g_gridViewArray[g_appSettings.gridViewMode];
redrawGrids();
goProcessRoster();
}
function cycleGridView() {
var mode = g_appSettings.gridViewMode;
mode++;
if (mode > 3) mode = 1;
if (mode < 1) mode = 1;
g_appSettings.gridViewMode = mode;
gridViewButton.innerHTML = g_gridViewArray[g_appSettings.gridViewMode];
redrawGrids();
}
function toggleEarth() {
g_appSettings.earthImgSrc ^= 1;
earthImg.src = g_earthShadowImageArray[g_appSettings.earthImgSrc];
if (g_appSettings.earthImgSrc == 1) {
dayNight.hide();
g_nightTime = dayNight.refresh();
} else {
g_nightTime = dayNight.refresh();
dayNight.show();
}
changeMapLayer();
}
function toggleOffline() {
if (g_map == null) return;
if (g_mapSettings.offlineMode == true) {
g_mapSettings.offlineMode = false;
offlineImg.src = g_mapImageArray[1];
conditionsButton.style.display = "inline-block";
gtFlagButton.style.display = "inline-block";
gtShareButton.style.display = "inline-block";
buttonStrikesDiv.style.display = "inline-block";
buttonPSKSpotsBoxDiv.style.display = "inline-block";
donateButton.style.display = "inline-block";
if (g_appSettings.gtShareEnable == true) {
gtFlagButton.style.display = "inline-block";
if (g_appSettings.gtMsgEnable == true)
msgButton.style.display = "inline-block";
else msgButton.style.display = "none";
} else {
msgButton.style.display = "none";
gtFlagButton.style.display = "none";
}
for (var key in g_adifLogSettings.menu) {
var value = g_adifLogSettings.menu[key];
var where = key + "Div";
document.getElementById(key).checked = value;
if (value == true) {
document.getElementById(where).style.display = "inline-block";
} else {
document.getElementById(where).style.display = "none";
}
}
pskReporterBandActivityDiv.style.display = "block";
} else {
g_mapSettings.offlineMode = true;
offlineImg.src = g_mapImageArray[0];
conditionsButton.style.display = "none";
buttonPsk24CheckBoxDiv.style.display = "none";
buttonQRZCheckBoxDiv.style.display = "none";
buttonLOTWCheckBoxDiv.style.display = "none";
buttonClubCheckBoxDiv.style.display = "none";
gtFlagButton.style.display = "none";
pskReporterBandActivityDiv.style.display = "none";
gtShareButton.style.display = "none";
msgButton.style.display = "none";
donateButton.style.display = "none";
buttonStrikesDiv.style.display = "none";
buttonPSKSpotsBoxDiv.style.display = "none";
setGtShareButtons();
}
loadMapSettings();
changeMapValues();
}
function ignoreMessagesToggle() {
g_ignoreMessages ^= 1;
if (g_ignoreMessages == 0) {
txrxdec.style.backgroundColor = "Green";
txrxdec.style.borderColor = "GreenYellow";
txrxdec.innerHTML = "RECEIVE";
txrxdec.title = "Click to ignore incoming messages";
} else {
txrxdec.style.backgroundColor = "DimGray";
txrxdec.style.borderColor = "DarkGray";
txrxdec.innerHTML = "IGNORE";
txrxdec.title = "Click to resume reading messages";
}
}
function toggleTime() {
g_appSettings.useLocalTime ^= 1;
displayTime();
}
function dateToString(dateTime) {
if (g_appSettings.useLocalTime == 1)
return dateTime.toLocaleString().replace(/,/g, "");
else return dateTime.toUTCString().replace(/GMT/g, "UTC").replace(/,/g, "");
}
function userDayString(Msec) {
var dateTime;
if (Msec != null) dateTime = new Date(Msec);
else dateTime = new Date();
var ds = dateTime.toUTCString().replace(/GMT/g, "UTC").replace(/,/g, "");
var dra = ds.split(" ");
dra.shift();
dra.pop();
dra.pop();
return dra.join(" ");
}
function userTimeString(Msec) {
var dateTime;
if (Msec != null) dateTime = new Date(Msec);
else dateTime = new Date();
return dateToString(dateTime);
}
function getWpx(callsign) {
var prefix = null;
if (callsign.includes("/"))
// Handle in the future?
return null;
if (!/\d/.test(callsign))
// Insert 0, never seen this
return null;
var end = callsign.length;
var foundPrefix = false;
var prefixEnd = 1;
while (prefixEnd != end) {
if (/\d/.test(callsign.charAt(prefixEnd))) {
while (prefixEnd + 1 != end && /\d/.test(callsign.charAt(prefixEnd + 1)))
prefixEnd++;
foundPrefix = true;
break;
}
prefixEnd++;
}
if (foundPrefix) prefix = callsign.substr(0, prefixEnd + 1);
return prefix;
}
function setState(details) {
if (details.state != null && details.state.length > 0) {
var isDigi = details.digital;
if (details.state.substr(0, 2) != "US")
details.state = "US-" + details.state;
g_tracker.worked.state[details.state + details.band + details.mode] = true;
g_tracker.worked.state[details.state] = true;
g_tracker.worked.state[details.state + details.mode] = true;
g_tracker.worked.state[details.state + details.band] = true;
if (isDigi) {
g_tracker.worked.state[details.state + "dg"] = true;
g_tracker.worked.state[details.state + details.band + "dg"] = true;
}
if (details.confirmed) {
g_tracker.confirmed.state[
details.state + details.band + details.mode
] = true;
g_tracker.confirmed.state[details.state] = true;
g_tracker.confirmed.state[details.state + details.mode] = true;
g_tracker.confirmed.state[details.state + details.band] = true;
if (isDigi) {
g_tracker.confirmed.state[details.state + "dg"] = true;
g_tracker.confirmed.state[details.state + details.band + "dg"] = true;
}
}
}
if (details.cnty != null && details.cnty.length > 0) {
var isDigi = details.digital;
g_tracker.worked.cnty[details.cnty + details.band + details.mode] = true;
g_tracker.worked.cnty[details.cnty] = true;
g_tracker.worked.cnty[details.cnty + details.mode] = true;
g_tracker.worked.cnty[details.cnty + details.band] = true;
if (isDigi) {
g_tracker.worked.cnty[details.cnty + "dg"] = true;
g_tracker.worked.cnty[details.cnty + details.band + "dg"] = true;
}
if (details.confirmed) {
g_tracker.confirmed.cnty[
details.cnty + details.band + details.mode
] = true;
g_tracker.confirmed.cnty[details.cnty] = true;
g_tracker.confirmed.cnty[details.cnty + details.mode] = true;
g_tracker.confirmed.cnty[details.cnty + details.band] = true;
if (isDigi) {
g_tracker.confirmed.cnty[details.cnty + "dg"] = true;
g_tracker.confirmed.cnty[details.cnty + details.band + "dg"] = true;
}
}
}
}
function isKnownCallsignDXCC(dxcc) {
if (dxcc in g_callsignDatabaseDXCC) return true;
return false;
}
function isKnownCallsignUS(dxcc) {
if (dxcc in g_callsignDatabaseUS) return true;
return false;
}
function isKnownCallsignUSplus(dxcc) {
if (dxcc in g_callsignDatabaseUSplus) return true;
return false;
}
function addDeDx(
finalGrid,
finalDXcall,
cq,
cqdx,
locked,
finalDEcall,
finalRSTsent,
finalTime,
ifinalMsg,
mode,
band,
confirmed,
notQso,
finalRSTrecv,
finalDxcc,
finalState,
finalCont,
finalCnty,
finalCqZone,
finalItuZone,
finalVucc = [],
finalPropMode = "",
finalDigital = false,
finalPhone = false,
finalIOTA = "",
finalSatName = ""
) {
var callsign = null;
var rect = null;
var worked = false;
var didConfirm = false;
var wspr = mode == "WSPR" ? parseInt(band) * 2 : null;
var hash = "";
var finalMsg = ifinalMsg.trim();
if (finalMsg.length > 40) finalMsg = finalMsg.substring(0, 40) + "...";
var details = null;
if (!notQso) {
var timeMod = finalTime - (finalTime % 360) + 180;
hash = unique(mode + band + finalDXcall + timeMod);
var lookupCall = false;
if (hash in g_QSOhash) {
details = g_QSOhash[hash];
if (finalGrid.length > 0 && finalGrid != details.grid) {
// only touch the grid if it's larger than the last grid && the 4wide is the same
if (
details.grid.length < 6 &&
(details.grid.substr(0, 4) == finalGrid.substr(0, 4) ||
details.grid.length == 0)
)
details.grid = finalGrid;
}
if (finalRSTsent.length > 0) details.RSTsent = finalRSTsent;
if (finalRSTrecv.length > 0) details.RSTrecv = finalRSTrecv;
if (finalCqZone.length > 0) details.cqz = finalCqZone;
if (finalItuZone.length > 0) details.ituz = finalItuZone;
if (finalState != null) details.state = finalState;
if (finalState == null && details.state) finalState = details.state;
if (finalDxcc < 1 && details.dxcc > 0) finalDxcc = details.dxcc;
if (finalCont == null && details.cont) finalCont = details.cont;
if (finalCnty == null && details.cnty) finalCnty = details.cnty;
if (finalPropMode.length > 0) details.propMode = finalPropMode;
if (finalVucc.length > 0) details.vucc_grids = finalVucc;
if (finalIOTA.length > 0) details.IOTA = finalIOTA;
if (finalSatName.length > 0) details.satName = finalSatName;
} else {
details = {};
details.grid = finalGrid;
details.RSTsent = finalRSTsent;
details.RSTrecv = finalRSTrecv;
details.msg = "-";
details.band = band;
details.mode = mode;
details.DEcall = finalDXcall;
details.DXcall = finalDEcall;
details.cqz = finalCqZone;
details.ituz = finalItuZone;
details.delta = -1;
details.time = finalTime;
details.state = finalState;
details.zipcode = null;
details.qso = true;
details.px = null;
details.zone = null;
details.cont = null;
details.vucc_grids = finalVucc;
details.propMode = finalPropMode;
details.digital = finalDigital;
details.phone = finalPhone;
details.IOTA = finalIOTA;
details.satName = finalSatName;
}
if (finalDxcc < 1) finalDxcc = callsignToDxcc(finalDXcall);
details.dxcc = finalDxcc;
if (details.dxcc > 0 && details.px == null) {
details.px = getWpx(finalDXcall);
if (details.px)
details.zone = Number(details.px.charAt(details.px.length - 1));
}
if (
details.state == null &&
isKnownCallsignUSplus(finalDxcc) &&
finalGrid.length > 0
) {
var fourGrid = finalGrid.substr(0, 4);
if (fourGrid in g_gridToState && g_gridToState[fourGrid].length == 1) {
details.state = g_gridToState[fourGrid][0];
}
lookupCall = true;
}
details.cont = finalCont;
if (details.cont == null && finalDxcc > 0) {
details.cont = g_worldGeoData[g_dxccToGeoData[finalDxcc]].continent;
if (details.dxcc == 390 && details.zone == 1) details.cont = "EU";
}
details.cnty = finalCnty;
if (details.cnty) {
details.qual = true;
}
if (isKnownCallsignUSplus(finalDxcc)) {
if (details.cnty == null) {
lookupCall = true;
} else {
if (!(details.cnty in g_cntyToCounty)) {
lookupCall = true;
}
}
}
var isDigi = details.digital;
var isPhone = details.phone;
details.wspr = wspr;
if (finalMsg.length > 0) details.msg = finalMsg;
g_tracker.worked.call[finalDXcall + band + mode] = true;
g_tracker.worked.call[finalDXcall] = true;
g_tracker.worked.call[finalDXcall + mode] = true;
g_tracker.worked.call[finalDXcall + band] = true;
if (isDigi == true) {
g_tracker.worked.call[finalDXcall + "dg"] = true;
g_tracker.worked.call[finalDXcall + band + "dg"] = true;
}
var fourGrid = details.grid.substr(0, 4);
if (fourGrid != "") {
g_tracker.worked.grid[fourGrid + band + mode] = true;
g_tracker.worked.grid[fourGrid] = true;
g_tracker.worked.grid[fourGrid + mode] = true;
g_tracker.worked.grid[fourGrid + band] = true;
if (isDigi == true) {
g_tracker.worked.grid[fourGrid + "dg"] = true;
g_tracker.worked.grid[fourGrid + band + "dg"] = true;
}
}
if (
details.ituz.length == 0 &&
fourGrid in g_gridToITUZone &&
g_gridToITUZone[fourGrid].length == 1
) {
details.ituz = g_gridToITUZone[fourGrid][0];
}
if (details.ituz.length > 0) {
g_tracker.worked.ituz[details.ituz + band + mode] = true;
g_tracker.worked.ituz[details.ituz] = true;
g_tracker.worked.ituz[details.ituz + mode] = true;
g_tracker.worked.ituz[details.ituz + band] = true;
if (isDigi == true) {
g_tracker.worked.ituz[details.ituz + "dg"] = true;
g_tracker.worked.ituz[details.ituz + band + "dg"] = true;
}
}
if (
details.cqz.length == 0 &&
fourGrid in g_gridToCQZone &&
g_gridToCQZone[fourGrid].length == 1
) {
details.cqz = g_gridToCQZone[fourGrid][0];
}
if (details.cqz.length > 0) {
g_tracker.worked.cqz[details.cqz + band + mode] = true;
g_tracker.worked.cqz[details.cqz] = true;
g_tracker.worked.cqz[details.cqz + mode] = true;
g_tracker.worked.cqz[details.cqz + band] = true;
if (isDigi == true) {
g_tracker.worked.cqz[details.cqz + "dg"] = true;
g_tracker.worked.cqz[details.cqz + band + "dg"] = true;
}
}
if (details.dxcc > 0) {
var sDXCC = String(details.dxcc);
g_tracker.worked.dxcc[sDXCC + band + mode] = true;
g_tracker.worked.dxcc[sDXCC] = true;
g_tracker.worked.dxcc[sDXCC + mode] = true;
g_tracker.worked.dxcc[sDXCC + band] = true;
if (isDigi == true) {
g_tracker.worked.dxcc[sDXCC + "dg"] = true;
g_tracker.worked.dxcc[sDXCC + band + "dg"] = true;
}
}
if (details.px) {
g_tracker.worked.px[details.px + band + mode] = true;
g_tracker.worked.px[details.px] = hash;
g_tracker.worked.px[details.px + mode] = true;
g_tracker.worked.px[details.px + band] = true;
if (isDigi == true) {
g_tracker.worked.px[details.px + "dg"] = true;
g_tracker.worked.px[details.px + band + "dg"] = true;
}
if (isPhone == true) {
g_tracker.worked.px[details.px + "ph"] = true;
g_tracker.worked.px[details.px + band + "ph"] = true;
}
}
if (details.cont) {
g_tracker.worked.cont[details.cont + band + mode] = true;
g_tracker.worked.cont[details.cont] = hash;
g_tracker.worked.cont[details.cont + mode] = true;
g_tracker.worked.cont[details.cont + band] = true;
if (isDigi == true) {
g_tracker.worked.cont[details.cont + "dg"] = true;
g_tracker.worked.cont[details.cont + band + "dg"] = true;
}
if (isPhone == true) {
g_tracker.worked.cont[details.cont + "ph"] = true;
g_tracker.worked.cont[details.cont + band + "ph"] = true;
}
}
worked = true;
locked = true;
details.worked = worked;
if (typeof details.confirmed == "undefined" || details.confirmed == false) {
details.confirmed = confirmed;
}
g_QSOhash[hash] = details;
setState(details);
if (lookupCall) {
if (g_callsignLookups.ulsUseEnable) {
lookupUsCallsign(details, true);
}
}
if (confirmed == true) {
if (fourGrid != "") {
g_tracker.confirmed.grid[fourGrid + band + mode] = true;
g_tracker.confirmed.grid[fourGrid] = true;
g_tracker.confirmed.grid[fourGrid + mode] = true;
g_tracker.confirmed.grid[fourGrid + band] = true;
if (isDigi == true) {
g_tracker.confirmed.grid[fourGrid + "dg"] = true;
g_tracker.confirmed.grid[fourGrid + band + "dg"] = true;
}
}
if (details.ituz.length > 0) {
g_tracker.confirmed.ituz[details.ituz + band + mode] = true;
g_tracker.confirmed.ituz[details.ituz] = true;
g_tracker.confirmed.ituz[details.ituz + mode] = true;
g_tracker.confirmed.ituz[details.ituz + band] = true;
if (isDigi == true) {
g_tracker.confirmed.ituz[details.ituz + "dg"] = true;
g_tracker.confirmed.ituz[details.ituz + band + "dg"] = true;
}
}
if (details.cqz.length > 0) {
g_tracker.confirmed.cqz[details.cqz + band + mode] = true;
g_tracker.confirmed.cqz[details.cqz] = true;
g_tracker.confirmed.cqz[details.cqz + mode] = true;
g_tracker.confirmed.cqz[details.cqz + band] = true;
if (isDigi == true) {
g_tracker.confirmed.cqz[details.cqz + "dg"] = true;
g_tracker.confirmed.cqz[details.cqz + band + "dg"] = true;
}
}
if (details.dxcc > 0) {
var sDXCC = String(details.dxcc);
g_tracker.confirmed.dxcc[sDXCC + band + mode] = true;
g_tracker.confirmed.dxcc[sDXCC] = true;
g_tracker.confirmed.dxcc[sDXCC + mode] = true;
g_tracker.confirmed.dxcc[sDXCC + band] = true;
if (isDigi == true) {
g_tracker.confirmed.dxcc[sDXCC + "dg"] = true;
g_tracker.confirmed.dxcc[sDXCC + band + "dg"] = true;
}
}
if (details.px) {
g_tracker.confirmed.px[details.px + band + mode] = true;
g_tracker.confirmed.px[details.px] = hash;
g_tracker.confirmed.px[details.px + mode] = true;
g_tracker.confirmed.px[details.px + band] = true;
if (isDigi == true) {
g_tracker.confirmed.px[details.px + "dg"] = true;
g_tracker.confirmed.px[details.px + band + "dg"] = true;
}
}
if (details.cont) {
g_tracker.confirmed.cont[details.cont + band + mode] = true;
g_tracker.confirmed.cont[details.cont] = hash;
g_tracker.confirmed.cont[details.cont + mode] = true;
g_tracker.confirmed.cont[details.cont + band] = true;
if (isDigi == true) {
g_tracker.confirmed.cont[details.cont + "dg"] = true;
g_tracker.confirmed.cont[details.cont + band + "dg"] = true;
}
}
g_tracker.confirmed.call[finalDXcall + band + mode] = true;
g_tracker.confirmed.call[finalDXcall] = true;
g_tracker.confirmed.call[finalDXcall + mode] = true;
g_tracker.confirmed.call[finalDXcall + band] = true;
if (isDigi == true) {
g_tracker.confirmed.call[finalDXcall + "dg"] = true;
g_tracker.confirmed.call[finalDXcall + band + "dg"] = true;
}
didConfirm = true;
}
}
if (finalDxcc < 1) finalDxcc = callsignToDxcc(finalDXcall);
hash = finalDXcall + band + mode;
if (notQso) {
if (hash in g_liveCallsigns) callsign = g_liveCallsigns[hash];
}
if (!notQso) {
if (
(g_appSettings.gtBandFilter.length == 0 ||
(g_appSettings.gtBandFilter == "auto"
? myBand == band
: g_appSettings.gtBandFilter == band)) &&
validateMapMode(mode) &&
validatePropMode(finalPropMode)
) {
details.rect = qthToQsoBox(
finalGrid,
hash,
cq,
cqdx,
locked,
finalDEcall,
worked,
didConfirm,
band,
wspr
);
}
return;
} else {
if (finalDxcc in g_dxccCount) g_dxccCount[finalDxcc]++;
else g_dxccCount[finalDxcc] = 1;
if (
(g_appSettings.gtBandFilter.length == 0 ||
(g_appSettings.gtBandFilter == "auto"
? myBand == band
: g_appSettings.gtBandFilter == band)) &&
validateMapMode(mode)
) {
rect = qthToBox(
finalGrid,
finalDXcall,
cq,
cqdx,
locked,
finalDEcall,
band,
wspr,
hash
);
}
}
if (callsign == null) {
var newCallsign = {};
newCallsign.DEcall = finalDXcall;
newCallsign.grid = finalGrid;
newCallsign.mode = mode;
newCallsign.band = band;
newCallsign.msg = finalMsg;
newCallsign.dxcc = finalDxcc;
newCallsign.worked = false;
newCallsign.confirmed = false;
newCallsign.RSTsent = "-";
newCallsign.RSTrecv = "-";
newCallsign.dt = 0.0;
newCallsign.qso = false;
newCallsign.distance = 0;
newCallsign.px = null;
newCallsign.zone = null;
newCallsign.cnty = finalCnty;
newCallsign.cont = finalCont;
if (finalDxcc > -1) {
newCallsign.px = getWpx(finalDXcall);
if (newCallsign.px)
newCallsign.zone = Number(
newCallsign.px.charAt(newCallsign.px.length - 1)
);
if (newCallsign.cont == null) {
newCallsign.cont = g_worldGeoData[g_dxccToGeoData[finalDxcc]].continent;
if (newCallsign.dxcc == 390 && newCallsign.zone == 1)
newCallsign.cont = "EU";
}
}
if (finalRSTsent != null) {
newCallsign.RSTsent = finalRSTsent;
}
if (finalRSTrecv != null) {
newCallsign.RSTrecv = finalRSTrecv;
}
newCallsign.time = finalTime;
newCallsign.delta = -1;
newCallsign.DXcall = finalDEcall;
newCallsign.rect = rect;
newCallsign.wspr = wspr;
newCallsign.state = finalState;
newCallsign.alerted = false;
newCallsign.instance = null;
newCallsign.shouldAlert = false;
newCallsign.zipcode = null;
newCallsign.qrz = false;
newCallsign.vucc_grids = [];
newCallsign.propMode = "";
newCallsign.digital = finalDigital;
newCallsign.phone = finalPhone;
newCallsign.IOTA = finalIOTA;
newCallsign.satName = finalSatName;
if (
newCallsign.state == null &&
isKnownCallsignDXCC(finalDxcc) &&
finalGrid.length > 0
) {
if (g_callsignLookups.ulsUseEnable) {
lookupUsCallsign(newCallsign);
}
if (newCallsign.state == null && isKnownCallsignUSplus(finalDxcc)) {
var fourGrid = finalGrid.substr(0, 4);
if (
fourGrid in g_gridToState &&
g_gridToState[finalGrid.substr(0, 4)].length == 1
) {
newCallsign.state = g_gridToState[finalGrid.substr(0, 4)][0];
}
}
}
g_liveCallsigns[hash] = newCallsign;
} else {
if (callsign.DXcall != "Self" && finalTime > callsign.time) {
callsign.time = finalTime;
callsign.mode = mode;
callsign.band = band;
callsign.delta = -1;
callsign.DXcall = finalDEcall;
callsign.msg = finalMsg;
callsign.rect = rect;
callsign.dxcc = finalDxcc;
callsign.wspr = wspr;
if (finalGrid.length > callsign.grid.length) callsign.grid = finalGrid;
if (
finalGrid.length == callsign.grid.length &&
finalGrid != callsign.grid
)
callsign.grid = finalGrid;
if (finalRSTsent != null) callsign.RSTsent = finalRSTsent;
if (finalRSTrecv != null) callsign.RSTrecv = finalRSTrecv;
callsign.vucc_grids = [];
callsign.propMode = "";
callsign.digital = finalDigital;
callsign.phone = finalPhone;
callsign.IOTA = finalIOTA;
callsign.satName = finalSatName;
}
}
}
function timeoutSetUdpPort() {
g_appSettings.wsjtUdpPort = udpPortInput.value;
lastMsgTimeDiv.innerHTML = "Waiting for msg...";
g_setNewUdpPortTimeoutHandle = null;
}
function setUdpPort() {
if (g_setNewUdpPortTimeoutHandle != null)
window.clearTimeout(g_setNewUdpPortTimeoutHandle);
lastMsgTimeDiv.innerHTML = "..setting..";
g_setNewUdpPortTimeoutHandle = window.setTimeout(timeoutSetUdpPort, 1000);
}
function changeGridDecay() {
g_appSettings.gridsquareDecayTime = parseInt(gridDecay.value);
decayRateTd.innerHTML =
Number(g_appSettings.gridsquareDecayTime) == 0
? "<I>No Decay</I>"
: Number(g_appSettings.gridsquareDecayTime).toDHMS();
}
function changeMouseOverValue() {
g_mapSettings.mouseOver = mouseOverValue.checked;
saveMapSettings();
}
function changeMergeOverlayValue() {
g_mapSettings.mergeOverlay = mergeOverlayValue.checked;
saveMapSettings();
setTrophyOverlay(g_currentOverlay);
}
function getPathColor() {
if (g_mapSettings.nightMapEnable && g_nightTime) {
if (g_mapSettings.nightPathColor == 0) return "#000";
if (g_mapSettings.nightPathColor == 361) return "#FFF";
return "hsl(" + g_mapSettings.nightPathColor + ", 100%, 50%)";
} else {
if (g_mapSettings.pathColor == 0) return "#000";
if (g_mapSettings.pathColor == 361) return "#FFF";
return "hsl(" + g_mapSettings.pathColor + ", 100%, 50%)";
}
}
function getQrzPathColor() {
if (g_mapSettings.nightMapEnable && g_nightTime) {
if (g_mapSettings.nightQrzPathColor == 0) return "#000";
if (g_mapSettings.nightQrzPathColor == 361) return "#FFF";
return "hsl(" + g_mapSettings.nightQrzPathColor + ", 100%, 50%)";
} else {
if (g_mapSettings.qrzPathColor == 0) return "#000";
if (g_mapSettings.qrzPathColor == 361) return "#FFF";
return "hsl(" + g_mapSettings.qrzPathColor + ", 100%, 50%)";
}
}
function changeShadow() {
g_mapSettings.shadow = shadowValue.value;
showDarknessTd.innerHTML = parseInt(shadowValue.value * 100) + "%";
saveMapSettings();
g_nightTime = dayNight.refresh();
}
function changePathWidth() {
g_appSettings.pathWidthWeight = pathWidthValue.value;
g_appSettings.qrzPathWidthWeight = qrzPathWidthValue.value;
pathWidthTd.innerHTML = pathWidthValue.value;
qrzPathWidthTd.innerHTML = qrzPathWidthValue.value;
for (var i = g_flightPaths.length - 1; i >= 0; i--) {
var featureStyle = g_flightPaths[i].getStyle();
var featureStroke = featureStyle.getStroke();
var color = g_flightPaths[i].isQRZ ? getQrzPathColor() : getPathColor();
var width = g_flightPaths[i].isQRZ
? qrzPathWidthValue.value
: pathWidthValue.value;
if (width == 0) {
if (typeof g_flightPaths[i].Arrow != "undefined")
g_layerSources["flight"].removeFeature(g_flightPaths[i].Arrow);
g_layerSources["flight"].removeFeature(g_flightPaths[i]);
delete g_flightPaths[i];
g_flightPaths[i] = null;
g_flightPaths.splice(i, 1);
continue;
}
featureStroke.setWidth(width);
if (g_flightPaths[i].isShapeFlight == 0) featureStroke.setColor(color);
featureStyle.setStroke(featureStroke);
g_flightPaths[i].setStyle(featureStyle);
if (typeof g_flightPaths[i].Arrow != "undefined") {
var stroke = new ol.style.Stroke({
color: color,
width: width,
});
var thisStle = new ol.style.Style({
image: new ol.style.Circle({
stroke: stroke,
radius: 3,
}),
});
g_flightPaths[i].Arrow.setStyle(thisStle);
}
}
if (g_transmitFlightPath != null) {
var featureStyle = g_transmitFlightPath.getStyle();
var featureStroke = featureStyle.getStroke();
if (qrzPathWidthValue.value == 0) {
g_layerSources["transmit"].clear();
delete g_transmitFlightPath;
g_transmitFlightPath = null;
} else {
featureStroke.setWidth(qrzPathWidthValue.value);
featureStroke.setColor(getQrzPathColor());
featureStyle.setStroke(featureStroke);
g_transmitFlightPath.setStyle(featureStyle);
if (typeof g_transmitFlightPath.Arrow != "undefined") {
var stroke = new ol.style.Stroke({
color: getQrzPathColor(),
width: qrzPathWidthValue.value,
});
var thisStle = new ol.style.Style({
image: new ol.style.Circle({
stroke: stroke,
radius: 3,
}),
});
g_transmitFlightPath.Arrow.setStyle(thisStle);
}
}
}
}
function compareCallsignTime(a, b) {
if (a.time < b.time) return -1;
if (a.time > b.time) return 1;
return 0;
}
function createFlagTipTable(toolElement) {
var myFlagtip = document.getElementById("myFlagtip");
var worker = "";
if (toolElement.size == 1) {
var key = toolElement.key;
var dxcc = callsignToDxcc(g_gtFlagPins[key].call);
var dxccName = g_dxccToAltName[dxcc];
var workColor = "cyan";
if (g_gtFlagPins[key].call + myBand + myMode in g_tracker.worked.call) {
workColor = "yellow";
}
if (g_gtFlagPins[key].call + myBand + myMode in g_tracker.confirmed.call) {
workColor = "#00FF00";
}
worker +=
"<div style='background-color:" +
workColor +
";color:#000;font-weight:bold;font-size:18px;border:2px solid gray;margin:0px' class='roundBorder'>" +
g_gtFlagPins[key].call.formatCallsign() +
"</div>";
worker += "<table id='tooltipTable' class='darkTable' >";
worker +=
"<tr><td>DXCC</td><td style='color:orange;'>" +
dxccName +
" <font color='lightgreen'>(" +
g_worldGeoData[g_dxccToGeoData[dxcc]].pp +
")</font></td>";
worker +=
"<tr><td>Grid</td><td style='color:cyan;' >" +
g_gtFlagPins[key].grid +
"</td></tr>";
worker +=
"<tr><td>Freq</td><td style='color:lightgreen' >" +
Number(g_gtFlagPins[key].freq / 1000).formatMhz(3, 3) +
" <font color='yellow'>(" +
Number(g_gtFlagPins[key].freq / 1000000).formatBand() +
")</font></td></tr>";
worker +=
"<tr><td>Mode</td><td style='color:orange' >" +
g_gtFlagPins[key].mode +
"</td></tr>";
var LL = squareToLatLongAll(g_gtFlagPins[key].grid);
var bearing = parseInt(
MyCircle.bearing(
g_myLat,
g_myLon,
LL.la2 - (LL.la2 - LL.la1) / 2,
LL.lo2 - (LL.lo2 - LL.lo1) / 2
)
);
worker +=
"<tr><td>Dist</td><td style='color:cyan'>" +
parseInt(
MyCircle.distance(
g_myLat,
g_myLon,
LL.la2 - (LL.la2 - LL.la1) / 2,
LL.lo2 - (LL.lo2 - LL.lo1) / 2,
distanceUnit.value
) * MyCircle.validateRadius(distanceUnit.value)
) +
distanceUnit.value.toLowerCase() +
"</td></tr>";
worker +=
"<tr><td>Azim</td><td style='color:yellow'>" +
bearing +
"&deg;</td></tr>";
worker += "</table>";
} else if (toolElement.size == 73) {
var props = toolElement.getProperties();
moment.locale(navigator.languages[0]);
var m = moment().tz(props.tzid);
worker +=
"<div style='background-color:cyan;color:#000;font-weight:bold;font-size:16px;border:2px solid gray;margin:0px;padding:1px' class='roundBorder'>" +
props.tzid +
"</div>";
worker += "<table id='tooltipTable' class='darkTable' align=center>";
var abbr = m.format("zz");
var zone = m.format("Z");
if (zone.indexOf(abbr) > -1) abbr = "";
else abbr = " <font color='orange'>(" + abbr + ")</font>";
worker +=
"<tr><td style='color:yellow;font-weight:bold'>" +
m.format("LLLL") +
"</td></tr>";
worker +=
"<tr><td style='color:#00FF00;font-weight:bold'>" +
zone +
abbr +
"</td></tr>";
worker += "</table>";
}
myFlagtip.innerHTML = worker;
return 1;
}
function remove_duplicates(arr) {
var obj = {};
var ret_arr = [];
for (var i = 0; i < arr.length; i++) {
obj[arr[i]] = true;
}
for (var key in obj) {
ret_arr.push(key);
}
return ret_arr;
}
function splitNoParen(s) {
var results = [];
var next;
var str = "";
var left = 0,
right = 0;
function keepResult() {
results.push(str.trim());
str = "";
}
for (var i = 0; i < s.length; i++) {
switch (s[i]) {
case ",":
if (left === right) {
keepResult();
left = right = 0;
} else {
str += s[i];
}
break;
case "(":
left++;
str += s[i];
break;
case ")":
right++;
str += s[i];
break;
default:
str += s[i];
}
}
keepResult();
return results;
}
function createSpotTipTable(toolElement) {
var now = timeNowSec();
var myTooltip = document.getElementById("myTooltip");
var worker = "";
if (toolElement.spot in g_receptionReports.spots) {
g_layerSources["psk-hop"].clear();
var report = g_receptionReports.spots[toolElement.spot];
var LL = squareToLatLongAll(myRawGrid);
var Lat = LL.la2 - (LL.la2 - LL.la1) / 2;
var Lon = LL.lo2 - (LL.lo2 - LL.lo1) / 2;
var fromPoint = ol.proj.fromLonLat([Lon, Lat]);
worker =
"<table id='tooltipTable' class='darkTable' ><tr><th colspan=2 style='color:cyan'>Rx Spot</th></tr>";
worker +=
"<tr><td>Age</td><td>" +
Number(now - report.when).toDHMS() +
"</td></tr>";
worker +=
"<tr><td>dB</td><td style='color:#DD44DD' >" +
Number(report.snr).formatSignalReport() +
"</td></tr>";
worker +=
"<tr><td>Call</td><td style='color:#ff0' >" +
report.call.formatCallsign() +
"</td></tr>";
if (report.dxcc > 0)
worker +=
"<tr><td>DXCC</td><td style='color:orange;'>" +
g_dxccToAltName[report.dxcc] +
" <font color='lightgreen'>(" +
g_worldGeoData[g_dxccToGeoData[report.dxcc]].pp +
")</font></td>";
worker +=
"<tr><td>Grid</td><td style='color:cyan;cursor:pointer' >" +
report.grid +
"</td></tr>";
worker +=
"<tr><td>Freq</td><td style='color:lightgreen' >" +
report.freq.formatMhz() +
" <font color='yellow'>(" +
report.band +
")</font></td></tr>";
worker +=
"<tr><td>Mode</td><td style='color:orange' >" +
report.mode +
"</td></tr>";
LL = squareToLatLongAll(report.grid);
report.bearing = parseInt(
MyCircle.bearing(
g_myLat,
g_myLon,
LL.la2 - (LL.la2 - LL.la1) / 2,
LL.lo2 - (LL.lo2 - LL.lo1) / 2
)
);
worker +=
"<tr><td>Dist</td><td style='color:cyan'>" +
parseInt(
MyCircle.distance(
g_myLat,
g_myLon,
LL.la2 - (LL.la2 - LL.la1) / 2,
LL.lo2 - (LL.lo2 - LL.lo1) / 2,
distanceUnit.value
) * MyCircle.validateRadius(distanceUnit.value)
) +
distanceUnit.value.toLowerCase() +
"</td></tr>";
worker +=
"<tr><td>Azim</td><td style='color:yellow'>" +
report.bearing +
"&deg;</td></tr>";
worker +=
"<tr><td>Time</td><td>" +
userTimeString(report.when * 1000) +
"</td></tr>";
worker += "</table>";
var strokeWeight = pathWidthValue.value;
Lat = LL.la2 - (LL.la2 - LL.la1) / 2;
Lon = LL.lo2 - (LL.lo2 - LL.lo1) / 2;
var toPoint = ol.proj.fromLonLat([Lon, Lat]);
var feature = flightFeature(
[fromPoint, toPoint],
{
weight: strokeWeight,
color: getQrzPathColor(),
steps: 75,
},
"psk-hop",
false
);
}
myTooltip.innerHTML = worker;
g_passingToolTipTableString = worker;
return 10;
}
function createTooltTipTable(toolElement) {
if (typeof toolElement.spot != "undefined") {
return createSpotTipTable(toolElement);
}
var myTooltip = document.getElementById("myTooltip");
var colspan = 10;
if (g_callsignLookups.lotwUseEnable == true) colspan++;
if (g_callsignLookups.eqslUseEnable == true) colspan++;
if (g_callsignLookups.oqrsUseEnable == true) colspan++;
if (toolElement.qso == true) colspan += 2;
var worker =
"<table id='tooltipTable' class='darkTable' ><tr><th colspan=" +
colspan +
" style='color:cyan'>" +
toolElement.qth +
"</th></tr>";
if (toolElement.qth in g_gridToDXCC) {
worker += "<tr><th colspan=" + colspan + " style='color:yellow'><small>";
for (var x = 0; x < g_gridToDXCC[toolElement.qth].length; x++) {
worker += g_dxccToAltName[g_gridToDXCC[toolElement.qth][x]];
if (toolElement.qth in g_gridToState) {
worker += " (<font color='orange'>";
var added = false;
for (var y = 0; y < g_gridToState[toolElement.qth].length; y++) {
if (
g_gridToDXCC[toolElement.qth][x] ==
g_StateData[g_gridToState[toolElement.qth][y]].dxcc
) {
worker +=
g_StateData[g_gridToState[toolElement.qth][y]].name + " / ";
added = true;
}
}
if (added == true)
worker = worker.substr(0, worker.length - " / ".length);
worker += "</font>)";
}
if (x + 1 < g_gridToDXCC[toolElement.qth].length) worker += ", ";
}
worker += "</small></th></tr>";
}
var newCallList = Array();
if (toolElement.qso == true) {
if (Object.keys(toolElement.hashes).length > 0) {
worker +=
"<tr align='center'><td>Call</td><td>Freq</td><td>Sent</td><td>Rcvd</td><td>Station</td><td>Mode</td><td>Band</td><td>QSL</td><td>Last Msg</td><td>DXCC</td><td>Time</td>";
if (g_callsignLookups.lotwUseEnable == true) worker += "<td>LoTW</td>";
if (g_callsignLookups.eqslUseEnable == true) worker += "<td>eQSL</td>";
if (g_callsignLookups.oqrsUseEnable == true) worker += "<td>OQRS</td>";
worker += "</tr>";
}
for (var KeyIsHash in toolElement.hashes) {
if (KeyIsHash in g_QSOhash) {
newCallList.push(g_QSOhash[KeyIsHash]);
}
}
if (
toolElement.qth in g_liveGrids &&
g_liveGrids[toolElement.qth].rectangle != null &&
g_liveGrids[toolElement.qth].isTriangle == false
) {
for (var KeyIsCall in g_liveGrids[toolElement.qth].rectangle.liveHash) {
if (KeyIsCall in g_liveCallsigns && g_appSettings.gridViewMode == 3)
newCallList.push(g_liveCallsigns[KeyIsCall]);
}
}
} else {
if (Object.keys(toolElement.liveHash).length > 0) {
worker +=
"<tr align='center'><td>Call</td><td>Freq</td><td>Sent</td><td>Rcvd</td><td>Station</td><td>Mode</td><td>Band</td><td>Last Msg</td><td>DXCC</td><td>Time</td>";
if (g_callsignLookups.lotwUseEnable == true) worker += "<td>LoTW</td>";
if (g_callsignLookups.eqslUseEnable == true) worker += "<td>eQSL</td>";
if (g_callsignLookups.oqrsUseEnable == true) worker += "<td>OQRS</td>";
worker += "</tr>";
}
for (var KeyIsCall in toolElement.liveHash) {
if (KeyIsCall in g_liveCallsigns)
newCallList.push(g_liveCallsigns[KeyIsCall]);
}
}
newCallList.sort(compareCallsignTime).reverse();
for (var x = 0; x < newCallList.length; x++) {
var callsign = newCallList[x];
var bgDX = " style='font-weight:bold;color:cyan;' ";
var bgDE = " style='font-weight:bold;color:yellow;' ";
if (callsign.DXcall == myDEcall)
bgDX = " style='background-color:cyan;color:#000;font-weight:bold' ";
if (callsign.DEcall == myDEcall)
bgDE = " style='background-color:#FFFF00;color:#000;font-weight:bold' ";
if (typeof callsign.msg == "undefined" || callsign.msg == "")
callsign.msg = "-";
var ageString = "";
if (timeNowSec() - callsign.time < 3601)
ageString = (timeNowSec() - callsign.time).toDHMS();
else {
ageString = userTimeString(callsign.time * 1000);
}
worker += "<tr><td" + bgDE + ">";
worker +=
"<div style='display:inline-table;cursor:pointer' onclick='startLookup(\"" +
callsign.DEcall +
'","' +
toolElement.qth +
"\");' >" +
callsign.DEcall.formatCallsign() +
"</div>";
worker += "</td>";
worker += "<td>" + (callsign.delta > -1 ? callsign.delta : "-") + "</td>";
worker += "<td>" + callsign.RSTsent + "</td>";
worker += "<td>" + callsign.RSTrecv + "</td>" + "<td" + bgDX + ">";
if (callsign.DXcall.indexOf("CQ") == 0 || callsign.DXcall == "-")
worker += callsign.DXcall.formatCallsign();
else
worker +=
"<div style='display:inline-table;cursor:pointer' onclick='startLookup(\"" +
callsign.DXcall +
"\",null);' >" +
callsign.DXcall.formatCallsign() +
"</div>";
worker +=
"</td>" +
"<td style='color:lightblue'>" +
callsign.mode +
"</td>" +
"<td style='color:lightgreen'>" +
callsign.band +
"</td>";
if (toolElement.qso == true) {
worker +=
"<td align='center'>" +
(callsign.confirmed ? "&#10004;" : "") +
"</td>";
}
worker +=
"<td>" +
callsign.msg +
"</td><td style='color:yellow'>" +
g_dxccToAltName[callsign.dxcc] +
" <font color='lightgreen'>(" +
g_worldGeoData[g_dxccToGeoData[callsign.dxcc]].pp +
")</font></td>" +
"<td align='center' style='color:lightblue' >" +
ageString +
"</td>";
if (g_callsignLookups.lotwUseEnable == true)
worker +=
"<td align='center'>" +
(callsign.DEcall in g_lotwCallsigns ? "&#10004;" : "") +
"</td>";
if (g_callsignLookups.eqslUseEnable == true)
worker +=
"<td align='center'>" +
(callsign.DEcall in g_eqslCallsigns ? "&#10004;" : "") +
"</td>";
if (g_callsignLookups.oqrsUseEnable == true)
worker +=
"<td align='center'>" +
(callsign.DEcall in g_oqrsCallsigns ? "&#10004;" : "") +
"</td>";
worker += "</tr>";
}
worker += "</table>";
myTooltip.innerHTML = worker;
g_passingToolTipTableString = worker;
return newCallList.length;
}
function renderTooltipWindow(feature) {
if (g_popupWindowHandle != null) {
try {
createTooltTipTable(feature);
var adif = g_popupWindowHandle.window.document.getElementById(
"adifTable"
);
adif.innerHTML = g_passingToolTipTableString;
var myTooltip = document.getElementById("myTooltip");
var positionInfo = myTooltip.getBoundingClientRect();
g_popupWindowHandle.show();
g_popupWindowHandle.focus();
g_popupWindowHandle.width = parseInt(positionInfo.width) + 20;
g_popupWindowHandle.height = parseInt(positionInfo.height) + 50;
} catch (e) {}
}
}
function leftClickGtFlag(feature) {
var e = window.event;
if ((e.which && e.which == 1) || (e.button && e.button == 1)) {
startLookup(g_gtFlagPins[feature.key].call, g_gtFlagPins[feature.key].grid);
}
return false;
}
function openConditionsWindow() {
if (g_conditionsWindowHandle == null) {
popupNewWindows();
var gui = require("nw.gui");
gui.Window.open(
"gt_conditions.html",
{
show: false,
id: "GT-Conditions",
},
function (new_win) {
g_conditionsWindowHandle = new_win;
new_win.on("loaded", function () {
g_conditionsWindowHandle.setMinimumSize(490, 290);
});
new_win.on("close", function () {
g_conditionsWindowHandle.window.g_isShowing = false;
g_conditionsWindowHandle.window.saveScreenSettings();
g_conditionsWindowHandle.hide();
});
}
);
lockNewWindows();
} else {
try {
g_conditionsWindowHandle.window.g_isShowing = true;
g_conditionsWindowHandle.window.saveScreenSettings();
g_conditionsWindowHandle.show();
g_conditionsWindowHandle.focus();
} catch (e) {}
}
}
var g_callRoster = {};
function insertMessageInRoster(
newMessage,
msgDEcallsign,
msgDXcallsign,
callObj,
hash
) {
var now = timeNowSec();
if (!(hash in g_callRoster)) {
g_callRoster[hash] = {};
callObj.life = now;
callObj.reset = false;
}
if (callObj.reset) {
callObj.life = now;
callObj.reset = false;
}
if (typeof callObj.life == "undefined") {
callObj.life = now;
callObj.reset = false;
}
g_callRoster[hash].message = newMessage;
g_callRoster[hash].callObj = callObj;
g_callRoster[hash].DXcall = msgDXcallsign;
g_callRoster[hash].DEcall = msgDEcallsign;
goProcessRoster(true);
}
function openCallRosterWindow(show = true) {
if (g_callRosterWindowHandle == null) {
popupNewWindows();
var gui = require("nw.gui");
gui.Window.open(
"gt_roster.html",
{
show: false,
id: "GT-roster",
icon: "img/roster-icon.png",
},
function (new_win) {
g_callRosterWindowHandle = new_win;
new_win.on("loaded", function () {
g_callRosterWindowHandle.setMinimumSize(390, 250);
g_callRosterWindowHandle.setResizable(true);
setRosterTop();
});
new_win.on("close", function () {
g_callRosterWindowHandle.window.g_isShowing = false;
g_callRosterWindowHandle.window.saveScreenSettings();
g_callRosterWindowHandle.hide();
});
}
);
lockNewWindows();
} else {
try {
g_callRosterWindowHandle.show();
g_callRosterWindowHandle.window.g_isShowing = true;
g_callRosterWindowHandle.window.saveScreenSettings();
g_callRosterWindowHandle.focus();
goProcessRoster();
} catch (e) {}
}
}
function updateRosterWorked() {
if (g_callRosterWindowHandle) {
try {
g_callRosterWindowHandle.window.updateWorked();
} catch (e) {}
}
}
function updateRosterInstances() {
if (g_callRosterWindowHandle) {
try {
g_callRosterWindowHandle.window.updateInstances();
} catch (e) {}
}
}
function updateLogbook() {
showWorkedBox(0, 0, true);
}
function openStatsWindow(show = true) {
if (g_statsWindowHandle == null) {
popupNewWindows();
var gui = require("nw.gui");
gui.Window.open(
"gt_stats.html",
{
show: false,
id: "GT-stats",
},
function (new_win) {
g_statsWindowHandle = new_win;
new_win.on("loaded", function () {
g_statsWindowHandle.setMinimumSize(620, 200);
g_statsWindowHandle.setResizable(true);
});
new_win.on("close", function () {
g_statsWindowHandle.window.g_isShowing = false;
g_statsWindowHandle.window.saveScreenSettings();
g_statsWindowHandle.hide();
});
}
);
lockNewWindows();
} else {
try {
g_statsWindowHandle.show();
g_statsWindowHandle.window.g_isShowing = true;
g_statsWindowHandle.window.saveScreenSettings();
g_statsWindowHandle.focus();
} catch (e) {}
}
}
function showMessaging(show = true, cid) {
if (g_chatWindowHandle == null) {
popupNewWindows();
var gui = require("nw.gui");
gui.Window.open(
"gt_chat.html",
{
show: false,
id: "GT-chat",
},
function (new_win) {
g_chatWindowHandle = new_win;
g_chatWindowHandle.on("loaded", function () {
g_chatWindowHandle.setMinimumSize(450, 140);
g_chatWindowHandle.setResizable(true);
});
g_chatWindowHandle.on("close", function () {
g_chatWindowHandle.window.closeMessageArea();
g_chatWindowHandle.window.g_isShowing = false;
g_chatWindowHandle.window.saveScreenSettings();
g_chatWindowHandle.hide();
});
}
);
lockNewWindows();
} else {
try {
g_chatWindowHandle.window.g_isShowing = true;
g_chatWindowHandle.window.saveScreenSettings();
g_chatWindowHandle.show();
g_chatWindowHandle.focus();
if (typeof cid != "undefined") g_chatWindowHandle.window.openId(cid);
} catch (e) {}
}
}
function onRightClickGridSquare(feature) {
var e = window.event;
if (
(e.which && e.button == 2 && event.shiftKey) ||
(e.button && e.button == 2 && event.shiftKey)
) {
var myTooltip = document.getElementById("myTooltip");
createTooltTipTable(feature);
selectElementContents(myTooltip);
} else if (e.button == 0 && g_mapSettings.mouseOver == false) {
mouseOverDataItem(feature, false);
} else if ((e.which && e.which == 3) || (e.button && e.button == 2)) {
if (g_popupWindowHandle == null) {
popupNewWindows();
var gui = require("nw.gui");
gui.Window.open(
"gt_popup.html",
{
show: false,
id: "GT-popup",
},
function (new_win) {
g_popupWindowHandle = new_win;
new_win.on("loaded", function () {
g_popupWindowHandle.show();
renderTooltipWindow(feature);
});
new_win.on("close", function () {
g_popupWindowHandle.hide();
});
}
);
lockNewWindows();
} else {
try {
renderTooltipWindow(feature);
} catch (e) {}
}
mouseOutOfDataItem();
} else if ((e.which && e.which == 1) || (e.button && e.button == 0)) {
if (typeof feature.spot != "undefined") {
spotLookupAndSetCall(feature.spot);
}
}
return false;
}
function onMouseUpdate(e) {
g_mouseX = e.pageX;
g_mouseY = e.pageY;
mouseMoveGrid();
}
function getMouseX() {
return g_mouseX;
}
function getMouseY() {
return g_mouseY;
}
var g_tempGridBox = null;
function tempGridToBox(iQTH, oldGrid, borderColor, boxColor, layer) {
var borderWeight = 2;
var newGridBox = null;
var LL = squareToLatLong(iQTH.substr(0, 4));
if (oldGrid) {
if (g_layerSources["temp"].hasFeature(oldGrid))
g_layerSources["temp"].removeFeature(oldGrid);
delete oldGrid;
}
var bounds = [
[LL.lo1, LL.la1],
[LL.lo2, LL.la2],
];
newGridBox = rectangle(bounds);
newGridBox.setId(iQTH);
const featureStyle = new ol.style.Style({
fill: new ol.style.Fill({
color: boxColor,
}),
stroke: new ol.style.Stroke({
color: borderColor,
width: borderWeight,
lineJoin: "round",
}),
zIndex: 60,
});
newGridBox.setStyle(featureStyle);
newGridBox.grid = iQTH;
newGridBox.size = 0;
g_layerSources["temp"].addFeature(newGridBox);
return newGridBox;
}
var g_tempGrids = Array();
function onMyKeyDown(event) {
if (g_MyGridIsUp == true && g_MyCurrentGrid.length == 4) {
var processedAlert = false;
var mediaClip = "";
var failedToAdd = g_dirSeperator + "Balloon-deflating-1.mp3";
if (event.code == "KeyM") {
mediaClip = g_dirSeperator + "Clicky-1.mp3";
var valid = addAlert(g_MyCurrentGrid, 2, 3, 2, "", "");
if (!valid) {
mediaClip = failedToAdd;
}
processedAlert = true;
} else if (event.code == "KeyT") {
mediaClip = g_dirSeperator + "Ping-coin.mp3";
var valid = addAlert(g_MyCurrentGrid, 2, 1, 2, "", "");
if (!valid) {
mediaClip = failedToAdd;
}
processedAlert = true;
} else if (event.code == "KeyV") {
mediaClip = g_dirSeperator + "Slide-ping.mp3";
var valid = addAlert(g_MyCurrentGrid, 2, 2, 2, "", "");
if (!valid) {
mediaClip = failedToAdd;
}
processedAlert = true;
}
if (processedAlert == true) {
playAlertMediaFile(g_mediaDir + mediaClip);
}
return;
}
if (event.keyCode == 27) {
alertsPopDiv.style.display = "none";
rootSettingsDiv.style.display = "none";
helpDiv.style.display = "none";
g_helpShow = false;
}
if (
alertsPopDiv.style.display == "none" &&
rootSettingsDiv.style.display == "none"
) {
if (event.code in g_hotKeys) {
if (typeof g_hotKeys[event.code].param1 != "undefined") {
var param2 = null;
if (typeof g_hotKeys[event.code].param2 != "undefined") {
if (typeof event[g_hotKeys[event.code].param2] != "undefined")
param2 = event[g_hotKeys[event.code].param2];
}
g_hotKeys[event.code].func(g_hotKeys[event.code].param1, param2);
} else {
if (event.ctrlKey == false) g_hotKeys[event.code].func();
}
} else if (event.key in g_hotKeys) {
if (typeof g_hotKeys[event.key].param1 != "undefined") {
var param2 = null;
if (typeof g_hotKeys[event.key].param2 != "undefined") {
if (typeof event[g_hotKeys[event.key].param2] != "undefined")
param2 = event[g_hotKeys[event.key].param2];
}
g_hotKeys[event.key].func(g_hotKeys[event.key].param1, param2);
} else {
if (event.ctrlKey == false) g_hotKeys[event.key].func();
}
}
}
}
function clearTempGrids() {
g_layerSources["temp"].clear();
g_tempGrids = Array();
}
var g_currentShapes = {};
function clearCurrentShapes() {
g_layerSources["award"].clear();
g_currentShapes = {};
}
function mapMemory(x, save, exit = false) {
if (save == true) {
g_mapMemory[x].LoLa = g_mapView.getCenter();
g_mapMemory[x].zoom = g_mapView.getZoom();
localStorage.mapMemory = JSON.stringify(g_mapMemory);
if (exit == false) {
playAlertMediaFile(g_mediaDir + g_dirSeperator + "Clicky-3.mp3");
}
} else {
if (g_mapMemory[x].zoom != -1) {
g_mapView.setCenter(g_mapMemory[x].LoLa);
g_mapView.setZoom(g_mapMemory[x].zoom);
}
}
}
var g_hotKeys = {};
function registerHotKey(key, func, param1, param2) {
g_hotKeys[key] = {};
g_hotKeys[key].func = func;
g_hotKeys[key].param1 = param1;
g_hotKeys[key].param2 = param2;
}
function registerHotKeys() {
registerHotKey("1", setTrophyOverlay, 0);
registerHotKey("2", setTrophyOverlay, 1);
registerHotKey("3", setTrophyOverlay, 2);
registerHotKey("4", setTrophyOverlay, 3);
registerHotKey("5", setTrophyOverlay, 4);
registerHotKey("6", setTrophyOverlay, 5);
registerHotKey("7", setTrophyOverlay, 6);
registerHotKey("8", setTrophyOverlay, 7);
registerHotKey("9", toggleTimezones);
registerHotKey("0", toggleNexrad);
registerHotKey("KeyA", toggleAnimate);
registerHotKey("KeyB", toggleAllGrids);
registerHotKey("KeyC", showConditionsBox);
registerHotKey("KeyD", toggleMoon);
registerHotKey("KeyE", toggleMoonTrack);
registerHotKey("KeyF", toggleSpotPaths);
registerHotKey("KeyG", toggleGtMap);
registerHotKey("KeyH", toggleHeatSpots);
registerHotKey("KeyI", showRootInfoBox);
//registerHotKey("KeyJ", setTrophyOverlay, 8);
registerHotKey("KeyK", makeScreenshots);
registerHotKey("KeyL", adifLoadDialog);
registerHotKey("KeyM", toggleAlertMute);
registerHotKey("KeyN", toggleEarth);
registerHotKey("KeyO", togglePskSpots);
registerHotKey("KeyP", togglePushPinMode);
registerHotKey("KeyQ", cycleGridView);
registerHotKey("KeyR", openCallRosterWindow);
registerHotKey("KeyS", showSettingsBox);
registerHotKey("KeyT", toggleSpotOverGrids);
registerHotKey("KeyU", toggleMergeOverlay);
registerHotKey("KeyW", toggleGridMode);
registerHotKey("KeyX", toggleMouseTrack);
registerHotKey("KeyY", toggleStrikeGlobal);
registerHotKey("KeyZ", setCenterQTH);
registerHotKey("Minus", toggleCRScript);
registerHotKey("F5", mapMemory, 0, "shiftKey");
registerHotKey("F6", mapMemory, 1, "shiftKey");
registerHotKey("F7", mapMemory, 2, "shiftKey");
registerHotKey("F8", mapMemory, 3, "shiftKey");
registerHotKey("F9", mapMemory, 4, "shiftKey");
registerHotKey("F10", mapMemory, 5, "shiftKey");
registerHotKey("F11", toggleFullscreen);
registerHotKey("F12", toggleMenu);
registerHotKey("F1", toggleHelp);
registerHotKey("?", toggleHelp);
registerHotKey("Equal", cycleTrophyOverlay);
}
function toggleMoon() {
g_appSettings.moonTrack ^= 1;
if (g_appSettings.moonTrack == 1) {
moonLayer.show();
} else {
moonLayer.hide();
}
}
function toggleMoonTrack() {
g_appSettings.moonPath ^= 1;
moonLayer.refresh();
}
function toggleFullscreen() {
if (document.fullscreenElement == null) {
mainBody.requestFullscreen();
} else {
document.exitFullscreen();
}
}
function toggleMenu() {
if (g_menuShowing == false) collapseMenu(false);
else collapseMenu(true);
}
g_helpShow = false;
function toggleHelp() {
g_helpShow = !g_helpShow;
if (g_helpShow == true) {
helpDiv.style.display = "block";
} else helpDiv.style.display = "none";
}
function onMyKeyUp(event) {}
var g_currentOverlay = 0;
function cycleTrophyOverlay() {
g_currentOverlay++;
g_currentOverlay %= 8;
setTrophyOverlay(g_currentOverlay);
}
function didWork(testObj) {
return testObj.worked;
}
function didConfirm(testObj) {
return testObj.confirmed;
}
function drawTitleInfo() {
var band =
g_appSettings.gtBandFilter.length == 0
? "Mixed"
: g_appSettings.gtBandFilter == "auto"
? myBand
: g_appSettings.gtBandFilter;
var mode =
g_appSettings.gtModeFilter.length == 0
? "Mixed"
: g_appSettings.gtModeFilter == "auto"
? myMode
: g_appSettings.gtModeFilter;
var space = " ";
var news =
gtVersionString +
" [" +
" Band: " +
band +
" Mode: " +
mode +
" Layer: " +
g_viewInfo[g_currentOverlay][1];
var end = " ]";
if (g_currentOverlay == 0 && g_appSettings.gridViewMode == 1) {
window.document.title = news + end;
} else {
var workline =
" -- Worked (" +
g_viewInfo[g_currentOverlay][2] +
") Confirmed (" +
g_viewInfo[g_currentOverlay][3] +
")";
if (
g_viewInfo[g_currentOverlay][2] <= g_viewInfo[g_currentOverlay][4] &&
g_viewInfo[g_currentOverlay][4] > 0
)
end =
" Needed (" +
(g_viewInfo[g_currentOverlay][4] - g_viewInfo[g_currentOverlay][2]) +
") ]";
window.document.title = news + workline + end;
}
}
function setTrophyOverlay(which) {
g_currentOverlay = which;
drawTitleInfo();
trophyImg.src = g_trophyImageArray[which];
myTrophyTooltip.style.zIndex = -1;
clearCurrentShapes();
// set the scope of key
var key = 0;
if (which == 0) {
for (key in g_layerVectors) {
g_layerVectors[key].setVisible(true);
}
if (
g_appSettings.gtFlagImgSrc > 0 &&
g_appSettings.gtShareEnable == true &&
g_mapSettings.offlineMode == false
) {
g_layerVectors["gtflags"].setVisible(true);
} else {
g_layerVectors["gtflags"].setVisible(false);
}
g_layerVectors["award"].setVisible(false);
if (g_showAllGrids == false) {
g_layerVectors["line-grids"].setVisible(false);
g_layerVectors["big-grids"].setVisible(false);
g_layerVectors["short-grids"].setVisible(false);
g_layerVectors["long-grids"].setVisible(false);
}
if (g_timezoneLayer) {
if (g_timezonesEnable == 1) {
g_timezoneLayer.setVisible(true);
} else {
g_timezoneLayer.setVisible(false);
}
}
} else {
if (g_mapSettings.mergeOverlay == false) {
for (key in g_layerVectors) {
g_layerVectors[key].setVisible(false);
}
} else {
for (key in g_layerVectors) {
g_layerVectors[key].setVisible(true);
}
if (
g_appSettings.gtFlagImgSrc > 0 &&
g_appSettings.gtShareEnable == true &&
g_mapSettings.offlineMode == false
) {
g_layerVectors["gtflags"].setVisible(true);
} else {
g_layerVectors["gtflags"].setVisible(false);
}
if (g_showAllGrids == false) {
g_layerVectors["line-grids"].setVisible(false);
g_layerVectors["big-grids"].setVisible(false);
g_layerVectors["short-grids"].setVisible(false);
g_layerVectors["long-grids"].setVisible(false);
}
}
g_layerVectors["award"].setVisible(true);
if (g_timezoneLayer) {
g_timezoneLayer.setVisible(false);
}
mapLoseFocus();
}
g_layerVectors["strikes"].setVisible(true);
if (which == 1) {
for (key in g_cqZones) {
var boxColor = "#FF000015";
var borderColor = "#005500FF";
var borderWeight = 1;
if (didConfirm(g_cqZones[key])) {
boxColor = "#00FF0066";
} else if (didWork(g_cqZones[key])) {
boxColor = "#FFFF0066";
}
g_currentShapes[key] = shapeFeature(
key,
g_cqZones[key].geo,
"cqzone",
boxColor,
borderColor,
borderWeight
);
g_layerSources["award"].addFeature(g_currentShapes[key]);
}
}
if (which == 2) {
for (key in g_ituZones) {
var boxColor = "#FF000015";
var borderColor = "#800080FF";
var borderWeight = 1;
if (didConfirm(g_ituZones[key])) {
boxColor = "#00FF0066";
borderWeight = 1;
} else if (didWork(g_ituZones[key])) {
boxColor = "#FFFF0066";
borderWeight = 1;
}
g_currentShapes[key] = shapeFeature(
key,
g_ituZones[key].geo,
"ituzone",
boxColor,
borderColor,
borderWeight
);
g_layerSources["award"].addFeature(g_currentShapes[key]);
}
}
if (which == 3) {
for (key in g_wacZones) {
var boxColor = "#FF000015";
var borderColor = "#006666FF";
var borderWeight = 1;
var originalKey = key;
if (didConfirm(g_wacZones[key])) {
boxColor = "#00FF0066";
} else if (didWork(g_wacZones[key])) {
boxColor = "#FFFF0066";
}
g_currentShapes[originalKey] = shapeFeature(
originalKey,
g_wacZones[originalKey].geo,
"wac",
boxColor,
borderColor,
borderWeight
);
g_layerSources["award"].addFeature(g_currentShapes[originalKey]);
}
}
if (which == 4) {
for (key in g_wasZones) {
var boxColor = "#FF000020";
var borderColor = "#0000FFFF";
var borderWeight = 1;
if (didConfirm(g_wasZones[key])) {
boxColor = "#00FF0066";
} else if (didWork(g_wasZones[key])) {
boxColor = "#FFFF0066";
}
g_currentShapes[key] = shapeFeature(
key,
g_wasZones[key].geo,
"was",
boxColor,
borderColor,
borderWeight
);
g_layerSources["award"].addFeature(g_currentShapes[key]);
}
}
if (which == 5) {
for (key in g_worldGeoData) {
var boxColor = "#FF000015";
var borderColor = "#0000FFFF";
var borderWeight = 1;
if (didConfirm(g_worldGeoData[key])) {
boxColor = "#00FF0066";
} else if (didWork(g_worldGeoData[key])) {
boxColor = "#FFFF0066";
}
if (g_worldGeoData[key].geo != "deleted") {
g_currentShapes[key] = shapeFeature(
key,
g_worldGeoData[key].geo,
"dxcc",
boxColor,
borderColor,
borderWeight
);
g_layerSources["award"].addFeature(g_currentShapes[key]);
}
}
}
if (which == 6) {
for (key in g_countyData) {
var boxColor = "#00000000";
var borderColor = "#0000FFFF";
var borderWeight = 0.1;
if (didConfirm(g_countyData[key])) {
boxColor = "#00FF0066";
borderWeight = 1;
} else if (didWork(g_countyData[key])) {
boxColor = "#FFFF0066";
borderWeight = 1;
}
g_currentShapes[key] = shapeFeature(
key,
g_countyData[key].geo,
"usc",
boxColor,
borderColor,
borderWeight
);
g_layerSources["award"].addFeature(g_currentShapes[key]);
}
}
if (which == 7) {
for (key in g_us48Data) {
var LL = squareToLatLong(key);
var bounds = [
[LL.lo1, LL.la1],
[LL.lo2, LL.la2],
];
var boxColor = "#FF000015";
var borderColor = "#0000FFFF";
var borderWeight = 0.1;
if (g_us48Data[key].confirmed) {
boxColor = "#00FF0066";
borderWeight = 0.2;
} else if (g_us48Data[key].worked) {
boxColor = "#FFFF0066";
borderWeight = 0.2;
}
g_currentShapes[key] = gridFeature(
key,
rectangle(bounds),
"us48",
boxColor,
borderColor,
borderWeight
);
g_layerSources["award"].addFeature(g_currentShapes[key]);
}
}
updateSpotView(true);
}
function gridFeature(
key,
objectData,
propname,
fillColor,
borderColor,
borderWidth
) {
var style = new ol.style.Style({
stroke: new ol.style.Stroke({
color: borderColor,
width: borderWidth,
}),
fill: new ol.style.Fill({
color: fillColor,
}),
});
objectData.setStyle(style);
objectData.set("prop", propname);
objectData.set("grid", key);
objectData.size = 2;
return objectData;
}
var g_lastMoon = null;
function moonOver(feature) {
var data = subLunar(timeNowSec());
var object = doRAconvert(g_myLon, g_myLat, data.RA, data.Dec);
var elevation = object.elevation.toFixed(1);
var elColor = "yellow";
if (elevation <= 0) elColor = "red";
if (elevation > 10.0) elColor = "lightgreen";
var worker = "<table class='darkTable'>";
worker +=
"<tr><th colspan=2 style='font-size:15px;color:cyan;'>Moon</th></tr>";
worker +=
"<tr><th >Azimuth</th><td style='color:lightgreen'>" +
object.azimuth.toFixed(1) +
"&deg;</td></tr>";
worker +=
"<tr><th >Elevation</th><td style='color:" +
elColor +
"'>" +
elevation +
"</td></tr>";
worker += "</table>";
myMoonTooltip.innerHTML = worker;
if (g_lastMoon) {
moonMove();
return;
}
g_lastMoon = feature;
var positionInfo = myMoonTooltip.getBoundingClientRect();
myMoonTooltip.style.left = getMouseX() - positionInfo.width / 2 + "px";
myMoonTooltip.style.top = getMouseY() + 22 + "px";
myMoonTooltip.style.zIndex = 499;
myMoonTooltip.style.display = "block";
}
function moonOut() {
g_lastMoon = null;
myMoonTooltip.style.zIndex = -1;
}
function moonMove() {
var positionInfo = myMoonTooltip.getBoundingClientRect();
myMoonTooltip.style.left = getMouseX() - positionInfo.width / 2 + "px";
myMoonTooltip.style.top = getMouseY() + 22 + "px";
}
var g_lastTrophy = null;
function trophyOver(feature) {
if (g_lastTrophy && g_lastTrophy == feature) {
trophyMove();
return;
}
g_lastTrophy = feature;
var name = feature.getGeometryName();
var infoObject = {};
var trophy = "";
var zone = null;
var key = feature.get("prop");
if (key == "cqzone") {
trophy = "CQ Zone";
infoObject = g_cqZones[name];
zone = name;
name = g_cqZones[name].name;
}
if (key == "ituzone") {
trophy = "ITU Zone";
infoObject = g_ituZones[name];
}
if (key == "wac" && name in g_wacZones) {
trophy = "Continent";
infoObject = g_wacZones[name];
}
if (key == "was" && name in g_wasZones) {
trophy = "US State";
infoObject = g_wasZones[name];
}
if (key == "dxcc" && name in g_worldGeoData) {
trophy = "DXCC";
var ref = name;
infoObject = g_worldGeoData[ref];
name =
g_worldGeoData[ref].name +
" <font color='orange'>(" +
g_worldGeoData[ref].pp +
")</font>";
}
if (key == "usc") {
trophy = "US County";
infoObject = g_countyData[name];
name = infoObject.geo.properties.n + ", " + infoObject.geo.properties.st;
}
if (key == "us48") {
trophy = "US Continental Grids";
infoObject = g_us48Data[feature.get("grid")];
name = feature.get("grid");
if (name in g_gridToState) {
zone = "";
for (var x = 0; x < g_gridToDXCC[name].length; x++) {
if (name in g_gridToState) {
for (var y = 0; y < g_gridToState[name].length; y++) {
if (
g_gridToDXCC[name][x] ==
g_StateData[g_gridToState[name][y]].dxcc &&
g_gridToDXCC[name][x] == 291
) {
zone += g_StateData[g_gridToState[name][y]].name + ", ";
}
}
}
}
zone = zone.substr(0, zone.length - 2);
}
}
var worker = "<table>";
worker += "<tr><th colspan=2 >" + trophy + "</th></tr>";
worker +=
"<tr><td colspan=2><font color='white'><b>" +
name +
"</b></font></td></tr>";
if (zone)
worker +=
" <tr><td colspan=2><font color='lightgreen'>" +
zone +
"</font></td></tr>";
var wc1Table = "<td></td>";
if (infoObject.worked) {
wc1Table = "<td align=center><table class='darkTable'>";
wc1Table +=
"<tr><td colspan=2 ><font color='yellow'>Worked</font></td></tr>";
wc1Table += "<tr><td align=right><font color='green'>Band</font></td>";
wc1Table += "<td align=left><table class='subtable'>";
var keys = Object.keys(infoObject.worked_bands).sort();
for (key in keys) {
wc1Table +=
"<tr><td align=right>" +
keys[key] +
"</td><td align=left> <font color='white'>(" +
infoObject.worked_bands[keys[key]] +
") " +
"</font></td></tr>";
}
wc1Table += "</table></td>";
wc1Table += "</tr>";
wc1Table += "<tr>";
wc1Table += "<td align=right><font color='orange'>Mode</font></td>";
wc1Table += "<td align=left><table class='subtable'>";
keys = Object.keys(infoObject.worked_modes).sort();
for (key in keys) {
wc1Table +=
"<tr><td align=right>" +
keys[key] +
"</td><td align=left> <font color='white'>(" +
infoObject.worked_modes[keys[key]] +
") " +
"</font></td></tr>";
}
wc1Table += "</table></td>";
wc1Table += "</tr>";
wc1Table += "</table></td>";
}
var wcTable = "<td></td>";
if (infoObject.confirmed) {
wcTable = "<td align=center><table class='darkTable'>";
wcTable +=
"<tr><td colspan=2 ><font color='lightgreen'>Confirmed</font></td></tr>";
wcTable += "<tr><td align=right><font color='green'>Band</font></td>";
wcTable += "<td align=left><table class='subtable'>";
var keys = Object.keys(infoObject.confirmed_bands).sort();
for (key in keys) {
wcTable +=
"<tr><td align=right>" +
keys[key] +
"</td><td align=left> <font color='white'>(" +
infoObject.confirmed_bands[keys[key]] +
") " +
"</font></td></tr>";
}
wcTable += "</table></td>";
wcTable += "</tr>";
wcTable += "<tr>";
wcTable += "<td align=right><font color='orange'>Mode</font></td>";
wcTable += "<td align=left><table class='subtable'>";
keys = Object.keys(infoObject.confirmed_modes).sort();
for (key in keys) {
wcTable +=
"<tr><td align=right>" +
keys[key] +
"</td><td align=left> <font color='white'>(" +
infoObject.confirmed_modes[keys[key]] +
") " +
"</font></td></tr>";
}
wcTable += "</table></td>";
wcTable += "</tr>";
wcTable += "</table></td>";
}
if (!infoObject.worked && !infoObject.confirmed)
worker +=
"<tr><td colspan=2 ><font color='orange'>Needed</font></td></tr>";
else {
worker += "<tr>" + wc1Table + wcTable + "</tr>";
}
worker += "</table>";
myTrophyTooltip.innerHTML =
"<div style='font-size:15px;color:cyan;' class='roundBorder'>" +
worker +
"</div>";
var positionInfo = myTrophyTooltip.getBoundingClientRect();
myTrophyTooltip.style.left = getMouseX() - positionInfo.width / 2 + "px";
myTrophyTooltip.style.top = getMouseY() - positionInfo.height - 22 + "px";
myTrophyTooltip.style.zIndex = 499;
myTrophyTooltip.style.display = "block";
}
function trophyOut() {
g_lastTrophy = null;
myTrophyTooltip.style.zIndex = -1;
}
function trophyMove() {
var positionInfo = myTrophyTooltip.getBoundingClientRect();
myTrophyTooltip.style.left = getMouseX() - positionInfo.width / 2 + "px";
myTrophyTooltip.style.top = getMouseY() - positionInfo.height - 22 + "px";
}
var g_MyCurrentGrid = "";
var g_MyGridIsUp = false;
function mouseDownGrid(longlat, event) {
var grid = "";
grid = latLonToGridSquare(longlat[1], longlat[0]);
g_MyCurrentGrid = grid.substr(0, 4);
var worker = "";
worker += "<table align='center' class='darkTable'><tr style='color:white;'>";
var bearing = parseInt(
MyCircle.bearing(g_myLat, g_myLon, longlat[1], longlat[0])
);
worker +=
"<tr><td>Dist</td><td style='color:lightgreen'>" +
parseInt(
MyCircle.distance(
g_myLat,
g_myLon,
longlat[1],
longlat[0],
distanceUnit.value
) * MyCircle.validateRadius(distanceUnit.value)
) +
distanceUnit.value.toLowerCase() +
"</td></tr>";
worker +=
"<tr><td>Azim</td><td style='color:yellow'>" + bearing + "&deg;</td></tr>";
worker +=
"<tr><td>Lat</td><td style='color:orange'>" +
longlat[1].toFixed(3) +
"</td></tr>";
worker +=
"<tr><td>Long</td><td style='color:lightblue'>" +
longlat[0].toFixed(3) +
"</td></tr></table>";
if (grid in g_gridToDXCC) {
worker +=
"<table align='center' class='darkTable' style='border-top:none'><tr style='color:white;'>";
worker += "<tr style='color:orange;'>";
for (var x = 0; x < g_gridToDXCC[grid].length; x++) {
worker +=
"<td>" +
g_dxccToAltName[g_gridToDXCC[grid][x]] +
" <font color='lightgreen'>(" +
g_worldGeoData[g_dxccToGeoData[g_gridToDXCC[grid][x]]].pp +
")</font></td>";
}
if (grid in g_gridToState) {
worker += "</tr><tr style='color:yellow;'>";
for (var x = 0; x < g_gridToDXCC[grid].length; x++) {
worker += "<td>";
if (grid in g_gridToState) {
for (var y = 0; y < g_gridToState[grid].length; y++) {
if (
g_gridToDXCC[grid][x] == g_StateData[g_gridToState[grid][y]].dxcc
) {
worker += g_StateData[g_gridToState[grid][y]].name + "<br/>";
}
}
}
worker += "</td>";
}
}
worker += "</tr></table>";
}
g_tempGridBox = tempGridToBox(grid, g_tempGridBox, "#000000FF", "#00000000");
myGridTooltip.innerHTML =
"<div style='font-size:14px;font-weight:bold;color:cyan;margin:0 auto' class='roundBorder'>" +
grid +
"</div>" +
worker;
var positionInfo = myGridTooltip.getBoundingClientRect();
myGridTooltip.style.left = event.pixel[0] - positionInfo.width / 2 + "px";
myGridTooltip.style.top = event.pixel[1] - positionInfo.height - 22 + "px";
myGridTooltip.style.zIndex = 499;
myGridTooltip.style.display = "block";
g_MyGridIsUp = true;
}
function mouseMoveGrid() {
if (g_MyGridIsUp == true) {
var positionInfo = myGridTooltip.getBoundingClientRect();
myGridTooltip.style.left = getMouseX() - positionInfo.width / 2 + "px";
myGridTooltip.style.top = getMouseY() - positionInfo.height - 22 + "px";
}
}
function mouseUpGrid() {
g_MyGridIsUp = false;
myGridTooltip.style.zIndex = -1;
if (g_tempGridBox) {
if (g_layerSources["temp"].hasFeature(g_tempGridBox))
g_layerSources["temp"].removeFeature(g_tempGridBox);
}
delete g_tempGridBox;
g_tempGridBox = null;
}
var g_lastGtFlag = null;
function mouseOverGtFlag(feature) {
if (g_lastGtFlag && g_lastGtFlag == feature) {
gtFlagMove();
return;
}
g_lastGtFlag = feature;
createFlagTipTable(feature);
var positionInfo = myFlagtip.getBoundingClientRect();
myFlagtip.style.left = getMouseX() + 15 + "px";
myFlagtip.style.top = getMouseY() - positionInfo.height - 5 + "px";
myFlagtip.style.zIndex = 499;
myFlagtip.style.display = "block";
if (feature.size == 73 && feature != g_lasttimezone) {
if (g_lasttimezone != null) {
g_lasttimezone.setStyle(null);
}
var style = new ol.style.Style({
fill: new ol.style.Fill({
color: "#FFFF0088",
}),
});
feature.setStyle(style);
g_lasttimezone = feature;
}
return;
}
function mouseOutGtFlag(mouseEvent) {
g_lastGtFlag = null;
myFlagtip.style.zIndex = -1;
if (g_lasttimezone != null) {
g_lasttimezone.setStyle(null);
g_lasttimezone = null;
}
}
function gtFlagMove() {
var positionInfo = myFlagtip.getBoundingClientRect();
myFlagtip.style.left = getMouseX() + 15 + "px";
myFlagtip.style.top = getMouseY() - positionInfo.height - 5 + "px";
}
var g_lastDataGridUp = null;
function mouseOverDataItem(mouseEvent, fromHover) {
if (g_MyGridIsUp) return;
if (g_lastDataGridUp && g_lastDataGridUp == mouseEvent) {
mouseMoveDataItem(mouseEvent);
return;
}
if (g_mapSettings.mouseOver == true && fromHover == false) return;
if (g_mapSettings.mouseOver == false && fromHover == true) return;
g_lastDataGridUp = mouseEvent;
var myTooltip = null;
var callListLength = 0;
var isFlag = false;
myTooltip = document.getElementById("myTooltip");
callListLength = createTooltTipTable(mouseEvent);
var positionInfo = myTooltip.getBoundingClientRect();
var windowWidth = window.innerWidth;
var top = 0;
var noRoomLeft = false;
var noRoomRight = false;
if (
typeof mouseEvent.spot != "undefined" &&
g_receptionReports.spots[mouseEvent.spot].bearing > 180
)
noRoomRight = true;
myTooltip.style.left = getMouseX() + 15 + "px";
top = parseInt(getMouseY() - 20 - (callListLength / 2) * 25);
if (windowWidth - getMouseX() < positionInfo.width || noRoomRight == true) {
myTooltip.style.left = getMouseX() - (10 + positionInfo.width) + "px";
top = parseInt(getMouseY() - 20 - (callListLength / 2) * 25);
noRoomRight = true;
}
if (getMouseX() - positionInfo.width < 0) {
noRoomLeft = true;
}
if (noRoomLeft == true && noRoomRight == true) {
myTooltip.style.left = getMouseX() - positionInfo.width / 2 + "px";
top = getMouseY() + 30;
}
if (top < 0) top = 0;
myTooltip.style.top = top + "px";
myTooltip.style.zIndex = 500;
myTooltip.style.display = "block";
}
function mouseMoveDataItem(mouseEvent) {
var myTooltip = document.getElementById("myTooltip");
var positionInfo = myTooltip.getBoundingClientRect();
var windowWidth = window.innerWidth;
var top = 0;
var noRoomLeft = false;
var noRoomRight = false;
if (
typeof mouseEvent.spot != "undefined" &&
g_receptionReports.spots[mouseEvent.spot].bearing > 180
)
noRoomRight = true;
myTooltip.style.left = getMouseX() + 15 + "px";
top = Number(myTooltip.style.top);
if (top > 20) top = getMouseY() - 20 + "px";
if (windowWidth - getMouseX() < positionInfo.width || noRoomRight == true) {
myTooltip.style.left = getMouseX() - (10 + positionInfo.width) + "px";
if (top > 20) top = getMouseY() - 20 + "px";
noRoomRight = true;
}
if (getMouseX() - positionInfo.width < 0) {
noRoomLeft = true;
}
if (noRoomLeft == true && noRoomRight == true) {
myTooltip.style.left = getMouseX() - positionInfo.width / 2 + "px";
top = getMouseY() + 30;
}
if (top < 0) top = 0;
myTooltip.style.top = top + "px";
}
function mouseOutOfDataItem(mouseEvent) {
var myTooltip = document.getElementById("myTooltip");
myTooltip.style.zIndex = -1;
g_lastDataGridUp = null;
if (g_spotsEnabled == 1) g_layerSources["psk-hop"].clear();
}
function reloadInfo(bandOrMode) {
if (g_statsWindowHandle != null) {
try {
g_statsWindowHandle.window.reloadInfo();
} catch (e) {}
}
}
function twoWideToLatLong(qth) {
qth = qth.toUpperCase();
var a = qth.charCodeAt(0) - 65;
var b = qth.charCodeAt(1) - 65;
var la1 = b * 10;
var lo1 = a * 20;
var la2 = la1 + 10;
var lo2 = lo1 + 20;
var LatLong = [];
la1 -= 90;
lo1 -= 180;
la2 -= 90;
lo2 -= 180;
LatLong.la1 = la1;
LatLong.lo1 = lo1;
LatLong.la2 = la2;
LatLong.lo2 = lo2;
return LatLong;
}
function squareToLatLongAll(qth) {
qth = qth.toUpperCase();
var a = qth.charCodeAt(0) - 65;
var b = qth.charCodeAt(1) - 65;
var c = qth.charCodeAt(2) - 48;
var d = qth.charCodeAt(3) - 48;
var la1 = b * 10 + d;
var lo1 = a * 20 + c * 2;
var la2;
var lo2;
var LatLong = [];
if (qth.length == 4) {
la2 = la1 + 1;
lo2 = lo1 + 2;
LatLong.size = 4;
} else {
var lo3;
var la3;
var e = qth.charCodeAt(4) - 65;
var f = qth.charCodeAt(5) - 65;
var R = 5 / 60;
var T = 2.5 / 60;
lo3 = (e * 5) / 60;
la3 = (f * 2.5) / 60;
la1 += la3;
lo1 += lo3;
la2 = la1 + T;
lo2 = lo1 + R;
LatLong.size = 6;
}
la1 -= 90;
lo1 -= 180;
la2 -= 90;
lo2 -= 180;
LatLong.la1 = la1;
LatLong.lo1 = lo1;
LatLong.la2 = la2;
LatLong.lo2 = lo2;
return LatLong;
}
function squareToLatLong(qth) {
qth = qth.toUpperCase();
var a = qth.charCodeAt(0) - 65;
var b = qth.charCodeAt(1) - 65;
var c = qth.charCodeAt(2) - 48;
var d = qth.charCodeAt(3) - 48;
var la1 = b * 10 + d;
var lo1 = a * 20 + c * 2;
var la2;
var lo2;
var LatLong = [];
if (qth.length == 4 || g_appSettings.sixWideMode == 0) {
la2 = la1 + 1;
lo2 = lo1 + 2;
LatLong.size = 4;
} else {
var lo3;
var la3;
var e = qth.charCodeAt(4) - 65;
var f = qth.charCodeAt(5) - 65;
var R = 5 / 60;
var T = 2.5 / 60;
lo3 = (e * 5) / 60;
la3 = (f * 2.5) / 60;
la1 += la3;
lo1 += lo3;
la2 = la1 + T;
lo2 = lo1 + R;
LatLong.size = 6;
}
la1 -= 90;
lo1 -= 180;
la2 -= 90;
lo2 -= 180;
LatLong.la1 = la1;
LatLong.lo1 = lo1;
LatLong.la2 = la2;
LatLong.lo2 = lo2;
return LatLong;
}
function iconFeature(center, iconObj, zIndex) {
var feature = new ol.Feature({
geometry: new ol.geom.Point(center),
name: "pin",
});
var iconStyle = new ol.style.Style({
zIndex: zIndex,
image: iconObj,
});
feature.setStyle(iconStyle);
return feature;
}
function qthToQsoBox(
iQTH,
iHash,
iCQ,
iNew,
locked,
DE,
worked,
confirmed,
band,
wspr
) {
if (g_appSettings.gridViewMode == 1) return null;
var borderColor = "#222288FF";
var boxColor = "#0000FF" + g_gridAlpha;
var borderWeight = 0.5;
var myDEzOffset = 10;
var myDEbox = false;
if (worked) {
boxColor = "#FFFF00" + g_gridAlpha;
borderColor = g_qsoWorkedBorderColor;
}
if (confirmed) {
boxColor = "#FF0000" + g_gridAlpha;
borderColor = g_qsoWorkedBorderColor;
}
if (wspr != null) {
boxColor = "hsl(" + wspr + ",100%,50%)";
borderColor = "gray";
}
var zIndex = 2;
var entityVisibility = Number(g_appSettings.gridViewMode) > 1 ? true : false;
var returnRectangle = null;
if (g_appSettings.sixWideMode == 0) iQTH = iQTH.substr(0, 4);
else iQTH = iQTH.substr(0, 6);
var rect = null;
if (iQTH == "") {
for (var key in g_qsoGrids) {
if (iHash in g_qsoGrids[key].rectangle.hashes) {
rect = g_qsoGrids[key];
break;
}
}
} else {
if (iQTH in g_qsoGrids) {
rect = g_qsoGrids[iQTH];
}
}
if (rect == null) {
if (iQTH != "") {
// Valid QTH
var triangleView = false;
if (
Number(g_appSettings.gridViewMode) == 3 &&
iQTH in g_liveGrids &&
entityVisibility == true &&
g_pushPinMode == false
) {
if (confirmed) {
hideLiveGrid(iQTH);
} else {
liveTriangleGrid(iQTH);
triangleView = true;
}
}
LL = squareToLatLong(iQTH);
if (LL.size == 6) {
borderColor = "#000000FF";
zIndex = 50;
}
newRect = {};
newRect.shouldDim = false;
newRect.qth = iQTH;
var bounds = [
[LL.lo1, LL.la1],
[LL.lo2, LL.la2],
];
if (triangleView == true) newRect.rectangle = triangle(bounds, true);
else newRect.rectangle = rectangle(bounds);
newRect.isTriangle = triangleView;
const featureHoverStyle = new ol.style.Style({
fill: new ol.style.Fill({
color: boxColor,
}),
stroke: new ol.style.Stroke({
color: borderColor,
width: borderWeight,
lineJoin: "round",
}),
zIndex: zIndex,
});
newRect.rectangle.setStyle(featureHoverStyle);
newRect.rectangle.qth = iQTH;
if (g_pushPinMode == false && entityVisibility == true)
g_layerSources["qso"].addFeature(newRect.rectangle);
var newPin = g_colorLeafletQPins.worked[band];
if (confirmed) newPin = g_colorLeafletQPins.confirmed[band];
newRect.rectangle.pin = iconFeature(
ol.extent.getCenter(newRect.rectangle.getGeometry().getExtent()),
g_appSettings.sixWideMode == 1 ? newPin : g_pushPinIconOff,
zIndex
);
newRect.rectangle.pin.qth = iQTH;
newRect.rectangle.pin.hashes = {};
newRect.rectangle.pin.hashes[iHash] = 1;
newRect.rectangle.pin.size = LL.size;
if (g_pushPinMode && entityVisibility == true)
g_layerSources["qso-pins"].addFeature(newRect.rectangle.pin);
newRect.rectangle.locked = locked;
newRect.rectangle.worked = worked;
newRect.rectangle.confirmed = confirmed;
newRect.rectangle.size = LL.size;
newRect.rectangle.hashes = {};
newRect.rectangle.hashes[iHash] = 1;
newRect.rectangle.qso = true;
newRect.rectangle.pin.qso = true;
g_qsoGrids[iQTH] = newRect;
returnRectangle = newRect.rectangle;
}
} else {
if (!(iHash in rect.rectangle.hashes)) {
rect.rectangle.hashes[iHash] = 1;
rect.rectangle.pin.hashes[iHash] = 1;
}
if (!confirmed && rect.rectangle.confirmed) {
return rect.rectangle;
}
if (worked && !rect.rectangle.worked) rect.rectangle.worked = worked;
if (confirmed && !rect.rectangle.confirmed)
rect.rectangle.confirmed = confirmed;
borderColor = g_qsoWorkedBorderColor;
if (myDEbox) borderWeight = 1;
zIndex = 2;
if (rect.rectangle.size == 6) {
borderColor = "#000000FF";
zIndex = 50;
}
rect.shouldDim = false;
const featureHoverStyle = new ol.style.Style({
fill: new ol.style.Fill({
color: boxColor,
}),
stroke: new ol.style.Stroke({
color: borderColor,
width: borderWeight,
lineJoin: "round",
}),
zIndex: zIndex,
});
rect.rectangle.setStyle(featureHoverStyle);
returnRectangle = rect.rectangle;
}
return returnRectangle;
}
function qthToBox(iQTH, iDEcallsign, iCQ, iNew, locked, DE, band, wspr, hash) {
if (g_appSettings.gridViewMode == 2) return null;
var borderColor = "#222288FF";
var boxColor = "#1111FF" + g_gridAlpha;
var borderWeight = 0.5;
var myDEzOffset = 0;
var myDEbox = false;
if (iCQ && iNew) {
borderColor = "#008888FF";
boxColor = "#00FF00" + g_gridAlpha;
} else if (iCQ && !iNew) {
borderColor = "#FFFF00FF";
boxColor = "#FFFF00" + g_gridAlpha;
}
if (DE == myDEcall) {
borderColor = "#FF0000FF";
boxColor = "#FFFF00" + g_gridAlpha;
borderWeight = 1.0;
myDEzOffset = 20;
myDEbox = true;
}
if (DE.indexOf("CQ DX") > -1) {
borderColor = "#008888FF";
boxColor = "#00FFFF" + g_gridAlpha;
}
if (locked) {
boxColor = "#FFA500" + g_gridAlpha;
borderColor = "#000000FF";
borderOpacity = 1;
}
if (wspr != null) {
boxColor = "hsl(" + wspr + ",100%,50%)";
borderColor = "gray";
//borderWeight = 1;
}
var zIndex = 2;
var returnRectangle = null;
if (g_appSettings.sixWideMode == 0) iQTH = iQTH.substr(0, 4);
else iQTH = iQTH.substr(0, 6);
var rect = null;
if (iQTH == "") {
for (var key in g_liveGrids) {
if (hash in g_liveGrids[key].rectangle.liveHash) {
rect = g_liveGrids[key];
break;
}
}
} else {
if (iQTH in g_liveGrids) {
rect = g_liveGrids[iQTH];
}
}
if (rect == null) {
if (iQTH != "") {
// Valid QTH
var entityVisibility = true;
var triangleView = false;
if (
Number(g_appSettings.gridViewMode) == 3 &&
iQTH in g_qsoGrids &&
g_pushPinMode == false
) {
if (
g_mapSettings.splitQSL ||
g_qsoGrids[iQTH].rectangle.confirmed == false
) {
qsoTriangleGrid(iQTH);
triangleView = true;
entityVisibility = true;
} else entityVisibility = false;
}
LL = squareToLatLong(iQTH);
if (LL.size == 6) {
borderColor = "#000000FF";
//borderWeight = 1.0;
zIndex = 50;
}
newRect = {};
newRect.age = g_timeNow;
newRect.shouldDim = false;
newRect.qth = iQTH;
var bounds = [
[LL.lo1, LL.la1],
[LL.lo2, LL.la2],
];
if (triangleView == true) newRect.rectangle = triangle(bounds, false);
else newRect.rectangle = rectangle(bounds);
newRect.isTriangle = triangleView;
newRect.rectangle.setId(iQTH);
const featureHoverStyle = new ol.style.Style({
fill: new ol.style.Fill({
color: boxColor,
}),
stroke: new ol.style.Stroke({
color: borderColor,
width: borderWeight,
lineJoin: "round",
}),
zIndex: zIndex,
});
newRect.rectangle.setStyle(featureHoverStyle);
newRect.rectangle.qth = iQTH;
if (g_pushPinMode == false && entityVisibility) {
g_layerSources["live"].addFeature(newRect.rectangle);
}
newRect.rectangle.pin = iconFeature(
ol.extent.getCenter(newRect.rectangle.getGeometry().getExtent()),
g_colorLeafletPins[band],
zIndex
);
newRect.rectangle.pin.qth = iQTH;
newRect.rectangle.pin.liveHash = {};
newRect.rectangle.pin.liveHash[hash] = 1;
newRect.rectangle.pin.size = LL.size;
if (g_pushPinMode && entityVisibility == true)
g_layerSources["live-pins"].addFeature(newRect.rectangle.pin);
newRect.rectangle.locked = locked;
newRect.rectangle.size = LL.size;
newRect.rectangle.liveHash = {};
newRect.rectangle.liveHash[hash] = 1;
newRect.rectangle.qso = false;
newRect.rectangle.pin.qso = false;
g_liveGrids[iQTH] = newRect;
returnRectangle = newRect.rectangle;
}
} else {
if (!(hash in rect.rectangle.liveHash)) {
rect.rectangle.liveHash[hash] = 1;
rect.rectangle.pin.liveHash[hash] = 1;
}
if (locked && !rect.rectangle.locked) rect.rectangle.locked = locked;
if (rect.rectangle.locked) {
borderColor = "#000000FF";
}
if (myDEbox) borderWeight = 1;
if (rect.rectangle.size == 6) {
borderColor = "#000000FF";
//borderWeight = 1.0;
zIndex = 50;
}
newRect.age = g_timeNow;
newRect.shouldDim = false;
const featureHoverStyle = new ol.style.Style({
fill: new ol.style.Fill({
color: boxColor,
}),
stroke: new ol.style.Stroke({
color: borderColor,
width: borderWeight,
lineJoin: "round",
}),
zIndex: zIndex,
});
rect.rectangle.setStyle(featureHoverStyle);
returnRectangle = rect.rectangle;
}
return returnRectangle;
}
function alphaFrom(rgba) {
var alphaInt = hexToA(rgba);
var alphaFloat = alphaInt / 255.0;
return alphaFloat;
}
function alphaTo(rgba, alphaFloat) {
var alphaInt = parseInt(alphaFloat * 255);
var alphaHex = alphaInt.toString(16);
if (alphaHex.length == 1) {
alphaHex = "0" + alphaHex;
}
return rgba.slice(0, -2) + alphaHex;
}
function intAlphaToRGB(rgb, alphaInt) {
var alphaHex = alphaInt.toString(16);
if (alphaHex.length == 1) {
alphaHex = "0" + alphaHex;
}
return rgb + alphaHex;
}
function dimFunction(qthObj) {
if (qthObj.rectangle.locked == false) {
var featureStyle = qthObj.rectangle.getStyle();
var featureFill = featureStyle.getFill();
var fillColor = featureFill.getColor();
var featureStroke = featureStyle.getStroke();
var strokeColor = featureStroke.getColor();
var percent = 1.0 - (g_timeNow - qthObj.age) / gridDecay.value;
var alpha = Math.max(0.06, (g_mapSettings.gridAlpha / 255) * percent);
fillColor = alphaTo(fillColor, alpha);
featureFill.setColor(fillColor);
featureStyle.setFill(featureFill);
strokeColor = alphaTo(strokeColor, alpha);
featureStroke.setColor(strokeColor);
featureStyle.setStroke(featureStroke);
qthObj.rectangle.setStyle(featureStyle);
}
}
function toggleTrafficDecode() {
trafficDecode.checked = trafficDecode.checked == true ? false : true;
changeTrafficDecode();
}
function changeTrafficDecode() {
g_mapSettings.trafficDecode = trafficDecode.checked;
trafficDecodeView();
saveMapSettings();
}
function trafficDecodeView() {
if (g_mapSettings.trafficDecode == false) {
trafficDiv.innerHTML = "";
g_lastTraffic = Array();
}
}
function changeFitQRZvalue() {
g_mapSettings.fitQRZ = fitQRZvalue.checked;
saveMapSettings();
}
function changeQrzDxccFallbackValue() {
g_mapSettings.qrzDxccFallback = qrzDxccFallbackValue.checked;
saveMapSettings();
}
function changeCqHiliteValue(check) {
g_mapSettings.CQhilite = check.checked;
saveMapSettings();
if (check.checked == false) removePaths();
}
function changeFocusRigValue(check) {
g_mapSettings.focusRig = check.checked;
saveMapSettings();
}
function changeHaltOntTxValue(check) {
g_mapSettings.haltAllOnTx = check.checked;
saveMapSettings();
}
function changeStrikesAlert() {
g_mapSettings.strikesAlert = strikesAlert.value;
saveMapSettings();
playStrikeAlert();
}
function playStrikeAlert() {
if (g_mapSettings.strikesAlert > 0) {
var filename = g_mediaDir + g_dirSeperator;
if (g_mapSettings.strikesAlert == 1) filename += "short-strike.wav";
if (g_mapSettings.strikesAlert == 2) filename += "long-strike.mp3";
if (g_mapSettings.strikesAlert == 3) filename += "strike-detected.mp3";
var audio = document.createElement("audio");
audio.src = "file://" + filename;
audio.setSinkId(g_soundCard);
audio.volume = g_audioSettings.volume;
audio.play();
}
}
function setStrikesButton() {
if (g_mapSettings.strikes) {
strikesImg.style.webkitFilter = "";
} else {
strikesImg.style.webkitFilter = "grayscale(1)";
}
}
function toggleStrikesValue() {
if (g_mapSettings.strikesNotify == false && g_mapSettings.strikes == false) {
var confirmed = window.confirm(
"Lighting Strike Detection is provided by Blitzortung.org\nWe are not responsible for missed strikes that could result in damage.\nBe sure to check your local weather providers for accurate data."
);
if (confirmed == false) {
return;
} else {
g_mapSettings.strikesNotify = true;
}
}
g_mapSettings.strikes = g_mapSettings.strikes == true ? false : true;
setStrikesButton();
saveMapSettings();
}
function changeSplitQSL() {
g_mapSettings.splitQSL = splitQSLValue.checked;
saveMapSettings();
redrawGrids();
}
function setAnimateView() {
if (animateValue.checked) {
animationSpeedTd.style.display = "inline-table";
} else {
animationSpeedTd.style.display = "none";
}
}
function toggleAnimate() {
animateValue.checked = animateValue.checked == true ? false : true;
changeAnimate();
}
function toggleAllGrids() {
g_showAllGrids = g_showAllGrids ? false : true;
setTrophyOverlay(g_currentOverlay);
}
function changeAnimate() {
g_mapSettings.animate = animateValue.checked;
saveMapSettings();
var dash = [];
var dashOff = 0;
if (g_mapSettings.animate == true) {
dash = g_flightPathLineDash;
dashOff = g_flightPathTotal - g_flightPathOffset;
}
for (var i = g_flightPaths.length - 1; i >= 0; i--) {
if (g_flightPaths[i].isShapeFlight == 0) {
var featureStyle = g_flightPaths[i].getStyle();
var featureStroke = featureStyle.getStroke();
featureStroke.setLineDash(dash);
featureStroke.setLineDashOffset(dashOff);
featureStyle.setStroke(featureStroke);
g_flightPaths[i].setStyle(featureStyle);
}
}
if (g_transmitFlightPath != null) {
var featureStyle = g_transmitFlightPath.getStyle();
var featureStroke = featureStyle.getStroke();
featureStroke.setLineDash(dash);
featureStroke.setLineDashOffset(dashOff);
featureStyle.setStroke(featureStroke);
g_transmitFlightPath.setStyle(featureStyle);
}
setAnimateView();
}
function changeAnimateSpeedValue() {
g_mapSettings.animateSpeed = 21 - animateSpeedValue.value;
saveMapSettings();
}
var g_animateFrame = 0;
var g_nextDimTime = 0;
var g_last = 0;
function animatePaths() {
requestAnimationFrame(animatePaths);
g_last ^= g_last;
if (g_last == 1) return;
g_animateFrame++;
g_animateFrame %= g_mapSettings.animateSpeed;
if (g_animateFrame > 0) return;
for (var i = g_flightPaths.length - 1; i >= 0; i--) {
if (g_flightPaths[i].age < g_timeNow) {
if (typeof g_flightPaths[i].Arrow != "undefined")
g_layerSources["flight"].removeFeature(g_flightPaths[i].Arrow);
g_layerSources["flight"].removeFeature(g_flightPaths[i]);
delete g_flightPaths[i];
g_flightPaths[i] = null;
g_flightPaths.splice(i, 1);
}
}
if (g_timeNow > g_nextDimTime) {
dimGridsquare();
}
if (g_mapSettings.animate == false) return;
g_flightPathOffset += 1;
g_flightPathOffset %= g_flightPathTotal;
var targetOffset = g_flightPathTotal - g_flightPathOffset;
var featureStyle = null;
var featureStroke = null;
for (var i = 0; i < g_flightPaths.length; i++) {
if (g_flightPaths[i].isShapeFlight == 0) {
featureStyle = g_flightPaths[i].getStyle();
featureStroke = featureStyle.getStroke();
featureStroke.setLineDashOffset(targetOffset);
g_flightPaths[i].setStyle(featureStyle);
}
}
if (g_transmitFlightPath != null) {
var featureStyle = g_transmitFlightPath.getStyle();
var featureStroke = featureStyle.getStroke();
featureStroke.setLineDashOffset(targetOffset);
featureStyle.setStroke(featureStroke);
g_transmitFlightPath.setStyle(featureStyle);
}
}
function removePaths() {
g_layerSources["flight"].clear();
g_flightPaths = Array();
}
function fadePaths() {
if (pathWidthValue.value == 0) {
removePaths();
return;
}
}
function dimGridsquare() {
if (gridDecay.value == 0) return;
for (var i in g_liveGrids) {
dimFunction(g_liveGrids[i]);
if (
g_timeNow - g_liveGrids[i].age >= gridDecay.value &&
g_liveGrids[i].rectangle.locked == false
) {
// Walk the rectangles DEcall's and remove them from g_liveCallsigns
for (var CallIsKey in g_liveGrids[i].rectangle.liveHash) {
if (CallIsKey in g_liveCallsigns) {
g_liveCallsigns[CallIsKey].rect = null;
delete g_liveCallsigns[CallIsKey];
}
}
if (g_liveGrids[i].rectangle.pin != null) {
if (
g_layerSources["live-pins"].hasFeature(g_liveGrids[i].rectangle.pin)
)
g_layerSources["live-pins"].removeFeature(
g_liveGrids[i].rectangle.pin
);
}
if (g_layerSources["live"].hasFeature(g_liveGrids[i].rectangle)) {
g_layerSources["live"].removeFeature(g_liveGrids[i].rectangle);
if (Number(g_appSettings.gridViewMode) == 3 && i in g_qsoGrids) {
if (g_qsoGrids[i].isTriangle) {
triangleToGrid(i, g_qsoGrids[i].rectangle);
g_qsoGrids[i].isTriangle = false;
}
}
}
g_liveGrids[i] = null;
delete g_liveGrids[i];
}
}
g_nextDimTime = g_timeNow + 7;
}
function updateCountStats() {
var count = Object.keys(g_liveCallsigns).length;
if (myDEcall in g_liveCallsigns) count--;
callsignCount.innerHTML = count;
qsoCount.innerHTML = g_QSOcount;
qslCount.innerHTML = g_QSLcount;
countryCount.innerHTML = Object.keys(g_dxccCount).length;
if (Object.keys(g_QSOhash).length > 0) {
clearOrLoadButton.innerHTML = "Clear Log";
g_loadQSOs = false;
} else {
clearOrLoadButton.innerHTML = "Load Logs";
g_loadQSOs = true;
}
}
function clearGrids() {
g_layerSources["live"].clear();
g_layerSources["live-pins"].clear();
for (var i in g_liveGrids) {
// Walk the rectangles DEcall's and remove the rect from the g_liveCallsigns
for (var CallIsKey in g_liveGrids[i].rectangle.liveHash) {
if (CallIsKey in g_liveCallsigns) g_liveCallsigns[CallIsKey].rect = null;
}
}
g_liveGrids = {};
}
function clearQsoGrids() {
g_layerSources["qso"].clear();
g_layerSources["qso-pins"].clear();
g_qsoGrids = {};
for (var key in g_worldGeoData) {
g_worldGeoData[key].worked = false;
g_worldGeoData[key].confirmed = false;
g_worldGeoData[key].worked_bands = {};
g_worldGeoData[key].confirmed_bands = {};
g_worldGeoData[key].worked_modes = {};
g_worldGeoData[key].confirmed_modes = {};
}
for (var key in g_cqZones) {
g_cqZones[key].worked = false;
g_cqZones[key].confirmed = false;
g_cqZones[key].worked_bands = {};
g_cqZones[key].confirmed_bands = {};
g_cqZones[key].worked_modes = {};
g_cqZones[key].confirmed_modes = {};
}
for (var key in g_ituZones) {
g_ituZones[key].worked = false;
g_ituZones[key].confirmed = false;
g_ituZones[key].worked_bands = {};
g_ituZones[key].confirmed_bands = {};
g_ituZones[key].worked_modes = {};
g_ituZones[key].confirmed_modes = {};
}
for (var key in g_wasZones) {
g_wasZones[key].worked = false;
g_wasZones[key].confirmed = false;
g_wasZones[key].worked_bands = {};
g_wasZones[key].confirmed_bands = {};
g_wasZones[key].worked_modes = {};
g_wasZones[key].confirmed_modes = {};
}
for (var key in g_wacZones) {
g_wacZones[key].worked = false;
g_wacZones[key].confirmed = false;
g_wacZones[key].worked_bands = {};
g_wacZones[key].confirmed_bands = {};
g_wacZones[key].worked_modes = {};
g_wacZones[key].confirmed_modes = {};
}
for (var key in g_countyData) {
g_countyData[key].worked = false;
g_countyData[key].confirmed = false;
g_countyData[key].worked_bands = {};
g_countyData[key].confirmed_bands = {};
g_countyData[key].worked_modes = {};
g_countyData[key].confirmed_modes = {};
}
for (var key in g_us48Data) {
g_us48Data[key].worked = false;
g_us48Data[key].confirmed = false;
g_us48Data[key].worked_bands = {};
g_us48Data[key].confirmed_bands = {};
g_us48Data[key].worked_modes = {};
g_us48Data[key].confirmed_modes = {};
}
}
function clearCalls() {
removePaths();
for (var i in g_liveCallsigns) {
if (
typeof g_liveCallsigns[i].rect != "undefined" &&
g_liveCallsigns[i].rect != null
) {
if (i in g_liveCallsigns[i].rect.liveHash)
delete g_liveCallsigns[i].rect.liveHash[i];
}
}
g_liveCallsigns = {};
g_dxccCount = {};
redrawGrids();
}
function clearLive() {
g_Decodes = 0;
g_lastMessages = Array();
g_lastTraffic = Array();
g_callRoster = {};
g_dxccCount = {};
removePaths();
removePaths();
clearGrids();
clearCalls();
clearTempGrids();
setHomeGridsquare();
redrawGrids();
updateRosterWorked();
goProcessRoster();
}
function clearAll() {
clearTempGrids();
clearCalls();
clearQSOs();
g_lastMessages = Array();
g_lastTraffic = Array();
g_dxccCount = {};
redrawGrids();
g_callRoster = {};
updateRosterWorked();
goProcessRoster();
}
function clearOrLoadQSOs() {
if (g_loadQSOs == true) {
startupAdifLoadCheck();
} else {
clearQSOs();
}
}
function clearAndLoadQSOs() {
initQSOdata();
g_QSOhash = {};
g_QSLcount = 0;
g_QSOcount = 0;
setTrophyOverlay(g_currentOverlay);
redrawGrids();
updateLogbook();
updateRosterWorked();
goProcessRoster();
startupAdifLoadCheck();
}
function clearQSOs() {
initQSOdata();
g_QSOhash = {};
g_QSLcount = 0;
g_QSOcount = 0;
setTrophyOverlay(g_currentOverlay);
redrawGrids();
updateLogbook();
updateRosterWorked();
goProcessRoster();
clearLogFilesAndCounts();
}
function clearLogFilesAndCounts() {
tryToDeleteLog("lotw_QSL.adif");
tryToDeleteLog("lotw_QSO.adif");
tryToDeleteLog("lotw.adif");
tryToDeleteLog("qrz.adif");
tryToDeleteLog("clublog.adif");
g_adifLogSettings.downloads = {};
localStorage.adifLogSettings = JSON.stringify(g_adifLogSettings);
}
function getCurrentBandModeHTML() {
var band =
g_appSettings.gtBandFilter == "auto"
? myBand + " (Auto)"
: g_appSettings.gtBandFilter.length == 0
? "Mixed Bands"
: g_appSettings.gtBandFilter;
var mode =
g_appSettings.gtModeFilter == "auto"
? myMode + " (Auto)"
: g_appSettings.gtModeFilter.length == 0
? "Mixed Modes"
: g_appSettings.gtModeFilter;
return (
"<div style='vertical-align:top;display:inline-block;margin-bottom:3px;color:lightgreen;font-weight:bold;font-size:larger'>Viewing: <text style='color:yellow'>" +
band +
"</text> / <text style='color:orange'>" +
mode +
"</text></b></div><br/>"
);
}
var displayTimeInterval = null;
var g_currentDay = 0;
var g_nightTime = false;
var g_currentNightState = false;
var g_timeNow = timeNowSec();
function displayTime() {
g_timeNow = timeNowSec();
if (menuDiv.className == "menuDivStart" && g_menuShowing == true) {
menuDiv.className = "menuDivEnd";
mapDiv.className = "mapDivEnd";
LegendDiv.className = "legendDivEnd";
g_map.updateSize();
}
currentTime.innerHTML =
"<font color='lightblue'>" + userTimeString(null) + "</font>";
if (g_lastTimeSinceMessageInSeconds > 0) {
var since = g_timeNow - g_lastTimeSinceMessageInSeconds;
secondsAgoMsg.innerHTML = since.toDHMS();
if (since > 17 && since < 122) {
secondsAgoMsg.style.backgroundColor = "yellow";
secondsAgoMsg.style.color = "#000";
} else if (since > 121) {
secondsAgoMsg.style.backgroundColor = "red";
secondsAgoMsg.style.color = "#000";
} else {
secondsAgoMsg.style.backgroundColor = "blue";
secondsAgoMsg.style.color = "#FF0";
}
} else secondsAgoMsg.innerHTML = "<b>Never</b>";
checkWsjtxListener();
if (g_timeNow % 22 == 0) {
g_nightTime = dayNight.refresh();
moonLayer.refresh();
}
pskSpotCheck(g_timeNow);
if (g_mapSettings.strikes && g_mapSettings.offlineMode == false) {
if (g_strikeWebSocket == null) loadStrikes();
var now = Date.now();
for (var time in g_bolts) {
if (now - time > 120000) {
if (g_layerSources["strikes"].hasFeature(g_bolts[time]))
g_layerSources["strikes"].removeFeature(g_bolts[time]);
delete g_bolts[time];
}
}
} else {
g_layerSources["strikes"].clear();
if (g_strikeWebSocket != null) {
try {
g_strikeWebSocket.close();
} catch (e) {
g_strikeWebSocket = null;
}
}
}
if (g_currentNightState != g_nightTime) {
changeMapLayer();
g_currentNightState = g_nightTime;
}
}
function timeNowSec() {
return parseInt(Date.now() / 1000);
}
var g_geo = null;
var g_feats = null;
var g_liveHoverInteraction = null;
var g_gtFlagHoverInteraction = null;
var g_trophyHoverInteraction = null;
function createGlobalHeatmapLayer(name, radius, blur) {
g_layerSources[name] = new ol.source.Vector({});
g_layerVectors[name] = new ol.layer.Heatmap({
source: g_layerSources[name],
zIndex: Object.keys(g_layerVectors).length + 1,
});
g_layerVectors[name].set("name", name);
}
function createGlobalMapLayer(name, maxResolution, minResolution) {
g_layerSources[name] = new ol.source.Vector({});
if (
typeof maxResolution == "undefined" &&
typeof minResolution == "undefined"
) {
var zIndex = Object.keys(g_layerVectors).length + 1;
if (name == "strikes") zIndex = 2000;
g_layerVectors[name] = new ol.layer.Vector({
source: g_layerSources[name],
zIndex: zIndex,
});
} else if (typeof minResolution == "undefined") {
g_layerVectors[name] = new ol.layer.Vector({
source: g_layerSources[name],
maxResolution: maxResolution,
zIndex: Object.keys(g_layerVectors).length + 1,
});
} else {
g_layerVectors[name] = new ol.layer.Vector({
source: g_layerSources[name],
maxResolution: maxResolution,
minResolution: minResolution,
zIndex: Object.keys(g_layerVectors).length + 1,
});
}
g_layerVectors[name].set("name", name);
}
function createGeoJsonLayer(name, url, color, stroke) {
var style = new ol.style.Style({
stroke: new ol.style.Stroke({
color: color,
width: stroke,
}),
fill: new ol.style.Fill({
color: "#00000000",
}),
});
var layerSource = new ol.source.Vector({
url: url,
format: new ol.format.GeoJSON({ geometryName: name }),
overlaps: false,
});
var layerVector = new ol.layer.Vector({
source: layerSource,
style: style,
visible: true,
zIndex: 1,
});
layerVector.set("name", name);
return layerVector;
}
var g_gtFlagIcon = new ol.style.Icon({
src: "./img/flag_gt_user.png",
anchorYUnits: "pixels",
anchorXUnits: "pixels",
anchor: [12, 17],
});
var g_pushPinIconOff = new ol.style.Icon({
src: "./img/red-circle.png",
anchorYUnits: "pixels",
anchorXUnits: "pixels",
anchor: [5, 18],
});
function panTo(location) {
var duration = 1000;
g_mapView.animate({
center: location,
duration: duration,
});
}
var g_lightningBolt = new ol.style.Icon({
src: "./img/lw.png",
anchorYUnits: "pixels",
anchorXUnits: "pixels",
size: [64, 64],
anchor: [9, 58],
scale: 0.75,
});
var g_lightningGlobal = Array();
g_lightningGlobal[0] = new ol.style.Icon({
src: "./img/l0.png",
anchorYUnits: "pixels",
anchorXUnits: "pixels",
opacity: 0.2,
anchor: [2, 31],
});
g_lightningGlobal[1] = new ol.style.Icon({
src: "./img/l6.png",
anchorYUnits: "pixels",
anchorXUnits: "pixels",
opacity: 0.2,
anchor: [1, 34],
});
var g_bolts = {};
var g_strikeWebSocket = null;
var g_strikeInterval = null;
var g_strikeRange = 0.4;
function toggleStrikeGlobal() {
g_mapSettings.strikesGlobal =
g_mapSettings.strikesGlobal == false ? true : false;
saveMapSettings();
var msg = "Local Strikes";
if (g_mapSettings.strikesGlobal == true) msg = "Global Strikes";
var worker =
"<font color='yellow'>Strike Distance Changed<br/>" + msg + "</font>";
if (g_mapSettings.strikes == false)
worker += "<br/><font color='red'>Detection is not enabled!</font>";
addLastTraffic(worker);
g_layerSources["strikes"].clear();
}
function setStrikeDistance() {
if (
g_mapSettings.offlineMode == true &&
g_strikeWebSocket != null &&
g_strikeWebSocket.readyState != 3
) {
g_strikeWebSocket.close();
return;
}
if (g_strikeWebSocket != null) {
var distance = g_strikeRange;
if (g_mapSettings.strikesGlobal == true) distance = 1000;
var send = '{"west":-180,"east":180,"north":-90,"south":-90}';
if (g_strikeInterval == null)
g_strikeInterval = setInterval(setStrikeDistance, 300000);
try {
g_strikeWebSocket.send(send);
} catch (e) {
delete g_strikeWebSocket;
g_strikeWebSocket = null;
}
} else {
if (g_strikeInterval != null) {
clearInterval(g_strikeInterval);
g_strikeInterval = null;
}
}
}
var g_strikeCount = 0;
function loadStrikes() {
if (g_strikeWebSocket) return;
var rnd = parseInt(Math.random() * 4);
var ws_server = "";
if (rnd < 1) {
ws_server = "ws7.blitzortung.org";
} else if (rnd < 2) {
ws_server = "ws6.blitzortung.org";
} else if (rnd < 3) {
ws_server = "ws5.blitzortung.org";
} else {
ws_server = "ws1.blitzortung.org";
}
try {
g_strikeWebSocket = new WebSocket("wss:///" + ws_server + ":3000");
} catch (e) {
g_strikeWebSocket = null;
return;
}
g_strikeWebSocket.onopen = function () {
setStrikeDistance();
};
g_strikeWebSocket.onmessage = function (evt) {
var Strikes = JSON.parse(evt.data);
Strikes.sig = null;
if (
"delay" in Strikes &&
"time" in Strikes &&
"lat" in Strikes &&
"lon" in Strikes
) {
var index = Date.now();
while (index in g_bolts) index++;
var inRange = true;
if (Math.abs(Strikes.lon - g_myLon) > g_strikeRange) inRange = false;
if (Math.abs(Strikes.lat - g_myLat) > g_strikeRange) inRange = false;
if (
g_mapSettings.strikesGlobal ||
(g_mapSettings.strikesGlobal == false && inRange)
) {
g_bolts[index] = iconFeature(
ol.proj.fromLonLat([Strikes.lon, Strikes.lat]),
inRange ? g_lightningBolt : g_lightningGlobal[0],
1
);
g_layerSources["strikes"].addFeature(g_bolts[index]);
}
if (inRange == true) {
playStrikeAlert();
var dist =
parseInt(
MyCircle.distance(
g_myLat,
g_myLon,
Strikes.lat,
Strikes.lon,
distanceUnit.value
) * MyCircle.validateRadius(distanceUnit.value)
).toLocaleString() +
" " +
distanceUnit.value.toLowerCase();
var azim =
parseInt(
MyCircle.bearing(g_myLat, g_myLon, Strikes.lat, Strikes.lon)
).toLocaleString() + "&deg;";
var worker =
"<font style='color:yellow;font-weight:bold'>Lighting Strike Detected!</font><br/>";
worker +=
"<font style='color:white'>" + userTimeString(null) + "</font><br/>";
worker +=
"<font style='color:orange'>Distance: </font><font style='color:lightblue;font-weight:bold'>" +
dist +
"</font><br/>";
worker +=
"<font style='color:cyan'>Bearing: </font><font style='color:lightgreen;font-weight:bold'>" +
azim +
"</font>";
addLastTraffic(worker);
}
}
delete Strikes;
delete evt.data;
};
g_strikeWebSocket.onerror = function () {
delete g_strikeWebSocket;
g_strikeWebSocket = null;
};
g_strikeWebSocket.onclose = function () {
delete g_strikeWebSocket;
g_strikeWebSocket = null;
};
}
function toggleMouseTrack() {
g_appSettings.mouseTrack ^= 1;
if (g_appSettings.mouseTrack == 0) mouseTrackDiv.style.display = "none";
}
function myGmapNameCompare(a, b) {
return g_maps[a].name.localeCompare(g_maps[b].name);
}
var g_Nexrad = null;
function initMap() {
document.getElementById("mapDiv").innerHTML = "";
g_maps = JSON.parse(fs.readFileSync(g_mapsFile));
if (g_maps) {
var entries = Object.keys(g_maps).sort(myGmapNameCompare);
for (var lmap in entries) {
var key = entries[lmap];
g_mapsLayer[key] = new ol.source.XYZ(g_maps[key]);
var option = document.createElement("option");
option.value = key;
option.text = g_maps[key].name;
mapSelect.appendChild(option);
option = document.createElement("option");
option.value = key;
option.text = g_maps[key].name;
mapNightSelect.appendChild(option);
}
mapSelect.value = g_mapSettings.mapIndex;
mapNightSelect.value = g_mapSettings.nightMapIndex;
} else g_mapsLayer[0] = new ol.source.OSM();
g_offlineLayer = new ol.source.XYZ({
url: "/map/sat/{z}/{x}/{y}.png",
});
if (g_mapSettings.offlineMode)
g_tileLayer = new ol.layer.Tile({
source: g_offlineLayer,
loadTilesWhileInteracting: true,
loadTilesWhileAnimating: true,
});
else
g_tileLayer = new ol.layer.Tile({
source: g_mapsLayer[mapSelect.value],
loadTilesWhileInteracting: true,
loadTilesWhileAnimating: true,
});
g_scaleLine = new ol.control.ScaleLine({
units: g_scaleUnits[g_appSettings.distanceUnit],
});
var g_mapControl = [
g_scaleLine,
new ol.control.Zoom(),
new ol.control.FullScreen({ source: "mainBody" }),
];
createGlobalMapLayer("award");
createGlobalHeatmapLayer("psk-heat", 10, 5);
createGlobalMapLayer("qso");
createGlobalMapLayer("qso-pins");
createGlobalMapLayer("live");
createGlobalMapLayer("live-pins");
createGlobalMapLayer("line-grids");
createGlobalMapLayer("long-grids", 3000);
createGlobalMapLayer("short-grids", 8000, 3001);
createGlobalMapLayer("big-grids", 50000, 3001);
createGlobalMapLayer("psk-flights");
createGlobalMapLayer("psk-spots");
createGlobalMapLayer("psk-hop");
createGlobalMapLayer("flight");
createGlobalMapLayer("transmit");
createGlobalMapLayer("gtflags");
createGlobalMapLayer("temp");
createGlobalMapLayer("tz");
createGlobalMapLayer("radar");
createGlobalMapLayer("strikes");
g_mapView = new ol.View({
center: [g_myLon, g_myLat],
zoomFactor: 1.25,
zoom: g_mapSettings.zoom,
showFullExtent: true,
});
g_map = new ol.Map({
target: "mapDiv",
layers: [
g_tileLayer,
g_layerVectors["award"],
g_layerVectors["psk-heat"],
g_layerVectors["qso"],
g_layerVectors["qso-pins"],
g_layerVectors["live"],
g_layerVectors["live-pins"],
g_layerVectors["line-grids"],
g_layerVectors["long-grids"],
g_layerVectors["short-grids"],
g_layerVectors["big-grids"],
g_layerVectors["psk-flights"],
g_layerVectors["psk-spots"],
g_layerVectors["psk-hop"],
g_layerVectors["flight"],
g_layerVectors["transmit"],
g_layerVectors["gtflags"],
g_layerVectors["temp"],
g_layerVectors["tz"],
g_layerVectors["radar"],
g_layerVectors["strikes"],
],
controls: g_mapControl,
loadTilesWhileInteracting: false,
loadTilesWhileAnimating: false,
view: g_mapView,
});
mapDiv.addEventListener("mousemove", function (event) {
onMouseUpdate(event);
var mousePosition = g_map.getEventPixel(event);
if (g_appSettings.mouseTrack == 1) {
var mouseLngLat = g_map.getEventCoordinate(event);
if (mouseLngLat) {
var LL = ol.proj.toLonLat(mouseLngLat);
var dist =
parseInt(
MyCircle.distance(
g_myLat,
g_myLon,
LL[1],
LL[0],
distanceUnit.value
) * MyCircle.validateRadius(distanceUnit.value)
) + distanceUnit.value.toLowerCase();
var azim =
parseInt(MyCircle.bearing(g_myLat, g_myLon, LL[1], LL[0])) + "&deg;";
var gg = latLonToGridSquare(LL[1], LL[0]);
mouseTrackDiv.innerHTML =
LL[1].toFixed(3) +
", " +
LL[0].toFixed(3) +
" " +
dist +
" " +
azim +
" " +
gg;
mouseTrackDiv.style.display = "block";
}
}
var noFeature = true;
var noFlag = true;
var noAward = true;
var noMoon = true;
var noTimeZone = true;
if (g_map.hasFeatureAtPixel(mousePosition)) {
var features = g_map.getFeaturesAtPixel(mousePosition);
if (features != null) {
features = features.reverse();
var finalGridFeature = null;
for (var index in features) {
if (features[index].geometryName_ == "tz") {
features[index].size = 73;
}
if (typeof features[index].size == "undefined") continue;
if (features[index].size == 99 && finalGridFeature == null) {
moonOver(features[index]);
noMoon = false;
break;
}
if (features[index].size == 2 && g_currentOverlay != 0) {
trophyOver(features[index]);
noAward = false;
break;
}
if (features[index].size == 1) {
mouseOverGtFlag(features[index]);
noFlag = false;
noFeature = true;
break;
}
if (features[index].size == 6) {
noFeature = false;
finalGridFeature = features[index];
}
if (features[index].size == 4 && finalGridFeature == null) {
noFeature = false;
finalGridFeature = features[index];
noFlag = true;
}
if (features[index].size == 73 && finalGridFeature == null) {
mouseOverGtFlag(features[index]);
noFlag = false;
}
}
if (finalGridFeature) {
mouseOverDataItem(finalGridFeature, true);
}
}
}
if (noFeature) mouseOutOfDataItem();
if (noFlag) mouseOutGtFlag();
if (noAward) trophyOut();
if (noMoon) moonOut();
});
//mapDiv.addEventListener('mouseout', mapLoseFocus, false);
mapDiv.addEventListener("mouseleave", mapLoseFocus, false);
mapDiv.addEventListener("contextmenu", function (event) {
event.preventDefault();
});
g_map.on("pointerdown", function (event) {
var shouldReturn = false;
var features = g_map.getFeaturesAtPixel(event.pixel);
if (features != null) {
features = features.reverse();
var finalGridFeature = null;
for (var index in features) {
if (typeof features[index].size == "undefined") continue;
if (features[index].size == 6) {
noFeature = false;
finalGridFeature = features[index];
}
if (features[index].size == 4 && finalGridFeature == null) {
noFeature = false;
finalGridFeature = features[index];
}
if (features[index].size == 1) {
leftClickGtFlag(features[index]);
shouldReturn = true;
}
}
if (finalGridFeature) {
onRightClickGridSquare(finalGridFeature);
shouldReturn = true;
}
}
if (shouldReturn) return true;
if (event.pointerEvent.buttons == 2 && g_currentOverlay == 0) {
mouseDownGrid(ol.proj.toLonLat(event.coordinate), event);
return true;
}
});
g_map.on("pointerup", function (event) {
mouseUpGrid();
if (g_mapSettings.mouseOver == false) mouseOutOfDataItem();
});
document.getElementById("menuDiv").style.display = "block";
dayNight.init(g_map);
if (g_appSettings.earthImgSrc == 1) {
dayNight.hide();
} else {
g_nightTime = dayNight.show();
}
moonLayer.init(g_map);
if (g_appSettings.moonTrack == 1) {
moonLayer.show();
} else {
moonLayer.hide();
}
g_tileLayer.setOpacity(Number(g_mapSettings.loudness));
requestAnimationFrame(animatePaths);
nightMapEnable.checked = g_mapSettings.nightMapEnable;
changeNightMapEnable(nightMapEnable);
}
function changeNightMapEnable(check) {
if (check.checked) {
nightMapTd.style.display = "inline-table";
spotNightPathColorDiv.style.display = "inline-block";
g_mapSettings.nightMapEnable = true;
g_nightTime = dayNight.refresh();
} else {
nightMapTd.style.display = "none";
spotNightPathColorDiv.style.display = "none";
g_mapSettings.nightMapEnable = false;
}
changeMapLayer();
redrawSpots();
saveMapSettings();
}
var g_lasttimezone = null;
var g_nexradInterval = null;
var g_nexradEnable = 0;
function createNexRad() {
var layerSource = new ol.source.TileWMS({
url: "http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0q.cgi",
params: { LAYERS: "nexrad-n0q" },
});
var layerVector = new ol.layer.Tile({
source: layerSource,
visible: true,
zIndex: 900,
});
layerVector.set("name", "radar");
return layerVector;
}
function toggleNexrad() {
g_nexradEnable ^= 1;
if (g_nexradEnable == 1) {
if (g_Nexrad != null) {
g_map.removeLayer(g_Nexrad);
delete g_Nexrad;
}
g_Nexrad = createNexRad();
g_map.addLayer(g_Nexrad);
if (g_nexradInterval == null)
g_nexradInterval = setInterval(nexradRefresh, 600000);
} else {
if (g_nexradInterval != null) {
clearInterval(g_nexradInterval);
g_nexradInterval = null;
}
if (g_Nexrad) {
g_map.removeLayer(g_Nexrad);
delete g_Nexrad;
g_Nexrad = null;
}
}
g_mapSettings.usNexrad = g_nexradEnable == 1 ? true : false;
}
function nexradRefresh() {
if (g_Nexrad != null) {
g_Nexrad.getSource().refresh();
}
}
function collapseMenu(shouldCollapse) {
if (shouldCollapse == true) {
g_menuShowing = false;
mapDiv.className = "mapDivStart";
menuDiv.className = "menuDivStart";
LegendDiv.className = "legendDivStart";
chevronDiv.className = "chevronDivEnd";
} else {
g_menuShowing = true;
chevronDiv.className = "chevronDivStart";
displayTime();
}
g_map.updateSize();
}
function mapLoseFocus() {
mouseOutOfDataItem();
trophyOut();
mouseUpGrid();
moonOut();
mouseOutGtFlag();
}
function lineString(points) {
var thing = new ol.geom.LineString(points);
var rect = new ol.Feature({
geometry: thing,
});
return rect;
}
function rectangle(bounds, options) {
var thing = new ol.geom.Polygon([
[
ol.proj.fromLonLat([bounds[0][0], bounds[0][1]]),
ol.proj.fromLonLat([bounds[0][0], bounds[1][1]]),
ol.proj.fromLonLat([bounds[1][0], bounds[1][1]]),
ol.proj.fromLonLat([bounds[1][0], bounds[0][1]]),
],
]);
var rect = new ol.Feature({
name: "rect",
geometry: thing,
});
return rect;
}
function triangle(bounds, topLeft) {
var thing = null;
if (topLeft) {
thing = new ol.geom.Polygon([
[
ol.proj.fromLonLat([bounds[0][0], bounds[0][1]]),
ol.proj.fromLonLat([bounds[0][0], bounds[1][1]]),
ol.proj.fromLonLat([bounds[1][0], bounds[1][1]]),
ol.proj.fromLonLat([bounds[0][0], bounds[0][1]]),
],
]);
} else {
thing = new ol.geom.Polygon([
[
ol.proj.fromLonLat([bounds[0][0], bounds[0][1]]),
ol.proj.fromLonLat([bounds[1][0], bounds[1][1]]),
ol.proj.fromLonLat([bounds[1][0], bounds[0][1]]),
ol.proj.fromLonLat([bounds[0][0], bounds[0][1]]),
],
]);
}
var rect = new ol.Feature({
name: "rect",
geometry: thing,
});
return rect;
}
function triangleToGrid(iQTH, feature) {
var LL = squareToLatLong(iQTH);
var bounds = [
[LL.lo1, LL.la1],
[LL.lo2, LL.la2],
];
var thing = new ol.geom.Polygon([
[
ol.proj.fromLonLat([bounds[0][0], bounds[0][1]]),
ol.proj.fromLonLat([bounds[0][0], bounds[1][1]]),
ol.proj.fromLonLat([bounds[1][0], bounds[1][1]]),
ol.proj.fromLonLat([bounds[1][0], bounds[0][1]]),
ol.proj.fromLonLat([bounds[0][0], bounds[0][1]]),
],
]);
feature.setGeometry(thing);
}
function gridToTriangle(iQTH, feature, topLeft) {
var LL = squareToLatLong(iQTH);
var bounds = [
[LL.lo1, LL.la1],
[LL.lo2, LL.la2],
];
var thing = null;
if (topLeft) {
thing = new ol.geom.Polygon([
[
ol.proj.fromLonLat([bounds[0][0], bounds[0][1]]),
ol.proj.fromLonLat([bounds[0][0], bounds[1][1]]),
ol.proj.fromLonLat([bounds[1][0], bounds[1][1]]),
ol.proj.fromLonLat([bounds[0][0], bounds[0][1]]),
],
]);
} else {
thing = new ol.geom.Polygon([
[
ol.proj.fromLonLat([bounds[0][0], bounds[0][1]]),
ol.proj.fromLonLat([bounds[1][0], bounds[1][1]]),
ol.proj.fromLonLat([bounds[1][0], bounds[0][1]]),
ol.proj.fromLonLat([bounds[0][0], bounds[0][1]]),
],
]);
}
feature.setGeometry(thing);
}
function liveHash(call, band, mode) {
return call + band + mode;
}
function setHomeGridsquare() {
g_appSettings.centerGridsquare = myDEGrid;
if (g_appSettings.centerGridsquare.length > 0) {
homeQTHInput.value = g_appSettings.centerGridsquare;
}
var hash = myDEcall;
var rect = qthToBox(
myDEGrid,
myDEcall,
false,
false,
true,
"",
myBand,
null,
hash
);
if (typeof rect != "undefined" && rect != null) {
var push = false;
if (!(hash in g_liveCallsigns)) {
newCallsign = {};
push = true;
} else newCallsign = g_liveCallsigns[hash];
newCallsign.DEcall = myDEcall;
newCallsign.grid = myDEGrid;
newCallsign.wspr = null;
newCallsign.msg = myDEGrid;
newCallsign.RSTsent = "-";
newCallsign.RSTrecv = "-";
newCallsign.time = timeNowSec();
newCallsign.delta = -1;
newCallsign.DXcall = "Self";
newCallsign.rect = rect;
newCallsign.mode = myMode;
newCallsign.band = myBand;
newCallsign.worked = false;
newCallsign.confirmed = false;
newCallsign.state = null;
newCallsign.zipcode = null;
newCallsign.cnty = null;
newCallsign.qual = false;
newCallsign.instance = null;
newCallsign.alerted = false;
newCallsign.shouldAlert = false;
g_myDXCC = newCallsign.dxcc = callsignToDxcc(myDEcall);
newCallsign.locked = true;
if (push) g_liveCallsigns[hash] = newCallsign;
}
}
var g_transmitFlightPath = null;
function haltAllTx(allTx = false) {
for (var instance in g_instances) {
if (instance != g_activeInstance || allTx == true) {
var responseArray = Buffer.alloc(1024);
var length = 0;
var port = g_instances[instance].remote.port;
var address = g_instances[instance].remote.address;
length = encodeQUINT32(responseArray, length, 0xadbccbda);
length = encodeQUINT32(responseArray, length, 2);
length = encodeQUINT32(responseArray, length, 8);
length = encodeQUTF8(responseArray, length, instance);
length = encodeQBOOL(responseArray, length, 0);
responseArray = responseArray.slice(0, length);
wsjtUdpMessage(responseArray, responseArray.length, port, address);
}
}
}
function initiateQso(thisCall) {
if (
thisCall in g_callRoster &&
g_callRoster[thisCall].message.instance in g_instances
) {
if (
g_mapSettings.focusRig &&
g_activeInstance != g_callRoster[thisCall].message.instance
) {
activeRig(g_callRoster[thisCall].message.instance);
}
if (g_mapSettings.haltAllOnTx) {
haltAllTx();
}
var newMessage = g_callRoster[thisCall].message;
var responseArray = Buffer.alloc(1024);
var length = 0;
var instance = g_callRoster[thisCall].message.instance;
var port = g_instances[instance].remote.port;
var address = g_instances[instance].remote.address;
length = encodeQUINT32(responseArray, length, newMessage.magic_key);
length = encodeQUINT32(responseArray, length, newMessage.schema_number);
length = encodeQUINT32(responseArray, length, 4);
length = encodeQUTF8(responseArray, length, newMessage.Id);
length = encodeQUINT32(responseArray, length, newMessage.TM);
length = encodeQINT32(responseArray, length, newMessage.SR);
length = encodeQDOUBLE(responseArray, length, newMessage.DT);
length = encodeQUINT32(responseArray, length, newMessage.DF);
length = encodeQUTF8(responseArray, length, newMessage.MO);
length = encodeQUTF8(responseArray, length, newMessage.Msg);
length = encodeQBOOL(responseArray, length, newMessage.LC);
length = encodeQBOOL(responseArray, length, 0);
responseArray = responseArray.slice(0, length);
wsjtUdpMessage(responseArray, responseArray.length, port, address);
}
}
function spotLookupAndSetCall(spot) {
var call = g_receptionReports.spots[spot].call;
var grid = g_receptionReports.spots[spot].grid;
var band = g_receptionReports.spots[spot].band;
var mode = g_receptionReports.spots[spot].mode;
for (var instance in g_instances) {
if (
g_instances[instance].valid &&
g_instances[instance].status.Band == band &&
g_instances[instance].status.MO == mode
) {
setCallAndGrid(call, grid, instance);
return;
}
}
setCallAndGrid(call, grid, null);
}
function setCallAndGrid(callsign, grid, instance = null) {
var thisInstance = null;
var port;
var address;
if (instance != null) {
if (instance in g_instances) {
thisInstance = g_instances[instance].status;
port = g_instances[instance].remote.port;
address = g_instances[instance].remote.address;
} else alert("major instance error");
} else {
if (g_instances[g_activeInstance].valid) {
thisInstance = g_instances[g_activeInstance].status;
port = g_instances[g_activeInstance].remote.port;
address = g_instances[g_activeInstance].remote.address;
}
}
if (thisInstance && thisInstance.TxEnabled == 0) {
var responseArray = Buffer.alloc(1024);
var length = 0;
length = encodeQUINT32(responseArray, length, thisInstance.magic_key);
length = encodeQUINT32(responseArray, length, thisInstance.schema_number);
length = encodeQUINT32(responseArray, length, 15);
length = encodeQUTF8(responseArray, length, thisInstance.Id);
length = encodeQUTF8(responseArray, length, thisInstance.MO);
length = encodeQUINT32(responseArray, length, thisInstance.FreqTol);
length = encodeQUTF8(responseArray, length, thisInstance.Submode);
length = encodeQBOOL(responseArray, length, thisInstance.Fastmode);
length = encodeQUINT32(responseArray, length, thisInstance.TRP);
length = encodeQUINT32(responseArray, length, thisInstance.RxDF);
length = encodeQUTF8(responseArray, length, callsign);
var hash = liveHash(callsign, thisInstance.Band, thisInstance.MO);
if (hash in g_liveCallsigns && g_liveCallsigns[hash].grid.length > 1)
grid = g_liveCallsigns[hash].grid;
if (grid.length == 0) grid = " ";
length = encodeQUTF8(responseArray, length, grid);
length = encodeQBOOL(responseArray, length, 1);
responseArray = responseArray.slice(0, length);
wsjtUdpMessage(responseArray, responseArray.length, port, address);
addLastTraffic("<font color='lightgreen'>Generated Msgs</font>");
}
if (thisInstance && thisInstance.TxEnabled == 1) {
addLastTraffic(
"<font color='yellow'>Transmit Enabled!</font><br/><font color='yellow'>Generate Msgs Aborted</font>"
);
}
}
var g_wsjtHandlers = {
0: handleWsjtxNotSupported,
1: handleWsjtxStatus,
2: handleWsjtxDecode,
3: handleWsjtxClear,
4: handleWsjtxNotSupported,
5: handleWsjtxQSO,
6: handleWsjtxClose,
7: handleWsjtxNotSupported,
8: handleWsjtxNotSupported,
9: handleWsjtxNotSupported,
10: handleWsjtxWSPR,
11: handleWsjtxNotSupported,
12: handleWsjtxADIF,
};
var g_oldQSOTimer = null;
function handleWsjtxADIF(newMessage) {
if (g_oldQSOTimer) {
clearTimeout(g_oldQSOTimer);
g_oldQSOTimer = null;
}
if (g_ignoreMessages == 0) {
onAdiLoadComplete(newMessage.ADIF);
}
sendToLogger(newMessage.ADIF);
}
function handleWsjtxQSO(newMessage) {
if (g_oldQSOTimer) {
clearTimeout(g_oldQSOTimer);
g_oldQSOTimer = null;
}
g_oldStyleLogMessage = Object.assign({}, newMessage);
g_oldQSOTimer = setTimeout(oldSendToLogger, 3000);
}
function handleWsjtxNotSupported(newMessage) {}
var g_gtShareCount = 0;
var g_lastBand = "";
var g_lastMode = "";
var g_lastRawGrid = "AA00AA";
var g_weAreDecoding = false;
var g_localDXcall = "";
var g_countIndex = 0;
var g_lastCountIndex = 0;
function rigChange(up) {
if (g_activeInstance == "") return;
var targetInstance = 0;
if (up) {
targetInstance = g_instances[g_activeInstance].intId + 1;
} else {
targetInstance = g_instances[g_activeInstance].intId - 1;
if (targetInstance < 0) targetInstance = g_instancesIndex.length - 1;
}
targetInstance %= g_instancesIndex.length;
setRig(targetInstance);
}
function setRig(instanceId) {
if (g_instances[g_instancesIndex[instanceId]].valid) {
if (g_lastMapView != null) {
g_mapView.animate({ zoom: g_lastMapView.zoom, duration: 100 });
g_mapView.animate({ center: g_lastMapView.LoLa, duration: 100 });
g_lastMapView = null;
}
g_activeInstance = g_instancesIndex[instanceId];
handleWsjtxStatus(g_instances[g_activeInstance].status);
handleClosed(g_instances[g_activeInstance].status);
}
}
function activeRig(instance) {
if (g_instances[instance].valid) {
if (g_lastMapView != null) {
g_mapView.animate({ zoom: g_lastMapView.zoom, duration: 100 });
g_mapView.animate({ center: g_lastMapView.LoLa, duration: 100 });
g_lastMapView = null;
}
g_activeInstance = instance;
handleWsjtxStatus(g_instances[g_activeInstance].status);
handleClosed(g_instances[g_activeInstance].status);
}
}
var g_lastDecodeCallsign = "";
var g_lastTransmitCallsign = {};
var g_lastStatusCallsign = {};
function handleWsjtxStatus(newMessage) {
if (g_ignoreMessages == 1) return;
if (g_callRosterWindowHandle) {
try {
g_callRosterWindowHandle.window.processStatus(newMessage);
} catch (e) {}
}
if (g_activeInstance == "") {
g_activeInstance = newMessage.instance;
}
if (Object.keys(g_instances).length > 1) {
rigWrap.style.display = "block";
} else {
rigWrap.style.display = "none";
}
var DXcall = newMessage.DXcall.trim();
if (DXcall.length > 1) {
if (!(newMessage.instance in g_lastTransmitCallsign))
g_lastTransmitCallsign[newMessage.instance] = "";
if (!(newMessage.instance in g_lastStatusCallsign))
g_lastStatusCallsign[newMessage.instance] = "";
if (
lookupOnTx.checked == true &&
newMessage.Transmitting == 1 &&
g_lastTransmitCallsign[newMessage.instance] != DXcall
) {
openLookupWindow(true);
g_lastTransmitCallsign[newMessage.instance] = DXcall;
}
if (g_lastStatusCallsign[newMessage.instance] != DXcall) {
g_lastStatusCallsign[newMessage.instance] = DXcall;
lookupCallsign(DXcall, newMessage.DXgrid.trim());
}
}
if (g_activeInstance == newMessage.instance) {
var sp = newMessage.Id.split(" - ");
rigDiv.innerHTML = sp[sp.length - 1].substring(0, 18);
var bandChange = false;
var modeChange = false;
var origMode = g_lastMode;
var origBand = g_lastBand;
wsjtxMode.innerHTML = "<font color='orange'>" + newMessage.MO + "</font>";
myMode = newMessage.MO;
myBand = Number(newMessage.Frequency / 1000000).formatBand();
if (g_lastBand != myBand) {
g_lastBand = myBand;
bandChange = true;
if (g_pskBandActivityTimerHandle != null) {
clearInterval(g_pskBandActivityTimerHandle);
g_pskBandActivityTimerHandle = null;
}
removePaths();
}
if (g_lastMode != myMode) {
g_lastMode = myMode;
modeChange = true;
if (g_pskBandActivityTimerHandle != null) {
clearInterval(g_pskBandActivityTimerHandle);
g_pskBandActivityTimerHandle = null;
}
}
if (g_pskBandActivityTimerHandle == null) pskGetBandActivity();
if (bandChange || modeChange) {
goProcessRoster();
redrawGrids();
redrawSpots();
redrawPins();
var msg = "";
msg += "<font color='yellow'>" + myBand + "</font> / ";
msg += "<font color='orange'>" + myMode + "</font>";
addLastTraffic(msg);
ackAlerts();
updateChatWindow();
}
myRawFreq = newMessage.Frequency;
frequency.innerHTML =
"<font color='lightgreen'>" +
Number(newMessage.Frequency / 1000).formatMhz(3, 3) +
" Hz </font><font color='yellow'>(" +
myBand +
")</font>";
myRawCall = newMessage.DEcall.trim();
myRawGrid = newMessage.DEgrid.trim().substr(0, 6);
var LL = squareToLatLongAll(myRawGrid);
g_mapSettings.latitude = g_myLat = LL.la2 - (LL.la2 - LL.la1) / 2;
g_mapSettings.longitude = g_myLon = LL.lo2 - (LL.lo2 - LL.lo1) / 2;
if (myRawGrid != g_lastRawGrid) {
g_lastRawGrid = myRawGrid;
}
dxCallBoxDiv.className = "DXCallBox";
var hash = DXcall + myBand + myMode;
if (hash in g_tracker.worked.call) {
dxCallBoxDiv.className = "DXCallBoxWorked";
}
if (hash in g_tracker.confirmed.call) {
dxCallBoxDiv.className = "DXCallBoxConfirmed";
}
g_localDXcall = DXcall;
localDXcall.innerHTML = DXcall.formatCallsign();
if (localDXcall.innerHTML.length == 0) {
localDXcall.innerHTML = "-";
g_localDXcall = "";
}
localDXGrid.innerHTML = myDXGrid = newMessage.DXgrid.trim();
if (myDXGrid.length == 0 && hash in g_liveCallsigns) {
localDXGrid.innerHTML = myDXGrid = g_liveCallsigns[hash].grid.substr(
0,
4
);
}
if (localDXGrid.innerHTML.length == 0) {
localDXGrid.innerHTML = "-";
localDXDistance.innerHTML = "&nbsp;";
localDXAzimuth.innerHTML = "&nbsp;";
} else {
var LL = squareToLatLongAll(myDXGrid);
localDXDistance.innerHTML =
parseInt(
MyCircle.distance(
g_myLat,
g_myLon,
LL.la2 - (LL.la2 - LL.la1) / 2,
LL.lo2 - (LL.lo2 - LL.lo1) / 2,
distanceUnit.value
) * MyCircle.validateRadius(distanceUnit.value)
) + distanceUnit.value.toLowerCase();
localDXAzimuth.innerHTML =
parseInt(
MyCircle.bearing(
g_myLat,
g_myLon,
LL.la2 - (LL.la2 - LL.la1) / 2,
LL.lo2 - (LL.lo2 - LL.lo1) / 2
)
) + "&deg;";
}
if (localDXcall.innerHTML != "-") {
localDXReport.innerHTML = Number(
newMessage.Report.trim()
).formatSignalReport();
if (DXcall.length > 0)
localDXCountry.innerHTML = g_dxccToAltName[callsignToDxcc(DXcall)];
else localDXCountry.innerHTML = "&nbsp;";
} else {
localDXReport.innerHTML = localDXCountry.innerHTML = "";
}
myDEcall = newMessage.DEcall;
myDEGrid = newMessage.DEgrid.trim().substr(0, 6);
if (myDEGrid.length > 0) setHomeGridsquare();
if (myDEGrid.length > 0) g_appSettings.centerGridsquare = myDEGrid;
if (newMessage.Decoding == 1) {
// Decoding
dimGridsquare();
fadePaths();
txrxdec.style.backgroundColor = "Blue";
txrxdec.style.borderColor = "Cyan";
txrxdec.innerHTML = "DECODE";
g_countIndex++;
g_weAreDecoding = true;
} else {
g_weAreDecoding = false;
if (g_countIndex != g_lastCountIndex) {
g_lastCountIndex = g_countIndex;
updateCountStats();
if (g_appSettings.gtShareEnable == "true") {
g_gtLiveStatusUpdate = true;
g_gtShareCount++;
} else g_gtShareCount = 0;
if (bandChange || modeChange) reloadInfo(bandChange || modeChange);
var worker = "";
worker +=
"<div style='vertical-align:top;display:inline-block;margin-right:8px;'>";
worker += "<table class='darkTable' align=center>";
worker +=
"<tr><th colspan=7>Last " +
g_lastMessages.length +
" Decoded Messages</th></tr>";
worker +=
"<tr><th>Time</th><th>dB</th><th>DT</th><th>Freq</th><th>Mode</th><th>Message</th><th>DXCC</th></tr>";
worker += g_lastMessages.join("");
worker += "</table></div>";
setStatsDiv("decodeLastListDiv", worker);
setStatsDivHeight(
"decodeLastListDiv",
getStatsWindowHeight() + 26 + "px"
);
if (
g_appSettings.gtShareEnable === true &&
Object.keys(g_spotCollector).length > 0
) {
gtChatSendSpots(g_spotCollector);
g_spotCollector = {};
}
}
txrxdec.style.backgroundColor = "Green";
txrxdec.style.borderColor = "GreenYellow";
txrxdec.innerHTML = "RECEIVE";
}
if (newMessage.TxEnabled) {
if (
g_mapSettings.fitQRZ &&
(!g_spotsEnabled || g_receptionSettings.mergeSpots)
) {
if (g_lastMapView == null) {
g_lastMapView = {};
g_lastMapView.LoLa = g_mapView.getCenter();
g_lastMapView.zoom = g_mapView.getZoom();
}
if (myDXGrid.length > 0) {
fitViewBetweenPoints([getPoint(myRawGrid), getPoint(myDXGrid)]);
} else if (
g_mapSettings.qrzDxccFallback &&
DXcall.length > 0 &&
callsignToDxcc(DXcall) > 0
) {
var dxcc = callsignToDxcc(DXcall);
var Lat = g_worldGeoData[g_dxccToGeoData[dxcc]].lat;
var Lon = g_worldGeoData[g_dxccToGeoData[dxcc]].lon;
fitViewBetweenPoints(
[getPoint(myRawGrid), ol.proj.fromLonLat([Lon, Lat])],
15
);
}
}
} else {
if (g_lastMapView != null) {
g_mapView.animate({ zoom: g_lastMapView.zoom, duration: 1200 });
g_mapView.animate({ center: g_lastMapView.LoLa, duration: 1200 });
g_lastMapView = null;
}
}
if (newMessage.Transmitting == 0) {
// Not Transmitting
g_layerSources["transmit"].clear();
g_transmitFlightPath = null;
} else {
txrxdec.style.backgroundColor = "Red";
txrxdec.style.borderColor = "Orange";
txrxdec.innerHTML = "TRANSMIT";
g_layerSources["transmit"].clear();
g_transmitFlightPath = null;
if (
qrzPathWidthValue.value != 0 &&
g_appSettings.gridViewMode != 2 &&
validateGridFromString(myRawGrid)
) {
var strokeColor = getQrzPathColor();
var strokeWeight = qrzPathWidthValue.value;
var LL = squareToLatLongAll(myRawGrid);
var Lat = LL.la2 - (LL.la2 - LL.la1) / 2;
var Lon = LL.lo2 - (LL.lo2 - LL.lo1) / 2;
var fromPoint = ol.proj.fromLonLat([Lon, Lat]);
var toPoint = null;
if (validateGridFromString(myDXGrid)) {
LL = squareToLatLongAll(myDXGrid);
Lat = LL.la2 - (LL.la2 - LL.la1) / 2;
Lon = LL.lo2 - (LL.lo2 - LL.lo1) / 2;
toPoint = ol.proj.fromLonLat([Lon, Lat]);
} else if (
g_mapSettings.qrzDxccFallback &&
DXcall.length > 0 &&
callsignToDxcc(DXcall) > 0
) {
var dxcc = callsignToDxcc(DXcall);
Lat = g_worldGeoData[g_dxccToGeoData[dxcc]].lat;
Lon = g_worldGeoData[g_dxccToGeoData[dxcc]].lon;
toPoint = ol.proj.fromLonLat([Lon, Lat]);
var locality = g_worldGeoData[g_dxccToGeoData[dxcc]].geo;
if (locality == "deleted") locality = null;
if (locality != null) {
var feature = shapeFeature(
"qrz",
locality,
"qrz",
"#FFFF0010",
"#FF0000FF",
1.0
);
g_layerSources["transmit"].addFeature(feature);
}
}
if (toPoint) {
g_transmitFlightPath = flightFeature(
[fromPoint, toPoint],
{
weight: strokeWeight,
color: strokeColor,
steps: 75,
zIndex: 90,
},
"transmit",
true
);
}
}
g_weAreDecoding = false;
}
g_appSettings.myDEcall = myDEcall;
g_appSettings.myDEGrid = myDEGrid;
g_appSettings.myMode = myMode;
g_appSettings.myBand = myBand;
g_appSettings.myRawFreq = myRawFreq;
g_appSettings.myRawCall = myRawCall;
g_appSettings.myRawGrid = myRawGrid;
}
if (newMessage.Decoding == 0) {
goProcessRoster();
processClassicAlerts();
}
}
var g_lastMapView = null;
function drawTraffic() {
while (g_lastTraffic.length > 60) g_lastTraffic.pop();
var worker = g_lastTraffic.join("<br/>");
worker = worker.split("80%'><br/>").join("80%'>");
if (g_localDXcall.length > 1)
worker = worker
.split(g_localDXcall)
.join("<font style='color:cyan'>" + g_localDXcall + "</font>");
if (myRawCall.length > 1)
worker = worker
.split(myRawCall)
.join("<font style='color:yellow'>" + myRawCall + "</font>");
trafficDiv.innerHTML = worker;
}
function getPoint(grid) {
var LL = squareToLatLongAll(grid);
var Lat = LL.la2 - (LL.la2 - LL.la1) / 2;
var Lon = LL.lo2 - (LL.lo2 - LL.lo1) / 2;
return ol.proj.fromLonLat([Lon, Lat]);
}
var g_showCQRU = true;
function fitViewBetweenPoints(points, maxZoom = 20) {
var start = ol.proj.toLonLat(points[0]);
var end = ol.proj.toLonLat(points[1]);
if (Math.abs(start[0] - end[0]) > 180) {
// Wrapped
if (end[0] < start[0]) {
start[0] -= 360;
} else {
end[0] -= 360;
}
}
start = ol.proj.fromLonLat(start);
end = ol.proj.fromLonLat(end);
var line = new ol.geom.LineString([start, end]);
var feature = new ol.Feature({ geometry: line });
var extent = feature.getGeometry().getExtent();
g_mapView.fit(extent, {
duration: 500,
maxZoom: maxZoom,
padding: [75, 75, 75, 75],
});
delete feature;
delete line;
}
var g_spotCollector = {};
function handleWsjtxDecode(newMessage) {
if (g_ignoreMessages == 1 || g_map == null) return;
var didAlert = false;
var didCustomAlert = false;
var validQTH = false;
var CQ = false;
var DEDX = false;
var msgDEcallsign = "";
var msgDXcallsign = "";
var theirQTH = "";
var countryName = "";
var newF;
if (newMessage.OF > 0) {
newF = Number((newMessage.OF + newMessage.DF) / 1000).formatMhz(3, 3);
} else {
newF = newMessage.DF;
}
theTimeStamp =
timeNowSec() - (timeNowSec() % 86400) + parseInt(newMessage.TM / 1000);
var messageColor = "white";
if (CQ == true) messageColor = "cyan";
// Break up the decoded message
var decodeWords = newMessage.Msg.split(" ").slice(0, 5);
while (decodeWords[decodeWords.length - 1] == "") decodeWords.pop();
if (decodeWords.length > 1 && newMessage.Msg.indexOf("<...>") == -1) {
if (newMessage.Msg.indexOf("<") != -1) {
for (var i in decodeWords) {
decodeWords[i] = decodeWords[i].replace("<", "").replace(">", "");
}
}
var rect = null;
// Grab the last word in the decoded message
var qth = decodeWords[decodeWords.length - 1].trim();
if (qth.length == 4) {
var LETTERS = qth.substr(0, 2);
var NUMBERS = qth.substr(2, 2);
if (/^[A-R]+$/.test(LETTERS) && /^[0-9]+$/.test(NUMBERS)) {
theirQTH = LETTERS + NUMBERS;
if (theirQTH != "RR73") {
validQTH = true;
} else {
theirQTH = "";
validQTH = false;
}
}
}
if (validQTH) msgDEcallsign = decodeWords[decodeWords.length - 2].trim();
if (validQTH == false && decodeWords.length == 3)
msgDEcallsign = decodeWords[decodeWords.length - 2].trim();
if (validQTH == false && decodeWords.length == 2)
msgDEcallsign = decodeWords[decodeWords.length - 1].trim();
if (decodeWords[0] == "CQ") {
CQ = true;
msgDXcallsign = "CQ";
}
if (decodeWords.length == 4 && CQ == true) {
msgDXcallsign += " " + decodeWords[1];
}
if (decodeWords.length == 3 && CQ == false) {
msgDXcallsign = decodeWords[0];
}
if (decodeWords.length >= 3 && CQ == true && validQTH == false) {
if (validateNumAndLetter(decodeWords[decodeWords.length - 1].trim()))
msgDEcallsign = decodeWords[decodeWords.length - 1].trim();
else msgDEcallsign = decodeWords[decodeWords.length - 2].trim();
}
if (decodeWords.length >= 4 && CQ == false) {
msgDXcallsign = decodeWords[0];
msgDEcallsign = decodeWords[1];
}
var callsign = null;
var hash = msgDEcallsign + newMessage.OB + newMessage.OM;
if (hash in g_liveCallsigns) callsign = g_liveCallsigns[hash];
if (validQTH == "" && msgDEcallsign in g_gtCallsigns) {
if (g_gtFlagPins[g_gtCallsigns[msgDEcallsign]].grid.length > 0)
validQTH = g_gtFlagPins[g_gtCallsigns[msgDEcallsign]].grid;
}
var canPath = false;
if (
(g_appSettings.gtBandFilter.length == 0 ||
(g_appSettings.gtBandFilter == "auto" && newMessage.OB == myBand) ||
newMessage.OB == g_appSettings.gtBandFilter) &&
(g_appSettings.gtModeFilter.length == 0 ||
(g_appSettings.gtModeFilter == "auto" && newMessage.OM == myMode) ||
newMessage.OM == g_appSettings.gtModeFilter ||
g_appSettings.gtModeFilter == "Digital")
) {
rect = qthToBox(
theirQTH,
msgDEcallsign,
CQ,
newMessage.NW,
false,
msgDXcallsign,
newMessage.OB,
null,
hash
);
canPath = true;
}
if (rect != null && theirQTH == "") {
theirQTH = rect.qth;
}
if (rect) {
g_liveGrids[theirQTH].age = g_timeNow;
}
if (callsign == null) {
newCallsign = {};
newCallsign.DEcall = msgDEcallsign;
newCallsign.grid = theirQTH;
newCallsign.wspr = null;
newCallsign.msg = newMessage.Msg;
newCallsign.RSTsent = newMessage.SR;
newCallsign.RSTrecv = "-";
newCallsign.time = theTimeStamp;
newCallsign.life = newCallsign.age = g_timeNow;
newCallsign.delta = newMessage.DF;
newCallsign.dt = newMessage.DT.toFixed(2);
newCallsign.DXcall = msgDXcallsign.trim();
newCallsign.rect = rect;
newCallsign.state = null;
newCallsign.zipcode = null;
newCallsign.worked = false;
newCallsign.confirmed = false;
newCallsign.qso = false;
newCallsign.dxcc = callsignToDxcc(newCallsign.DEcall);
newCallsign.px = null;
newCallsign.zone = null;
newCallsign.vucc_grids = [];
newCallsign.propMode = "";
newCallsign.digital = true;
newCallsign.phone = false;
newCallsign.IOTA = "";
newCallsign.satName = "";
if (newCallsign.dxcc != -1) {
newCallsign.px = getWpx(newCallsign.DEcall);
if (newCallsign.px)
newCallsign.zone = Number(
newCallsign.px.charAt(newCallsign.px.length - 1)
);
newCallsign.cont =
g_worldGeoData[g_dxccToGeoData[newCallsign.dxcc]].continent;
if (newCallsign.dxcc == 390 && newCallsign.zone == 1)
details.cont = "EU";
}
newCallsign.ituza = Array();
newCallsign.cqza = Array();
newCallsign.distance = 0;
newCallsign.heading = 0;
newCallsign.cnty = null;
newCallsign.qual = false;
getLookupCachedObject(msgDEcallsign, null, null, null, newCallsign);
if (
g_callsignLookups.ulsUseEnable == true &&
isKnownCallsignDXCC(newCallsign.dxcc)
) {
lookupUsCallsign(newCallsign, false);
}
if (newCallsign.dxcc in g_dxccCount) g_dxccCount[newCallsign.dxcc]++;
else g_dxccCount[newCallsign.dxcc] = 1;
newCallsign.alerted = false;
newCallsign.shouldAlert = false;
g_liveCallsigns[hash] = newCallsign;
callsign = newCallsign;
} else {
if (validQTH) {
callsign.grid = theirQTH;
if (rect != null && callsign.grid != rect.qth) {
if (
(g_appSettings.gtBandFilter.length == 0 ||
(g_appSettings.gtBandFilter == "auto" &&
newMessage.OB == myBand) ||
newMessage.OB == g_appSettings.gtBandFilter) &&
(g_appSettings.gtModeFilter.length == 0 ||
(g_appSettings.gtModeFilter == "auto" &&
newMessage.OM == myMode) ||
newMessage.OM == g_appSettings.gtModeFilter ||
g_appSettings.gtModeFilter == "Digital")
) {
rect = qthToBox(
theirQTH,
msgDEcallsign,
CQ,
newMessage.NW,
false,
msgDXcallsign,
newMessage.OB,
null,
hash
);
canPath = true;
}
}
}
callsign.time = theTimeStamp;
callsign.age = g_timeNow;
callsign.RSTsent = newMessage.SR;
callsign.delta = newMessage.DF;
callsign.DXcall = msgDXcallsign.trim();
callsign.msg = newMessage.Msg;
callsign.rect = rect;
callsign.dt = newMessage.DT.toFixed(2);
}
callsign.mode = newMessage.OM;
callsign.band = newMessage.OB;
callsign.instance = newMessage.instance;
callsign.grid = callsign.grid.substr(0, 4);
callsign.CQ = CQ;
if (msgDXcallsign == myDEcall) callsign.qrz = true;
else callsign.qrz = false;
if (callsign.grid.length > 0 && callsign.distance == 0) {
var LL = squareToLatLongAll(callsign.grid);
callsign.distance = MyCircle.distance(
g_myLat,
g_myLon,
LL.la2 - (LL.la2 - LL.la1) / 2,
LL.lo2 - (LL.lo2 - LL.lo1) / 2,
distanceUnit.value
);
callsign.heading = MyCircle.bearing(
g_myLat,
g_myLon,
LL.la2 - (LL.la2 - LL.la1) / 2,
LL.lo2 - (LL.lo2 - LL.lo1) / 2
);
if (callsign.grid in g_gridToITUZone) {
callsign.ituza = g_gridToITUZone[callsign.grid];
}
if (callsign.grid in g_gridToCQZone) {
callsign.cqza = g_gridToCQZone[callsign.grid];
}
}
if (newMessage.NW) {
didCustomAlert = processAlertMessage(
decodeWords,
newMessage.Msg.substr(0, 30).trim(),
callsign.band,
callsign.mode
);
didAlert = checkClassicAlerts(CQ, callsign, newMessage, msgDXcallsign);
insertMessageInRoster(
newMessage,
msgDEcallsign,
msgDXcallsign,
callsign,
hash
);
if (
g_mapSettings.trafficDecode &&
(didAlert == true || didCustomAlert == true)
) {
var traffic = htmlEntities(newMessage.Msg);
if (didAlert == true) {
traffic = "⚠️ " + traffic;
}
if (didCustomAlert == true) {
traffic = traffic + " 🚩";
}
g_lastTraffic.unshift(traffic);
g_lastTraffic.unshift(userTimeString(null));
g_lastTraffic.unshift(
"<hr style='border-color:#333;margin-top:0px;margin-bottom:2px;width:80%'>"
);
drawTraffic();
lastMessageWasInfo = true;
}
if (
g_appSettings.gtSpotEnable === true &&
g_appSettings.gtSpotEnable === true &&
callsign.DEcall in g_gtCallsigns
) {
if (
g_gtCallsigns[callsign.DEcall] in g_gtFlagPins &&
g_gtFlagPins[g_gtCallsigns[callsign.DEcall]].o == 1
)
g_spotCollector[g_gtCallsigns[callsign.DEcall]] = callsign.RSTsent;
}
}
if (callsign.dxcc != -1) countryName = g_dxccToAltName[callsign.dxcc];
if (canPath == true) {
if (
callsign.DXcall.indexOf("CQ") < 0 &&
g_appSettings.gridViewMode != 2
) {
// Nothing special, we know the callers grid
if (callsign.grid != "") {
// Our msgDEcallsign is not sending a CQ.
// Let's see if we can locate who he's talking to in our known list
var DEcallsign = null;
if (
callsign.DXcall + newMessage.OB + newMessage.OM in
g_liveCallsigns
) {
DEcallsign =
g_liveCallsigns[callsign.DXcall + newMessage.OB + newMessage.OM];
} else if (callsign.DXcall in g_liveCallsigns) {
DEcallsign = g_liveCallsigns[callsign.DXcall];
}
if (DEcallsign != null && DEcallsign.grid != "") {
var strokeColor = getPathColor();
var strokeWeight = pathWidthValue.value;
var flightPath = null;
var isQRZ = false;
if (msgDXcallsign == myDEcall) {
strokeColor = getQrzPathColor();
strokeWeight = qrzPathWidthValue.value;
isQRZ = true;
}
if (strokeWeight != 0) {
var fromPoint = getPoint(callsign.grid);
var toPoint = getPoint(DEcallsign.grid);
flightPath = flightFeature(
[fromPoint, toPoint],
{
weight: strokeWeight,
color: strokeColor,
steps: 75,
zIndex: 90,
},
"flight",
true
);
flightPath.age = g_timeNow + g_flightDuration;
flightPath.isShapeFlight = 0;
flightPath.isQRZ = isQRZ;
g_flightPaths.push(flightPath);
}
}
} else if (
g_mapSettings.qrzDxccFallback &&
msgDXcallsign == myDEcall &&
callsign.dxcc > 0
) {
// the caller is calling us, but they don't have a grid, so lookup the DXCC and show it
var strokeColor = getQrzPathColor();
var strokeWeight = qrzPathWidthValue.value;
var flightPath = null;
var isQRZ = true;
var DEcallsign = g_liveCallsigns[myDEcall];
if (strokeWeight != 0) {
var toPoint = getPoint(DEcallsign.grid);
var Lat = g_worldGeoData[g_dxccToGeoData[callsign.dxcc]].lat;
var Lon = g_worldGeoData[g_dxccToGeoData[callsign.dxcc]].lon;
var fromPoint = ol.proj.fromLonLat([Lon, Lat]);
flightPath = flightFeature(
[fromPoint, toPoint],
{
weight: strokeWeight,
color: strokeColor,
steps: 75,
zIndex: 90,
},
"flight",
true
);
flightPath.age = g_timeNow + g_flightDuration;
flightPath.isShapeFlight = 0;
flightPath.isQRZ = isQRZ;
g_flightPaths.push(flightPath);
var feature = shapeFeature(
"qrz",
g_worldGeoData[g_dxccToGeoData[callsign.dxcc]].geo,
"qrz",
"#FFFF0010",
"#FF0000FF",
1.0
);
feature.age = g_timeNow + g_flightDuration;
feature.isShapeFlight = 1;
feature.isQRZ = isQRZ;
g_layerSources["flight"].addFeature(feature);
g_flightPaths.push(feature);
}
}
} else if (
g_mapSettings.CQhilite &&
msgDXcallsign.indexOf("CQ ") == 0 &&
callsign.grid != "" &&
g_appSettings.gridViewMode != 2 &&
pathWidthValue.value != 0
) {
var CCd = msgDXcallsign.replace("CQ ", "").split(" ")[0];
if (CCd.length < 5 && !(CCd in g_pathIgnore)) {
var locality = null;
// Direct lookup US states, Continents, possibly
if (CCd in g_replaceCQ) CCd = g_replaceCQ[CCd];
if (CCd.length == 2 && CCd in g_shapeData) {
locality = g_shapeData[CCd];
} else if (CCd.length == 3) {
// maybe it's DEL, or WYO. check the first two letters
if (CCd.substr(0, 2) in g_shapeData)
locality = g_shapeData[CCd.substr(0, 2)];
}
if (locality == null) {
// Check the prefix for dxcc direct
var dxcc = callsignToDxcc(CCd);
if (dxcc != -1) {
locality = g_worldGeoData[g_dxccToGeoData[dxcc]].geo;
if (locality == "deleted") locality = null;
} else {
}
}
if (locality != null) {
var strokeColor = getPathColor();
var strokeWeight = pathWidthValue.value;
var flightPath = null;
var feature = shapeFeature(
CCd,
locality,
CCd,
"#00000000",
"#FF0000C0",
strokeWeight
);
feature.age = g_timeNow + g_flightDuration;
feature.isShapeFlight = 1;
feature.isQRZ = false;
g_layerSources["flight"].addFeature(feature);
g_flightPaths.push(feature);
var fromPoint = getPoint(callsign.grid);
var toPoint = ol.proj.fromLonLat(locality.properties.center);
flightPath = flightFeature(
[fromPoint, toPoint],
{
weight: strokeWeight,
color: strokeColor,
steps: 75,
zIndex: 90,
},
"flight",
true
);
flightPath.age = g_timeNow + g_flightDuration;
flightPath.isShapeFlight = 0;
flightPath.isQRZ = false;
g_flightPaths.push(flightPath);
}
}
}
}
}
var bgColor = "black";
if (newMessage.LC > 0) bgColor = "#880000";
g_lastMessages.unshift(
"<tr style='background-color:" +
bgColor +
"'><td style='color:lightblue'>" +
userTimeString(theTimeStamp * 1000) +
"</td><td style='color:orange'>" +
newMessage.SR +
"</td><td style='color:gray'>" +
newMessage.DT.toFixed(1) +
"</td><td style='color:lightgreen'>" +
newF +
"</td><td>" +
newMessage.MO +
"</td><td style='color:" +
messageColor +
"'>" +
htmlEntities(newMessage.Msg) +
"</td><td style='color:yellow'>" +
countryName +
"</td></tr>"
);
while (g_lastMessages.length > 100) g_lastMessages.pop();
}
function addLastTraffic(traffic) {
g_lastTraffic.unshift(traffic);
g_lastTraffic.unshift(
"<hr style='border-color:#333;margin-top:0px;margin-bottom:2px;width:80%'>"
);
drawTraffic();
}
function htmlEntities(str) {
return String(str)
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}
function shapeFeature(
key,
geoJsonData,
propname,
fillColor,
borderColor,
borderWidth
) {
var feature = new ol.format.GeoJSON({
geometryName: key,
}).readFeature(geoJsonData, {
featureProjection: "EPSG:3857",
});
var style = new ol.style.Style({
stroke: new ol.style.Stroke({
color: borderColor,
width: borderWidth,
}),
fill: new ol.style.Fill({
color: fillColor,
}),
});
feature.setStyle(style);
feature.set("prop", propname);
feature.size = 2;
return feature;
}
function handleWsjtxClear(newMessage) {
for (var hash in g_liveCallsigns) {
if (
g_liveCallsigns[hash].instance == newMessage.instance ||
g_liveCallsigns[hash].mode == g_instances[newMessage.instance].status.MO
)
delete g_liveCallsigns[hash];
}
for (var call in g_callRoster) {
if (g_callRoster[call].callObj.instance == newMessage.instance)
delete g_callRoster[call];
}
redrawGrids();
redrawPins();
updateCountStats();
goProcessRoster();
}
function goProcessRoster(isRealtime = false) {
var now = timeNowSec();
for (var call in g_callRoster) {
if (now - g_callRoster[call].callObj.age > 300) {
g_callRoster[call].callObj.alerted = false;
g_callRoster[call].callObj.shouldAlert = false;
delete g_callRoster[call];
continue;
}
}
if (g_callRosterWindowHandle) {
try {
if (isRealtime == true) {
if (g_callRosterWindowHandle.window.g_rosterSettings.realtime == false)
return;
}
g_callRosterWindowHandle.window.processRoster(g_callRoster);
} catch (e) {}
}
}
function handleClosed(newMessage) {
if (
g_activeInstance == newMessage.Id &&
g_instances[newMessage.Id].open == false
) {
txrxdec.style.backgroundColor = "Purple";
txrxdec.style.borderColor = "Purple";
var name = newMessage.Id.toUpperCase().split(" - ");
var txt = name[name.length - 1];
txrxdec.innerHTML = txt + " Closed";
}
}
function handleWsjtxClose(newMessage) {
updateCountStats();
g_instances[newMessage.Id].open = false;
handleClosed(newMessage);
updateRosterInstances();
}
function handleWsjtxWSPR(newMessage) {
if (g_ignoreMessages == 1) return;
addDeDx(
newMessage.Grid,
newMessage.Callsign,
false,
false,
false,
"-",
Number(newMessage.SR),
timeNowSec(),
"Pwr:" +
newMessage.Power +
" Freq:" +
Number(newMessage.Frequency / 1000).formatMhz(3, 3) +
" Delta:" +
Number(newMessage.DT).toFixed(2) +
" Drift:" +
newMessage.Drift,
"WSPR",
Number(newMessage.Frequency / 1000000).formatBand(),
false,
true,
null,
callsignToDxcc(newMessage.Callsign),
null,
null,
null,
"",
""
);
processAlertMessage(newMessage.Callsign.trim() + " " + newMessage.Grid);
updateCountStats();
}
function centerOn(grid) {
if (grid.length >= 4) {
var LL = squareToLatLong(grid);
g_map
.getView()
.setCenter(
ol.proj.fromLonLat([
LL.lo2 - (LL.lo2 - LL.lo1) / 2,
LL.la2 - (LL.la2 - LL.la1) / 2,
])
);
}
}
function setCenterQTH() {
if (homeQTHInput.value.length >= 4) {
g_appSettings.centerGridsquare = homeQTHInput.value;
// Grab home QTH Gridsquare from Center QTH
var LL = squareToLatLong(homeQTHInput.value);
//panTo(ol.proj.fromLonLat([LL.lo2 - (LL.lo2 - LL.lo1) / 2, LL.la2 - ((LL.la2 - LL.la1) / 2)]));
g_map
.getView()
.setCenter(
ol.proj.fromLonLat([
LL.lo2 - (LL.lo2 - LL.lo1) / 2,
LL.la2 - (LL.la2 - LL.la1) / 2,
])
);
} else {
homeQTHInput.value = "";
return;
}
}
function setCenterGridsquare() {
if (g_mapMemory[6].zoom != -1) {
mapMemory(6, false);
return;
}
setCenterQTH();
}
function changeLookupMerge() {
g_appSettings.lookupMerge = lookupMerge.checked;
g_appSettings.lookupMissingGrid = lookupMissingGrid.checked;
if (g_appSettings.lookupMerge == true) {
lookupMissingGridDiv.style.display = "inline-block";
} else {
lookupMissingGridDiv.style.display = "none";
}
}
function changelookupOnTx() {
g_appSettings.lookupOnTx = lookupOnTx.checked;
g_appSettings.lookupCloseLog = lookupCloseLog.checked;
}
function exportSettings() {
var filename = g_appData + g_dirSeperator + "gt_settings.json";
var toWrite = JSON.stringify(localStorage);
fs.writeFileSync(filename, toWrite);
checkForSettings();
}
function checkForSettings() {
var filename = g_appData + g_dirSeperator + "gt_settings.json";
if (fs.existsSync(filename)) {
importSettingsButton.style.display = "inline-block";
importSettingsFile.style.display = "inline-block";
importSettingsFile.innerHTML = filename;
} else {
importSettingsButton.style.display = "none";
importSettingsFile.style.display = "none";
}
}
function importSettings() {
checkForSettings();
var filename = g_appData + g_dirSeperator + "gt_settings.json";
if (fs.existsSync(filename)) {
var data = fs.readFileSync(filename);
data = JSON.parse(data);
if (
typeof data.appSettings != "undefined" &&
data.currentVersion == localStorage.currentVersion
) {
localStorage.clear();
for (var key in data) {
localStorage[key] = data[key];
}
fs.unlinkSync(filename);
chrome.runtime.reload();
} else {
if (typeof data.appSettings == "undefined") {
importSettingsFile.innerHTML =
"<font style='color:red'>Settings File Corrupt!</font>";
} else if (data.currentVersion != localStorage.currentVersion) {
importSettingsFile.innerHTML =
"<font style='color:red'>Settings Version Mismatch!</font>";
}
}
}
}
function showCallsignBox(redraw) {
var worker =
"<div style='vertical-align:top;display:inline-block;margin:2px;color:cyan;font-weight:bold'>Callsigns and DXCC Heard</div><br/>";
g_newCallsignCount = Object.keys(g_liveCallsigns).length;
if (g_newCallsignCount > 0) {
var newCallList = Array();
worker +=
"<div style='display:inline-block;padding-right:8px;overflow:auto;overflow-x:hidden;height:" +
Math.min(g_newCallsignCount * 24 + 26, getStatsWindowHeight()) +
"px;'><table class='darkTable' align=center><th align=left>Callsign</th><th align=left>Grid</th><th>DXCC</th><th>CQ</th><th>ITU</th><th>Flag</th><th align=left>QSO</th><th>QSL</th><th>When</th>"; //<th>ITUz</th><th>CQz</th><th>ISO</th>";
if (g_callsignLookups.lotwUseEnable == true) worker += "<th>LoTW</th>";
if (g_callsignLookups.eqslUseEnable == true) worker += "<th>eQSL</th>";
if (g_callsignLookups.oqrsUseEnable == true) worker += "<th>OQRS</th>";
g_lastCallsignCount = g_newCallsignCount;
for (var x in g_liveCallsigns) {
if (g_liveCallsigns[x].dxcc != -1) {
newCallList.push(g_liveCallsigns[x]);
}
}
newCallList.sort(compareCallsignTime).reverse();
for (var x in newCallList) {
if (newCallList[x].DEcall == myRawCall) continue;
var grid = newCallList[x].rect ? newCallList[x].rect.qth : "-";
var cqzone =
grid in g_gridToCQZone ? g_gridToCQZone[grid].join(", ") : "-";
var ituzone =
grid in g_gridToITUZone ? g_gridToITUZone[grid].join(", ") : "-";
var geo = g_worldGeoData[g_dxccToGeoData[newCallList[x].dxcc]];
var thisCall = newCallList[x].DEcall.formatCallsign();
worker +=
"<tr><td align=left style='color:#ff0;cursor:pointer' onClick='window.opener.startLookup(\"" +
newCallList[x].DEcall +
'","' +
grid +
"\");'>" +
thisCall +
"</td><td align=left style='color:cyan;' >" +
grid +
"</td><td style='color:orange;'>" +
geo.name +
"<font style='color:lightgreen;'> (" +
geo.pp +
")<font></td>";
worker += "<td>" + cqzone + "</td><td>" + ituzone + "</td>";
worker +=
"<td align='center' style='margin:0;padding:0'><img style='padding-top:4px' src='./img/flags/16/" +
geo.flag +
"'></td>";
worker +=
"<td>" +
(thisCall in g_tracker.worked.call ? "&#10004;" : "") +
"</td><td>" +
(thisCall in g_tracker.confirmed.call ? "&#10004;" : "") +
"</td>";
var ageString = "";
if (timeNowSec() - newCallList[x].time < 3601)
ageString = (timeNowSec() - newCallList[x].time).toDHMS();
else {
ageString = userTimeString(newCallList[x].time * 1000);
}
worker += "<td>" + ageString + "</td>";
if (g_callsignLookups.lotwUseEnable == true)
worker +=
"<td align='center'>" +
(thisCall in g_lotwCallsigns ? "&#10004;" : "") +
"</td>";
if (g_callsignLookups.eqslUseEnable == true)
worker +=
"<td align='center'>" +
(thisCall in g_eqslCallsigns ? "&#10004;" : "") +
"</td>";
if (g_callsignLookups.oqrsUseEnable == true)
worker +=
"<td align='center'>" +
(thisCall in g_oqrsCallsigns ? "&#10004;" : "") +
"</td>";
worker += "</tr>";
}
worker += "</table></div>";
}
var heard = 0;
var List = {};
if (Object.keys(g_dxccCount).length > 0) {
for (var key in g_dxccCount) {
if (key != -1) {
var item = {};
item.total = g_dxccCount[key];
item.confirmed = g_worldGeoData[g_dxccToGeoData[key]].confirmed;
item.worked = g_worldGeoData[g_dxccToGeoData[key]].worked;
item.dxcc = key;
item.flag = g_worldGeoData[g_dxccToGeoData[key]].flag;
List[g_dxccToAltName[key]] = item;
heard++;
}
}
worker +=
"<div style='vertical-align:top;display:inline-block;margin-right:2px;overflow:auto;overflow-x:hidden;height:" +
Math.min(
Object.keys(g_dxccCount).length * 23 + 45,
getStatsWindowHeight()
) +
"px;'><table class='darkTable' align=center><tr><th colspan=4 style='font-weight:bold'>DXCC (" +
heard +
")</th><tr><th align=left>Name</th><th>Flag</th><th align=left>Calls</th></tr>";
Object.keys(List)
.sort()
.forEach(function (key, i) {
worker += "<tr><td align=left style='color:#ff0;' >" + key + "</td>";
worker +=
"<td align='center' style='margin:0;padding:0'><img style='padding-top:3px' src='./img/flags/16/" +
List[key].flag +
"'></td>";
worker +=
"<td align=left style='color:lightblue;' >" +
List[key].total +
"</td>";
worker += "</tr>";
});
worker += "</table></div>";
}
worker += "</div>";
setStatsDiv("callsignListDiv", worker);
}
function setStatsDiv(div, worker) {
if (
g_statsWindowHandle != null &&
typeof g_statsWindowHandle.window[div] !== "undefined"
) {
g_statsWindowHandle.window[div].innerHTML = worker;
}
}
function setStatsDivHeight(div, heightWithPx) {
if (
g_statsWindowHandle != null &&
typeof g_statsWindowHandle.window[div] !== "undefined"
) {
g_statsWindowHandle.window[div].style.height = heightWithPx;
}
}
function getStatsWindowHeight() {
if (
g_statsWindowHandle != null &&
typeof g_statsWindowHandle.window.window !== "undefined"
) {
return g_statsWindowHandle.window.window.innerHeight - 63;
}
return 300;
}
function setLookupDiv(div, worker) {
if (
g_lookupWindowHandle &&
typeof g_lookupWindowHandle.window[div].innerHTML !== "undefined"
) {
g_lookupWindowHandle.window[div].innerHTML = worker;
}
}
function setLookupDivHeight(div, heightWithPx) {
if (
g_lookupWindowHandle &&
typeof g_lookupWindowHandle.window[div].style !== "undefined"
) {
g_lookupWindowHandle.window[div].style.height = heightWithPx;
}
}
function getLookupWindowHeight() {
if (
g_lookupWindowHandle &&
typeof g_lookupWindowHandle.window.window !== "undefined"
) {
return g_lookupWindowHandle.window.window.innerHeight;
}
return 300;
}
function showConditionsBox() {
if (g_mapSettings.offlineMode == false) {
openConditionsWindow();
}
}
function myCallCompare(a, b) {
return a.DEcall.localeCompare(b.DEcall);
}
function myGridCompare(a, b) {
return a.grid.localeCompare(b.grid);
}
function myModeCompare(a, b) {
return a.mode.localeCompare(b.mode);
}
function myDxccCompare(a, b) {
return g_dxccToAltName[a.dxcc].localeCompare(g_dxccToAltName[b.dxcc]);
}
function myDxccIntCompare(a, b) {
if (!a in g_dxccToAltName) return 0;
if (!b in g_dxccToAltName)
return g_dxccToAltName[a].localeCompare(g_dxccToAltName[b]);
}
function myTimeCompare(a, b) {
if (a.time > b.time) return 1;
if (a.time < b.time) return -1;
return 0;
}
function myBandCompare(a, b) {
return a.band.localeCompare(b.band);
}
function myConfirmedCompare(a, b) {
if (a.confirmed && !b.confirmed) return 1;
if (!a.confirmed && b.confirmed) return -1;
return 0;
}
var g_sortFunction = [
myCallCompare,
myGridCompare,
myModeCompare,
myDxccCompare,
myTimeCompare,
myBandCompare,
myConfirmedCompare,
];
var g_lastSortIndex = 4;
var g_qsoPages = 1;
var g_qsoPage = 0;
var g_qsoItemsPerPage = 100;
var g_lastSortType = 0;
var g_searchWB = "";
var g_gridSearch = "";
var g_filterBand = "Mixed";
var g_filterMode = "Mixed";
var g_filterDxcc = 0;
var g_filterQSL = "All";
var g_lastSearchSelection = null;
function resetSearch() {
g_lastSortIndex = 4;
g_qsoPages = 1;
g_qsoPage = 0;
g_qsoItemsPerPage = 100;
g_lastSortType = 2;
g_searchWB = "";
g_gridSearch = "";
g_filterBand = "Mixed";
g_filterMode = "Mixed";
g_filterDxcc = 0;
g_filterQSL = "All";
g_lastSearchSelection = null;
}
function showWorkedByCall(callsign, evt) {
evt.preventDefault();
resetSearch();
g_searchWB = callsign;
if (event.shiftKey == true) g_filterQSL = "true";
openInfoTab("qsobox", "workedBoxDiv", showWorkedBox);
}
function showWorkedSearchChanged(object, index) {
ValidateCallsign(object, null);
g_searchWB = object.value.toUpperCase();
g_lastSearchSelection = object.id;
showWorkedBox(index, 0);
}
function showWorkedSearchGrid(object, index) {
ValidateCallsign(object, null);
g_gridSearch = object.value.toUpperCase();
g_lastSearchSelection = object.id;
showWorkedBox(index, 0);
}
function filterBandFunction(event, index) {
g_filterBand = this.value;
g_lastSearchSelection = this.id;
showWorkedBox(index, 0);
}
function filterModeFunction(event, index) {
g_filterMode = this.value;
g_lastSearchSelection = this.id;
showWorkedBox(index, 0);
}
function filterDxccFunction(event, index) {
g_filterDxcc = this.value;
g_lastSearchSelection = this.id;
showWorkedBox(index, 0);
}
function filterQSLFunction(event, index) {
g_filterQSL = this.value;
g_lastSearchSelection = this.id;
showWorkedBox(index, 0);
}
function showWorkedBox(sortIndex, nextPage, redraw) {
try {
var myObjects = null;
var mySort = sortIndex;
var bandOptions;
var modeOptions;
var dxccOptions;
var bands = {};
var modes = {};
var dxccs = {};
var ObjectCount = 0;
myObjects = g_QSOhash;
if (sortIndex == null || typeof sortIndex == "undefined") {
mySort = 4;
g_lastSortIndex = 4;
g_lastSortType = 2;
}
var list = Object.values(myObjects);
if (g_searchWB.length > 0) {
list = list.filter(function (value) {
return value.DEcall.indexOf(g_searchWB) > -1;
});
}
if (g_gridSearch.length > 0)
list = list.filter(function (value) {
var x = value.grid.indexOf(g_gridSearch);
var y = value.vucc_grids.indexOf(g_gridSearch);
return x == 0 || y == 0;
});
for (var key in list) {
bands[list[key].band] = list[key].band;
modes[list[key].mode] = list[key].mode;
var pp =
g_dxccToGeoData[list[key].dxcc] in g_worldGeoData
? g_worldGeoData[g_dxccToGeoData[list[key].dxcc]].pp
: "?";
dxccs[g_dxccToAltName[list[key].dxcc] + " (" + pp + ")"] = list[key].dxcc;
}
if (g_filterBand != "Mixed")
list = list.filter(function (value) {
return value.band == g_filterBand;
});
if (g_filterMode != "Mixed")
list = list.filter(function (value) {
if (
g_filterMode == "Phone" &&
value.mode in g_modes_phone &&
g_modes_phone[value.mode]
)
return true;
if (
g_filterMode == "Digital" &&
value.mode in g_modes &&
g_modes[value.mode]
)
return true;
return value.mode == g_filterMode;
});
if (g_filterDxcc != 0)
list = list.filter(function (value) {
return value.dxcc == g_filterDxcc;
});
if (g_filterQSL != "All") {
list = list.filter(function (value) {
return value.confirmed == (g_filterQSL == "true" ? true : false);
});
}
if (typeof redraw == "undefined") {
if (typeof nextPage == "undefined") {
nextPage = 0;
if (g_lastSortIndex != mySort) {
list = list.sort(g_sortFunction[mySort]);
g_lastSortIndex = mySort;
g_lastSortType = 1;
g_qsoPage = 0;
} else {
list = list.sort(g_sortFunction[mySort]).reverse();
g_lastSortIndex = -1;
g_lastSortType = 2;
g_qsoPage = 0;
}
} else {
if (g_lastSortType == 1) {
list = list.sort(g_sortFunction[mySort]);
} else {
list = list.sort(g_sortFunction[mySort]).reverse();
}
}
} else {
mySort = g_lastSortIndex;
if (mySort == -1) mySort = 4;
if (g_lastSortType == 1) {
list = list.sort(g_sortFunction[mySort]);
} else {
list = list.sort(g_sortFunction[mySort]).reverse();
}
}
ObjectCount = list.length;
var g_qsoPages = parseInt(ObjectCount / g_qsoItemsPerPage) + 1;
g_qsoPage += nextPage;
g_qsoPage %= g_qsoPages;
if (g_qsoPage < 0) g_qsoPage = g_qsoPages - 1;
var startIndex = g_qsoPage * g_qsoItemsPerPage;
var endIndex = startIndex + g_qsoItemsPerPage;
if (endIndex > ObjectCount) endIndex = ObjectCount;
{
var workHead = "<b> Entries (" + ObjectCount + ")</b>";
if (g_qsoPages > 1) {
workHead +=
"<br/><font style='font-size:15px;' color='cyan' onClick='window.opener.showWorkedBox(" +
mySort +
", -1);'>&#8678;&nbsp;</font>";
workHead +=
" Page " +
(g_qsoPage + 1) +
" of " +
g_qsoPages +
" (" +
(endIndex - startIndex) +
") ";
workHead +=
"<font style='font-size:16px;' color='cyan' onClick='window.opener.showWorkedBox(" +
mySort +
", 1);'>&nbsp;&#8680;</font>";
}
setStatsDiv("workedHeadDiv", workHead);
if (myObjects != null) {
var worker = "";
worker +=
"<table id='logTable' style='white-space:nowrap;overflow:auto;overflow-x;hidden;' class='darkTable' align=center>";
worker += "<tr>";
worker +=
"<th><input type='text' id='searchWB' style='margin:0px' class='inputTextValue' value='" +
g_searchWB +
"' size='8' oninput='window.opener.showWorkedSearchChanged(this);' / ></th>";
worker +=
"<th><input type='text' id='searchGrid' style='margin:0px' class='inputTextValue' value='" +
g_gridSearch +
"' size='6' oninput='window.opener.showWorkedSearchGrid(this);' / ></th>";
worker += "<th><div id='bandFilterDiv'></div></th>";
worker += "<th><div id='modeFilterDiv'></div></th>";
worker += "<th><div id='qslFilterDiv'></div></th>";
worker += "<th></th>";
worker += "<th></th>";
worker += "<th colspan=2><div id='dxccFilterDiv'></div></th>";
worker += "</tr> ";
worker +=
"<tr><th style='cursor:pointer;' align=center onclick='window.opener.showWorkedBox(0);'>Station</th>";
worker +=
"<th style='cursor:pointer;' align=center onclick='window.opener.showWorkedBox(1);'>Grid</th>";
worker +=
"<th style='cursor:pointer;' align=center onclick='window.opener.showWorkedBox(5);'>Band</th>";
worker +=
"<th style='cursor:pointer;' align=center onclick='window.opener.showWorkedBox(2);'>Mode</th>";
worker +=
"<th style='cursor:pointer;' align=center onclick='window.opener.showWorkedBox(6);'>QSL</th>";
worker += "<th align=center>Sent</th>";
worker += "<th align=center>Rcvd</th>";
worker +=
"<th style='cursor:pointer;' align=center onclick='window.opener.showWorkedBox(3);'>DXCC</th>";
worker +=
"<th style='cursor:pointer;' align=center onclick='window.opener.showWorkedBox(3);'>Flag</th>";
worker +=
"<th style='cursor:pointer;' align=center onclick='window.opener.showWorkedBox(4);'>When</th>";
if (g_callsignLookups.lotwUseEnable == true) worker += "<th>LoTW</th>";
if (g_callsignLookups.eqslUseEnable == true) worker += "<th>eQSL</th>";
if (g_callsignLookups.oqrsUseEnable == true) worker += "<th>OQRS</th>";
worker += "</tr>";
var key = null;
for (var i = startIndex; i < endIndex; i++) {
key = list[i];
worker +=
"<tr align=left><td style='color:#ff0;cursor:pointer' onclick='window.opener.startLookup(\"" +
key.DEcall +
'","' +
key.grid +
"\");' >" +
key.DEcall.formatCallsign() +
"</td>";
worker +=
"<td style='color:cyan;' >" +
key.grid +
(key.vucc_grids.length ? ", " + key.vucc_grids.join(", ") : "") +
"</td>";
worker += "<td style='color:lightgreen'>" + key.band + "</td>";
worker += "<td style='color:lightblue'>" + key.mode + "</td>";
worker +=
"<td align=center>" + (key.confirmed ? "&#10004;" : "") + "</td>";
worker += "<td>" + key.RSTsent + "</td>";
worker += "<td>" + key.RSTrecv + "</td>";
worker +=
"<td style='color:orange'>" +
g_dxccToAltName[key.dxcc] +
" <font color='lightgreen'>(" +
(g_dxccToGeoData[key.dxcc] in g_worldGeoData
? g_worldGeoData[g_dxccToGeoData[key.dxcc]].pp
: "?") +
")</font></td>";
worker +=
"<td align=center style='margin:0;padding:0' ><img style='padding-top:4px' src='./img/flags/16/" +
(g_dxccToGeoData[key.dxcc] in g_worldGeoData
? g_worldGeoData[g_dxccToGeoData[key.dxcc]].flag
: "_United Nations.png") +
"'></td>";
worker +=
"<td style='color:lightblue'>" +
userTimeString(key.time * 1000) +
"</td>";
if (g_callsignLookups.lotwUseEnable == true)
worker +=
"<td align=center>" +
(key.DEcall in g_lotwCallsigns ? "&#10004;" : "") +
"</td>";
if (g_callsignLookups.eqslUseEnable == true)
worker +=
"<td align=center>" +
(key.DEcall in g_eqslCallsigns ? "&#10004;" : "") +
"</td>";
if (g_callsignLookups.oqrsUseEnable == true)
worker +=
"<td align=center>" +
(key.DEcall in g_oqrsCallsigns ? "&#10004;" : "") +
"</td>";
worker += "</tr>";
}
worker += "</table>";
setStatsDiv("workedListDiv", worker);
statsValidateCallByElement("searchWB");
statsValidateCallByElement("searchGrid");
var newSelect = document.createElement("select");
newSelect.id = "bandFilter";
newSelect.title = "Band Filter";
var option = document.createElement("option");
option.value = "Mixed";
option.text = "Mixed";
newSelect.appendChild(option);
Object.keys(bands)
.sort(function (a, b) {
return parseInt(a) - parseInt(b);
})
.forEach(function (key) {
var option = document.createElement("option");
option.value = key;
option.text = key;
newSelect.appendChild(option);
});
statsAppendChild(
"bandFilterDiv",
newSelect,
"filterBandFunction",
g_filterBand,
true
);
newSelect = document.createElement("select");
newSelect.id = "modeFilter";
newSelect.title = "Mode Filter";
option = document.createElement("option");
option.value = "Mixed";
option.text = "Mixed";
newSelect.appendChild(option);
option = document.createElement("option");
option.value = "Phone";
option.text = "Phone";
newSelect.appendChild(option);
option = document.createElement("option");
option.value = "Digital";
option.text = "Digital";
newSelect.appendChild(option);
Object.keys(modes)
.sort()
.forEach(function (key) {
var option = document.createElement("option");
option.value = key;
option.text = key;
newSelect.appendChild(option);
});
statsAppendChild(
"modeFilterDiv",
newSelect,
"filterModeFunction",
g_filterMode,
true
);
newSelect = document.createElement("select");
newSelect.id = "dxccFilter";
newSelect.title = "DXCC Filter";
option = document.createElement("option");
option.value = 0;
option.text = "All";
newSelect.appendChild(option);
Object.keys(dxccs)
.sort()
.forEach(function (key) {
var option = document.createElement("option");
option.value = dxccs[key];
option.text = key;
newSelect.appendChild(option);
});
statsAppendChild(
"dxccFilterDiv",
newSelect,
"filterDxccFunction",
g_filterDxcc,
true
);
newSelect = document.createElement("select");
newSelect.id = "qslFilter";
newSelect.title = "QSL Filter";
option = document.createElement("option");
option.value = "All";
option.text = "All";
newSelect.appendChild(option);
option = document.createElement("option");
option.value = true;
option.text = "Yes";
newSelect.appendChild(option);
option = document.createElement("option");
option.value = false;
option.text = "No";
newSelect.appendChild(option);
statsAppendChild(
"qslFilterDiv",
newSelect,
"filterQSLFunction",
g_filterQSL,
true
);
statsFocus(g_lastSearchSelection);
setStatsDivHeight("workedListDiv", getStatsWindowHeight() - 6 + "px");
} else setStatsDiv("workedListDiv", "None");
}
myObjects = null;
} catch (e) {
console.log(e);
}
}
function statsValidateCallByElement(elementString) {
if (
g_statsWindowHandle != null &&
typeof g_statsWindowHandle.window.validateCallByElement !== "undefined"
) {
g_statsWindowHandle.window.validateCallByElement(elementString);
}
}
function statsFocus(selection) {
if (
g_statsWindowHandle != null &&
typeof g_statsWindowHandle.window.statsFocus !== "undefined"
) {
g_statsWindowHandle.window.statsFocus(selection);
}
}
function lookupValidateCallByElement(elementString) {
if (
g_lookupWindowHandle != null &&
typeof g_statsWindowHandle.window.validateCallByElement !== "undefined"
) {
g_lookupWindowHandle.window.validateCallByElement(elementString);
}
}
function lookupFocus(selection) {
if (
g_lookupWindowHandle != null &&
typeof g_statsWindowHandle.window.statsFocus !== "undefined"
) {
g_lookupWindowHandle.window.statsFocus(selection);
}
}
function statsAppendChild(elementString, object, onInputString, defaultValue) {
if (
g_statsWindowHandle != null &&
typeof g_statsWindowHandle.window.appendToChild !== "undefined"
) {
g_statsWindowHandle.window.appendToChild(
elementString,
object,
onInputString,
defaultValue
);
}
}
function showDXCCsBox() {
{
var worker = getCurrentBandModeHTML();
var confirmed = 0;
var worked = 0;
var needed = 0;
var List = {};
var ListConfirmed = {};
var ListNotWorked = {};
for (var key in g_worldGeoData) {
if (key != -1) {
if (g_worldGeoData[key].worked == true) {
var item = {};
item.dxcc = g_worldGeoData[key].dxcc;
item.flag = g_worldGeoData[key].flag;
item.confirmed = g_worldGeoData[key].confirmed;
List[g_worldGeoData[key].name] = item;
worked++;
}
if (g_worldGeoData[key].confirmed == true) {
var item = {};
item.dxcc = g_worldGeoData[key].dxcc;
item.flag = g_worldGeoData[key].flag;
item.confirmed = g_worldGeoData[key].confirmed;
ListConfirmed[g_worldGeoData[key].name] = item;
confirmed++;
}
if (
g_worldGeoData[key].worked == false &&
g_worldGeoData[key].confirmed == false &&
g_worldGeoData[key].pp != "" &&
g_worldGeoData[key].geo != "deleted"
) {
var item = {};
item.dxcc = g_worldGeoData[key].dxcc;
item.flag = g_worldGeoData[key].flag;
item.confirmed = g_worldGeoData[key].confirmed;
ListNotWorked[g_worldGeoData[key].name] = item;
needed++;
}
}
}
if (worked > 0) {
worker +=
"<div style='vertical-align:top;display:inline-block;margin-right:2px;overflow:auto;overflow-x:hidden;height:" +
Math.min(Object.keys(List).length * 23 + 45, getStatsWindowHeight()) +
"px;'><table class='darkTable' align=center><tr><th colspan=5 style='font-weight:bold'>Worked (" +
worked +
")</th><tr><th align=left>Name</th><th>Flag</th><th align=left>DXCC</th></tr>";
Object.keys(List)
.sort()
.forEach(function (key, i) {
var confirmed = List[key].confirmed
? ""
: "background-clip:content-box;box-shadow: 0 0 8px 3px inset ";
worker +=
"<tr><td align=left style='color:#ff0;" +
confirmed +
"' >" +
key +
"</td>";
worker +=
"<td align='center' style='margin:0;padding:0'><img style='padding-top:3px' src='./img/flags/16/" +
List[key].flag +
"'></td>";
worker +=
"<td align=left style='color:cyan;' >" + List[key].dxcc + "</td>";
});
worker += "</table></div>";
}
if (confirmed > 0) {
worker +=
"<div style='padding:0px;vertical-align:top;display:inline-block;margin-right:2px;overflow:auto;overflow-x:hidden;height:" +
Math.min(
Object.keys(ListConfirmed).length * 23 + 45,
getStatsWindowHeight()
) +
"px;'><table class='darkTable' align=center><tr><th colspan=5 style='font-weight:bold'>Confirmed (" +
confirmed +
")</th><tr><th align=left>Name</th><th>Flag</th><th align=left>DXCC</th></tr>";
Object.keys(ListConfirmed)
.sort()
.forEach(function (key, i) {
worker += "<tr><td align=left style='color:#ff0;' >" + key + "</td>";
worker +=
"<td align='center' style='margin:0;padding:0'><img style='padding-top:3px' src='./img/flags/16/" +
ListConfirmed[key].flag +
"'></td>";
worker +=
"<td align=left style='color:cyan;' >" +
ListConfirmed[key].dxcc +
"</td>";
});
worker += "</table></div>";
}
if (needed > 0) {
worker +=
"<div style='vertical-align:top;display:inline-block;overflow:auto;overflow-x:hidden;height:" +
Math.min(
Object.keys(ListNotWorked).length * 23 + 45,
getStatsWindowHeight()
) +
"px;'><table class='darkTable' align=center><tr><th colspan=3 style='font-weight:bold'>Needed (" +
needed +
")</th><tr><th align=left>Name</th><th>Flag</th><th align=left>DXCC</th></tr>";
Object.keys(ListNotWorked)
.sort()
.forEach(function (key, i) {
worker += "<tr><td align=left style='color:#ff0;' >" + key + "</td>";
worker +=
"<td align='center' style='margin:0;padding:0'><img style='padding-top:3px' src='./img/flags/16/" +
ListNotWorked[key].flag +
"'></td>";
worker +=
"<td align=left style='color:cyan;' >" +
ListNotWorked[key].dxcc +
"</td>";
});
worker += "</table></div>";
}
setStatsDiv("dxccListDiv", worker);
}
}
function showCQzoneBox() {
var worker = getCurrentBandModeHTML();
worker +=
"<div style='vertical-align:top;display:inline-block;margin-right:8px;overflow:auto;overflow-x:hidden;color:cyan;'><b>Worked CQ Zones</b><br/>";
worker += displayItemList(g_cqZones, "#FFFFFF");
worker += "</div>";
setStatsDiv("cqzoneListDiv", worker);
}
function showITUzoneBox() {
var worker = getCurrentBandModeHTML();
worker +=
"<div style='vertical-align:top;display:inline-block;margin-right:8px;overflow:auto;overflow-x:hidden;color:cyan;'><b>Worked ITU Zones</b><br/>";
worker += displayItemList(g_ituZones, "#FFFFFF");
worker += "</div>";
setStatsDiv("ituzoneListDiv", worker);
}
function showWASWACzoneBox() {
var worker = getCurrentBandModeHTML();
worker +=
"<div style='vertical-align:top;display:inline-block;margin-right:8px;overflow:auto;overflow-x:hidden;color:cyan;'><b>Worked All Continents</b><br/>";
worker += displayItemList(g_wacZones, "#90EE90");
worker += "</div>";
worker +=
"<div style='vertical-align:top;display:inline-block;margin-right:8px;overflow:auto;overflow-x:hidden;color:cyan;'><b>Worked All States</b><br/>";
worker += displayItemList(g_wasZones, "#00DDDD");
worker += "</div>";
setStatsDiv("waswacListDiv", worker);
}
function displayItemList(table, color) {
var worked = 0;
var needed = 0;
var confirmed = 0;
for (var key in table) {
if (table[key].worked == true) {
worked++;
}
if (table[key].confirmed == true) {
confirmed++;
}
if (table[key].confirmed == false && table[key].worked == false) {
needed++;
}
}
var worker =
"<div style='color:white;vertical-align:top;display:inline-block;margin-right:8px;overflow:auto;overflow-x:hidden;height:" +
Math.min(
Object.keys(table).length * 23 + (23 + 45),
getStatsWindowHeight() - 12
) +
"px;'>";
worker += "<table class='darkTable' align=center>";
worker +=
"<tr><th style='font-weight:bold'>Worked (" + worked + ")</th></tr>";
worker +=
"<tr><th style='font-weight:bold'>Confirmed (" + confirmed + ")</th></tr>";
worker +=
"<tr><th style='font-weight:bold'>Needed (" + needed + ")</th></tr>";
worker += "<tr><th align=left>Name</th></tr>";
var inversionAlpha = "DD";
var confirmed = "";
var bold = "text-shadow: 0px 0px 1px black;";
var unconf = "background-clip:content-box;box-shadow: 0 0 8px 3px inset ";
Object.keys(table)
.sort()
.forEach(function (key, i) {
var style;
if (table[key].confirmed == true) {
style = "color:" + color + ";" + confirmed;
} else if (table[key].worked == true) {
style = "color:" + color + ";" + unconf;
} else {
// needed
style = "color:#000000;background-color:" + color + ";" + bold;
}
worker +=
"<tr><td align=left style='" + style + "'>" + key + "</td></tr>";
});
worker += "</table></div>";
return worker;
}
function showWPXBox() {
var worker = getCurrentBandModeHTML();
var band =
g_appSettings.gtBandFilter == "auto"
? myBand
: g_appSettings.gtBandFilter.length == 0
? ""
: g_appSettings.gtBandFilter;
var mode =
g_appSettings.gtModeFilter == "auto"
? myMode
: g_appSettings.gtModeFilter.length == 0
? ""
: g_appSettings.gtModeFilter;
if (mode == "Digital") mode = "dg";
if (mode == "Phone") mode = "ph";
var modifier = String(band) + String(mode);
var worked = 0;
var confirmed = 0;
var List = {};
var ListConfirmed = {};
for (var key in g_tracker.worked.px) {
if (
typeof g_tracker.worked.px[key] == "string" &&
key + modifier in g_tracker.worked.px
) {
List[key] = key;
}
}
for (var key in g_tracker.confirmed.px) {
if (
typeof g_tracker.confirmed.px[key] == "string" &&
key + modifier in g_tracker.confirmed.px
) {
ListConfirmed[key] = key;
}
}
worked = Object.keys(List).length;
confirmed = Object.keys(ListConfirmed).length;
if (worked > 0) {
worker +=
"<div style='vertical-align:top;display:inline-block;margin-right:8px;overflow:auto;overflow-x:hidden;color:cyan;'><b>Worked Prefixes (<font color='#fff'>" +
worked +
"</font>)</b><br/>";
worker +=
"<div style='color:white;vertical-align:top;display:inline-block;margin-right:8px;overflow:auto;overflow-x:hidden;height:" +
Math.min(worked * 23 + 45, getStatsWindowHeight() - 6) +
"px;'><table class='darkTable' align=center>";
Object.keys(List)
.sort()
.forEach(function (key, i) {
worker +=
"<tr><td align=left style='color:#ff0;' >" +
key.formatCallsign() +
"</td><td style='color:#0ff;'>" +
g_QSOhash[g_tracker.worked.px[key]].DEcall.formatCallsign() +
"</td></tr>";
});
worker += "</table></div>";
worker += "</div>";
}
if (confirmed > 0) {
worker +=
"<div style='vertical-align:top;display:inline-block;margin-right:8px;overflow:auto;overflow-x:hidden;color:cyan;'><b>Confirmed Prefixes (<font color='#fff'>" +
confirmed +
"</font>)</b><br/>";
worker +=
"<div style='color:white;vertical-align:top;display:inline-block;margin-right:8px;overflow:auto;overflow-x:hidden;height:" +
Math.min(confirmed * 23 + 45, getStatsWindowHeight() - 6) +
"px;'><table class='darkTable' align=center>";
Object.keys(ListConfirmed)
.sort()
.forEach(function (key, i) {
worker +=
"<tr><td align=left style='color:#ff0;' >" +
key.formatCallsign() +
"</td><td style='color:#0ff;'>" +
g_QSOhash[g_tracker.confirmed.px[key]].DEcall.formatCallsign() +
"</td></tr>";
});
worker += "</table></div>";
worker += "</div>";
}
setStatsDiv("wpxListDiv", worker);
}
function showRootInfoBox() {
openStatsWindow();
return;
}
function showSettingsBox() {
{
updateRunningProcesses();
helpDiv.style.display = "none";
g_helpShow = false;
rootSettingsDiv.style.display = "inline-block";
}
}
function toggleBaWindow(event) {
event.preventDefault();
if (g_baWindowHandle == null) {
openBaWindow(true);
} else {
if (g_baWindowHandle.window.g_isShowing == true) {
openBaWindow(false);
} else {
openBaWindow(true);
}
}
}
function openBaWindow(show = true) {
if (g_baWindowHandle == null) {
popupNewWindows();
var gui = require("nw.gui");
gui.Window.open(
"gt_bandactivity.html",
{
show: false,
id: "GT-baac",
frame: false,
resizable: true,
always_on_top: true,
},
function (new_win) {
g_baWindowHandle = new_win;
new_win.on("loaded", function () {
g_baWindowHandle.setMinimumSize(198, 52);
});
new_win.on("close", function () {
g_baWindowHandle.window.g_isShowing = false;
g_baWindowHandle.window.saveScreenSettings();
g_baWindowHandle.hide();
});
}
);
lockNewWindows();
} else {
try {
if (show == true) {
g_baWindowHandle.show();
g_baWindowHandle.window.g_isShowing = true;
g_baWindowHandle.window.saveScreenSettings();
} else {
g_baWindowHandle.window.g_isShowing = false;
g_baWindowHandle.window.saveScreenSettings();
g_baWindowHandle.hide();
}
} catch (e) {}
}
}
function openLookupWindow(show = false) {
if (g_lookupWindowHandle == null) {
popupNewWindows();
var gui = require("nw.gui");
gui.Window.open(
"gt_lookup.html",
{
show: false,
id: "GT-lookups",
icon: "img/lookup-icon.png",
},
function (new_win) {
g_lookupWindowHandle = new_win;
new_win.on("loaded", function () {
g_lookupWindowHandle.setMinimumSize(680, 200);
g_lookupWindowHandle.setResizable(true);
});
new_win.on("close", function () {
g_lookupWindowHandle.window.g_isShowing = false;
g_lookupWindowHandle.window.saveScreenSettings();
g_lookupWindowHandle.hide();
});
}
);
lockNewWindows();
} else {
try {
if (show) {
g_lookupWindowHandle.show();
g_lookupWindowHandle.window.g_isShowing = true;
g_lookupWindowHandle.window.saveScreenSettings();
} else {
g_lookupWindowHandle.hide();
g_lookupWindowHandle.window.g_isShowing = false;
g_lookupWindowHandle.window.saveScreenSettings();
}
} catch (e) {}
}
}
function openInfoTab(evt, tabName, callFunc, callObj) {
openStatsWindow();
if (g_statsWindowHandle != null) {
// Declare all variables
var i, infoTabcontent, infoTablinks;
// Get all elements with class="infoTabcontent" and hide them
infoTabcontent = g_statsWindowHandle.window.document.getElementsByClassName(
"infoTabcontent"
);
for (i = 0; i < infoTabcontent.length; i++) {
infoTabcontent[i].style.display = "none";
}
// Get all elements with class="infoTablinks" and remove the class "active"
infoTablinks = g_statsWindowHandle.window.document.getElementsByClassName(
"infoTablinks"
);
for (i = 0; i < infoTablinks.length; i++) {
infoTablinks[i].className = infoTablinks[i].className.replace(
" active",
""
);
}
// Show the current tab, and add an "active" class to the button that opened the tab
g_statsWindowHandle.window.document.getElementById(tabName).style.display =
"block";
if (evt) {
evt = g_statsWindowHandle.window.document.getElementById(evt);
}
if (evt) {
if (typeof evt.currentTarget != "undefined")
evt.currentTarget.className += " active";
else evt.className += " active";
}
if (callFunc) {
if (callObj) callFunc(callObj);
else callFunc();
}
}
}
function openSettingsTab(evt, tabName) {
// Declare all variables
var i, settingsTabcontent, settingsTablinks;
// Get all elements with class="settingsTabcontent" and hide them
settingsTabcontent = document.getElementsByClassName("settingsTabcontent");
for (i = 0; i < settingsTabcontent.length; i++) {
settingsTabcontent[i].style.display = "none";
}
// Get all elements with class="settingsTablinks" and remove the class "active"
settingsTablinks = document.getElementsByClassName("settingsTablinks");
for (i = 0; i < settingsTablinks.length; i++) {
settingsTablinks[i].className = settingsTablinks[i].className.replace(
" active",
""
);
}
displayAlerts();
// Show the current tab, and add an "active" class to the button that opened the tab
document.getElementById(tabName).style.display = "block";
if (typeof evt.currentTarget != "undefined")
evt.currentTarget.className += " active";
else evt.className += " active";
}
function setGridMode(mode) {
g_appSettings.sixWideMode = mode;
modeImg.src = g_maidenheadModeImageArray[g_appSettings.sixWideMode];
clearTempGrids();
redrawGrids();
}
function toggleGridMode() {
g_appSettings.sixWideMode ^= 1;
modeImg.src = g_maidenheadModeImageArray[g_appSettings.sixWideMode];
clearTempGrids();
redrawGrids();
}
function newStatObject() {
var statObject = {};
statObject.worked = 0;
statObject.confirmed = 0;
statObject.worked_bands = {};
statObject.confirmed_bands = {};
statObject.worked_modes = {};
statObject.confirmed_modes = {};
statObject.worked_types = {};
statObject.confirmed_types = {};
return statObject;
}
function newStatCountObject() {
var statCountObject = {};
statCountObject.worked = 0;
statCountObject.confirmed = 0;
statCountObject.worked_bands = {};
statCountObject.confirmed_bands = {};
statCountObject.worked_modes = {};
statCountObject.confirmed_modes = {};
statCountObject.worked_types = {};
statCountObject.confirmed_types = {};
statCountObject.worked_high = 0;
statCountObject.confirmed_high = 0;
statCountObject.worked_high_key = null;
statCountObject.confirmed_high_key = null;
return statCountObject;
}
function newDistanceObject(start = 0) {
var distance = {};
distance.worked_unit = start;
distance.worked_hash = "";
distance.confirmed_unit = start;
distance.confirmed_hash = null;
return distance;
}
function newModeType() {
var modeType = {};
modeType.worked = 0;
modeType.confirmed = 0;
return modeType;
}
var g_statBoxTimer = null;
function showStatBox(resize) {
var count = Object.keys(g_QSOhash).length;
if (typeof resize != "undefined" && resize) {
setStatsDivHeight("statViewDiv", getStatsWindowHeight() + 29 + "px");
return;
}
if (g_statBoxTimer) clearTimeout(g_statBoxTimer);
if (count > 0) {
setStatsDiv(
"statViewDiv",
"&nbsp;<br/>...Parsing Log Entries...<br/>&nbsp;"
);
setStatsDivHeight("statViewDiv", "auto");
g_statBoxTimer = setTimeout(renderStatsBox, 250);
} else {
setStatsDiv(
"statViewDiv",
"&nbsp;<br/>No log entries available, load one or more ADIF logs<br/>&nbsp;"
);
setStatsDivHeight("statViewDiv", "auto");
}
}
function getTypeFromMode(mode) {
if (mode in g_modes) {
if (g_modes[mode] == true) return "Digital";
else if (g_modes_phone[mode] == true) return "Phone";
else if (mode == "CW") return "CW";
}
return "Other";
}
function workObject(obj, count, band, mode, type, didConfirm) {
obj.worked++;
obj.worked_bands[band] = ~~obj.worked_bands[band] + 1;
obj.worked_modes[mode] = ~~obj.worked_modes[mode] + 1;
if (!count) {
obj.worked_types["Mixed"] = ~~obj.worked_modes["Mixed"] + 1;
if (type) obj.worked_types[type] = ~~obj.worked_modes[type] + 1;
}
if (didConfirm) {
obj.confirmed++;
obj.confirmed_bands[band] = ~~obj.confirmed_bands[band] + 1;
obj.confirmed_modes[mode] = ~~obj.confirmed_modes[mode] + 1;
if (!count) {
obj.confirmed_types["Mixed"] = ~~obj.confirmed_types["Mixed"] + 1;
if (type) obj.confirmed_types[type] = ~~obj.confirmed_types[type] + 1;
}
}
return obj;
}
function renderStatsBox() {
var worker = "";
var scoreSection = "Initial";
try {
var worldGeoData = {};
var cqZones = {};
var ituZones = {};
var wasZones = {};
var wacZones = {};
var countyData = {};
var gridData = {};
var wpxData = {};
var callData = {};
var gtData = {};
var long_distance = newDistanceObject();
var short_distance = newDistanceObject(100000);
long_distance.band = {};
long_distance.mode = {};
long_distance.type = {};
short_distance.band = {};
short_distance.mode = {};
short_distance.type = {};
var modet = {};
modet.Mixed = newStatCountObject();
modet.Digital = newStatCountObject();
modet.Phone = newStatCountObject();
modet.CW = newStatCountObject();
modet.Other = newStatCountObject();
var details = {};
details.callsigns = {};
details.oldest = timeNowSec() + 86400;
details.newest = 0;
scoreSection = "QSO";
for (var i in g_QSOhash) {
var finalGrid = g_QSOhash[i].grid;
var didConfirm = g_QSOhash[i].confirmed;
var band = g_QSOhash[i].band;
var mode = g_QSOhash[i].mode;
var state = g_QSOhash[i].state;
var cont = g_QSOhash[i].cont;
var finalDxcc = g_QSOhash[i].dxcc;
var cnty = g_QSOhash[i].cnty;
var ituz = g_QSOhash[i].ituz;
var cqz = g_QSOhash[i].cqz;
var wpx = g_QSOhash[i].px;
var call = g_QSOhash[i].DXcall;
var who = g_QSOhash[i].DEcall;
var type = getTypeFromMode(mode);
if (!(who in callData)) callData[who] = newStatObject();
workObject(callData[who], false, band, mode, type, didConfirm);
details.callsigns[call] = ~~details.callsigns[call] + 1;
if (g_QSOhash[i].time < details.oldest)
details.oldest = g_QSOhash[i].time;
if (g_QSOhash[i].time > details.newest)
details.newest = g_QSOhash[i].time;
workObject(modet.Mixed, true, band, mode, type, didConfirm);
if (mode in g_modes) {
if (g_modes[mode] == true) {
workObject(modet.Digital, true, band, mode, type, didConfirm);
} else if (g_modes_phone[mode] == true) {
workObject(modet.Phone, true, band, mode, type, didConfirm);
} else if (mode == "CW") {
workObject(modet.CW, true, band, mode, type, didConfirm);
} else workObject(modet.Other, true, band, mode, type, didConfirm);
} else workObject(modet.Other, true, band, mode, type, didConfirm);
if (state != null && isKnownCallsignUS(finalDxcc)) {
if (state.substr(0, 2) != "US") state = "US-" + state;
if (state in g_StateData) {
var name = g_StateData[state].name;
if (name in g_wasZones) {
if (!(name in wasZones)) wasZones[name] = newStatObject();
workObject(wasZones[name], false, band, mode, type, didConfirm);
}
}
}
if (wpx != null) {
if (!(wpx in wpxData)) wpxData[wpx] = newStatObject();
workObject(wpxData[wpx], false, band, mode, type, didConfirm);
}
if (who in g_gtCallsigns) {
if (!(i in gtData)) gtData[i] = newStatObject();
gtData[i] = true;
}
if (cnty != null) {
if (cnty in g_cntyToCounty) {
if (!(cnty in countyData)) countyData[cnty] = newStatObject();
workObject(countyData[cnty], false, band, mode, type, didConfirm);
}
}
if (cont != null) {
if (cont in g_shapeData) {
var name = g_shapeData[cont].properties.name;
if (name in g_wacZones) {
if (!(name in wacZones)) wacZones[name] = newStatObject();
workObject(wacZones[name], false, band, mode, type, didConfirm);
}
}
}
if (finalGrid.length > 0) {
LL = squareToLatLongAll(finalGrid);
unit = parseInt(
MyCircle.distance(
g_myLat,
g_myLon,
LL.la2 - (LL.la2 - LL.la1) / 2,
LL.lo2 - (LL.lo2 - LL.lo1) / 2,
distanceUnit.value
) * MyCircle.validateRadius(distanceUnit.value)
);
if (unit > long_distance.worked_unit) {
long_distance.worked_unit = unit;
long_distance.worked_hash = i;
}
if (!(band in long_distance.band))
long_distance.band[band] = newDistanceObject();
if (!(mode in long_distance.mode))
long_distance.mode[mode] = newDistanceObject();
if (!(type in long_distance.type))
long_distance.type[type] = newDistanceObject();
if (unit > long_distance.mode[mode].worked_unit) {
long_distance.mode[mode].worked_unit = unit;
long_distance.mode[mode].worked_hash = i;
}
if (unit > long_distance.band[band].worked_unit) {
long_distance.band[band].worked_unit = unit;
long_distance.band[band].worked_hash = i;
}
if (unit > long_distance.type[type].worked_unit) {
long_distance.type[type].worked_unit = unit;
long_distance.type[type].worked_hash = i;
}
if (didConfirm) {
if (unit > long_distance.confirmed_unit) {
long_distance.confirmed_unit = unit;
long_distance.confirmed_hash = i;
}
if (unit > long_distance.mode[mode].confirmed_unit) {
long_distance.mode[mode].confirmed_unit = unit;
long_distance.mode[mode].confirmed_hash = i;
}
if (unit > long_distance.band[band].confirmed_unit) {
long_distance.band[band].confirmed_unit = unit;
long_distance.band[band].confirmed_hash = i;
}
if (unit > long_distance.type[type].confirmed_unit) {
long_distance.type[type].confirmed_unit = unit;
long_distance.type[type].confirmed_hash = i;
}
}
if (unit > 0) {
if (unit < short_distance.worked_unit) {
short_distance.worked_unit = unit;
short_distance.worked_hash = i;
}
if (!(band in short_distance.band))
short_distance.band[band] = newDistanceObject(100000);
if (!(mode in short_distance.mode))
short_distance.mode[mode] = newDistanceObject(100000);
if (!(type in short_distance.type))
short_distance.type[type] = newDistanceObject(100000);
if (unit < short_distance.mode[mode].worked_unit) {
short_distance.mode[mode].worked_unit = unit;
short_distance.mode[mode].worked_hash = i;
}
if (unit < short_distance.band[band].worked_unit) {
short_distance.band[band].worked_unit = unit;
short_distance.band[band].worked_hash = i;
}
if (unit < short_distance.type[type].worked_unit) {
short_distance.type[type].worked_unit = unit;
short_distance.type[type].worked_hash = i;
}
if (didConfirm) {
if (unit < short_distance.confirmed_unit) {
short_distance.confirmed_unit = unit;
short_distance.confirmed_hash = i;
}
if (unit < short_distance.mode[mode].confirmed_unit) {
short_distance.mode[mode].confirmed_unit = unit;
short_distance.mode[mode].confirmed_hash = i;
}
if (unit < short_distance.band[band].confirmed_unit) {
short_distance.band[band].confirmed_unit = unit;
short_distance.band[band].confirmed_hash = i;
}
if (unit < short_distance.type[type].confirmed_unit) {
short_distance.type[type].confirmed_unit = unit;
short_distance.type[type].confirmed_hash = i;
}
}
}
}
if (!(g_dxccToAltName[finalDxcc] in worldGeoData))
worldGeoData[g_dxccToAltName[finalDxcc]] = newStatObject();
workObject(
worldGeoData[g_dxccToAltName[finalDxcc]],
false,
band,
mode,
type,
didConfirm
);
if (finalGrid.length > 0) {
var gridCheck = finalGrid.substr(0, 4);
if (cqz.length > 0) {
var name = g_cqZones[cqz].name;
if (!(name in cqZones)) cqZones[name] = newStatObject();
workObject(cqZones[name], false, band, mode, type, didConfirm);
} else if (gridCheck in g_gridToCQZone) {
if (g_gridToCQZone[gridCheck].length == 1) {
var name = g_cqZones[g_gridToCQZone[gridCheck][0]].name;
if (!(name in cqZones)) cqZones[name] = newStatObject();
workObject(cqZones[name], false, band, mode, type, didConfirm);
}
}
if (ituz.length > 0) {
if (!(ituz in ituZones)) ituZones[ituz] = newStatObject();
workObject(ituZones[ituz], false, band, mode, type, didConfirm);
} else if (gridCheck in g_gridToITUZone) {
if (g_gridToITUZone[gridCheck].length == 1) {
if (!(g_gridToITUZone[gridCheck][0] in ituZones))
ituZones[g_gridToITUZone[gridCheck][0]] = newStatObject();
workObject(
ituZones[g_gridToITUZone[gridCheck][0]],
false,
band,
mode,
type,
didConfirm
);
}
}
if (!(gridCheck in gridData)) gridData[gridCheck] = newStatObject();
workObject(gridData[gridCheck], false, band, mode, type, didConfirm);
}
}
scoreSection = "Stats";
var stats = {};
var output = {};
worldGeoData.order = 1;
stats["DXCC"] = worldGeoData;
stats["GRID"] = gridData;
stats["CQ"] = cqZones;
stats["ITU"] = ituZones;
stats["WAC"] = wacZones;
stats["WAS"] = wasZones;
stats["USC"] = countyData;
stats["WPX"] = wpxData;
stats["WRFA"] = callData;
for (i in stats) {
output[i] = newStatCountObject();
for (var key in stats[i]) {
if (stats[i][key].worked) {
output[i].worked++;
if (stats[i][key].worked > output[i].worked_high) {
output[i].worked_high = stats[i][key].worked;
output[i].worked_high_key = key;
}
}
if (stats[i][key].confirmed) {
output[i].confirmed++;
if (stats[i][key].confirmed > output[i].confirmed_high) {
output[i].confirmed_high = stats[i][key].confirmed;
output[i].confirmed_high_key = key;
}
}
for (var band in stats[i][key].worked_bands) {
output[i].worked_bands[band] = ~~output[i].worked_bands[band] + 1;
}
for (var band in stats[i][key].confirmed_bands) {
output[i].confirmed_bands[band] =
~~output[i].confirmed_bands[band] + 1;
}
for (var mode in stats[i][key].worked_modes) {
output[i].worked_modes[mode] = ~~output[i].worked_modes[mode] + 1;
}
for (var mode in stats[i][key].confirmed_modes) {
output[i].confirmed_modes[mode] =
~~output[i].confirmed_modes[mode] + 1;
}
for (var type in stats[i][key].worked_types) {
output[i].worked_types[type] = ~~output[i].worked_types[type] + 1;
}
for (var type in stats[i][key].confirmed_types) {
output[i].confirmed_types[type] =
~~output[i].confirmed_types[type] + 1;
}
}
stats[i] = null;
}
scoreSection = "Modes";
output["MIXED"] = modet.Mixed;
output["DIGITAL"] = modet.Digital;
output["PHONE"] = modet.Phone;
output["CW"] = modet.CW;
output["Other"] = modet.Other;
for (var i in output) {
output[i].worked_band_count = Object.keys(output[i].worked_bands).length;
output[i].confirmed_band_count = Object.keys(
output[i].confirmed_bands
).length;
output[i].worked_mode_count = Object.keys(output[i].worked_modes).length;
output[i].confirmed_mode_count = Object.keys(
output[i].confirmed_modes
).length;
output[i].worked_type_count = Object.keys(output[i].worked_types).length;
output[i].confirmed_type_count = Object.keys(
output[i].confirmed_types
).length;
}
var TypeNames = {
0: ["MIXED", "Mixed", ""],
1: ["DIGITAL", "Digital", ""],
2: ["PHONE", "Phone", ""],
3: ["CW", "CW", ""],
4: ["Other", "Other", ""],
};
var AwardNames = {
0: ["WRFA", "Callsigns", "WRFA", "yellow"],
1: ["GRID", "Grids", "GSA", "cyan"],
2: ["DXCC", "DXCCs", "DXWA", "orange"],
3: ["CQ", "CQ Zones", "WAZ", "lightgreen"],
4: ["ITU", "ITU Zones", "ITUz", "#DD44DD"],
5: ["WAC", "Continents", "WAC", "cyan"],
6: ["WAS", "US States", "WAS", "lightblue"],
7: ["USC", "US Counties", "USA-CA", "orange"],
8: ["WPX", "Prefixes", "WPX", "yellow"],
};
worker = "<font color='cyan'>";
worker += "<h1>Logbook</h1>";
worker +=
"<table style='display:inline-table;margin:5px;' class='darkTable'>";
var ws = "";
if (Object.keys(details.callsigns).length > 1) ws = "s";
worker +=
"<tr><td>Callsign" +
ws +
"</td><td style='color:yellow' ><b>" +
Object.keys(details.callsigns).sort().join(", ") +
"</b></td></tr>";
worker +=
"<tr><td>First Contact</td><td style='color:white' >" +
userTimeString(details.oldest * 1000) +
"</td></tr>";
worker +=
"<tr><td>Last Contact</td><td style='color:white' >" +
userTimeString(details.newest * 1000) +
"</td></tr>";
worker += "</table>";
worker += "</br>";
worker += "<h1>Score Card</h1>";
worker +=
"<table style='display:inline-table;margin:5px;' class='darkTable'>";
worker +=
"<tr><th>Top Score</th><th style='color:yellow'>Worked</th><th style='color:lightgreen'>Confirmed</th></tr>";
for (var key in AwardNames) {
scoreSection = "Award " + AwardNames[key][1];
var infoObject = output[AwardNames[key][0]];
worker += "<tr><td style='color:white'>" + AwardNames[key][1] + "</td>";
worker +=
"<td style='color:" +
AwardNames[key][3] +
"'>" +
infoObject.worked_high_key +
"<font color='white'> (" +
infoObject.worked_high +
")</font></td>";
if (infoObject.confirmed_high_key) {
worker +=
"<td style='color:" +
AwardNames[key][3] +
"'>" +
infoObject.confirmed_high_key +
"<font color='white'> (" +
infoObject.confirmed_high +
")</font></td>";
} else worker += "<td></td>";
worker += "</tr>";
}
scoreSection = "Long Distance";
worker += "<tr><td style='color:white'>Long Distance</td>";
worker +=
"<td style='color:lightgreen'>" +
long_distance.worked_unit +
" " +
distanceUnit.value.toLowerCase();
worker +=
"<font style='color:yellow' > " +
g_QSOhash[long_distance.worked_hash].DEcall +
"</font>";
worker +=
"<font style='color:orange' > " +
g_QSOhash[long_distance.worked_hash].grid +
"</font></td>";
if (long_distance.confirmed_hash && long_distance.confirmed_unit > 0) {
worker +=
"<td style='color:lightgreen'>" +
long_distance.confirmed_unit +
" " +
distanceUnit.value.toLowerCase();
worker +=
"<font style='color:yellow' > " +
g_QSOhash[long_distance.confirmed_hash].DEcall +
"</font>";
worker +=
"<font style='color:orange' > " +
g_QSOhash[long_distance.confirmed_hash].grid +
"</font></td>";
} else worker += "<td></td>";
scoreSection = "Short Distance";
worker += "<tr><td style='color:white' >Short Distance</td>";
worker +=
"<td style='color:lightblue'>" +
short_distance.worked_unit +
" " +
distanceUnit.value.toLowerCase();
worker +=
"<font style='color:yellow' > " +
g_QSOhash[short_distance.worked_hash].DEcall +
"</font>";
worker +=
"<font style='color:orange' > " +
g_QSOhash[short_distance.worked_hash].grid +
"</font></td>";
if (short_distance.confirmed_hash && short_distance.confirmed_unit > 0) {
worker +=
"<td style='color:lightblue'>" +
short_distance.confirmed_unit +
" " +
distanceUnit.value.toLowerCase();
worker +=
"<font style='color:yellow' > " +
g_QSOhash[short_distance.confirmed_hash].DEcall +
"</font>";
worker +=
"<font style='color:orange' > " +
g_QSOhash[short_distance.confirmed_hash].grid +
"</font></td>";
} else worker += "<td></td>";
worker += "</tr>";
worker += "</table>";
worker += "</br>";
worker += "<h1>Award Types</h1>";
scoreSection = "Award Types";
for (var key in AwardNames)
worker += createStatTable(
AwardNames[key][1],
output[AwardNames[key][0]],
AwardNames[key][2]
);
worker += "<br/>";
scoreSection = "Mode Types";
worker += "<h1>Mode Types</h1>";
for (var key in TypeNames)
worker += createStatTable(
TypeNames[key][1],
output[TypeNames[key][0]],
TypeNames[key][2]
);
worker += "<br/>";
worker += "<h1>Distances</h1>";
scoreSection = "Distances";
worker += createDistanceTable(long_distance, "Longest Distance");
worker += createDistanceTable(short_distance, "Shortest Distance");
worker += "<br/>";
if (g_appSettings.gtShareEnable == true) {
scoreSection = "GT Users";
worker += "<h1>Worked GridTracker Stations<br/>Online Now</h1>";
worker += "</font>";
worker += "<font color='white'>";
worker += createGtStationsTable(gtData);
worker += "<br/>";
worker += "</font>";
}
worker += "</font>";
} catch (e) {
worker +=
"<br/> In Section: " +
scoreSection +
"<br/>Error Generating Stats<br/>Please take a screenshot and send to gridtracker@gmail.com";
}
setStatsDiv("statViewDiv", worker);
setStatsDivHeight("statViewDiv", getStatsWindowHeight() + 29 + "px");
}
function hashNameSort(a, b) {
if (g_QSOhash[a].DEcall > g_QSOhash[b].DEcall) return 1;
if (g_QSOhash[b].DEcall > g_QSOhash[a].DEcall) return -1;
return 0;
}
function createGtStationsTable(obj) {
var worker =
"<table style='display:inline-table;margin:5px;white-space:nowrap;' class='darkTable'>";
worker +=
"<tr align='center'><th>Call</th><th>Grid</th><th>Sent</th><th>Rcvd</th><th>Mode</th><th>Band</th><th>QSL</th><th>Comment</th><th>DXCC</th><th>Time</th></th></tr>";
var keys = Object.keys(obj).sort(hashNameSort);
for (var key in keys) {
var callsign = g_QSOhash[keys[key]];
var bgDX = " style='font-weight:bold;color:cyan;' ";
var bgDE = " style='font-weight:bold;color:yellow;' ";
if (typeof callsign.msg == "undefined" || callsign.msg == "")
callsign.msg = "-";
var ageString = "";
if (timeNowSec() - callsign.time < 3601)
ageString = (timeNowSec() - callsign.time).toDHMS();
else {
ageString = userTimeString(callsign.time * 1000);
}
worker += "<tr><td" + bgDE + ">";
worker +=
"<div style='display:inline-table;cursor:pointer' onclick='window.opener.startLookup(\"" +
callsign.DEcall +
'","' +
callsign.grid +
"\");' >" +
callsign.DEcall.formatCallsign() +
"</div>";
worker += "</td>";
worker += "<td style='color:orange'>" + callsign.grid + "</td>";
worker += "<td>" + callsign.RSTsent + "</td>";
worker += "<td>" + callsign.RSTrecv + "</td>";
worker +=
"</td>" +
"<td style='color:lightblue'>" +
callsign.mode +
"</td>" +
"<td style='color:lightgreen'>" +
callsign.band +
"</td>";
worker +=
"<td align='center'>" + (callsign.confirmed ? "&#10004;" : "") + "</td>";
worker +=
"<td>" +
callsign.msg +
"</td><td style='color:yellow'>" +
g_dxccToAltName[callsign.dxcc] +
" <font color='lightgreen'>(" +
g_worldGeoData[g_dxccToGeoData[callsign.dxcc]].pp +
")</font></td>" +
"<td align='center' style='color:lightblue' >" +
ageString +
"</td>";
worker += "</tr>";
}
worker += "</table>";
return worker;
}
function createDistanceTable(obj, name) {
var worker =
"<table style='display:inline-table;margin:5px;' class='darkTable'>";
worker +=
"<tr><th colspan = 3 align=left style='font-size:15px;color:cyan;'>" +
name +
"</th></tr>";
worker +=
"<tr><td></td><td><font color='yellow'>Worked</font></td><td colspan=2 ><font color='lightgreen'>Confirmed</font></td></tr>";
worker += "<tr><td align=center><font color='lightgreen'>Bands</font></td>";
worker += "<td align=left><table class='subtable'>";
var keys = Object.keys(obj.band).sort(numberSort);
for (var key in keys) {
var grid = g_QSOhash[obj.band[keys[key]].worked_hash].grid;
var call = g_QSOhash[obj.band[keys[key]].worked_hash].DEcall;
worker +=
"<tr><td align=right>" +
keys[key] +
"</td><td style='color:lightgreen' align=left>(" +
obj.band[keys[key]].worked_unit +
" " +
distanceUnit.value.toLowerCase() +
")</td>";
worker +=
"<td style='color:yellow;cursor:pointer' align=left onclick='window.opener.startLookup(\"" +
call +
'","' +
grid +
"\");' >" +
call +
"</td>";
worker += "<td style='color:orange' align=left>" + grid + "</td>";
worker += "</tr>";
}
worker += "</table></td>";
worker += "<td align=left><table class='subtable'>";
for (var key in keys) {
if (keys[key] in obj.band && obj.band[keys[key]].confirmed_hash) {
var grid = g_QSOhash[obj.band[keys[key]].confirmed_hash].grid;
var call = g_QSOhash[obj.band[keys[key]].confirmed_hash].DEcall;
worker +=
"<tr><td align=right>" +
keys[key] +
"</td><td style='color:lightgreen' align=left>(" +
obj.band[keys[key]].confirmed_unit +
" " +
distanceUnit.value.toLowerCase() +
")</td>";
worker +=
"<td style='color:yellow;cursor:pointer' align=left onclick='window.opener.startLookup(\"" +
call +
'","' +
grid +
"\");'>" +
call +
"</td>";
worker += "<td style='color:orange' align=left>" + grid + "</td>";
worker += "</tr>";
} else worker += "<tr><td>&nbsp;</td></tr>";
}
worker += "</table></td>";
worker += "</tr>";
worker += "<tr><td align=center><font color='orange'>Modes</font></td>";
worker += "<td align=left><table class='subtable'>";
keys = Object.keys(obj.mode).sort();
for (var key in keys) {
var grid = g_QSOhash[obj.mode[keys[key]].worked_hash].grid;
var call = g_QSOhash[obj.mode[keys[key]].worked_hash].DEcall;
worker +=
"<tr><td align=right>" +
keys[key] +
"</td><td style='color:lightgreen' align=left>(" +
obj.mode[keys[key]].worked_unit +
" " +
distanceUnit.value.toLowerCase() +
")</td>";
worker +=
"<td style='color:yellow;cursor:pointer' align=left onclick='window.opener.startLookup(\"" +
call +
'","' +
grid +
"\");' >" +
call +
"</td>";
worker += "<td style='color:orange' align=left>" + grid + "</td>";
worker += "</tr>";
}
worker += "</table></td>";
worker += "<td align=left><table class='subtable'>";
for (var key in keys) {
if (keys[key] in obj.mode && obj.mode[keys[key]].confirmed_hash) {
var grid = g_QSOhash[obj.mode[keys[key]].confirmed_hash].grid;
var call = g_QSOhash[obj.mode[keys[key]].confirmed_hash].DEcall;
worker +=
"<tr><td align=right>" +
keys[key] +
"</td><td style='color:lightgreen' align=left>(" +
obj.mode[keys[key]].confirmed_unit +
" " +
distanceUnit.value.toLowerCase() +
")</td>";
worker +=
"<td style='color:yellow;cursor:pointer' align=left onclick='window.opener.startLookup(\"" +
call +
'","' +
grid +
"\");' >" +
call +
"</td>";
worker += "<td style='color:orange' align=left>" + grid + "</td>";
worker += "</tr>";
} else worker += "<tr><td>&nbsp;</td></tr>";
}
worker += "</table></td>";
worker += "</tr>";
worker += "<tr><td align=center><font color='#DD44DD'>Types</font></td>";
worker += "<td align=left><table class='subtable'>";
keys = Object.keys(obj.type).sort();
for (var key in keys) {
var grid = g_QSOhash[obj.type[keys[key]].worked_hash].grid;
var call = g_QSOhash[obj.type[keys[key]].worked_hash].DEcall;
worker +=
"<tr><td align=right>" +
keys[key] +
"</td><td style='color:lightgreen' align=left>(" +
obj.type[keys[key]].worked_unit +
" " +
distanceUnit.value.toLowerCase() +
")</td>";
worker +=
"<td style='color:yellow;cursor:pointer' align=left onclick='window.opener.startLookup(\"" +
call +
'","' +
grid +
"\");' >" +
call +
"</td>";
worker += "<td style='color:orange' align=left>" + grid + "</td>";
worker += "</tr>";
}
worker += "</table></td>";
worker += "<td align=left><table class='subtable'>";
for (var key in keys) {
if (keys[key] in obj.type && obj.type[keys[key]].confirmed_hash) {
var grid = g_QSOhash[obj.type[keys[key]].confirmed_hash].grid;
var call = g_QSOhash[obj.type[keys[key]].confirmed_hash].DEcall;
worker +=
"<tr><td align=right>" +
keys[key] +
"</td><td style='color:lightgreen' align=left>(" +
obj.type[keys[key]].confirmed_unit +
" " +
distanceUnit.value.toLowerCase() +
")</td>";
worker +=
"<td style='color:yellow;cursor:pointer' align=left onclick='window.opener.startLookup(\"" +
call +
'","' +
grid +
"\");' >" +
call +
"</td>";
worker += "<td style='color:orange' align=left>" + grid + "</td>";
worker += "</tr>";
} else worker += "<tr><td>&nbsp;</td></tr>";
}
worker += "</table></td>";
worker += "</tr>";
worker += "</table>";
return worker;
}
function numberSort(a, b) {
if (parseInt(a) > parseInt(b)) return 1;
if (parseInt(b) > parseInt(a)) return -1;
return 0;
}
function createStatTable(title, infoObject, awardName) {
var wc1Table = "";
if (infoObject.worked) {
wc1Table =
"<table style='display:inline-table;margin:5px;' class='darkTable'>";
wc1Table +=
"<tr><th colspan = 3 align=left style='font-size:15px;color:cyan;'>" +
title +
"</th></tr>";
var award = "<th></th>";
wc1Table +=
"<tr>" +
award +
"<td><font color='yellow'>Worked</font> <font color='white'>(" +
infoObject.worked +
")</font></td><td colspan=2 ><font color='lightgreen'>Confirmed</font> <font color='white'>(" +
infoObject.confirmed +
")</font></td></tr>";
wc1Table +=
"<tr><td align=center><font color='lightgreen'>Bands</font></td>";
wc1Table += "<td align=left><table class='subtable'>";
var keys = Object.keys(infoObject.worked_bands).sort(numberSort);
for (var key in keys) {
wc1Table +=
"<tr><td align=right>" +
keys[key] +
"</td><td align=left> <font color='white'>(" +
infoObject.worked_bands[keys[key]] +
")</font></td></tr>";
}
wc1Table += "</table></td>";
wc1Table += "<td align=left><table class='subtable'>";
for (var key in keys) {
if (keys[key] in infoObject.confirmed_bands) {
wc1Table +=
"<tr><td align=right>" +
keys[key] +
"</td><td align=left> <font color='white'>(" +
infoObject.confirmed_bands[keys[key]] +
")</font></td></tr>";
} else wc1Table += "<tr><td>&nbsp;</td></tr>";
}
wc1Table += "</table></td>";
wc1Table += "</tr>";
wc1Table += "<tr>";
wc1Table += "<td align=center><font color='orange'>Modes</font></td>";
wc1Table += "<td align=left><table class='subtable'>";
keys = Object.keys(infoObject.worked_modes).sort();
for (var key in keys) {
wc1Table +=
"<tr><td align=right>" +
keys[key] +
"</td><td align=left> <font color='white'>(" +
infoObject.worked_modes[keys[key]] +
")</font></td></tr>";
}
wc1Table += "</table></td>";
wc1Table += "<td align=left><table class='subtable'>";
for (var key in keys) {
if (keys[key] in infoObject.confirmed_modes) {
wc1Table +=
"<tr><td align=right>" +
keys[key] +
"</td><td align=left> <font color='white'>(" +
infoObject.confirmed_modes[keys[key]] +
")</font></td></tr>";
} else wc1Table += "<tr><td>&nbsp;</td></tr>";
}
wc1Table += "</table></td>";
wc1Table += "</tr>";
if (infoObject.worked_type_count > 0) {
wc1Table += "<tr>";
wc1Table += "<td align=center><font color='#DD44DD'>Types</font></td>";
wc1Table += "<td align=left><table class='subtable'>";
var keys = Object.keys(infoObject.worked_types).sort();
for (var key in keys) {
wc1Table +=
"<tr><td align=right>" +
keys[key] +
"</td><td align=left> <font color='white'>(" +
infoObject.worked_types[keys[key]] +
") " +
"</font></td></tr>";
}
wc1Table += "</table></td>";
wc1Table += "<td align=left><table class='subtable'>";
for (var key in keys) {
if (keys[key] in infoObject.confirmed_types) {
wc1Table +=
"<tr><td align=right>" +
keys[key] +
"</td><td align=left> <font color='white'>(" +
infoObject.confirmed_types[keys[key]] +
") " +
"</font></td></tr>";
} else wc1Table += "<tr><td>&nbsp;</td></tr>";
}
wc1Table += "</table></td>";
wc1Table += "</tr>";
}
wc1Table += "</table>";
}
return wc1Table;
}
function validatePropMode(propMode) {
if (g_appSettings.gtPropFilter == "mixed") return true;
return g_appSettings.gtPropFilter == propMode;
}
function validateMapMode(mode) {
if (g_appSettings.gtModeFilter.length == 0) return true;
if (g_appSettings.gtModeFilter == "auto") return myMode == mode;
if (g_appSettings.gtModeFilter == "Digital") {
if (mode in g_modes && g_modes[mode]) return true;
return false;
}
if (g_appSettings.gtModeFilter == "Phone") {
if (mode in g_modes_phone && g_modes_phone[mode]) return true;
return false;
}
if (g_appSettings.gtModeFilter == "CW" && mode == "CW") return true;
return g_appSettings.gtModeFilter == mode;
}
function redrawGrids() {
if (g_appSettings.gridViewMode == 2) removePaths();
clearGrids();
clearQsoGrids();
g_QSLcount = 0;
g_QSOcount = 0;
for (var i in g_QSOhash) {
var finalGrid = g_QSOhash[i].grid;
var worked = g_QSOhash[i].worked;
var didConfirm = g_QSOhash[i].confirmed;
var band = g_QSOhash[i].band;
var mode = g_QSOhash[i].mode;
g_QSOcount++;
if (didConfirm) g_QSLcount++;
if (
(g_appSettings.gtBandFilter.length == 0 ||
(g_appSettings.gtBandFilter == "auto"
? myBand == g_QSOhash[i].band
: g_appSettings.gtBandFilter == g_QSOhash[i].band)) &&
validateMapMode(g_QSOhash[i].mode) &&
validatePropMode(g_QSOhash[i].propMode)
) {
if (g_appSettings.gridViewMode > 1) {
g_QSOhash[i].rect = qthToQsoBox(
g_QSOhash[i].grid,
i,
false,
false,
false,
g_QSOhash[i].DXcall,
g_QSOhash[i].worked,
g_QSOhash[i].confirmed,
g_QSOhash[i].band,
g_QSOhash[i].wspr
);
for (var vucc in g_QSOhash[i].vucc_grids) {
qthToQsoBox(
g_QSOhash[i].vucc_grids[vucc],
i,
false,
false,
false,
g_QSOhash[i].DXcall,
g_QSOhash[i].worked,
g_QSOhash[i].confirmed,
g_QSOhash[i].band,
g_QSOhash[i].wspr
);
}
}
var state = g_QSOhash[i].state;
var cont = g_QSOhash[i].cont;
var finalDxcc = g_QSOhash[i].dxcc;
var cnty = g_QSOhash[i].cnty;
var ituz = g_QSOhash[i].ituz;
var cqz = g_QSOhash[i].cqz;
if (state != null && isKnownCallsignUS(finalDxcc)) {
if (state.substr(0, 2) != "US") state = "US-" + state;
if (state in g_StateData) {
var name = g_StateData[state].name;
if (name in g_wasZones) {
if (g_wasZones[name].worked == false) {
g_wasZones[name].worked = worked;
}
if (worked) {
g_wasZones[name].worked_bands[band] =
~~g_wasZones[name].worked_bands[band] + 1;
g_wasZones[name].worked_modes[mode] =
~~g_wasZones[name].worked_modes[mode] + 1;
}
if (g_wasZones[name].confirmed == false) {
g_wasZones[name].confirmed = didConfirm;
}
if (didConfirm) {
g_wasZones[name].confirmed_bands[band] =
~~g_wasZones[name].confirmed_bands[band] + 1;
g_wasZones[name].confirmed_modes[mode] =
~~g_wasZones[name].confirmed_modes[mode] + 1;
}
}
}
}
if (cnty != null) {
if (cnty in g_cntyToCounty) {
if (g_countyData[cnty].worked == false) {
g_countyData[cnty].worked = worked;
}
if (worked) {
g_countyData[cnty].worked_bands[band] =
~~g_countyData[cnty].worked_bands[band] + 1;
g_countyData[cnty].worked_modes[mode] =
~~g_countyData[cnty].worked_modes[mode] + 1;
}
if (g_countyData[cnty].confirmed == false) {
g_countyData[cnty].confirmed = didConfirm;
}
if (didConfirm) {
g_countyData[cnty].confirmed_bands[band] =
~~g_countyData[cnty].confirmed_bands[band] + 1;
g_countyData[cnty].confirmed_modes[mode] =
~~g_countyData[cnty].confirmed_modes[mode] + 1;
}
}
}
if (cont != null) {
if (cont in g_shapeData) {
var name = g_shapeData[cont].properties.name;
if (name in g_wacZones) {
if (g_wacZones[name].worked == false) {
g_wacZones[name].worked = worked;
}
if (worked) {
g_wacZones[name].worked_bands[band] =
~~g_wacZones[name].worked_bands[band] + 1;
g_wacZones[name].worked_modes[mode] =
~~g_wacZones[name].worked_modes[mode] + 1;
}
if (g_wacZones[name].confirmed == false) {
g_wacZones[name].confirmed = didConfirm;
}
if (didConfirm) {
g_wacZones[name].confirmed_bands[band] =
~~g_wacZones[name].confirmed_bands[band] + 1;
g_wacZones[name].confirmed_modes[mode] =
~~g_wacZones[name].confirmed_modes[mode] + 1;
}
}
}
}
if (g_worldGeoData[g_dxccToGeoData[finalDxcc]].worked == false) {
g_worldGeoData[g_dxccToGeoData[finalDxcc]].worked = worked;
}
if (worked) {
g_worldGeoData[g_dxccToGeoData[finalDxcc]].worked_bands[band] =
~~g_worldGeoData[g_dxccToGeoData[finalDxcc]].worked_bands[band] + 1;
g_worldGeoData[g_dxccToGeoData[finalDxcc]].worked_modes[mode] =
~~g_worldGeoData[g_dxccToGeoData[finalDxcc]].worked_modes[mode] + 1;
}
if (g_worldGeoData[g_dxccToGeoData[finalDxcc]].confirmed == false) {
g_worldGeoData[g_dxccToGeoData[finalDxcc]].confirmed = didConfirm;
}
if (didConfirm) {
g_worldGeoData[g_dxccToGeoData[finalDxcc]].confirmed_bands[band] =
~~g_worldGeoData[g_dxccToGeoData[finalDxcc]].confirmed_bands[band] +
1;
g_worldGeoData[g_dxccToGeoData[finalDxcc]].confirmed_modes[mode] =
~~g_worldGeoData[g_dxccToGeoData[finalDxcc]].confirmed_modes[mode] +
1;
}
if (finalGrid.length > 0) {
var gridCheck = finalGrid.substr(0, 4);
if (gridCheck in g_us48Data) {
if (g_us48Data[gridCheck].worked == false) {
g_us48Data[gridCheck].worked = worked;
}
if (worked) {
g_us48Data[gridCheck].worked_bands[band] =
~~g_us48Data[gridCheck].worked_bands[band] + 1;
g_us48Data[gridCheck].worked_modes[mode] =
~~g_us48Data[gridCheck].worked_modes[mode] + 1;
}
if (g_us48Data[gridCheck].confirmed == false) {
g_us48Data[gridCheck].confirmed = didConfirm;
}
if (didConfirm) {
g_us48Data[gridCheck].confirmed_bands[band] =
~~g_us48Data[gridCheck].confirmed_bands[band] + 1;
g_us48Data[gridCheck].confirmed_modes[mode] =
~~g_us48Data[gridCheck].confirmed_modes[mode] + 1;
}
}
if (cqz.length > 0) {
if (g_cqZones[cqz].worked == false) {
g_cqZones[cqz].worked = worked;
}
if (worked) {
g_cqZones[cqz].worked_bands[band] =
~~g_cqZones[cqz].worked_bands[band] + 1;
g_cqZones[cqz].worked_modes[mode] =
~~g_cqZones[cqz].worked_modes[mode] + 1;
}
if (g_cqZones[cqz].confirmed == false) {
g_cqZones[cqz].confirmed = didConfirm;
}
if (didConfirm) {
g_cqZones[cqz].confirmed_bands[band] =
~~g_cqZones[cqz].confirmed_bands[band] + 1;
g_cqZones[cqz].confirmed_modes[mode] =
~~g_cqZones[cqz].confirmed_modes[mode] + 1;
}
} else if (gridCheck in g_gridToCQZone) {
if (g_gridToCQZone[gridCheck].length == 1) {
if (g_cqZones[g_gridToCQZone[gridCheck][0]].worked == false) {
g_cqZones[g_gridToCQZone[gridCheck][0]].worked = worked;
}
if (worked) {
g_cqZones[g_gridToCQZone[gridCheck][0]].worked_bands[band] =
~~g_cqZones[g_gridToCQZone[gridCheck][0]].worked_bands[band] +
1;
g_cqZones[g_gridToCQZone[gridCheck][0]].worked_modes[mode] =
~~g_cqZones[g_gridToCQZone[gridCheck][0]].worked_modes[mode] +
1;
}
if (g_cqZones[g_gridToCQZone[gridCheck][0]].confirmed == false) {
g_cqZones[g_gridToCQZone[gridCheck][0]].confirmed = didConfirm;
}
if (didConfirm) {
g_cqZones[g_gridToCQZone[gridCheck][0]].confirmed_bands[band] =
~~g_cqZones[g_gridToCQZone[gridCheck][0]].confirmed_bands[
band
] + 1;
g_cqZones[g_gridToCQZone[gridCheck][0]].confirmed_modes[mode] =
~~g_cqZones[g_gridToCQZone[gridCheck][0]].confirmed_modes[
mode
] + 1;
}
}
}
if (ituz.length > 0) {
if (g_ituZones[ituz].worked == false) {
g_ituZones[ituz].worked = worked;
}
if (worked) {
g_ituZones[ituz].worked_bands[band] =
~~g_ituZones[ituz].worked_bands[band] + 1;
g_ituZones[ituz].worked_modes[mode] =
~~g_ituZones[ituz].worked_modes[mode] + 1;
}
if (g_ituZones[ituz].confirmed == false) {
g_ituZones[ituz].confirmed = didConfirm;
}
if (didConfirm) {
g_ituZones[ituz].confirmed_bands[band] =
~~g_ituZones[ituz].confirmed_bands[band] + 1;
g_ituZones[ituz].confirmed_modes[mode] =
~~g_ituZones[ituz].confirmed_modes[mode] + 1;
}
} else if (gridCheck in g_gridToITUZone) {
if (g_gridToITUZone[gridCheck].length == 1) {
if (g_ituZones[g_gridToITUZone[gridCheck][0]].worked == false) {
g_ituZones[g_gridToITUZone[gridCheck][0]].worked = worked;
}
if (worked) {
g_ituZones[g_gridToITUZone[gridCheck][0]].worked_bands[band] =
~~g_ituZones[g_gridToITUZone[gridCheck][0]].worked_bands[band] +
1;
g_ituZones[g_gridToITUZone[gridCheck][0]].worked_modes[mode] =
~~g_ituZones[g_gridToITUZone[gridCheck][0]].worked_modes[mode] +
1;
}
if (g_ituZones[g_gridToITUZone[gridCheck][0]].confirmed == false) {
g_ituZones[g_gridToITUZone[gridCheck][0]].confirmed = didConfirm;
}
if (didConfirm) {
g_ituZones[g_gridToITUZone[gridCheck][0]].confirmed_bands[band] =
~~g_ituZones[g_gridToITUZone[gridCheck][0]].confirmed_bands[
band
] + 1;
g_ituZones[g_gridToITUZone[gridCheck][0]].confirmed_modes[mode] =
~~g_ituZones[g_gridToITUZone[gridCheck][0]].confirmed_modes[
mode
] + 1;
}
}
}
}
for (var key in g_QSOhash[i].vucc_grids) {
var grid = g_QSOhash[i].vucc_grids[key].substr(0, 4);
if (grid in g_us48Data) {
if (g_us48Data[grid].worked == false) {
g_us48Data[grid].worked = worked;
}
if (worked) {
g_us48Data[grid].worked_bands[band] =
~~g_us48Data[grid].worked_bands[band] + 1;
g_us48Data[grid].worked_modes[mode] =
~~g_us48Data[grid].worked_modes[mode] + 1;
}
if (g_us48Data[grid].confirmed == false) {
g_us48Data[grid].confirmed = didConfirm;
}
if (didConfirm) {
g_us48Data[grid].confirmed_bands[band] =
~~g_us48Data[grid].confirmed_bands[band] + 1;
g_us48Data[grid].confirmed_modes[mode] =
~~g_us48Data[grid].confirmed_modes[mode] + 1;
}
}
}
}
}
for (var layer in g_viewInfo) {
var search = window[g_viewInfo[layer][0]];
var worked = (confirmed = 0);
if (layer == 0) {
for (var key in search) {
if (search[key].rectangle.worked) worked++;
if (search[key].rectangle.confirmed) confirmed++;
}
g_viewInfo[layer][2] = worked;
g_viewInfo[layer][3] = confirmed;
} else if (layer == 5) {
for (var key in search) {
if (search[key].geo != "deleted") {
if (search[key].worked) worked++;
if (search[key].confirmed) confirmed++;
}
}
g_viewInfo[layer][2] = worked;
g_viewInfo[layer][3] = confirmed;
} else {
for (var key in search) {
if (search[key].worked) worked++;
if (search[key].confirmed) confirmed++;
}
g_viewInfo[layer][2] = worked;
g_viewInfo[layer][3] = confirmed;
}
}
for (var i in g_liveCallsigns) {
if (
g_appSettings.gridViewMode != 2 &&
(g_appSettings.gtBandFilter.length == 0 ||
(g_appSettings.gtBandFilter == "auto"
? myBand == g_liveCallsigns[i].band
: g_appSettings.gtBandFilter == g_liveCallsigns[i].band)) &&
validateMapMode(g_liveCallsigns[i].mode)
) {
if (g_appSettings.gridViewMode == 1 || g_appSettings.gridViewMode == 3) {
g_liveCallsigns[i].rect = qthToBox(
g_liveCallsigns[i].grid,
g_liveCallsigns[i].DEcall,
false,
false,
false,
g_liveCallsigns[i].DXcall,
g_liveCallsigns[i].band,
g_liveCallsigns[i].wspr,
i
);
}
}
}
reloadInfo(false);
setHomeGridsquare();
setTrophyOverlay(g_currentOverlay);
updateCountStats();
}
function toggleAlertMute() {
g_appSettings.alertMute ^= 1;
alertMuteImg.src = g_alertImageArray[g_appSettings.alertMute];
if (g_appSettings.alertMute == 1) {
chrome.tts.stop();
}
}
function togglePushPinMode() {
if (g_pushPinMode == false) g_pushPinMode = true;
else g_pushPinMode = false;
g_appSettings.pushPinMode = g_pushPinMode;
pinImg.src = g_pinImageArray[g_pushPinMode == false ? 0 : 1];
clearTempGrids();
redrawGrids();
}
function stopAsking(checkbox) {
g_appSettings.stopAskingVersion = checkbox.checked;
}
function toggleGtShareEnable() {
if (g_appSettings.gtShareEnable == true) {
g_appSettings.gtShareEnable = false;
} else g_appSettings.gtShareEnable = true;
setGtShareButtons();
}
function setGtShareButtons() {
if (
g_appSettings.gtShareEnable == true &&
g_mapSettings.offlineMode == false
) {
if (g_appSettings.gtMsgEnable == true)
msgButton.style.display = "inline-block";
else msgButton.style.display = "none";
gtFlagButton.style.display = "inline-block";
if (g_appSettings.gtFlagImgSrc > 0) {
g_layerVectors["gtflags"].setVisible(true);
} else {
g_layerVectors["gtflags"].setVisible(false);
}
} else {
msgButton.style.display = "none";
gtFlagButton.style.display = "none";
g_layerVectors["gtflags"].setVisible(false);
clearGtFlags();
// Clear list
g_gtFlagPins = {};
if (g_chatWindowHandle != null) {
try {
g_chatWindowHandle.hide();
} catch (e) {}
}
}
gtShareFlagImg.src =
g_gtShareFlagImageArray[g_appSettings.gtShareEnable == false ? 0 : 1];
}
function setMulticastIp() {
g_appSettings.wsjtIP = multicastIpInput.value;
}
function setMulticastEnable(checkbox) {
if (checkbox.checked == true) {
multicastTD.style.display = "block";
if (ValidateMulticast(multicastIpInput)) {
g_appSettings.wsjtIP = multicastIpInput.value;
} else {
g_appSettings.wsjtIP = "";
}
} else {
multicastTD.style.display = "none";
g_appSettings.wsjtIP = "";
}
g_appSettings.multicast = checkbox.checked;
}
function setUdpForwardEnable(checkbox) {
if (checkbox.checked) {
if (
ValidatePort(
udpForwardPortInput,
null,
CheckForwardPortIsNotReceivePort
) &&
ValidateIPaddress(udpForwardIpInput, null)
) {
g_appSettings.wsjtForwardUdpEnable = checkbox.checked;
return;
}
}
checkbox.checked = false;
g_appSettings.wsjtForwardUdpEnable = checkbox.checked;
}
function setGTspotEnable(checkbox) {
g_appSettings.gtSpotEnable = checkbox.checked;
g_gtLiveStatusUpdate = true;
}
function setMsgEnable(checkbox) {
g_appSettings.gtMsgEnable = checkbox.checked;
if (g_appSettings.gtShareEnable == true) {
if (g_appSettings.gtMsgEnable == true)
msgButton.style.display = "inline-block";
else {
msgButton.style.display = "none";
if (g_chatWindowHandle != null) {
g_chatWindowHandle.hide();
}
}
}
g_gtLiveStatusUpdate = true;
setMsgSettingsView();
}
function newMessageSetting(whichSetting) {
if (whichSetting.id in g_msgSettings) {
g_msgSettings[whichSetting.id] = whichSetting.value;
localStorage.msgSettings = JSON.stringify(g_msgSettings);
setMsgSettingsView();
}
}
function checkForNewVersion(showUptoDate) {
if (typeof nw != "undefined")
getBuffer(
"https://gridtracker.org/gt/version.txt?lang=" + g_localeString,
versionCheck,
showUptoDate,
"https",
443
);
}
function renderBandActivity() {
var buffer = "";
if (typeof g_bandActivity.lines[myMode] != "undefined") {
var lines = g_bandActivity.lines[myMode];
var bands = [
"630m",
"160m",
"80m",
"60m",
"40m",
"30m",
"20m",
"17m",
"15m",
"12m",
"10m",
"6m",
"4m",
"2m",
];
if (g_myDXCC in g_callsignDatabaseUSplus)
bands = [
"630m",
"160m",
"80m",
"60m",
"40m",
"30m",
"20m",
"17m",
"15m",
"12m",
"10m",
"6m",
"2m",
];
var bandData = {};
var maxValue = 0;
for (var i = 0; i < bands.length; i++) {
bandData[bands[i]] = {};
bandData[bands[i]].score = 0;
bandData[bands[i]].spots = 0;
bandData[bands[i]].tx = 0;
bandData[bands[i]].rx = 0;
}
for (var x = 0; x < lines.length; x++) {
var firstChar = lines[x].charCodeAt(0);
if (firstChar != 35 && lines[x].length > 1) {
// doesn't begins with # and has something
var values = lines[x].trim().split(" ");
var band = Number(Number(values[0]) / 1000000).formatBand();
if (band in bandData) {
var place = bandData[band];
place.score += Number(values[1]);
place.spots += Number(values[2]);
place.tx += Number(values[3]);
place.rx += Number(values[4]);
if (maxValue < place.score) maxValue = place.score;
if (maxValue < place.spots) maxValue = place.spots;
}
}
}
var scaleFactor = 1.0;
if (maxValue > 26) {
scaleFactor = 26 / maxValue;
}
for (var band in bandData) {
var blockMyBand = "";
if (band == myBand) blockMyBand = " class='myBand' ";
{
var title =
"Score: " +
bandData[band].score +
" Spots: " +
bandData[band].spots +
"\nTx: " +
bandData[band].tx +
"\tRx: " +
bandData[band].rx;
buffer +=
"<div title='" +
title +
"' style='display:inline-block;margin:1px;' class='aBand'>";
buffer +=
"<div style='height: " +
(bandData[band].score * scaleFactor + 1) +
"px;' class='barTx'></div>";
buffer +=
"<div style='height: " +
(bandData[band].spots * scaleFactor + 1) +
"px;' class='barRx'></div>";
buffer +=
"<div style='font-size:10px' " +
blockMyBand +
">" +
parseInt(band) +
"</div>";
buffer += "</div>";
}
}
} else {
buffer = "..no data yet..";
}
graphDiv.innerHTML = buffer;
if (g_baWindowHandle) {
g_baWindowHandle.window.graphDiv.innerHTML = buffer;
}
}
function pskBandActivityCallback(buffer, flag) {
var result = String(buffer);
if (result.indexOf("frequency score") > -1) {
// looks good so far
g_bandActivity.lines[myMode] = result.split("\n");
g_bandActivity.lastUpdate[myMode] = g_timeNow + 600;
localStorage.bandActivity = JSON.stringify(g_bandActivity);
}
renderBandActivity();
}
function pskGetBandActivity() {
if (g_mapSettings.offlineMode == true) return;
if (typeof g_bandActivity.lastUpdate[myMode] == "undefined") {
g_bandActivity.lastUpdate[myMode] = 0;
}
if (
myMode.length > 0 &&
myDEGrid.length > 0 &&
g_timeNow > g_bandActivity.lastUpdate[myMode]
) {
getBuffer(
"https://pskreporter.info/cgi-bin/psk-freq.pl?mode=" +
myMode +
"&grid=" +
myDEGrid.substr(0, 4),
pskBandActivityCallback,
null,
"https",
443
);
}
renderBandActivity();
if (g_pskBandActivityTimerHandle != null) {
clearInterval(g_pskBandActivityTimerHandle);
}
g_pskBandActivityTimerHandle = setInterval(function () {
pskGetBandActivity();
}, 601000); // every 20 minutes, 1 second
}
function getIniFromApp(appName) {
var result = Array();
result.port = -1;
result.ip = "";
result.MyCall = "NOCALL";
result.MyGrid = "";
result.MyBand = "";
result.MyMode = "";
result.IniPath = "";
result.N1MMServer = "";
result.N1MMServerPort = 0;
result.BroadcastToN1MM = false;
result.appName = appName;
var wsjtxCfgPath = "";
var data = String(nw.App.dataPath);
var end = 0;
if (g_platform == "windows") {
end = data.indexOf("GridTracker\\User Data\\Default");
if (end > -1) {
wsjtxCfgPath = data.substr(0, end) + appName + "\\" + appName + ".ini";
}
}
if (g_platform == "mac") {
process = require("process");
wsjtxCfgPath = process.env.HOME + "/Library/Preferences/WSJT-X.ini";
}
if (g_platform == "linux") {
process = require("process");
wsjtxCfgPath = process.env.HOME + "/.config/" + appName + ".ini";
}
if (fs.existsSync(wsjtxCfgPath)) {
var fileBuf = fs.readFileSync(wsjtxCfgPath, "ascii");
var fileArray = fileBuf.split("\n");
for (var key in fileArray) fileArray[key] = fileArray[key].trim();
result.IniPath = data.substr(0, end) + appName + "\\";
for (var x = 0; x < fileArray.length; x++) {
var indexOfPort = fileArray[x].indexOf("UDPServerPort=");
if (indexOfPort == 0) {
var portSplit = fileArray[x].split("=");
result.port = portSplit[1];
}
indexOfPort = fileArray[x].indexOf("UDPServer=");
if (indexOfPort == 0) {
var portSplit = fileArray[x].split("=");
result.ip = portSplit[1];
}
indexOfPort = fileArray[x].indexOf("MyCall=");
if (indexOfPort == 0) {
var portSplit = fileArray[x].split("=");
result.MyCall = portSplit[1];
}
indexOfPort = fileArray[x].indexOf("MyGrid=");
if (indexOfPort == 0) {
var portSplit = fileArray[x].split("=");
result.MyGrid = portSplit[1].substr(0, 6);
}
indexOfPort = fileArray[x].indexOf("Mode=");
if (indexOfPort == 0) {
var portSplit = fileArray[x].split("=");
result.MyMode = portSplit[1];
}
indexOfPort = fileArray[x].indexOf("DialFreq=");
if (indexOfPort == 0) {
var portSplit = fileArray[x].split("=");
result.MyBand = Number(portSplit[1] / 1000000).formatBand();
}
indexOfPort = fileArray[x].indexOf("N1MMServerPort=");
if (indexOfPort == 0) {
var portSplit = fileArray[x].split("=");
result.N1MMServerPort = portSplit[1];
}
indexOfPort = fileArray[x].indexOf("N1MMServer=");
if (indexOfPort == 0) {
var portSplit = fileArray[x].split("=");
result.N1MMServer = portSplit[1];
}
indexOfPort = fileArray[x].indexOf("BroadcastToN1MM=");
if (indexOfPort == 0) {
var portSplit = fileArray[x].split("=");
result.BroadcastToN1MM = portSplit[1] == "true";
}
}
}
return result;
}
function checkRunningProcesses() {
var list = "";
if (g_platform == "windows") {
var child_process = require("child_process");
list = child_process.execFileSync("tasklist.exe");
if (list.indexOf("wsjtx") > -1) g_wsjtxProcessRunning = true;
else g_wsjtxProcessRunning = false;
if (list.indexOf("jtdx") > -1) g_jtdxProcessRunning = true;
else g_jtdxProcessRunning = false;
}
if (g_platform == "mac") {
var child_process = require("child_process");
list = child_process.execFileSync("ps", ["-aef"]);
if (list.indexOf("jt9 -s WSJT-X") > -1) g_wsjtxProcessRunning = true;
else g_wsjtxProcessRunning = false;
// no jtdx on Mac, woot!
g_jtdxProcessRunning = false;
}
if (g_platform == "linux") {
var child_process = require("child_process");
list = child_process.execFileSync("ps", ["-aef"]);
if (list.indexOf("wsjtx") > -1) g_wsjtxProcessRunning = true;
else g_wsjtxProcessRunning = false;
if (list.indexOf("jtdx") > -1) g_jtdxProcessRunning = true;
else g_jtdxProcessRunning = false;
}
}
function updateRunningProcesses() {
try {
checkRunningProcesses();
} catch (e) {
g_wsjtxProcessRunning = false;
g_jtdxProcessRunning = false;
}
runningAppsDiv.innerHTML = "WSJT-X ";
if (g_wsjtxProcessRunning == true) runningAppsDiv.innerHTML += " - up - ";
else runningAppsDiv.innerHTML += " - ? - ";
g_wsjtxIni = getIniFromApp("WSJT-X");
if (g_wsjtxIni.port > -1) {
runningAppsDiv.innerHTML +=
"<b>(" + g_wsjtxIni.ip + " / " + g_wsjtxIni.port + ")</b> ";
} else runningAppsDiv.innerHTML += "<b>(?)</b> ";
if (g_platform != "mac") {
runningAppsDiv.innerHTML += " / JTDX ";
if (g_jtdxProcessRunning == true) runningAppsDiv.innerHTML += " - up - ";
else runningAppsDiv.innerHTML += " - ? - ";
g_jtdxIni = getIniFromApp("JTDX");
if (g_jtdxIni.port > -1) {
runningAppsDiv.innerHTML +=
"<b>(" + g_jtdxIni.ip + " / " + g_jtdxIni.port + ")</b> ";
} else runningAppsDiv.innerHTML += "<b>(?)</b> ";
}
}
function updateBasedOnIni() {
var which = null;
var count = 0;
if (g_wsjtxProcessRunning) count++;
if (g_jtdxProcessRunning) count++;
// UdpPortNotSet
if (g_appSettings.wsjtUdpPort == 0 && count == 1) {
if (g_wsjtxProcessRunning) which = g_wsjtxIni;
else if (g_jtdxProcessRunning) which = g_jtdxIni;
if (which != null && which.port > -1) {
g_appSettings.wsjtUdpPort = which.port;
g_appSettings.wsjtIP = which.ip;
}
if (which == null) {
g_appSettings.wsjtUdpPort = 2237;
g_appSettings.wsjtIP = "";
}
if (
ipToInt(g_appSettings.wsjtIP) >= ipToInt("224.0.0.0") &&
ipToInt(g_appSettings.wsjtIP) < ipToInt("240.0.0.0")
) {
g_appSettings.multicast = true;
} else g_appSettings.multicast = false;
}
// Which INI do we load?
if (g_appSettings.wsjtUdpPort) {
which = null;
if (g_wsjtxIni.port == g_appSettings.wsjtUdpPort) which = g_wsjtxIni;
else if (g_jtdxIni.port == g_appSettings.wsjtUdpPort) which = g_jtdxIni;
if (which != null) {
myDEcall = which.MyCall;
myDEGrid = which.MyGrid;
g_lastBand = myBand;
g_lastMode = myMode;
g_workingIniPath = which.IniPath;
}
if (
which != null &&
which.BroadcastToN1MM == true &&
g_N1MMSettings.enable == true
) {
if (
which.N1MMServer == g_N1MMSettings.ip &&
which.N1MMServerPort == g_N1MMSettings.port
) {
buttonN1MMCheckBox.checked = g_N1MMSettings.enable = false;
localStorage.N1MMSettings = JSON.stringify(g_N1MMSettings);
alert(
which.appName +
" N1MM Logger+ is enabled with same settings, disabled GridTracker N1MM logger"
);
}
}
if (which != null) {
if (g_appSettings.wsjtIP == "") {
g_appSettings.wsjtIP = which.ip;
}
}
}
if (myDEGrid.length > 0) setHomeGridsquare();
else {
if (typeof nw != "undefined") {
// lets see if we can find our location the hard way
getBuffer(
"https://api.ipstack.com/check?access_key=8c9233ec1c09861a707951ab3718a7f6&format=1",
ipLocation,
null,
"https",
443
);
}
}
}
function CheckReceivePortIsNotForwardPort(value) {
if (
udpForwardIpInput.value == "127.0.0.1" &&
udpForwardPortInput.value == value &&
g_appSettings.wsjtIP == "" &&
udpForwardEnable.checked
) {
return false;
}
return true;
}
function CheckForwardPortIsNotReceivePort(value) {
if (
udpForwardIpInput.value == "127.0.0.1" &&
udpPortInput.value == value &&
g_appSettings.wsjtIP == ""
)
return false;
return true;
}
function setForwardIp() {
g_appSettings.wsjtForwardUdpIp = udpForwardIpInput.value;
if (ValidatePort(udpPortInput, null, CheckReceivePortIsNotForwardPort)) {
setUdpPort();
}
ValidatePort(udpForwardPortInput, null, CheckForwardPortIsNotReceivePort);
}
function setForwardPort() {
g_appSettings.wsjtForwardUdpPort = udpForwardPortInput.value;
ValidateIPaddress(udpForwardIpInput, null);
if (ValidatePort(udpPortInput, null, CheckReceivePortIsNotForwardPort)) {
setUdpPort();
}
}
function validIpKeys(value) {
if (value == 46) return true;
return value >= 48 && value <= 57;
}
function validNumberKeys(value) {
return value >= 48 && value <= 57;
}
function validateNumAndLetter(input) {
if (/\d/.test(input) && /[A-Z]/.test(input)) return true;
else return false;
}
function validCallsignsKeys(value) {
if (value == 44) return true;
if (value >= 47 && value <= 57) return true;
if (value >= 65 && value <= 90) return true;
return value >= 97 && value <= 122;
}
function ValidateCallsigns(inputText, validDiv) {
inputText.value = inputText.value.toUpperCase();
var callsigns = inputText.value.split(",");
var passed = false;
for (var call in callsigns) {
if (callsigns[call].length > 0) {
if (/\d/.test(callsigns[call]) && /[A-Z]/.test(callsigns[call])) {
passed = true;
} else {
passed = false;
break;
}
} else {
passed = false;
break;
}
}
if (passed) {
inputText.style.color = "#FF0";
inputText.style.backgroundColor = "green";
} else {
inputText.style.color = "#000";
inputText.style.backgroundColor = "yellow";
}
return passed;
}
function ValidateCallsign(inputText, validDiv) {
addError.innerHTML = "";
if (inputText.value.length > 0) {
var passed = false;
inputText.value = inputText.value.toUpperCase();
if (/\d/.test(inputText.value) || /[A-Z]/.test(inputText.value)) {
passed = true;
}
if (passed) {
inputText.style.color = "#FF0";
inputText.style.backgroundColor = "green";
if (validDiv) validDiv.innerHTML = "Valid!";
return true;
} else {
inputText.style.color = "#000";
inputText.style.backgroundColor = "yellow";
if (validDiv) validDiv.innerHTML = "Invalid!";
return false;
}
} else {
inputText.style.color = "#000";
inputText.style.backgroundColor = "yellow";
if (validDiv) validDiv.innerHTML = "Invalid!";
return false;
}
}
function ValidateGridsquareOnly4(inputText, validDiv) {
addError.innerHTML = "";
if (inputText.value.length == 4) {
var gridSquare = "";
var LETTERS = inputText.value.substr(0, 2).toUpperCase();
var NUMBERS = inputText.value.substr(2, 2).toUpperCase();
if (/^[A-R]+$/.test(LETTERS) && /^[0-9]+$/.test(NUMBERS)) {
gridSquare = LETTERS + NUMBERS;
}
if (gridSquare != "") {
inputText.style.color = "#FF0";
inputText.style.backgroundColor = "green";
inputText.value = gridSquare;
if (validDiv) validDiv.innerHTML = "Valid!";
return true;
} else {
inputText.style.color = "#FFF";
inputText.style.backgroundColor = "red";
if (validDiv) validDiv.innerHTML = "Invalid!";
return false;
}
} else {
inputText.style.color = "#000";
inputText.style.backgroundColor = "yellow";
if (validDiv) validDiv.innerHTML = "Valid!";
return true;
}
}
function validateGridFromString(inputText) {
if (inputText.length == 4 || inputText.length == 6) {
var gridSquare = "";
var LETTERS = inputText.substr(0, 2).toUpperCase();
var NUMBERS = inputText.substr(2, 2).toUpperCase();
if (/^[A-R]+$/.test(LETTERS) && /^[0-9]+$/.test(NUMBERS)) {
gridSquare = LETTERS + NUMBERS;
}
if (inputText.length > 4) {
var LETTERS_SUB = inputText.substr(4, 2).toUpperCase();
gridSquare = "";
if (
/^[A-R]+$/.test(LETTERS) &&
/^[0-9]+$/.test(NUMBERS) &&
/^[A-Xa-x]+$/.test(LETTERS_SUB)
) {
gridSquare = LETTERS + NUMBERS + LETTERS_SUB;
}
}
if (gridSquare != "") {
return true;
} else {
return false;
}
} else {
return false;
}
}
function ValidateGridsquare(inputText, validDiv) {
if (inputText.value.length == 4 || inputText.value.length == 6) {
var gridSquare = "";
var LETTERS = inputText.value.substr(0, 2).toUpperCase();
var NUMBERS = inputText.value.substr(2, 2).toUpperCase();
if (/^[A-R]+$/.test(LETTERS) && /^[0-9]+$/.test(NUMBERS)) {
gridSquare = LETTERS + NUMBERS;
}
if (inputText.value.length > 4) {
var LETTERS_SUB = inputText.value.substr(4, 2);
gridSquare = "";
if (
/^[A-R]+$/.test(LETTERS) &&
/^[0-9]+$/.test(NUMBERS) &&
/^[A-Xa-x]+$/.test(LETTERS_SUB)
) {
gridSquare = LETTERS + NUMBERS + LETTERS_SUB;
}
}
if (gridSquare != "") {
inputText.style.color = "#FF0";
inputText.style.backgroundColor = "green";
inputText.value = gridSquare;
if (validDiv) validDiv.innerHTML = "Valid!";
return true;
} else {
inputText.style.color = "#FFF";
inputText.style.backgroundColor = "red";
if (validDiv) validDiv.innerHTML = "Invalid!";
return false;
}
} else {
inputText.style.color = "#FFF";
inputText.style.backgroundColor = "red";
if (validDiv) validDiv.innerHTML = "Invalid!";
return false;
}
}
function ipToInt(ip) {
return ip
.split(".")
.map((octet, index, array) => {
return parseInt(octet) * Math.pow(256, array.length - index - 1);
})
.reduce((prev, curr) => {
return prev + curr;
});
}
function ValidateMulticast(inputText) {
var ipformat = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
if (inputText.value.match(ipformat)) {
if (inputText.value != "0.0.0.0" && inputText.value != "255.255.255.255") {
var ipInt = ipToInt(inputText.value);
if (ipInt >= ipToInt("224.0.0.0") && ipInt < ipToInt("240.0.0.0")) {
if (ipInt > ipToInt("224.0.0.255")) {
inputText.style.color = "black";
inputText.style.backgroundColor = "yellow";
} else {
inputText.style.color = "#FF0";
inputText.style.backgroundColor = "green";
}
return true;
} else {
inputText.style.color = "#FFF";
inputText.style.backgroundColor = "red";
return false;
}
} else {
inputText.style.color = "#FFF";
inputText.style.backgroundColor = "red";
return false;
}
} else {
inputText.style.color = "#FFF";
inputText.style.backgroundColor = "red";
return false;
}
}
function ValidateIPaddress(inputText, checkBox) {
var ipformat = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
if (inputText.value.match(ipformat)) {
if (inputText.value != "0.0.0.0" && inputText.value != "255.255.255.255") {
inputText.style.color = "#FF0";
inputText.style.backgroundColor = "green";
return true;
} else {
inputText.style.color = "#FFF";
inputText.style.backgroundColor = "red";
if (checkBox) checkBox.checked = false;
return false;
}
} else {
inputText.style.color = "#FFF";
inputText.style.backgroundColor = "red";
if (checkBox) checkBox.checked = false;
return false;
}
}
function ValidatePort(inputText, checkBox, callBackCheck) {
var value = Number(inputText.value);
if (value > 1023 && value < 65536) {
if (callBackCheck && !callBackCheck(value)) {
inputText.style.color = "#FFF";
inputText.style.backgroundColor = "red";
if (checkBox) checkBox.checked = false;
return false;
} else {
inputText.style.color = "#FF0";
inputText.style.backgroundColor = "green";
return true;
}
} else {
inputText.style.color = "#FFF";
inputText.style.backgroundColor = "red";
if (checkBox) checkBox.checked = false;
return false;
}
}
function workingCallsignEnableChanged(ele) {
g_appSettings.workingCallsignEnable = ele.checked;
applyCallsignsAndDateDiv.style.display = "";
}
function workingDateEnableChanged(ele) {
g_appSettings.workingDateEnable = ele.checked;
applyCallsignsAndDateDiv.style.display = "";
}
function workingDateChanged() {
var fields = workingDateValue.value.split("-");
var date = new Date(
Date.UTC(
parseInt(fields[0]),
parseInt(fields[1]) - 1,
parseInt(fields[2]),
0,
0,
0
)
);
g_appSettings.workingDate =
Date.UTC(
parseInt(fields[0]),
parseInt(fields[1]) - 1,
parseInt(fields[2]),
0,
0,
0
) / 1000;
displayWorkingDate();
applyCallsignsAndDateDiv.style.display = "";
}
function displayWorkingDate() {
var date = new Date(g_appSettings.workingDate * 1000);
workingDateString.innerHTML = dateToString(date);
}
var g_tempWorkingCallsigns = {};
function workingCallsignsChanged(ele) {
g_tempWorkingCallsigns = {};
var callsigns = ele.value.split(",");
for (var call in callsigns) {
g_tempWorkingCallsigns[callsigns[call]] = true;
}
if (callsigns.length > 0) {
g_appSettings.workingCallsigns = Object.assign({}, g_tempWorkingCallsigns);
if (g_appSettings.workingCallsignEnable)
applyCallsignsAndDateDiv.style.display = "";
} else applyCallsignsAndDateDiv.style.display = "none";
}
function applyCallsignsAndDates() {
clearAndLoadQSOs();
applyCallsignsAndDateDiv.style.display = "none";
}
function selectElementContents(el) {
var body = document.body,
range,
sel;
if (document.createRange && window.getSelection) {
range = document.createRange();
sel = window.getSelection();
sel.removeAllRanges();
range.selectNodeContents(el);
sel.addRange(range);
var text = sel.toString();
text = text.replace(/\t/g, ",");
sel.removeAllRanges();
selectNodeDiv.innerText = text;
range.selectNodeContents(selectNodeDiv);
sel.addRange(range);
document.execCommand("copy");
sel.removeAllRanges();
selectNodeDiv.innerText = "";
}
}
function ipLocation(buffer, flag) {
var obj = JSON.parse(buffer);
if (
typeof obj != "undefined" &&
obj != null &&
typeof obj.latitude != "undefined"
) {
g_appSettings.centerGridsquare = latLonToGridSquare(
obj.latitude,
obj.longitude
).substr(0, 6);
if (g_appSettings.centerGridsquare.length > 0) {
homeQTHInput.value = g_appSettings.centerGridsquare;
if (ValidateGridsquare(homeQTHInput, null)) setCenterGridsquare();
}
}
}
function popupNewWindows() {
if (typeof nw != "undefined") {
win.on("new-win-policy", function (frame, url, policy) {
policy.forceNewPopup();
g_lastUrl = "";
});
}
}
var g_lastUrl = "";
function lockNewWindows() {
if (typeof nw != "undefined") {
win.on("new-win-policy", function (frame, url, policy) {
if (url != g_lastUrl) {
nw.Shell.openExternal(url);
g_lastUrl = url;
}
policy.ignore();
});
}
}
function byName(a, b) {
if (g_enums[a] < g_enums[b]) return -1;
if (g_enums[a] > g_enums[b]) return 1;
return 0;
}
var ancPrefixes = ["P", "M", "MM", "AM", "A", "NWS"];
function callsignToDxcc(insign) {
var callsign = insign;
if (!/\d/.test(callsign) || !/[a-zA-Z]/.test(callsign)) {
return -1;
}
if (callsign in g_directCallToDXCC)
return Number(g_directCallToDXCC[callsign]);
if (callsign.includes("/")) {
var parts = callsign.split("/");
var end = parts.length - 1;
if (ancPrefixes.includes(parts[end])) {
parts.pop();
end = parts.length - 1;
}
if (end) {
if (isNaN(parts[end])) {
if (parts[1].length > parts[0].length) {
callsign = parts[0];
} else {
if (callsignToDxcc(parts[1]) != -1) callsign = parts[1];
else callsign = parts[0];
}
} else callsign = parts[0];
} else callsign = parts[0];
if (callsign in g_directCallToDXCC)
return Number(g_directCallToDXCC[callsign]);
}
for (var x = callsign.length; x > 0; x--) {
if (callsign.substr(0, x) in g_prefixToMap) {
return Number(g_worldGeoData[g_prefixToMap[callsign.substr(0, x)]].dxcc);
}
}
return -1;
}
function loadMaidenHeadData() {
var file = "./data/mh-root-prefixed.json";
if (fs.existsSync(file)) {
var fileBuf = fs.readFileSync(file, "UTF-8");
g_worldGeoData = JSON.parse(fileBuf);
for (var key in g_worldGeoData) {
g_worldGeoData[key].geo = "deleted";
g_worldGeoData[key].worked_bands = {};
g_worldGeoData[key].confirmed_bands = {};
g_worldGeoData[key].worked_modes = {};
g_worldGeoData[key].confirmed_modes = {};
g_dxccToAltName[g_worldGeoData[key].dxcc] = g_worldGeoData[key].name;
g_dxccToADIFName[g_worldGeoData[key].dxcc] = g_worldGeoData[key].aname;
g_dxccToGeoData[g_worldGeoData[key].dxcc] = key;
for (var x = 0; x < g_worldGeoData[key].prefix.length; x++) {
if (g_worldGeoData[key].prefix[x].charAt(0) == "=")
g_directCallToDXCC[g_worldGeoData[key].prefix[x].substr(1)] =
g_worldGeoData[key].dxcc;
else g_prefixToMap[g_worldGeoData[key].prefix[x]] = key;
}
delete g_worldGeoData[key].prefix;
for (var x = 0; x < g_worldGeoData[key].mh.length; x++) {
if (!(g_worldGeoData[key].mh[x] in g_gridToDXCC))
g_gridToDXCC[g_worldGeoData[key].mh[x]] = Array();
g_gridToDXCC[g_worldGeoData[key].mh[x]].push(g_worldGeoData[key].dxcc);
}
if (
g_worldGeoData[key].dxcc != 291 &&
g_worldGeoData[key].dxcc != 110 &&
g_worldGeoData[key].dxcc != 6
)
delete g_worldGeoData[key].mh;
}
file = "./data/dxcc.json";
var files = fs.readFileSync(file);
var dxccGeo = JSON.parse(files);
for (var key in dxccGeo.features) {
var dxcc = dxccGeo.features[key].properties.dxcc_entity_code;
g_worldGeoData[g_dxccToGeoData[dxcc]].geo = dxccGeo.features[key];
}
delete dxccGeo;
file = "./data/counties.json";
files = fs.readFileSync(file);
var countyData = JSON.parse(files);
for (var id in countyData) {
if (!(countyData[id].properties.st in g_stateToCounty))
g_stateToCounty[countyData[id].properties.st] = Array();
g_stateToCounty[countyData[id].properties.st].push(id);
var cnty =
countyData[id].properties.st +
"," +
countyData[id].properties.n.toUpperCase().replaceAll(" ", "");
if (!(cnty in g_cntyToCounty))
g_cntyToCounty[cnty] = countyData[id].properties.n.toProperCase();
g_countyData[cnty] = {};
g_countyData[cnty].geo = countyData[id];
g_countyData[cnty].worked = false;
g_countyData[cnty].confirmed = false;
g_countyData[cnty].worked_bands = {};
g_countyData[cnty].confirmed_bands = {};
g_countyData[cnty].worked_modes = {};
g_countyData[cnty].confirmed_modes = {};
for (var x in countyData[id].properties.z) {
var zipS = String(countyData[id].properties.z[x]);
if (!(zipS in g_zipToCounty)) {
g_zipToCounty[zipS] = Array();
}
g_zipToCounty[zipS].push(cnty);
}
}
files = null;
countyData = null;
g_shapeData = JSON.parse(fs.readFileSync(g_shapeFile));
for (var key in g_shapeData) {
if (g_shapeData[key].properties.alias == key)
g_shapeData[key].properties.alias = null;
else if (
g_shapeData[key].properties.alias &&
g_shapeData[key].properties.alias.length > 2 &&
(g_shapeData[key].properties.alias.indexOf("US") == 0 ||
g_shapeData[key].properties.alias.indexOf("CA") == 0)
)
g_shapeData[key].properties.alias = null;
if (
g_shapeData[key].properties.alias &&
g_shapeData[key].properties.alias.length < 2
)
g_shapeData[key].properties.alias = null;
if (g_shapeData[key].properties.alias != null) {
if (key.indexOf("CN-") == 0) {
if (g_shapeData[key].properties.alias == key.replace("CN-", ""))
g_shapeData[key].properties.alias = null;
}
}
if (
g_shapeData[key].properties.alias != null &&
g_shapeData[key].properties.alias.length != 2
)
g_shapeData[key].properties.alias = null;
}
//finalDxcc == 291 || finalDxcc == 110 || finalDxcc == 6
// Create "US" shape from US Dxcc geos
var x = g_worldGeoData[g_dxccToGeoData[291]].geo.geometry;
var y = g_shapeData["AK"].geometry;
var z = g_shapeData["HI"].geometry;
var feature = {
type: "Feature",
geometry: {
type: "GeometryCollection",
geometries: [x, y, z],
},
properties: {
name: "United States",
center: g_worldGeoData[g_dxccToGeoData[291]].geo.properties.center,
postal: "US",
type: "Country",
},
};
g_shapeData["US"] = feature;
y = g_shapeData["OC"].geometry;
z = g_shapeData["AU"].geometry;
q = g_shapeData["AN"].geometry;
feature = {
type: "Feature",
geometry: {
type: "GeometryCollection",
geometries: [y, z, q],
},
properties: {
name: "Oceania",
center: [167.97602, -29.037824],
postal: "OC",
type: "Continent",
},
};
g_shapeData["OC"] = feature;
g_shapeData["AU"].properties.type = "Country";
g_StateData = JSON.parse(fs.readFileSync("./data/state.json"));
g_StateData["US-AK"] = {};
g_StateData["US-AK"].postal = "US-AK";
g_StateData["US-AK"].name = "Alaska";
g_StateData["US-AK"].mh = g_worldGeoData[5].mh;
g_StateData["US-AK"].dxcc = 6;
g_StateData["US-HI"] = {};
g_StateData["US-HI"].postal = "US-HI";
g_StateData["US-HI"].name = "Hawaii";
g_StateData["US-HI"].mh = g_worldGeoData[100].mh;
g_StateData["US-HI"].dxcc = 110;
for (var key in g_StateData) {
for (var x = 0; x < g_StateData[key].mh.length; x++) {
if (!(g_StateData[key].mh[x] in g_gridToState))
g_gridToState[g_StateData[key].mh[x]] = Array();
g_gridToState[g_StateData[key].mh[x]].push(g_StateData[key].postal);
}
g_StateData[key].worked_bands = {};
g_StateData[key].confirmed_bands = {};
g_StateData[key].worked_modes = {};
g_StateData[key].confirmed_modes = {};
}
file = "./data/phone.json";
fileBuf = fs.readFileSync(file, "UTF-8");
g_phonetics = JSON.parse(fileBuf);
file = "./data/enums.json";
fileBuf = fs.readFileSync(file, "UTF-8");
g_enums = JSON.parse(fileBuf);
for (var key in g_worldGeoData) {
if (
g_worldGeoData[key].pp != "" &&
g_worldGeoData[key].geo != "deleted"
) {
g_enums[g_worldGeoData[key].dxcc] = g_worldGeoData[key].name;
}
if (key == 270) {
// US Mainland
for (var mh in g_worldGeoData[key].mh) {
var sqr = g_worldGeoData[key].mh[mh];
g_us48Data[sqr] = {};
g_us48Data[sqr].name = sqr;
g_us48Data[sqr].worked = false;
g_us48Data[sqr].confirmed = false;
g_us48Data[sqr].worked_bands = {};
g_us48Data[sqr].confirmed_bands = {};
g_us48Data[sqr].worked_modes = {};
g_us48Data[sqr].confirmed_modes = {};
}
}
}
fileBuf = fs.readFileSync("./data/cqzone.json");
g_cqZones = JSON.parse(fileBuf);
for (var key in g_cqZones) {
for (var x = 0; x < g_cqZones[key].mh.length; x++) {
if (!(g_cqZones[key].mh[x] in g_gridToCQZone))
g_gridToCQZone[g_cqZones[key].mh[x]] = Array();
g_gridToCQZone[g_cqZones[key].mh[x]].push(String(key));
}
delete g_cqZones[key].mh;
}
fileBuf = fs.readFileSync("./data/ituzone.json");
g_ituZones = JSON.parse(fileBuf);
for (var key in g_ituZones) {
for (var x = 0; x < g_ituZones[key].mh.length; x++) {
if (!(g_ituZones[key].mh[x] in g_gridToITUZone))
g_gridToITUZone[g_ituZones[key].mh[x]] = Array();
g_gridToITUZone[g_ituZones[key].mh[x]].push(String(key));
}
delete g_ituZones[key].mh;
}
for (var key in g_StateData) {
if (key.substr(0, 3) == "US-") {
var shapeKey = key.substr(3, 2);
var name = g_StateData[key].name;
if (shapeKey in g_shapeData) {
g_wasZones[name] = {};
g_wasZones[name].geo = g_shapeData[shapeKey];
g_wasZones[name].worked = false;
g_wasZones[name].confirmed = false;
g_wasZones[name].worked_bands = {};
g_wasZones[name].confirmed_bands = {};
g_wasZones[name].worked_modes = {};
g_wasZones[name].confirmed_modes = {};
}
}
}
var name = "Alaska";
var shapeKey = "AK";
g_wasZones[name] = {};
g_wasZones[name].geo = g_shapeData[shapeKey];
g_wasZones[name].worked = false;
g_wasZones[name].confirmed = false;
g_wasZones[name].worked_bands = {};
g_wasZones[name].confirmed_bands = {};
g_wasZones[name].worked_modes = {};
g_wasZones[name].confirmed_modes = {};
name = "Hawaii";
shapeKey = "HI";
g_wasZones[name] = {};
g_wasZones[name].geo = g_shapeData[shapeKey];
g_wasZones[name].worked = false;
g_wasZones[name].confirmed = false;
g_wasZones[name].worked_bands = {};
g_wasZones[name].confirmed_bands = {};
g_wasZones[name].worked_modes = {};
g_wasZones[name].confirmed_modes = {};
for (var key in g_shapeData) {
if (g_shapeData[key].properties.type == "Continent") {
var name = g_shapeData[key].properties.name;
g_wacZones[name] = {};
g_wacZones[name].geo = g_shapeData[key];
g_wacZones[name].worked = false;
g_wacZones[name].confirmed = false;
g_wacZones[name].worked_bands = {};
g_wacZones[name].confirmed_bands = {};
g_wacZones[name].worked_modes = {};
g_wacZones[name].confirmed_modes = {};
}
}
delete fileBuf;
}
}
var g_timezonesEnable = 0;
var g_timezoneLayer = null;
function createZoneLayer() {
g_timezoneLayer = createGeoJsonLayer(
"tz",
"./data/combined-with-oceans.json",
"#000088FF",
0.5
);
g_map.addLayer(g_timezoneLayer);
g_timezoneLayer.setVisible(false);
}
function toggleTimezones() {
if (g_currentOverlay != 0) return;
g_timezonesEnable ^= 1;
mouseOutGtFlag();
if (g_timezonesEnable == 1) {
if (g_timezoneLayer == null) {
createZoneLayer();
}
g_timezoneLayer.setVisible(true);
} else {
if (g_timezoneLayer != null) {
g_map.removeLayer(g_timezoneLayer);
delete g_timezoneLayer;
g_timezoneLayer = null;
}
}
}
function drawAllGrids() {
var borderColor = "#000";
var borderWeight = 0.5;
for (var x = -178; x < 181; x += 2) {
var fromPoint = ol.proj.fromLonLat([x, -90]);
var toPoint = ol.proj.fromLonLat([x, 90]);
var points = [fromPoint, toPoint];
if (x % 20 == 0) borderWeight = 0.75;
else borderWeight = 0.25;
var newGridBox = lineString(points);
var featureStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: borderColor,
width: borderWeight,
}),
});
newGridBox.setStyle(featureStyle);
g_layerSources["line-grids"].addFeature(newGridBox);
}
for (var x = -90; x < 91; x++) {
var fromPoint = ol.proj.fromLonLat([-180, x]);
var toPoint = ol.proj.fromLonLat([180, x]);
var points = [fromPoint, toPoint];
if (x % 10 == 0) borderWeight = 0.75;
else borderWeight = 0.25;
var newGridBox = lineString(points);
var featureStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: borderColor,
width: borderWeight,
}),
});
newGridBox.setStyle(featureStyle);
g_layerSources["line-grids"].addFeature(newGridBox);
}
for (var x = 65; x < 83; x++)
for (var y = 65; y < 83; y++) {
for (var a = 0; a < 10; a++)
for (var b = 0; b < 10; b++) {
var LL = squareToLatLong(
String.fromCharCode(x) +
String.fromCharCode(y) +
String(a) +
String(b)
);
var Lat = LL.la2 - (LL.la2 - LL.la1) / 2;
var Lon = LL.lo2 - (LL.lo2 - LL.lo1) / 2;
var point = ol.proj.fromLonLat([Lon, Lat]);
var feature = new ol.Feature({
geometry: new ol.geom.Point(point),
name: String(a) + String(b),
});
var featureStyle = new ol.style.Style({
text: new ol.style.Text({
fill: new ol.style.Fill({ color: "#000" }),
font: "normal 16px sans-serif",
stroke: new ol.style.Stroke({
color: "#88888888",
width: 1,
}),
text: String(a) + String(b),
offsetY: 1,
}),
});
feature.setStyle(featureStyle);
g_layerSources["short-grids"].addFeature(feature);
feature = new ol.Feature({
geometry: new ol.geom.Point(point),
name: String(a) + String(b),
});
featureStyle = new ol.style.Style({
text: new ol.style.Text({
fill: new ol.style.Fill({ color: "#000" }),
font: "normal 16px sans-serif",
stroke: new ol.style.Stroke({
color: "#88888888",
width: 1,
}),
text:
String.fromCharCode(x) +
String.fromCharCode(y) +
String(a) +
String(b),
offsetY: 1,
}),
});
feature.setStyle(featureStyle);
g_layerSources["long-grids"].addFeature(feature);
}
var LL = twoWideToLatLong(
String.fromCharCode(x) + String.fromCharCode(y)
);
var Lat = LL.la2 - (LL.la2 - LL.la1) / 2;
var Lon = LL.lo2 - (LL.lo2 - LL.lo1) / 2;
var point = ol.proj.fromLonLat([Lon, Lat]);
feature = new ol.Feature(new ol.geom.Point(point));
featureStyle = new ol.style.Style({
text: new ol.style.Text({
fill: new ol.style.Fill({ color: "#000" }),
font: "normal 24px sans-serif",
stroke: new ol.style.Stroke({
color: "#88888888",
width: 1,
}),
text: String.fromCharCode(x) + String.fromCharCode(y),
}),
});
feature.setStyle(featureStyle);
g_layerSources["big-grids"].addFeature(feature);
}
}
function versionCheck(buffer, flag) {
var version = String(buffer);
if (version.indexOf("gridtracker") == 0) {
// good, we're looking at our version string
var versionArray = version.split(":");
if (versionArray.length == 3) {
// Good, there are 3 parts
var stableVersion = Number(versionArray[1]);
var betaVersion = Number(versionArray[2]);
if (gtVersion < stableVersion) {
var verString = String(stableVersion);
main.style.display = "none";
newVersionMustDownloadDiv.innerHTML =
"New Version v" +
verString.substr(0, 1) +
"." +
verString.substr(1, 2) +
"." +
verString.substr(3) +
" available for download.<br />Go there now?<br /><br />";
versionDiv.style.display = "block";
} else {
if (flag) {
if (gtVersion < betaVersion) {
var verString = String(betaVersion);
main.style.display = "none";
newVersionMustDownloadDiv.innerHTML =
"New <b><i>Beta</i></b> Version v" +
verString.substr(0, 1) +
"." +
verString.substr(1, 2) +
"." +
verString.substr(3) +
" available for download.<br />Go there now?<br /><br />";
versionDiv.style.display = "block";
} else {
main.style.display = "none";
upToDateDiv.style.display = "block";
}
}
}
}
}
}
function onExitAppToGoWebsite() {
require("nw.gui").Shell.openExternal("https://gridtracker.org/");
saveAndCloseApp();
}
function mailThem(address) {
require("nw.gui").Shell.openExternal("mailto:" + address);
}
function openSite(address) {
require("nw.gui").Shell.openExternal(address);
}
function closeUpdateToDateDiv() {
upToDateDiv.style.display = "none";
main.style.display = "block";
}
function cancelVersion() {
main.style.display = "block";
versionDiv.style.display = "none";
}
function getBuffer(file_url, callback, flag, mode, port, cache = null) {
var url = require("url");
var http = require(mode);
var fileBuffer = null;
var options = null;
options = {
host: url.parse(file_url).host,
port: port,
followAllRedirects: true,
path: url.parse(file_url).path,
};
http.get(options, function (res) {
var fsize = res.headers["content-length"];
var cookies = null;
if (typeof res.headers["set-cookie"] != "undefined")
cookies = res.headers["set-cookie"];
res
.on("data", function (data) {
if (fileBuffer == null) fileBuffer = data;
else fileBuffer += data;
})
.on("end", function () {
if (typeof callback === "function") {
// Call it, since we have confirmed it is callable
callback(fileBuffer, flag, cache);
}
})
.on("error", function (e) {
console.error("Got error: " + e.message);
});
});
}
function getPostBuffer(
file_url,
callback,
flag,
mode,
port,
theData,
timeoutMs,
timeoutCallback,
who
) {
var querystring = require("querystring");
var postData = querystring.stringify(theData);
var url = require("url");
var http = require(mode);
var fileBuffer = null;
var options = {
host: url.parse(file_url).host,
port: port,
path: url.parse(file_url).path,
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Content-Length": postData.length,
},
};
var req = http.request(options, function (res) {
var fsize = res.headers["content-length"];
var cookies = null;
if (typeof res.headers["set-cookie"] != "undefined")
cookies = res.headers["set-cookie"];
res
.on("data", function (data) {
if (fileBuffer == null) fileBuffer = data;
else fileBuffer += data;
})
.on("end", function () {
if (typeof callback === "function") {
// Call it, since we have confirmed it is callable
callback(fileBuffer, flag, cookies);
}
})
.on("error", function () {
if (typeof errorCallback === "function") {
errorCallback();
}
});
});
if (typeof timeoutMs == "number" && timeoutMs > 0) {
req.on("socket", function (socket) {
socket.setTimeout(timeoutMs);
socket.on("timeout", function () {
req.abort();
});
});
req.on("error", function (err) {
if (typeof timeoutCallback != "undefined")
timeoutCallback(
file_url,
callback,
flag,
mode,
port,
theData,
timeoutMs,
timeoutCallback,
who
);
});
}
req.write(postData);
req.end();
}
function colorToHex(color) {
if (color.substr(0, 1) === "#") {
return color;
}
var digits = /(.*?)rgb\((\d+), (\d+), (\d+)\)/.exec(color);
var red = parseInt(digits[2]);
var green = parseInt(digits[3]);
var blue = parseInt(digits[4]);
var rgb = ("00" + (+red).toString(16)).substr(-2);
rgb += ("00" + (+green).toString(16)).substr(-2);
rgb += ("00" + (+blue).toString(16)).substr(-2);
return "#" + rgb;
}
function setHueColor() {
g_mapHue = colorToHex(hueDiv.style.backgroundColor);
if (g_mapHue == "#000000") g_mapHue = 0;
}
function loadMapSettings() {
shadowValue.value = g_mapSettings.shadow;
showDarknessTd.innerHTML = parseInt(shadowValue.value * 100) + "%";
pathWidthTd.innerHTML = pathWidthValue.value = g_appSettings.pathWidthWeight;
qrzPathWidthTd.innerHTML = qrzPathWidthValue.value =
g_appSettings.qrzPathWidthWeight;
gridDecay.value = g_appSettings.gridsquareDecayTime;
changeGridDecay();
pathColorValue.value = g_mapSettings.pathColor;
qrzPathColorValue.value = g_mapSettings.qrzPathColor;
brightnessValue.value = g_mapSettings.loudness;
nightBrightnessValue.value = g_mapSettings.nightLoudness;
nightPathColorValue.value = g_mapSettings.nightPathColor;
nightQrzPathColorValue.value = g_mapSettings.nightQrzPathColor;
mouseOverValue.checked = g_mapSettings.mouseOver;
mergeOverlayValue.checked = g_mapSettings.mergeOverlay;
offlineImg.src = g_mapImageArray[g_mapSettings.offlineMode ? 0 : 1];
mapSelect.value = g_mapSettings.mapIndex;
mapNightSelect.value = g_mapSettings.nightMapIndex;
animateValue.checked = g_mapSettings.animate;
animateSpeedValue.value = 21 - g_mapSettings.animateSpeed;
setAnimateView();
splitQSLValue.checked = g_mapSettings.splitQSL;
fitQRZvalue.checked = g_mapSettings.fitQRZ;
qrzDxccFallbackValue.checked = g_mapSettings.qrzDxccFallback;
CqHiliteValue.checked = g_mapSettings.CQhilite;
focusRigValue.checked = g_mapSettings.focusRig;
haltAllOnTxValue.checked = g_mapSettings.haltAllOnTx;
strikesAlert.value = g_mapSettings.strikesAlert;
setStrikesButton();
trafficDecode.checked = g_mapSettings.trafficDecode;
pskSpotsImg.style.filter = g_spotsEnabled == 1 ? "" : "grayscale(1);";
g_bandToColor = JSON.parse(JSON.stringify(g_pskColors));
setGridOpacity();
var pathColor =
pathColorValue.value == 0
? "#000"
: pathColorValue.value == 361
? "#FFF"
: "hsl(" + pathColorValue.value + ", 100%, 50%)";
if (pathColorValue.value != 0) {
pathColorDiv.style.color = "#000";
pathColorDiv.style.backgroundColor = pathColor;
} else {
pathColorDiv.style.color = "#FFF";
pathColorDiv.style.backgroundColor = pathColor;
}
pathColor =
qrzPathColorValue.value == 0
? "#000"
: qrzPathColorValue.value == 361
? "#FFF"
: "hsl(" + qrzPathColorValue.value + ", 100%, 50%)";
if (qrzPathColorValue.value != 0) {
qrzPathColorDiv.style.color = "#000";
qrzPathColorDiv.style.backgroundColor = pathColor;
} else {
qrzPathColorDiv.style.color = "#FFF";
qrzPathColorDiv.style.backgroundColor = pathColor;
}
setNightHtml();
displayLegend();
}
function changeDistanceUnit() {
g_appSettings.distanceUnit = distanceUnit.value;
g_scaleLine.setUnits(g_scaleUnits[g_appSettings.distanceUnit]);
goProcessRoster();
}
function changeMapNightValues() {
g_mapSettings.nightPathColor = nightPathColorValue.value;
g_mapSettings.nightQrzPathColor = nightQrzPathColorValue.value;
g_mapSettings.nightMapIndex = mapNightSelect.value;
g_mapSettings.nightLoudness = nightBrightnessValue.value;
saveMapSettings();
setNightHtml();
changeMapLayer();
}
function setNightHtml() {
var pathColor =
g_mapSettings.nightPathColor == 0
? "#000"
: g_mapSettings.nightPathColor == 361
? "#FFF"
: "hsl(" + g_mapSettings.nightPathColor + ", 100%, 50%)";
if (g_mapSettings.nightPathColor != 0) {
pathNightColorDiv.style.color = "#000";
pathNightColorDiv.style.backgroundColor = pathColor;
} else {
pathNightColorDiv.style.color = "#FFF";
pathNightColorDiv.style.backgroundColor = pathColor;
}
pathColor =
g_mapSettings.nightQrzPathColor == 0
? "#000"
: g_mapSettings.nightQrzPathColor == 361
? "#FFF"
: "hsl(" + g_mapSettings.nightQrzPathColor + ", 100%, 50%)";
if (g_mapSettings.nightQrzPathColor != 0) {
pathNightQrzColorDiv.style.color = "#000";
pathNightQrzColorDiv.style.backgroundColor = pathColor;
} else {
pathNightQrzColorDiv.style.color = "#FFF";
pathNightQrzColorDiv.style.backgroundColor = pathColor;
}
}
function changeMapValues() {
g_mapSettings.pathColor = pathColorValue.value;
g_mapSettings.qrzPathColor = qrzPathColorValue.value;
g_mapSettings.loudness = brightnessValue.value;
g_mapSettings.mapIndex = mapSelect.value;
if (
g_appSettings.gtFlagImgSrc > 0 &&
g_mapSettings.offlineMode == false &&
g_appSettings.gtShareEnable == true
)
g_layerVectors["gtflags"].setVisible(true);
else g_layerVectors["gtflags"].setVisible(false);
saveMapSettings();
saveAlertSettings();
var pathColor =
g_mapSettings.pathColor == 0
? "#000"
: g_mapSettings.pathColor == 361
? "#FFF"
: "hsl(" + g_mapSettings.pathColor + ", 100%, 50%)";
if (g_mapSettings.pathColor != 0) {
pathColorDiv.style.color = "#000";
pathColorDiv.style.backgroundColor = pathColor;
} else {
pathColorDiv.style.color = "#FFF";
pathColorDiv.style.backgroundColor = pathColor;
}
pathColor =
g_mapSettings.qrzPathColor == 0
? "#000"
: g_mapSettings.qrzPathColor == 361
? "#FFF"
: "hsl(" + g_mapSettings.qrzPathColor + ", 100%, 50%)";
if (g_mapSettings.qrzPathColor != 0) {
qrzPathColorDiv.style.color = "#000";
qrzPathColorDiv.style.backgroundColor = pathColor;
} else {
qrzPathColorDiv.style.color = "#FFF";
qrzPathColorDiv.style.backgroundColor = pathColor;
}
changeMapLayer();
displayLegend();
}
function toggleLegend() {
if (g_mapSettings.legend == true) g_mapSettings.legend = false;
else g_mapSettings.legend = true;
saveMapSettings();
displayLegend();
}
function hideLegend() {
LegendDiv.style.display = "none";
}
function displayLegend() {
if (g_mapSettings.legend == true) {
LegendDiv.style.display = "block";
legendImg.style.webkitFilter = "";
} else {
LegendDiv.style.display = "none";
legendImg.style.webkitFilter = "grayscale(1) brightness(50%)";
}
}
function rgbToHex(R, G, B) {
return toHex(R) + toHex(G) + toHex(B);
}
function toHex(n) {
n = parseInt(n, 10);
if (isNaN(n)) return "00";
n = Math.max(0, Math.min(n, 255));
return (
"0123456789ABCDEF".charAt((n - (n % 16)) / 16) +
"0123456789ABCDEF".charAt(n % 16)
);
}
function hexToR(h) {
return parseInt(cutHex(h).substring(0, 2), 16);
}
function hexToG(h) {
return parseInt(cutHex(h).substring(2, 4), 16);
}
function hexToB(h) {
return parseInt(cutHex(h).substring(4, 6), 16);
}
function hexToA(h) {
return parseInt(cutHex(h).substring(6, 8), 16);
}
function cutHex(h) {
return h.charAt(0) == "#" ? h.substring(1, 9) : h;
}
function changeMapLayer() {
if (g_mapSettings.offlineMode) {
g_tileLayer.setSource(g_offlineLayer);
g_tileLayer.setOpacity(Number(g_mapSettings.loudness));
} else {
if (g_mapSettings.nightMapEnable && g_nightTime) {
g_tileLayer.setSource(g_mapsLayer[g_mapSettings.nightMapIndex]);
g_tileLayer.setOpacity(Number(g_mapSettings.nightLoudness));
} else {
g_tileLayer.setSource(g_mapsLayer[g_mapSettings.mapIndex]);
g_tileLayer.setOpacity(Number(g_mapSettings.loudness));
}
}
changePathWidth();
redrawSpots();
}
function voiceChangedValue() {
g_speechSettings.voice = Number(alertVoiceInput.value) + 1;
changeSpeechValues();
}
function timedGetVoices() {
g_voices = window.speechSynthesis.getVoices();
if (g_voices.length > 0) {
var newSelect = document.createElement("select");
newSelect.id = "alertVoiceInput";
newSelect.title = "Select Voice";
for (var i = 0; i < g_voices.length; i++) {
var option = document.createElement("option");
option.value = i;
newstring = g_voices[i].name.replace(/ /g, "");
option.text = newstring;
if (g_voices[i].default) {
option.selected = true;
}
newSelect.appendChild(option);
}
newSelect.oninput = voiceChangedValue;
voicesDiv.appendChild(newSelect);
}
g_speechAvailable = true;
loadAlerts();
}
function initSpeech() {
window.speechSynthesis.onvoiceschanged = function () {
setTimeout(timedGetVoices, 500);
};
var msg = new SpeechSynthesisUtterance(".");
msg.lang = g_localeString;
window.speechSynthesis.speak(msg);
}
function initSoundCards() {
navigator.mediaDevices
.enumerateDevices()
.then(gotAudioDevices)
.catch(errorCallback);
}
function errorCallback(e) {}
function gotAudioDevices(deviceInfos) {
soundCardDiv.innerHTML = "";
var newSelect = document.createElement("select");
newSelect.id = "soundCardInput";
newSelect.title = "Select Sound Card";
for (var i = 0; i !== deviceInfos.length; ++i) {
var deviceInfo = deviceInfos[i];
if (deviceInfo.kind === "audiooutput") {
var option = document.createElement("option");
option.value = deviceInfo.deviceId;
option.text = deviceInfo.label || "Speaker " + (newSelect.length + 1);
newSelect.appendChild(option);
}
}
newSelect.oninput = soundCardChangedValue;
soundCardDiv.appendChild(newSelect);
soundCardInput.value = g_soundCard;
}
function soundCardChangedValue() {
g_appSettings.soundCard = g_soundCard = soundCardInput.value;
playTestFile();
}
function setPins() {
g_colorLeafletPins = {};
g_colorLeafleteQPins = {};
g_colorLeafletQPins.worked = {};
g_colorLeafletQPins.confirmed = {};
for (var i = 0; i < g_colorBands.length; i++) {
var pin = new ol.style.Icon({
src: "./img/pin/" + g_colorBands[i] + ".png",
anchorYUnits: "pixels",
anchorXUnits: "pixels",
anchor: [5, 18],
});
g_colorLeafletPins[g_colorBands[i]] = pin;
pin = new ol.style.Icon({
src: "./img/pin/" + g_colorBands[i] + "w.png",
anchorYUnits: "pixels",
anchorXUnits: "pixels",
anchor: [5, 18],
});
g_colorLeafletQPins.worked[g_colorBands[i]] = pin;
pin = new ol.style.Icon({
src: "./img/pin/" + g_colorBands[i] + "q.png",
anchorYUnits: "pixels",
anchorXUnits: "pixels",
anchor: [5, 18],
});
g_colorLeafletQPins.confirmed[g_colorBands[i]] = pin;
}
}
function loadViewSettings() {
gtBandFilter.value = g_appSettings.gtBandFilter;
gtModeFilter.value = g_appSettings.gtModeFilter;
gtPropFilter.value = g_appSettings.gtPropFilter;
distanceUnit.value = g_appSettings.distanceUnit;
N1MMIpInput.value = g_N1MMSettings.ip;
N1MMPortInput.value = g_N1MMSettings.port;
buttonN1MMCheckBox.checked = g_N1MMSettings.enable;
ValidatePort(N1MMPortInput, buttonN1MMCheckBox, null);
ValidateIPaddress(N1MMIpInput, buttonN1MMCheckBox, null);
log4OMIpInput.value = g_log4OMSettings.ip;
log4OMPortInput.value = g_log4OMSettings.port;
buttonLog4OMCheckBox.checked = g_log4OMSettings.enable;
ValidatePort(log4OMPortInput, buttonLog4OMCheckBox, null);
ValidateIPaddress(log4OMIpInput, buttonLog4OMCheckBox, null);
acLogIpInput.value = g_acLogSettings.ip;
acLogPortInput.value = g_acLogSettings.port;
buttonacLogCheckBox.checked = g_acLogSettings.enable;
ValidatePort(acLogPortInput, buttonacLogCheckBox, null);
ValidateIPaddress(acLogIpInput, buttonacLogCheckBox, null);
dxkLogIpInput.value = g_dxkLogSettings.ip;
dxkLogPortInput.value = g_dxkLogSettings.port;
buttondxkLogCheckBox.checked = g_dxkLogSettings.enable;
ValidatePort(dxkLogPortInput, buttondxkLogCheckBox, null);
ValidateIPaddress(dxkLogIpInput, buttondxkLogCheckBox, null);
hrdLogbookIpInput.value = g_HRDLogbookLogSettings.ip;
hrdLogbookPortInput.value = g_HRDLogbookLogSettings.port;
buttonHrdLogbookCheckBox.checked = g_HRDLogbookLogSettings.enable;
ValidatePort(hrdLogbookPortInput, buttonHrdLogbookCheckBox, null);
ValidateIPaddress(hrdLogbookIpInput, buttonHrdLogbookCheckBox, null);
spotHistoryTimeValue.value = parseInt(
g_receptionSettings.viewHistoryTimeSec / 60
);
spotHistoryTimeTd.innerHTML =
"Max Age: " + Number(g_receptionSettings.viewHistoryTimeSec).toDHM();
spotPathsValue.checked = g_receptionSettings.viewPaths;
spotPathColorValue.value = g_receptionSettings.pathColor;
spotNightPathColorValue.value = g_receptionSettings.pathNightColor;
spotWidthTd.innerHTML = spotWidthValue.value = g_receptionSettings.spotWidth;
spotMergeValue.checked = g_receptionSettings.mergeSpots;
lookupOnTx.checked = g_appSettings.lookupOnTx;
lookupCloseLog.checked = g_appSettings.lookupCloseLog;
lookupMerge.checked = g_appSettings.lookupMerge;
lookupMissingGrid.checked = g_appSettings.lookupMissingGrid;
if (g_appSettings.lookupMerge == true) {
lookupMissingGridDiv.style.display = "inline-block";
} else {
lookupMissingGridDiv.style.display = "none";
}
if (g_receptionSettings.viewPaths) {
spotPathWidthDiv.style.display = "inline-block";
} else {
spotPathWidthDiv.style.display = "none";
}
spotPathChange();
setRosterTimeView();
}
function loadMsgSettings() {
msgEnable.checked = g_appSettings.gtMsgEnable;
GTspotEnable.checked = g_appSettings.gtSpotEnable;
pskSpotsImg.style.filter = g_spotsEnabled == 1 ? "" : "grayscale(1)";
for (var key in g_msgSettings) {
document.getElementById(key).value = g_msgSettings[key];
}
ValidateText(msgAwayText);
setMsgSettingsView();
}
function setMsgSettingsView() {
if (msgEnable.checked) msgSettingsDiv.style.display = "inline-block";
else msgSettingsDiv.style.display = "none";
if (g_msgSettings.msgAlertSelect > 0) {
msgFrequencySelectDiv.style.display = "inline-block";
if (g_msgSettings.msgAlertSelect == 1) {
msgAlertWord.style.display = "inline-block";
msgAlertMedia.style.display = "none";
ValidateText(msgAlertWord);
}
if (g_msgSettings.msgAlertSelect == 2) {
msgAlertWord.style.display = "none";
msgAlertMedia.style.display = "inline-block";
}
} else {
msgFrequencySelectDiv.style.display = "none";
msgAlertWord.style.display = "none";
msgAlertMedia.style.display = "none";
}
if (g_msgSettings.msgAwaySelect > 0)
msgAwayTextDiv.style.display = "inline-block";
else msgAwayTextDiv.style.display = "none";
}
function loadAdifSettings() {
workingCallsignEnable.checked = g_appSettings.workingCallsignEnable;
workingCallsignsValue.value = Object.keys(
g_appSettings.workingCallsigns
).join(",");
ValidateCallsigns(workingCallsignsValue);
workingDateEnable.checked = g_appSettings.workingDateEnable;
displayWorkingDate();
if (g_platform == "mac") {
selectTQSLButton.style.display = "none";
}
for (var key in g_adifLogSettings.menu) {
var value = g_adifLogSettings.menu[key];
var where = key + "Div";
if (document.getElementById(key) != null) {
document.getElementById(key).checked = value;
if (value == true) {
document.getElementById(where).style.display = "inline-block";
} else {
document.getElementById(where).style.display = "none";
}
}
}
for (var key in g_adifLogSettings.startup) {
if (document.getElementById(key) != null)
document.getElementById(key).checked = g_adifLogSettings.startup[key];
}
for (var key in g_adifLogSettings.nickname) {
if (document.getElementById(key) != null) {
document.getElementById(key).checked = g_adifLogSettings.nickname[key];
if (key == "nicknameeQSLCheckBox") {
if (document.getElementById(key).checked == true) {
eQSLNickname.style.display = "inline-block";
} else {
eQSLNickname.style.display = "none";
}
}
}
}
for (var key in g_adifLogSettings.text) {
if (document.getElementById(key) != null) {
document.getElementById(key).value = g_adifLogSettings.text[key];
ValidateText(document.getElementById(key));
}
}
for (var key in g_adifLogSettings.qsolog) {
if (document.getElementById(key) != null) {
document.getElementById(key).checked = g_adifLogSettings.qsolog[key];
if (key == "logLOTWqsoCheckBox") {
if (document.getElementById(key).checked == true) {
lotwUpload.style.display = "inline-block";
trustedTestButton.style.display = "inline-block";
} else {
lotwUpload.style.display = "none";
trustedTestButton.style.display = "none";
}
}
}
}
if (clubCall.value == "" && myRawCall != "NOCALL") {
clubCall.value = myRawCall;
ValidateText(clubCall);
localStorage.adifLogSettings = JSON.stringify(g_adifLogSettings);
}
try {
findTrustedQSLPaths();
} catch (e) {
if (logLOTWqsoCheckBox.checked == true) {
alert(
"Unable to access LoTW TrustedQSL (TQSL) due to OS permissions\nLogging to LoTW disabled for this session\nRun as administrator or allow file access to GridTracker if problem persists"
);
logLOTWqsoCheckBox.checked = false;
}
}
setAdifStartup(loadAdifCheckBox);
ValidateQrzApi(qrzApiKey);
}
function startupVersionInit() {
if (!g_developerMode) {
document.body.addEventListener("contextmenu", function (ev) {
ev.preventDefault();
});
}
imSureCheck.checked = false;
stopAskingCheckbox.checked = g_appSettings.stopAskingVersion;
if (stopAskingCheckbox.checked == false) {
checkForNewVersion(false);
setInterval(function () {
checkForNewVersion(false);
}, 86400000);
}
}
function startupButtonsAndInputs() {
try {
g_pushPinMode = !(g_appSettings.pushPinMode == true);
togglePushPinMode();
udpForwardEnable.checked = g_appSettings.wsjtForwardUdpEnable;
multicastEnable.checked = g_appSettings.multicast;
gridViewButton.innerHTML = g_gridViewArray[g_appSettings.gridViewMode];
earthImg.src = g_earthShadowImageArray[g_appSettings.earthImgSrc];
gtFlagImg.src = g_gtFlagImageArray[g_appSettings.gtFlagImgSrc];
gtShareFlagImg.src =
g_gtShareFlagImageArray[g_appSettings.gtShareEnable == false ? 0 : 1];
alertMuteImg.src = g_alertImageArray[g_appSettings.alertMute];
modeImg.src = g_maidenheadModeImageArray[g_appSettings.sixWideMode];
rosterAlwaysOnTop.checked = g_appSettings.rosterAlwaysOnTop;
if (g_appSettings.centerGridsquare.length > 0) {
homeQTHInput.value = g_appSettings.centerGridsquare.substr(0, 6);
if (ValidateGridsquare(homeQTHInput, null)) setCenterGridsquare();
}
ValidateCallsign(alertValueInput, null);
if (g_mapSettings.offlineMode == true) {
conditionsButton.style.display = "none";
buttonPsk24CheckBoxDiv.style.display = "none";
buttonQRZCheckBoxDiv.style.display = "none";
buttonLOTWCheckBoxDiv.style.display = "none";
buttonClubCheckBoxDiv.style.display = "none";
gtFlagButton.style.display = "none";
gtShareButton.style.display = "none";
msgButton.style.display = "none";
donateButton.style.display = "none";
pskReporterBandActivityDiv.style.display = "none";
buttonStrikesDiv.style.display = "none";
buttonPSKSpotsBoxDiv.style.display = "none";
}
setGtShareButtons();
} catch (e) {}
}
function startupEventsAndTimers() {
document.addEventListener("keydown", onMyKeyDown, true);
document.addEventListener("keyup", onMyKeyUp, false);
displayTimeInterval = setInterval(displayTime, 1000);
}
var g_finishedLoading = false;
function postInit() {
redrawSpots();
checkForSettings();
updateForwardListener();
addLastTraffic("GridTracker</br>" + gtShortVersion);
g_nexradEnable = g_mapSettings.usNexrad ? 0 : 1;
toggleNexrad();
if (String(gtVersion) != String(g_startVersion)) {
//generalbut.className = "settingsTablinks";
showSettingsBox();
openSettingsTab(updatebut, "updateSettingsDiv");
}
g_finishedLoading = true;
//tagme
var x = document.querySelectorAll("input[type='range']");
for (var i = 0; i < x.length; i++) {
if (x[i].title.length > 0) x[i].title += "\n";
x[i].title += "(Use Arrow Keys For Smaller Increments)";
}
openLookupWindow(false);
openBaWindow(false);
openCallRosterWindow(false);
openConditionsWindow(false);
showMessaging(false);
}
document.addEventListener("dragover", function (event) {
event.preventDefault();
});
document.addEventListener("drop", function (event) {
event.preventDefault();
if (g_finishedLoading == true) dropHandler(event);
});
var g_startupTable = [
[startupVersionInit, "Completed Version Check"],
[qsoBackupFileInit, "QSO Backup Initialized"],
[callsignServicesInit, "Callsign Services Initialized"],
[loadMapSettings, "Map Settings Initialized"],
[initMap, "Loaded Map"],
[setPins, "Created Pins"],
[loadViewSettings, "Loaded View Settings"],
[loadMsgSettings, "Loaded Messaging Settings"],
[setFileSelectors, "Set File Selectors"],
[lockNewWindows, "Locked New Windows"],
[loadMaidenHeadData, "Loaded Maidenhead Dataset"],
[drawAllGrids, "Rendered All Maidenhead Grids"],
[updateRunningProcesses, "Updated Running Processes"],
[updateBasedOnIni, "Updated from WSJT-X/JTDX"],
[loadAdifSettings, "Loaded ADIF Settings"],
[startupButtonsAndInputs, "Buttons and Inputs Initialized"],
[initSpeech, "Speech Initialized"],
[initSoundCards, "Sounds Initialized"],
[loadPortSettings, "Loaded Network Settings"],
[loadLookupDetails, "Callsign Lookup Details Loaded"],
[startupEventsAndTimers, "Set Events and Timers"],
[registerHotKeys, "Registered Hotkeys"],
[gtChatSystemInit, "User System Initialized"],
[postInit, "Finalizing System"],
];
function init() {
startupVersionDiv.innerHTML = gtVersionString;
aboutVersionDiv.innerHTML = gtVersionString;
g_currentDay = parseInt(timeNowSec() / 86400);
if (mediaCheck() == false) {
startupDiv.style.display = "none";
documentsDiv.style.display = "block";
searchedDocFolder.innerHTML = g_appData;
} else {
documentsDiv.style.display = "none";
startupDiv.style.display = "block";
startupStatusDiv.innerHTML = "Starting...";
setTimeout(startupEngine, 10);
}
}
function startupEngine() {
if (g_startupTable.length > 0) {
var funcInfo = g_startupTable.shift();
funcInfo[0]();
startupStatusDiv.innerHTML = funcInfo[1];
setTimeout(startupEngine, 10);
} else {
startupStatusDiv.innerHTML = "Completed";
setTimeout(endStartup, 2000);
startupAdifLoadCheck();
openStatsWindow(false);
}
}
function directoryInput(what) {
g_appSettings.savedAppData = what.files[0].path;
init();
}
function endStartup() {
startupDiv.style.display = "none";
main.style.display = "block";
g_map.updateSize();
}
function loadPortSettings() {
multicastEnable.checked = g_appSettings.multicast;
multicastIpInput.value = g_appSettings.wsjtIP;
setMulticastEnable(multicastEnable);
udpPortInput.value = g_appSettings.wsjtUdpPort;
ValidatePort(udpPortInput, null, CheckReceivePortIsNotForwardPort);
udpForwardPortInput.value = g_appSettings.wsjtForwardUdpPort;
ValidatePort(udpForwardPortInput, null, CheckForwardPortIsNotReceivePort);
udpForwardIpInput.value = g_appSettings.wsjtForwardUdpIp;
ValidateIPaddress(udpForwardIpInput, null);
udpForwardEnable.checked = g_appSettings.wsjtForwardUdpEnable;
setUdpForwardEnable(udpForwardEnable);
}
var g_wsjtCurrentPort = -1;
var g_wsjtUdpServer = null;
var g_wsjtUdpSocketReady = false;
var g_wsjtUdpSocketError = false;
var g_qtToSplice = 0;
function decodeQUINT8(byteArray) {
g_qtToSplice = 1;
return byteArray[0];
}
function encodeQBOOL(byteArray, offset, value) {
return byteArray.writeUInt8(value, offset);
}
function decodeQUINT32(byteArray) {
g_qtToSplice = 4;
return byteArray.readUInt32BE(0);
}
function encodeQUINT32(byteArray, offset, value) {
if (value == -1) value = 4294967295;
return byteArray.writeUInt32BE(value, offset);
}
function decodeQINT32(byteArray) {
g_qtToSplice = 4;
return byteArray.readInt32BE(0);
}
function encodeQINT32(byteArray, offset, value) {
return byteArray.writeInt32BE(value, offset);
}
function decodeQUINT64(byteArray) {
var value = 0;
for (var i = 0; i < 8; i++) {
value = value * 256 + byteArray[i];
}
g_qtToSplice = 8;
return value;
}
function encodeQUINT64(byteArray, offset, value) {
var breakOut = Array();
for (var i = 0; i < 8; i++) {
breakOut[i] = value & 0xff;
value >>= 8;
}
for (var i = 0; i < 8; i++) {
offset = encodeQBOOL(byteArray, offset, breakOut[7 - i]);
}
return offset;
}
function decodeQUTF8(byteArray) {
var utf8_len = decodeQUINT32(byteArray);
var result = "";
byteArray = byteArray.slice(g_qtToSplice);
if (utf8_len == 0xffffffff) utf8_len = 0;
else result = byteArray.slice(0, utf8_len);
g_qtToSplice = utf8_len + 4;
return result.toString();
}
function encodeQUTF8(byteArray, offset, value) {
offset = encodeQUINT32(byteArray, offset, value.length);
var wrote = byteArray.write(value, offset, value.length);
return wrote + offset;
}
function decodeQDOUBLE(byteArray) {
g_qtToSplice = 8;
return byteArray.readDoubleBE(0);
}
function encodeQDOUBLE(byteArray, offset, value) {
return byteArray.writeDoubleBE(value, offset);
}
var g_forwardUdpServer = null;
function updateForwardListener() {
if (g_forwardUdpServer != null) {
g_forwardUdpServer.close();
}
if (g_closing == true) return;
var dgram = require("dgram");
g_forwardUdpServer = dgram.createSocket({
type: "udp4",
reuseAddr: true,
});
g_forwardUdpServer.on("listening", function () {});
g_forwardUdpServer.on("error", function () {
g_forwardUdpServer.close();
g_forwardUdpServer = null;
});
g_forwardUdpServer.on("message", function (originalMessage, remote) {
// Decode enough to get the rig-name, so we know who to send to
var message = Object.assign({}, originalMessage);
var newMessage = {};
newMessage.magic_key = decodeQUINT32(message);
message = message.slice(g_qtToSplice);
if (newMessage.magic_key == 0xadbccbda) {
newMessage.schema_number = decodeQUINT32(message);
message = message.slice(g_qtToSplice);
newMessage.type = decodeQUINT32(message);
message = message.slice(g_qtToSplice);
newMessage.Id = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
var instanceId = newMessage.Id;
if (instanceId in g_instances) {
wsjtUdpMessage(
originalMessage,
originalMessage.length,
g_instances[instanceId].remote.port,
g_instances[instanceId].remote.address
);
}
}
});
g_forwardUdpServer.bind(0);
}
function sendForwardUdpMessage(msg, length, port, address) {
if (g_forwardUdpServer) {
g_forwardUdpServer.send(msg, 0, length, port, address);
}
}
function wsjtUdpMessage(msg, length, port, address) {
if (g_wsjtUdpServer) {
g_wsjtUdpServer.send(msg, 0, length, port, address);
}
}
function checkWsjtxListener() {
if (
g_wsjtUdpServer == null ||
(g_wsjtUdpSocketReady == false && g_wsjtUdpSocketError == true)
) {
g_wsjtCurrentPort = -1;
g_wsjtCurrentIP = "none";
}
updateWsjtxListener(g_appSettings.wsjtUdpPort);
}
var g_instances = {};
var g_instancesIndex = Array();
var g_activeInstance = "";
var g_activeIndex = 0;
var g_currentID = null;
function updateWsjtxListener(port) {
if (port == g_wsjtCurrentPort && g_appSettings.wsjtIP == g_wsjtCurrentIP)
return;
if (g_wsjtUdpServer != null) {
if (multicastEnable.checked == true && g_appSettings.wsjtIP != "") {
try {
g_wsjtUdpServer.dropMembership(g_appSettings.wsjtIP);
} catch (e) {}
}
g_wsjtUdpServer.close();
g_wsjtUdpServer = null;
g_wsjtUdpSocketReady = false;
}
if (g_closing == true) return;
g_wsjtUdpSocketError = false;
var dgram = require("dgram");
g_wsjtUdpServer = dgram.createSocket({
type: "udp4",
reuseAddr: true,
});
if (multicastEnable.checked == true && g_appSettings.wsjtIP != "") {
g_wsjtUdpServer.on("listening", function () {
var address = g_wsjtUdpServer.address();
g_wsjtUdpServer.setBroadcast(true);
g_wsjtUdpServer.setMulticastTTL(128);
g_wsjtUdpServer.addMembership(g_appSettings.wsjtIP);
g_wsjtUdpSocketReady = true;
});
} else {
g_appSettings.multicast = false;
g_wsjtCurrentIP = g_appSettings.wsjtIP = "";
g_wsjtUdpServer.on("listening", function () {
g_wsjtUdpServer.setBroadcast(true);
g_wsjtUdpSocketReady = true;
});
}
g_wsjtUdpServer.on("error", function () {
g_wsjtUdpServer.close();
g_wsjtUdpServer = null;
g_wsjtUdpSocketReady = false;
g_wsjtUdpSocketError = true;
});
g_wsjtUdpServer.on("message", function (message, remote) {
if (g_closing == true) true;
if (
typeof udpForwardEnable != "undefined" &&
udpForwardEnable.checked == true
) {
sendForwardUdpMessage(
message,
message.length,
udpForwardPortInput.value,
udpForwardIpInput.value
);
}
var newMessage = {};
newMessage.magic_key = decodeQUINT32(message);
message = message.slice(g_qtToSplice);
if (newMessage.magic_key == 0xadbccbda) {
newMessage.schema_number = decodeQUINT32(message);
message = message.slice(g_qtToSplice);
newMessage.type = decodeQUINT32(message);
message = message.slice(g_qtToSplice);
newMessage.Id = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
var instanceId = newMessage.Id;
if (!(instanceId in g_instances)) {
g_instances[instanceId] = {};
g_instances[instanceId].valid = false;
g_instancesIndex.push(instanceId);
g_instances[instanceId].intId = g_instancesIndex.length - 1;
g_instances[instanceId].crEnable = true;
if (g_instancesIndex.length > 1) {
multiRigCRDiv.style.display = "inline-block";
haltTXDiv.style.display = "inline-block";
}
updateRosterInstances();
}
var notify = false;
if (g_instances[instanceId].open == false) notify = true;
g_instances[instanceId].open = true;
g_instances[instanceId].remote = remote;
if (notify) updateRosterInstances();
if (newMessage.type == 1) {
newMessage.event = "Status";
newMessage.Frequency = decodeQUINT64(message);
newMessage.Band = Number(newMessage.Frequency / 1000000).formatBand();
message = message.slice(g_qtToSplice);
newMessage.MO = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.DXcall = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.Report = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.TxMode = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.TxEnabled = decodeQUINT8(message);
message = message.slice(g_qtToSplice);
newMessage.Transmitting = decodeQUINT8(message);
message = message.slice(g_qtToSplice);
newMessage.Decoding = decodeQUINT8(message);
message = message.slice(g_qtToSplice);
newMessage.RxDF = decodeQINT32(message);
message = message.slice(g_qtToSplice);
newMessage.TxDF = decodeQINT32(message);
message = message.slice(g_qtToSplice);
newMessage.DEcall = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.DEgrid = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.DXgrid = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.TxWatchdog = decodeQUINT8(message);
message = message.slice(g_qtToSplice);
newMessage.Submode = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.Fastmode = decodeQUINT8(message);
message = message.slice(g_qtToSplice);
if (message.length > 0) {
newMessage.SopMode = decodeQUINT8(message);
message = message.slice(g_qtToSplice);
} else {
newMessage.SopMode = -1;
}
if (message.length > 0) {
newMessage.FreqTol = decodeQINT32(message);
message = message.slice(g_qtToSplice);
} else {
newMessage.FreqTol = -1;
}
if (message.length > 0) {
newMessage.TRP = decodeQINT32(message);
message = message.slice(g_qtToSplice);
} else {
newMessage.TRP = -1;
}
if (message.length > 0) {
newMessage.ConfName = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
} else {
newMessage.ConfName = null;
}
g_instances[instanceId].status = newMessage;
g_instances[instanceId].valid = true;
}
if (g_instances[instanceId].valid == true) {
if (newMessage.type == 2) {
newMessage.event = "Decode";
newMessage.NW = decodeQUINT8(message);
message = message.slice(g_qtToSplice);
newMessage.TM = decodeQUINT32(message);
message = message.slice(g_qtToSplice);
newMessage.SR = decodeQINT32(message);
message = message.slice(g_qtToSplice);
newMessage.DT = decodeQDOUBLE(message);
message = message.slice(g_qtToSplice);
newMessage.DF = decodeQUINT32(message);
message = message.slice(g_qtToSplice);
newMessage.MO = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.Msg = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.LC = decodeQUINT8(message);
message = message.slice(g_qtToSplice);
newMessage.OA = decodeQUINT8(message);
message = message.slice(g_qtToSplice);
newMessage.OF = g_instances[instanceId].status.Frequency;
newMessage.OC = g_instances[instanceId].status.DEcall;
newMessage.OG = g_instances[instanceId].status.DEgrid;
newMessage.OM = g_instances[instanceId].status.MO;
newMessage.OB = g_instances[instanceId].status.Band;
}
if (newMessage.type == 3) {
newMessage.event = "Clear";
}
if (newMessage.type == 5) {
newMessage.event = "QSO Logged";
newMessage.DateOff = decodeQUINT64(message);
message = message.slice(g_qtToSplice);
newMessage.TimeOff = decodeQUINT32(message);
message = message.slice(g_qtToSplice);
newMessage.timespecOff = decodeQUINT8(message);
message = message.slice(g_qtToSplice);
if (newMessage.timespecOff == 2) {
newMessage.offsetOff = decodeQINT32(message);
message = message.slice(g_qtToSplice);
}
newMessage.DXCall = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.DXGrid = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.Frequency = decodeQUINT64(message);
message = message.slice(g_qtToSplice);
newMessage.MO = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.ReportSend = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.ReportRecieved = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.TXPower = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.Comments = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.Name = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.DateOn = decodeQUINT64(message);
message = message.slice(g_qtToSplice);
newMessage.TimeOn = decodeQUINT32(message);
message = message.slice(g_qtToSplice);
newMessage.timespecOn = decodeQUINT8(message);
message = message.slice(g_qtToSplice);
if (newMessage.timespecOn == 2) {
newMessage.offsetOn = decodeQINT32(message);
message = message.slice(g_qtToSplice);
}
if (message.length > 0) {
newMessage.Operatorcall = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
} else newMessage.Operatorcall = "";
if (message.length > 0) {
newMessage.Mycall = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
} else newMessage.Mycall = "";
if (message.length > 0) {
newMessage.Mygrid = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
} else newMessage.Mygrid = "";
if (message.length > 0) {
newMessage.ExchangeSent = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
} else newMessage.ExchangeSent = "";
if (message.length > 0) {
newMessage.ExchangeReceived = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
} else newMessage.ExchangeReceived = "";
}
if (newMessage.type == 6) {
newMessage.event = "Close";
}
if (newMessage.type == 10) {
newMessage.event = "WSPRDecode";
newMessage.NW = decodeQUINT8(message);
message = message.slice(g_qtToSplice);
newMessage.TM = decodeQUINT32(message);
message = message.slice(g_qtToSplice);
newMessage.SR = decodeQINT32(message);
message = message.slice(g_qtToSplice);
newMessage.DT = decodeQDOUBLE(message);
message = message.slice(g_qtToSplice);
newMessage.Frequency = decodeQUINT64(message);
message = message.slice(g_qtToSplice);
newMessage.Drift = decodeQINT32(message);
message = message.slice(g_qtToSplice);
newMessage.Callsign = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.Grid = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
newMessage.Power = decodeQINT32(message);
message = message.slice(g_qtToSplice);
newMessage.OA = decodeQUINT8(message);
message = message.slice(g_qtToSplice);
newMessage.OF = g_instances[instanceId].status.Frequency;
newMessage.OC = g_instances[instanceId].status.DEcall;
newMessage.OG = g_instances[instanceId].status.DEgrid;
newMessage.OM = g_instances[instanceId].status.MO;
newMessage.OB = g_instances[instanceId].status.Band;
}
if (newMessage.type == 12) {
newMessage.event = "ADIF";
newMessage.ADIF = decodeQUTF8(message);
message = message.slice(g_qtToSplice);
}
if (newMessage.type in g_wsjtHandlers) {
newMessage.remote = remote;
newMessage.instance = instanceId;
lastMsgTimeDiv.innerHTML = "Received from " + newMessage.Id;
g_wsjtHandlers[newMessage.type](newMessage);
g_lastTimeSinceMessageInSeconds = parseInt(Date.now() / 1000);
}
}
}
});
g_wsjtUdpServer.bind(port);
g_wsjtCurrentPort = port;
g_wsjtCurrentIP = g_appSettings.wsjtIP;
}
function loadLookupDetails() {
lookupService.value = g_appSettings.lookupService;
if (lookupService.value == "QRZ") {
lookupLogin.value = g_appSettings.lookupLoginQrz;
lookupPassword.value = g_appSettings.lookupPasswordQrz;
}
if (lookupService.value == "QRZCQ") {
lookupLogin.value = g_appSettings.lookupLoginCq;
lookupPassword.value = g_appSettings.lookupPasswordCq;
}
if (lookupService.value == "HAMQTH") {
lookupLogin.value = g_appSettings.lookupLoginQth;
lookupPassword.value = g_appSettings.lookupPasswordQth;
}
ValidateText(lookupLogin);
ValidateText(lookupPassword);
if (lookupService.value == "CALLOOK")
lookupCredentials.style.display = "none";
else lookupCredentials.style.display = "block";
}
function lookupValueChanged(what) {
if (g_appSettings.lookupService != lookupService.value) {
g_lastLookupCallsign = "";
if (lookupService.value == "QRZ") {
lookupLogin.value = g_appSettings.lookupLoginQrz;
lookupPassword.value = g_appSettings.lookupPasswordQrz;
}
if (lookupService.value == "QRZCQ") {
lookupLogin.value = g_appSettings.lookupLoginCq;
lookupPassword.value = g_appSettings.lookupPasswordCq;
}
if (lookupService.value == "HAMQTH") {
lookupLogin.value = g_appSettings.lookupLoginQth;
lookupPassword.value = g_appSettings.lookupPasswordQth;
}
}
g_appSettings.lookupService = lookupService.value;
lookupQrzTestResult.innerHTML = "";
g_qrzLookupSessionId = null;
if (lookupService.value == "CALLOOK")
lookupCredentials.style.display = "none";
else lookupCredentials.style.display = "block";
if (ValidateText(lookupLogin) && ValidateText(lookupPassword)) {
if (lookupService.value == "QRZ") {
g_appSettings.lookupLoginQrz = lookupLogin.value;
g_appSettings.lookupPasswordQrz = lookupPassword.value;
}
if (lookupService.value == "QRZCQ") {
g_appSettings.lookupLoginCq = lookupLogin.value;
g_appSettings.lookupPasswordCq = lookupPassword.value;
}
if (lookupService.value == "HAMQTH") {
g_appSettings.lookupLoginQth = lookupLogin.value;
g_appSettings.lookupPasswordQth = lookupPassword.value;
}
}
}
var g_lastLookupCallsign = "";
var g_lookupTimeout = null;
function lookupCallsign(callsign, gridPass, useCache = true) {
if (g_mapSettings.offlineMode == true && useCache == false) return;
g_lastLookupCallsign = callsign;
if (g_lookupWindowHandle) {
g_lookupWindowHandle.window.lookupCallsignInput.value = callsign;
lookupValidateCallByElement("lookupCallsignInput");
}
if (g_lookupTimeout != null) {
window.clearTimeout(g_lookupTimeout);
g_lookupTimeout = null;
}
g_lookupTimeout = setTimeout(searchLogForCallsign, 500, callsign);
if (useCache)
getLookupCachedObject(
callsign,
gridPass,
cacheLookupObject,
continueWithLookup
);
else continueWithLookup(callsign, gridPass);
}
function continueWithLookup(callsign, gridPass) {
setLookupDiv(
"lookupInfoDiv",
"Looking up <font color='cyan'>" + callsign + "</font>, please wait..."
);
if (g_appSettings.lookupService != "CALLOOK") {
g_qrzLookupCallsign = callsign;
g_qrzLookupGrid = gridPass;
if (
g_qrzLookupSessionId == null ||
timeNowSec() - g_sinceLastLookup > 3600
) {
g_qrzLookupSessionId = null;
g_sinceLastLookup = timeNowSec();
GetSessionID(null, true);
} else {
g_sinceLastLookup = timeNowSec();
GetLookup(true);
}
} else {
var dxcc = callsignToDxcc(callsign);
var where;
var ccode = 0;
if (dxcc in g_dxccToAltName) {
where = g_dxccToAltName[dxcc];
ccode = g_worldGeoData[g_dxccToGeoData[dxcc]].ccode;
} else where = "Unknown";
if (ccode == 840) {
getBuffer(
"https://callook.info/" + callsign + "/json",
callookResults,
gridPass,
"https",
443,
true
);
} else {
var worker =
"<center>C A L L O O K<br/>NO-NONSENSE AMATEUR RADIO U.S.A. CALLSIGN LOOKUPS<br/>are limited to United States and United States Territories Only<br/>";
worker +=
"<br/>The callsign <font color='orange'>" +
callsign +
"</font> requested is from <font color='yellow'>" +
where +
"</font><br/>";
worker +=
"<br/><br/>You might want to consider using QRZ.com, they have a free membership that provides limited data for most callsigns<br/>";
worker +=
"and they have full details available for paid members<br/></center>";
setLookupDiv("lookupInfoDiv", worker);
}
}
}
function callookResults(buffer, gridPass) {
var results = JSON.parse(buffer);
if (typeof results.status != undefined) {
if (results.status == "VALID") {
var callObject = {};
var dxcc = callsignToDxcc(results.current.callsign);
if (dxcc in g_dxccToAltName) callObject["land"] = g_dxccToAltName[dxcc];
callObject["type"] = results.type;
callObject["call"] = results.current.callsign;
callObject["dxcc"] = dxcc;
callObject["email"] = "";
callObject["class"] = results.current.operClass;
callObject["aliases"] = results.previous.callsign;
callObject["trustee"] =
results.trustee.callsign +
(results.trustee.name.length > 0 ? "; " + results.trustee.name : "");
callObject["name"] = results.name;
callObject["fname"] = "";
callObject["addr1"] = results.address.line1;
callObject["addr2"] = results.address.line2;
callObject["addrAttn"] = results.address.attn;
callObject["lat"] = results.location.latitude;
callObject["lon"] = results.location.longitude;
callObject["grid"] = results.location.gridsquare;
callObject["efdate"] = results.otherInfo.grantDate;
callObject["expdate"] = results.otherInfo.expiryDate;
callObject["frn"] = results.otherInfo.frn;
callObject["bio"] = 0;
callObject["image"] = "";
callObject["country"] = "United States";
if (gridPass) callObject["gtGrid"] = gridPass;
callObject["source"] =
"<tr><td>Source</td><td><font color='orange'><b><div style='cursor:pointer' onClick='window.opener.openSite(\"https://callook.info/" +
results.current.callsign +
"\");'>C A L L O O K</div></b></font></td></tr>";
cacheLookupObject(callObject, gridPass, true);
} else if (results.status == "INVALID") {
setLookupDiv("lookupInfoDiv", "Invalid Lookup");
} else {
setLookupDiv("lookupInfoDiv", "Server is down for maintenance");
}
} else setLookupDiv("lookupInfoDiv", "Unknown Lookup Error");
}
var g_qrzLookupSessionId = null;
var g_qrzLookupCallsign = "";
var g_qrzLookupGrid = "";
var g_sinceLastLookup = 0;
function GetSessionID(resultTd, useCache) {
if (g_mapSettings.offlineMode == true) return;
if (resultTd != null) resultTd.innerHTML = "Testing";
if (g_appSettings.lookupService == "QRZCQ")
getBuffer(
"https://ssl.qrzcq.com/xml?username=" +
g_appSettings.lookupLoginCq +
"&password=" +
encodeURIComponent(g_appSettings.lookupPasswordCq) +
"&agent=GridTracker1.18",
qrzGetSessionCallback,
resultTd,
"https",
443,
useCache
);
else if (g_appSettings.lookupService == "QRZ")
getBuffer(
"https://xmldata.qrz.com/xml/current/?username=" +
g_appSettings.lookupLoginQrz +
";password=" +
encodeURIComponent(g_appSettings.lookupPasswordQrz),
qrzGetSessionCallback,
resultTd,
"https",
443,
useCache
);
else
getBuffer(
"https://www.hamqth.com/xml.php?u=" +
g_appSettings.lookupLoginQth +
"&p=" +
encodeURIComponent(g_appSettings.lookupPasswordQth),
hamQthGetSessionCallback,
resultTd,
"https",
443,
useCache
);
}
function hamQthGetSessionCallback(buffer, resultTd) {
var oParser = new DOMParser();
var oDOM = oParser.parseFromString(buffer, "text/xml");
var result = "";
if (oDOM != null) {
var json = XML2jsobj(oDOM.documentElement);
if (json.hasOwnProperty("session")) {
if (json.session.hasOwnProperty("session_id")) {
result = "<font color='green'>Valid</font>";
g_qrzLookupSessionId = json.session.session_id;
} else {
result = "<font color='red'>" + json.session.error + "</font>";
g_qrzLookupSessionId = null;
}
} else {
result = "<font color='red'>Invalid Response</font>";
g_qrzLookupSessionId = null;
}
} else {
result = "<font color='red'>Unknown Error</font>";
g_qrzLookupSessionId = null;
}
if (resultTd == null) {
// It's a true session Request
SessionResponse(g_qrzLookupSessionId, result);
} else {
g_qrzLookupSessionId = null;
resultTd.innerHTML = result;
}
}
function qrzGetSessionCallback(buffer, resultTd, useCache) {
var oParser = new DOMParser();
var oDOM = oParser.parseFromString(buffer, "text/xml");
var result = "";
if (oDOM != null) {
var json = XML2jsobj(oDOM.documentElement);
if (json.hasOwnProperty("Session")) {
if (json.Session.hasOwnProperty("Key")) {
result = "<font color='green'>Valid</font>";
g_qrzLookupSessionId = json.Session.Key;
} else {
result = "<font color='red'>" + json.Session.Error + "</font>";
g_qrzLookupSessionId = null;
}
} else {
result = "<font color='red'>Invalid Response</font>";
g_qrzLookupSessionId = null;
}
} else {
result = "<font color='red'>Unknown Error</font>";
g_qrzLookupSessionId = null;
}
if (resultTd == null) {
// It's a true session Request
SessionResponse(g_qrzLookupSessionId, result, useCache);
} else resultTd.innerHTML = result;
}
function SessionResponse(newKey, result, useCache) {
// for QRZCQ.com as well
if (newKey == null) {
setLookupDiv("lookupInfoDiv", result, useCache);
} else {
GetLookup(useCache);
}
}
function GetLookup(useCache) {
if (g_appSettings.lookupService == "QRZCQ")
getBuffer(
"https://ssl.qrzcq.com/xml?s=" +
g_qrzLookupSessionId +
"&callsign=" +
g_qrzLookupCallsign +
"&agent=GridTracker",
qrzLookupResults,
g_qrzLookupGrid,
"https",
443,
useCache
);
else if (g_appSettings.lookupService == "QRZ")
getBuffer(
"http://xmldata.qrz.com/xml/current/?s=" +
g_qrzLookupSessionId +
";callsign=" +
g_qrzLookupCallsign,
qrzLookupResults,
g_qrzLookupGrid,
"http",
80,
useCache
);
else
getBuffer(
"https://www.hamqth.com/xml.php?id=" +
g_qrzLookupSessionId +
"&callsign=" +
g_qrzLookupCallsign +
"&prg=GridTracker",
qthHamLookupResults,
g_qrzLookupGrid,
"https",
443,
useCache
);
}
function qthHamLookupResults(buffer, gridPass, useCache) {
var oParser = new DOMParser();
var oDOM = oParser.parseFromString(buffer, "text/xml");
var result = "";
if (oDOM != null) {
var json = XML2jsobj(oDOM.documentElement);
if (json.hasOwnProperty("search")) {
if (gridPass) json.search.gtGrid = gridPass;
json.search.source =
"<tr><td>Source</td><td><font color='orange'><b><div style='cursor:pointer' onClick='window.opener.openSite(\"https://www.hamqth.com/" +
json.search.callsign.toUpperCase() +
"\");'>HamQTH</div></b></font></td></tr>";
cacheLookupObject(json.search, gridPass, true);
} else {
g_qrzLookupSessionId = null;
setLookupDiv(
"lookupInfoDiv",
"<br/><b>No result for callsign</b><br/><br/>"
);
}
} else {
setLookupDiv("lookupInfoDiv", buffer);
g_qrzLookupSessionId = null;
}
}
function qrzLookupResults(buffer, gridPass, useCache) {
var oParser = new DOMParser();
var oDOM = oParser.parseFromString(buffer, "text/xml");
var result = "";
if (oDOM != null) {
var json = XML2jsobj(oDOM.documentElement);
if (json.hasOwnProperty("Callsign")) {
var call = "";
if (json.Callsign.hasOwnProperty("callsign")) {
json.Callsign.call = lookup.callsign;
delete json.Callsign.callsign;
}
if (json.Callsign.hasOwnProperty("call")) call = json.Callsign.call;
if (g_appSettings.lookupService == "QRZ")
json.Callsign.source =
"<tr><td>Source</td><td><font color='orange'><b><div style='cursor:pointer' onClick='window.opener.openSite(\"https://www.qrz.com/lookup?callsign=" +
call +
"\");'>QRZ.com</div></b></font></td></tr>";
else
json.Callsign.source =
"<tr><td>Source</td><td><font color='orange'><b><div style='cursor:pointer' onClick='window.opener.openSite(\"https://www.qrzcq.com/call/" +
call +
"\");'>QRZCQ.com</div></b></font></td></tr>";
if (gridPass) json.Callsign.gtGrid = gridPass;
cacheLookupObject(json.Callsign, gridPass, true);
} else {
setLookupDiv(
"lookupInfoDiv",
"<br/><b>No result for callsign</b><br/><br/>"
);
g_qrzLookupSessionId = null;
}
} else {
setLookupDiv("lookupInfoDiv", buffer);
g_qrzLookupSessionId = null;
}
}
var g_lastLookupAddress = null;
var g_Idb = null;
var g_Irequest = null;
function initialDatabases() {
g_Irequest = window.indexedDB.open("GridTracker", 1);
g_Irequest.onerror = function (event) {
alert(
"Database error: " +
event.target.errorCode +
" : GridTracker will have issues"
);
};
g_Irequest.onsuccess = function (event) {
g_Idb = g_Irequest.result;
if (!g_Idb.objectStoreNames.contains("lookups")) {
g_Idb.createObjectStore("lookups", { keyPath: "call" });
}
init();
};
g_Irequest.onupgradeneeded = function (event) {
g_Idb = g_Irequest.result;
if (!g_Idb.objectStoreNames.contains("lookups")) {
g_Idb.createObjectStore("lookups", { keyPath: "call" });
}
init();
};
}
function addLookupObjectToIndexedDB(lookupObject) {
var request = g_Idb
.transaction(["lookups"], "readwrite")
.objectStore("lookups")
.put(lookupObject);
request.onerror = function (event) {
addLastTraffic("<font style='color:orange'>Lookup Write Issue</font>");
};
}
function getLookupCachedObject(
call,
gridPass,
resultFunction = null,
noResultFunction = null,
callObject = null
) {
var request = g_Idb
.transaction(["lookups"], "readwrite")
.objectStore("lookups")
.get(call);
request.onsuccess = function (event) {
if (
request.result &&
parseInt(request.result.cached) + 604800 > timeNowSec()
) {
// 7 days, should an option Tag! I know right?!
delete request.result;
request.result = null;
g_Idb
.transaction(["lookups"], "readwrite")
.objectStore("lookups")
.delete(call);
}
if (callObject != null) {
if (request.result != null) {
callObject.cnty = request.result.cnty;
if (callObject.cnty in g_countyData) callObject.qual = true;
else {
callObject.cnty = null;
callObject.qual = false;
}
}
return;
}
if (request.result != null && resultFunction)
resultFunction(request.result, gridPass, false);
else if (noResultFunction) noResultFunction(call, gridPass);
};
request.onerror = function (event) {
if (noResultFunction) noResultFunction(call, gridPass);
};
}
function cacheLookupObject(lookup, gridPass, cacheable = false) {
if (!("cnty" in lookup)) lookup.cnty = null;
if (lookup.hasOwnProperty("callsign")) {
lookup.call = lookup.callsign;
delete lookup.callsign;
}
lookup.call = lookup.call.toUpperCase();
if (lookup.hasOwnProperty("latitude")) {
lookup.lat = lookup.latitude;
delete lookup.latitude;
}
if (lookup.hasOwnProperty("longitude")) {
lookup.lon = lookup.longitude;
delete lookup.longitude;
}
if (lookup.hasOwnProperty("locator")) {
lookup.grid = lookup.locator;
delete lookup.locator;
}
if (lookup.hasOwnProperty("website")) {
lookup.url = lookup.website;
delete lookup.website;
}
if (lookup.hasOwnProperty("web")) {
lookup.url = lookup.web;
delete lookup.web;
}
if (lookup.hasOwnProperty("qslpic")) {
lookup.image = lookup.qslpic;
delete lookup.qslpic;
}
if (lookup.hasOwnProperty("picture")) {
lookup.image = lookup.picture;
delete lookup.picture;
}
if (lookup.hasOwnProperty("address")) {
lookup.addr1 = lookup.address;
delete lookup.address;
}
if (lookup.hasOwnProperty("adr_city")) {
lookup.addr2 = lookup.adr_city;
delete lookup.adr_city;
}
if (lookup.hasOwnProperty("city")) {
lookup.addr2 = lookup.city;
delete lookup.city;
}
if (lookup.hasOwnProperty("itu")) {
lookup.ituzone = lookup.itu;
delete lookup.itu;
}
if (lookup.hasOwnProperty("cq")) {
lookup.cqzone = lookup.cq;
delete lookup.cq;
}
if (lookup.hasOwnProperty("adif")) {
lookup.dxcc = lookup.adif;
delete lookup.adif;
}
if (!lookup.hasOwnProperty("dxcc")) {
lookup.dxcc = callsignToDxcc(lookup.call.toUpperCase());
}
if (lookup.hasOwnProperty("adr_name")) {
lookup.name = lookup.adr_name;
delete lookup.adr_name;
}
if (lookup.hasOwnProperty("adr_street1")) {
lookup.addr1 = lookup.adr_street1;
delete lookup.adr_street1;
}
if (lookup.hasOwnProperty("us_state")) {
lookup.state = lookup.us_state;
delete lookup.us_state;
}
if (lookup.hasOwnProperty("oblast")) {
lookup.state = lookup.oblast;
delete lookup.oblast;
}
if (lookup.hasOwnProperty("district")) {
lookup.state = lookup.district;
delete lookup.district;
}
if (lookup.hasOwnProperty("adr_zip")) {
lookup.zip = lookup.adr_zip;
delete lookup.adr_zip;
}
if (lookup.hasOwnProperty("adr_country")) {
lookup.country = lookup.adr_country;
delete lookup.adr_country;
}
if (lookup.hasOwnProperty("us_county")) {
lookup.county = lookup.us_county;
delete lookup.us_county;
}
if (lookup.hasOwnProperty("qsldirect")) {
lookup.mqsl = lookup.qsldirect;
delete lookup.qsldirect;
}
if (lookup.hasOwnProperty("qsl")) {
lookup.bqsl = lookup.qsl;
delete lookup.qsl;
}
if (lookup.hasOwnProperty("utc_offset")) {
lookup.GMTOffset = lookup.utc_offset;
delete lookup.utc_offset;
}
if (lookup.hasOwnProperty("land")) {
lookup.country = lookup.land;
delete lookup.land;
}
if ("grid" in lookup) lookup.grid = lookup.grid.toUpperCase();
if (lookup.hasOwnProperty("state") && lookup.hasOwnProperty("county")) {
var foundCounty = false;
if (lookup.cnty == null) {
lookup.county = lookup.state + ", " + lookup.county;
lookup.cnty = lookup.county.toUpperCase().replaceAll(" ", "");
}
if (lookup.cnty in g_countyData) {
for (var hash in g_liveCallsigns) {
if (
g_liveCallsigns[hash].DEcall == lookup.call &&
g_liveCallsigns[hash].state == "US-" + lookup.state
) {
g_liveCallsigns[hash].cnty = lookup.cnty;
g_liveCallsigns[hash].qual = true;
foundCounty = true;
}
}
if (foundCounty) {
goProcessRoster();
}
} else {
//console.log( "bad county: " + lookup.cnty);
lookup.cnty = null;
}
}
lookup.name = joinSpaceIf(
getLookProp(lookup, "fname"),
getLookProp(lookup, "name")
);
lookup.fname = "";
if (cacheable) {
lookup.cached = timeNowSec();
addLookupObjectToIndexedDB(lookup);
}
displayLookupObject(lookup, gridPass, cacheable);
}
function displayLookupObject(lookup, gridPass, fromCache = false) {
var worker = "";
var thisCall = getLookProp(lookup, "call").toUpperCase();
worker +=
"<table title='Click to copy address to clipboard' onclick='setClipboardFromLookup();' style='cursor:pointer' >";
worker += "<tr>";
worker += "<td style='font-size:36pt;color:cyan;font-weight:bold'>";
worker += getLookProp(lookup, "call").toUpperCase().formatCallsign();
worker += "</td>";
worker += "<td align='center' style='margin:0;padding:0'>";
if (lookup.dxcc > 0 && lookup.dxcc in g_dxccToGeoData)
worker +=
"<img style='padding-top:4px' src='./img/flags/24/" +
g_worldGeoData[g_dxccToGeoData[lookup.dxcc]].flag +
"'>";
worker += "</td>";
worker += "<td rowspan=6>";
var image = getLookProp(lookup, "image");
if (image.length > 0)
worker +=
"<img style='border:1px solid gray' class='roundBorder' width='220px' src='" +
image +
"'>";
worker += "</td>";
worker += "</tr>";
g_lastLookupAddress = "";
if (getLookProp(lookup, "addrAttn").length > 0) {
worker += "<tr>";
worker += "<td>";
worker += getLookProp(lookup, "addrAttn");
g_lastLookupAddress += getLookProp(lookup, "addrAttn") + "\n";
worker += "</td>";
worker += "</tr>";
}
worker += "<tr>";
worker += "<td>";
worker += "<b>" + getLookProp(lookup, "name") + "</b>";
g_lastLookupAddress += getLookProp(lookup, "name") + "\n";
worker += "</td>";
worker += "</tr>";
worker += "<tr>";
worker += "<td>";
worker += getLookProp(lookup, "addr1");
g_lastLookupAddress += getLookProp(lookup, "addr1") + "\n";
worker += "</td>";
worker += "</tr>";
worker += "<tr>";
worker += "<td>";
worker += joinCommaIf(
getLookProp(lookup, "addr2"),
joinSpaceIf(getLookProp(lookup, "state"), getLookProp(lookup, "zip"))
);
g_lastLookupAddress +=
joinCommaIf(
getLookProp(lookup, "addr2"),
joinSpaceIf(getLookProp(lookup, "state"), getLookProp(lookup, "zip"))
) + "\n";
worker += "</td>";
worker += "</tr>";
worker += "<tr>";
worker += "<td>";
var country = getLookProp(lookup, "country");
worker += country;
g_lastLookupAddress += country + "\n";
worker += "</td>";
worker += "</tr>";
worker += "<tr>";
worker += "<td>";
var email = getLookProp(lookup, "email");
if (email.length > 0) {
worker +=
"<div style='cursor:pointer;font-weight:bold;vertical-align:top' onclick='window.opener.mailThem(\"" +
email +
"\");'>" +
email +
"</div>";
g_lastLookupAddress += email + "\n";
}
worker += "</td>";
worker += "</tr>";
worker += "</table>";
var card =
"<div class='mapItem' id='callCard' style='top:0;padding:4px;'>" +
worker +
"</div>";
worker = "";
worker += "<table align='center' class='bioTable' >";
worker += "<tr><th colspan=2>Details</th></tr>";
if (getLookProp(lookup, "url").length > 0) {
worker += "<tr>";
worker += "<td>Website</td>";
worker += "<td >";
worker +=
"<font color='orange'><b><div style='cursor:pointer' onClick='window.opener.openSite(\"" +
getLookProp(lookup, "url") +
"\");' >Link</div></b></font>";
worker += "</td>";
worker += "</tr>";
}
if (Number(getLookProp(lookup, "bio")) > 0) {
worker += "<tr>";
worker += "<td>Biography</td>";
worker += "<td>";
worker +=
"<font color='orange'><b><div style='cursor:pointer' onClick='window.opener.openSite(\"https://www.qrz.com/db/" +
getLookProp(lookup, "call") +
"\");'>Link</div></b></font>";
worker += "</td>";
worker += "</tr>";
}
worker += makeRow("Type", lookup, "type");
worker += makeRow("Class", lookup, "class");
worker += makeRow("Codes", lookup, "codes");
worker += makeRow("QTH", lookup, "qth");
var dates = joinIfBothWithDash(
getLookProp(lookup, "efdate"),
getLookProp(lookup, "expdate")
);
if (dates.length > 0) {
worker += "<tr><td>Effective Dates</td><td>" + dates + "</td></tr>";
}
var Aliases = joinCommaIf(
getLookProp(lookup, "aliases"),
getLookProp(lookup, "p_call")
);
if (Aliases.length > 0) {
worker +=
"<tr title='" +
Aliases +
"' ><td>Aliases</td><td>" +
Aliases +
"</td></tr>";
}
worker += makeRow("Polish OT", lookup, "plot");
worker += makeRow("German DOK", lookup, "dok");
worker += makeYesNoRow("DOK is Sonder-DOK", lookup, "sondok");
worker += makeRow("DXCC", lookup, "dxcc");
worker += makeRow("CQ zone", lookup, "cqzone");
worker += makeRow("ITU zone", lookup, "ituzone");
worker += makeRow("IOTA", lookup, "iota");
worker += makeRow("FIPS", lookup, "fips");
worker += makeRow("FRN", lookup, "frn");
worker += makeRow("Timezone", lookup, "TimeZone");
worker += makeRow("GMT Offset", lookup, "GMTOffset");
worker += makeRow("County", lookup, "county");
worker += makeRow("Latitude", lookup, "lat");
worker += makeRow("Longitude", lookup, "lon");
worker += makeRow("Grid", lookup, "grid", true);
if (
getLookProp(lookup, "gtGrid").length > 0 &&
getLookProp(lookup, "gtGrid").toUpperCase() !=
getLookProp(lookup, "grid").toUpperCase()
) {
worker += makeRow("GT Grid", lookup, "gtGrid");
}
worker += makeRow("Born", lookup, "born");
worker += makeYesNoRow("LoTW", lookup, "lotw");
worker += makeYesNoRow("eQSL", lookup, "eqsl");
worker += makeYesNoRow("Bureau QSL", lookup, "bqsl");
worker += makeYesNoRow("Mail Direct QSL", lookup, "mqsl");
worker += makeRow("QSL Via", lookup, "qsl_via");
worker += makeRow("QRZ Admin", lookup, "user");
worker += makeRow("Prefix", lookup, "prefix");
worker += lookup.source;
if (g_callsignLookups.lotwUseEnable == true && thisCall in g_lotwCallsigns) {
lookup["ulotw"] =
"&#10004; (" +
userDayString(g_lotwCallsigns[thisCall] * 86400 * 1000) +
")";
worker += makeRow("LoTW Member", lookup, "ulotw");
}
if (g_callsignLookups.eqslUseEnable == true && thisCall in g_eqslCallsigns) {
lookup["ueqsl"] = "&#10004;";
worker += makeRow("eQSL Member", lookup, "ueqsl");
}
if (g_callsignLookups.oqrsUseEnable == true && thisCall in g_oqrsCallsigns) {
lookup["uoqrs"] = "&#10004;";
worker += makeRow("ClubLog OQRS", lookup, "uoqrs");
}
if (fromCache) {
worker +=
"<tr><td>Cached Record</td><td>" +
userTimeString(lookup["cached"] * 1000) +
"</td></tr>";
}
worker += "</table>";
var details =
"<div class='mapItem' id='callDetails' style='padding:4px;'>" +
worker +
"</div>";
var genMessage =
'<tr><td colspan=2><div title="Clear" class="button" onclick="window.opener.clearLookup();" >Clear</div> <div title="Generate Messages" class="button" onclick="window.opener.setCallAndGrid(\'' +
getLookProp(lookup, "call") +
"','" +
getLookProp(lookup, "grid") +
"');\">Generate Messages</div></td></tr>";
setLookupDiv(
"lookupInfoDiv",
"<table align='center'><tr><td>" +
card +
"</td><td>" +
details +
"</td></tr>" +
genMessage +
"</table>"
);
setLookupDivHeight("lookupBoxDiv", getLookupWindowHeight() + "px");
}
function clearLookup() {
if (g_lookupWindowHandle) {
g_lookupWindowHandle.window.lookupCallsignInput.value = "";
lookupValidateCallByElement("lookupCallsignInput");
setLookupDiv("lookupLocalDiv", "");
setLookupDiv("lookupInfoDiv", "");
setLookupDivHeight("lookupBoxDiv", getLookupWindowHeight() + "px");
}
}
function addTextToClipboard(data) {
navigator.clipboard.writeText(data);
}
function saveToCsv(lookup) {
var name = joinSpaceIf(
getLookProp(lookup, "fname"),
getLookProp(lookup, "name")
);
var addr1 = getLookProp(lookup, "addr1");
var addr2 =
'"' +
joinCommaIf(
getLookProp(lookup, "addr2"),
joinSpaceIf(getLookProp(lookup, "state"), getLookProp(lookup, "zip"))
) +
'"';
var country = getLookProp(lookup, "country");
if (
getLookProp(lookup, "land").length > 0 &&
country != getLookProp(lookup, "land")
)
country = getLookProp(lookup, "land");
if (country == "United States") country = "";
tryToWriteAdifToDocFolder(
"thanks.csv",
name + "," + addr1 + "," + addr2 + "," + country + "\r\n",
true
);
}
function makeYesNoRow(first, object, key) {
var value = getLookProp(object, key);
if (value.length > 0) {
var test = value.toUpperCase();
if (test == "Y") return "<tr><td>" + first + "</td><td>Yes</td></tr>";
if (test == "N") return "<tr><td>" + first + "</td><td>No</td></tr>";
if (test == "?") return "";
return (
"<tr><td>" +
first +
"</td><td>" +
(object[key] == 1 ? "Yes" : "No") +
"</td></tr>"
);
}
return "";
}
function makeRow(first, object, key, clip = false) {
var value = getLookProp(object, key);
if (value.length > 0) {
if (clip) {
return (
"<tr><td>" +
first +
"</td><td title='Copy to clipboard' style='cursor:pointer;color:cyan;font-weight: bold;' onClick='addTextToClipboard(\"" +
object[key].substr(0, 45) +
"\")'>" +
object[key].substr(0, 45) +
"</td></tr>"
);
} else {
return (
"<tr><td>" +
first +
"</td><td>" +
object[key].substr(0, 45) +
"</td></tr>"
);
}
}
return "";
}
function getLookProp(object, key) {
return object.hasOwnProperty(key) ? object[key] : "";
}
function joinSpaceIf(camera1, camera2) {
if (camera1.length > 0 && camera2.length > 0) return camera1 + " " + camera2;
if (camera1.length > 0) return camera1;
if (camera2.length > 0) return camera2;
return "";
}
function joinCommaIf(camera1, camera2) {
if (camera1.length > 0 && camera2.length > 0) {
if (camera1.indexOf(",") > -1) return camera1 + " " + camera2;
else return camera1 + ", " + camera2;
}
if (camera1.length > 0) return camera1;
if (camera2.length > 0) return camera2;
return "";
}
function joinIfBothWithDash(camera1, camera2) {
if (camera1.length > 0 && camera2.length > 0)
return camera1 + " / " + camera2;
return "";
}
function startLookup(call, grid) {
if (call == "-") return;
if (grid == "-") grid = "";
openLookupWindow(true);
lookupCallsign(call, grid);
}
function searchLogForCallsign(call) {
setLookupDiv("lookupLocalDiv", "");
var list = Object.values(g_QSOhash)
.filter(function (value) {
return value.DEcall == call;
})
.sort(myBandCompare);
if (list.length > 0) {
var work = {};
var conf = {};
var lastTime = 0;
var lastRow = null;
var dxcc = list[0].dxcc;
for (row in list) {
var what = list[row].band + "," + list[row].mode;
if (list[row].time > lastTime) {
lastRow = row;
lastTime = list[row].time;
}
if (list[row].confirmed) {
conf[what] = g_pskColors[list[row].band];
if (what in work) delete work[what];
} else if (!(what in conf)) work[what] = g_pskColors[list[row].band];
}
var worker =
"<div class='mapItemNoSize'><table align='center' class='darkTable'>";
if (Object.keys(work).length > 0) {
worker += "<tr><th style='color:yellow'>Worked</th><td>";
var k = Object.keys(work).sort();
for (var key in k) {
worker += "<font color='#" + work[k[key]] + "'>" + k[key] + " </font>";
}
worker += "</td></tr>";
}
if (Object.keys(conf).length > 0) {
worker += "<tr><th style='color:lightgreen'>Confirmed</th><td>";
var k = Object.keys(conf).sort();
for (var key in k) {
worker += "<font color='#" + conf[k[key]] + "'>" + k[key] + " </font>";
}
worker += "</td></tr>";
}
if (lastRow) {
worker += "<tr><th style='color:cyan'>Last QSO</th><td>";
worker +=
"<font color='#" +
g_pskColors[list[lastRow].band] +
"'>" +
list[lastRow].band +
"," +
list[lastRow].mode +
" </font> " +
userTimeString(list[lastRow].time * 1000);
worker += "</td></tr>";
}
worker +=
"<tr><th style='color:orange'>" +
g_dxccToAltName[dxcc] +
" (" +
g_worldGeoData[g_dxccToGeoData[dxcc]].pp +
")</th><td>";
for (var band in g_colorBands) {
if (String(dxcc) + g_colorBands[band] in g_tracker.worked.dxcc) {
var strike = "";
if (String(dxcc) + g_colorBands[band] in g_tracker.confirmed.dxcc)
strike = "text-decoration: underline overline;";
worker +=
"<div style='" +
strike +
"display:inline-block;color:#" +
g_pskColors[g_colorBands[band]] +
"'>" +
g_colorBands[band] +
"</div>&nbsp;";
}
}
worker += "</td></tr></table></div>";
setLookupDiv("lookupLocalDiv", worker);
}
delete list;
list = null;
}
function startGenMessages(call, grid, instance = null) {
if (call == "-") return;
if (grid == "-") grid = "";
setCallAndGrid(call, grid, instance);
}
function is_dir(path) {
try {
var stat = fs.lstatSync(path);
return stat.isDirectory();
} catch (e) {
// lstatSync throws an error if path doesn't exist
return false;
}
}
function mediaCheck() {
if (g_platform == "windows") {
var process = require("process");
g_appData = process.env.USERPROFILE + "\\Dokumente";
if (!is_dir(g_appData)) {
g_appData = process.env.USERPROFILE + "\\Documents";
if (!is_dir(g_appData)) {
if (g_appSettings.savedAppData != null) {
g_appData = g_appSettings.savedAppData;
if (!is_dir(g_appData)) return false;
} else return false;
}
}
g_appData += "\\GridTracker";
g_mediaDir = g_appData + "\\media";
g_jsonDir = g_appData + "\\data";
g_NWappData = nw.App.dataPath + "\\Ginternal";
g_screenshotDir = g_appData + "\\screenshots";
g_scriptDir = g_appData + "\\scripts";
try {
if (!fs.existsSync(g_appData)) {
fs.mkdirSync(g_appData);
}
if (!fs.existsSync(g_NWappData)) {
fs.mkdirSync(g_NWappData);
}
if (!fs.existsSync(g_screenshotDir)) {
fs.mkdirSync(g_screenshotDir);
}
if (!fs.existsSync(g_scriptDir)) {
fs.mkdirSync(g_scriptDir);
}
g_jsonDir += g_dirSeperator;
g_NWappData += g_dirSeperator;
g_screenshotDir += g_dirSeperator;
g_scriptDir += g_dirSeperator;
if (!fs.existsSync(g_mediaDir + g_dirSeperator + "long-strike.mp3")) {
if (!fs.existsSync(g_mediaDir)) fs.mkdirSync(g_mediaDir);
var sourceMediaDir = ".\\media";
if (fs.existsSync(sourceMediaDir)) {
var filesToMove = fs.readdirSync(sourceMediaDir);
for (var key in filesToMove) {
var source = sourceMediaDir + g_dirSeperator + filesToMove[key];
var target = g_mediaDir + g_dirSeperator + filesToMove[key];
fs.copyFileSync(
sourceMediaDir + g_dirSeperator + filesToMove[key],
g_mediaDir + "\\" + filesToMove[key]
);
}
}
}
} catch (e) {
alert(
"Unable to create or access " +
g_appData +
" folder.\r\nPermission violation, GT cannot continue"
);
nw.App.quit();
}
g_qsoLogFile = g_appData + "\\GridTracker_QSO.adif";
}
if (g_platform == "mac" || g_platform == "linux") {
var process = require("process");
g_appData = process.env.HOME + "/Dokumente";
if (!is_dir(g_appData)) {
g_appData = process.env.HOME + "/Documents";
if (!is_dir(g_appData)) {
if (g_appSettings.savedAppData != null) {
g_appData = g_appSettings.savedAppData;
if (!is_dir(g_appData)) return false;
} else return false;
}
}
g_appData += "/GridTracker";
var mediaDir = g_appData + "/media";
g_jsonDir = g_appData + "/data";
g_NWappData = nw.App.dataPath + "/Ginternal";
g_screenshotDir = g_appData + "/screenshots";
g_scriptDir = g_appData + "/scripts";
try {
if (!fs.existsSync(g_appData)) {
fs.mkdirSync(g_appData);
}
if (!fs.existsSync(g_NWappData)) {
fs.mkdirSync(g_NWappData);
}
if (!fs.existsSync(g_screenshotDir)) {
fs.mkdirSync(g_screenshotDir);
}
if (!fs.existsSync(g_scriptDir)) {
fs.mkdirSync(g_scriptDir);
}
if (!fs.existsSync(mediaDir + g_dirSeperator + "long-strike.mp3")) {
if (!fs.existsSync(mediaDir)) fs.mkdirSync(mediaDir);
var sourceMediaDir = "./media";
if (fs.existsSync(sourceMediaDir)) {
var filesToMove = fs.readdirSync(sourceMediaDir);
for (var key in filesToMove) {
var source = sourceMediaDir + g_dirSeperator + filesToMove[key];
var target = mediaDir + g_dirSeperator + filesToMove[key];
fs.copyFileSync(
sourceMediaDir + g_dirSeperator + filesToMove[key],
mediaDir + g_dirSeperator + filesToMove[key]
);
}
}
}
} catch (e) {
alert(
"Unable to create or access " +
g_appData +
" folder.\r\nPermission violation, GT cannot continue"
);
nw.App.quit();
}
g_jsonDir += g_dirSeperator;
g_NWappData += g_dirSeperator;
g_screenshotDir += g_dirSeperator;
g_scriptDir += g_dirSeperator;
g_mediaDir = mediaDir;
g_qsoLogFile = g_appData + g_dirSeperator + "GridTracker_QSO.adif";
}
logEventMedia.appendChild(newOption("none", "None"));
msgAlertMedia.appendChild(newOption("none", "Select File"));
alertMediaSelect.appendChild(newOption("none", "Select File"));
huntCallsignNotifyMedia.appendChild(newOption("none", "Select File"));
huntGridNotifyMedia.appendChild(newOption("none", "Select File"));
huntDXCCNotifyMedia.appendChild(newOption("none", "Select File"));
huntCQzNotifyMedia.appendChild(newOption("none", "Select File"));
huntITUzNotifyMedia.appendChild(newOption("none", "Select File"));
huntStatesNotifyMedia.appendChild(newOption("none", "Select File"));
huntRosterNotifyMedia.appendChild(newOption("none", "Select File"));
var mediaFiles = fs.readdirSync(g_mediaDir);
var path = g_mediaDir + g_dirSeperator;
for (var key in mediaFiles) {
var path = g_mediaDir + g_dirSeperator + mediaFiles[key];
logEventMedia.appendChild(newOption(mediaFiles[key], mediaFiles[key]));
alertMediaSelect.appendChild(newOption(path, mediaFiles[key]));
huntCallsignNotifyMedia.appendChild(newOption(path, mediaFiles[key]));
huntGridNotifyMedia.appendChild(newOption(path, mediaFiles[key]));
huntDXCCNotifyMedia.appendChild(newOption(path, mediaFiles[key]));
huntCQzNotifyMedia.appendChild(newOption(path, mediaFiles[key]));
huntITUzNotifyMedia.appendChild(newOption(path, mediaFiles[key]));
huntStatesNotifyMedia.appendChild(newOption(path, mediaFiles[key]));
huntRosterNotifyMedia.appendChild(newOption(path, mediaFiles[key]));
msgAlertMedia.appendChild(newOption(path, mediaFiles[key]));
}
var modeData = fs.readFileSync("./data/modes.json");
g_modes = JSON.parse(modeData);
for (var key in g_modes) {
gtModeFilter.appendChild(newOption(key));
}
modeData = fs.readFileSync("./data/modes-phone.json");
g_modes_phone = JSON.parse(modeData);
initQSOdata();
g_QSOhash = {};
g_QSLcount = 0;
g_QSOcount = 0;
// Old log filename, no longer referenced
tryToDeleteLog("lotw.adif");
try {
if (fs.existsSync(g_NWappData + "internal_qso.json")) {
var data = JSON.parse(fs.readFileSync(g_NWappData + "internal_qso.json"));
if (typeof data.version != "undefined" && data.version == gtVersion) {
g_tracker = data.tracker;
if (typeof g_tracker.worked.px == "undefined") {
g_tracker.worked.px = {};
g_tracker.confirmed.px = {};
}
g_QSOhash = data.g_QSOhash;
for (var i in g_QSOhash) {
if (
typeof g_QSOhash[i].px == "undefined" ||
g_QSOhash[i].px == null
) {
if (g_QSOhash[i].dxcc != -1)
g_QSOhash[i].px = getWpx(g_QSOhash[i].DEcall);
else g_QSOhash[i].px = null;
}
g_QSOcount++;
if (g_QSOhash[i].confirmed) g_QSLcount++;
}
} else {
clearLogFilesAndCounts();
}
delete data;
fs.unlinkSync(g_NWappData + "internal_qso.json");
}
loadReceptionReports();
} catch (e) {}
return true;
}
function newOption(value, text) {
if (typeof text == "undefined") text = value;
var option = document.createElement("option");
option.value = value;
option.text = text;
return option;
}
var g_rosterSpot = false;
function setRosterSpot(enabled) {
g_rosterSpot = enabled;
}
function saveReceptionReports() {
try {
fs.writeFileSync(
g_NWappData + "spots.json",
JSON.stringify(g_receptionReports)
);
} catch (e) {}
}
function loadReceptionReports() {
try {
var clear = true;
if (fs.existsSync(g_NWappData + "spots.json")) {
g_receptionReports = JSON.parse(
fs.readFileSync(g_NWappData + "spots.json")
);
if (timeNowSec() - g_receptionReports.lastDownloadTimeSec <= 86400)
clear = false;
}
if (clear == true) {
g_receptionReports = {
lastDownloadTimeSec: 0,
lastSequenceNumber: "0",
spots: {},
};
}
} catch (e) {
g_receptionReports = {
lastDownloadTimeSec: 0,
lastSequenceNumber: "0",
spots: {},
};
}
}
function pskSpotCheck(timeSec) {
if (g_mapSettings.offlineMode == true) return;
if (myDEcall == null || myDEcall == "NOCALL" || myDEcall == "") return;
if (
timeSec - g_receptionReports.lastDownloadTimeSec > 120 &&
(g_spotsEnabled == 1 || g_rosterSpot)
) {
g_receptionReports.lastDownloadTimeSec = timeSec;
localStorage.receptionSettings = JSON.stringify(g_receptionSettings);
spotRefreshDiv.innerHTML = "..refreshing..";
getBuffer(
"https://retrieve.pskreporter.info/query?rronly=1&lastseqno=" +
g_receptionReports.lastSequenceNumber +
"&senderCallsign=" +
encodeURIComponent(myRawCall) +
"&appcontact=" +
encodeURIComponent("contact@gridtracker.org"),
pskSpotResults,
null,
"https",
443
);
} else if (g_spotsEnabled == 1) {
spotRefreshDiv.innerHTML =
"Refresh: " +
Number(120 - (timeSec - g_receptionReports.lastDownloadTimeSec)).toDHMS();
}
}
function pskSpotResults(buffer, flag) {
var oParser = new DOMParser();
var oDOM = oParser.parseFromString(buffer, "text/xml");
var result = "";
if (oDOM != null) {
var json = XML2jsobj(oDOM.documentElement);
if (typeof json.lastSequenceNumber != "undefined") {
g_receptionReports.lastSequenceNumber = json.lastSequenceNumber.value;
if (typeof json.receptionReport != "undefined") {
for (var key in json.receptionReport) {
if (
typeof json.receptionReport[key].frequency != "undefined" &&
typeof json.receptionReport[key].sNR != "undefined"
) {
var report;
var call = json.receptionReport[key].receiverCallsign;
var mode = json.receptionReport[key].mode;
var grid = json.receptionReport[key].receiverLocator.substr(0, 6);
var band = Number(
parseInt(json.receptionReport[key].frequency) / 1000000
).formatBand();
var hash = call + mode + band + grid.substr(0, 4);
if (hash in g_receptionReports.spots) {
report = g_receptionReports.spots[hash];
if (
parseInt(json.receptionReport[key].flowStartSeconds) <
report.when
)
continue;
} else {
report = g_receptionReports.spots[hash] = {};
report.call = call;
report.band = band;
report.grid = grid.toUpperCase();
report.mode = mode;
}
if (
typeof json.receptionReport[key].receiverCallsign != "undefined"
)
report.dxcc = callsignToDxcc(
json.receptionReport[key].receiverCallsign
);
else report.dxcc = -1;
report.when = parseInt(json.receptionReport[key].flowStartSeconds);
report.snr = json.receptionReport[key].sNR;
report.freq = parseInt(json.receptionReport[key].frequency);
var SNR = parseInt((parseInt(report.snr) + 25) * 9);
if (SNR > 255) SNR = 255;
if (SNR < 0) SNR = 0;
report.color = SNR;
}
}
}
}
}
g_receptionReports.lastDownloadTimeSec = timeNowSec();
localStorage.receptionSettings = JSON.stringify(g_receptionSettings);
redrawSpots();
if (g_rosterSpot) goProcessRoster();
}
var g_oamsSpotTimeout = null;
function addNewOAMSSpot(cid, db) {
if (cid in g_gtFlagPins) {
if (g_oamsSpotTimeout !== null) {
clearTimeout(g_oamsSpotTimeout);
g_oamsSpotTimeout = null;
}
var report;
var call = g_gtFlagPins[cid].call;
var mode = g_gtFlagPins[cid].mode;
var grid = g_gtFlagPins[cid].grid.substr(0, 6);
var band = g_gtFlagPins[cid].band;
var hash = call + mode + band + grid.substr(0, 4);
if (hash in g_receptionReports.spots) {
report = g_receptionReports.spots[hash];
} else {
report = g_receptionReports.spots[hash] = {};
report.call = call;
report.band = band;
report.grid = grid;
report.mode = mode;
}
report.dxcc = g_gtFlagPins[cid].dxcc;
report.when = timeNowSec();
report.snr = Number(db);
report.freq = g_gtFlagPins[cid].freq;
var SNR = parseInt((parseInt(report.snr) + 25) * 9);
if (SNR > 255) SNR = 255;
if (SNR < 0) SNR = 0;
report.color = SNR;
g_oamsSpotTimeout = setTimeout(redrawSpots, 500);
}
}
function spotFeature(center) {
return new ol.Feature(
ol.geom.Polygon.circular(center, 30000, 63).transform(
"EPSG:4326",
"EPSG:3857"
)
);
}
var g_spotTotalCount = 0;
function createSpot(report, key, fromPoint, addToLayer = true) {
var LL = squareToLatLongAll(report.grid);
var Lat = LL.la2 - (LL.la2 - LL.la1) / 2;
var Lon = LL.lo2 - (LL.lo2 - LL.lo1) / 2;
var spot = spotFeature([Lon, Lat]);
var colorNoAlpha = "#" + g_bandToColor[report.band];
var colorAlpha = intAlphaToRGB(colorNoAlpha, report.color);
var spotColor = colorAlpha;
var workingColor =
g_mapSettings.nightMapEnable && g_nightTime
? g_receptionSettings.pathNightColor
: g_receptionSettings.pathColor;
if (workingColor != -1) {
var testColor =
workingColor < 1
? "#0000000"
: workingColor == 361
? "#FFFFFF"
: "hsla(" + workingColor + ", 100%, 50%," + report.color / 255 + ")";
if (workingColor < 1 || workingColor == 361)
spotColor = intAlphaToRGB(testColor.substr(0, 7), report.color);
else spotColor = testColor;
}
featureStyle = new ol.style.Style({
fill: new ol.style.Fill({
color: spotColor,
}),
stroke: new ol.style.Stroke({
color: "#000000FF",
width: 0.25,
}),
});
spot.setStyle(featureStyle);
spot.spot = key;
spot.size = 6; // Mouseover detection
g_layerSources["psk-spots"].addFeature(spot);
var toPoint = ol.proj.fromLonLat([Lon, Lat]);
var lonLat = new ol.geom.Point(toPoint);
var pointFeature = new ol.Feature({
geometry: lonLat,
weight: report.color / 255, // e.g. temperature
});
g_layerSources["psk-heat"].addFeature(pointFeature);
if (g_receptionSettings.viewPaths && g_receptionSettings.spotWidth > 0) {
var strokeWeight = g_receptionSettings.spotWidth;
var flightColor =
workingColor == -1
? colorNoAlpha + "BB"
: g_mapSettings.nightMapEnable && g_nightTime
? g_spotNightFlightColor
: g_spotFlightColor;
var feature = flightFeature(
[fromPoint, toPoint],
{
weight: strokeWeight,
color: flightColor,
steps: 75,
},
"psk-flights",
false
);
}
}
function redrawSpots() {
var shouldSave = false;
var now = timeNowSec();
g_spotTotalCount = 0;
g_layerSources["psk-spots"].clear();
g_layerSources["psk-flights"].clear();
g_layerSources["psk-hop"].clear();
g_layerSources["psk-heat"].clear();
var fromPoint = getPoint(myRawGrid);
if (g_receptionSettings.mergeSpots == false) {
var spot = iconFeature(fromPoint, g_gtFlagIcon, 100);
g_layerSources["psk-spots"].addFeature(spot);
g_layerSources["psk-heat"].addFeature(spot);
}
for (var key in g_receptionReports.spots) {
report = g_receptionReports.spots[key];
if (now - report.when > 86400) {
delete g_receptionReports.spots[key];
shouldSave = true;
continue;
}
if (
(g_appSettings.gtBandFilter.length == 0 ||
(g_appSettings.gtBandFilter == "auto"
? myBand == report.band
: g_appSettings.gtBandFilter == report.band)) &&
validateMapMode(report.mode)
) {
if (now - report.when <= g_receptionSettings.viewHistoryTimeSec) {
createSpot(report, key, fromPoint);
g_spotTotalCount++;
}
}
}
if (shouldSave) {
saveReceptionReports();
}
updateSpotCountDiv();
}
function updateSpotCountDiv() {
spotCountDiv.innerHTML = "Spots: " + g_spotTotalCount;
}
var g_spotFlightColor = "#FFFFFFBB";
var g_spotNightFlightColor = "#FFFFFFBB";
function changeSpotValues() {
g_receptionSettings.viewHistoryTimeSec =
parseInt(spotHistoryTimeValue.value) * 60;
spotHistoryTimeTd.innerHTML =
"Max Age: " + Number(g_receptionSettings.viewHistoryTimeSec).toDHM();
g_receptionSettings.viewPaths = spotPathsValue.checked;
if (g_receptionSettings.viewPaths) {
spotPathWidthDiv.style.display = "inline-block";
} else {
spotPathWidthDiv.style.display = "none";
}
g_receptionSettings.mergeSpots = spotMergeValue.checked;
localStorage.receptionSettings = JSON.stringify(g_receptionSettings);
setTrophyOverlay(g_currentOverlay);
updateSpotView();
if (g_rosterSpot) goProcessRoster();
}
function mapTransChange() {
g_mapSettings.mapTrans = mapTransValue.value;
mapTransTd.innerHTML =
String(100 - parseInt(((g_mapSettings.mapTrans * 255) / 255) * 100)) + "%";
mapSettingsDiv.style.backgroundColor =
"rgba(0,0,0, " + g_mapSettings.mapTrans + ")";
}
function spotPathChange() {
g_receptionSettings.pathColor = spotPathColorValue.value;
var pathColor =
g_receptionSettings.pathColor < 1
? "#000"
: g_receptionSettings.pathColor == 361
? "#FFF"
: "hsl(" + g_receptionSettings.pathColor + ", 100%, 50%)";
if (g_receptionSettings.pathColor > 0) {
spotPathColorDiv.style.color = "#000";
spotPathColorDiv.style.backgroundColor = pathColor;
} else {
spotPathColorDiv.style.color = "#FFF";
spotPathColorDiv.style.backgroundColor = pathColor;
}
if (g_receptionSettings.pathColor == -1)
spotPathInfoTd.innerHTML = "PSK-Reporter Palette";
else spotPathInfoTd.innerHTML = "";
g_spotFlightColor =
g_receptionSettings.pathColor < 1
? "#0000000BB"
: g_receptionSettings.pathColor == 361
? "#FFFFFFBB"
: "hsla(" + g_receptionSettings.pathColor + ", 100%, 50%,0.73)";
g_receptionSettings.pathNightColor = spotNightPathColorValue.value;
var pathNightColor =
g_receptionSettings.pathNightColor < 1
? "#000"
: g_receptionSettings.pathNightColor == 361
? "#FFF"
: "hsl(" + g_receptionSettings.pathNightColor + ", 100%, 50%)";
if (g_receptionSettings.pathNightColor > 0) {
spotNightPathColorDiv.style.color = "#000";
spotNightPathColorDiv.style.backgroundColor = pathNightColor;
} else {
spotNightPathColorDiv.style.color = "#FFF";
spotNightPathColorDiv.style.backgroundColor = pathNightColor;
}
if (g_receptionSettings.pathNightColor == -1)
spotNightPathInfoTd.innerHTML = "PSK-Reporter Palette";
else spotNightPathInfoTd.innerHTML = "";
g_spotNightFlightColor =
g_receptionSettings.pathNightColor < 1
? "#0000000BB"
: g_receptionSettings.pathNightColor == 361
? "#FFFFFFBB"
: "hsla(" + g_receptionSettings.pathNightColor + ", 100%, 50%,0.73)";
spotWidthTd.innerHTML = g_receptionSettings.spotWidth = spotWidthValue.value;
localStorage.receptionSettings = JSON.stringify(g_receptionSettings);
}
function toggleSpotOverGrids() {
spotMergeValue.checked = spotMergeValue.checked == true ? false : true;
changeSpotValues();
redrawSpots();
}
function toggleMergeOverlay() {
mergeOverlayValue.checked = mergeOverlayValue.checked == true ? false : true;
changeMergeOverlayValue();
}
function toggleSpotPaths() {
var spotPaths = spotPathsValue.checked == true ? 1 : 0;
spotPaths ^= 1;
spotPathsValue.checked = spotPaths == 1 ? true : false;
g_receptionSettings.viewPaths = spotPathsValue.checked;
localStorage.receptionSettings = JSON.stringify(g_receptionSettings);
if (g_receptionSettings.viewPaths) {
spotPathWidthDiv.style.display = "inline-block";
} else {
spotPathWidthDiv.style.display = "none";
}
redrawSpots();
}
function toggleHeatSpots() {
g_heatEnabled ^= 1;
g_appSettings.heatEnabled = g_heatEnabled;
updateSpotView();
}
function togglePskSpots() {
g_spotsEnabled ^= 1;
g_appSettings.spotsEnabled = g_spotsEnabled;
pskSpotsImg.style.filter = g_spotsEnabled == 1 ? "" : "grayscale(1)";
setTrophyOverlay(g_currentOverlay);
updateSpotView();
}
function toggleCRScript() {
g_crScript ^= 1;
g_appSettings.crScript = g_crScript;
if (g_crScript == 1)
addLastTraffic(
"<font style='color:lightgreen'>Call Roster Script Enabled</font>"
);
else
addLastTraffic(
"<font style='color:yellow'>Call Roster Script Disabled</font>"
);
goProcessRoster();
}
function updateSpotView(leaveCount = true) {
if (g_spotsEnabled == 1) {
if (g_receptionSettings.mergeSpots == false) {
for (var key in g_layerVectors) {
g_layerVectors[key].setVisible(false);
}
}
if (g_heatEnabled == 0) {
g_layerVectors["psk-spots"].setVisible(true);
g_layerVectors["psk-flights"].setVisible(true);
g_layerVectors["psk-hop"].setVisible(true);
g_layerVectors["psk-heat"].setVisible(false);
} else {
g_layerVectors["psk-spots"].setVisible(false);
g_layerVectors["psk-flights"].setVisible(false);
g_layerVectors["psk-hop"].setVisible(false);
g_layerVectors["psk-heat"].setVisible(true);
}
SpotsDiv.style.display = "block";
if (leaveCount == false) spotRefreshDiv.innerHTML = "&nbsp;";
} else {
g_layerVectors["psk-spots"].setVisible(false);
g_layerVectors["psk-flights"].setVisible(false);
g_layerVectors["psk-hop"].setVisible(false);
g_layerVectors["psk-heat"].setVisible(false);
SpotsDiv.style.display = "none";
spotRefreshDiv.innerHTML = "&nbsp;";
}
g_layerVectors["strikes"].setVisible(true);
}
function gotoDonate() {
var gui = require("nw.gui");
gui.Shell.openExternal("https://gridtracker.org/donations/");
}
function changeRosterTime() {
g_mapSettings.rosterTime = rosterTime.value;
setRosterTimeView();
saveMapSettings();
goProcessRoster();
}
function changeRosterTop(butt) {
g_appSettings.rosterAlwaysOnTop = butt.checked;
setRosterTop();
}
function setRosterTop() {
if (g_callRosterWindowHandle) {
try {
g_callRosterWindowHandle.setAlwaysOnTop(g_appSettings.rosterAlwaysOnTop);
} catch (e) {}
}
}
function setRosterTimeView() {
rosterTime.value = g_mapSettings.rosterTime;
rosterTimeTd.innerHTML = Number(rosterTime.value).toDHMS();
}
function getSpotTime(hash) {
if (hash in g_receptionReports.spots) {
return g_receptionReports.spots[hash];
} else return null;
}
function setGridOpacity() {
opacityValue.value = g_mapSettings.gridAlpha;
showOpacityTd.innerHTML =
parseInt((g_mapSettings.gridAlpha / 255) * 100) + "%";
g_gridAlpha = parseInt(g_mapSettings.gridAlpha).toString(16);
}
function changeGridOpacity() {
g_mapSettings.gridAlpha = opacityValue.value;
showOpacityTd.innerHTML =
parseInt((g_mapSettings.gridAlpha / 255) * 100) + "%";
g_gridAlpha = parseInt(g_mapSettings.gridAlpha).toString(16);
saveMapSettings();
}
function currentTimeStampString() {
var now = new Date();
return (
now.getFullYear() +
"-" +
(now.getMonth() + 1) +
"-" +
now.getDate() +
" " +
now.getHours().pad() +
"." +
now.getMinutes().pad() +
"." +
now.getSeconds().pad()
);
}
function showNativeFolder(fn) {
nw.Shell.showItemInFolder(decodeURI(fn));
}
function makeScreenshots() {
var win = gui.Window.get();
win.capturePage(
function (buffer) {
var clipboard = nw.Clipboard.get();
clipboard.set(buffer, "png", true);
},
{ format: "png", datatype: "raw" }
);
win.capturePage(
function (buffer) {
try {
var fn =
g_screenshotDir + "Screenshot " + currentTimeStampString() + ".png";
fs.writeFileSync(fn, buffer);
addLastTraffic(
"<font style='color:lightgreen;cursor:pointer;' onclick='showNativeFolder(\"" +
encodeURI(fn).trim() +
"\");''>Saved Screenshot</font>"
);
} catch (e) {
addLastTraffic(
"<font style='color:red'>Screenshot write failed</font>"
);
}
},
{ format: "png", datatype: "buffer" }
);
}
window.addEventListener("load", function () {
picker.attach({
target: "workingDateValue",
container: "pick-inline",
fire: "workingDateChanged",
});
});