File indexing completed on 2024-05-12 04:42:47

0001 /*
0002     SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "hvt.h"
0008 
0009 #include <QDebug>
0010 
0011 using namespace KPublicTransport;
0012 
0013 Line::Mode Gtfs::Hvt::typeToMode(int hvt)
0014 {
0015     if (hvt < 0) {
0016         return Line::Unknown;
0017     }
0018 
0019     // individually handled cases - https://developers.google.com/transit/gtfs/reference/extended-route-types
0020     switch (hvt) {
0021         case 101:
0022         case 102:
0023             return Line::LongDistanceTrain;
0024         case 106:
0025             return Line::LocalTrain;
0026         case 109:
0027             return Line::RapidTransit;
0028         case 401:
0029         case 402:
0030             return Line::Metro;
0031         case 403:
0032             return Line::RapidTransit;
0033         case 717:
0034             return Line::Taxi;
0035         case 1502:
0036             return Line::Boat;
0037     }
0038 
0039     // coarse top-level types - https://developers.google.com/transit/gtfs/reference/#routestxt
0040     switch (hvt) {
0041         case 0:
0042         case 5: // cable car
0043         case 6: // TODO gondola
0044             return Line::Tramway;
0045         case 1:
0046             return Line::Metro;
0047         case 2:
0048             return Line::Train;
0049         case 3:
0050             return Line::Bus;
0051         case 4:
0052             return Line::Ferry;
0053         case 7:
0054             return Line::Funicular;
0055     }
0056 
0057     // type ranges - https://developers.google.com/transit/gtfs/reference/extended-route-types
0058     if (hvt >= 100 && hvt < 199) {
0059         return Line::Train;
0060     }
0061     if (hvt >= 200 && hvt < 299) {
0062         return Line::Coach;
0063     }
0064     if (hvt >= 400 && hvt < 499) {
0065         return Line::RapidTransit;
0066     }
0067     if (hvt >= 700 && hvt < 899) {
0068         return Line::Bus;
0069     }
0070     if (hvt >= 900 && hvt < 999) {
0071         return Line::Tramway;
0072     }
0073     if (hvt >= 1000 && hvt < 1099) {
0074         return Line::Boat;
0075     }
0076     if (hvt >= 1100 && hvt < 1199) {
0077         return Line::Air;
0078     }
0079     if (hvt >= 1200 && hvt < 1299) {
0080         return Line::Ferry;
0081     }
0082     if (hvt >= 1300 && hvt < 1399) {
0083         return Line::Tramway; // TODO gondola/aerial lift
0084     }
0085     if (hvt >= 1400 && hvt < 1499) {
0086         return Line::Funicular;
0087     }
0088     if (hvt >= 1500 && hvt < 1599) {
0089         return Line::Taxi;
0090     }
0091     if (hvt == 1700) { // not officially specified, but de-facto standard in a number of OTP deployments
0092         return Line::RideShare;
0093     }
0094 
0095     qDebug() << "encountered unknown GTFS (extended) route type:" << hvt;
0096     return Line::Unknown;
0097 }
0098 
0099 // top-level types, complete list
0100 struct {
0101     const char *typeName;
0102     Line::Mode mode;
0103 } static const coarse_mode_map[] = {
0104     { "air", Line::Air },
0105     { "bus", Line::Bus },
0106     { "cableway", Line::Tramway }, // TODO
0107     { "coach", Line::Coach },
0108     { "funicular", Line::Funicular },
0109     { "lift", Line::Tramway }, // ???
0110     { "metro", Line::Metro },
0111     { "rail", Line::Train },
0112     { "subway", Line::Metro },
0113     { "tram", Line::Tramway },
0114     { "unknown", Line::Unknown },
0115     { "water", Line::Boat },
0116 };
0117 
0118 // fine-grained types, special cases that can't be found by pattern matches
0119 struct {
0120     const char *typeName;
0121     Line::Mode mode;
0122 } static const fine_mode_map[] = {
0123     { "airportlinkrail", Line::RapidTransit },
0124     { "airshipservice", Line::Air },
0125     { "blackcab", Line::Taxi },
0126     { "canalbarge", Line::Boat },
0127     { "cablecar", Line::Tramway }, // TODO
0128     { "helicopterservice", Line::Air },
0129     { "international", Line::LongDistanceTrain },
0130     { "interregionalrail", Line::Train },
0131     { "local", Line::LocalTrain },
0132     { "longdistance", Line::LongDistanceTrain },
0133     { "minicab", Line::Taxi },
0134     { "regionalrail", Line::LocalTrain },
0135     { "riverbus", Line::Boat },
0136     { "streetcablecar", Line::Tramway },
0137     { "suburbanrailway", Line::RapidTransit },
0138     { "trainFerry", Line::Ferry }, // disambiguate as this matches multiple patterns
0139     { "tube", Line::Metro },
0140     { "urbanrailway", Line::RapidTransit },
0141     { "watertaxi", Line::Boat },
0142 };
0143 
0144 // patterns for groups of fine-grained types
0145 struct {
0146     const char *namePattern;
0147     Line::Mode mode;
0148 } static const mode_pattern_map[] = {
0149     { "boat", Line::Boat },
0150     { "bus", Line::Bus },
0151     { "coach", Line::Coach },
0152     { "ferry", Line::Ferry },
0153     { "flight", Line::Air },
0154     { "funicular", Line::Funicular },
0155     { "highspeed", Line::LongDistanceTrain },
0156     { "lift", Line::Tramway }, // ???
0157     { "rail", Line::Train },
0158     { "taxi", Line::Taxi },
0159     { "telecabin", Line::Tramway }, // ???
0160     { "train", Line::Train },
0161     { "tram", Line::Tramway },
0162 };
0163 
0164 Line::Mode Gtfs::Hvt::typeToMode(const QString &hvt)
0165 {
0166     if (hvt.isEmpty()) {
0167         return Line::Unknown;
0168     }
0169 
0170     // fine-grained types, exact matches
0171     for (const auto &m : fine_mode_map) {
0172         if (hvt.compare(QLatin1String(m.typeName), Qt::CaseInsensitive) == 0) {
0173             return m.mode;
0174         }
0175     }
0176 
0177     // top-level types, exact matches
0178     for (const auto &m : coarse_mode_map) {
0179         if (hvt.compare(QLatin1String(m.typeName), Qt::CaseInsensitive) == 0) {
0180             return m.mode;
0181         }
0182     }
0183 
0184     // pattern matches on fine grained types
0185     for (const auto &m : mode_pattern_map) {
0186         if (hvt.contains(QLatin1String(m.namePattern), Qt::CaseInsensitive)) {
0187             return m.mode;
0188         }
0189     }
0190 
0191     qDebug() << "encountered unknown GTFS (extended) route type:" << hvt;
0192     return Line::Unknown;
0193 }