Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+505
@@ -0,0 +1,505 @@
|
||||
/**
|
||||
* @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
|
||||
Reference in new issue
Block a user