Skip to content

Commit

Permalink
[F] Sort DSQ status (#228)
Browse files Browse the repository at this point in the history
* Add Sort option for status DSQ

* Fix tests

* Add test for default sort option
  • Loading branch information
SSchulze1989 authored Feb 3, 2025
1 parent 1c9801d commit 889edc0
Show file tree
Hide file tree
Showing 21 changed files with 102 additions and 38 deletions.
1 change: 1 addition & 0 deletions src/iRLeagueApiCore.Common/Enums/SortOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,5 @@ public enum SortOptions
RacesScoredDesc,
RacesInPointsAsc,
RacesInPointsDesc,
StatusDSQ,
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public sealed class RawResultRowModel
[DataMember]
public double Incidents { get; set; }
[DataMember]
public int Status { get; set; }
public RaceStatus Status { get; set; }
[DataMember]
public TimeSpan QualifyingTime { get; set; }
[DataMember]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public sealed class StandingResultRowModel
/// Driver status at the end of the race (checkered flag)
/// </summary>
[DataMember]
public int Status { get; set; }
public RaceStatus Status { get; set; }
/// <summary>
/// Irating before the event
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected async Task<ResultRowEntity> MapToResultRowEntity(ResultRowEntity entit
entity.LeadLaps = model.LeadLaps;
entity.FastLapNr = model.FastLapNr;
entity.Incidents = model.Incidents;
entity.Status = model.Status;
entity.Status = (int)model.Status;
entity.QualifyingTime = model.QualifyingTime;
entity.Interval = model.Interval;
entity.AvgLapTime = model.AvgLapTime;
Expand Down Expand Up @@ -89,7 +89,7 @@ protected static RawResultRowModel MapToModResultRowModel(RawResultRowModel mode
model.LeadLaps = entity.LeadLaps;
model.FastLapNr = entity.FastLapNr;
model.Incidents = entity.Incidents;
model.Status = entity.Status;
model.Status = (RaceStatus)entity.Status;
model.QualifyingTime = entity.QualifyingTime;
model.Interval = entity.Interval;
model.AvgLapTime = entity.AvgLapTime;
Expand Down Expand Up @@ -248,7 +248,7 @@ protected static RawResultRowModel MapToModResultRowModel(RawResultRowModel mode
LeadLaps = row.LeadLaps,
FastLapNr = row.FastLapNr,
Incidents = row.Incidents,
Status = row.Status,
Status = (RaceStatus)row.Status,
QualifyingTime = row.QualifyingTime,
Interval = row.Interval,
AvgLapTime = row.AvgLapTime,
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 iRLeagueApiCore.Common.Models.Standings;
using System.Linq.Expressions;

Expand Down Expand Up @@ -112,7 +113,7 @@ protected async Task<IEnumerable<StandingsModel>> AlignStandingResultRows(long s
RacePoints = standingResultRow.ScoredResultRow.RacePoints,
SeasonStartIrating = standingResultRow.ScoredResultRow.SeasonStartIRating,
StartPosition = standingResultRow.ScoredResultRow.StartPosition,
Status = standingResultRow.ScoredResultRow.Status,
Status = (RaceStatus)standingResultRow.ScoredResultRow.Status,
TotalPoints = standingResultRow.ScoredResultRow.TotalPoints,
IsScored = standingResultRow.IsScored,
}).ToList(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ internal abstract class CalculationPointRuleBase : PointRule<ResultRowCalculatio
public FilterGroupRowFilter<ResultRowCalculationResult> PointFilters { get; set; } = new();
public FilterGroupRowFilter<ResultRowCalculationResult> ChampSeasonFilters { get; set; } = new();
public FilterGroupRowFilter<ResultRowCalculationResult> ResultFilters { get; set; } = new();
public IEnumerable<SortOptions> PointSortOptions { get; set; } = Array.Empty<SortOptions>();
public IEnumerable<SortOptions> FinalSortOptions { get; set; } = Array.Empty<SortOptions>();
public IEnumerable<BonusPointConfiguration> BonusPoints { get; set; } = Array.Empty<BonusPointConfiguration>();
public IEnumerable<AutoPenaltyConfigurationData> AutoPenalties { get; set; } = Array.Empty<AutoPenaltyConfigurationData>();
public IEnumerable<SortOptions> PointSortOptions { get; set; } = [];
public IEnumerable<SortOptions> FinalSortOptions { get; set; } = [];
public IEnumerable<BonusPointConfiguration> BonusPoints { get; set; } = [];
public IEnumerable<AutoPenaltyConfigurationData> AutoPenalties { get; set; } = [];

public override FilterGroupRowFilter<ResultRowCalculationResult> GetResultFilters() => ResultFilters;
public override FilterGroupRowFilter<ResultRowCalculationResult> GetPointFilters() => PointFilters;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ internal static IEnumerable<ResultRowCalculationResult> CombineResults<T>(IEnume
row.PenaltyPoints += sessionRow.PenaltyPoints;
row.RacePoints += sessionRow.RacePoints;
row.PointsEligible |= sessionRow.PointsEligible;
row.Status = Math.Min(row.Status, sessionRow.Status);
row.Status = CombineRaceStatus(row.Status, sessionRow.Status);
}
// handle practice and qualy sessions separately
var otherSessions = group.Except(raceSessions);
Expand All @@ -154,6 +154,29 @@ internal static IEnumerable<ResultRowCalculationResult> CombineResults<T>(IEnume
return combined.ToList();
}

protected static RaceStatus CombineRaceStatus(params RaceStatus[] raceStatuses)
{
if (raceStatuses.Length == 0)
{
return RaceStatus.Unknown;
}

var currentStatus = raceStatuses[0];
foreach (var raceStatus in raceStatuses.Skip(1))
{
if (currentStatus == raceStatus)
{
continue;
}
if (currentStatus.GetRaceStatusOrderValue() <= raceStatus.GetRaceStatusOrderValue())
{
continue;
}
currentStatus = raceStatus;
}
return currentStatus;
}

private static AddPenaltyCalculationData CreateAddPenaltyFromReviewPenalty(ResultRowCalculationResult row, ReviewPenaltyCalculationResult reviewPenalty)
{
return new()
Expand Down Expand Up @@ -202,7 +225,7 @@ private static IEnumerable<ResultRowCalculationResult> ApplyAddPenaltyDsq(IEnume
{
foreach (var row in rows.Where(x => x.AddPenalties.Any(x => x.Type == PenaltyType.Disqualification)))
{
row.Status = (int)RaceStatus.Disqualified;
row.Status = RaceStatus.Disqualified;
}
return rows;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ private static IEnumerable<IComparable> GetFilterValuesOfType(Type type, IEnumer
{
return values.Select(x => TimeSpan.Parse(x)).Cast<IComparable>();
}
if (type.IsEnum)
{
return values.Select(x => Enum.Parse(type, x)).Cast<IComparable>();
}
return values.Select(x => Convert.ChangeType(x, type, CultureInfo.InvariantCulture)).Cast<IComparable>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ public override Task<SessionCalculationResult> Calculate(SessionCalculationData
teamRow.PenaltyPoints += memberRow.PenaltyPoints;
teamRow.PointsEligible |= memberRow.PointsEligible;
teamRow.AddPenalties = [.. teamRow.AddPenalties, .. memberRow.AddPenalties.Where(x => x.MemberId != null)];
teamRow.Status = CombineRaceStatus(teamRow.Status, memberRow.Status);
}
teamRow.StartPosition = teamMemberRows.Min(x => x.StartPosition);
(_, teamRow.QualifyingTime) = GetBestLapValue(teamMemberRows, x => x.MemberId, x => x.QualifyingTime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ private static EventCalculationData FillQualyLap(EventCalculationConfiguration c
return data;
}

private EventCalculationData FillFastestLapTimes(EventCalculationData data)
private static EventCalculationData FillFastestLapTimes(EventCalculationData data)
{
foreach (var sessionResult in data.SessionResults)
{
Expand Down Expand Up @@ -218,7 +218,7 @@ private static bool LapIsValid(TimeSpan lap)
RacePoints = row.RacePoints,
SeasonStartIrating = row.SeasonStartIRating,
StartPosition = row.StartPosition,
Status = row.Status,
Status = (RaceStatus)row.Status,
TotalPoints = row.RacePoints,
PointsEligible = row.PointsEligible,
CountryCode = row.CountryCode,
Expand Down Expand Up @@ -276,7 +276,7 @@ private static bool LapIsValid(TimeSpan lap)
PenaltyPoints = row.PenaltyPoints,
SeasonStartIrating = row.SeasonStartIRating,
StartPosition = row.StartPosition,
Status = row.Status,
Status = (RaceStatus)row.Status,
TotalPoints = row.RacePoints,
PointsEligible = row.PointsEligible,
PenaltyTime = row.PenaltyTime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ private async Task<ICollection<ScoredSessionResultEntity>> MapToScoredSessionRes
return sessionResultEntities;
}

private ScoredSessionResultEntity MapToScoredSessionResultEntity(SessionCalculationResult result, ScoredSessionResultEntity entity,
private static ScoredSessionResultEntity MapToScoredSessionResultEntity(SessionCalculationResult result, ScoredSessionResultEntity entity,
RequiredEntities requiredEntities)
{
entity.Name = result.Name;
Expand All @@ -88,7 +88,7 @@ private ScoredSessionResultEntity MapToScoredSessionResultEntity(SessionCalculat
return entity;
}

private ICollection<ScoredResultRowEntity> MapToScoredResultRows(IEnumerable<ResultRowCalculationResult> resultRows,
private static ICollection<ScoredResultRowEntity> MapToScoredResultRows(IEnumerable<ResultRowCalculationResult> resultRows,
ICollection<ScoredResultRowEntity> rowEntities, RequiredEntities requiredEntities)
{
var keepRows = new List<ScoredResultRowEntity>();
Expand Down Expand Up @@ -120,7 +120,7 @@ private ICollection<ScoredResultRowEntity> MapToScoredResultRows(IEnumerable<Res
return rowEntities;
}

private ScoredResultRowEntity MaptoScoredResultRow(ResultRowCalculationResult row, ScoredResultRowEntity rowEntity,
private static ScoredResultRowEntity MaptoScoredResultRow(ResultRowCalculationResult row, ScoredResultRowEntity rowEntity,
RequiredEntities requiredEntities)
{
rowEntity.Member = requiredEntities.Members.FirstOrDefault(x => x.Id == row.MemberId);
Expand Down Expand Up @@ -162,7 +162,7 @@ private ScoredResultRowEntity MaptoScoredResultRow(ResultRowCalculationResult ro
rowEntity.ReviewPenalties = MapToReviewPenaltyList(row, rowEntity.ReviewPenalties, requiredEntities);
rowEntity.SeasonStartIRating = row.SeasonStartIrating;
rowEntity.StartPosition = row.StartPosition;
rowEntity.Status = row.Status;
rowEntity.Status = (int)row.Status;
rowEntity.TotalPoints = row.TotalPoints;
rowEntity.TeamResultRows = requiredEntities.ScoredResultRows
.Where(x => row.ScoredMemberResultRowIds.Contains(x.ScoredResultRowId)).ToList();
Expand All @@ -172,7 +172,7 @@ private ScoredResultRowEntity MaptoScoredResultRow(ResultRowCalculationResult ro
return rowEntity;
}

private ICollection<ReviewPenaltyEntity> MapToReviewPenaltyList(ResultRowCalculationResult row, ICollection<ReviewPenaltyEntity> penaltyEntities,
private static ICollection<ReviewPenaltyEntity> MapToReviewPenaltyList(ResultRowCalculationResult row, ICollection<ReviewPenaltyEntity> penaltyEntities,
RequiredEntities requiredEntities)
{
foreach (var penalty in row.ReviewPenalties)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,17 @@ private static PointRule<ResultRowCalculationResult> GetPointRuleFromEntity(Poin
pointRule.PointFilters = CreatePointsEligibleFilter();
}

// Move dsq drivers to bottom by default
pointRule.PointSortOptions = [SortOptions.StatusDSQ, .. pointRule.PointSortOptions];

// Add normal status filter for Disqualified drivers, when status is not explicitly filtered already.
var hasStatusPointFilter = configurationEntity.PointFilters.Any(x => x.Conditions.Any(y => y.ColumnPropertyName == nameof(ResultRowCalculationResult.Status)));
if (hasStatusPointFilter == false)
{
var statusFilter = (FilterCombination.And, new ColumnValueRowFilter(
propertyName: nameof(ResultRowCalculationResult.Status),
comparatorType: ComparatorType.IsEqual,
values: [((int)RaceStatus.Disqualified).ToString()],
values: [RaceStatus.Disqualified.ToString()],
action: MatchedValueAction.Remove) as RowFilter<ResultRowCalculationResult>);
pointRule.PointFilters = new FilterGroupRowFilter<ResultRowCalculationResult>(
pointRule.PointFilters.GetFilters().Concat([statusFilter]));
Expand Down Expand Up @@ -211,7 +214,7 @@ private static FilterGroupRowFilter<ResultRowCalculationResult> MapFromFilterEnt
return MapToFilterGroup(pointFilters.Select(x => x.Conditions.FirstOrDefault()));
}

private static IReadOnlyDictionary<int, T> PointsPerPlaceToDictionary<T>(IEnumerable<T> points)
private static Dictionary<int, T> PointsPerPlaceToDictionary<T>(IEnumerable<T> points)
{
return points
.Select((x, i) => new { pos = i + 1, value = x })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ private async Task<IEnumerable<EventCalculationResult>> GetPreviousResultsAsync(
RacePoints = row.RacePoints,
SeasonStartIrating = row.SeasonStartIRating,
StartPosition = row.StartPosition,
Status = row.Status,
Status = (RaceStatus)row.Status,
TotalPoints = row.RacePoints,
BonusPoints = row.BonusPoints,
ClubName = row.ClubName,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace iRLeagueApiCore.Services.ResultService.Extensions;
using iRLeagueApiCore.Common.Enums;

namespace iRLeagueApiCore.Services.ResultService.Extensions;

public static class CalculationExtensions
{
Expand Down Expand Up @@ -28,4 +30,13 @@ public static IEnumerable<TValue> GetMultiple<TKey, TValue>(this IDictionary<TKe
.Where(x => keys.Contains(x.Key))
.Select(x => x.Value);
}

public static int GetRaceStatusOrderValue(this RaceStatus raceStatus) => raceStatus switch
{
RaceStatus.Running => 0,
RaceStatus.Disconnected => 1,
RaceStatus.Disqualified => 2,
RaceStatus.Unknown => 3,
_ => 99,
};
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using iRLeagueApiCore.Common.Enums;
using iRLeagueApiCore.Services.ResultService.Models;
using Mysqlx.Resultset;

namespace iRLeagueApiCore.Services.ResultService.Extensions;

Expand Down Expand Up @@ -37,6 +38,7 @@ public static Func<T, object> GetSortingValue<T>(this SortOptions sortOption) wh
SortOptions.TotalPtsWoBonusDesc => row => -(row.RacePoints - row.PenaltyPoints),
SortOptions.TotalPtsWoPenaltyAsc => row => row.RacePoints + row.BonusPoints,
SortOptions.TotalPtsWoPenaltyDesc => row => -(row.RacePoints + row.BonusPoints),
SortOptions.StatusDSQ => row => row.Status == RaceStatus.Disqualified ? 1 : 0,
_ => row => 0,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ internal class ResultRowCalculationData : IPointRow, IPenaltyRow
public double LeadLaps { get; set; }
public int FastLapNr { get; set; }
public double Incidents { get; set; }
public int Status { get; set; }
public RaceStatus Status { get; set; }
public TimeSpan QualifyingTime { get; set; }
public TimeSpan Interval { get; set; }
public TimeSpan AvgLapTime { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ public async Task Calculate_ShouldApplyDsqPenalty()
const int rowCount = 3;
var data = GetCalculationData();
data.ResultRows = TestRowBuilder()
.With(x => x.Status, (int)RaceStatus.Running)
.With(x => x.Status, RaceStatus.Running)
.CreateMany(rowCount);
var addPenalty = fixture.Build<AddPenaltyCalculationData>()
.With(x => x.Type, PenaltyType.Disqualification)
Expand All @@ -673,7 +673,7 @@ public async Task Calculate_ShouldApplyDsqPenalty()
var test = await sut.Calculate(data);

var testResultRow = test.ResultRows.First(x => x.ScoredResultRowId == penaltyRow.ScoredResultRowId);
testResultRow.Status.Should().Be((int)RaceStatus.Disqualified);
testResultRow.Status.Should().Be(RaceStatus.Disqualified);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ public async Task Calculate_ShouldApplyTeamPenalties(PenaltyType penaltyType)
testRow.FinalPosition.Should().Be(position + penalty.Positions);
break;
case PenaltyType.Disqualification:
testRow.Status.Should().Be((int)RaceStatus.Disqualified);
testRow.Status.Should().Be(RaceStatus.Disqualified);
break;
default:
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ public async Task GetData_ShouldProvideResultRowData()
testRow.LeadLaps.Should().Be(compareRow.LeadLaps);
testRow.FastLapNr.Should().Be(compareRow.FastLapNr);
testRow.Incidents.Should().Be(compareRow.Incidents);
testRow.Status.Should().Be(compareRow.Status);
testRow.Status.Should().Be((RaceStatus)compareRow.Status);
testRow.QualifyingTime.Should().Be(compareRow.QualifyingTime);
testRow.Interval.Should().Be(compareRow.Interval);
testRow.AvgLapTime.Should().Be(compareRow.AvgLapTime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ public async Task StoreCalculationResult_ShouldStoreResultRowData()
testRow.LeadLaps.Should().Be(compareRow.LeadLaps);
testRow.FastLapNr.Should().Be(compareRow.FastLapNr);
testRow.Incidents.Should().Be(compareRow.Incidents);
testRow.Status.Should().Be(compareRow.Status);
testRow.Status.Should().Be((int)compareRow.Status);
testRow.QualifyingTime.Should().Be(compareRow.QualifyingTime);
testRow.Interval.Should().Be(compareRow.Interval);
testRow.AvgLapTime.Should().Be(compareRow.AvgLapTime);
Expand Down
Loading

0 comments on commit 889edc0

Please sign in to comment.