diff --git a/src/blackmisc/simulation/aircraftmodel.cpp b/src/blackmisc/simulation/aircraftmodel.cpp index 643bede39..177216574 100644 --- a/src/blackmisc/simulation/aircraftmodel.cpp +++ b/src/blackmisc/simulation/aircraftmodel.cpp @@ -322,6 +322,11 @@ namespace BlackMisc this->setModelMode(CAircraftModel::modelModeFromString(mode)); } + bool CAircraftModel::matchesSimulator(const CSimulatorInfo &simulator) const + { + return (static_cast(simulator.getSimulator()) & static_cast(this->getSimulatorInfo().getSimulator())) > 0; + } + void CAircraftModel::updateMissingParts(const CAircraftModel &otherModel, bool dbModelPriority) { if (dbModelPriority && !this->hasValidDbKey() && otherModel.hasValidDbKey()) diff --git a/src/blackmisc/simulation/aircraftmodel.h b/src/blackmisc/simulation/aircraftmodel.h index 90d5ebfcc..25f7f8202 100644 --- a/src/blackmisc/simulation/aircraftmodel.h +++ b/src/blackmisc/simulation/aircraftmodel.h @@ -227,6 +227,9 @@ namespace BlackMisc //! Set simulator info void setSimulatorInfo(const CSimulatorInfo &simulator) { this->m_simulator = simulator; } + //! Matches given simulator? + bool matchesSimulator(const CSimulatorInfo &simulator) const; + //! File name (corresponding data for simulator, only available if representing simulator model QString getFileName() const { return m_fileName; } diff --git a/src/blackmisc/simulation/aircraftmodellist.cpp b/src/blackmisc/simulation/aircraftmodellist.cpp index 8cac62456..1f77ab848 100644 --- a/src/blackmisc/simulation/aircraftmodellist.cpp +++ b/src/blackmisc/simulation/aircraftmodellist.cpp @@ -129,10 +129,9 @@ namespace BlackMisc CAircraftModelList CAircraftModelList::matchesSimulator(const CSimulatorInfo &simulator) const { - const CSimulatorInfo::Simulator s = simulator.getSimulator(); - return this->findBy([ = ](const CAircraftModel & model) + return this->findBy([ = ](const CAircraftModel &model) { - return (s & model.getSimulatorInfo().getSimulator()) > 0; + return model.matchesSimulator(simulator); }); } @@ -197,6 +196,25 @@ namespace BlackMisc return d; } + int CAircraftModelList::removeIfNotMatchingSimulator(const CSimulatorInfo &needToMatch) + { + if (this->isEmpty()) { return 0; } + int c = 0; + for (auto it = this->begin(); it != this->end();) + { + if (it->matchesSimulator(needToMatch)) + { + ++it; + } + else + { + c++; + it = this->erase(it); + } + } + return c; + } + int CAircraftModelList::replaceOrAddModelsWithString(const CAircraftModelList &addOrReplaceList, Qt::CaseSensitivity sensitivity) { if (addOrReplaceList.isEmpty()) { return 0; } @@ -251,6 +269,39 @@ namespace BlackMisc return ms; } + CCountPerSimulator CAircraftModelList::countPerSimulator() const + { + CCountPerSimulator count; + for (const CAircraftModel &model : (*this)) + { + count.increaseSimulatorCounts(model.getSimulatorInfo()); + } + return count; + } + + CSimulatorInfo CAircraftModelList::simulatorsWithMaxEntries() const + { + if (this->isEmpty()) { return CSimulatorInfo(); } // not known + const CCountPerSimulator counts(this->countPerSimulator()); + const int simulatorsRepresented = counts.simulatorsRepresented(); + if (simulatorsRepresented < 1) + { + return CSimulatorInfo(); + } + const QMultiMap cps(counts.countPerSimulator()); + CSimulatorInfo maxSim = cps.last(); + if (simulatorsRepresented > 0) + { + const int count = cps.lastKey(); // how many elements + const QList infoWithMaxValues = cps.values(count); // all with the same counts + for (const CSimulatorInfo &info : infoWithMaxValues) + { + maxSim.addSimulator(info); + } + } + return maxSim; + } + void CAircraftModelList::updateDistributor(const CDistributor &distributor) { for (CAircraftModel &model : *this) diff --git a/src/blackmisc/simulation/aircraftmodellist.h b/src/blackmisc/simulation/aircraftmodellist.h index 85da35a9c..60ee1b61d 100644 --- a/src/blackmisc/simulation/aircraftmodellist.h +++ b/src/blackmisc/simulation/aircraftmodellist.h @@ -101,6 +101,9 @@ namespace BlackMisc //! \return number of elements removed int removeModelsWithString(const QStringList &modelStrings, Qt::CaseSensitivity sensitivity); + //! Remove if not matching simulator + int removeIfNotMatchingSimulator(const CSimulatorInfo &needToMatch); + //! Replace or add based on model string //! \return number of elements removed int replaceOrAddModelsWithString(const CAircraftModelList &addOrReplaceList, Qt::CaseSensitivity sensitivity); @@ -108,6 +111,12 @@ namespace BlackMisc //! Model strings QStringList getModelStrings(bool sort = true) const; + //! Simulator counts + CCountPerSimulator countPerSimulator() const; + + //! Which simulator(s) have the most entries + CSimulatorInfo simulatorsWithMaxEntries() const; + //! Update distributors void updateDistributor(const CDistributor &distributor); diff --git a/src/blackmisc/simulation/simulatorinfo.cpp b/src/blackmisc/simulation/simulatorinfo.cpp index fd81721bb..0e50a6c70 100644 --- a/src/blackmisc/simulation/simulatorinfo.cpp +++ b/src/blackmisc/simulation/simulatorinfo.cpp @@ -11,6 +11,7 @@ #include "blackmisc/project.h" #include "blackmisc/comparefunctions.h" #include "blackmisc/simulation/fscommon/fscommonutil.h" +#include using namespace BlackMisc; using namespace BlackMisc::Simulation::FsCommon; @@ -187,5 +188,100 @@ namespace BlackMisc ); return sim; } + + CCountPerSimulator::CCountPerSimulator() + { + this->m_counts.reserve(CSimulatorInfo::NumberOfSimulators + 1); + for (int i = 0; i < CSimulatorInfo::NumberOfSimulators + 1; i++) + { + this->m_counts.push_back(0); + } + } + + int CCountPerSimulator::getCount(const CSimulatorInfo &simulator) const + { + return this->m_counts[internalIndex(simulator)]; + } + + int CCountPerSimulator::getCountForUnknownSimulators() const + { + return this->m_counts[CSimulatorInfo::NumberOfSimulators]; + } + + int CCountPerSimulator::getMaximum() const + { + return *std::min_element(m_counts.begin(), m_counts.end()); + } + + int CCountPerSimulator::getMinimum() const + { + return *std::max_element(m_counts.begin(), m_counts.end()); + } + + int CCountPerSimulator::simulatorsRepresented() const + { + int c = 0; + for (int i = 0; i < this->m_counts.size() - 1; i++) + { + if (this->m_counts[i] > 0) { c++; } + } + return c; + } + + QMultiMap CCountPerSimulator::countPerSimulator() const + { + QMultiMap counts; + for (int i = 0; i < this->m_counts.size(); i++) + { + counts.insertMulti(this->m_counts[i], simulator(i)); + } + return counts; + } + + void CCountPerSimulator::setCount(int count, const CSimulatorInfo &simulator) + { + this->m_counts[internalIndex(simulator)] = count; + } + + void CCountPerSimulator::increaseSimulatorCounts(const CSimulatorInfo &simulator) + { + if (simulator.isNoSimulator() || simulator.isUnspecified()) + { + // unknown count + m_counts[4] = m_counts[4] + 1; + return; + } + if (simulator.fsx()) { m_counts[0] = m_counts[0] + 1; } + if (simulator.p3d()) { m_counts[1] = m_counts[1] + 1; } + if (simulator.fs9()) { m_counts[2] = m_counts[2] + 1; } + if (simulator.xplane()) { m_counts[3] = m_counts[3] + 1; } + } + + int CCountPerSimulator::internalIndex(const CSimulatorInfo &simulator) + { + Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "Need single simulator"); + switch (simulator.getSimulator()) + { + case CSimulatorInfo::FSX: return 0; + case CSimulatorInfo::P3D: return 1; + case CSimulatorInfo::FS9: return 2; + case CSimulatorInfo::XPLANE: return 3; + default: + return CSimulatorInfo::NumberOfSimulators; // unknown + } + } + + CSimulatorInfo CCountPerSimulator::simulator(int internalIndex) + { + switch (internalIndex) + { + case 0: return CSimulatorInfo(CSimulatorInfo::FSX); + case 1: return CSimulatorInfo(CSimulatorInfo::P3D); + case 2: return CSimulatorInfo(CSimulatorInfo::FS9); + case 3: return CSimulatorInfo(CSimulatorInfo::XPLANE); + default: + return CSimulatorInfo(CSimulatorInfo::None); + } + } } // ns } // ns diff --git a/src/blackmisc/simulation/simulatorinfo.h b/src/blackmisc/simulation/simulatorinfo.h index 6a2883ee1..a64e5f19e 100644 --- a/src/blackmisc/simulation/simulatorinfo.h +++ b/src/blackmisc/simulation/simulatorinfo.h @@ -14,6 +14,7 @@ #include "blackmisc/blackmiscexport.h" #include "blackmisc/valueobject.h" +#include namespace BlackMisc { @@ -46,6 +47,9 @@ namespace BlackMisc }; Q_DECLARE_FLAGS(Simulator, SimulatorFlag) + //! Number of known individual simulators + static constexpr int NumberOfSimulators = 4; + //! Default constructor CSimulatorInfo(); @@ -103,6 +107,12 @@ namespace BlackMisc //! Simulator void setSimulator(Simulator s) { m_simulator = static_cast(s); } + //! Add simulator flags + void addSimulator(Simulator s) { m_simulator |= static_cast(s); } + + //! Add simulator + void addSimulator(CSimulatorInfo simulatorInfo) { this->addSimulator(simulatorInfo.getSimulator()); } + //! All simulators void setAllSimulators() { setSimulator(All); } @@ -131,12 +141,47 @@ namespace BlackMisc BLACK_ENABLE_TUPLE_CONVERSION(CSimulatorInfo) int m_simulator = static_cast(None); }; + + //! Count per simulator, small utility class allows to retrieve values as per simulator + class BLACKMISC_EXPORT CCountPerSimulator + { + public: + //! Constructor + CCountPerSimulator(); + + //! Object count for given simulator + int getCount(const CSimulatorInfo &simulator) const; + + //! Unkown count + int getCountForUnknownSimulators() const; + + //! Set count + void setCount(int count, const CSimulatorInfo &simulator); + + //! Increase all simulators given here + void increaseSimulatorCounts(const CSimulatorInfo &simulator); + + //! Maximum + int getMaximum() const; + + //! Minimum + int getMinimum() const; + + //! Number of simulators with count > 0 + int simulatorsRepresented() const; + + //! Sorted (ascending) per simulator + QMultiMap countPerSimulator() const; + + private: + QList m_counts; + static int internalIndex(const CSimulatorInfo &simulator); + static CSimulatorInfo simulator(int internalIndex); + }; } // ns } // ns -BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Simulation::CSimulatorInfo, ( - attr(o.m_simulator) - )) +BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Simulation::CSimulatorInfo, (attr(o.m_simulator))) Q_DECLARE_METATYPE(BlackMisc::Simulation::CSimulatorInfo) Q_DECLARE_METATYPE(BlackMisc::Simulation::CSimulatorInfo::SimulatorFlag) Q_DECLARE_OPERATORS_FOR_FLAGS(BlackMisc::Simulation::CSimulatorInfo::Simulator)