mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2025-10-27 08:49:27 +00:00
113 lines
4.5 KiB
Python
113 lines
4.5 KiB
Python
from dataclasses import dataclass
|
|
from datetime import datetime
|
|
|
|
from pyhamtools.locator import locator_to_latlong, latlong_to_locator
|
|
|
|
from core.constants import DXCC_FLAGS
|
|
from core.utils import infer_mode_family_from_mode, infer_band_from_freq, infer_continent_from_callsign, \
|
|
infer_country_from_callsign, infer_cq_zone_from_callsign, infer_itu_zone_from_callsign, infer_dxcc_id_from_callsign
|
|
|
|
# Data class that defines a spot.
|
|
@dataclass
|
|
class Spot:
|
|
# Callsign of the operator that has been spotted
|
|
dx_call: str = None
|
|
# Callsign of the operator that has spotted them
|
|
de_call: str = None
|
|
# Country of the DX operator
|
|
dx_country: str = None
|
|
# Country of the spotter
|
|
de_country: str = None
|
|
# Country flag of the DX operator
|
|
dx_flag: str = None
|
|
# Country flag of the spotter
|
|
de_flag: str = None
|
|
# Continent of the DX operator
|
|
dx_continent: str = None
|
|
# Continent of the spotter
|
|
de_continent: str = None
|
|
# DXCC ID of the DX operator
|
|
dx_dxcc_id: int = None
|
|
# DXCC ID of the spotter
|
|
de_dxcc_id: int = None
|
|
# CQ zone of the DX operator
|
|
dx_cq_zone: int = None
|
|
# ITU zone of the DX operator
|
|
dx_itu_zone: int = None
|
|
# Reported mode, such as SSB, PHONE, CW, FT8...
|
|
mode: str = None
|
|
# Inferred mode "family". One of "CW", "PHONE" or "DIGI".
|
|
mode_family: str = None
|
|
# Frequency, in kHz
|
|
freq: float = None
|
|
# Band, defined by the frequency, e.g. "40m" or "70cm"
|
|
band: str = None
|
|
# Colour to use for the band
|
|
band_color: str = None
|
|
# Contrast colour to use for text on a background of band_color
|
|
band_contrast_color: str = None
|
|
# Time of the spot
|
|
time: datetime = None
|
|
# Comment left by the spotter, if any
|
|
comment: str = None
|
|
# Special Interest Group (SIG), e.g. outdoor activity programme such as POTA
|
|
sig: str = None
|
|
# SIG references. We allow multiple here for e.g. n-fer activations, unlike ADIF SIG_INFO
|
|
sig_refs: list = None
|
|
# SIG reference names
|
|
sig_refs_names: list = None
|
|
# Maidenhead grid locator for the spot. This could be from a geographical reference e.g. POTA, or just from the country
|
|
grid: str = None
|
|
# Latitude & longitude, in degrees. This could be from a geographical reference e.g. POTA, or just from the country
|
|
latitude: float = None
|
|
longitude: float = None
|
|
# QRT state. Some APIs return spots marked as QRT. Otherwise we can check the comments.
|
|
qrt: bool = None
|
|
# Where we got the spot from, e.g. "POTA", "Cluster"...
|
|
source: str = None
|
|
# The ID the source gave it, if any.
|
|
source_id: str = None
|
|
|
|
# Infer missing parameters where possible
|
|
def infer_missing(self):
|
|
if self.dx_call and not self.dx_country:
|
|
self.dx_country = infer_country_from_callsign(self.dx_call)
|
|
if self.dx_call and not self.dx_continent:
|
|
self.dx_continent = infer_continent_from_callsign(self.dx_call)
|
|
if self.dx_call and not self.dx_cq_zone:
|
|
self.dx_cq_zone = infer_cq_zone_from_callsign(self.dx_call)
|
|
if self.dx_call and not self.dx_itu_zone:
|
|
self.dx_itu_zone = infer_itu_zone_from_callsign(self.dx_call)
|
|
if self.dx_call and not self.dx_dxcc_id:
|
|
self.dx_dxcc_id = infer_dxcc_id_from_callsign(self.dx_call)
|
|
if self.dx_dxcc_id and not self.dx_flag:
|
|
self.dx_flag = DXCC_FLAGS[self.dx_dxcc_id]
|
|
|
|
if self.de_call and not self.de_country:
|
|
self.de_country = infer_country_from_callsign(self.de_call)
|
|
if self.de_call and not self.de_continent:
|
|
self.de_continent = infer_continent_from_callsign(self.de_call)
|
|
if self.de_call and not self.de_dxcc_id:
|
|
self.de_dxcc_id = infer_dxcc_id_from_callsign(self.de_call)
|
|
if self.de_dxcc_id and not self.de_flag:
|
|
self.de_flag = DXCC_FLAGS[self.de_dxcc_id]
|
|
|
|
if self.freq and not self.band:
|
|
band = infer_band_from_freq(self.freq)
|
|
self.band = band.name
|
|
self.band_color = band.color
|
|
self.band_contrast_color = band.contrast_color
|
|
|
|
if self.mode and not self.mode_family:
|
|
self.mode_family=infer_mode_family_from_mode(self.mode)
|
|
|
|
if self.grid and not self.latitude:
|
|
ll = locator_to_latlong(self.grid)
|
|
self.latitude = ll[0]
|
|
self.longitude = ll[1]
|
|
|
|
if self.latitude and self.longitude and not self.grid:
|
|
self.grid = latlong_to_locator(self.latitude, self.longitude, 8)
|
|
|
|
# TODO use QRZ provider to get grids, lat Lon, DX name
|
|
# TODO lat/lon from DXCC centre? |