WineQualityStatistics: Add and fix grouping by KMW

This commit is contained in:
2024-03-30 15:21:02 +01:00
parent 869f652afc
commit 27b5d653e6
5 changed files with 110 additions and 24 deletions

View File

@ -9,8 +9,8 @@ using System.Threading.Tasks;
namespace Elwig.Models.Dtos {
public class WineQualityStatisticsData {
public record struct QualityRow(string? Variety, string? Attribute, string? Cultivation, string? Type, string QualId, double Grad, int Num, int Weight);
public record struct QualitySection(string Name, string? Type, Dictionary<string, (double Grad, int Num, int Weight)[]> Data);
public record struct QualityRow(string? Variety, string? Attribute, string? Cultivation, string? Type, string QualId, double AvgKmw, double Grad, int Num, int Weight);
public record struct QualitySection(string Name, string? Type, Dictionary<string, (double Grad, double AvgKmw, int Num, int Weight)[]> Data);
public bool UseOe = true;
public QualitySection[] Sections;
@ -21,8 +21,8 @@ namespace Elwig.Models.Dtos {
private static QualitySection[] GetQualitySections(IEnumerable<QualityRow> rows) {
var data = new List<QualitySection>();
var currentQual = new Dictionary<double, (int Num, int Weight)>();
var current = new Dictionary<string, (double, int, int)[]>();
var currentQual = new Dictionary<double, (double AvgKmw, int Num, int Weight)>();
var current = new Dictionary<string, (double, double, int, int)[]>();
string? lastSection = null;
string? lastType = null;
string? lastQual = null;
@ -31,25 +31,25 @@ namespace Elwig.Models.Dtos {
$"{(row.Attribute != null ? " / " : "")}{row.Attribute}" +
$"{(row.Cultivation != null ? " / " : "")}{row.Cultivation}";
if (lastQual != null && lastQual != row.QualId) {
current[lastQual] = currentQual.Select(kv => (kv.Key, kv.Value.Num, kv.Value.Weight)).ToArray();
current[lastQual] = currentQual.Select(kv => (kv.Key, kv.Value.AvgKmw, kv.Value.Num, kv.Value.Weight)).ToArray();
currentQual.Clear();
}
if (lastSection != null && lastSection != sec) {
if (!current.ContainsKey(lastQual!)) {
current[lastQual!] = currentQual.Select(kv => (kv.Key, kv.Value.Num, kv.Value.Weight)).ToArray();
current[lastQual!] = currentQual.Select(kv => (kv.Key, kv.Value.AvgKmw, kv.Value.Num, kv.Value.Weight)).ToArray();
currentQual.Clear();
}
data.Add(new(lastSection, lastType, current));
current = [];
currentQual.Clear();
}
currentQual[row.Grad] = (row.Num, row.Weight);
currentQual[row.Grad] = (row.AvgKmw, row.Num, row.Weight);
lastSection = sec;
lastType = row.Type;
lastQual = row.QualId;
}
if (lastQual != null) {
current[lastQual] = currentQual.Select(kv => (kv.Key, kv.Value.Num, kv.Value.Weight)).ToArray();
current[lastQual] = currentQual.Select(kv => (kv.Key, kv.Value.AvgKmw, kv.Value.Num, kv.Value.Weight)).ToArray();
currentQual.Clear();
}
if (lastSection != null) {
@ -60,7 +60,7 @@ namespace Elwig.Models.Dtos {
return [.. data];
}
public static async Task<WineQualityStatisticsData> FromQuery(IQueryable<DeliveryPart> query, bool useOe = true) {
public static async Task<WineQualityStatisticsData> FromQuery(IQueryable<DeliveryPart> query, int mode = 0) {
var rows = (await query
.GroupBy(p => new {
p.Variety.Type,
@ -68,15 +68,24 @@ namespace Elwig.Models.Dtos {
Attribute = p.Attribute!.Name,
Cultivation = p.Cultivation!.Name,
p.QualId,
Oe = useOe ? Math.Round(p.Kmw * (4.54 + 0.022 * p.Kmw), 0) : Math.Round(p.Kmw, 1),
}, (k, g) => new { Key = k, Num = g.Count(), Weight = g.Sum(p => p.Weight) })
Grad = mode == 0 ? Math.Round(p.Kmw * (4.54 + 0.022 * p.Kmw), 0) :
mode == 1 ? Math.Floor(p.Kmw) :
mode == 2 ? Math.Floor(p.Kmw * 2) / 2 :
mode == 3 ? Math.Floor(p.Kmw * 5) / 5 :
Math.Round(p.Kmw, 1),
}, (k, g) => new {
Key = k,
Num = g.Count(),
Weight = g.Sum(p => p.Weight),
AvgKmw = g.Sum(p => p.Weight * p.Kmw) / g.Sum(p => p.Weight),
})
.OrderBy(g => g.Key.Variety)
.ThenBy(g => g.Key.Attribute)
.ThenBy(g => g.Key.Cultivation)
.ThenBy(g => g.Key.QualId)
.ThenBy(g => g.Key.Oe)
.ThenBy(g => g.Key.Grad)
.ToListAsync())
.Select(r => new QualityRow(r.Key.Variety, r.Key.Attribute, r.Key.Cultivation, r.Key.Type, r.Key.QualId, r.Key.Oe, r.Num, r.Weight))
.Select(r => new QualityRow(r.Key.Variety, r.Key.Attribute, r.Key.Cultivation, r.Key.Type, r.Key.QualId, r.AvgKmw, r.Key.Grad, r.Num, r.Weight))
.ToList();
var data = GetQualitySections(rows);
@ -84,7 +93,14 @@ namespace Elwig.Models.Dtos {
return new(data);
var typeRows = rows
.GroupBy(s => new { s.Type, s.QualId, s.Grad }, (k, g) => new QualityRow(null, null, null, k.Type, k.QualId, k.Grad, g.Sum(g => g.Num), g.Sum(p => p.Weight)))
.GroupBy(s => new { s.Type, s.QualId, s.Grad }, (k, g) => new QualityRow(
null, null, null,
k.Type, k.QualId,
g.Sum(p => p.Weight * p.AvgKmw) / g.Sum(p => p.Weight),
k.Grad,
g.Sum(p => p.Num),
g.Sum(p => p.Weight)
))
.OrderBy(g => g.Type)
.ThenBy(g => g.QualId)
.ThenBy(g => g.Grad)
@ -94,12 +110,19 @@ namespace Elwig.Models.Dtos {
return new([.. typeData, .. data]);
var totalRows = rows
.GroupBy(s => new { s.QualId, s.Grad }, (k, g) => new QualityRow(null, null, null, null, k.QualId, k.Grad, g.Sum(p => p.Num), g.Sum(p => p.Weight)))
.GroupBy(s => new { s.QualId, s.Grad }, (k, g) => new QualityRow(
null, null, null, null,
k.QualId,
g.Sum(p => p.Weight * p.AvgKmw) / g.Sum(p => p.Weight),
k.Grad,
g.Sum(p => p.Num),
g.Sum(p => p.Weight)
))
.OrderBy(g => g.QualId)
.ThenBy(g => g.Grad)
.ToList();
var totalData = GetQualitySections(totalRows);
return new([.. totalData, .. typeData, .. data]) { UseOe = useOe };
return new([.. totalData, .. typeData, .. data]) { UseOe = mode == 0 };
}
}
}