147 lines
4.5 KiB
C++
Executable File
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
|