diff --git a/src/app/publictransport.cpp b/src/app/publictransport.cpp index 7e5c9df..a42f612 100644 --- a/src/app/publictransport.cpp +++ b/src/app/publictransport.cpp @@ -1,365 +1,367 @@ /* Copyright (C) 2019 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "publictransport.h" #include "logging.h" #include #include #include #include #include #include #include #include #include #include #include #include #include static bool isTrainMode(KPublicTransport::Line::Mode mode) { using namespace KPublicTransport; switch (mode) { case Line::Train: case Line::Funicular: case Line::LocalTrain: case Line::LongDistanceTrain: case Line::Metro: case Line::RailShuttle: case Line::RapidTransit: case Line::Tramway: return true; default: return false; } } static bool isBusMode(KPublicTransport::Line::Mode mode) { using namespace KPublicTransport; switch (mode) { case Line::Bus: case Line::BusRapidTransit: case Line::Coach: return true; default: return false; } } KPublicTransport::Location PublicTransport::locationFromPlace(const QVariant& place, const QVariant &reservation) { using namespace KItinerary; KPublicTransport::Location loc; if (JsonLd::isA(reservation) || JsonLd::isA(reservation) || JsonLd::isA(reservation)) { loc.setName(KItinerary::LocationUtil::name(place)); } else { const auto addr = KItinerary::LocationUtil::address(place); loc.setStreetAddress(addr.streetAddress()); loc.setPostalCode(addr.postalCode()); loc.setLocality(addr.addressLocality()); loc.setRegion(addr.addressRegion()); loc.setCountry(addr.addressCountry()); } const auto geo = KItinerary::LocationUtil::geo(place); loc.setCoordinate(geo.latitude(), geo.longitude()); if (KItinerary::JsonLd::canConvert(place)) { const auto p = KItinerary::JsonLd::convert(place); if (!p.identifier().isEmpty()) { const auto idSplit = p.identifier().split(QLatin1Char(':')); if (idSplit.size() == 2) { loc.setIdentifier(idSplit.at(0), idSplit.at(1)); } } } return loc; } QString PublicTransport::lineIcon(const QVariant &line) { using namespace KPublicTransport; const auto l = line.value(); const auto logo = l.logo(); if (!logo.isEmpty()) { return logo; } const auto modeLogo = l.modeLogo(); if (!modeLogo.isEmpty()) { return modeLogo; } return lineModeIcon(l.mode()); } QString PublicTransport::lineModeIcon(int lineMode) { using namespace KPublicTransport; switch (lineMode) { case Line::Air: return QStringLiteral("qrc:///images/flight.svg"); case Line::Boat: case Line::Ferry: return QStringLiteral("qrc:///images/ferry.svg"); case Line::Bus: return QStringLiteral("qrc:///images/bus.svg"); case Line::BusRapidTransit: case Line::Coach: return QStringLiteral("qrc:///images/coach.svg"); case Line::Funicular: return QStringLiteral("qrc:///images/Funicular.svg"); case Line::LocalTrain: case Line::Train: return QStringLiteral("qrc:///images/train.svg"); case Line::LongDistanceTrain: return QStringLiteral("qrc:///images/longdistancetrain.svg"); case Line::Metro: return QStringLiteral("qrc:///images/subway.svg"); case Line::RailShuttle: case Line::RapidTransit: return QStringLiteral("qrc:///images/rapidtransit.svg"); case Line::Shuttle: return QStringLiteral("qrc:///images/shuttle.svg"); case Line::Taxi: return QStringLiteral("qrc:///images/taxi.svg"); case Line::Tramway: return QStringLiteral("qrc:///images/tramway.svg"); + case Line::RideShare: + return QStringLiteral("qrc:///images/car.svg"); } return QStringLiteral("question"); } static KItinerary::Ticket clearSeat(KItinerary::Ticket ticket) { auto seat = ticket.ticketedSeat(); seat.setSeatNumber(QString()); seat.setSeatRow(QString()); seat.setSeatSection(QString()); ticket.setTicketedSeat(seat); return ticket; } static KItinerary::TrainReservation applyJourneySection(KItinerary::TrainReservation res, const KPublicTransport::JourneySection §ion) { using namespace KItinerary; auto trip = res.reservationFor().value(); trip.setDepartureTime(section.scheduledDepartureTime()); trip.setArrivalTime(section.scheduledArrivalTime()); trip.setTrainNumber(section.route().line().name()); trip.setTrainName(section.route().line().modeString()); trip.setDeparturePlatform(section.scheduledDeparturePlatform()); trip.setArrivalPlatform(section.scheduledArrivalPlatform()); trip.setDepartureStation(PublicTransport::updateToLocation(trip.departureStation(), section.from())); trip.setArrivalStation(PublicTransport::updateToLocation(trip.arrivalStation(), section.to())); res.setReservationFor(trip); res.setReservedTicket(clearSeat(res.reservedTicket().value())); return res; } static KItinerary::BusReservation applyJourneySection(KItinerary::BusReservation res, const KPublicTransport::JourneySection §ion) { using namespace KItinerary; auto trip = res.reservationFor().value(); trip.setDepartureTime(section.scheduledDepartureTime()); trip.setArrivalTime(section.scheduledArrivalTime()); trip.setBusNumber(section.route().line().name()); trip.setBusName(section.route().line().modeString()); trip.setDeparturePlatform(section.scheduledDeparturePlatform()); trip.setArrivalPlatform(section.scheduledArrivalPlatform()); trip.setDepartureBusStop(PublicTransport::updateToLocation(trip.departureBusStop(), section.from())); trip.setArrivalBusStop(PublicTransport::updateToLocation(trip.arrivalBusStop(), section.to())); res.setReservationFor(trip); res.setReservedTicket(clearSeat(res.reservedTicket().value())); return res; } QVariant PublicTransport::reservationFromJourneySection(const KPublicTransport::JourneySection §ion) { using namespace KItinerary; if (isTrainMode(section.route().line().mode())) { return ::applyJourneySection(TrainReservation(), section); } if (isBusMode(section.route().line().mode())) { return ::applyJourneySection(BusReservation(), section); } qCWarning(Log) << "Unsupported section type:" << section.route().line().mode(); return {}; } QVariant PublicTransport::applyJourneySection(const QVariant &res, const KPublicTransport::JourneySection §ion) { using namespace KItinerary; if (JsonLd::isA(res)) { return ::applyJourneySection(res.value(), section); } if (JsonLd::isA(res)) { return ::applyJourneySection(res.value(), section); } qCWarning(Log) << res.typeName() << "Unsupported section type!"; return res; } QVariant PublicTransport::mergeDeparture(const QVariant &res, const KPublicTransport::Stopover &dep) { using namespace KItinerary; QVariant newRes; if (isTrainMode(dep.route().line().mode())) { TrainTrip trip; trip.setDepartureStation(placeFromLocation(dep.stopPoint())); trip.setDepartureTime(dep.scheduledDepartureTime()); trip.setDeparturePlatform(dep.scheduledPlatform()); TrainReservation trainRes; trainRes.setReservationFor(trip); newRes = trainRes; } else if (isBusMode(dep.route().line().mode())) { BusTrip trip; trip.setDepartureBusStop(placeFromLocation(dep.stopPoint())); trip.setDepartureTime(dep.scheduledDepartureTime()); trip.setDeparturePlatform(dep.scheduledPlatform()); BusReservation busRes; busRes.setReservationFor(trip); newRes = busRes; } return MergeUtil::merge(newRes, res); } QVariant PublicTransport::mergeArrival(const QVariant &res, const KPublicTransport::Stopover &arr) { using namespace KItinerary; QVariant newRes; if (isTrainMode(arr.route().line().mode())) { TrainTrip trip; trip.setArrivalStation(placeFromLocation(arr.stopPoint())); trip.setArrivalTime(arr.scheduledArrivalTime()); trip.setArrivalPlatform(arr.scheduledPlatform()); TrainReservation trainRes; trainRes.setReservationFor(trip); newRes = trainRes; } else if (isBusMode(arr.route().line().mode())) { BusTrip trip; trip.setArrivalBusStop(placeFromLocation(arr.stopPoint())); trip.setArrivalTime(arr.scheduledArrivalTime()); trip.setArrivalPlatform(arr.scheduledPlatform()); BusReservation busRes; busRes.setReservationFor(trip); newRes = busRes; } return MergeUtil::merge(newRes, res); } bool PublicTransport::isSameMode(const QVariant &res, KPublicTransport::Line::Mode mode) { using namespace KPublicTransport; if (KItinerary::JsonLd::isA(res)) { return isTrainMode(mode); } else if (KItinerary::JsonLd::isA(res)) { return isBusMode(mode); } else if (KItinerary::JsonLd::isA(res)) { return mode == Line::Air; } else if (res.isValid()) { qCWarning(Log) << "unexpected reservation type!?" << res; } return false; } bool PublicTransport::isSameMode(const QVariant &res, const KPublicTransport::JourneySection §ion) { return isSameMode(res, section.route().line().mode()); } KPublicTransport::StopoverRequest PublicTransport::stopoverRequestForPlace(const QVariant &place, const QDateTime &dt) const { KPublicTransport::StopoverRequest req; req.setDateTime(std::max(dt, QDateTime::currentDateTime())); req.setStop(PublicTransport::locationFromPlace(place, {})); req.setDownloadAssets(true); return req; } QString PublicTransport::attributionSummary(const QVariantList& attributions) const { QStringList l; l.reserve(attributions.size()); for (const auto &v : attributions) { const auto attr = v.value(); l.push_back(QLatin1String("") + attr.name() + QLatin1String("")); } return l.join(QLatin1String(", ")); } bool PublicTransport::warnAboutSection(const KPublicTransport::JourneySection §ion) const { using namespace KPublicTransport; switch (section.mode()) { case JourneySection::Walking: case JourneySection::Transfer: return section.duration() > 20*60 || section.distance() > 1000; case JourneySection::Waiting: return section.duration() > 20*60; default: return false; } } QString PublicTransport::idenfitierFromLocation(const KPublicTransport::Location &loc) { auto id = loc.identifier(QLatin1String("ibnr")); if (!id.isEmpty()) { return QLatin1String("ibnr:") + id; } id = loc.identifier(QLatin1String("uic")); if (!id.isEmpty()) { return QLatin1String("uic:") + id; } return {}; } KItinerary::PostalAddress PublicTransport::addressFromLocation(const KPublicTransport::Location &loc) { KItinerary::PostalAddress addr; addr.setStreetAddress(loc.streetAddress()); addr.setPostalCode(loc.postalCode()); addr.setAddressLocality(loc.locality()); addr.setAddressRegion(loc.region()); addr.setAddressCountry(loc.country()); return addr; } #include "moc_publictransport.cpp"