379 lines
12 KiB
C++
Executable File
379 lines
12 KiB
C++
Executable File
#include "object_charge_effect.h"
|
|
#include "object_base.h"
|
|
#include <QtCore/QDateTime>
|
|
#include <QtCore/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::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::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);
|
|
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>(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)
|
|
{
|
|
case AesEffectState::EsPrepared:
|
|
case AesEffectState::EsActivated:
|
|
setNextState();
|
|
startStateTimer();
|
|
publish();
|
|
|
|
return;
|
|
case AesEffectState::EsExpired:
|
|
emit finished(m_data.id);
|
|
|
|
return;
|
|
case AesEffectState::EsUnknown:
|
|
case AesEffectState::EsError:
|
|
case AesEffectState::EsRemoved:
|
|
case AesEffectState::EsCreated:
|
|
case AesEffectState::EsPaused:
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ObjectChargeEffect::setNextState()
|
|
{
|
|
AesEffectState oldState = m_state;
|
|
m_stateChanged = false;
|
|
|
|
switch (m_state)
|
|
{
|
|
case AesEffectState::EsPrepared:
|
|
m_state = AesEffectState::EsActivated;
|
|
break;
|
|
case AesEffectState::EsActivated:
|
|
m_state = AesEffectState::EsExpired;
|
|
break;
|
|
case AesEffectState::EsExpired:
|
|
case AesEffectState::EsUnknown:
|
|
case AesEffectState::EsError:
|
|
case AesEffectState::EsRemoved:
|
|
case AesEffectState::EsCreated:
|
|
case AesEffectState::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::EsPrepared;
|
|
else if (QDateTime::currentMSecsSinceEpoch() >= effectStartMsecs && QDateTime::currentMSecsSinceEpoch() < durationEndMsecs)
|
|
m_state = AesEffectState::EsActivated;
|
|
else // expired
|
|
m_state = AesEffectState::EsExpired;
|
|
|
|
if (oldState != m_state)
|
|
m_stateChanged = true;
|
|
DEBUG_LOG(m_logger) << "Setting init state: " << m_state;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ObjectChargeEffect::startStateTimer()
|
|
{
|
|
switch (m_state)
|
|
{
|
|
case AesEffectState::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::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::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::EsUnknown:
|
|
case AesEffectState::EsError:
|
|
case AesEffectState::EsRemoved:
|
|
case AesEffectState::EsCreated:
|
|
case AesEffectState::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
|