Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Badge trading #231

Open
wants to merge 21 commits into
base: badge-trading
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
56 changes: 56 additions & 0 deletions TPP.Persistence.MongoDB.Tests/Repos/BadgeBuyOfferRepoTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using Moq;
using NodaTime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TPP.Persistence.Models;
using TPP.Persistence.MongoDB.Repos;
using MongoDB.Driver;
using NUnit.Framework;
using TPP.Common;
using TPP.Persistence.Repos;

namespace TPP.Persistence.MongoDB.Tests.Repos
{
class BadgeBuyOfferRepoTest : MongoTestBase
{
public BadgeBuyOfferRepo CreateBadgeBuyOfferRepo()
{
IMongoDatabase db = CreateTemporaryDatabase();
BadgeRepo mockBadgeRepo = new BadgeRepo(db, Mock.Of<IMongoBadgeLogRepo>(), Mock.Of<IClock>());
return new BadgeBuyOfferRepo(db, mockBadgeRepo, Mock.Of<IClock>());
}

internal class MockClock : IClock
{
public Instant FixedCurrentInstant = Instant.FromUnixTimeSeconds(1234567890);
public Instant GetCurrentInstant() => FixedCurrentInstant;
}

[Test]
public async Task write_then_read_are_equal()
{
string userId = "m4";
PkmnSpecies species = PkmnSpecies.OfId("1");
int form = 0;
Badge.BadgeSource source = Badge.BadgeSource.ManualCreation;
bool shiny = true;
int price = 999;
int amount = 1;

IBadgeBuyOfferRepo badgeBuyOfferRepo = CreateBadgeBuyOfferRepo();

BadgeBuyOffer offer = await badgeBuyOfferRepo.CreateBuyOffer(userId, species, form, source, shiny, price, amount, Instant.MaxValue);

Assert.AreEqual(userId, offer.UserId);
Assert.AreEqual(species, offer.Species);
Assert.AreEqual(form, offer.Form);
Assert.AreEqual(source, offer.Source);
Assert.AreEqual(shiny, offer.Shiny);
Assert.AreEqual(price, offer.Price);
Assert.AreEqual(amount, offer.Amount);
}
}
}
74 changes: 74 additions & 0 deletions TPP.Persistence.MongoDB/Repos/BadgeBuyOfferRepo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.IdGenerators;
using MongoDB.Driver;
using NodaTime;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TPP.Common;
using TPP.Persistence.Models;
using TPP.Persistence.MongoDB.Serializers;
using TPP.Persistence.Repos;

namespace TPP.Persistence.MongoDB.Repos
{
public class BadgeBuyOfferRepo : IBadgeBuyOfferRepo
{
private const string CollectionName = "badgebuyoffers";

public readonly IMongoCollection<BadgeBuyOffer> Collection;
private readonly IBadgeRepo _badgeRepo;
private readonly IClock _clock;

static BadgeBuyOfferRepo()
{
BsonClassMap.RegisterClassMap<BadgeBuyOffer>(cm =>
{
cm.MapIdProperty(o => o.Id)
.SetIdGenerator(StringObjectIdGenerator.Instance)
.SetSerializer(ObjectIdAsStringSerializer.Instance);
cm.MapProperty(o => o.UserId).SetElementName("user");
cm.MapProperty(o => o.Species).SetElementName("species");
cm.MapProperty(o => o.Source).SetElementName("source");
cm.MapProperty(o => o.CreatedAt).SetElementName("created_at");
cm.MapProperty(o => o.Form).SetElementName("form")
.SetDefaultValue(0);
Mogiiii marked this conversation as resolved.
Show resolved Hide resolved
cm.MapProperty(o => o.Shiny).SetElementName("shiny")
.SetDefaultValue(false)
.SetIgnoreIfDefault(true);
});
}

public BadgeBuyOfferRepo(IMongoDatabase database, BadgeRepo badgeRepo, IClock clock)
{
_badgeRepo = badgeRepo;

database.CreateCollectionIfNotExists(CollectionName).Wait();
Collection = database.GetCollection<BadgeBuyOffer>(CollectionName);
_clock = clock;
}

public async Task<BadgeBuyOffer> CreateBuyOffer(string userId, PkmnSpecies species, int? form, Badge.BadgeSource? source, bool? shiny, int price, int amount, Instant? createdAt=null)
{
BadgeBuyOffer buyOffer = new BadgeBuyOffer(
id: string.Empty,
userId: userId,
species: species,
form: form,
source: source,
shiny: shiny,
price: price,
amount: amount,
createdAt: createdAt ?? _clock.GetCurrentInstant()
);

await Collection.InsertOneAsync(buyOffer);
Debug.Assert(buyOffer.Id.Length > 0, "The MongoDB driver injected a generated ID");
return buyOffer;
}

}
}
90 changes: 90 additions & 0 deletions TPP.Persistence/Models/BadgeBuyOffer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using NodaTime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TPP.Common;

namespace TPP.Persistence.Models
{
public class BadgeBuyOffer
{
/// <summary>
/// Unique Id.
/// </summary>
public string Id { get; init; }

/// <summary>
/// The ID of the user that created the buy offer.
/// </summary>
public string UserId { get; init; }

/// <summary>
/// The species of pokemon to buy.
/// </summary>
public PkmnSpecies Species { get; init; }

/// <summary>
/// The form of pokemon to buy.
/// </summary>
public int? Form { get; init; }

/// <summary>
/// The source of the badge to buy.
/// </summary>
public Badge.BadgeSource? Source { get; init; }

/// <summary>
/// Is the offer seeking shiny badges.
/// </summary>
public bool? Shiny { get; init; }

/// <summary>
/// How much to pay for each badge.
/// </summary>
public int Price { get; init; }

/// <summary>
/// The number of badges to buy.
/// </summary>
public int Amount { get; private set; }

/// <summary>
/// When the buy offer was created.
/// </summary>
public Instant CreatedAt { get; init; }

/// <summary>
/// When this offer was last updated.
/// </summary>
public Instant WaitingSince { get; private set; }

//duration and expires_at depricated from old core

public BadgeBuyOffer(string id, string userId, PkmnSpecies species, int? form, Badge.BadgeSource? source, bool? shiny, int price, int amount, Instant createdAt)
{
Id = id;
UserId = userId;
Species = species;
Form = form;
Source = source;
Shiny = shiny;
Price = price;
Amount = amount;
CreatedAt = createdAt;
WaitingSince = createdAt;
}

/// <summary>
/// Decrement the amount to buy.
/// </summary>
public void decrement(Instant decrementedAt)
{
if (Amount <= 0)
throw new InvalidOperationException("The buy offer has no badges remaining, and cannot be decremented further.");
Amount--;
WaitingSince = decrementedAt;
}
}
}
16 changes: 16 additions & 0 deletions TPP.Persistence/Repos/IBadgeBuyOfferRepo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using NodaTime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TPP.Common;
using TPP.Persistence.Models;

namespace TPP.Persistence.Repos
{
public interface IBadgeBuyOfferRepo
{
public Task<BadgeBuyOffer> CreateBuyOffer(string userId, PkmnSpecies species, int? form, Badge.BadgeSource? source, bool? shiny, int price, int amount, Instant? createdAt);
}
}