/** * @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 #include #include #include #include #include namespace { QSet participantIdsFromParty(const QMap &participants, int partyId, bool isGlobal) { QSet 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 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 PositionsCnr::positionsForGlobal(const AudioVideoManagement::CnrConfig &config) const { bool isGlobal = !config.exerciseId().is_set(); Q_ASSERT(isGlobal); return positionsForLocal(config); } QVector 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 PositionsCnr::positionsForLocal(const AudioVideoManagement::CnrConfig &config) const { auto allParticipants = m_ppmDtc->participants(); QSet 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 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 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