Files
qt5-legatus-legacy/Lts/Services/CentralEffectSimulation/Plugins/ArtillerySound/handler_artillerie_sound.cpp
T
2026-08-13 18:33:10 +02:00

224 lines
8.1 KiB
C++
Executable File

/**
* Handler for player data
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2017-02-20
*/
#include "handler_artillerie_sound.h"
#include "settings.h"
#include <LtsUtilsSettings/settings.h>
#include <QNetworkReply>
#include <qmath.h>
#include <math.h>
namespace CesArtillerySound
{
HandlerArtillerieSound::HandlerArtillerieSound(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &buildingDataHandler,
QObject *parent)
: QObject(parent)
, m_ddsHandler(ddsHandler)
, m_handlerBuildingData(buildingDataHandler)
, m_logger(CentralEffectSimulation::getLogger("Plugin.ArtillerySound.HandlerArtillerieSound"))
{
}
HandlerArtillerieSound::~HandlerArtillerieSound()
{
} // end of dtor()
//-----------------------------------------------------------------------------
bool HandlerArtillerieSound::init()
{
if (Settings::cesPlayArtillerieSounds())
{
DEBUG_LOG(m_logger) << "init with Artillerie-Sounds";
auto dtcAes = m_ddsHandler->dtcAes();
dtcAes->enableExplosionSingle();
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::explosionSingleChanged,
this, &HandlerArtillerieSound::onExplosionSingleChanged);
dtcAes->enableTechnicalArea();
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::technicalAreaChanged,
this, &HandlerArtillerieSound::onTechnicalAreaChanged);
}
else
DEBUG_LOG(m_logger) << "init without Artillerie-Sounds";
return true;
} // end of init()
//-----------------------------------------------------------------------------
void HandlerArtillerieSound::onExplosionSingleChanged(const AreaEffectSimulation::ExplosionSingle &data, DataModification modType)
{
bool handleExplosion = false;
if (modType != DataModification::eAdded &&
modType != DataModification::eModified)
{
m_explosionSingleState.remove(data.id());
return;
}
if (data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsRemoved)
{
DEBUG_LOG(m_logger) << "Remove SingleExplosion";
m_explosionSingleState.remove(data.id());
return;
}
// Only handle transitions from prepared or fired to activated
if ((m_explosionSingleState.value(data.id()) == AreaEffectSimulation::AesEffectState_def::EsPrepared ||
m_explosionSingleState.value(data.id()) == AreaEffectSimulation::AesEffectState_def::EsFired) &&
data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsActivated)
{
DEBUG_LOG(m_logger) << "Handle SingleExplosion";
handleExplosion = true;
}
m_explosionSingleState.insert(data.id(), data.effectStateId());
DEBUG_LOG(m_logger) << "Got ExplosionSingle State=" << data.effectStateId()
<< " id=" << data.id();
if (handleExplosion)
{
DEBUG_LOG(m_logger) << "Handle ExplosionSingle (EsActivated) HandlerArtillerieSound";
auto assetPositions = m_handlerBuildingData->getAssetPositions();
///////////////////////////////////////////////////////////////////
/// Play Sound to each EGCU and OSGU volume depends on distance
///////////////////////////////////////////////////////////////////
INFO_LOG(m_logger) << "printAssetPositions: ";
QHashIterator<int, CentralEffectSimulation::HandlerBuildingData::AssetPosition> i(assetPositions);
while (i.hasNext())
{
i.next();
INFO_LOG(m_logger) << "printAssetPositions: "
<< i.key() << ": " << i.value().structureElementId
<< " type = " << i.value().mountingPointType
<< " hostname =" << i.value().hostname
<< " pos=" << i.value().geoPosition
<< " posUtm=" << i.value().positionUtm.x()
<< "/" << i.value().positionUtm.y()
<< " zone=" << i.value().zone;
// Calculate the distance between the speaker and the explosion
const QPointF posExplosionUtm = CentralEffectSimulation::geographic2Utm(data.impactPosition(), i.value().zone);
const qreal distance = qSqrt(qPow(posExplosionUtm.x() - i.value().positionUtm.x(), 2) + qPow(posExplosionUtm.y() - i.value().positionUtm.y(), 2));
int sound = Settings::cesSoundId();
const qreal distanceThreshold = Settings::cesDistanceThreshold(); // [m]
const qreal factor = Settings::cesFactor();
const qreal cesReduceFactor = Settings::cesReduceFactor();
INFO_LOG(m_logger) << "Distance to Explosion =" << distance
<< " hostname =" << i.value().hostname
<< " distanceThreshold=" << distanceThreshold
<< " factor=" << factor;
qreal volumePercent = 100;
if (distance > distanceThreshold)
volumePercent = factor * log10(distance) * cesReduceFactor;
QString user = Settings::cesUser();
QString passwd = Settings::cesPasswd();
playSound(user, passwd, i.value().hostname, sound, volumePercent);
}
}
} // onExplosionSingleChanged
void HandlerArtillerieSound::playSound(QString &user, QString &passwd, const QString &host, int &sound, qreal &volume)
{
QUrl url;
QString request = QStringLiteral("http://%1/hitsound.php?sound=%2&vol=%3")
.arg(host)
.arg(sound)
.arg(volume);
url.setUrl(request);
url.setUserName(user);
url.setPassword(passwd);
DEBUG_LOG(m_logger) << "startRequest: " << url.toString();
startRequest(url);
}
void HandlerArtillerieSound::startRequest(const QUrl &requestedUrl)
{
DEBUG_LOG(m_logger) << "startRequest: " << requestedUrl.toString();
m_httpRequestAborted = false;
auto reply = m_qnam.get(QNetworkRequest(requestedUrl));
connect(reply, &QNetworkReply::finished, this, &HandlerArtillerieSound::httpFinished);
}
void HandlerArtillerieSound::httpFinished()
{
DEBUG_LOG(m_logger) << "httpFinished";
auto reply = qobject_cast<QNetworkReply *>(sender());
if (!reply)
return;
if (m_httpRequestAborted)
{
ERROR_LOG(m_logger) << "httpRequestAborted";
reply->deleteLater();
return;
}
if (reply->error())
{
QNetworkRequest request = reply->request();
QUrl url = request.url();
ERROR_LOG(m_logger) << "reply->error: " << reply->errorString()
<< " host=" << url.host()
<< " query='" << url.query()
<< "' '" << qUtf8Printable(url.toString()) << "'";
reply->deleteLater();
return;
}
// Sucess
//parse the reply JSON and display result in the UI
const QByteArray json(reply->readAll());
DEBUG_LOG(m_logger) << "Sucess " << json;
reply->deleteLater();
}
void HandlerArtillerieSound::onTechnicalAreaChanged(const AreaEffectSimulation::TechnicalArea &data, DataModification modType)
{
if (modType != DataModification::eAdded &&
modType != DataModification::eModified)
{
m_technicalAreas.remove(data.id());
return;
}
if (data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsRemoved)
{
DEBUG_LOG(m_logger) << "Remove TechnicalArea";
m_technicalAreas.remove(data.id());
return;
}
if (data.type() == AreaEffectSimulation::AesTechnicalAreaType_def::TatSoundZone)
{
int zone = -1;
m_technicalAreas.insert(data.id(), data);
DEBUG_LOG(m_logger) << "Handle TechnicalArea HandlerArtillerieSound id=" << data.id();
QPointF cornerButtomLeft = CentralEffectSimulation::geographic2Utm(data.area().cornerBottomLeft(), &zone);
qreal x = cornerButtomLeft.x() + data.area().width() / 2;
qreal y = cornerButtomLeft.y() + data.area().height() / 2;
QPointF center(x, y);
DEBUG_LOG(m_logger) << "Handle TechnicalArea HandlerArtillerieSound cornerButtomLeft = " << cornerButtomLeft.x() << "/" << cornerButtomLeft.y()
<< " zone=" << zone;
DEBUG_LOG(m_logger) << "Handle TechnicalArea HandlerArtillerieSound center = " << center.x() << "/" << center.y()
<< " zone=" << zone;
}
} // onTechnicalAreaChanged
} // namespace CesArtillerySound