#!/usr/bin/env python import sys from aman.types.ArrivalRoute import ArrivalRoute from aman.types.Waypoint import Waypoint class SctEseFormat: def readFile(filename : str): fileBlocks = {} block = None # read the file line by line and create segments based on []-entries with open(filename) as file: for line in file: line = line.strip() # found a new segment if line.startswith('['): block = line[1:-1] fileBlocks.setdefault(block, []) # append the last backend elif None != block and 0 != len(line): fileBlocks[block].append(line) return fileBlocks def parseWaypoint(waypoint : str, nameIdx : int, latitudeIdx : int, longitudeIdx : int): split = list(filter(None, waypoint.split(' '))) if len(split) <= longitudeIdx: sys.stderr.write('Invalid waypoint format: ' + waypoint) sys.exit(-1) return Waypoint(split[nameIdx], Waypoint.dms2dd(split[latitudeIdx]), Waypoint.dms2dd(split[longitudeIdx])) def extractWaypoints(self, sctFilepath : str): config = SctEseFormat.readFile(sctFilepath) foundAirports = False foundVOR = False foundNDB = False foundFix = False for key in config: if 'VOR' == key: foundVOR = True elif 'NDB' == key: foundNDB = True elif 'FIXES' == key: foundFix = True elif 'AIRPORT' == key: foundAirports = True if False == foundVOR: sys.stderr.write('Unable to find VOR-entries in the sector file') sys.exit(-1) if False == foundNDB: sys.stderr.write('Unable to find NDB-entries in the sector file') sys.exit(-1) if False == foundFix: sys.stderr.write('Unable to find FIX-entries in the sector file') sys.exit(-1) if False == foundAirports: sys.stderr.write('Unable to find AIRPORT-entries in the sector file') sys.exit(-1) # extract all waypoints for waypoint in config['VOR']: waypoint = SctEseFormat.parseWaypoint(waypoint, 0, 2, 3) self.waypoints.setdefault(waypoint.name, []).append(waypoint) for waypoint in config['NDB']: waypoint = SctEseFormat.parseWaypoint(waypoint, 0, 1, 2) self.waypoints.setdefault(waypoint.name, []).append(waypoint) for waypoint in config['FIXES']: waypoint = SctEseFormat.parseWaypoint(waypoint, 0, 1, 2) self.waypoints.setdefault(waypoint.name, []).append(waypoint) # extract the airports for airport in config['AIRPORT']: airport = SctEseFormat.parseWaypoint(airport,0, 2, 3) self.airports.setdefault(airport.name, []).append(airport) def parseArrivalRoute(self, route : str, airport : Waypoint): # split the route and validate that it is a STAR for the airport split = route.split(':') if 5 != len(split) or 'STAR' != split[0] or split[1] != airport.name: return None # find all waypoints waypoints = [] route = list(filter(None, split[4].split(' '))) for waypoint in route: # find the waypoint in the route coordinates = self.waypoints[waypoint] # no waypoint with this name defined if None == coordinates: sys.stderr.write('Unable to find waypoint ' + waypoint) sys.exit(-1) # multiple waypoints, but use Haversine distance to distinct between candidates elif 1 != len(coordinates): minDistance = sys.float_info.max nearest = None # we assume that waypoints with the same name are not close each other for coordinate in coordinates: distance = coordinate.haversine(airport) # found a closer waypoint if minDistance > distance: minDistance = distance nearest = coordinate if None == nearest: sys.stderr.write('Unable to find a close waypoint for ' + waypoint) sys.exit(-1) waypoints.append(nearest) # extend the list of waypoints else: waypoints.append(coordinates[0]) # create the arrival route return ArrivalRoute(split[3], split[2], waypoints) def extractArrivalRoutes(self, eseFilepath : str, airport : str, allowedRoutes : list): config = SctEseFormat.readFile(eseFilepath) foundSidsStars = False # search the airport in the extracted list if not airport in self.airports: sys.stderr.write(airport + 'in self.airports', 'Unable to find the requested airport') sys.exit(-1) airport = self.airports[airport][0] for key in config: if 'SIDSSTARS' == key: foundSidsStars = True if False == foundSidsStars: sys.stderr.write('Unable to find SIDSSTARS-entries in the sector file') sys.exit(-1) # parse all arrival routes for line in config['SIDSSTARS']: route = self.parseArrivalRoute(line, airport) if None != route and route.name in allowedRoutes: self.arrivalRoutes.setdefault(route.runway, []).append(route) def __init__(self, sctFilepath : str, eseFilepath : str, airport : str, allowedRoutes : list): self.arrivalRoutes = {} self.waypoints = {} self.airports = {} self.extractWaypoints(sctFilepath) self.extractArrivalRoutes(eseFilepath, airport, allowedRoutes)