mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-09-20 14:27:42 +00:00
Add icons back to spots & alerts
This commit is contained in:
+35
-1
@@ -1,5 +1,5 @@
|
|||||||
from core.config import SERVER_OWNER_CALLSIGN
|
from core.config import SERVER_OWNER_CALLSIGN
|
||||||
from core.enums import SIGType
|
from core.enums import SIGRefType, SIGType
|
||||||
from data.band import Band
|
from data.band import Band
|
||||||
from data.sig import SIG
|
from data.sig import SIG
|
||||||
|
|
||||||
@@ -17,6 +17,7 @@ SIGS = [
|
|||||||
comment_names=["POTA"],
|
comment_names=["POTA"],
|
||||||
description="Parks on the Air",
|
description="Parks on the Air",
|
||||||
sig_type=SIGType.WORLDWIDE,
|
sig_type=SIGType.WORLDWIDE,
|
||||||
|
ref_type=SIGRefType.PARK,
|
||||||
ref_regex=r"[A-Z]{2}\-\d{4,5}|K\-TEST",
|
ref_regex=r"[A-Z]{2}\-\d{4,5}|K\-TEST",
|
||||||
icon="fa-tree",
|
icon="fa-tree",
|
||||||
refs_globally_unique=False,
|
refs_globally_unique=False,
|
||||||
@@ -26,6 +27,7 @@ SIGS = [
|
|||||||
comment_names=["SOTA"],
|
comment_names=["SOTA"],
|
||||||
description="Summits on the Air",
|
description="Summits on the Air",
|
||||||
sig_type=SIGType.WORLDWIDE,
|
sig_type=SIGType.WORLDWIDE,
|
||||||
|
ref_type=SIGRefType.SUMMIT,
|
||||||
ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}",
|
ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}",
|
||||||
icon="fa-mountain-sun",
|
icon="fa-mountain-sun",
|
||||||
refs_globally_unique=False,
|
refs_globally_unique=False,
|
||||||
@@ -35,6 +37,7 @@ SIGS = [
|
|||||||
comment_names=["WWFF"],
|
comment_names=["WWFF"],
|
||||||
description="World Wide Flora & Fauna",
|
description="World Wide Flora & Fauna",
|
||||||
sig_type=SIGType.WORLDWIDE,
|
sig_type=SIGType.WORLDWIDE,
|
||||||
|
ref_type=SIGRefType.PARK,
|
||||||
ref_regex=r"[A-Z0-9]{1,3}FF\-\d{4}",
|
ref_regex=r"[A-Z0-9]{1,3}FF\-\d{4}",
|
||||||
icon="fa-seedling",
|
icon="fa-seedling",
|
||||||
refs_globally_unique=True,
|
refs_globally_unique=True,
|
||||||
@@ -44,6 +47,7 @@ SIGS = [
|
|||||||
comment_names=["GMA"],
|
comment_names=["GMA"],
|
||||||
description="Global Mountain Activity",
|
description="Global Mountain Activity",
|
||||||
sig_type=SIGType.WORLDWIDE,
|
sig_type=SIGType.WORLDWIDE,
|
||||||
|
ref_type=SIGRefType.SUMMIT,
|
||||||
ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}",
|
ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}",
|
||||||
icon="fa-person-hiking",
|
icon="fa-person-hiking",
|
||||||
refs_globally_unique=False,
|
refs_globally_unique=False,
|
||||||
@@ -53,6 +57,7 @@ SIGS = [
|
|||||||
comment_names=["WWBOTA", "BOTA"],
|
comment_names=["WWBOTA", "BOTA"],
|
||||||
description="Worldwide Bunkers on the Air",
|
description="Worldwide Bunkers on the Air",
|
||||||
sig_type=SIGType.WORLDWIDE,
|
sig_type=SIGType.WORLDWIDE,
|
||||||
|
ref_type=SIGRefType.BUNKER,
|
||||||
ref_regex=r"B\/[A-Z0-9]{1,3}\-\d{3,4}",
|
ref_regex=r"B\/[A-Z0-9]{1,3}\-\d{3,4}",
|
||||||
icon="fa-radiation",
|
icon="fa-radiation",
|
||||||
refs_globally_unique=True,
|
refs_globally_unique=True,
|
||||||
@@ -62,6 +67,7 @@ SIGS = [
|
|||||||
comment_names=["HEMA"],
|
comment_names=["HEMA"],
|
||||||
description="HuMPs Excluding Marilyns Award",
|
description="HuMPs Excluding Marilyns Award",
|
||||||
sig_type=SIGType.WORLDWIDE,
|
sig_type=SIGType.WORLDWIDE,
|
||||||
|
ref_type=SIGRefType.SUMMIT,
|
||||||
ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{3}\-\d{3}",
|
ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{3}\-\d{3}",
|
||||||
icon="fa-mound",
|
icon="fa-mound",
|
||||||
refs_globally_unique=False,
|
refs_globally_unique=False,
|
||||||
@@ -71,6 +77,7 @@ SIGS = [
|
|||||||
comment_names=["IOTA"],
|
comment_names=["IOTA"],
|
||||||
description="Islands on the Air",
|
description="Islands on the Air",
|
||||||
sig_type=SIGType.WORLDWIDE,
|
sig_type=SIGType.WORLDWIDE,
|
||||||
|
ref_type=SIGRefType.ISLAND,
|
||||||
ref_regex=r"[A-Z]{2}\-\d{3}",
|
ref_regex=r"[A-Z]{2}\-\d{3}",
|
||||||
icon="fa-book-atlas",
|
icon="fa-book-atlas",
|
||||||
refs_globally_unique=False,
|
refs_globally_unique=False,
|
||||||
@@ -80,6 +87,7 @@ SIGS = [
|
|||||||
comment_names=[],
|
comment_names=[],
|
||||||
description="Global Mountain Activity - Islands",
|
description="Global Mountain Activity - Islands",
|
||||||
sig_type=SIGType.WORLDWIDE,
|
sig_type=SIGType.WORLDWIDE,
|
||||||
|
ref_type=SIGRefType.ISLAND,
|
||||||
ref_regex=r"(([A-Z]{2}\-\d{3})|([A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}))",
|
ref_regex=r"(([A-Z]{2}\-\d{3})|([A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}))",
|
||||||
icon="fa-person-hiking",
|
icon="fa-person-hiking",
|
||||||
refs_globally_unique=False,
|
refs_globally_unique=False,
|
||||||
@@ -89,6 +97,7 @@ SIGS = [
|
|||||||
comment_names=["ARLHS"],
|
comment_names=["ARLHS"],
|
||||||
description="Amateur Radio Lighthouse Society",
|
description="Amateur Radio Lighthouse Society",
|
||||||
sig_type=SIGType.WORLDWIDE,
|
sig_type=SIGType.WORLDWIDE,
|
||||||
|
ref_type=SIGRefType.LIGHTHOUSE,
|
||||||
ref_regex=r"[A-Z]{3}[\- ]\d{3,4}",
|
ref_regex=r"[A-Z]{3}[\- ]\d{3,4}",
|
||||||
icon="fa-house-flood-water",
|
icon="fa-house-flood-water",
|
||||||
refs_globally_unique=False,
|
refs_globally_unique=False,
|
||||||
@@ -98,6 +107,7 @@ SIGS = [
|
|||||||
comment_names=["ILLW"],
|
comment_names=["ILLW"],
|
||||||
description="International Lighthouse & Lightship Weekend",
|
description="International Lighthouse & Lightship Weekend",
|
||||||
sig_type=SIGType.EVENT,
|
sig_type=SIGType.EVENT,
|
||||||
|
ref_type=SIGRefType.LIGHTHOUSE,
|
||||||
ref_regex=r"[A-Z]{2}\d{4}",
|
ref_regex=r"[A-Z]{2}\d{4}",
|
||||||
icon="fa-house-flood-water",
|
icon="fa-house-flood-water",
|
||||||
refs_globally_unique=False,
|
refs_globally_unique=False,
|
||||||
@@ -107,6 +117,7 @@ SIGS = [
|
|||||||
comment_names=["MOTA"],
|
comment_names=["MOTA"],
|
||||||
description="Mills on the Air",
|
description="Mills on the Air",
|
||||||
sig_type=SIGType.EVENT,
|
sig_type=SIGType.EVENT,
|
||||||
|
ref_type=SIGRefType.MILL,
|
||||||
ref_regex=r"X\d{4,6}",
|
ref_regex=r"X\d{4,6}",
|
||||||
icon="fa-fan",
|
icon="fa-fan",
|
||||||
refs_globally_unique=True,
|
refs_globally_unique=True,
|
||||||
@@ -116,6 +127,7 @@ SIGS = [
|
|||||||
comment_names=["SIOTA"],
|
comment_names=["SIOTA"],
|
||||||
description="Silos on the Air",
|
description="Silos on the Air",
|
||||||
sig_type=SIGType.WORLDWIDE,
|
sig_type=SIGType.WORLDWIDE,
|
||||||
|
ref_type=SIGRefType.SILO,
|
||||||
ref_regex=r"[A-Z]{2}\-[A-Z]{3}\d",
|
ref_regex=r"[A-Z]{2}\-[A-Z]{3}\d",
|
||||||
icon="fa-wheat-awn",
|
icon="fa-wheat-awn",
|
||||||
refs_globally_unique=False,
|
refs_globally_unique=False,
|
||||||
@@ -125,6 +137,7 @@ SIGS = [
|
|||||||
comment_names=["WCA"],
|
comment_names=["WCA"],
|
||||||
description="World Castles Award",
|
description="World Castles Award",
|
||||||
sig_type=SIGType.WORLDWIDE,
|
sig_type=SIGType.WORLDWIDE,
|
||||||
|
ref_type=SIGRefType.CASTLE,
|
||||||
ref_regex=r"[A-Z0-9]{1,3}\-\d{5}",
|
ref_regex=r"[A-Z0-9]{1,3}\-\d{5}",
|
||||||
icon="fa-chess-rook",
|
icon="fa-chess-rook",
|
||||||
refs_globally_unique=False,
|
refs_globally_unique=False,
|
||||||
@@ -134,6 +147,7 @@ SIGS = [
|
|||||||
comment_names=["ZLOTA"],
|
comment_names=["ZLOTA"],
|
||||||
description="New Zealand on the Air",
|
description="New Zealand on the Air",
|
||||||
sig_type=SIGType.REGIONAL,
|
sig_type=SIGType.REGIONAL,
|
||||||
|
ref_type=None,
|
||||||
ref_regex=r"ZL[A-Z]/[A-Z]{2}\-\d{3,4}",
|
ref_regex=r"ZL[A-Z]/[A-Z]{2}\-\d{3,4}",
|
||||||
icon="fa-kiwi-bird",
|
icon="fa-kiwi-bird",
|
||||||
region_flag="🇳🇿",
|
region_flag="🇳🇿",
|
||||||
@@ -144,6 +158,7 @@ SIGS = [
|
|||||||
comment_names=["WOTA"],
|
comment_names=["WOTA"],
|
||||||
description="Wainwrights on the Air",
|
description="Wainwrights on the Air",
|
||||||
sig_type=SIGType.REGIONAL,
|
sig_type=SIGType.REGIONAL,
|
||||||
|
ref_type=SIGRefType.SUMMIT,
|
||||||
ref_regex=r"[A-Z]{3}-[0-9]{2}",
|
ref_regex=r"[A-Z]{3}-[0-9]{2}",
|
||||||
icon="fa-w",
|
icon="fa-w",
|
||||||
region_flag="🇬🇧",
|
region_flag="🇬🇧",
|
||||||
@@ -154,6 +169,7 @@ SIGS = [
|
|||||||
comment_names=[],
|
comment_names=[],
|
||||||
description="Beaches on the Air",
|
description="Beaches on the Air",
|
||||||
sig_type=SIGType.WORLDWIDE,
|
sig_type=SIGType.WORLDWIDE,
|
||||||
|
ref_type=SIGRefType.BEACH,
|
||||||
icon="fa-umbrella-beach",
|
icon="fa-umbrella-beach",
|
||||||
refs_globally_unique=False,
|
refs_globally_unique=False,
|
||||||
),
|
),
|
||||||
@@ -162,6 +178,7 @@ SIGS = [
|
|||||||
comment_names=["KRMNPA"],
|
comment_names=["KRMNPA"],
|
||||||
description="Keith Roget Memorial National Parks Award",
|
description="Keith Roget Memorial National Parks Award",
|
||||||
sig_type=SIGType.REGIONAL,
|
sig_type=SIGType.REGIONAL,
|
||||||
|
ref_type=SIGRefType.PARK,
|
||||||
ref_regex=r"VKFF\-\d{4}",
|
ref_regex=r"VKFF\-\d{4}",
|
||||||
icon="fa-earth-oceania",
|
icon="fa-earth-oceania",
|
||||||
region_flag="🇦🇺",
|
region_flag="🇦🇺",
|
||||||
@@ -172,6 +189,7 @@ SIGS = [
|
|||||||
comment_names=["SANPCPA"],
|
comment_names=["SANPCPA"],
|
||||||
description="South Australian National Parks and Conservation Parks Award",
|
description="South Australian National Parks and Conservation Parks Award",
|
||||||
sig_type=SIGType.REGIONAL,
|
sig_type=SIGType.REGIONAL,
|
||||||
|
ref_type=SIGRefType.PARK,
|
||||||
ref_regex=r"VKFF\-\d{4}",
|
ref_regex=r"VKFF\-\d{4}",
|
||||||
icon="fa-earth-oceania",
|
icon="fa-earth-oceania",
|
||||||
region_flag="🇦🇺",
|
region_flag="🇦🇺",
|
||||||
@@ -182,6 +200,7 @@ SIGS = [
|
|||||||
comment_names=["LLOTA"],
|
comment_names=["LLOTA"],
|
||||||
description="Lagos y Lagunas on the Air",
|
description="Lagos y Lagunas on the Air",
|
||||||
sig_type=SIGType.WORLDWIDE,
|
sig_type=SIGType.WORLDWIDE,
|
||||||
|
ref_type=SIGRefType.LAKE,
|
||||||
ref_regex=r"LL[A-Z]{2}\-\d{4}",
|
ref_regex=r"LL[A-Z]{2}\-\d{4}",
|
||||||
icon="fa-water",
|
icon="fa-water",
|
||||||
refs_globally_unique=True,
|
refs_globally_unique=True,
|
||||||
@@ -191,6 +210,7 @@ SIGS = [
|
|||||||
comment_names=["TOTA"],
|
comment_names=["TOTA"],
|
||||||
description="Towers on the Air",
|
description="Towers on the Air",
|
||||||
sig_type=SIGType.WORLDWIDE,
|
sig_type=SIGType.WORLDWIDE,
|
||||||
|
ref_type=SIGRefType.TOWER,
|
||||||
ref_regex=r"[A-Z]{2,3}R\-\d{4}",
|
ref_regex=r"[A-Z]{2,3}R\-\d{4}",
|
||||||
icon="fa-tower-observation",
|
icon="fa-tower-observation",
|
||||||
refs_globally_unique=False,
|
refs_globally_unique=False,
|
||||||
@@ -200,6 +220,7 @@ SIGS = [
|
|||||||
comment_names=[],
|
comment_names=[],
|
||||||
description="Tiles on the Air",
|
description="Tiles on the Air",
|
||||||
sig_type=SIGType.WORLDWIDE,
|
sig_type=SIGType.WORLDWIDE,
|
||||||
|
ref_type=SIGRefType.GRID,
|
||||||
ref_regex=r"[A-Za-z]{2}[0-9]{2}[A-Za-z]{2}",
|
ref_regex=r"[A-Za-z]{2}[0-9]{2}[A-Za-z]{2}",
|
||||||
icon="fa-square",
|
icon="fa-square",
|
||||||
refs_globally_unique=False,
|
refs_globally_unique=False,
|
||||||
@@ -209,6 +230,7 @@ SIGS = [
|
|||||||
comment_names=["WAB"],
|
comment_names=["WAB"],
|
||||||
description="Worked All Britain",
|
description="Worked All Britain",
|
||||||
sig_type=SIGType.REGIONAL,
|
sig_type=SIGType.REGIONAL,
|
||||||
|
ref_type=SIGRefType.GRID,
|
||||||
ref_regex=r"[A-Z]{1,2}[0-9]{2}",
|
ref_regex=r"[A-Z]{1,2}[0-9]{2}",
|
||||||
icon="fa-table-cells-large",
|
icon="fa-table-cells-large",
|
||||||
region_flag="🇬🇧",
|
region_flag="🇬🇧",
|
||||||
@@ -219,6 +241,7 @@ SIGS = [
|
|||||||
comment_names=["WAI"],
|
comment_names=["WAI"],
|
||||||
description="Worked All Ireland",
|
description="Worked All Ireland",
|
||||||
sig_type=SIGType.REGIONAL,
|
sig_type=SIGType.REGIONAL,
|
||||||
|
ref_type=SIGRefType.GRID,
|
||||||
ref_regex=r"[A-Z][0-9]{2}",
|
ref_regex=r"[A-Z][0-9]{2}",
|
||||||
icon="fa-table-cells-large",
|
icon="fa-table-cells-large",
|
||||||
region_flag="🇮🇪",
|
region_flag="🇮🇪",
|
||||||
@@ -229,6 +252,7 @@ SIGS = [
|
|||||||
comment_names=["DME"],
|
comment_names=["DME"],
|
||||||
description="Diploma Municipios de España",
|
description="Diploma Municipios de España",
|
||||||
sig_type=SIGType.REGIONAL,
|
sig_type=SIGType.REGIONAL,
|
||||||
|
ref_type=SIGRefType.TOWN,
|
||||||
ref_regex=r"\d{4,5}",
|
ref_regex=r"\d{4,5}",
|
||||||
icon="fa-building",
|
icon="fa-building",
|
||||||
region_flag="🇪🇸",
|
region_flag="🇪🇸",
|
||||||
@@ -239,6 +263,7 @@ SIGS = [
|
|||||||
comment_names=["FEA"],
|
comment_names=["FEA"],
|
||||||
description="Diploma Faros de España",
|
description="Diploma Faros de España",
|
||||||
sig_type=SIGType.REGIONAL,
|
sig_type=SIGType.REGIONAL,
|
||||||
|
ref_type=SIGRefType.LIGHTHOUSE,
|
||||||
# FEA references are technically [DE]\-\d{4}(\.\d)? but spotters always seem to miss out the D- or E-
|
# 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 or FEA 1234, so allow for that. The FEA sigref data provider adds both
|
# prefix and just use FEA-1234 or FEA 1234, so allow for that. The FEA sigref data provider adds both
|
||||||
# forms to the database.
|
# forms to the database.
|
||||||
@@ -252,6 +277,7 @@ SIGS = [
|
|||||||
comment_names=["DMUE"],
|
comment_names=["DMUE"],
|
||||||
description="Diploma Museos de España",
|
description="Diploma Museos de España",
|
||||||
sig_type=SIGType.REGIONAL,
|
sig_type=SIGType.REGIONAL,
|
||||||
|
ref_type=SIGRefType.BUILDING,
|
||||||
ref_regex=r"MUE[A-Z]{2}-\d{3}",
|
ref_regex=r"MUE[A-Z]{2}-\d{3}",
|
||||||
icon="fa-landmark",
|
icon="fa-landmark",
|
||||||
region_flag="🇪🇸",
|
region_flag="🇪🇸",
|
||||||
@@ -262,6 +288,7 @@ SIGS = [
|
|||||||
comment_names=["DMVE"],
|
comment_names=["DMVE"],
|
||||||
description="Diploma Monumentos y Vestigios de España",
|
description="Diploma Monumentos y Vestigios de España",
|
||||||
sig_type=SIGType.REGIONAL,
|
sig_type=SIGType.REGIONAL,
|
||||||
|
ref_type=SIGRefType.BUILDING,
|
||||||
ref_regex=r"MV[A-Z]{1,2}-\d{4}",
|
ref_regex=r"MV[A-Z]{1,2}-\d{4}",
|
||||||
icon="fa-monument",
|
icon="fa-monument",
|
||||||
region_flag="🇪🇸",
|
region_flag="🇪🇸",
|
||||||
@@ -272,6 +299,7 @@ SIGS = [
|
|||||||
comment_names=["DCE"],
|
comment_names=["DCE"],
|
||||||
description="Diploma Castillos de España",
|
description="Diploma Castillos de España",
|
||||||
sig_type=SIGType.REGIONAL,
|
sig_type=SIGType.REGIONAL,
|
||||||
|
ref_type=SIGRefType.CASTLE,
|
||||||
ref_regex=r"C[A-Z]{1,2}-\d{3}",
|
ref_regex=r"C[A-Z]{1,2}-\d{3}",
|
||||||
icon="fa-chess-rook",
|
icon="fa-chess-rook",
|
||||||
region_flag="🇪🇸",
|
region_flag="🇪🇸",
|
||||||
@@ -282,6 +310,7 @@ SIGS = [
|
|||||||
comment_names=["DEFE"],
|
comment_names=["DEFE"],
|
||||||
description="Diploma Estaciones de Ferrocarril de España",
|
description="Diploma Estaciones de Ferrocarril de España",
|
||||||
sig_type=SIGType.REGIONAL,
|
sig_type=SIGType.REGIONAL,
|
||||||
|
ref_type=SIGRefType.BUILDING,
|
||||||
ref_regex=r"EF[A-Z]{1,2}-\d{3}",
|
ref_regex=r"EF[A-Z]{1,2}-\d{3}",
|
||||||
icon="fa-train",
|
icon="fa-train",
|
||||||
region_flag="🇪🇸",
|
region_flag="🇪🇸",
|
||||||
@@ -292,6 +321,7 @@ SIGS = [
|
|||||||
comment_names=["DTMBA"],
|
comment_names=["DTMBA"],
|
||||||
description="Diploma Teatri Musei e Belle Arti",
|
description="Diploma Teatri Musei e Belle Arti",
|
||||||
sig_type=SIGType.REGIONAL,
|
sig_type=SIGType.REGIONAL,
|
||||||
|
ref_type=SIGRefType.BUILDING,
|
||||||
ref_regex=r"I-?[0-9]{3,4}\s?[A-Z]{2}",
|
ref_regex=r"I-?[0-9]{3,4}\s?[A-Z]{2}",
|
||||||
icon="fa-landmark",
|
icon="fa-landmark",
|
||||||
region_flag="🇮🇹",
|
region_flag="🇮🇹",
|
||||||
@@ -302,6 +332,7 @@ SIGS = [
|
|||||||
comment_names=["BIWOTA"],
|
comment_names=["BIWOTA"],
|
||||||
description="British Inland Waterways on the Air",
|
description="British Inland Waterways on the Air",
|
||||||
sig_type=SIGType.EVENT,
|
sig_type=SIGType.EVENT,
|
||||||
|
ref_type=SIGRefType.WATERWAY,
|
||||||
icon="fa-ship",
|
icon="fa-ship",
|
||||||
region_flag="🇬🇧",
|
region_flag="🇬🇧",
|
||||||
refs_globally_unique=False,
|
refs_globally_unique=False,
|
||||||
@@ -311,6 +342,7 @@ SIGS = [
|
|||||||
comment_names=["COTA"],
|
comment_names=["COTA"],
|
||||||
description="Castles on the Air",
|
description="Castles on the Air",
|
||||||
sig_type=SIGType.REGIONAL,
|
sig_type=SIGType.REGIONAL,
|
||||||
|
ref_type=SIGRefType.CASTLE,
|
||||||
ref_regex=r"[A-Z]{3}\-[0-9]{3,5}",
|
ref_regex=r"[A-Z]{3}\-[0-9]{3,5}",
|
||||||
icon="fa-chess-rook",
|
icon="fa-chess-rook",
|
||||||
region_flag="🇩🇪",
|
region_flag="🇩🇪",
|
||||||
@@ -321,6 +353,7 @@ SIGS = [
|
|||||||
comment_names=["PGA"],
|
comment_names=["PGA"],
|
||||||
description="Polish Gmina Award",
|
description="Polish Gmina Award",
|
||||||
sig_type=SIGType.REGIONAL,
|
sig_type=SIGType.REGIONAL,
|
||||||
|
ref_type=SIGRefType.REGION,
|
||||||
ref_regex=r"[A-Z]{2}[0-9]{2}",
|
ref_regex=r"[A-Z]{2}[0-9]{2}",
|
||||||
icon="fa-g",
|
icon="fa-g",
|
||||||
region_flag="🇵🇱",
|
region_flag="🇵🇱",
|
||||||
@@ -331,6 +364,7 @@ SIGS = [
|
|||||||
comment_names=[],
|
comment_names=[],
|
||||||
description="Toilets on the Air",
|
description="Toilets on the Air",
|
||||||
sig_type=SIGType.EVENT,
|
sig_type=SIGType.EVENT,
|
||||||
|
ref_type=SIGRefType.TOILET,
|
||||||
ref_regex=r"T\-[0-9]{2}",
|
ref_regex=r"T\-[0-9]{2}",
|
||||||
icon="fa-toilet",
|
icon="fa-toilet",
|
||||||
region_flag="🏴☠️",
|
region_flag="🏴☠️",
|
||||||
|
|||||||
+29
-23
@@ -2,20 +2,22 @@ import logging
|
|||||||
|
|
||||||
from pyhamtools.locator import latlong_to_locator, locator_to_latlong
|
from pyhamtools.locator import latlong_to_locator, locator_to_latlong
|
||||||
|
|
||||||
|
from core.constants import SIGS
|
||||||
from core.data_store import DATA_STORE
|
from core.data_store import DATA_STORE
|
||||||
|
from core.enums import SIGRefType
|
||||||
from core.geo_utils import wab_wai_square_to_lat_lon
|
from core.geo_utils import wab_wai_square_to_lat_lon
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def get_sig_ref_info(sig, ref_id):
|
def get_sig_ref_info(sig_name, ref_id):
|
||||||
"""Look up details of a SIG reference (e.g. POTA park) such as name, lat/lon, and grid. Takes in a sig name and
|
"""Look up details of a SIG reference (e.g. POTA park) such as name, lat/lon, and grid. Takes in a sig name and
|
||||||
a reference ID (both strings) and returns a SigRef object populated with as much data as we can find. This makes
|
a reference ID (both strings) and returns a SigRef object populated with as much data as we can find. This makes
|
||||||
use of SIG ref data in the data store, live lookups from the web, or just automatic calculation depending on which
|
use of SIG ref data in the data store, live lookups from the web, or just automatic calculation depending on which
|
||||||
SIG we are getting data for."""
|
SIG we are getting data for."""
|
||||||
|
|
||||||
if sig is None or sig == "" or ref_id is None or ref_id == "":
|
if sig_name is None or sig_name == "" or ref_id is None or ref_id == "":
|
||||||
logger.debug("Failed to look up sig_ref info, sig or ref were not set.")
|
logger.debug("Failed to look up sig_ref info, sig or ref were not set.")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -24,33 +26,43 @@ def get_sig_ref_info(sig, ref_id):
|
|||||||
ref_id.replace(" ", "-")
|
ref_id.replace(" ", "-")
|
||||||
|
|
||||||
# Prepare the object to be returned
|
# Prepare the object to be returned
|
||||||
sig_ref = SIGRef(sig=sig, id=ref_id)
|
sig_ref = SIGRef(sig=sig_name, id=ref_id)
|
||||||
|
|
||||||
|
# We can always get the reference type and the icon from the SIG itself, if the reference data doesn't already
|
||||||
|
# contain it. If the sig ref already has this data, it should be used for preference.
|
||||||
|
for sig in SIGS:
|
||||||
|
if sig.name.upper() == sig_name.upper():
|
||||||
|
if not sig_ref.ref_type:
|
||||||
|
sig_ref.ref_type = sig.ref_type
|
||||||
|
if not sig_ref.icon:
|
||||||
|
sig_ref.icon = sig.icon
|
||||||
|
|
||||||
try:
|
try:
|
||||||
### FUDGES ###
|
### FUDGES ###
|
||||||
#
|
#
|
||||||
# DME fudge. Our database has leading zeros padding to 5 digits which is the expected format, but not all
|
# DME fudge. Our database has leading zeros padding to 5 digits which is the expected format, but not all
|
||||||
# activators add leading zeros.
|
# activators add leading zeros.
|
||||||
if sig.upper() == "DME":
|
if sig_name.upper() == "DME":
|
||||||
ref_id = ref_id.zfill(5)
|
ref_id = ref_id.zfill(5)
|
||||||
|
|
||||||
# DTMBA spotters sometimes include spaces and dashes, our regex allows them but they must be removed here so we
|
# DTMBA spotters sometimes include spaces and dashes, our regex allows them but they must be removed here so we
|
||||||
# can look up against the official list which doesn't have them
|
# can look up against the official list which doesn't have them
|
||||||
if sig.upper() == "DTMBA":
|
if sig_name.upper() == "DTMBA":
|
||||||
ref_id = ref_id.replace("-", "").replace(" ", "")
|
ref_id = ref_id.replace("-", "").replace(" ", "")
|
||||||
|
|
||||||
# If the SIG is HEMA, we have no current lookup for this so just skip the lookup here.
|
### NO DATA SIGS ###
|
||||||
if sig.upper() == "HEMA":
|
#
|
||||||
sig_ref.ref_type = "Summit"
|
# If the SIG is HEMA or BIWOTA, we have no way to either generate useful data or look it up on a reference list,
|
||||||
|
# so just skip the lookup here.
|
||||||
|
if sig_name.upper() == "HEMA" or sig_name.upper() == "BIWOTA":
|
||||||
return sig_ref
|
return sig_ref
|
||||||
|
|
||||||
### PROGRAMMATIC DATA GENERATION INSTEAD OF LOOKUPS ###
|
### PROGRAMMATIC DATA GENERATION INSTEAD OF LOOKUPS ###
|
||||||
#
|
#
|
||||||
# If the SIG is Tiles, WAB, WAI or BOTA (Beaches), we don't have anything to look up from the data store, we can
|
# If the SIG is Tiles, WAB, WAI or BOTA (Beaches), we don't have anything to look up from the data store, we can
|
||||||
# calculate all the information we are going to get directly.
|
# calculate all the information we are going to get directly.
|
||||||
if sig.upper() == "TILES":
|
if sig_name.upper() == "TILES":
|
||||||
# Tiles on the Air just uses Maidenhead 6-digit squares, so ID, Name and Grid are all the same
|
# Tiles on the Air just uses Maidenhead 6-digit squares, so ID, Name and Grid are all the same
|
||||||
sig_ref.ref_type = "Grid"
|
|
||||||
if not sig_ref.name:
|
if not sig_ref.name:
|
||||||
sig_ref.name = sig_ref.id
|
sig_ref.name = sig_ref.id
|
||||||
if not sig_ref.grid:
|
if not sig_ref.grid:
|
||||||
@@ -61,8 +73,7 @@ def get_sig_ref_info(sig, ref_id):
|
|||||||
sig_ref.longitude = ll[1]
|
sig_ref.longitude = ll[1]
|
||||||
return sig_ref
|
return sig_ref
|
||||||
|
|
||||||
elif sig.upper() == "WAB" or sig.upper() == "WAI":
|
elif sig_name.upper() == "WAB" or sig_name.upper() == "WAI":
|
||||||
sig_ref.ref_type = "Grid"
|
|
||||||
ll = wab_wai_square_to_lat_lon(ref_id)
|
ll = wab_wai_square_to_lat_lon(ref_id)
|
||||||
if ll:
|
if ll:
|
||||||
sig_ref.name = ref_id
|
sig_ref.name = ref_id
|
||||||
@@ -74,20 +85,15 @@ def get_sig_ref_info(sig, ref_id):
|
|||||||
logger.warning("Invalid lat/lon received for WAB/WAI reference")
|
logger.warning("Invalid lat/lon received for WAB/WAI reference")
|
||||||
return sig_ref
|
return sig_ref
|
||||||
|
|
||||||
elif sig.upper() == "BOTA":
|
elif sig_name.upper() == "BOTA":
|
||||||
# For BOTA all we can ever generate is the URL, there is no data file or lookup for lat/longs
|
# For BOTA all we can ever generate is the URL, there is no data file or lookup for lat/longs
|
||||||
sig_ref.ref_type = "Beach"
|
|
||||||
if not sig_ref.name:
|
if not sig_ref.name:
|
||||||
sig_ref.name = sig_ref.id
|
sig_ref.name = sig_ref.id
|
||||||
if sig_ref.name:
|
if sig_ref.name:
|
||||||
sig_ref.url = f"https://www.beachesontheair.com/beaches/{sig_ref.name.lower().replace(' ', '-')}"
|
sig_ref.url = f"https://www.beachesontheair.com/beaches/{sig_ref.name.lower().replace(' ', '-')}"
|
||||||
return sig_ref
|
return sig_ref
|
||||||
|
|
||||||
elif sig.upper() == "BIWOTA":
|
elif sig_name.upper() == "GMA Islands":
|
||||||
# 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
|
# 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.
|
# the best result.
|
||||||
iota_lookup = get_sig_ref_info("IOTA", ref_id)
|
iota_lookup = get_sig_ref_info("IOTA", ref_id)
|
||||||
@@ -98,14 +104,14 @@ def get_sig_ref_info(sig, ref_id):
|
|||||||
for key, value in gma_lookup.__dict__.items():
|
for key, value in gma_lookup.__dict__.items():
|
||||||
if value is not None and sig_ref.__dict__.get(key) is None:
|
if value is not None and sig_ref.__dict__.get(key) is None:
|
||||||
sig_ref.__dict__[key] = value
|
sig_ref.__dict__[key] = value
|
||||||
sig_ref.ref_type = "Island"
|
sig_ref.ref_type = SIGRefType.ISLAND
|
||||||
return sig_ref
|
return sig_ref
|
||||||
|
|
||||||
### ACTUAL LOOKUP ###
|
### ACTUAL LOOKUP ###
|
||||||
#
|
#
|
||||||
# OK, this is something we have to look up. Now check to see if our data store contains reference data and use
|
# OK, this is something we have to look up. Now check to see if our data store contains reference data and use
|
||||||
# that.
|
# that.
|
||||||
key = f"{sig}:{ref_id}"
|
key = f"{sig_name}:{ref_id}"
|
||||||
lookup_data = DATA_STORE.sigrefs.get(key) if key in DATA_STORE.sigrefs else None
|
lookup_data = DATA_STORE.sigrefs.get(key) if key in DATA_STORE.sigrefs else None
|
||||||
if lookup_data:
|
if lookup_data:
|
||||||
return lookup_data
|
return lookup_data
|
||||||
@@ -113,10 +119,10 @@ def get_sig_ref_info(sig, ref_id):
|
|||||||
else:
|
else:
|
||||||
# Maybe a super new reference we don't know about yet, but more likely a typo or a test reference,
|
# Maybe a super new reference we don't know about yet, but more likely a typo or a test reference,
|
||||||
# just silently ignore it.
|
# just silently ignore it.
|
||||||
logger.debug(f"{sig} database did not contain data for ref {ref_id}")
|
logger.debug(f"{sig_name} database did not contain data for ref {ref_id}")
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception(f"Exception when looking up sig_ref info for {sig} ref {ref_id}")
|
logger.exception(f"Exception when looking up sig_ref info for {sig_name} ref {ref_id}")
|
||||||
return sig_ref
|
return sig_ref
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+10
-1
@@ -99,7 +99,16 @@ def infer_mode_from_frequency(freq):
|
|||||||
or (28180 <= khz < 28183)
|
or (28180 <= khz < 28183)
|
||||||
):
|
):
|
||||||
mode = "FT4"
|
mode = "FT4"
|
||||||
return mode
|
|
||||||
|
if not mode:
|
||||||
|
return None
|
||||||
|
|
||||||
|
mode = mode.upper()
|
||||||
|
if mode in MODE_ALIASES:
|
||||||
|
mode = MODE_ALIASES[mode]
|
||||||
|
|
||||||
|
return Mode(mode)
|
||||||
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
+39
-10
@@ -20,6 +20,9 @@ class Alert:
|
|||||||
|
|
||||||
# Unique identifier for the alert
|
# Unique identifier for the alert
|
||||||
id: str | None = None
|
id: str | None = None
|
||||||
|
|
||||||
|
# DX (alerting) operator info
|
||||||
|
|
||||||
# Callsigns of the operators that has been alerted
|
# Callsigns of the operators that has been alerted
|
||||||
dx_calls: list | None = None
|
dx_calls: list | None = None
|
||||||
# Names of the operators that has been alerted
|
# Names of the operators that has been alerted
|
||||||
@@ -36,6 +39,9 @@ class Alert:
|
|||||||
dx_cq_zone: int | None = None
|
dx_cq_zone: int | None = None
|
||||||
# ITU zone of the DX operator
|
# ITU zone of the DX operator
|
||||||
dx_itu_zone: int | None = None
|
dx_itu_zone: int | None = None
|
||||||
|
|
||||||
|
# General alert info
|
||||||
|
|
||||||
# Intended frequencies & modes of operation. Essentially just a different kind of comment field.
|
# Intended frequencies & modes of operation. Essentially just a different kind of comment field.
|
||||||
freqs_modes: str | None = None
|
freqs_modes: str | None = None
|
||||||
# Start time of the activation, UTC seconds since UNIX epoch
|
# Start time of the activation, UTC seconds since UNIX epoch
|
||||||
@@ -46,27 +52,41 @@ class Alert:
|
|||||||
end_time: float | None = None
|
end_time: float | None = None
|
||||||
# End time of the activation of the alert, ISO 8601
|
# End time of the activation of the alert, ISO 8601
|
||||||
end_time_iso: str | None = None
|
end_time_iso: str | None = None
|
||||||
|
# Comment made by the alerter, if any
|
||||||
|
comment: str | None = None
|
||||||
|
# The type of alert this is: xOTA, DXpedition, or Contest.
|
||||||
|
alert_type: AlertType | None = None
|
||||||
|
# A URL link to more information, if any
|
||||||
|
url: str | None = None
|
||||||
|
|
||||||
|
# Special Interest Group info
|
||||||
|
|
||||||
|
# Special Interest Group (SIG), e.g. outdoor activity programme such as POTA
|
||||||
|
sig: str | None = None
|
||||||
|
# SIG references. We allow multiple here for e.g. n-fer activations, unlike ADIF SIG_INFO
|
||||||
|
sig_refs: list | None = None
|
||||||
|
|
||||||
|
# Timing info
|
||||||
|
|
||||||
# Time that this software received the alert, UTC seconds since UNIX epoch. This is used with the "since_received"
|
# Time that this software received the alert, UTC seconds since UNIX epoch. This is used with the "since_received"
|
||||||
# call to our API to receive all data that is new to us, even if by a quirk of the API it might be older than the
|
# call to our API to receive all data that is new to us, even if by a quirk of the API it might be older than the
|
||||||
# list time the client polled the API.
|
# list time the client polled the API.
|
||||||
received_time: float | None = None
|
received_time: float | None = None
|
||||||
# Time that this software received the alert, ISO 8601
|
# Time that this software received the alert, ISO 8601
|
||||||
received_time_iso: str | None = None
|
received_time_iso: str | None = None
|
||||||
# Comment made by the alerter, if any
|
|
||||||
comment: str | None = None
|
# Source info
|
||||||
# Special Interest Group (SIG), e.g. outdoor activity programme such as POTA
|
|
||||||
sig: str | None = None
|
|
||||||
# SIG references. We allow multiple here for e.g. n-fer activations, unlike ADIF SIG_INFO
|
|
||||||
sig_refs: list | None = None
|
|
||||||
# The type of alert this is: xOTA, DXpedition, or Contest.
|
|
||||||
alert_type: AlertType | None = None
|
|
||||||
# A URL link to more information, if any
|
|
||||||
url: str | None = None
|
|
||||||
# Where we got the alert from, e.g. "POTA", "SOTA"...
|
# Where we got the alert from, e.g. "POTA", "SOTA"...
|
||||||
source: str | None = None
|
source: str | None = None
|
||||||
# The ID the source gave it, if any.
|
# The ID the source gave it, if any.
|
||||||
source_id: str | None = None
|
source_id: str | None = None
|
||||||
|
|
||||||
|
# Display info
|
||||||
|
|
||||||
|
# Icon to use when displaying this alert in the web UI. Chosen from the Font Awesome set.
|
||||||
|
icon: str | None = None
|
||||||
|
|
||||||
def infer_missing(self, credentials=None):
|
def infer_missing(self, credentials=None):
|
||||||
"""Infer missing parameters where possible"""
|
"""Infer missing parameters where possible"""
|
||||||
|
|
||||||
@@ -132,6 +152,15 @@ class Alert:
|
|||||||
if self.dx_calls and not self.dx_names:
|
if self.dx_calls and not self.dx_names:
|
||||||
self.dx_names = [get_call_info(c, credentials).name for c in self.dx_calls]
|
self.dx_names = [get_call_info(c, credentials).name for c in self.dx_calls]
|
||||||
|
|
||||||
|
# Icon for the spot should be the icon of the first SIG ref if present, otherwise a radio tower
|
||||||
|
self.icon = "fa-tower-cell"
|
||||||
|
if self.alert_type == AlertType.DXPEDITION:
|
||||||
|
self.icon = "fa-globe-africa"
|
||||||
|
elif self.alert_type == AlertType.CONTEST:
|
||||||
|
self.icon = "fa-trophy"
|
||||||
|
elif self.sig_refs and len(self.sig_refs) > 0 and self.sig_refs[0].icon:
|
||||||
|
self.icon = self.sig_refs[0].icon
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception("Exception while inferring missing data from spot")
|
logger.exception("Exception while inferring missing data from spot")
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -1,6 +1,6 @@
|
|||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
from core.enums import SIGType
|
from core.enums import SIGRefType, SIGType
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -27,6 +27,9 @@ class SIG:
|
|||||||
refs_globally_unique: bool
|
refs_globally_unique: bool
|
||||||
# SIG names as they might appear in cluster spot comments, e.g. ["TOTA"]
|
# SIG names as they might appear in cluster spot comments, e.g. ["TOTA"]
|
||||||
comment_names: list[str] = field(default_factory=list)
|
comment_names: list[str] = field(default_factory=list)
|
||||||
|
# Reference type, what gets activated e.g. Park, Summit. May be None if the SIG is for multiple types of things, in
|
||||||
|
# which case the spot data will have to provide this instead.
|
||||||
|
ref_type: SIGRefType | None = None
|
||||||
# Regex matcher for references, e.g. for POTA r"[A-Z]{2}\-\d+".
|
# Regex matcher for references, e.g. for POTA r"[A-Z]{2}\-\d+".
|
||||||
ref_regex: str | None = None
|
ref_regex: str | None = None
|
||||||
# Icon to use in the UI when referencing this SIG. Chosen from the Font Awesome set.
|
# Icon to use in the UI when referencing this SIG. Chosen from the Font Awesome set.
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ class SIGRef:
|
|||||||
ref_type: SIGRefType | None = None
|
ref_type: SIGRefType | None = None
|
||||||
# URL to look up more information about the reference, if known.
|
# URL to look up more information about the reference, if known.
|
||||||
url: str | None = None
|
url: str | None = None
|
||||||
|
# Icon to use for the reference, derived from the SIG. Chosen from the Font Awesome set.
|
||||||
|
icon: str | None = None
|
||||||
# Latitude of the reference, in degrees, if known.
|
# Latitude of the reference, in degrees, if known.
|
||||||
latitude: float | None = None
|
latitude: float | None = None
|
||||||
# Longitude of the reference, in degrees, if known.
|
# Longitude of the reference, in degrees, if known.
|
||||||
|
|||||||
@@ -146,6 +146,11 @@ class Spot:
|
|||||||
# The ID the source gave it, if any.
|
# The ID the source gave it, if any.
|
||||||
source_id: str | None = None
|
source_id: str | None = None
|
||||||
|
|
||||||
|
# Display info
|
||||||
|
|
||||||
|
# Icon to use when displaying this spot in the web UI. Chosen from the Font Awesome set.
|
||||||
|
icon: str | None = None
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
"""Normalise fields that don't survive a plain dict to Spot conversion. This is used in the "add spot" API
|
"""Normalise fields that don't survive a plain dict to Spot conversion. This is used in the "add spot" API
|
||||||
endpoint where the client is submitting JSON, and we want to recreate a full Spot object, including nested
|
endpoint where the client is submitting JSON, and we want to recreate a full Spot object, including nested
|
||||||
@@ -455,6 +460,11 @@ class Spot:
|
|||||||
self.de_longitude = de_call_info.longitude
|
self.de_longitude = de_call_info.longitude
|
||||||
self.de_grid = de_call_info.grid
|
self.de_grid = de_call_info.grid
|
||||||
|
|
||||||
|
# Icon for the spot should be the icon of the first SIG ref if present, otherwise a radio tower
|
||||||
|
self.icon = "fa-tower-cell"
|
||||||
|
if self.sig_refs and len(self.sig_refs) > 0 and self.sig_refs[0].icon:
|
||||||
|
self.icon = self.sig_refs[0].icon
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception("Exception while inferring missing data from spot")
|
logger.exception("Exception while inferring missing data from spot")
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ info:
|
|||||||
* Added DTMBA, FEA, BIWOTA, COTA & PGA SIGs
|
* Added DTMBA, FEA, BIWOTA, COTA & PGA 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.
|
* 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 `sig_type`, `icon`, `region_flag` and `refs_globally_unique` to SIG data
|
* Added `sig_type`, `icon`, `region_flag` and `refs_globally_unique` to SIG data
|
||||||
|
* Added `icon` to spot and alert data
|
||||||
* Added `alert_type` and `url` to alert data
|
* Added `alert_type` and `url` to alert data
|
||||||
* Added `contests_skip_max_duration_check` to alert query parameters
|
* Added `contests_skip_max_duration_check` to alert query parameters
|
||||||
* SIG reference types (e.g. "Park") are now capitalised to match other enums
|
* SIG reference types (e.g. "Park") are now capitalised to match other enums
|
||||||
@@ -1298,6 +1299,10 @@ components:
|
|||||||
Propagation mode, if known. This is only populated when the upstream spot specifically states it; Spothole
|
Propagation mode, if known. This is only populated when the upstream spot specifically states it; Spothole
|
||||||
does not try to determine it using its own algorithm.
|
does not try to determine it using its own algorithm.
|
||||||
$ref: "#/components/schemas/PropagationMode"
|
$ref: "#/components/schemas/PropagationMode"
|
||||||
|
icon:
|
||||||
|
type: string
|
||||||
|
description: Icon to use when displaying this spot in the web UI. Chosen from the Font Awesome set.
|
||||||
|
example: "fa-tower-cell"
|
||||||
|
|
||||||
|
|
||||||
SpotSubmission:
|
SpotSubmission:
|
||||||
@@ -1466,6 +1471,10 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
description: The ID the source gave it, if any.
|
description: The ID the source gave it, if any.
|
||||||
example: "GUID-123456"
|
example: "GUID-123456"
|
||||||
|
icon:
|
||||||
|
type: string
|
||||||
|
description: Icon to use when displaying this spot in the web UI. Chosen from the Font Awesome set.
|
||||||
|
example: "fa-tower-cell"
|
||||||
|
|
||||||
|
|
||||||
AlertStream:
|
AlertStream:
|
||||||
|
|||||||
+2
-2
@@ -273,7 +273,7 @@ function addAlertRowsToTable(tbody, alerts) {
|
|||||||
$tr.append(`<td class='hideonmobile'>${commentText}</td>`);
|
$tr.append(`<td class='hideonmobile'>${commentText}</td>`);
|
||||||
}
|
}
|
||||||
if (showSource) {
|
if (showSource) {
|
||||||
$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>`);
|
$tr.append(`<td class='nowrap hideonmobile'><span class='icon-wrapper'><i class='fa-solid ${a["icon"]}'></i></span> ${sigSourceText}</td>`);
|
||||||
}
|
}
|
||||||
if (showRef) {
|
if (showRef) {
|
||||||
$tr.append(`<td class='hideonmobile'>${sig_refs}</td>`);
|
$tr.append(`<td class='hideonmobile'>${sig_refs}</td>`);
|
||||||
@@ -291,7 +291,7 @@ function addAlertRowsToTable(tbody, alerts) {
|
|||||||
|
|
||||||
const $td2 = $("<td colspan='100'>");
|
const $td2 = $("<td colspan='100'>");
|
||||||
if (showSource) {
|
if (showSource) {
|
||||||
$td2.append(`<span class='icon-wrapper'><i class='fa-solid ${sigToIcon(a["sig"], options["sigs"], "fa-globe-africa")}'></i></span> `);
|
$td2.append(`<span class='icon-wrapper'><i class='fa-solid ${a["icon"]}'></i></span> `);
|
||||||
}
|
}
|
||||||
if (showRef) {
|
if (showRef) {
|
||||||
$td2.append(`${sig_refs} `);
|
$td2.append(`${sig_refs} `);
|
||||||
|
|||||||
@@ -285,20 +285,6 @@ 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
|
// Startup
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
usePreferredTheme();
|
usePreferredTheme();
|
||||||
|
|||||||
+10
-4
@@ -223,7 +223,7 @@ function updateMap() {
|
|||||||
// Get an icon for a spot, based on its band, using PSK Reporter colours, its program etc.
|
// Get an icon for a spot, based on its band, using PSK Reporter colours, its program etc.
|
||||||
function getIcon(s) {
|
function getIcon(s) {
|
||||||
return L.ExtraMarkers.icon({
|
return L.ExtraMarkers.icon({
|
||||||
icon: sigToIcon(s["sig"], options["sigs"], "fa-tower-cell"),
|
icon: s["icon"],
|
||||||
iconColor: bandToContrastColor(s["band"]),
|
iconColor: bandToContrastColor(s["band"]),
|
||||||
markerColor: bandToColor(s["band"]),
|
markerColor: bandToColor(s["band"]),
|
||||||
shape: 'circle',
|
shape: 'circle',
|
||||||
@@ -243,13 +243,19 @@ function getTooltipText(s) {
|
|||||||
dx_call = dx_call + "-" + s["dx_ssid"];
|
dx_call = dx_call + "-" + s["dx_ssid"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Format dx country
|
||||||
|
let dx_country = s["dx_country"];
|
||||||
|
if (dx_country == null) {
|
||||||
|
dx_country = "Unknown or not a country";
|
||||||
|
}
|
||||||
|
|
||||||
// Format DX flag
|
// Format DX flag
|
||||||
let dx_flag = "<i class='fa-solid fa-globe-africa'></i>";
|
let dx_flag = "<i class='fa-solid fa-globe-africa'></i>";
|
||||||
if (dx_call == null) {
|
if (dx_call == null) {
|
||||||
dx_flag = "";
|
dx_flag = "";
|
||||||
}
|
}
|
||||||
if (s["dx_flag"] && s["dx_flag"] != null && s["dx_flag"] !== "") {
|
if (s["dx_dxcc_id"] && s["dx_dxcc_id"] != null && s["dx_dxcc_id"] !== 0) {
|
||||||
dx_flag = s["dx_flag"];
|
dx_flag = `<img src="static/img/flags/${s['dx_dxcc_id']}.png" class="flag" width="24" alt="${dx_country}" title="${dx_country}"/>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format the frequency
|
// Format the frequency
|
||||||
@@ -303,7 +309,7 @@ function getTooltipText(s) {
|
|||||||
ttt += "<br/>";
|
ttt += "<br/>";
|
||||||
|
|
||||||
// Source / SIG / Ref
|
// Source / SIG / Ref
|
||||||
ttt += `<span class='nowrap'><span class='icon-wrapper'><i class='fa-solid ${sigToIcon(s["sig"], options["sigs"], "fa-tower-cell")}'></i></span> ${sigSourceText} ${sig_refs}</span><br/>`;
|
ttt += `<span class='nowrap'><span class='icon-wrapper'><i class='fa-solid ${s["icon"]}'></i></span> ${sigSourceText} ${sig_refs}</span><br/>`;
|
||||||
|
|
||||||
// Time
|
// Time
|
||||||
ttt += `<span class='icon-wrapper'><i class='fa-solid fa-clock markerPopupIcon'></i></span> ${moment.unix(s["time"]).fromNow()}`;
|
ttt += `<span class='icon-wrapper'><i class='fa-solid fa-clock markerPopupIcon'></i></span> ${moment.unix(s["time"]).fromNow()}`;
|
||||||
|
|||||||
+2
-2
@@ -398,7 +398,7 @@ function createNewTableRowsForSpot(s, highlightNew) {
|
|||||||
$tr.append(`<td class='nowrap hideonmobile'>${distanceText}</td>`);
|
$tr.append(`<td class='nowrap hideonmobile'>${distanceText}</td>`);
|
||||||
}
|
}
|
||||||
if (showType) {
|
if (showType) {
|
||||||
$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>`);
|
$tr.append(`<td class='nowrap hideonmobile'><span class='icon-wrapper'><i class='fa-solid ${s["icon"]}'></i></span> ${typeText}</td>`);
|
||||||
}
|
}
|
||||||
if (showRef) {
|
if (showRef) {
|
||||||
$tr.append(`<td class='hideonmobile' style='max-width: 11em;'>${sig_refs}</td>`);
|
$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 $td2 = $("<td colspan='100'>");
|
||||||
const $td2floatleft = $(`<div style="float: left;">`);
|
const $td2floatleft = $(`<div style="float: left;">`);
|
||||||
if (showType) {
|
if (showType) {
|
||||||
$td2floatleft.append(`<span class='icon-wrapper'><i class='fa-solid ${sigToIcon(s["sig"], options["sigs"], "fa-tower-cell")}'></i></span> ${typeText} `);
|
$td2floatleft.append(`<span class='icon-wrapper'><i class='fa-solid ${s["icon"]}'></i></span> ${typeText} `);
|
||||||
}
|
}
|
||||||
if (showRef) {
|
if (showRef) {
|
||||||
$td2floatleft.append(`${sig_refs} `);
|
$td2floatleft.append(`${sig_refs} `);
|
||||||
|
|||||||
@@ -77,7 +77,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/add-spot.js?v=1788595232"></script>
|
<script src="/static/js/add-spot.js?v=1788598136"></script>
|
||||||
<script>$(document).ready(function () {
|
<script>$(document).ready(function () {
|
||||||
$("#nav-link-add-spot").addClass("active");
|
$("#nav-link-add-spot").addClass("active");
|
||||||
}); <!-- highlight active page in nav --></script>
|
}); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
@@ -81,7 +81,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/alerts.js?v=1788595233"></script>
|
<script src="/static/js/alerts.js?v=1788598136"></script>
|
||||||
<script>$(document).ready(function () {
|
<script>$(document).ready(function () {
|
||||||
$("#nav-link-alerts").addClass("active");
|
$("#nav-link-alerts").addClass("active");
|
||||||
}); <!-- highlight active page in nav --></script>
|
}); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
@@ -76,8 +76,8 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/spotsbandsandmap.js?v=1788595232"></script>
|
<script src="/static/js/spotsbandsandmap.js?v=1788598136"></script>
|
||||||
<script src="/static/js/bands.js?v=1788595232"></script>
|
<script src="/static/js/bands.js?v=1788598136"></script>
|
||||||
<script>$(document).ready(function () {
|
<script>$(document).ready(function () {
|
||||||
$("#nav-link-bands").addClass("active");
|
$("#nav-link-bands").addClass("active");
|
||||||
}); <!-- highlight active page in nav --></script>
|
}); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
+5
-5
@@ -1,6 +1,6 @@
|
|||||||
{% extends "skeleton.html" %}
|
{% extends "skeleton.html" %}
|
||||||
{% block head_extra %}
|
{% block head_extra %}
|
||||||
<link rel="stylesheet" href="/static/css/style.css?v=1788595232" type="text/css">
|
<link rel="stylesheet" href="/static/css/style.css?v=1788598136" type="text/css">
|
||||||
<link href="/static/vendor/css/bootstrap-5.3.8.min.css" rel="stylesheet">
|
<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/fontawesome-6.7.2.min.css" rel="stylesheet">
|
||||||
<link href="/static/vendor/css/solid-6.7.2.min.css" rel="stylesheet">
|
<link href="/static/vendor/css/solid-6.7.2.min.css" rel="stylesheet">
|
||||||
@@ -16,10 +16,10 @@
|
|||||||
window.fetchEventSource = fetchEventSource;
|
window.fetchEventSource = fetchEventSource;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script src="/static/js/utils.js?v=1788595232"></script>
|
<script src="/static/js/utils.js?v=1788598136"></script>
|
||||||
<script src="/static/js/ui-ham.js?v=1788595232"></script>
|
<script src="/static/js/ui-ham.js?v=1788598136"></script>
|
||||||
<script src="/static/js/geo.js?v=1788595232"></script>
|
<script src="/static/js/geo.js?v=1788598136"></script>
|
||||||
<script src="/static/js/common.js?v=1788595232"></script>
|
<script src="/static/js/common.js?v=1788598136"></script>
|
||||||
{% end %}
|
{% end %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|||||||
@@ -284,7 +284,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/vendor/js/chart-4.4.9.umd.min.js"></script>
|
<script src="/static/vendor/js/chart-4.4.9.umd.min.js"></script>
|
||||||
<script src="/static/js/conditions.js?v=1788595232"></script>
|
<script src="/static/js/conditions.js?v=1788598136"></script>
|
||||||
<script>$(document).ready(function () {
|
<script>$(document).ready(function () {
|
||||||
$("#nav-link-conditions").addClass("active");
|
$("#nav-link-conditions").addClass("active");
|
||||||
}); <!-- highlight active page in nav --></script>
|
}); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
+2
-2
@@ -113,8 +113,8 @@
|
|||||||
const CARTODB_API_KEY = "{{ web_ui_options.get('cartodb_api_key', '') }}";
|
const CARTODB_API_KEY = "{{ web_ui_options.get('cartodb_api_key', '') }}";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script src="/static/js/spotsbandsandmap.js?v=1788595233"></script>
|
<script src="/static/js/spotsbandsandmap.js?v=1788598136"></script>
|
||||||
<script src="/static/js/map.js?v=1788595233"></script>
|
<script src="/static/js/map.js?v=1788598136"></script>
|
||||||
<script>$(document).ready(function () {
|
<script>$(document).ready(function () {
|
||||||
$("#nav-link-map").addClass("active");
|
$("#nav-link-map").addClass("active");
|
||||||
}); <!-- highlight active page in nav --></script>
|
}); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
@@ -113,8 +113,8 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/spotsbandsandmap.js?v=1788595232"></script>
|
<script src="/static/js/spotsbandsandmap.js?v=1788598136"></script>
|
||||||
<script src="/static/js/spots.js?v=1788595232"></script>
|
<script src="/static/js/spots.js?v=1788598136"></script>
|
||||||
<script>$(document).ready(function () {
|
<script>$(document).ready(function () {
|
||||||
$("#nav-link-spots").addClass("active");
|
$("#nav-link-spots").addClass("active");
|
||||||
}); <!-- highlight active page in nav --></script>
|
}); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/status.js?v=1788595232"></script>
|
<script src="/static/js/status.js?v=1788598136"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$("#nav-link-status").addClass("active");
|
$("#nav-link-status").addClass("active");
|
||||||
|
|||||||
Reference in New Issue
Block a user