Files
qt5-legatus-legacy/Lts/Services/AreaEffectSimulation/object_charge_effect.cpp
T
2026-08-13 18:33:10 +02:00

379 lines
12 KiB
C++
Executable File

#include "object_charge_effect.h"
#include "object_base.h"
#include <QDateTime>
#include <QTimer>
#include "main_handler.h"
namespace AreaEffectSimulation
{
qint32 ObjectChargeEffect::s_afterglowMsecs = 0;
//-----------------------------------------------------------------------------
ObjectChargeEffect::ObjectChargeEffect(const Database::AesChargeEffect &data, MainHandler *mainHandler, QObject *parent)
: ObjectChargeEffect(mainHandler, parent)
{
m_data = data;
}
//-----------------------------------------------------------------------------
ObjectChargeEffect::ObjectChargeEffect(MainHandler *mainHandler, QObject *parent)
: QObject(parent)
, m_mainHandler(mainHandler)
, m_trajectoryId(-1)
, m_state(AesEffectState::inner_enum::EsUnknown)
, m_stateChanged(false)
, m_stateTimer(new QTimer(this))
, m_logger(getLogger(QStringLiteral("ObjectChargeEffect")))
{
m_stateTimer->setSingleShot(true);
connect(m_stateTimer, &QTimer::timeout, this, &ObjectChargeEffect::onStateTimerTimeout);
}
//-----------------------------------------------------------------------------
Core::FunctionReplyObject ObjectChargeEffect::create(const ChargeEffectModifyRequest &data)
{
Core::FunctionReplyObject reply(data.id());
Database::AesChargeEffect dbData = functionTopicToDatabase(data);
if (!m_mainHandler)
reply.setStr("Not possible to create ChargeEffect --> No MainHandler present.");
else if (data.effectStart() < QDateTime::currentMSecsSinceEpoch())
reply.setStr("Not possible to create ChargeEffect --> EffectStart has to be in the future.");
else if (data.effectDuration() < 1000)
reply.setStr("Not possible to create ChargeEffect --> EffectDuration must be at least 1000ms.");
else if (data.name().empty())
reply.setStr("Not possible to create ChargeEffect --> Name must not be empty.");
else if (!m_mainHandler->db()->insert(dbData))
reply.setStr("Not possible to create ChargeEffect --> Database insert failed.");
else
{
// everything is fine
m_data = dbData;
}
if (reply.error())
ERROR_LOG(m_logger) << reply.str();
if (reply.id() == 0)
reply.setId(m_data.id);
return reply;
}
//-----------------------------------------------------------------------------
Core::FunctionReplyObject ObjectChargeEffect::update(const ChargeEffectModifyRequest &data)
{
Core::FunctionReplyObject reply(data.id());
Database::AesChargeEffect dbData = functionTopicToDatabase(data);
if (!m_mainHandler)
reply.setStr("Not possible to update ChargeEffect --> No MainHandler present.");
else if (data.id() != m_data.id)
reply.setStr("Not possible to update ChargeEffect --> Id mismatch.");
else if (m_state != AesEffectState::inner_enum::EsPrepared)
{
// properties update is allowed!!!
if (dbData.properties != m_data.properties)
updatedProperties(dbData);
else
reply.setStr("Not possible to update ChargeEffect --> It is not allowed to make changes EsState doesn't allow it.");
}
else if (data.name().empty())
reply.setStr("Not possible to update ChargeEffect --> Name must not be empty.");
else if (!hasChanges(dbData))
reply.setStr("Not possible to update ChargeEffect --> There are no changes.");
else if (!m_mainHandler->db()->update(dbData))
reply.setStr("Not possible to update ChargeEffect --> Database update failed.");
else // everything is fine
{
m_data = dbData;
init();
}
if (reply.error())
ERROR_LOG(m_logger) << reply.str();
return reply;
}
/*!
* \brief ObjectChargeEffect::updateOnEsActivated
* This method is call to update some parameter of charge effect
* The effect state is not EsPrepared
* \param dbData
* \return
*/
void ObjectChargeEffect::updatedProperties(const Database::AesChargeEffect &dbData)
{
// update properties // "used": true/false
DEBUG_LOG(m_logger)<<" !!! update charge effect when not EsPrepared !!! ";
const QString tmpProps = m_data.properties;
m_data.properties = dbData.properties; // update properties is allowed!!
if (!m_mainHandler->db()->update(m_data))
{
m_data.properties = tmpProps;
ERROR_LOG(m_logger)<<" Couldn't update charge effect when not EsPrepared!!!";
}
}
//-----------------------------------------------------------------------------
bool ObjectChargeEffect::remove()
{
if (!m_mainHandler)
{
ERROR_LOG(m_logger) << "Not possible to remove ChargeEffect --> No MainHandler present.";
return false;
}
if (!m_mainHandler->dds()->dts()->removeChargeEffectByKey(m_data.id))
{
ERROR_LOG(m_logger) << "Not possible to remove ChargeEffect --> Could not remove from DDS.";
return false;
}
// TODO Remove trajectory
return true;
}
//-----------------------------------------------------------------------------
Database::AesChargeEffect ObjectChargeEffect::functionTopicToDatabase(const ChargeEffectModifyRequest &data)
{
Database::AesChargeEffect dbData;
dbData.id = data.id();
dbData.name = QString::fromStdString(data.name());
dbData.chargeTypeId = data.chargeTypeId();
dbData.igniterTypeId = data.igniterTypeId();
dbData.effectDuration = data.effectDuration();
dbData.effectStart = QDateTime::fromMSecsSinceEpoch(data.effectStart());
dbData.gearTypeId = data.gearTypeId();
dbData.originatorId = data.originatorId();
dbData.originatorTypeId = static_cast<int>(data.originatorTypeId().underlying());
dbData.position.setX(data.position().lon());
dbData.position.setY(data.position().lat());
dbData.position.setZ(data.position().z());
dbData.properties = QString::fromStdString(data.properties());
return dbData;
}
//-----------------------------------------------------------------------------
ChargeEffect ObjectChargeEffect::dataBaseToDataTopic(const Database::AesChargeEffect &data)
{
ChargeEffect dataTopic;
dataTopic.id(data.id);
dataTopic.name(data.name.toStdString());
dataTopic.chargeTypeId(data.chargeTypeId);
dataTopic.effectDuration(data.effectDuration);
dataTopic.effectStart(data.effectStart.toMSecsSinceEpoch());
dataTopic.igniterTypeId(data.igniterTypeId);
dataTopic.gearTypeId(data.gearTypeId);
dataTopic.originatorId(data.originatorId);
dataTopic.originatorTypeId(static_cast<ProjectDataManagement::StateChangeOriginator::inner_enum>(data.originatorTypeId));
dataTopic.position().lon(data.position.x());
dataTopic.position().lat(data.position.y());
dataTopic.position().z(data.position.z());
dataTopic.state(m_state);
dataTopic.properties(data.properties.toStdString());
dataTopic.sampleTime(m_mainHandler->dds()->currentPartitionTimeMSec());
return dataTopic;
}
//-----------------------------------------------------------------------------
void ObjectChargeEffect::publish()
{
if (!m_mainHandler)
{
ERROR_LOG(m_logger) << QStringLiteral("Not possible to publish ChargeEffect --> Could not remove from DDS.");
return;
}
if (!m_mainHandler->dds()->dts()->publish(dataBaseToDataTopic(m_data)))
{
ERROR_LOG(m_logger) << QStringLiteral("Not possible to publish ChargeEffect --> DDS publish failed.");
return;
}
if (m_stateChanged)
{
emit chargeEffectStateChanged(m_data.id, m_state);
m_stateChanged = false;
}
}
//-----------------------------------------------------------------------------
void ObjectChargeEffect::init()
{
calculateInitEffectState();
publish();
startStateTimer();
}
QDateTime ObjectChargeEffect::getEffectStart() const { return m_data.effectStart; }
//-----------------------------------------------------------------------------
qint32 ObjectChargeEffect::id() const { return m_data.id; }
//-----------------------------------------------------------------------------
bool ObjectChargeEffect::isFinished() const
{
return (m_data.effectStart.toMSecsSinceEpoch() + m_data.effectDuration + s_afterglowMsecs) < QDateTime::currentMSecsSinceEpoch();
}
//-----------------------------------------------------------------------------
void ObjectChargeEffect::onStateTimerTimeout()
{
switch (m_state.underlying())
{
case AesEffectState::inner_enum::EsPrepared:
case AesEffectState::inner_enum::EsActivated:
setNextState();
startStateTimer();
publish();
return;
case AesEffectState::inner_enum::EsExpired:
emit finished(m_data.id);
return;
case AesEffectState::inner_enum::EsUnknown:
case AesEffectState::inner_enum::EsError:
case AesEffectState::inner_enum::EsRemoved:
case AesEffectState::inner_enum::EsCreated:
case AesEffectState::inner_enum::EsPaused:
default:
return;
}
}
//-----------------------------------------------------------------------------
void ObjectChargeEffect::setNextState()
{
AesEffectState oldState = m_state;
m_stateChanged = false;
switch (m_state.underlying())
{
case AesEffectState::inner_enum::EsPrepared:
m_state = AesEffectState::EsActivated;
break;
case AesEffectState::inner_enum::EsActivated:
m_state = AesEffectState::EsExpired;
break;
case AesEffectState::inner_enum::EsExpired:
case AesEffectState::inner_enum::EsUnknown:
case AesEffectState::inner_enum::EsError:
case AesEffectState::inner_enum::EsRemoved:
case AesEffectState::inner_enum::EsCreated:
case AesEffectState::inner_enum::EsPaused:
default:
m_state = AesEffectState::EsUnknown;
break;
}
if (oldState != m_state)
m_stateChanged = true;
DEBUG_LOG(m_logger) << "Switching from " << oldState << "to " << m_state;
}
//-----------------------------------------------------------------------------
void ObjectChargeEffect::calculateInitEffectState()
{
const qint64 effectStartMsecs = m_data.effectStart.toMSecsSinceEpoch();
const qint64 durationEndMsecs = effectStartMsecs + m_data.effectDuration;
AesEffectState oldState = m_state;
m_stateChanged = false;
if (QDateTime::currentMSecsSinceEpoch() < effectStartMsecs)
m_state = AesEffectState::inner_enum::EsPrepared;
else if (QDateTime::currentMSecsSinceEpoch() >= effectStartMsecs && QDateTime::currentMSecsSinceEpoch() < durationEndMsecs)
m_state = AesEffectState::inner_enum::EsActivated;
else // expired
m_state = AesEffectState::inner_enum::EsExpired;
if (oldState != m_state)
m_stateChanged = true;
DEBUG_LOG(m_logger) << "Setting init state: " << m_state;
}
//-----------------------------------------------------------------------------
void ObjectChargeEffect::startStateTimer()
{
switch (m_state.underlying())
{
case AesEffectState::inner_enum::EsPrepared:
{
qint64 timeToActivatedMsecs = m_data.effectStart.toMSecsSinceEpoch() - QDateTime::currentMSecsSinceEpoch();
DEBUG_LOG(m_logger) << "Time to Avtivated [ms]: " << timeToActivatedMsecs;
m_stateTimer->start(timeToActivatedMsecs);
return;
}
case AesEffectState::inner_enum::EsActivated:
{
qint64 timeToExpiredMsecs = m_data.effectStart.toMSecsSinceEpoch() + m_data.effectDuration - QDateTime::currentMSecsSinceEpoch();
DEBUG_LOG(m_logger) << "Time to Expired [ms]: " << timeToExpiredMsecs;
m_stateTimer->start(timeToExpiredMsecs);
return;
}
case AesEffectState::inner_enum::EsExpired:
{
qint64 timeToFinishMsecs = m_data.effectStart.toMSecsSinceEpoch() + m_data.effectDuration + s_afterglowMsecs - QDateTime::currentMSecsSinceEpoch();
DEBUG_LOG(m_logger) << "Time to finish/deletion [ms]: " << timeToFinishMsecs;
m_stateTimer->start(timeToFinishMsecs);
return;
}
case AesEffectState::inner_enum::EsUnknown:
case AesEffectState::inner_enum::EsError:
case AesEffectState::inner_enum::EsRemoved:
case AesEffectState::inner_enum::EsCreated:
case AesEffectState::inner_enum::EsPaused:
default:
return;
}
}
//-----------------------------------------------------------------------------
bool ObjectChargeEffect::hasChanges(const Database::AesChargeEffect newData) const
{
return m_data.id != newData.id || m_data.name != newData.name || m_data.chargeTypeId != newData.chargeTypeId || m_data.effectDuration != newData.effectDuration
|| m_data.effectStart != newData.effectStart || m_data.igniterTypeId != newData.igniterTypeId || m_data.gearTypeId != newData.gearTypeId
|| m_data.originatorId != newData.originatorId || m_data.originatorTypeId != newData.originatorTypeId || m_data.position != newData.position;
}
} // namespace AreaEffectSimulation