/// <summary> /// Calculate the Levenstein similarity probability that the query has a Bible book based on the version. /// </summary> /// <param name="splitQuery">The simplified query from which the version has been removed.</param> /// <param name="version">The version to find the Bible book in.</param> /// <param name="book">The closest book that was found. May be completely incorrect (check the return value)</param> /// <returns>The Levenstein distance of the closest Bible book to the result book string found.</returns> public static float QueryHasBibleBook(ref List <string> splitQuery, BibleVersion version, ref string book) { float levSimilarity; foreach (var item in splitQuery) { Debug.WriteLine("ITEM: " + item); } if (splitQuery.Count == 0) { return(0f); } else if (QueryHasNumeral(ref splitQuery)) { book = ClosestBookName(version, CutQueryAtNumber(ref splitQuery), out levSimilarity); Debug.WriteLine(book + " found from " + splitQuery[0] + " with lev distance of " + levSimilarity); splitQuery.RemoveAt(0); return(levSimilarity); } else { string bookName = CutQueryAtNumber(ref splitQuery); book = ClosestBookName(version, bookName, out levSimilarity); Debug.WriteLine(book + " found from " + bookName + " with lev distance of " + levSimilarity); splitQuery.RemoveAt(0); return(levSimilarity); } }
/// <summary> /// Return the Bible book name that most resembles the query according to Levenshtein distance (ignoring diacritics). /// </summary> /// <param name="version">The version of the Bible in which to search through the book names</param> /// <param name="query">The text the user entered to match one of the Bible's book names</param> /// <returns>The closest book name to the query string. Guaranteed to return something, no matter how unreasonable.</returns> public static string ClosestBookName(BibleVersion version, string query, out float levensteinPercent) { if (query == null || query.Length == 0) { levensteinPercent = 0.0f; return(version.BookNames.First()); } // When the user types an exact match to the first letters of a book, return that book. // For example, EPH is EPHesians, not Esther as according to the Levenshtein distance. foreach (string bookName in version.BookNames) { // Include only queries that are a subset of the book name if (query.Length <= bookName.Length) { if (query.ToLower().RemoveDiacritics() == bookName.Substring(0, query.Length).ToLower().RemoveDiacritics()) { levensteinPercent = 1.0f; return(bookName); } } } // Store the percent similarity for each book name SortedDictionary <float, string> results = new SortedDictionary <float, string>(); // With this, a book name is guaranteed to be returned, so unintentional misspellings can be ignored. // However, because typing ASDF will return AMOS, it is best to check the Levenstein distance for a too large error margin, // so that a better search result can be presented instead. float similarity = 0f; foreach (string bookName in version.BookNames) { similarity = LevenshteinSimilarity(query.ToLower().RemoveDiacritics(), bookName.ToLower().RemoveDiacritics()); if (similarity == 1.0f) { levensteinPercent = similarity; return(bookName); } else { results.TryAdd(similarity, bookName); } } Debug.WriteLine("FOUND " + results.Last().Value + " WITH A SIMILARITY OF " + similarity); levensteinPercent = similarity; return(results.Last().Value); }
/// <summary> /// Check whether a query has a Bible version. /// </summary> /// <param name="splitQuery">The original search query split between spaces and punctuation. /// Removes the BibleVersion parameter if it is found.</param> /// <param name="version">Changes to the correct BibleVersion if the version is found.</param> /// <returns>True if a version that is installed is found.</returns> public static bool QueryHasBibleVersion(ref List <string> splitQuery, ref BibleVersion version, ref BibleVersion compareVersion) { if (splitQuery.Count > 0 && VersionByAbbreviation(splitQuery[0]) != null) { if (splitQuery.Count > 1 && VersionByAbbreviation(splitQuery[1]) != null) { version = VersionByAbbreviation(splitQuery[0]); compareVersion = VersionByAbbreviation(splitQuery[1]); splitQuery.RemoveAt(0); splitQuery.RemoveAt(0); return(true); } version = VersionByAbbreviation(splitQuery[0]); compareVersion = null; splitQuery.RemoveAt(0); return(true); } else { return(false); } }
/// <summary> /// Initialize the tabs to when the browser was previously open. /// Assign the tabs to the loaded data. /// </summary> public static async Task LoadSavedTabs() { // There may not be a saved document try { // Read the saved XML tabs StorageFile readFile = await m_localFolder.GetFileAsync("SavedTabs.xml"); string text = await FileIO.ReadTextAsync(readFile); // Debug file contents Debug.WriteLine("The saved tabs xml file contents :"); Debug.WriteLine(text); XDocument XMLTabs = XDocument.Parse(text); // Debug the file contents Debug.WriteLine("Tabs loaded :"); Debug.WriteLine(XMLTabs); // Create the tab list from XML IEnumerable <XElement> tabs = XMLTabs.Descendants("Reference"); TrulyObservableCollection <BrowserTab> savedTabs = new TrulyObservableCollection <BrowserTab>(); foreach (XElement node in tabs) { // Get the information from XML BibleVersion bibleVersion = new BibleVersion(node.Element("FileName").Value); BibleVersion comparisonVersion; if (node.Element("ComparisonFileName").Value == "Null") { comparisonVersion = null; } else { comparisonVersion = new BibleVersion(node.Element("ComparisonFileName").Value); } string bookName = node.Element("BookName").Value; BibleBook book = BibleReference.StringToBook(bookName, bibleVersion); int chapter = int.Parse(node.Element("Chapter").Value); int verse = int.Parse(node.Element("Verse").Value); // Create the reference that goes in the tab BibleReference reference = new BibleReference(bibleVersion, comparisonVersion, book, chapter, verse); savedTabs.Add(new BrowserTab(reference)); } // Add the tabs to the browser foreach (BrowserTab tab in savedTabs) { Tabs.Add(tab); } RequireNewTab(); } catch (System.IO.FileNotFoundException fileNotFoundE) { Debug.WriteLine("A resource was not loaded correctly; this may be a missing bible version :"); Debug.WriteLine(fileNotFoundE.Message); RequireNewTab(); } catch (System.Xml.XmlException xmlE) // Parse error { Debug.WriteLine("Reading the saved tabs xml file choked :"); Debug.WriteLine(xmlE.Message); RequireNewTab(); } catch (Exception e) { Debug.WriteLine("Loading saved tabs was interrupted :"); Debug.WriteLine(e.Message); RequireNewTab(); } }
/// <summary> /// Asynchronously search the Bible for every verse that contains a certain text as a substring. /// </summary> /// <param name="query">The string to be matched in the Bible reference for the verse to be returned.</param> public static async Task <SearchProgressInfo> SearchAsync(BibleVersion version, string query, IProgress <SearchProgressInfo> progress, CancellationTokenSource cancellation) { SearchProgressInfo progressInfo = new SearchProgressInfo(query); query = query.ToLower(CultureInfo.InvariantCulture).RemoveDiacritics().RemovePunctuation(); progressInfo = await Task.Run <SearchProgressInfo>(() => { // Go through each book of the Bible for (int book = 0; book < version.BookNumbers.Count; book++) { // Throw an exception if cancellation was requested try { BibleReference reference = new BibleReference(version, null, (BibleBook)book); progressInfo.Completion = DGL.Math.Percent(book + 1, version.BookNumbers.Count); progressInfo.Status = version.BookNames[book]; // Go through each chapter of the book of the Bible Parallel.For(1, version.GetChapterCount(reference) + 1, chapter => { // See if the search has hit too many results for the computer's good if (progressInfo.ResultCount > TOOMANYRESULTS) { cancellation.Cancel(); Debug.WriteLine("******************* TOO MANY RESULTS"); progress.Report(progressInfo); throw new OperationCanceledException(); } else if (cancellation.IsCancellationRequested) { cancellation.Cancel(); Debug.WriteLine("******************* CANCELLATION REQUESTED"); progress.Report(progressInfo); throw new OperationCanceledException(); } else { BibleReference chapterReference = new BibleReference(version, null, (BibleBook)book, chapter); // Go through each verse of the chapter int verseNumber = 1; foreach (string verse in version.GetChapterVerses(chapterReference)) { if (verse.ToLower().RemoveDiacritics().RemovePunctuation().Contains(query)) { BibleReference hit = new BibleReference(version, null, (BibleBook)book, chapter, verseNumber); Debug.WriteLine(hit + ":" + verseNumber + " -- " + verse); progressInfo.AddResult(new SearchResult(hit, verse, query)); } verseNumber++; } progress.Report(progressInfo); } }); } catch (OperationCanceledException) { progressInfo.IsCanceled = true; return(progressInfo); } catch (Exception) { progressInfo.IsCanceled = true; return(progressInfo); } } return(progressInfo); }); return(progressInfo); }