Commit 70341a84 authored by Volker Krause's avatar Volker Krause
Browse files

Also merge events in the same location with slightly varying names

This happens when for example details about adult/child tickets end up
being part of the name.
parent 5ed57262
......@@ -34,6 +34,16 @@ private Q_SLOTS:
QFETCH(QString, out);
QCOMPARE(StringUtil::normalize(in), out);
}
void testPrefixSimilarity()
{
QCOMPARE(StringUtil::prefixSimilarity(QString(), QString()), 0.0f);
QCOMPARE(StringUtil::prefixSimilarity(u"aaa", QString()), 0.0f);
QCOMPARE(StringUtil::prefixSimilarity(u"aaaa", u"AA"), 0.5f);
QCOMPARE(StringUtil::prefixSimilarity(u"aba", u"aBa"), 1.0f);
QCOMPARE(StringUtil::prefixSimilarity(u"ab", u"aa"), 0.5f);
QCOMPARE(StringUtil::prefixSimilarity(u"ac", u"abbb"), 0.25f);
}
};
QTEST_APPLESS_MAIN(StringUtilTest)
......
......@@ -7,6 +7,7 @@
#include "mergeutil.h"
#include "logging.h"
#include "compare-logging.h"
#include "locationutil.h"
#include "stringutil.h"
#include "sortutil.h"
......@@ -423,8 +424,14 @@ bool MergeUtil::isSamePerson(const Person& lhs, const Person& rhs)
static bool isSameEvent(const Event &lhs, const Event &rhs)
{
return equalAndPresent(lhs.name(), rhs.name())
&& equalAndPresent(lhs.startDate(), rhs.startDate());
if (!equalAndPresent(lhs.startDate(), rhs.startDate())) {
return false;
}
// event names can contain additional qualifiers, like for Adult/Child tickets,
// those don't change the event though
const auto namePrefix = StringUtil::prefixSimilarity(lhs.name(), rhs.name());
return namePrefix == 1.0f || (namePrefix > 0.65f && LocationUtil::isSameLocation(lhs.location(), rhs.location(), LocationUtil::Exact));
}
static bool isSameRentalCar(const RentalCar &lhs, const RentalCar &rhs)
......
......@@ -90,3 +90,23 @@ QStringView StringUtil::betterString(QStringView lhs, QStringView rhs)
}
return rhs;
}
float StringUtil::prefixSimilarity(QStringView s1, QStringView s2)
{
if (s1.empty() || s2.empty()) {
return 0.0f;
}
if (s1.size() > s2.size()) {
std::swap(s1, s2);
}
for (int i = 0; i < s1.size(); ++i) {
if (s1[i].toCaseFolded() == s2[i].toCaseFolded()) {
continue;
}
return (float)i / (float)s2.size();
}
return (float)s1.size() / (float)s2.size();
}
......@@ -29,6 +29,12 @@ namespace StringUtil
* That is, prefer the one that didn't lose casing/unicode/etc in previous processing.
*/
QStringView betterString(QStringView lhs, QStringView rhs);
/** Returns how much of the prefix of two given strings are equal, in
* relation to the longer of the two input strings.
* @internal only exported for unit tests
*/
KITINERARY_EXPORT float prefixSimilarity(QStringView s1, QStringView s2);
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment