// 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 & 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 + " \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 ? "No Decay" : 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 += "
" + g_gtFlagPins[key].call.formatCallsign() + "
"; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; 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 += ""; worker += ""; worker += "
DXCC" + dxccName + " (" + g_worldGeoData[g_dxccToGeoData[dxcc]].pp + ")
Grid" + g_gtFlagPins[key].grid + "
Freq" + Number(g_gtFlagPins[key].freq / 1000).formatMhz(3, 3) + " (" + Number(g_gtFlagPins[key].freq / 1000000).formatBand() + ")
Mode" + g_gtFlagPins[key].mode + "
Dist" + 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() + "
Azim" + bearing + "°
"; } else if (toolElement.size == 73) { var props = toolElement.getProperties(); moment.locale(navigator.languages[0]); var m = moment().tz(props.tzid); worker += "
" + props.tzid + "
"; worker += ""; var abbr = m.format("zz"); var zone = m.format("Z"); if (zone.indexOf(abbr) > -1) abbr = ""; else abbr = " (" + abbr + ")"; worker += ""; worker += ""; worker += "
" + m.format("LLLL") + "
" + zone + abbr + "
"; } 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 = ""; worker += ""; worker += ""; worker += ""; if (report.dxcc > 0) worker += ""; worker += ""; worker += ""; worker += ""; 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 += ""; worker += ""; worker += ""; worker += "
Rx Spot
Age" + Number(now - report.when).toDHMS() + "
dB" + Number(report.snr).formatSignalReport() + "
Call" + report.call.formatCallsign() + "
DXCC" + g_dxccToAltName[report.dxcc] + " (" + g_worldGeoData[g_dxccToGeoData[report.dxcc]].pp + ")
Grid" + report.grid + "
Freq" + report.freq.formatMhz() + " (" + report.band + ")
Mode" + report.mode + "
Dist" + 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() + "
Azim" + report.bearing + "°
Time" + userTimeString(report.when * 1000) + "
"; 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 = ""; if (toolElement.qth in g_gridToDXCC) { worker += ""; } var newCallList = Array(); if (toolElement.qso == true) { if (Object.keys(toolElement.hashes).length > 0) { worker += ""; if (g_callsignLookups.lotwUseEnable == true) worker += ""; if (g_callsignLookups.eqslUseEnable == true) worker += ""; if (g_callsignLookups.oqrsUseEnable == true) worker += ""; worker += ""; } 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 += ""; if (g_callsignLookups.lotwUseEnable == true) worker += ""; if (g_callsignLookups.eqslUseEnable == true) worker += ""; if (g_callsignLookups.oqrsUseEnable == true) worker += ""; worker += ""; } 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 += ""; worker += "
" + callsign.DEcall.formatCallsign() + "
"; worker += ""; worker += "
"; worker += ""; worker += "" + ""; if (callsign.DXcall.indexOf("CQ") == 0 || callsign.DXcall == "-") worker += callsign.DXcall.formatCallsign(); else worker += "
" + callsign.DXcall.formatCallsign() + "
"; worker += "" + "
" + ""; if (toolElement.qso == true) { worker += ""; } worker += "" + ""; if (g_callsignLookups.lotwUseEnable == true) worker += ""; if (g_callsignLookups.eqslUseEnable == true) worker += ""; if (g_callsignLookups.oqrsUseEnable == true) worker += ""; worker += ""; } worker += "
" + toolElement.qth + "
"; 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 += " ("; 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 += ")"; } if (x + 1 < g_gridToDXCC[toolElement.qth].length) worker += ", "; } worker += "
CallFreqSentRcvdStationModeBandQSLLast MsgDXCCTimeLoTWeQSLOQRS
CallFreqSentRcvdStationModeBandLast MsgDXCCTimeLoTWeQSLOQRS
" + (callsign.delta > -1 ? callsign.delta : "-") + "" + callsign.RSTsent + "" + callsign.RSTrecv + "" + callsign.mode + "" + callsign.band + "" + (callsign.confirmed ? "✔" : "") + "" + callsign.msg + "" + g_dxccToAltName[callsign.dxcc] + " (" + g_worldGeoData[g_dxccToGeoData[callsign.dxcc]].pp + ")" + ageString + "" + (callsign.DEcall in g_lotwCallsigns ? "✔" : "") + "" + (callsign.DEcall in g_eqslCallsigns ? "✔" : "") + "" + (callsign.DEcall in g_oqrsCallsigns ? "✔" : "") + "
"; 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 = ""; worker += ""; worker += ""; worker += ""; worker += "
Moon
Azimuth" + object.azimuth.toFixed(1) + "°
Elevation" + elevation + "
"; 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 + " (" + g_worldGeoData[ref].pp + ")"; } 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 = ""; worker += ""; worker += ""; if (zone) worker += " "; var wc1Table = ""; if (infoObject.worked) { wc1Table = ""; } var wcTable = ""; if (infoObject.confirmed) { wcTable = ""; } if (!infoObject.worked && !infoObject.confirmed) worker += ""; else { worker += "" + wc1Table + wcTable + ""; } worker += "
" + trophy + "
" + name + "
" + zone + "
"; wc1Table += ""; wc1Table += ""; wc1Table += ""; wc1Table += ""; wc1Table += ""; wc1Table += ""; wc1Table += ""; wc1Table += ""; wc1Table += "
Worked
Band"; var keys = Object.keys(infoObject.worked_bands).sort(); for (key in keys) { wc1Table += ""; } wc1Table += "
" + keys[key] + " (" + infoObject.worked_bands[keys[key]] + ") " + "
Mode"; keys = Object.keys(infoObject.worked_modes).sort(); for (key in keys) { wc1Table += ""; } wc1Table += "
" + keys[key] + " (" + infoObject.worked_modes[keys[key]] + ") " + "
"; wcTable += ""; wcTable += ""; wcTable += ""; wcTable += ""; wcTable += ""; wcTable += ""; wcTable += ""; wcTable += ""; wcTable += "
Confirmed
Band"; var keys = Object.keys(infoObject.confirmed_bands).sort(); for (key in keys) { wcTable += ""; } wcTable += "
" + keys[key] + " (" + infoObject.confirmed_bands[keys[key]] + ") " + "
Mode"; keys = Object.keys(infoObject.confirmed_modes).sort(); for (key in keys) { wcTable += ""; } wcTable += "
" + keys[key] + " (" + infoObject.confirmed_modes[keys[key]] + ") " + "
Needed
"; myTrophyTooltip.innerHTML = "
" + worker + "
"; 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 += ""; var bearing = parseInt( MyCircle.bearing(g_myLat, g_myLon, longlat[1], longlat[0]) ); worker += ""; worker += ""; worker += ""; worker += "
Dist" + parseInt( MyCircle.distance( g_myLat, g_myLon, longlat[1], longlat[0], distanceUnit.value ) * MyCircle.validateRadius(distanceUnit.value) ) + distanceUnit.value.toLowerCase() + "
Azim" + bearing + "°
Lat" + longlat[1].toFixed(3) + "
Long" + longlat[0].toFixed(3) + "
"; if (grid in g_gridToDXCC) { worker += ""; worker += ""; for (var x = 0; x < g_gridToDXCC[grid].length; x++) { worker += ""; } if (grid in g_gridToState) { worker += ""; for (var x = 0; x < g_gridToDXCC[grid].length; x++) { worker += ""; } } worker += "
" + g_dxccToAltName[g_gridToDXCC[grid][x]] + " (" + g_worldGeoData[g_dxccToGeoData[g_gridToDXCC[grid][x]]].pp + ")
"; 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 + "
"; } } } worker += "
"; } g_tempGridBox = tempGridToBox(grid, g_tempGridBox, "#000000FF", "#00000000"); myGridTooltip.innerHTML = "
" + grid + "
" + 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 ( "
Viewing: " + band + " / " + mode + "

" ); } 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 = "" + userTimeString(null) + ""; 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 = "Never"; 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 = "Strike Distance Changed
" + msg + "
"; if (g_mapSettings.strikes == false) worker += "
Detection is not enabled!"; 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() + "°"; var worker = "Lighting Strike Detected!
"; worker += "" + userTimeString(null) + "
"; worker += "Distance: " + dist + "
"; worker += "Bearing: " + azim + ""; 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])) + "°"; 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("Generated Msgs"); } if (thisInstance && thisInstance.TxEnabled == 1) { addLastTraffic( "Transmit Enabled!
Generate Msgs Aborted" ); } } 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 = "" + newMessage.MO + ""; 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 += "" + myBand + " / "; msg += "" + myMode + ""; addLastTraffic(msg); ackAlerts(); updateChatWindow(); } myRawFreq = newMessage.Frequency; frequency.innerHTML = "" + Number(newMessage.Frequency / 1000).formatMhz(3, 3) + " Hz (" + myBand + ")"; 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 = " "; localDXAzimuth.innerHTML = " "; } 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 ) ) + "°"; } if (localDXcall.innerHTML != "-") { localDXReport.innerHTML = Number( newMessage.Report.trim() ).formatSignalReport(); if (DXcall.length > 0) localDXCountry.innerHTML = g_dxccToAltName[callsignToDxcc(DXcall)]; else localDXCountry.innerHTML = " "; } 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 += "
"; worker += ""; worker += ""; worker += ""; worker += g_lastMessages.join(""); worker += "
Last " + g_lastMessages.length + " Decoded Messages
TimedBDTFreqModeMessageDXCC
"; 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("
"); worker = worker.split("80%'>
").join("80%'>"); if (g_localDXcall.length > 1) worker = worker .split(g_localDXcall) .join("" + g_localDXcall + ""); if (myRawCall.length > 1) worker = worker .split(myRawCall) .join("" + myRawCall + ""); 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( "
" ); 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( "" + userTimeString(theTimeStamp * 1000) + "" + newMessage.SR + "" + newMessage.DT.toFixed(1) + "" + newF + "" + newMessage.MO + "" + htmlEntities(newMessage.Msg) + "" + countryName + "" ); while (g_lastMessages.length > 100) g_lastMessages.pop(); } function addLastTraffic(traffic) { g_lastTraffic.unshift(traffic); g_lastTraffic.unshift( "
" ); drawTraffic(); } function htmlEntities(str) { return String(str) .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """); } 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 = "Settings File Corrupt!"; } else if (data.currentVersion != localStorage.currentVersion) { importSettingsFile.innerHTML = "Settings Version Mismatch!"; } } } } function showCallsignBox(redraw) { var worker = "
Callsigns and DXCC Heard

"; g_newCallsignCount = Object.keys(g_liveCallsigns).length; if (g_newCallsignCount > 0) { var newCallList = Array(); worker += "
"; //"; if (g_callsignLookups.lotwUseEnable == true) worker += ""; if (g_callsignLookups.eqslUseEnable == true) worker += ""; if (g_callsignLookups.oqrsUseEnable == true) worker += ""; 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 += ""; worker += ""; worker += ""; worker += ""; var ageString = ""; if (timeNowSec() - newCallList[x].time < 3601) ageString = (timeNowSec() - newCallList[x].time).toDHMS(); else { ageString = userTimeString(newCallList[x].time * 1000); } worker += ""; if (g_callsignLookups.lotwUseEnable == true) worker += ""; if (g_callsignLookups.eqslUseEnable == true) worker += ""; if (g_callsignLookups.oqrsUseEnable == true) worker += ""; worker += ""; } worker += "
CallsignGridDXCCCQITUFlagQSOQSLWhenITUzCQzISOLoTWeQSLOQRS
" + thisCall + "" + grid + "" + geo.name + " (" + geo.pp + ")" + cqzone + "" + ituzone + "" + (thisCall in g_tracker.worked.call ? "✔" : "") + "" + (thisCall in g_tracker.confirmed.call ? "✔" : "") + "" + ageString + "" + (thisCall in g_lotwCallsigns ? "✔" : "") + "" + (thisCall in g_eqslCallsigns ? "✔" : "") + "" + (thisCall in g_oqrsCallsigns ? "✔" : "") + "
"; } 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 += "
"; Object.keys(List) .sort() .forEach(function (key, i) { worker += ""; worker += ""; worker += ""; worker += ""; }); worker += "
DXCC (" + heard + ")
NameFlagCalls
" + key + "" + List[key].total + "
"; } worker += ""; 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 = " Entries (" + ObjectCount + ")"; if (g_qsoPages > 1) { workHead += "
⇦ "; workHead += " Page " + (g_qsoPage + 1) + " of " + g_qsoPages + " (" + (endIndex - startIndex) + ") "; workHead += " ⇨"; } setStatsDiv("workedHeadDiv", workHead); if (myObjects != null) { var worker = ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += " "; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; if (g_callsignLookups.lotwUseEnable == true) worker += ""; if (g_callsignLookups.eqslUseEnable == true) worker += ""; if (g_callsignLookups.oqrsUseEnable == true) worker += ""; worker += ""; var key = null; for (var i = startIndex; i < endIndex; i++) { key = list[i]; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; if (g_callsignLookups.lotwUseEnable == true) worker += ""; if (g_callsignLookups.eqslUseEnable == true) worker += ""; if (g_callsignLookups.oqrsUseEnable == true) worker += ""; worker += ""; } worker += "
StationGridBandModeQSLSentRcvdDXCCFlagWhenLoTWeQSLOQRS
" + key.DEcall.formatCallsign() + "" + key.grid + (key.vucc_grids.length ? ", " + key.vucc_grids.join(", ") : "") + "" + key.band + "" + key.mode + "" + (key.confirmed ? "✔" : "") + "" + key.RSTsent + "" + key.RSTrecv + "" + g_dxccToAltName[key.dxcc] + " (" + (g_dxccToGeoData[key.dxcc] in g_worldGeoData ? g_worldGeoData[g_dxccToGeoData[key.dxcc]].pp : "?") + ")" + userTimeString(key.time * 1000) + "" + (key.DEcall in g_lotwCallsigns ? "✔" : "") + "" + (key.DEcall in g_eqslCallsigns ? "✔" : "") + "" + (key.DEcall in g_oqrsCallsigns ? "✔" : "") + "
"; 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 += "
"; 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 += ""; worker += ""; worker += ""; }); worker += "
Worked (" + worked + ")
NameFlagDXCC
" + key + "" + List[key].dxcc + "
"; } if (confirmed > 0) { worker += "
"; Object.keys(ListConfirmed) .sort() .forEach(function (key, i) { worker += ""; worker += ""; worker += ""; }); worker += "
Confirmed (" + confirmed + ")
NameFlagDXCC
" + key + "" + ListConfirmed[key].dxcc + "
"; } if (needed > 0) { worker += "
"; Object.keys(ListNotWorked) .sort() .forEach(function (key, i) { worker += ""; worker += ""; worker += ""; }); worker += "
Needed (" + needed + ")
NameFlagDXCC
" + key + "" + ListNotWorked[key].dxcc + "
"; } setStatsDiv("dxccListDiv", worker); } } function showCQzoneBox() { var worker = getCurrentBandModeHTML(); worker += "
Worked CQ Zones
"; worker += displayItemList(g_cqZones, "#FFFFFF"); worker += "
"; setStatsDiv("cqzoneListDiv", worker); } function showITUzoneBox() { var worker = getCurrentBandModeHTML(); worker += "
Worked ITU Zones
"; worker += displayItemList(g_ituZones, "#FFFFFF"); worker += "
"; setStatsDiv("ituzoneListDiv", worker); } function showWASWACzoneBox() { var worker = getCurrentBandModeHTML(); worker += "
Worked All Continents
"; worker += displayItemList(g_wacZones, "#90EE90"); worker += "
"; worker += "
Worked All States
"; worker += displayItemList(g_wasZones, "#00DDDD"); worker += "
"; 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 = "
"; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; 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 += ""; }); worker += "
Worked (" + worked + ")
Confirmed (" + confirmed + ")
Needed (" + needed + ")
Name
" + key + "
"; 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 += "
Worked Prefixes (" + worked + ")
"; worker += "
"; Object.keys(List) .sort() .forEach(function (key, i) { worker += ""; }); worker += "
" + key.formatCallsign() + "" + g_QSOhash[g_tracker.worked.px[key]].DEcall.formatCallsign() + "
"; worker += "
"; } if (confirmed > 0) { worker += "
Confirmed Prefixes (" + confirmed + ")
"; worker += "
"; Object.keys(ListConfirmed) .sort() .forEach(function (key, i) { worker += ""; }); worker += "
" + key.formatCallsign() + "" + g_QSOhash[g_tracker.confirmed.px[key]].DEcall.formatCallsign() + "
"; worker += "
"; } 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", " 
...Parsing Log Entries...
 " ); setStatsDivHeight("statViewDiv", "auto"); g_statBoxTimer = setTimeout(renderStatsBox, 250); } else { setStatsDiv( "statViewDiv", " 
No log entries available, load one or more ADIF logs
 " ); 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 = ""; worker += "

Logbook

"; worker += ""; var ws = ""; if (Object.keys(details.callsigns).length > 1) ws = "s"; worker += ""; worker += ""; worker += ""; worker += "
Callsign" + ws + "" + Object.keys(details.callsigns).sort().join(", ") + "
First Contact" + userTimeString(details.oldest * 1000) + "
Last Contact" + userTimeString(details.newest * 1000) + "
"; worker += "
"; worker += "

Score Card

"; worker += ""; worker += ""; for (var key in AwardNames) { scoreSection = "Award " + AwardNames[key][1]; var infoObject = output[AwardNames[key][0]]; worker += ""; worker += ""; if (infoObject.confirmed_high_key) { worker += ""; } else worker += ""; worker += ""; } scoreSection = "Long Distance"; worker += ""; worker += ""; if (long_distance.confirmed_hash && long_distance.confirmed_unit > 0) { worker += ""; } else worker += ""; scoreSection = "Short Distance"; worker += ""; worker += ""; if (short_distance.confirmed_hash && short_distance.confirmed_unit > 0) { worker += ""; } else worker += ""; worker += ""; worker += "
Top ScoreWorkedConfirmed
" + AwardNames[key][1] + "" + infoObject.worked_high_key + " (" + infoObject.worked_high + ")" + infoObject.confirmed_high_key + " (" + infoObject.confirmed_high + ")
Long Distance" + long_distance.worked_unit + " " + distanceUnit.value.toLowerCase(); worker += " " + g_QSOhash[long_distance.worked_hash].DEcall + ""; worker += " " + g_QSOhash[long_distance.worked_hash].grid + "" + long_distance.confirmed_unit + " " + distanceUnit.value.toLowerCase(); worker += " " + g_QSOhash[long_distance.confirmed_hash].DEcall + ""; worker += " " + g_QSOhash[long_distance.confirmed_hash].grid + "
Short Distance" + short_distance.worked_unit + " " + distanceUnit.value.toLowerCase(); worker += " " + g_QSOhash[short_distance.worked_hash].DEcall + ""; worker += " " + g_QSOhash[short_distance.worked_hash].grid + "" + short_distance.confirmed_unit + " " + distanceUnit.value.toLowerCase(); worker += " " + g_QSOhash[short_distance.confirmed_hash].DEcall + ""; worker += " " + g_QSOhash[short_distance.confirmed_hash].grid + "
"; worker += "
"; worker += "

Award Types

"; scoreSection = "Award Types"; for (var key in AwardNames) worker += createStatTable( AwardNames[key][1], output[AwardNames[key][0]], AwardNames[key][2] ); worker += "
"; scoreSection = "Mode Types"; worker += "

Mode Types

"; for (var key in TypeNames) worker += createStatTable( TypeNames[key][1], output[TypeNames[key][0]], TypeNames[key][2] ); worker += "
"; worker += "

Distances

"; scoreSection = "Distances"; worker += createDistanceTable(long_distance, "Longest Distance"); worker += createDistanceTable(short_distance, "Shortest Distance"); worker += "
"; if (g_appSettings.gtShareEnable == true) { scoreSection = "GT Users"; worker += "

Worked GridTracker Stations
Online Now

"; worker += "
"; worker += ""; worker += createGtStationsTable(gtData); worker += "
"; worker += "
"; } worker += ""; } catch (e) { worker += "
In Section: " + scoreSection + "
Error Generating Stats
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 = ""; worker += ""; 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 += ""; worker += "
" + callsign.DEcall.formatCallsign() + "
"; worker += ""; worker += "
"; worker += ""; worker += ""; worker += "" + "" + ""; worker += ""; worker += "" + ""; worker += ""; } worker += "
CallGridSentRcvdModeBandQSLCommentDXCCTime
" + callsign.grid + "" + callsign.RSTsent + "" + callsign.RSTrecv + "" + callsign.mode + "" + callsign.band + "" + (callsign.confirmed ? "✔" : "") + "" + callsign.msg + "" + g_dxccToAltName[callsign.dxcc] + " (" + g_worldGeoData[g_dxccToGeoData[callsign.dxcc]].pp + ")" + ageString + "
"; return worker; } function createDistanceTable(obj, name) { var worker = ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += "
" + name + "
WorkedConfirmed
Bands"; 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 += ""; worker += ""; worker += ""; worker += ""; } worker += "
" + keys[key] + "(" + obj.band[keys[key]].worked_unit + " " + distanceUnit.value.toLowerCase() + ")" + call + "" + grid + "
"; 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 += ""; worker += ""; worker += ""; worker += ""; } else worker += ""; } worker += "
" + keys[key] + "(" + obj.band[keys[key]].confirmed_unit + " " + distanceUnit.value.toLowerCase() + ")" + call + "" + grid + "
 
Modes"; 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 += ""; worker += ""; worker += ""; worker += ""; } worker += "
" + keys[key] + "(" + obj.mode[keys[key]].worked_unit + " " + distanceUnit.value.toLowerCase() + ")" + call + "" + grid + "
"; 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 += ""; worker += ""; worker += ""; worker += ""; } else worker += ""; } worker += "
" + keys[key] + "(" + obj.mode[keys[key]].confirmed_unit + " " + distanceUnit.value.toLowerCase() + ")" + call + "" + grid + "
 
Types"; 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 += ""; worker += ""; worker += ""; worker += ""; } worker += "
" + keys[key] + "(" + obj.type[keys[key]].worked_unit + " " + distanceUnit.value.toLowerCase() + ")" + call + "" + grid + "
"; 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 += ""; worker += ""; worker += ""; worker += ""; } else worker += ""; } worker += "
" + keys[key] + "(" + obj.type[keys[key]].confirmed_unit + " " + distanceUnit.value.toLowerCase() + ")" + call + "" + grid + "
 
"; 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 = ""; wc1Table += ""; var award = ""; wc1Table += "" + award + ""; wc1Table += ""; wc1Table += ""; wc1Table += ""; wc1Table += ""; wc1Table += ""; wc1Table += ""; wc1Table += ""; wc1Table += ""; wc1Table += ""; if (infoObject.worked_type_count > 0) { wc1Table += ""; wc1Table += ""; wc1Table += ""; wc1Table += ""; wc1Table += ""; } wc1Table += "
" + title + "
Worked (" + infoObject.worked + ")Confirmed (" + infoObject.confirmed + ")
Bands"; var keys = Object.keys(infoObject.worked_bands).sort(numberSort); for (var key in keys) { wc1Table += ""; } wc1Table += "
" + keys[key] + " (" + infoObject.worked_bands[keys[key]] + ")
"; for (var key in keys) { if (keys[key] in infoObject.confirmed_bands) { wc1Table += ""; } else wc1Table += ""; } wc1Table += "
" + keys[key] + " (" + infoObject.confirmed_bands[keys[key]] + ")
 
Modes"; keys = Object.keys(infoObject.worked_modes).sort(); for (var key in keys) { wc1Table += ""; } wc1Table += "
" + keys[key] + " (" + infoObject.worked_modes[keys[key]] + ")
"; for (var key in keys) { if (keys[key] in infoObject.confirmed_modes) { wc1Table += ""; } else wc1Table += ""; } wc1Table += "
" + keys[key] + " (" + infoObject.confirmed_modes[keys[key]] + ")
 
Types"; var keys = Object.keys(infoObject.worked_types).sort(); for (var key in keys) { wc1Table += ""; } wc1Table += "
" + keys[key] + " (" + infoObject.worked_types[keys[key]] + ") " + "
"; for (var key in keys) { if (keys[key] in infoObject.confirmed_types) { wc1Table += ""; } else wc1Table += ""; } wc1Table += "
" + keys[key] + " (" + infoObject.confirmed_types[keys[key]] + ") " + "
 
"; } 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 += "
"; buffer += "
"; buffer += "
"; buffer += "
" + parseInt(band) + "
"; buffer += "
"; } } } 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 += "(" + g_wsjtxIni.ip + " / " + g_wsjtxIni.port + ") "; } else runningAppsDiv.innerHTML += "(?) "; 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 += "(" + g_jtdxIni.ip + " / " + g_jtdxIni.port + ") "; } else runningAppsDiv.innerHTML += "(?) "; } } 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.
Go there now?

"; versionDiv.style.display = "block"; } else { if (flag) { if (gtVersion < betaVersion) { var verString = String(betaVersion); main.style.display = "none"; newVersionMustDownloadDiv.innerHTML = "New Beta Version v" + verString.substr(0, 1) + "." + verString.substr(1, 2) + "." + verString.substr(3) + " available for download.
Go there now?

"; 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
" + 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 " + callsign + ", 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 = "
C A L L O O K
NO-NONSENSE AMATEUR RADIO U.S.A. CALLSIGN LOOKUPS
are limited to United States and United States Territories Only
"; worker += "
The callsign " + callsign + " requested is from " + where + "
"; worker += "

You might want to consider using QRZ.com, they have a free membership that provides limited data for most callsigns
"; worker += "and they have full details available for paid members
"; 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"] = "Source
C A L L O O K
"; 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 = "Valid"; g_qrzLookupSessionId = json.session.session_id; } else { result = "" + json.session.error + ""; g_qrzLookupSessionId = null; } } else { result = "Invalid Response"; g_qrzLookupSessionId = null; } } else { result = "Unknown Error"; 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 = "Valid"; g_qrzLookupSessionId = json.Session.Key; } else { result = "" + json.Session.Error + ""; g_qrzLookupSessionId = null; } } else { result = "Invalid Response"; g_qrzLookupSessionId = null; } } else { result = "Unknown Error"; 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 = "Source
HamQTH
"; cacheLookupObject(json.search, gridPass, true); } else { g_qrzLookupSessionId = null; setLookupDiv( "lookupInfoDiv", "
No result for callsign

" ); } } 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 = "Source
QRZ.com
"; else json.Callsign.source = "Source
QRZCQ.com
"; if (gridPass) json.Callsign.gtGrid = gridPass; cacheLookupObject(json.Callsign, gridPass, true); } else { setLookupDiv( "lookupInfoDiv", "
No result for callsign

" ); 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("Lookup Write Issue"); }; } 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 += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; g_lastLookupAddress = ""; if (getLookProp(lookup, "addrAttn").length > 0) { worker += ""; worker += ""; worker += ""; } worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += ""; worker += "
"; worker += getLookProp(lookup, "call").toUpperCase().formatCallsign(); worker += ""; if (lookup.dxcc > 0 && lookup.dxcc in g_dxccToGeoData) worker += ""; worker += ""; var image = getLookProp(lookup, "image"); if (image.length > 0) worker += ""; worker += "
"; worker += getLookProp(lookup, "addrAttn"); g_lastLookupAddress += getLookProp(lookup, "addrAttn") + "\n"; worker += "
"; worker += "" + getLookProp(lookup, "name") + ""; g_lastLookupAddress += getLookProp(lookup, "name") + "\n"; worker += "
"; worker += getLookProp(lookup, "addr1"); g_lastLookupAddress += getLookProp(lookup, "addr1") + "\n"; worker += "
"; 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 += "
"; var country = getLookProp(lookup, "country"); worker += country; g_lastLookupAddress += country + "\n"; worker += "
"; var email = getLookProp(lookup, "email"); if (email.length > 0) { worker += "
" + email + "
"; g_lastLookupAddress += email + "\n"; } worker += "
"; var card = "
" + worker + "
"; worker = ""; worker += ""; worker += ""; if (getLookProp(lookup, "url").length > 0) { worker += ""; worker += ""; worker += ""; worker += ""; } if (Number(getLookProp(lookup, "bio")) > 0) { worker += ""; worker += ""; worker += ""; worker += ""; } 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 += ""; } var Aliases = joinCommaIf( getLookProp(lookup, "aliases"), getLookProp(lookup, "p_call") ); if (Aliases.length > 0) { worker += ""; } 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"] = "✔ (" + userDayString(g_lotwCallsigns[thisCall] * 86400 * 1000) + ")"; worker += makeRow("LoTW Member", lookup, "ulotw"); } if (g_callsignLookups.eqslUseEnable == true && thisCall in g_eqslCallsigns) { lookup["ueqsl"] = "✔"; worker += makeRow("eQSL Member", lookup, "ueqsl"); } if (g_callsignLookups.oqrsUseEnable == true && thisCall in g_oqrsCallsigns) { lookup["uoqrs"] = "✔"; worker += makeRow("ClubLog OQRS", lookup, "uoqrs"); } if (fromCache) { worker += ""; } worker += "
Details
Website"; worker += "
Link
"; worker += "
Biography"; worker += "
Link
"; worker += "
Effective Dates" + dates + "
Aliases" + Aliases + "
Cached Record" + userTimeString(lookup["cached"] * 1000) + "
"; var details = "
" + worker + "
"; var genMessage = '
Clear
Generate Messages
"; setLookupDiv( "lookupInfoDiv", "" + genMessage + "
" + card + "" + details + "
" ); 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 "" + first + "Yes"; if (test == "N") return "" + first + "No"; if (test == "?") return ""; return ( "" + first + "" + (object[key] == 1 ? "Yes" : "No") + "" ); } return ""; } function makeRow(first, object, key, clip = false) { var value = getLookProp(object, key); if (value.length > 0) { if (clip) { return ( "" + first + "" + object[key].substr(0, 45) + "" ); } else { return ( "" + first + "" + object[key].substr(0, 45) + "" ); } } 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 = "
"; if (Object.keys(work).length > 0) { worker += ""; } if (Object.keys(conf).length > 0) { worker += ""; } if (lastRow) { worker += ""; } worker += "
Worked"; var k = Object.keys(work).sort(); for (var key in k) { worker += "" + k[key] + " "; } worker += "
Confirmed"; var k = Object.keys(conf).sort(); for (var key in k) { worker += "" + k[key] + " "; } worker += "
Last QSO"; worker += "" + list[lastRow].band + "," + list[lastRow].mode + " " + userTimeString(list[lastRow].time * 1000); worker += "
" + g_dxccToAltName[dxcc] + " (" + g_worldGeoData[g_dxccToGeoData[dxcc]].pp + ")"; 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 += "
" + g_colorBands[band] + "
 "; } } worker += "
"; 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( "Call Roster Script Enabled" ); else addLastTraffic( "Call Roster Script Disabled" ); 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 = " "; } 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 = " "; } 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( "Saved Screenshot" ); } catch (e) { addLastTraffic( "Screenshot write failed" ); } }, { format: "png", datatype: "buffer" } ); } window.addEventListener("load", function () { picker.attach({ target: "workingDateValue", container: "pick-inline", fire: "workingDateChanged", }); });