diff --git a/Megrez.Tests/LMDataForTests.cs b/Megrez.Tests/LMDataForTests.cs
index 9c91428..7b66d39 100644
--- a/Megrez.Tests/LMDataForTests.cs
+++ b/Megrez.Tests/LMDataForTests.cs
@@ -190,6 +190,7 @@ nian2zhong1 年中 -11.373044
gao1ke1ji4 高科技 -9.842421
zhe4yang4 這樣 -6.000000 // Non-LibTaBE
ni3zhe4 你這 -9.000000 // Non-LibTaBE
+ke1ke1 顆顆 -8.000000 // Non-LibTaBE
jiao4 教 -3.676169
jiao4 較 -3.24869962
jiao4yu4 教育 -3.32220565
diff --git a/Megrez.Tests/Megrez.Tests.csproj b/Megrez.Tests/Megrez.Tests.csproj
index f825975..9223003 100644
--- a/Megrez.Tests/Megrez.Tests.csproj
+++ b/Megrez.Tests/Megrez.Tests.csproj
@@ -4,7 +4,7 @@
net6.0
enable
false
- 2.6.0
+ 2.6.2
diff --git a/Megrez.Tests/MegrezTests.cs b/Megrez.Tests/MegrezTests.cs
index 9abf7de..cba4320 100644
--- a/Megrez.Tests/MegrezTests.cs
+++ b/Megrez.Tests/MegrezTests.cs
@@ -538,4 +538,42 @@ public void Test21_Compositor_hardCopy() {
List resultB = compositorB.Walk().WalkedNodes;
Assert.True(resultA.SequenceEqual(resultB));
}
+
+ [Test]
+ public void Test22_Compositor_SanitizingNodeCrossing() {
+ SimpleLM theLM = new(input: StrSampleData);
+ string rawReadings = "ke1 ke1";
+ Compositor compositor = new(langModel: theLM, separator: "");
+ foreach (string key in rawReadings.Split(separator: " ")) {
+ compositor.InsertKey(key);
+ }
+ int a = compositor.FetchCandidatesAt(givenLocation: 1, filter: Compositor.CandidateFetchFilter.BeginAt)
+ .Select(x => x.KeyArray.Count)
+ .Max();
+ int b = compositor.FetchCandidatesAt(givenLocation: 1, filter: Compositor.CandidateFetchFilter.EndAt)
+ .Select(x => x.KeyArray.Count)
+ .Max();
+ int c = compositor.FetchCandidatesAt(givenLocation: 0, filter: Compositor.CandidateFetchFilter.BeginAt)
+ .Select(x => x.KeyArray.Count)
+ .Max();
+ int d = compositor.FetchCandidatesAt(givenLocation: 2, filter: Compositor.CandidateFetchFilter.EndAt)
+ .Select(x => x.KeyArray.Count)
+ .Max();
+ Assert.AreEqual(actual: $"{a} {b} {c} {d}", expected: "1 1 2 2");
+ compositor.Cursor = compositor.Length;
+ compositor.InsertKey("jin1");
+ a = compositor.FetchCandidatesAt(givenLocation: 1, filter: Compositor.CandidateFetchFilter.BeginAt)
+ .Select(x => x.KeyArray.Count)
+ .Max();
+ b = compositor.FetchCandidatesAt(givenLocation: 1, filter: Compositor.CandidateFetchFilter.EndAt)
+ .Select(x => x.KeyArray.Count)
+ .Max();
+ c = compositor.FetchCandidatesAt(givenLocation: 0, filter: Compositor.CandidateFetchFilter.BeginAt)
+ .Select(x => x.KeyArray.Count)
+ .Max();
+ d = compositor.FetchCandidatesAt(givenLocation: 2, filter: Compositor.CandidateFetchFilter.EndAt)
+ .Select(x => x.KeyArray.Count)
+ .Max();
+ Assert.AreEqual(actual: $"{a} {b} {c} {d}", expected: "1 1 2 2");
+ }
}
diff --git a/Megrez.sln b/Megrez.sln
index dc69c73..7f6e0e9 100644
--- a/Megrez.sln
+++ b/Megrez.sln
@@ -52,6 +52,6 @@ Global
$0.DotNetNamingPolicy = $4
$4.DirectoryNamespaceAssociation = PrefixedHierarchical
$0.StandardHeader = $5
- version = 2.6.0
+ version = 2.6.2
EndGlobalSection
EndGlobal
diff --git a/Megrez/Megrez.csproj b/Megrez/Megrez.csproj
index 33c44cc..7b423fa 100644
--- a/Megrez/Megrez.csproj
+++ b/Megrez/Megrez.csproj
@@ -3,16 +3,16 @@
net6.0
enable
- 2.6.0
+ 2.6.2
vChewing.Megrez
Shiki Suen
Atelier Inmu
(c) 2022 and onwards The vChewing Project for Megrez-specific changes; (c) 2022 and onwards Lukhnos Liu for upstream contents.
https://github.com/ShikiSuen/MegrezNT
zh-TW
- 2.6.0
- 2.6.0
- 2.6.0
+ 2.6.2
+ 2.6.2
+ 2.6.2
Megrez
True
README.md
diff --git a/Megrez/src/3_KeyValuePaired.cs b/Megrez/src/3_KeyValuePaired.cs
index 546d330..f966fa7 100644
--- a/Megrez/src/3_KeyValuePaired.cs
+++ b/Megrez/src/3_KeyValuePaired.cs
@@ -165,21 +165,27 @@ public enum CandidateFetchFilter {
///
/// 返回在當前位置的所有候選字詞(以詞音配對的形式)。如果組字器內有幅位、且游標
/// 位於組字器的(文字輸入順序的)最前方(也就是游標位置的數值是最大合規數值)的
- /// 話,那麼這裡會用到 location - 1、以免去在呼叫該函式後再處理的麻煩。
+ /// 話,那麼這裡會對 location 的位置自動減去 1、以免去在呼叫該函式後再處理的麻煩。
///
- /// 游標位置。
+ /// 游標位置,必須是顯示的游標位置、不得做任何事先糾偏處理。
/// 候選字音配對陣列。
///
- public List FetchCandidatesAt(int location, CandidateFetchFilter filter = CandidateFetchFilter.All) {
+ public List FetchCandidatesAt(int? givenLocation = null,
+ CandidateFetchFilter filter = CandidateFetchFilter.All) {
List result = new();
if (Keys.IsEmpty()) return result;
+ int location = Math.Max(0, Math.Min(givenLocation ?? Cursor, Keys.Count));
+ if (filter == CandidateFetchFilter.EndAt) {
+ if (location == Keys.Count) filter = CandidateFetchFilter.All;
+ location -= 1;
+ }
location = Math.Max(0, Math.Min(location, Keys.Count - 1));
-
// 按照讀音的長度(幅位長度)來給節點排序。
List anchors =
FetchOverlappingNodesAt(location).StableSorted((x, y) => x.SpanLength.CompareTo(y.SpanLength));
string keyAtCursor = Keys[location];
- foreach (Node theNode in anchors.Select(x => x.Node).Where(x => !x.KeyArray.IsEmpty())) {
+ foreach (NodeAnchor theAnchor in anchors) {
+ Node theNode = theAnchor.Node;
foreach (Unigram gram in theNode.Unigrams) {
switch (filter) {
case CandidateFetchFilter.All:
@@ -187,10 +193,11 @@ public List FetchCandidatesAt(int location, CandidateFetchFilter
if (!theNode.KeyArray.Contains(keyAtCursor)) continue;
break;
case CandidateFetchFilter.BeginAt:
- if (theNode.KeyArray.First() != keyAtCursor) continue;
+ if (theAnchor.SpanIndex != location) continue;
break;
case CandidateFetchFilter.EndAt:
if (theNode.KeyArray.Last() != keyAtCursor) continue;
+ if (theNode.SpanLength >= 2 && theAnchor.SpanIndex + theAnchor.SpanLength - 1 != location) continue;
break;
}
result.Add(new(theNode.KeyArray, gram.Value));
diff --git a/Megrez/src/4_SpanUnit.cs b/Megrez/src/4_SpanUnit.cs
index b46e49b..b424d1b 100644
--- a/Megrez/src/4_SpanUnit.cs
+++ b/Megrez/src/4_SpanUnit.cs
@@ -112,11 +112,13 @@ public bool DropNodesOfOrBeyond(int length) {
/// 一個包含所有與該位置重疊的節點的陣列。
internal List FetchOverlappingNodesAt(int givenLocation) {
List results = new();
- if (Spans.IsEmpty() || givenLocation >= Spans.Count) return results;
+ givenLocation = Math.Max(0, Math.Min(givenLocation, Keys.Count - 1));
+ if (Spans.IsEmpty()) return results;
// 先獲取該位置的所有單字節點。
foreach (int spanLength in new BRange(1, Spans[givenLocation].MaxLength + 1)) {
if (Spans[givenLocation].NodeOf(spanLength) is not {} node) continue;
+ if (string.IsNullOrEmpty(node.KeyArray.Joined())) continue;
results.Add(new(node, givenLocation));
}
@@ -127,6 +129,7 @@ internal List FetchOverlappingNodesAt(int givenLocation) {
if (alpha > bravo) continue;
foreach (int theLength in new BRange(alpha, bravo + 1)) {
if (Spans[theLocation].NodeOf(theLength) is not {} node) continue;
+ if (string.IsNullOrEmpty(node.KeyArray.Joined())) continue;
results.Add(new(node, theLocation));
}
}