Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/Lts/Services/AreaEffectSimulation/Utils/firing_timer.cpp
T
torstenandCopilot d5af8b9764 Session 026: Lts/Services Qt5:: to Qt6:: migration
- 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>
2026-08-25 19:23:30 +02:00

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