Skip to content

Commit

Permalink
Merge pull request #188 from SSchulze1989/develop
Browse files Browse the repository at this point in the history
v 0.11.3
  • Loading branch information
SSchulze1989 authored Feb 27, 2024
2 parents 2b5782a + 4d95476 commit 067caad
Show file tree
Hide file tree
Showing 23 changed files with 363 additions and 44 deletions.
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.11.0" />
<PackageReference Include="iRLeagueApiCore.Common" Version="0.11.1" />
<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="7.3.1" />
Expand All @@ -13,7 +13,7 @@
<OutputType>Library</OutputType>
<TargetFrameworks>net6.0</TargetFrameworks>
<PackageId>iRLeagueApiCore.Client</PackageId>
<Version>0.11.2</Version>
<Version>0.11.3</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
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,15 @@ private async Task<ScoringEntity> MapToScoringEntityAsync(LeagueUser user, Scori
private async Task<PointRuleEntity> MapToPointRuleEntityAsync(LeagueUser user, PointRuleModel pointRuleModel, PointRuleEntity pointRuleEntity,
CancellationToken cancellationToken)
{
pointRuleEntity.RuleType = pointRuleModel.RuleType;
pointRuleEntity.BonusPoints = pointRuleModel.BonusPoints;
pointRuleEntity.FinalSortOptions = pointRuleModel.FinalSortOptions;
pointRuleEntity.MaxPoints = pointRuleModel.MaxPoints;
pointRuleEntity.Name = pointRuleModel.Name;
pointRuleEntity.PointDropOff = pointRuleModel.PointDropOff;
pointRuleEntity.PointsPerPlace = pointRuleModel.PointsPerPlace;
pointRuleEntity.PointsSortOptions = pointRuleModel.PointsSortOptions;
pointRuleEntity.Formula = pointRuleModel.Formula;
pointRuleEntity.AutoPenalties = await MapToAutoPenaltyCollection(pointRuleModel.AutoPenalties, pointRuleEntity.AutoPenalties, cancellationToken);
UpdateVersionEntity(user, pointRuleEntity);
return pointRuleEntity;
Expand Down Expand Up @@ -220,6 +222,7 @@ protected virtual async Task<ResultConfigurationEntity> MapToResultConfigEntityA
UseSourcePoints = scoring.UseExternalSourcePoints,
PointRule = scoring.PointsRule != null ? new PointRuleModel()
{
RuleType = scoring.PointsRule.RuleType,
BonusPoints = scoring.PointsRule.BonusPoints,
FinalSortOptions = scoring.PointsRule.FinalSortOptions,
LeagueId = scoring.LeagueId,
Expand All @@ -229,6 +232,7 @@ protected virtual async Task<ResultConfigurationEntity> MapToResultConfigEntityA
PointsPerPlace = scoring.PointsRule.PointsPerPlace.ToList(),
PointsSortOptions = scoring.PointsRule.PointsSortOptions,
Name = scoring.PointsRule.Name,
Formula = scoring.PointsRule.Formula,
AutoPenalties = scoring.PointsRule.AutoPenalties.Select(penalty => new AutoPenaltyConfiguration()
{
Conditions = penalty.Conditions,
Expand Down
6 changes: 3 additions & 3 deletions src/iRLeagueApiCore.Server/iRLeagueApiCore.Server.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
<PackageReference Include="Aydsko.iRacingData" Version="2303.0.0" />
<PackageReference Include="FluentValidation" Version="11.0.1" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.0.1" />
<PackageReference Include="iRLeagueApiCore.Common" Version="0.11.0" CopyToOutputDirectory="lib/net6.0">
<PackageReference Include="iRLeagueApiCore.Common" Version="0.11.1" CopyToOutputDirectory="lib/net6.0">
</PackageReference>
<PackageReference Include="iRLeagueDatabaseCore" Version="0.11.0" />
<PackageReference Include="iRLeagueDatabaseCore" Version="0.11.1" />
<PackageReference Include="MediatR" Version="10.0.1" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="10.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.9" />
Expand Down Expand Up @@ -72,7 +72,7 @@

<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Version>0.11.2</Version>
<Version>0.11.3</Version>
<Nullable>enable</Nullable>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ protected static IEnumerable<ResultRowCalculationResult> ApplyPoints(IEnumerable
pointRows = pointRule.GetPointFilters().FilterRows(pointRows);

// Calculation
pointRule.ApplyPoints(pointRows.ToList());
pointRule.ApplyPoints(data, pointRows.ToList());
// remove points from filtered rows and set points eligible
pointRows.ForEach(x => x.PointsEligible = true);
rows.Except(pointRows)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal class DefaultPointRule<TRow> : PointRule<TRow> where TRow : IPointRow,

public override IEnumerable<AutoPenaltyConfigurationData> GetAutoPenalties() => Array.Empty<AutoPenaltyConfigurationData>();

public override IReadOnlyList<T> ApplyPoints<T>(IReadOnlyList<T> rows)
public override IReadOnlyList<T> ApplyPoints<T>(SessionCalculationData _, IReadOnlyList<T> rows)
{
foreach (var row in rows)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using iRLeagueApiCore.Services.ResultService.Models;

namespace iRLeagueApiCore.Services.ResultService.Calculation;
internal record FormulaParameter(string[] Aliases, string Description, Func<SessionCalculationData, ResultRowCalculationData, double> valueFunc);

public static class FormulaParameters
{
internal static IEnumerable<FormulaParameter> Parameters { get; } = new List<FormulaParameter>()
{
new(["pos", "position"], "Finish position", (_, row) => row.FinishPosition),
new(["start", "start_position"], "Starting position", (_, row) => row.StartPosition),
new(["irating"], "Irating at the start of the session", (_, row) => row.OldIrating),
new(["sof", "strength_of_field"], "SOF - Strength of field (Irating)", (session, _) => session.Sof),
new(["count", "driver_count"], "Number of drivers/teams in the result", (session, _) => session.ResultRows.Count()),
new(["flap", "fastest_lap"], "Personal fastest lap", (_, row) => row.FastestLapTime.TotalSeconds),
new(["qlap", "qualy_lap"], "Personal qualy lap", (_, row) => row.QualifyingTime.TotalSeconds),
new(["avglap", "avg_lap"], "Personal avg. lap", (_, row) => row.AvgLapTime.TotalSeconds),
new(["flapsession", "session_fastest_lap"], "Fastest lap in the session", (session, _) => session.FastestLap.TotalSeconds),
new(["qlapsession", "session_fastest_qualy_lap"], "Fastest qualy lap in the session", (session, _) => session.FastestQualyLap.TotalSeconds),
new(["avglapsession", "session_fastest_avg_lap"], "Fastest avg. lap in the session", (session, _) => session.FastestAvgLap.TotalSeconds),
};

internal static IDictionary<string, FormulaParameter> ParameterDict => Parameters
.SelectMany(x => x.Aliases.Select(y => (name: y, parameter: x)))
.ToDictionary(k => k.name, v => v.parameter);

public static IEnumerable<(string[] aliases, string description)> ParameterInfo => Parameters.Select(x => (x.Aliases, x.Description));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

using iRLeagueApiCore.Services.ResultService.Models;
using MySqlX.XDevAPI.Relational;
using NCalc;

namespace iRLeagueApiCore.Services.ResultService.Calculation;
internal class FormulaPointRule : CalculationPointRuleBase
{
public string Formula { get; }
public bool AllowNegativePoints { get; }
private static IDictionary<string, FormulaParameter> _parameters = FormulaParameters.ParameterDict;

public FormulaPointRule(string formula, bool allowNegativePoints)
{
Formula = formula;
AllowNegativePoints = allowNegativePoints;
}

public override IReadOnlyList<T> ApplyPoints<T>(SessionCalculationData session, IReadOnlyList<T> rows)
{
// prepare parameters
var e = new NCalc.Expression(Formula, EvaluateOptions.IterateParameters);
foreach (var (key, parameter) in _parameters)
{
e.Parameters[key] = rows.Select(row => parameter.valueFunc.Invoke(session, row)).ToArray();
}
// calculate
if (e.Evaluate() is not IList<object> points)
{
return rows;
}
// assign points to rows
foreach (var (row, rowPoints) in rows.Zip(points))
{
row.RacePoints = Convert.ToDouble(rowPoints);
if (!AllowNegativePoints)
{
row.RacePoints = Math.Max(row.RacePoints, 0);
}
}
return rows;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace iRLeagueApiCore.Services.ResultService.Calculation;
using iRLeagueApiCore.Services.ResultService.Models;

namespace iRLeagueApiCore.Services.ResultService.Calculation;

internal sealed class MaxPointRule : CalculationPointRuleBase
{
Expand All @@ -11,7 +13,7 @@ public MaxPointRule(int maxPoints, int dropOff)
DropOff = dropOff;
}

public override IReadOnlyList<T> ApplyPoints<T>(IReadOnlyList<T> rows)
public override IReadOnlyList<T> ApplyPoints<T>(SessionCalculationData _, IReadOnlyList<T> rows)
{
foreach ((var row, var pos) in rows.Select((x, i) => (x, i + 1)))
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace iRLeagueApiCore.Services.ResultService.Calculation;
using iRLeagueApiCore.Services.ResultService.Models;

namespace iRLeagueApiCore.Services.ResultService.Calculation;

internal sealed class PerPlacePointRule : CalculationPointRuleBase
{
Expand All @@ -9,7 +11,7 @@ public PerPlacePointRule(IReadOnlyDictionary<int, double> pointPerPlace)
PointsPerPlace = pointPerPlace;
}

public override IReadOnlyList<T> ApplyPoints<T>(IReadOnlyList<T> rows)
public override IReadOnlyList<T> ApplyPoints<T>(SessionCalculationData _, IReadOnlyList<T> rows)
{
foreach ((var row, var pos) in rows.Select((x, i) => (x, i + 1)))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ internal abstract class PointRule<TRow> where TRow : IPointRow, IPenaltyRow
public abstract IEnumerable<AutoPenaltyConfigurationData> GetAutoPenalties();
public abstract IEnumerable<BonusPointConfiguration> GetBonusPoints();
public abstract IReadOnlyList<T> SortForPoints<T>(IEnumerable<T> rows) where T : TRow;
public abstract IReadOnlyList<T> ApplyPoints<T>(IReadOnlyList<T> rows) where T : TRow;
public abstract IReadOnlyList<T> ApplyPoints<T>(SessionCalculationData session, IReadOnlyList<T> rows) where T : TRow;
public abstract IReadOnlyList<T> SortFinal<T>(IEnumerable<T> rows) where T : TRow;

private readonly static DefaultPointRule<TRow> defaultPointRule = new();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
namespace iRLeagueApiCore.Services.ResultService.Calculation;
using iRLeagueApiCore.Services.ResultService.Models;

namespace iRLeagueApiCore.Services.ResultService.Calculation;

internal sealed class UseResultPointsPointRule : CalculationPointRuleBase
{
public override IReadOnlyList<T> ApplyPoints<T>(IReadOnlyList<T> rows)
public override IReadOnlyList<T> ApplyPoints<T>(SessionCalculationData _, IReadOnlyList<T> rows)
{
return rows;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public EventCalculationDataProvider(LeagueDbContext dbContext) :

data = await AssociatePenalties(config, data, cancellationToken);
// Fill Qualy lap
data = FillQualyLapTime(config, data);
data = FillQualyLap(config, data);
data = FillFastestLapTimes(data);
return data;
}

Expand All @@ -51,7 +52,7 @@ public EventCalculationDataProvider(LeagueDbContext dbContext) :
/// <param name="config"></param>
/// <param name="data"></param>
/// <returns></returns>
private static EventCalculationData FillQualyLapTime(EventCalculationConfiguration config, EventCalculationData data)
private static EventCalculationData FillQualyLap(EventCalculationConfiguration config, EventCalculationData data)
{
// find driver qualy laps
var qualySessionNr = config.SessionResultConfigurations.FirstOrDefault(x => x.SessionType == Common.Enums.SessionType.Qualifying)?.SessionNr;
Expand Down Expand Up @@ -83,6 +84,29 @@ private static EventCalculationData FillQualyLapTime(EventCalculationConfigurati
return data;
}

private EventCalculationData FillFastestLapTimes(EventCalculationData data)
{
foreach (var sessionResult in data.SessionResults)
{
sessionResult.FastestLap = sessionResult.ResultRows
.Select(x => x.FastestLapTime)
.Where(LapIsValid)
.OrderBy(x => x)
.FirstOrDefault();
sessionResult.FastestQualyLap = sessionResult.ResultRows
.Select(x => x.QualifyingTime)
.Where(LapIsValid)
.OrderBy(x => x)
.FirstOrDefault();
sessionResult.FastestAvgLap = sessionResult.ResultRows
.Select(x => x.AvgLapTime)
.Where(LapIsValid)
.OrderBy(x => x)
.FirstOrDefault();
}
return data;
}

private async Task<EventCalculationData> AssociatePenalties(EventCalculationConfiguration config, EventCalculationData data, CancellationToken cancellationToken)
{
// get existing scoredresultrows
Expand Down Expand Up @@ -111,6 +135,11 @@ private async Task<EventCalculationData> AssociatePenalties(EventCalculationConf
return data;
}

private static bool LapIsValid(TimeSpan lap)
{
return lap > TimeSpan.Zero;
}

private static Expression<Func<EventResultEntity, EventCalculationData>> MapToEventResultCalculationDataExpression => eventResult => new EventCalculationData()
{
LeagueId = eventResult.LeagueId,
Expand All @@ -132,6 +161,7 @@ private async Task<EventCalculationData> AssociatePenalties(EventCalculationConf
VoteCategoryId = vote.VoteCategoryId,
ReviewVoteId = vote.ReviewVoteId,
}),
Sof = sessionResult.IRSimSessionDetails == null ? 0 : sessionResult.IRSimSessionDetails.EventStrengthOfField,
ResultRows = sessionResult.ResultRows.Select(row => new ResultRowCalculationData()
{
ScoredResultRowId = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ private async Task<IEnumerable<SessionCalculationConfiguration>> DefaultSessionR
SessionId = x.SessionId,
SessionNr = x.SessionNr,
UseResultSetTeam = false,
MaxResultsPerGroup = (configurationEntity?.ResultsPerTeam is null or <=0) ? int.MaxValue : configurationEntity.ResultsPerTeam,
MaxResultsPerGroup = (configurationEntity?.ResultsPerTeam is null or <= 0) ? int.MaxValue : configurationEntity.ResultsPerTeam,
Name = x.Name,
UpdateTeamOnRecalculation = false,
ResultKind = configurationEntity?.ChampSeason.ResultKind ?? ResultKind.Member,
Expand Down Expand Up @@ -125,19 +125,13 @@ private static PointRule<ResultRowCalculationResult> GetPointRuleFromEntity(Poin
{
CalculationPointRuleBase pointRule;

if (pointsRuleEntity?.PointsPerPlace.Any() == true)
pointRule = pointsRuleEntity switch
{
pointRule = new PerPlacePointRule(PointsPerPlaceToDictionary<double>(pointsRuleEntity.PointsPerPlace
.Select(x => (double)x)));
}
else if (pointsRuleEntity?.MaxPoints > 0)
{
pointRule = new MaxPointRule(pointsRuleEntity.MaxPoints, pointsRuleEntity.PointDropOff);
}
else
{
pointRule = new UseResultPointsPointRule();
}
var rule when rule?.RuleType == PointRuleType.PointList && rule.PointsPerPlace.Any() => new PerPlacePointRule(PointsPerPlaceToDictionary(rule.PointsPerPlace.Select(x => (double)x))),
var rule when rule?.RuleType == PointRuleType.MaxPointsDropOff && rule.MaxPoints > 0 => new MaxPointRule(rule.MaxPoints, rule.PointDropOff),
var rule when rule?.RuleType == PointRuleType.Formula && string.IsNullOrEmpty(rule.Formula) == false => new FormulaPointRule(rule.Formula, false),
_ => new UseResultPointsPointRule()
};

pointRule.PointSortOptions = pointsRuleEntity?.PointsSortOptions ?? Array.Empty<SortOptions>();
pointRule.FinalSortOptions = pointsRuleEntity?.FinalSortOptions ?? Array.Empty<SortOptions>();
Expand All @@ -159,9 +153,9 @@ private static PointRule<ResultRowCalculationResult> GetPointRuleFromEntity(Poin
if (hasStatusPointFilter == false)
{
var statusFilter = (FilterCombination.And, new ColumnValueRowFilter(
nameof(ResultRowCalculationResult.Status),
ComparatorType.IsEqual,
new[] { ((int)RaceStatus.Disqualified).ToString() },
nameof(ResultRowCalculationResult.Status),
ComparatorType.IsEqual,
new[] { ((int)RaceStatus.Disqualified).ToString() },
MatchedValueAction.Remove) as RowFilter<ResultRowCalculationResult>);
pointRule.PointFilters = new FilterGroupRowFilter<ResultRowCalculationResult>(
pointRule.PointFilters.GetFilters().Concat(new[] { statusFilter }));
Expand Down Expand Up @@ -198,12 +192,12 @@ private static AutoPenaltyConfigurationData MapFromAutoPenaltyConfig(AutoPenalty

private static FilterGroupRowFilter<ResultRowCalculationResult> CreatePointsEligibleFilter() => new(
new (FilterCombination, RowFilter<ResultRowCalculationResult>)[] {
(FilterCombination.And, new ColumnValueRowFilter(nameof(ResultRowCalculationResult.PointsEligible), ComparatorType.IsEqual,
(FilterCombination.And, new ColumnValueRowFilter(nameof(ResultRowCalculationResult.PointsEligible), ComparatorType.IsEqual,
new[] { true.ToString() }, MatchedValueAction.Keep))
}
);

private static FilterGroupRowFilter<ResultRowCalculationResult> MapFromFilterEntities(ICollection<FilterConditionModel> pointFilters,
private static FilterGroupRowFilter<ResultRowCalculationResult> MapFromFilterEntities(ICollection<FilterConditionModel> pointFilters,
bool allowForEach = false, FilterCombination? overrideFilterCombination = null)
{
return MapToFilterGroup(pointFilters, allowForEach: allowForEach, overrideFilterCombination: overrideFilterCombination);
Expand Down Expand Up @@ -249,7 +243,7 @@ private static FilterGroupRowFilter<ResultRowCalculationResult> MapToFilterGroup
{
return condition?.FilterType switch
{
FilterType.ColumnProperty => new ColumnValueRowFilter(condition.ColumnPropertyName, condition.Comparator,
FilterType.ColumnProperty => new ColumnValueRowFilter(condition.ColumnPropertyName, condition.Comparator,
condition.FilterValues, condition.Action, allowForEach: allowForEach),
FilterType.Member => new IdRowFilter<long>(condition.FilterValues, x => x.MemberId.GetValueOrDefault(), condition.Action),
FilterType.Team => new IdRowFilter<long>(condition.FilterValues, x => x.TeamId.GetValueOrDefault(), condition.Action),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ internal sealed class SessionCalculationData
public long LeagueId { get; set; }
public long? SessionId { get; set; }
public int? SessionNr { get; set; }
public int Sof { get; set; }
public TimeSpan FastestLap { get; set; }
public TimeSpan FastestQualyLap { get; set; }
public TimeSpan FastestAvgLap { get; set; }
public IEnumerable<AcceptedReviewVoteCalculationData> AcceptedReviewVotes { get; set; } = Array.Empty<AcceptedReviewVoteCalculationData>();
public IEnumerable<ResultRowCalculationData> ResultRows { get; set; } = Array.Empty<ResultRowCalculationData>();
}
Loading

0 comments on commit 067caad

Please sign in to comment.