import logging from pyhamtools.locator import latlong_to_locator, locator_to_latlong from core.constants import SIGS from core.data_store import DATA_STORE from core.geo_utils import wab_wai_square_to_lat_lon def get_ref_regex_for_sig(sig): """Utility function to get the regex string for a SIG reference for a named SIG. If no match is found, None will be returned.""" for s in SIGS: if s.name.upper() == sig.upper(): return s.ref_regex return None def get_sig_name_from_comment_name(sig): """Utility function to get the name of a SIG from its "comment name". Generally these will be the same but there are some cases (e.g. is "TOTA" Towers, Tiles or Toilets?) where we need to transform one to the other.""" for s in SIGS: if any(n.upper() == sig.upper() for n in s.comment_names): return s.name return None def populate_sig_ref_info(sig_ref): """Look up details of a SIG reference (e.g. POTA park) such as name, lat/lon, and grid. Takes in a sig_ref object which must at minimum have a "sig" and an "id". The rest of the object will be populated and returned. This makes use of SIG ref data in the data store, live lookups from the web, or just automatic calculation depending on which SIG we are getting data for. Note there is currently no support for KRMNPA location lookup, see issue #61.""" if sig_ref.sig is None or sig_ref.sig == "" or sig_ref.id is None or sig_ref.id == "": logging.debug("Failed to look up sig_ref info, sig or id were not set.") return sig_ref sig = sig_ref.sig ref_id = sig_ref.id # DME fudge. Our database has leading zeros padding to 5 digits which is the expected format, but not all activators # add leading zeros. if sig.upper() == "DME": ref_id = ref_id.zfill(5) try: # If the SIG is HEMA or KRMNPA, we have no current lookup for this so just skip it. if sig.upper() == "HEMA" or sig.upper() == "KRMNPA": return sig_ref # If the SIG is Tiles, WAB, WAI or BOTA (Beaches), we don't have anything to look up from the data store, we can # calculate all the information we are going to get directly. So handle those cases first elif sig.upper() == "TILES": # Tiles on the Air just uses Maidenhead 6-digit squares, so ID, Name and Grid are all the same if not sig_ref.name: sig_ref.name = sig_ref.id if not sig_ref.grid: sig_ref.grid = sig_ref.id if sig_ref.grid and not sig_ref.latitude: ll = locator_to_latlong(str(sig_ref.grid)) sig_ref.latitude = ll[0] sig_ref.longitude = ll[1] elif sig.upper() == "WAB" or sig.upper() == "WAI": ll = wab_wai_square_to_lat_lon(ref_id) if ll: sig_ref.name = ref_id try: sig_ref.grid = latlong_to_locator(ll[0], ll[1], 6) sig_ref.latitude = ll[0] sig_ref.longitude = ll[1] except: logging.warning("Invalid lat/lon received for WAB/WAI reference") elif sig.upper() == "BOTA": # For BOTA all we can ever generate is the URL, there is no data file or lookup for lat/longs if not sig_ref.name: sig_ref.name = sig_ref.id sig_ref.url = "https://www.beachesontheair.com/beaches/" + sig_ref.name.lower().replace(" ", "-") # OK, this is something we have to look up. Now check to see if our data store contains SIG ref information for # this SIG. If so, check for the reference data and use that. elif sig in DATA_STORE.sigrefs: key = sig + ":" + ref_id lookup_data = DATA_STORE.sigrefs.get(key) if key in DATA_STORE.sigrefs else None if lookup_data: # Copy new sig ref data into existing object sig_ref.__dict__.update(lookup_data.__dict__) else: logging.warning("%s database did not contain data for ref %s", sig, ref_id) else: logging.warning(f"Tried to look up a SIG called %s but Spothole does not know what that is.", sig) except Exception: logging.error("Exception when looking up sig_ref info for " + sig + " ref " + ref_id, exc_info=True) return sig_ref # Regex matching any SIG's "comment name", i.e. how it may be referred to in spot comments ANY_SIG_REGEX = r"(" + r"|".join(n for s in SIGS for n in s.comment_names) + r")"