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

Refactor/presenter #72

Merged
merged 2 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
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