From 44065282e31d8ce0500be7960c7d8a89f7a2a233 Mon Sep 17 00:00:00 2001 From: ltx <1006158920@qq.com> Date: Mon, 28 Sep 2026 14:26:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E5=8F=B0=E8=A3=81=E5=88=A4?= =?UTF-8?q?=E5=88=97=E6=8C=89=E8=A3=81=E5=88=A4=E7=B1=BB=E5=9E=8B=E5=B1=95?= =?UTF-8?q?=E7=A4=BA=E5=AF=B9=E5=BA=94=E5=88=86=E5=80=BC=EF=BC=8C=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E7=BB=9F=E4=B8=80=E9=94=99=E8=AF=AF=E5=9C=B0=E8=AF=BB?= =?UTF-8?q?=E5=8F=96=E8=AF=84=E5=88=86=E5=8D=95=E6=80=BB=E5=88=86=E3=80=82?= =?UTF-8?q?=20=E4=B8=BB=E8=A3=81=E5=88=97=E7=8E=B0=E5=9C=A8=E5=B1=95?= =?UTF-8?q?=E7=A4=BA=E6=9C=80=E7=BB=88=E6=B1=87=E6=80=BB=E6=89=A3=E5=88=86?= =?UTF-8?q?=EF=BC=8C=E5=B7=B2=E5=8C=85=E5=90=AB=E8=A1=A8=E7=8E=B0=E8=A3=81?= =?UTF-8?q?=E5=88=A4=E5=92=8C=E4=B8=BB=E8=A3=81=E7=9A=84=E5=A4=B1=E8=AF=AF?= =?UTF-8?q?=E6=AC=A1=E6=95=B0=E5=B9=B3=E5=9D=87=E6=8D=A2=E7=AE=97=E7=BB=93?= =?UTF-8?q?=E6=9E=9C=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Event/Scoring/ScoreSheetCalculator.cs | 2 +- .../Judge/Dtos/JudgeScoringDtos.cs | 4 +- .../JudgeScore/FreestyleRuleDefinition.cs | 17 +++--- .../Scoring/ScoreSheetCalculationService.cs | 52 +++++++++++++++++-- YD_Event.Core/InitData/scoreruleitem.txt | 20 +++---- 5 files changed, 71 insertions(+), 24 deletions(-) diff --git a/YD_Event.Application/Event/Scoring/ScoreSheetCalculator.cs b/YD_Event.Application/Event/Scoring/ScoreSheetCalculator.cs index 78218f3..ae96a7b 100644 --- a/YD_Event.Application/Event/Scoring/ScoreSheetCalculator.cs +++ b/YD_Event.Application/Event/Scoring/ScoreSheetCalculator.cs @@ -129,7 +129,7 @@ public class ScoreItemDefinition public List? StepDeductions { get; set; } /// - /// 规定元素目标完成量(个人花样、车轮跳花样默认 4),只配在缺失数自动项上 + /// 规定元素目标完成量(个人花样为 4,车轮跳花样为 4 类 × 每类 4 个),只配在缺失数自动项上 /// public decimal? RequiredTarget { get; set; } diff --git a/YD_Event.Application/Judge/Dtos/JudgeScoringDtos.cs b/YD_Event.Application/Judge/Dtos/JudgeScoringDtos.cs index c9a271f..6f1c3ab 100644 --- a/YD_Event.Application/Judge/Dtos/JudgeScoringDtos.cs +++ b/YD_Event.Application/Judge/Dtos/JudgeScoringDtos.cs @@ -431,12 +431,12 @@ public class JudgeScoreItemDto public List? StepDeductions { get; set; } /// - /// 规定元素目标完成量(个人花样、车轮跳花样为 4) + /// 规定元素目标完成量(个人花样为 4,车轮跳花样为 16) /// public decimal? RequiredTarget { get; set; } /// - /// 规定元素是否按类别计完成量。true 时该类别录入数量大于 0 即计一类(车轮跳花样), + /// 规定元素是否按类别计完成量。true 时该类别录入数量大于 0 即计一类(如表演赛), /// false 时按数量 × 单位分值折算(个人花样 3 级及以上按 1 计、2 级及以下按 0.5 计)。 /// public bool RequiredAsCategory { get; set; } diff --git a/YD_Event.Application/JudgeScore/FreestyleRuleDefinition.cs b/YD_Event.Application/JudgeScore/FreestyleRuleDefinition.cs index 5934d17..1efabbe 100644 --- a/YD_Event.Application/JudgeScore/FreestyleRuleDefinition.cs +++ b/YD_Event.Application/JudgeScore/FreestyleRuleDefinition.cs @@ -104,9 +104,14 @@ public static class FreestyleRuleDefinition public const decimal RequiredMissingUnit = 0.025m; /// - /// 车轮跳花样的规定元素目标类别数(力量和体操、多摇、绳子运用、互动配合) + /// 车轮跳花样每类规定元素的要求完成数量。 /// - public const decimal WheelRequiredTarget = 4m; + public const decimal WheelRequiredCountPerElement = 4m; + + /// + /// 车轮跳花样规定元素应完成总数:4 类 × 每类 4 个。 + /// + public static decimal WheelRequiredTarget => WheelRequiredElements.Count * WheelRequiredCountPerElement; /// /// 摇绳运动员难度取用的动作数(少于 20 个动作时分母仍按 20) @@ -241,7 +246,7 @@ public static class FreestyleRuleDefinition items.AddRange(BuildPerformanceItems(ref sort)); items.AddRange(BuildChiefDeductionItems("T_INTERVAL", "间歇", ref sort)); - // 规定元素:每类只要有动作即计一类完成,缺失类别数由服务端算出后参与 Q。 + // 规定元素:4 类元素每类均需完成 4 个,未完成数由服务端算出后参与 Q。 foreach (var element in WheelRequiredElements) { items.Add(new PrescribedRuleItemDefinition @@ -249,9 +254,9 @@ public static class FreestyleRuleDefinition JudgeRoleType = RoleChief, ItemCode = element.ItemCode, ItemName = element.ItemName, ItemType = ScoreItemType.RequiredElement, ScoreDimension = ScoreDimensionType.Required, CalcMode = ScoreCalcMode.CountByUnit, - UnitValue = 1m, MinValue = 0m, MaxValue = 50m, StepValue = 1m, DefaultValue = 0m, + UnitValue = 1m, MinValue = 0m, MaxValue = WheelRequiredCountPerElement, StepValue = 1m, DefaultValue = 0m, IsRequired = false, Sort = ++sort, - ExtensionJson = FreestyleItemExtension.RequiredElement() + ExtensionJson = FreestyleItemExtension.Count("个") }); } items.Add(new PrescribedRuleItemDefinition @@ -519,7 +524,7 @@ public static class FreestyleItemExtension new JObject { ["inputMode"] = "count", ["unitLabel"] = unitLabel }.ToString(Formatting.None); /// - /// 规定元素类别项:录入数量大于 0 即计一类完成 + /// 规定元素类别项:录入数量大于 0 即计一类完成(表演赛使用)。 /// public static string RequiredElement() => new JObject diff --git a/YD_Event.Application/Scoring/ScoreSheetCalculationService.cs b/YD_Event.Application/Scoring/ScoreSheetCalculationService.cs index 9fa3454..ead6a76 100644 --- a/YD_Event.Application/Scoring/ScoreSheetCalculationService.cs +++ b/YD_Event.Application/Scoring/ScoreSheetCalculationService.cs @@ -7,6 +7,13 @@ namespace YD_Event.Application.Scoring; /// public static class ScoreSheetCalculationService { + private const decimal WheelRequiredCountPerElement = 4m; + private const decimal WheelRequiredTotal = 16m; + private static readonly string[] WheelRequiredElementCodes = + { + "REQ_STRENGTH_GYMNASTICS", "REQ_MULTIPLE_ROPE", "REQ_ROPE_MANIPULATION", "REQ_INTERACTION" + }; + /// /// 按项目类型判断评分项适用范围 /// @@ -24,18 +31,23 @@ public static class ScoreSheetCalculationService /// public static List ResolveItems(IEnumerable ruleItems, string judgeRoleType, string scope) { - return ruleItems + var matchedItems = ruleItems .Where(x => string.Equals(x.JudgeRoleType, judgeRoleType, StringComparison.OrdinalIgnoreCase)) .Where(x => MatchScope(x, scope)) .OrderBy(x => x.ItemType).ThenBy(x => x.Sort).ThenBy(x => x.Id) - .Select(x => CreateDefinition(x, scope)) .ToList(); + var isWheelRequiredRule = WheelRequiredElementCodes.All(code => matchedItems.Any(item => + string.Equals(item.ItemCode, code, StringComparison.OrdinalIgnoreCase))); + return matchedItems.Select(x => CreateDefinition(x, scope, isWheelRequiredRule)).ToList(); } /// /// 解析评分项定义。scope 为 personal 或 team,用于取对应的分值上限。 /// - public static ScoreItemDefinition CreateDefinition(ScoreRuleItem item, string scope) + public static ScoreItemDefinition CreateDefinition(ScoreRuleItem item, string scope) => + CreateDefinition(item, scope, false); + + private static ScoreItemDefinition CreateDefinition(ScoreRuleItem item, string scope, bool isWheelRequiredRule) { var definition = new ScoreItemDefinition { @@ -51,7 +63,11 @@ public static class ScoreSheetCalculationService // 扩展配置由人工维护,格式不合法时按无扩展配置处理,评分项本身仍然可用。 try { extension = JObject.Parse(item.ExtensionJson); } catch (JsonException) { extension = null; } } - if (extension == null) return definition; + if (extension == null) + { + ApplyWheelRequiredElementCompatibility(item, definition, isWheelRequiredRule); + return definition; + } definition.InputMode = extension["inputMode"]?.ToString() ?? definition.InputMode; definition.UnitLabel = extension["unitLabel"]?.ToString(); @@ -81,9 +97,31 @@ public static class ScoreSheetCalculationService definition.StepDeductions = stepDeductions .Select(x => ReadDecimal(x)).Where(x => x.HasValue).Select(x => x!.Value).ToList(); } + ApplyWheelRequiredElementCompatibility(item, definition, isWheelRequiredRule); return definition; } + /// + /// 兼容尚未执行规则数据更新的环境:车轮跳 4 类规定元素每类均需完成 4 个。 + /// + private static void ApplyWheelRequiredElementCompatibility(ScoreRuleItem item, ScoreItemDefinition definition, + bool isWheelRequiredRule) + { + if (!isWheelRequiredRule) return; + + if (WheelRequiredElementCodes.Contains(item.ItemCode, StringComparer.OrdinalIgnoreCase)) + { + definition.MaxValue = WheelRequiredCountPerElement; + definition.StepValue = 1m; + definition.RequiredAsCategory = false; + return; + } + + if (!string.Equals(item.ItemCode, "REQUIRED_MISSING", StringComparison.OrdinalIgnoreCase)) return; + definition.MaxValue = WheelRequiredTotal; + definition.RequiredTarget = WheelRequiredTotal; + } + /// /// 读取扩展配置里的文本,空白按未配置处理 /// @@ -155,6 +193,9 @@ public static class ScoreSheetCalculationService inputMap.TryGetValue(definition.ItemCode, out var input); var line = BuildLine(definition, input, requireAll); if (line == null) continue; + // 难度裁判端的单项小计与规则展示精度保持一致。 + if (definition.Item.ScoreDimension == ScoreDimensionCode.Difficulty) + line.Subtotal = config.Round(line.Subtotal); result.Lines.Add(line); if (definition.IsDisqualifyReason) @@ -348,7 +389,8 @@ public static class ScoreSheetCalculationService /// /// 规定元素完成量与缺失量。 /// 按数量折算时(个人花样)3 级及以上按 1 计、2 级及以下按 0.5 计; - /// 按类别计数时(车轮跳花样)每个类别只要录入数量大于 0 就计一类。 + /// 按类别计数时(如表演赛)每个类别只要录入数量大于 0 就计一类; + /// 车轮跳花样按实际完成数累加,4 类元素每类上限 4 个。 /// 缺失量 = max(0, 目标数 - 完成量),作为自动项落明细,供跨裁判聚合按 Q = 1 - 系数 × 缺失量 计算。 /// private static void ApplyRequiredElements(List definitions, diff --git a/YD_Event.Core/InitData/scoreruleitem.txt b/YD_Event.Core/InitData/scoreruleitem.txt index 5e0817c..67bed63 100644 --- a/YD_Event.Core/InitData/scoreruleitem.txt +++ b/YD_Event.Core/InitData/scoreruleitem.txt @@ -1285,13 +1285,13 @@ "ParentItemCode": null, "UnitValue": 1, "MinValue": 0, - "MaxValue": 50, + "MaxValue": 4, "StepValue": 1, "DefaultValue": 0, "CalcMode": 0, "ScoreDimension": 3, "IsRequired": false, - "ExtensionJson": "{\"inputMode\":\"count\",\"unitLabel\":\"个\",\"requiredAsCategory\":true}", + "ExtensionJson": "{\"inputMode\":\"count\",\"unitLabel\":\"个\"}", "Sort": 40, "DeleteMark": false, "CreatedUserId": 1000, @@ -1307,13 +1307,13 @@ "ParentItemCode": null, "UnitValue": 1, "MinValue": 0, - "MaxValue": 50, + "MaxValue": 4, "StepValue": 1, "DefaultValue": 0, "CalcMode": 0, "ScoreDimension": 3, "IsRequired": false, - "ExtensionJson": "{\"inputMode\":\"count\",\"unitLabel\":\"个\",\"requiredAsCategory\":true}", + "ExtensionJson": "{\"inputMode\":\"count\",\"unitLabel\":\"个\"}", "Sort": 41, "DeleteMark": false, "CreatedUserId": 1000, @@ -1329,13 +1329,13 @@ "ParentItemCode": null, "UnitValue": 1, "MinValue": 0, - "MaxValue": 50, + "MaxValue": 4, "StepValue": 1, "DefaultValue": 0, "CalcMode": 0, "ScoreDimension": 3, "IsRequired": false, - "ExtensionJson": "{\"inputMode\":\"count\",\"unitLabel\":\"个\",\"requiredAsCategory\":true}", + "ExtensionJson": "{\"inputMode\":\"count\",\"unitLabel\":\"个\"}", "Sort": 42, "DeleteMark": false, "CreatedUserId": 1000, @@ -1351,13 +1351,13 @@ "ParentItemCode": null, "UnitValue": 1, "MinValue": 0, - "MaxValue": 50, + "MaxValue": 4, "StepValue": 1, "DefaultValue": 0, "CalcMode": 0, "ScoreDimension": 3, "IsRequired": false, - "ExtensionJson": "{\"inputMode\":\"count\",\"unitLabel\":\"个\",\"requiredAsCategory\":true}", + "ExtensionJson": "{\"inputMode\":\"count\",\"unitLabel\":\"个\"}", "Sort": 43, "DeleteMark": false, "CreatedUserId": 1000, @@ -1373,13 +1373,13 @@ "ParentItemCode": null, "UnitValue": null, "MinValue": 0, - "MaxValue": 4, + "MaxValue": 16, "StepValue": 1, "DefaultValue": 0, "CalcMode": 1, "ScoreDimension": 0, "IsRequired": false, - "ExtensionJson": "{\"inputMode\":\"score\",\"isAuto\":true,\"unitLabel\":\"个\",\"requiredTarget\":4.0}", + "ExtensionJson": "{\"inputMode\":\"score\",\"isAuto\":true,\"unitLabel\":\"个\",\"requiredTarget\":16.0}", "Sort": 44, "DeleteMark": false, "CreatedUserId": 1000,