Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+924
@@ -0,0 +1,924 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Api for VWM
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLSA, 2013-03-05
|
||||
*/
|
||||
|
||||
#include "vwm_api.h"
|
||||
#include "vwm_deposition.h"
|
||||
#include "vwm_xml_reader.h"
|
||||
#include "vwm_state_store.h"
|
||||
#include "vwm_math.h"
|
||||
#include <QDateTime>
|
||||
#include <settings.h>
|
||||
#include <QFile>
|
||||
#include <initializer_list>
|
||||
#ifdef LTS_DEBUG
|
||||
// For ShotResult.cvs
|
||||
# include <QTextStream>
|
||||
# include <sstream>
|
||||
#endif // LTS_DEBUG
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonParseError>
|
||||
#include <QDebug>
|
||||
|
||||
namespace BuildingControlUnit
|
||||
{
|
||||
namespace VWM
|
||||
{
|
||||
Api::Api(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_lastHitResult(HitResult())
|
||||
, m_logger(BuildingControlUnit::getLogger("VWM.Api"))
|
||||
{}
|
||||
|
||||
bool Api::init(const QString &chargesConfig,
|
||||
const QString &vulBuildingConfig,
|
||||
const BuildingBsmConfig &bsmConfig,
|
||||
const bool initBuilding)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "chargesConfig=" << chargesConfig;
|
||||
if (!XmlReader::readCharges(chargesConfig, m_chargeMap))
|
||||
return false;
|
||||
if (!XmlReader::readBuilding(vulBuildingConfig, m_building))
|
||||
return false;
|
||||
|
||||
// Fake:
|
||||
QString fltXml = QString(QStringLiteral("/opt/BuildingModels/StaticMeshes/%1.flt.xml")).arg(m_building.name());
|
||||
if (!XmlReader::readBuildingGeometry(fltXml, m_buildingRoomGeometry ))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error reading buildingRoomGeometry from file: " << fltXml << "'";
|
||||
// return false;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "Building buildingRoomGeometry read successfully from file: " << fltXml << "'";
|
||||
|
||||
|
||||
|
||||
int numberOfRemoved = m_building.cleanupPolygons();
|
||||
int numberOfDuplicates = m_building.checkPolygons();
|
||||
DEBUG_LOG(m_logger) << "Building cleanupPolygons: " << m_building.name() << "' -> " << numberOfRemoved << " points removed";
|
||||
if (numberOfDuplicates > 0)
|
||||
ERROR_LOG(m_logger) << "Building checkPolygons: " << m_building.name() << "' -> " << numberOfDuplicates << " duplicates";
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "Building checkPolygons: " << m_building.name() << "' -> " << numberOfDuplicates << " duplicates";
|
||||
|
||||
|
||||
m_bsmMap = bsmConfig.bsmMap;
|
||||
m_building.init();
|
||||
if (!initBuilding)
|
||||
StateStore::loadState(m_building, m_lastHitResult, m_contaminationStates);
|
||||
else
|
||||
StateStore::saveState(m_building, m_lastHitResult, m_contaminationStates);
|
||||
m_lastHitResult.rooms = m_building.roomStates();
|
||||
m_lastHitResult.damageState = m_building.damageState();
|
||||
m_lastHitResult.damagePercentNew = m_building.damagePercent();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Api::onHitOptical(qint64 timeMSec, int sensorId, int originatorId, int chargeTypeId, int deposition1, int deposition2)
|
||||
{
|
||||
// Reale Position berechnen (Ablage)
|
||||
// 1. zugehöriges BSM suchen
|
||||
const Bsm bsm = m_bsmMap.value(sensorId);
|
||||
// 2. ist BSM gültig
|
||||
if (!bsm.isValid())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Given bsm id " << sensorId << " is not in our internal bsm list!";
|
||||
return;
|
||||
}
|
||||
// 3. Ablage berechnen (wenn deposition1 != 0 || deposition2 != 0)
|
||||
const LtsUtils::QPoint3D depositionRel = getDeposition(deposition1, deposition2, bsm.direction);
|
||||
|
||||
Hit hit;
|
||||
hit.effectTimeMSec = timeMSec;
|
||||
hit.sensorId = sensorId;
|
||||
hit.originatorId = originatorId;
|
||||
hit.originatorType = OriginatorType::DirectHit;
|
||||
hit.chargeTypeId = chargeTypeId;
|
||||
hit.position = bsm.position + depositionRel;
|
||||
hit.direction = bsm.direction * -1; // bsm looks away from building
|
||||
|
||||
sendHitToVwm(hit);
|
||||
}
|
||||
|
||||
void Api::onSetEffectStatesRequest(const QString &hostname, const QVector<BcuEffectState> &effectStates)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onSetEffectStatesRequest:"
|
||||
<< " hostname= " << hostname
|
||||
<< " effectStes.zize=" << effectStates.size();
|
||||
|
||||
QJsonObject overridesObj;
|
||||
|
||||
if (hostname.isEmpty())
|
||||
{
|
||||
for (const BcuEffectState &es : effectStates)
|
||||
{
|
||||
if (es.type == BcuEffectType::BET_BsmFlash)
|
||||
{
|
||||
if (es.effectOverride == BcuEffectOverride::BEO_Off)
|
||||
{
|
||||
overridesObj.insert(QStringLiteral("flash"), 0);
|
||||
DEBUG_LOG(m_logger) << "flash = 0";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QJsonArray relayStateArray;
|
||||
for (const BcuEffectState &es : effectStates)
|
||||
{
|
||||
if (es.effectOverride == BcuEffectOverride::BEO_Auto)
|
||||
continue;
|
||||
|
||||
if (es.type == BcuEffectType::BET_Relay)
|
||||
{
|
||||
QJsonObject relayStateObj;
|
||||
relayStateObj[QString::number(es.id)]=es.effectOverride;
|
||||
DEBUG_LOG(m_logger) << "relay = " << QString::number(es.id)
|
||||
<< " " << es.effectOverride;
|
||||
relayStateArray.append(relayStateObj);
|
||||
}
|
||||
else if (es.type == BcuEffectType::BET_BackgroundSound)
|
||||
{
|
||||
overridesObj.insert(QStringLiteral("sound"), es.effectOverride);
|
||||
DEBUG_LOG(m_logger) << "sound=" << es.effectOverride;
|
||||
}
|
||||
}
|
||||
overridesObj.insert(QStringLiteral("relays"), relayStateArray);
|
||||
}
|
||||
|
||||
QJsonObject propertiesObj;
|
||||
propertiesObj[QStringLiteral("Overrides")] = overridesObj;
|
||||
|
||||
QString totalString = QString::fromLatin1(QJsonDocument(propertiesObj).toJson(QJsonDocument::Compact));
|
||||
DEBUG_LOG(m_logger) << "totalString=" << totalString;
|
||||
m_building.setSegmentProperties(hostname,totalString);
|
||||
StateStore::saveState(m_building, m_lastHitResult, m_contaminationStates);
|
||||
}
|
||||
|
||||
void Api::dumpHitResult(const Hit &hit, const HitResult &result, const Charge &chargeOrg, const Charge &charge, const QString &context)
|
||||
{
|
||||
// write ShotResult.cvs
|
||||
static QString filename = QString(QLatin1String("/tmp/ShotResult_%1_%2.csv")).arg(m_building.name()).arg(result.effectTimeMSec);
|
||||
QFile data(filename);
|
||||
if(data.open(QFile::WriteOnly | QIODevice::Append/* |QFile::Truncate*/ ))
|
||||
{
|
||||
QTextStream output(&data);
|
||||
|
||||
output << "EffectTime at," << QDateTime::fromMSecsSinceEpoch(result.effectTimeMSec).toString(QStringLiteral("yyyy.MM.dd hh:mm::ss")) << "\n";
|
||||
output << ",(" << result.effectTimeMSec << ")\n";
|
||||
|
||||
output << "Bldg-Name," << m_building.name() << "\n";
|
||||
|
||||
output << "Context," << context << "\n";
|
||||
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << result.originatorType;
|
||||
output << "OriginatorType," << QString::fromStdString(stream.str()) << "\n";
|
||||
}
|
||||
|
||||
{ // some values, more or less 'const':
|
||||
output << " [BCU]minimumRemainEffectThreshold," << Settings::minimumRemainEffectThreshold() << "\n";
|
||||
output << " [BCU]transitionMultiplier," << Settings::transitionMultiplier() << "\n";
|
||||
output << " buildingProtectionLevel," << m_building.buildingProtectionLevel() << "\n";
|
||||
}
|
||||
|
||||
output << "ChargeTypeId," << result.chargeTypeId << "\n";
|
||||
|
||||
output << " Original dstrctvZF/pntrtnWF, "
|
||||
<< QString::number(chargeOrg.destructiveFactor) << QStringLiteral("/") << QString::number(chargeOrg.penetrationEffect)<< "\n";
|
||||
output << " Current dstrctvZF/pntrtnWF, "
|
||||
<< QString::number(charge.destructiveFactor) << QStringLiteral("/") << QString::number(charge.penetrationEffect)<< "\n";
|
||||
|
||||
output << "OriginatorId," << result.originatorId << "\n";
|
||||
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << hit.typeOfHit;
|
||||
output << "TypeOfHit," << QString::fromStdString(stream.str()) << "\n";
|
||||
output << "BelowGround(Hack)," << m_building.isLastHitPositionBelowGroundHack() << "\n";
|
||||
}
|
||||
|
||||
output << "RoomId," << m_building.lastHitPosition().roomId << "\n";
|
||||
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << result.damageState;
|
||||
output << "DamageState," << QString::fromStdString(stream.str()) << "\n";
|
||||
}
|
||||
|
||||
output << "DamagePercentNew," << result.damagePercentNew << "\n";
|
||||
output << "DamagePercentOld," << result.damagePercentOld << "\n";
|
||||
|
||||
output << ",," << "\n";
|
||||
|
||||
output << "RoomId,damagePercent,remainingEffectPercent,directHit" << "\n";
|
||||
for (const HitRoom &hitRoom : qAsConst(result.rooms))
|
||||
{
|
||||
output << hitRoom.roomId << ","
|
||||
<< hitRoom.damagePercent << ","
|
||||
<< hitRoom.remainingEffectPercent << ","
|
||||
<< hitRoom.directHit << ","
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
output << ",," << "\n";
|
||||
output << ",," << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void Api::onHitOpticalOC(qint64 timeMSec, int sensorId, int originatorId, int chargeTypeId, DamageState damageState)
|
||||
{
|
||||
Hit hit;
|
||||
const Bsm bsm = m_bsmMap.value(sensorId);
|
||||
if (bsm.isValid())
|
||||
{
|
||||
hit.position = bsm.position;
|
||||
hit.direction = bsm.direction * -1; // bsm looks away from building
|
||||
}
|
||||
hit.sensorId = sensorId;
|
||||
hit.effectTimeMSec = timeMSec;
|
||||
hit.damageStateOverride = damageState;
|
||||
hit.chargeTypeId = chargeTypeId;
|
||||
hit.originatorId = originatorId;
|
||||
hit.originatorType = OriginatorType::OC;
|
||||
|
||||
sendHitToVwm(hit);
|
||||
}
|
||||
|
||||
void Api::onHitEcc(int originatorId, DamageState damageState, const QVector<int> &roomIds)
|
||||
{
|
||||
Hit hit;
|
||||
hit.effectTimeMSec = QDateTime::currentMSecsSinceEpoch();
|
||||
hit.damageStateOverride = damageState;
|
||||
hit.originatorId = originatorId;
|
||||
hit.originatorType = OriginatorType::ECC;
|
||||
hit.affectedRoomIds = roomIds;
|
||||
|
||||
sendHitToVwm(hit);
|
||||
}
|
||||
|
||||
void Api::onSetContaminationState(const std::vector<ContaminationState> &contaminationStates)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "contaminationStates.size=" << contaminationStates.size();
|
||||
|
||||
for (const auto &newcs : contaminationStates)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "newcs.damagePercentNew=" << newcs.damagePercentNew
|
||||
<< " m_lastHitResult.damagePercentNew=" << m_lastHitResult.damagePercentNew;
|
||||
if ( newcs.damagePercentNew > m_lastHitResult.damagePercentNew)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "newcs.damagePercentNew=" << newcs.damagePercentNew;
|
||||
m_lastHitResult.damagePercentNew = newcs.damagePercentNew;
|
||||
}
|
||||
if (m_contaminationStates.contains(newcs.aesId))
|
||||
{
|
||||
|
||||
//used in qt >5.14
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,10,0)
|
||||
//satisfy 42.3 Build
|
||||
QSet<int> roomsSet;
|
||||
for (const auto i: qAsConst(newcs.rooms))
|
||||
{
|
||||
roomsSet.insert(i);
|
||||
}
|
||||
#else
|
||||
QSet<int> roomsSet = QSet<int>(newcs.rooms.begin(), newcs.rooms.end());
|
||||
#endif
|
||||
const auto &rooms = m_contaminationStates.value(newcs.aesId).rooms;
|
||||
for (const auto &oldRoom : rooms)
|
||||
roomsSet.insert(oldRoom);
|
||||
|
||||
ContaminationState contaState;
|
||||
contaState.aesId = newcs.aesId;
|
||||
contaState.damagePercentNew = newcs.damagePercentNew;
|
||||
contaState.rooms = std::vector<int>(roomsSet.begin(), roomsSet.end());
|
||||
m_contaminationStates[newcs.aesId] = contaState;
|
||||
}
|
||||
else
|
||||
m_contaminationStates.insert(newcs.aesId, newcs);
|
||||
}
|
||||
DEBUG_LOG(m_logger) << "onSetContaminationState emit hitResult "
|
||||
<< " m_lastHitResult.damagePercentNew=" << m_lastHitResult.damagePercentNew;
|
||||
emit hitResult(m_lastHitResult, m_contaminationStates, false);
|
||||
StateStore::saveState(m_building, m_lastHitResult, m_contaminationStates);
|
||||
}
|
||||
|
||||
void Api::onResetContaminations()
|
||||
{
|
||||
m_contaminationStates.clear();
|
||||
DEBUG_LOG(m_logger) << "onResetContaminations emit hitResult";
|
||||
m_lastHitResult.chargeTypeId = 0;
|
||||
m_lastHitResult.originatorId = 0;
|
||||
m_lastHitResult.originatorType = BuildingControlUnit::OriginatorType::ECC;
|
||||
emit hitResult(m_lastHitResult, m_contaminationStates, false);
|
||||
StateStore::saveState(m_building, m_lastHitResult, m_contaminationStates);
|
||||
}
|
||||
|
||||
void Api::onHitCes(const qint64 effectTimeMSec, const int chargeTypeId,
|
||||
const int destructiveFactor, const int penetrationFactor,
|
||||
const int aesId, const LtsUtils::QPoint3D &posImpact,
|
||||
const QString &properties)
|
||||
{
|
||||
Q_UNUSED(properties); // intention: data could be added to struct 'Hit' and passed to the user
|
||||
|
||||
Hit hit;
|
||||
hit.effectTimeMSec = effectTimeMSec;
|
||||
hit.chargeTypeId = chargeTypeId;
|
||||
hit.destructiveFactor = destructiveFactor;
|
||||
hit.penetrationFactor = penetrationFactor;
|
||||
hit.originatorId = aesId;
|
||||
hit.originatorType = OriginatorType::CesHit;
|
||||
hit.position = posImpact;
|
||||
|
||||
// use "1" meter here to find rooms ABOVE ground:
|
||||
hit.position.setZ(1);
|
||||
|
||||
INFO_LOG(m_logger) << "XXXXX CES Hit = " << hit;
|
||||
|
||||
// first we have to check if the building was hit directly
|
||||
// -> check every wall if it would be hit with bsm direction 0/0/1
|
||||
BuildingControlUnit::VWM::HitPosition hitPos;
|
||||
hitPos.distance = +10000;
|
||||
|
||||
LtsUtils::QPoint3D posTmp(posImpact);
|
||||
posTmp.setZ(10000);
|
||||
const LtsUtils::QPoint3D direction(0,0,1); // fake bsm dir -> looking upwards
|
||||
const auto hitPosTmp = BuildingControlUnit::VWM::Math::checkBsmPosition(posTmp, direction, m_building.rooms());
|
||||
INFO_LOG(m_logger) << "XXXXX hitPosTmp after checkBsmPosition = " << hitPosTmp;
|
||||
if (hitPosTmp.state != BuildingControlUnit::VWM::HitPosition::State::NoHit)
|
||||
{
|
||||
auto room = m_building.rooms().value(hitPosTmp.roomId);
|
||||
if (room.isValid()) // should not happen but who knows...
|
||||
{
|
||||
// At the beginning, only on-ground-bulding were considered.
|
||||
// Starting with U-Bahn-Tunnel and Kanalisation, below-ground-building have to be considerd.
|
||||
// In that cases the distance is like 10003 meters...
|
||||
// so skip this additional check
|
||||
// // if (hitPosTmp.distance < hitPos.distance)
|
||||
{
|
||||
hitPos = hitPosTmp;
|
||||
hit.direction = direction * -1; // look downwards
|
||||
hit.position = posTmp; // hit from above, use this pos with z == 10000;
|
||||
}
|
||||
}
|
||||
// not really relevant, but who knows:
|
||||
hit.typeOfHit = TypeOfHit::InsideBuilding;
|
||||
}
|
||||
|
||||
// if not inside building -> find nearest wall point to impact position
|
||||
LtsUtils::QPoint3D posImpactOnGround(posImpact);
|
||||
posImpactOnGround.setZ(1); // use "1" meter here to find rooms ABOVE ground:
|
||||
|
||||
// struct NearestWall
|
||||
// {
|
||||
// int roomId{0};
|
||||
// WallElement wallElement;
|
||||
// };
|
||||
NearestWall nearestWall;
|
||||
if (hitPos.state == BuildingControlUnit::VWM::HitPosition::State::NoHit)
|
||||
{
|
||||
INFO_LOG(m_logger) << "XXXXX CES Hit outside building - searching nearest wall ...";
|
||||
|
||||
double distanceOut = 0;
|
||||
LtsUtils::QPoint3D directionWallElementPointToDetonationOut;
|
||||
nearestWall = findNearestWall(posImpactOnGround, distanceOut, directionWallElementPointToDetonationOut);
|
||||
|
||||
if (nearestWall.isValid())
|
||||
{
|
||||
hitPos.state = BuildingControlUnit::VWM::HitPosition::State::OuterWall;
|
||||
hitPos.distance = distanceOut;
|
||||
hit.direction = directionWallElementPointToDetonationOut;
|
||||
hit.typeOfHit = TypeOfHit::OutsideBuilding; // will reduce charge (effect)
|
||||
}
|
||||
}
|
||||
|
||||
if (hitPos.state == BuildingControlUnit::VWM::HitPosition::State::NoHit)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Internal error - could not find impact position on building "
|
||||
<< m_building.name() << " with impact pos " << posImpactOnGround;
|
||||
}
|
||||
INFO_LOG(m_logger) << "XXXXX Aes hit - hit pos: " << posImpactOnGround << " direction: " << hit.direction
|
||||
<< " (p=" << hit.direction+posImpactOnGround << ")"
|
||||
<< " ; nearestWall.roomId=" << nearestWall.roomId;
|
||||
for (auto item : qAsConst(nearestWall.wallElement))
|
||||
DEBUG_LOG(m_logger) << "Aes hit - hit pos: " << posImpactOnGround << " direction: " << hit.direction
|
||||
<< " (p=" << hit.direction+posImpactOnGround
|
||||
<< " - " << item;
|
||||
|
||||
if (nearestWall.wallElement.isEmpty())
|
||||
{
|
||||
sendHitToVwm(hit);
|
||||
} else {
|
||||
|
||||
const LtsUtils::QPoint3D ¢er = centerOfWallElement3D(nearestWall.wallElement);
|
||||
|
||||
INFO_LOG(m_logger) << "XXXXX Aes hit - hit pos: " << posImpactOnGround << " direction: " << hit.direction
|
||||
<< ", m_building.name=" << m_building.name()
|
||||
<< ", m_building.modelId=" << m_building.modelId()
|
||||
<< ", nearestWall.roomId=" << nearestWall.roomId
|
||||
<< ", hitPos.distance=" << hitPos.distance
|
||||
<< ", center=" << center
|
||||
<< ", direction would be " << center-posImpactOnGround;
|
||||
|
||||
hit.direction = center - posImpactOnGround;
|
||||
|
||||
sendHitToVwm(hit);
|
||||
}
|
||||
}
|
||||
|
||||
NearestWall Api::findNearestWall(const LtsUtils::QPoint3D &detonationLocation, double &distanceOut, LtsUtils::QPoint3D &directionWallElementPointToDetonationOut)
|
||||
{
|
||||
NearestWall nearestWall;
|
||||
distanceOut = std::numeric_limits<double>::max();
|
||||
|
||||
INFO_LOG(m_logger) << "XXXXX searching nearest wall ...";
|
||||
for (const Room &room : qAsConst(m_building.rooms()))
|
||||
{
|
||||
for (const OuterWall &wall : qAsConst(room.outerWalls()))
|
||||
{
|
||||
for (const WallElement &we : qAsConst(wall.elements()))
|
||||
{
|
||||
for (const LtsUtils::QPoint3D &p : qAsConst(we))
|
||||
{
|
||||
const double dist = (detonationLocation - p).length();
|
||||
DEBUG_LOG(m_logger) << "Room[" << room.id() << "]: " << p << ", dist = " << dist;
|
||||
if (dist >= distanceOut)
|
||||
continue;
|
||||
|
||||
// hitPos.state = BuildingControlUnit::VWM::HitPosition::State::OuterWall;
|
||||
distanceOut = dist;
|
||||
INFO_LOG(m_logger) << "New min distance " << dist << " Room[" << room.id() << "]: " << p;
|
||||
directionWallElementPointToDetonationOut = p - detonationLocation;
|
||||
|
||||
nearestWall.roomId = room.id();
|
||||
nearestWall.wallElement = we;
|
||||
|
||||
// hit.typeOfHit = TypeOfHit::OutsideBuilding; // will reduce charge (effect)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nearestWall;
|
||||
}
|
||||
|
||||
void Api::onHitCes3D_Evaluation(const qint64 effectTimeMSec,
|
||||
const int chargeTypeId, const int destructiveFactor, const int penetrationFactor,
|
||||
const int aesId,
|
||||
const LtsUtils::QPoint3D &posImpact,
|
||||
const LtsUtils::QPoint3D &detonationLocation,
|
||||
const double detonationDistance,
|
||||
const QString &properties)
|
||||
{
|
||||
Q_UNUSED(posImpact);
|
||||
Q_UNUSED(properties); // intention: data could be added to struct 'Hit' and passed to the user
|
||||
|
||||
Hit hit;
|
||||
hit.effectTimeMSec = effectTimeMSec;
|
||||
hit.chargeTypeId = chargeTypeId;
|
||||
hit.originatorId = aesId;
|
||||
hit.originatorType = OriginatorType::CesHit3D;
|
||||
hit.position = detonationLocation;
|
||||
// hit.direction
|
||||
// hit.detonationLocation
|
||||
|
||||
INFO_LOG(m_logger) << "XXXXXXXXXX CES Hit 3D = " << hit
|
||||
<< ", detonationLocation = " << detonationLocation
|
||||
<< ", detonationDistance = " << detonationDistance
|
||||
<< ", chargeTypeId = " << chargeTypeId
|
||||
<< ", destructiveFactor = " << destructiveFactor
|
||||
<< ", penetrationFactor = " << penetrationFactor;
|
||||
|
||||
// Aufschlagzünder == 0 ?
|
||||
// Verzögerungszünder > 0 ?
|
||||
// Annäherungszünder < 0 ?
|
||||
|
||||
// ProjectDataManagement::FuseType::FtProximity -> position = (1.91756,10.9597,9.94583), direction = (0,0,0)
|
||||
// ProjectDataManagement::FuseType::FtImpact -> position = (1.91756,10.9597,9.94583), direction = (0,0,0)
|
||||
// ProjectDataManagement::FuseType::FtDelay ->
|
||||
|
||||
QVector<int> roomsWithDetonation;
|
||||
const bool bIsDelayed = detonationDistance > 0;
|
||||
|
||||
HitPosition hitPosPreCalculated;
|
||||
hitPosPreCalculated.state = HitPosition::State::OuterWall;
|
||||
hitPosPreCalculated.outerWallIdx = 0; // will point to the dummyWall !?
|
||||
|
||||
|
||||
if (bIsDelayed)
|
||||
{
|
||||
roomsWithDetonation = m_buildingRoomGeometry.pointIsInWhichRooms(detonationLocation);
|
||||
if (roomsWithDetonation.isEmpty())
|
||||
{
|
||||
INFO_LOG(m_logger) << "XXXX Building '" << m_building.name() << "'"
|
||||
<< ", detonationLocation = " << detonationLocation
|
||||
<< " -> found no room";
|
||||
} else {
|
||||
if (roomsWithDetonation.size() == 1)
|
||||
INFO_LOG(m_logger) << "XXXX Building '" << m_building.name() << "'"
|
||||
<< ", detonationLocation = " << detonationLocation
|
||||
<< " -> found just one room: " << roomsWithDetonation.first();
|
||||
else
|
||||
INFO_LOG(m_logger) << "XXXX Building '" << m_building.name() << "'"
|
||||
<< ", detonationLocation = " << detonationLocation
|
||||
<< " -> found several rooms, choose first: " << roomsWithDetonation.first();
|
||||
|
||||
hitPosPreCalculated.roomId = roomsWithDetonation.first();
|
||||
hitPosPreCalculated.exclusionZoneIdx = -1;
|
||||
hitPosPreCalculated.distance = 0;
|
||||
}
|
||||
} // if
|
||||
|
||||
if (!bIsDelayed ||
|
||||
roomsWithDetonation.isEmpty()) // fallback
|
||||
{
|
||||
// handle similar as before: findNearestWall
|
||||
double distanceOut = 0;
|
||||
LtsUtils::QPoint3D directionWallElementPointToDetonationOut;
|
||||
NearestWall nearestWall = findNearestWall(detonationLocation, distanceOut, directionWallElementPointToDetonationOut);
|
||||
|
||||
INFO_LOG(m_logger) << "XXXXX CES Hit outside building - searching nearest wall ..."
|
||||
<< ", detonationDistance = " << detonationDistance
|
||||
<< ", nearestWall.roomId = " << nearestWall.roomId;
|
||||
|
||||
if (nearestWall.isValid())
|
||||
{
|
||||
hitPosPreCalculated.roomId = nearestWall.roomId;
|
||||
hitPosPreCalculated.distance = distanceOut;
|
||||
hit.direction = directionWallElementPointToDetonationOut;
|
||||
if (bIsDelayed)
|
||||
hit.typeOfHit = TypeOfHit::InsideBuilding;
|
||||
else
|
||||
hit.typeOfHit = TypeOfHit::OutsideBuilding; // will reduce charge (effect)
|
||||
}
|
||||
} // if
|
||||
|
||||
|
||||
HitResult result;
|
||||
result.damagePercentOld = m_building.damagePercent();
|
||||
result.effectTimeMSec = effectTimeMSec;
|
||||
|
||||
// von hier ueber a) sendHitToVwm, b) hitResult
|
||||
// Oder direkt hitResult??
|
||||
|
||||
QString context(QStringLiteral("onHitCes-3D - "));
|
||||
|
||||
const Charge &chargeOrg = chargeFromChargeTypeId(chargeTypeId);
|
||||
Charge charge = chargeOrg;
|
||||
charge.destructiveFactor = destructiveFactor;
|
||||
charge.penetrationEffect = penetrationFactor;
|
||||
if (detonationDistance>0)
|
||||
{
|
||||
charge.destructiveFactor *= 2.1;
|
||||
charge.penetrationEffect *= 2.1;
|
||||
context += QStringLiteral("FtDelay");
|
||||
} else if (detonationDistance<0)
|
||||
{
|
||||
charge.destructiveFactor *= 0.55;
|
||||
charge.penetrationEffect *= 0.55;
|
||||
context += QStringLiteral("FtProximity");
|
||||
} else {
|
||||
context += QStringLiteral("FtImpact");
|
||||
}
|
||||
|
||||
bool hitSuccess = m_building.hit(LtsUtils::QPoint3D(), LtsUtils::QPoint3D(), // pos and dir: default values are okay
|
||||
charge, &hitPosPreCalculated);
|
||||
|
||||
INFO_LOG(m_logger) << "onHitCes3D_Evaluation hitSuccess=" << hitSuccess;
|
||||
|
||||
result.rooms = m_building.roomStates();
|
||||
result.damageState = m_building.damageState();
|
||||
result.damagePercentNew = m_building.damagePercent();
|
||||
//add Values from function:
|
||||
result.chargeTypeId = chargeTypeId;
|
||||
result.originatorType = OriginatorType::CesHit;
|
||||
result.originatorId = aesId;
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
// write ShotResult.cvs
|
||||
dumpHitResult(hit, result, chargeOrg, charge, context);
|
||||
#endif // LTS_DEBUG
|
||||
|
||||
emit hitResult(result, m_contaminationStates, true);
|
||||
}
|
||||
|
||||
void Api::onFortifyFactorRequest(int originatorId, const QVector<FortifyInfo> &foritfyInfos)
|
||||
{
|
||||
|
||||
HitResult result;
|
||||
result.effectTimeMSec = QDateTime::currentMSecsSinceEpoch();
|
||||
result.originatorId = originatorId;
|
||||
result.originatorType = OriginatorType::ECC;
|
||||
result.damagePercentOld = m_building.damagePercent();
|
||||
|
||||
m_building.setFortifyInfo(foritfyInfos);
|
||||
result.rooms = m_building.roomStates();
|
||||
result.damageState = m_building.damageState();
|
||||
result.damagePercentNew = m_building.damagePercent();
|
||||
|
||||
emit hitResult(result, m_contaminationStates, true);
|
||||
|
||||
m_lastHitResult = result;
|
||||
}
|
||||
|
||||
void Api::onRelayStatesRequest(const QString &hostname, const QVector<RelayStateInfo> &relayStateInfos)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onRelayStateRequest hostname=" << hostname
|
||||
<< " only hanlde in svcBuildings"
|
||||
<< " relayStateInfos.size()=" << relayStateInfos.size();
|
||||
}
|
||||
|
||||
void Api::sendOverrides()
|
||||
{
|
||||
const QMap<QString, QString> &segmentPropertyMap = m_building.segmentPropertyMap();
|
||||
QVector<BcuEffectState> effectStates;
|
||||
for (auto it = segmentPropertyMap.cbegin(); it != segmentPropertyMap.cend(); ++it)
|
||||
{
|
||||
QString hostname = it.key();
|
||||
QString properties = it.value();
|
||||
effectStates.clear();
|
||||
QJsonParseError parserError;
|
||||
const QJsonDocument doc(QJsonDocument::fromJson(properties.toUtf8(), &parserError));
|
||||
|
||||
if (parserError.error != QJsonParseError::NoError)
|
||||
continue;
|
||||
|
||||
QJsonObject docObj = QJsonObject(doc.object());
|
||||
|
||||
DEBUG_LOG(m_logger) << "sendOverrides hostname=" << hostname
|
||||
<< " properties=" << properties;
|
||||
|
||||
/////////////////////////////////////////
|
||||
/// \brief BCU-Flash
|
||||
///
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sendOverrides hostname=" << hostname
|
||||
<< " properties=" << properties << "BCU-Flash";
|
||||
BcuEffectState bcuEffectState;
|
||||
bcuEffectState.id = 1; // Id aus effect_config.xml
|
||||
bcuEffectState.type = BcuEffectType::BET_BsmFlash;
|
||||
BcuEffectOverride eo = BcuEffectOverride::BEO_Auto;
|
||||
|
||||
QJsonObject overrideObj;
|
||||
QJsonObject flashObj;
|
||||
if (docObj.contains(QStringLiteral("Overrides")))
|
||||
{
|
||||
overrideObj = docObj[QStringLiteral("Overrides")].toObject();
|
||||
}
|
||||
|
||||
if (overrideObj.contains(QStringLiteral("flash")))
|
||||
{
|
||||
flashObj = docObj[QStringLiteral("flash")].toObject();
|
||||
eo = static_cast<BuildingControlUnit::BcuEffectOverride>(flashObj.value(QStringLiteral("flash")).toInt());
|
||||
}
|
||||
if (eo != BcuEffectOverride::BEO_Auto)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "bcuEffectState.effectOverride = eo" << eo;
|
||||
bcuEffectState.effectOverride = eo;
|
||||
emit newOverrides({}, {bcuEffectState});
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////
|
||||
|
||||
|
||||
QJsonObject overridesObj = docObj.value(QStringLiteral("Overrides")).toObject();
|
||||
QJsonArray arrEgcus = overridesObj.value(QStringLiteral("relays")).toArray();
|
||||
for (int i=0; i<arrEgcus.size(); ++i)
|
||||
{
|
||||
QJsonObject objState = arrEgcus[i].toObject();
|
||||
QStringList keys = objState.keys();
|
||||
QString relayIdString = keys.at(0);
|
||||
int relayId = relayIdString.toInt();
|
||||
if (!objState.contains(relayIdString))
|
||||
continue;
|
||||
BcuEffectOverride eo = static_cast<BuildingControlUnit::BcuEffectOverride>(objState.value(relayIdString).toInt());
|
||||
if (eo == BcuEffectOverride::BEO_Auto)
|
||||
continue;
|
||||
BuildingControlUnit::BcuEffectState bcuEffectState;
|
||||
bcuEffectState.id = relayId;
|
||||
bcuEffectState.type = BcuEffectType::BET_Relay;
|
||||
bcuEffectState.effectOverride = eo;
|
||||
effectStates.append(bcuEffectState);
|
||||
}
|
||||
|
||||
{
|
||||
BuildingControlUnit::BcuEffectState bcuEffectState;
|
||||
bcuEffectState.id = 1; // Id aus effect_config.xml
|
||||
bcuEffectState.type = BcuEffectType::BET_BackgroundSound;
|
||||
BcuEffectOverride eo = BcuEffectOverride::BEO_Auto;
|
||||
if (overridesObj.contains(QStringLiteral("sound")))
|
||||
eo = static_cast<BuildingControlUnit::BcuEffectOverride>(overridesObj.value(QStringLiteral("sound")).toInt());
|
||||
if (eo != BcuEffectOverride::BEO_Auto)
|
||||
{
|
||||
bcuEffectState.effectOverride = eo;
|
||||
effectStates.append(bcuEffectState);
|
||||
}
|
||||
}
|
||||
emit newOverrides(hostname,effectStates);
|
||||
}
|
||||
}
|
||||
|
||||
void Api::sendHitToVwm(const Hit &hit)
|
||||
{
|
||||
m_hitsSinceLastInit += hit;
|
||||
|
||||
INFO_LOG(m_logger) << " XXXXX sendHitToVwm, Incoming hit=" << hit
|
||||
<< " hit.chargeTypeId=" << hit.chargeTypeId
|
||||
<< " originatorId=" << hit.originatorId
|
||||
<< " typeOfHit=" << hit.typeOfHit;
|
||||
|
||||
HitResult result;
|
||||
result.sensorId = hit.sensorId;
|
||||
result.effectTimeMSec = hit.effectTimeMSec;
|
||||
result.originatorId = hit.originatorId;
|
||||
result.originatorType = hit.originatorType;
|
||||
result.damagePercentOld = m_building.damagePercent();
|
||||
switch (hit.originatorType)
|
||||
{
|
||||
case OriginatorType::CesHit:
|
||||
case OriginatorType::CesHit3D:
|
||||
case OriginatorType::DirectHit:
|
||||
{
|
||||
Charge charge, chargeOrg;
|
||||
charge = chargeFromChargeTypeId(hit.chargeTypeId); // we know the correct charge id
|
||||
if ( ( hit.originatorType == OriginatorType::CesHit)
|
||||
|| ( hit.originatorType == OriginatorType::CesHit3D))
|
||||
{
|
||||
// [GUEZE-2821] Building protects buildings
|
||||
charge.destructiveFactor = hit.destructiveFactor;
|
||||
charge.penetrationEffect = hit.penetrationFactor;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "charge=" << charge.chargeTypeId
|
||||
<< " destructiveFactor" << charge.destructiveFactor
|
||||
<< " penetrationEffect" << charge.penetrationEffect;
|
||||
chargeOrg = charge;
|
||||
result.chargeTypeId = hit.chargeTypeId;
|
||||
result.effectSoundId = charge.effectSoundId;
|
||||
|
||||
if ( charge.destructiveFactor == 0 // no effect on the building
|
||||
&& !charge.showHitLine)
|
||||
return;
|
||||
|
||||
if ((hit.originatorType == OriginatorType::CesHit) &&
|
||||
(hit.typeOfHit == TypeOfHit::OutsideBuilding))
|
||||
{
|
||||
|
||||
LtsUtils::QPoint3D dummyDist = hit.position - hit.direction;
|
||||
|
||||
INFO_LOG(m_logger) << " XXXX CES outside bulding, reduce charge: " << charge
|
||||
<< ", hit.position " << hit.position
|
||||
<< ", hit.direction " << hit.direction
|
||||
<< ", dummyDist " << dummyDist.length();
|
||||
charge.destructiveFactor *= 0.5;
|
||||
charge.penetrationEffect *= 0.5;
|
||||
INFO_LOG(m_logger) << " XXXX CES outside bulding, reduce charge: " << charge;
|
||||
}
|
||||
|
||||
if (!charge.isValid())
|
||||
{
|
||||
if (hit.originatorType == OriginatorType::CesHit)
|
||||
WARNING_LOG(m_logger) << "Charge with id " << hit.chargeTypeId
|
||||
<< " not configured - can not caluclate impact effect for this charge";
|
||||
else
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Direct charge with id " << hit.chargeTypeId
|
||||
<< " not configured - can not caluclate impact effect for this charge";
|
||||
emit unknownDirectHit(hit.sensorId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!m_building.hit(hit.position, hit.direction, charge))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Detected hit was outside of the building - ignored";
|
||||
break;
|
||||
}
|
||||
result.rooms = m_building.roomStates();
|
||||
result.damageState = m_building.damageState();
|
||||
result.damagePercentNew = m_building.damagePercent();
|
||||
|
||||
emit hitResult(result, m_contaminationStates, true);
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
// write ShotResult.cvs
|
||||
dumpHitResult(hit, result, chargeOrg, charge, QStringLiteral("default"));
|
||||
#endif // LTS_DEBUG
|
||||
|
||||
m_lastHitResult = result;
|
||||
break;
|
||||
}
|
||||
case OriginatorType::ECC:
|
||||
case OriginatorType::OC:
|
||||
{
|
||||
if (!hit.affectedRoomIds.isEmpty())
|
||||
{
|
||||
// destroy/init a special room from ECC
|
||||
m_building.setRoomState(hit.damageStateOverride, hit.affectedRoomIds);
|
||||
|
||||
result.rooms = m_building.roomStates();
|
||||
result.damageState = m_building.damageState();
|
||||
result.damagePercentNew = m_building.damagePercent();
|
||||
|
||||
emit hitResult(result, m_contaminationStates, true);
|
||||
|
||||
m_lastHitResult = result;
|
||||
break;
|
||||
}
|
||||
switch (hit.damageStateOverride)
|
||||
{
|
||||
case DamageState::NoDamage:
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Hit OC/ECC with NoDamage";
|
||||
m_building.init();
|
||||
|
||||
result.effectSoundId = Settings::effectSoundIdEccActivate();
|
||||
result.rooms = m_building.roomStates();
|
||||
result.damageState = DamageState::NoDamage;
|
||||
result.damagePercentNew = m_building.damagePercent();
|
||||
|
||||
emit hitResult(result, m_contaminationStates, true);
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
// write ShotResult.cvs
|
||||
dumpHitResult(hit, result, Charge(), Charge(), QStringLiteral("Reset by ECC/OC"));
|
||||
#endif // LTS_DEBUG
|
||||
|
||||
m_hitsSinceLastInit.clear();
|
||||
m_hitsSinceLastInit += hit;
|
||||
|
||||
m_lastHitResult = result;
|
||||
break;
|
||||
}
|
||||
case DamageState::Destroyed:
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Hit OC/ECC with Destroyed";
|
||||
const DamageState dsOld = m_building.damageState();
|
||||
|
||||
m_building.destroyAllRooms();
|
||||
|
||||
result.effectSoundId = Settings::effectSoundIdEccDestroy();
|
||||
result.rooms = m_building.roomStates();
|
||||
result.damageState = DamageState::Destroyed;
|
||||
result.damagePercentNew = m_building.damagePercent();
|
||||
|
||||
if (dsOld != DamageState::Destroyed)
|
||||
{
|
||||
emit hitResult(result, m_contaminationStates, true);
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
// write ShotResult.cvs
|
||||
dumpHitResult(hit, result, Charge(), Charge(), QStringLiteral("Destroyed by ECC/OC"));
|
||||
#endif // LTS_DEBUG
|
||||
}
|
||||
|
||||
m_lastHitResult = result;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WARNING_LOG(m_logger) << "Invalid damage state override given: " << hit.damageStateOverride;
|
||||
result = HitResult();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OriginatorType::Unknown:
|
||||
WARNING_LOG(m_logger) << "Unknown originator type given: " << hit.originatorType;
|
||||
result = HitResult();
|
||||
break;
|
||||
}
|
||||
StateStore::saveState(m_building, m_lastHitResult, m_contaminationStates);
|
||||
}
|
||||
|
||||
|
||||
const Charge Api::chargeFromChargeTypeId(int chargeTypeId) const
|
||||
{
|
||||
|
||||
if (chargeTypeId > 4000)
|
||||
{
|
||||
chargeTypeId %= 1000;
|
||||
chargeTypeId += 2000;
|
||||
}
|
||||
|
||||
for (auto i = m_chargeMap.cbegin(), end = m_chargeMap.cend(); i != end; ++i)
|
||||
{
|
||||
TRACE_LOG(m_logger) << "key=" << i.key() << " value=" << i.value();
|
||||
if ( chargeTypeId == i.value().id)
|
||||
return m_chargeMap.value(i.key());
|
||||
}
|
||||
|
||||
return m_chargeMap.value(chargeTypeId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace VWM
|
||||
} // namespace BuildingControlUnit
|
||||
Reference in new issue
Block a user