#!/usr/bin/env python import copy import sys from aman.types.ArrivalRoute import ArrivalRoute from aman.types.Runway import Runway 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(name = split[nameIdx], latitude = split[latitudeIdx], longitude = split[longitudeIdx]) def parseRunway(runway : str): split = list(filter(None, runway.split(' '))) if 9 != len(split) or '' == split[8]: return None, None, None waypoint0 = Waypoint(name = split[0], latitude = split[4], longitude = split[5]) waypoint1 = Waypoint(name = split[1], latitude = split[6], longitude = split[7]) return split[8], Runway(waypoint0, waypoint1), Runway(waypoint1, waypoint0) def extractSctInformation(self, sctFilepath : str): config = SctEseFormat.readFile(sctFilepath) foundAirports = False foundRunways = 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 elif 'RUNWAY' == key: foundRunways = 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) if False == foundRunways: sys.stderr.write('Unable to find RUNWAY-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) # extract the runways for runway in config['RUNWAY']: airport, runway0, runway1 = SctEseFormat.parseRunway(runway) if None != airport: if not airport in self.Runways: self.Runways.setdefault(airport, []) self.Runways[airport].append(runway0) self.Runways[airport].append(runway1) 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(copy.deepcopy(nearest)) # extend the list of waypoints else: waypoints.append(copy.deepcopy(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('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.Runways = {} self.extractSctInformation(sctFilepath) self.extractArrivalRoutes(eseFilepath, airport, allowedRoutes)