import Foundation public struct EntryWarning: Equatable, Sendable { public enum Level: Int, Comparable, Sendable { case note = 0, warning, error public static func < (a: Level, b: Level) -> Bool { a.rawValue < b.rawValue } } public let level: Level public let message: String public init(level: Level, message: String) { self.level = level self.message = message } } /// Flags dictionary entries that are likely to corrupt normal text. public enum EntryWarnings { /// - Parameter others: all entries except the one being checked. public static func check(_ kind: DictionaryEntry.Kind, among others: [DictionaryEntry], knowledge: WordKnowledge) -> [EntryWarning] { let source: String let isCorrection: Bool switch kind { case .term(let term): (source, isCorrection) = (term, false) case .correction(let heard, _): (source, isCorrection) = (heard, true) } let parts = EntryKey.parts(source) guard !parts.isEmpty else { return [EntryWarning(level: .error, message: "Leeg: vul een woord in.")] } var result: [EntryWarning] = [] if others.contains(where: { EntryKey.key($0.source) == EntryKey.key(source) }) { result.append(EntryWarning(level: .error, message: "Dubbele invoer: deze bron staat er al, de eerste telt.")) } if !isCorrection { if parts.count == 1, knowledge.isWord(source) { result.append(EntryWarning(level: .note, message: "Gewoon woord: krijgt alleen voorrang bij het model, geen automatische hoofdletterregel.")) } return result.sorted { $0.level > $1.level } } if parts.count == 1, knowledge.isWord(parts[0]) { result.append(EntryWarning(level: .warning, message: "'\(parts[0])' is een gewoon woord en wordt overal in je tekst vervangen.")) } if source.filter(\.isLetter).count < 3 { result.append(EntryWarning(level: .warning, message: "Erg kort (minder dan 3 letters): veel kans op ongewenste vervangingen.")) } if parts.count > 1 { var flagged = false if let common = parts.first(where: { knowledge.isFunctionWord($0) }) { result.append(EntryWarning(level: .warning, message: "Bevat het veelvoorkomende woord '\(common)'; dit kan gewone zinnen raken.")) flagged = true } let glued = parts.joined() if knowledge.isWord(glued) { result.append(EntryWarning(level: .warning, message: "Aaneengeschreven ('\(glued)') is een bestaand woord en wordt ook vervangen.")) flagged = true } if !flagged, parts.allSatisfy({ knowledge.isWord($0) }) { result.append(EntryWarning(level: .note, message: "Alle delen zijn gewone woorden: alleen de hele combinatie wordt vervangen.")) } } return result.sorted { $0.level > $1.level } } }