181 рядки
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			181 рядки
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/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)
 |