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
 | |
|     }
 | |
| }
 |