RunwayManager.py 4.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #!/usr/bin/env python
  2. from datetime import datetime, timedelta
  3. from aman.sys.aco.Configuration import Configuration
  4. from aman.sys.aco.Constraints import SpacingConstraints
  5. from aman.types.Inbound import Inbound
  6. class RunwayManager:
  7. def __init__(self, configuration : Configuration):
  8. self.Spacings = SpacingConstraints()
  9. self.Configuration = configuration
  10. # initialize the tracker which inbound arrives at which runway
  11. self.RunwayInbounds = {}
  12. if None != configuration.PreceedingInbounds:
  13. for runway in configuration.PreceedingInbounds:
  14. self.RunwayInbounds[runway] = configuration.PreceedingInbounds[runway]
  15. for runway in configuration.RunwayConstraints.ActiveArrivalRunways:
  16. if not runway.Runway.Name in self.RunwayInbounds:
  17. self.RunwayInbounds[runway.Runway.Name] = None
  18. def validateWtc(inbound : Inbound):
  19. wtc = inbound.Report.aircraft.wtc.upper()
  20. if 'L' == wtc or 'M' == wtc or 'H' == wtc or 'J' == wtc:
  21. return wtc
  22. else:
  23. return None
  24. def calculateEarliestArrivalTime(self, runway : str, inbound : Inbound, useITA : bool, earliestArrivalTime : datetime):
  25. earliestArrivalTimes = []
  26. if None != self.RunwayInbounds[runway]:
  27. # get the WTC based ETA
  28. wtcPre = RunwayManager.validateWtc(self.RunwayInbounds[runway])
  29. wtcThis = RunwayManager.validateWtc(inbound)
  30. if None == wtcPre or None == wtcThis:
  31. spacing = 3
  32. else:
  33. spacing = self.Spacings[wtcPre][wtcThis]
  34. delay = timedelta(minutes = spacing / (inbound.PerformanceData.SpeedApproach / 60))
  35. earliestArrivalTimes.append(self.RunwayInbounds[runway].PlannedArrivalTime + delay)
  36. # get the runway time spacing
  37. spacing = self.Configuration.RunwayConstraints.findRunway(runway).Spacing
  38. delay = timedelta(minutes = spacing / (inbound.PerformanceData.SpeedApproach / 60))
  39. earliestArrivalTimes.append(self.RunwayInbounds[runway].PlannedArrivalTime + delay)
  40. # calculate the arrival times for the dependent inbounds
  41. for dependentRunway in self.Configuration.RunwayConstraints.findDependentRunways(runway):
  42. if None != self.RunwayInbounds[dependentRunway.Runway.Name]:
  43. delay = timedelta(minutes = 3 / (inbound.PerformanceData.SpeedApproach / 60))
  44. earliestArrivalTimes.append(self.RunwayInbounds[dependentRunway.Runway.Name].PlannedArrivalTime + delay)
  45. # get the arrival time on the runway of the inbound
  46. if True == useITA:
  47. arrivalTime = inbound.ArrivalCandidates[runway].EarliestArrivalTime
  48. else:
  49. arrivalTime = inbound.ArrivalCandidates[runway].InitialArrivalTime
  50. if 0 == len(earliestArrivalTimes):
  51. return arrivalTime, timedelta(seconds = 0)
  52. else:
  53. eta = max(earliestArrivalTimes)
  54. if eta < arrivalTime:
  55. return arrivalTime, arrivalTime - eta
  56. else:
  57. return eta, timedelta(seconds = 0)
  58. def selectArrivalRunway(self, inbound : Inbound, useITA : bool, earliestArrivalTime : datetime):
  59. availableRunways = []
  60. for runway in self.Configuration.RunwayConstraints.ActiveArrivalRunways:
  61. availableRunways.append(runway)
  62. #if 1 < len(availableRunways):
  63. # TODO filter based on type
  64. # TODO filter based on airline
  65. # ensure that at least one runway is available
  66. # fallback to check if we have available runways
  67. if 0 == len(availableRunways):
  68. runway = self.Configuration.RunwayConstraints.ActiveArrivalRunways[0]
  69. return runway, self.calculateEarliestArrivalTime(runway.Runway.Name, inbound, useITA, earliestArrivalTime)
  70. # start with the beginning
  71. selectedRunway = None
  72. lostTime = None
  73. eta = None
  74. # get the runway with the earliest ETA
  75. for runway in availableRunways:
  76. candidate, delta = self.calculateEarliestArrivalTime(runway.Runway.Name, inbound, useITA, earliestArrivalTime)
  77. if None == eta or eta > candidate:
  78. selectedRunway = runway.Runway
  79. lostTime = delta
  80. eta = candidate
  81. return selectedRunway, eta, lostTime