523 lines
18 KiB
C++
Executable File
523 lines
18 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* HMI Plugin for EffectShowManagement - Effect Show Overview Dialog Model
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Patric Karwat, SLSE, 2016-10.05
|
|
*/
|
|
|
|
#include "esm_effect_show_model.h"
|
|
#include "esm_effect_show_actor_model.h"
|
|
#include "esm_effect_show_actor_relocation_model.h"
|
|
#include <EffectShowManagement/esm_translation.h>
|
|
#include <AreaEffectSimulation/aes_translation.h>
|
|
#include <ParticipantManagement/ppm_data_plugin_interface.h>
|
|
#include <EffectShowManagement/esm_data_plugin_interface.h>
|
|
#include <AreaEffectSimulation/aes_data_plugin_interface.h>
|
|
#include <LtsCoordTrans/lts_coord_trans.h>
|
|
#include <LtsSession/lts_session.h>
|
|
#include <ngltools/ngltools_dtg.h>
|
|
|
|
namespace EffectShowManagement
|
|
{
|
|
//---------------------------------
|
|
// Effect Show Model
|
|
//---------------------------------
|
|
EffectShowModel::EffectShowModel(QObject *parent)
|
|
: LtsWidgets::LtsAbstractTableModel<EffectShowManagement::EffectShow>(
|
|
{
|
|
tr("Name AES"),
|
|
tr("Id"),
|
|
tr("Fire"),
|
|
tr("Duration"),
|
|
tr("Position"),
|
|
tr("AesStatus"),
|
|
tr("Actor"),
|
|
tr("Volley"),
|
|
tr("Shots in total"),
|
|
tr("Dimension [m]"),
|
|
tr("Rotation"),
|
|
tr("Status"),
|
|
tr("Answer")
|
|
},
|
|
parent)
|
|
, m_dtc(nullptr)
|
|
, m_effectShowActorProxyModel(nullptr)
|
|
, m_effectShowActorModel(nullptr)
|
|
, m_effectShowActorRelocationModel(nullptr)
|
|
, m_logger(getLogger("EffectShowModel"))
|
|
{}
|
|
|
|
EffectShowModel::~EffectShowModel()
|
|
{
|
|
delete m_effectShowActorProxyModel;
|
|
delete m_effectShowActorModel;
|
|
delete m_effectShowActorRelocationModel;
|
|
}
|
|
|
|
|
|
bool EffectShowModel::initModel(LtsSession::LtsSession *session)
|
|
{
|
|
if (!session->getDtc<EffectShowManagement::DataInterface>(m_dtc))
|
|
return false;
|
|
if (!session->getDtc<ParticipantManagement::DataInterface>(m_dtcPpm))
|
|
return false;
|
|
if (!session->getDtc<AreaEffectSimulation::DataInterface>(m_dtcAes))
|
|
return false;
|
|
|
|
connect(m_dtc.get(), &EffectShowManagement::Interface::Dtc::effectShowChanged,
|
|
this, &EffectShowModel::onDataChanged);
|
|
connect(m_dtc.get(), &EffectShowManagement::Interface::Dtc::effectShowVehicleStatusChanged,
|
|
this, &EffectShowModel::onEffectShowVehicleStatusChanged);
|
|
|
|
|
|
// insert Model
|
|
m_dtc->effectShows([this](const EffectShowManagement::EffectShow & effectShow) { insertRow(effectShow); });
|
|
m_effectShowVehicleStatus = m_dtc->effectShowVehicleStatuss();
|
|
|
|
m_effectShowActorModel = new EffectShowActorModel(this, this);
|
|
m_effectShowActorProxyModel = new EffectShowActorProxyModel(m_effectShowActorModel, this, this);
|
|
m_effectShowActorModel->initModel(session);
|
|
|
|
m_effectShowActorRelocationModel = new EffectShowActorRelocationModel(this, this);
|
|
m_effectShowActorRelocationModel->initModel(m_dtc);
|
|
|
|
m_dtc->effectShowVehicleStatuss([this](const EffectShowManagement::EffectShowVehicleStatus &item) { onEffectShowVehicleStatusChanged(item, DataModification::eAdded);});
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
QVariant EffectShowModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
if (role != Qt::DisplayRole || !indexIsValid(index))
|
|
return QVariant();
|
|
|
|
const EffectShowManagement::EffectShow &effectShow = m_vecData.at(index.row());
|
|
AreaEffectSimulation::AesItem aesItem;
|
|
m_dtcAes->aesItemFromId(effectShow.idAreaEffectSimulation(), aesItem);
|
|
|
|
switch (index.column())
|
|
{
|
|
case Id:
|
|
return effectShow.id();
|
|
case Name_AES:
|
|
return QString::fromStdString(effectShow.nameAreaEffectSimulation());
|
|
case Duration:
|
|
return LtsWidgets::readableDuration(effectShow.duration());;
|
|
case StartTime:
|
|
return effectShow.startTime().is_set() ? DTG::toStringMSec(effectShow.startTime().get()) : QStringLiteral("---");
|
|
case Position:
|
|
{
|
|
const Core::GeoPosition2D &pos = effectShow.position();
|
|
return LtsCoordTrans::mgrsFromGeographic(pos.lon(), pos.lat());
|
|
}
|
|
case EffectShowActor:
|
|
{
|
|
int id = effectShow.esmParticipantId();
|
|
return (id > 0) ? getParticipantName(id) : QStringLiteral("---");
|
|
}
|
|
case Volley:
|
|
{
|
|
if (effectShow.typeOfAmmunition() == 5) //smoke
|
|
return QStringLiteral("--");
|
|
else
|
|
return effectShow.numOfVolley();
|
|
}
|
|
case ShotsInTotal:
|
|
{
|
|
if (effectShow.typeOfAmmunition() == 5) //smoke
|
|
return QStringLiteral("--");
|
|
else
|
|
return effectShow.shotsPerVolley();
|
|
}
|
|
case Size:
|
|
return tr("%1 x %2").arg(QString::number(effectShow.areaWidth()), QString::number(effectShow.areaDepth()));
|
|
case Rotation:
|
|
return effectShow.areaRotation();
|
|
case Status:
|
|
return EffectShowManagement::toString(effectShow.orderConfirmation());
|
|
case Answer:
|
|
return QString::fromStdString(effectShow.answerText());
|
|
case AesStatus:
|
|
return AreaEffectSimulation::toString(aesItem.effectStateId());
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
QMap<int, QString> EffectShowModel::getParticipantList() const
|
|
{
|
|
QMap<int, QString> ret;
|
|
int numRow = m_effectShowActorProxyModel->rowCount(QModelIndex());
|
|
|
|
for (int i = 0; i < numRow; ++i)
|
|
{
|
|
const ParticipantManagement::Participant part = m_effectShowActorModel->getRowData(m_effectShowActorProxyModel->mapToSource(m_effectShowActorProxyModel->index(i, 0)).row());
|
|
if (hasVehicleReportedOperationalToday(part.equipmentNumber().get()))
|
|
ret.insert(part.id(), getParticipantName(part.id()));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
QMap<int, QString> EffectShowModel::getParticipantList(bool is_smoke) const
|
|
{
|
|
QMap<int, QString> ret;
|
|
int numRow = m_effectShowActorProxyModel->rowCount(QModelIndex());
|
|
|
|
for (int i = 0; i < numRow; ++i)
|
|
{
|
|
int realRow = m_effectShowActorProxyModel->mapToSource(m_effectShowActorProxyModel->index(i, 0)).row();
|
|
const ParticipantManagement::Participant part = m_effectShowActorModel->getRowData(realRow);
|
|
|
|
if (!hasVehicleReportedOperationalToday(part.equipmentNumber().get()))
|
|
continue;
|
|
|
|
EffectShowManagement::Feature_e feature = m_effectShowActorModel->getFeature(realRow);
|
|
if (feature != EffectShowManagement::Feature_e_def::NotSpecified &&
|
|
(
|
|
(feature == EffectShowManagement::Feature_e_def::Smoke && is_smoke) ||
|
|
(feature != EffectShowManagement::Feature_e_def::Smoke && !is_smoke)
|
|
)
|
|
)
|
|
ret.insert(part.id(), getParticipantName(part.id()));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
QVector<QPair<int, QString>> EffectShowModel::getParticipantListByDistance(bool is_smoke, const Core::GeoPosition2D &origin)
|
|
{
|
|
QVector<QPair<int, QString>> ret;
|
|
|
|
//first get the list of all pariticpants and it's name
|
|
QMap<int, QString> participantList = getParticipantList(is_smoke);
|
|
//reserve
|
|
ret.reserve(participantList.size());
|
|
|
|
QMap<double, int> distanceMapSorted;
|
|
for (const auto partId : participantList.keys())
|
|
{
|
|
|
|
int eqNr = m_dtcPpm->equipmentNumberByParticipantId(partId);
|
|
if (eqNr <= 0)
|
|
continue;
|
|
EffectShowManagement::EffectShowVehicleStatus vehicleStatus;
|
|
bool isVehicleStatus = getVehicleStatus(eqNr, vehicleStatus);
|
|
if (!isVehicleStatus)
|
|
continue;
|
|
const ParticipantManagement::ParticipantPosition &pos = m_dtcPpm->participantPosition(partId);
|
|
|
|
//Get Distance to Effect Show (center?)
|
|
LtsCoordTrans::UtmCoordinate pPos = LtsCoordTrans::UtmCoordinate::fromGeographic(pos.pos().lon(), pos.pos().lat());
|
|
LtsCoordTrans::UtmCoordinate pOrigin = LtsCoordTrans::UtmCoordinate::fromGeographic(origin.lon(), origin.lat());
|
|
|
|
double distance = LtsCoordTrans::distance(pPos, pOrigin);
|
|
// Save distance and particiapnt Id into temporar map.
|
|
// the map is sorted so we can use that later instead of writing a sort method vor a vec
|
|
// for now
|
|
distanceMapSorted.insert(distance, partId);
|
|
|
|
//get already assigned effect shows
|
|
QString currentAssigendEffectShows;
|
|
for (const auto &dat : m_vecData)
|
|
{
|
|
if (dat.esmParticipantId() == partId)
|
|
{
|
|
if (!currentAssigendEffectShows.isEmpty())
|
|
currentAssigendEffectShows.append(QStringLiteral(", "));
|
|
currentAssigendEffectShows.append(QString::fromStdString(dat.nameAreaEffectSimulation()));
|
|
}
|
|
}
|
|
|
|
//Now we create the new Info String
|
|
// they want
|
|
// the Name
|
|
// Available pyrotechnics/smoke pots (and current load?)
|
|
// Distance to Target Area
|
|
// already
|
|
QString newString = participantList.value(partId);
|
|
newString.append(QStringLiteral(" "));
|
|
newString.append(tr("Mag: %1 | Avail: %2").arg(vehicleStatus.ammunitionMagazine()).arg(vehicleStatus.ammunitionAvailable()));
|
|
newString.append(tr(" | Dist: %1[m]").arg(QString::number(int(distance))));
|
|
if (!currentAssigendEffectShows.isEmpty())
|
|
newString.append(tr(" | Assigned: %1").arg(currentAssigendEffectShows));
|
|
// Update the String from the original list
|
|
participantList.insert(partId, newString);
|
|
}
|
|
|
|
QMapIterator<double, int> it(distanceMapSorted);
|
|
while(it.hasNext())
|
|
{
|
|
it.next();
|
|
ret.append(QPair<int, QString>(it.value(), participantList.value(it.value())));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
QString EffectShowModel::getParticipantName(int id) const
|
|
{
|
|
auto it = m_effectShowActorModel->getIt(id);
|
|
if (it == m_effectShowActorModel->getItEnd()) return QString();
|
|
QString eqNumber = QStringLiteral("-");
|
|
if (it->equipmentNumber().is_set())
|
|
eqNumber = QString::number(it->equipmentNumber().get());
|
|
return QStringLiteral("%1 - %2 (%3)").arg(QString::fromStdString(it->designator())).arg(QString::fromStdString(it->tacticalIdentifier())).arg(eqNumber);
|
|
}
|
|
|
|
QString EffectShowModel::getParticipantAmmunition(int id) const
|
|
{
|
|
auto it = m_effectShowActorModel->getIt(id);
|
|
if (it == m_effectShowActorModel->getItEnd()) return QString();
|
|
|
|
EffectShowManagement::EffectShowVehicleStatus vehicleStatus;
|
|
if (!getVehicleStatus(it->equipmentNumber().get(), vehicleStatus)) return QString();
|
|
|
|
QString res = QString::number(vehicleStatus.ammunitionMagazine());
|
|
res.append(QLatin1String(" / "));
|
|
res.append(QString::number(vehicleStatus.ammunitionAvailable()));
|
|
return res;
|
|
}
|
|
|
|
|
|
bool EffectShowModel::isVehicleStatus(int equipmentNum) const
|
|
{
|
|
auto it = m_effectShowVehicleStatus.find(equipmentNum);
|
|
return (it != m_effectShowVehicleStatus.end());
|
|
}
|
|
|
|
bool EffectShowModel::getVehicleStatus(int equipmentNum, EffectShowManagement::EffectShowVehicleStatus &vehicleStatus) const
|
|
{
|
|
auto it = m_effectShowVehicleStatus.find(equipmentNum);
|
|
if (it == m_effectShowVehicleStatus.end())
|
|
return false;
|
|
|
|
vehicleStatus = it.value();
|
|
return true;
|
|
}
|
|
|
|
bool EffectShowModel::hasVehicleReportedOperationalToday(int equipmentNum) const
|
|
{
|
|
EffectShowVehicleStatus vehicleStatus;
|
|
getVehicleStatus(equipmentNum, vehicleStatus);
|
|
|
|
// vehicle is operational ...................................................................................................
|
|
if (vehicleStatus.operational())
|
|
{
|
|
DEBUG_LOG(m_logger) << "Effect show actor " << vehicleStatus.nameEffectShowActor() << " with participantId "
|
|
<< vehicleStatus.esmParticipantId() << " is operational.";
|
|
return true;
|
|
} // if
|
|
|
|
// vehicle has never reported as operational ................................................................................
|
|
if (!m_effectShowVehicleLastTimeOperational.contains(equipmentNum))
|
|
{
|
|
DEBUG_LOG(m_logger) << "Effect show actor " << vehicleStatus.nameEffectShowActor() << " with participantId "
|
|
<< vehicleStatus.esmParticipantId() << " has not reported operational at any time.";
|
|
return false;
|
|
} // if
|
|
|
|
// check last time vehicle reported as operational ..........................................................................
|
|
bool bRet = QDateTime().addMSecs(m_effectShowVehicleLastTimeOperational[equipmentNum]).date() == QDate::currentDate();
|
|
if (bRet)
|
|
DEBUG_LOG(m_logger) << "Effect show actor " << vehicleStatus.nameEffectShowActor() << " with participantId "
|
|
<< vehicleStatus.esmParticipantId() << " is not operational, but has reported operational today.";
|
|
else
|
|
DEBUG_LOG(m_logger) << "Effect show actor " << vehicleStatus.nameEffectShowActor() << " with participantId "
|
|
<< vehicleStatus.esmParticipantId() << " is not operational and has not reported operational today.";
|
|
return bRet;
|
|
}
|
|
|
|
QString EffectShowModel::getTimeAndPositionOfNextEffectShow(int idParticipant) const
|
|
{
|
|
auto it = m_vecData.begin();
|
|
if (it == m_vecData.end())
|
|
return QString();
|
|
|
|
qint64 effectStart = 0;
|
|
int numOrder = 0;
|
|
Core::GeoPosition2D position;
|
|
while (it != m_vecData.end())
|
|
{
|
|
if (it->orderConfirmation() != OrderConfirmation_e::OrderCarriedOut &&
|
|
it->esmParticipantId() == idParticipant)
|
|
{
|
|
++numOrder;
|
|
qint64 start = it->startTime().is_set() ? it->startTime().get() : 0;
|
|
|
|
if (effectStart == 0)
|
|
{
|
|
effectStart = start;
|
|
position = it->position();
|
|
}
|
|
else if (start < effectStart)
|
|
{
|
|
effectStart = start;
|
|
position = it->position();
|
|
}
|
|
}
|
|
++it;
|
|
}
|
|
if ((numOrder == 0) || ((numOrder > 1) && (effectStart == 0)))
|
|
return QString(); // no order, or all order without start time
|
|
|
|
QString res;
|
|
res = (effectStart != 0) ? DTG::toStringMSec(effectStart) : tr("---");
|
|
|
|
res += QLatin1String(", ");
|
|
res += LtsCoordTrans::mgrsFromGeographic(position.lon(), position.lat());
|
|
|
|
return res;
|
|
}
|
|
|
|
QString EffectShowModel::getTimeAndPositionOfNextActorRelocation(int idParticipant) const
|
|
{
|
|
auto it = m_effectShowActorRelocationModel->getItBegin();
|
|
if (it == m_effectShowActorRelocationModel->getItEnd())
|
|
return QString();
|
|
|
|
qint64 arrivalTime = std::numeric_limits<qint64>::max();
|
|
Core::GeoPosition2D position;
|
|
bool found = false;
|
|
|
|
while (it != m_effectShowActorRelocationModel->getItEnd())
|
|
{
|
|
if (it->orderConfirmation() != OrderConfirmation_e::OrderCarriedOut &&
|
|
it->orderConfirmation() != OrderConfirmation_e::PositionReached &&
|
|
it->orderConfirmation() != OrderConfirmation_e::Abort &&
|
|
it->orderConfirmation() != OrderConfirmation_e::Nonacceptance &&
|
|
it->esmParticipantId() == idParticipant)
|
|
{
|
|
if (it->arrival_time().get() < arrivalTime)
|
|
{
|
|
arrivalTime = it->arrival_time().get();
|
|
position = it->position();
|
|
found = true;
|
|
}
|
|
}
|
|
++it;
|
|
}
|
|
|
|
if (!found)
|
|
return QString();
|
|
|
|
QString res;
|
|
res = (arrivalTime != 0) ? DTG::toStringMSec(arrivalTime) : tr("---");
|
|
|
|
res += QLatin1String(", ");
|
|
res += LtsCoordTrans::mgrsFromGeographic(position.lon(), position.lat());
|
|
|
|
return res;
|
|
}
|
|
|
|
void EffectShowModel::updateAll()
|
|
{
|
|
this->update();
|
|
m_effectShowActorModel->update();
|
|
m_effectShowActorRelocationModel->update();
|
|
}
|
|
|
|
bool EffectShowModel::onEffectShowVehicleStatusChanged(const EffectShowManagement::EffectShowVehicleStatus &data, DataModification modType)
|
|
{
|
|
int equipmentNumber = m_dtcPpm->equipmentNumberByParticipantId(data.esmParticipantId());
|
|
|
|
switch (modType)
|
|
{
|
|
case DataModification::eAdded:
|
|
case DataModification::eModified:
|
|
if (m_effectShowVehicleStatus.contains(equipmentNumber))
|
|
{
|
|
if (m_effectShowVehicleStatus[equipmentNumber].operational() && !data.operational())
|
|
m_effectShowVehicleLastTimeOperational[equipmentNumber] = data.sampleTime();
|
|
} // if
|
|
else
|
|
m_effectShowVehicleLastTimeOperational[equipmentNumber] = 0;
|
|
m_effectShowVehicleStatus[equipmentNumber] = data;
|
|
break;
|
|
|
|
case DataModification::eRemoved:
|
|
m_effectShowVehicleStatus.remove(equipmentNumber);
|
|
m_effectShowVehicleLastTimeOperational.remove(equipmentNumber);
|
|
break;
|
|
}
|
|
|
|
updateAll();
|
|
emit effectShowVehicleStatusChanged(data, modType);
|
|
return true;
|
|
}
|
|
|
|
void EffectShowProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
|
|
{
|
|
m_sourceModel = qobject_cast<EffectShowModel *>(sourceModel);
|
|
LtsWidgets::LtsColumnFilterProxyModel::setSourceModel(sourceModel);
|
|
}
|
|
|
|
void EffectShowProxyModel::setShowExpired(bool show)
|
|
{
|
|
if (m_showExpired == show)
|
|
return;
|
|
|
|
m_showExpired = show;
|
|
invalidateFilter();
|
|
}
|
|
|
|
bool EffectShowProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
|
|
{
|
|
if (!m_sourceModel ||
|
|
source_left.column() != source_right.column() ||
|
|
!source_left.isValid() ||
|
|
!source_right.isValid())
|
|
return LtsWidgets::LtsColumnFilterProxyModel::lessThan(source_left, source_right);
|
|
const auto &dataLeft = m_sourceModel->m_vecData.at(source_left.row());
|
|
const auto dataRight = m_sourceModel->m_vecData.at(source_right.row());
|
|
switch (source_left.column())
|
|
{
|
|
case EffectShowModel::StartTime:
|
|
if (dataLeft.startTime().is_set() && dataRight.startTime().is_set())
|
|
return dataLeft.startTime().get() < dataRight.startTime().get();
|
|
if (dataRight.startTime().is_set())
|
|
return true;
|
|
if (dataLeft.startTime().is_set())
|
|
return false;
|
|
return dataLeft.id() < dataRight.id();
|
|
|
|
case EffectShowModel::Name_AES:
|
|
case EffectShowModel::Id:
|
|
case EffectShowModel::Duration:
|
|
case EffectShowModel::Position:
|
|
case EffectShowModel::EffectShowActor:
|
|
case EffectShowModel::Volley:
|
|
case EffectShowModel::ShotsInTotal:
|
|
case EffectShowModel::Status:
|
|
case EffectShowModel::Answer:
|
|
break;
|
|
}
|
|
return LtsWidgets::LtsColumnFilterProxyModel::lessThan(source_left, source_right);
|
|
}
|
|
|
|
bool EffectShowProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
|
{
|
|
bool bRet = checkFilter(source_row);
|
|
if (!bRet)
|
|
return false;
|
|
return LtsWidgets::LtsColumnFilterProxyModel::filterAcceptsRow(source_row, source_parent);
|
|
}
|
|
|
|
bool EffectShowProxyModel::checkFilter(int source_row) const
|
|
{
|
|
|
|
// If showExpired: Show all
|
|
if (showExpired())
|
|
return true;
|
|
|
|
const auto effectShowSource = m_sourceModel->getRowData(source_row);
|
|
|
|
// show when not expired
|
|
if (effectShowSource.orderConfirmation() != EffectShowManagement::OrderConfirmation_e_def::OrderCarriedOut)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
} // namespace EffectShowModel
|