|
@@ -17,61 +17,11 @@
|
|
|
#include "../filesystem/Filesystem.h"
|
|
|
#include "../modding/ModScope.h"
|
|
|
#include "../modding/CModHandler.h"
|
|
|
+#include "../texts/TextOperations.h"
|
|
|
#include "../ScopeGuard.h"
|
|
|
|
|
|
VCMI_LIB_NAMESPACE_BEGIN
|
|
|
|
|
|
-// Algorithm for detection of typos in words
|
|
|
-// Determines how 'different' two strings are - how many changes must be done to turn one string into another one
|
|
|
-// https://en.wikipedia.org/wiki/Levenshtein_distance#Iterative_with_two_matrix_rows
|
|
|
-static int getLevenshteinDistance(const std::string & s, const std::string & t)
|
|
|
-{
|
|
|
- int n = t.size();
|
|
|
- int m = s.size();
|
|
|
-
|
|
|
- // create two work vectors of integer distances
|
|
|
- std::vector<int> v0(n+1, 0);
|
|
|
- std::vector<int> v1(n+1, 0);
|
|
|
-
|
|
|
- // initialize v0 (the previous row of distances)
|
|
|
- // this row is A[0][i]: edit distance from an empty s to t;
|
|
|
- // that distance is the number of characters to append to s to make t.
|
|
|
- for (int i = 0; i < n; ++i)
|
|
|
- v0[i] = i;
|
|
|
-
|
|
|
- for (int i = 0; i < m; ++i)
|
|
|
- {
|
|
|
- // calculate v1 (current row distances) from the previous row v0
|
|
|
-
|
|
|
- // first element of v1 is A[i + 1][0]
|
|
|
- // edit distance is delete (i + 1) chars from s to match empty t
|
|
|
- v1[0] = i + 1;
|
|
|
-
|
|
|
- // use formula to fill in the rest of the row
|
|
|
- for (int j = 0; j < n; ++j)
|
|
|
- {
|
|
|
- // calculating costs for A[i + 1][j + 1]
|
|
|
- int deletionCost = v0[j + 1] + 1;
|
|
|
- int insertionCost = v1[j] + 1;
|
|
|
- int substitutionCost;
|
|
|
-
|
|
|
- if (s[i] == t[j])
|
|
|
- substitutionCost = v0[j];
|
|
|
- else
|
|
|
- substitutionCost = v0[j] + 1;
|
|
|
-
|
|
|
- v1[j + 1] = std::min({deletionCost, insertionCost, substitutionCost});
|
|
|
- }
|
|
|
-
|
|
|
- // copy v1 (current row) to v0 (previous row) for next iteration
|
|
|
- // since data in v1 is always invalidated, a swap without copy could be more efficient
|
|
|
- std::swap(v0, v1);
|
|
|
- }
|
|
|
-
|
|
|
- // after the last swap, the results of v1 are now in v0
|
|
|
- return v0[n];
|
|
|
-}
|
|
|
-
|
|
|
/// Searches for keys similar to 'target' in 'candidates' map
|
|
|
/// Returns closest match or empty string if no suitable candidates are found
|
|
|
static std::string findClosestMatch(const JsonMap & candidates, const std::string & target)
|
|
@@ -84,7 +34,7 @@ static std::string findClosestMatch(const JsonMap & candidates, const std::strin
|
|
|
|
|
|
for (auto const & candidate : candidates)
|
|
|
{
|
|
|
- int newDistance = getLevenshteinDistance(candidate.first, target);
|
|
|
+ int newDistance = TextOperations::getLevenshteinDistance(candidate.first, target);
|
|
|
|
|
|
if (newDistance < bestDistance)
|
|
|
{
|