957 lines
37 KiB
C++
Executable File
957 lines
37 KiB
C++
Executable File
/**
|
|
* Handler for all exercise objects
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Hanna E. Rathje, SLSE, 2015-09-03
|
|
*/
|
|
|
|
#include "handler_effect_show.h"
|
|
#include "handler_ppm_data.h"
|
|
#include "handler_tab_data.h"
|
|
#include "handler_mdm_data.h"
|
|
#include "object_effect_show.h"
|
|
#include "effect_show_explosion_area.h"
|
|
#include "effect_show_explosion_cluster.h"
|
|
#include "effect_show_effect_cluster.h"
|
|
|
|
#include "effect_show_mine_area.h"
|
|
#include "initialization.h"
|
|
#include <EffectShowManagement/esm_db.h>
|
|
|
|
#include <random>
|
|
|
|
namespace EffectShowManagement
|
|
{
|
|
//=============================================================================
|
|
HandlerEffectShow::HandlerEffectShow(Initialization *mainHandler,
|
|
QObject *parent)
|
|
: QObject(parent)
|
|
, EffectShowModifyRequestHandler(mainHandler->dds()->fts())
|
|
, EffectShowRemoveRequestHandler(mainHandler->dds()->fts())
|
|
, m_cleanupTimer(new QTimer(this))
|
|
, m_timerMeteoData(new QTimer(this))
|
|
, m_mainHandler(mainHandler)
|
|
, m_logger(getLogger("HandlerEffectShow"))
|
|
{} // end of ctor()
|
|
//=============================================================================
|
|
|
|
HandlerEffectShow::~HandlerEffectShow()
|
|
{
|
|
qDeleteAll(m_effectShowObjMap);
|
|
m_effectShowObjMap.clear();
|
|
} // end of dtor()
|
|
//=============================================================================
|
|
|
|
bool HandlerEffectShow::init()
|
|
{
|
|
bool bRet = true;
|
|
// create Effect Show Objects
|
|
auto cbEffectShow = [this, &bRet](const Database::EsmEffectShow & data)
|
|
{
|
|
ObjectEffectShow *ifs(new ObjectEffectShow(m_mainHandler, this));
|
|
Core::FunctionReplyObject ret = ifs->createObject(data);
|
|
if (ret.error())
|
|
{
|
|
delete ifs;
|
|
ERROR_LOG(m_logger) << ret();
|
|
bRet = false;
|
|
return;
|
|
}
|
|
m_effectShowObjMap.insert(ifs->getId(), ifs);
|
|
};
|
|
if (!m_mainHandler->db()->select(cbEffectShow) || !bRet)
|
|
{
|
|
ERROR_LOG(m_logger) << "Error reading data from database 'esm_effect_show!";
|
|
return false;
|
|
}
|
|
|
|
// provision of timer for meteo data
|
|
connect(m_timerMeteoData, &QTimer::timeout, this, &HandlerEffectShow::onSendMeteoData);
|
|
m_timerMeteoData->start(HandlerEffectShow::meteoDataSendInterval);
|
|
//cleanupTimer
|
|
connect(m_cleanupTimer, &QTimer::timeout, this, &HandlerEffectShow::onCleanUp);
|
|
m_cleanupTimer->start(CLEANUPTIME); //10 minutes
|
|
|
|
DEBUG_LOG(m_logger) << "m_effectShowObjMap.size() = " << m_effectShowObjMap.size();
|
|
return true;
|
|
} // end of init()
|
|
//=============================================================================
|
|
void HandlerEffectShow::onExplosionAreaChanged(const AreaEffectSimulation::ExplosionArea &data, KindOfModification_e kindOfModification)
|
|
{
|
|
INFO_LOG(m_logger) << "onExplosionAreaChanged: " << data << ", kindOfModification: " << enumToString(kindOfModification);
|
|
switch (kindOfModification)
|
|
{
|
|
case KindOfModification_e::Added:
|
|
createEffectShowsRelatedToExplosionArea(data);
|
|
break;
|
|
case KindOfModification_e::ModifiedArea:
|
|
modifyEffectShowsRelatedToExplosionArea(data);
|
|
break;
|
|
case KindOfModification_e::ModifiedData:
|
|
updateEffectShowsRelatedToExplosionArea(data);
|
|
updateEffectShowOrdersRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::Removed:
|
|
if(data.effectStateId() == AreaEffectSimulation::AesEffectState::EsRemoved)
|
|
removeEffectShowsRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::Paused:
|
|
updateEffectShowsRelatedToExplosionArea(data);
|
|
updateEffectShowOrdersRelatedToAes(data.id());
|
|
//pauseEffectShowsRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::Continued:
|
|
updateEffectShowsRelatedToExplosionArea(data);
|
|
updateEffectShowOrdersRelatedToAes(data.id());
|
|
//continueEffectShowsRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::None:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void HandlerEffectShow::onExplosionClusterChanged(const AreaEffectSimulation::ExplosionCluster &data, HandlerEffectShow::KindOfModification_e kindOfModification)
|
|
{
|
|
INFO_LOG(m_logger) << "onExplosionClusterChanged: " << data << ", kindOfModification: " << enumToString(kindOfModification);
|
|
switch (kindOfModification)
|
|
{
|
|
case KindOfModification_e::Added:
|
|
createEffectShowsRelatedToExplosionCluster(data);
|
|
break;
|
|
case KindOfModification_e::ModifiedArea:
|
|
modifyEffectShowsRelatedToExplosionCluster(data);
|
|
break;
|
|
case KindOfModification_e::ModifiedData:
|
|
updateEffectShowsRelatedToExplosionCluster(data);
|
|
updateEffectShowOrdersRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::Removed:
|
|
if(data.effectStateId() == AreaEffectSimulation::AesEffectState::EsRemoved)
|
|
removeEffectShowsRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::Paused:
|
|
updateEffectShowsRelatedToExplosionCluster(data);
|
|
updateEffectShowOrdersRelatedToAes(data.id());
|
|
//pauseEffectShowsRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::Continued:
|
|
updateEffectShowsRelatedToExplosionCluster(data);
|
|
updateEffectShowOrdersRelatedToAes(data.id());
|
|
//continueEffectShowsRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::None:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
void HandlerEffectShow::onEffectClusterChanged(const AreaEffectSimulation::EffectCluster &data, KindOfModification_e kindOfModification)
|
|
{
|
|
INFO_LOG(m_logger) << "onEffectClusterChanged: " << data << ", kindOfModification: " << enumToString(kindOfModification);
|
|
switch (kindOfModification)
|
|
{
|
|
case KindOfModification_e::Added:
|
|
createEffectShowsRelatedToEffectCluster(data);
|
|
break;
|
|
case KindOfModification_e::ModifiedArea:
|
|
modifyEffectShowsRelatedToEffectCluster(data);
|
|
break;
|
|
case KindOfModification_e::ModifiedData:
|
|
updateEffectShowsRelatedToEffectCluster(data);
|
|
updateEffectShowOrdersRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::Removed:
|
|
if(data.effectStateId() == AreaEffectSimulation::AesEffectState::EsRemoved)
|
|
removeEffectShowsRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::Paused:
|
|
updateEffectShowsRelatedToEffectCluster(data);
|
|
updateEffectShowOrdersRelatedToAes(data.id());
|
|
//pauseEffectShowsRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::Continued:
|
|
updateEffectShowsRelatedToEffectCluster(data);
|
|
updateEffectShowOrdersRelatedToAes(data.id());
|
|
//continueEffectShowsRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::None:
|
|
break;
|
|
}
|
|
|
|
} // end of onExplosionClusterChanged()
|
|
|
|
//=============================================================================
|
|
void HandlerEffectShow::onMineAreaChanged(const AreaEffectSimulation::MineArea &data, KindOfModification_e kindOfModification)
|
|
{
|
|
INFO_LOG(m_logger) << "onMineAreaChanged: " << data << ", kindOfModification: " << enumToString(kindOfModification);
|
|
switch (kindOfModification)
|
|
{
|
|
case KindOfModification_e::Added:
|
|
createEffectShowsRelatedToMineArea(data);
|
|
break;
|
|
case KindOfModification_e::ModifiedArea:
|
|
modifyEffectShowsRelatedToMineArea(data);
|
|
break;
|
|
case KindOfModification_e::ModifiedData:
|
|
updateEffectShowsRelatedToMineArea(data);
|
|
updateEffectShowOrdersRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::Removed:
|
|
if(data.effectStateId() == AreaEffectSimulation::AesEffectState::EsRemoved)
|
|
removeEffectShowsRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::Paused:
|
|
updateEffectShowsRelatedToMineArea(data);
|
|
updateEffectShowOrdersRelatedToAes(data.id());
|
|
// pauseEffectShowsRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::Continued:
|
|
updateEffectShowsRelatedToMineArea(data);
|
|
updateEffectShowOrdersRelatedToAes(data.id());
|
|
//continueEffectShowsRelatedToAes(data.id());
|
|
break;
|
|
case KindOfModification_e::None:
|
|
break;
|
|
}
|
|
} // end of onMineAreaChanged()
|
|
//=============================================================================
|
|
void HandlerEffectShow::effectShowOrderConfirmationReceived(const ConvertFromTab::OrderConfirmation_t &orderConfirmation)
|
|
{
|
|
DEBUG_LOG(m_logger) << "onEffectShowConfirmationReceived()";
|
|
|
|
ObjectEffectShow *ifs = m_effectShowObjMap.value(orderConfirmation.orderId);
|
|
if (ifs == nullptr)
|
|
{
|
|
WARNING_LOG(m_logger) << "Error receiving effect show ID not known: " << orderConfirmation.orderId;
|
|
return;
|
|
}
|
|
const auto oldId = ifs->getData().orderConfirmation;
|
|
|
|
// add confirmation data
|
|
ifs->updateObject(orderConfirmation);
|
|
|
|
if (oldId != ifs->getData().orderConfirmation && ifs->getData().orderConfirmation == EffectShowManagement::OrderConfirmation_e::FiringReadiness)
|
|
{
|
|
DEBUG_LOG(m_logger) << "effectShowOrderConfirmationReceived Got Fire Readyness, send to aes for " << ifs->getId();
|
|
AreaEffectSimulation::SetAesItemEffectorStateRequest req;
|
|
req.aesId(ifs->getIdAES());
|
|
req.newEffectorState(AreaEffectSimulation::AesEffectorState::EsReadyToFire);
|
|
req.participantId(ifs->getData().esmParticipantId);
|
|
m_mainHandler->dds()->ftcAes()->setAesItemEffectorStateRequest(req, this);
|
|
}
|
|
switch (orderConfirmation.confirmation.underlying())
|
|
{
|
|
case EffectShowManagement::OrderConfirmation_e_def::DriveOff:
|
|
case EffectShowManagement::OrderConfirmation_e_def::FiringReadiness:
|
|
case EffectShowManagement::OrderConfirmation_e_def::InterruptExecution:
|
|
case EffectShowManagement::OrderConfirmation_e_def::PositionReached:
|
|
{
|
|
triggerMeteoData(ifs); // send meteo data for effect show position
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
} // end of onEffectShowConfirmationReceived()
|
|
//=============================================================================
|
|
void HandlerEffectShow::createEffectShow(const Database::EsmEffectShow &data, bool bForceUpdateDb)
|
|
{
|
|
ObjectEffectShow *ifs(new ObjectEffectShow(m_mainHandler));
|
|
Core::FunctionReplyObject ret = ifs->createObject(data, bForceUpdateDb);
|
|
if (ret.error())
|
|
{
|
|
delete ifs;
|
|
ERROR_LOG(m_logger) << ret();
|
|
}
|
|
else
|
|
{
|
|
m_effectShowObjMap.insert(ifs->getId(), ifs);
|
|
triggerEffectShowOrder(ifs);
|
|
}
|
|
|
|
} // end of createEffectShow
|
|
//-----------------------------------------------------------------------------
|
|
void HandlerEffectShow::onEffectShowModifyRequest(
|
|
const rti::core::SampleIdentity &cookie,
|
|
const EffectShow &request)
|
|
{
|
|
DEBUG_LOG(m_logger) << "onEffectShowModifyRequest: " << request.id();
|
|
if (request.id() <= 0)
|
|
{
|
|
ERROR_LOG(m_logger) << "Illegal Effect Show Id: " << request.id();
|
|
return;
|
|
}
|
|
|
|
// Sende Feuerbereitschaft zum SAA
|
|
// m_mainHandler->handlerTabData()->sendAdlerFqFb(request.idAreaEffectSimulation());
|
|
|
|
auto ret = effectShowModifyRequest(request);
|
|
if (ret.error())
|
|
ERROR_LOG(m_logger) << ret();
|
|
|
|
m_mainHandler->dds()->fts()->effectShowModifyReply(cookie, ret);
|
|
|
|
} // end of onEffectShowModifyRequest()
|
|
//-------------------------------------------------------------------------------
|
|
Core::FunctionReplyObject HandlerEffectShow::effectShowModifyRequest(const EffectShow &request)
|
|
{
|
|
ObjectEffectShow *ifs = m_effectShowObjMap.value(request.id());
|
|
if (ifs == nullptr)
|
|
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "EffectShow with id %1 not found")).arg(request.id());
|
|
|
|
Core::FunctionReplyObject ret;
|
|
auto idCurrent = ifs->getData().esmParticipantId;
|
|
if ((idCurrent != -1) && (request.esmParticipantId() != idCurrent))
|
|
{
|
|
triggerRetractOrder(ifs); // trigger retract order to current effect show actor, if needed
|
|
ret = ifs->updateObject(request); // update effect show
|
|
if (!ret.error())
|
|
ifs->resetOrderConfirmation(); // reset confirmation status
|
|
}
|
|
else
|
|
{
|
|
ret = ifs->updateObject(request); // update effect show
|
|
}
|
|
|
|
if (!ret.error() && ifs->getData().esmParticipantId != -1)
|
|
triggerEffectShowOrder(ifs); // trigger effect show order to effect show actor
|
|
|
|
if (ret.error())
|
|
WARNING_LOG(m_logger) << ret();
|
|
|
|
return ret;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
void HandlerEffectShow::onEffectShowRemoveRequest(const rti::core::SampleIdentity &cookie,
|
|
const Core::RemoveElementRequest &request)
|
|
{
|
|
DEBUG_LOG(m_logger) << "onEffectShowRemoveRequest: " << request.id();
|
|
|
|
ObjectEffectShow *ifs = m_effectShowObjMap.value(request.id());
|
|
Core::FunctionReplyObject ret;
|
|
|
|
if (ifs == nullptr)
|
|
{
|
|
ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "EffectShow id %1 is not valid")).arg(request.id());
|
|
m_mainHandler->dds()->fts()->effectShowRemoveReply(cookie, ret);
|
|
return;
|
|
}
|
|
|
|
EffectShowManagement::EffectShow ddsData;
|
|
ddsData.id(ifs->getId());
|
|
|
|
if (m_mainHandler->dds()->topicLockMaster()->isLocked(ddsData, m_mainHandler->exerciseId()))
|
|
{
|
|
ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "EffectShow '%1' is used by another user!")).arg(ifs->getName());
|
|
m_mainHandler->dds()->fts()->effectShowRemoveReply(cookie, ret);
|
|
return;
|
|
}
|
|
|
|
ret = removeEffectShow(ifs); // trigger retract order if needed, before object remove
|
|
|
|
m_mainHandler->dds()->fts()->effectShowRemoveReply(cookie, ret);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
static std::string toString(const Database::EsmEffectShow &esmEffectShow)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << "Created Effect Show "
|
|
<< "\n ID: " << esmEffectShow.id
|
|
<< "\n Name: " << esmEffectShow.name
|
|
<< "\n Start time: " << esmEffectShow.startTime
|
|
<< "\n Duration: " << esmEffectShow.duration
|
|
<< "\n ID AES: " << esmEffectShow.idAreaEffectSimulation
|
|
<< "\n ID Effect Show Actor: " << esmEffectShow.esmParticipantId
|
|
<< "\n numOfVOlley" << esmEffectShow.numOfVolley
|
|
<< "\n shotsPervolley" << esmEffectShow.shotsPerVolley;
|
|
return oss.str();
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
void HandlerEffectShow::createEffectShowsRelatedToMineArea(const AreaEffectSimulation::MineArea &data)
|
|
{
|
|
const auto esmEffectShows = createEffectShowDbDataRelatedToMineArea(data);
|
|
for (const auto &esmEffectShow : esmEffectShows)
|
|
{
|
|
createEffectShow(esmEffectShow);
|
|
DEBUG_LOG(m_logger) << toString(esmEffectShow);
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
void HandlerEffectShow::createEffectShowsRelatedToExplosionArea(const AreaEffectSimulation::ExplosionArea &data)
|
|
{
|
|
const auto esmEffectShows = createEffectShowDbDataRelatedToExplosionArea(data);
|
|
for (const auto &esmEffectShow : esmEffectShows)
|
|
{
|
|
createEffectShow(esmEffectShow);
|
|
DEBUG_LOG(m_logger) << toString(esmEffectShow);
|
|
}
|
|
}
|
|
|
|
void HandlerEffectShow::createEffectShowsRelatedToExplosionCluster(const AreaEffectSimulation::ExplosionCluster &data)
|
|
{
|
|
const auto esmEffectShows = createEffectShowDbDataRelatedToExplosionCluster(data);
|
|
for (const auto &esmEffectShow : esmEffectShows)
|
|
{
|
|
createEffectShow(esmEffectShow);
|
|
DEBUG_LOG(m_logger) << toString(esmEffectShow);
|
|
}
|
|
}
|
|
|
|
void HandlerEffectShow::createEffectShowsRelatedToEffectCluster(const AreaEffectSimulation::EffectCluster &data)
|
|
{
|
|
const auto esmEffectShows = createEffectShowDbDataRelatedToEffectCluster(data);
|
|
for (const auto &esmEffectShow : esmEffectShows)
|
|
{
|
|
createEffectShow(esmEffectShow);
|
|
DEBUG_LOG(m_logger) << toString(esmEffectShow);
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
QVector<Database::EsmEffectShow> HandlerEffectShow::createEffectShowDbDataRelatedToMineArea(const AreaEffectSimulation::MineArea &data)
|
|
{
|
|
QVector<Database::EsmEffectShow> ret;
|
|
|
|
DEBUG_LOG(m_logger) << "createEffectShowDbDataRelatedToExplosionArea: ";
|
|
|
|
EffectShowMineArea effectShowMineArea(data);
|
|
Database::EsmEffectShow esmEffectShow = effectShowMineArea.getEffectShow();
|
|
ret.push_back(esmEffectShow);
|
|
return ret;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
QVector<Database::EsmEffectShow> HandlerEffectShow::createEffectShowDbDataRelatedToExplosionArea(const AreaEffectSimulation::ExplosionArea &data)
|
|
{
|
|
QVector<Database::EsmEffectShow> ret;
|
|
|
|
DEBUG_LOG(m_logger) << "createEffectShowDbDataRelatedToExplosionArea: ";
|
|
|
|
EffectShowExplosionArea effectShowExplosionArea(data, m_mainHandler->handlerPdmData());
|
|
|
|
if (m_mainHandler->handlerPdmData()->isSmoke(data.chargeStruct()))
|
|
{
|
|
//create exact 1
|
|
ret.reserve(1);
|
|
Database::EsmEffectShow esmEffectShow = effectShowExplosionArea.getEffectShow(0);
|
|
DEBUG_LOG(m_logger) << toString(esmEffectShow);
|
|
ret.push_back(std::move(esmEffectShow));
|
|
}
|
|
else
|
|
{
|
|
int max = effectShowExplosionArea.getNumOfEffectShows() > MAX_EFFECT_SHOWS ? MAX_EFFECT_SHOWS : effectShowExplosionArea.getNumOfEffectShows();
|
|
std::random_device rd; //Will be used to obtain a seed for the random number engine
|
|
std::mt19937 gen(rd());
|
|
std::uniform_int_distribution<uint32_t> dist(0, effectShowExplosionArea.getNumOfEffectShows() - 1);
|
|
QSet<int> taken;
|
|
|
|
// only create MAX_EFFECT_SHOWS orders even there are more needed for this area
|
|
ret.reserve(max);
|
|
for (int i = 0; i < max; ++i)
|
|
{
|
|
int randomNr = dist(gen);
|
|
Database::EsmEffectShow esmEffectShow = effectShowExplosionArea.getEffectShow(randomNr);
|
|
while (taken.contains(randomNr))
|
|
{
|
|
randomNr = dist(gen);
|
|
esmEffectShow = effectShowExplosionArea.getEffectShow(randomNr);
|
|
}
|
|
taken.insert(randomNr);
|
|
|
|
int shootsPerArea = effectShowExplosionArea.getShotsPerArea(max);
|
|
|
|
esmEffectShow.numOfVolley = effectShowExplosionArea.getNumberOfVolley(shootsPerArea);
|
|
esmEffectShow.shotsPerVolley = effectShowExplosionArea.getShotsPerArea();
|
|
if (esmEffectShow.shotsPerVolley < esmEffectShow.numOfVolley)
|
|
esmEffectShow.shotsPerVolley = esmEffectShow.numOfVolley; // set minimum shots per volley
|
|
DEBUG_LOG(m_logger) << toString(esmEffectShow);
|
|
|
|
ret.push_back(std::move(esmEffectShow));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
QVector<Database::EsmEffectShow> HandlerEffectShow::createEffectShowDbDataRelatedToExplosionCluster(const AreaEffectSimulation::ExplosionCluster &data)
|
|
{
|
|
EffectShowExplosionCluster effectShowExplosionCluster(data, m_mainHandler->handlerPdmData());
|
|
|
|
QVector<Database::EsmEffectShow> ret;
|
|
if (m_mainHandler->handlerPdmData()->isSmoke(data.chargeStruct()))
|
|
{
|
|
//create exact 1
|
|
ret.reserve(1);
|
|
Database::EsmEffectShow esmEffectShow = effectShowExplosionCluster.getEffectShow(0);
|
|
if(data.esmParticipantIds().size() > 0)
|
|
esmEffectShow.esmParticipantId = data.esmParticipantIds().at(0); // TODO handle vector
|
|
DEBUG_LOG(m_logger) << toString(esmEffectShow);
|
|
ret.push_back(std::move(esmEffectShow));
|
|
}
|
|
else
|
|
{
|
|
int max = effectShowExplosionCluster.getNumOfEffectShows() > MAX_EFFECT_SHOWS ? MAX_EFFECT_SHOWS : effectShowExplosionCluster.getNumOfEffectShows();
|
|
std::random_device rd; //Will be used to obtain a seed for the random number engine
|
|
std::mt19937 gen(rd());
|
|
std::uniform_int_distribution<uint32_t> dist(0, effectShowExplosionCluster.getNumOfEffectShows() - 1);
|
|
QSet<int> taken;
|
|
|
|
// only create MAX_EFFECT_SHOWS orders even there are more needed for this area
|
|
ret.reserve(max);
|
|
for (int i = 0; i < max; ++i)
|
|
{
|
|
int randomNr = dist(gen);
|
|
Database::EsmEffectShow esmEffectShow = effectShowExplosionCluster.getEffectShow(randomNr);
|
|
while (taken.contains(randomNr))
|
|
{
|
|
randomNr = dist(gen);
|
|
esmEffectShow = effectShowExplosionCluster.getEffectShow(randomNr);
|
|
}
|
|
taken.insert(randomNr);
|
|
|
|
int shootsPerArea = effectShowExplosionCluster.getShotsPerArea(max);
|
|
|
|
esmEffectShow.numOfVolley = effectShowExplosionCluster.getNumberOfVolley(shootsPerArea);
|
|
esmEffectShow.shotsPerVolley = effectShowExplosionCluster.getShotsPerArea();
|
|
if (esmEffectShow.shotsPerVolley < esmEffectShow.numOfVolley)
|
|
esmEffectShow.shotsPerVolley = esmEffectShow.numOfVolley; // set minimum shots per volley
|
|
DEBUG_LOG(m_logger) << toString(esmEffectShow);
|
|
|
|
// Evlt. nicht bei DM42 (dann ist max > 1)
|
|
if(data.esmParticipantIds().size() > 0)
|
|
esmEffectShow.esmParticipantId = data.esmParticipantIds().at(0); // TODO handle vector
|
|
ret.push_back(std::move(esmEffectShow));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
QVector<Database::EsmEffectShow> HandlerEffectShow::createEffectShowDbDataRelatedToEffectCluster(const AreaEffectSimulation::EffectCluster &data)
|
|
{
|
|
EffectShowEffectCluster effectShowEffectCluster(data, m_mainHandler->handlerPdmData());
|
|
|
|
QVector<Database::EsmEffectShow> ret;
|
|
if (m_mainHandler->handlerPdmData()->isSmoke(data.chargeStruct()))
|
|
{
|
|
//create exact 1
|
|
ret.reserve(1);
|
|
Database::EsmEffectShow esmEffectShow = effectShowEffectCluster.getEffectShow(0);
|
|
if(data.esmParticipantIds().size() > 0)
|
|
esmEffectShow.esmParticipantId = data.esmParticipantIds().at(0); // TODO handle vector
|
|
DEBUG_LOG(m_logger) << toString(esmEffectShow);
|
|
ret.push_back(std::move(esmEffectShow));
|
|
}
|
|
else
|
|
{
|
|
int max = effectShowEffectCluster.getNumOfEffectShows() > MAX_EFFECT_SHOWS ? MAX_EFFECT_SHOWS : effectShowEffectCluster.getNumOfEffectShows();
|
|
std::random_device rd; //Will be used to obtain a seed for the random number engine
|
|
std::mt19937 gen(rd());
|
|
std::uniform_int_distribution<uint32_t> dist(0, effectShowEffectCluster.getNumOfEffectShows() - 1);
|
|
QSet<int> taken;
|
|
|
|
// only create MAX_EFFECT_SHOWS orders even there are more needed for this area
|
|
ret.reserve(max);
|
|
for (int i = 0; i < max; ++i)
|
|
{
|
|
int randomNr = dist(gen);
|
|
Database::EsmEffectShow esmEffectShow = effectShowEffectCluster.getEffectShow(randomNr);
|
|
while (taken.contains(randomNr))
|
|
{
|
|
randomNr = dist(gen);
|
|
esmEffectShow = effectShowEffectCluster.getEffectShow(randomNr);
|
|
}
|
|
taken.insert(randomNr);
|
|
|
|
int shootsPerArea = effectShowEffectCluster.getShotsPerArea(max);
|
|
|
|
esmEffectShow.numOfVolley = effectShowEffectCluster.getNumberOfVolley(shootsPerArea);
|
|
esmEffectShow.shotsPerVolley = effectShowEffectCluster.getShotsPerArea();
|
|
if (esmEffectShow.shotsPerVolley < esmEffectShow.numOfVolley)
|
|
esmEffectShow.shotsPerVolley = esmEffectShow.numOfVolley; // set minimum shots per volley
|
|
//DEBUG_LOG(m_logger) << toString(esmEffectShow);
|
|
|
|
// Evlt. nicht bei DM42 (dann ist max > 1)
|
|
if(data.esmParticipantIds().size() > (size_t)i)
|
|
esmEffectShow.esmParticipantId = data.esmParticipantIds().at(i); // TODO handle vector
|
|
DEBUG_LOG(m_logger) << toString(esmEffectShow);
|
|
|
|
ret.push_back(std::move(esmEffectShow));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
void HandlerEffectShow::removeEffectShowsRelatedToAes(int idAes, bool retract)
|
|
{
|
|
DEBUG_LOG(m_logger) << "removeEffectShowsRelatedToAes(" << idAes << ")";
|
|
auto it = m_effectShowObjMap.begin();
|
|
while (it != m_effectShowObjMap.end())
|
|
{
|
|
bool remove = false;
|
|
if (it.value()->getIdAES() == idAes)
|
|
{
|
|
if ((it.value()->getData().orderConfirmation != EffectShowManagement::OrderConfirmation_e_def::Execution) &&
|
|
(it.value()->getData().orderConfirmation != EffectShowManagement::OrderConfirmation_e_def::OrderCarriedOut))
|
|
remove = true;
|
|
else
|
|
INFO_LOG(m_logger) << "Effect Show: " << it.value()->getId() << " not removed due to EXECUTION / ORDER CARRIED OUT";
|
|
}
|
|
if (remove)
|
|
{
|
|
ObjectEffectShow *objToDelete = it.value();
|
|
++it;
|
|
removeEffectShow(objToDelete, true, retract); // trigger retract order if needed, before object remove
|
|
}
|
|
else
|
|
++it;
|
|
}
|
|
} // end of removeEffectShowsRelatedToAes()
|
|
//-------------------------------------------------------------------------------
|
|
void HandlerEffectShow::updateEffectShowsRelatedToMineArea(const AreaEffectSimulation::MineArea &data)
|
|
{
|
|
for (ObjectEffectShow *obj : qAsConst(m_effectShowObjMap))
|
|
{
|
|
if (obj->getIdAES() == data.id())
|
|
{
|
|
Database::EsmEffectShow esmEffectShow = obj->getData();
|
|
EffectShowMineArea effectShowMineArea(data);
|
|
effectShowMineArea.updateEffectShow(esmEffectShow);
|
|
obj->updateObject(esmEffectShow);
|
|
}
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
void HandlerEffectShow::updateEffectShowsRelatedToExplosionArea(const AreaEffectSimulation::ExplosionArea &data)
|
|
{
|
|
for (ObjectEffectShow *obj : qAsConst(m_effectShowObjMap))
|
|
{
|
|
if (obj->getIdAES() == data.id())
|
|
{
|
|
Database::EsmEffectShow esmEffectShow = obj->getData();
|
|
EffectShowExplosionArea effectShowExplosionArea(data, m_mainHandler->handlerPdmData());
|
|
effectShowExplosionArea.updateEffectShow(esmEffectShow);
|
|
obj->updateObject(esmEffectShow);
|
|
}
|
|
}
|
|
}
|
|
|
|
void HandlerEffectShow::updateEffectShowsRelatedToExplosionCluster(const AreaEffectSimulation::ExplosionCluster &data)
|
|
{
|
|
for (ObjectEffectShow *obj : qAsConst(m_effectShowObjMap))
|
|
{
|
|
if (obj->getIdAES() == data.id())
|
|
{
|
|
Database::EsmEffectShow esmEffectShow = obj->getData();
|
|
EffectShowExplosionCluster effectShowExplosionCluster(data, m_mainHandler->handlerPdmData());
|
|
effectShowExplosionCluster.updateEffectShow(esmEffectShow);
|
|
obj->updateObject(esmEffectShow);
|
|
}
|
|
}
|
|
}
|
|
|
|
void HandlerEffectShow::updateEffectShowsRelatedToEffectCluster(const AreaEffectSimulation::EffectCluster &data)
|
|
{
|
|
for (ObjectEffectShow *obj : qAsConst(m_effectShowObjMap))
|
|
{
|
|
if (obj->getIdAES() == data.id())
|
|
{
|
|
Database::EsmEffectShow esmEffectShow = obj->getData();
|
|
EffectShowEffectCluster effectShowEffectCluster(data, m_mainHandler->handlerPdmData());
|
|
effectShowEffectCluster.updateEffectShow(esmEffectShow);
|
|
obj->updateObject(esmEffectShow);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void copyOldActorData(Database::EsmEffectShow &newData, const Database::EsmEffectShow &oldData)
|
|
{
|
|
newData.id = oldData.id;
|
|
newData.orderConfirmation = oldData.orderConfirmation;
|
|
newData.answerText = oldData.answerText;
|
|
newData.esmParticipantId = oldData.esmParticipantId;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
void HandlerEffectShow::modifyEffectShowsRelatedToMineArea(const AreaEffectSimulation::MineArea &data)
|
|
{
|
|
// even there can currently only be one object we use the same logic as for
|
|
// modifyEffectShowsRelatedToExplosionArea for convenience
|
|
modifyEffectShows(createEffectShowDbDataRelatedToMineArea(data), data.id());
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
void HandlerEffectShow::modifyEffectShowsRelatedToExplosionArea(const AreaEffectSimulation::ExplosionArea &data)
|
|
{
|
|
modifyEffectShows(createEffectShowDbDataRelatedToExplosionArea(data), data.id());
|
|
}
|
|
|
|
void HandlerEffectShow::modifyEffectShowsRelatedToExplosionCluster(const AreaEffectSimulation::ExplosionCluster &data)
|
|
{
|
|
modifyEffectShows(createEffectShowDbDataRelatedToExplosionCluster(data), data.id());
|
|
}
|
|
|
|
void HandlerEffectShow::modifyEffectShowsRelatedToEffectCluster(const AreaEffectSimulation::EffectCluster &data)
|
|
{
|
|
modifyEffectShows(createEffectShowDbDataRelatedToEffectCluster(data), data.id());
|
|
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
void HandlerEffectShow::modifyEffectShows(const QVector<Database::EsmEffectShow> &esmEffectShows, int aesId)
|
|
{
|
|
// a lot of stuff might have changed - therefore we recalculate the effect shows,
|
|
// use the old ids and send out a complete update
|
|
|
|
// first retrieve all objects for the area
|
|
QVector<ObjectEffectShow * > objects = removeFromEffectShowMapByAesId(aesId);
|
|
// fewer objects than before -> remove the superfluous ones
|
|
while (objects.size() > esmEffectShows.size())
|
|
removeEffectShow(objects.takeLast(), false, false);
|
|
|
|
// update all for the existing objects, create new ones if needed
|
|
for (int i = 0; i < esmEffectShows.size(); ++i)
|
|
{
|
|
auto esmEffectShow = esmEffectShows.at(i);
|
|
if (objects.size() > i)
|
|
{
|
|
auto oldObj = objects.at(i);
|
|
copyOldActorData(esmEffectShow, oldObj->getData());
|
|
oldObj->setRemoveFromDdsOnDestruction(false);
|
|
delete oldObj;
|
|
}
|
|
createEffectShow(esmEffectShow, true);
|
|
}
|
|
updateEffectShowOrdersRelatedToAes(aesId);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
void HandlerEffectShow::updateEffectShowOrdersRelatedToAes(int idAes)
|
|
{
|
|
for (ObjectEffectShow *obj : qAsConst(m_effectShowObjMap))
|
|
{
|
|
if (obj->getIdAES() == idAes)
|
|
triggerEffectShowOrder(obj);
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
void HandlerEffectShow::pauseEffectShowsRelatedToAes(int idAes)
|
|
{
|
|
for (ObjectEffectShow *obj : qAsConst(m_effectShowObjMap))
|
|
{
|
|
if (obj->getIdAES() == idAes)
|
|
triggerEffectShowStop(obj);
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
void HandlerEffectShow::continueEffectShowsRelatedToAes(int idAes)
|
|
{
|
|
for (ObjectEffectShow *obj : qAsConst(m_effectShowObjMap))
|
|
{
|
|
if (obj->getIdAES() == idAes)
|
|
triggerEffectShowContinue(obj);
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
QVector<ObjectEffectShow * > HandlerEffectShow::removeFromEffectShowMapByAesId(int aesId)
|
|
{
|
|
QVector<ObjectEffectShow * > ret;
|
|
for (auto it = m_effectShowObjMap.begin(); it != m_effectShowObjMap.end();)
|
|
{
|
|
ObjectEffectShow *obj = it.value();
|
|
if (obj->getIdAES() == aesId)
|
|
{
|
|
ret += obj;
|
|
it = m_effectShowObjMap.erase(it);
|
|
}
|
|
else
|
|
++it;
|
|
}
|
|
// in modifyEffectShowsRelatedToFOO we want to remove the last objects first when no longer needed
|
|
std::sort(ret.begin(), ret.end(), [](const ObjectEffectShow * a, const ObjectEffectShow * b) { return a->getId() < b->getId();});
|
|
return ret;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
Core::FunctionReplyObject HandlerEffectShow::removeEffectShow(ObjectEffectShow *ifs, bool bWarnWhenNotInMap, bool retract)
|
|
{
|
|
const int effectShowId = ifs->getId();
|
|
// retract order if needed
|
|
if (retract)
|
|
triggerRetractOrder(ifs);
|
|
|
|
// remove from data base
|
|
Core::FunctionReplyObject ret = ifs->removeObject();
|
|
if (ret.error())
|
|
{
|
|
ERROR_LOG(m_logger) << ret();
|
|
return ret;
|
|
}
|
|
|
|
// delete object and remove from data distribution
|
|
delete ifs;
|
|
|
|
// remove from map
|
|
if (!m_effectShowObjMap.remove(effectShowId) && bWarnWhenNotInMap)
|
|
WARNING_LOG(m_logger) << "Remove of EffectShow(" << effectShowId << ") failed.";
|
|
else
|
|
DEBUG_LOG(m_logger) << "EffectShow(" << effectShowId << ") removed.";
|
|
|
|
return ret;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
void HandlerEffectShow::triggerEffectShowOrder(const ObjectEffectShow *ifs)
|
|
{
|
|
const Database::EsmEffectShow &effectShow = ifs->getData();
|
|
INFO_LOG(m_logger) << "triggerEffectShowOrder for id " << ifs->getId()
|
|
<< ", aesId: " << ifs->getIdAES()
|
|
<< ", actor: " << effectShow.esmParticipantId;
|
|
if (effectShow.esmParticipantId == -1)
|
|
return; // no effect show actor allocated
|
|
|
|
// trigger effect show order
|
|
int equipmentNumber = m_mainHandler->handlerPpmData()->getEquipmentNumber(effectShow.esmParticipantId);
|
|
m_mainHandler->handlerTabData()->effectShowOrder(equipmentNumber, effectShow.esmParticipantId, ifs->getEffectShowOrder());
|
|
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
void HandlerEffectShow::triggerRetractOrder(const ObjectEffectShow *ifs)
|
|
{
|
|
const Database::EsmEffectShow &effectShow = ifs->getData();
|
|
INFO_LOG(m_logger) << "triggerRetractOrder for id " << ifs->getId()
|
|
<< ", aesId: " << ifs->getIdAES()
|
|
<< ", actor: " << effectShow.esmParticipantId;
|
|
if (effectShow.esmParticipantId == -1)
|
|
return; // up to now no actor allocated
|
|
if (effectShow.orderConfirmation >= EffectShowManagement::OrderConfirmation_e_def::OrderCarriedOut)
|
|
return; // order obsolete
|
|
|
|
// trigger retract order
|
|
int equipmentNumber = m_mainHandler->handlerPpmData()->getEquipmentNumber(effectShow.esmParticipantId);
|
|
m_mainHandler->handlerTabData()->retractOrder(equipmentNumber, effectShow.esmParticipantId, ifs->getRetractOrder());
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
void HandlerEffectShow::triggerEffectShowStop(const ObjectEffectShow *ifs)
|
|
{
|
|
const Database::EsmEffectShow &effectShow = ifs->getData();
|
|
INFO_LOG(m_logger) << "triggerEffectShowStop for id " << ifs->getId()
|
|
<< ", aesId: " << ifs->getIdAES()
|
|
<< ", actor: " << effectShow.esmParticipantId;
|
|
if (effectShow.esmParticipantId == -1)
|
|
return; // up to now no actor allocated
|
|
|
|
// trigger effect show stop
|
|
int equipmentNumber = m_mainHandler->handlerPpmData()->getEquipmentNumber(effectShow.esmParticipantId);
|
|
m_mainHandler->handlerTabData()->effectShowStop(equipmentNumber, effectShow.esmParticipantId, ifs->getId());
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
void HandlerEffectShow::triggerEffectShowContinue(const ObjectEffectShow *ifs)
|
|
{
|
|
const Database::EsmEffectShow &effectShow = ifs->getData();
|
|
INFO_LOG(m_logger) << "triggerEffectShowContinue for id " << ifs->getId()
|
|
<< ", aesId: " << ifs->getIdAES()
|
|
<< ", actor: " << effectShow.esmParticipantId;
|
|
if (effectShow.esmParticipantId == -1)
|
|
return; // up to now no actor allocated
|
|
|
|
// trigger retract order
|
|
int equipmentNumber = m_mainHandler->handlerPpmData()->getEquipmentNumber(effectShow.esmParticipantId);
|
|
m_mainHandler->handlerTabData()->effectShowContinue(equipmentNumber, effectShow.esmParticipantId, ifs->getContinueOrder());
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
void HandlerEffectShow::triggerMeteoData(const ObjectEffectShow *ifs)
|
|
{
|
|
const Database::EsmEffectShow &effectShow = ifs->getData();
|
|
|
|
// get weather near to the effect show position
|
|
Core::GeoPosition2D pos(effectShow.centerPosition.x(), effectShow.centerPosition.y());
|
|
MeteoDataManagement::MeteoData meteoData;
|
|
if (m_mainHandler->handlerMdmData()->getNearestWeather(pos, meteoData))
|
|
{
|
|
if (!meteoData.windOk() && !meteoData.climateOk())
|
|
{
|
|
WARNING_LOG(m_logger) << "Found MeteoStation but no weather Data available, try again in 1 minute";
|
|
QTimer::singleShot(6000, this, &HandlerEffectShow::onSendMeteoData);
|
|
return;
|
|
}
|
|
// trigger meteo data to effect show vehicle
|
|
int equipmentNumber = m_mainHandler->handlerPpmData()->getEquipmentNumber(effectShow.esmParticipantId);
|
|
m_mainHandler->handlerTabData()->meteoData(equipmentNumber, effectShow.esmParticipantId, meteoData);
|
|
|
|
// meteo data available
|
|
qint64 deltaTime = m_mainHandler->dds()->currentPartitionTime() - meteoData.timeStamp();
|
|
if (deltaTime > (60 * 15 * 1000))
|
|
WARNING_LOG(m_logger) << "Age of meteo data=" << (deltaTime / 60000) << "min for vehicle: " << equipmentNumber;
|
|
}
|
|
else
|
|
{
|
|
int equipmentNumber = m_mainHandler->handlerPpmData()->getEquipmentNumber(effectShow.esmParticipantId);
|
|
WARNING_LOG(m_logger) << "Meteo data not available for effect show vehicle: " << equipmentNumber;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void HandlerEffectShow::onSendMeteoData()
|
|
{
|
|
for (ObjectEffectShow *obj : qAsConst(m_effectShowObjMap))
|
|
{
|
|
const Database::EsmEffectShow &effectShow = obj->getData();
|
|
if (effectShow.esmParticipantId == -1)
|
|
continue; // no actor allocated
|
|
|
|
if ((effectShow.orderConfirmation < EffectShowManagement::OrderConfirmation_e_def::DriveOff) ||
|
|
(effectShow.orderConfirmation >= EffectShowManagement::OrderConfirmation_e_def::OrderCarriedOut))
|
|
continue; // effect show not processed
|
|
|
|
triggerMeteoData(obj);
|
|
}
|
|
}
|
|
|
|
void HandlerEffectShow::onCleanUp()
|
|
{
|
|
DEBUG_LOG(m_logger) << "Start Cleanup ";
|
|
QVector<ObjectEffectShow * > objects;
|
|
for (ObjectEffectShow *obj : qAsConst(m_effectShowObjMap))
|
|
{
|
|
const Database::EsmEffectShow &effectShow = obj->getData();
|
|
if (effectShow.orderConfirmation == OrderConfirmation_e::OrderCarriedOut || effectShow.startTime <= 0 || effectShow.id <= 0)
|
|
continue;
|
|
|
|
DEBUG_LOG(m_logger) << "Effect show with ID " << effectShow.id << " will expire at: " << QDateTime::fromMSecsSinceEpoch(effectShow.startTime + effectShow.duration + CLEANUPTIME).toString() << " current time: " << QDateTime::fromMSecsSinceEpoch(m_mainHandler->dds()->currentPartitionTime()).toString();
|
|
if ((effectShow.startTime + effectShow.duration + CLEANUPTIME) < m_mainHandler->dds()->currentPartitionTime())
|
|
{
|
|
//remove object
|
|
DEBUG_LOG(m_logger) << "Remove Effect Show " << effectShow.id ;
|
|
objects.append(obj);
|
|
}
|
|
}
|
|
|
|
while (objects.size() > 0)
|
|
removeEffectShow(objects.takeLast(), false, true);
|
|
}
|
|
|
|
QString HandlerEffectShow::enumToString(HandlerEffectShow::KindOfModification_e mod)
|
|
{
|
|
switch (mod)
|
|
{
|
|
case HandlerEffectShow::KindOfModification_e::Added:
|
|
return QLatin1String("KindOfModification_e::Added");
|
|
case HandlerEffectShow::KindOfModification_e::ModifiedArea:
|
|
return QLatin1String("KindOfModification_e::ModifiedArea");
|
|
case HandlerEffectShow::KindOfModification_e::ModifiedData:
|
|
return QLatin1String("KindOfModification_e::ModifiedData");
|
|
case HandlerEffectShow::KindOfModification_e::Removed:
|
|
return QLatin1String("KindOfModification_e::Removed");
|
|
case HandlerEffectShow::KindOfModification_e::Paused:
|
|
return QLatin1String("KindOfModification_e::Paused");
|
|
case HandlerEffectShow::KindOfModification_e::Continued:
|
|
return QLatin1String("KindOfModification_e::Continued");
|
|
case HandlerEffectShow::KindOfModification_e::None:
|
|
return QLatin1String("KindOfModification_e::None");
|
|
}
|
|
Q_ASSERT(false);
|
|
return QStringLiteral("Unknown KindOfModification_e (%1)").arg(int(mod));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
} // namespace EffectShowManagement
|