Trivia converted, removed currency reward
This commit is contained in:
parent
8a7ae9339e
commit
d6465fb6af
@ -9,14 +9,16 @@ using System.Text;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
// todo rewrite?
|
||||||
|
// todo DB
|
||||||
namespace NadekoBot.Modules.Games.Commands.Trivia
|
namespace NadekoBot.Modules.Games.Commands.Trivia
|
||||||
{
|
{
|
||||||
internal class TriviaGame
|
public class TriviaGame
|
||||||
{
|
{
|
||||||
private readonly SemaphoreSlim _guessLock = new SemaphoreSlim(1,1);
|
private readonly SemaphoreSlim _guessLock = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
private Server server { get; }
|
private IGuild guild { get; }
|
||||||
private Channel channel { get; }
|
private ITextChannel channel { get; }
|
||||||
|
|
||||||
private int QuestionDurationMiliseconds { get; } = 30000;
|
private int QuestionDurationMiliseconds { get; } = 30000;
|
||||||
private int HintTimeoutMiliseconds { get; } = 6000;
|
private int HintTimeoutMiliseconds { get; } = 6000;
|
||||||
@ -26,18 +28,18 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
|
|||||||
public TriviaQuestion CurrentQuestion { get; private set; }
|
public TriviaQuestion CurrentQuestion { get; private set; }
|
||||||
public HashSet<TriviaQuestion> oldQuestions { get; } = new HashSet<TriviaQuestion>();
|
public HashSet<TriviaQuestion> oldQuestions { get; } = new HashSet<TriviaQuestion>();
|
||||||
|
|
||||||
public ConcurrentDictionary<User, int> Users { get; } = new ConcurrentDictionary<User, int>();
|
public ConcurrentDictionary<IGuildUser, int> Users { get; } = new ConcurrentDictionary<IGuildUser, int>();
|
||||||
|
|
||||||
public bool GameActive { get; private set; } = false;
|
public bool GameActive { get; private set; } = false;
|
||||||
public bool ShouldStopGame { get; private set; }
|
public bool ShouldStopGame { get; private set; }
|
||||||
|
|
||||||
public int WinRequirement { get; } = 10;
|
public int WinRequirement { get; } = 10;
|
||||||
|
|
||||||
public TriviaGame(CommandEventArgs e, bool showHints, int winReq = 10)
|
public TriviaGame(IGuild guild, ITextChannel channel, bool showHints, int winReq = 10)
|
||||||
{
|
{
|
||||||
ShowHints = showHints;
|
ShowHints = showHints;
|
||||||
server = e.Server;
|
this.guild = guild;
|
||||||
channel = e.Channel;
|
this.channel = channel;
|
||||||
WinRequirement = winReq;
|
WinRequirement = winReq;
|
||||||
Task.Run(StartGame);
|
Task.Run(StartGame);
|
||||||
}
|
}
|
||||||
@ -53,13 +55,13 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
|
|||||||
CurrentQuestion = TriviaQuestionPool.Instance.GetRandomQuestion(oldQuestions);
|
CurrentQuestion = TriviaQuestionPool.Instance.GetRandomQuestion(oldQuestions);
|
||||||
if (CurrentQuestion == null)
|
if (CurrentQuestion == null)
|
||||||
{
|
{
|
||||||
await channel.SendMessage($":exclamation: Failed loading a trivia question").ConfigureAwait(false);
|
await channel.SendMessageAsync($":exclamation: Failed loading a trivia question").ConfigureAwait(false);
|
||||||
await End().ConfigureAwait(false);
|
await End().ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
oldQuestions.Add(CurrentQuestion); //add it to exclusion list so it doesn't show up again
|
oldQuestions.Add(CurrentQuestion); //add it to exclusion list so it doesn't show up again
|
||||||
//sendquestion
|
//sendquestion
|
||||||
await channel.SendMessage($":question: **{CurrentQuestion.Question}**").ConfigureAwait(false);
|
await channel.SendMessageAsync($":question: **{CurrentQuestion.Question}**").ConfigureAwait(false);
|
||||||
|
|
||||||
//receive messages
|
//receive messages
|
||||||
NadekoBot.Client.MessageReceived += PotentialGuess;
|
NadekoBot.Client.MessageReceived += PotentialGuess;
|
||||||
@ -72,7 +74,7 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
|
|||||||
//hint
|
//hint
|
||||||
await Task.Delay(HintTimeoutMiliseconds, token).ConfigureAwait(false);
|
await Task.Delay(HintTimeoutMiliseconds, token).ConfigureAwait(false);
|
||||||
if (ShowHints)
|
if (ShowHints)
|
||||||
await channel.SendMessage($":exclamation:**Hint:** {CurrentQuestion.GetHint()}").ConfigureAwait(false);
|
await channel.SendMessageAsync($":exclamation:**Hint:** {CurrentQuestion.GetHint()}").ConfigureAwait(false);
|
||||||
|
|
||||||
//timeout
|
//timeout
|
||||||
await Task.Delay(QuestionDurationMiliseconds - HintTimeoutMiliseconds, token).ConfigureAwait(false);
|
await Task.Delay(QuestionDurationMiliseconds - HintTimeoutMiliseconds, token).ConfigureAwait(false);
|
||||||
@ -81,7 +83,7 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
|
|||||||
catch (TaskCanceledException) { } //means someone guessed the answer
|
catch (TaskCanceledException) { } //means someone guessed the answer
|
||||||
GameActive = false;
|
GameActive = false;
|
||||||
if (!triviaCancelSource.IsCancellationRequested)
|
if (!triviaCancelSource.IsCancellationRequested)
|
||||||
await channel.Send($":clock2: :question: **Time's up!** The correct answer was **{CurrentQuestion.Answer}**").ConfigureAwait(false);
|
await channel.SendMessageAsync($":clock2: :question: **Time's up!** The correct answer was **{CurrentQuestion.Answer}**").ConfigureAwait(false);
|
||||||
NadekoBot.Client.MessageReceived -= PotentialGuess;
|
NadekoBot.Client.MessageReceived -= PotentialGuess;
|
||||||
// load next question if game is still running
|
// load next question if game is still running
|
||||||
await Task.Delay(2000).ConfigureAwait(false);
|
await Task.Delay(2000).ConfigureAwait(false);
|
||||||
@ -92,46 +94,43 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
|
|||||||
private async Task End()
|
private async Task End()
|
||||||
{
|
{
|
||||||
ShouldStopGame = true;
|
ShouldStopGame = true;
|
||||||
await channel.SendMessage("**Trivia game ended**\n" + GetLeaderboard()).ConfigureAwait(false);
|
await channel.SendMessageAsync("**Trivia game ended**\n" + GetLeaderboard()).ConfigureAwait(false);
|
||||||
TriviaGame throwAwayValue;
|
|
||||||
TriviaCommands.RunningTrivias.TryRemove(server.Id, out throwAwayValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StopGame()
|
public async Task StopGame()
|
||||||
{
|
{
|
||||||
if (!ShouldStopGame)
|
if (!ShouldStopGame)
|
||||||
await channel.SendMessage(":exclamation: Trivia will stop after this question.").ConfigureAwait(false);
|
await channel.SendMessageAsync(":exclamation: Trivia will stop after this question.").ConfigureAwait(false);
|
||||||
ShouldStopGame = true;
|
ShouldStopGame = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void PotentialGuess(object sender, MessageEventArgs e)
|
private async Task PotentialGuess(IMessage imsg)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (e.Channel.IsPrivate) return;
|
if (!(imsg.Channel is IGuildChannel && imsg.Channel is ITextChannel)) return;
|
||||||
if (e.Server != server) return;
|
if ((imsg.Channel as IGuildChannel).Guild != guild) return;
|
||||||
if (e.User.Id == NadekoBot.Client.CurrentUser.Id) return;
|
if (imsg.Author.Id == (await NadekoBot.Client.GetCurrentUserAsync()).Id) return;
|
||||||
|
|
||||||
|
var guildUser = imsg.Author as IGuildUser;
|
||||||
|
|
||||||
var guess = false;
|
var guess = false;
|
||||||
await _guessLock.WaitAsync().ConfigureAwait(false);
|
await _guessLock.WaitAsync().ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (GameActive && CurrentQuestion.IsAnswerCorrect(e.Message.Text) && !triviaCancelSource.IsCancellationRequested)
|
if (GameActive && CurrentQuestion.IsAnswerCorrect(imsg.Content) && !triviaCancelSource.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
Users.TryAdd(e.User, 0); //add if not exists
|
Users.AddOrUpdate(guildUser, 0, (gu, old) => old++);
|
||||||
Users[e.User]++; //add 1 point to the winner
|
|
||||||
guess = true;
|
guess = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally { _guessLock.Release(); }
|
finally { _guessLock.Release(); }
|
||||||
if (!guess) return;
|
if (!guess) return;
|
||||||
triviaCancelSource.Cancel();
|
triviaCancelSource.Cancel();
|
||||||
await channel.SendMessage($"☑️ {e.User.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false);
|
await channel.SendMessageAsync($"☑️ {guildUser.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false);
|
||||||
if (Users[e.User] != WinRequirement) return;
|
if (Users[guildUser] != WinRequirement) return;
|
||||||
ShouldStopGame = true;
|
ShouldStopGame = true;
|
||||||
await channel.Send($":exclamation: We have a winner! It's {e.User.Mention}.").ConfigureAwait(false);
|
await channel.SendMessageAsync($":exclamation: We have a winner! It's {guildUser.Mention}.").ConfigureAwait(false);
|
||||||
// add points to the winner
|
|
||||||
await FlowersHandler.AddFlowersAsync(e.User, "Won Trivia", 2).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
@ -146,7 +145,7 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
|
|||||||
|
|
||||||
foreach (var kvp in Users.OrderBy(kvp => kvp.Value))
|
foreach (var kvp in Users.OrderBy(kvp => kvp.Value))
|
||||||
{
|
{
|
||||||
sb.AppendLine($"**{kvp.Key.Name}** has {kvp.Value} points".ToString().SnPl(kvp.Value));
|
sb.AppendLine($"**{kvp.Key.Username}** has {kvp.Value} points".ToString().SnPl(kvp.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
// THANKS @ShoMinamimoto for suggestions and coding help
|
// THANKS @ShoMinamimoto for suggestions and coding help
|
||||||
@ -28,7 +29,7 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
|
|||||||
this.Category = c;
|
this.Category = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetHint() => Answer.Scramble();
|
public string GetHint() => Scramble(Answer);
|
||||||
|
|
||||||
public bool IsAnswerCorrect(string guess)
|
public bool IsAnswerCorrect(string guess)
|
||||||
{
|
{
|
||||||
@ -80,5 +81,27 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
|
|||||||
|
|
||||||
public override string ToString() =>
|
public override string ToString() =>
|
||||||
"Question: **" + this.Question + "?**";
|
"Question: **" + this.Question + "?**";
|
||||||
|
|
||||||
|
private static string Scramble(string word)
|
||||||
|
{
|
||||||
|
var letters = word.ToArray();
|
||||||
|
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(" ", letters) + "`";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
|
|||||||
public class TriviaQuestionPool
|
public class TriviaQuestionPool
|
||||||
{
|
{
|
||||||
public static TriviaQuestionPool Instance { get; } = new TriviaQuestionPool();
|
public static TriviaQuestionPool Instance { get; } = new TriviaQuestionPool();
|
||||||
|
//todo DB
|
||||||
public HashSet<TriviaQuestion> pool = new HashSet<TriviaQuestion>();
|
public HashSet<TriviaQuestion> pool = new HashSet<TriviaQuestion>();
|
||||||
|
|
||||||
private Random rng { get; } = new Random();
|
private Random rng { get; } = new Random();
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
//using Discord.Commands;
|
|
||||||
//using NadekoBot.Classes;
|
|
||||||
//using NadekoBot.Modules.Games.Commands.Trivia;
|
|
||||||
//using System;
|
|
||||||
//using System.Collections.Concurrent;
|
|
||||||
//using System.Linq;
|
|
||||||
|
|
||||||
////todo DB
|
|
||||||
////todo Rewrite?
|
|
||||||
|
|
||||||
//namespace NadekoBot.Modules.Games.Commands
|
|
||||||
//{
|
|
||||||
// internal class TriviaCommands : DiscordCommand
|
|
||||||
// {
|
|
||||||
// public static ConcurrentDictionary<ulong, TriviaGame> RunningTrivias = new ConcurrentDictionary<ulong, TriviaGame>();
|
|
||||||
|
|
||||||
// public TriviaCommands(DiscordModule module) : base(module)
|
|
||||||
// {
|
|
||||||
// }
|
|
||||||
|
|
||||||
// internal override void Init(CommandGroupBuilder cgb)
|
|
||||||
// {
|
|
||||||
// cgb.CreateCommand(Module.Prefix + "t")
|
|
||||||
// .Description($"Starts a game of trivia. You can add nohint to prevent hints." +
|
|
||||||
// "First player to get to 10 points wins by default. You can specify a different number. 30 seconds per question." +
|
|
||||||
// $" |`{Module.Prefix}t nohint` or `{Module.Prefix}t 5 nohint`")
|
|
||||||
// .Parameter("args", ParameterType.Multiple)
|
|
||||||
// .Do(async e =>
|
|
||||||
// {
|
|
||||||
// TriviaGame trivia;
|
|
||||||
// if (!RunningTrivias.TryGetValue(e.Server.Id, out trivia))
|
|
||||||
// {
|
|
||||||
// var showHints = !e.Args.Contains("nohint");
|
|
||||||
// var number = e.Args.Select(s =>
|
|
||||||
// {
|
|
||||||
// int num;
|
|
||||||
// return new Tuple<bool, int>(int.TryParse(s, out num), num);
|
|
||||||
// }).Where(t => t.Item1).Select(t => t.Item2).FirstOrDefault();
|
|
||||||
// if (number < 0)
|
|
||||||
// return;
|
|
||||||
// var triviaGame = new TriviaGame(e, showHints, number == 0 ? 10 : number);
|
|
||||||
// if (RunningTrivias.TryAdd(e.Server.Id, triviaGame))
|
|
||||||
// await imsg.Channel.SendMessageAsync($"**Trivia game started! {triviaGame.WinRequirement} points needed to win.**").ConfigureAwait(false);
|
|
||||||
// else
|
|
||||||
// await triviaGame.StopGame().ConfigureAwait(false);
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// await imsg.Channel.SendMessageAsync("Trivia game is already running on this server.\n" + trivia.CurrentQuestion).ConfigureAwait(false);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// cgb.CreateCommand(Module.Prefix + "tl")
|
|
||||||
// .Description($"Shows a current trivia leaderboard. | `{Prefix}tl`")
|
|
||||||
// .Do(async e =>
|
|
||||||
// {
|
|
||||||
// TriviaGame trivia;
|
|
||||||
// if (RunningTrivias.TryGetValue(e.Server.Id, out trivia))
|
|
||||||
// await imsg.Channel.SendMessageAsync(trivia.GetLeaderboard()).ConfigureAwait(false);
|
|
||||||
// else
|
|
||||||
// await imsg.Channel.SendMessageAsync("No trivia is running on this server.").ConfigureAwait(false);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// cgb.CreateCommand(Module.Prefix + "tq")
|
|
||||||
// .Description($"Quits current trivia after current question. | `{Prefix}tq`")
|
|
||||||
// .Do(async e =>
|
|
||||||
// {
|
|
||||||
// TriviaGame trivia;
|
|
||||||
// if (RunningTrivias.TryGetValue(e.Server.Id, out trivia))
|
|
||||||
// {
|
|
||||||
// await trivia.StopGame().ConfigureAwait(false);
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// await imsg.Channel.SendMessageAsync("No trivia is running on this server.").ConfigureAwait(false);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
80
src/NadekoBot/Modules/Games/Commands/TriviaCommands.cs
Normal file
80
src/NadekoBot/Modules/Games/Commands/TriviaCommands.cs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Attributes;
|
||||||
|
using NadekoBot.Classes;
|
||||||
|
using NadekoBot.Modules.Games.Commands.Trivia;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
//todo DB
|
||||||
|
//todo Rewrite?
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Games.Commands
|
||||||
|
{
|
||||||
|
public partial class GamesModule
|
||||||
|
{
|
||||||
|
|
||||||
|
[Group]
|
||||||
|
public class TriviaCommands
|
||||||
|
{
|
||||||
|
public static ConcurrentDictionary<ulong, TriviaGame> RunningTrivias = new ConcurrentDictionary<ulong, TriviaGame>();
|
||||||
|
|
||||||
|
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Trivia(IMessage imsg, string[] args)
|
||||||
|
{
|
||||||
|
var channel = imsg.Channel as IGuildChannel;
|
||||||
|
|
||||||
|
TriviaGame trivia;
|
||||||
|
if (!RunningTrivias.TryGetValue(channel.Guild.Id, out trivia))
|
||||||
|
{
|
||||||
|
var showHints = !args.Contains("nohint");
|
||||||
|
var number = args.Select(s =>
|
||||||
|
{
|
||||||
|
int num;
|
||||||
|
return new Tuple<bool, int>(int.TryParse(s, out num), num);
|
||||||
|
}).Where(t => t.Item1).Select(t => t.Item2).FirstOrDefault();
|
||||||
|
if (number < 0)
|
||||||
|
return;
|
||||||
|
var triviaGame = new TriviaGame(channel.Guild, imsg.Channel as ITextChannel, showHints, number == 0 ? 10 : number);
|
||||||
|
if (RunningTrivias.TryAdd(channel.Guild.Id, triviaGame))
|
||||||
|
await imsg.Channel.SendMessageAsync($"**Trivia game started! {triviaGame.WinRequirement} points needed to win.**").ConfigureAwait(false);
|
||||||
|
else
|
||||||
|
await triviaGame.StopGame().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
await imsg.Channel.SendMessageAsync("Trivia game is already running on this server.\n" + trivia.CurrentQuestion).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Tl(IMessage imsg)
|
||||||
|
{
|
||||||
|
var channel = imsg.Channel as IGuildChannel;
|
||||||
|
|
||||||
|
TriviaGame trivia;
|
||||||
|
if (RunningTrivias.TryGetValue(channel.Guild.Id, out trivia))
|
||||||
|
await imsg.Channel.SendMessageAsync(trivia.GetLeaderboard()).ConfigureAwait(false);
|
||||||
|
else
|
||||||
|
await imsg.Channel.SendMessageAsync("No trivia is running on this server.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Tq(IMessage imsg)
|
||||||
|
{
|
||||||
|
var channel = imsg.Channel as IGuildChannel;
|
||||||
|
|
||||||
|
TriviaGame trivia;
|
||||||
|
if (RunningTrivias.TryRemove(channel.Guild.Id, out trivia))
|
||||||
|
{
|
||||||
|
await trivia.StopGame().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
await imsg.Channel.SendMessageAsync("No trivia is running on this server.").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -137,5 +137,85 @@ namespace NadekoBot.Extensions
|
|||||||
return string.Concat(str.Take(maxLength - 3)) + (hideDots ? "" : "...");
|
return string.Concat(str.Take(maxLength - 3)) + (hideDots ? "" : "...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes trailing S or ES (if specified) on the given string if the num is 1
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str"></param>
|
||||||
|
/// <param name="num"></param>
|
||||||
|
/// <param name="es"></param>
|
||||||
|
/// <returns>String with the correct singular/plural form</returns>
|
||||||
|
public static string SnPl(this string str, int? num, bool es = false)
|
||||||
|
{
|
||||||
|
if (str == null)
|
||||||
|
throw new ArgumentNullException(nameof(str));
|
||||||
|
if (num == null)
|
||||||
|
throw new ArgumentNullException(nameof(num));
|
||||||
|
return num == 1 ? str.Remove(str.Length - 1, es ? 2 : 1) : str;
|
||||||
|
}
|
||||||
|
|
||||||
|
//http://www.dotnetperls.com/levenshtein
|
||||||
|
public static int LevenshteinDistance(this string s, string t)
|
||||||
|
{
|
||||||
|
var n = s.Length;
|
||||||
|
var m = t.Length;
|
||||||
|
var d = new int[n + 1, m + 1];
|
||||||
|
|
||||||
|
// Step 1
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m == 0)
|
||||||
|
{
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2
|
||||||
|
for (var i = 0; i <= n; d[i, 0] = i++)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var j = 0; j <= m; d[0, j] = j++)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3
|
||||||
|
for (var i = 1; i <= n; i++)
|
||||||
|
{
|
||||||
|
//Step 4
|
||||||
|
for (var j = 1; j <= m; j++)
|
||||||
|
{
|
||||||
|
// Step 5
|
||||||
|
var cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
|
||||||
|
|
||||||
|
// Step 6
|
||||||
|
d[i, j] = Math.Min(
|
||||||
|
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
|
||||||
|
d[i - 1, j - 1] + cost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Step 7
|
||||||
|
return d[n, m];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int KiB(this int value) => value * 1024;
|
||||||
|
public static int KB(this int value) => value * 1000;
|
||||||
|
|
||||||
|
public static int MiB(this int value) => value.KiB() * 1024;
|
||||||
|
public static int MB(this int value) => value.KB() * 1000;
|
||||||
|
|
||||||
|
public static int GiB(this int value) => value.MiB() * 1024;
|
||||||
|
public static int GB(this int value) => value.MB() * 1000;
|
||||||
|
|
||||||
|
public static ulong KiB(this ulong value) => value * 1024;
|
||||||
|
public static ulong KB(this ulong value) => value * 1000;
|
||||||
|
|
||||||
|
public static ulong MiB(this ulong value) => value.KiB() * 1024;
|
||||||
|
public static ulong MB(this ulong value) => value.KB() * 1000;
|
||||||
|
|
||||||
|
public static ulong GiB(this ulong value) => value.MiB() * 1024;
|
||||||
|
public static ulong GB(this ulong value) => value.MB() * 1000;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user