new_docker_build.sh gains Group 12 (212 GUI/Data plugins); fixes LtsUtilsGuiDds visibility (LTO-stripped exports), LtsProjectionWorkstation unity name shadow, 6 unity-off dirs (dup file-scope statics, ddsftc INTERFACE sources) and reconfigures BUILD_FILTERMANAGEMENT/BUILD_PLUGINS_SERVICEMONITOR=ON
145 lines
4.3 KiB
C++
Executable File
145 lines
4.3 KiB
C++
Executable File
|
|
|
|
|
|
#include "positions_cnr.h"
|
|
#include <utility>
|
|
#include "exercise_manager.h"
|
|
#include "helper.h"
|
|
#include <AudioVideoManagement/avm_dtc.h>
|
|
#include <ParticipantManagement/ppm.hpp>
|
|
#include <ParticipantManagement/ppm_dtc.h>
|
|
#include <LtsUtils/LtsUtilsCore/outdated_position.h>
|
|
#include <QtGlobal>
|
|
#include <QtCore/QDateTime>
|
|
#include <QtCore/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;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
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.has_value();
|
|
Q_ASSERT(isGlobal);
|
|
return positionsForLocal(config);
|
|
}
|
|
|
|
QVector<WebSocketInterface::Messages::ReplyMessage::LonLatPoint> PositionsCnr::positionsFor(const AudioVideoManagement::CnrConfig &config) const
|
|
{
|
|
bool isLocal = config.exerciseId.has_value();
|
|
if (isLocal)
|
|
return positionsForLocal(config);
|
|
else
|
|
return m_exerciseManager->positionsForGlobal(config);
|
|
}
|
|
|
|
|
|
|
|
QVector<WebSocketInterface::Messages::ReplyMessage::LonLatPoint> PositionsCnr::positionsForLocal(const AudioVideoManagement::CnrConfig &config) const
|
|
{
|
|
auto allParticipants = m_ppmDtc->participants();
|
|
|
|
QSet<int> participantIdsInUnit;
|
|
if (config.unitId.has_value())
|
|
m_ppmDtc->participantIdsByUnit(config.unitId.get(), allParticipants, participantIdsInUnit);
|
|
else
|
|
{
|
|
bool isGlobal = !config.exerciseId.has_value();
|
|
participantIdsInUnit = participantIdsFromParty(allParticipants, config.partyId, isGlobal);
|
|
}
|
|
|
|
const qint64 now = QDateTime::currentMSecsSinceEpoch();
|
|
|
|
QVector<WebSocketInterface::Messages::ReplyMessage::LonLatPoint> positions;
|
|
for (int participantId : std::as_const(participantIdsInUnit))
|
|
{
|
|
const ParticipantManagement::Participant &participant = allParticipants.value(participantId);
|
|
if (!participant.equipmentNumber.has_value())
|
|
continue;
|
|
|
|
const ParticipantManagement::Type &type = m_ppmDtc->type(participant.typeId);
|
|
if (type.radioCount < 1)
|
|
continue;
|
|
|
|
const auto &pos = m_ppmDtc->participantPosition(participantId);
|
|
if (pos.participantId != participantId)
|
|
continue;
|
|
|
|
if (LtsUtils::isPositionTimeOutdated(now, pos.sampleTime))
|
|
continue;
|
|
|
|
WebSocketInterface::Messages::ReplyMessage::LonLatPoint point;
|
|
point.lon = toDeg(pos.pos.lon);
|
|
point.lat = toDeg(pos.pos.lat);
|
|
positions.push_back(point);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
}
|