- Migrated all 104 CMakeLists.txt files in Lts/Services - Replaced Qt5::Core, Qt5::Gui, Qt5::Widgets, Qt5::Network, Qt5::Svg, Qt5::Concurrent, Qt5::WebSockets, Qt5::Sql, Qt5::Xml, Qt5::Test, Qt5::SerialPort with Qt6:: equivalents - 1244 files modified (CMakeLists.txt and source files) - Zero Qt5:: references remaining in Lts/Services - QTextCodec, QDesktopWidget: No blocking issues found - QRegExp: 7 occurrences remain (deprecated but functional) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
506 lines
15 KiB
C++
Executable File
506 lines
15 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* Firing Timer, a helperclass for ExplosionCluster
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Norbert Thoden, ESVG, 2024-09-03
|
|
*/
|
|
|
|
#include "firing_timer.h"
|
|
#include "../logger.h"
|
|
|
|
#include <LtsUtilsCore/qpoint3d.h>
|
|
|
|
#include <QString>
|
|
#include <QTimer>
|
|
#include <QElapsedTimer>
|
|
#include <QDateTime>
|
|
#include <QDebug>
|
|
|
|
#include <iostream>
|
|
#include <cmath>
|
|
|
|
|
|
namespace AreaEffectSimulation
|
|
{
|
|
|
|
|
|
// To be able to aesily differentiate between different instances:
|
|
#define MY_LOGFUNCTION "debugInfo='" << d->m_debugInfo << "' " << Q_FUNC_INFO
|
|
|
|
|
|
static long s_counter{0};
|
|
|
|
//------------------------------------------------------------------------------
|
|
// class
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// class FiringTimer::Private
|
|
//------------------------------------------------------------------------------
|
|
class FiringTimer::Private
|
|
{
|
|
public:
|
|
Q_DISABLE_COPY(Private);
|
|
|
|
Private()
|
|
{
|
|
m_etActive = new QElapsedTimer();
|
|
m_etPaused = new QElapsedTimer();
|
|
m_firingTimer = new QTimer();
|
|
reset();
|
|
}
|
|
~Private()
|
|
{
|
|
delete m_etActive;
|
|
delete m_etPaused;
|
|
}
|
|
|
|
QString m_debugInfo;
|
|
|
|
|
|
double m_effectDurationMsec{-1};
|
|
int m_ammoCount;
|
|
long m_intervallMsec{-1};
|
|
long m_ammoFlightDurationMsec{-1};
|
|
|
|
FiringMode m_currentFiringMode {FiringMode::FM_Undefined};
|
|
|
|
QElapsedTimer *m_etActive{nullptr};
|
|
qint64 m_activeMsec{0};
|
|
QElapsedTimer *m_etPaused{nullptr};
|
|
qint64 m_pausedMsec{0};
|
|
|
|
QTimer *m_firingTimer{nullptr};
|
|
int m_firedAmmoCount{0};
|
|
|
|
FiringTimer::CMD m_lastDelayedStateCmd {CMD::CMD_UNDEFINED};
|
|
|
|
QStringList m_logHistorie;
|
|
|
|
void reset()
|
|
{
|
|
m_effectDurationMsec = -1;
|
|
m_ammoCount = -1;
|
|
m_intervallMsec = -1;
|
|
m_ammoFlightDurationMsec = -1;
|
|
|
|
m_currentFiringMode = FiringMode::FM_Undefined;
|
|
|
|
m_etActive->invalidate();
|
|
m_activeMsec = 0;
|
|
m_etPaused->invalidate();
|
|
m_pausedMsec = 0;
|
|
|
|
m_firingTimer->stop();
|
|
m_firedAmmoCount = 0;
|
|
|
|
m_lastDelayedStateCmd = CMD::CMD_UNDEFINED;
|
|
m_logHistorie.clear();
|
|
}
|
|
|
|
void dump()
|
|
{
|
|
static LOGGER_T logger = getLogger("Utils.FiringTimer");
|
|
|
|
INFO_LOG(logger) << " DUMP m_effectDurationMsec=" << m_effectDurationMsec
|
|
<< ", m_ammoCount=" << m_ammoCount
|
|
<< "-> m_intervallMsec=" << m_intervallMsec
|
|
<< ", m_ammoFlightDurationMsec=" << m_ammoFlightDurationMsec
|
|
<< ", m_currentFiringMode=" << (int)m_currentFiringMode
|
|
<< ", m_lastDelayedStateCmd=" << m_lastDelayedStateCmd
|
|
<< ", m_etActive=" << m_etActive
|
|
<< ", m_activeMsec=" << m_activeMsec
|
|
<< ", m_etPaused=" << m_etPaused
|
|
<< ", m_pausedMsec=" << m_pausedMsec
|
|
<< ", m_firingTimer=" << m_firingTimer
|
|
<< ", m_firedAmmoCount=" << m_firedAmmoCount;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// class FiringTimer
|
|
//------------------------------------------------------------------------------
|
|
|
|
FiringTimer::FiringTimer(const QString &debugInfo)
|
|
: BaseClass(nullptr)
|
|
, d(new Private)
|
|
, m_logger(getLogger("Utils.FiringTimer"))
|
|
{
|
|
++s_counter;
|
|
d->m_debugInfo = debugInfo;
|
|
DEBUG_LOG(m_logger) << MY_LOGFUNCTION << " START, s_counter=" << s_counter << " this=" << this;
|
|
DEBUG_LOG(m_logger) << MY_LOGFUNCTION << " END, s_counter=" << s_counter << " this=" << this;
|
|
}
|
|
|
|
FiringTimer::~FiringTimer()
|
|
{
|
|
--s_counter;
|
|
DEBUG_LOG(m_logger) << MY_LOGFUNCTION << " START, s_counter=" << s_counter << " this=" << this;
|
|
QString debugInfoSave = d->m_debugInfo;
|
|
delete d;
|
|
//DEBUG_LOG(m_logger) << MY_LOGFUNCTION << " END, s_counter=" << s_counter << " this=" << this;
|
|
DEBUG_LOG(m_logger) << "debugInfo='" << debugInfoSave << "'" << LOGFUNCTION << " END, s_counter=" << s_counter << " this=" << this;
|
|
}
|
|
|
|
void FiringTimer::setDebugInfo(const QString &debugInfo)
|
|
{
|
|
d->m_debugInfo = debugInfo;
|
|
}
|
|
|
|
void FiringTimer::reset()
|
|
{
|
|
TRACE_LOG(m_logger) << MY_LOGFUNCTION << " START";
|
|
d->reset();
|
|
TRACE_LOG(m_logger) << MY_LOGFUNCTION << " END";
|
|
}
|
|
|
|
bool FiringTimer::init(long effectDurationMsec, int ammoCount, long ammoFlightDurationMsec)
|
|
{
|
|
TRACE_LOG(m_logger) << MY_LOGFUNCTION << " START,"
|
|
<< ", effectDurationMsec=" << effectDurationMsec
|
|
<< ", ammoCount=" << ammoCount
|
|
<< ", ammoFlightDurationMsec=" << ammoFlightDurationMsec;
|
|
reset();
|
|
|
|
d->m_effectDurationMsec = effectDurationMsec;
|
|
d->m_ammoCount = ammoCount;
|
|
d->m_ammoFlightDurationMsec = ammoFlightDurationMsec;
|
|
d->m_intervallMsec = static_cast<double>(d->m_effectDurationMsec) / d->m_ammoCount; // ensure float calculation
|
|
DEBUG_LOG(m_logger) << MY_LOGFUNCTION << " m_intervallMsec " << d->m_intervallMsec;
|
|
|
|
d->m_firingTimer->stop();
|
|
d->m_firingTimer->setSingleShot(false);
|
|
d->m_firingTimer->setInterval(d->m_intervallMsec);
|
|
connect(d->m_firingTimer, &QTimer::timeout,
|
|
this, &FiringTimer::onFiringTimout, Qt::UniqueConnection);
|
|
|
|
TRACE_LOG(m_logger) << MY_LOGFUNCTION << " END";
|
|
return true;
|
|
}
|
|
|
|
bool FiringTimer::startFiring()
|
|
{
|
|
TRACE_LOG(m_logger) << MY_LOGFUNCTION << " START";
|
|
|
|
if ((d->m_currentFiringMode != FiringMode::FM_Undefined) &&
|
|
(d->m_currentFiringMode != FiringMode::FM_Paused))
|
|
{
|
|
ERROR_LOG(m_logger) << MY_LOGFUNCTION << " wrong firingMode, cur = " << (int)d->m_currentFiringMode;
|
|
return false;
|
|
}
|
|
|
|
if (remainingAmmoCount() <= 0)
|
|
{
|
|
ERROR_LOG(m_logger) << MY_LOGFUNCTION << " no ammo left"
|
|
<< " (total ammoCount was: " << d->m_ammoCount
|
|
<< " cur firingMode = " << (int)d->m_currentFiringMode;
|
|
return false;
|
|
}
|
|
|
|
|
|
#ifdef SUPPORT_STATE_CHANGE_DELAYED
|
|
if (d->m_currentFiringMode == FiringMode::FM_Paused)
|
|
{
|
|
int firedAmmoCountCopy = d->m_firedAmmoCount;
|
|
QTimer::singleShot(d->m_ammoFlightDurationMsec, this, [this, firedAmmoCountCopy](){
|
|
emitStateChangeDelayed(CMD::CMD_RESUME, firedAmmoCountCopy);
|
|
});
|
|
}
|
|
#endif // SUPPORT_STATE_CHANGE_DELAYED
|
|
|
|
|
|
DEBUG_LOG(m_logger) << MY_LOGFUNCTION << " start firing with m_firedAmmoCount = " << d->m_firedAmmoCount;
|
|
|
|
d->m_firingTimer->start();
|
|
d->m_currentFiringMode = FiringMode::FM_Active;
|
|
d->m_etActive->start();
|
|
|
|
// maybe m_etPaused is active, maybe not:
|
|
qint64 pausedElapsedMsec = 0;
|
|
if (d->m_etPaused->isValid())
|
|
{
|
|
pausedElapsedMsec = d->m_etPaused->elapsed();
|
|
d->m_pausedMsec += pausedElapsedMsec;
|
|
d->m_etPaused->invalidate();
|
|
}
|
|
DEBUG_LOG(m_logger) << MY_LOGFUNCTION << " start firing after [ms]: " << pausedElapsedMsec
|
|
<< ", m_activeMsec in total = " << d->m_activeMsec
|
|
<< ", m_pausedMsec in total = " << d->m_pausedMsec;
|
|
|
|
QString cmd = QString(QStringLiteral("StartFiring_at_%1")).arg(QDateTime::currentMSecsSinceEpoch());
|
|
d->m_logHistorie.push_back(cmd);
|
|
|
|
// ammoCount : 2 ammo
|
|
// effect Duration : 10000 msec
|
|
// => interval : 5000 msec
|
|
// _____________
|
|
// | | |
|
|
// _____________
|
|
// ^ ^
|
|
// | |_ fire 2
|
|
// |_ fire 1
|
|
//
|
|
// ^ ^
|
|
// |_ signal firing(1, 2)
|
|
// |_ signal firing(2,2)
|
|
//
|
|
// ^ ^
|
|
// |_ signal firingFinishedPlus
|
|
// |_ signal firingFinished
|
|
|
|
|
|
// to fire at the beginning of the interval:
|
|
onFiringTimout();
|
|
|
|
TRACE_LOG(m_logger) << MY_LOGFUNCTION << " END";
|
|
return true;
|
|
}
|
|
|
|
bool FiringTimer::startFiringDelay(qint64 delayMsec)
|
|
{
|
|
if (delayMsec <= 0)
|
|
return false;
|
|
QTimer::singleShot(delayMsec, this, &FiringTimer::startFiring);
|
|
return true;
|
|
}
|
|
|
|
bool FiringTimer::pauseFiring()
|
|
{
|
|
TRACE_LOG(m_logger) << MY_LOGFUNCTION << " START";
|
|
|
|
if (d->m_currentFiringMode != FiringMode::FM_Active)
|
|
{
|
|
ERROR_LOG(m_logger) << MY_LOGFUNCTION << " wrong firingMode";
|
|
return false;
|
|
}
|
|
|
|
if (remainingAmmoCount() <= 0)
|
|
{
|
|
ERROR_LOG(m_logger) << MY_LOGFUNCTION << " no ammo left"
|
|
<< " (total ammoCount was: " << d->m_ammoCount;
|
|
return false;
|
|
}
|
|
|
|
#ifdef SUPPORT_STATE_CHANGE_DELAYED
|
|
int curAmmoCountCopy = d->m_firedAmmoCount;
|
|
QTimer::singleShot(d->m_ammoFlightDurationMsec, this, [this, curAmmoCountCopy](){
|
|
emitStateChangeDelayed(CMD::CMD_PAUSE, curAmmoCountCopy);
|
|
});
|
|
#endif // SUPPORT_STATE_CHANGE_DELAYED
|
|
|
|
|
|
DEBUG_LOG(m_logger) << MY_LOGFUNCTION << " stop firing at m_firedAmmoCount = " << d->m_firedAmmoCount;
|
|
d->m_firingTimer->stop();
|
|
d->m_currentFiringMode = FiringMode::FM_Paused;
|
|
d->m_etPaused->start();
|
|
|
|
|
|
Q_ASSERT_X(d->m_etActive->isValid(), "FiringTimer", "d->m_etActive not valid");
|
|
|
|
|
|
const qint64 activeElapsedMsec = d->m_etActive->elapsed();
|
|
d->m_activeMsec += activeElapsedMsec;
|
|
d->m_etActive->invalidate();
|
|
DEBUG_LOG(m_logger) << MY_LOGFUNCTION << " stop firing after [ms]: " << activeElapsedMsec
|
|
<< ", m_activeMsec in total = " << d->m_activeMsec
|
|
<< ", m_pausedMsec in total = " << d->m_pausedMsec;
|
|
|
|
QString log = QString(QStringLiteral("pauseFiring_at_%1")).arg(QDateTime::currentMSecsSinceEpoch()) ;
|
|
d->m_logHistorie.append(log);
|
|
|
|
TRACE_LOG(m_logger) << MY_LOGFUNCTION << " END";
|
|
return true;
|
|
}
|
|
|
|
long FiringTimer::ammoFlightDurationMsec() const
|
|
{
|
|
return d->m_ammoFlightDurationMsec;
|
|
}
|
|
|
|
int FiringTimer::firedAmmoCount() const
|
|
{
|
|
return d->m_firedAmmoCount;
|
|
}
|
|
|
|
int FiringTimer::nextAmmoToFire() const
|
|
{
|
|
if (remainingAmmoCount() <= 0)
|
|
return -1;
|
|
return firedAmmoCount() + 1;
|
|
}
|
|
|
|
int FiringTimer::remainingAmmoCount() const
|
|
{
|
|
return d->m_ammoCount - d->m_firedAmmoCount;
|
|
}
|
|
|
|
long FiringTimer::intervallMsec() const
|
|
{
|
|
return d->m_intervallMsec;
|
|
}
|
|
|
|
#ifdef SUPPORT_STATE_CHANGE_DELAYED
|
|
void FiringTimer::emitStateChangeDelayed(AreaEffectSimulation::FiringTimer::CMD cmd, int firedAmmoCount)
|
|
{
|
|
DEBUG_LOG(m_logger) << MY_LOGFUNCTION << " SUPPORT_STATE_CHANGE_DELAYED: " << cmd
|
|
<< ", firedAmmoCount = " << firedAmmoCount;
|
|
emit stateChangeDelayedAsInt(static_cast<int>(cmd), firedAmmoCount);
|
|
}
|
|
#endif // SUPPORT_STATE_CHANGE_DELAYED
|
|
|
|
QStringList FiringTimer::getLogHistorie() const
|
|
{
|
|
return d->m_logHistorie;
|
|
}
|
|
|
|
QString FiringTimer::toString(const CMD cmd)
|
|
{
|
|
switch(cmd)
|
|
{
|
|
case CMD::CMD_UNDEFINED:
|
|
return QStringLiteral("CMD_UNDEFINED");
|
|
case CMD::CMD_START:
|
|
return QStringLiteral("CMD_START");
|
|
case CMD::CMD_RESUME:
|
|
return QStringLiteral("CMD_RESUME");
|
|
case CMD::CMD_PAUSE:
|
|
return QStringLiteral("CMD_PAUSE");
|
|
case CMD::CMD_EXPIRED:
|
|
return QStringLiteral("CMD_EXPIRED");
|
|
case CMD::CMD_EXPIRED_PLUS:
|
|
return QStringLiteral("CMD_EXPIRED_PLUS");
|
|
default:
|
|
return QStringLiteral("CMD_Error");
|
|
}
|
|
}
|
|
|
|
void FiringTimer::onFiringTimout()
|
|
{
|
|
TRACE_LOG(m_logger) << MY_LOGFUNCTION << " START";
|
|
|
|
++d->m_firedAmmoCount;
|
|
|
|
INFO_LOG(m_logger) << MY_LOGFUNCTION << " emit firing with: " << d->m_firedAmmoCount
|
|
<< " of total ammoCount = " << d->m_ammoCount;
|
|
emit firing(d->m_firedAmmoCount, d->m_ammoCount);
|
|
|
|
// prepared signal for impact, not interruptable
|
|
if (d->m_ammoFlightDurationMsec >= 0)
|
|
{
|
|
// copy values:
|
|
// i am not sure, if '=' would work here, so copy to local vars:
|
|
int currentFiringNumber = d->m_firedAmmoCount;
|
|
int totalFiringNumber = d->m_ammoCount;
|
|
|
|
DEBUG_LOG(m_logger) << MY_LOGFUNCTION << " XXXXXXXXX schedule 'emit impact' " << currentFiringNumber;
|
|
|
|
QTimer::singleShot(d->m_ammoFlightDurationMsec, this, [this, currentFiringNumber, totalFiringNumber]()
|
|
{
|
|
|
|
#ifdef SUPPORT_STATE_CHANGE_DELAYED
|
|
if (currentFiringNumber == 1) // Number -> start counting at '1'
|
|
{
|
|
emitStateChangeDelayed(CMD::CMD_START, currentFiringNumber);
|
|
}
|
|
#endif // SUPPORT_STATE_CHANGE_DELAYED
|
|
|
|
INFO_LOG(m_logger) << MY_LOGFUNCTION << " emit impact " << currentFiringNumber
|
|
<< " of total = " << totalFiringNumber;
|
|
emit impact(currentFiringNumber, totalFiringNumber);
|
|
|
|
#ifdef SUPPORT_STATE_CHANGE_DELAYED
|
|
if (currentFiringNumber >= totalFiringNumber)
|
|
{
|
|
emitStateChangeDelayed(CMD::CMD_EXPIRED, currentFiringNumber);
|
|
|
|
// for ..PLUS we need a delay:
|
|
QTimer::singleShot(d->m_intervallMsec, this, [this, currentFiringNumber]()
|
|
{
|
|
emitStateChangeDelayed(CMD::CMD_EXPIRED_PLUS, currentFiringNumber);
|
|
});
|
|
}
|
|
#endif // SUPPORT_STATE_CHANGE_DELAYED
|
|
|
|
});
|
|
}
|
|
|
|
if (d->m_firedAmmoCount >= d->m_ammoCount)
|
|
{
|
|
INFO_LOG(m_logger) << MY_LOGFUNCTION << " no ammo left, finishing firing"
|
|
<< ", " << d->m_firedAmmoCount << " of total ammoCount = " << d->m_ammoCount << " are fired";
|
|
d->m_firingTimer->stop();
|
|
|
|
d->m_currentFiringMode = FiringMode::FM_Expired;
|
|
|
|
const qint64 activeElapsedMsec = d->m_etActive->elapsed();
|
|
|
|
// !! Attention: do pauseFiring() WITHIN the intervall will reduce amount of time the firing is active !!
|
|
|
|
DEBUG_LOG(m_logger) << MY_LOGFUNCTION << " stop firing after [ms]: " << activeElapsedMsec
|
|
<< ", m_activeMsec in total = " << d->m_activeMsec
|
|
<< ", m_pausedMsec in total = " << d->m_pausedMsec
|
|
<< " now FiringTimoutExpiredPlus ...";
|
|
|
|
// !! Attention: do pauseFiring() WITHIN the intervall will reduce amount of time the firing is active !!
|
|
|
|
emit firingFinished();
|
|
|
|
d->dump();
|
|
|
|
// FM_ExpiredPlus
|
|
// maybe use disconnect via QMetaObject :
|
|
delete d->m_firingTimer;
|
|
d->m_firingTimer = new QTimer();
|
|
d->m_firingTimer->setInterval(d->m_intervallMsec);
|
|
// : maybe use disconnect via QMetaObject
|
|
|
|
connect(d->m_firingTimer, &QTimer::timeout,
|
|
this, &FiringTimer::onFiringTimoutExpiredPlus, Qt::UniqueConnection);
|
|
|
|
d->m_firingTimer->setSingleShot(true);
|
|
d->m_firingTimer->start();
|
|
}
|
|
|
|
TRACE_LOG(m_logger) << MY_LOGFUNCTION << " END" << ", m_firedAmmoCount " << d->m_firedAmmoCount;
|
|
}
|
|
|
|
void FiringTimer::onFiringTimoutExpiredPlus()
|
|
{
|
|
TRACE_LOG(m_logger) << MY_LOGFUNCTION << " START";
|
|
|
|
d->m_currentFiringMode = FiringMode::FM_ExpiredPlus;
|
|
|
|
const qint64 activeElapsedMsec = d->m_etActive->elapsed();
|
|
d->m_activeMsec += activeElapsedMsec;
|
|
d->m_etActive->invalidate();
|
|
|
|
// !! Attention: do pauseFiring() WITHIN the intervall will reduce amount of time the firing is active !!
|
|
|
|
DEBUG_LOG(m_logger) << MY_LOGFUNCTION << " stop firing2 after [ms]: " << activeElapsedMsec
|
|
<< ", m_activeMsec in total = " << d->m_activeMsec
|
|
<< ", m_pausedMsec in total = " << d->m_pausedMsec;
|
|
|
|
// !! Attention: do pauseFiring() WITHIN the intervall will reduce amount of time the firing is active !!
|
|
|
|
emit firingFinishedPlus();
|
|
|
|
TRACE_LOG(m_logger) << MY_LOGFUNCTION << " END";
|
|
}
|
|
|
|
|
|
|
|
|
|
AES_COMMON_EXPORT std::ostream &operator<< (std::ostream &stream, const FiringTimer::CMD value)
|
|
{
|
|
stream << FiringTimer::toString(value);
|
|
return stream;
|
|
}
|
|
|
|
|
|
} // namespace AreaEffectSimulation
|