Skip to content

Commit

Permalink
atdd: 抵押(只有抵押、未實作贖回)
Browse files Browse the repository at this point in the history
  • Loading branch information
takeiteasy23 committed Aug 8, 2023
1 parent c275b11 commit 4a93d63
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 5 deletions.
30 changes: 30 additions & 0 deletions Application/Usecases/MortgageUsecase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Application.Common;
using Domain.Common;

namespace Application.Usecases;

public record MortgageRequest(string GameId, string PlayerId, string BlockId)
: Request(GameId, PlayerId);

public class MortgageUsecase : Usecase<MortgageRequest>
{
public MortgageUsecase(IRepository repository, IEventBus<DomainEvent> eventBus)
: base(repository, eventBus)
{
}

public override async Task ExecuteAsync(MortgageRequest request)
{
//查
var game = Repository.FindGameById(request.GameId);

//改
game.MortgageLandContract(request.PlayerId, request.BlockId);

//存
Repository.Save(game);

//推
await EventBus.PublishAsync(game.DomainEvents);
}
}
10 changes: 10 additions & 0 deletions Domain/Block.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ public virtual decimal CalcullateToll(Player payee)
return _price * RATE_OF_HOUSE[house] * RATE_OF_LOT[lotCount];
}

public virtual decimal GetMortgagePrice()
{
return _price * (1 + house) * (decimal)0.7;
}

public override Player? GetOwner()
{
return landContract.Owner;
Expand Down Expand Up @@ -197,6 +202,11 @@ public override decimal CalcullateToll(Player payee)
return _price * lotCount;
}

public override decimal GetMortgagePrice()
{
return _price;
}

public override DomainEvent BuildHouse(Player player)
{
return new PlayerCannotBuildHouseEvent(player.Monopoly.Id, player.Id, Id);
Expand Down
9 changes: 9 additions & 0 deletions Domain/Events/PlayerMortgageEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Domain.Common;

namespace Domain.Events;

public record PlayerMortgageEvent(string GameId, string PlayerId, decimal PlayerMoney, string BlockId, int DeadLine)
: DomainEvent(GameId);

public record PlayerCannotMortgageEvent(string GameId, string PlayerId, decimal PlayerMoney, string BlockId)
: DomainEvent(GameId);
2 changes: 1 addition & 1 deletion Domain/Monopoly.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public void MortgageLandContract(string playerId, string landId)
{
Player player = GetPlayer(playerId);
VerifyCurrentPlayer(player);
player.MortgageLandContract(landId);
AddDomainEvent(player.MortgageLandContract(landId));
}

public void PayToll(string payerId)
Expand Down
26 changes: 22 additions & 4 deletions Domain/Player.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Domain.Events;
using System.Numerics;
using Domain.Events;
using System.Numerics;
using Domain.Interfaces;
using Domain.Common;

Expand Down Expand Up @@ -94,13 +94,31 @@ internal void SelectDirection(Map.Direction direction)
Monopoly.AddDomainEvent(events);
}

internal void MortgageLandContract(string landId)
internal DomainEvent MortgageLandContract(string landId)
{
if(mortgages.Exists(m => m.LandContract.Land.Id == landId))
{
return new PlayerCannotMortgageEvent(Monopoly.Id, Id, Money, landId);
}
else{
var landContract = _landContractList.First(l => l.Land.Id == landId);
mortgages.Add(new Mortgage(this, landContract));
Money += landContract.Land.GetMortgagePrice();
return new PlayerMortgageEvent(Monopoly.Id, Id, Money,
mortgages[mortgages.Count-1].LandContract.Land.Id,
mortgages[mortgages.Count-1].Deadline);
}
}

#region 測試用
public void MortgageForTest(string landId)
{
var landContract = _landContractList.First(l => l.Land.Id == landId);
mortgages.Add(new Mortgage(this, landContract));
Money += landContract.Land.Price * (decimal)0.7;
}

#endregion

public void PayToll(Player payee, decimal amount)
{
Money -= amount;
Expand Down
4 changes: 4 additions & 0 deletions Server/Hubs/IMonopolyResponses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,8 @@ public interface IMonopolyResponses
Task PlayerTooPoorToBuildHouseEvent(string PlayerId, string BlockId, decimal PlayerMoney, decimal UpgradePrice);

Task HouseMaxEvent(string PlayerId, string BlockId, int House);

Task PlayerMortgageEvent(string PlayerId, decimal PlayerMoney, string BlockId, int DeadLine);

Task PlayerCannotMortgageEvent(string PlayerId, decimal PlayerMoney, string BlockId);
}
5 changes: 5 additions & 0 deletions Server/Hubs/MonopolyHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ public async Task PlayerBuildHouse(string gameId, string userId, BuildHouseUseca
await usecase.ExecuteAsync(new BuildHouseRequest(gameId, userId));
}

public async Task PlayerMortgage(string gameId, string userId, string blockId, MortgageUsecase usecase)
{
await usecase.ExecuteAsync(new MortgageRequest(gameId, userId, blockId));
}

public MonopolyHub(IRepository repository)
{
_repository = repository;
Expand Down
8 changes: 8 additions & 0 deletions Server/MonopolyEventBus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@ public async Task PublishAsync(IEnumerable<DomainEvent> events)
{
await _hubContext.Clients.All.HouseMaxEvent(hme.PlayerId, hme.BlockId, hme.House);
}
else if (e is PlayerMortgageEvent pme)
{
await _hubContext.Clients.All.PlayerMortgageEvent(pme.PlayerId, pme.PlayerMoney, pme.BlockId, pme.DeadLine);
}
else if (e is PlayerCannotMortgageEvent pctme)
{
await _hubContext.Clients.All.PlayerCannotMortgageEvent(pctme.PlayerId, pctme.PlayerMoney, pctme.BlockId);
}
}
}
}
101 changes: 101 additions & 0 deletions Test/ServerTests/AcceptanceTests/MortgageTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
using Domain;
using Server.Hubs;
using static Domain.Map;
using static ServerTests.Utils;

namespace ServerTests.AcceptanceTests;

[TestClass]
public class MortgageTest
{
private MonopolyTestServer server = default!;

[TestInitialize]

public void SetUp()
{
server = new MonopolyTestServer();
}

[TestMethod]
[Description(
"""
Given: A 持有 A1,價值 1000元
A 持有 5000元
When: A 抵押 A1
Then: A 持有 5000+1000*70% = 5700元
A 持有 A1
A1 在 10回合 後收回
""")]
public async Task 玩家抵押房地產()
{
Player A = new("A", 5000);

const string gameId = "1";
var monopolyBuilder = new MonopolyBuilder("1")
.WithPlayer(
new MonopolyPlayer(A.Id)
.WithMoney(A.Money)
.WithPosition("Start", Direction.Right.ToString())
.WithLandContract("A1")
)
.WithCurrentPlayer(nameof(A));

monopolyBuilder.Save(server);

var hub = await server.CreateHubConnectionAsync(gameId, "A");

// Act
await hub.SendAsync(nameof(MonopolyHub.PlayerMortgage), gameId, "A", "A1");

// Assert
// A 抵押房地產
hub.Verify<string, decimal, string, int>(
nameof(IMonopolyResponses.PlayerMortgageEvent),
(playerId, playerMoney, blockId, deadLine)
=> playerId == "A" && playerMoney == 5700 && blockId == "A1" && deadLine == 10);
hub.VerifyNoElseEvent();
}

[TestMethod]
[Description(
"""
Given: A 持有 A1,價值 1000元,抵押中
A 持有 1000元
When: A 抵押 A1
Then: A 無法再次抵押
A 持有 1000元
""")]
public async Task 玩家不能抵押已抵押房地產()
{
Player A = new("A", 1000);

const string gameId = "1";
var monopolyBuilder = new MonopolyBuilder("1")
.WithPlayer(
new MonopolyPlayer(A.Id)
.WithMoney(A.Money)
.WithPosition("Start", Direction.Right.ToString())
.WithLandContract("A1")
.WithMortgage("A1")
)
.WithCurrentPlayer(nameof(A));

monopolyBuilder.Save(server);

var hub = await server.CreateHubConnectionAsync(gameId, "A");

// Act
await hub.SendAsync(nameof(MonopolyHub.PlayerMortgage), gameId, "A", "A1");

// Assert
// A 抵押房地產
hub.Verify<string, decimal, string>(
nameof(IMonopolyResponses.PlayerCannotMortgageEvent),
(playerId, playerMoney, blockId)
=> playerId == "A" && playerMoney == 1000 && blockId == "A1");
hub.VerifyNoElseEvent();
}
}


15 changes: 15 additions & 0 deletions Test/ServerTests/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ public Monopoly Build()
Land land = (Land)map.FindBlockById(l);
for (int i = 0; i < p.House[l]; i++) land.Upgrade();
});
p.Mortgages.ForEach(l =>
{
player.MortgageForTest(l);
});
monopoly.AddPlayer(player, p.BlockId, direction);
if (CurrentPlayer == player.Id)
{
Expand All @@ -106,6 +110,7 @@ public class MonopolyPlayer
public string BlockId { get; set; }
public string Direction { get; set; }
public List<string> LandContracts { get; set; }
public List<string> Mortgages { get; set; }
public IDictionary<string, int> House = new Dictionary<string, int>();

public MonopolyPlayer(string id)
Expand All @@ -115,6 +120,7 @@ public MonopolyPlayer(string id)
BlockId = "StartPoint";
Direction = "Right";
LandContracts = new();
Mortgages = new();
}

public MonopolyPlayer WithMoney(decimal money)
Expand All @@ -136,5 +142,14 @@ public MonopolyPlayer WithLandContract(string landId, int house = 0)
House.Add(landId, house);
return this;
}

public MonopolyPlayer WithMortgage(string landId)
{
if (LandContracts.Exists(l => l == landId))
{
Mortgages.Add(landId);
}
return this;
}
}
}

0 comments on commit 4a93d63

Please sign in to comment.