lmUserOverride // Another attempt to make it functional.

- Now it successfully generates keys and starts observing things. The rest issue is that it cannot give a useful suggestion.
This commit is contained in:
ShikiSuen 2022-05-17 15:56:53 +08:00
parent dd317455e2
commit b466c57137
1 changed files with 53 additions and 65 deletions

View File

@ -1,6 +1,5 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// Refactored from the ObjCpp-version of this class by: // Refactored from the ObjCpp-version of this class by Mengjuei Hsieh (MIT License).
// (c) 2011 and onwards The OpenVanilla Project (MIT License).
/* /*
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in
@ -68,7 +67,7 @@ extension vChewing {
var mutCapacity: Int var mutCapacity: Int
var mutDecayExponent: Double var mutDecayExponent: Double
var mutLRUList = [KeyObservationPair]() var mutLRUList: [KeyObservationPair] = []
var mutLRUMap: [String: KeyObservationPair] = [:] var mutLRUMap: [String: KeyObservationPair] = [:]
let kDecayThreshold: Double = 1.0 / 1_048_576.0 let kDecayThreshold: Double = 1.0 / 1_048_576.0
@ -86,27 +85,27 @@ extension vChewing {
candidate: String, candidate: String,
timestamp: Double timestamp: Double
) { ) {
let key = getWalkedNodesToKey(walkedNodes: walkedNodes, cursorIndex: cursorIndex) let key = convertKeyFrom(walkedNodes: walkedNodes, cursorIndex: cursorIndex)
guard !key.isEmpty
else {
return
}
guard mutLRUMap[key] != nil else { guard mutLRUMap[key] != nil else {
var observation: Observation = .init() var observation: Observation = .init()
observation.update(candidate: candidate, timestamp: timestamp) observation.update(candidate: candidate, timestamp: timestamp)
mutLRUMap[key] = KeyObservationPair(key: key, observation: observation) let koPair = KeyObservationPair(key: key, observation: observation)
mutLRUList.insert(KeyObservationPair(key: key, observation: observation), at: 0) mutLRUMap[key] = koPair
mutLRUList.insert(koPair, at: 0)
if mutLRUList.count > mutCapacity { if mutLRUList.count > mutCapacity {
mutLRUMap[mutLRUList.reversed()[0].key] = nil mutLRUMap[mutLRUList[mutLRUList.endIndex].key] = nil
mutLRUList.removeLast() mutLRUList.removeLast()
} }
IME.prtDebugIntel("UOM: Observation finished with new observation: \(key)")
return return
} }
mutLRUList.insert(contentsOf: mutLRUMap.values, at: 0) if var theNeta = mutLRUMap[key] {
theNeta.observation.update(candidate: candidate, timestamp: timestamp)
if mutLRUMap[key] != nil { mutLRUList.insert(theNeta, at: 0)
mutLRUMap[key]?.observation.update(candidate: candidate, timestamp: timestamp) mutLRUMap[key] = theNeta
IME.prtDebugIntel("UOM: Observation finished with existing observation: \(key)")
} }
} }
@ -115,25 +114,22 @@ extension vChewing {
cursorIndex: Int, cursorIndex: Int,
timestamp: Double timestamp: Double
) -> String { ) -> String {
let key = getWalkedNodesToKey(walkedNodes: walkedNodes, cursorIndex: cursorIndex) let key = convertKeyFrom(walkedNodes: walkedNodes, cursorIndex: cursorIndex)
guard let keyValuePair = mutLRUMap[key], guard let koPair = mutLRUMap[key] else {
!key.isEmpty IME.prtDebugIntel("UOM: mutLRUMap[key] is nil, throwing blank suggestion for key: \(key).")
else {
return "" return ""
} }
IME.prtDebugIntel("Suggest - A: \(key)") let observation = koPair.observation
IME.prtDebugIntel("Suggest - B: \(keyValuePair.key)")
let observation = keyValuePair.observation
var candidate = "" var candidate = ""
var score = 0.0 var score = 0.0
for overrideNeta in Array(observation.overrides) { for overrideNeta in Array(observation.overrides) {
let overrideScore = getScore( let override: Override = overrideNeta.value
eventCount: overrideNeta.value.count, let overrideScore: Double = getScore(
eventCount: override.count,
totalCount: observation.count, totalCount: observation.count,
eventTimestamp: overrideNeta.value.timestamp, eventTimestamp: override.timestamp,
timestamp: timestamp, timestamp: timestamp,
lambda: mutDecayExponent lambda: mutDecayExponent
) )
@ -147,13 +143,12 @@ extension vChewing {
score = overrideScore score = overrideScore
} }
} }
if candidate.isEmpty {
IME.prtDebugIntel("UOM: No usable suggestions in the result for key: \(key).")
}
return candidate return candidate
} }
func isEndingPunctuation(value: String) -> Bool {
["", "", "", "", "", "", "", ""].contains(value)
}
public func getScore( public func getScore(
eventCount: Int, eventCount: Int,
totalCount: Int, totalCount: Int,
@ -170,58 +165,51 @@ extension vChewing {
return prob * decay return prob * decay
} }
func getWalkedNodesToKey( func convertKeyFrom(
walkedNodes: [Megrez.NodeAnchor], cursorIndex: Int walkedNodes: [Megrez.NodeAnchor], cursorIndex: Int
) -> String { ) -> String {
var strOutput = "" let arrEndingPunctuation = ["", "", "", "", "", "", "", ""]
var arrNodes: [Megrez.NodeAnchor] = [] var arrNodesReversed: [Megrez.NodeAnchor] = []
var intLength = 0 var intLength = 0
for nodeNeta in walkedNodes { for theNodeAnchor in walkedNodes {
arrNodes.append(nodeNeta) // .reverse()
intLength += nodeNeta.spanningLength arrNodesReversed = [theNodeAnchor] + arrNodesReversed
intLength += theNodeAnchor.spanningLength
if intLength >= cursorIndex { if intLength >= cursorIndex {
break break
} }
} }
// .reversed 使 Swift if arrNodesReversed.isEmpty { return "" }
//
var arrNodesReversed: [Megrez.NodeAnchor] = []
arrNodesReversed.append(contentsOf: arrNodes.reversed())
if arrNodesReversed.isEmpty { var strCurrent = "()"
var strPrevious = "()"
var strAnterior = "()"
guard let kvCurrent = arrNodesReversed[0].node?.currentKeyValue(),
!arrEndingPunctuation.contains(kvCurrent.value)
else {
return "" return ""
} }
var strCurrent = "()" //
var strPrev = "()" strCurrent = kvCurrent.key
var strAnterior = "()"
for (theIndex, theAnchor) in arrNodesReversed.enumerated() { if arrNodesReversed.count >= 2,
if strCurrent != "()", let nodeCurrent = theAnchor.node { let kvPrevious = arrNodesReversed[1].node?.currentKeyValue(),
let keyCurrent = nodeCurrent.currentKeyValue().key !arrEndingPunctuation.contains(kvPrevious.value)
let valCurrent = nodeCurrent.currentKeyValue().value {
strCurrent = "(\(keyCurrent), \(valCurrent))" strPrevious = "(\(kvPrevious.key),\(kvPrevious.value))"
if let nodePrev = arrNodesReversed[theIndex + 1].node {
let keyPrev = nodePrev.currentKeyValue().key
let valPrev = nodePrev.currentKeyValue().value
strPrev = "(\(keyPrev), \(valPrev))"
}
if let nodeAnterior = arrNodesReversed[theIndex + 2].node {
let keyAnterior = nodeAnterior.currentKeyValue().key
let valAnterior = nodeAnterior.currentKeyValue().value
strAnterior = "(\(keyAnterior), \(valAnterior))"
}
break //
}
} }
strOutput = "(\(strAnterior),\(strPrev),\(strCurrent))" if arrNodesReversed.count >= 3,
if strOutput == "((),(),())" { let kvAnterior = arrNodesReversed[2].node?.currentKeyValue(),
strOutput = "" !arrEndingPunctuation.contains(kvAnterior.value)
{
strAnterior = "(\(kvAnterior.key),\(kvAnterior.value))"
} }
return strOutput return "(\(strAnterior),\(strPrevious),\(strCurrent))"
} }
} }
} }