198 lines
7.6 KiB
C++
Executable File
198 lines
7.6 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* Custom ppm functions (extends tab_db_impl.cpp/.h)
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
*/
|
|
|
|
#include "ppm_common.h"
|
|
|
|
#include <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;
|
|
ret.vulnerabilityState(ProjectDataManagement::VulnerabilityState::NotReady);
|
|
|
|
if (stateList.empty())
|
|
{
|
|
if (debug)
|
|
qWarning() << ">> stateList empty! not ready";
|
|
return ret;
|
|
}
|
|
|
|
// bool readyToDebug = false;
|
|
// for (const ParticipantManagement::StateInformation &si : qAsConst(stateList))
|
|
// {
|
|
// if (si.originatorId() == 0
|
|
// && si.originatorType() == ProjectDataManagement::StateChangeOriginator_def::ExerciseControl
|
|
// && (si.vulnerabilityState() == ProjectDataManagement::VulnerabilityState_def::CatastrophicKill
|
|
// || si.vulnerabilityState() == ProjectDataManagement::VulnerabilityState_def::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 : qAsConst(sortedStateList))
|
|
qWarning() << ">>>> si" << "siVulnId" << (uint8_t)si.vulnerabilityState().underlying() << "bits" << si.vulnerabilityBits() << "time" << si.stateTime();
|
|
|
|
qWarning() << ">> checking SIs";
|
|
}
|
|
|
|
|
|
for (const ParticipantManagement::StateInformation &si : qAsConst(sortedStateList))
|
|
{
|
|
const uint8_t siVulnId = si.vulnerabilityState().underlying();
|
|
|
|
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::CatastrophicKill)
|
|
{
|
|
if (debug)
|
|
qWarning() << ">>>> vulnId is higher than CK!";
|
|
continue;
|
|
}
|
|
|
|
if (bSkipSanitation && si.originatorType() == ProjectDataManagement::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::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::CatastrophicKill)
|
|
continue;
|
|
if (stateList.at(i).originatorType() == ProjectDataManagement::StateChangeOriginator::Sanitation ||
|
|
stateList.at(i).originatorType() == ProjectDataManagement::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::ObserverController || stateList.at(i).originatorType() == ProjectDataManagement::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::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::Sanitation
|
|
&& stateList.at(i).originatorType() != ProjectDataManagement::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
|
|
|