function processRosterHunting(callRoster, rosterSettings, awardTracker) { // these lets, do they rely on anything between the top and here? // if not could they be put in the let list at the beginning? let hasGtPin = false; let inversionAlpha = "DD"; let row = "#000000"; let bold = "#000000;font-weight: bold;"; let unconf = "background-clip:padding-box;box-shadow: 0 0 7px 3px inset "; let layeredAlpha = "77"; let layeredInversionAlpha = "66"; let layeredUnconf = "background-clip:padding-box;box-shadow: 0 0 4px 2px inset "; let layeredUnconfAlpha = "AA"; const currentYear = new Date().getFullYear(); const currentYearSuffix = `’${currentYear - 2000}`; const potaEnabled = (window.opener.GT.appSettings.potaEnabled == 1); // TODO: Hunting results might be used to filter, based on the "Callsigns: Only Wanted" option, // so maybe we can move this loop first, and add a check to the filtering loop? // award tracker overrides let awardTrackerOverrides = { call: false, grids: false, dxcc: false, states: false, cnty: false, cqz: false, px: false, cont: false }; if (CR.rosterSettings.reference == LOGBOOK_AWARD_TRACKER) { for (let key in awardTracker) { if (awardTracker[key].enable) { awardTrackerOverrides[awardTracker[key].rule.type] = true; } } } // Second loop, hunting and highlighting for (const callHash in callRoster) { let entry = callRoster[callHash]; let callObj = entry.callObj; // Special case check for called station if (callObj.qrz == true && entry.tx == false) { // The instance has to be enabled if (window.opener.GT.instances[callObj.instance].crEnable == true) { // Calling us, but we wouldn't normally display // If they are not ignored or we're in a QSO with them, let it through // TODO: This is here because it's after the filtering stage if ((!(entry.DEcall in CR.blockedCalls) && !(callObj.dxcc in CR.blockedDxcc)) || window.opener.GT.instances[callObj.instance].status.DXcall == entry.DEcall) { entry.tx = true; } } } // Only render entries with `tx == true`, ignore the rest if (entry.tx == true) { // In layered mode ("Hunting: mixed") the workHashSuffix becomes a more stricter 'live band', // while the layered suffix is a broader 'mixed band' let workHashSuffix, layeredHashSuffix; if (rosterSettings.layeredMode) { workHashSuffix = hashMaker("", callObj, rosterSettings.layeredMode); layeredHashSuffix = hashMaker("", callObj, CR.rosterSettings.reference); } else { workHashSuffix = hashMaker("", callObj, CR.rosterSettings.reference); layeredHashSuffix = false } let workHash = workHashSuffix; // TODO: Remove after replacing all occurrences with Suffix let callsign = entry.DEcall; callObj.hunting = {}; callObj.callFlags = {}; callObj.style = callObj.style || {}; callObj.DEcallHTML = null; callObj.DXcallHTML = null; callObj.msgHTML = null; let colorObject = Object(); let callPointer = callObj.CQ == true ? "cursor:pointer" : ""; let call = "#FFFF00"; let grid = "#00FFFF"; let calling = "#90EE90"; let dxcc = "#FFA500"; let state = "#90EE90"; let cnty = "#CCDD00"; let cont = "#00DDDD"; let pota = "#fbb6fc"; let cqz = "#DDDDDD"; let ituz = "#DDDDDD"; let wpx = "#FFFF00"; hasGtPin = false; let shouldAlert = false; let callBg, gridBg, callingBg, dxccBg, stateBg, cntyBg, contBg, potaBg, cqzBg, ituzBg, wpxBg, gtBg; let callConf, gridConf, callingConf, dxccConf, stateConf, cntyConf, contConf, potaConf, cqzConf, ituzConf, wpxConf; callBg = gridBg = callingBg = dxccBg = stateBg = cntyBg = contBg = potaBg = cqzBg = ituzBg = wpxBg = gtBg = row; callConf = gridConf = callingConf = dxccConf = stateConf = cntyConf = contConf = potaConf = cqzConf = ituzConf = wpxConf = ""; let cntyPointer = (callObj.cnty && callObj.qual == false) ? "cursor: pointer;" : ""; let didWork = false; let hash = callsign + workHashSuffix; // Call worked in current logbook settings, regardless of hunting mode if (hash in CR.worked.call) { callObj.callFlags.worked = true; didWork = true; callConf = `${unconf}${call}${inversionAlpha};`; if (hash in CR.confirmed.call) { callObj.callFlags.confirmed = true; callPointer = "text-decoration: line-through; "; callConf = ""; } } // Calls that have OAMS chat support if (callsign in window.opener.GT.gtCallsigns) { callObj.gt = 0; for (const cid in window.opener.GT.gtCallsigns[callsign]) { if (cid in window.opener.GT.gtFlagPins && window.opener.GT.gtFlagPins[cid].canmsg == true) { // found the first one we can message, break now callObj.callFlags.oams = true; callObj.gt = cid; hasGtPin = true; break; } } } else { callObj.gt = 0; } // We only do hunt highlighting when showing all entries // This means "Callsigns: All Traffic", "Callsigns: All Traffic/Only Wanted" // There is no highlighting in other modes if (rosterSettings.callMode == "all") { // Skip when "only new calls" // Questions: Move to the first loop? Why only skip new calls in "all traffic" and not other modes? if (allOnlyNew.checked == true && didWork && callObj.qrz == false) { entry.tx = false; continue; } // Special Calls if (callObj.DEcall.match("^[A-Z][0-9][A-Z](/w+)?$")) { callObj.style.call = "class='oneByOne'"; } // Entries currently calling or being called by us if (callObj.DEcall == window.opener.GT.instances[callObj.instance].status.DXcall) { if (window.opener.GT.instances[callObj.instance].status.TxEnabled == 1) { callObj.hunting.call = "calling"; callObj.style.call = "class='dxCalling'"; } else { callObj.hunting.call = "caller"; callObj.style.call = "class='dxCaller'"; } } // Hunting for callsigns if (huntCallsign.checked || awardTrackerOverrides.call) { let hash = callsign + workHashSuffix; let layeredHash = rosterSettings.layeredMode && (callsign + layeredHashSuffix) if (rosterSettings.huntIndex && !(hash in rosterSettings.huntIndex.call)) { shouldAlert |= true; callObj.reason.push("call"); if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.call) { if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.call) { callObj.hunting.call = "worked-and-mixed"; callConf = `${layeredUnconf}${call}${layeredUnconfAlpha};`; callBg = `${call}${layeredInversionAlpha}`; call = bold; } // /* Currently we don't have a way to figure out // * if the call is worked only in this band or also others, // * so we cannot cover this particular combination // * and have to default to just showing it as plain "worked" // */ // else if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.call) // { // callObj.hunting.call = "worked-and-mixed-worked"; // callConf = `${layeredUnconf}${call}${layeredAlpha};`; // } else { callObj.hunting.call = "worked"; callConf = `${unconf}${call}${inversionAlpha};`; } } else { if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.call) { callObj.hunting.call = "mixed"; callBg = `${call}${layeredAlpha};`; call = bold; } else if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.call) { callObj.hunting.call = "mixed-worked"; callConf = `${unconf}${call}${layeredAlpha};`; } else { callObj.hunting.call = "hunted"; callBg = `${call}${inversionAlpha};`; call = bold; } } } } if (huntWatcher.checked) { shouldAlert |= processWatchers(callObj); } // Hunting for "stations calling you" if (huntQRZ.checked == true && callObj.qrz == true) { callObj.callFlags.calling = true callObj.hunting.qrz = "hunted"; shouldAlert = true; callObj.reason.push("qrz"); } // Hunting for stations with OAMS if (huntOAMS.checked == true && hasGtPin == true) { callObj.hunting.oams = "hunted"; shouldAlert = true; callObj.reason.push("oams"); } // Hunting for grids if ((huntGrid.checked || awardTrackerOverrides.grids) && callObj.grid.length > 1) { let hash = callObj.grid.substr(0, 4) + workHashSuffix; let layeredHash = rosterSettings.layeredMode && (callObj.grid.substr(0, 4) + layeredHashSuffix) if (rosterSettings.huntIndex && !(hash in rosterSettings.huntIndex.grid)) { shouldAlert = true; callObj.reason.push("grid"); if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.grid) { if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.grid) { callObj.hunting.grid = "worked-and-mixed"; gridConf = `${layeredUnconf}${grid}${layeredUnconfAlpha};`; gridBg = `${grid}${layeredInversionAlpha}`; grid = bold; } else { callObj.hunting.grid = "worked"; gridConf = `${unconf}${grid}${inversionAlpha};`; } } else { if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.grid) { callObj.hunting.grid = "mixed"; gridBg = `${grid}${layeredAlpha};`; grid = bold; } else if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.grid) { callObj.hunting.grid = "mixed-worked"; gridConf = `${unconf}${grid}${layeredAlpha};`; } else { callObj.hunting.grid = "hunted"; gridBg = `${grid}${inversionAlpha};`; grid = bold; } } } } // Hunting for DXCC if (huntDXCC.checked || awardTrackerOverrides.dxcc || awardTrackerOverrides.dxcc2band) { let hash = String(callObj.dxcc) + "|" + workHashSuffix; let layeredHash = rosterSettings.layeredMode && (String(callObj.dxcc) + "|" + layeredHashSuffix) if (rosterSettings.huntIndex && !(hash in rosterSettings.huntIndex.dxcc)) { shouldAlert = true; callObj.reason.push("dxcc"); if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.dxcc) { if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.dxcc) { callObj.hunting.dxcc = "worked-and-mixed"; dxccConf = `${layeredUnconf}${dxcc}${layeredUnconfAlpha};`; dxccBg = `${dxcc}${layeredInversionAlpha}`; dxcc = bold; } else { callObj.hunting.dxcc = "worked"; dxccConf = `${unconf}${dxcc}${inversionAlpha};`; } } else { if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.dxcc) { callObj.hunting.dxcc = "mixed"; dxccBg = `${dxcc}${layeredAlpha};`; dxcc = bold; } else if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.dxcc) { callObj.hunting.dxcc = "mixed-worked"; dxccConf = `${unconf}${dxcc}${layeredAlpha};`; } else { callObj.hunting.dxcc = "hunted"; dxccBg = `${dxcc}${inversionAlpha};`; dxcc = bold; } } } callObj.dxccSuffix = null if (huntMarathon.checked && callObj.hunting.dxcc != "hunted" && callObj.hunting.dxcc != "checked") { callObj.reason.push("dxcc-marathon"); let hash = `${callObj.dxcc}-${currentYear}`; if (rosterSettings.huntIndex && !(hash in rosterSettings.huntIndex.dxcc)) { if (!rosterSettings.workedIndex || !(hash in rosterSettings.workedIndex.dxcc)) { callObj.dxccSuffix = currentYearSuffix; callObj.hunting.dxccMarathon = "hunted"; if (!callObj.hunting.dxcc) { dxccConf = `${unconf}${dxcc}${layeredAlpha};`; } } } } } // Hunting for US States if ((huntState.checked || awardTrackerOverrides.states) && window.opener.GT.callsignLookups.ulsUseEnable == true) { let stateSearch = callObj.state; let finalDxcc = callObj.dxcc; if (finalDxcc == 291 || finalDxcc == 110 || finalDxcc == 6) { if (stateSearch in window.opener.GT.StateData) { let hash = stateSearch + workHashSuffix; let layeredHash = rosterSettings.layeredMode && (stateSearch + layeredHashSuffix) if (rosterSettings.huntIndex && !(hash in rosterSettings.huntIndex.state)) { shouldAlert = true; callObj.reason.push("state"); if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.state) { if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.state) { callObj.hunting.state = "worked-and-mixed"; stateConf = `${layeredUnconf}${state}${layeredUnconfAlpha};`; stateBg = `${state}${layeredInversionAlpha}`; state = bold; } else { callObj.hunting.state = "worked"; stateConf = `${unconf}${state}${inversionAlpha};`; } } else { if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.state) { callObj.hunting.state = "mixed"; stateBg = `${state}${layeredAlpha};`; state = bold; } else if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.state) { callObj.hunting.state = "mixed-worked"; stateConf = `${unconf}${state}${layeredAlpha};`; } else { callObj.hunting.state = "hunted"; stateBg = `${state}${inversionAlpha};`; state = bold; } } } } } } // Hunting for US Counties if ((huntCounty.checked || awardTrackerOverrides.cnty) && window.opener.GT.callsignLookups.ulsUseEnable == true) { let finalDxcc = callObj.dxcc; if (callObj.cnty && (finalDxcc == 291 || finalDxcc == 110 || finalDxcc == 6 || finalDxcc == 202) && callObj.cnty.length > 0) { let hash = callObj.cnty + (rosterSettings.layeredMode ? layeredHashSuffix : workHashSuffix); if ((rosterSettings.huntIndex && !(hash in rosterSettings.huntIndex.cnty)) || callObj.qual == false) { if (callObj.qual == false) { let counties = window.opener.GT.zipToCounty[callObj.zipcode]; let foundHit = false; for (const cnt in counties) { let hh = counties[cnt] + workHash; callObj.cnty = counties[cnt]; if (rosterSettings.huntIndex && !(hh in rosterSettings.huntIndex.cnty)) { foundHit = true; break; } } if (foundHit) shouldAlert = true; } else { shouldAlert = true; } if (shouldAlert) { callObj.reason.push("cnty"); if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.cnty) { callObj.hunting.cnty = "worked"; cntyConf = `${unconf}${cnty}${inversionAlpha};`; } else { callObj.hunting.cnty = "hunted"; cntyBg = `${cnty}${inversionAlpha}`; cnty = bold; } } } } } // Hunting for POTAs if (potaEnabled && huntPOTA.checked == true && callObj.pota) { let hash = CR.dayAsString + callsign + callObj.pota + (rosterSettings.layeredMode ? layeredHashSuffix : workHashSuffix); // POTA is only in the worked list if (!(hash in CR.worked.pota)) { shouldAlert = true; callObj.reason.push("pota"); callObj.hunting.pota = "hunted"; potaBg = `${pota}${inversionAlpha};`; pota = bold; } } // Hunting for CQ Zones if ((huntCQz.checked || awardTrackerOverrides.cqz) && callObj.cqz) { let huntTotal = 1; let huntFound = 0, layeredFound = 0, workedFound = 0, layeredWorkedFound = 0, marathonFound = 0; let hash = callObj.cqz + "|" + workHashSuffix; let layeredHash = rosterSettings.layeredMode && (callObj.cqz + "|" + layeredHashSuffix); let marathonHash = huntMarathon.checked && `${callObj.cqz}-${currentYear}`; if (rosterSettings.huntIndex && hash in rosterSettings.huntIndex.cqz) huntFound++; if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.cqz) layeredFound++; if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.cqz) workedFound++; if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.cqz) layeredWorkedFound++; if (marathonHash) { if (rosterSettings.huntIndex && marathonHash in rosterSettings.huntIndex.cqz) marathonFound++; else if (rosterSettings.workedIndex && marathonHash in rosterSettings.workedIndex.cqz) marathonFound++; } if (huntFound != huntTotal) { shouldAlert = true; callObj.reason.push("cqz"); if (rosterSettings.workedIndex && workedFound == huntTotal) { if (rosterSettings.layeredMode && layeredFound == huntTotal) { callObj.hunting.cqz = "worked-and-mixed"; cqzConf = `${layeredUnconf}${cqz}${layeredUnconfAlpha};`; cqzBg = `${cqz}${layeredInversionAlpha}`; cqz = bold; } else { callObj.hunting.cqz = "worked"; cqzConf = `${unconf}${cqz}${inversionAlpha};`; } } else { if (rosterSettings.layeredMode && layeredFound == huntTotal) { callObj.hunting.cqz = "mixed"; cqzBg = `${cqz}${layeredAlpha};`; cqz = bold; } else if (rosterSettings.layeredMode && layeredWorkedFound == huntTotal) { callObj.hunting.cqz = "mixed-worked"; cqzConf = `${unconf}${cqz}${layeredAlpha};`; } else { callObj.hunting.cqz = "hunted"; cqzBg = `${cqz}${inversionAlpha};`; cqz = bold; } } } callObj.cqzSuffix = null; if (huntMarathon.checked && callObj.hunting.cqz != "hunted" && callObj.hunting.cqz != "worked") { if (marathonFound != huntTotal) { callObj.reason.push("cqz-marathon"); callObj.cqzSuffix = currentYearSuffix; callObj.hunting.cqzMarathon = "hunted"; if (!callObj.hunting.cqz) { cqzConf = `${unconf}${cqz}${layeredAlpha};`; } } } } // Hunting for ITU Zones if (huntITUz.checked == true && callObj.ituz) { let huntTotal = 1; let huntFound = 0, layeredFound = 0, workedFound = 0, layeredWorkedFound = 0; let hash = callObj.ituz + "|" + workHashSuffix; let layeredHash = rosterSettings.layeredMode && (callObj.ituz + "|" + layeredHashSuffix) if (rosterSettings.huntIndex && hash in rosterSettings.huntIndex.ituz) huntFound++; if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.ituz) layeredFound++; if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.ituz) workedFound++; if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.ituz) layeredWorkedFound++; if (huntFound != huntTotal) { shouldAlert = true; callObj.reason.push("ituz"); if (rosterSettings.workedIndex && workedFound == huntTotal) { if (rosterSettings.layeredMode && layeredFound == huntTotal) { callObj.hunting.ituz = "worked-and-mixed"; ituzConf = `${layeredUnconf}${ituz}${layeredUnconfAlpha};`; ituzBg = `${ituz}${layeredInversionAlpha}`; ituz = bold; } else { callObj.hunting.ituz = "worked"; ituzConf = `${unconf}${ituz}${inversionAlpha};`; } } else { if (rosterSettings.layeredMode && layeredFound == huntTotal) { callObj.hunting.ituz = "mixed"; ituzBg = `${ituz}${layeredAlpha};`; ituz = bold; } else if (rosterSettings.layeredMode && layeredWorkedFound == huntTotal) { callObj.hunting.ituz = "mixed-worked"; ituzConf = `${unconf}${ituz}${layeredAlpha};`; } else { callObj.hunting.ituz = "hunted"; ituzBg = `${ituz}${inversionAlpha};`; ituz = bold; } } } } // Hunting for WPX (Prefixes) if ((huntPX.checked || awardTrackerOverrides.px) && callObj.px) { let hash = String(callObj.px) + workHashSuffix; let layeredHash = rosterSettings.layeredMode && (String(callObj.px) + layeredHashSuffix) if (rosterSettings.huntIndex && !(hash in rosterSettings.huntIndex.px)) { shouldAlert = true; callObj.reason.push("wpx"); if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.px) { if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.px) { callObj.hunting.wpx = "worked-and-mixed"; wpxConf = `${layeredUnconf}${wpx}${layeredUnconfAlpha};`; wpxBg = `${wpx}${layeredInversionAlpha}`; wpx = bold; } else { callObj.hunting.wpx = "worked"; wpxConf = `${unconf}${wpx}${inversionAlpha};`; } } else { if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.px) { callObj.hunting.wpx = "mixed"; wpxBg = `${wpx}${layeredAlpha};`; wpx = bold; } else if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.px) { callObj.hunting.wpx = "mixed-worked"; wpxConf = `${unconf}${wpx}${layeredAlpha};`; } else { callObj.hunting.wpx = "hunted"; wpxBg = `${wpx}${inversionAlpha};`; wpx = bold; } } } } // Hunting for Continents if ((huntCont.checked || awardTrackerOverrides.cont) && callObj.cont) { let hash = String(callObj.cont) + workHashSuffix; let layeredHash = rosterSettings.layeredMode && (String(callObj.cont) + layeredHashSuffix) if (rosterSettings.huntIndex && !(hash in rosterSettings.huntIndex.cont)) { shouldAlert = true; callObj.reason.push("cont"); if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.cont) { if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.cont) { callObj.hunting.cont = "worked-and-mixed"; contConf = `${layeredUnconf}${cont}${layeredUnconfAlpha};`; contBg = `${cont}${layeredInversionAlpha}`; cont = bold; } else { callObj.hunting.cont = "worked"; contConf = `${unconf}${cont}${inversionAlpha};`; } } else { if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.cont) { callObj.hunting.cont = "mixed"; contBg = `${cont}${layeredAlpha};`; cont = bold; } else if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.cont) { callObj.hunting.cont = "mixed-worked"; contConf = `${unconf}${cont}${layeredAlpha};`; } else { callObj.hunting.cont = "hunted"; contBg = `${cont}${inversionAlpha};`; cont = bold; } } } } } // Station is calling us if (callObj.DXcall == window.opener.GT.appSettings.myCall) { callingBg = "#0000FF" + inversionAlpha; calling = "#FFFF00;text-shadow: 0px 0px 2px #FFFF00"; } else if ((callObj.CQ == true || (CR.rosterSettings.wantRRCQ && callObj.RR73 == true)) && !CR.rosterSettings.cqOnly) { callingBg = calling + inversionAlpha; calling = bold; // If treating RR73/73 as CQ, soften highlighting to help differentiate foreshadow from an actual CQ if (CR.rosterSettings.wantRRCQ && callObj.RR73 == true) { callingConf = `${unconf}#90EE90${inversionAlpha};`; calling = `#90EE90${inversionAlpha};` callingBg = "#000000" } } let huzzah = ""; // Uncomment to test // callObj.DXcall = "CQ GT"; if (CR.rosterSettings.animateCQGT == true && callObj.CQ == true && (callObj.DXcall == "CQ GT" || callObj.DXcall == "GridTracker")) { huzzah = "class='huzzah' "; callObj.DXcall = "GridTracker"; calling = "white"; } else if (CR.rosterSettings.animateCQGT == false && callObj.DXcall == "GridTracker") { callObj.DXcall = "CQ GT"; } // Assemble all styles colorObject.call = "style='" + callConf + "background-color:" + callBg + ";color:" + call + ";" + callPointer + "'"; colorObject.grid = "style='" + gridConf + "background-color:" + gridBg + ";color:" + grid + ";cursor:pointer'"; colorObject.calling = huzzah + "style='" + callingConf + "background-color:" + callingBg + ";color:" + calling + "'"; colorObject.dxcc = "style='" + dxccConf + "background-color:" + dxccBg + ";color:" + dxcc + "'"; colorObject.state = "style='" + stateConf + "background-color:" + stateBg + ";color:" + state + "'"; colorObject.cnty = "style='" + cntyConf + "background-color:" + cntyBg + ";color:" + cnty + ";" + cntyPointer + "'"; colorObject.pota = "style='" + potaConf + "background-color:" + potaBg + ";color:" + pota + "'"; colorObject.cont = "style='" + contConf + "background-color:" + contBg + ";color:" + cont + "'"; colorObject.cqz = "style='" + cqzConf + "background-color:" + cqzBg + ";color:" + cqz + "'"; colorObject.ituz = "style='" + ituzConf + "background-color:" + ituzBg + ";color:" + ituz + "'"; colorObject.px = "style='" + wpxConf + "background-color:" + wpxBg + ";color:" + wpx + "'"; // callObj.shouldAlert ||= shouldAlert; // eslint doesn't like this, why? // If alert was set (award tracker), don't clear it if (!callObj.shouldAlert) { callObj.shouldAlert = shouldAlert; } callObj.style = colorObject; rosterSettings.modes[callObj.mode] = true; rosterSettings.bands[callObj.band] = true; } } } function buildWatcher(watcher) { if (watcher.regex) { watcher.test = new RegExp(watcher.text, "gi"); } else { watcher.test = new RegExp("^" + watcher.text + "$", "gi"); } if (watcher.type == "Callsign") { watcher.source = "DEcall"; watcher.html = "DEcallHTML"; } else if (watcher.type == "Calling") { watcher.source = "DXcall"; watcher.html = "DXcallHTML"; } else { watcher.source = "msg"; watcher.html = "msgHTML"; } return watcher.test; } function processWatchers(callObj) { let now = Date.now(); for (let key in CR.watchers) { let watcher = CR.watchers[key]; if (watcher.watch) { if (watcher.start && now < watcher.startTime) continue; if (watcher.end && now > watcher.endTime) { if (watcher.autoDelete) { // Don't call deleteWatcher() as it calls the roster renderer delete CR.watchers[key]; writeRosterSettings(); wantRenderWatchersTab(); } else { watcher.watch = false; wantRenderWatchersTab(); } continue; } watcher.test = watcher.test || buildWatcher(watcher); try { if (callObj[watcher.source].match(watcher.test)) { callObj.reason.push("watcher"); callObj.hunting.watcher = "hunted"; callObj.watcherKey = key; let htmlPrevent = htmlEntities(callObj[watcher.source]); callObj[watcher.html] = htmlPrevent.replace(watcher.test, (x, y) => `${x}`); return true; } } catch (e) {} } } return false; }