public void Preprocess() { // Filter out nodes with links (probably nodes for the vehicle network) _taxiNodes = _nodeDict.Values.Where(v => v.IncomingEdges.Count > 0); // Filter out parkings with operation type none. _parkings = _parkings.Where(p => p.Operation != OperationType.None).ToList(); // With unneeded nodes gone, parse the lat/lon string and convert the values to radians foreach (TaxiNode v in _taxiNodes) { v.ComputeLonLat(); } // Compute distance and bearing of each edge foreach (TaxiEdge edge in _edges) { edge.Compute(); } Dictionary <XPlaneAircraftCategory, int> numberOfParkingsPerCategory = new Dictionary <XPlaneAircraftCategory, int>(); for (XPlaneAircraftCategory cat = XPlaneAircraftCategory.A; cat < XPlaneAircraftCategory.Max; cat++) { numberOfParkingsPerCategory[cat] = 0; } Dictionary <WorldTrafficAircraftType, int> numberOfParkingsPerWTType = new Dictionary <WorldTrafficAircraftType, int>(); for (WorldTrafficAircraftType cat = WorldTrafficAircraftType.Fighter; cat <= WorldTrafficAircraftType.Max; cat++) { numberOfParkingsPerWTType[cat] = 0; } foreach (Parking parking in _parkings) { parking.DetermineWtTypes(); parking.DetermineTaxiOutLocation(_taxiNodes); // Move this to first if we need pushback info in the parking def numberOfParkingsPerCategory[parking.MaxSize]++; foreach (XPlaneAircraftType wtt in parking.XpTypes) { WorldTrafficAircraftType t = AircraftTypeConverter.WTTypeFromXPlaneTypeAndCat(parking.MaxSize, wtt); numberOfParkingsPerWTType[t]++; } //parking.FindNearestLine(_lines); } Log($"Parkings by Category: {string.Join(" ", numberOfParkingsPerCategory.Select(kvp => kvp.Key.ToString() + ": " + kvp.Value.ToString()))}"); Log($"Parkings by WorldTraffic type:\n\t{string.Join("\n\t", numberOfParkingsPerWTType.Select(kvp => $"{kvp.Key.ToString(),-15}: {kvp.Value.ToString()}"))}".Replace("Max", "Undefined")); StringBuilder sb = new StringBuilder(); _flows.Analyze(sb); foreach (Runway r in _runways) { r.Analyze(_taxiNodes, _edges); } }
internal void Write(string icao) { string operationFile = Path.Combine(Settings.WorldTrafficOperations, $"{icao}.txt"); using (InvariantWriter sw = new InvariantWriter(operationFile, Encoding.ASCII)) { sw.WriteLine(" Start End"); sw.WriteLine("INDEX Low Wind Speed High Wind Speed Low Wind Dir High Wind Dir Time Time Comments (not parsed)"); sw.WriteLine("---------------------------------------------------------------------------------------------------------------------"); sw.WriteLine("START_OPERATIONS"); foreach (string op in _operations) { sw.WriteLine(op); } sw.WriteLine("END_OPERATIONS\n\n"); sw.WriteLine("Ops 1 2 Start End"); sw.WriteLine("Index Active Runway Arr Dep Time Time Comments (not parsed)"); sw.WriteLine("-------------------------------------------------------------------------------------------------"); sw.WriteLine("START_RUNWAY_OPS"); foreach (string rwop in _runwayOps) { sw.WriteLine(rwop); } sw.WriteLine("END_RUNWAY_OPS\n\n"); sw.WriteLine(" Supported AC Types Supported Approaches"); sw.WriteLine("Runway 0 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8"); sw.WriteLine("---------------------------------------------------------------------------"); sw.WriteLine("START_RUNWAYS"); IEnumerable <IGrouping <string, RunwayUse> > uses = TrafficRules.SelectMany(tr => tr.RunwayUses).GroupBy(ru => ru.Designator); foreach (IGrouping <string, RunwayUse> use in uses) { IEnumerable <XPlaneAircraftType> types = use.SelectMany(u => u.XpTypes).Distinct(); IEnumerable <WorldTrafficAircraftType> wtTypes = AircraftTypeConverter.WTTypesFromXPlaneTypes(types); List <int> onOffs = new List <int>(); for (WorldTrafficAircraftType t = WorldTrafficAircraftType.Fighter; t < WorldTrafficAircraftType.Ground; t++) { onOffs.Add(wtTypes.Contains(t) ? 1 : 0); } sw.WriteLine($"{use.Key,-7} {string.Join(" ", onOffs)} 1 1 1 1 1 1 1 0"); } sw.WriteLine("END_RUNWAYS"); } }
private void button2_Click(object sender, EventArgs e) { string aircraftFolder = Path.Combine(Settings.XPlaneLocation, "ClassicJetSimUtils", "WorldTraffic", "AircraftTypes"); IEnumerable <string> baseAircraft = Directory.EnumerateFiles(aircraftFolder, "*_BASE.txt"); rtbAircraft.Clear(); rtbAircraft.AppendText($"Found {baseAircraft.Count()} 'base' aircraft.\n\n"); WorldTrafficAircraftType currentType = WorldTrafficAircraftType.Fighter; Dictionary <WorldTrafficAircraftType, List <AircraftBase> > aircraft = new Dictionary <WorldTrafficAircraftType, List <AircraftBase> >(); for (WorldTrafficAircraftType wat = WorldTrafficAircraftType.Fighter; wat < WorldTrafficAircraftType.Max; wat++) { aircraft[wat] = new List <AircraftBase>(); } foreach (string basecraft in baseAircraft) { AircraftBase aircraftBase = null; string[] lines = File.ReadAllLines(basecraft); bool startFound = false; string nameCache = ""; foreach (string line in lines) { string[] tokens = line.ToLower().Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length < 1) { continue; } if (!startFound) { if (tokens[0] != "start") { continue; } else { startFound = true; continue; } } if (tokens.Length < 2) { continue; } switch (tokens[0]) { case "type": currentType = (WorldTrafficAircraftType)int.Parse(tokens[1]); aircraftBase = new AircraftBase { Name = nameCache.ToUpper() }; break; case "name": nameCache = tokens[1]; break; case "wingspan": aircraftBase.WingSpan = VortexMath.Parse(tokens[1]); break; case "takeoffdistatmtow": aircraftBase.TakeOffDist = VortexMath.Parse(tokens[1]); break; case "landingdist": aircraftBase.LandingDist = VortexMath.Parse(tokens[1]); break; case "minlandingdist": aircraftBase.MinLandingDist = VortexMath.Parse(tokens[1]); break; default: break; } } aircraft[currentType].Add(aircraftBase); } for (WorldTrafficAircraftType wat = WorldTrafficAircraftType.Fighter; wat < WorldTrafficAircraftType.Max; wat++) { if (aircraft[wat].Count > 0) { rtbAircraft.AppendText($"World Traffic Type {(int)wat} <{wat}> {aircraft[wat].Count} base aircraft\n"); var byCat = aircraft[wat].GroupBy(ac => SpanToCat(ac.WingSpan)); var catCounts = byCat.ToDictionary(ca => ca.Key, ca => ca.ToList().Count); double minLandingDist = aircraft[wat].Min(ac => ac.LandingDist); double maxLandingDist = aircraft[wat].Max(ac => ac.LandingDist); var withMLD = aircraft[wat].Where(ac => ac.MinLandingDist > 0); double minMinLandingDist = withMLD.Count() > 0 ? withMLD.Min(ac => ac.MinLandingDist) : 0.0; int noMinLandingDist = aircraft[wat].Count(ac => ac.MinLandingDist == 0); double maxMinLandingDist = aircraft[wat].Max(ac => ac.MinLandingDist); double minWingSpan = aircraft[wat].Min(ac => ac.WingSpan); double maxWingSpan = aircraft[wat].Max(ac => ac.WingSpan); double minTakeOff = aircraft[wat].Min(ac => ac.TakeOffDist); double maxTakeOff = aircraft[wat].Max(ac => ac.TakeOffDist); string Name = aircraft[wat].First(ac => ac.WingSpan == maxWingSpan).Name; rtbAircraft.AppendText($" Required Gate/Taxiway Size: <{SpanToCat(maxWingSpan)}> ({Name} has wingspan {maxWingSpan,4:0.0})\n"); foreach (var group in byCat) { rtbAircraft.AppendText($" Number of cat {group.Key} : {catCounts[group.Key],5} {string.Join(", ", group)}\n"); } Name = aircraft[wat].First(ac => ac.TakeOffDist == minTakeOff).Name; rtbAircraft.AppendText($" Shortest Takeoff possible : {minTakeOff,5} ({Name})\n"); Name = aircraft[wat].First(ac => ac.TakeOffDist == maxTakeOff).Name; rtbAircraft.AppendText($" Max Takeoff required : {maxTakeOff,5} ({Name})\n"); Name = aircraft[wat].First(ac => ac.LandingDist == minLandingDist).Name; rtbAircraft.AppendText($" Shortest Landing Distance : {minLandingDist,5} ({Name})\n"); Name = aircraft[wat].First(ac => ac.LandingDist == maxLandingDist).Name; rtbAircraft.AppendText($" Longest Landing Distance : {maxLandingDist,5} ({Name})\n"); Name = aircraft[wat].First(ac => ac.MinLandingDist == minMinLandingDist).Name; rtbAircraft.AppendText($" Shortest Min Ldg Dist. : {minMinLandingDist,5} ({Name})\n"); Name = aircraft[wat].First(ac => ac.MinLandingDist == maxMinLandingDist).Name; rtbAircraft.AppendText($" Longest Min Ldg Dist. : {maxMinLandingDist,5} ({Name})\n"); rtbAircraft.AppendText($" Without Min Ldg Dist. : {noMinLandingDist,5}\n"); //rtbAircraft.AppendText($"{wat,-10} {aircraft[wat].Count(),2} {minLandingDist,5} {maxLandingDist,5} {minMinLandingDist,5} {maxMinLandingDist,5} {minTakeOff,5} {maxTakeOff,5} {minWingSpan,4:0.0} <{SpanToCat(minWingSpan)}> {maxWingSpan,4:0.0} <{SpanToCat(maxWingSpan)}>\n"); rtbAircraft.AppendText("\n"); } } //foreach (KeyValuePair<int, List<AircraftBase>> details in aircraft.OrderBy(ac => ac.Key)) //{ // double averageWingSpan = details.Value.Average(a => a.WingSpan); // double minWingSpan = details.Value.Min(a => a.WingSpan); // double maxWingSpan = details.Value.Max(a => a.WingSpan); // rtbAircraft.AppendText($"{details.Key} Wingspan: mn {minWingSpan:0.0} <{SpanToCat(minWingSpan)}> av {averageWingSpan:0.0} mx: {maxWingSpan:0.0} <{SpanToCat(maxWingSpan)}>\n"); //} //foreach (KeyValuePair<int, List<AircraftBase>> details in aircraft.OrderBy(ac => ac.Key)) //{ // double averageLength = details.Value.Average(a => a.TakeOffDist); // double minLength = details.Value.Min(a => a.TakeOffDist); // double maxLength = details.Value.Max(a => a.TakeOffDist); // rtbAircraft.AppendText($"{details.Key} TakeOffDist: mn {minLength:0} av {averageLength:0} mx: {maxLength:0}\n"); //} //foreach (KeyValuePair<int, List<AircraftBase>> details in aircraft.OrderBy(ac => ac.Key)) //{ // double averageLength = details.Value.Average(a => a.LandingDist); // double minLength = details.Value.Min(a => a.LandingDist); // double maxLength = details.Value.Max(a => a.LandingDist); // rtbAircraft.AppendText($"{details.Key} LandingDist: mn {minLength:0} av {averageLength:0} mx: {maxLength:0}\n"); //} }