diff --git a/Source/Modules/LanguageParsers/Megrez/6_Node.swift b/Source/Modules/LanguageParsers/Megrez/6_Node.swift index c17c457c..ebbc9df9 100644 --- a/Source/Modules/LanguageParsers/Megrez/6_Node.swift +++ b/Source/Modules/LanguageParsers/Megrez/6_Node.swift @@ -140,6 +140,43 @@ extension Array where Element == Megrez.Compositor.Node { /// 從一個節點陣列當中取出目前的索引鍵陣列。 public var keys: [String] { map(\.key) } + /// 返回一連串的節點起點。結果為 (Result A, Result B) 辭典陣列 + /// Result A 以索引查座標,Result B 以座標查索引。 + public var nodeBorderPointDictPair: ([Int: Int], [Int: Int]) { + // Result A 以索引查座標,Result B 以座標查索引。 + var resultA = [Int: Int]() + var resultB = [Int: Int]() + var i = 0 + for (j, neta) in enumerated() { + resultA[j] = i + neta.keyArray.forEach { _ in + resultB[i] = j + i += 1 + } + } + resultA[resultA.count] = i + resultB[i] = resultB.count + return (resultA, resultB) + } + + /// 總讀音單元數量,也就是總幅位長度。 + public var totalKeyCount: Int { map(\.keyArray.count).reduce(0, +) } + + /// 根據給定的游標,返回其前後最近的邊界點。 + /// - Parameter cursor: 給定的游標。 + public func contextRange(ofGivenCursor cursor: Int) -> Range { + guard !isEmpty else { return 0..<0 } + let lastSpanningLength = reversed()[0].keyArray.count + var nilReturn = (totalKeyCount - lastSpanningLength)..= totalKeyCount { return nilReturn } // 防呆 + let cursor = Swift.max(0, cursor) // 防呆 + nilReturn = cursor.. Megrez.Compositor.Node? { guard !isEmpty else { return nil } - let cursor = Swift.max(0, Swift.min(cursor, keys.count)) - - if cursor == 0, let theFirst = first { - outCursorPastNode = theFirst.spanLength - return theFirst - } - - // 同時應對「游標在右端」與「游標離右端還差一個位置」的情形。 - if cursor >= keys.count - 1, let theLast = last { - outCursorPastNode = keys.count - return theLast - } - - var accumulated = 0 - for neta in self { - accumulated += neta.spanLength - if accumulated > cursor { - outCursorPastNode = accumulated - return neta - } - } - - // 下述情形本不應該出現。 - return nil + let cursor = Swift.min(Swift.max(0, cursor), totalKeyCount - 1) // 防呆 + let range = contextRange(ofGivenCursor: cursor) + outCursorPastNode = range.upperBound + guard let rearNodeID = nodeBorderPointDictPair.1[cursor] else { return nil } + return count - 1 >= rearNodeID ? self[rearNodeID] : nil } /// 在陣列內以給定游標位置找出對應的節點。