コード例 #1
0
ファイル: StringComp.cs プロジェクト: steel9/SteelQuiz
 public SimilarityData(int difference, CorrectCertainty certainty, string correctAnswer, Card card)
 {
     Difference    = difference;
     Certainty     = certainty;
     CorrectAnswer = correctAnswer;
     Card          = card;
 }
コード例 #2
0
ファイル: StringComp.cs プロジェクト: steel9/SteelQuiz
        private static SimilarityData Similarity(string userAnswer, string correctAnswer, Card card, Rules rules, CorrectCertainty certainty)
        {
            var similarityData = new List <SimilarityData>();

            void KeepBestSimilarityData()
            {
                // Keep best similarity data
                similarityData = similarityData.OrderBy(x => x.Difference).ThenBy(x => (int)x.Certainty).ToList();
                similarityData = similarityData.Take(1).ToList();
            }

            if (rules.HasFlag(Rules.IgnoreOpeningWhitespace))
            {
                similarityData.Add(Similarity(userAnswer.TrimStart(' '), correctAnswer.TrimStart(' '), card, rules & ~Rules.IgnoreOpeningWhitespace,
                                              (CorrectCertainty)Math.Max((int)CorrectCertainty.ProbablyCorrect, (int)certainty)));
                // Math.Max to use worst certainty (if the certainty when calling this method was 'maybe correct', new certainty can't be 'probably correct' for instance)
            }

            if (rules.HasFlag(Rules.IgnoreEndingWhitespace))
            {
                similarityData.Add(Similarity(userAnswer.TrimEnd(' '), correctAnswer.TrimEnd(' '), card, rules & ~Rules.IgnoreEndingWhitespace,
                                              (CorrectCertainty)Math.Max((int)CorrectCertainty.ProbablyCorrect, (int)certainty)));
            }

            if (rules.HasFlag(Rules.IgnoreFirstCapitalization))
            {
                similarityData.Add(Similarity(CapitalizeFirstChar(userAnswer), CapitalizeFirstChar(correctAnswer), card, rules & ~Rules.IgnoreFirstCapitalization,
                                              (CorrectCertainty)Math.Max((int)CorrectCertainty.ProbablyCorrect, (int)certainty)));
            }

            if (rules.HasFlag(Rules.IgnoreDotsInEnd))
            {
                similarityData.Add(Similarity(userAnswer.TrimEnd('.'), correctAnswer.TrimEnd('.'), card, rules & ~Rules.IgnoreDotsInEnd,
                                              (CorrectCertainty)Math.Max((int)CorrectCertainty.ProbablyCorrect, (int)certainty)));
            }

            if (rules.HasFlag(Rules.TreatWordsBetweenSlashAsSynonyms))
            {
                if (correctAnswer.Contains("/"))
                {
                    var  synonymSimilarities = new List <SimilarityData>();
                    bool any = false;
                    foreach (var userSynonym in userAnswer.Split('/').Where(x => !string.IsNullOrWhiteSpace(x)))
                    {
                        any = true;

                        var matches = new List <SimilarityData>();
                        foreach (var correctSynonym in correctAnswer.Split('/').Where(x => !string.IsNullOrWhiteSpace(x)))
                        {
                            matches.Add(Similarity(userSynonym, correctSynonym.TrimStart(' '), card, rules,
                                                   (CorrectCertainty)Math.Max((int)CorrectCertainty.ProbablyCorrect, (int)certainty)));
                        }

                        // Add best match
                        synonymSimilarities.Add(matches.OrderBy(x => x.Difference).First());
                    }

                    if (any)
                    {
                        // At least one synonym was entered!

                        if (synonymSimilarities.All(x => x.Difference == 0))
                        {
                            // Provided synonyms are correct
                            similarityData.Add(
                                new SimilarityData(0, (CorrectCertainty)Math.Max((int)CorrectCertainty.ProbablyCorrect, (int)certainty), correctAnswer, card));
                        }
                        else
                        {
                            similarityData.Add(
                                new SimilarityData(synonymSimilarities.Select(x => x.Difference).Max(),
                                                   (CorrectCertainty)Math.Max((int)CorrectCertainty.ProbablyCorrect, (int)certainty), correctAnswer, card));
                        }
                    }
                }
            }

            if (rules.HasFlag(Rules.TreatWordInParenthesisAsOptional))
            {
                if (correctAnswer.Contains("(") && correctAnswer.Contains(")"))
                {
                    if (!correctAnswer.TrimStart().StartsWith("("))
                    {
                        string w1 = correctAnswer.Split('(')[0].TrimEnd(' '); // tarp (tarpaulin) => tarp
                        similarityData.Add(Similarity(userAnswer, w1, card, rules, (CorrectCertainty)Math.Max((int)CorrectCertainty.ProbablyCorrect, (int)certainty)));
                    }

                    string w2 = correctAnswer.Split('(')[1].Split(')')[0].TrimStart(' ').TrimEnd(' '); // tarp (tarpaulin) => tarpaulin
                    similarityData.Add(Similarity(userAnswer, w2, card, rules, (CorrectCertainty)Math.Max((int)CorrectCertainty.MaybeCorrect, (int)certainty)));

                    //string w3 = correctAnswer.Replace("(", "").Replace(")", ""); // (eye)lash => eyelash

                    var rgp1 = new Regex(Regex.Escape("("));
                    var rgp2 = new Regex(Regex.Escape(")"));

                    string w3 = rgp1.Replace(correctAnswer, "", 1); // (eye)lash => eye)lash (replace first occurence of starting paranthesis)
                    w3 = rgp2.Replace(w3, "", 1);                   // eyelash => eyelash (replace first occurence of ending paranthesis)

                    similarityData.Add(Similarity(userAnswer, w3, card, rules, (CorrectCertainty)Math.Max((int)CorrectCertainty.ProbablyCorrect, (int)certainty)));

                    if (!correctAnswer.TrimEnd().EndsWith(")") || correctAnswer.Count(c => c == ')') > 1)
                    {
                        string w4 = correctAnswer.Split(new[] { ')' }, 2)[1].TrimStart(' '); // (eye)lash => lash
                        similarityData.Add(Similarity(userAnswer, w4, card, rules, (CorrectCertainty)Math.Max((int)CorrectCertainty.ProbablyCorrect, (int)certainty)));
                    }
                }
            }

            int difference = Fastenshtein.Levenshtein.Distance(userAnswer, correctAnswer);

            similarityData.Add(new SimilarityData(difference, certainty, correctAnswer, card));
            KeepBestSimilarityData();
//#warning the best similarity data that is being kept is not necessarily equal to the written answer in the quiz!!! this potentially shows a wrong answer in "ProbablyCorrectAnswer" dialog
            SimilarityData best = similarityData.First();

            return(best);
        }