Skip to content

Commit

Permalink
Merge branch 'refs/heads/refactor/split-readyroom-and-monopoly' into …
Browse files Browse the repository at this point in the history
…develop

# Conflicts:
#	Application/Common/IRepository.cs
#	Monopoly.Web/Pages/Ready/Components/ColorChoicePanel.razor.cs
#	Monopoly.Web/Pages/Ready/Components/ReadyButton.razor.cs
#	Monopoly.Web/Pages/Ready/ReadyPage.razor.cs
  • Loading branch information
aa89227 committed Jun 2, 2024
2 parents f420f03 + da0d179 commit 03575be
Show file tree
Hide file tree
Showing 244 changed files with 3,830 additions and 2,115 deletions.
1 change: 1 addition & 0 deletions Application/Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\DomainLayer\Monopoly.DomainLayer.ReadyRoom\Monopoly.DomainLayer.ReadyRoom.csproj" />
<ProjectReference Include="..\Domain\Domain.csproj" />
</ItemGroup>

Expand Down
4 changes: 4 additions & 0 deletions Application/Common/GameRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace Application.Common;

public abstract record BaseRequest;
public abstract record GameRequest(string GameId, string PlayerId): BaseRequest;
4 changes: 2 additions & 2 deletions Application/Common/IEventBus.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using Domain.Common;
using Monopoly.DomainLayer.Common;

namespace Application.Common;

public interface IEventBus<TEvent> where TEvent : DomainEvent
{
public Task PublishAsync(IEnumerable<TEvent> events);
public Task PublishAsync(IEnumerable<TEvent> events, CancellationToken cancellationToken);
}
4 changes: 2 additions & 2 deletions Application/Common/IPresenter.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Application.Common;

public interface IPresenter<in TResponse>
public interface IPresenter<TResponse>
{
public Task PresentAsync(TResponse response);
public Task PresentAsync(TResponse response, CancellationToken cancellationToken);
}
4 changes: 2 additions & 2 deletions Application/Common/IRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ namespace Application.Common;

public interface IRepository
{
public Monopoly FindGameById(string id);
public MonopolyDataModel FindGameById(string id);
public string[] GetRooms();
public bool IsExist(string id);
public string Save(Monopoly monopoly);
public string Save(MonopolyDataModel monopolyDataModel);
}

public interface ICommandRepository : IRepository
Expand Down
188 changes: 188 additions & 0 deletions Application/Common/RepositoryExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
using Application.DataModels;
using Domain.Maps;

namespace Application.Common;

internal static class RepositoryExtensions
{
internal static string Save(this IRepository repository, Domain.MonopolyAggregate domainMonopolyAggregate)
{
var monopoly = domainMonopolyAggregate.ToApplication();
return repository.Save(monopoly);
}

/// <summary>
/// (Monopoly) Domain to Application
/// </summary>
/// <param name="domainMonopolyAggregate"></param>
/// <returns></returns>
private static MonopolyDataModel ToApplication(this Domain.MonopolyAggregate domainMonopolyAggregate)
{
var players = domainMonopolyAggregate.Players.Select(player =>
{
var playerChess = player.Chess;

Chess chess = new(playerChess.CurrentBlockId, playerChess.CurrentDirection.ToApplicationDirection());

var landContracts = player.LandContractList.Select(contract =>
new LandContract(contract.Land.Id, contract.InMortgage, contract.Deadline)).ToArray();

return new Player(
player.Id,
player.Money,
chess,
landContracts,
player.State,
player.BankruptRounds,
player.LocationId,
player.RoleId
);
}).ToArray();

Map map = new(domainMonopolyAggregate.Map.Id, domainMonopolyAggregate.Map.Blocks
.Select(row => { return row.Select(block => block?.ToApplicationBlock()).ToArray(); }).ToArray()
);
var gamestage = domainMonopolyAggregate.GameStage switch
{
Domain.GameStage.Ready => GameStage.Preparing,
Domain.GameStage.Gaming => GameStage.Gaming,
_ => throw new NotImplementedException(),
};
if (gamestage == GameStage.Preparing)
{
return new MonopolyDataModel(domainMonopolyAggregate.Id, [..players], map, domainMonopolyAggregate.HostId, null!,
null!, gamestage);
}

var currentPlayer =
domainMonopolyAggregate.Players.First(player =>
player.Id == domainMonopolyAggregate.CurrentPlayerState.PlayerId);
var auction = domainMonopolyAggregate.CurrentPlayerState.Auction;
var currentPlayerState = new CurrentPlayerState(
domainMonopolyAggregate.CurrentPlayerState.PlayerId,
domainMonopolyAggregate.CurrentPlayerState.IsPayToll,
domainMonopolyAggregate.CurrentPlayerState.IsBoughtLand,
domainMonopolyAggregate.CurrentPlayerState.IsUpgradeLand,
domainMonopolyAggregate.CurrentPlayerState.Auction is null
? null
: new Auction(auction!.LandContract.Land.Id, auction.HighestBidder?.Id, auction.HighestPrice),
domainMonopolyAggregate.CurrentPlayerState.RemainingSteps,
domainMonopolyAggregate.CurrentPlayerState.HadSelectedDirection
);
var LandHouses = domainMonopolyAggregate.Map.Blocks.SelectMany(block => block).OfType<Domain.Land>()
.Where(land => land.House > 0)
.Select(land => new LandHouse(land.Id, land.House)).ToArray();


return new DataModels.MonopolyDataModel(domainMonopolyAggregate.Id, players, map, domainMonopolyAggregate.HostId,
currentPlayerState, LandHouses, gamestage);
}

private static Block ToApplicationBlock(this Domain.Block domainBlock)
{
return domainBlock switch
{
Domain.StartPoint startBlock => new StartPoint(startBlock.Id),
Domain.Station stationBlock => new Station(stationBlock.Id),
Domain.Land landBlock => new Land(landBlock.Id),
Domain.ParkingLot parkingLotBlock => new ParkingLot(parkingLotBlock.Id),
Domain.Jail prisonBlock => new Jail(prisonBlock.Id),
null => new EmptyBlock(),
_ => throw new NotImplementedException(),
};
}

/// <summary>
/// (Monopoly) Application to Domain
/// </summary>
/// <param name="monopolyDataModel"></param>
/// <returns></returns>
internal static Domain.MonopolyAggregate ToDomain(this MonopolyDataModel monopolyDataModel)
{
//Domain.Map map = new(monopoly.Map.Id, monopoly.Map.Blocks
// .Select(row =>
// {
// return row.Select(block => block?.ToDomainBlock()).ToArray();
// }).ToArray()
// );
Domain.Map map = new SevenXSevenMap();
var builder = new Domain.Builders.MonopolyBuilder()
.WithId(monopolyDataModel.Id)
.WithHost(monopolyDataModel.HostId)
.WithMap(map);
monopolyDataModel.Players.ToList().ForEach(
p => builder.WithPlayer(p.Id, playerBuilder =>
playerBuilder.WithMoney(p.Money)
.WithPosition(p.Chess.CurrentPosition, p.Chess.Direction.ToString())
.WithLandContracts(p.LandContracts)
.WithBankrupt(p.BankruptRounds)
.WithLocation(p.LocationId)
.WithRole(p.RoleId)
.WithState(p.PlayerState)
));
builder.WithGameStage(monopolyDataModel.GameStage switch
{
GameStage.Preparing => Domain.GameStage.Ready,
GameStage.Gaming => Domain.GameStage.Gaming,
_ => throw new NotImplementedException(),
});
if (monopolyDataModel.GameStage == GameStage.Preparing)
{
return builder.Build();
}

var cps = monopolyDataModel.CurrentPlayerState;
if (cps.Auction is null)
{
builder.WithCurrentPlayer(cps.PlayerId, x => x.WithBoughtLand(cps.IsBoughtLand)
.WithUpgradeLand(cps.IsUpgradeLand)
.WithPayToll(cps.IsPayToll)
.WithSelectedDirection(cps.HadSelectedDirection));
}
else
{
builder.WithCurrentPlayer(cps.PlayerId, x => x.WithAuction(
cps.Auction.LandId, cps.Auction.HighestBidderId, cps.Auction.HighestPrice));
}

monopolyDataModel.LandHouses.ToList().ForEach(LandHouse => builder.WithLandHouse(LandHouse.LandId, LandHouse.House));

return builder.Build();
}

private static Domain.Builders.PlayerBuilder WithLandContracts(this Domain.Builders.PlayerBuilder builder,
LandContract[] landContracts)
{
landContracts.ToList().ForEach(landContract =>
{
builder.WithLandContract(landContract.LandId, landContract.InMortgage, landContract.Deadline);
});
return builder;
}

private static Domain.Block? ToDomainBlock(this Block? block)
{
return block switch
{
StartPoint startBlock => new Domain.StartPoint(startBlock.Id),
Station stationBlock => new Domain.Station(stationBlock.Id),
Land landBlock => new Domain.Land(landBlock.Id),
ParkingLot parkingLotBlock => new Domain.ParkingLot(parkingLotBlock.Id),
Jail prisonBlock => new Domain.Jail(prisonBlock.Id),
EmptyBlock => null,
_ => throw new NotImplementedException(),
};
}

private static Direction ToApplicationDirection(this Domain.Map.Direction direction)
{
return direction switch
{
Domain.Map.Direction.Up => Direction.Up,
Domain.Map.Direction.Down => Direction.Down,
Domain.Map.Direction.Left => Direction.Left,
Domain.Map.Direction.Right => Direction.Right,
_ => throw new NotImplementedException(),
};
}
}
3 changes: 0 additions & 3 deletions Application/Common/Request.cs

This file was deleted.

1 change: 1 addition & 0 deletions Application/Common/Response.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Domain.Common;
using Monopoly.DomainLayer.Common;

namespace Application.Common;

Expand Down
11 changes: 6 additions & 5 deletions Application/Common/Usecase.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
using Domain.Common;
using Monopoly.DomainLayer.Common;

namespace Application.Common;

public abstract class Usecase<TRequest, TResponse>()
where TRequest : Request where TResponse : Response
where TRequest : BaseRequest where TResponse : Response
{
public abstract Task ExecuteAsync(TRequest request, IPresenter<TResponse> presenter);
public abstract Task ExecuteAsync(TRequest request, IPresenter<TResponse> presenter,
CancellationToken cancellationToken = default);
}

public abstract class CommandUsecase<TRequest, TResponse>(ICommandRepository repository, IEventBus<DomainEvent> eventBus)
: Usecase<TRequest, TResponse>()
where TRequest : Request where TResponse : Response
where TRequest : GameRequest where TResponse : Response
{
protected ICommandRepository Repository { get; } = repository;
protected IEventBus<DomainEvent> EventBus { get; } = eventBus;
}

public abstract class QueryUsecase<TRequest, TResponse>(ICommandRepository repository)
where TRequest : Request
where TRequest : GameRequest
{
protected ICommandRepository Repository { get; } = repository;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Application.DataModels;

public record Monopoly(string Id, Player[] Players, Map Map, string HostId, CurrentPlayerState CurrentPlayerState, LandHouse[] LandHouses, GameStage GameStage);
public record MonopolyDataModel(string Id, Player[] Players, Map Map, string HostId, CurrentPlayerState CurrentPlayerState, LandHouse[] LandHouses, GameStage GameStage);

public record Player(string Id, decimal Money, Chess Chess, LandContract[] LandContracts, Domain.PlayerState PlayerState, int BankruptRounds, int LocationId, string? RoleId);
public record CurrentPlayerState(string PlayerId, bool IsPayToll, bool IsBoughtLand, bool IsUpgradeLand, Auction? Auction, int RemainingSteps, bool HadSelectedDirection);
Expand Down
9 changes: 7 additions & 2 deletions Application/DependencyInjection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,24 @@ private static IServiceCollection AddUseCases(this IServiceCollection services)
{
var assembly = typeof(DependencyInjection).Assembly;
var types = assembly.GetTypes();
var useCaseType = typeof(CommandUsecase<,>);
var commandUseCaseType = typeof(CommandUsecase<,>);
var queryUsecaseType = typeof(QueryUsecase<,>);
var usecaseType = typeof(Usecase<,>);

foreach (var type in types.Where(t => t.BaseType?.IsGenericType is true && t.IsAbstract == false))
{
if (type.BaseType?.GetGenericTypeDefinition() == useCaseType)
if (type.BaseType?.GetGenericTypeDefinition() == commandUseCaseType)
{
services.AddTransient(type, type);
}
else if (type.BaseType?.GetGenericTypeDefinition() == queryUsecaseType)
{
services.AddTransient(type, type);
}
else if (type.BaseType?.GetGenericTypeDefinition() == usecaseType)
{
services.AddTransient(type, type);
}
}

return services;
Expand Down
32 changes: 0 additions & 32 deletions Application/Queries/GetReadyInfoUsecase.cs

This file was deleted.

20 changes: 20 additions & 0 deletions Application/Queries/GetReadyRoomInfosUsecase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Application.Common;
using Application.Usecases.ReadyRoom;
using Monopoly.DomainLayer.ReadyRoom;

namespace Application.Queries;

public record GetReadyRoomInfosRequest(string GameId, string PlayerId)
: GameRequest(GameId, PlayerId);
public record GetReadyRoomInfosResponse(string RequestPlayerId, ReadyRoomAggregate ReadyRoom) : Response;

public class GetReadyRoomInfosUsecase(IReadyRoomRepository repository)
: Usecase<GetReadyRoomInfosRequest, GetReadyRoomInfosResponse>
{
public override async Task ExecuteAsync(GetReadyRoomInfosRequest request,
IPresenter<GetReadyRoomInfosResponse> presenter, CancellationToken cancellationToken = default)
{
var readyRoom = await repository.GetReadyRoomAsync(request.GameId);
await presenter.PresentAsync(new GetReadyRoomInfosResponse(request.PlayerId, readyRoom), cancellationToken);
}
}
9 changes: 5 additions & 4 deletions Application/Usecases/BidUsecase.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
using Application.Common;
using Domain.Common;
using Monopoly.DomainLayer.Common;

namespace Application.Usecases;

public record BidRequest(string GameId, string PlayerId, decimal BidPrice)
: Request(GameId, PlayerId);
: GameRequest(GameId, PlayerId);

public record BidResponse(IReadOnlyList<DomainEvent> Events) : CommandResponse(Events);

public class BidUsecase(ICommandRepository repository, IEventBus<DomainEvent> eventBus)
: CommandUsecase<BidRequest, BidResponse>(repository, eventBus)
{
public override async Task ExecuteAsync(BidRequest request, IPresenter<BidResponse> presenter)
public override async Task ExecuteAsync(BidRequest request, IPresenter<BidResponse> presenter,
CancellationToken cancellationToken = default)
{
//查
var game = Repository.FindGameById(request.GameId).ToDomain();
Expand All @@ -23,6 +24,6 @@ public override async Task ExecuteAsync(BidRequest request, IPresenter<BidRespon
Repository.Save(game);

//推
await presenter.PresentAsync(new BidResponse(game.DomainEvents));
await presenter.PresentAsync(new BidResponse(game.DomainEvents), cancellationToken);
}
}
Loading

0 comments on commit 03575be

Please sign in to comment.