Skip to content

Commit e826a76

Browse files
committed
Adapted departure RWY detection to attempt matching against active ES RWYs
If no active RWY is provided by EuroScope (e.g. a SID is not available for the active RWYs), DelHel now attempts to find matching SIDs for the currently active RWYs
1 parent fd3ea41 commit e826a76

File tree

4 files changed

+77
-27
lines changed

4 files changed

+77
-27
lines changed

DelHel/CDelHel.cpp

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ bool CDelHel::OnCompileCommand(const char* sCommandLine)
5353
if (starts_with(args[0], ".delhel")) {
5454
if (args.size() == 1) {
5555
std::ostringstream msg;
56-
msg << "Version " << PLUGIN_VERSION << " loaded. Available commands: auto, debug, nap, reload, reset, update";
56+
msg << "Version " << PLUGIN_VERSION << " loaded. Available commands: auto, debug, nap, reload, reset, update, rflblw, logminmaxrfl, minmaxrfl, flash";
5757

5858
this->LogMessage(msg.str());
5959

@@ -434,25 +434,28 @@ void CDelHel::ReadAirportConfig()
434434
continue;
435435
}
436436

437-
for (auto& [rwy, jsi] : jrwys.items()) {
437+
std::ostringstream rrs;
438+
rrs << icao << "\\/(";
439+
for (auto it = jrwys.items().begin(); it != jrwys.items().end(); ++it) {
438440
sidinfo si{
439-
rwy, // rwy
440-
jsi.value<std::string>("dep", ""), // dep
441-
jsi.value<std::string>("nap", "") // nap
441+
it.key(), // rwy
442+
it.value().value<std::string>("dep", ""), // dep
443+
it.value().value<std::string>("nap", "") // nap
442444
};
443445

444446
s.rwys.emplace(si.rwy, si);
445-
ap.rwys.insert(si.rwy);
446-
}
447-
448-
ap.sids.emplace(wp, s);
447+
ap.rwys.emplace(si.rwy, false);
449448

450-
std::ostringstream rrs;
451-
rrs << icao << "\\/(";
452-
std::copy(ap.rwys.begin(), ap.rwys.end(), std::ostream_iterator<std::string>(rrs, "|"));
449+
rrs << si.rwy;
450+
if (std::next(it) != jrwys.items().end()) {
451+
rrs << '|';
452+
}
453+
}
453454
rrs << ')';
454455

455456
ap.rwy_regex = std::regex(rrs.str(), std::regex_constants::ECMAScript);
457+
458+
ap.sids.emplace(wp, s);
456459
}
457460

458461
this->airports.emplace(icao, ap);
@@ -464,21 +467,39 @@ void CDelHel::ReadAirportConfig()
464467
void CDelHel::UpdateActiveAirports()
465468
{
466469
this->SelectActiveSectorfile();
467-
for (auto sfe = this->SectorFileElementSelectFirst(EuroScopePlugIn::SECTOR_ELEMENT_AIRPORT); sfe.IsValid(); sfe = this->SectorFileElementSelectNext(sfe, EuroScopePlugIn::SECTOR_ELEMENT_AIRPORT)) {
468-
std::string dep = sfe.GetName();
469-
to_upper(dep);
470+
for (auto sfe = this->SectorFileElementSelectFirst(EuroScopePlugIn::SECTOR_ELEMENT_RUNWAY); sfe.IsValid(); sfe = this->SectorFileElementSelectNext(sfe, EuroScopePlugIn::SECTOR_ELEMENT_RUNWAY)) {
471+
std::string ap = trim(sfe.GetAirportName());
472+
to_upper(ap);
470473

471-
auto ait = this->airports.find(dep);
474+
auto ait = this->airports.find(ap);
472475
if (ait == this->airports.end()) {
473476
continue;
474477
}
475478

476-
ait->second.active = sfe.IsElementActive(true, 0);
479+
std::string rwy = trim(sfe.GetRunwayName(0));
480+
to_upper(rwy);
481+
482+
auto rit = ait->second.rwys.find(rwy);
483+
if (rit != ait->second.rwys.end()) {
484+
rit->second = sfe.IsElementActive(true, 0);
485+
}
486+
487+
rwy = trim(sfe.GetRunwayName(1));
488+
to_upper(rwy);
489+
490+
rit = ait->second.rwys.find(rwy);
491+
if (rit != ait->second.rwys.end()) {
492+
rit->second = sfe.IsElementActive(true, 1);
493+
}
494+
495+
if (!ait->second.active) {
496+
ait->second.active = sfe.IsElementActive(true, 0) || sfe.IsElementActive(true, 1);
497+
}
477498
}
478499
}
479500

480501

481-
validation CDelHel::ProcessFlightPlan(const EuroScopePlugIn::CFlightPlan& fp, bool nap, bool validateOnly)
502+
validation CDelHel::ProcessFlightPlan(EuroScopePlugIn::CFlightPlan& fp, bool nap, bool validateOnly)
482503
{
483504
validation res{
484505
true, // valid
@@ -617,18 +638,35 @@ validation CDelHel::ProcessFlightPlan(const EuroScopePlugIn::CFlightPlan& fp, bo
617638
return res;
618639
}
619640

641+
std::map<std::string, sidinfo>::iterator sit;
620642
std::string rwy = fpd.GetDepartureRwy();
621643
if (rwy == "") {
622-
this->LogMessage("Failed to process flightplan, no runway assigned", cs);
644+
this->LogDebugMessage("No runway assigned, attempting to pick first active runway for SID", cs);
623645

624-
res.valid = false;
625-
res.tag = "RWY";
626-
res.color = TAG_COLOR_RED;
646+
for (auto [r, active] : ap.rwys) {
647+
if (active) {
648+
sit = sid.rwys.find(r);
649+
if (sit != sid.rwys.end()) {
650+
rwy = r;
651+
break;
652+
}
653+
}
654+
}
627655

628-
return res;
656+
if (rwy == "") {
657+
this->LogMessage("Failed to process flightplan, no runway assigned", cs);
658+
659+
res.valid = false;
660+
res.tag = "RWY";
661+
res.color = TAG_COLOR_RED;
662+
663+
return res;
664+
}
665+
}
666+
else {
667+
sit = sid.rwys.find(rwy);
629668
}
630669

631-
auto sit = sid.rwys.find(rwy);
632670
if (sit == sid.rwys.end()) {
633671
this->LogMessage("Invalid flightplan, no matching SID found for runway", cs);
634672

@@ -701,7 +739,6 @@ validation CDelHel::ProcessFlightPlan(const EuroScopePlugIn::CFlightPlan& fp, bo
701739
for (auto wyprouit = vait->waypts.begin(); wyprouit != vait->waypts.end(); ++wyprouit) {
702740
for (auto wypfpl = fpl.route.begin() + count; wypfpl != fpl.route.end(); ++wypfpl) {
703741

704-
this->LogDebugMessage("Looking for json-Wypt: " + *wyprouit + " comparing to fpl-Wypt: " + wypfpl->name, cs);
705742
if (wypfpl->airway && wypfpl->name.rfind(*wyprouit) == 0) { // check if waypoint name is part of the airway (e.g. SID)
706743

707744
routecheck = true;

DelHel/CDelHel.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class CDelHel : public EuroScopePlugIn::CPlugIn
5555
void ReadAirportConfig();
5656
void UpdateActiveAirports();
5757

58-
validation ProcessFlightPlan(const EuroScopePlugIn::CFlightPlan& fp, bool nap, bool validateOnly = false);
58+
validation ProcessFlightPlan(EuroScopePlugIn::CFlightPlan& fp, bool nap, bool validateOnly = false);
5959
bool CDelHel::CheckFlightPlanProcessed(const EuroScopePlugIn::CFlightPlan& fp);
6060
bool IsFlightPlanProcessed(const EuroScopePlugIn::CFlightPlan& fp);
6161
void AutoProcessFlightPlans();

DelHel/airport.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ struct airport {
1313
int elevation;
1414
bool active;
1515
std::map<std::string, sid> sids;
16-
std::set<std::string> rwys;
16+
std::map<std::string, bool> rwys;
1717
std::vector<routing> validroutes;
1818
std::regex rwy_regex;
1919
};

DelHel/helpers.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,17 @@ inline void to_upper(std::string& str)
9797
inline int round_to_closest(int num, int closest)
9898
{
9999
return ((num + closest / 2) / closest) * closest;
100+
}
101+
102+
inline std::string trim(const std::string& str, const std::string& charset = " \t")
103+
{
104+
size_t begin = str.find_first_not_of(charset);
105+
if (begin == std::string::npos) {
106+
// Empty string or only characters from charset provided
107+
return "";
108+
}
109+
110+
size_t end = str.find_last_not_of(charset);
111+
112+
return str.substr(begin, end - begin + 1);
100113
}

0 commit comments

Comments
 (0)