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

414 lines
16 KiB
C++
Executable File

/**
* Handler for player data
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2017-02-20
*/
#include "handler_building_ownership.h"
#include <LtsCoordTrans/lts_coord_trans.h>
#include <ngldb/dbtransaction.h>
#include <QJsonDocument>
#include <QJsonObject>
namespace CesBuildings
{
HandlerBuildingOwnership::HandlerBuildingOwnership(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &buildingDataHandler,
const std::shared_ptr<CentralEffectSimulation::DatabaseInterface> &db,
QObject *parent)
: QObject(parent)
, SetOwnershipRequestHandler(ddsHandler->ftsCes())
, m_ddsHandler(ddsHandler)
, m_handlerParticipant(participantHandler)
, m_handlerBuildingData(buildingDataHandler)
, m_db(db)
, m_logger(CentralEffectSimulation::getLogger("Plugin.Buildings.HandlerBuildingOwnership"))
{
INFO_LOG(m_logger) << "HandlerBuildingOwnership::HandlerBuildingOwnership";
} // end of ctor()
//-----------------------------------------------------------------------------
HandlerBuildingOwnership::~HandlerBuildingOwnership()
{
} // end of dtor()
//-----------------------------------------------------------------------------
bool HandlerBuildingOwnership::init()
{
INFO_LOG(m_logger) << "HandlerBuildingOwnership::init";
auto dtcIsm = m_ddsHandler->dtcIsm();
DEBUG_LOG(m_logger) << "init";
loadOwnershipsFromDb();
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newOutdoorPosition,
this, &HandlerBuildingOwnership::onParticipantPositionChanged);
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newIndoorPosition,
this, &HandlerBuildingOwnership::onParticipantPositionChanged);
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newNotfightMode,
this, &HandlerBuildingOwnership::onParticipantPositionChanged);
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::participantLeavesBuilding,
this, &HandlerBuildingOwnership::onParticipantLeavesBuilding);
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newParticipantState,
this, &HandlerBuildingOwnership::onParticipantPositionChanged);
dtcIsm->waitForHistoricalDataMainStructureElement(1000);
connect(dtcIsm.get(), &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged,
this, &HandlerBuildingOwnership::onMainStructureElementChanged);
// Get 'static' data for all MainStructureElements
{
auto cb = [this](const InfrastructureManagement::MainStructureElement & mse)
{
onMainStructureElementChanged(mse, DataModification::eAdded);
};
if (!dtcIsm->mainStructureElements(cb))
return false;
}
return true;
} // end of init()
//-----------------------------------------------------------------------------
// ///////////////////////////////////
// B L D (Buildings)
// ///////////////////////////////////
void HandlerBuildingOwnership::onSetOwnershipRequest(const rti::core::SampleIdentity &cookie,
const CentralEffectSimulation::SetOwnershipRequest &request)
{
INFO_LOG(m_logger) << "onSetOwnershipRequest: " << request;
// remove Ownership, if partyId == 0
if (request.partyId() == 0)
removeFromDbBuildingId(request.buildingId());
const QVector<int> floors = m_handlerBuildingData->getFloorsFromBuilding(request.buildingId());
for (int floorId : floors)
saveBuildingOwnership(floorId, request.partyId(), request.buildingId());
if (!floors.isEmpty())
sendBuildingOwnership(request.buildingId());
m_ddsHandler->ftsCes()->setOwnershipReply(cookie, Core::FunctionReplyObject(request.buildingId()));
}
void HandlerBuildingOwnership::onParticipantPositionChanged(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &partPos)
{
const int participantId = partPos.participantId();
INFO_LOG(m_logger) << "BuildingOwnership onParticipantPositionChanged participantId=" << participantId
<< " vulnerabilityState=" << partPos.vulnerabilityState
<< " buildingId=" << partPos.buildingId()
<< " notfightMode=" << partPos.notfightMode;
// [GUEZE-2256] 3D Wirksim - Funktionsraum Nicht Kampffaehig
// Teilnehmer, die den Status Nicht Kampffaehig haben, düfen nicht bei der Berechnung des Gebaeudebesitzes beruecksichtigt werden.
if (partPos.notfightMode)
return;
int floorId = m_handlerBuildingData->getFloorIdFromRoomId(partPos.roomId());
if (partPos.vulnerabilityState == ProjectDataManagement::VulnerabilityState_def::CatastrophicKill)
m_participantFloor.remove(participantId);
else
m_participantFloor.insert(participantId, floorId);
int newOwnership = calculateOwnershipByParticipantId(participantId);
checkAndSendOwnership(newOwnership, floorId);
INFO_LOG(m_logger) << "END BuildingOwnership onParticipantPositionChanged participantId=" << participantId
<< " vulnerabilityState=" << partPos.vulnerabilityState;
} // end of onParticipantPositionChanged()
// ///////////////////////////////////
// I S M (InfrastructureManagement)
// ///////////////////////////////////
void HandlerBuildingOwnership::onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data, DataModification modType)
{
INFO_LOG(m_logger) << "onMainStructureElementChanged id=" << data.id()
<< " modelId =" << data.modelId();
if (modType == DataModification::eRemoved || data.modelId() <= 0)
{
m_buildingOwnership.remove(data.id());
return;
}
QJsonArray jsonArray = QJsonDocument::fromJson(QByteArray::fromStdString(data.properties())).object().value(QLatin1String("available_in_exercise")).toArray();
DEBUG_LOG(m_logger) << "available_in_exercise jsonDocument.size()=" << jsonArray.size();
QVector<int> result;
result.reserve(jsonArray.size());
// Check if present in the current exercise and remove
if (m_buildingOwnership.contains(data.id()))
{
int id = data.id();
m_buildingOwnership.remove(id);
m_ddsHandler->dtsCes()->removeBuildingOwnershipByKey(id);
}
for (auto it = jsonArray.constBegin(); it != jsonArray.constEnd(); ++it)
{
DEBUG_LOG(m_logger) << "available_in_exercise jsonDocument=" << it->toInt();
if (m_ddsHandler->getExerciseId() != it->toInt())
continue;
DEBUG_LOG(m_logger) << "Got MainStructureElement"
<< " data.id()=" << data.id()
<< " data.modelId=" << data.modelId();
if (!m_buildingOwnership.contains(data.id()))
{
// insert in m_buildingOwnership and publish to dds
CentralEffectSimulation::BuildingOwnership bo;
bo.buildingId(data.id());
bo.sampleTime(QDateTime::currentMSecsSinceEpoch());
updateOwnerships(&bo);
m_buildingOwnership.insert(data.id(), bo);
m_ddsHandler->dtsCes()->publish(bo);
} // if
} // for
}
void HandlerBuildingOwnership::onParticipantLeavesBuilding(const int participantId)
{
INFO_LOG(m_logger) << "BuildingOwnership onParticipantLeavesBuilding participantId=" << participantId;
auto it = m_participantFloor.find(participantId);
if (it == m_participantFloor.end())
return;
m_participantFloor.erase(it);
const int floorId = it.value();
const int newOwnership = calculateOwnershipByFloorId(floorId);
DEBUG_LOG(m_logger) << "newOwnership=" << newOwnership;
if (newOwnership > 0)
checkAndSendOwnership(newOwnership, floorId);
} // end of onParticipantLeavesBuilding()
int HandlerBuildingOwnership::calculateOwnershipByParticipantId(const int participantId)
{
INFO_LOG(m_logger) << "BuildingOwnership calculateOwnershipByParticipantId participantId=" << participantId;
CentralEffectSimulation::HandlerParticipant::CesParticipantData partPos = m_handlerParticipant->position(participantId);
return calculateOwnershipByFloorId(m_handlerBuildingData->getFloorIdFromRoomId(partPos.roomId()));
}
int HandlerBuildingOwnership::calculateOwnershipByFloorId(const int floorId)
{
INFO_LOG(m_logger) << "BuildingOwnership calculateOwnershipByFloorId floorId=" << floorId;
int ownership = -1;
if (floorId == -1)
return ownership;
DEBUG_LOG(m_logger) << "calculateOwnership floorId = " << floorId;
QHash <int, int> partyCount; // key = Party, value= Count of Participants;
// Suche alle Participants in der Etage
for (auto it = m_participantFloor.cbegin(); it != m_participantFloor.cend(); ++it)
{
int iteratorFloor = it.value();
int iteratorParticipant = it.key();
if (floorId == iteratorFloor)
{
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &localPartPos = m_handlerParticipant->position(iteratorParticipant);
if (localPartPos.vulnerabilityState == ProjectDataManagement::VulnerabilityState::CatastrophicKill)
continue; // Don't count participants with catastrophic Kill
const int partyId = localPartPos.partyId();
++partyCount[partyId];
}
}
// berechne daraus die Farbe der Partei
int countParty = 0;
for (auto it = partyCount.begin(); it != partyCount.end(); ++it)
{
if (it.value() > countParty)
{
countParty = it.value();
ownership = it.key();
}
}
return ownership;
}
int HandlerBuildingOwnership::getOwnership(int buildingId, int floorId) const
{
INFO_LOG(m_logger) << "BuildingOwnership getOwnership buildingId=" << buildingId
<< " floorId=" << floorId;
auto itBldg = m_buildingOwnership.find(buildingId);
if (itBldg == m_buildingOwnership.end())
return -1;
const CentralEffectSimulation::BuildingOwnership &bo = itBldg.value();
for (const CentralEffectSimulation::Ownership &ownership : bo.ownerships())
{
if (ownership.floorId() == floorId)
return ownership.partyId();
}
return -1;
}
void HandlerBuildingOwnership::checkAndSendOwnership(const int newOwnership, const int floorId)
{
INFO_LOG(m_logger) << "BuildingOwnership checkAndSendOwnership";
if (floorId < 0) // outside building
return;
const int buildingId = m_handlerBuildingData->getBuildingIdFromFloorId(floorId);
if (buildingId < 0)
{
WARNING_LOG(m_logger) << "Could not find building for floor with id " << floorId << " - ignoring";
return;
}
// prüfe, ob sich die Farbe geändert hat.
const int oldOwnership = getOwnership(buildingId, floorId);
DEBUG_LOG(m_logger) << "checkAndSendOwnership buildingId = "
<< buildingId
<< " floorId=" << floorId
<< " oldOwnership=" << oldOwnership
<< " newOwnership=" << newOwnership;
if (oldOwnership != newOwnership) // Kriterium zum Senden
{
// Wenn ja, Eintrag in der Verwaltung
saveBuildingOwnership(floorId, newOwnership, buildingId);
// und Meldung verschicken.
sendBuildingOwnership(buildingId);
DEBUG_LOG(m_logger) << "new Building Ownership";
}
}
void HandlerBuildingOwnership::updateOwnerships(CentralEffectSimulation::BuildingOwnership *bo)
{
INFO_LOG(m_logger) << "BuildingOwnership updateOwnerships";
QMap <int, int> ownershipMap;
const QVector<int> floors = m_handlerBuildingData->getFloorsFromBuilding(bo->buildingId());
DEBUG_LOG(m_logger) << "updateOwnerships floors.size= " << floors.size();
for (const int floorId : floors)
ownershipMap[floorId] = 0;
for (const CentralEffectSimulation::Ownership &ownership : bo->ownerships())
{
DEBUG_LOG(m_logger) << "updateOwnerships floorId=" << ownership.floorId() << ": " << ownership.partyId();
ownershipMap[ownership.floorId()] = ownership.partyId();
}
bo->ownerships().resize(0);
bo->ownerships().reserve(ownershipMap.size());
CentralEffectSimulation::Ownership ownership;
for (auto it = ownershipMap.cbegin(); it != ownershipMap.cend(); ++it)
{
DEBUG_LOG(m_logger) << it.key() << ": " << it.value();
ownership.floorId(it.key());
ownership.partyId(it.value());
bo->ownerships().push_back(ownership);
}
}
void HandlerBuildingOwnership::saveBuildingOwnership(int floorId, int partyId, int buildingId)
{
INFO_LOG(m_logger) << "saveBuildingOwnership floorId: " << floorId
<< ", partyId: " << partyId
<< ", buildingId: " << buildingId;
// Vorhandenen Eintrag für das Gebäude suchen
auto it = m_buildingOwnership.find(buildingId);
if (it != m_buildingOwnership.end())
{
CentralEffectSimulation::BuildingOwnership &bo = *it;
// Vorhanden Eintrag für das Stockwerk suchen:
for (CentralEffectSimulation::Ownership &ownership : bo.ownerships())
{
if (ownership.floorId() == floorId)
{
ownership.partyId(partyId);
return;
}
}
// Neuen Eintrag für das Stockwerk anlegen
CentralEffectSimulation::Ownership ownership;
ownership.floorId(floorId);
ownership.partyId(partyId);
bo.ownerships().push_back(std::move(ownership));
m_buildingOwnership.insert(buildingId, bo);
return;
}
// Neuen Eintrag für das Gebäude anlegen
CentralEffectSimulation::BuildingOwnership bo;
CentralEffectSimulation::Ownership ownership;
bo.buildingId(buildingId);
ownership.floorId(floorId);
ownership.partyId(partyId);
bo.ownerships().resize(1, ownership);
m_buildingOwnership.insert(buildingId, bo);
}
void HandlerBuildingOwnership::sendBuildingOwnership(int buildingId)
{
INFO_LOG(m_logger) << "sendBuildingOwnership for building: " << buildingId;
CentralEffectSimulation::BuildingOwnership bo = m_buildingOwnership.value(buildingId);
bo.buildingId(buildingId);
bo.sampleTime(QDateTime::currentMSecsSinceEpoch());
updateOwnerships(&bo);
m_ddsHandler->dtsCes()->publish(bo);
insertInDb(bo);
}
// ///////////////////////////////////////////////////
/// \brief HandlerConfigureAlarms::loadOwnershipsFromDb
/// \return
///
bool HandlerBuildingOwnership::loadOwnershipsFromDb()
{
INFO_LOG(m_logger) << "HandlerBuildingOwnership::loadOwnershipsFromDb ";
m_buildingOwnership.clear();
auto cbBo = [this](const CentralEffectSimulation::Database::CesOwnership & bo)
{
saveBuildingOwnership(bo.floorId, bo.partyId, bo.buildingId);
};
if (!m_db->select(cbBo))
{
ERROR_LOG(m_logger) << "Error reading data from database 'CesOwnership'";
return false;
}
return true;
}
void HandlerBuildingOwnership::removeFromDbBuildingId(const int buildingId)
{
INFO_LOG(m_logger) << "HandlerBuildingOwnership::removeFromDbBuildingId buildingId: " << buildingId;
m_db->removeCesOwnershipByBuildingId(buildingId);
}
void HandlerBuildingOwnership::insertInDb(const CentralEffectSimulation::BuildingOwnership &bo)
{
DBTransaction trans(m_db->database());
removeFromDbBuildingId(bo.buildingId());
INFO_LOG(m_logger) << "insertInDb buildingId: " << bo.buildingId()
<< ", bo.ownerships().size(): " << bo.ownerships().size();
CentralEffectSimulation::Database::CesOwnership newOwnership;
newOwnership.buildingId = bo.buildingId();
for (const CentralEffectSimulation::Ownership &ownership : bo.ownerships())
{
newOwnership.id = 0;
newOwnership.floorId = ownership.floorId();
newOwnership.partyId = ownership.partyId();
DEBUG_LOG(m_logger) << "ownership: floorId = " << newOwnership.floorId
<< " partyId = " << newOwnership.partyId;
if (!m_db->insert(newOwnership))
ERROR_LOG(m_logger) << "Error adding 'CesOwnership' to database "
<< " buildingId =" << newOwnership.buildingId
<< " floorId = " << newOwnership.floorId
<< " partyId = " << newOwnership.partyId;
}
trans.commit();
} // end of insertInDb
} // namespace CesBuildings