diff --git a/qrail.pri b/qrail.pri index 3890aea..4155853 100644 --- a/qrail.pri +++ b/qrail.pri @@ -32,8 +32,12 @@ SOURCES += \ $$PWD/src/engines/router/routerroutelegend.cpp \ $$PWD/src/engines/router/routerstationstopprofile.cpp \ $$PWD/src/engines/router/routertrainprofile.cpp \ + $$PWD/src/engines/router/routerjourney.cpp \ + $$PWD/src/engines/router/routernulljourney.cpp \ $$PWD/src/engines/liveboard/liveboardfactory.cpp \ $$PWD/src/engines/liveboard/liveboardboard.cpp \ + $$PWD/src/engines/liveboard/liveboardnullboard.cpp \ + $$PWD/src/engines/vehicle/vehiclenullvehicle.cpp \ $$PWD/src/engines/station/stationstation.cpp \ $$PWD/src/engines/station/stationnullstation.cpp \ $$PWD/src/engines/station/stationfactory.cpp \ @@ -47,9 +51,7 @@ SOURCES += \ $$PWD/src/fragments/fragmentspage.cpp \ $$PWD/src/fragments/fragmentsfactory.cpp \ $$PWD/src/fragments/fragmentsdispatcher.cpp \ - $$PWD/src/qrail.cpp \ - $$PWD/src/engines/vehicle/vehiclenullvehicle.cpp \ - $$PWD/src/engines/liveboard/liveboardnullboard.cpp + $$PWD/src/qrail.cpp HEADERS += \ $$PWD/src/include/engines/alerts/alertsmessage.h \ @@ -60,6 +62,8 @@ HEADERS += \ $$PWD/src/include/engines/router/routerroutelegend.h \ $$PWD/src/include/engines/router/routerstationstopprofile.h \ $$PWD/src/include/engines/router/routertrainprofile.h \ + $$PWD/src/include/engines/router/routerjourney.h \ + $$PWD/src/include/engines/router/routernulljourney.h \ $$PWD/src/include/engines/liveboard/liveboardfactory.h \ $$PWD/src/include/engines/liveboard/liveboardboard.h \ $$PWD/src/include/engines/liveboard/liveboardnullboard.h \ diff --git a/qrail.pro b/qrail.pro index d8ae877..c2b5fd1 100644 --- a/qrail.pro +++ b/qrail.pro @@ -16,7 +16,7 @@ # TARGET = qrail -VERSION = 0.0.2 +VERSION = 0.0.4 # Uncomment this config if you want to build a static library CONFIG += staticlib diff --git a/src/engines/liveboard/liveboardboard.cpp b/src/engines/liveboard/liveboardboard.cpp index 54ae72b..1c115cf 100644 --- a/src/engines/liveboard/liveboardboard.cpp +++ b/src/engines/liveboard/liveboardboard.cpp @@ -55,6 +55,8 @@ QRail::LiveboardEngine::Board::Board(const QListhydraNext() << - timeOldHydraNext; // Only accept URI that's later in time if (timeNewHydraNext > timeOldHydraNext) { m_hydraNext = hydraNext; @@ -130,7 +130,6 @@ void QRail::LiveboardEngine::Board::setHydraNext(const QUrl &hydraNext) } // Current hydraNext is still empty, setting it to the received hydraNext else { - qDebug() << "Empty hydraNext"; m_hydraNext = hydraNext; emit this->hydraNextChanged(); } @@ -151,9 +150,6 @@ void QRail::LiveboardEngine::Board::setHydraPrevious(const QUrl &hydraPrevious) queryNewHydraPrevious.queryItemValue("departureTime"), Qt::ISODate); QDateTime timeOldHydraPrevious = QDateTime::fromString( queryOldHydraPrevious.queryItemValue("departureTime"), Qt::ISODate); - qDebug() << "HYDRA PREVIOUS=" << hydraPrevious << timeNewHydraPrevious << "|" << - this->hydraPrevious() << - timeOldHydraPrevious; // Only accept URI that's earlier in time if (timeNewHydraPrevious < timeOldHydraPrevious) { m_hydraPrevious = hydraPrevious; @@ -162,7 +158,6 @@ void QRail::LiveboardEngine::Board::setHydraPrevious(const QUrl &hydraPrevious) } // Current hydraPrevious is still empty, setting it to the received hydraPrevious else { - qDebug() << "Empty hydraPrevious"; m_hydraPrevious = hydraPrevious; emit this->hydraPreviousChanged(); } diff --git a/src/engines/router/routerjourney.cpp b/src/engines/router/routerjourney.cpp new file mode 100644 index 0000000..adf3f56 --- /dev/null +++ b/src/engines/router/routerjourney.cpp @@ -0,0 +1,192 @@ +/* + * This file is part of QRail. + * + * QRail is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QRail is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QRail. If not, see . + */ +#include "engines/router/routerjourney.h" +using namespace QRail; + +RouterEngine::Journey::Journey(QObject *parent) : QObject(parent) +{ + +} + +RouterEngine::Journey::Journey(const QList &routes, + const QMap &TArray, + const QMap > &SArray, + const QUrl &departureStation, + const QUrl &arrivalStation, + const QDateTime &departureTime, + const QDateTime &arrivalTime, + const quint16 &maxTransfers, + QObject *parent) : QObject(parent) +{ + // Use private members to avoid signal firing on construction + m_routes = routes; + m_TArray = TArray; + m_SArray = SArray; + m_departureStation = departureStation; + m_arrivalStation = arrivalStation; + m_departureTime = departureTime; + m_arrivalTime = arrivalTime; + m_maxTransfers = maxTransfers; + m_hydraPrevious = QUrl(); + m_hydraNext = QUrl(); +} + +// Getters & Setters +QList RouterEngine::Journey::routes() const +{ + return m_routes; +} + +void RouterEngine::Journey::setRoutes(const QList &routes) +{ + m_routes = routes; + emit this->routesChanged(); +} + +QMap RouterEngine::Journey::TArray() const +{ + return m_TArray; +} + +void RouterEngine::Journey::setTArray(const QMap + &TArray) +{ + m_TArray = TArray; + emit this->TArrayChanged(); +} + +QMap > RouterEngine::Journey::SArray() const +{ + return m_SArray; +} + +void RouterEngine::Journey::setSArray(const + QMap > &SArray) +{ + m_SArray = SArray; + emit this->SArrayChanged(); +} + +QUrl RouterEngine::Journey::departureStation() const +{ + return m_departureStation; +} + +void RouterEngine::Journey::setDepartureStation(const QUrl &departureStation) +{ + m_departureStation = departureStation; + emit this->departureStationChanged(); +} + +QUrl RouterEngine::Journey::arrivalStation() const +{ + return m_arrivalStation; +} + +void RouterEngine::Journey::setArrivalStation(const QUrl &arrivalStation) +{ + m_arrivalStation = arrivalStation; + emit this->arrivalStationChanged(); +} + +quint16 RouterEngine::Journey::maxTransfers() const +{ + return m_maxTransfers; +} + +void RouterEngine::Journey::setMaxTransfers(const quint16 &maxTransfers) +{ + m_maxTransfers = maxTransfers; + emit this->maxTransfersChanged(); +} + +QUrl RouterEngine::Journey::hydraPrevious() const +{ + return m_hydraPrevious; +} + +void RouterEngine::Journey::setHydraPrevious(const QUrl &hydraPrevious) +{ + // New hydraPrevious URI is earlier in time? + if (hydraPrevious.hasQuery() && this->hydraPrevious().hasQuery()) { + QUrlQuery queryNewHydraPrevious = QUrlQuery(hydraPrevious.query()); + QUrlQuery queryOldHydraPrevious = QUrlQuery(this->hydraPrevious().query()); + QDateTime timeNewHydraPrevious = QDateTime::fromString( + queryNewHydraPrevious.queryItemValue("departureTime"), Qt::ISODate); + QDateTime timeOldHydraPrevious = QDateTime::fromString( + queryOldHydraPrevious.queryItemValue("departureTime"), Qt::ISODate); + // Only accept URI that's earlier in time + if (timeNewHydraPrevious < timeOldHydraPrevious) { + m_hydraPrevious = hydraPrevious; + emit this->hydraPreviousChanged(); + } + } + // Current hydraPrevious is still empty, setting it to the received hydraPrevious + else { + m_hydraPrevious = hydraPrevious; + emit this->hydraPreviousChanged(); + } +} + +QUrl RouterEngine::Journey::hydraNext() const +{ + return m_hydraNext; +} + +void RouterEngine::Journey::setHydraNext(const QUrl &hydraNext) +{ + // New hydraNext URI is further in time? + if (hydraNext.hasQuery() && this->hydraNext().isValid()) { + QUrlQuery queryNewHydraNext = QUrlQuery(hydraNext.query()); + QUrlQuery queryOldHydraNext = QUrlQuery(this->hydraNext().query()); + QDateTime timeNewHydraNext = QDateTime::fromString( + queryNewHydraNext.queryItemValue("departureTime"), Qt::ISODate); + QDateTime timeOldHydraNext = QDateTime::fromString( + queryOldHydraNext.queryItemValue("departureTime"), Qt::ISODate); + + // Only accept URI that's later in time + if (timeNewHydraNext > timeOldHydraNext) { + m_hydraNext = hydraNext; + emit this->hydraNextChanged(); + } + } + // Current hydraNext is still empty, setting it to the received hydraNext + else { + m_hydraNext = hydraNext; + emit this->hydraNextChanged(); + } +} + +QDateTime RouterEngine::Journey::arrivalTime() const +{ + return m_arrivalTime; +} + +void RouterEngine::Journey::setArrivalTime(const QDateTime &arrivalTime) +{ + m_arrivalTime = arrivalTime; +} + +QDateTime RouterEngine::Journey::departureTime() const +{ + return m_departureTime; +} + +void RouterEngine::Journey::setDepartureTime(const QDateTime &departureTime) +{ + m_departureTime = departureTime; +} diff --git a/src/engines/router/routernulljourney.cpp b/src/engines/router/routernulljourney.cpp new file mode 100644 index 0000000..b6b6c01 --- /dev/null +++ b/src/engines/router/routernulljourney.cpp @@ -0,0 +1,71 @@ +/* + * This file is part of QRail. + * + * QRail is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QRail is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QRail. If not, see . + */ +#include "engines/router/routernulljourney.h" +using namespace QRail; +RouterEngine::NullJourney *RouterEngine::NullJourney::m_instance = nullptr; + +/** + * @file routernulljourney.cpp + * @author Dylan Van Assche + * @date 07 Oct 2018 + * @brief Gets a RouterEngine::NullJourney instance + * @return RouterEngine::NullJourney *journey + * @package RouterEngine + * @public + * Constructs a RouterEngine::NullJourney if none exists and returns the instance. + */ +RouterEngine::NullJourney::NullJourney( + const QList &routes, + const QMap &TArray, + const QMap > &SArray, + const QUrl &departureStation, + const QUrl &arrivalStation, + const QDateTime &departureTime, + const QDateTime &arrivalTime, + const quint16 &maxTransfers, + QObject *parent) : RouterEngine::Journey(routes, TArray, SArray, departureStation, arrivalStation, + departureTime, arrivalTime, maxTransfers, parent) +{ + +} + +/** + * @file routernulljourney.cpp + * @author Dylan Van Assche + * @date 07 Oct 2018 + * @brief Gets a RouterEngine::NullJourney instance + * @return RouterEngine::NullJourney *journey + * @package RouterEngine + * @public + * Constructs a RouterEngine::NullJourney if none exists and returns the instance. + */ +RouterEngine::NullJourney *QRail::RouterEngine::NullJourney::getInstance() +{ + // Singleton pattern + if (m_instance == nullptr) { + qDebug() << "Generating new NullJourney"; + m_instance = new NullJourney(QList(), + QMap(), + QMap >(), + QUrl(), + QUrl(), + QDateTime(), + QDateTime(), + 0); + } + return m_instance; +} diff --git a/src/engines/router/routerplanner.cpp b/src/engines/router/routerplanner.cpp index 14181d7..f00f345 100644 --- a/src/engines/router/routerplanner.cpp +++ b/src/engines/router/routerplanner.cpp @@ -81,6 +81,19 @@ void QRail::RouterEngine::Planner::getConnections(const QUrl &departureStation, const QUrl &arrivalStation, const QDateTime &departureTime, const quint16 &maxTransfers) +{ + this->getConnections(departureStation, + arrivalStation, + departureTime, + this->calculateArrivalTime(departureTime), + maxTransfers); +} + +void RouterEngine::Planner::getConnections(const QUrl &departureStation, + const QUrl &arrivalStation, + const QDateTime &departureTime, + const QDateTime &arrivalTime, + const quint16 &maxTransfers) { /* * The CSA algorithm is based on the Connection Scan Algorithm paper, March @@ -110,7 +123,10 @@ void QRail::RouterEngine::Planner::getConnections(const QUrl &departureStation, * Docs: https://doc.qt.io/qt-5.6/qtconcurrent.html */ - if (departureStation.isValid() && arrivalStation.isValid() && departureStation.isValid()) { + if (departureStation.isValid() + && arrivalStation.isValid() + && departureTime.isValid() + && arrivalTime.isValid()) { qDebug() << "Init CSA algorithm"; plannerProcessingMutex.lock(); // Queue requests this->setTArray(QMap()); @@ -118,10 +134,19 @@ void QRail::RouterEngine::Planner::getConnections(const QUrl &departureStation, this->setDepartureStationURI(departureStation); this->setArrivalStationURI(arrivalStation); this->setDepartureTime(departureTime); - this->setArrivalTime(this->calculateArrivalTime(this->departureTime())); + this->setArrivalTime(arrivalTime); this->setMaxTransfers(maxTransfers); this->setRoutes(QList()); this->initUsedPages(); + this->setJourney(new QRail::RouterEngine::Journey()); + this->journey()->setTArray(QMap()); + this->journey()->setSArray(QMap>()); + this->journey()->setDepartureStation(departureStation); + this->journey()->setArrivalStation(arrivalStation); + this->journey()->setDepartureTime(departureTime); + this->journey()->setArrivalTime(arrivalTime); + this->journey()->setMaxTransfers(maxTransfers); + this->journey()->setRoutes(QList()); /* * Setup footpaths for the arrival station since CSA profile @@ -148,7 +173,6 @@ void QRail::RouterEngine::Planner::getConnections(const QUrl &departureStation, // Jumpstart the page fetching this->fragmentsFactory()->getPage(this->arrivalTime(), this); - //qApp->processEvents(); qDebug() << "CSA init OK"; } else { qCritical() << "Invalid stations or timestamps"; @@ -173,7 +197,7 @@ void QRail::RouterEngine::Planner::getConnections(const QUrl &departureStation, * a maximum of transfers. Emit the finished signal when completed, the error * signal is emitted in case an error comes up. * - * Invalid input will directly emit the finished signal with an empty list. + * Invalid input will directly emit the finished signal with a NullJourney instance. */ void RouterEngine::Planner::getConnections(const QGeoCoordinate &departurePosition, const QGeoCoordinate &arrivalPosition, @@ -191,10 +215,74 @@ void RouterEngine::Planner::getConnections(const QGeoCoordinate &departurePositi qCritical() << "Departure position:" << departurePosition; qCritical() << "Arrival position:" << arrivalPosition; qCritical() << "Departure time:" << departureTime; - emit this->finished(QList()); + emit this->finished(QRail::RouterEngine::NullJourney::getInstance()); } } +void RouterEngine::Planner::getNextConnectionForJourney(RouterEngine::Journey *journey) +{ + // Later arrival time is a problem! The S and T array are different since CSA runs backwards + // A better solution here would be great! TO DO + /*this->setTArray(QMap()); + this->setSArray(QMap>()); + QUrlQuery queryHydraNext = QUrlQuery(journey->hydraNext().query()); + QDateTime timeHydraNext = QDateTime::fromString( + queryHydraNext.queryItemValue("departureTime"), Qt::ISODate); + this->setDepartureTime(journey->departureTime()); + this->setArrivalTime(timeHydraNext); + this->setDepartureStationURI(journey->departureStation()); + this->setArrivalStationURI(journey->arrivalStation()); + + // Jumpstart the page fetching, use hydraPrevious to get the previous page of the last page + this->fragmentsFactory()->getPage(journey->hydraNext(), this);*/ + QUrlQuery queryHydraNext = QUrlQuery(journey->hydraNext().query()); + QDateTime timeHydraNext = QDateTime::fromString( + queryHydraNext.queryItemValue("departureTime"), Qt::ISODate); + qDebug() << "NEXT connections"; + qDebug() << journey->departureStation(); + qDebug() << journey->arrivalStation(); + qDebug() << journey->departureTime(); + qDebug() << timeHydraNext; + qDebug() << journey->maxTransfers(); + this->getConnections(journey->departureStation(), + journey->arrivalStation(), + journey->departureTime(), + timeHydraNext, + journey->maxTransfers()); +} + +void RouterEngine::Planner::getPreviousConnectionForJourney(RouterEngine::Journey *journey) +{ + // Later arrival time is a problem! The S and T array are different since CSA runs backwards + // A better solution here would be great! TO DO + /*this->setSArray(journey->SArray()); + this->setTArray(journey->TArray()); + QUrlQuery queryHydraPrevious = QUrlQuery(journey->hydraPrevious().query()); + QDateTime timeHydraPrevious = QDateTime::fromString( + queryHydraPrevious.queryItemValue("departureTime"), Qt::ISODate); + this->setDepartureTime(timeHydraPrevious); + this->setArrivalTime(journey->arrivalTime()); + this->setDepartureStationURI(journey->departureStation()); + this->setArrivalStationURI(journey->arrivalStation()); + + // Jumpstart the page fetching, use hydraPrevious to get the previous page of the last page + this->fragmentsFactory()->getPage(journey->hydraPrevious(), this);*/ + QUrlQuery queryHydraPrevious = QUrlQuery(journey->hydraPrevious().query()); + QDateTime timeHydraPrevious = QDateTime::fromString( + queryHydraPrevious.queryItemValue("departureTime"), Qt::ISODate); + qDebug() << "PREVIOUS connections"; + qDebug() << journey->departureStation(); + qDebug() << journey->arrivalStation(); + qDebug() << timeHydraPrevious; + qDebug() << journey->arrivalTime(); + qDebug() << journey->maxTransfers(); + this->getConnections(journey->departureStation(), + journey->arrivalStation(), + timeHydraPrevious, + journey->arrivalTime(), + journey->maxTransfers()); +} + // Processors /** * @file routerplanner.cpp @@ -236,6 +324,10 @@ void QRail::RouterEngine::Planner::parsePage(QRail::Fragments::Page *page) qDebug() << "\tmaxTransfers:" << this->maxTransfers(); #endif + // Update hydraPrevious and hydraNext pointers + this->journey()->setHydraNext(page->hydraNext()); + this->journey()->setHydraPrevious(page->hydraPrevious()); + // Keep a reference to this page for later deletion this->addToUsedPages(page); @@ -246,8 +338,6 @@ void QRail::RouterEngine::Planner::parsePage(QRail::Fragments::Page *page) // We can only process fragments which are departing after our departure time if (fragment->departureTime() < this->departureTime()) { - qDebug() << fragment->departureTime() << fragment->uri() << "in page:" << page->uri(); - qDebug() << fragment->departureTime().isValid(); hasPassedDepartureTimeLimit = true; continue; } @@ -713,7 +803,7 @@ void QRail::RouterEngine::Planner::parsePage(QRail::Fragments::Page *page) // Results found, process them if (this->SArray().contains(this->departureStationURI())) { - qDebug() << "Processing results: " << this->SArray().value(this->departureStationURI()); + //qDebug() << "Processing results: " << this->SArray().value(this->departureStationURI()); foreach (QRail::RouterEngine::StationStopProfile *profile, this->SArray().value(this->departureStationURI())) { QList legs = QList(); @@ -830,7 +920,6 @@ void QRail::RouterEngine::Planner::parsePage(QRail::Fragments::Page *page) // Routes with the same arrival and departure times are duplicates if (route->departureTime() == r->departureTime() && route->arrivalTime() == r->arrivalTime()) { - qDebug() << "Duplicate found, skipping"; newRoute = false; break; } @@ -881,7 +970,10 @@ void QRail::RouterEngine::Planner::parsePage(QRail::Fragments::Page *page) } // Emit finished signal when we completely parsed and processed all Linked Connections pages - emit this->finished(this->routes()); + this->journey()->setRoutes(this->routes()); + this->journey()->setTArray(this->TArray()); + this->journey()->setSArray(this->SArray()); + emit this->finished(this->journey()); // Clean up pages when we're finished this->deleteUsedPages(); @@ -954,8 +1046,7 @@ QRail::RouterEngine::StationStopProfile *QRail::RouterEngine::Planner::getFirstR */ void QRail::RouterEngine::Planner::processPage(QRail::Fragments::Page *page) { - qDebug() << "Factory generated requested Linked Connection page:" << page << - "starting processing thread..."; + //qDebug() << "Factory generated requested Linked Connection page:" << page << "starting processing thread..."; emit this->processing(page->uri()); /* @@ -966,7 +1057,7 @@ void QRail::RouterEngine::Planner::processPage(QRail::Fragments::Page *page) * If not, fetch new pages */ if (page->fragments().first()->departureTime() > this->departureTime()) { - qDebug() << "Requesting another page from QRail::Fragments::Factory"; + //qDebug() << "Requesting another page from QRail::Fragments::Factory"; this->fragmentsFactory()->getPage(page->hydraPrevious(), this); emit this->requested(page->hydraPrevious()); } @@ -1362,3 +1453,13 @@ void QRail::RouterEngine::Planner::setSArray(const { m_SArray = SArray; } + +QRail::RouterEngine::Journey *RouterEngine::Planner::journey() const +{ + return m_journey; +} + +void RouterEngine::Planner::setJourney(QRail::RouterEngine::Journey *journey) +{ + m_journey = journey; +} diff --git a/src/include/engines/liveboard/liveboardnullboard.h b/src/include/engines/liveboard/liveboardnullboard.h index b4d17ba..e50cc77 100644 --- a/src/include/engines/liveboard/liveboardnullboard.h +++ b/src/include/engines/liveboard/liveboardnullboard.h @@ -35,11 +35,11 @@ class QRAIL_SHARED_EXPORT NullBoard : public LiveboardEngine::Board static NullBoard *getInstance(); private: - NullBoard(const QList &entries, - StationEngine::Station *station, - const QDateTime &from, - const QDateTime &until, - QObject *parent = nullptr); + explicit NullBoard(const QList &entries, + StationEngine::Station *station, + const QDateTime &from, + const QDateTime &until, + QObject *parent = nullptr); static LiveboardEngine::NullBoard *m_instance; }; } diff --git a/src/include/engines/router/routerjourney.h b/src/include/engines/router/routerjourney.h new file mode 100644 index 0000000..1da3c4e --- /dev/null +++ b/src/include/engines/router/routerjourney.h @@ -0,0 +1,93 @@ +/* + * This file is part of QRail. + * + * QRail is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QRail is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QRail. If not, see . + */ +#ifndef ROUTERJOURNEY_H +#define ROUTERJOURNEY_H + +#include +#include +#include +#include +#include +#include + +#include "engines/router/routerroute.h" +#include "engines/router/routerstationstopprofile.h" +#include "engines/router/routertrainprofile.h" + +namespace QRail { +namespace RouterEngine { +class Journey : public QObject +{ + Q_OBJECT +public: + explicit Journey(QObject *parent = nullptr); + explicit Journey(const QList &routes, + const QMap &TArray, + const QMap > &SArray, + const QUrl &departureStation, + const QUrl &arrivalStation, + const QDateTime &departureTime, + const QDateTime &arrivalTime, + const quint16 &maxTransfers, + QObject *parent = nullptr); + QList routes() const; + void setRoutes(const QList &routes); + QMap TArray() const; + void setTArray(const QMap &TArray); + QMap > SArray() const; + void setSArray(const QMap > &SArray); + QUrl departureStation() const; + void setDepartureStation(const QUrl &departureStation); + QUrl arrivalStation() const; + void setArrivalStation(const QUrl &arrivalStation); + quint16 maxTransfers() const; + void setMaxTransfers(const quint16 &maxTransfers); + QUrl hydraPrevious() const; + void setHydraPrevious(const QUrl &hydraPrevious); + QUrl hydraNext() const; + void setHydraNext(const QUrl &hydraNext); + QDateTime departureTime() const; + void setDepartureTime(const QDateTime &departureTime); + QDateTime arrivalTime() const; + void setArrivalTime(const QDateTime &arrivalTime); + +signals: + void routesChanged(); + void TArrayChanged(); + void SArrayChanged(); + void departureStationChanged(); + void arrivalStationChanged(); + void maxTransfersChanged(); + void hydraPreviousChanged(); + void hydraNextChanged(); + +private: + QList m_routes; + QMap m_TArray; + QMap > m_SArray; + QUrl m_departureStation; + QUrl m_arrivalStation; + QDateTime m_departureTime; + QDateTime m_arrivalTime; + quint16 m_maxTransfers; + QUrl m_hydraPrevious; + QUrl m_hydraNext; +}; +} +} + +#endif // ROUTERJOURNEY_H diff --git a/src/include/engines/router/routernulljourney.h b/src/include/engines/router/routernulljourney.h new file mode 100644 index 0000000..85282d3 --- /dev/null +++ b/src/include/engines/router/routernulljourney.h @@ -0,0 +1,53 @@ +/* + * This file is part of QRail. + * + * QRail is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QRail is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QRail. If not, see . + */ +#ifndef ROUTERNULLJOURNEY_H +#define ROUTERNULLJOURNEY_H + +#include +#include +#include +#include +#include + +#include "engines/router/routertrainprofile.h" +#include "engines/router/routerstationstopprofile.h" +#include "engines/router/routerjourney.h" +#include "qrail.h" + +namespace QRail { +namespace RouterEngine { +class QRAIL_SHARED_EXPORT NullJourney : public RouterEngine::Journey +{ +public: + static NullJourney *getInstance(); + +private: + explicit NullJourney(const QList &routes, + const QMap &TArray, + const QMap > &SArray, + const QUrl &departureStation, + const QUrl &arrivalStation, + const QDateTime &departureTime, + const QDateTime &arrivalTime, + const quint16 &maxTransfers, + QObject *parent = nullptr); + static RouterEngine::NullJourney *m_instance; +}; +} +} + +#endif // ROUTERNULLJOURNEY_H diff --git a/src/include/engines/router/routerplanner.h b/src/include/engines/router/routerplanner.h index 4ea2c00..8c27a6c 100644 --- a/src/include/engines/router/routerplanner.h +++ b/src/include/engines/router/routerplanner.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include // C++ header needed for std:sort function @@ -37,6 +39,8 @@ #include "engines/router/routerstationstopprofile.h" #include "engines/router/routertrainprofile.h" #include "engines/router/routertransfer.h" +#include "engines/router/routerjourney.h" +#include "engines/router/routernulljourney.h" #include "engines/station/stationfactory.h" #include "engines/station/stationstation.h" #include "fragments/fragmentsfactory.h" @@ -74,10 +78,17 @@ class QRAIL_SHARED_EXPORT Planner : public QObject const QUrl &arrivalStation, const QDateTime &departureTime, const quint16 &maxTransfers); + void getConnections(const QUrl &departureStation, + const QUrl &arrivalStation, + const QDateTime &departureTime, + const QDateTime &arrivalTime, + const quint16 &maxTransfers); void getConnections(const QGeoCoordinate &departurePosition, const QGeoCoordinate &arrivalPosition, const QDateTime &departureTime, const quint16 &maxTransfers); + void getNextConnectionForJourney(QRail::RouterEngine::Journey *journey); + void getPreviousConnectionForJourney(QRail::RouterEngine::Journey *journey); QDateTime calculateArrivalTime(const QDateTime &departureTime); QDateTime departureTime() const; QDateTime arrivalTime() const; @@ -89,7 +100,7 @@ class QRAIL_SHARED_EXPORT Planner : public QObject virtual void customEvent(QEvent *event); signals: - void finished(const QList &routes); + void finished(QRail::RouterEngine::Journey *journey); void stream(QRail::RouterEngine::Route *route); void error(const QString &message); void requested(const QUrl &pageURI); @@ -110,6 +121,7 @@ class QRAIL_SHARED_EXPORT Planner : public QObject QMap m_TArray; QMap m_DArray; QList m_usedPages; + QRail::RouterEngine::Journey *m_journey; explicit Planner(QObject *parent = nullptr); static QRail::RouterEngine::Planner *m_instance; void parsePage(QRail::Fragments::Page *page); @@ -135,6 +147,8 @@ class QRAIL_SHARED_EXPORT Planner : public QObject void setMaxTransfers(const qint16 &maxTransfers); void setDepartureStationURI(const QUrl &departureStationURI); void setArrivalStationURI(const QUrl &arrivalStationURI); + QRail::RouterEngine::Journey *journey() const; + void setJourney(QRail::RouterEngine::Journey *journey); }; } // namespace RouterEngine } // namespace QRail diff --git a/tests/src/engines/router/routerplannertest.cpp b/tests/src/engines/router/routerplannertest.cpp index 4fd9577..9001544 100644 --- a/tests/src/engines/router/routerplannertest.cpp +++ b/tests/src/engines/router/routerplannertest.cpp @@ -19,6 +19,8 @@ using namespace QRail; void QRail::RouterEngine::PlannerTest::initCSAPlannerTest() { + qInfo() << "Init PlannerTest"; + // Get a Planner instance planner = QRail::RouterEngine::Planner::getInstance(); @@ -26,8 +28,8 @@ void QRail::RouterEngine::PlannerTest::initCSAPlannerTest() qRegisterMetaType>("QList"); // Connect the signals - connect(planner, SIGNAL(finished(QList)), this, - SLOT(processRoutesFinished(QList))); + connect(planner, SIGNAL(finished(QRail::RouterEngine::Journey *)), this, + SLOT(processRoutesFinished(QRail::RouterEngine::Journey *))); connect(planner, SIGNAL(stream(QRail::RouterEngine::Route *)), this, SLOT(processRoutesStream(QRail::RouterEngine::Route *))); connect(planner, SIGNAL(processing(QUrl)), this, SLOT(processing(QUrl))); @@ -36,6 +38,7 @@ void QRail::RouterEngine::PlannerTest::initCSAPlannerTest() void QRail::RouterEngine::PlannerTest::runCSAPlannerTest() { + qInfo() << "Running PlannerTest"; /* * Guess the arrival time given a departure time. * The arrival time must come after the departure time to be valid. @@ -52,7 +55,7 @@ void QRail::RouterEngine::PlannerTest::runCSAPlannerTest() * https://lc2irail.thesis.bertmarcelis.be/connections/008811189/008891009/departing/2018-08-02T13:00:00+00:00 */ - + // Create journey QDateTime start = QDateTime::currentDateTime(); planner->getConnections( QUrl("http://irail.be/stations/NMBS/008811189"), // From: Vilvoorde @@ -63,17 +66,42 @@ void QRail::RouterEngine::PlannerTest::runCSAPlannerTest() // Start an eventloop to wait for the finished signal to allow benchmarking of asynchronous events QEventLoop loop; - connect(planner, SIGNAL(finished(QList)), &loop, SLOT(quit())); + connect(planner, SIGNAL(finished(QRail::RouterEngine::Journey *)), &loop, SLOT(quit())); loop.exec(); qInfo() << "Routing Vilvoorde -> Brugge took" << start.msecsTo(QDateTime::currentDateTime()) << "msecs"; + + // Extend with next page (later arrival time) + /*start = QDateTime::currentDateTime(); + planner->getNextConnectionForJourney(this->journey); + + // Start an eventloop to wait for the finished signal to allow benchmarking of asynchronous events + QEventLoop loopNext; + connect(planner, SIGNAL(finished(QRail::RouterEngine::Journey *)), &loopNext, SLOT(quit())); + loopNext.exec(); + qInfo() << "Extending NEXT: later arrival time took" + << start.msecsTo(QDateTime::currentDateTime()) + << "msecs";*/ + + // Extend with previous page (earlier departure time) + /*start = QDateTime::currentDateTime(); + planner->getPreviousConnectionForJourney(this->journey); + + // Start an eventloop to wait for the finished signal to allow benchmarking of asynchronous events + QEventLoop loopPrevious; + connect(planner, SIGNAL(finished(QRail::RouterEngine::Journey *)), &loopPrevious, SLOT(quit())); + loopPrevious.exec(); + qInfo() << "Extending PREVIOUS: later arrival time took" + << start.msecsTo(QDateTime::currentDateTime()) + << "msecs";*/ } void QRail::RouterEngine::PlannerTest::cleanCSAPlannerTest() { - disconnect(planner, SIGNAL(finished(QList)), - this, SLOT(processRoutesFinished(QList))); + qInfo() << "Cleaning up PlannerTest"; + disconnect(planner, SIGNAL(finished(QRail::RouterEngine::Journey *)), + this, SLOT(processRoutesFinished(QRail::RouterEngine::Journey *))); disconnect(planner, SIGNAL(processing(QUrl)), this, SLOT(processing(QUrl))); disconnect(planner, SIGNAL(requested(QUrl)), @@ -82,21 +110,12 @@ void QRail::RouterEngine::PlannerTest::cleanCSAPlannerTest() this, SLOT(processRoutesStream(QRail::RouterEngine::Route *))); } -void QRail::RouterEngine::PlannerTest::processing(const QUrl &pageURI) +void RouterEngine::PlannerTest::processRoutesFinished(RouterEngine::Journey *journey) { - qDebug() << "Page received:" << pageURI.toString(); -} + this->journey = journey; -void QRail::RouterEngine::PlannerTest::requested(const QUrl &pageURI) -{ - qDebug() << "Page requested:" << pageURI.toString(); -} - -void QRail::RouterEngine::PlannerTest::processRoutesFinished(const - QList - &routes) -{ - qDebug() << "CSA found" << routes.size() << "possible routes"; + qDebug() << "Journey calculation finished, found" << journey->routes().length() << "routes"; + QList routes = journey->routes(); foreach (QRail::RouterEngine::Route *route, routes) { // Verify the complete trip qDebug() << "Trip:" << route->departureStation()->station()->name().value( @@ -137,7 +156,16 @@ void QRail::RouterEngine::PlannerTest::processRoutesFinished(const } } } - qDebug() << "All routes processed"; +} + +void QRail::RouterEngine::PlannerTest::processing(const QUrl &pageURI) +{ + qDebug() << "Page received:" << pageURI.toString(); +} + +void QRail::RouterEngine::PlannerTest::requested(const QUrl &pageURI) +{ + qDebug() << "Page requested:" << pageURI.toString(); } void RouterEngine::PlannerTest::processRoutesStream(QRail::RouterEngine::Route *route) diff --git a/tests/src/engines/router/routerplannertest.h b/tests/src/engines/router/routerplannertest.h index e30840a..5b7ca86 100644 --- a/tests/src/engines/router/routerplannertest.h +++ b/tests/src/engines/router/routerplannertest.h @@ -35,13 +35,14 @@ private slots: void cleanCSAPlannerTest(); public slots: - void processRoutesFinished(const QList &routes); + void processRoutesFinished(QRail::RouterEngine::Journey *journey); void processRoutesStream(QRail::RouterEngine::Route *route); void processing(const QUrl &pageURI); void requested(const QUrl &pageURI); private: QRail::RouterEngine::Planner *planner; + QRail::RouterEngine::Journey *journey; }; } // namespace RouterEngine } // namespace QRail diff --git a/tests/src/qrail-tests.cpp b/tests/src/qrail-tests.cpp index 731da24..7b8218a 100644 --- a/tests/src/qrail-tests.cpp +++ b/tests/src/qrail-tests.cpp @@ -63,22 +63,22 @@ int main(int argc, char *argv[]) QRail::StationEngine::FactoryTest testSuiteStationFactory; // Run unit tests without passing arguments - networkManagerResult = QTest::qExec(&testSuiteNetworkManager, 0, nullptr); - dbManagerResult = QTest::qExec(&testSuiteDBManager, 0, nullptr); - lcFragmentResult = QTest::qExec(&testSuiteLCFragment, 0, nullptr); - lcPageResult = QTest::qExec(&testSuiteLCPage, 0, nullptr); + /*networkManagerResult = QTest::qExec(&testSuiteNetworkManager, qApp->arguments()); + dbManagerResult = QTest::qExec(&testSuiteDBManager, qApp->arguments()); + lcFragmentResult = QTest::qExec(&testSuiteLCFragment, qApp->arguments()); + lcPageResult = QTest::qExec(&testSuiteLCPage, qApp->arguments()); // Run QRail::LiveboardEngine::Factory integration test - liveboardFactoryResult = QTest::qExec(&testSuiteLiveboardFactory, 0, nullptr); + vehicleFactoryResult = QTest::qExec(&testSuiteVehicleFactory, qApp->arguments()); - // Run QRail::RouterEngine::Planner integration test - routerPlannerResult = QTest::qExec(&testSuiteCSAPlanner, 0, nullptr); + // Run QRail::StationEngine::Factory integration test + stationFactoryResult = QTest::qExec(&testSuiteStationFactory, qApp->arguments()); // Run QRail::LiveboardEngine::Factory integration test - vehicleFactoryResult = QTest::qExec(&testSuiteVehicleFactory, 0, nullptr); + liveboardFactoryResult = QTest::qExec(&testSuiteLiveboardFactory, qApp->arguments());*/ - // Run QRail::StationEngine::Factory integration test - stationFactoryResult = QTest::qExec(&testSuiteStationFactory, 0, nullptr); + // Run QRail::RouterEngine::Planner integration test + routerPlannerResult = QTest::qExec(&testSuiteCSAPlanner, qApp->arguments()); // Return the status code of every test for CI/CD QCoreApplication::exit(networkManagerResult | dbManagerResult | lcFragmentResult | lcPageResult |