156 rader
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			156 rader
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#!/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.name, []).append(route)
 | 
						|
 | 
						|
    def __init__(self, sctFilepath : str, eseFilepath : str, airport : str, allowedRoutes : list):
 | 
						|
        self.arrivalRoutes = {}
 | 
						|
        self.waypoints = {}
 | 
						|
        self.airports = {}
 | 
						|
 | 
						|
        self.extractWaypoints(sctFilepath)
 | 
						|
        print('Extracted ' + str(len(self.waypoints)) + ' waypoints')
 | 
						|
 | 
						|
        self.extractArrivalRoutes(eseFilepath, airport, allowedRoutes)
 | 
						|
        print('Extracted ' + str(len(self.arrivalRoutes)) + ' arrival routes for ' + airport)
 |