Skip to content

Commit

Permalink
Refactor/presenter (#72)
Browse files Browse the repository at this point in the history
* Refactor

* Clean namespace
  • Loading branch information
ricksu978 committed Jan 19, 2024
1 parent c5e5bd8 commit 1e49735
Show file tree
Hide file tree
Showing 121 changed files with 545 additions and 893 deletions.
1 change: 0 additions & 1 deletion src/BackEnd/src/Application/Common/GameEventBus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using Wsa.Gaas.Werewolf.Domain.Common;

namespace Wsa.Gaas.Werewolf.Application.Common;

public class GameEventBus
{
private readonly IServiceScopeFactory _factory;
Expand Down
1 change: 0 additions & 1 deletion src/BackEnd/src/Application/Common/IGameEventHandler.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Wsa.Gaas.Werewolf.Domain.Common;

namespace Wsa.Gaas.Werewolf.Application.Common;

public interface IGameEventHandler
{
Task Handle(GameEvent events, CancellationToken cancellationToken = default);
Expand Down
1 change: 0 additions & 1 deletion src/BackEnd/src/Application/Common/IPresenter.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Wsa.Gaas.Werewolf.Domain.Common;

namespace Wsa.Gaas.Werewolf.Application.Common;

public interface IPresenter<TGameEvent>
where TGameEvent : GameEvent
{
Expand Down
1 change: 0 additions & 1 deletion src/BackEnd/src/Application/Common/IRepository.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Wsa.Gaas.Werewolf.Domain.Objects;

namespace Wsa.Gaas.Werewolf.Application.Common;

public interface IRepository
{
// 讀
Expand Down
1 change: 0 additions & 1 deletion src/BackEnd/src/Application/Common/Policy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using Wsa.Gaas.Werewolf.Domain.Common;

namespace Wsa.Gaas.Werewolf.Application.Common;

internal abstract class Policy<T> : IGameEventHandler<T>
where T : GameEvent
{
Expand Down
10 changes: 3 additions & 7 deletions src/BackEnd/src/Application/Common/UseCase.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
using Wsa.Gaas.Werewolf.Domain.Common;

namespace Wsa.Gaas.Werewolf.Application.Common;

public abstract class UseCase<TRequest, TGameEvent>
where TGameEvent : GameEvent
namespace Wsa.Gaas.Werewolf.Application.Common;
public abstract class UseCase<TRequest, TResponse>
{
protected IRepository Repository { get; }
protected GameEventBus GameEventBus { get; }
Expand All @@ -14,5 +10,5 @@ protected UseCase(IRepository repository, GameEventBus gameEventBus)
GameEventBus = gameEventBus;
}

public abstract Task ExecuteAsync(TRequest request, IPresenter<TGameEvent> presenter, CancellationToken cancellationToken = default);
public abstract Task<TResponse> ExecuteAsync(TRequest request, CancellationToken cancellationToken = default);
}
2 changes: 0 additions & 2 deletions src/BackEnd/src/Application/DependencyInjection.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Wsa.Gaas.Werewolf.Application.Common;

namespace Wsa.Gaas.Werewolf.Application;

public static class DependencyInjection
{
public static IServiceCollection AddWerewolfApplication(this IServiceCollection services)
Expand Down
8 changes: 8 additions & 0 deletions src/BackEnd/src/Application/Dtos/PlayerDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Wsa.Gaas.Werewolf.Application.Dtos;

public class PlayerDto
{
public ulong UserId { get; set; }
public int PlayerNumber { get; set; }
public string Role { get; set; } = null!;
}
3 changes: 3 additions & 0 deletions src/BackEnd/src/Application/GlobalUsing.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
global using Wsa.Gaas.Werewolf.Application.Common;
global using Wsa.Gaas.Werewolf.Domain.Events;
global using Wsa.Gaas.Werewolf.Domain.Exceptions;
1 change: 0 additions & 1 deletion src/BackEnd/src/Application/Options/GameSettingOptions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
namespace Wsa.Gaas.Werewolf.Application.Options;

public class GameSettingOptions
{
public TimeSpan PlayerRoleConfirmationTimer { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
using Microsoft.Extensions.Options;
using Wsa.Gaas.Werewolf.Application.Common;
using Wsa.Gaas.Werewolf.Application.Options;
using Wsa.Gaas.Werewolf.Domain.Events;
using Wsa.Gaas.Werewolf.Domain.Exceptions;

namespace Wsa.Gaas.Werewolf.Application.Policies;

internal class PlayerRoleConfirmationStartedPolicy : Policy<PlayerRoleConfirmationStartedEvent>
{
public PlayerRoleConfirmationStartedPolicy(
Expand Down
34 changes: 15 additions & 19 deletions src/BackEnd/src/Application/Policies/SeerRoundStartedEventPolicy.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
using Microsoft.Extensions.Options;
using Wsa.Gaas.Werewolf.Application.Common;
using Wsa.Gaas.Werewolf.Application.Options;
using Wsa.Gaas.Werewolf.Domain.Events;
using Wsa.Gaas.Werewolf.Domain.Exceptions;

namespace Wsa.Gaas.Werewolf.Application.Policies
namespace Wsa.Gaas.Werewolf.Application.Policies;
internal class SeerRoundStartedEventPolicy : Policy<SeerRoundStartedEvent>
{
internal class SeerRoundStartedEventPolicy : Policy<SeerRoundStartedEvent>
public SeerRoundStartedEventPolicy(IOptions<GameSettingOptions> options, IRepository repository, GameEventBus gameEventBus) : base(options, repository, gameEventBus)
{
public SeerRoundStartedEventPolicy(IOptions<GameSettingOptions> options, IRepository repository, GameEventBus gameEventBus) : base(options, repository, gameEventBus)
{
}
}

public override async Task Handle(SeerRoundStartedEvent gameEvent, CancellationToken cancellationToken = default)
{
// 30 seconds
await Task.Delay(Options.SeerRoundTimer, cancellationToken);
public override async Task Handle(SeerRoundStartedEvent gameEvent, CancellationToken cancellationToken = default)
{
// 30 seconds
await Task.Delay(Options.SeerRoundTimer, cancellationToken);

// 時間到 raise PlayerRoleConfirmationEndedEvent
var game = Repository.FindByDiscordChannelId(gameEvent.Data.DiscordVoiceChannelId)
?? throw new GameNotFoundException(gameEvent.Data.DiscordVoiceChannelId)
;
// 時間到 raise PlayerRoleConfirmationEndedEvent
var game = Repository.FindByDiscordChannelId(gameEvent.Data.DiscordVoiceChannelId)
?? throw new GameNotFoundException(gameEvent.Data.DiscordVoiceChannelId)
;

var @event = game.StartWitchAntidoteRound();
var @event = game.StartWitchAntidoteRound();

await GameEventBus.BroadcastAsync(@event, cancellationToken);
}
await GameEventBus.BroadcastAsync(@event, cancellationToken);
}
}

Original file line number Diff line number Diff line change
@@ -1,33 +1,29 @@
using Microsoft.Extensions.Options;
using Wsa.Gaas.Werewolf.Application.Common;
using Wsa.Gaas.Werewolf.Application.Options;
using Wsa.Gaas.Werewolf.Domain.Events;
using Wsa.Gaas.Werewolf.Domain.Exceptions;

namespace Wsa.Gaas.Werewolf.Application.Policies
namespace Wsa.Gaas.Werewolf.Application.Policies;
internal class WerewolfRoundStartedEventPolicy : Policy<WerewolfRoundStartedEvent>
{
internal class WerewolfRoundStartedEventPolicy : Policy<WerewolfRoundStartedEvent>
public WerewolfRoundStartedEventPolicy(
IOptions<GameSettingOptions> options,
IRepository repository,
GameEventBus gameEventBus
) : base(options, repository, gameEventBus)
{
public WerewolfRoundStartedEventPolicy(
IOptions<GameSettingOptions> options,
IRepository repository,
GameEventBus gameEventBus
) : base(options, repository, gameEventBus)
{
}
}

public override async Task Handle(WerewolfRoundStartedEvent gameEvent, CancellationToken cancellationToken = default)
{
await Task.Delay(Options.WerewolfRoundTimer, cancellationToken);
public override async Task Handle(WerewolfRoundStartedEvent gameEvent, CancellationToken cancellationToken = default)
{
await Task.Delay(Options.WerewolfRoundTimer, cancellationToken);

// 時間到 raise WerewolfRoundEndedEvent
var game = Repository.FindByDiscordChannelId(gameEvent.Data.DiscordVoiceChannelId)
?? throw new GameNotFoundException(gameEvent.Data.DiscordVoiceChannelId)
;
// 時間到 raise WerewolfRoundEndedEvent
var game = Repository.FindByDiscordChannelId(gameEvent.Data.DiscordVoiceChannelId)
?? throw new GameNotFoundException(gameEvent.Data.DiscordVoiceChannelId)
;

var @event = game.StartSeerRound();
var @event = game.StartSeerRound();

await GameEventBus.BroadcastAsync(@event, cancellationToken);
}
await GameEventBus.BroadcastAsync(@event, cancellationToken);
}
}

Original file line number Diff line number Diff line change
@@ -1,31 +1,27 @@
using Microsoft.Extensions.Options;
using Wsa.Gaas.Werewolf.Application.Common;
using Wsa.Gaas.Werewolf.Application.Options;
using Wsa.Gaas.Werewolf.Domain.Events;
using Wsa.Gaas.Werewolf.Domain.Exceptions;

namespace Wsa.Gaas.Werewolf.Application.Policies
namespace Wsa.Gaas.Werewolf.Application.Policies;
internal class WitchAntidoteRoundStartedEventPolicy : Policy<WitchAntidoteRoundStartedEvent>
{
internal class WitchAntidoteRoundStartedEventPolicy : Policy<WitchAntidoteRoundStartedEvent>
public WitchAntidoteRoundStartedEventPolicy(IOptions<GameSettingOptions> options, IRepository repository, GameEventBus gameEventBus) : base(options, repository, gameEventBus)
{
public WitchAntidoteRoundStartedEventPolicy(IOptions<GameSettingOptions> options, IRepository repository, GameEventBus gameEventBus) : base(options, repository, gameEventBus)
{
}
}

public override async Task Handle(WitchAntidoteRoundStartedEvent gameEvent, CancellationToken cancellationToken = default)
{
// 15 seconds
await Task.Delay(Options.WitchAntidoteRoundTimer, cancellationToken);
public override async Task Handle(WitchAntidoteRoundStartedEvent gameEvent, CancellationToken cancellationToken = default)
{
// 15 seconds
await Task.Delay(Options.WitchAntidoteRoundTimer, cancellationToken);

// 時間到
var game = Repository.FindByDiscordChannelId(gameEvent.Data.DiscordVoiceChannelId)
?? throw new GameNotFoundException(gameEvent.Data.DiscordVoiceChannelId)
;
// 時間到
var game = Repository.FindByDiscordChannelId(gameEvent.Data.DiscordVoiceChannelId)
?? throw new GameNotFoundException(gameEvent.Data.DiscordVoiceChannelId)
;

var @event = game.StartWitchPoisonRound();
var @event = game.StartWitchPoisonRound();

await GameEventBus.BroadcastAsync(@event, cancellationToken);
await GameEventBus.BroadcastAsync(@event, cancellationToken);

}
}
}

19 changes: 10 additions & 9 deletions src/BackEnd/src/Application/UseCases/ConfirmPlayerRoleUseCase.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
using Wsa.Gaas.Werewolf.Application.Common;
using Wsa.Gaas.Werewolf.Domain.Events;
using Wsa.Gaas.Werewolf.Domain.Exceptions;

namespace Wsa.Gaas.Werewolf.Application.UseCases;

namespace Wsa.Gaas.Werewolf.Application.UseCases;
public class ConfirmPlayerRoleRequest
{
public ulong DiscordVoiceChannelId { get; set; }
public ulong PlayerId { get; set; }
}

public class ConfirmPlayerRoleUseCase : UseCase<ConfirmPlayerRoleRequest, PlayerRoleConfirmedEvent>
public record ConfirmPlayerRoleResponse(string GameId, string PlayerId, string Role);

public class ConfirmPlayerRoleUseCase : UseCase<ConfirmPlayerRoleRequest, ConfirmPlayerRoleResponse>
{
public ConfirmPlayerRoleUseCase(IRepository repository, GameEventBus gameEventBus) : base(repository, gameEventBus)
{
}

public async override Task ExecuteAsync(ConfirmPlayerRoleRequest request, IPresenter<PlayerRoleConfirmedEvent> presenter, CancellationToken cancellationToken = default)
public async override Task<ConfirmPlayerRoleResponse> ExecuteAsync(ConfirmPlayerRoleRequest request, CancellationToken cancellationToken = default)
{
// Query
var game = await Repository.FindByDiscordChannelIdAsync(request.DiscordVoiceChannelId);
Expand All @@ -32,6 +29,10 @@ public async override Task ExecuteAsync(ConfirmPlayerRoleRequest request, IPrese
// Save

// Push
await presenter.PresentAsync(gameEvent, cancellationToken);
return new ConfirmPlayerRoleResponse(
gameEvent.Data.DiscordVoiceChannelId.ToString(),
gameEvent.PlayerId.ToString(),
gameEvent.Role
);
}
}
31 changes: 24 additions & 7 deletions src/BackEnd/src/Application/UseCases/CreateGameUseCase.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,41 @@
using Wsa.Gaas.Werewolf.Application.Common;
using Wsa.Gaas.Werewolf.Domain.Events;
using Wsa.Gaas.Werewolf.Domain.Exceptions;
using Wsa.Gaas.Werewolf.Application.Dtos;
using Wsa.Gaas.Werewolf.Domain.Common;
using Wsa.Gaas.Werewolf.Domain.Objects;

namespace Wsa.Gaas.Werewolf.Application.UseCases;

public class CreateGameRequest
{
public ulong DiscordVoiceChannelId { get; set; }
}

public class CreateGameUseCase : UseCase<CreateGameRequest, GameCreatedEvent>
public class CreateGameResponse
{
public CreateGameResponse(GameEvent gameEvent)
{
Id = gameEvent.Data.DiscordVoiceChannelId;
Players = gameEvent.Data.Players.Select(p => new PlayerDto
{
UserId = p.UserId,
Role = p.Role.Name,
PlayerNumber = p.PlayerNumber
}).ToList();
Status = gameEvent.Data.Status;
}

public ulong Id { get; set; }
public List<PlayerDto> Players { get; set; } = new List<PlayerDto>();
public GameStatus Status { get; set; }
}

public class CreateGameUseCase : UseCase<CreateGameRequest, CreateGameResponse>
{
private readonly static object _lock = new();

public CreateGameUseCase(IRepository repository, GameEventBus eventPublisher) : base(repository, eventPublisher)
{
}

public override async Task ExecuteAsync(CreateGameRequest request, IPresenter<GameCreatedEvent> presenter, CancellationToken cancellationToken = default)
public override async Task<CreateGameResponse> ExecuteAsync(CreateGameRequest request, CancellationToken cancellationToken = default)
{
Game? game;

Expand Down Expand Up @@ -46,6 +63,6 @@ public override async Task ExecuteAsync(CreateGameRequest request, IPresenter<Ga
await GameEventBus.BroadcastAsync(new[] { gameEvent }, cancellationToken);

// Restful API
await presenter.PresentAsync(gameEvent, cancellationToken);
return new CreateGameResponse(gameEvent);
}
}
22 changes: 12 additions & 10 deletions src/BackEnd/src/Application/UseCases/DiscoverPlayerRoleUseCase.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
using Wsa.Gaas.Werewolf.Application.Common;
using Wsa.Gaas.Werewolf.Domain.Events;
using Wsa.Gaas.Werewolf.Domain.Exceptions;

namespace Wsa.Gaas.Werewolf.Application.UseCases;

namespace Wsa.Gaas.Werewolf.Application.UseCases;
public class DiscoverPlayerRoleRequest
{
public ulong DiscordVoiceChannelId { get; set; }
public ulong PlayerId { get; set; }
public int DiscoverPlayerNumber { get; set; }
}

public class DiscoverPlayerRoleUseCase : UseCase<DiscoverPlayerRoleRequest, SeerDiscoveredEvent>
public record DiscoverPlayerRoleResponse(string GameId, string PlayerId, int DiscoveredPlayerNumber, string DiscoveredRoleFaction);

public class DiscoverPlayerRoleUseCase : UseCase<DiscoverPlayerRoleRequest, DiscoverPlayerRoleResponse>
{
public DiscoverPlayerRoleUseCase(IRepository repository, GameEventBus gameEventBus) : base(repository, gameEventBus)
{
}

public override async Task ExecuteAsync(DiscoverPlayerRoleRequest request, IPresenter<SeerDiscoveredEvent> presenter, CancellationToken cancellationToken = default)
public override async Task<DiscoverPlayerRoleResponse> ExecuteAsync(DiscoverPlayerRoleRequest request, CancellationToken cancellationToken = default)
{
// Query
var game = await Repository.FindByDiscordChannelIdAsync(request.DiscordVoiceChannelId);
Expand All @@ -28,11 +25,16 @@ public override async Task ExecuteAsync(DiscoverPlayerRoleRequest request, IPres
}

// Update
var seerDiscoveredEvent = game.DiscoverPlayerRole(request.PlayerId, request.DiscoverPlayerNumber);
var gameEvent = game.DiscoverPlayerRole(request.PlayerId, request.DiscoverPlayerNumber);

// Save

// Push
await presenter.PresentAsync(seerDiscoveredEvent, cancellationToken);
return new DiscoverPlayerRoleResponse(
gameEvent.Data.DiscordVoiceChannelId.ToString(),
gameEvent.PlayerId.ToString(),
gameEvent.DiscoveredPlayerNumber,
gameEvent.DiscoveredRoleFaction.ToString()
);
}
}
Loading

0 comments on commit 1e49735

Please sign in to comment.