From aeb774a8ed14d8c7c55652fa60e4758a20cdaa60 Mon Sep 17 00:00:00 2001 From: ovadmin Date: Mon, 2 Oct 2017 00:59:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=8F=E5=B9=85=E9=87=8D=E6=A7=8B=E9=87=8D?= =?UTF-8?q?=E8=A4=87=E7=9A=84=E7=A8=8B=E5=BC=8F=E7=A2=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Source/Engine/Gramambular/Grid.h | 29 ++++++++++++++++++++++++ Source/InputMethodController.mm | 39 ++++++++++++++------------------ 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/Source/Engine/Gramambular/Grid.h b/Source/Engine/Gramambular/Grid.h index e13c8eab..d4103c99 100644 --- a/Source/Engine/Gramambular/Grid.h +++ b/Source/Engine/Gramambular/Grid.h @@ -47,7 +47,18 @@ namespace Formosa { size_t width() const; vector nodesEndingAt(size_t inLocation); vector nodesCrossingOrEndingAt(size_t inLocation); + + // "Freeze" the node with the unigram that represents the selected canditate value. + // After this, the node that contains the unigram will always be evaluated to that + // unigram, while all other overlapping nodes will be reset to their initial state + // (that is, if any of those nodes were "frozen" or fixed, they will be unfrozen.) void fixNodeSelectedCandidate(size_t location, const string& value); + + // Similar to fixNodeSelectedCandidate, but instead of "freezing" the node, only + // boost the unigram that represents the value with an overriding score. This + // has the same side effect as fixNodeSelectedCandidate, which is that all other + // overlapping nodes will be reset to their initial state. + void overrideNodeScoreForSelectedCandidate(size_t location, const string& value, float overridingScore); const string dumpDOT(); @@ -194,6 +205,24 @@ namespace Formosa { } } } + + inline void Grid::overrideNodeScoreForSelectedCandidate(size_t location, const string& value, float overridingScore) + { + vector nodes = nodesCrossingOrEndingAt(location); + for (auto nodeAnchor : nodes) { + auto candidates = nodeAnchor.node->candidates(); + + // Reset the candidate-fixed state of every node at the location. + const_cast(nodeAnchor.node)->resetCandidate(); + + for (size_t i = 0, c = candidates.size(); i < c; ++i) { + if (candidates[i].value == value) { + const_cast(nodeAnchor.node)->selectFloatingCandidateAtIndex(i, overridingScore); + break; + } + } + } + } inline const string Grid::dumpDOT() { diff --git a/Source/InputMethodController.mm b/Source/InputMethodController.mm index dfc43e3d..9e48f829 100644 --- a/Source/InputMethodController.mm +++ b/Source/InputMethodController.mm @@ -150,6 +150,19 @@ public: } }; +static const double kEpsilon = 0.000001; + +static double FindHighestScore(const vector& nodes, double epsilon) { + double highestScore = 0.0; + for (auto ni = nodes.begin(), ne = nodes.end(); ni != ne; ++ni) { + double score = ni->node->highestUnigramScore(); + if (score > highestScore) { + highestScore = score; + } + } + return highestScore + epsilon; +} + @implementation McBopomofoInputMethodController - (void)dealloc { @@ -665,32 +678,14 @@ public: [self popOverflowComposingTextAndWalk:client]; // get user override model suggestion - string overrideCandidate = + string overrideValue = (_inputMode == kPlainBopomofoModeIdentifier) ? "" : _uom->suggest(_walkedNodes, _builder->cursorIndex(), [[NSDate date] timeIntervalSince1970]); - if (!overrideCandidate.empty()) { + if (!overrideValue.empty()) { size_t cursorIndex = [self actualCandidateCursorIndex]; vector nodes = _builder->grid().nodesCrossingOrEndingAt(cursorIndex); - - double highestScore = 0.0; - for (auto ni = nodes.begin(), ne = nodes.end(); ni != ne; ++ni) { - double score = ni->node->highestUnigramScore(); - if (score > highestScore) { - highestScore = score; - } - } - highestScore += 0.00001; - - for (vector::iterator ni = nodes.begin(), ne = nodes.end(); ni != ne; ++ni) { - const vector& candidates = (*ni).node->candidates(); - for (size_t i = 0, c = candidates.size(); i < c; ++i) { - if (candidates[i].value == overrideCandidate) { - // found our node - const_cast((*ni).node)->selectFloatingCandidateAtIndex(i, highestScore); - break; - } - } - } + double highestScore = FindHighestScore(nodes, kEpsilon); + _builder->grid().overrideNodeScoreForSelectedCandidate(cursorIndex, overrideValue, highestScore); } // then update the text