from enum import Enum class Continent(str, Enum): EU = "EU" NA = "NA" SA = "SA" AS = "AS" AF = "AF" OC = "OC" 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): PHONE = "PHONE" CW = "CW" DATA = "DATA" UNKNOWN = "UNKNOWN" class ModeSource(str, Enum): """Where the mode data came from in a spot.""" SPOT = "SPOT" COMMENT = "COMMENT" BANDPLAN = "BANDPLAN" NONE = "NONE" class LocationSourceForSpot(str, Enum): """Where the location data came from in a spot.""" SPOT = "SPOT" SIG_REF_LOOKUP = "SIG REF LOOKUP" GRID = "GRID" HOME_QTH = "HOME QTH" DXCC = "DXCC" NONE = "NONE" class LocationSourceForCallsign(str, Enum): """Where the location data came from in a callsign data object.""" HOME_QTH = "HOME QTH" DXCC = "DXCC" 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", }