[fix](trx): ignore FTx farewell pseudo-locators and narrow split slider

This commit is contained in:
2026-03-05 19:24:54 +01:00
parent 05e72e21e8
commit 49f44e84a0
4 changed files with 34 additions and 8 deletions
@@ -130,7 +130,7 @@ function renderFt8Message(message) {
while (j < message.length && isAlphaNum(message[j])) j++; while (j < message.length && isAlphaNum(message[j])) j++;
const token = message.slice(i, j); const token = message.slice(i, j);
const grid = token.toUpperCase(); const grid = token.toUpperCase();
if (/^[A-R]{2}\d{2}(?:[A-X]{2})?$/.test(grid)) { if (isMaidenheadGridToken(grid)) {
out += `<span class="ft8-locator">${grid}</span>`; out += `<span class="ft8-locator">${grid}</span>`;
} else { } else {
out += escapeHtml(token); out += escapeHtml(token);
@@ -154,7 +154,7 @@ function extractAllGrids(message) {
while (j < message.length && isAlphaNum(message[j])) j++; while (j < message.length && isAlphaNum(message[j])) j++;
const token = message.slice(i, j); const token = message.slice(i, j);
const grid = token.toUpperCase(); const grid = token.toUpperCase();
if (/^[A-R]{2}\d{2}(?:[A-X]{2})?$/.test(grid) && !seen.has(grid)) { if (isMaidenheadGridToken(grid) && !seen.has(grid)) {
seen.add(grid); seen.add(grid);
out.push(grid); out.push(grid);
} }
@@ -172,12 +172,22 @@ function extractLikelyCallsign(message) {
if (!token) continue; if (!token) continue;
if (token.length < 3 || token.length > 12) continue; if (token.length < 3 || token.length > 12) continue;
if (token === "CQ" || token === "DE" || token === "QRZ" || token === "DX") continue; if (token === "CQ" || token === "DE" || token === "QRZ" || token === "DX") continue;
if (/^[A-R]{2}\d{2}(?:[A-X]{2})?$/.test(token)) continue; if (isMaidenheadGridToken(token)) continue;
if (/^[A-Z0-9/]{1,5}\d[A-Z0-9/]{1,6}$/.test(token)) return token; if (/^[A-Z0-9/]{1,5}\d[A-Z0-9/]{1,6}$/.test(token)) return token;
} }
return null; return null;
} }
function isFtxFarewellToken(token) {
const normalized = String(token || "").trim().toUpperCase();
return normalized === "RR73" || normalized === "73" || normalized === "RR";
}
function isMaidenheadGridToken(token) {
const normalized = String(token || "").trim().toUpperCase();
return /^[A-R]{2}\d{2}(?:[A-X]{2})?$/.test(normalized) && !isFtxFarewellToken(normalized);
}
function escapeHtml(input) { function escapeHtml(input) {
return input return input
.replaceAll("&", "&amp;") .replaceAll("&", "&amp;")
@@ -86,7 +86,7 @@ function extractAllGrids(message) {
const parts = message.toUpperCase().split(/[^A-Z0-9]+/); const parts = message.toUpperCase().split(/[^A-Z0-9]+/);
for (const token of parts) { for (const token of parts) {
if (!token) continue; if (!token) continue;
if (/^[A-R]{2}\d{2}(?:[A-X]{2})?$/.test(token) && !seen.has(token)) { if (isMaidenheadGridToken(token) && !seen.has(token)) {
seen.add(token); seen.add(token);
out.push(token); out.push(token);
} }
@@ -100,12 +100,22 @@ function extractLikelyCallsign(message) {
if (!token) continue; if (!token) continue;
if (token.length < 3 || token.length > 12) continue; if (token.length < 3 || token.length > 12) continue;
if (token === "CQ" || token === "DE" || token === "QRZ" || token === "DX") continue; if (token === "CQ" || token === "DE" || token === "QRZ" || token === "DX") continue;
if (/^[A-R]{2}\d{2}(?:[A-X]{2})?$/.test(token)) continue; if (isMaidenheadGridToken(token)) continue;
if (/^[A-Z0-9/]{1,5}\d[A-Z0-9/]{1,6}$/.test(token)) return token; if (/^[A-Z0-9/]{1,5}\d[A-Z0-9/]{1,6}$/.test(token)) return token;
} }
return null; return null;
} }
function isFtxFarewellToken(token) {
const normalized = String(token || "").trim().toUpperCase();
return normalized === "RR73" || normalized === "73" || normalized === "RR";
}
function isMaidenheadGridToken(token) {
const normalized = String(token || "").trim().toUpperCase();
return /^[A-R]{2}\d{2}(?:[A-X]{2})?$/.test(normalized) && !isFtxFarewellToken(normalized);
}
function applyWsprFilterToRow(row) { function applyWsprFilterToRow(row) {
if (!wsprFilterText) { if (!wsprFilterText) {
row.style.display = ""; row.style.display = "";
@@ -548,7 +548,7 @@ small { color: var(--text-muted); }
#signal-split-slider { #signal-split-slider {
writing-mode: vertical-lr; writing-mode: vertical-lr;
direction: rtl; direction: rtl;
width: 0.76rem; width: 0.62rem;
height: 5.4rem; height: 5.4rem;
margin: 0; margin: 0;
accent-color: var(--accent-green); accent-color: var(--accent-green);
@@ -1850,7 +1850,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
#signal-split-slider { #signal-split-slider {
writing-mode: horizontal-tb; writing-mode: horizontal-tb;
direction: ltr; direction: ltr;
width: 4.6rem; width: 4rem;
height: 1rem; height: 1rem;
cursor: ew-resize; cursor: ew-resize;
} }
+7 -1
View File
@@ -219,7 +219,7 @@ fn normalize_token(token: &str) -> String {
fn parse_locator(message: &str) -> Option<String> { fn parse_locator(message: &str) -> Option<String> {
message.split_whitespace().find_map(|raw| { message.split_whitespace().find_map(|raw| {
let t = normalize_token(raw); let t = normalize_token(raw);
if is_locator(&t) { if !is_ftx_farewell_token(&t) && is_locator(&t) {
Some(t) Some(t)
} else { } else {
None None
@@ -272,6 +272,10 @@ fn is_locator(token: &str) -> bool {
} }
} }
fn is_ftx_farewell_token(token: &str) -> bool {
matches!(token, "RR73" | "73" | "RR")
}
fn maidenhead_from_lat_lon(lat: f64, lon: f64) -> String { fn maidenhead_from_lat_lon(lat: f64, lon: f64) -> String {
let lat = lat.clamp(-90.0, 90.0 - f64::EPSILON); let lat = lat.clamp(-90.0, 90.0 - f64::EPSILON);
let lon = lon.clamp(-180.0, 180.0 - f64::EPSILON); let lon = lon.clamp(-180.0, 180.0 - f64::EPSILON);
@@ -433,6 +437,8 @@ mod tests {
Some("SP2SJG".to_string()) Some("SP2SJG".to_string())
); );
assert_eq!(parse_locator("CQ SP2SJG JO93"), Some("JO93".to_string())); assert_eq!(parse_locator("CQ SP2SJG JO93"), Some("JO93".to_string()));
assert_eq!(parse_locator("CQ SP2SJG RR73"), None);
assert_eq!(parse_locator("SP2SJG RR 73"), None);
} }
#[test] #[test]