Files
qt5-legatus-legacy/Lts/Services/EffectShowManagement/effect_show_effect_cluster.cpp
T
2026-08-13 18:33:10 +02:00

316 lines
13 KiB
C++
Executable File

/**
* Handler for the HMI language
* $Id$
* $HeadURL$
* $Author$
*/
#include "effect_show_effect_cluster.h"
#include <QJsonDocument>
#include <QObject>
#include "settings.h"
const static int DEFAULT_EFFECT_DURATION = 777777;
namespace EffectShowManagement
{
EffectShowEffectCluster::EffectShowEffectCluster(const AreaEffectSimulation::EffectCluster &effectCluster,
const std::shared_ptr<HandlerPdmData> &handlerPdmData)
: m_effectCluster(effectCluster)
, m_handlerPdmData(handlerPdmData)
, m_numOfEffectShows(0)
, m_logger(getLogger("EffectShowEffectCluster"))
{
}
//=============================================================================
int EffectShowEffectCluster::getNumOfEffectShows()
{
if (m_numOfEffectShows == 0)
calculateSquare();
return m_numOfEffectShows;
}
//=============================================================================
Database::EsmEffectShow EffectShowEffectCluster::getEffectShow(int idx)
{
if (m_numOfEffectShows == 0)
calculateSquare();
Database::EsmEffectShow esmEffectShow;
if (!m_handlerPdmData->isSmoke(m_effectCluster.chargeStruct()))
{
int indX = idx % m_areasWidth.numOfAreas;
int indY = idx / m_areasWidth.numOfAreas;
// calculate lower left position
double x_off = 0.0;
for (int i = 0; i < indX; ++i)
x_off += m_areasWidth.side(i);
double y_off = 0.0;
for (int i = 0; i < indY; ++i)
y_off += m_areasDepth.side(i);
LtsCoordTrans::UtmCoordinate lowerLeftPos = m_lowerLeftPos;
lowerLeftPos.x = lowerLeftPos.x + x_off;
lowerLeftPos.y = lowerLeftPos.y + y_off;
LtsCoordTrans::UtmCoordinate lowerLeftPosRotated = rotate(lowerLeftPos, m_lowerLeftPos, rotationRad());
// calculate center position
LtsCoordTrans::UtmCoordinate centerPos = lowerLeftPos;
centerPos.x = centerPos.x + m_areasWidth.side(indX) / 2.;
centerPos.y = centerPos.y + m_areasDepth.side(indY) / 2.;
LtsCoordTrans::UtmCoordinate centerPosRotated = rotate(centerPos, m_lowerLeftPos, rotationRad());
esmEffectShow.id = 0;
esmEffectShow.name = QStringLiteral("EXP");
esmEffectShow.startTime = m_effectCluster.effectStart().is_set() ? m_effectCluster.effectStart().get() : 0;
esmEffectShow.centerPosition = centerPosRotated.geographic();
esmEffectShow.idAreaEffectSimulation = m_effectCluster.id();
esmEffectShow.esmParticipantId = -1;
esmEffectShow.nameAreaEfffectSimulation = QString::fromStdString(m_effectCluster.name());
esmEffectShow.numOfVolley = getNumberOfVolley();
esmEffectShow.shotsPerVolley = getShotsPerArea() / esmEffectShow.numOfVolley;
esmEffectShow.typeOfAmmunition = m_effectCluster.chargeStruct().chargeTypeId();
// can there be more then 48 shoots?
if (esmEffectShow.shotsPerVolley > 48)
esmEffectShow.shotsPerVolley = 48;// (48 / esmEffectShow.numOfVolley);
if (esmEffectShow.shotsPerVolley <= 0)
esmEffectShow.shotsPerVolley = 1;
DEBUG_LOG(m_logger) << "recalc effectDuration ";
if (m_effectCluster.effectDuration() == DEFAULT_EFFECT_DURATION)
{
QJsonObject probObject = QJsonDocument::fromJson(QByteArray::fromStdString(m_effectCluster.properties())).object();
AreaEffectSimulation::FiringType firingType = AreaEffectSimulation::FiringType::ReportReadyToFire;
if (probObject.contains(QStringLiteral("abfeuerungsArt")))
firingType = static_cast<AreaEffectSimulation::FiringType::inner_enum>(probObject[QStringLiteral("abfeuerungsArt")].toInt());
if (firingType == AreaEffectSimulation::FiringType::FireOnCommand)
{
//use default
esmEffectShow.duration = Settings::getDefaultCadence() * esmEffectShow.shotsPerVolley;
DEBUG_LOG(m_logger) << " recalc effectDuration use default value as fireoncommand " << esmEffectShow.duration ;
}
else
{
// use cadence
if (m_effectCluster.effectors().size()) //should always be there!
{
esmEffectShow.duration = m_effectCluster.effectors().at(0).chargeAmount() * m_handlerPdmData.get()->getCadence(m_effectCluster.effectors().at(0).chargeStruct().chargeTypeId());
DEBUG_LOG(m_logger) << " recalc effectDuration use cadence value " << esmEffectShow.duration << " effector shots: " << m_effectCluster.effectors().at(0).chargeAmount() << " cadence " << m_handlerPdmData.get()->getCadence(m_effectCluster.effectors().at(0).chargeStruct().chargeTypeId());
}
}
}
else
{
DEBUG_LOG(m_logger) << "Use effectDuration directly ";
esmEffectShow.duration = m_effectCluster.effectDuration();
}
esmEffectShow.lowerLeftPosition = lowerLeftPosRotated.geographic();
esmEffectShow.areaWidth = m_areasWidth.side(indX);
esmEffectShow.areaDepth = m_areasDepth.side(indY);
esmEffectShow.areaRotation = m_effectCluster.area().rotation() + 90;
DEBUG_LOG(m_logger) << "\nWidth: " << m_effectCluster.area().width() << " Height: " << m_effectCluster.area().height()
<< "\nRotated LL Pos: " << lowerLeftPosRotated.mgrs()
<< "\nduration: " << esmEffectShow.duration
<< "\nRotated Center Pos: " << centerPosRotated.mgrs()
<< "\nOffset x,y: " << x_off << " , " << y_off
<< "\nSide x,y: " << m_areasWidth.side(indX) << " , " << m_areasDepth.side(indY)
<< "\nindX: " << indX << " grid " << m_areasWidth.numSideLength1 << ' ' << m_areasWidth.sideLength1 << ' ' << m_areasWidth.numSideLength2 << ' ' << m_areasWidth.sideLength2
<< "\nindY: " << indY << " grid " << m_areasDepth.numSideLength1 << ' ' << m_areasDepth.sideLength1 << ' ' << m_areasDepth.numSideLength2 << ' ' << m_areasDepth.sideLength2;
}
else
{
LtsCoordTrans::UtmCoordinate lowerLeftPos = m_lowerLeftPos; //unnötig?
LtsCoordTrans::UtmCoordinate lowerLeftPosRotated = rotate(lowerLeftPos, m_lowerLeftPos, rotationRad());
// calculate center position
LtsCoordTrans::UtmCoordinate centerPos = lowerLeftPosRotated;
centerPos.x = centerPos.x + m_effectCluster.area().width() / 2.;
centerPos.y = centerPos.y + m_effectCluster.area().height() / 2.;
LtsCoordTrans::UtmCoordinate centerPosRotated = rotate(centerPos, m_lowerLeftPos, rotationRad());
esmEffectShow.id = 0;
esmEffectShow.name = QStringLiteral("EXP");
esmEffectShow.startTime = m_effectCluster.effectStart().is_set() ? m_effectCluster.effectStart().get() : 0;
esmEffectShow.duration = m_effectCluster.effectDuration();
esmEffectShow.centerPosition = centerPosRotated.geographic();
esmEffectShow.idAreaEffectSimulation = m_effectCluster.id();
esmEffectShow.esmParticipantId = -1;
esmEffectShow.nameAreaEfffectSimulation = QString::fromStdString(m_effectCluster.name());
esmEffectShow.typeOfAmmunition = m_effectCluster.chargeStruct().chargeTypeId();
esmEffectShow.numOfVolley = 1;
esmEffectShow.shotsPerVolley = 1;
esmEffectShow.lowerLeftPosition = lowerLeftPosRotated.geographic();
esmEffectShow.areaWidth = m_effectCluster.area().width();
esmEffectShow.areaDepth = m_effectCluster.area().height();
esmEffectShow.areaRotation = m_effectCluster.area().rotation() + 90;
DEBUG_LOG(m_logger) << "\nWidth: " << m_effectCluster.area().width() << " Height: " << m_effectCluster.area().height()
<< "\nRotated LL Pos: " << lowerLeftPosRotated.mgrs()
<< "\nRotated Center Pos: " << centerPosRotated.mgrs()
<< "\nSide x,y: " << m_effectCluster.area().width() << " , " << m_effectCluster.area().height();
}
return esmEffectShow;
}
//=============================================================================
void EffectShowEffectCluster::updateEffectShow(Database::EsmEffectShow &data)
{
DEBUG_LOG(m_logger) << "update EffectSHow for (" << data.id << ")";
data.nameAreaEfffectSimulation = QString::fromStdString(m_effectCluster.name());
data.startTime = m_effectCluster.effectStart().is_set() ? m_effectCluster.effectStart().get() : 0;
DEBUG_LOG(m_logger) << "Recalc effectDuration ";
if (m_effectCluster.effectDuration() == DEFAULT_EFFECT_DURATION)
{
QJsonObject probObject = QJsonDocument::fromJson(QByteArray::fromStdString(m_effectCluster.properties())).object();
AreaEffectSimulation::FiringType firingType = AreaEffectSimulation::FiringType::ReportReadyToFire;
if (probObject.contains(QStringLiteral("abfeuerungsArt")))
firingType = static_cast<AreaEffectSimulation::FiringType::inner_enum>(probObject[QStringLiteral("abfeuerungsArt")].toInt());
if (firingType == AreaEffectSimulation::FiringType::FireOnCommand)
{
//use default
data.duration = Settings::getDefaultCadence() * data.shotsPerVolley;
DEBUG_LOG(m_logger) << " recalc effectDuration use default value as fireoncommand " << data.duration ;
}
else
{
// use cadence
if (m_effectCluster.effectors().size()) //should always be there!
{
data.duration = m_effectCluster.effectors().at(0).chargeAmount() * m_handlerPdmData.get()->getCadence(m_effectCluster.effectors().at(0).chargeStruct().chargeTypeId());
DEBUG_LOG(m_logger) << " recalc effectDuration use cadence value " << data.duration << " effector shots: " << m_effectCluster.effectors().at(0).chargeAmount() << " cadence " << m_handlerPdmData.get()->getCadence(m_effectCluster.effectors().at(0).chargeStruct().chargeTypeId());
}
}
}
else
{
DEBUG_LOG(m_logger) << "Use effectDuration directly ";
data.duration = m_effectCluster.effectDuration();
}
if (data.shotsPerVolley > 48)
data.shotsPerVolley = 48;//(48 / data.numOfVolley);
if (data.shotsPerVolley <= 0)
data.shotsPerVolley = 1;
data.typeOfAmmunition = m_effectCluster.chargeStruct().chargeTypeId();
data.esmParticipantId = (m_effectCluster.esmParticipantIds().size() > 0)
? m_effectCluster.esmParticipantIds().at(0)
: -1;
}
//-----------------------------------------------------------------------------
void EffectShowEffectCluster::calculateSquare()
{
Core::GeoPosition2D geoPos = m_effectCluster.area().cornerBottomLeft();
m_lowerLeftPos = LtsCoordTrans::UtmCoordinate::fromGeographic(geoPos.lon(), geoPos.lat());
// Calculate squares.
m_areasWidth = getAreasSideLength(m_effectCluster.area().width()); // Squares in x-direction
m_areasDepth = getAreasSideLength(m_effectCluster.area().height()); // Squares in y-direction
m_numOfEffectShows = m_handlerPdmData->effectShowCount(m_effectCluster.chargeStruct());
}
//static ----------------------------------------------------------------------
LtsCoordTrans::UtmCoordinate EffectShowEffectCluster::rotate(const LtsCoordTrans::UtmCoordinate &p, const LtsCoordTrans::UtmCoordinate &c, double angle)
{
LtsCoordTrans::UtmCoordinate res = p; // copy zone, northp
res.x = ((p.x - c.x) * cos(angle)) - ((p.y - c.y) * sin(angle)) + c.x;
res.y = ((p.x - c.x) * sin(angle)) + ((p.y - c.y) * cos(angle)) + c.y;
return res;
}
//static ----------------------------------------------------------------------
EffectShowEffectCluster::areas_t EffectShowEffectCluster::getAreasSideLength(double sideLength)
{
areas_t res;
int sl = qRound(sideLength + 0.5);
int n50 = (sl < 25) ? 1 : (sl + 25) / 50; // number of 50m squares
int n300 = n50 / 6; // number of 300m squares
int len = n50 * 50; // length to be diveded into squares
res.numOfAreas = ((n300 * 6) == n50) ? n300 : n300 + 1; // number of areas at all
res.sideLength1 = (len / (res.numOfAreas * 50)) * 50;
res.numSideLength2 = (len - (res.numOfAreas * res.sideLength1)) / 50;
res.sideLength2 = res.sideLength1 + 50;
res.numSideLength1 = res.numOfAreas - res.numSideLength2;
//qCritical() << "sl = " << sl << " n50= " << n50 << " n300 = " << n300 << " len = "
// << len << " numOfAreas = " << res.numOfAreas << " sideLength1 = " << res.sideLength1;
return res;
}
//-----------------------------------------------------------------------------
int EffectShowEffectCluster::getNumberOfVolley() const
{
const int v = getShotsPerArea();
return getNumberOfVolley(v);
}
//-----------------------------------------------------------------------------
int EffectShowEffectCluster::getShotsPerArea() const
{
if (!m_numOfEffectShows)
return 0;
int v = 0;
for (const auto &effector: m_effectCluster.effectors())
{
v+= effector.chargeAmount();
}
return v / m_numOfEffectShows; //split even across all effect shows
}
int EffectShowEffectCluster::getShotsPerArea(int areas) const
{
if (areas == 0)
return 0;
int v = 0;
for (const auto &effector: m_effectCluster.effectors())
{
v+= effector.chargeAmount();
}
return v / areas;
}
int EffectShowEffectCluster::getNumberOfVolley(int v)
{
if (v < 3) // <= 0 should not happen but did...
return qMax(1, v);
if (v <= 25)
return 3;
if (v <= 50)
return 6;
if (v <= 100)
return 9;
if (v <= 150)
return 12;
if (v <= 200)
return 15;
return 18;
}
//-----------------------------------------------------------------------------
double EffectShowEffectCluster::rotationRad() const
{
return -m_effectCluster.area().rotation() * LtsCoordTrans::deg2rad();
}
//-----------------------------------------------------------------------------
} // Namespace EffectShowManagement