public void Analyze(String sent, String recorded) { _resultsRTB.Clear(); MorseCompareResults results = Comparer.Compare(sent, recorded); ShowStrings(results); ShowStats(results); _resultsRTB.Select(0, 0); _resultsRTB.ScrollToCaret(); }
private void ShowStrings(MorseCompareResults results) { Write("I sent : "); ResultsFlags flags = ResultsFlags.Valid | ResultsFlags.Dropped; foreach (MorseSubstring substring in results.SubStrings) { Write(substring.Str(flags), substring.Color); } Write(Environment.NewLine); Write("You typed: "); flags = ResultsFlags.Valid | ResultsFlags.Extra; foreach (MorseSubstring substring in results.SubStrings) { Write(substring.Str(flags), substring.Color); } Write(Environment.NewLine); }
/// <summary> /// Compares two strings and returns the results. /// </summary> /// <param name="sent">The sent string</param> /// <param name="recorded">The string the user entered while listening</param> /// <returns>Am objecxt with results</returns> public static MorseCompareResults Compare(string sent, string recorded) { const int SEARCH_AMOUNT = 20; int sentStart = 0; int recordedStart = 0; int sentLength = sent.Length; int recordedLength = recorded.Length; int sum = 0; int sentOffset = 0; int recordedOffset = 0; int matched = 0; int threshold; int matchedTotal = 0; List <MorseSubstring> substringList = new List <MorseSubstring>(); // As long as there are unprocessed characters while (sentStart < sentLength || recordedStart < recordedLength) { bool searching = true; int sentRemaining = sentLength - sentStart; int recordedRemaining = recordedLength - recordedStart; int maxSum = sentRemaining + recordedRemaining; // start with a higher threshold to filter false positives, then loosen for (int thresholdIndex = 0; searching && (thresholdIndex < matchLengthThresholdArray.Length); ++thresholdIndex) { // a match is considered a match if it is contains at least 'threshold' contiguous matching characters threshold = matchLengthThresholdArray[thresholdIndex]; int searchAmount = Math.Min(SEARCH_AMOUNT, maxSum); // The algorithm here is to match positive offsets on each string // starting from (0,0) (0,1) (1,0) (0,2) (1,1) (2,0) (0,3) (1,2) (2,1) (3,0) (0,4) ... // until (0,searchAmount) ... (searchAmount,0) for (sum = 0; searching && (sum < searchAmount); ++sum) { for (sentOffset = 0; sentOffset <= sum; ++sentOffset) { // get the respective offsets from the start recordedOffset = sum - sentOffset; // number of matching characters starting at the respective offsets matched = matchCount(sent, recorded, sentStart + sentOffset, recordedStart + recordedOffset); // got matched, leave sentOffset for loop if (matched >= threshold) { // found! searching = false; break; } } } } // At this point we have matched and the offsets if (searching) { // didn't find a match--punt and just put everything into the mismatch output sentOffset = sentLength - sentStart; recordedOffset = recordedLength - recordedStart; } // sum > 0 means that there was either extra or dropped characters detected before a substring match if (sum > 0) { if (sentOffset > 0) { // at least one character was dropped MorseSubstring dropped = new MorseDropped(sent.Substring(sentStart, sentOffset)); substringList.Add(dropped); // skip over the dropped characters to the start of the match sentStart += sentOffset; } if (recordedOffset > 0) { // at least one unsent character was detected before a substring match MorseSubstring extra = new MorseExtra(recorded.Substring(recordedStart, recordedOffset)); substringList.Add(extra); // skip over the extra characters to the start of the match recordedStart += recordedOffset; } } if (matched > 0) { // there was a match MorseSubstring valid = new MorseValid(sent.Substring(sentStart, matched)); substringList.Add(valid); // skip over the match in each string recordedStart += matched; sentStart += matched; // keep track of the matched total matchedTotal += matched; } } MorseCompareResults results = new MorseCompareResults(substringList, sent, recorded); return(results); }
private void ShowStats(MorseCompareResults results) { int[] sent = new int[256]; int[] valid = new int[256]; int[] dropped = new int[256]; int[] extra = new int[256]; int totalValid = 0; foreach (char c in results.Sent) { sent[c]++; } foreach (MorseSubstring substring in results.SubStrings) { int[] counter = null; switch (substring.ResultInfo & ResultsFlags.All) { case ResultsFlags.Dropped: counter = dropped; break; case ResultsFlags.Extra: counter = extra; break; case ResultsFlags.Valid: counter = valid; totalValid += substring.Chars.Length; break; } if (counter != null) { foreach (char c in substring.Chars) { counter[c]++; } } } Write(String.Format("Sent {0} and {1} recorded valid: {2:0}%" + Environment.NewLine, results.Sent.Length, totalValid, 100 * (float)totalValid / (float)results.Sent.Length)); // Show characters sent Write(Environment.NewLine + "Characters sent:" + Environment.NewLine); foreach (char c in MorseInfo.PossibleCharacters) { if (sent[c] != 0) { Write(String.Format(" {0} {1}/{2} : {3},{4}" + Environment.NewLine, MorseInfo.ExpandProsigns(c), valid[c], sent[c], dropped[c], extra[c])); } } // Show extra characters received Write(Environment.NewLine + "Characters not sent:" + Environment.NewLine); foreach (char c in MorseInfo.PossibleCharacters) { if (sent[c] == 0 && extra[c] != 0) { Write(String.Format(" {0} {1}/{2} : {3},{4}" + Environment.NewLine, MorseInfo.ExpandProsigns(c), valid[c], sent[c], dropped[c], extra[c])); } } }