refactored games module

This commit is contained in:
Master Kwoth 2016-04-14 23:30:13 +02:00
parent fe67591081
commit 3e6b2df73d
9 changed files with 104 additions and 58 deletions

View File

@ -96,7 +96,7 @@ namespace NadekoBot.Classes.Trivia
ShouldStopGame = true; ShouldStopGame = true;
await channel.SendMessage("**Trivia game ended**\n" + GetLeaderboard()); await channel.SendMessage("**Trivia game ended**\n" + GetLeaderboard());
TriviaGame throwAwayValue; TriviaGame throwAwayValue;
Commands.Trivia.RunningTrivias.TryRemove(server.Id, out throwAwayValue); Modules.Games.Commands.Trivia.RunningTrivias.TryRemove(server.Id, out throwAwayValue);
} }
public async Task StopGame() public async Task StopGame()

View File

@ -1,6 +1,7 @@
using Discord.Commands; using Discord.Commands;
using NadekoBot.Classes.JSONModels; using NadekoBot.Classes.JSONModels;
using NadekoBot.Commands; using NadekoBot.Commands;
using NadekoBot.Modules.Games.Commands;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@ -1,25 +1,28 @@
using System; using Discord.Commands;
using NadekoBot.Commands;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands;
using NadekoBot.Modules;
namespace NadekoBot.Commands { namespace NadekoBot.Modules.Games.Commands
class BetrayGame : DiscordCommand { {
class BetrayGame : DiscordCommand
{
public BetrayGame(DiscordModule module) : base(module) { } public BetrayGame(DiscordModule module) : base(module) { }
private enum Answers { private enum Answers
{
Cooperate, Cooperate,
Betray Betray
} }
internal override void Init(CommandGroupBuilder cgb) { internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "betray") cgb.CreateCommand(Module.Prefix + "betray")
.Description("BETRAY GAME. Betray nadeko next turn." + .Description("BETRAY GAME. Betray nadeko next turn." +
"If Nadeko cooperates - you get extra points, nadeko loses a LOT." + "If Nadeko cooperates - you get extra points, nadeko loses a LOT." +
"If Nadeko betrays - you both lose some points.") "If Nadeko betrays - you both lose some points.")
.Do(async e => { .Do(async e =>
{
await ReceiveAnswer(e, Answers.Betray); await ReceiveAnswer(e, Answers.Betray);
}); });
@ -27,7 +30,8 @@ namespace NadekoBot.Commands {
.Description("BETRAY GAME. Cooperate with nadeko next turn." + .Description("BETRAY GAME. Cooperate with nadeko next turn." +
"If Nadeko cooperates - you both get bonus points." + "If Nadeko cooperates - you both get bonus points." +
"If Nadeko betrays - you lose A LOT, nadeko gets extra.") "If Nadeko betrays - you lose A LOT, nadeko gets extra.")
.Do(async e => { .Do(async e =>
{
await ReceiveAnswer(e, Answers.Cooperate); await ReceiveAnswer(e, Answers.Cooperate);
}); });
@ -55,7 +59,8 @@ namespace NadekoBot.Commands {
private int round = 0; private int round = 0;
private Answers NextAnswer = Answers.Cooperate; private Answers NextAnswer = Answers.Cooperate;
private async Task ReceiveAnswer(CommandEventArgs e, Answers userAnswer) { private async Task ReceiveAnswer(CommandEventArgs e, Answers userAnswer)
{
var response = userAnswer == Answers.Betray var response = userAnswer == Answers.Betray
? ":no_entry: `You betrayed nadeko` - you monster." ? ":no_entry: `You betrayed nadeko` - you monster."
: ":ok: `You cooperated with nadeko.` "; : ":ok: `You cooperated with nadeko.` ";
@ -64,16 +69,23 @@ namespace NadekoBot.Commands {
? ":no_entry: `aww Nadeko betrayed you` - she is so cute" ? ":no_entry: `aww Nadeko betrayed you` - she is so cute"
: ":ok: `Nadeko cooperated.`"; : ":ok: `Nadeko cooperated.`";
NextAnswer = userAnswer; NextAnswer = userAnswer;
if (userAnswer == Answers.Betray && currentAnswer == Answers.Betray) { if (userAnswer == Answers.Betray && currentAnswer == Answers.Betray)
{
NadekoPoints--; NadekoPoints--;
UserPoints--; UserPoints--;
} else if (userAnswer == Answers.Cooperate && currentAnswer == Answers.Cooperate) { }
else if (userAnswer == Answers.Cooperate && currentAnswer == Answers.Cooperate)
{
NadekoPoints += 2; NadekoPoints += 2;
UserPoints += 2; UserPoints += 2;
} else if (userAnswer == Answers.Betray && currentAnswer == Answers.Cooperate) { }
else if (userAnswer == Answers.Betray && currentAnswer == Answers.Cooperate)
{
NadekoPoints -= 3; NadekoPoints -= 3;
UserPoints += 3; UserPoints += 3;
} else if (userAnswer == Answers.Cooperate && currentAnswer == Answers.Betray) { }
else if (userAnswer == Answers.Cooperate && currentAnswer == Answers.Betray)
{
NadekoPoints += 3; NadekoPoints += 3;
UserPoints -= 3; UserPoints -= 3;
} }
@ -98,7 +110,8 @@ namespace NadekoBot.Commands {
} }
} }
public class BetraySetting { public class BetraySetting
{
private string Story = $"{0} have robbed a bank and got captured by a police." + private string Story = $"{0} have robbed a bank and got captured by a police." +
$"Investigators gave you a choice:\n" + $"Investigators gave you a choice:\n" +
$"You can either >COOPERATE with your friends and " + $"You can either >COOPERATE with your friends and " +

View File

@ -1,14 +1,14 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Classes; using NadekoBot.Classes;
using NadekoBot.Modules; using NadekoBot.Commands;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace NadekoBot.Commands namespace NadekoBot.Modules.Games.Commands
{ {
/// <summary> /// <summary>
/// Flower picking/planting idea is given to me by its /// Flower picking/planting idea is given to me by its

View File

@ -1,6 +1,6 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Modules; using NadekoBot.Commands;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@ -8,7 +8,7 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace NadekoBot.Commands namespace NadekoBot.Modules.Games.Commands
{ {
internal class PollCommand : DiscordCommand internal class PollCommand : DiscordCommand
{ {

View File

@ -1,30 +1,37 @@
using System; using Discord;
using Discord.Commands;
using NadekoBot.Classes;
using NadekoBot.Classes._DataModels;
using NadekoBot.Commands;
using NadekoBot.Extensions;
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using NadekoBot.Classes;
using NadekoBot.Classes._DataModels;
using NadekoBot.Extensions;
using NadekoBot.Modules;
namespace NadekoBot.Commands { namespace NadekoBot.Modules.Games.Commands
{
public static class SentencesProvider { public static class SentencesProvider
internal static string GetRandomSentence() { {
internal static string GetRandomSentence()
{
var data = DbHandler.Instance.GetAllRows<TypingArticle>(); var data = DbHandler.Instance.GetAllRows<TypingArticle>();
try { try
{
return data.ToList()[new Random().Next(0, data.Count())].Text; return data.ToList()[new Random().Next(0, data.Count())].Text;
} catch { }
catch
{
return "Failed retrieving data from parse. Owner didn't add any articles to type using `typeadd`."; return "Failed retrieving data from parse. Owner didn't add any articles to type using `typeadd`.";
} }
} }
} }
public class TypingGame { public class TypingGame
{
public const float WORD_VALUE = 4.5f; public const float WORD_VALUE = 4.5f;
private readonly Channel channel; private readonly Channel channel;
public string CurrentSentence; public string CurrentSentence;
@ -32,7 +39,8 @@ namespace NadekoBot.Commands {
private readonly Stopwatch sw; private readonly Stopwatch sw;
private readonly List<ulong> finishedUserIds; private readonly List<ulong> finishedUserIds;
public TypingGame(Channel channel) { public TypingGame(Channel channel)
{
this.channel = channel; this.channel = channel;
IsActive = false; IsActive = false;
sw = new Stopwatch(); sw = new Stopwatch();
@ -41,7 +49,8 @@ namespace NadekoBot.Commands {
public Channel Channell { get; internal set; } public Channel Channell { get; internal set; }
internal async Task<bool> Stop() { internal async Task<bool> Stop()
{
if (!IsActive) return false; if (!IsActive) return false;
NadekoBot.Client.MessageReceived -= AnswerReceived; NadekoBot.Client.MessageReceived -= AnswerReceived;
finishedUserIds.Clear(); finishedUserIds.Clear();
@ -52,8 +61,10 @@ namespace NadekoBot.Commands {
return true; return true;
} }
internal async Task Start() { internal async Task Start()
while (true) { {
while (true)
{
if (IsActive) return; // can't start running game if (IsActive) return; // can't start running game
IsActive = true; IsActive = true;
CurrentSentence = SentencesProvider.GetRandomSentence(); CurrentSentence = SentencesProvider.GetRandomSentence();
@ -71,7 +82,8 @@ namespace NadekoBot.Commands {
sw.Start(); sw.Start();
HandleAnswers(); HandleAnswers();
while (i > 0) { while (i > 0)
{
await Task.Delay(1000); await Task.Delay(1000);
i--; i--;
if (!IsActive) if (!IsActive)
@ -82,64 +94,79 @@ namespace NadekoBot.Commands {
} }
} }
private void HandleAnswers() { private void HandleAnswers()
{
NadekoBot.Client.MessageReceived += AnswerReceived; NadekoBot.Client.MessageReceived += AnswerReceived;
} }
private async void AnswerReceived(object sender, MessageEventArgs e) { private async void AnswerReceived(object sender, MessageEventArgs e)
try { {
try
{
if (e.Channel == null || e.Channel.Id != channel.Id || e.User.Id == NadekoBot.Client.CurrentUser.Id) return; if (e.Channel == null || e.Channel.Id != channel.Id || e.User.Id == NadekoBot.Client.CurrentUser.Id) return;
var guess = e.Message.RawText; var guess = e.Message.RawText;
var distance = CurrentSentence.LevenshteinDistance(guess); var distance = CurrentSentence.LevenshteinDistance(guess);
var decision = Judge(distance, guess.Length); var decision = Judge(distance, guess.Length);
if (decision && !finishedUserIds.Contains(e.User.Id)) { if (decision && !finishedUserIds.Contains(e.User.Id))
{
finishedUserIds.Add(e.User.Id); finishedUserIds.Add(e.User.Id);
await channel.Send($"{e.User.Mention} finished in **{sw.Elapsed.Seconds}** seconds with { distance } errors, **{ CurrentSentence.Length / WORD_VALUE / sw.Elapsed.Seconds * 60 }** WPM!"); await channel.Send($"{e.User.Mention} finished in **{sw.Elapsed.Seconds}** seconds with { distance } errors, **{ CurrentSentence.Length / WORD_VALUE / sw.Elapsed.Seconds * 60 }** WPM!");
if (finishedUserIds.Count % 2 == 0) { if (finishedUserIds.Count % 2 == 0)
{
await e.Channel.SendMessage($":exclamation: `A lot of people finished, here is the text for those still typing:`\n\n:book:**{CurrentSentence}**:book:"); await e.Channel.SendMessage($":exclamation: `A lot of people finished, here is the text for those still typing:`\n\n:book:**{CurrentSentence}**:book:");
} }
} }
} catch { } }
catch { }
} }
private bool Judge(int errors, int textLength) => errors <= textLength / 25; private bool Judge(int errors, int textLength) => errors <= textLength / 25;
} }
internal class SpeedTyping : DiscordCommand { internal class SpeedTyping : DiscordCommand
{
public static ConcurrentDictionary<ulong, TypingGame> RunningContests; public static ConcurrentDictionary<ulong, TypingGame> RunningContests;
public SpeedTyping(DiscordModule module) : base(module) { public SpeedTyping(DiscordModule module) : base(module)
{
RunningContests = new ConcurrentDictionary<ulong, TypingGame>(); RunningContests = new ConcurrentDictionary<ulong, TypingGame>();
} }
public Func<CommandEventArgs, Task> DoFunc() => public Func<CommandEventArgs, Task> DoFunc() =>
async e => { async e =>
{
var game = RunningContests.GetOrAdd(e.User.Server.Id, id => new TypingGame(e.Channel)); var game = RunningContests.GetOrAdd(e.User.Server.Id, id => new TypingGame(e.Channel));
if (game.IsActive) { if (game.IsActive)
{
await e.Channel.SendMessage( await e.Channel.SendMessage(
$"Contest already running in " + $"Contest already running in " +
$"{game.Channell.Mention} channel."); $"{game.Channell.Mention} channel.");
} else { }
else
{
await game.Start(); await game.Start();
} }
}; };
private Func<CommandEventArgs, Task> QuitFunc() => private Func<CommandEventArgs, Task> QuitFunc() =>
async e => { async e =>
{
TypingGame game; TypingGame game;
if (RunningContests.TryRemove(e.User.Server.Id, out game)) { if (RunningContests.TryRemove(e.User.Server.Id, out game))
{
await game.Stop(); await game.Stop();
return; return;
} }
await e.Channel.SendMessage("No contest to stop on this channel."); await e.Channel.SendMessage("No contest to stop on this channel.");
}; };
internal override void Init(CommandGroupBuilder cgb) { internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "typestart") cgb.CreateCommand(Module.Prefix + "typestart")
.Description("Starts a typing contest.") .Description("Starts a typing contest.")
.Do(DoFunc()); .Do(DoFunc());
@ -151,10 +178,12 @@ namespace NadekoBot.Commands {
cgb.CreateCommand(Module.Prefix + "typeadd") cgb.CreateCommand(Module.Prefix + "typeadd")
.Description("Adds a new article to the typing contest. Owner only.") .Description("Adds a new article to the typing contest. Owner only.")
.Parameter("text", ParameterType.Unparsed) .Parameter("text", ParameterType.Unparsed)
.Do(async e => { .Do(async e =>
{
if (!NadekoBot.IsOwner(e.User.Id) || string.IsNullOrWhiteSpace(e.GetArg("text"))) return; if (!NadekoBot.IsOwner(e.User.Id) || string.IsNullOrWhiteSpace(e.GetArg("text"))) return;
DbHandler.Instance.InsertData(new TypingArticle { DbHandler.Instance.InsertData(new TypingArticle
{
Text = e.GetArg("text"), Text = e.GetArg("text"),
DateAdded = DateTime.Now DateAdded = DateTime.Now
}); });

View File

@ -1,10 +1,10 @@
using Discord.Commands; using Discord.Commands;
using NadekoBot.Modules; using NadekoBot.Commands;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Linq; using System.Linq;
using TriviaGame = NadekoBot.Classes.Trivia.TriviaGame; using TriviaGame = NadekoBot.Classes.Trivia.TriviaGame;
namespace NadekoBot.Commands namespace NadekoBot.Modules.Games.Commands
{ {
internal class Trivia : DiscordCommand internal class Trivia : DiscordCommand
{ {

View File

@ -4,6 +4,7 @@ using NadekoBot.Classes.JSONModels;
using NadekoBot.Classes.Permissions; using NadekoBot.Classes.Permissions;
using NadekoBot.Commands; using NadekoBot.Commands;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Modules.Games.Commands;
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;

View File

@ -8,7 +8,9 @@ using NadekoBot.Modules;
using NadekoBot.Modules.Administration; using NadekoBot.Modules.Administration;
using NadekoBot.Modules.Gambling; using NadekoBot.Modules.Gambling;
using NadekoBot.Modules.Games; using NadekoBot.Modules.Games;
using NadekoBot.Modules.Games.Commands;
using NadekoBot.Modules.Pokemon; using NadekoBot.Modules.Pokemon;
using NadekoBot.Modules.Searches;
using NadekoBot.Modules.Translator; using NadekoBot.Modules.Translator;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;