129 lines
4.2 KiB
Swift
129 lines
4.2 KiB
Swift
//
|
|
// TokiDictionaryViewModel.swift
|
|
// Toki Trainer
|
|
//
|
|
// Created by Avery Ada Pace on 11/4/21.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
class TokiDictionaryViewModel: ObservableObject {
|
|
|
|
let jsonLoader: TokiJSONLoader = TokiJSONLoader()
|
|
|
|
private var fullDictionary: [TokiDictEntry] = []
|
|
private var fullPartsOfSpeech: [TokiPartOfSpeech] = []
|
|
|
|
@Published var dictionary: [TokiDictEntry] = []
|
|
@Published var partsOfSpeech: [TokiPartOfSpeech] = []
|
|
|
|
@Published var translatedDictionary: [TokiSubWordListEntry] = []
|
|
|
|
init() {
|
|
if let safeDictionary = jsonLoader.loadDictionary() {
|
|
dictionary = safeDictionary
|
|
fullDictionary = safeDictionary
|
|
}
|
|
if let safePartsOfSpeech = jsonLoader.loadPOS() {
|
|
partsOfSpeech = safePartsOfSpeech
|
|
fullPartsOfSpeech = safePartsOfSpeech
|
|
}
|
|
}
|
|
|
|
func filterDictionary(_ input: String) {
|
|
dictionary = []
|
|
|
|
for value in fullDictionary {
|
|
if value.word.hasPrefix(input) {
|
|
dictionary.append(value)
|
|
}
|
|
}
|
|
}
|
|
|
|
func filterDictionaryEnglishMode(_ input: String) {
|
|
dictionary = []
|
|
|
|
for value in fullDictionary {
|
|
|
|
var entryMatch = false
|
|
|
|
// Check if word matches toki pona form, even partially
|
|
// Commented out because toki words shouldn't be matched in english mode
|
|
// if value.word.hasPrefix(input) {
|
|
// entryMatch = true
|
|
// }
|
|
|
|
// Check if any part of the word definitions match in English, even partially, but
|
|
// only by prefix (if one of the definition words matches the beginning of the word with
|
|
// the search term)
|
|
for definition in value.definitions {
|
|
let capturePattern = #"(\w+)"#
|
|
let captures = self.searchStringForRegex(string: definition.definition, regex: capturePattern)
|
|
for capture in captures {
|
|
if capture.hasPrefix(input) {
|
|
entryMatch = true
|
|
}
|
|
}
|
|
// Commented out, less strict matching that will match on any substring match
|
|
// if definition.definition.contains(input) {
|
|
// entryMatch = true
|
|
// }
|
|
}
|
|
|
|
// Add to dictionary
|
|
if entryMatch == true {
|
|
dictionary.append(value)
|
|
}
|
|
}
|
|
}
|
|
|
|
func translatePhrase(_ input: String) {
|
|
dictionary = []
|
|
translatedDictionary = []
|
|
|
|
if input.isEmpty {
|
|
dictionary = fullDictionary
|
|
translatedDictionary.append(TokiSubWordListEntry("Dictionary"))
|
|
}
|
|
|
|
let capturePattern = #"(\w+)"#
|
|
let captures = self.searchStringForRegex(string: input, regex: capturePattern)
|
|
for capture in captures {
|
|
let translatedWord = TokiSubWordListEntry(capture)
|
|
translatedDictionary.append(translatedWord)
|
|
for value in fullDictionary {
|
|
if value.word == capture {
|
|
dictionary.append(value)
|
|
translatedWord.subDictionary.removeAll()
|
|
translatedWord.subDictionary.append(value)
|
|
break
|
|
} else if value.word.hasPrefix(capture) {
|
|
dictionary.append(value)
|
|
translatedWord.subDictionary.append(value)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func searchStringForRegex(string: String, regex: String) -> [String] {
|
|
let lowerCaseString = string.lowercased()
|
|
let strRange = NSRange(lowerCaseString.startIndex..<lowerCaseString.endIndex, in: lowerCaseString)
|
|
let nameRegex = try! NSRegularExpression(pattern: regex, options: [])
|
|
|
|
let results = nameRegex.matches(in: lowerCaseString, options: [], range: strRange)
|
|
|
|
return results.map {
|
|
String(lowerCaseString[Range($0.range, in: lowerCaseString)!])
|
|
}
|
|
}
|
|
}
|
|
|
|
class TokiSubWordListEntry: Identifiable {
|
|
let header: String
|
|
var subDictionary: [TokiDictEntry] = []
|
|
|
|
init(_ header: String) {
|
|
self.header = header
|
|
}
|
|
}
|