Compare commits

...
6 Commits
24 changed files with 252 additions and 101 deletions
+3
View File
@@ -258,6 +258,9 @@ sig_ref_data_providers:
- class: "DTMBA"
enabled: true
- class: "COTA"
enabled: true
- class: "Toilets"
enabled: true
+87 -11
View File
@@ -16,164 +16,240 @@ SIGS = [
comment_names=["POTA"],
description="Parks on the Air",
ref_regex=r"[A-Z]{2}\-\d{4,5}|K\-TEST",
icon="fa-tree",
refs_globally_unique=False
),
SIG(
name="SOTA",
comment_names=["SOTA"],
description="Summits on the Air",
ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}",
icon="fa-mountain-sun",
refs_globally_unique=False
),
SIG(
name="WWFF",
comment_names=["WWFF"],
description="World Wide Flora & Fauna",
ref_regex=r"[A-Z0-9]{1,3}FF\-\d{4}",
icon="fa-seedling",
refs_globally_unique=True
),
SIG(
name="GMA",
comment_names=["GMA"],
description="Global Mountain Activity",
ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}",
icon="fa-person-hiking",
refs_globally_unique=False
),
SIG(
name="WWBOTA",
comment_names=["WWBOTA", "BOTA"],
description="Worldwide Bunkers on the Air",
ref_regex=r"B\/[A-Z0-9]{1,3}\-\d{3,4}",
icon="fa-radiation",
refs_globally_unique=True
),
SIG(
name="HEMA",
comment_names=["HEMA"],
description="HuMPs Excluding Marilyns Award",
ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{3}\-\d{3}",
icon="fa-mound",
refs_globally_unique=False
),
SIG(
name="IOTA",
comment_names=["IOTA"],
description="Islands on the Air",
ref_regex=r"[A-Z]{2}\-\d{3}",
icon="fa-book-atlas",
refs_globally_unique=False
),
SIG(
name="GMA Islands",
comment_names=[],
description="Global Mountain Activity - Islands",
ref_regex=r"(([A-Z]{2}\-\d{3})|([A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}))",
),
SIG(
name="MOTA",
comment_names=["MOTA"],
description="Mills on the Air",
ref_regex=r"X\d{4,6}",
icon="fa-person-hiking",
refs_globally_unique=False
),
SIG(
name="ARLHS",
comment_names=["ARLHS"],
description="Amateur Radio Lighthouse Society",
ref_regex=r"[A-Z]{3}[\- ]\d{3,4}",
icon="fa-house-flood-water",
refs_globally_unique=False
),
SIG(
name="ILLW",
comment_names=["ILLW"],
description="International Lighthouse & Lightship Weekend",
ref_regex=r"[A-Z]{2}\d{4}",
icon="fa-house-flood-water",
refs_globally_unique=False
),
SIG(
name="MOTA",
comment_names=["MOTA"],
description="Mills on the Air",
ref_regex=r"X\d{4,6}",
icon="fa-fan",
refs_globally_unique=True
),
SIG(
name="SIOTA",
comment_names=["SIOTA"],
description="Silos on the Air",
ref_regex=r"[A-Z]{2}\-[A-Z]{3}\d",
icon="fa-wheat-awn",
refs_globally_unique=False
),
SIG(
name="WCA",
comment_names=["WCA"],
description="World Castles Award",
ref_regex=r"[A-Z0-9]{1,3}\-\d{5}",
icon="fa-chess-rook",
refs_globally_unique=False
),
SIG(
name="ZLOTA",
comment_names=["ZLOTA"],
description="New Zealand on the Air",
ref_regex=r"ZL[A-Z]/[A-Z]{2}\-\d{3,4}",
icon="fa-kiwi-bird",
region_flag="🇳🇿",
refs_globally_unique=True
),
SIG(
name="WOTA",
comment_names=["WOTA"],
description="Wainwrights on the Air",
ref_regex=r"[A-Z]{3}-[0-9]{2}",
icon="fa-w",
region_flag="🇬🇧",
refs_globally_unique=False
),
SIG(name="BOTA",
comment_names=[],
description="Beaches on the Air",
icon="fa-umbrella-beach"
),
SIG(name="BOTA", comment_names=[], description="Beaches on the Air"),
SIG(
name="KRMNPA",
comment_names=["KRMNPA"],
description="Keith Roget Memorial National Parks Award",
ref_regex=r"VKFF\-\d{4}",
icon="fa-earth-oceania",
region_flag="🇦🇺"
),
SIG(
name="SANPCPA",
comment_names=["SANPCPA"],
description="South Australian National Parks and Conservation Parks Award",
ref_regex=r"VKFF\-\d{4}",
icon="fa-earth-oceania",
region_flag="🇦🇺"
),
SIG(
name="LLOTA",
comment_names=["LLOTA"],
description="Lagos y Lagunas on the Air",
ref_regex=r"LL[A-Z]{2}\-\d{4}",
icon="fa-water",
refs_globally_unique=True
),
SIG(
name="Towers",
comment_names=["TOTA"],
description="Towers on the Air",
ref_regex=r"[A-Z]{2,3}R\-\d{4}",
icon="fa-tower-observation",
refs_globally_unique=False
),
SIG(
name="Tiles",
comment_names=[],
description="Tiles on the Air",
ref_regex=r"[A-Za-z]{2}[0-9]{2}[A-Za-z]{2}",
icon="fa-square",
refs_globally_unique=False
),
SIG(
name="WAB",
comment_names=["WAB"],
description="Worked All Britain",
ref_regex=r"[A-Z]{1,2}[0-9]{2}",
icon="fa-table-cells-large",
region_flag="🇬🇧",
refs_globally_unique=False
),
SIG(
name="WAI",
comment_names=["WAI"],
description="Worked All Ireland",
ref_regex=r"[A-Z][0-9]{2}",
icon="fa-table-cells-large",
region_flag="🇮🇪",
refs_globally_unique=False
),
SIG(
name="DME",
comment_names=["DME"],
description="Diploma Municipios de España",
ref_regex=r"\d{4,5}",
icon="fa-building",
region_flag="🇪🇸",
refs_globally_unique=False
),
SIG(
name="FEA",
comment_names=["FEA"],
description="Diploma Faros de España",
# FEA references are technically [DE]\-\d{4}(\.\d)? but spotters always seem to miss out the D- or E-
# prefix and just use FEA 1234, so we treat FEA reference IDs as if they were just the number.
ref_regex=r"\d{4}(\.\d)?",
# prefix and just use FEA-1234 or FEA 1234, so allow for that. The FEA sigref data provider adds both
# forms to the database.
ref_regex=r"([DE]|FEA)[\- ]\d{4}(\.\d)?",
icon="fa-house-flood-water",
region_flag="🇪🇸",
refs_globally_unique=True
),
SIG(
name="DTMBA",
comment_names=["DTMBA"],
description="Diploma Teatri Musei e Belle Arti",
ref_regex=r"I-?[0-9]{3,4}\s?[A-Z]{2}",
icon="fa-masks-theater",
region_flag="🇮🇹",
refs_globally_unique=True
),
SIG(
name="BIOWTA",
name="BIWOTA",
comment_names=["BIWOTA"],
description="British Inland Waterways on the Air"
description="British Inland Waterways on the Air",
icon="fa-ship",
region_flag="🇬🇧"
),
SIG(
name="COTA",
comment_names=["COTA"],
description="Castles on the Air",
ref_regex=r"[A-Z]{3}\-[0-9]{3,5}",
icon="fa-chess-rook",
region_flag="🇩🇪",
refs_globally_unique=False
),
SIG(
name="Toilets",
comment_names=[],
description="Toilets on the Air",
ref_regex=r"T\-[0-9]{2}",
icon="fa-toilet",
region_flag="🏴‍☠️",
refs_globally_unique=True
),
]
+9
View File
@@ -19,6 +19,11 @@ def get_sig_ref_info(sig, ref_id):
logger.debug("Failed to look up sig_ref info, sig or ref were not set.")
return None
# Sometimes we allow spaces instead of dashes in references due to common usage that way, but official reference
# lists never do, so convert them here.
ref_id.replace(" ", "-")
# Prepare the object to be returned
sig_ref = SIGRef(sig=sig, id=ref_id)
try:
@@ -78,6 +83,10 @@ def get_sig_ref_info(sig, ref_id):
sig_ref.url = f"https://www.beachesontheair.com/beaches/{sig_ref.name.lower().replace(' ', '-')}"
return sig_ref
elif sig.upper() == "BIWOTA":
# For BIWOTA there are no references, all we can set is a type
sig_ref.ref_type = "Waterway"
elif sig.upper() == "GMA Islands":
# GMA Islands is a bit of a mess of GMA and IOTA references. Try looking them both up and see what returns
# the best result.
+3 -2
View File
@@ -1,4 +1,5 @@
import logging
import re
import simplejson
from pyhamtools.frequency import freq_to_band
@@ -30,10 +31,10 @@ def infer_mode_from_comment(comment):
"""Infer a mode from the comment"""
for mode in ALL_MODES:
if mode in comment.upper():
if re.match(r"(^|\W)" + mode + r"($|\W)", comment, re.IGNORECASE):
return mode
for mode in MODE_ALIASES:
if mode in comment.upper():
if re.match(r"(^|\W)" + mode + r"($|\W)", comment, re.IGNORECASE):
return MODE_ALIASES[mode]
return None
+11
View File
@@ -19,3 +19,14 @@ class SIG:
comment_names: list[str] = field(default_factory=list)
# Regex matcher for references, e.g. for POTA r"[A-Z]{2}\-\d+".
ref_regex: str | None = None
# Identifies that the SIG's reference ID structure defined by its regex is unique across all programmes and
# anything else we expect a user to put in a spot comment, and therefore we can pull references out of
# spot comments without also needing to see the SIG name first. For example, "OHFF-1234" or "B/G-1234" are
# obviously WWFF and WWBOTA, nothing else looks like those. But "SZ09" could be WAB or Tiles, "GB1234" could
# conceivably be POTA or ILLW, etc.
refs_globally_unique: bool = False
# Icon to use in the UI when referencing this SIG. Chosen from the Font Awesome set.
icon: str | None = None
# Emoji flag for the country or region where this SIG is relevant, if any. If None, this implies the SIG is in
# worldwide usage.
region_flag: str | None = None
+15 -2
View File
@@ -11,7 +11,7 @@ from pyhamtools.locator import latlong_to_locator, locator_to_latlong
from core.call_lookup_helper import get_call_info
from core.config import MAX_SPOT_AGE
from core.constants import MODE_ALIASES, PROPAGATION_MODES
from core.constants import MODE_ALIASES, PROPAGATION_MODES, SIGS
from core.geo_utils import lat_lon_to_cq_zone, lat_lon_to_itu_zone
from core.sig_lookup_helper import populate_missing_sig_ref_info
from core.sig_utils import (
@@ -270,7 +270,7 @@ class Spot:
sig = self.sig_refs[0].sig.upper()
regex = get_ref_regex_for_sig(sig)
if regex:
all_comment_ref_matches = re.finditer(r"(^|\W)(" + regex + r")(^|\W)", self.comment, re.IGNORECASE)
all_comment_ref_matches = re.finditer(r"(^|\W)(" + regex + r")($|\W)", self.comment, re.IGNORECASE)
for ref_match in all_comment_ref_matches:
self._append_sig_ref_if_missing(SIGRef(id=ref_match.group(2).upper(), sig=sig))
@@ -298,6 +298,19 @@ class Spot:
for ref_match in ref_matches:
self._append_sig_ref_if_missing(SIGRef(id=ref_match.group(3).upper(), sig=found_sig))
# See if the comment looks like it contains any SIG references *without* the corresponding SIG name, but
# where the SIG reference is unique-looking enough that we can't confuse it with any other SIG.
if self.comment:
for sig in SIGS:
if sig.refs_globally_unique and sig.ref_regex:
ref_matches = re.finditer(r"(^|\W)(" + sig.ref_regex + r")($|\W)", self.comment, re.IGNORECASE)
for ref_match in ref_matches:
# First of all, if we haven't got a SIG for this spot set yet, now we have. This covers things
# like cluster spots where the comment is just "OHFF-1234", now we know it's WWFF.
if not self.sig:
self.sig = sig.name
self._append_sig_ref_if_missing(SIGRef(id=ref_match.group(2).upper(), sig=sig.name))
# Fetch SIG data. In case a particular API doesn't provide a full set of name, lat, lon & grid for a reference
# in its initial call, we use this code to populate the rest of the data. This includes working out grid refs
# from WAB and WAI, which count as a SIG even though there's no real lookup, just maths
+1 -10
View File
@@ -1,12 +1,9 @@
AA343,"Almaty, Kazakhstan"
AL945,"Alpena, United States"
AT138,"Athens, Greece"
AU930,"Austin, United States"
BR52P,"Brisbane, Australia"
BVJ03,"Boa Vista, Brazil"
CAJ2M,"Cachoeira Paulista, Brazil"
CB53N,"Canberra, Australia"
CGK21,"Campo Grande, Brazil"
DB049,"Dourbes, Belgium"
DW41K,"Darwin, Australia"
EA036,"El Arenosillo, Spain"
@@ -18,24 +15,18 @@ GM037,"Gibilmanna, Italy"
GR13L,"Grahamstown, South Africa"
HE13N,"Hermanus, South Africa"
HO54K,"Hobart, Australia"
IC437,"I-Cheon, South Korea"
IF843,"Idaho National Laboratory, United States"
JI91J,"Jicamarca, Peru"
JR055,"Juliusruh, Germany"
LAA38,"Lajes Terceira Island, Portugal"
LL721,"Lualualei, United States"
LM42B,"Learmonth, Australia"
LV12P,"Louisvale, South Africa"
MHJ45,"Millstone Hill, United States"
ML10L,"Malindi, Kenya"
NI135,"Nicosia, Cyprus"
NI63_,"Norfolk, Australia"
PA836,"Portt Arguello, United States"
PA836,"Port Arguello, United States"
PE43K,"Perth, Australia"
PF765,"Poker Flat, United States"
PQ052,"Pruhonice, Czechia"
RO041,"Rome, Italy"
SAA0K,"Saoluis, Brazil"
SO148,"Sopron, Hungary"
TR169,"Tromso, Norway"
TV51R,"Townsville, Australia"
1 AA343 Almaty, Kazakhstan
2 AL945 Alpena, United States
3 AT138 Athens, Greece
AU930 Austin, United States
BR52P Brisbane, Australia
4 BVJ03 Boa Vista, Brazil
5 CAJ2M Cachoeira Paulista, Brazil
6 CB53N Canberra, Australia
CGK21 Campo Grande, Brazil
7 DB049 Dourbes, Belgium
8 DW41K Darwin, Australia
9 EA036 El Arenosillo, Spain
15 GR13L Grahamstown, South Africa
16 HE13N Hermanus, South Africa
17 HO54K Hobart, Australia
IC437 I-Cheon, South Korea
18 IF843 Idaho National Laboratory, United States
19 JI91J Jicamarca, Peru
20 JR055 Juliusruh, Germany
21 LAA38 Lajes Terceira Island, Portugal
22 LL721 Lualualei, United States
LM42B Learmonth, Australia
LV12P Louisvale, South Africa
23 MHJ45 Millstone Hill, United States
ML10L Malindi, Kenya
24 NI135 Nicosia, Cyprus
25 NI63_ Norfolk, Australia
26 PA836 Portt Arguello, United States Port Arguello, United States
27 PE43K Perth, Australia
PF765 Poker Flat, United States
28 PQ052 Pruhonice, Czechia
29 RO041 Rome, Italy
SAA0K Saoluis, Brazil
30 SO148 Sopron, Hungary
31 TR169 Tromso, Norway
32 TV51R Townsville, Australia
+51
View File
@@ -0,0 +1,51 @@
from time import sleep
from pyhamtools.locator import latlong_to_locator
from data.sig_ref import SIGRef
from providers.sigrefdata.file_download_sig_ref_data_provider import FileDownloadSIGRefDataProvider
class COTA(FileDownloadSIGRefDataProvider):
"""SIG ref data provider for Castles on the Air"""
POLL_INTERVAL_DAYS = 30
SIG = "COTA"
DATA_URL = "https://www.cotagroup.org/cotagroup/map/data/castles-all-7d90ee2a5e1175e5dece1bbf9dc87504.json"
def __init__(self, provider_config):
super().__init__(self.SIG, provider_config, self.DATA_URL, self.POLL_INTERVAL_DAYS)
def _http_response_to_data(self, http_response):
new_data = []
data = http_response.json()
if isinstance(data, list):
for ref in data[2]:
ref_id = ref[3]
name = ref[4]
lat = float(ref[0])
lon = float(ref[1])
grid = latlong_to_locator(lat, lon)
new_data.append(
SIGRef(
sig=self.SIG,
id=ref_id,
name=name,
ref_type="Castle",
grid=grid,
latitude=lat,
longitude=lon,
)
)
# Bail out if a stop has been requested, i.e. the program is shutting down - no need to parse the rest
# of the data in this case
if self._stop_event.is_set():
break
# Very short pause. This will extend the time to handle sig refs by a few seconds but will ensure some time
# is available for other threads e.g. the web server.
sleep(0.001)
return new_data
+5 -3
View File
@@ -37,9 +37,11 @@ class FEA(FileDownloadSIGRefDataProvider):
for row in all_rows:
if not "REF" in row[0] and not "\n" in row[0]:
# FEA references are technically [DE]\-\d{4}(\.\d)? but spotters always seem to miss out the D- or E-
# prefix and just use FEA 1234, so we treat FEA reference IDs as if they were just the number.
ref_id = row[0].strip().replace("D-", "").replace("E-", "")
new_data.append(SIGRef(sig=self.SIG, id=ref_id, name=row[1].strip(), ref_type="Lighthouse"))
# prefix and just use FEA-1234 or FEA 1234, so we add both copies to the database.
ref_id_1 = row[0].strip()
ref_id_2 = ref_id_1.replace("D-", "FEA-").replace("E-", "FEA-")
new_data.append(SIGRef(sig=self.SIG, id=ref_id_1, name=row[1].strip(), ref_type="Lighthouse"))
new_data.append(SIGRef(sig=self.SIG, id=ref_id_2, name=row[1].strip(), ref_type="Lighthouse"))
# Bail out if a stop has been requested, i.e. the program is shutting down - no need to parse the rest of
# the data in this case
+19
View File
@@ -19,6 +19,7 @@ info:
* Added DTMBA, FEA and BIWOTA SIGs
* Removed the distinction between LSB & USB (both will now show as SSB) and between the various digital voice modes, which will now show as DV.
* Added `icon`, `region_flag` and `refs_globally_unique` to SIG information
### 2.0
@@ -1504,6 +1505,24 @@ components:
Regex that matches this SIG's reference IDs. Generally for Spothole's own internal use,
clients probably won't need this.
example: "[A-Z]{2}\\-\\d+"
refs_globally_unique:
type: boolean
description: >
Identifies that the SIG's reference ID structure defined by its regex is unique across all programmes and
anything else we expect a user to put in a spot comment, and therefore we can pull references out of
spot comments without also needing to see the SIG name first. For example, "OHFF-1234" or "B/G-1234" are
obviously WWFF and WWBOTA, nothing else looks like those. But "SZ09" could be WAB or Tiles, "GB1234" could
conceivably be POTA or ILLW, etc. Generally for Spothole's own internal use, clients probably won't need
this.
icon:
type: string
description: Icon from the Font Awesome set that represents this SIG, for use in the front end.
example: "fa-tree"
region_flag:
type: string
description: >
Flag emoji, if this SIG is specific to a country or region. If null, this SIG is treated as worldwide.
example: "🇺🇳"
SolarConditions:
type: object
+2 -2
View File
@@ -264,7 +264,7 @@ function addAlertRowsToTable(tbody, alerts) {
$tr.append(`<td class='hideonmobile'>${commentText}</td>`);
}
if (showSource) {
$tr.append(`<td class='nowrap hideonmobile'><span class='icon-wrapper'><i class='fa-solid ${sigToIcon(a["sig"], "fa-globe-africa")}'></i></span> ${sigSourceText}</td>`);
$tr.append(`<td class='nowrap hideonmobile'><span class='icon-wrapper'><i class='fa-solid ${sigToIcon(a["sig"], options["sigs"], "fa-globe-africa")}'></i></span> ${sigSourceText}</td>`);
}
if (showRef) {
$tr.append(`<td class='hideonmobile'>${sig_refs}</td>`);
@@ -282,7 +282,7 @@ function addAlertRowsToTable(tbody, alerts) {
const $td2 = $("<td colspan='100'>");
if (showSource) {
$td2.append(`<span class='icon-wrapper'><i class='fa-solid ${sigToIcon(a["sig"], "fa-globe-africa")}'></i></span> `);
$td2.append(`<span class='icon-wrapper'><i class='fa-solid ${sigToIcon(a["sig"], options["sigs"], "fa-globe-africa")}'></i></span> `);
}
if (showRef) {
$td2.append(`${sig_refs} `);
+13
View File
@@ -285,6 +285,19 @@ function callWanted(call) {
}
}
// Get the Font Awesome icon for a given SIG. If the SIG is unknown, the provided default symbol will be returned
// The sig is provided by name as a string, while all_sigs contains all the SIG info from the options call. This
// is because sometimes the sig name arrives via a spot and therefore we need to look up the rest of the SIG data
// separately.
function sigToIcon(sig, all_sigs, defaultIcon) {
if (sig) {
const match = all_sigs.find((check_sig) => check_sig["name"].toUpperCase() === sig.toUpperCase());
if (match) {
return match["icon"];
}
}
return defaultIcon;
}
// Startup
$(document).ready(function () {
+2 -2
View File
@@ -223,7 +223,7 @@ function updateMap() {
// Get an icon for a spot, based on its band, using PSK Reporter colours, its program etc.
function getIcon(s) {
return L.ExtraMarkers.icon({
icon: sigToIcon(s["sig"], "fa-tower-cell"),
icon: sigToIcon(s["sig"], options["sigs"], "fa-tower-cell"),
iconColor: bandToContrastColor(s["band"]),
markerColor: bandToColor(s["band"]),
shape: 'circle',
@@ -303,7 +303,7 @@ function getTooltipText(s) {
ttt += "<br/>";
// Source / SIG / Ref
ttt += `<span class='nowrap'><span class='icon-wrapper'><i class='fa-solid ${sigToIcon(s["sig"], "fa-tower-cell")}'></i></span>&nbsp;${sigSourceText} ${sig_refs}</span><br/>`;
ttt += `<span class='nowrap'><span class='icon-wrapper'><i class='fa-solid ${sigToIcon(s["sig"], options["sigs"], "fa-tower-cell")}'></i></span>&nbsp;${sigSourceText} ${sig_refs}</span><br/>`;
// Time
ttt += `<span class='icon-wrapper'><i class='fa-solid fa-clock markerPopupIcon'></i></span>&nbsp;${moment.unix(s["time"]).fromNow()}`;
+2 -2
View File
@@ -398,7 +398,7 @@ function createNewTableRowsForSpot(s, highlightNew) {
$tr.append(`<td class='nowrap hideonmobile'>${distanceText}</td>`);
}
if (showType) {
$tr.append(`<td class='nowrap hideonmobile'><span class='icon-wrapper'><i class='fa-solid ${sigToIcon(s["sig"], "fa-tower-cell")}'></i></span> ${typeText}</td>`);
$tr.append(`<td class='nowrap hideonmobile'><span class='icon-wrapper'><i class='fa-solid ${sigToIcon(s["sig"], options["sigs"], "fa-tower-cell")}'></i></span> ${typeText}</td>`);
}
if (showRef) {
$tr.append(`<td class='hideonmobile' style='max-width: 11em;'>${sig_refs}</td>`);
@@ -430,7 +430,7 @@ function createNewTableRowsForSpot(s, highlightNew) {
const $td2 = $("<td colspan='100'>");
const $td2floatleft = $(`<div style="float: left;">`);
if (showType) {
$td2floatleft.append(`<span class='icon-wrapper'><i class='fa-solid ${sigToIcon(s["sig"], "fa-tower-cell")}'></i></span> ${typeText} `);
$td2floatleft.append(`<span class='icon-wrapper'><i class='fa-solid ${sigToIcon(s["sig"], options["sigs"], "fa-tower-cell")}'></i></span> ${typeText} `);
}
if (showRef) {
$td2floatleft.append(`${sig_refs} `);
+14 -5
View File
@@ -40,14 +40,23 @@ function setHamHFBandToggles() {
// Generate SIGs filter card. This one is also a special case.
function generateSIGsMultiToggleFilterCard(sig_options) {
const $grid = $('<div class="row row-cols-2 g-1 mb-1">');
sig_options.forEach(o => {
const $grid1 = $('<div class="row row-cols-2 g-1 mb-1">');
$("#sig-options").append('<strong>Worldwide</strong>');
sig_options.filter(o => o["region_flag"] == null).forEach(o => {
const domSafeName = o["name"].replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
$grid.append(`<div class="col"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-sig storeable-checkbox" id="filter-button-sig-${domSafeName}" value="${o['name']}" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" id="filter-button-label-sig-${domSafeName}" for="filter-button-sig-${domSafeName}" title="${o['description']}"><i class="fa-solid ${sigToIcon(o['name'], 'fa-tower-cell')}"></i> ${o['name']}</label></div></div>`);
$grid1.append(`<div class="col"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-sig storeable-checkbox" id="filter-button-sig-${domSafeName}" value="${o['name']}" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" id="filter-button-label-sig-${domSafeName}" for="filter-button-sig-${domSafeName}" title="${o['description']}"><i class="fa-solid ${o['icon']}"></i> ${o['name']}</label></div></div>`);
});
$("#sig-options").append($grid1);
const $grid2 = $('<div class="row row-cols-2 g-1 mb-1">');
$("#sig-options").append('<strong>Regional</strong>');
sig_options.filter(o => o["region_flag"] != null).forEach(o => {
const domSafeName = o["name"].replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
$grid2.append(`<div class="col"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-sig storeable-checkbox" id="filter-button-sig-${domSafeName}" value="${o['name']}" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" id="filter-button-label-sig-${domSafeName}" for="filter-button-sig-${domSafeName}" title="${o['description']}"><i class="fa-solid ${o['icon']}"></i> ${o['name']} ${o['region_flag']}</label></div></div>`);
});
$("#sig-options").append($grid2);
$("#sig-options").append('<strong>Other</strong>');
// Bonus "NO_SIG" / "General DX" option
$grid.append(`<div class="w-100"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-sig storeable-checkbox" id="filter-button-sig-NO_SIG" value="NO_SIG" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" id="filter-button-label-sig-NO_SIG" for="filter-button-sig-NO_SIG"><i class="fa-solid fa-tower-cell"></i> General DX</label></div></div>`);
$("#sig-options").append($grid);
$("#sig-options").append(`<div class="w-100"><div class="form-check"><input type="checkbox" class="form-check-input filter-button-sig storeable-checkbox" id="filter-button-sig-NO_SIG" value="NO_SIG" autocomplete="off" onClick="filtersUpdated()" checked><label class="form-check-label" id="filter-button-label-sig-NO_SIG" for="filter-button-sig-NO_SIG"><i class="fa-solid fa-tower-cell"></i> General DX</label></div></div>`);
$("#sig-options").append(`<div class="mt-1"><a href="#" onclick="toggleFilterButtons('sig', true); return false;">All</a> &nbsp; <a href="#" onclick="toggleFilterButtons('sig', false); return false;">None</a></div>`);
}
-47
View File
@@ -323,50 +323,3 @@ function bandToContrastColor(band) {
const lum = 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2];
return (lum > 128) ? "#000000" : "#ffffff";
}
const SIG_ICONS = {
"POTA": "fa-tree",
"SOTA": "fa-mountain-sun",
"WWFF": "fa-seedling",
"GMA": "fa-person-hiking",
"GMA Islands": "fa-person-hiking",
"WWBOTA": "fa-radiation",
"HEMA": "fa-mound",
"IOTA": "fa-book-atlas",
"MOTA": "fa-fan",
"ARLHS": "fa-house-flood-water",
"ILLW": "fa-house-flood-water",
"SIOTA": "fa-wheat-awn",
"WCA": "fa-chess-rook",
"ZLOTA": "fa-kiwi-bird",
"WOTA": "fa-w",
"BOTA": "fa-umbrella-beach",
"KRMNPA": "fa-earth-oceania",
"SANPCPA": "fa-earth-oceania",
"LLOTA": "fa-water",
"Towers": "fa-tower-observation",
"WAB": "fa-table-cells-large",
"WAI": "fa-table-cells-large",
"DME": "fa-building",
"FEA": "fa-house-flood-water",
"Tiles": "fa-square",
"DTMBA": "fa-masks-theater",
"BIWOTA": "fa-ship",
"Toilets": "fa-toilet"
}
// Get the Font Awesome icon for a given SIG. If the SIG is unknown, the provided default symbol will be returned
function sigToIcon(sig, defaultIcon) {
let col = (sig != null) ? SIG_ICONS[sig] : null;
if (col) {
return col;
} else {
let col = (sig != null) ? SIG_ICONS[sig.toUpperCase()] : null;
if (col) {
return col;
} else {
return defaultIcon;
}
}
}
+1 -1
View File
@@ -76,7 +76,7 @@
</div>
<script src="/static/js/add-spot.js?v=1788171425"></script>
<script src="/static/js/add-spot.js?v=1788207475"></script>
<script>$(document).ready(function () {
$("#nav-link-add-spot").addClass("active");
}); <!-- highlight active page in nav --></script>
+1 -1
View File
@@ -84,7 +84,7 @@
</div>
<script src="/static/js/alerts.js?v=1788171425"></script>
<script src="/static/js/alerts.js?v=1788207475"></script>
<script>$(document).ready(function () {
$("#nav-link-alerts").addClass("active");
}); <!-- highlight active page in nav --></script>
+2 -2
View File
@@ -76,8 +76,8 @@
</div>
<script src="/static/js/spotsbandsandmap.js?v=1788171425"></script>
<script src="/static/js/bands.js?v=1788171425"></script>
<script src="/static/js/spotsbandsandmap.js?v=1788207475"></script>
<script src="/static/js/bands.js?v=1788207475"></script>
<script>$(document).ready(function () {
$("#nav-link-bands").addClass("active");
}); <!-- highlight active page in nav --></script>
+5 -5
View File
@@ -1,6 +1,6 @@
{% extends "skeleton.html" %}
{% block head_extra %}
<link rel="stylesheet" href="/static/css/style.css?v=1788171425" type="text/css">
<link rel="stylesheet" href="/static/css/style.css?v=1788207475" type="text/css">
<link href="/static/vendor/css/bootstrap-5.3.8.min.css" rel="stylesheet">
<link href="/static/vendor/css/fontawesome-6.7.2.min.css" rel="stylesheet">
<link href="/static/vendor/css/solid-6.7.2.min.css" rel="stylesheet">
@@ -15,10 +15,10 @@
window.fetchEventSource = fetchEventSource;
</script>
<script src="/static/js/utils.js?v=1788171425"></script>
<script src="/static/js/ui-ham.js?v=1788171425"></script>
<script src="/static/js/geo.js?v=1788171425"></script>
<script src="/static/js/common.js?v=1788171425"></script>
<script src="/static/js/utils.js?v=1788207475"></script>
<script src="/static/js/ui-ham.js?v=1788207475"></script>
<script src="/static/js/geo.js?v=1788207475"></script>
<script src="/static/js/common.js?v=1788207475"></script>
{% end %}
{% block body %}
<div class="container">
+1 -1
View File
@@ -284,7 +284,7 @@
</div>
<script src="/static/vendor/js/chart-4.4.9.umd.min.js"></script>
<script src="/static/js/conditions.js?v=1788171425"></script>
<script src="/static/js/conditions.js?v=1788207475"></script>
<script>$(document).ready(function () {
$("#nav-link-conditions").addClass("active");
}); <!-- highlight active page in nav --></script>
+2 -2
View File
@@ -113,8 +113,8 @@
const CARTODB_API_KEY = "{{ web_ui_options.get('cartodb_api_key', '') }}";
</script>
<script src="/static/js/spotsbandsandmap.js?v=1788171425"></script>
<script src="/static/js/map.js?v=1788171425"></script>
<script src="/static/js/spotsbandsandmap.js?v=1788207475"></script>
<script src="/static/js/map.js?v=1788207475"></script>
<script>$(document).ready(function () {
$("#nav-link-map").addClass("active");
}); <!-- highlight active page in nav --></script>
+2 -2
View File
@@ -113,8 +113,8 @@
</div>
<script src="/static/js/spotsbandsandmap.js?v=1788171425"></script>
<script src="/static/js/spots.js?v=1788171425"></script>
<script src="/static/js/spotsbandsandmap.js?v=1788207475"></script>
<script src="/static/js/spots.js?v=1788207475"></script>
<script>$(document).ready(function () {
$("#nav-link-spots").addClass("active");
}); <!-- highlight active page in nav --></script>
+1 -1
View File
@@ -86,7 +86,7 @@
</div>
</div>
<script src="/static/js/status.js?v=1788171425"></script>
<script src="/static/js/status.js?v=1788207475"></script>
<script>
$(document).ready(function () {
$("#nav-link-status").addClass("active");