- NGL_ADD_LIBRARY2: 87 CMakeLists.txt konvertiert für Export-Header Generierung - 44 Export-Header Include-Pfade korrigiert (_export.h) - 81 DDS-Stub-Header generiert (*_dtc.h, *_fts.h, *_dts.h, *_ftc.h) - INGLLogger: Duplikat gelöscht, m_logger Member entfernt, variadische Makros - Q_FUNC_INFO Redefinition behoben (Qt6 definiert bereits) - FATAL_LOG Makro hinzugefügt - InfrastructureManagement DDS-Stubs (ism.hpp, ism_enums.hpp, ism_ftc.h) - FilterManagement DDS-Stubs (flt_ftc.h, flt_dts.h) - AreaEffectSimulation DDS-Stubs (aes.hpp, aes_enums.hpp) - SymbolAppearance Klasse vollständig definiert mit content() Methode - BuildingComponentFilter Klasse definiert mit Copy-Konstruktor - Ftc Factory: nullptr Return (abstract class) - AesFilter Klasse in aes.hpp hinzugefügt - Dtc Klasse in ppm.hpp mit participantChanged Signal - AesType Enum: alle 15 At* Werte definiert - AesEffectState_def: EsReceived hinzugefügt - DataModification Enum: eAdded/eModified/eRemoved - function_reply_object.h → core_types.h Include-Pfad (72 Dateien) - Enum-Class-Streaming Template-Operator in INGLLogger.h - ism_mounting_point.h: QImage → QtGui/QImage, QGuiApplication/QScreen - ism_data_plugin_interface.h: QSet Include, Include-Reihenfolge - QRegExp → QRegularExpression in tpm_js_parser.cpp - .underlying() Aufrufe zu direktem Enum-Vergleich korrigiert - Include-Pfade: aes.hpp in symbol_appearance_settings_impl.h und aes_display_filter_impl.h Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
471 lines
13 KiB
C++
Executable File
471 lines
13 KiB
C++
Executable File
|
|
|
|
|
|
#include "xmlreader.h"
|
|
|
|
#include <QFile>
|
|
#include <QUrlQuery>
|
|
#include <QXmlStreamAttributes>
|
|
|
|
namespace BuildingControlUnit
|
|
{
|
|
|
|
XmlReader::XmlReader(QObject *parent)
|
|
: QObject(parent)
|
|
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("XmlReader"))
|
|
{
|
|
}
|
|
|
|
bool XmlReader::init(const QString &effectConfigFile)
|
|
{
|
|
m_contents.effects.clear();
|
|
|
|
QFile file(effectConfigFile);
|
|
DEBUG_LOG() << "open effectConfigFile: " << effectConfigFile;
|
|
|
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
|
{
|
|
WARNING_LOG() << "Couldn't open EffectConfigFile: " << effectConfigFile;
|
|
return false;
|
|
}
|
|
|
|
QXmlStreamReader xml(file.readAll());
|
|
while (!xml.atEnd() && !xml.hasError())
|
|
{
|
|
QXmlStreamReader::TokenType token = xml.readNext();
|
|
if (token == QXmlStreamReader::StartDocument)
|
|
continue;
|
|
else if (token == QXmlStreamReader::StartElement)
|
|
{
|
|
if (xml.name() == QStringLiteral("effects"))
|
|
continue;
|
|
else if (xml.name() == QStringLiteral("backgroundSoundVolume"))
|
|
m_contents.bgSoundVolume = xml.readElementText().toInt();
|
|
else if (xml.name() == QStringLiteral("hitSoundVolume"))
|
|
m_contents.hitSoundVolume = xml.readElementText().toInt();
|
|
else if (xml.name() == QStringLiteral("password"))
|
|
m_contents.password = xml.readElementText();
|
|
else if (xml.name() == QStringLiteral("port"))
|
|
m_contents.port = xml.readElementText().toInt();
|
|
else if (xml.name() == QStringLiteral("username"))
|
|
m_contents.username = xml.readElementText();
|
|
else if (xml.name() == QStringLiteral("updateRelayState"))
|
|
m_contents.updateRelayState = xml.readElementText().toInt();
|
|
|
|
if (xml.name() == QStringLiteral("effect"))
|
|
{
|
|
Effect *e = this->parseEffect(xml);
|
|
if (e)
|
|
m_contents.effects.append(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (xml.hasError())
|
|
{
|
|
ERROR_LOG() << "Effect Config File had XML Errors:\n" << xml.errorString();
|
|
return false;
|
|
}
|
|
|
|
DEBUG_LOG() << "Effect Config File Contents: " << m_contents.toString();
|
|
createHttpRequests();
|
|
return true;
|
|
}
|
|
|
|
Effect *XmlReader::parseEffect(QXmlStreamReader &xml)
|
|
{
|
|
DEBUG_LOG() << "- parseEffect Start";
|
|
|
|
if (xml.tokenType() != QXmlStreamReader::StartElement ||
|
|
xml.name() != QStringLiteral("effect"))
|
|
return {};
|
|
|
|
Effect *e = new Effect();
|
|
QXmlStreamAttributes attributes = xml.attributes();
|
|
|
|
if (attributes.hasAttribute(QStringLiteral("type")))
|
|
{
|
|
QString typeString = attributes.value(QStringLiteral("type")).toString();
|
|
if (typeString == QStringLiteral("relayAction"))
|
|
e->effectType = ET_Relay;
|
|
else if (typeString == QStringLiteral("backgroundSoundAction"))
|
|
e->effectType = ET_BackgroundSound;
|
|
else if (typeString == QStringLiteral("bsmFlashAction"))
|
|
e->effectType = ET_BsmFlash;
|
|
}
|
|
xml.readNext();
|
|
|
|
while (!(xml.tokenType() == QXmlStreamReader::EndElement &&
|
|
xml.name() == QStringLiteral("effect")))
|
|
{
|
|
if (xml.tokenType() == QXmlStreamReader::StartElement)
|
|
{
|
|
if (xml.name() == QStringLiteral("id"))
|
|
{
|
|
QXmlStreamAttributes attributesName = xml.attributes();
|
|
if (attributesName.hasAttribute(QStringLiteral("name")))
|
|
{
|
|
e->name = attributesName.value(QStringLiteral("name")).toString();
|
|
}
|
|
e->id = xml.readElementText().toInt();
|
|
}
|
|
|
|
if (xml.name() == QStringLiteral("category"))
|
|
{
|
|
e->category = static_cast<Category>(xml.readElementText().toInt());
|
|
}
|
|
|
|
if (xml.name() == QStringLiteral("override"))
|
|
{
|
|
e->override = static_cast<EffectOverride>(xml.readElementText().toInt());
|
|
}
|
|
|
|
if (xml.name() == QStringLiteral("range"))
|
|
e->ranges.append(parseRange(xml));
|
|
}
|
|
xml.readNext();
|
|
}
|
|
DEBUG_LOG() << "- parseEffect: Name: " << e->id
|
|
<< ", Type: " << e->effectType
|
|
<< ", Category: " << e->category
|
|
<< ", Name: " << e->name
|
|
<< ", override: " << e->override;
|
|
DEBUG_LOG() << "- parseEffect End. It has " << e->ranges.size() << " ranges";
|
|
return e;
|
|
}
|
|
|
|
Range *XmlReader::parseRange(QXmlStreamReader &xml)
|
|
{
|
|
if (xml.tokenType() != QXmlStreamReader::StartElement ||
|
|
xml.name() != QStringLiteral("range"))
|
|
return {};
|
|
|
|
DEBUG_LOG() << "-- parseRange Start";
|
|
Range *r = new Range();
|
|
|
|
QXmlStreamAttributes attributes = xml.attributes();
|
|
|
|
if (attributes.hasAttribute(QStringLiteral("min")))
|
|
r->min = attributes.value(QStringLiteral("min")).toInt();
|
|
if (attributes.hasAttribute(QStringLiteral("max")))
|
|
r->max = attributes.value(QStringLiteral("max")).toInt();
|
|
if (attributes.hasAttribute(QStringLiteral("restartOnChange")))
|
|
r->restartOnChange = attributes.value(QLatin1String("restartOnChange")).toString().toLower() == QLatin1String("true");
|
|
|
|
xml.readNext();
|
|
|
|
|
|
while (!(xml.tokenType() == QXmlStreamReader::EndElement &&
|
|
xml.name() == QLatin1String("range")))
|
|
{
|
|
Action *a = parseAction(xml);
|
|
if (a && a->aclass != AC_Unset)
|
|
r->actions << a;
|
|
|
|
xml.readNext();
|
|
}
|
|
DEBUG_LOG() << "-- parseRange: [" << r->min << "-" << r->max << "]"
|
|
<< ", restartOnChange: " <<r->restartOnChange
|
|
<< ", ActionCount: " << r->actions.count();
|
|
DEBUG_LOG() << "-- parseRange End";
|
|
return r;
|
|
}
|
|
|
|
Action *XmlReader::parseAction(QXmlStreamReader &xml)
|
|
{
|
|
if (xml.tokenType() != QXmlStreamReader::StartElement)
|
|
return {};
|
|
|
|
if (xml.name() == QStringLiteral("action"))
|
|
return parseStandardAction(xml);;
|
|
|
|
if (xml.name() == QStringLiteral("pause"))
|
|
return parsePauseAction(xml);
|
|
|
|
if (xml.name() == QStringLiteral("repeat"))
|
|
return parseRepeatAction(xml);
|
|
|
|
if (xml.name() == QStringLiteral("bsm"))
|
|
return parseBsmAction(xml);
|
|
|
|
WARNING_LOG() << "--- parseUnknownAction with name '" << xml.name().string() << "'cannot be handled.";
|
|
return {};
|
|
}
|
|
|
|
PauseAction *XmlReader::parsePauseAction(QXmlStreamReader &xml)
|
|
{
|
|
if (xml.tokenType() != QXmlStreamReader::StartElement ||
|
|
xml.name() != QLatin1String("pause"))
|
|
return {};
|
|
|
|
DEBUG_LOG() << "--- parsePauseAction Start";
|
|
QXmlStreamAttributes attributes = xml.attributes();
|
|
PauseAction *p = new PauseAction();
|
|
p->atype = static_cast<ActionType>(attributes.value(QStringLiteral("type")).toInt());
|
|
if (attributes.hasAttribute(QStringLiteral("comment")))
|
|
p->comment = attributes.value(QStringLiteral("comment")).toString();
|
|
p->pause = xml.readElementText().toInt();
|
|
DEBUG_LOG() << "--- parsePauseAction: "
|
|
<< " Pause: " << p->pause
|
|
<< ", Comment: " << p->comment;
|
|
|
|
DEBUG_LOG() << "--- parsePauseAction End";
|
|
return p;
|
|
}
|
|
|
|
RepeatAction *XmlReader::parseRepeatAction(QXmlStreamReader &xml)
|
|
{
|
|
if (xml.tokenType() != QXmlStreamReader::StartElement ||
|
|
xml.name() != QStringLiteral("repeat"))
|
|
return {};
|
|
DEBUG_LOG() << "--- parseRepeatAction Start";
|
|
RepeatAction *ra = new RepeatAction();
|
|
QXmlStreamAttributes attributes = xml.attributes();
|
|
|
|
if (attributes.hasAttribute(QStringLiteral("count")))
|
|
ra->count = attributes.value(QStringLiteral("count")).toInt();
|
|
if (attributes.hasAttribute(QStringLiteral("comment")))
|
|
ra->comment = attributes.value(QStringLiteral("comment")).toString();
|
|
|
|
if (ra->count == 0)
|
|
ra->count = -1;
|
|
|
|
xml.readNext();
|
|
|
|
while (!(xml.tokenType() == QXmlStreamReader::EndElement &&
|
|
xml.name() == QStringLiteral("repeat")))
|
|
{
|
|
Action *a = parseAction(xml);
|
|
if (a && a->aclass != AC_Unset)
|
|
ra->actions << a;
|
|
xml.readNext();
|
|
}
|
|
|
|
QString repetitions = QString::number(ra->count);
|
|
if (ra->count < 0)
|
|
repetitions = QLatin1String("Infinite");
|
|
DEBUG_LOG() << "--- parseRepeatAction: Repetitions: " << repetitions << ", Comment: " << ra->comment;
|
|
DEBUG_LOG() << "--- parseRepeatAction End";
|
|
return ra;
|
|
}
|
|
|
|
Action *XmlReader::parseStandardAction(QXmlStreamReader &xml)
|
|
{
|
|
|
|
if (xml.tokenType() != QXmlStreamReader::StartElement ||
|
|
xml.name() != QStringLiteral("action"))
|
|
return {};
|
|
|
|
DEBUG_LOG() << "--- parseStandardAction Start";
|
|
|
|
QXmlStreamAttributes attributes = xml.attributes();
|
|
|
|
if (!attributes.hasAttribute(QStringLiteral("type")))
|
|
return {};
|
|
|
|
Action *a = new Action();
|
|
|
|
a->aclass = AC_Standard;
|
|
a->atype = static_cast<ActionType>(attributes.value(QStringLiteral("type")).toInt());
|
|
if (attributes.hasAttribute(QStringLiteral("comment")))
|
|
a->comment = attributes.value(QStringLiteral("comment")).toString();
|
|
DEBUG_LOG() << "--- parseStandardAction: Type: " << a->atype
|
|
<< ", Comment: " << a->comment;
|
|
DEBUG_LOG() << "--- parseStandardAction End";
|
|
return a;
|
|
}
|
|
|
|
BsmAction *XmlReader::parseBsmAction(QXmlStreamReader &xml)
|
|
{
|
|
QXmlStreamAttributes attributes = xml.attributes();
|
|
|
|
|
|
DEBUG_LOG() << "--- parseBsmAction Start";
|
|
BsmAction *a = new BsmAction();
|
|
a->atype = static_cast<ActionType>(attributes.value(QStringLiteral("type")).toInt());
|
|
if (attributes.hasAttribute(QStringLiteral("comment")))
|
|
a->comment = attributes.value(QStringLiteral("comment")).toString();
|
|
|
|
xml.readNext();
|
|
while (!(xml.tokenType() == QXmlStreamReader::EndElement &&
|
|
xml.name() == QStringLiteral("bsm")))
|
|
{
|
|
|
|
if (xml.name() == QStringLiteral("pause"))
|
|
a->pause = xml.readElementText().toInt();
|
|
if (xml.name() == QStringLiteral("choplength"))
|
|
a->choplength = xml.readElementText().toInt();
|
|
if (xml.name() == QStringLiteral("pulses"))
|
|
a->pulses = xml.readElementText().toInt();
|
|
if (xml.name() == QStringLiteral("pulseduration"))
|
|
a->pulseduration = xml.readElementText().toInt();
|
|
xml.readNext();
|
|
}
|
|
|
|
DEBUG_LOG() << "--- parseBsmAction: Type: " << a->atype
|
|
<< ", Pause: " << a->pause
|
|
<< ", Choplength: " << a->choplength
|
|
<< ", Count: " << a->count
|
|
<< ", Pulses: " << a->pulses
|
|
<< ", Pulseduration: " << a->pulseduration
|
|
<< ", Comment: " << a->comment;
|
|
DEBUG_LOG() << "--- parseBsmAction End";
|
|
return a;
|
|
}
|
|
|
|
|
|
|
|
void XmlReader::createHttpRequests()
|
|
{
|
|
for (const Effect *e : m_contents.constEffects())
|
|
{
|
|
for (const Range *r : e->constRanges())
|
|
{
|
|
generateUrls(e, r->actions);
|
|
}
|
|
}
|
|
}
|
|
|
|
QUrl XmlReader::createPreparedUrl(const XmlContents &contents, const QString &hostname)
|
|
{
|
|
QUrl url;
|
|
url.setScheme(QStringLiteral("http"));
|
|
url.setUserName(contents.username);
|
|
url.setPassword(contents.password);
|
|
if (!hostname.isEmpty())
|
|
url.setHost(hostname);
|
|
url.setPort(contents.port);
|
|
return url;
|
|
}
|
|
|
|
void XmlReader::generateUrl(const Effect *e, Action *a)
|
|
{
|
|
switch (a->aclass)
|
|
{
|
|
case AC_Standard:
|
|
{
|
|
QUrl url = createPreparedUrl(m_contents);
|
|
QUrlQuery query;
|
|
|
|
switch (e->effectType)
|
|
{
|
|
case ET_Relay:
|
|
{
|
|
url.setPath(QStringLiteral("/relay.php"));
|
|
query.addQueryItem(QStringLiteral("state"), QString::number(a->atype));
|
|
query.addQueryItem(QStringLiteral("number"), QString::number(e->id));
|
|
break;
|
|
}
|
|
case ET_BackgroundSound:
|
|
{
|
|
url.setPath(QStringLiteral("/bgsound.php"));
|
|
query.addQueryItem(QStringLiteral("category"), categoryName(e->category));
|
|
query.addQueryItem(QStringLiteral("sound"), QString::number(e->id));
|
|
query.addQueryItem(QStringLiteral("vol"), QString::number(m_contents.bgSoundVolume));
|
|
switch (a->atype)
|
|
{
|
|
case AT_Off:
|
|
query.addQueryItem(QStringLiteral("control"), QStringLiteral("2"));
|
|
break;
|
|
case AT_On:
|
|
query.addQueryItem(QStringLiteral("control"), QStringLiteral("1"));
|
|
break;
|
|
case AT_Infinite:
|
|
query.addQueryItem(QStringLiteral("control"), QStringLiteral("3"));
|
|
break;
|
|
case AT_Flash:
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
url.setQuery(query);
|
|
a->url = url;
|
|
DEBUG_LOG() << "Effect " << e->name << ", Action '" << a->comment << "' now has URL: " << url.toString();
|
|
break;
|
|
}
|
|
case AC_Repeat:
|
|
{
|
|
const RepeatAction *ra = static_cast<const RepeatAction *>(a);
|
|
generateUrls(e, ra->actions);
|
|
break;
|
|
}
|
|
case AC_Unset:
|
|
case AC_Pause:
|
|
case AC_Bsm:
|
|
default:
|
|
DEBUG_LOG() << "Effect " << e->name << ", Action '" << a->comment << "' of Type " << a->aclass << " needs no URL";
|
|
break;
|
|
}
|
|
}
|
|
|
|
void XmlReader::generateUrls(const Effect *e, const QVector<Action *> &actions)
|
|
{
|
|
for (Action *a : actions)
|
|
generateUrl(e,a);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Range* Effect::getRangeByDamagePercent(int damagePercent) const
|
|
{
|
|
for (Range *r : ranges)
|
|
{
|
|
if (r->fits(damagePercent))
|
|
return r;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
QString XmlReader::categoryName(Category c)
|
|
{
|
|
switch (c)
|
|
{
|
|
case CT_BGS_Bahnhof:
|
|
return QStringLiteral("bahnhof");
|
|
case CT_BGS_Personen:
|
|
return QStringLiteral("personen");
|
|
case CT_BGS_Sonstige:
|
|
return QStringLiteral("sonstige");
|
|
case CT_BGS_Stadt:
|
|
return QStringLiteral("stadt");
|
|
case CT_BGS_Testsounds:
|
|
return QStringLiteral("testsounds");
|
|
case CT_BGS_Aircrafts:
|
|
return QStringLiteral("Aircrafts");
|
|
case CT_BGS_Battlefields:
|
|
return QStringLiteral("Battlefields");
|
|
case CT_BGS_Boats:
|
|
return QStringLiteral("Boats");
|
|
case CT_BGS_Explosions:
|
|
return QStringLiteral("Explosions");
|
|
case CT_BGS_Helicopter:
|
|
return QStringLiteral("Helicopter");
|
|
case CT_BGS_Motors_and_urban_traffic:
|
|
return QStringLiteral("Motors_and_urban_traffic");
|
|
case CT_BGS_InsideBuildings:
|
|
return QStringLiteral("Inside_buildings");
|
|
case CT_BGS_Vehicles:
|
|
return QStringLiteral("Vehicles");
|
|
case CT_Default:
|
|
default:
|
|
return QStringLiteral("Default");
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
}
|