File indexing completed on 2024-05-12 04:42:37
0001 /* 0002 SPDX-FileCopyrightText: 2023 Jonah Brüchert <jbb@kaidan.im> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include <QFile> 0008 #include <QJsonDocument> 0009 #include <QJsonArray> 0010 0011 #include <unordered_map> 0012 0013 #include "localbackendutils.h" 0014 #include "journeyrequest.h" 0015 0016 0017 using namespace KPublicTransport::LocalBackendUtils; 0018 0019 class Transliteration { 0020 public: 0021 /// simplify less common characters into simpler multi-character equivalents 0022 QString latinize(const QString &string) const { 0023 static std::unordered_map<QChar, QStringView> table { 0024 {u'đ', u"dj"}, {u'ć', u"c"} 0025 }; 0026 0027 QString out; 0028 out.reserve(string.size()); 0029 0030 for (auto c : string) { 0031 if (table.contains(c)) { 0032 out.append(table.at(c)); 0033 } else { 0034 out.push_back(c); 0035 } 0036 } 0037 0038 return out; 0039 } 0040 0041 /// Converts strings from the cyrillic alphabet to their latin equivalents 0042 QString transliterate(const QString &cyrillic) const { 0043 // Avoid construction of transliteration table and manual string copy if nothing requires transliteration 0044 if (std::none_of(cyrillic.begin(), cyrillic.end(), [](QChar c) { 0045 return c.script() == QChar::Script_Cyrillic; 0046 })) { 0047 // No copy, because implicitly shared 0048 return cyrillic; 0049 } 0050 0051 // Generated from <table> element on https://de.wikipedia.org/wiki/ISO_9 0052 // using src/lib/networks/stations/generate_transliteration_table.py 0053 static std::unordered_map<QChar, QStringView> iso9Table = { 0054 {u'А', u"A"}, {u'а', u"a"}, {u'Ӑ', u"Ă"}, {u'ӑ', u"ă"}, {u'Ӓ', u"Ä"}, 0055 {u'ӓ', u"ä"}, {u'Ә', u"A"}, {u'ә', u"a"}, {u'Б', u"B"}, {u'б', u"b"}, 0056 {u'В', u"V"}, {u'в', u"v"}, {u'Г', u"G"}, {u'г', u"g"}, {u'Ґ', u"G"}, 0057 {u'ґ', u"g"}, {u'Ҕ', u"Ğ"}, {u'ҕ', u"ğ"}, {u'Ғ', u"Ġ"}, {u'ғ', u"ġ"}, 0058 {u'Д', u"D"}, {u'д', u"d"}, {u'Ђ', u"Đ"}, {u'ђ', u"đ"}, {u'Ѓ', u"Ǵ"}, 0059 {u'ѓ', u"ǵ"}, {u'Е', u"E"}, {u'е', u"e"}, {u'Ё', u"Ë"}, {u'ё', u"ë"}, 0060 {u'Ӗ', u"Ĕ"}, {u'ӗ', u"ĕ"}, {u'Є', u"Ê"}, {u'є', u"ê"}, {u'Ҽ', u"C"}, 0061 {u'ҽ', u"c"}, {u'Ҿ', u"Ç"}, {u'ҿ', u"ç"}, {u'Ж', u"Ž"}, {u'ж', u"ž"}, 0062 {u'Ӂ', u"Z"}, {u'ӂ', u"z"}, {u'Ӝ', u"Z"}, {u'ӝ', u"z"}, {u'Җ', u"Ž"}, 0063 {u'җ', u"ž"}, {u'З', u"Z"}, {u'з', u"z"}, {u'Ӟ', u"Z"}, {u'ӟ', u"z"}, 0064 {u'Ѕ', u"Ẑ"}, {u'ѕ', u"ẑ"}, {u'Ӡ', u"Ź"}, {u'ӡ', u"ź"}, {u'И', u"I"}, 0065 {u'и', u"i"}, {u'Ӥ', u"Î"}, {u'ӥ', u"î"}, {u'І', u"Ì"}, {u'і', u"ì"}, 0066 {u'Ї', u"Ï"}, {u'ї', u"ï"}, {u'Й', u"J"}, {u'й', u"j"}, {u'Ј', u"J"}, 0067 {u'ј', u"ǰ"}, {u'К', u"K"}, {u'к', u"k"}, {u'Қ', u"Ķ"}, {u'қ', u"ķ"}, 0068 {u'Ҟ', u"K"}, {u'ҟ', u"k"}, {u'Л', u"L"}, {u'л', u"l"}, {u'Љ', u"L"}, 0069 {u'љ', u"l̂"}, {u'М', u"M"}, {u'м', u"m"}, {u'Н', u"N"}, {u'н', u"n"}, 0070 {u'Њ', u"N"}, {u'њ', u"n"}, {u'Ҥ', u"Ṅ"}, {u'ҥ', u"ṅ"}, {u'Ң', u"Ṇ"}, 0071 {u'ң', u"ṇ"}, {u'О', u"O"}, {u'о', u"o"}, {u'Ӧ', u"Ö"}, {u'ӧ', u"ö"}, 0072 {u'Ө', u"Ô"}, {u'ө', u"ô"}, {u'П', u"P"}, {u'п', u"p"}, {u'Ҧ', u"Ṕ"}, 0073 {u'ҧ', u"ṕ"}, {u'Р', u"R"}, {u'р', u"r"}, {u'С', u"S"}, {u'с', u"s"}, 0074 {u'Ҫ', u"Ç"}, {u'ҫ', u"ç"}, {u'Т', u"T"}, {u'т', u"t"}, {u'Ҭ', u"Ţ"}, 0075 {u'ҭ', u"ţ"}, {u'Ћ', u"Ć"}, {u'ћ', u"ć"}, {u'Ќ', u"Ḱ"}, {u'ќ', u"ḱ"}, 0076 {u'У', u"U"}, {u'у', u"u"}, {u'У', u"Ú"}, {u'у', u"ú"}, {u'Ў', u"Ŭ"}, 0077 {u'ў', u"ŭ"}, {u'Ӱ', u"Ü"}, {u'ӱ', u"ü"}, {u'Ӳ', u"Ű"}, {u'ӳ', u"ű"}, 0078 {u'Ү', u"Ù"}, {u'ү', u"ù"}, {u'Ф', u"F"}, {u'ф', u"f"}, {u'Х', u"H"}, 0079 {u'х', u"h"}, {u'Ҳ', u"Ḩ"}, {u'ҳ', u"ḩ"}, {u'Һ', u"Ḥ"}, {u'һ', u"ḥ"}, 0080 {u'Ц', u"C"}, {u'ц', u"c"}, {u'Ҵ', u"C"}, {u'ҵ', u"c"}, {u'Ч', u"Č"}, 0081 {u'ч', u"č"}, {u'Ӵ', u"C"}, {u'ӵ', u"c"}, {u'Ҷ', u"Ç"}, {u'ҷ', u"ç"}, 0082 {u'Џ', u"D"}, {u'џ', u"d"}, {u'Ш', u"Š"}, {u'ш', u"š"}, {u'Щ', u"Ŝ"}, 0083 {u'щ', u"ŝ"}, {u'Ы', u"Y"}, {u'ы', u"y"}, {u'Ӹ', u"Ÿ"}, {u'ӹ', u"ÿ"}, 0084 {u'Э', u"È"}, {u'э', u"è"}, {u'Ю', u"Û"}, {u'ю', u"û"}, {u'Я', u"Â"}, 0085 {u'я', u"â"}, {u'Ѣ', u"Ě"}, {u'ѣ', u"ě"}, {u'Ѫ', u"Ǎ"}, {u'ѫ', u"ǎ"}, 0086 {u'Ѳ', u"F"}, {u'ѳ', u"f"}, {u'Ѵ', u"Ỳ"}, {u'ѵ', u"ỳ"}, {u'Ҩ', u"Ò"}, 0087 {u'ҩ', u"ò"}, {u'Ӏ', u"‡"}, {u'’', u"‵"}, 0088 }; 0089 0090 0091 QString out; 0092 out.reserve(cyrillic.size()); 0093 0094 for (auto c : cyrillic) { 0095 if (iso9Table.contains(c)) { 0096 out.append(iso9Table.at(c)); 0097 } else { 0098 out.push_back(c); 0099 } 0100 } 0101 0102 return out; 0103 }; 0104 }; 0105 0106 0107 QString KPublicTransport::LocalBackendUtils::makeSearchableName(const QString &name) 0108 { 0109 Transliteration t; 0110 return t.latinize(t.transliterate(name)) 0111 // Remove parts in parantheses, the DB API likes to add the country in parantheses 0112 .replace(QRegularExpression(QStringLiteral(R"(\([^)]*\))")), QString()) 0113 // Split accents into their own charcters 0114 .normalized(QString::NormalizationForm_D) 0115 // filter those characters out 0116 .replace(QRegularExpression(QStringLiteral("[^a-zA-Z0-9\\s]")), QString()) 0117 // Remove spaces 0118 .replace(QStringLiteral(" "), QString()) 0119 .toLower() 0120 .trimmed(); 0121 } 0122 0123 bool KPublicTransport::LocalBackendUtils::isInSelectedTimeframe(const QDateTime &departure, const QDateTime &arrival, const JourneyRequest &req) 0124 { 0125 // Filter for requested arrival / departure time frame 0126 if (req.dateTimeMode() == JourneyRequest::Departure) { 0127 if (departure < req.dateTime()) { 0128 return false; 0129 } 0130 } else { 0131 if (arrival > req.dateTime()) { 0132 return false; 0133 } 0134 } 0135 0136 return true; 0137 }