From c275b111faaf91fcfc0ef5a4a4cfb3cefd9786b3 Mon Sep 17 00:00:00 2001 From: melo Date: Mon, 7 Aug 2023 15:30:26 +0800 Subject: [PATCH] =?UTF-8?q?atdd:=20=E5=AF=A6=E4=BD=9C=E8=BB=8A=E7=AB=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Domain/Block.cs | 34 +++++++++++-- Domain/Maps/SevenXSevenMap.cs | 8 ++-- .../AcceptanceTests/BuildHouseTest.cs | 38 +++++++++++++++ .../AcceptanceTests/PayTollTest.cs | 48 +++++++++++++++++++ 4 files changed, 119 insertions(+), 9 deletions(-) diff --git a/Domain/Block.cs b/Domain/Block.cs index a608cc4..8badfd1 100644 --- a/Domain/Block.cs +++ b/Domain/Block.cs @@ -55,8 +55,8 @@ public class Land : Block private static readonly decimal[] RATE_OF_LOT = new decimal[] { 0, 1, 1.3m, 2, 4, 8, 16 }; private static readonly int MAX_HOUSE = 5; - private LandContract landContract; - private readonly decimal _price; + protected LandContract landContract; + protected readonly decimal _price; private int house; public decimal Price => _price; // 土地購買價格 @@ -73,7 +73,7 @@ public Land(string id, decimal price = 1000, string lot = " ") : base(id) this.lot = lot; } - public void Upgrade() + public virtual void Upgrade() { house++; } @@ -115,7 +115,7 @@ public List PayToll(Player payer) return domainEvents; } - public decimal CalcullateToll(Player payee) + public virtual decimal CalcullateToll(Player payee) { int lotCount = payee.LandContractList.Count(t => t.Land.Lot == lot); @@ -132,7 +132,7 @@ public override void UpdateOwner(Player Owner) landContract.Owner = Owner; } - public DomainEvent BuildHouse(Player player) + public virtual DomainEvent BuildHouse(Player player) { if(GetOwner() == player) { @@ -177,4 +177,28 @@ public class ParkingLot : Block public ParkingLot(string id) : base(id) { } +} + +public class Station : Land +{ + public Station(string id, decimal price = 1000, string lot = "S") : base(id, price,lot) + { + } + + public override void Upgrade() + { + throw new Exception("車站不能蓋房子!"); + } + + public override decimal CalcullateToll(Player payee) + { + int lotCount = payee.LandContractList.Count(t => t.Land.Lot == lot); + + return _price * lotCount; + } + + public override DomainEvent BuildHouse(Player player) + { + return new PlayerCannotBuildHouseEvent(player.Monopoly.Id, player.Id, Id); + } } \ No newline at end of file diff --git a/Domain/Maps/SevenXSevenMap.cs b/Domain/Maps/SevenXSevenMap.cs index 8e2f3c2..1f4eb4c 100644 --- a/Domain/Maps/SevenXSevenMap.cs +++ b/Domain/Maps/SevenXSevenMap.cs @@ -9,12 +9,12 @@ public SevenXSevenMap() : base(Blocks) private static Block?[][] Blocks => new Block?[][] { - new Block?[] { new StartPoint("Start"), new Land("A1", lot:"A"), new Land("Station1"), new Land("A2", lot:"A"), new Land("A3", lot:"A"), null, null }, + new Block?[] { new StartPoint("Start"), new Land("A1", lot:"A"), new Station("Station1"), new Land("A2", lot:"A"), new Land("A3", lot:"A"), null, null }, new Block?[] { new Land("F4", lot:"F"), null, null, null, new Land("A4", lot:"A"), null, null }, - new Block?[] { new Land("Station4"), null, new Land("B5", lot:"B"), new Land("B6", lot:"B"), new ParkingLot("ParkingLot"), new Land("C1", lot:"C"), new Land("C2", lot:"C") }, + new Block?[] { new Station("Station4"), null, new Land("B5", lot:"B"), new Land("B6", lot:"B"), new ParkingLot("ParkingLot"), new Land("C1", lot:"C"), new Land("C2", lot:"C") }, new Block?[] { new Land("F3", lot:"F"), null, new Land("B4", lot:"B"), null, new Land("B1", lot:"B"), null, new Land("C3", lot:"C") }, - new Block?[] { new Land("F2", lot:"F"), new Land("F1", lot:"F"), new Jail("Jail"), new Land("B3", lot:"B"), new Land("B2", lot:"B"), null, new Land("Station2") }, + new Block?[] { new Land("F2", lot:"F"), new Land("F1", lot:"F"), new Jail("Jail"), new Land("B3", lot:"B"), new Land("B2", lot:"B"), null, new Station("Station2") }, new Block?[] { null, null, new Land("E3", lot:"E"), null, null, null, new Land("D1", lot:"D") }, - new Block?[] { null, null, new Land("E2", lot:"E"), new Land("E1", lot:"E"), new Land("Station3"), new Land("D3", lot:"D"), new Land("D2", lot:"D") }, + new Block?[] { null, null, new Land("E2", lot:"E"), new Land("E1", lot:"E"), new Station("Station3"), new Land("D3", lot:"D"), new Land("D2", lot:"D") }, }; } \ No newline at end of file diff --git a/Test/ServerTests/AcceptanceTests/BuildHouseTest.cs b/Test/ServerTests/AcceptanceTests/BuildHouseTest.cs index c8cbf85..19a6dc5 100644 --- a/Test/ServerTests/AcceptanceTests/BuildHouseTest.cs +++ b/Test/ServerTests/AcceptanceTests/BuildHouseTest.cs @@ -95,4 +95,42 @@ public async Task 土地最多蓋5間房子() => playId == "A" && blockId == "A1" && house == 5); hub.VerifyNoElseEvent(); } + + [TestMethod] + [Description( + """ + Given: A 持有 車站1,購買價 1000元 + A 持有 1000元,在 車站1 上 + When: A 蓋房子 + Then: A 不能蓋房子 + """)] + 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("Station1", Direction.Right.ToString()) + .WithLandContract("Station1") + ) + .WithCurrentPlayer(nameof(A)); + + monopolyBuilder.Save(server); + + var hub = await server.CreateHubConnectionAsync(gameId, "A"); + + // Act + await hub.SendAsync(nameof(MonopolyHub.PlayerBuildHouse), gameId, "A"); + + // Assert + // A 蓋房子 + hub.Verify( + nameof(IMonopolyResponses.PlayerCannotBuildHouseEvent), + (playId, blockId) + => playId == "A" && blockId == "Station1"); + hub.VerifyNoElseEvent(); + } } diff --git a/Test/ServerTests/AcceptanceTests/PayTollTest.cs b/Test/ServerTests/AcceptanceTests/PayTollTest.cs index 483257d..7da1ffe 100644 --- a/Test/ServerTests/AcceptanceTests/PayTollTest.cs +++ b/Test/ServerTests/AcceptanceTests/PayTollTest.cs @@ -206,4 +206,52 @@ public async Task 玩家在別人的土地上但餘額不足以付過路費() => playerId == "A" && playerMoney == 30 && toll == 50); hub.VerifyNoElseEvent(); } + + [TestMethod] + [Description( + """ + Given: 目前輪到A + A 在 車站1 上,持有 3000元 + B 持有 1000元 + 車站1 是 B 的土地,價值 1000元 + When: A 付過路費 + Then: A 持有 2000元 + B 持有 2000元 + """)] + public async Task 玩家在別人的車站上付過路費() + { + // Arrange + Player A = new("A", 3000); + Player B = new("B", 1000); + + const string gameId = "1"; + var monopolyBuilder = new MonopolyBuilder("1") + .WithPlayer( + new MonopolyPlayer(A.Id) + .WithMoney(A.Money) + .WithPosition("Station1", Direction.Right.ToString()) + ) + .WithPlayer( + new MonopolyPlayer(B.Id) + .WithMoney(B.Money) + .WithPosition("A1", Direction.Right.ToString()) + .WithLandContract("Station1") + ) + .WithCurrentPlayer(nameof(A)); + + monopolyBuilder.Save(server); + + var hub = await server.CreateHubConnectionAsync(gameId, A.Id); + + // Act + await hub.SendAsync(nameof(MonopolyHub.PlayerPayToll), gameId, "A"); + + // Assert + // A 付過路費 + hub.Verify( + nameof(IMonopolyResponses.PlayerPayTollEvent), + (playerId, playerMoney, ownerId, ownerMoney) + => playerId == "A" && playerMoney == 2000 && ownerId == "B" && ownerMoney == 2000); + hub.VerifyNoElseEvent(); + } } \ No newline at end of file