Files
aman-sys/aman/formats/SctEseFormat.py

180 lines
7.1 KiB
Python

#!/usr/bin/env python
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(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('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)