Files
nadekobot/src/NadekoBot/Modules/Games/Trivia/TriviaQuestion.cs

108 lines
3.2 KiB
C#

#nullable disable
using System.Text.RegularExpressions;
// THANKS @ShoMinamimoto for suggestions and coding help
namespace NadekoBot.Modules.Games.Common.Trivia;
public class TriviaQuestion
{
public const int maxStringLength = 22;
//represents the min size to judge levDistance with
private static readonly HashSet<Tuple<int, int>> strictness = new()
{
new(9, 0), new(14, 1), new(19, 2), new(22, 3)
};
public string Category { get; set; }
public string Question { get; set; }
public string ImageUrl { get; set; }
public string AnswerImageUrl { get; set; }
public string Answer { get; set; }
public string CleanAnswer
=> cleanAnswer ?? (cleanAnswer = Clean(Answer));
private string cleanAnswer;
public TriviaQuestion(
string q,
string a,
string c,
string img = null,
string answerImage = null)
{
Question = q;
Answer = a;
Category = c;
ImageUrl = img;
AnswerImageUrl = answerImage ?? img;
}
public string GetHint()
=> Scramble(Answer);
public bool IsAnswerCorrect(string guess)
{
if (Answer.Equals(guess, StringComparison.InvariantCulture)) return true;
var cleanGuess = Clean(guess);
if (CleanAnswer.Equals(cleanGuess, StringComparison.InvariantCulture)) return true;
var levDistanceClean = CleanAnswer.LevenshteinDistance(cleanGuess);
var levDistanceNormal = Answer.LevenshteinDistance(guess);
return JudgeGuess(CleanAnswer.Length, cleanGuess.Length, levDistanceClean)
|| JudgeGuess(Answer.Length, guess.Length, levDistanceNormal);
}
private static bool JudgeGuess(int guessLength, int answerLength, int levDistance)
{
foreach (var level in strictness)
if (guessLength <= level.Item1 || answerLength <= level.Item1)
{
if (levDistance <= level.Item2)
return true;
return false;
}
return false;
}
private static string Clean(string str)
{
str = " " + str.ToLowerInvariant() + " ";
str = Regex.Replace(str, "\\s+", " ");
str = Regex.Replace(str, "[^\\w\\d\\s]", "");
//Here's where custom modification can be done
str = Regex.Replace(str, "\\s(a|an|the|of|in|for|to|as|at|be)\\s", " ");
//End custom mod and cleanup whitespace
str = Regex.Replace(str, "^\\s+", "");
str = Regex.Replace(str, "\\s+$", "");
//Trim the really long answers
str = str.Length <= maxStringLength ? str : str[..maxStringLength];
return str;
}
private static string Scramble(string word)
{
var letters = word.ToCharArray();
var count = 0;
for (var i = 0; i < letters.Length; i++)
{
if (letters[i] == ' ')
continue;
count++;
if (count <= letters.Length / 5)
continue;
if (count % 3 == 0)
continue;
if (letters[i] != ' ')
letters[i] = '_';
}
return string.Join(" ",
new string(letters).Replace(" ", " \u2000", StringComparison.InvariantCulture).AsEnumerable());
}
}