三人交互绳花样

难度裁判:跳绳运动员难度(DJ)等级从0(间歇)-5;摇绳运动员难度(DT)等级从1-5 ;两种难度每个等级都应包含 x-、x、x+ (x为等级)
主裁:失误项放到最下面
This commit is contained in:
马梓彭 2026-09-29 22:21:19 +08:00
parent 8e66cd293b
commit 29419e84eb
4 changed files with 1245 additions and 967 deletions

View File

@ -145,6 +145,19 @@ public static class FreestyleRuleDefinition
new("DIFF_LEVEL_8", "8 级", 2.56m)
};
/// <summary>
/// 交互绳跳绳运动员难度等级。间歇单独按0级记录;1~5级均支持减号、标准和加号档。
/// 减号按 x-0.25、加号按 x+0.5 换算,分值为 L(x)=1.5^x,保留4位小数。
/// </summary>
public static IReadOnlyList<DifficultyLevelDefinition> WireJumperDifficultyLevels { get; } =
BuildWireDifficultyLevels(includeBreak: true);
/// <summary>
/// 交互绳摇绳运动员难度等级。1~5级均支持减号、标准和加号档。
/// </summary>
public static IReadOnlyList<DifficultyLevelDefinition> WireTurnerDifficultyLevels { get; } =
BuildWireDifficultyLevels(includeBreak: false);
/// <summary>
/// 表现五维。权重合计必须为 1,页面按此顺序展示。
/// </summary>
@ -281,8 +294,10 @@ public static class FreestyleRuleDefinition
var items = new List<PrescribedRuleItemDefinition>();
var sort = 0;
items.AddRange(BuildDifficultyItems(RoleDifficultyJumper, null, null, Scoring.Dtos.DifficultyAggregateMode.Average, null, null, ref sort));
items.AddRange(BuildDifficultyItems(RoleDifficultyTurner, null, null, Scoring.Dtos.DifficultyAggregateMode.Top, TurnerTopCount, null, ref sort));
items.AddRange(BuildDifficultyItems(RoleDifficultyJumper, null, null,
Scoring.Dtos.DifficultyAggregateMode.Average, null, null, ref sort, WireJumperDifficultyLevels));
items.AddRange(BuildDifficultyItems(RoleDifficultyTurner, null, null,
Scoring.Dtos.DifficultyAggregateMode.Top, TurnerTopCount, null, ref sort, WireTurnerDifficultyLevels));
items.AddRange(BuildPerformanceItems(ref sort));
items.AddRange(BuildChiefDeductionItems("T_SPACE_VIOLATION", "空间违例", ref sort));
items.AddRange(BuildDisqualifyItems(ref sort));
@ -373,15 +388,6 @@ public static class FreestyleRuleDefinition
{
var items = new List<PrescribedRuleItemDefinition>
{
new()
{
JudgeRoleType = RoleChief, ItemCode = "T_FAILURE", ItemName = "失误",
ItemType = ScoreItemType.Deduction, ScoreDimension = ScoreDimensionType.Deduction,
CalcMode = ScoreCalcMode.CountByUnit,
UnitValue = FailureStepDeductions[0], MinValue = 0m, MaxValue = 50m, StepValue = 1m, DefaultValue = 0m,
IsRequired = false, Sort = ++sort,
ExtensionJson = FreestyleItemExtension.StepDeduction(FailureStepDeductions)
},
new()
{
JudgeRoleType = RoleChief, ItemCode = "T_VIOLATION", ItemName = "违例",
@ -392,19 +398,54 @@ public static class FreestyleRuleDefinition
ExtensionJson = FreestyleItemExtension.Count("次")
}
};
if (string.IsNullOrEmpty(extraCode)) return items;
if (!string.IsNullOrEmpty(extraCode))
{
items.Add(new PrescribedRuleItemDefinition
{
JudgeRoleType = RoleChief, ItemCode = extraCode, ItemName = extraName ?? extraCode,
ItemType = ScoreItemType.Deduction, ScoreDimension = ScoreDimensionType.Deduction,
CalcMode = ScoreCalcMode.CountByUnit,
UnitValue = ViolationUnitDeduction, MinValue = 0m, MaxValue = 50m, StepValue = 1m, DefaultValue = 0m,
IsRequired = false, Sort = ++sort,
ExtensionJson = FreestyleItemExtension.Count("次")
});
}
items.Add(new PrescribedRuleItemDefinition
{
JudgeRoleType = RoleChief, ItemCode = extraCode, ItemName = extraName ?? extraCode,
JudgeRoleType = RoleChief, ItemCode = "T_FAILURE", ItemName = "失误",
ItemType = ScoreItemType.Deduction, ScoreDimension = ScoreDimensionType.Deduction,
CalcMode = ScoreCalcMode.CountByUnit,
UnitValue = ViolationUnitDeduction, MinValue = 0m, MaxValue = 50m, StepValue = 1m, DefaultValue = 0m,
UnitValue = FailureStepDeductions[0], MinValue = 0m, MaxValue = 50m, StepValue = 1m, DefaultValue = 0m,
IsRequired = false, Sort = ++sort,
ExtensionJson = FreestyleItemExtension.Count("次")
ExtensionJson = FreestyleItemExtension.StepDeduction(FailureStepDeductions)
});
return items;
}
private static List<DifficultyLevelDefinition> BuildWireDifficultyLevels(bool includeBreak)
{
var levels = new List<DifficultyLevelDefinition>();
if (includeBreak)
levels.Add(new DifficultyLevelDefinition("DIFF_LEVEL_0", "0 级(间歇)", 0m));
for (var level = 1; level <= 5; level++)
{
levels.Add(NewWireDifficultyLevel(level, "MINUS", "-", -0.25));
levels.Add(NewWireDifficultyLevel(level, null, string.Empty, 0));
levels.Add(NewWireDifficultyLevel(level, "PLUS", "+", 0.5));
}
return levels;
}
private static DifficultyLevelDefinition NewWireDifficultyLevel(int level, string? codeSuffix,
string nameSuffix, double levelOffset)
{
var itemCode = codeSuffix == null ? $"DIFF_LEVEL_{level}" : $"DIFF_LEVEL_{level}_{codeSuffix}";
var levelValue = decimal.Round((decimal)Math.Pow(1.5, level + levelOffset), 4,
MidpointRounding.AwayFromZero);
return new DifficultyLevelDefinition(itemCode, $"{level}{nameSuffix} 级", levelValue);
}
/// <summary>
/// 构造主裁的取消比赛资格原因项,勾选任一项即整条成绩按 0 分处理
/// </summary>

View File

@ -72,9 +72,9 @@ public class OrderBookService : IDynamicApiController, ITransient
/// <returns></returns>
[DisplayName("下载秩序册导入模板")]
[HttpGet("template")]
public IActionResult DownloadTemplate([FromQuery] string? projectMode)
public async Task<IActionResult> DownloadTemplate([FromQuery] string? projectMode)
{
var bytes = new OrderBookTemplateExporter().ExportAsync().GetAwaiter().GetResult();
var bytes = await new OrderBookTemplateExporter().ExportAsync();
return new FileContentResult(bytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{
FileDownloadName = "秩序册导入模板.xlsx"

View File

@ -310,9 +310,8 @@ public static class ScoreSheetCalculationService
}
/// <summary>
/// 表现维度计算。个人及同步花样的失误在每个维度扣一次,同时独立提交给综合扣分 M;
/// 其他花样项目沿用额外失误联动表现维度的既有口径。
/// 每个维度 = 基准分 + 人工加 - (人工减 + 失误自动减) - 失误次数,限制在上下限内,
/// 表现维度计算。失误在每个维度只扣一次,同时独立提交给综合扣分 M;
/// 每个维度 = 基准分 + 人工加 - 人工减 - 失误次数,限制在上下限内,
/// 再按各维度权重加权求和得到本裁判的表现分。失误自动减分作为自动项落明细,裁判不可直接修改。
/// </summary>
private static void ApplyPerformanceDimensions(List<ScoreItemDefinition> definitions,
@ -323,12 +322,11 @@ public static class ScoreSheetCalculationService
.ToList();
if (dimensions.Count == 0) return;
// 个人及同步花样的每个表现维度按一次失误扣减,失误数量另用于综合扣分。
// 每个表现维度只按一次失误扣减;同一失误数量另用于跨裁判汇总综合扣分 M。
var failure = definitions.FirstOrDefault(x => x.IsFailureCount);
var failureCount = failure == null
? 0m
: result.Lines.FirstOrDefault(x => string.Equals(x.ItemCode, failure.ItemCode, StringComparison.OrdinalIgnoreCase))?.CountValue ?? 0m;
var isIndividualFamily = ScoreRuleConfigService.IsIndividualFamily(config.RuleType);
var performanceFailureCount = failureCount;
var hasPerformanceMarks = definitions.Any(x => !x.IsAuto && x.AdjustSign != 0 &&
result.Lines.Any(line => string.Equals(line.ItemCode, x.ItemCode, StringComparison.OrdinalIgnoreCase)
@ -348,8 +346,7 @@ public static class ScoreSheetCalculationService
.FirstOrDefault(x => string.Equals(x.ItemCode, adjust.ItemCode, StringComparison.OrdinalIgnoreCase))?.CountValue ?? 0m;
raw += adjust.AdjustSign * count * (adjust.Item.UnitValue ?? 1m);
}
// 其他花样项目保留失误联动减号;个人及同步花样按一次失误扣减。
raw -= performanceFailureCount * (isIndividualFamily ? 1m : 2m) * (dimension.Item.UnitValue ?? 1m);
raw -= performanceFailureCount * (dimension.Item.UnitValue ?? 1m);
// 维度分限制在规则给出的上下限内(规程为 0~24)并取整。
var value = !hasPerformanceMarks && performanceFailureCount == 0m
? 0m
@ -370,9 +367,7 @@ public static class ScoreSheetCalculationService
Code = $"DIM_{dimension.DimensionCode}", Label = dimension.Item.ItemName,
Formula = !hasPerformanceMarks && performanceFailureCount == 0m
? "尚未录入表现加减或失误,表现分为 0"
: isIndividualFamily
? $"{Trim(dimension.BaseValue ?? 0m)} + 人工加 - 人工减 - 失误{Trim(performanceFailureCount)}次"
: $"{Trim(dimension.BaseValue ?? 0m)} + 人工加 - (人工减 + 失误联动减{Trim(performanceFailureCount)}) - 失误{Trim(performanceFailureCount)}次",
: $"{Trim(dimension.BaseValue ?? 0m)} + 人工加 - 人工减 - 失误{Trim(performanceFailureCount)}次",
Value = value
});
}

File diff suppressed because it is too large Load Diff