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

v 0.10.0 #179

Merged
merged 19 commits into from
Oct 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
12 changes: 12 additions & 0 deletions src/iRLeagueApiCore.Client/Endpoints/Cars/CarsEndpoint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using iRLeagueApiCore.Client.Http;
using iRLeagueApiCore.Client.QueryBuilder;
using iRLeagueApiCore.Common.Models.Results;

namespace iRLeagueApiCore.Client.Endpoints.Cars;
internal sealed class CarsEndpoint : GetEndpoint<CarListModel>, ICarsEndpoint
{
public CarsEndpoint(HttpClientWrapper httpClient, RouteBuilder routeBuilder) : base(httpClient, routeBuilder)
{
RouteBuilder.AddEndpoint("Cars");
}
}
6 changes: 6 additions & 0 deletions src/iRLeagueApiCore.Client/Endpoints/Cars/ICarsEndpoint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using iRLeagueApiCore.Common.Models.Results;

namespace iRLeagueApiCore.Client.Endpoints.Cars;
public interface ICarsEndpoint : IGetEndpoint<CarListModel>
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using Microsoft.AspNetCore.Mvc;

namespace iRLeagueApiCore.Client.Endpoints.Penalties;
internal sealed class PenaltiesEndpoint : EndpointBase, IPenaltiesEndpoint, IGetAllEndpoint<PenaltyModel>, IPostEndpoint<PenaltyModel, PostPenaltyModel>
internal sealed class PenaltiesEndpoint : EndpointBase, IPenaltiesEndpoint, IGetAllEndpoint<PenaltyModel>
{
public PenaltiesEndpoint(HttpClientWrapper httpClient, RouteBuilder routeBuilder)
: base(httpClient, routeBuilder)
Expand All @@ -22,9 +22,4 @@ async Task<ClientActionResult<IEnumerable<PenaltyModel>>> IGetEndpoint<IEnumerab
{
return await HttpClientWrapper.GetAsClientActionResult<IEnumerable<PenaltyModel>>(QueryUrl, cancellationToken);
}

async Task<ClientActionResult<PenaltyModel>> IPostEndpoint<PenaltyModel, PostPenaltyModel>.Post(PostPenaltyModel model, CancellationToken cancellationToken)
{
return await HttpClientWrapper.PostAsClientActionResult<PenaltyModel>(QueryUrl, model, cancellationToken);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using iRLeagueApiCore.Client.Endpoints.Members;
using iRLeagueApiCore.Client.Endpoints.Cars;
using iRLeagueApiCore.Client.Endpoints.Members;
using iRLeagueApiCore.Client.Endpoints.Protests;
using iRLeagueApiCore.Client.Endpoints.Results;
using iRLeagueApiCore.Client.Endpoints.Reviews;
using iRLeagueApiCore.Client.Endpoints.Standings;
using iRLeagueApiCore.Client.Http;
using iRLeagueApiCore.Client.QueryBuilder;
using iRLeagueApiCore.Common.Models;
using iRLeagueApiCore.Common.Models.Results;
using iRLeagueApiCore.Common.Models.Reviews;
using iRLeagueApiCore.Common.Models.Standings;

Expand All @@ -24,6 +26,11 @@ public IGetAllEndpoint<MemberModel> Members()
return new MembersEndpoint(HttpClientWrapper, RouteBuilder);
}

public IGetEndpoint<CarListModel> Cars()
{
return new CarsEndpoint(HttpClientWrapper, RouteBuilder);
}

IGetAllEndpoint<ProtestModel> IEventByIdEndpoint.Protests()
{
return new ProtestsEndpoint(HttpClientWrapper, RouteBuilder);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using iRLeagueApiCore.Client.Endpoints.Results;
using iRLeagueApiCore.Common.Models;
using iRLeagueApiCore.Common.Models.Results;
using iRLeagueApiCore.Common.Models.Reviews;
using iRLeagueApiCore.Common.Models.Standings;

Expand All @@ -12,4 +13,5 @@ public interface IEventByIdEndpoint : IUpdateEndpoint<EventModel, PutEventModel>
IGetAllEndpoint<MemberModel> Members();
IGetAllEndpoint<StandingsModel> Standings();
IGetAllEndpoint<ProtestModel> Protests();
IGetEndpoint<CarListModel> Cars();
}
4 changes: 2 additions & 2 deletions src/iRLeagueApiCore.Client/iRLeagueApiCore.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup />

<ItemGroup>
<PackageReference Include="iRLeagueApiCore.Common" Version="0.9.3" />
<PackageReference Include="iRLeagueApiCore.Common" Version="0.10.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.10.0" />
Expand All @@ -13,7 +13,7 @@
<OutputType>Library</OutputType>
<TargetFrameworks>net6.0</TargetFrameworks>
<PackageId>iRLeagueApiCore.Client</PackageId>
<Version>0.9.5</Version>
<Version>0.10.0</Version>
<Authors>Simon Schulze</Authors>
<Company>Simon Schulze</Company>
<PackageDescription>This package contains shared objects for all members of the iRLeagueDatabase-iRLeagueApi stack</PackageDescription>
Expand Down
32 changes: 32 additions & 0 deletions src/iRLeagueApiCore.Server/Controllers/CarsController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using iRLeagueApiCore.Common.Models.Results;
using iRLeagueApiCore.Server.Filters;
using iRLeagueApiCore.Server.Handlers.Cars;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace iRLeagueApiCore.Server.Controllers;

/// <summary>
/// Endpoint for retrieving information about cars
/// </summary>
[Authorize]
[TypeFilter(typeof(LeagueAuthorizeAttribute))]
[TypeFilter(typeof(SetTenantLeagueIdAttribute))]
[Route("{leagueName}/[controller]")]
public class CarsController : LeagueApiController<CarsController>
{
public CarsController(ILogger<CarsController> logger, IMediator mediator) : base(logger, mediator)
{
}

[HttpGet]
[Route("/{leagueName}/Events/{eventId:long}/[controller]")]
[AllowAnonymous]
public async Task<ActionResult<CarListModel>> Get([FromRoute] string leagueName, [FromRoute] long eventId,
CancellationToken cancellationToken)
{
var request = new GetCarsFromEventRequest(eventId);
var getMembers = await mediator.Send(request, cancellationToken);
return Ok(getMembers);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ namespace iRLeagueApiCore.Server.Controllers;
[Authorize]
[TypeFilter(typeof(LeagueAuthorizeAttribute))]
[TypeFilter(typeof(SetTenantLeagueIdAttribute))]
[RequireLeagueRole]
[Route("{leagueName}/[controller]")]
public sealed class MembersController : LeagueApiController<MembersController>
{
Expand Down
6 changes: 3 additions & 3 deletions src/iRLeagueApiCore.Server/Controllers/PenaltiesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ public async Task<ActionResult<IEnumerable<PenaltyModel>>> GetPenaltiesFromEvent
}

[HttpPost]
[Route("/{leagueName}/ScoredSessionResults/{resultId:long}/Drivers/{memberId:long}/[controller]")]
public async Task<ActionResult<PenaltyModel>> PostPenaltyToResult([FromRoute] string leagueName, [FromRoute] long resultId, [FromRoute] long memberId,
[Route("/{leagueName}/ScoredSessionResults/{resultId:long}/Rows/{resultRowId:long}/[controller]")]
public async Task<ActionResult<PenaltyModel>> PostPenaltyToResult([FromRoute] string leagueName, [FromRoute] long resultId, [FromRoute] long resultRowId,
[FromBody] PostPenaltyModel postPenalty, CancellationToken cancellationToken)
{
var request = new PostPenaltyToResultRequest(resultId, memberId, postPenalty);
var request = new PostPenaltyToResultRequest(resultId, resultRowId, postPenalty);
var result = await mediator.Send(request, cancellationToken);
return Ok(result);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public async Task<ActionResult> DeleteFromEvent([FromRoute] string leagueName, [
CancellationToken cancellationToken = default)
{
var request = new DeleteResultRequest(eventId);
var getResults = await mediator.Send(request, cancellationToken);
await mediator.Send(request, cancellationToken);
return NoContent();
}

Expand Down
1 change: 0 additions & 1 deletion src/iRLeagueApiCore.Server/Controllers/TeamsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ namespace iRLeagueApiCore.Server.Controllers;
[Authorize]
[TypeFilter(typeof(LeagueAuthorizeAttribute))]
[TypeFilter(typeof(SetTenantLeagueIdAttribute))]
[RequireLeagueRole]
[Route("{leagueName}/[controller]")]
public sealed class TeamsController : LeagueApiController<TeamsController>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using iRLeagueApiCore.Common.Models;
using iRLeagueApiCore.Common.Models.Results;
using iRLeagueApiCore.Services.ResultService.Extensions;
using System.Linq.Expressions;

namespace iRLeagueApiCore.Server.Handlers.Cars;

public record GetCarsFromEventRequest(long EventId) : IRequest<CarListModel>;

public class GetCarsFromEventHandler : HandlerBase<GetCarsFromEventHandler, GetCarsFromEventRequest>,
IRequestHandler<GetCarsFromEventRequest, CarListModel>
{
public GetCarsFromEventHandler(ILogger<GetCarsFromEventHandler> logger, LeagueDbContext dbContext, IEnumerable<IValidator<GetCarsFromEventRequest>> validators) :
base(logger, dbContext, validators)
{
}

public async Task<CarListModel> Handle(GetCarsFromEventRequest request, CancellationToken cancellationToken)
{
await validators.ValidateAllAndThrowAsync(request, cancellationToken).ConfigureAwait(false);
var eventCars = (await GetEventCarsPerMemberAsync(request.EventId, cancellationToken));
var groupedCars = eventCars
.GroupBy(x => new { x.Number, x.Team?.TeamId })
.Select(x => new EventCarInfoModel()
{
Number = x.First().Number,
Car = x.First().Car,
CarId = x.First().CarId,
Class = x.First().Class,
Members = x.SelectMany(x => x.Members),
Team = x.First().Team,
});
bool isTeamEvent = groupedCars.Any(x => x.Members.Count() > 1) && groupedCars.None(x => x.Team == null);
return new CarListModel()
{
IsTeamEvent = isTeamEvent,
Cars = isTeamEvent ? groupedCars : eventCars,
};
}

private async Task<IEnumerable<EventCarInfoModel>> GetEventCarsPerMemberAsync(long eventId, CancellationToken cancellationToken)
{
var memberCarRows = await dbContext.EventResults
.Where(x => x.EventId == eventId)
.SelectMany(x => x.SessionResults)
.SelectMany(x => x.ResultRows)
.Select(MapToCarInfoModelExpression)
.ToListAsync(cancellationToken);
return memberCarRows
.DistinctBy(x => x.MemberId)
.Select(x => x.EventCar);
}

private static Expression<Func<ResultRowEntity, MemberCarInfo>> MapToCarInfoModelExpression => row => new(
row.MemberId,
new() {
Car = row.Car,
CarId = row.CarId,
Class = row.CarClass,
Members = new[] { new MemberInfoModel()
{
MemberId = row.MemberId,
FirstName = row.Member.Firstname,
LastName = row.Member.Lastname,
}
},
Team = row.Team == null ? default : new()
{
TeamId = row.Team.TeamId,
Name = row.Team.Name,
TeamColor = row.Team.TeamColor,
},
Number = row.CarNumber,
}
);

private record MemberCarInfo(long MemberId, EventCarInfoModel EventCar);
}
13 changes: 13 additions & 0 deletions src/iRLeagueApiCore.Server/Handlers/HandlerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ protected HandlerBase(ILogger<THandler> logger, LeagueDbContext dbContext, IEnum
.FirstOrDefaultAsync(x => x.Id == memberId, cancellationToken);
}

protected virtual async Task<TeamEntity?> GetTeamEntityAsync(long? teamId, CancellationToken cancellationToken = default)
{
return await dbContext.Teams
.FirstOrDefaultAsync(x => x.TeamId == teamId, cancellationToken);
}

protected virtual async Task<VoteCategoryEntity?> GetVoteCategoryEntityAsync(long leagueId, long? voteCategoryId, CancellationToken cancellationToken = default)
{
return await dbContext.VoteCategories
Expand All @@ -73,6 +79,13 @@ protected virtual async Task<ICollection<MemberEntity>> GetMemberListAsync(IEnum
.ToListAsync(cancellationToken);
}

protected virtual async Task<ICollection<TeamEntity>> GetTeamListAsync(IEnumerable<long> teamIds, CancellationToken cancellationToken)
{
return await dbContext.Teams
.Where(x => teamIds.Contains(x.TeamId))
.ToListAsync(cancellationToken);
}

/// <summary>
/// Returns a utc date time from the provided datetime without performin a conversion
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@ private async Task<IEnumerable<MemberModel>> GetMembersFromEvent(long eventId, C
var resultMembers = await dbContext.EventResults
.Where(x => x.EventId == eventId)
.Select(x => x.SessionResults
.SelectMany(y => y.ResultRows)
.Select(y => y.MemberId))
.SelectMany(y => y.ResultRows)
.Select(y => y.MemberId))
.SelectMany(x => x!)
.ToListAsync(cancellationToken)
?? throw new ResourceNotFoundException();
.ToListAsync(cancellationToken);
var scoredResultMembers = await dbContext.ScoredEventResults
.Where(x => x.EventId == eventId)
.Select(x => x.ScoredSessionResults
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ private async Task<ResultRowEntity> ReadResultRowAsync(long leagueId, SubSession
//row.Car = FIXME is this data important??
row.CarClass = sessionData.CarClasses.FirstOrDefault(x => x.CarClassId == data.CarClassId)?.ShortName ?? string.Empty;
row.CarId = data.CarId;
row.CarNumber = int.TryParse(data.Livery.CarNumber, out int carNumber) ? carNumber : -1; // Todo: change to string!
row.CarNumber = data.Livery.CarNumber ?? string.Empty;
row.ClassId = data.CarClassId;
row.ClubId = data.ClubId;
row.ClubName = data.ClubName;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using iRLeagueApiCore.Common.Models;
using iRLeagueApiCore.Common.Enums;
using iRLeagueApiCore.Common.Models;
using System.Linq.Expressions;

namespace iRLeagueApiCore.Server.Handlers.Results;
Expand Down Expand Up @@ -41,6 +42,7 @@ protected async Task<IEnumerable<EventResultModel>> MapToGetResultModelsFromEven
.OrderBy(x => x.FinalPosition)
.Select(row => new ResultRowModel()
{
ScoredResultRowId = row.ScoredResultRowId,
MemberId = row.MemberId,
Interval = new Interval(row.Interval),
FastestLapTime = row.FastestLapTime,
Expand Down Expand Up @@ -79,7 +81,7 @@ protected async Task<IEnumerable<EventResultModel>> MapToGetResultModelsFromEven
PositionChange = row.PositionChange,
QualifyingTime = row.QualifyingTime,
SeasonStartIrating = row.SeasonStartIRating,
Status = row.Status,
Status = (RaceStatus)row.Status,
TeamId = row.TeamId,
TeamColor = (row.Team != null) ? row.Team.TeamColor : string.Empty,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ private async Task<ResultRowEntity> ReadResultRowAsync(long leagueId, ParseSimSe
Car = data.car_name,
CarClass = sessionData.car_classes.FirstOrDefault(x => x.car_class_id == data.car_class_id)?.short_name ?? string.Empty,
CarId = data.car_id,
CarNumber = int.TryParse(data.livery.car_number, out int carNumber) ? carNumber : -1, // Todo: change to string!
CarNumber = data.livery.car_number ?? string.Empty,
ClassId = data.car_class_id,
ClubId = data.club_id,
ClubName = data.club_name,
Expand Down
15 changes: 11 additions & 4 deletions src/iRLeagueApiCore.Server/Handlers/Reviews/CommentHandlerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public CommentHandlerBase(ILogger<THandler> logger, LeagueDbContext dbContext, I
return await dbContext.ReviewComments
.Include(x => x.ReviewCommentVotes)
.Where(x => x.CommentId == commentId)
.FirstOrDefaultAsync();
.FirstOrDefaultAsync(cancellationToken: cancellationToken);
}

protected virtual async Task<ReviewCommentEntity> MapToReviewCommentEntityAsync(LeagueUser user, PostReviewCommentModel postComment,
Expand All @@ -39,7 +39,8 @@ protected virtual async Task<ReviewCommentVoteEntity> MapToCommentVoteEntityAsyn
{
voteEntity.Description = voteModel.Description;
voteEntity.MemberAtFault = await GetMemberEntityAsync(voteModel.MemberAtFault?.MemberId, cancellationToken);
voteEntity.VoteCategory = await GetVoteCategoryEntityAsync(voteEntity.LeagueId, voteModel.VoteCategoryId);
voteEntity.TeamAtFault = await GetTeamEntityAsync(voteModel.TeamAtFault?.TeamId, cancellationToken);
voteEntity.VoteCategory = await GetVoteCategoryEntityAsync(voteEntity.LeagueId, voteModel.VoteCategoryId, cancellationToken);
return voteEntity;
}

Expand Down Expand Up @@ -91,12 +92,18 @@ protected virtual async Task<ICollection<ReviewCommentVoteEntity>> MapCommentVot
Description = vote.Description,
VoteCategoryId = vote.VoteCategoryId.GetValueOrDefault(),
VoteCategoryText = vote.VoteCategory.Text,
MemberAtFault = vote.MemberAtFault == null ? null : new MemberInfoModel()
MemberAtFault = vote.MemberAtFault == null ? default : new()
{
MemberId = vote.MemberAtFault.Id,
FirstName = vote.MemberAtFault.Firstname,
LastName = vote.MemberAtFault.Lastname
}
},
TeamAtFault = vote.TeamAtFault == null ? default : new()
{
TeamId = vote.TeamAtFault.TeamId,
Name = vote.TeamAtFault.Name,
TeamColor = vote.TeamAtFault.TeamColor,
},
}).ToList(),
CreatedByUserId = comment.CreatedByUserId,
CreatedByUserName = comment.CreatedByUserName,
Expand Down
Loading