Files
pilotclient/src/blackmisc/simulation/categorymatcher.cpp
Klaus Basan f986e9ca8b Style
2020-01-07 19:46:15 +00:00

177 lines
8.8 KiB
C++

/* Copyright (C) 2019
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
* or distributed except according to the terms contained in the LICENSE file.
*/
#include "categorymatcher.h"
#include "simulatedaircraft.h"
#include "aircraftmatchersetup.h"
#include "matchingutils.h"
#include "blackmisc/statusmessagelist.h"
#include <QStringBuilder>
using namespace BlackMisc::Aviation;
namespace BlackMisc
{
namespace Simulation
{
const CLogCategoryList &CCategoryMatcher::getLogCategories()
{
static const CLogCategoryList cats { CLogCategory::matching() };
return cats;
}
void CCategoryMatcher::setCategories(const CAircraftCategoryList &categories)
{
m_all = categories;
m_all.sortByLevel();
CAircraftCategoryList gliders = categories.findByName("glider").findFirstLevels();
if (!gliders.isEmpty())
{
const int fl = gliders.front().getFirstLevel();
gliders = categories.findByFirstLevel(fl);
gliders.sortByLevel();
m_gliders = gliders;
}
CAircraftCategoryList militaryWing = categories.findByName("wing military").findFirstLevels();
if (!militaryWing.isEmpty())
{
const int fl = militaryWing.front().getFirstLevel();
militaryWing = categories.findByFirstLevel(fl);
militaryWing.sortByLevel();
m_militaryWingAircraft = militaryWing;
}
CAircraftCategoryList militaryRotor = categories.findByName("rotor military").findFirstLevels();
if (!militaryRotor.isEmpty())
{
const int fl = militaryRotor.front().getFirstLevel();
militaryRotor = categories.findByFirstLevel(fl);
militaryRotor.sortByLevel();
m_militaryRotorAircraft = militaryRotor;
}
}
CAircraftModelList CCategoryMatcher::reduceByCategories(const CAircraftModelList &alreadyMatchedModels, const CAircraftModelList &modelSet, const CAircraftMatcherSetup &setup, const CSimulatedAircraft &remoteAircraft, bool &reduced, bool shortLog, CStatusMessageList *log) const
{
Q_UNUSED(shortLog)
reduced = false;
if (!setup.useCategoryMatching())
{
if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Disabled category matching"), getLogCategories()); }
return alreadyMatchedModels;
}
if (m_all.isEmpty())
{
// no categories?
CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Disabled category matching"), getLogCategories());
return alreadyMatchedModels;
}
if (!remoteAircraft.getAircraftIcaoCode().hasCategory())
{
CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("No category in remote aircraft"), getLogCategories());
return alreadyMatchedModels;
}
if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Remote aircraft has category '%1'").arg(remoteAircraft.getAircraftIcaoCode().getCategory().getNameDbKey()), getLogCategories()); }
if (!m_gliders.isEmpty() && setup.getMatchingMode().testFlag(CAircraftMatcherSetup::ByCategoryGlider) && this->isGlider(remoteAircraft.getAircraftIcaoCode()))
{
// we have a glider
// and we search in the whole set: this is a special case
const int firstLevel = this->gliderFirstLevel();
const CAircraftModelList gliders = modelSet.findByCategoryFirstLevel(firstLevel); // all gliders from model set
if (!gliders.isEmpty())
{
const CAircraftCategory category = remoteAircraft.getAircraftIcaoCode().getCategory();
reduced = true; // in any case reduced (to gliders)
// find same category
const CAircraftModelList sameGliders = gliders.findByCategory(category);
if (!sameGliders.isEmpty())
{
if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Reduced to %1 models by category: '%2'").arg(sameGliders.size()).arg(category.toQString(true)), getLogCategories()); }
return sameGliders;
}
// find parallel branch category
const CAircraftCategoryList otherBranches = m_gliders.findInParallelBranch(category);
if (!otherBranches.isEmpty())
{
const CAircraftModelList otherBranchGliders = gliders.findByCategories(otherBranches);
if (!otherBranchGliders.isEmpty())
{
if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Reduced to %1 parallel branch models of '%2' by categories: '%3'").arg(otherBranchGliders.size()).arg(category.getLevelAndName(), otherBranches.getLevelsString()), getLogCategories()); }
return otherBranchGliders;
}
}
const CAircraftCategoryList siblings = m_gliders.findSiblings(category);
if (!siblings.isEmpty())
{
const CAircraftModelList siblingGliders = modelSet.findByCategories(siblings);
if (!siblings.isEmpty() && !siblingGliders.isEmpty())
{
if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Reduced to %1 sibling models of '%2' by categories: '%3'").arg(siblingGliders.size()).arg(category.getLevelAndName(), siblings.getLevelsString()), getLogCategories()); }
return siblingGliders;
}
}
CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Reduced to %1 models by 'GLIDER' category").arg(sameGliders.size()), getLogCategories());
return gliders;
}
else
{
if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("No glider category '%1' in set").arg(m_gliders.front().getLevelAndName()), getLogCategories()); }
static const QStringList substituteIcaos({ "UHEL", "GLID", "ULAC" }); // maybe also GYRO
static const QString substituteIcaosStr = substituteIcaos.join(", ");
CAircraftModelList substitutes = alreadyMatchedModels.findByDesignatorsOrFamilyWithColorLivery(substituteIcaos);
if (substitutes.isEmpty())
{
substitutes = alreadyMatchedModels.findByCombinedType(QStringLiteral("L1P"));
if (!substitutes.isEmpty())
{
reduced = true;
if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("No gliders, reduced to 'L1P' models: %1' (avoid absurd matchings)").arg(substitutes.size()), getLogCategories()); }
return substitutes;
}
}
else
{
reduced = true;
if (log) { CMatchingUtils::addLogDetailsToList(log, remoteAircraft, QStringLiteral("Reduced to %1 models by '%2'").arg(substitutes.size()).arg(substituteIcaosStr), getLogCategories()); }
return substitutes;
}
}
}
return alreadyMatchedModels;
}
bool CCategoryMatcher::isGlider(const CAircraftIcaoCode &icao) const
{
if (icao.getDesignator() == CAircraftIcaoCode::getGliderDesignator()) { return true; }
const int glider1st = this->gliderFirstLevel();
if (glider1st >= 0 && icao.hasCategory())
{
return icao.getCategory().getFirstLevel() == glider1st;
}
return false;
}
int CCategoryMatcher::gliderFirstLevel() const
{
if (m_gliders.isEmpty()) { return -1; }
return m_gliders.front().getFirstLevel();
}
} // namespace
} // namespace