Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/Lts/Services/ParticipantManagement/ppm_common.cpp
T
2026-10-03 09:20:13 +02:00

201 lines
8.0 KiB
C++
Executable File

/**
* @RDE_HEADER@
* Custom ppm functions (extends tab_db_impl.cpp/.h)
* $Id$
* $HeadURL$
* $Author$
*/
#include "ppm_common.h"
#include <utility>
#include <QtCore/QVector>
#include <QDebug>
namespace ParticipantManagement
{
StateInformation youngestStateInformation(const std::vector<ParticipantManagement::StateInformation> &stateList,
bool bSkipVbgGreaterCatastrophicKill, bool bSkipSanitation, bool debug)
{
std::shared_ptr<int> _(nullptr, [debug](int *) { if (debug) qWarning() << "##############################################"; });
if (debug)
qWarning() << "########## youngestStateInformation ##########";
ParticipantManagement::StateInformation ret;
// rtiddsgen 7.7 generates plain public members (no setters) and prefixed
// PDM enumerators (commit be912de9d resolved duplicate enumerators).
ret.vulnerabilityState = ProjectDataManagement::VulnerabilityState::VulnerabilityState_NotReady;
if (stateList.empty())
{
if (debug)
qWarning() << ">> stateList empty! not ready";
return ret;
}
// bool readyToDebug = false;
// for (const ParticipantManagement::StateInformation &si : std::as_const(stateList))
// {
// if (si.originatorId() == 0
// && si.originatorType() == ProjectDataManagement::StateChangeOriginator::ExerciseControl
// && (si.vulnerabilityState() == ProjectDataManagement::VulnerabilityState::CatastrophicKill
// || si.vulnerabilityState() == ProjectDataManagement::VulnerabilityState::CombatReady)
// )
// readyToDebug = true;
// }
/* NOTE: Participant::setState in PPM doesn't respect the vulnId sent by the TNE, but instead sets it to
* the highest vuln (ignoring TemporarySeverance, NearMiss and HitWithNoEffect!) that was found in
* the vulnerabilityBits. So the latest state in the history is always the state we are looking for.
* NOTE: StateInformation's stateTime max resolution is seconds instead of milliseconds
* NOTE: StateInformations can have the same stateTime, which means a CombatReady might be incorrectly
* chosen because it has the same stateTime as a CatastrophicKill - if not sorted by time *and* state
*/
std::vector<ParticipantManagement::StateInformation> sortedStateList(stateList); // copy list
// sort list by sample time, desc (highest time = youngest)
std::sort(sortedStateList.begin(), sortedStateList.end(),
[/*&debug,readyToDebug*/](const ParticipantManagement::StateInformation &left, const ParticipantManagement::StateInformation &right)
{
if (left.stateTime == right.stateTime && left.vulnerabilityState != right.vulnerabilityState)
{
// if (readyToDebug)
// debug = true;
// qWarning() << "WARNING: StateInformation with state" << (int)left.vulnerabilityState().underlying() << "has the same stateTime as StateInformation with state" << (int)right.vulnerabilityState().underlying();
// sort by state if time is the same (higher state = winner)
return (left.vulnerabilityState > right.vulnerabilityState);
}
return (left.stateTime > right.stateTime);
});
if (debug)
{
qWarning() << ">> printing all SIs";
for (const ParticipantManagement::StateInformation &si : std::as_const(sortedStateList))
qWarning() << ">>>> si" << "siVulnId" << (uint8_t)si.vulnerabilityState << "bits" << si.vulnerabilityBits << "time" << si.stateTime;
qWarning() << ">> checking SIs";
}
for (const ParticipantManagement::StateInformation &si : std::as_const(sortedStateList))
{
const uint8_t siVulnId = static_cast<uint8_t>(si.vulnerabilityState);
if (debug)
{
qWarning() << "MWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMW";
qWarning() << ">>>> si" << "siVulnId" << siVulnId;
}
// we're only interested in 'visible' VBGs, don't care about near miss etc. here
if (bSkipVbgGreaterCatastrophicKill && si.vulnerabilityState > ProjectDataManagement::VulnerabilityState::VulnerabilityState_CatastrophicKill)
{
if (debug)
qWarning() << ">>>> vulnId is higher than CK!";
continue;
}
if (bSkipSanitation && si.originatorType == ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_Sanitation)
{
if (debug)
qWarning() << ">>>> is sanitation!";
continue;
}
if (debug)
qWarning() << ">>>> match! done!";
return si;
}
if (debug)
qWarning() << ">> no state found" << "bSkipVbgGreaterCatastrophicKill" << bSkipVbgGreaterCatastrophicKill << "bSkipSanitation" << bSkipSanitation;
return ret;
}
StateInformation youngestRealStateInformation(const std::vector<ParticipantManagement::StateInformation> &stateList,
bool bSkipVbgGreaterCatastrophicKill)
{
if (stateList.size() == 0)
{
ParticipantManagement::StateInformation ret;
ret.vulnerabilityState = ProjectDataManagement::VulnerabilityState::VulnerabilityState_NotReady;
return ret;
}
StateInformation youngestState = youngestStateInformation(stateList);
size_t youngest = 0;
for (size_t i = 1; i < stateList.size(); ++i)
{
const auto &tCurrent = stateList.at(i).stateTime;
const auto &tYoungest = stateList.at(youngest).stateTime;
// we're only interested in 'visible' VBGs, don't care about near miss etc. here
if (bSkipVbgGreaterCatastrophicKill && stateList.at(i).vulnerabilityState > ProjectDataManagement::VulnerabilityState::VulnerabilityState_CatastrophicKill)
continue;
if (stateList.at(i).originatorType == ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_Sanitation ||
stateList.at(i).originatorType == ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_MedicalTimeout)
continue;
if (tCurrent > youngestState.stateTime)
continue;
bool higherState = (stateList.at(i).vulnerabilityState > stateList.at(youngest).vulnerabilityState ) ||
(stateList.at(i).vulnerabilityState == stateList.at(youngest).vulnerabilityState && (stateList.at(i).vitality < stateList.at(youngest).vitality));
if ((tCurrent > tYoungest && (stateList.at(i).originatorType == ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_ObserverController || stateList.at(i).originatorType == ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_ExerciseControl)) ||
(tCurrent > tYoungest && higherState) ||
(tCurrent == tYoungest && higherState))
youngest = i;
}
if (youngest == 0)
return youngestState;
return stateList.at(youngest);
}
ParticipantManagement::SanitationResult proceduresDone(const std::vector<StateInformation> &stateList)
{
// Empty List or 1 Entry ("CombatReady"): No Effect
if (stateList.size() <= 1)
return SanitationResult::NoEffect;
// If that guy is killed: NoEffect
StateInformation youngestReal = youngestRealStateInformation(stateList);
if (youngestReal.vulnerabilityState == ProjectDataManagement::VulnerabilityState::VulnerabilityState_CatastrophicKill)
return SanitationResult::NoEffect;
SanitationResult ret = SanitationResult::Unhandled;
for (size_t i = 1; i < stateList.size(); ++i)
{
// Better than "Unhandled" can only occur if this is done by Sanitation or O/C
if (stateList.at(i).originatorType != ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_Sanitation
&& stateList.at(i).originatorType != ProjectDataManagement::StateChangeOriginator::StateChangeOriginator_ObserverController )
continue;
// Let's find the newest
if (stateList.at(i).stateTime < youngestReal.stateTime)
continue;
//
if (ret == SanitationResult::Unhandled ) //we have a sanitation so at least 1
ret = stateList.at(i).sanitationResult;
if (stateList.at(i).sanitationResult == SanitationResult::Sufficient && ret != SanitationResult::Optimal )
ret = SanitationResult::Sufficient;
if (stateList.at(i).sanitationResult == SanitationResult::Optimal)
ret = SanitationResult::Optimal;
}
return ret;
}
} // namespace ParticipantManagement