TokiTrainer/Toki Trainer/ViewModels/TokiDictionaryViewModel.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
}
}