1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-06-19 10:41:36 +00:00

Dialogue: improve conflict resolution for chains of overlapping keywords (unit test for such a case will follow)

This commit is contained in:
scrawl 2015-01-09 20:08:52 +01:00
parent 65ab31eae6
commit ce2cbab402

View file

@ -66,8 +66,14 @@ public:
return false; return false;
} }
static bool sortMatches(const Match& left, const Match& right)
{
return left.mBeg < right.mBeg;
}
void highlightKeywords (Point beg, Point end, std::vector<Match>& out) void highlightKeywords (Point beg, Point end, std::vector<Match>& out)
{ {
std::vector<Match> matches;
for (Point i = beg; i != end; ++i) for (Point i = beg; i != end; ++i)
{ {
// check if previous character marked start of new word // check if previous character marked start of new word
@ -144,42 +150,51 @@ public:
match.mValue = candidate->second.mValue; match.mValue = candidate->second.mValue;
match.mBeg = i; match.mBeg = i;
match.mEnd = k; match.mEnd = k;
out.push_back(match); matches.push_back(match);
break; break;
} }
} }
// resolve overlapping keywords // resolve overlapping keywords
for (typename std::vector<Match>::iterator it = out.begin(); it != out.end();) while (matches.size())
{ {
typename std::vector<Match>::iterator next = it; int longestKeywordSize = 0;
++next; typename std::vector<Match>::iterator longestKeyword;
for (typename std::vector<Match>::iterator it = matches.begin(); it != matches.end(); ++it)
if (next == out.end())
break;
if (it->mEnd <= next->mBeg)
{ {
++it;
continue; // no overlap
}
else
{
// prefer the longer keyword
int size = it->mEnd - it->mBeg; int size = it->mEnd - it->mBeg;
int nextSize = next->mEnd - next->mBeg; if (size > longestKeywordSize)
if (size >= nextSize) // if both are the same length, then prefer the first keyword
{ {
out.erase(next); longestKeywordSize = size;
continue; longestKeyword = it;
} }
typename std::vector<Match>::iterator next = it;
++next;
if (next == matches.end())
break;
if (it->mEnd <= next->mBeg)
{
break; // no overlap
}
}
Match keyword = *longestKeyword;
matches.erase(longestKeyword);
out.push_back(keyword);
// erase anything that overlaps with the keyword we just added to the output
for (typename std::vector<Match>::iterator it = matches.begin(); it != matches.end();)
{
if (it->mBeg < keyword.mEnd && it->mEnd > keyword.mBeg)
it = matches.erase(it);
else else
{ ++it;
it = out.erase(it);
continue;
}
} }
} }
std::sort(out.begin(), out.end(), sortMatches);
} }
private: private: