mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-09-20 14:27:42 +00:00
Split out event type SIGs, and do other enum conversions. Closes #138
This commit is contained in:
+41
-44
@@ -1,4 +1,5 @@
|
|||||||
from core.config import SERVER_OWNER_CALLSIGN
|
from core.config import SERVER_OWNER_CALLSIGN
|
||||||
|
from core.enums import SIGType
|
||||||
from data.band import Band
|
from data.band import Band
|
||||||
from data.sig import SIG
|
from data.sig import SIG
|
||||||
|
|
||||||
@@ -15,6 +16,7 @@ SIGS = [
|
|||||||
name="POTA",
|
name="POTA",
|
||||||
comment_names=["POTA"],
|
comment_names=["POTA"],
|
||||||
description="Parks on the Air",
|
description="Parks on the Air",
|
||||||
|
sig_type=SIGType.WORLDWIDE,
|
||||||
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,
|
||||||
@@ -23,6 +25,7 @@ SIGS = [
|
|||||||
name="SOTA",
|
name="SOTA",
|
||||||
comment_names=["SOTA"],
|
comment_names=["SOTA"],
|
||||||
description="Summits on the Air",
|
description="Summits on the Air",
|
||||||
|
sig_type=SIGType.WORLDWIDE,
|
||||||
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,
|
||||||
@@ -31,6 +34,7 @@ SIGS = [
|
|||||||
name="WWFF",
|
name="WWFF",
|
||||||
comment_names=["WWFF"],
|
comment_names=["WWFF"],
|
||||||
description="World Wide Flora & Fauna",
|
description="World Wide Flora & Fauna",
|
||||||
|
sig_type=SIGType.WORLDWIDE,
|
||||||
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,
|
||||||
@@ -39,6 +43,7 @@ SIGS = [
|
|||||||
name="GMA",
|
name="GMA",
|
||||||
comment_names=["GMA"],
|
comment_names=["GMA"],
|
||||||
description="Global Mountain Activity",
|
description="Global Mountain Activity",
|
||||||
|
sig_type=SIGType.WORLDWIDE,
|
||||||
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,
|
||||||
@@ -47,6 +52,7 @@ SIGS = [
|
|||||||
name="WWBOTA",
|
name="WWBOTA",
|
||||||
comment_names=["WWBOTA", "BOTA"],
|
comment_names=["WWBOTA", "BOTA"],
|
||||||
description="Worldwide Bunkers on the Air",
|
description="Worldwide Bunkers on the Air",
|
||||||
|
sig_type=SIGType.WORLDWIDE,
|
||||||
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,
|
||||||
@@ -55,6 +61,7 @@ SIGS = [
|
|||||||
name="HEMA",
|
name="HEMA",
|
||||||
comment_names=["HEMA"],
|
comment_names=["HEMA"],
|
||||||
description="HuMPs Excluding Marilyns Award",
|
description="HuMPs Excluding Marilyns Award",
|
||||||
|
sig_type=SIGType.WORLDWIDE,
|
||||||
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,
|
||||||
@@ -63,6 +70,7 @@ SIGS = [
|
|||||||
name="IOTA",
|
name="IOTA",
|
||||||
comment_names=["IOTA"],
|
comment_names=["IOTA"],
|
||||||
description="Islands on the Air",
|
description="Islands on the Air",
|
||||||
|
sig_type=SIGType.WORLDWIDE,
|
||||||
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,
|
||||||
@@ -71,6 +79,7 @@ SIGS = [
|
|||||||
name="GMA Islands",
|
name="GMA Islands",
|
||||||
comment_names=[],
|
comment_names=[],
|
||||||
description="Global Mountain Activity - Islands",
|
description="Global Mountain Activity - Islands",
|
||||||
|
sig_type=SIGType.WORLDWIDE,
|
||||||
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,
|
||||||
@@ -79,6 +88,7 @@ SIGS = [
|
|||||||
name="ARLHS",
|
name="ARLHS",
|
||||||
comment_names=["ARLHS"],
|
comment_names=["ARLHS"],
|
||||||
description="Amateur Radio Lighthouse Society",
|
description="Amateur Radio Lighthouse Society",
|
||||||
|
sig_type=SIGType.WORLDWIDE,
|
||||||
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,
|
||||||
@@ -87,6 +97,7 @@ SIGS = [
|
|||||||
name="ILLW",
|
name="ILLW",
|
||||||
comment_names=["ILLW"],
|
comment_names=["ILLW"],
|
||||||
description="International Lighthouse & Lightship Weekend",
|
description="International Lighthouse & Lightship Weekend",
|
||||||
|
sig_type=SIGType.EVENT,
|
||||||
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,
|
||||||
@@ -95,6 +106,7 @@ SIGS = [
|
|||||||
name="MOTA",
|
name="MOTA",
|
||||||
comment_names=["MOTA"],
|
comment_names=["MOTA"],
|
||||||
description="Mills on the Air",
|
description="Mills on the Air",
|
||||||
|
sig_type=SIGType.EVENT,
|
||||||
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,
|
||||||
@@ -103,6 +115,7 @@ SIGS = [
|
|||||||
name="SIOTA",
|
name="SIOTA",
|
||||||
comment_names=["SIOTA"],
|
comment_names=["SIOTA"],
|
||||||
description="Silos on the Air",
|
description="Silos on the Air",
|
||||||
|
sig_type=SIGType.WORLDWIDE,
|
||||||
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,
|
||||||
@@ -111,6 +124,7 @@ SIGS = [
|
|||||||
name="WCA",
|
name="WCA",
|
||||||
comment_names=["WCA"],
|
comment_names=["WCA"],
|
||||||
description="World Castles Award",
|
description="World Castles Award",
|
||||||
|
sig_type=SIGType.WORLDWIDE,
|
||||||
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,
|
||||||
@@ -119,6 +133,7 @@ SIGS = [
|
|||||||
name="ZLOTA",
|
name="ZLOTA",
|
||||||
comment_names=["ZLOTA"],
|
comment_names=["ZLOTA"],
|
||||||
description="New Zealand on the Air",
|
description="New Zealand on the Air",
|
||||||
|
sig_type=SIGType.REGIONAL,
|
||||||
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="🇳🇿",
|
||||||
@@ -128,32 +143,45 @@ SIGS = [
|
|||||||
name="WOTA",
|
name="WOTA",
|
||||||
comment_names=["WOTA"],
|
comment_names=["WOTA"],
|
||||||
description="Wainwrights on the Air",
|
description="Wainwrights on the Air",
|
||||||
|
sig_type=SIGType.REGIONAL,
|
||||||
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="🇬🇧",
|
||||||
refs_globally_unique=False,
|
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_type=SIGType.WORLDWIDE,
|
||||||
|
icon="fa-umbrella-beach",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
SIG(
|
SIG(
|
||||||
name="KRMNPA",
|
name="KRMNPA",
|
||||||
comment_names=["KRMNPA"],
|
comment_names=["KRMNPA"],
|
||||||
description="Keith Roget Memorial National Parks Award",
|
description="Keith Roget Memorial National Parks Award",
|
||||||
|
sig_type=SIGType.REGIONAL,
|
||||||
ref_regex=r"VKFF\-\d{4}",
|
ref_regex=r"VKFF\-\d{4}",
|
||||||
icon="fa-earth-oceania",
|
icon="fa-earth-oceania",
|
||||||
region_flag="🇦🇺",
|
region_flag="🇦🇺",
|
||||||
|
refs_globally_unique=False,
|
||||||
),
|
),
|
||||||
SIG(
|
SIG(
|
||||||
name="SANPCPA",
|
name="SANPCPA",
|
||||||
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,
|
||||||
ref_regex=r"VKFF\-\d{4}",
|
ref_regex=r"VKFF\-\d{4}",
|
||||||
icon="fa-earth-oceania",
|
icon="fa-earth-oceania",
|
||||||
region_flag="🇦🇺",
|
region_flag="🇦🇺",
|
||||||
|
refs_globally_unique=False,
|
||||||
),
|
),
|
||||||
SIG(
|
SIG(
|
||||||
name="LLOTA",
|
name="LLOTA",
|
||||||
comment_names=["LLOTA"],
|
comment_names=["LLOTA"],
|
||||||
description="Lagos y Lagunas on the Air",
|
description="Lagos y Lagunas on the Air",
|
||||||
|
sig_type=SIGType.WORLDWIDE,
|
||||||
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,
|
||||||
@@ -162,6 +190,7 @@ SIGS = [
|
|||||||
name="Towers",
|
name="Towers",
|
||||||
comment_names=["TOTA"],
|
comment_names=["TOTA"],
|
||||||
description="Towers on the Air",
|
description="Towers on the Air",
|
||||||
|
sig_type=SIGType.WORLDWIDE,
|
||||||
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,
|
||||||
@@ -170,6 +199,7 @@ SIGS = [
|
|||||||
name="Tiles",
|
name="Tiles",
|
||||||
comment_names=[],
|
comment_names=[],
|
||||||
description="Tiles on the Air",
|
description="Tiles on the Air",
|
||||||
|
sig_type=SIGType.WORLDWIDE,
|
||||||
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,
|
||||||
@@ -178,6 +208,7 @@ SIGS = [
|
|||||||
name="WAB",
|
name="WAB",
|
||||||
comment_names=["WAB"],
|
comment_names=["WAB"],
|
||||||
description="Worked All Britain",
|
description="Worked All Britain",
|
||||||
|
sig_type=SIGType.REGIONAL,
|
||||||
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="🇬🇧",
|
||||||
@@ -187,6 +218,7 @@ SIGS = [
|
|||||||
name="WAI",
|
name="WAI",
|
||||||
comment_names=["WAI"],
|
comment_names=["WAI"],
|
||||||
description="Worked All Ireland",
|
description="Worked All Ireland",
|
||||||
|
sig_type=SIGType.REGIONAL,
|
||||||
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="🇮🇪",
|
||||||
@@ -196,6 +228,7 @@ SIGS = [
|
|||||||
name="DME",
|
name="DME",
|
||||||
comment_names=["DME"],
|
comment_names=["DME"],
|
||||||
description="Diploma Municipios de España",
|
description="Diploma Municipios de España",
|
||||||
|
sig_type=SIGType.REGIONAL,
|
||||||
ref_regex=r"\d{4,5}",
|
ref_regex=r"\d{4,5}",
|
||||||
icon="fa-building",
|
icon="fa-building",
|
||||||
region_flag="🇪🇸",
|
region_flag="🇪🇸",
|
||||||
@@ -205,6 +238,7 @@ SIGS = [
|
|||||||
name="FEA",
|
name="FEA",
|
||||||
comment_names=["FEA"],
|
comment_names=["FEA"],
|
||||||
description="Diploma Faros de España",
|
description="Diploma Faros de España",
|
||||||
|
sig_type=SIGType.REGIONAL,
|
||||||
# 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.
|
||||||
@@ -217,6 +251,7 @@ SIGS = [
|
|||||||
name="DTMBA",
|
name="DTMBA",
|
||||||
comment_names=["DTMBA"],
|
comment_names=["DTMBA"],
|
||||||
description="Diploma Teatri Musei e Belle Arti",
|
description="Diploma Teatri Musei e Belle Arti",
|
||||||
|
sig_type=SIGType.REGIONAL,
|
||||||
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-masks-theater",
|
icon="fa-masks-theater",
|
||||||
region_flag="🇮🇹",
|
region_flag="🇮🇹",
|
||||||
@@ -226,13 +261,16 @@ SIGS = [
|
|||||||
name="BIWOTA",
|
name="BIWOTA",
|
||||||
comment_names=["BIWOTA"],
|
comment_names=["BIWOTA"],
|
||||||
description="British Inland Waterways on the Air",
|
description="British Inland Waterways on the Air",
|
||||||
|
sig_type=SIGType.EVENT,
|
||||||
icon="fa-ship",
|
icon="fa-ship",
|
||||||
region_flag="🇬🇧",
|
region_flag="🇬🇧",
|
||||||
|
refs_globally_unique=False,
|
||||||
),
|
),
|
||||||
SIG(
|
SIG(
|
||||||
name="COTA",
|
name="COTA",
|
||||||
comment_names=["COTA"],
|
comment_names=["COTA"],
|
||||||
description="Castles on the Air",
|
description="Castles on the Air",
|
||||||
|
sig_type=SIGType.REGIONAL,
|
||||||
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="🇩🇪",
|
||||||
@@ -242,6 +280,7 @@ SIGS = [
|
|||||||
name="PGA",
|
name="PGA",
|
||||||
comment_names=["PGA"],
|
comment_names=["PGA"],
|
||||||
description="Polish Gmina Award",
|
description="Polish Gmina Award",
|
||||||
|
sig_type=SIGType.REGIONAL,
|
||||||
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="🇵🇱",
|
||||||
@@ -251,6 +290,7 @@ SIGS = [
|
|||||||
name="Toilets",
|
name="Toilets",
|
||||||
comment_names=[],
|
comment_names=[],
|
||||||
description="Toilets on the Air",
|
description="Toilets on the Air",
|
||||||
|
sig_type=SIGType.EVENT,
|
||||||
ref_regex=r"T\-[0-9]{2}",
|
ref_regex=r"T\-[0-9]{2}",
|
||||||
icon="fa-toilet",
|
icon="fa-toilet",
|
||||||
region_flag="🏴☠️",
|
region_flag="🏴☠️",
|
||||||
@@ -258,49 +298,6 @@ SIGS = [
|
|||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Modes. Note "DIGI" and "DIGITAL" are also supported but are normalised into "DATA".
|
|
||||||
CW_MODES = ["CW"]
|
|
||||||
PHONE_MODES = ["PHONE", "SSB", "AM", "FM", "DV"]
|
|
||||||
DATA_MODES = [
|
|
||||||
"DATA",
|
|
||||||
"FT8",
|
|
||||||
"FT4",
|
|
||||||
"RTTY",
|
|
||||||
"SSTV",
|
|
||||||
"JS8",
|
|
||||||
"HELL",
|
|
||||||
"PSK",
|
|
||||||
"FSK",
|
|
||||||
"OLIVIA",
|
|
||||||
"PKT",
|
|
||||||
"MSK144",
|
|
||||||
]
|
|
||||||
ALL_MODES = CW_MODES + PHONE_MODES + DATA_MODES
|
|
||||||
|
|
||||||
# Mode aliases. Sometimes we get spots with a mode described in a different way that is effectively the same as a mode
|
|
||||||
# we already know, or we want to normalise things for consistency. The lookup table for this is here. Incoming spots
|
|
||||||
# that match a key in this table will be converted to the corresponding value, so only the modes above will actually be
|
|
||||||
# present in the spots.
|
|
||||||
MODE_ALIASES = {
|
|
||||||
"USB": "SSB",
|
|
||||||
"LSB": "SSB",
|
|
||||||
"DIGITALVOICE": "DV",
|
|
||||||
"DIGITALVOI": "DV",
|
|
||||||
"DMR": "DV",
|
|
||||||
"DSTAR": "DV",
|
|
||||||
"C4FM": "DV",
|
|
||||||
"FUSION": "DV",
|
|
||||||
"M17": "DV",
|
|
||||||
"RTT": "RTTY",
|
|
||||||
"BPSK": "PSK",
|
|
||||||
"PSK31": "PSK",
|
|
||||||
"BPSK31": "PSK",
|
|
||||||
"MFSK": "FSK",
|
|
||||||
"MFSK32": "FSK",
|
|
||||||
"DIGI": "DATA",
|
|
||||||
"DIGITAL": "DATA",
|
|
||||||
}
|
|
||||||
|
|
||||||
# Band definitions
|
# Band definitions
|
||||||
BANDS = [
|
BANDS = [
|
||||||
Band(name="2200m", start_freq=135700, end_freq=137800),
|
Band(name="2200m", start_freq=135700, end_freq=137800),
|
||||||
|
|||||||
+102
@@ -11,6 +11,52 @@ class Continent(str, Enum):
|
|||||||
AN = "AN"
|
AN = "AN"
|
||||||
|
|
||||||
|
|
||||||
|
class Mode(str, Enum):
|
||||||
|
CW = "CW"
|
||||||
|
PHONE = "PHONE"
|
||||||
|
SSB = "SSB"
|
||||||
|
AM = "AM"
|
||||||
|
FM = "FM"
|
||||||
|
DV = "DV"
|
||||||
|
DATA = "DATA"
|
||||||
|
FT8 = "FT8"
|
||||||
|
FT4 = "FT4"
|
||||||
|
RTTY = "RTTY"
|
||||||
|
SSTV = "SSTV"
|
||||||
|
JS8 = "JS8"
|
||||||
|
HELL = "HELL"
|
||||||
|
PSK = "PSK"
|
||||||
|
FSK = "FSK"
|
||||||
|
OLIVIA = "OLIVIA"
|
||||||
|
PKT = "PKT"
|
||||||
|
MSK144 = "MSK144"
|
||||||
|
UNKNOWN = "UNKNOWN"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_cw(self) -> bool:
|
||||||
|
return self == Mode.CW
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_phone(self) -> bool:
|
||||||
|
return self in {Mode.PHONE, Mode.SSB, Mode.AM, Mode.FM, Mode.DV}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_data(self) -> bool:
|
||||||
|
return not (self.is_cw or self.is_phone or self == Mode.UNKNOWN)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_name(name):
|
||||||
|
"""Convert a string to an enum mode using the alias table."""
|
||||||
|
|
||||||
|
try:
|
||||||
|
return Mode(name.upper())
|
||||||
|
except ValueError:
|
||||||
|
try:
|
||||||
|
return Mode(MODE_ALIASES[name.upper()])
|
||||||
|
except ValueError:
|
||||||
|
return Mode.UNKNOWN
|
||||||
|
|
||||||
|
|
||||||
class ModeType(str, Enum):
|
class ModeType(str, Enum):
|
||||||
PHONE = "PHONE"
|
PHONE = "PHONE"
|
||||||
CW = "CW"
|
CW = "CW"
|
||||||
@@ -44,3 +90,59 @@ class LocationSourceForCallsign(str, Enum):
|
|||||||
HOME_QTH = "HOME QTH"
|
HOME_QTH = "HOME QTH"
|
||||||
DXCC = "DXCC"
|
DXCC = "DXCC"
|
||||||
NONE = "NONE"
|
NONE = "NONE"
|
||||||
|
|
||||||
|
|
||||||
|
class SIGRefType(str, Enum):
|
||||||
|
"""Type of a Special Interest Group reference."""
|
||||||
|
|
||||||
|
PARK = "PARK"
|
||||||
|
SUMMIT = "SUMMIT"
|
||||||
|
CASTLE = "CASTLE"
|
||||||
|
LIGHTHOUSE = "LIGHTHOUSE"
|
||||||
|
ISLAND = "ISLAND"
|
||||||
|
BUNKER = "BUNKER"
|
||||||
|
MILL = "MILL"
|
||||||
|
SILO = "SILO"
|
||||||
|
BEACH = "BEACH"
|
||||||
|
LAKE = "LAKE"
|
||||||
|
TOWER = "TOWER"
|
||||||
|
WATERWAY = "WATERWAY"
|
||||||
|
TOWN = "TOWN"
|
||||||
|
BUILDING = "BUILDING"
|
||||||
|
REGION = "REGION"
|
||||||
|
GRID = "GRID"
|
||||||
|
TOILET = "TOILET"
|
||||||
|
UNKNOWN = "UNKNOWN"
|
||||||
|
|
||||||
|
|
||||||
|
class SIGType(str, Enum):
|
||||||
|
"""Type of a Special Interest Group. Used to group them in the web UI."""
|
||||||
|
|
||||||
|
WORLDWIDE = "WORLDWIDE"
|
||||||
|
REGIONAL = "REGIONAL"
|
||||||
|
EVENT = "EVENT"
|
||||||
|
|
||||||
|
|
||||||
|
# Mode aliases. Sometimes we get spots with a mode described in a different way that is effectively the same as a mode
|
||||||
|
# we already know, or we want to normalise things for consistency. The lookup table for this is here. Incoming spots
|
||||||
|
# that match a key in this table will be converted to the corresponding value, so only the modes above will actually be
|
||||||
|
# present in the spots.
|
||||||
|
MODE_ALIASES = {
|
||||||
|
"USB": "SSB",
|
||||||
|
"LSB": "SSB",
|
||||||
|
"DIGITALVOICE": "DV",
|
||||||
|
"DIGITALVOI": "DV",
|
||||||
|
"DMR": "DV",
|
||||||
|
"DSTAR": "DV",
|
||||||
|
"C4FM": "DV",
|
||||||
|
"FUSION": "DV",
|
||||||
|
"M17": "DV",
|
||||||
|
"RTT": "RTTY",
|
||||||
|
"BPSK": "PSK",
|
||||||
|
"PSK31": "PSK",
|
||||||
|
"BPSK31": "PSK",
|
||||||
|
"MFSK": "FSK",
|
||||||
|
"MFSK32": "FSK",
|
||||||
|
"DIGI": "DATA",
|
||||||
|
"DIGITAL": "DATA",
|
||||||
|
}
|
||||||
|
|||||||
+26
-25
@@ -5,17 +5,9 @@ import simplejson
|
|||||||
from pyhamtools.frequency import freq_to_band
|
from pyhamtools.frequency import freq_to_band
|
||||||
from pyhamtools.locator import latlong_to_locator
|
from pyhamtools.locator import latlong_to_locator
|
||||||
|
|
||||||
from core.constants import (
|
from core.constants import BANDS, UNKNOWN_BAND
|
||||||
ALL_MODES,
|
|
||||||
BANDS,
|
|
||||||
CW_MODES,
|
|
||||||
DATA_MODES,
|
|
||||||
MODE_ALIASES,
|
|
||||||
PHONE_MODES,
|
|
||||||
UNKNOWN_BAND,
|
|
||||||
)
|
|
||||||
from core.data_store import DATA_STORE
|
from core.data_store import DATA_STORE
|
||||||
from core.enums import Continent, ModeType
|
from core.enums import MODE_ALIASES, Continent, Mode, ModeType
|
||||||
from data.callsign import Callsign, LocationSourceForCallsign
|
from data.callsign import Callsign, LocationSourceForCallsign
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -28,31 +20,40 @@ def safe_json_dumps(obj):
|
|||||||
return simplejson.dumps(obj, ensure_ascii=False, ignore_nan=True, default=lambda o: o.__dict__)
|
return simplejson.dumps(obj, ensure_ascii=False, ignore_nan=True, default=lambda o: o.__dict__)
|
||||||
|
|
||||||
|
|
||||||
def infer_mode_from_comment(comment):
|
def infer_mode_from_comment(comment: str) -> Mode:
|
||||||
"""Infer a mode from the comment"""
|
"""Infer a mode from the comment"""
|
||||||
|
|
||||||
for mode in ALL_MODES:
|
if not comment:
|
||||||
|
return Mode.UNKNOWN
|
||||||
|
|
||||||
|
for mode in Mode:
|
||||||
if re.search(r"(^|\W)" + mode + r"($|\W)", comment, re.IGNORECASE):
|
if re.search(r"(^|\W)" + mode + r"($|\W)", comment, re.IGNORECASE):
|
||||||
return mode
|
return mode
|
||||||
for mode in MODE_ALIASES:
|
for alias in MODE_ALIASES:
|
||||||
if re.search(r"(^|\W)" + mode + r"($|\W)", comment, re.IGNORECASE):
|
if re.search(r"(^|\W)" + alias + r"($|\W)", comment, re.IGNORECASE):
|
||||||
return MODE_ALIASES[mode]
|
return Mode(MODE_ALIASES[alias])
|
||||||
return None
|
|
||||||
|
return Mode.UNKNOWN
|
||||||
|
|
||||||
|
|
||||||
def infer_mode_type_from_mode(mode):
|
def infer_mode_type_from_mode(mode: str) -> ModeType:
|
||||||
"""Infer a "mode family" from a mode."""
|
"""Infer a "mode family" from a mode ."""
|
||||||
|
|
||||||
if mode.upper() in CW_MODES:
|
if not mode:
|
||||||
return ModeType.CW
|
return ModeType.UNKNOWN
|
||||||
elif mode.upper() in PHONE_MODES:
|
|
||||||
return ModeType.PHONE
|
try:
|
||||||
elif mode.upper() in DATA_MODES:
|
mode = Mode(mode.upper())
|
||||||
|
if mode.is_cw:
|
||||||
|
return ModeType.CW
|
||||||
|
if mode.is_phone:
|
||||||
|
return ModeType.PHONE
|
||||||
return ModeType.DATA
|
return ModeType.DATA
|
||||||
else:
|
|
||||||
|
except ValueError:
|
||||||
if mode.upper() != "OTHER" and mode != "?":
|
if mode.upper() != "OTHER" and mode != "?":
|
||||||
logger.warning(f"Found an unrecognised mode: {mode}. Developer should categorise this.")
|
logger.warning(f"Found an unrecognised mode: {mode}. Developer should categorise this.")
|
||||||
return None
|
return ModeType.UNKNOWN
|
||||||
|
|
||||||
|
|
||||||
def infer_band_from_freq(freq):
|
def infer_band_from_freq(freq):
|
||||||
|
|||||||
+1
-1
@@ -93,7 +93,7 @@ class Alert:
|
|||||||
if self.dx_calls and self.dx_calls[0] and not self.dx_country:
|
if self.dx_calls and self.dx_calls[0] and not self.dx_country:
|
||||||
self.dx_country = call_info.country
|
self.dx_country = call_info.country
|
||||||
if self.dx_calls and self.dx_calls[0] and not self.dx_continent:
|
if self.dx_calls and self.dx_calls[0] and not self.dx_continent:
|
||||||
self.dx_continent = Continent(call_info.continent)
|
self.dx_continent = Continent(call_info.continent) if call_info.continent else None
|
||||||
if self.dx_calls and self.dx_calls[0] and not self.dx_cq_zone:
|
if self.dx_calls and self.dx_calls[0] and not self.dx_cq_zone:
|
||||||
self.dx_cq_zone = call_info.cq_zone
|
self.dx_cq_zone = call_info.cq_zone
|
||||||
if self.dx_calls and self.dx_calls[0] and not self.dx_itu_zone:
|
if self.dx_calls and self.dx_calls[0] and not self.dx_itu_zone:
|
||||||
|
|||||||
+9
-5
@@ -1,5 +1,7 @@
|
|||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
|
from core.enums import SIGType
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class SIG:
|
class SIG:
|
||||||
@@ -15,16 +17,18 @@ class SIG:
|
|||||||
name: str
|
name: str
|
||||||
# Description, e.g. "Towers on the Air"
|
# Description, e.g. "Towers on the Air"
|
||||||
description: str
|
description: str
|
||||||
# SIG names as they might appear in cluster spot comments, e.g. ["TOTA"]
|
# Type, either Worldwide, Regional or Event. Used for sorting in the web UI.
|
||||||
comment_names: list[str] = field(default_factory=list)
|
sig_type: SIGType
|
||||||
# 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
|
# 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
|
# 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
|
# 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
|
# obviously WWFF and WWBOTA, nothing else looks like those. But "SZ09" could be WAB or Tiles, "GB1234" could
|
||||||
# conceivably be POTA or ILLW, etc.
|
# conceivably be POTA or ILLW, etc.
|
||||||
refs_globally_unique: bool = False
|
refs_globally_unique: bool
|
||||||
|
# SIG names as they might appear in cluster spot comments, e.g. ["TOTA"]
|
||||||
|
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
|
||||||
# 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.
|
||||||
icon: str | None = None
|
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
|
# Emoji flag for the country or region where this SIG is relevant, if any. If None, this implies the SIG is in
|
||||||
|
|||||||
+3
-1
@@ -1,5 +1,7 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class SIGRef:
|
class SIGRef:
|
||||||
@@ -13,7 +15,7 @@ class SIGRef:
|
|||||||
# Name of the reference, e.g. "Null Country Park", if known.
|
# Name of the reference, e.g. "Null Country Park", if known.
|
||||||
name: str | None = None
|
name: str | None = None
|
||||||
# Type of the reference, e.g. "Park", if known.
|
# Type of the reference, e.g. "Park", if known.
|
||||||
ref_type: str | None = None
|
ref_type: SIGRefType = SIGRefType.UNKNOWN
|
||||||
# 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
|
||||||
# Latitude of the reference, in degrees, if known.
|
# Latitude of the reference, in degrees, if known.
|
||||||
|
|||||||
+11
-11
@@ -11,8 +11,8 @@ from pyhamtools.locator import latlong_to_locator, locator_to_latlong
|
|||||||
|
|
||||||
from core.call_lookup_helper import get_call_info
|
from core.call_lookup_helper import get_call_info
|
||||||
from core.config import MAX_SPOT_AGE
|
from core.config import MAX_SPOT_AGE
|
||||||
from core.constants import MODE_ALIASES, PROPAGATION_MODES, SIGS
|
from core.constants import PROPAGATION_MODES, SIGS
|
||||||
from core.enums import Continent, LocationSourceForSpot, ModeSource, ModeType
|
from core.enums import Continent, LocationSourceForSpot, Mode, ModeSource, ModeType
|
||||||
from core.geo_utils import lat_lon_to_cq_zone, lat_lon_to_itu_zone
|
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_lookup_helper import populate_missing_sig_ref_info
|
||||||
from core.sig_utils import (
|
from core.sig_utils import (
|
||||||
@@ -103,7 +103,7 @@ class Spot:
|
|||||||
# General QSO info
|
# General QSO info
|
||||||
|
|
||||||
# Reported mode, such as SSB, PHONE, CW, FT8...
|
# Reported mode, such as SSB, PHONE, CW, FT8...
|
||||||
mode: str | None = None
|
mode: Mode = Mode.UNKNOWN
|
||||||
# Inferred mode "family".
|
# Inferred mode "family".
|
||||||
mode_type: ModeType = ModeType.UNKNOWN
|
mode_type: ModeType = ModeType.UNKNOWN
|
||||||
# Source of the mode information.
|
# Source of the mode information.
|
||||||
@@ -239,21 +239,21 @@ class Spot:
|
|||||||
self.band = band.name
|
self.band = band.name
|
||||||
|
|
||||||
# Mode from comments or bandplan
|
# Mode from comments or bandplan
|
||||||
if self.mode:
|
if not self.mode:
|
||||||
|
self.mode = Mode.UNKNOWN
|
||||||
|
if self.mode != Mode.UNKNOWN:
|
||||||
self.mode_source = ModeSource.SPOT
|
self.mode_source = ModeSource.SPOT
|
||||||
if self.comment and not self.mode:
|
if self.comment and self.mode == Mode.UNKNOWN:
|
||||||
self.mode = infer_mode_from_comment(self.comment)
|
self.mode = infer_mode_from_comment(self.comment)
|
||||||
self.mode_source = ModeSource.COMMENT
|
self.mode_source = ModeSource.COMMENT
|
||||||
if self.freq and not self.mode:
|
if self.freq and self.mode == Mode.UNKNOWN:
|
||||||
self.mode = infer_mode_from_frequency(self.freq)
|
self.mode = infer_mode_from_frequency(self.freq)
|
||||||
self.mode_source = ModeSource.BANDPLAN
|
self.mode_source = ModeSource.BANDPLAN
|
||||||
|
|
||||||
# Normalise mode if necessary.
|
|
||||||
if self.mode in MODE_ALIASES:
|
|
||||||
self.mode = MODE_ALIASES[self.mode]
|
|
||||||
|
|
||||||
# Mode type from mode
|
# Mode type from mode
|
||||||
if self.mode and not self.mode_type:
|
if not self.mode_type:
|
||||||
|
self.mode_type = ModeType.UNKNOWN
|
||||||
|
if self.mode != Mode.UNKNOWN and self.mode_type == ModeType.UNKNOWN:
|
||||||
self.mode_type = infer_mode_type_from_mode(self.mode)
|
self.mode_type = infer_mode_type_from_mode(self.mode)
|
||||||
|
|
||||||
# If we have a latitude or grid at this point, it can only have been provided by the spot itself
|
# If we have a latitude or grid at this point, it can only have been provided by the spot itself
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -27,7 +28,7 @@ class ARLHS(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=row.get("Name", None),
|
name=row.get("Name", None),
|
||||||
ref_type="Lighthouse",
|
ref_type=SIGRefType.LIGHTHOUSE,
|
||||||
url=f"https://www.cqgma.org/zinfo.php?ref={ref_id}",
|
url=f"https://www.cqgma.org/zinfo.php?ref={ref_id}",
|
||||||
latitude=float(row["Latitude"]) if "Latitude" in row and row["Latitude"] != "" else None,
|
latitude=float(row["Latitude"]) if "Latitude" in row and row["Latitude"] != "" else None,
|
||||||
longitude=float(row["Longitude"]) if "Longitude" in row and row["Longitude"] != "" else None,
|
longitude=float(row["Longitude"]) if "Longitude" in row and row["Longitude"] != "" else None,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from time import sleep
|
|||||||
|
|
||||||
from pyhamtools.locator import latlong_to_locator
|
from pyhamtools.locator import latlong_to_locator
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import FileDownloadSIGRefDataProvider
|
from providers.sigrefdata.file_download_sig_ref_data_provider import FileDownloadSIGRefDataProvider
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ class COTA(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=name,
|
name=name,
|
||||||
ref_type="Castle",
|
ref_type=SIGRefType.CASTLE,
|
||||||
grid=grid,
|
grid=grid,
|
||||||
latitude=lat,
|
latitude=lat,
|
||||||
longitude=lon,
|
longitude=lon,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from time import sleep
|
|||||||
|
|
||||||
from pyhamtools.locator import latlong_to_locator
|
from pyhamtools.locator import latlong_to_locator
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.local_file_sig_ref_data_provider import (
|
from providers.sigrefdata.local_file_sig_ref_data_provider import (
|
||||||
LocalFileSIGRefDataProvider,
|
LocalFileSIGRefDataProvider,
|
||||||
@@ -37,7 +38,7 @@ class DME(LocalFileSIGRefDataProvider):
|
|||||||
ref = SIGRef(
|
ref = SIGRef(
|
||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
ref_type="Town",
|
ref_type=SIGRefType.TOWN,
|
||||||
name=f"{row['NOMBRE_ACTUAL']}, {row['PROVINCIA']}",
|
name=f"{row['NOMBRE_ACTUAL']}, {row['PROVINCIA']}",
|
||||||
latitude=latitude,
|
latitude=latitude,
|
||||||
longitude=longitude,
|
longitude=longitude,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import FileDownloadSIGRefDataProvider
|
from providers.sigrefdata.file_download_sig_ref_data_provider import FileDownloadSIGRefDataProvider
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ class DTMBA(FileDownloadSIGRefDataProvider):
|
|||||||
split = row.split(";")
|
split = row.split(";")
|
||||||
ref_id = split[0]
|
ref_id = split[0]
|
||||||
ref_name = split[1]
|
ref_name = split[1]
|
||||||
new_data.append(SIGRef(sig=self.SIG, id=ref_id, name=ref_name, ref_type="Building"))
|
new_data.append(SIGRef(sig=self.SIG, id=ref_id, name=ref_name, ref_type=SIGRefType.BUILDING))
|
||||||
|
|
||||||
# Bail out if a stop has been requested, i.e. the program is shutting down - no need to parse the rest of
|
# 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
|
# the data in this case
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from time import sleep
|
|||||||
|
|
||||||
import pdfplumber
|
import pdfplumber
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import FileDownloadSIGRefDataProvider
|
from providers.sigrefdata.file_download_sig_ref_data_provider import FileDownloadSIGRefDataProvider
|
||||||
|
|
||||||
@@ -40,8 +41,8 @@ class FEA(FileDownloadSIGRefDataProvider):
|
|||||||
# prefix and just use FEA-1234 or FEA 1234, so we add both copies to the database.
|
# 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_1 = row[0].strip()
|
||||||
ref_id_2 = ref_id_1.replace("D-", "FEA-").replace("E-", "FEA-")
|
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_1, name=row[1].strip(), ref_type=SIGRefType.LIGHTHOUSE))
|
||||||
new_data.append(SIGRef(sig=self.SIG, id=ref_id_2, name=row[1].strip(), ref_type="Lighthouse"))
|
new_data.append(SIGRef(sig=self.SIG, id=ref_id_2, name=row[1].strip(), ref_type=SIGRefType.LIGHTHOUSE))
|
||||||
|
|
||||||
# Bail out if a stop has been requested, i.e. the program is shutting down - no need to parse the rest of
|
# 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
|
# the data in this case
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -26,7 +27,7 @@ class GMA(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=row.get("Name", None),
|
name=row.get("Name", None),
|
||||||
ref_type="Summit",
|
ref_type=SIGRefType.SUMMIT,
|
||||||
url=f"https://www.cqgma.org/zinfo.php?ref={ref_id}",
|
url=f"https://www.cqgma.org/zinfo.php?ref={ref_id}",
|
||||||
latitude=float(row["Latitude"]) if "Latitude" in row and row["Latitude"] != "" else None,
|
latitude=float(row["Latitude"]) if "Latitude" in row and row["Latitude"] != "" else None,
|
||||||
longitude=float(row["Longitude"]) if "Longitude" in row and row["Longitude"] != "" else None,
|
longitude=float(row["Longitude"]) if "Longitude" in row and row["Longitude"] != "" else None,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -27,7 +28,7 @@ class ILLW(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=row.get("Name", None),
|
name=row.get("Name", None),
|
||||||
ref_type="Lighthouse",
|
ref_type=SIGRefType.LIGHTHOUSE,
|
||||||
url=f"https://www.cqgma.org/zinfo.php?ref={ref_id}",
|
url=f"https://www.cqgma.org/zinfo.php?ref={ref_id}",
|
||||||
latitude=float(row["Latitude"]) if "Latitude" in row and row["Latitude"] != "" else None,
|
latitude=float(row["Latitude"]) if "Latitude" in row and row["Latitude"] != "" else None,
|
||||||
longitude=float(row["Longitude"]) if "Longitude" in row and row["Longitude"] != "" else None,
|
longitude=float(row["Longitude"]) if "Longitude" in row and row["Longitude"] != "" else None,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from time import sleep
|
|||||||
|
|
||||||
from pyhamtools.locator import latlong_to_locator
|
from pyhamtools.locator import latlong_to_locator
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -44,7 +45,7 @@ class IOTA(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=ref["name"],
|
name=ref["name"],
|
||||||
ref_type="Island",
|
ref_type=SIGRefType.ISLAND,
|
||||||
grid=grid,
|
grid=grid,
|
||||||
latitude=latitude,
|
latitude=latitude,
|
||||||
longitude=longitude,
|
longitude=longitude,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from time import sleep
|
|||||||
|
|
||||||
from pyhamtools.locator import locator_to_latlong
|
from pyhamtools.locator import locator_to_latlong
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -32,7 +33,7 @@ class LLOTA(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=str(ref["name"]),
|
name=str(ref["name"]),
|
||||||
ref_type="Lake",
|
ref_type=SIGRefType.LAKE,
|
||||||
url=f"https://llota.app/list/ref/{ref_id}",
|
url=f"https://llota.app/list/ref/{ref_id}",
|
||||||
grid=grid,
|
grid=grid,
|
||||||
latitude=ll[0],
|
latitude=ll[0],
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -26,7 +27,7 @@ class MOTA(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=row.get("Name", None),
|
name=row.get("Name", None),
|
||||||
ref_type="Mill",
|
ref_type=SIGRefType.MILL,
|
||||||
url=f"https://www.cqgma.org/zinfo.php?ref={ref_id}",
|
url=f"https://www.cqgma.org/zinfo.php?ref={ref_id}",
|
||||||
latitude=float(row["Latitude"]) if "Latitude" in row and row["Latitude"] != "" else None,
|
latitude=float(row["Latitude"]) if "Latitude" in row and row["Latitude"] != "" else None,
|
||||||
longitude=float(row["Longitude"]) if "Longitude" in row and row["Longitude"] != "" else None,
|
longitude=float(row["Longitude"]) if "Longitude" in row and row["Longitude"] != "" else None,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from time import sleep
|
|||||||
|
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import FileDownloadSIGRefDataProvider
|
from providers.sigrefdata.file_download_sig_ref_data_provider import FileDownloadSIGRefDataProvider
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ class PGA(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=name,
|
name=name,
|
||||||
ref_type="Region",
|
ref_type=SIGRefType.REGION,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from time import sleep
|
|||||||
from fastkml import kml
|
from fastkml import kml
|
||||||
from pyhamtools.locator import latlong_to_locator
|
from pyhamtools.locator import latlong_to_locator
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -43,7 +44,7 @@ class ParksNPeaksKMLSIGRefDataProvider(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.sig_name,
|
sig=self.sig_name,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=placemark.name,
|
name=placemark.name,
|
||||||
ref_type="Park",
|
ref_type=SIGRefType.PARK,
|
||||||
url=f"https://parksnpeaks.org/getPark.php?actPark={ref_id}",
|
url=f"https://parksnpeaks.org/getPark.php?actPark={ref_id}",
|
||||||
latitude=latitude,
|
latitude=latitude,
|
||||||
longitude=longitude,
|
longitude=longitude,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -26,7 +27,7 @@ class POTA(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=row.get("name", None),
|
name=row.get("name", None),
|
||||||
ref_type="Park",
|
ref_type=SIGRefType.PARK,
|
||||||
url=f"https://pota.app/#/park/{ref_id}",
|
url=f"https://pota.app/#/park/{ref_id}",
|
||||||
grid=row.get("grid", None),
|
grid=row.get("grid", None),
|
||||||
latitude=float(row["latitude"]) if "latitude" in row and row["latitude"] != "" else None,
|
latitude=float(row["latitude"]) if "latitude" in row and row["latitude"] != "" else None,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -26,7 +27,7 @@ class SIOTA(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=row.get("NAME", None),
|
name=row.get("NAME", None),
|
||||||
ref_type="Silo",
|
ref_type=SIGRefType.SILO,
|
||||||
grid=row.get("LOCATOR", None),
|
grid=row.get("LOCATOR", None),
|
||||||
latitude=float(row["LAT"]) if "LAT" in row else None,
|
latitude=float(row["LAT"]) if "LAT" in row else None,
|
||||||
longitude=float(row["LNG"]) if "LNG" in row else None,
|
longitude=float(row["LNG"]) if "LNG" in row else None,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from time import sleep
|
|||||||
|
|
||||||
from pyhamtools.locator import latlong_to_locator
|
from pyhamtools.locator import latlong_to_locator
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -30,7 +31,7 @@ class SOTA(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=row.get("SummitName", None),
|
name=row.get("SummitName", None),
|
||||||
ref_type="Summit",
|
ref_type=SIGRefType.SUMMIT,
|
||||||
url=f"https://www.sotadata.org.uk/en/summit/{ref_id}",
|
url=f"https://www.sotadata.org.uk/en/summit/{ref_id}",
|
||||||
latitude=latitude,
|
latitude=latitude,
|
||||||
longitude=longitude,
|
longitude=longitude,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import csv
|
import csv
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.local_file_sig_ref_data_provider import (
|
from providers.sigrefdata.local_file_sig_ref_data_provider import (
|
||||||
LocalFileSIGRefDataProvider,
|
LocalFileSIGRefDataProvider,
|
||||||
@@ -26,7 +27,7 @@ class Toilets(LocalFileSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=row["ref"],
|
id=row["ref"],
|
||||||
name=row["ref"],
|
name=row["ref"],
|
||||||
ref_type="Toilet",
|
ref_type=SIGRefType.TOILET,
|
||||||
latitude=float(row["lat"]),
|
latitude=float(row["lat"]),
|
||||||
longitude=float(row["lon"]),
|
longitude=float(row["lon"]),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -26,7 +27,7 @@ class Towers(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=row.get("Nazev", None),
|
name=row.get("Nazev", None),
|
||||||
ref_type="Tower",
|
ref_type=SIGRefType.TOWER,
|
||||||
url=f"https://wwtota.com/seznam/karta_rozhledny.php?ref={ref_id}",
|
url=f"https://wwtota.com/seznam/karta_rozhledny.php?ref={ref_id}",
|
||||||
grid=row["Lokator"] if "Lokator" in row and row["Lokator"] != "" else None,
|
grid=row["Lokator"] if "Lokator" in row and row["Lokator"] != "" else None,
|
||||||
latitude=float(row["Lat"]) if "Lat" in row and row["Lat"] != "" else None,
|
latitude=float(row["Lat"]) if "Lat" in row and row["Lat"] != "" else None,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from time import sleep
|
|||||||
|
|
||||||
from pyhamtools.locator import latlong_to_locator
|
from pyhamtools.locator import latlong_to_locator
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -45,7 +46,7 @@ class WCA(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=row.get("CLEAN NAME", None),
|
name=row.get("CLEAN NAME", None),
|
||||||
ref_type="Castle",
|
ref_type=SIGRefType.CASTLE,
|
||||||
url=f"https://www.cqgma.org/zinfo.php?ref={ref_id}",
|
url=f"https://www.cqgma.org/zinfo.php?ref={ref_id}",
|
||||||
latitude=latitude,
|
latitude=latitude,
|
||||||
longitude=longitude,
|
longitude=longitude,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -33,7 +34,7 @@ class WOTA(FileDownloadSIGRefDataProvider):
|
|||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=feature["properties"]["title"],
|
name=feature["properties"]["title"],
|
||||||
url=url,
|
url=url,
|
||||||
ref_type="Summit",
|
ref_type=SIGRefType.SUMMIT,
|
||||||
grid=feature["properties"]["qthLocator"],
|
grid=feature["properties"]["qthLocator"],
|
||||||
latitude=feature["geometry"]["coordinates"][1],
|
latitude=feature["geometry"]["coordinates"][1],
|
||||||
longitude=feature["geometry"]["coordinates"][0],
|
longitude=feature["geometry"]["coordinates"][0],
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -26,7 +27,7 @@ class WWBOTA(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=row.get("Name", None),
|
name=row.get("Name", None),
|
||||||
ref_type="Bunker",
|
ref_type=SIGRefType.BUNKER,
|
||||||
url=f"https://bunkerwiki.org/?s={ref_id}" if ref_id.startswith("B/G") else None,
|
url=f"https://bunkerwiki.org/?s={ref_id}" if ref_id.startswith("B/G") else None,
|
||||||
grid=row["Locator"] if "Locator" in row and row["Locator"] != "" else None,
|
grid=row["Locator"] if "Locator" in row and row["Locator"] != "" else None,
|
||||||
latitude=float(row["Lat"]) if "Lat" in row and row["Lat"] != "" else None,
|
latitude=float(row["Lat"]) if "Lat" in row and row["Lat"] != "" else None,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -26,7 +27,7 @@ class WWFF(FileDownloadSIGRefDataProvider):
|
|||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=row.get("name", None),
|
name=row.get("name", None),
|
||||||
ref_type="Park",
|
ref_type=SIGRefType.PARK,
|
||||||
url=f"https://wwff.co/directory/?showRef={ref_id}",
|
url=f"https://wwff.co/directory/?showRef={ref_id}",
|
||||||
grid=row["iaruLocator"] if "iaruLocator" in row and row["iaruLocator"] != "-" else None,
|
grid=row["iaruLocator"] if "iaruLocator" in row and row["iaruLocator"] != "-" else None,
|
||||||
latitude=float(row["latitude"])
|
latitude=float(row["latitude"])
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from time import sleep
|
|||||||
|
|
||||||
from pyhamtools.locator import latlong_to_locator
|
from pyhamtools.locator import latlong_to_locator
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
from providers.sigrefdata.file_download_sig_ref_data_provider import (
|
||||||
FileDownloadSIGRefDataProvider,
|
FileDownloadSIGRefDataProvider,
|
||||||
@@ -26,12 +27,16 @@ class ZLOTA(FileDownloadSIGRefDataProvider):
|
|||||||
ref_id = ref["code"]
|
ref_id = ref["code"]
|
||||||
latitude = ref["latitude"]
|
latitude = ref["latitude"]
|
||||||
longitude = ref["longitude"]
|
longitude = ref["longitude"]
|
||||||
|
try:
|
||||||
|
ref_type = SIGRefType(ref["asset_type"].title().upper())
|
||||||
|
except ValueError:
|
||||||
|
ref_type = SIGRefType.UNKNOWN
|
||||||
|
|
||||||
new_ref = SIGRef(
|
new_ref = SIGRef(
|
||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
id=ref_id,
|
id=ref_id,
|
||||||
name=ref["name"],
|
name=ref["name"],
|
||||||
ref_type=ref["asset_type"].title(),
|
ref_type=ref_type,
|
||||||
url=f"https://ontheair.nz/assets/{ref_id.replace('/', '_')}",
|
url=f"https://ontheair.nz/assets/{ref_id.replace('/', '_')}",
|
||||||
latitude=latitude,
|
latitude=latitude,
|
||||||
longitude=longitude,
|
longitude=longitude,
|
||||||
|
|||||||
+11
-1
@@ -4,6 +4,7 @@ from datetime import datetime
|
|||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
from core.constants import HTTP_HEADERS
|
from core.constants import HTTP_HEADERS
|
||||||
|
from core.enums import Mode, SIGRefType
|
||||||
from core.url_data_cache import URLDataCache
|
from core.url_data_cache import URLDataCache
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
@@ -65,7 +66,9 @@ class GMA(HTTPSpotProvider):
|
|||||||
if (source_spot["QRG"] != "" and source_spot["QRG"] != "QRT")
|
if (source_spot["QRG"] != "" and source_spot["QRG"] != "QRT")
|
||||||
else None,
|
else None,
|
||||||
# Filter out some weird mode strings
|
# Filter out some weird mode strings
|
||||||
mode=source_spot["MODE"].upper() if "<>" not in source_spot["MODE"] else None,
|
mode=Mode.from_name(source_spot["MODE"].upper())
|
||||||
|
if "<>" not in source_spot["MODE"]
|
||||||
|
else Mode.UNKNOWN,
|
||||||
comment=source_spot["TEXT"],
|
comment=source_spot["TEXT"],
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
SIGRef(
|
SIGRef(
|
||||||
@@ -113,24 +116,31 @@ class GMA(HTTPSpotProvider):
|
|||||||
match ref_info["reftype"]:
|
match ref_info["reftype"]:
|
||||||
case "Summit":
|
case "Summit":
|
||||||
spot.sig_refs[0].sig = "GMA"
|
spot.sig_refs[0].sig = "GMA"
|
||||||
|
spot.sig_refs[0].ref_type = SIGRefType.SUMMIT
|
||||||
spot.sig = "GMA"
|
spot.sig = "GMA"
|
||||||
case "IOTA Island":
|
case "IOTA Island":
|
||||||
spot.sig_refs[0].sig = "IOTA"
|
spot.sig_refs[0].sig = "IOTA"
|
||||||
|
spot.sig_refs[0].ref_type = SIGRefType.ISLAND
|
||||||
spot.sig = "IOTA"
|
spot.sig = "IOTA"
|
||||||
case "GMA Island":
|
case "GMA Island":
|
||||||
spot.sig_refs[0].sig = "GMA Islands"
|
spot.sig_refs[0].sig = "GMA Islands"
|
||||||
|
spot.sig_refs[0].ref_type = SIGRefType.ISLAND
|
||||||
spot.sig = "GMA Islands"
|
spot.sig = "GMA Islands"
|
||||||
case "Lighthouse (ILLW)":
|
case "Lighthouse (ILLW)":
|
||||||
spot.sig_refs[0].sig = "ILLW"
|
spot.sig_refs[0].sig = "ILLW"
|
||||||
|
spot.sig_refs[0].ref_type = SIGRefType.LIGHTHOUSE
|
||||||
spot.sig = "ILLW"
|
spot.sig = "ILLW"
|
||||||
case "Lighthouse (ARLHS)":
|
case "Lighthouse (ARLHS)":
|
||||||
spot.sig_refs[0].sig = "ARLHS"
|
spot.sig_refs[0].sig = "ARLHS"
|
||||||
|
spot.sig_refs[0].ref_type = SIGRefType.LIGHTHOUSE
|
||||||
spot.sig = "ARLHS"
|
spot.sig = "ARLHS"
|
||||||
case "Castle":
|
case "Castle":
|
||||||
spot.sig_refs[0].sig = "WCA"
|
spot.sig_refs[0].sig = "WCA"
|
||||||
|
spot.sig_refs[0].ref_type = SIGRefType.CASTLE
|
||||||
spot.sig = "WCA"
|
spot.sig = "WCA"
|
||||||
case "Mill":
|
case "Mill":
|
||||||
spot.sig_refs[0].sig = "MOTA"
|
spot.sig_refs[0].sig = "MOTA"
|
||||||
|
spot.sig_refs[0].ref_type = SIGRefType.MILL
|
||||||
spot.sig = "MOTA"
|
spot.sig = "MOTA"
|
||||||
case _:
|
case _:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import requests
|
|||||||
from requests.exceptions import ConnectionError, ConnectTimeout, ReadTimeout
|
from requests.exceptions import ConnectionError, ConnectTimeout, ReadTimeout
|
||||||
|
|
||||||
from core.constants import HTTP_HEADERS
|
from core.constants import HTTP_HEADERS
|
||||||
|
from core.enums import Mode, SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -59,7 +60,7 @@ class HEMA(HTTPSpotProvider):
|
|||||||
dx_call=spot_items[2].upper(),
|
dx_call=spot_items[2].upper(),
|
||||||
de_call=spotter_comment_match.group(1).upper(),
|
de_call=spotter_comment_match.group(1).upper(),
|
||||||
freq=float(freq_mode_match.group(1)) * 1000000,
|
freq=float(freq_mode_match.group(1)) * 1000000,
|
||||||
mode=freq_mode_match.group(2).upper(),
|
mode=Mode.from_name(freq_mode_match.group(2).upper()),
|
||||||
comment=spotter_comment_match.group(2),
|
comment=spotter_comment_match.group(2),
|
||||||
sig="HEMA",
|
sig="HEMA",
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
@@ -69,6 +70,7 @@ class HEMA(HTTPSpotProvider):
|
|||||||
name=spot_items[4],
|
name=spot_items[4],
|
||||||
latitude=float(spot_items[7]),
|
latitude=float(spot_items[7]),
|
||||||
longitude=float(spot_items[8]),
|
longitude=float(spot_items[8]),
|
||||||
|
ref_type=SIGRefType.SUMMIT,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
time=datetime.strptime(spot_items[0], "%d/%m/%Y %H:%M")
|
time=datetime.strptime(spot_items[0], "%d/%m/%Y %H:%M")
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
from core.enums import Mode, SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -31,7 +32,7 @@ class LLOTA(HTTPSpotProvider):
|
|||||||
dx_call=source_spot["callsign"].upper(),
|
dx_call=source_spot["callsign"].upper(),
|
||||||
de_call=spotter.upper() if spotter else None,
|
de_call=spotter.upper() if spotter else None,
|
||||||
freq=float(source_spot["frequency"]) * 1000000,
|
freq=float(source_spot["frequency"]) * 1000000,
|
||||||
mode=source_spot["mode"].upper(),
|
mode=Mode.from_name(source_spot["mode"].upper()),
|
||||||
comment=comment,
|
comment=comment,
|
||||||
sig="LLOTA",
|
sig="LLOTA",
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
@@ -39,6 +40,7 @@ class LLOTA(HTTPSpotProvider):
|
|||||||
id=source_spot["reference"],
|
id=source_spot["reference"],
|
||||||
sig="LLOTA",
|
sig="LLOTA",
|
||||||
name=source_spot["reference_name"],
|
name=source_spot["reference_name"],
|
||||||
|
ref_type=SIGRefType.LAKE,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
time=datetime.fromisoformat(source_spot["updated_at"].replace("Z", "+00:00")).timestamp(),
|
time=datetime.fromisoformat(source_spot["updated_at"].replace("Z", "+00:00")).timestamp(),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import pytz
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from core.constants import HTTP_HEADERS
|
from core.constants import HTTP_HEADERS
|
||||||
|
from core.enums import Mode
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -51,7 +52,7 @@ class ParksNPeaks(HTTPSpotProvider):
|
|||||||
if (source_spot["actFreq"] != "")
|
if (source_spot["actFreq"] != "")
|
||||||
else None,
|
else None,
|
||||||
# Seen PNP spots with empty frequency, and with comma-separated thousands digits
|
# Seen PNP spots with empty frequency, and with comma-separated thousands digits
|
||||||
mode=source_spot["actMode"].upper(),
|
mode=Mode.from_name(source_spot["actMode"].upper()),
|
||||||
comment=source_spot["actComments"],
|
comment=source_spot["actComments"],
|
||||||
time=datetime.strptime(source_spot["actTime"], "%Y-%m-%d %H:%M:%S")
|
time=datetime.strptime(source_spot["actTime"], "%Y-%m-%d %H:%M:%S")
|
||||||
.replace(tzinfo=pytz.UTC)
|
.replace(tzinfo=pytz.UTC)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import pytz
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from core.constants import HTTP_HEADERS
|
from core.constants import HTTP_HEADERS
|
||||||
|
from core.enums import Mode, SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -30,7 +31,7 @@ class POTA(HTTPSpotProvider):
|
|||||||
dx_call=source_spot["activator"].upper(),
|
dx_call=source_spot["activator"].upper(),
|
||||||
de_call=source_spot["spotter"].upper(),
|
de_call=source_spot["spotter"].upper(),
|
||||||
freq=float(source_spot["frequency"]) * 1000 if source_spot["frequency"] != "INVALID" else None,
|
freq=float(source_spot["frequency"]) * 1000 if source_spot["frequency"] != "INVALID" else None,
|
||||||
mode=source_spot["mode"].upper(),
|
mode=Mode.from_name(source_spot["mode"].upper()),
|
||||||
comment=source_spot["comments"],
|
comment=source_spot["comments"],
|
||||||
sig="POTA",
|
sig="POTA",
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
@@ -40,6 +41,7 @@ class POTA(HTTPSpotProvider):
|
|||||||
name=source_spot["name"],
|
name=source_spot["name"],
|
||||||
latitude=source_spot["latitude"],
|
latitude=source_spot["latitude"],
|
||||||
longitude=source_spot["longitude"],
|
longitude=source_spot["longitude"],
|
||||||
|
ref_type=SIGRefType.PARK
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
time=datetime.strptime(source_spot["spotTime"], "%Y-%m-%dT%H:%M:%S")
|
time=datetime.strptime(source_spot["spotTime"], "%Y-%m-%dT%H:%M:%S")
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import requests
|
|||||||
from requests.exceptions import ConnectionError, ConnectTimeout, ReadTimeout
|
from requests.exceptions import ConnectionError, ConnectTimeout, ReadTimeout
|
||||||
|
|
||||||
from core.constants import HTTP_HEADERS
|
from core.constants import HTTP_HEADERS
|
||||||
|
from core.enums import Mode, SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -53,7 +54,7 @@ class SOTA(HTTPSpotProvider):
|
|||||||
if (source_spot["frequency"] is not None)
|
if (source_spot["frequency"] is not None)
|
||||||
else None,
|
else None,
|
||||||
# Seen SOTA spots with no frequency!
|
# Seen SOTA spots with no frequency!
|
||||||
mode=source_spot["mode"].upper(),
|
mode=Mode.from_name(source_spot["mode"].upper()),
|
||||||
comment=source_spot["comments"],
|
comment=source_spot["comments"],
|
||||||
sig="SOTA",
|
sig="SOTA",
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
@@ -64,6 +65,7 @@ class SOTA(HTTPSpotProvider):
|
|||||||
latitude=source_spot["latitude"],
|
latitude=source_spot["latitude"],
|
||||||
longitude=source_spot["longitude"],
|
longitude=source_spot["longitude"],
|
||||||
activation_score=source_spot["points"],
|
activation_score=source_spot["points"],
|
||||||
|
ref_type=SIGRefType.SUMMIT,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
dx_latitude=source_spot["latitude"],
|
dx_latitude=source_spot["latitude"],
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from datetime import datetime
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from core.constants import HTTP_HEADERS
|
from core.constants import HTTP_HEADERS
|
||||||
from core.enums import LocationSourceForSpot
|
from core.enums import LocationSourceForSpot, Mode, SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -56,7 +56,7 @@ class Tiles(HTTPSpotProvider):
|
|||||||
# No separate spotter callsign, assume all spots are self-spots
|
# No separate spotter callsign, assume all spots are self-spots
|
||||||
de_call=source_spot["call_sign"].upper(),
|
de_call=source_spot["call_sign"].upper(),
|
||||||
freq=freq,
|
freq=freq,
|
||||||
mode=source_spot["mode"].upper(),
|
mode=Mode.from_name(source_spot["mode"].upper()),
|
||||||
comment=source_spot["notes"],
|
comment=source_spot["notes"],
|
||||||
sig="Tiles",
|
sig="Tiles",
|
||||||
# Tiles spots can include POTA & SOTA references, but ignore those on the basis that we will get them separately from the POTA/SOTA providers anyway.
|
# Tiles spots can include POTA & SOTA references, but ignore those on the basis that we will get them separately from the POTA/SOTA providers anyway.
|
||||||
@@ -68,6 +68,7 @@ class Tiles(HTTPSpotProvider):
|
|||||||
name=source_spot["maidenhead_grid"],
|
name=source_spot["maidenhead_grid"],
|
||||||
latitude=source_spot["latitude"],
|
latitude=source_spot["latitude"],
|
||||||
longitude=source_spot["longitude"],
|
longitude=source_spot["longitude"],
|
||||||
|
ref_type=SIGRefType.GRID
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
time=datetime.fromisoformat(source_spot["created_at"].replace("Z", "+00:00")).timestamp(),
|
time=datetime.fromisoformat(source_spot["created_at"].replace("Z", "+00:00")).timestamp(),
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import json
|
import json
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
import pytz
|
||||||
|
|
||||||
|
from core.enums import SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -32,10 +35,10 @@ class Towers(HTTPSpotProvider):
|
|||||||
freq=likely_freq,
|
freq=likely_freq,
|
||||||
comment=source_spot["comment"],
|
comment=source_spot["comment"],
|
||||||
sig="Towers",
|
sig="Towers",
|
||||||
sig_refs=[SIGRef(id=source_spot["ref"], sig="Towers")],
|
sig_refs=[SIGRef(id=source_spot["ref"], sig="Towers", ref_type=SIGRefType.TOWER)],
|
||||||
time=datetime.strptime(
|
time=datetime.strptime(response_json["updated"][:10] + source_spot["time"], "%Y-%m-%d%H:%M")
|
||||||
response_json["updated"][:10] + source_spot["time"], "%Y-%m-%d%H:%M"
|
.replace(tzinfo=pytz.utc)
|
||||||
).timestamp(),
|
.timestamp(),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add to our list. Don't worry about de-duping, removing old spots etc. at this point; other code will do
|
# Add to our list. Don't worry about de-duping, removing old spots etc. at this point; other code will do
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
|
from core.enums import Mode
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
|
|
||||||
@@ -77,7 +78,7 @@ class UKPacketNet(HTTPSpotProvider):
|
|||||||
dx_call=heard["callsign"].upper(),
|
dx_call=heard["callsign"].upper(),
|
||||||
de_call=node["callsign"].upper(),
|
de_call=node["callsign"].upper(),
|
||||||
freq=freq,
|
freq=freq,
|
||||||
mode="PKT",
|
mode=Mode.PKT,
|
||||||
comment=comment,
|
comment=comment,
|
||||||
time=datetime.strptime(heard["lastHeard"], "%Y-%m-%d %H:%M:%S")
|
time=datetime.strptime(heard["lastHeard"], "%Y-%m-%d %H:%M:%S")
|
||||||
.replace(tzinfo=pytz.UTC)
|
.replace(tzinfo=pytz.UTC)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import pytz
|
|||||||
from rss_parser import Parser
|
from rss_parser import Parser
|
||||||
from rss_parser.models.rss import RSS
|
from rss_parser.models.rss import RSS
|
||||||
|
|
||||||
|
from core.enums import Mode, SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -87,10 +88,10 @@ class WOTA(HTTPSpotProvider):
|
|||||||
dx_call=dx_call,
|
dx_call=dx_call,
|
||||||
de_call=spotter,
|
de_call=spotter,
|
||||||
freq=freq_hz,
|
freq=freq_hz,
|
||||||
mode=mode,
|
mode=Mode.from_name(mode),
|
||||||
comment=comment,
|
comment=comment,
|
||||||
sig="WOTA",
|
sig="WOTA",
|
||||||
sig_refs=[SIGRef(id=ref, sig="WOTA", name=ref_name)] if ref else [],
|
sig_refs=[SIGRef(id=ref, sig="WOTA", name=ref_name, ref_type=SIGRefType.SUMMIT)] if ref else [],
|
||||||
time=time.timestamp(),
|
time=time.timestamp(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
from core.enums import Mode, SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.sse_spot_provider import SSESpotProvider
|
from providers.spot.sse_spot_provider import SSESpotProvider
|
||||||
@@ -26,6 +27,7 @@ class WWBOTA(SSESpotProvider):
|
|||||||
name=ref["name"],
|
name=ref["name"],
|
||||||
latitude=ref["lat"],
|
latitude=ref["lat"],
|
||||||
longitude=ref["long"],
|
longitude=ref["long"],
|
||||||
|
ref_type=SIGRefType.BUNKER
|
||||||
)
|
)
|
||||||
refs.append(sigref)
|
refs.append(sigref)
|
||||||
|
|
||||||
@@ -34,7 +36,7 @@ class WWBOTA(SSESpotProvider):
|
|||||||
dx_call=source_spot["call"].upper(),
|
dx_call=source_spot["call"].upper(),
|
||||||
de_call=source_spot["spotter"].upper(),
|
de_call=source_spot["spotter"].upper(),
|
||||||
freq=float(source_spot["freq"]) * 1000000,
|
freq=float(source_spot["freq"]) * 1000000,
|
||||||
mode=source_spot["mode"].upper() if "mode" in source_spot else None,
|
mode=Mode.from_name(source_spot["mode"].upper()) if "mode" in source_spot else Mode.UNKNOWN,
|
||||||
comment=source_spot["comment"],
|
comment=source_spot["comment"],
|
||||||
sig="WWBOTA",
|
sig="WWBOTA",
|
||||||
sig_refs=refs,
|
sig_refs=refs,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
|
from core.enums import Mode, SIGRefType
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -27,7 +28,7 @@ class WWFF(HTTPSpotProvider):
|
|||||||
dx_call=source_spot["activator"].upper(),
|
dx_call=source_spot["activator"].upper(),
|
||||||
de_call=source_spot["spotter"].upper(),
|
de_call=source_spot["spotter"].upper(),
|
||||||
freq=float(source_spot["frequency_khz"]) * 1000,
|
freq=float(source_spot["frequency_khz"]) * 1000,
|
||||||
mode=source_spot["mode"].upper(),
|
mode=Mode.from_name(source_spot["mode"].upper()),
|
||||||
comment=source_spot["remarks"],
|
comment=source_spot["remarks"],
|
||||||
sig="WWFF",
|
sig="WWFF",
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
@@ -37,6 +38,7 @@ class WWFF(HTTPSpotProvider):
|
|||||||
name=source_spot["reference_name"],
|
name=source_spot["reference_name"],
|
||||||
latitude=source_spot["latitude"],
|
latitude=source_spot["latitude"],
|
||||||
longitude=source_spot["longitude"],
|
longitude=source_spot["longitude"],
|
||||||
|
ref_type=SIGRefType.PARK
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
time=datetime.fromtimestamp(source_spot["spot_time"], tz=pytz.UTC).timestamp(),
|
time=datetime.fromtimestamp(source_spot["spot_time"], tz=pytz.UTC).timestamp(),
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
|
from core.enums import Mode
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.websocket_spot_provider import WebsocketSpotProvider
|
from providers.spot.websocket_spot_provider import WebsocketSpotProvider
|
||||||
@@ -34,7 +35,7 @@ class XOTA(WebsocketSpotProvider):
|
|||||||
source_id=source_spot["id"],
|
source_id=source_spot["id"],
|
||||||
dx_call=source_spot["stationCallSign"].upper(),
|
dx_call=source_spot["stationCallSign"].upper(),
|
||||||
freq=float(source_spot["freq"]) * 1000,
|
freq=float(source_spot["freq"]) * 1000,
|
||||||
mode=source_spot["mode"].upper(),
|
mode=Mode.from_name(source_spot["mode"].upper()),
|
||||||
sig=self.SIG,
|
sig=self.SIG,
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
SIGRef(
|
SIGRef(
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
|
from core.enums import Mode
|
||||||
from data.sig_ref import SIGRef
|
from data.sig_ref import SIGRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -32,7 +33,7 @@ class ZLOTA(HTTPSpotProvider):
|
|||||||
dx_call=source_spot["activator"].upper(),
|
dx_call=source_spot["activator"].upper(),
|
||||||
de_call=source_spot["spotter"].upper(),
|
de_call=source_spot["spotter"].upper(),
|
||||||
freq=freq_hz,
|
freq=freq_hz,
|
||||||
mode=source_spot["mode"].upper().strip(),
|
mode=Mode.from_name(source_spot["mode"].upper().strip()),
|
||||||
comment=source_spot["comments"],
|
comment=source_spot["comments"],
|
||||||
sig="ZLOTA",
|
sig="ZLOTA",
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ from tornado import httputil
|
|||||||
from tornado.web import Application
|
from tornado.web import Application
|
||||||
|
|
||||||
from core.config import ALLOW_SPOTTING, MAX_SPOT_AGE
|
from core.config import ALLOW_SPOTTING, MAX_SPOT_AGE
|
||||||
from core.constants import ALL_MODES, BANDS, PROPAGATION_MODES, SIGS
|
from core.constants import BANDS, PROPAGATION_MODES, SIGS
|
||||||
from core.enums import Continent, ModeType
|
from core.enums import Continent, Mode, ModeType
|
||||||
from core.prometheus_metrics_handler import api_requests_counter
|
from core.prometheus_metrics_handler import api_requests_counter
|
||||||
from core.utils import safe_json_dumps
|
from core.utils import safe_json_dumps
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ class APIOptionsHandler(tornado.web.RequestHandler):
|
|||||||
|
|
||||||
options = {
|
options = {
|
||||||
"bands": BANDS,
|
"bands": BANDS,
|
||||||
"modes": ALL_MODES,
|
"modes": [m.value for m in Mode],
|
||||||
"mode_types": [t.value for t in ModeType],
|
"mode_types": [t.value for t in ModeType],
|
||||||
"sigs": SIGS,
|
"sigs": SIGS,
|
||||||
"spot_providers": spot_providers,
|
"spot_providers": spot_providers,
|
||||||
|
|||||||
@@ -19,8 +19,9 @@ 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 `icon`, `region_flag` and `refs_globally_unique` to SIG information
|
* Added `sig_type`, `icon`, `region_flag` and `refs_globally_unique` to SIG information
|
||||||
* Unknown mode types now return "UNKNOWN" not null
|
* Unknown modes and mode types now return "UNKNOWN" not null
|
||||||
|
* SIG reference types (e.g. "Park") are now capitalised to match other enums
|
||||||
|
|
||||||
### 2.0
|
### 2.0
|
||||||
|
|
||||||
@@ -867,6 +868,14 @@ components:
|
|||||||
- Toilets
|
- Toilets
|
||||||
example: POTA
|
example: POTA
|
||||||
|
|
||||||
|
SIGType:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- WORLDWIDE
|
||||||
|
- REGIONAL
|
||||||
|
- EVENT
|
||||||
|
example: WORLDWIDE
|
||||||
|
|
||||||
SIGNameIncludingNoSIG:
|
SIGNameIncludingNoSIG:
|
||||||
oneOf:
|
oneOf:
|
||||||
- $ref: "#/components/schemas/SIGName"
|
- $ref: "#/components/schemas/SIGName"
|
||||||
@@ -874,6 +883,29 @@ components:
|
|||||||
enum: [ NO_SIG ]
|
enum: [ NO_SIG ]
|
||||||
example: POTA
|
example: POTA
|
||||||
|
|
||||||
|
SIGRefType:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- PARK
|
||||||
|
- SUMMIT
|
||||||
|
- CASTLE
|
||||||
|
- LIGHTHOUSE
|
||||||
|
- ISLAND
|
||||||
|
- BUNKER
|
||||||
|
- MILL
|
||||||
|
- SILO
|
||||||
|
- BEACH
|
||||||
|
- LAKE
|
||||||
|
- TOWER
|
||||||
|
- WATERWAY
|
||||||
|
- TOWN
|
||||||
|
- BUILDING
|
||||||
|
- REGION
|
||||||
|
- GRID
|
||||||
|
- TOILET
|
||||||
|
- UNKNOWN
|
||||||
|
example: PARK
|
||||||
|
|
||||||
Continent:
|
Continent:
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
@@ -938,6 +970,7 @@ components:
|
|||||||
- FSK
|
- FSK
|
||||||
- PKT
|
- PKT
|
||||||
- MSK144
|
- MSK144
|
||||||
|
- UNKNOWN
|
||||||
example: SSB
|
example: SSB
|
||||||
|
|
||||||
ModeType:
|
ModeType:
|
||||||
@@ -1006,9 +1039,8 @@ components:
|
|||||||
description: SIG reference name
|
description: SIG reference name
|
||||||
example: Null Country Park
|
example: Null Country Park
|
||||||
ref_type:
|
ref_type:
|
||||||
type: string
|
|
||||||
description: SIG reference type
|
description: SIG reference type
|
||||||
example: Park
|
$ref: "#/components/schemas/SIGRefType"
|
||||||
url:
|
url:
|
||||||
type: string
|
type: string
|
||||||
description: SIG reference URL, which the user can look up for more information
|
description: SIG reference URL, which the user can look up for more information
|
||||||
@@ -1493,6 +1525,12 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
description: The full name of the SIG
|
description: The full name of the SIG
|
||||||
example: Parks on the Air
|
example: Parks on the Air
|
||||||
|
sig_type:
|
||||||
|
type: boolean
|
||||||
|
description: >
|
||||||
|
Whether the SIG is worldwide, regional, or for a specific event. Generally for Spothole's own internal use,
|
||||||
|
clients probably won't need this. Used to group them in the web UI.
|
||||||
|
$ref: "#/components/schemas/SIGType"
|
||||||
comment_names:
|
comment_names:
|
||||||
type: array
|
type: array
|
||||||
description: >
|
description: >
|
||||||
|
|||||||
@@ -42,18 +42,25 @@ function setHamHFBandToggles() {
|
|||||||
function generateSIGsMultiToggleFilterCard(sig_options) {
|
function generateSIGsMultiToggleFilterCard(sig_options) {
|
||||||
const $grid1 = $('<div class="row row-cols-2 g-1 mb-1">');
|
const $grid1 = $('<div class="row row-cols-2 g-1 mb-1">');
|
||||||
$("#sig-options").append('<strong>Worldwide</strong>');
|
$("#sig-options").append('<strong>Worldwide</strong>');
|
||||||
sig_options.filter(o => o["region_flag"] == null).forEach(o => {
|
sig_options.filter(o => o["sig_type"] === "WORLDWIDE").forEach(o => {
|
||||||
const domSafeName = o["name"].replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
|
const domSafeName = o["name"].replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
|
||||||
$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>`);
|
$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']} ${(o["region_flag"] != null) ? o['region_flag'] : ''}</label></div></div>`);
|
||||||
});
|
});
|
||||||
$("#sig-options").append($grid1);
|
$("#sig-options").append($grid1);
|
||||||
const $grid2 = $('<div class="row row-cols-2 g-1 mb-1">');
|
const $grid2 = $('<div class="row row-cols-2 g-1 mb-1">');
|
||||||
$("#sig-options").append('<strong>Regional</strong>');
|
$("#sig-options").append('<strong>Regional</strong>');
|
||||||
sig_options.filter(o => o["region_flag"] != null).forEach(o => {
|
sig_options.filter(o => o["sig_type"] === "REGIONAL").forEach(o => {
|
||||||
const domSafeName = o["name"].replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
|
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>`);
|
$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"] != null) ? o['region_flag'] : ''}</label></div></div>`);
|
||||||
});
|
});
|
||||||
$("#sig-options").append($grid2);
|
$("#sig-options").append($grid2);
|
||||||
|
const $grid3 = $('<div class="row row-cols-2 g-1 mb-1">');
|
||||||
|
$("#sig-options").append('<strong>Event</strong>');
|
||||||
|
sig_options.filter(o => o["sig_type"] === "EVENT").forEach(o => {
|
||||||
|
const domSafeName = o["name"].replace(/^[^A-Za-z0-9]+|[^\w]+/gi, "");
|
||||||
|
$grid3.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"] != null) ? o['region_flag'] : ''}</label></div></div>`);
|
||||||
|
});
|
||||||
|
$("#sig-options").append($grid3);
|
||||||
$("#sig-options").append('<strong>Other</strong>');
|
$("#sig-options").append('<strong>Other</strong>');
|
||||||
// Bonus "NO_SIG" / "General DX" option
|
// Bonus "NO_SIG" / "General DX" option
|
||||||
$("#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="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>`);
|
||||||
|
|||||||
@@ -77,7 +77,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/add-spot.js?v=1788334633"></script>
|
<script src="/static/js/add-spot.js?v=1788338285"></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>
|
||||||
|
|||||||
@@ -84,7 +84,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/alerts.js?v=1788334633"></script>
|
<script src="/static/js/alerts.js?v=1788338286"></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=1788334633"></script>
|
<script src="/static/js/spotsbandsandmap.js?v=1788338285"></script>
|
||||||
<script src="/static/js/bands.js?v=1788334633"></script>
|
<script src="/static/js/bands.js?v=1788338285"></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=1788334633" type="text/css">
|
<link rel="stylesheet" href="/static/css/style.css?v=1788338285" 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=1788334633"></script>
|
<script src="/static/js/utils.js?v=1788338285"></script>
|
||||||
<script src="/static/js/ui-ham.js?v=1788334633"></script>
|
<script src="/static/js/ui-ham.js?v=1788338285"></script>
|
||||||
<script src="/static/js/geo.js?v=1788334633"></script>
|
<script src="/static/js/geo.js?v=1788338285"></script>
|
||||||
<script src="/static/js/common.js?v=1788334633"></script>
|
<script src="/static/js/common.js?v=1788338285"></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=1788334633"></script>
|
<script src="/static/js/conditions.js?v=1788338285"></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=1788334633"></script>
|
<script src="/static/js/spotsbandsandmap.js?v=1788338286"></script>
|
||||||
<script src="/static/js/map.js?v=1788334633"></script>
|
<script src="/static/js/map.js?v=1788338286"></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=1788334633"></script>
|
<script src="/static/js/spotsbandsandmap.js?v=1788338285"></script>
|
||||||
<script src="/static/js/spots.js?v=1788334633"></script>
|
<script src="/static/js/spots.js?v=1788338285"></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=1788334633"></script>
|
<script src="/static/js/status.js?v=1788338285"></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