Files
qt5-legatus-legacy/Lts/Proxies/CombatNetRadio/positions_cnr.cpp
T
2026-08-13 18:33:10 +02:00

147 lines
4.5 KiB
C++
Executable File

/**
* @RDE_HEADER@
* PositionsCnr
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Fröbel, NLE, 2019-08-05
*/
#include "positions_cnr.h"
#include "exercise_manager.h"
#include "helper.h"
#include <AudioVideoManagement/avm_dtc.h>
#include <ParticipantManagement/ppm_dtc.h>
#include <LtsUtilsCore/outdated_position.h>
#include <QtGlobal>
#include <QDateTime>
#include <QSet>
namespace
{
QSet<int> participantIdsFromParty(const QMap<int32_t, ParticipantManagement::Participant> &participants, int partyId, bool isGlobal)
{
QSet<int> ret;
if (isGlobal)
{
ret.reserve(participants.size());
for (const auto &p : participants)
ret += p.id();
}
else
{
for (const auto &participant : participants)
if (participant.partyId() == partyId)
ret += participant.id();
}
return ret;
}
} // anonymous namespace
namespace CombatNetRadio
{
PositionsCnr::PositionsCnr(int exerciseId, ExerciseManager *exerciseManager, ParticipantManagement::Interface::Dtc *ppmDtc, AudioVideoManagement::Interface::Dtc *avmDtc)
: m_exerciseId(exerciseId)
, m_exerciseManager(exerciseManager)
, m_ppmDtc(ppmDtc)
, m_avmDtc(avmDtc)
{
Q_ASSERT(exerciseId > 0);
Q_ASSERT(exerciseManager);
Q_ASSERT(ppmDtc);
Q_ASSERT(avmDtc);
}
WebSocketInterface::Messages::PositionsCnrMessage::PositionsCnrMessageData PositionsCnr::data() const
{
WebSocketInterface::Messages::PositionsCnrMessage::PositionsCnrMessageData positionsData;
positionsData.time = QDateTime::currentDateTime().toString(Qt::ISODate);
boost::optional<AudioVideoManagement::FrequencyPlanning> plan = activePlan();
if (!plan)
return positionsData;
for (const auto &entry : plan->data())
{
AudioVideoManagement::CnrConfig cnrConfig = m_avmDtc->cnrConfig(entry.cnrConfigId());
AudioVideoManagement::CnrChannel cnrChannel = m_avmDtc->cnrChannel(cnrConfig.cnrChannelId());
positionsData.radioCircuit.push_back({toRcIdString(cnrChannel), positionsFor(cnrConfig)});
}
return positionsData;
}
QVector<WebSocketInterface::Messages::ReplyMessage::LonLatPoint> PositionsCnr::positionsForGlobal(const AudioVideoManagement::CnrConfig &config) const
{
bool isGlobal = !config.exerciseId().is_set();
Q_ASSERT(isGlobal);
return positionsForLocal(config);
}
QVector<WebSocketInterface::Messages::ReplyMessage::LonLatPoint> PositionsCnr::positionsFor(const AudioVideoManagement::CnrConfig &config) const
{
bool isLocal = config.exerciseId().is_set();
if (isLocal)
return positionsForLocal(config);
else
return m_exerciseManager->positionsForGlobal(config);
}
/**
* Can be called for a global config, too. But then only positions for Participants of this Exercise will be returned.
*/
QVector<WebSocketInterface::Messages::ReplyMessage::LonLatPoint> PositionsCnr::positionsForLocal(const AudioVideoManagement::CnrConfig &config) const
{
auto allParticipants = m_ppmDtc->participants();
QSet<int> participantIdsInUnit;
if (config.unitId().is_set())
m_ppmDtc->participantIdsByUnit(config.unitId().get(), allParticipants, participantIdsInUnit);
else
{
bool isGlobal = !config.exerciseId().is_set();
participantIdsInUnit = participantIdsFromParty(allParticipants, config.partyId(), isGlobal);
}
const qint64 now = QDateTime::currentMSecsSinceEpoch();
QVector<WebSocketInterface::Messages::ReplyMessage::LonLatPoint> positions;
for (int participantId : qAsConst(participantIdsInUnit))
{
const ParticipantManagement::Participant &participant = allParticipants.value(participantId);
if (!participant.equipmentNumber().is_set())
continue;
const ParticipantManagement::Type &type = m_ppmDtc->type(participant.typeId());
if (type.radioCount() < 1)
continue; // participant has no radio equipped
const auto &pos = m_ppmDtc->participantPosition(participantId);
if (pos.participantId() != participantId)
continue; // participant has no position
if (LtsUtils::isPositionTimeOutdated(now, pos.sampleTime()))
continue; // position invalid
positions.push_back({toDeg(pos.pos().lon()), toDeg(pos.pos().lat())});
}
return positions;
}
boost::optional<AudioVideoManagement::FrequencyPlanning> PositionsCnr::activePlan() const
{
AudioVideoManagement::ActiveFrequencyPlanning activePlanning = m_avmDtc->activeFrequencyPlanning(m_exerciseId);
if (activePlanning.exerciseId() != m_exerciseId)
return boost::none;
return m_avmDtc->frequencyPlanning(activePlanning.frequencyPlanningId());
}
} // namespace CombatNetRadio