Skip to content

Commit

Permalink
Merge branch 'next' into test
Browse files Browse the repository at this point in the history
  • Loading branch information
sei-bstein committed Dec 4, 2024
2 parents 46749c5 + 2f28682 commit 49d10b8
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,24 @@ namespace Gameboard.Api.Features.Certificates;

public record GetCompetitiveModeCertificateHtmlQuery(string GameId, string OwnerUserId, string ActingUserId) : IRequest<string>;

internal class GetCompetitiveModeCertificateHtmlHandler : IRequestHandler<GetCompetitiveModeCertificateHtmlQuery, string>
internal class GetCompetitiveModeCertificateHtmlHandler
(
EntityExistsValidator<GetCompetitiveModeCertificateHtmlQuery, Data.Game> gameExists,
PlayerService playerService,
IStore store,
IValidatorService<GetCompetitiveModeCertificateHtmlQuery> validatorService
) : IRequestHandler<GetCompetitiveModeCertificateHtmlQuery, string>
{
private readonly EntityExistsValidator<GetCompetitiveModeCertificateHtmlQuery, Data.Game> _gameExists;
private readonly PlayerService _playerService;
private readonly IStore _store;
private readonly IValidatorService<GetCompetitiveModeCertificateHtmlQuery> _validatorService;

public GetCompetitiveModeCertificateHtmlHandler
(
EntityExistsValidator<GetCompetitiveModeCertificateHtmlQuery, Data.Game> gameExists,
PlayerService playerService,
IStore store,
IValidatorService<GetCompetitiveModeCertificateHtmlQuery> validatorService
)
{
_gameExists = gameExists;
_playerService = playerService;
_store = store;
_validatorService = validatorService;
}
private readonly EntityExistsValidator<GetCompetitiveModeCertificateHtmlQuery, Data.Game> _gameExists = gameExists;
private readonly PlayerService _playerService = playerService;
private readonly IStore _store = store;
private readonly IValidatorService<GetCompetitiveModeCertificateHtmlQuery> _validatorService = validatorService;

public async Task<string> Handle(GetCompetitiveModeCertificateHtmlQuery request, CancellationToken cancellationToken)
{
var isPublished = await _store
.WithNoTracking<PublishedCompetitiveCertificate>()
.AnyAsync(c => c.GameId == request.GameId && c.OwnerUserId == request.OwnerUserId);
.AnyAsync(c => c.GameId == request.GameId && c.OwnerUserId == request.OwnerUserId, cancellationToken);

await _validatorService
.AddValidator(_gameExists.UseProperty(r => r.GameId))
Expand All @@ -54,7 +46,7 @@ await _validatorService
.WithNoTracking<Data.Player>()
.Where(p => p.UserId == request.OwnerUserId)
.Where(p => p.GameId == request.GameId)
.FirstAsync();
.FirstAsync(cancellationToken);

var certificate = await _playerService.MakeCertificate(player.Id);
return certificate.Html;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,12 @@ await _validatorService
.Validate(request, cancellationToken);

if (certificate is null)
{
throw new ResourceNotFound<PublishedPracticeCertificate>(request.ChallengeSpecId, $"Couldn't resolve a certificate for owner {request.CertificateOwnerUserId} and challenge spec {request.ChallengeSpecId}");
}

// load the outer template from this application (this is custom crafted by us to ensure we end up)
// with a consistent HTML-compliant base
// load the outer template from this application (this is custom crafted by us to ensure we end up
// with a consistent HTML-compliant base)
var outerTemplatePath = Path.Combine(_coreOptions.TemplatesDirectory, "practice-certificate.template.html");
var outerTemplate = File.ReadAllText(outerTemplatePath);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,22 @@ public interface IChallengeSyncService
/// <summary>
/// Used by the Job service to update challenges which have expired
/// </summary>
internal class ChallengeSyncService : IChallengeSyncService
internal class ChallengeSyncService
(
ConsoleActorMap consoleActorMap,
IGameEngineService gameEngine,
ILogger<IChallengeSyncService> logger,
IMapper mapper,
INowService now,
IStore store
) : IChallengeSyncService
{
private readonly ConsoleActorMap _consoleActorMap;
private readonly IGameEngineService _gameEngine;
private readonly ILogger<IChallengeSyncService> _logger;
private readonly IMapper _mapper;
private readonly INowService _now;
private readonly IStore _store;

public ChallengeSyncService
(
ConsoleActorMap consoleActorMap,
IGameEngineService gameEngine,
ILogger<IChallengeSyncService> logger,
IMapper mapper,
INowService now,
IStore store
)
{
_consoleActorMap = consoleActorMap;
_logger = logger;
_gameEngine = gameEngine;
_mapper = mapper;
_now = now;
_store = store;
}
private readonly ConsoleActorMap _consoleActorMap = consoleActorMap;
private readonly IGameEngineService _gameEngine = gameEngine;
private readonly ILogger<IChallengeSyncService> _logger = logger;
private readonly IMapper _mapper = mapper;
private readonly INowService _now = now;
private readonly IStore _store = store;

public Task Sync(Data.Challenge challenge, GameEngineGameState state, string actingUserId, CancellationToken cancellationToken)
=> Sync(cancellationToken, new SyncEntry(actingUserId, challenge, state));
Expand Down Expand Up @@ -104,7 +94,7 @@ public async Task SyncExpired(CancellationToken cancellationToken)
.Where(p => playerIds.Contains(p.Id))
.ToDictionaryAsync(p => p.Id, p => p.SessionEnd, cancellationToken);

_logger.LogInformation($"The ChallengeSyncService is synchronizing {challenges.Count()} challenges...");
_logger.LogInformation("The ChallengeSyncService is synchronizing {syncCount} challenges...", challenges.Count());
foreach (var challenge in challenges)
{
try
Expand Down
5 changes: 5 additions & 0 deletions src/Gameboard.Api/Features/ChallengeSpec/ChallengeSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ public sealed class ChallengeSpecSummary
public required IEnumerable<string> Tags { get; set; }
}

public sealed class ChallengeSpecSectionPerformance
{
public required string Text { get; set; }
}

public sealed class ChallengeSpecQuestionPerformance
{
public required int QuestionRank { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@
namespace Gameboard.Api.Controllers;

[Authorize]
public class ChallengeSpecController(
public class ChallengeSpecController
(
IActingUserService actingUserService,
ILogger<ChallengeSpecController> logger,
IDistributedCache cache,
IMediator mediator,
ChallengeSpecValidator validator,
ChallengeSpecService challengespecService,
IUserRolePermissionsService permissionsService
) : GameboardLegacyController(actingUserService, logger, cache, validator)
) : GameboardLegacyController(actingUserService, logger, cache, validator)
{
private readonly IMediator _mediator = mediator;
private readonly IUserRolePermissionsService _permissionsService = permissionsService;
Expand Down
10 changes: 7 additions & 3 deletions src/Gameboard.Api/Features/ChallengeSpec/ChallengeSpecService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,6 @@ public async Task<IEnumerable<GameChallengeSpecs>> ListByGame()
public async Task<IOrderedEnumerable<ChallengeSpecQuestionPerformance>> GetQuestionPerformance(string challengeSpecId, CancellationToken cancellationToken)
{
var results = await GetQuestionPerformance([challengeSpecId], cancellationToken);
if (!results.Any())
throw new ArgumentException($"Couldn't load performance for specId {challengeSpecId}", nameof(challengeSpecId));

return results[challengeSpecId];
}
Expand Down Expand Up @@ -151,7 +149,13 @@ public async Task<IDictionary<string, IOrderedEnumerable<ChallengeSpecQuestionPe
// because of topo architecture, we can't tell the caller anything about the challenge unless it's been attempted
// at least once
if (data is null || !data.Values.Any(v => v.Any()))
return null;
{
return challengeSpecIds.ToDictionary
(
specId => specId,
specId => Array.Empty<ChallengeSpecQuestionPerformance>().OrderBy(c => c.CountCorrect)
);
}

// deserialize states
var questionPerformance = new Dictionary<string, IOrderedEnumerable<ChallengeSpecQuestionPerformance>>();
Expand Down
2 changes: 1 addition & 1 deletion src/Gameboard.Api/Features/Game/GameService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ public async Task<UploadedFile> SaveGameCardImage(string gameId, IFormFile file)
var fileName = $"{GetGameCardFileNameBase(gameId)}{Path.GetExtension(file.FileName.ToLower())}";
var path = Path.Combine(Options.ImageFolder, fileName);

using var stream = new FileStream(path, FileMode.Create);
using var stream = new FileStream(path, FileMode.OpenOrCreate);
await file.CopyToAsync(stream);
await UpdateImage(gameId, "card", fileName);

Expand Down
4 changes: 2 additions & 2 deletions src/Gameboard.Api/Features/Player/Services/PlayerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ private PlayerCertificate CertificateFromTemplate(Data.Player player, int player
certificateHTML = certificateHTML.Replace("{{player_count}}", playerCount.ToString());
certificateHTML = certificateHTML.Replace("{{team_count}}", teamCount.ToString());

return new Api.PlayerCertificate
return new PlayerCertificate
{
Game = _mapper.Map<Game>(player.Game),
PublishedOn = player.User.PublishedCompetitiveCertificates.FirstOrDefault(c => c.GameId == player.Game.Id)?.PublishedOn,
Expand Down Expand Up @@ -726,7 +726,7 @@ private async Task<Player> RegisterPracticeSession(NewPlayer model, Data.User us
{
int count = await _store
.WithNoTracking<Data.Player>()
.CountAsync<Data.Player>
.CountAsync
(
p =>
p.Mode == PlayerMode.Practice &&
Expand Down

0 comments on commit 49d10b8

Please sign in to comment.