Skip to content

Commit

Permalink
refactor: game UI
Browse files Browse the repository at this point in the history
  • Loading branch information
ricksu978 committed Jul 10, 2023
1 parent 7a11ca7 commit 07ed20b
Show file tree
Hide file tree
Showing 36 changed files with 348 additions and 427 deletions.
21 changes: 10 additions & 11 deletions src/BackEnd/src/Application/Common/GameEventBus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,12 @@ public class GameEventBus
{
private readonly IServiceScopeFactory _factory;

#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
protected GameEventBus() { }
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.

public GameEventBus(IServiceScopeFactory facotry)
{
_factory = facotry;
}

public virtual Task BroadcastAsync<T>(T gameEvent, CancellationToken cancellationToken = default)
public virtual Task BroadcastAsync<T>(IEnumerable<T> gameEvents, CancellationToken cancellationToken = default)
where T : GameEvent
{
// Run this in sparate Thread
Expand All @@ -27,19 +23,22 @@ public virtual Task BroadcastAsync<T>(T gameEvent, CancellationToken cancellatio
// Trigger Handlers
// 1. Game Event Hub Handler
// Game Event Hub Handler
var handler = provider.GetRequiredService<IGameEventHandler>();
await handler.Handle(gameEvent, cancellationToken);
// 2. Policies
if (provider.GetService<Policy<T>>() is Policy<T> policy)
foreach (var gameEvent in gameEvents)
{
await policy.ExecuteAsync(gameEvent, cancellationToken);
await handler.Handle(gameEvent, cancellationToken);
}
}, cancellationToken);

return Task.CompletedTask;
}

public virtual Task BroadcastAsync<T>(T gameEvent, CancellationToken cancellationToken = default)
where T : GameEvent
{
return BroadcastAsync(new[] { gameEvent }, cancellationToken);
}
}
}
2 changes: 1 addition & 1 deletion src/BackEnd/src/Application/Common/IGameEventHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ namespace Wsa.Gaas.Werewolf.Application.Common
{
public interface IGameEventHandler
{
Task Handle(GameEvent gameEvent, CancellationToken cancellationToken = default);
Task Handle(GameEvent events, CancellationToken cancellationToken = default);
}
}
1 change: 1 addition & 0 deletions src/BackEnd/src/Application/Common/IRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public interface IRepository
// 讀
Task<Game?> FindByIdAsync(Guid id);
Task<Game?> FindByDiscordChannelIdAsync(ulong discordChannelId);
Game? FindByDiscordChannelId(ulong discordChannelId);
IQueryable<Game> FindAll();

// 存
Expand Down
19 changes: 0 additions & 19 deletions src/BackEnd/src/Application/Common/Policy.cs

This file was deleted.

20 changes: 0 additions & 20 deletions src/BackEnd/src/Application/DependencyInjection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ public static IServiceCollection AddWerewolfApplication(this IServiceCollection
// Inject Use Cases
services.AddUseCases();

// Inject Policies
services.AddPolicies();

// GameEvenPublisher
services.AddScoped<GameEventBus>();

Expand All @@ -36,22 +33,5 @@ private static IServiceCollection AddUseCases(this IServiceCollection services)

return services;
}

private static IServiceCollection AddPolicies(this IServiceCollection services)
{
var assembly = typeof(DependencyInjection).Assembly;
var types = assembly.GetTypes();
var policyType = typeof(Policy<>);

foreach (var type in types)
{
if (type.BaseType?.IsGenericType == true && type.BaseType?.GetGenericTypeDefinition() == policyType)
{
services.AddScoped(type.BaseType, type);
}
}

return services;
}
}
}
33 changes: 0 additions & 33 deletions src/BackEnd/src/Application/Policies/GameStartedPolicy.cs

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ public async override Task ExecuteAsync(ConfirmPlayerRoleRequest request, IPrese

// Save


// Push
await GameEventBus.BroadcastAsync(gameEvent, cancellationToken);
await presenter.PresentAsync(gameEvent, cancellationToken);
}
}
Expand Down
11 changes: 4 additions & 7 deletions src/BackEnd/src/Application/UseCases/CreateGameUseCase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,14 @@ public CreateGameUseCase(IRepository repository, GameEventBus eventPublisher) :

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

lock (_lock)
{
// Query
var anyExistingActiveGame = Repository.FindAll()
.Where(x => x.DiscordVoiceChannelId == request.DiscordVoiceChannelId)
.Where(x => x.Status != GameStatus.Ended)
.Any();
game = Repository.FindByDiscordChannelId(request.DiscordVoiceChannelId);

if (anyExistingActiveGame)
if (game != null)
{
throw new GameChannelException();
}
Expand All @@ -46,7 +43,7 @@ public override async Task ExecuteAsync(CreateGameRequest request, IPresenter<Ga
var gameEvent = new GameCreatedEvent(game);

// SignalR
await GameEventBus.BroadcastAsync(gameEvent, cancellationToken);
await GameEventBus.BroadcastAsync(new[] { gameEvent }, cancellationToken);

// Restful API
await presenter.PresentAsync(gameEvent, cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Wsa.Gaas.Werewolf.Application.Common;
using Wsa.Gaas.Werewolf.Domain.Events;
using Wsa.Gaas.Werewolf.Domain.Exceptions;
using Wsa.Gaas.Werewolf.Domain.Objects;

namespace Wsa.Gaas.Werewolf.Application.UseCases
{
Expand All @@ -28,20 +27,8 @@ public override async Task ExecuteAsync(DiscoverPlayerRoleRequest request, IPres
throw new GameNotFoundException(request.DiscordVoiceChannelId);
}

var discoverPlayer = Repository.FindAll().Where(x => x.DiscordVoiceChannelId == request.DiscordVoiceChannelId)
.Where(x => x.Status == GameStatus.SeerRoundStarted)
.SelectMany(y => y.Players)
.Where(y => y.IsDead == false)
.Where(y => y.PlayerNumber == request.DiscoverPlayerNumber)
.FirstOrDefault();

if (discoverPlayer == null)
{
throw new PlayerNotSurvivedException(request.DiscoverPlayerNumber);
}

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

// Save

Expand Down
20 changes: 3 additions & 17 deletions src/BackEnd/src/Application/UseCases/EndGameUseCase.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wsa.Gaas.Werewolf.Application.Common;
using Wsa.Gaas.Werewolf.Domain.Common;
using Wsa.Gaas.Werewolf.Application.Common;
using Wsa.Gaas.Werewolf.Domain.Events;
using Wsa.Gaas.Werewolf.Domain.Exceptions;
using Wsa.Gaas.Werewolf.Domain.Objects;
Expand All @@ -28,23 +22,15 @@ public override async Task ExecuteAsync(EndGameRequest request, IPresenter<GameE
{
Game? game;
lock (_lock)
{
{
// 查
game = Repository.FindAll()
.Where(x => x.DiscordVoiceChannelId == request.DiscordVoiceChannelId)
//.Where(x => x.Status != GameStatus.Ended)
.FirstOrDefault();
game = Repository.FindByDiscordChannelId(request.DiscordVoiceChannelId);

if (game == null)
{
throw new GameNotFoundException(request.DiscordVoiceChannelId);
}

if (game.Status == GameStatus.Ended)
{
throw new GameAlreadyEndedException(request.DiscordVoiceChannelId);
}

game.EndGame();

Repository.Save(game);
Expand Down
18 changes: 9 additions & 9 deletions src/BackEnd/src/Application/UseCases/StartGameUseCase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Wsa.Gaas.Werewolf.Application.Common;
using Wsa.Gaas.Werewolf.Domain.Common;
using Wsa.Gaas.Werewolf.Domain.Events;
using Wsa.Gaas.Werewolf.Domain.Exceptions;
using Wsa.Gaas.Werewolf.Domain.Objects;
Expand All @@ -23,34 +24,33 @@ public StartGameUseCase(IRepository repository, GameEventBus eventPublisher) : b
public override async Task ExecuteAsync(StartGameRequest request, IPresenter<GameStartedEvent> presenter, CancellationToken cancellationToken = default)
{
Game? game;
GameStartedEvent? gameEvent;
IEnumerable<GameEvent> events;

lock (_lock)
{
// 查
game = Repository
.FindByDiscordChannelIdAsync(request.DiscordVoiceChannelId)
.GetAwaiter()
.GetResult()
;
game = Repository.FindByDiscordChannelId(request.DiscordVoiceChannelId);

if (game == null)
{
throw new GameNotFoundException(request.DiscordVoiceChannelId);
}

// 改
gameEvent = game.StartGame(request.Players);
events = game.StartGame(request.Players);

// 存
Repository.Save(game);
}

// SignalR
await GameEventBus.BroadcastAsync(gameEvent, cancellationToken);
await GameEventBus.BroadcastAsync(events, cancellationToken);

// Restful API
await presenter.PresentAsync(gameEvent, cancellationToken);
await presenter.PresentAsync(
(GameStartedEvent)events.First(x => x is GameStartedEvent),
cancellationToken
);
}
}

Expand Down
Loading

0 comments on commit 07ed20b

Please sign in to comment.