mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-31 04:25:35 +08:00
Ref T658, adjusted matching with script
* return values changed * pass in model and matched model * JavaScript objects for web services, model set * allow to pass back a model
This commit is contained in:
committed by
Mat Sutcliffe
parent
891d75598e
commit
ab5fc6f0ee
@@ -22,6 +22,7 @@
|
||||
#include "blackmisc/logmessage.h"
|
||||
#include "blackmisc/statusmessagelist.h"
|
||||
#include "blackmisc/directoryutils.h"
|
||||
#include "aircraftmatcher.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QStringList>
|
||||
@@ -108,7 +109,7 @@ namespace BlackCore
|
||||
return code;
|
||||
}
|
||||
|
||||
CAircraftModel CAircraftMatcher::getClosestMatch(const CSimulatedAircraft &remoteAircraft, MatchingLog whatToLog, CStatusMessageList *log) const
|
||||
CAircraftModel CAircraftMatcher::getClosestMatch(const CSimulatedAircraft &remoteAircraft, MatchingLog whatToLog, CStatusMessageList *log, bool useMatchingScript) const
|
||||
{
|
||||
CAircraftModelList modelSet(m_modelSet); // Models for this matching
|
||||
const CAircraftMatcherSetup setup = m_setup;
|
||||
@@ -119,13 +120,14 @@ namespace BlackCore
|
||||
static const QString m3("Matching uses model set of %1 models\n%2");
|
||||
static const QString m4("Setup %1");
|
||||
static const QString summary(
|
||||
"\n"
|
||||
"Matching summary\n"
|
||||
"-----------------------------------------\n"
|
||||
"- Combined: %1 -> %2\n"
|
||||
"- Aircraft: %3 -> %4\n"
|
||||
"- Airline: %5 -> %6\n"
|
||||
"- Livery: %7 -> %8\n"
|
||||
"- Model: %9 -> %10\n"
|
||||
"- Script modifed value: %11\n"
|
||||
"-----------------------------------------\n");
|
||||
|
||||
const QDateTime startTime = QDateTime::currentDateTimeUtc();
|
||||
@@ -246,20 +248,7 @@ namespace BlackCore
|
||||
break;
|
||||
}
|
||||
|
||||
if (log)
|
||||
{
|
||||
static const QString nms = "no model string";
|
||||
CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Picking among %1 by strategy '%2'").arg(candidates.size()).arg(CAircraftMatcherSetup::strategyToString(usedStrategy)));
|
||||
CMatchingUtils::addLogDetailsToList(log, remoteAircraft,
|
||||
summary.arg(
|
||||
remoteAircraft.getAircraftIcaoCode().getCombinedType(), matchedModel.getAircraftIcaoCode().getCombinedType(),
|
||||
remoteAircraft.getAircraftIcaoCode().getDesignatorDbKey(), matchedModel.getAircraftIcaoCode().getDesignatorDbKey(),
|
||||
remoteAircraft.getAirlineIcaoCode().getVDesignatorDbKey(), matchedModel.getAirlineIcaoCode().getVDesignatorDbKey()
|
||||
).arg(
|
||||
remoteAircraft.getLivery().getCombinedCodePlusInfoAndId(), matchedModel.getLivery().getCombinedCodePlusInfoAndId(),
|
||||
defaultIfEmpty(remoteAircraft.getModel().getModelStringAndDbKey(), nms), matchedModel.getModelStringAndDbKey()
|
||||
));
|
||||
}
|
||||
if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Picking among %1 by strategy '%2'").arg(candidates.size()).arg(CAircraftMatcherSetup::strategyToString(usedStrategy))); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,9 +256,53 @@ namespace BlackCore
|
||||
matchedModel.setCallsign(remoteAircraft.getCallsign());
|
||||
matchedModel.setModelType(CAircraftModel::TypeModelMatching);
|
||||
|
||||
// matching script
|
||||
bool didRunAndModifyMatchingScript = false;
|
||||
if (useMatchingScript && setup.doRunMsMatchingStageScript())
|
||||
{
|
||||
CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Matching script: Matching stage script used"));
|
||||
const MSReturnValues rv = CAircraftMatcher::matchingStageScript(remoteAircraft.getModel(), matchedModel, setup, modelSet, log);
|
||||
if (rv.runScriptAndModified())
|
||||
{
|
||||
matchedModel = rv.model;
|
||||
didRunAndModifyMatchingScript = true;
|
||||
}
|
||||
|
||||
if (rv.runScriptModifiedAndRerun())
|
||||
{
|
||||
CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Matching script: Modified values and re-run requested"));
|
||||
CSimulatedAircraft rerunAircraft(remoteAircraft);
|
||||
rerunAircraft.setModel(matchedModel);
|
||||
matchedModel = CAircraftMatcher::getClosestMatch(rerunAircraft, whatToLog, log, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Matching script: No matching stage script used"));
|
||||
}
|
||||
|
||||
// copy over callsign validate (again, just in case it was changed in mathcing script)
|
||||
matchedModel.setCallsign(remoteAircraft.getCallsign());
|
||||
matchedModel.setModelType(CAircraftModel::TypeModelMatching);
|
||||
|
||||
Q_ASSERT_X(!matchedModel.getCallsign().isEmpty(), Q_FUNC_INFO, "Missing callsign");
|
||||
Q_ASSERT_X(matchedModel.hasModelString(), Q_FUNC_INFO, "Missing model string");
|
||||
|
||||
if (log)
|
||||
{
|
||||
static const QString nms = "no model string";
|
||||
CMatchingUtils::addLogDetailsToList(log, remoteAircraft,
|
||||
summary.arg(
|
||||
remoteAircraft.getAircraftIcaoCode().getCombinedType(), matchedModel.getAircraftIcaoCode().getCombinedType(),
|
||||
remoteAircraft.getAircraftIcaoCode().getDesignatorDbKey(), matchedModel.getAircraftIcaoCode().getDesignatorDbKey(),
|
||||
remoteAircraft.getAirlineIcaoCode().getVDesignatorDbKey(), matchedModel.getAirlineIcaoCode().getVDesignatorDbKey()
|
||||
).arg(
|
||||
remoteAircraft.getLivery().getCombinedCodePlusInfoAndId(), matchedModel.getLivery().getCombinedCodePlusInfoAndId(),
|
||||
defaultIfEmpty(remoteAircraft.getModel().getModelStringAndDbKey(), nms), matchedModel.getModelStringAndDbKey(),
|
||||
boolToYesNo(didRunAndModifyMatchingScript)
|
||||
));
|
||||
} // log
|
||||
|
||||
const QDateTime endTime = QDateTime::currentDateTimeUtc();
|
||||
const qint64 matchingTime = startTime.msecsTo(endTime);
|
||||
static const QString em("--- Matching end: UTC %1, time %2ms ---");
|
||||
@@ -292,40 +325,85 @@ namespace BlackCore
|
||||
return model;
|
||||
}
|
||||
|
||||
CAircraftModel CAircraftMatcher::networkEntryScript(const CAircraftModel &inModel, const CAircraftMatcherSetup &setup, CStatusMessageList *log)
|
||||
MSReturnValues CAircraftMatcher::reverseLookupScript(const CAircraftModel &inModel, const CAircraftMatcherSetup &setup, CStatusMessageList *log)
|
||||
{
|
||||
if (!setup.doRunMsNetworkEntryScript()) { return inModel; }
|
||||
if (!setup.doRunMsReverseLookupScript()) { return MSReturnValues(inModel); }
|
||||
if (!sApp || sApp->isShuttingDown() || !sApp->hasWebDataServices()) { return inModel; }
|
||||
const QString js = CFileUtils::readFileToString(setup.getMsReverseLookupFile());
|
||||
static const CAircraftModelList noModelSet;
|
||||
const MSReturnValues rv = CAircraftMatcher::matchingScript(js, inModel, inModel, setup, noModelSet, ReverseLookup, log);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// matching script
|
||||
MSReturnValues CAircraftMatcher::matchingStageScript(const CAircraftModel &inModel, const CAircraftModel &matchedModel, const CAircraftMatcherSetup &setup, const CAircraftModelList &modelSet, CStatusMessageList *log)
|
||||
{
|
||||
if (!setup.doRunMsMatchingStageScript()) { return MSReturnValues(inModel); }
|
||||
if (!sApp || sApp->isShuttingDown() || !sApp->hasWebDataServices()) { return inModel; }
|
||||
const QString js = CFileUtils::readFileToString(setup.getMsMatchingStageFile());
|
||||
const MSReturnValues rv = CAircraftMatcher::matchingScript(js, inModel, matchedModel, setup, modelSet, MatchingStage, log);
|
||||
return rv;
|
||||
}
|
||||
|
||||
MSReturnValues CAircraftMatcher::matchingScript(const QString &js, const CAircraftModel &inModel, const CAircraftModel &matchedModel, const CAircraftMatcherSetup &setup, const CAircraftModelList &modelSet, MatchingScript ms, CStatusMessageList *log)
|
||||
{
|
||||
MSReturnValues rv(inModel);
|
||||
QString logMessage;
|
||||
const CCallsign callsign = inModel.getCallsign();
|
||||
const CAircraftIcaoCode inAircraftIcao = inModel.getAircraftIcaoCode();
|
||||
const CAirlineIcaoCode inAirlineIcao = inModel.getAirlineIcaoCode();
|
||||
const CLivery inLivery = inModel.getLivery();
|
||||
|
||||
while (setup.doRunMsNetworkEntryScript())
|
||||
while (!js.isEmpty() && sApp && !sApp->isShuttingDown())
|
||||
{
|
||||
const QString js = CFileUtils::readFileToString(setup.getMsNetworkEntryFile());
|
||||
if (js.isEmpty()) { break; }
|
||||
rv.runScript = true;
|
||||
|
||||
// matching script
|
||||
const bool msReverse = (ms == ReverseLookup);
|
||||
const QString lf = msReverse ? setup.getMsReverseLookupFile() : setup.getMsMatchingStageFile();
|
||||
static const QString logFileR = CFileUtils::appendFilePaths(CDirectoryUtils::logDirectory(), "logMatchingScriptReverseLookup.log");
|
||||
static const QString logFileM = CFileUtils::appendFilePaths(CDirectoryUtils::logDirectory(), "logMatchingScriptMatchingStage.log");
|
||||
|
||||
if (log)
|
||||
{
|
||||
CMatchingUtils::addLogDetailsToList(log, callsign, QStringLiteral("Matching script (%1): '%2'").arg(msToString(ms), lf));
|
||||
}
|
||||
|
||||
if (log) { CMatchingUtils::addLogDetailsToList(log, callsign, QStringLiteral("Matching script (rev.lookup): '%1'").arg(setup.getMsNetworkEntryFile())); }
|
||||
static const QString logFile = CFileUtils::appendFilePaths(CDirectoryUtils::logDirectory(), "logMatchingSriptEntry.log");
|
||||
QJSEngine engine;
|
||||
// engine.installExtensions(QJSEngine::ConsoleExtension);
|
||||
static const QJSValue jsMetaObject = engine.newQMetaObject(&MSSwiftValues::staticMetaObject);
|
||||
engine.globalObject().setProperty("SwiftValues", jsMetaObject);
|
||||
MSSwiftValues networkObject(callsign.asString(), inAircraftIcao, inLivery);
|
||||
MSSwiftValues reverseModel(callsign.asString(), inAircraftIcao, inLivery);
|
||||
MSSwiftValues returnObject;
|
||||
static const QJSValue jsInMetaObject = engine.newQMetaObject(&MSInOutValues::staticMetaObject);
|
||||
engine.globalObject().setProperty("SwiftInObject", jsInMetaObject);
|
||||
static const QJSValue jsSetMetaObject = engine.newQMetaObject(&MSModelSet::staticMetaObject);
|
||||
engine.globalObject().setProperty("SwiftModelSet", jsSetMetaObject);
|
||||
static const QJSValue jsWebServicesMetaObject = engine.newQMetaObject(&MSWebServices::staticMetaObject);
|
||||
engine.globalObject().setProperty("SwiftWebServices", jsWebServicesMetaObject);
|
||||
|
||||
QJSValue jsNetworkObject = engine.newQObject(&networkObject);
|
||||
engine.globalObject().setProperty("networkObject", jsNetworkObject);
|
||||
QJSValue jsReverseObject = engine.newQObject(&networkObject);
|
||||
engine.globalObject().setProperty("reverseObject", jsNetworkObject);
|
||||
QJSValue jsReturnObject = engine.newQObject(&returnObject);
|
||||
engine.globalObject().setProperty("returnObject", jsNetworkObject);
|
||||
// init models and set
|
||||
MSInOutValues inObject(inModel);
|
||||
MSInOutValues matchedObject(matchedModel); // same as inModel for reverse lookup
|
||||
matchedObject.evaluateChanges(inModel.getAircraftIcaoCode(), inModel.getAirlineIcaoCode());
|
||||
MSInOutValues outObject(matchedModel); // set default values for out object
|
||||
MSModelSet modelSetObject(modelSet); // empty in reverse lookup
|
||||
modelSetObject.initByAircraftAndAirline(inModel.getAircraftIcaoCode(), inModel.getAirlineIcaoCode());
|
||||
MSWebServices webServices; // web services encapsulated
|
||||
|
||||
QString logMessage;
|
||||
QJSValue ms = engine.evaluate(js, logFile);
|
||||
// object as from network
|
||||
const QJSValue jsInObject = engine.newQObject(&inObject);
|
||||
engine.globalObject().setProperty("inObject", jsInObject);
|
||||
|
||||
// object that will be returned
|
||||
const QJSValue jsOutObject = engine.newQObject(&outObject);
|
||||
engine.globalObject().setProperty("outObject", jsOutObject);
|
||||
|
||||
// object as matched so far, same as inObject in reverse lookup
|
||||
const QJSValue jsMatchedObject = engine.newQObject(&matchedObject);
|
||||
engine.globalObject().setProperty("matchedObject", jsMatchedObject);
|
||||
|
||||
// wrapper for model set
|
||||
const QJSValue jsModelSetObject = engine.newQObject(&modelSetObject);
|
||||
engine.globalObject().setProperty("modelSet", jsModelSetObject);
|
||||
|
||||
// wrapper for web services
|
||||
const QJSValue jsWebServices = engine.newQObject(&webServices);
|
||||
engine.globalObject().setProperty("webServices", jsWebServices);
|
||||
|
||||
QJSValue ms = engine.evaluate(js, msReverse ? logFileR : logFileM);
|
||||
ms = ms.call();
|
||||
if (ms.isError())
|
||||
{
|
||||
@@ -337,20 +415,73 @@ namespace BlackCore
|
||||
{
|
||||
if (ms.isQObject())
|
||||
{
|
||||
const MSSwiftValues *reverseModelProcessed = qobject_cast<const MSSwiftValues *>(ms.toQObject());
|
||||
const MSInOutValues *reverseModelProcessed = qobject_cast<const MSInOutValues *>(ms.toQObject());
|
||||
logMessage = reverseModelProcessed->getLogMessage();
|
||||
if (!reverseModelProcessed->isModified()) { break; }
|
||||
|
||||
// changed
|
||||
if (reverseModel.hasChangedAircraftIcao(inAircraftIcao))
|
||||
// rerun
|
||||
rv.rerun = reverseModelProcessed->isRerun();
|
||||
|
||||
// changed model by model string?
|
||||
if (reverseModelProcessed->hasChangedModelString(inModel.getModelString()))
|
||||
{
|
||||
CAircraftIcaoCode icao;
|
||||
if (log) { CMatchingUtils::addLogDetailsToList(log, callsign, QStringLiteral("Matching script: '%1' -> '%2'").arg(inAircraftIcao.getDesignatorDbKey(), icao.getDesignatorDbKey())); }
|
||||
const CAircraftModel model = sApp->getWebDataServices()->getModelForModelString(reverseModelProcessed->getModelString());
|
||||
if (model.hasValidDbKey())
|
||||
{
|
||||
// found full model from DB
|
||||
rv.model = model;
|
||||
rv.modified = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (reverseModel.hasChangedAirlineIcao(inAirlineIcao))
|
||||
// changed model by model id?
|
||||
if (reverseModelProcessed->hasChangedModelId(inModel))
|
||||
{
|
||||
const CAircraftModel model = sApp->getWebDataServices()->getModelForDbKey(reverseModelProcessed->getDbModelId());
|
||||
if (model.hasValidDbKey())
|
||||
{
|
||||
// found full model from DB
|
||||
rv.model = model;
|
||||
rv.modified = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// changed aircraft ICAO
|
||||
if (reverseModelProcessed->hasChangedAircraftIcao(matchedModel.getAircraftIcaoCode()))
|
||||
{
|
||||
CAircraftIcaoCode icao(reverseModelProcessed->getAircraftIcao());
|
||||
if (reverseModelProcessed->hasChangedAircraftIcaoId(matchedModel.getAircraftIcaoCode()))
|
||||
{
|
||||
icao = sApp->getWebDataServices()->getAircraftIcaoCodeForDbKey(reverseModelProcessed->getDbAircraftIcaoId());
|
||||
}
|
||||
rv.modified = true;
|
||||
rv.model.setAircraftIcaoCode(icao);
|
||||
}
|
||||
|
||||
if (reverseModelProcessed->hasChangedLiveryId(matchedModel.getLivery()))
|
||||
{
|
||||
const CLivery livery(sApp->getWebDataServices()->getLiveryForDbKey(reverseModelProcessed->getDbLiveryId()));
|
||||
rv.model.setLivery(livery);
|
||||
rv.modified = true;
|
||||
}
|
||||
else if (reverseModelProcessed->hasChangedAirlineIcao(matchedModel.getAirlineIcaoCode()))
|
||||
{
|
||||
CAirlineIcaoCode icao;
|
||||
if (reverseModelProcessed->hasChangedAirlineIcaoId(matchedModel.getAirlineIcaoCode()))
|
||||
{
|
||||
icao = sApp->getWebDataServices()->getAirlineIcaoCodeForDbKey(reverseModelProcessed->getDbAirlineIcaoId());
|
||||
}
|
||||
else
|
||||
{
|
||||
icao = sApp->getWebDataServices()->getAirlineIcaoCodeForUniqueDesignatorOrDefault(reverseModelProcessed->getAirlineIcao(), true);
|
||||
}
|
||||
|
||||
const CLivery livery(sApp->getWebDataServices()->getStdLiveryForAirlineCode(icao));
|
||||
rv.model.setLivery(livery);
|
||||
if (log) { CMatchingUtils::addLogDetailsToList(log, callsign, QStringLiteral("Matching script, changed airline ICAO: '%1' -> '%2'").arg(matchedModel.getAirlineIcaoCode().toQString(true), icao.toQString(true))); }
|
||||
rv.modified = true;
|
||||
}
|
||||
}
|
||||
else if (ms.isString())
|
||||
@@ -359,15 +490,15 @@ namespace BlackCore
|
||||
}
|
||||
}
|
||||
|
||||
// log message
|
||||
if (log && !logMessage.isEmpty()) { CMatchingUtils::addLogDetailsToList(log, callsign, QStringLiteral("Matching script: '%1'").arg(logMessage)); }
|
||||
|
||||
// end this
|
||||
break;
|
||||
}
|
||||
|
||||
// not yet using the script model
|
||||
return inModel;
|
||||
// log message
|
||||
if (log && !logMessage.isEmpty()) { CMatchingUtils::addLogDetailsToList(log, callsign, QStringLiteral("Matching script: '%1'").arg(logMessage)); }
|
||||
|
||||
// end
|
||||
return rv;
|
||||
}
|
||||
|
||||
CAircraftModel CAircraftMatcher::reverseLookupModel(const CAircraftModel &modelToLookup, const QString &networkLiveryInfo, CStatusMessageList *log)
|
||||
@@ -532,6 +663,21 @@ namespace BlackCore
|
||||
return model;
|
||||
}
|
||||
|
||||
CAircraftModel CAircraftMatcher::reverseLookupModel(const CAircraftModel &modelToLookup, const QString &networkLiveryInfo, const CAircraftMatcherSetup &setup, CStatusMessageList *log)
|
||||
{
|
||||
CAircraftModel reverseModel = reverseLookupModel(modelToLookup, networkLiveryInfo, log);
|
||||
if (!setup.doRunMsReverseLookupScript()) { return reverseModel; }
|
||||
const CCallsign cs = modelToLookup.getCallsign();
|
||||
const MSReturnValues rv = reverseLookupScript(reverseModel, setup, log);
|
||||
if (rv.runScriptModifiedAndRerun())
|
||||
{
|
||||
CMatchingUtils::addLogDetailsToList(log, cs, QStringLiteral("Matching script: Modified value and requested rerun"));
|
||||
reverseModel = reverseLookupModel(rv.model, networkLiveryInfo, log);
|
||||
return reverseModel;
|
||||
}
|
||||
return (rv.runScriptAndModified() ? rv.model : reverseModel);
|
||||
}
|
||||
|
||||
CAircraftModel CAircraftMatcher::reverseLookupModelString(const QString &modelString, const CCallsign &callsign, CStatusMessageList *log)
|
||||
{
|
||||
if (!sApp || sApp->isShuttingDown() || !sApp->hasWebDataServices()) { return CAircraftModel(); }
|
||||
|
||||
Reference in New Issue
Block a user