Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions TPP.ArgsParsing/TypeParsers/AnyOrderParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ public override async Task<ArgsParseResult<AnyOrder>> Parse(
2 => typeof(AnyOrder<,>),
3 => typeof(AnyOrder<,,>),
4 => typeof(AnyOrder<,,,>),
5 => typeof(AnyOrder<,,,,>),
6 => typeof(AnyOrder<,,,,,>),
var num => throw new InvalidOperationException(
$"An implementation of {typeof(AnyOrder)} for {num} generic arguments " +
"needs to be implemented and wired up where this exception is thrown. " +
Expand Down
37 changes: 37 additions & 0 deletions TPP.ArgsParsing/TypeParsers/BadgeSourceParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using TPP.Persistence.Models;

namespace TPP.ArgsParsing.TypeParsers
{
public class BadgeSourceParser : BaseArgumentParser<Badge.BadgeSource>
{
public override Task<ArgsParseResult<Badge.BadgeSource>> Parse(IImmutableList<string> args, Type[] genericTypes)
{
string source = args[0];
ArgsParseResult<Badge.BadgeSource> result;
Badge.BadgeSource? parsedSource = null;
try
{
parsedSource = (Badge.BadgeSource)Enum.Parse(typeof(Badge.BadgeSource), source, ignoreCase: true);
}
catch (ArgumentException)
{
switch (args[1].ToLower())
{
case "run":
case "caught":
parsedSource = Badge.BadgeSource.RunCaught;
break;
}
}
if (parsedSource != null)
result = ArgsParseResult<Badge.BadgeSource>.Success(parsedSource.Value, args.Skip(1).ToImmutableList());
else
result = ArgsParseResult<Badge.BadgeSource>.Failure($"Did not find a source named '{args[0]}'");
return Task.FromResult(result);
}
}
}
44 changes: 44 additions & 0 deletions TPP.ArgsParsing/TypeParsers/ShinyParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using TPP.Common;

namespace TPP.ArgsParsing.TypeParsers
{
/// <summary>
/// A parser that finds a badge form by name.
/// </summary>
public class ShinyParser : BaseArgumentParser<bool>
{
string[] shinyWords =
{
"shiny",
"shiny:true"
};
string[] plainWords =
{
"plain",
"regular",
"shiny:false"
};
public override Task<ArgsParseResult<bool>> Parse(IImmutableList<string> args, Type[] genericTypes)
{
string s = args[0];
ArgsParseResult<bool> result;
if (shinyWords.Contains(s))
{
result = ArgsParseResult<bool>.Success(true, args.Skip(1).ToImmutableList());
}
else if (plainWords.Contains(s))
{
result = ArgsParseResult<bool>.Success(false, args.Skip(1).ToImmutableList());
}
else
{
result = ArgsParseResult<bool>.Failure("The argument couldn't be understood as shiny or not", ErrorRelevanceConfidence.Unlikely);
}
return Task.FromResult(result);
}
}
}
43 changes: 43 additions & 0 deletions TPP.ArgsParsing/Types/AnyOrder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,47 @@ public AnyOrder(T1 item1, T2 item2, T3 item3, T4 item4)
public void Deconstruct(out T1 item1, out T2 item2, out T3 item3, out T4 item4) =>
(item1, item2, item3, item4) = (Item1, Item2, Item3, Item4);
}

public class AnyOrder<T1, T2, T3, T4, T5> : AnyOrder
{
public T1 Item1 { get; }
public T2 Item2 { get; }
public T3 Item3 { get; }
public T4 Item4 { get; }
public T5 Item5 { get; }

public AnyOrder(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
{
Item1 = item1;
Item2 = item2;
Item3 = item3;
Item4 = item4;
Item5 = item5;
}

public void Deconstruct(out T1 item1, out T2 item2, out T3 item3, out T4 item4, out T5 item5) =>
(item1, item2, item3, item4, item5) = (Item1, Item2, Item3, Item4, Item5);
}
public class AnyOrder<T1, T2, T3, T4, T5, T6> : AnyOrder
{
public T1 Item1 { get; }
public T2 Item2 { get; }
public T3 Item3 { get; }
public T4 Item4 { get; }
public T5 Item5 { get; }
public T6 Item6 { get; }

public AnyOrder(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6)
{
Item1 = item1;
Item2 = item2;
Item3 = item3;
Item4 = item4;
Item5 = item5;
Item6 = item6;
}

public void Deconstruct(out T1 item1, out T2 item2, out T3 item3, out T4 item4, out T5 item5, out T6 item6) =>
(item1, item2, item3, item4, item5, item6) = (Item1, Item2, Item3, Item4, Item5, Item6);
}
}
63 changes: 63 additions & 0 deletions TPP.Common/PkmnForms.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using TPP.Common;

namespace TPP.Common
{
public static class PkmnForms
{
/// <summary>
///
/// </summary>
static readonly Dictionary<string, Dictionary<string, int>> Forms = new Dictionary<string, Dictionary<string, int>>
{
["unown"] = new Dictionary<string, int>
{
["a"] = 1,
["b"] = 2,
},
["shellos"] = new Dictionary<string, int>
{
["west sea"] = 1,
["westsea"] = 1,
["west"] = 1,
["pink"] = 1,
["east sea"] = 2,
["eastsea"] = 2,
["east"] = 2,
["blue"] = 2,
},
};

public static string getFormName(PkmnSpecies pokemon, int formid)
{
string pkmnName = pokemon.Name.ToLower(); //TODO: use normalize_name from pkmnspecies
Dictionary<string, int>? forms;
if (!Forms.TryGetValue(pkmnName, out forms))
throw new ArgumentException($"{pokemon.Name} does not have alternate forms.");
string formName = forms.FirstOrDefault(p => p.Value == formid).Key;
if (formName == null)
throw new ArgumentException($"{pokemon.Name} does not have a form with id {formid}.");
return formName;
}

public static int getFormId(PkmnSpecies pokemon, string formName)
{
string pkmnName = pokemon.Name.ToLower();
Dictionary<string, int>? forms;
if (!Forms.TryGetValue(pkmnName, out forms))
throw new ArgumentException($"{pokemon.Name} does not have alternate forms.");
int formid = forms.GetValueOrDefault(formName.ToLower());
if (formid == 0)
throw new ArgumentException($"{pokemon.Name} does not have a form called {formName}.");
return formid;
}

public static bool pokemonHasForms(PkmnSpecies pokemon)
{
return Forms.ContainsKey(pokemon.Name.ToLower());
}
}
}
6 changes: 3 additions & 3 deletions TPP.Core.Tests/Commands/Definitions/BadgeCommandsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,9 @@ public async Task TestGiftBadgeSuccessful()
User user = MockUser("MockUser");
User recipient = MockUser("Recipient");
_userRepoMock.Setup(repo => repo.FindBySimpleName("recipient")).Returns(Task.FromResult((User?)recipient));
Badge badge1 = new("badge1", user.Id, species, Badge.BadgeSource.ManualCreation, Instant.MinValue);
Badge badge2 = new("badge2", user.Id, species, Badge.BadgeSource.ManualCreation, Instant.MinValue);
Badge badge3 = new("badge3", user.Id, species, Badge.BadgeSource.ManualCreation, Instant.MinValue);
Badge badge1 = new("badge1", user.Id, species, Badge.BadgeSource.ManualCreation, Instant.MinValue, 0, false);
Badge badge2 = new("badge2", user.Id, species, Badge.BadgeSource.ManualCreation, Instant.MinValue, 0, false);
Badge badge3 = new("badge3", user.Id, species, Badge.BadgeSource.ManualCreation, Instant.MinValue, 0, false);
_badgeRepoMock.Setup(repo => repo.FindByUserAndSpecies(user.Id, species))
.Returns(Task.FromResult(new List<Badge> { badge1, badge2, badge3, }));

Expand Down
10 changes: 5 additions & 5 deletions TPP.Core.Tests/Commands/Definitions/OperatorCommandsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,9 @@ public async Task TestTransferBadgeSuccessful()
_messageSenderMock.Object, _badgeRepoMock.Object);
_userRepoMock.Setup(repo => repo.FindBySimpleName("gifter")).Returns(Task.FromResult((User?)gifter));
_userRepoMock.Setup(repo => repo.FindBySimpleName("recipient")).Returns(Task.FromResult((User?)recipient));
Badge badge1 = new("badge1", gifter.Id, species, Badge.BadgeSource.ManualCreation, Instant.MinValue);
Badge badge2 = new("badge2", gifter.Id, species, Badge.BadgeSource.ManualCreation, Instant.MinValue);
Badge badge3 = new("badge3", gifter.Id, species, Badge.BadgeSource.ManualCreation, Instant.MinValue);
Badge badge1 = new("badge1", gifter.Id, species, Badge.BadgeSource.ManualCreation, Instant.MinValue, 0, false);
Badge badge2 = new("badge2", gifter.Id, species, Badge.BadgeSource.ManualCreation, Instant.MinValue, 0, false);
Badge badge3 = new("badge3", gifter.Id, species, Badge.BadgeSource.ManualCreation, Instant.MinValue, 0, false);
_badgeRepoMock.Setup(repo => repo.FindByUserAndSpecies(gifter.Id, species))
.Returns(Task.FromResult(new List<Badge> { badge1, badge2, badge3, }));

Expand Down Expand Up @@ -256,10 +256,10 @@ public async Task TestCreateBadge()
CommandResult result = await operatorCommands.CreateBadge(new CommandContext(MockMessage(user),
ImmutableList.Create("recipient", "species", "123"), _argsParser));

Assert.AreEqual("123 badges of species #001 Species created for user Recipient.", result.Response);
Assert.AreEqual("123 Normal #001 Species badges created for Recipient.", result.Response);
Assert.AreEqual(ResponseTarget.Source, result.ResponseTarget);
_badgeRepoMock.Verify(repo =>
repo.AddBadge(recipient.Id, species, Badge.BadgeSource.ManualCreation, null),
repo.AddBadge(recipient.Id, species, Badge.BadgeSource.ManualCreation, 0, false, null),
Times.Exactly(123));
}
}
Expand Down
30 changes: 25 additions & 5 deletions TPP.Core/Commands/Definitions/BadgeCommands.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
Expand Down Expand Up @@ -48,7 +49,7 @@ public class BadgeCommands : ICommandCollection
new Command("giftbadge", GiftBadge)
{
Description =
"Gift a badge you own to another user with no price. Arguments: <pokemon> <number of badges>(Optional) <username>"
"Gift a badge you own to another user with no price. Arguments: <pokemon> <number of badges>(Optional) <username>" //TODO also update this before merge
},
};

Expand Down Expand Up @@ -271,15 +272,34 @@ public async Task<CommandResult> Pokedex(CommandContext context)
public async Task<CommandResult> GiftBadge(CommandContext context)
{
User gifter = context.Message.User;
(User recipient, PkmnSpecies species, Optional<PositiveInt> amountOpt) =
await context.ParseArgs<AnyOrder<User, PkmnSpecies, Optional<PositiveInt>>>();
(User recipient, PkmnSpecies species, Optional<PositiveInt> amountOpt, Optional<Badge.BadgeSource> sourceOpt, Optional<string> formOpt, Optional<string> formOpt2) =
await context.ParseArgs<AnyOrder<User, PkmnSpecies, Optional<PositiveInt>, Optional<Badge.BadgeSource>, Optional<string>, Optional<string>>>();
int amount = amountOpt.Map(i => i.Number).OrElse(1);

Badge.BadgeSource? source = sourceOpt.IsPresent ? sourceOpt.Value : null;
int? form = null;
if (formOpt.IsPresent)
{
string formName = formOpt.Value;
if (formOpt2.IsPresent)
formName += " " + formOpt2.Value;
try
{
form = PkmnForms.getFormId(species, formName);
}
catch (ArgumentException e)
{
return new CommandResult
{
Response = e.Message
};
}
}
if (recipient == gifter)
return new CommandResult { Response = "You cannot gift to yourself" };

List<Badge> badges = await _badgeRepo.FindByUserAndSpecies(gifter.Id, species);
List<Badge> badges = await _badgeRepo.FindAllByCustom(gifter.Id, species, form, source);
if (badges.Count < amount)
//TODO big improve before merge
return new CommandResult
{
Response = $"You tried to gift {amount} {species} badges, but you only have {badges.Count}."
Expand Down
35 changes: 28 additions & 7 deletions TPP.Core/Commands/Definitions/OperatorCommands.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
Expand Down Expand Up @@ -183,18 +184,38 @@ await _messageSender.SendWhisper(recipient, amount > 1

public async Task<CommandResult> CreateBadge(CommandContext context)
{
(User recipient, PkmnSpecies species, Optional<PositiveInt> amountOpt) =
await context.ParseArgs<AnyOrder<User, PkmnSpecies, Optional<PositiveInt>>>();
(User recipient, PkmnSpecies species, Optional<PositiveInt> amountOpt, Optional<string> formOpt, Optional<bool> shinyOpt) =
await context.ParseArgs<AnyOrder<User, PkmnSpecies, Optional<PositiveInt>, Optional<string>, Optional<bool>>>();
int amount = amountOpt.Map(i => i.Number).OrElse(1);

int form = PkmnForms.pokemonHasForms(species) ? 0 : 1; // default to the first listed form if form is unspecified
bool shiny = shinyOpt.IsPresent ? shinyOpt.Value : false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be condensed to shinyOpt.OrElse(false)

if (formOpt.IsPresent)
{
string formName = formOpt.Value;
try
{
form = PkmnForms.getFormId(species, formName);
}
catch (ArgumentException e)
{
return new CommandResult
{
Response = e.Message
};
}
}
for (int i = 0; i < amount; i++)
await _badgeRepo.AddBadge(recipient.Id, species, Badge.BadgeSource.ManualCreation);
await _badgeRepo.AddBadge(recipient.Id, species, Badge.BadgeSource.ManualCreation, form, shiny);

return new CommandResult
{
Response = amount > 1
? $"{amount} badges of species {species} created for user {recipient.Name}."
: $"Badge of species {species} created for user {recipient.Name}."
Response = PkmnForms.pokemonHasForms(species)
? amount > 1
? $"{amount} {PkmnForms.getFormName(species, form)} {species} badges created for {recipient.Name}."
: $"{PkmnForms.getFormName(species, form)} {species} badge created for {recipient.Name}."
: amount > 1
? $"{amount} {species} badges created for {recipient.Name}."
: $"{species} badge created for {recipient.Name}."
};
}
}
Expand Down
2 changes: 2 additions & 0 deletions TPP.Core/Setups.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public static ArgsParser SetUpArgsParser(IUserRepo userRepo, PokedexData pokedex
argsParser.AddArgumentParser(new SignedPokeyenParser());
argsParser.AddArgumentParser(new SignedTokensParser());
argsParser.AddArgumentParser(new PkmnSpeciesParser(pokedexData.KnownSpecies, PokedexData.NormalizeName));
argsParser.AddArgumentParser(new ShinyParser());
argsParser.AddArgumentParser(new BadgeSourceParser());

argsParser.AddArgumentParser(new AnyOrderParser(argsParser));
argsParser.AddArgumentParser(new OneOfParser(argsParser));
Expand Down
Loading