316 lines
13 KiB
C++
Executable File
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
|