From 8f1c20dd1ddf1f687641b14fc1567ad1bdf5dadc Mon Sep 17 00:00:00 2001 From: Tag Date: Mon, 28 Nov 2022 20:26:59 -0800 Subject: [PATCH] POTA fixes --- package.nw/lib/adif.js | 7 +- package.nw/lib/gt.js | 30 ++- package.nw/lib/pota.js | 197 ++++++++++-------- package.nw/lib/roster/processRosterHunting.js | 12 +- package.nw/lib/roster/rosterColumns.js | 20 +- 5 files changed, 135 insertions(+), 131 deletions(-) diff --git a/package.nw/lib/adif.js b/package.nw/lib/adif.js index 69a09b9..753907a 100644 --- a/package.nw/lib/adif.js +++ b/package.nw/lib/adif.js @@ -1882,12 +1882,11 @@ function sendToLogger(ADIF) record.GRIDSQUARE = g_liveCallsigns[localHash].grid.substr(0, 4); } - if (g_appSettings.potaEnabled == 1 && localHash in g_liveCallsigns && g_liveCallsigns[localHash].pota.length > 0) + if (g_appSettings.potaEnabled == 1 && localHash in g_liveCallsigns && g_liveCallsigns[localHash].pota) { - var pota = g_liveCallsigns[localHash].pota[0]; - if (pota != "?-????") + if (g_liveCallsigns[localHash].pota != "?-????") { - record.POTA = pota; + record.POTA = g_liveCallsigns[localHash].pota; } } diff --git a/package.nw/lib/gt.js b/package.nw/lib/gt.js index 18813d0..a3381a1 100644 --- a/package.nw/lib/gt.js +++ b/package.nw/lib/gt.js @@ -1537,7 +1537,7 @@ function addDeDx( newCallsign.distance = 0; newCallsign.px = null; newCallsign.zone = null; - newCallsign.pota = []; + newCallsign.pota = null; newCallsign.cnty = finalCnty; newCallsign.cont = finalCont; if (finalDxcc > -1) @@ -6455,7 +6455,6 @@ function handleWsjtxStatus(newMessage) if (newMessage.Transmitting == 1 && newMessage.TxMessage && g_lastTxMessage != newMessage.TxMessage) { g_lastTxMessage = newMessage.TxMessage; - addLastTraffic(newMessage.TxMessage); if (newMessage.TxMessage.substr(0, 2) == "CQ" && DXcall.length > 0) { setCallAndGrid("", "", newMessage.instance, false); @@ -6904,7 +6903,7 @@ function handleWsjtxDecode(newMessage) newCallsign.qso = false; newCallsign.dxcc = callsignToDxcc(newCallsign.DEcall); newCallsign.px = null; - newCallsign.pota = []; + newCallsign.pota = null; newCallsign.zone = null; newCallsign.vucc_grids = []; newCallsign.propMode = ""; @@ -7013,38 +7012,40 @@ function handleWsjtxDecode(newMessage) if (g_appSettings.potaEnabled == 1) { + callsign.pota = null; if (callsign.DEcall in g_pota.callSpots || callsign.DEcall in g_pota.callSchedule) { - callsign.pota = []; + var now = Date.now(); if (callsign.DEcall in g_pota.callSpots) { - // copies the entire array - callsign.pota = [...g_pota.callSpots[callsign.DEcall]]; + if (g_pota.callSpots[callsign.DEcall] in g_pota.parkSpots && g_pota.parkSpots[g_pota.callSpots[callsign.DEcall]][callsign.DEcall].expire > now) + { + callsign.pota = g_pota.callSpots[callsign.DEcall]; + } } else if (callsign.DEcall in g_pota.callSchedule) { - var now = Date.now(); for (var i in g_pota.callSchedule[callsign.DEcall]) { if (now < g_pota.callSchedule[callsign.DEcall][i].end && now >= g_pota.callSchedule[callsign.DEcall][i].start) { - callsign.pota.push(g_pota.callSchedule[callsign.DEcall][i].id); + callsign.pota = g_pota.callSchedule[callsign.DEcall][i].id; break; } } } - if (callsign.pota.length > 0) + if (callsign.pota) { potaSpotFromDecode(callsign); } else if (CQ == true && msgDXcallsign == "CQ POTA") { - callsign.pota = ["?-????"]; + callsign.pota = "?-????"; } } else if (CQ == true && msgDXcallsign == "CQ POTA") { - callsign.pota = ["?-????"]; + callsign.pota = "?-????"; } } @@ -15516,11 +15517,8 @@ function mediaCheck() } } - if (typeof g_QSOhash[i].pota == "undefined" || g_QSOhash[i].pota == null) - { - g_QSOhash[i].pota = []; - } - + g_QSOhash[i].pota = null; + g_QSOcount++; if (g_QSOhash[i].confirmed) g_QSLcount++; } diff --git a/package.nw/lib/pota.js b/package.nw/lib/pota.js index 833e282..8e6825d 100644 --- a/package.nw/lib/pota.js +++ b/package.nw/lib/pota.js @@ -24,6 +24,7 @@ var g_potaSpotTemplate = { band: "", reference: "", spotTime: 0, + expire: 0, spotter: "", comments: "", source: "GT", @@ -132,10 +133,10 @@ function makeParkFeatures() { if (park in g_pota.parks) { - let parkObj = Object.assign({}, g_parkTemplate); + var parkObj = Object.assign({}, g_parkTemplate); for (const call in g_pota.parkSpots[park]) { - let report = g_pota.parkSpots[park][call]; + var report = g_pota.parkSpots[park][call]; if (parkObj.feature == null && validateMapBandAndMode(report.band, report.mode)) { parkObj.feature = iconFeature(ol.proj.fromLonLat([Number(g_pota.parks[park].longitude), Number(g_pota.parks[park].latitude)]), g_gtParkIconActive, 1); @@ -158,85 +159,106 @@ function makeParkFeatures() function potaSpotFromDecode(callObj) { - for (const i in callObj.pota) + if (myDEcall != "" && myDEcall != "NOCALL") { - let park = callObj.pota[i]; - let spotObj = null; + var park = callObj.pota; - if (!(callObj.DEcall in g_pota.callSpots)) + if (callObj.DEcall in g_pota.callSpots && park in g_pota.parkSpots) { - // new call and park - g_pota.callSpots[callObj.DEcall] = [park]; - } - else if (!g_pota.callSpots[callObj.DEcall].includes(park)) - { - // new park - g_pota.callSpots[callObj.DEcall].push(park); - } + // update spot + var newObj = spotFromCallObj(callObj, park, g_pota.parkSpots[park][callObj.DEcall].count); + g_pota.parkSpots[park][callObj.DEcall] = fillObjectFromTemplate(g_pota.parkSpots[park][callObj.DEcall], newObj); - if (!(park in g_pota.parkSpots)) - { - g_pota.parkSpots[park] = {}; - g_pota.parkSpots[park][callObj.DEcall] = spotFromCallObj(callObj, park, 0, 0); + // may or may not be on screen, so try + if (g_appSettings.potaMapEnabled) + { + addParkSpotFeature(park, g_pota.parkSpots[park][callObj.DEcall]); + } + + var hash = park + callObj.DEcall; + if (!(hash in g_pota.rbnReportTimes) || Date.now() > g_pota.rbnReportTimes[hash]) + { + g_pota.rbnReportTimes[hash] = Date.now() + g_pota.rbnFrequency; + reportPotaRBN(g_pota.parkSpots[park][callObj.DEcall]); + } } - else if (!(callObj.DEcall in g_pota.parkSpots[park])) + else if (callObj.DEcall in g_pota.callSchedule) { - g_pota.parkSpots[park][callObj.DEcall] = spotFromCallObj(callObj, park, 0, 0); + // Looks like it's scheduled, so it's new + g_pota.callSpots[callObj.DEcall] = park; + + if (!(park in g_pota.parkSpots)) + { + g_pota.parkSpots[park] = {}; + } + + var newObj = spotFromCallObj(callObj, park, 0); + newObj.expire = newObj.spotTime + 300000; + g_pota.parkSpots[park][callObj.DEcall] = newObj; + + if (g_appSettings.potaMapEnabled) + { + addParkSpotFeature(park, g_pota.parkSpots[park][callObj.DEcall]); + } + + var hash = park + callObj.DEcall; + if (!(hash in g_pota.rbnReportTimes) || Date.now() > g_pota.rbnReportTimes[hash]) + { + g_pota.rbnReportTimes[hash] = Date.now() + g_pota.rbnFrequency; + reportPotaRBN(g_pota.parkSpots[park][callObj.DEcall]); + } } else { - // update spot - g_pota.parkSpots[park][callObj.DEcall] = spotFromCallObj(callObj, park, g_pota.parkSpots[park][callObj.DEcall].count); - } - - // may or may not be on screen, so try - if (g_appSettings.potaMapEnabled) - { - addParkSpotFeature(park, g_pota.parkSpots[park][callObj.DEcall]); - } - - let hash = park + callObj.DEcall; - if (!(hash in g_pota.rbnReportTimes) || Date.now() > g_pota.rbnReportTimes[hash]) - { - g_pota.rbnReportTimes[hash] = Date.now() + g_pota.rbnFrequency; - reportPotaRBN(g_pota.parkSpots[park][callObj.DEcall]); + console.log("No spot data found"); + if (!(callObj.DEcall in g_pota.callSpots)) + { + console.log("No call spot: " + callObj.DEcall); + } + if (!(park in g_pota.parkSpots)) + { + console.log("No park spot: " + park); + } } } } function reportPotaRBN(callSpot) { - let report = { - activator: callSpot.activator, - spotter: myDEcall + "-#", - frequency: String(parseInt(callSpot.frequency * 1000)), - reference: callSpot.reference, - mode: callSpot.mode, - source: "RBN", - comments: callSpot.comments, - activatorGrid: callSpot.activatorGrid, - spotterGrid: callSpot.spotterGrid - } - - if (Number(report.frequency) > 0) + if (Date.now() < callSpot.expire) { - getPostJSONBuffer( - "https://api.pota.app/spot", - rbnReportResult, - null, - "https", - 443, - report, - 10000, - null, - null - ); + var report = { + activator: callSpot.activator, + spotter: myDEcall + "-#", + frequency: String(parseInt(callSpot.frequency * 1000)), + reference: callSpot.reference, + mode: callSpot.mode, + source: "RBN", + comments: callSpot.comments, + activatorGrid: callSpot.activatorGrid, + spotterGrid: callSpot.spotterGrid + } + + if (Number(report.frequency) > 0) + { + getPostJSONBuffer( + "https://api.pota.app/spot", + rbnReportResult, + null, + "https", + 443, + report, + 10000, + null, + null + ); + } } } function reportPotaQSO(record) { - let report = { + var report = { activator: record.CALL, spotter: record.STATION_CALLSIGN, frequency: record.FREQ, @@ -282,7 +304,7 @@ function rbnReportResult(buffer, flag, cookies) function spotFromCallObj(callObj, park, inCount, rbnTime) { - let callSpot = { + var callSpot = { activator: callObj.DEcall, activatorGrid: callObj.grid, spotter: myDEcall + "-#", @@ -301,7 +323,7 @@ function spotFromCallObj(callObj, park, inCount, rbnTime) function addParkSpotFeature(park, report) { - let parkObj = Object.assign({}, g_parkTemplate); + var parkObj = Object.assign({}, g_parkTemplate); if (park in g_pota.mapParks) { parkObj = g_pota.mapParks[park]; @@ -326,11 +348,11 @@ function processPotaParks(buffer) { try { - let data = JSON.parse(buffer); - let newParks = data.parks; + var data = JSON.parse(buffer); + var newParks = data.parks; for (const park in newParks) { - let locations = newParks[park].locationDesc.split(","); + var locations = newParks[park].locationDesc.split(","); for (const i in locations) { if (locations[i] in data.locations) @@ -381,7 +403,7 @@ function getPotaParks() // This is a shallow copy, don't use with objects that contain other objects or arrays function fillObjectFromTemplate(template, input) { - let object = {}; + var object = {}; for (const key in template) { if (key in input) @@ -399,7 +421,7 @@ function fillObjectFromTemplate(template, input) function uniqueArrayFromArray(input) { - let unique = []; + var unique = []; input.forEach((c) => { if (!unique.includes(c)) @@ -416,37 +438,36 @@ function processPotaSpots(buffer) { try { - let spots = JSON.parse(buffer); + var spots = JSON.parse(buffer); g_pota.callSpots = {}; g_pota.parkSpots = {}; for (const spot in spots) { if (spots[spot].reference in g_pota.parks) { - let newSpot = fillObjectFromTemplate(g_potaSpotTemplate, spots[spot]); + var newSpot = fillObjectFromTemplate(g_potaSpotTemplate, spots[spot]); newSpot.spotTime = Date.parse(newSpot.spotTime + "Z"); newSpot.frequency = parseInt(newSpot.frequency) / 1000; + newSpot.expire = newSpot.spotTime + (Number(newSpot.expire) * 1000); newSpot.band = newSpot.frequency.formatBand(); if (newSpot.spotter == newSpot.activator && newSpot.comments.match(/qrt/gi)) { // don't add the spot, they have self-QRT'ed } + else if (Date.now() > newSpot.expire) + { + // Spot is expired! + } else { - (g_pota.callSpots[newSpot.activator] = g_pota.callSpots[newSpot.activator] || []).push(newSpot.reference); + g_pota.callSpots[newSpot.activator] = newSpot.reference; if (!(newSpot.reference in g_pota.parkSpots)) { g_pota.parkSpots[newSpot.reference] = {}; } - if (newSpot.activator in g_pota.parkSpots[newSpot.reference]) - { - g_pota.parkSpots[newSpot.reference][newSpot.activator] = fillObjectFromTemplate(g_pota.parkSpots[newSpot.reference][newSpot.activator], newSpot); - } - else - { - g_pota.parkSpots[newSpot.reference][newSpot.activator] = newSpot; - } + + g_pota.parkSpots[newSpot.reference][newSpot.activator] = newSpot; } } else @@ -454,12 +475,6 @@ function processPotaSpots(buffer) console.log("PotaSpots: unknown park id: " + spots[spot].reference); } } - - // Sanity dedupe checks - for (const spot in g_pota.callSpots) - { - g_pota.callSpots[spot] = uniqueArrayFromArray(g_pota.callSpots[spot]); - } redrawParks(); } @@ -498,12 +513,12 @@ function processPotaSchedule(buffer) { try { - let schedules = JSON.parse(buffer); + var schedules = JSON.parse(buffer); g_pota.callSchedule = {}; g_pota.parkSchedule = {}; for (const i in schedules) { - let newObj = {}; + var newObj = {}; newObj.id = schedules[i].reference; newObj.start = Date.parse(schedules[i].startDate + "T" + schedules[i].startTime + "Z"); newObj.end = Date.parse(schedules[i].endDate + "T" + schedules[i].endTime + "Z"); @@ -608,10 +623,10 @@ function mouseParkMove() function createParkTipTable(toolElement) { - let worker = ""; + var worker = ""; - let key = toolElement.key; - let now = Date.now(); + var key = toolElement.key; + var now = Date.now(); worker += "
" + key + @@ -645,8 +660,8 @@ function createParkTipTable(toolElement) buffer += "ActivatorStartEndFrequenciesComment"; for (const i in g_pota.parkSchedule[key]) { - let start = g_pota.parkSchedule[key][i].start; - let end = g_pota.parkSchedule[key][i].end; + var start = g_pota.parkSchedule[key][i].start; + var end = g_pota.parkSchedule[key][i].end; if (now < end) { buffer += ""; diff --git a/package.nw/lib/roster/processRosterHunting.js b/package.nw/lib/roster/processRosterHunting.js index 28c50bb..87f83f1 100644 --- a/package.nw/lib/roster/processRosterHunting.js +++ b/package.nw/lib/roster/processRosterHunting.js @@ -518,17 +518,15 @@ function processRosterHunting(callRoster, rosterSettings, awardTracker) } // Hunting for POTAs - if (potaEnabled && huntPOTA.checked == true && callObj.pota.length > 0) + if (potaEnabled && huntPOTA.checked == true && callObj.pota) { - let huntTotal = callObj.pota.length; + let huntTotal = 1; let workedFound = 0; - for (const index in callObj.pota) - { - let hash = g_dayAsString + callsign + callObj.pota[index] + (rosterSettings.layeredMode ? layeredHashSuffix : workHashSuffix); + let hash = g_dayAsString + callsign + callObj.pota + (rosterSettings.layeredMode ? layeredHashSuffix : workHashSuffix); - if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.pota) workedFound++; - } + if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.pota) workedFound++; + if (workedFound != huntTotal) { shouldAlert = true; diff --git a/package.nw/lib/roster/rosterColumns.js b/package.nw/lib/roster/rosterColumns.js index 535854c..d3638d5 100644 --- a/package.nw/lib/roster/rosterColumns.js +++ b/package.nw/lib/roster/rosterColumns.js @@ -400,14 +400,9 @@ const ROSTER_COLUMNS = { function potaColumnRef(callObj) { - if (callObj.pota.length > 0) + if (callObj.pota) { - let value = callObj.pota[0]; - if (callObj.pota.length > 1) - { - value += " +" + String(callObj.pota.length - 1); - } - return value; + return callObj.pota; } else { @@ -417,14 +412,13 @@ function potaColumnRef(callObj) function potaColumnHover(callObj) { - let value = "" - for (let i in callObj.pota) + let value = ""; + + if (callObj.pota in window.opener.g_pota.parks) { - if (callObj.pota[i] in window.opener.g_pota.parks) - { - value += callObj.pota[i] + " - " + window.opener.g_pota.parks[callObj.pota[i]].name + "\n"; - } + value += callObj.pota + " - " + window.opener.g_pota.parks[callObj.pota].name + "\n"; } + return value; }