將用戶選字記憶機制整合入 InputMethodController

This commit is contained in:
ovadmin 2017-09-30 11:22:44 +08:00 committed by Lukhnos Liu
parent d672136843
commit 3e0e859feb
3 changed files with 53 additions and 0 deletions

View File

@ -47,10 +47,12 @@ namespace Formosa {
const vector<KeyValuePair>& candidates() const;
void selectCandidateAtIndex(size_t inIndex = 0, bool inFix = true);
void resetCandidate();
void selectFloatingCandidateAtIndex(size_t index, double score);
const string& key() const;
double score() const;
const KeyValuePair currentKeyValue() const;
double highestUnigramScore() const;
protected:
const LanguageModel* m_LM;
@ -175,6 +177,16 @@ namespace Formosa {
m_score = m_unigrams[0].score;
}
}
inline void Node::selectFloatingCandidateAtIndex(size_t index, double score) {
if (index >= m_unigrams.size()) {
m_selectedUnigramIndex = 0;
} else {
m_selectedUnigramIndex = index;
}
m_candidateFixed = false;
m_score = score;
}
inline const string& Node::key() const
{
@ -185,6 +197,13 @@ namespace Formosa {
{
return m_score;
}
inline double Node::highestUnigramScore() const {
if (m_unigrams.empty()) {
return 0.0;
}
return m_unigrams[0].score;
}
inline const KeyValuePair Node::currentKeyValue() const
{

View File

@ -37,6 +37,7 @@
#import "Mandarin.h"
#import "Gramambular.h"
#import "FastLM.h"
#import "UserOverrideModel.h"
@interface McBopomofoInputMethodController : IMKInputController
{
@ -53,6 +54,9 @@
// latest walked path (trellis) using the Viterbi algorithm
std::vector<Formosa::Gramambular::NodeAnchor> _walkedNodes;
// user override model
McBopomofo::UserOverrideModel *_uom;
// the latest composing buffer that is updated to the foreground app
NSMutableString *_composingBuffer;
NSInteger _latestReadingCursor;

View File

@ -114,6 +114,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/McBopomofo-visualization.dot
// shared language model object that stores our phrase-term probability database
FastLM gLanguageModel;
FastLM gLanguageModelPlainBopomofo;
McBopomofo::UserOverrideModel gUserOverrideModel(200, 60.0);
// https://clang-analyzer.llvm.org/faq.html
__attribute__((annotate("returns_localized_nsstring")))
@ -176,6 +177,7 @@ public:
// create the lattice builder
_languageModel = &gLanguageModel;
_builder = new BlockReadingBuilder(_languageModel);
_uom = &gUserOverrideModel;
// each Mandarin syllable is separated by a hyphen
_builder->setJoinSeparator("-");
@ -659,6 +661,33 @@ public:
// then walk the lattice
[self popOverflowComposingTextAndWalk:client];
// get user override model suggestion
string overrideCandidate = _uom->suggest(_walkedNodes, _builder->cursorIndex(), [[NSDate date] timeIntervalSince1970]);
if (!overrideCandidate.empty()) {
size_t cursorIndex = [self actualCandidateCursorIndex];
vector<NodeAnchor> 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<NodeAnchor>::iterator ni = nodes.begin(), ne = nodes.end(); ni != ne; ++ni) {
const vector<KeyValuePair>& 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<Node*>((*ni).node)->selectFloatingCandidateAtIndex(i, highestScore);
break;
}
}
}
}
// then update the text
_bpmfReadingBuffer->clear();
[self updateClientComposingBuffer:client];
@ -1373,6 +1402,7 @@ public:
size_t cursorIndex = [self actualCandidateCursorIndex];
_builder->grid().fixNodeSelectedCandidate(cursorIndex, selectedValue);
_uom->observe(_walkedNodes, cursorIndex, selectedValue, [[NSDate date] timeIntervalSince1970]);
[_candidates removeAllObjects];