diff --git a/YD_Event.Application/Client/EventClientController.Scores.cs b/YD_Event.Application/Client/EventClientController.Scores.cs index 83df612..8fdba41 100644 --- a/YD_Event.Application/Client/EventClientController.Scores.cs +++ b/YD_Event.Application/Client/EventClientController.Scores.cs @@ -11,20 +11,11 @@ public partial class EventClientController [AllowAnonymous] [DisplayName("获取成绩赛事")] public async Task> GetScoreEvents( - [FromServices] ISqlSugarRepository resultRepository, [FromServices] ISqlSugarRepository eventRepository) { - var eventIds = await resultRepository.AsQueryable() - .Where(x => x.Status == AvailabilityStatus.Enable && !x.DeleteMark) - .Select(x => x.EventId) - .Distinct() - .ToListAsync(); - - if (eventIds.Count == 0) return new List(); - var events = await eventRepository.AsQueryable() - .Where(x => eventIds.Contains(x.Id) && x.Status == AvailabilityStatus.Enable && !x.DeleteMark) - // 原型要求成绩查询只显示进行中、已结束状态的赛事。 + .Where(x => x.Status == AvailabilityStatus.Enable && !x.DeleteMark) + // 成绩查询按赛事状态开放,未产生成绩时也应允许选择比赛中、已结束的赛事。 .Where(x => x.EventStatus == EventStatus.Ongoing || x.EventStatus == EventStatus.Ended) .OrderByDescending(x => x.MatchStartTime) .ToListAsync(); diff --git a/YD_Event.Application/Event/EventArrangementService.cs b/YD_Event.Application/Event/EventArrangementService.cs index b2f5e0c..08d6954 100644 --- a/YD_Event.Application/Event/EventArrangementService.cs +++ b/YD_Event.Application/Event/EventArrangementService.cs @@ -514,7 +514,9 @@ namespace YD_Event.Application.Event; ProjectName = proj.Name, ProjectType = proj.ProjectType.Description(), GroupName = person.GroupName, - TeamName = person.TeamName, + // 个人项目的出场单元是报名人,单位报名时携带的队伍/单位名不能当成团队名。 + // 否则裁判端会优先显示该名称,导致同单位的多名运动员看起来是重复出场。 + TeamName = null, AthleteName = person.Name, UnitName = displayUnitName, ProjectTotalDurationSeconds = projectTotalDurationSeconds, diff --git a/YD_Event.Application/Event/Scoring/EventScoreCalculationService.cs b/YD_Event.Application/Event/Scoring/EventScoreCalculationService.cs index 2b67d6c..a8eb2b2 100644 --- a/YD_Event.Application/Event/Scoring/EventScoreCalculationService.cs +++ b/YD_Event.Application/Event/Scoring/EventScoreCalculationService.cs @@ -210,7 +210,7 @@ public class EventScoreCalculationService : ITransient if (persist) { - var members = await LoadEntryMembersAsync(entries); + var members = await LoadEntryMembersAsync(entries, ctx.Scope); foreach (var entry in written) { var outcome = outcomes.First(x => x.SessionEntryId == entry.Id); @@ -237,7 +237,7 @@ public class EventScoreCalculationService : ITransient var outcome = new EntryCalculationOutcome { SessionEntryId = entry.Id, EntryNo = entry.EntryNo, - ParticipantName = string.IsNullOrWhiteSpace(entry.TeamName) ? entry.ParticipantName : entry.TeamName!, + ParticipantName = DisplayParticipantName(entry, ctx.Scope), GroupName = entry.GroupName }; @@ -311,6 +311,15 @@ public class EventScoreCalculationService : ITransient var userId = operatorUserId ?? 0; var personIds = athletes.Select(x => x.Id).ToList(); + if (!isTeam) + { + // 修复旧逻辑已经造成的串成绩:个人项一个出场号只允许归属当前报名人。 + // 重算时作废同出场号下误写给其他人的成绩,并保留版本留痕。 + var mismatchedResults = await _resultRepository.GetListAsync(x => x.SessionEntryId == entry.Id + && x.ResultStatus != ResultStatusVoided && !personIds.Contains(x.RegistrationPersonId)); + await VoidResultsAsync(mismatchedResults, operatorUserId); + } + // 同一名运动员可能因重赛等原因在同一项目中产生多条出场记录, // 成绩必须以“出场 + 运动员”为业务键更新,不能覆盖其他出场的历史成绩。 var existing = await _resultRepository.GetListAsync(x => x.EventId == ctx.Session.EventId @@ -407,6 +416,14 @@ public class EventScoreCalculationService : ITransient private async Task VoidResultAsync(EventSessionEntry entry, long? operatorUserId) { var results = await _resultRepository.GetListAsync(x => x.SessionEntryId == entry.Id && x.ResultStatus != ResultStatusVoided); + await VoidResultsAsync(results, operatorUserId); + } + + /// + /// 作废指定成绩及其当前版本,历史版本保留留痕。 + /// + private async Task VoidResultsAsync(List results, long? operatorUserId) + { if (results.Count == 0) return; var now = DateTime.Now; foreach (var result in results) @@ -493,7 +510,8 @@ public class EventScoreCalculationService : ITransient /// /// 取各出场对应的运动员名单。集体项目取同一报名项下的全部运动员,个人项目只有一人。 /// - private async Task>> LoadEntryMembersAsync(List entries) + private async Task>> LoadEntryMembersAsync( + List entries, string scope) { var result = new Dictionary>(); var itemIds = entries.Where(x => x.RegistrationItemId.HasValue).Select(x => x.RegistrationItemId!.Value).Distinct().ToList(); @@ -505,7 +523,10 @@ public class EventScoreCalculationService : ITransient } // 少数出场只关联了参赛记录(如现场补录),按参赛记录反查报名人。 - var recordIds = entries.Where(x => !x.RegistrationItemId.HasValue && x.ParticipationRecordId.HasValue) + // 个人项即使有 RegistrationItemId,也必须优先按 ParticipationRecordId 定位到唯一报名人。 + // 单位报名会让多名个人项运动员共享一个 RegistrationItemId。 + var recordIds = entries.Where(x => x.ParticipationRecordId.HasValue + && (scope == ScoreScope.Personal || !x.RegistrationItemId.HasValue)) .Select(x => x.ParticipationRecordId!.Value).Distinct().ToList(); var personByRecord = new Dictionary(); if (recordIds.Count > 0) @@ -523,7 +544,23 @@ public class EventScoreCalculationService : ITransient foreach (var entry in entries) { var members = new List(); - if (entry.RegistrationItemId.HasValue && personsByItem.TryGetValue(entry.RegistrationItemId.Value, out var candidates)) + if (scope == ScoreScope.Personal) + { + if (entry.ParticipationRecordId.HasValue + && personByRecord.TryGetValue(entry.ParticipationRecordId.Value, out var personal)) + { + members.Add(personal); + } + else if (entry.RegistrationItemId.HasValue + && personsByItem.TryGetValue(entry.RegistrationItemId.Value, out var personalCandidates)) + { + // 只为无有效参赛记录的历史数据做姓名精确回退,绝不将整个报名项写成一个人的成绩。 + var matched = personalCandidates.FirstOrDefault(x => + string.Equals(x.Name, entry.ParticipantName, StringComparison.Ordinal)); + if (matched != null) members.Add(matched); + } + } + else if (entry.RegistrationItemId.HasValue && personsByItem.TryGetValue(entry.RegistrationItemId.Value, out var candidates)) { // 报名人里可能同时含教练、领队,成绩只算运动员;没有标记运动员的历史数据全部计入。 members = candidates.Where(x => x.PersonType == PersonType.Athlete).OrderBy(x => x.Name).ToList(); @@ -537,4 +574,12 @@ public class EventScoreCalculationService : ITransient } return result; } + + /// + /// 个人项始终显示出场人快照,只有集体项才使用队名。 + /// + private static string DisplayParticipantName(EventSessionEntry entry, string scope) => + scope == ScoreScope.Team && !string.IsNullOrWhiteSpace(entry.TeamName) + ? entry.TeamName + : entry.ParticipantName; } diff --git a/YD_Event.Application/Event/Scoring/ScoreRuleConfig.cs b/YD_Event.Application/Event/Scoring/ScoreRuleConfig.cs index 390141f..a2b5921 100644 --- a/YD_Event.Application/Event/Scoring/ScoreRuleConfig.cs +++ b/YD_Event.Application/Event/Scoring/ScoreRuleConfig.cs @@ -170,6 +170,12 @@ public class RoleAggregationConfig /// public string Aggregate { get; set; } = ScoreRuleConfig.AggregateAvg; + /// + /// 聚合后保留的小数位数。为空时沿用计分规则的 ScoreDecimals; + /// 个人花样规定元素缺失数按同类型裁判平均后需四舍五入到整数,因此配置为 0。 + /// + public int? AggregateDecimals { get; set; } + /// /// 参与总分时的符号:1-加分,-1-减分 /// diff --git a/YD_Event.Application/Judge/JudgeScoringController.cs b/YD_Event.Application/Judge/JudgeScoringController.cs index 3c3203b..5809aec 100644 --- a/YD_Event.Application/Judge/JudgeScoringController.cs +++ b/YD_Event.Application/Judge/JudgeScoringController.cs @@ -41,6 +41,7 @@ public class JudgeScoringController : IDynamicApiController private readonly ISqlSugarRepository _attachmentRepository; private readonly ISqlSugarRepository _resultRepository; private readonly ISqlSugarRepository _personRepository; + private readonly ISqlSugarRepository _participationRepository; private readonly EventScoreCalculationService _calculationService; private readonly AuthManager _authManager; private readonly IIdGenerator _idGenerator; @@ -65,6 +66,7 @@ public class JudgeScoringController : IDynamicApiController ISqlSugarRepository attachmentRepository, ISqlSugarRepository resultRepository, ISqlSugarRepository personRepository, + ISqlSugarRepository participationRepository, EventScoreCalculationService calculationService, AuthManager authManager, IIdGenerator idGenerator, @@ -88,6 +90,7 @@ public class JudgeScoringController : IDynamicApiController _attachmentRepository = attachmentRepository; _resultRepository = resultRepository; _personRepository = personRepository; + _participationRepository = participationRepository; _calculationService = calculationService; _authManager = authManager; _idGenerator = idGenerator; @@ -268,8 +271,8 @@ public class JudgeScoringController : IDynamicApiController var assignment = await GetMyAssignmentAsync(sessionId, referee.Id); var session = await _sessionRepository.GetFirstAsync(x => x.Id == sessionId); if (session == null) throw Oops.Bah("比赛场次不存在"); - var config = ScoreRuleConfigService.Parse( - (await _ruleRepository.GetFirstAsync(x => x.Id == session.ScoreRuleId))?.RuleConfigJson); + var ctx = await _calculationService.LoadContextAsync(sessionId); + var config = ctx.Config; var entries = (await _entryRepository.AsQueryable() .Where(x => x.SessionId == sessionId && !x.IsVoided && @@ -298,7 +301,7 @@ public class JudgeScoringController : IDynamicApiController EntryNo = entry.EntryNo, PlayOrder = entry.PlayOrder, ScheduleOrder = entry.SourceType == 1 ? entry.Id : 0, - ParticipantName = string.IsNullOrWhiteSpace(entry.TeamName) ? entry.ParticipantName : entry.TeamName!, + ParticipantName = DisplayParticipantName(entry, ctx.Scope), GroupName = entry.GroupName, EntryStatus = entry.EntryStatus, IsRematch = entry.IsRematch, @@ -348,7 +351,11 @@ public class JudgeScoringController : IDynamicApiController var stageAllowsScoring = CompetitionStagePolicy.CanScore(ctx.Session.SessionStatus, eventInfo.EventStatus); var scoreSheetAllowsEditing = submitted == null || correction != null; var canEdit = stageAllowsScoring && scoreSheetAllowsEditing; - var members = await LoadMemberNamesAsync(entry); + var members = await LoadMemberNamesAsync(entry, ctx.Scope); + // 个人项目以参赛记录解析出的当前运动员为准,兼容历史出场快照误存单位名的情况。 + var participantName = ctx.Scope == ScoreScope.Personal && members.Count == 1 + ? members[0] + : DisplayParticipantName(entry, ctx.Scope); var venue = await _venueRepository.GetFirstAsync(x => x.Id == ctx.Session.VenueId); var nextVersion = (submitted?.SheetVersion ?? 0) + 1; @@ -379,7 +386,7 @@ public class JudgeScoringController : IDynamicApiController entry.GroupName, venue?.VenueName ?? "-"), EntryNo = entry.EntryNo, - ParticipantName = string.IsNullOrWhiteSpace(entry.TeamName) ? entry.ParticipantName : entry.TeamName!, + ParticipantName = participantName, MemberNames = members, JudgeRole = assignment.JudgeRole, JudgeRoleType = roleType, @@ -661,8 +668,7 @@ public class JudgeScoringController : IDynamicApiController ScoreSheetId = sheet.Id, SessionEntryId = sheet.SessionEntryId, EntryNo = entry?.EntryNo ?? string.Empty, - ParticipantName = entry == null ? string.Empty - : string.IsNullOrWhiteSpace(entry.TeamName) ? entry.ParticipantName : entry.TeamName!, + ParticipantName = entry == null ? string.Empty : DisplayParticipantName(entry, ctx.Scope), MyScore = ctx.Config.Format(sheet.TotalScore), SubmittedTime = sheet.SubmittedTime, CorrectionStatus = status, @@ -731,7 +737,7 @@ public class JudgeScoringController : IDynamicApiController { var referee = await EnsureRefereeAsync(); var userId = _authManager.UserId; - var messages = (await _messageRepository.AsQueryable() + var messages = await _messageRepository.AsQueryable() .Where(x => x.RefereeId == referee.Id || x.ReceiverUserId == userId) .WhereIF(onlyUnread == true, x => !x.IsRead) .ToListAsync()) @@ -969,8 +975,28 @@ public class JudgeScoringController : IDynamicApiController /// /// 取出场对应的运动员姓名,用于评分表表头展示 /// - private async Task> LoadMemberNamesAsync(EventSessionEntry entry) + private async Task> LoadMemberNamesAsync(EventSessionEntry entry, string scope) { + // 单位可以在同一报名项下填报多名个人项运动员。 + // 个人项必须通过出场记录关联的参赛记录精确取一人,不能按 RegistrationItemId 整体取人。 + if (scope == ScoreScope.Personal) + { + if (entry.ParticipationRecordId.HasValue) + { + var record = await _participationRepository.GetFirstAsync(x => x.Id == entry.ParticipationRecordId.Value); + if (record != null) + { + var person = await _personRepository.GetFirstAsync(x => x.Id == record.RegistrationPersonId); + if (person != null) return new List { person.Name }; + } + } + + // 历史异常关联不扩大到同报名项的其他人,使用出场快照保证不串人。 + return string.IsNullOrWhiteSpace(entry.ParticipantName) + ? new List() + : new List { entry.ParticipantName }; + } + if (!entry.RegistrationItemId.HasValue) return new List(); var persons = await _personRepository.GetListAsync(x => x.RegistrationItemId == entry.RegistrationItemId.Value); var athletes = persons.Where(x => x.PersonType == PersonType.Athlete).ToList(); @@ -978,6 +1004,15 @@ public class JudgeScoringController : IDynamicApiController return athletes.OrderBy(x => x.Name).Select(x => x.Name).ToList(); } + /// + /// 个人项始终显示出场人快照;只有集体项才优先显示队名。 + /// 兼容修复前已经编排、TeamName 被误写为单位名的历史出场记录。 + /// + private static string DisplayParticipantName(EventSessionEntry entry, string scope) => + scope == ScoreScope.Team && !string.IsNullOrWhiteSpace(entry.TeamName) + ? entry.TeamName + : entry.ParticipantName; + /// /// 该评分单是否有正在处理中的修正申请 /// @@ -1046,7 +1081,7 @@ public class JudgeScoringController : IDynamicApiController sessionName = ctx.Session.SessionName ?? ctx.Session.SessionNo, entryNo = entry.EntryNo, groupName = entry.GroupName, - participantName = string.IsNullOrWhiteSpace(entry.TeamName) ? entry.ParticipantName : entry.TeamName, + participantName = DisplayParticipantName(entry, ctx.Scope), judgeRole = assignment.JudgeRole, judgeRoleType = roleType, scope = ctx.Scope @@ -1274,6 +1309,11 @@ public class JudgeScoringController : IDynamicApiController /// private const int TaskStatusVoided = 90; + /// + /// 消息类型:成绩修正提醒 + /// + private const int MessageTypeCorrection = 1; + /// /// 评分任务类型:成绩修正 /// diff --git a/YD_Event.Application/JudgeScore/FreestyleRuleDefinition.cs b/YD_Event.Application/JudgeScore/FreestyleRuleDefinition.cs index 1727516..5934d17 100644 --- a/YD_Event.Application/JudgeScore/FreestyleRuleDefinition.cs +++ b/YD_Event.Application/JudgeScore/FreestyleRuleDefinition.cs @@ -290,10 +290,11 @@ public static class FreestyleRuleDefinition /// itemCodePrefix 用于表演赛把同一裁判的多个类别拆成独立评分项(如 SR_DIFF_LEVEL_3),避免编码互相覆盖。 /// internal static List BuildDifficultyItems(string roleType, string? subjectCode, - string? subjectName, string? aggregate, int? topCount, string? itemCodePrefix, ref int sort) + string? subjectName, string? aggregate, int? topCount, string? itemCodePrefix, ref int sort, + IReadOnlyList? difficultyLevels = null) { var items = new List(); - foreach (var level in DifficultyLevels) + foreach (var level in difficultyLevels ?? DifficultyLevels) { items.Add(new PrescribedRuleItemDefinition { diff --git a/YD_Event.Application/JudgeScore/ShowcaseRuleDefinition.cs b/YD_Event.Application/JudgeScore/ShowcaseRuleDefinition.cs index 78eb617..970acc4 100644 --- a/YD_Event.Application/JudgeScore/ShowcaseRuleDefinition.cs +++ b/YD_Event.Application/JudgeScore/ShowcaseRuleDefinition.cs @@ -8,10 +8,10 @@ namespace YD_Event.Application.JudgeScore; /// /// /// 计分口径(裁判端原型 + 花样跳绳裁判端逻辑与测试验收说明书 6.7):
-/// 席位:难度A组×3、难度B组×3、表现P×3、主裁T×1。
-/// A 组裁判一人评 个人绳(DP+DM)、车轮跳(DA)、交互绳(DT_INTERACTION)、旅行跳(DT_TRAVEL) 四个类别,A=average(A1,A2,A3);
-/// B 组裁判一人评 个人绳(DR)、车轮跳(DB)、交互绳(DJ)、长绳(DL) 四个类别,B=average(B1,B2,B3);
-/// 总难度 D=(A+B)/2;表现 P=average(p1,p2,p3)×0.05;
+/// 席位:难度A组×1~3、难度B组×1~3、表现P×1~3、主裁T×1。
+/// A 组裁判一人评 个人绳(DP+DM)、车轮跳(DA)、交互绳(DT_INTERACTION)、旅行跳(DT_TRAVEL) 四个类别,A=average(实际A组裁判);
+/// B 组裁判一人评 个人绳(DR)、车轮跳(DB)、交互绳(DJ)、长绳(DL) 四个类别,B=average(实际B组裁判);
+/// 总难度 D=(A+B)/2;表现 P=average(实际表现裁判)×0.05;
/// 规定元素 Q=max(0,1-0.05×缺失类别数),5 类为 个人绳、车轮跳、交互绳、长绳(6米以上)、旅行跳;
/// 扣分 M=max(0,1-(失误+违例)),表演赛不记间歇与空间违例;
/// 总分 R=max(0, D×(1+P)×Q×M)。 @@ -54,6 +54,24 @@ public static class ShowcaseRuleDefinition /// public const decimal RequiredTarget = 5m; + /// + /// 长绳、旅行跳难度等级按脑图公式 L(x)=1.5^x 换算。 + /// UnitValue 入库精度为 4 位小数,因此在此按四位小数固化,避免运行期浮点差异。 + /// + public static IReadOnlyList ExponentialDifficultyLevels { get; } = new List + { + new("DIFF_LEVEL_0", "0 级", 1m), + new("DIFF_LEVEL_0_5", "0.5 级", 1.2247m), + new("DIFF_LEVEL_1", "1 级", 1.5m), + new("DIFF_LEVEL_2", "2 级", 2.25m), + new("DIFF_LEVEL_3", "3 级", 3.375m), + new("DIFF_LEVEL_4", "4 级", 5.0625m), + new("DIFF_LEVEL_5", "5 级", 7.5938m), + new("DIFF_LEVEL_6", "6 级", 11.3906m), + new("DIFF_LEVEL_7", "7 级", 17.0859m), + new("DIFF_LEVEL_8", "8 级", 25.6289m) + }; + /// /// A 组难度裁判要评的类别。 /// 逻辑说明书要求把脑图里两个同名 DT 拆成 DT_INTERACTION(交互绳)与 DT_TRAVEL(旅行跳),避免字段互相覆盖。 @@ -93,7 +111,7 @@ public static class ShowcaseRuleDefinition /// 表演赛裁判席位配置:A/B 组难度裁判各 1~3 人、表现裁判 1~3 人、主裁 1 人 /// public const string JudgeRoleSchemaJson = """ - [{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DGA","name":"难度裁判-A组裁判","min":1,"max":3,"categories":["DP+DM (个人绳)","DA (车轮跳)","DT (交互绳)","DT (旅行跳)"]},{"code":"DGB","name":"难度裁判-B组裁判","min":1,"max":3,"categories":["DR (个人绳)","DB (车轮跳)","DJ (交互绳)","DL (旅行跳)"]}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":3}]}] + [{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DGA","name":"难度裁判-A组裁判","min":1,"max":3,"categories":["DP+DM (个人绳)","DA (车轮跳)","DT (交互绳)","DT (旅行跳)"]},{"code":"DGB","name":"难度裁判-B组裁判","min":1,"max":3,"categories":["DR (个人绳)","DB (车轮跳)","DJ (交互绳)","DL (长绳)"]}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":3}]}] """; /// @@ -122,12 +140,14 @@ public static class ShowcaseRuleDefinition foreach (var category in GroupACategories) { items.AddRange(FreestyleRuleDefinition.BuildDifficultyItems(RoleDifficultyGroupA, - category.Code, category.DisplayName, null, null, category.Code, ref sort)); + category.Code, category.DisplayName, null, null, category.Code, ref sort, + DifficultyLevelsFor(category))); } foreach (var category in GroupBCategories) { items.AddRange(FreestyleRuleDefinition.BuildDifficultyItems(RoleDifficultyGroupB, - category.Code, category.DisplayName, null, null, category.Code, ref sort)); + category.Code, category.DisplayName, null, null, category.Code, ref sort, + DifficultyLevelsFor(category))); } items.AddRange(FreestyleRuleDefinition.BuildPerformanceItems(ref sort)); @@ -160,6 +180,11 @@ public static class ShowcaseRuleDefinition items.AddRange(FreestyleRuleDefinition.BuildDisqualifyItems(ref sort)); return items; } + + private static IReadOnlyList DifficultyLevelsFor(ShowcaseDifficultyCategory category) => + category.Code is "DT_TRAVEL" or "DL" + ? ExponentialDifficultyLevels + : FreestyleRuleDefinition.DifficultyLevels; } /// diff --git a/YD_Event.Application/Scoring/EntryResultCalculationService.cs b/YD_Event.Application/Scoring/EntryResultCalculationService.cs index ee0674a..adab47e 100644 --- a/YD_Event.Application/Scoring/EntryResultCalculationService.cs +++ b/YD_Event.Application/Scoring/EntryResultCalculationService.cs @@ -52,7 +52,10 @@ public static class EntryResultCalculationService }); } // 该类型暂无裁判提交时按 0 分计入,成绩是否可用由调用方按提交进度判断。 - symbol.Value = config.Round(Combine(symbol.Judges.Select(x => x.Value).ToList(), role.Aggregate)); + var combinedValue = Combine(symbol.Judges.Select(x => x.Value).ToList(), role.Aggregate); + symbol.Value = role.AggregateDecimals.HasValue + ? Math.Round(combinedValue, role.AggregateDecimals.Value, MidpointRounding.AwayFromZero) + : (config.IsFactorTotal ? combinedValue : config.Round(combinedValue)); result.Symbols.Add(symbol); ApplyTargetField(result, role.TargetField, symbol.Value); total += role.Sign * symbol.Value; @@ -146,7 +149,8 @@ public static class EntryResultCalculationService .Sum(x => x.Subtotal) : 0m; var otherDeduction = Math.Max(0m, deductionSymbol.Value - originalChiefFailureDeduction); - var totalDeduction = config.Round(otherDeduction + failureDeduction); + // m 可能包含 0.075,因子计算前不得提前按最终展示精度取整。 + var totalDeduction = otherDeduction + failureDeduction; deductionSymbol.Value = totalDeduction; result.DeductionScore = totalDeduction; result.FailureAggregation = new EntryFailureAggregation @@ -156,9 +160,9 @@ public static class EntryResultCalculationService JudgeCount = judgeCount, AverageFailureCount = averageCount, RoundedFailureCount = roundedCount, - OriginalChiefFailureDeduction = config.Round(originalChiefFailureDeduction), - FailureDeduction = config.Round(failureDeduction), - OtherDeduction = config.Round(otherDeduction), + OriginalChiefFailureDeduction = originalChiefFailureDeduction, + FailureDeduction = failureDeduction, + OtherDeduction = otherDeduction, TotalDeduction = totalDeduction }; } @@ -182,13 +186,12 @@ public static class EntryResultCalculationService foreach (var (symbol, weight) in difficultySymbols) difficulty += symbol.Value * weight; // 除数为 0 视为漏配,按裁判类型数量取平均,避免除零。 var divisor = config.DifficultyDivisor is > 0m ? config.DifficultyDivisor!.Value : difficultySymbols.Count; - difficulty = config.Round(difficulty / divisor); + difficulty /= divisor; } var performance = 0m; foreach (var (symbol, weight) in FactorSymbols(config, result, ScoreFactorCode.Performance)) performance += symbol.Value * weight; - performance = config.Round(performance); // 规定元素与扣分都是“扣减型”因子,聚合值越大因子越小,下限取 0。 var required = 1m; @@ -211,14 +214,14 @@ public static class EntryResultCalculationService result.DifficultyFactor = difficulty; result.PerformanceFactor = performance; - result.RequiredFactor = config.Round(required); - result.DeductionFactor = config.Round(deduction); + result.RequiredFactor = required; + result.DeductionFactor = deduction; // 排名的并列比较取的是成绩表上的四个分值字段,这里统一回写为花样赛口径: // 难度分=D,表现分=P,规定分=Q,扣分=最终扣分合计(越小越靠前)。 result.DifficultyScore = difficulty; result.PerformanceScore = performance; result.RequiredScore = result.RequiredFactor; - result.DeductionScore = config.Round(penalty); + result.DeductionScore = penalty; return config.Round(Math.Max(0m, difficulty * (1m + performance) * required * deduction)); } diff --git a/YD_Event.Application/Scoring/ScoreRuleConfigService.cs b/YD_Event.Application/Scoring/ScoreRuleConfigService.cs index 51da4e9..b43ec51 100644 --- a/YD_Event.Application/Scoring/ScoreRuleConfigService.cs +++ b/YD_Event.Application/Scoring/ScoreRuleConfigService.cs @@ -46,6 +46,7 @@ public static class ScoreRuleConfigService SourceField = node["sourceField"]?.ToString() ?? nameof(EventJudgeScoreSheet.TotalScore), TargetField = node["targetField"]?.ToString() ?? node["sourceField"]?.ToString() ?? nameof(EventResult.TotalScore), Aggregate = (node["aggregate"]?.ToString() ?? ScoreRuleConfig.AggregateAvg).Trim().ToLowerInvariant(), + AggregateDecimals = ReadInt(node["aggregateDecimals"], 0, 4), Sign = ReadSign(node["sign"]), Factor = ReadFactor(node["factor"]), FactorWeight = ReadDecimal(node["factorWeight"]) ?? 1m @@ -88,6 +89,22 @@ public static class ScoreRuleConfigService catch (Exception ex) when (ex is FormatException or InvalidCastException or OverflowException) { return null; } } + /// + /// 读取受限整数配置,非法值按未配置处理。 + /// + private static int? ReadInt(JToken? node, int min, int max) + { + try + { + var value = node?.Value(); + return value.HasValue ? Math.Clamp(value.Value, min, max) : null; + } + catch (Exception ex) when (ex is FormatException or InvalidCastException or OverflowException) + { + return null; + } + } + /// /// 未配置聚合方式时按规定赛的 T1/T2/T3 兜底 /// diff --git a/YD_Event.Application/Scoring/ScoreSheetCalculationService.cs b/YD_Event.Application/Scoring/ScoreSheetCalculationService.cs index 98f474e..22be844 100644 --- a/YD_Event.Application/Scoring/ScoreSheetCalculationService.cs +++ b/YD_Event.Application/Scoring/ScoreSheetCalculationService.cs @@ -189,10 +189,15 @@ public static class ScoreSheetCalculationService ApplyStepDeductions(definitions, result, config); ApplyRequiredElements(definitions, result, config); - result.DifficultyScore = config.Round(result.DifficultyScore); - result.PerformanceScore = config.Round(result.PerformanceScore); - result.RequiredScore = config.Round(result.RequiredScore); - result.DeductionScore = config.Round(result.DeductionScore); + // 花样赛的 D/P/Q/M 需要继续参与跨裁判乘法,不能在单张评分单阶段提前按最终展示精度取整。 + // 尤其失误第 2 档为 0.075,提前保留两位会改变 M。规定赛仍沿用原有两位小数口径。 + if (!config.IsFactorTotal) + { + result.DifficultyScore = config.Round(result.DifficultyScore); + result.PerformanceScore = config.Round(result.PerformanceScore); + result.RequiredScore = config.Round(result.RequiredScore); + result.DeductionScore = config.Round(result.DeductionScore); + } // 花样赛的单张评分单只提供本裁判的分项值,最终 R 由跨裁判聚合按 D×(1+P)×Q×M 计算。 result.TotalScore = config.IsFactorTotal ? config.Round(result.DifficultyScore + result.PerformanceScore + result.RequiredScore) @@ -297,7 +302,7 @@ public static class ScoreSheetCalculationService result.Steps.Add(new ScoreSheetStep { Code = $"DIM_{dimension.DimensionCode}", Label = dimension.Item.ItemName, - Formula = $"{Trim(dimension.BaseValue ?? 0m)} + 人工加 - 人工减 - 失误{Trim(failureCount)}次 × {Trim(dimension.DimensionWeight.Value)}", + Formula = $"{Trim(dimension.BaseValue ?? 0m)} + 人工加 - 人工减 - 失误{Trim(failureCount)}次", Value = value }); } @@ -332,7 +337,7 @@ public static class ScoreSheetCalculationService { Code = $"STEP_{definition.ItemCode}", Label = definition.Item.ItemName, Formula = string.Join(" + ", Enumerable.Range(0, count).Select(i => Trim(steps[Math.Min(i, steps.Count - 1)]))), - Value = config.Round(deduction) + Value = config.IsFactorTotal ? deduction : config.Round(deduction) }); } } diff --git a/YD_Event.Application/Workbench/WorkbenchController.cs b/YD_Event.Application/Workbench/WorkbenchController.cs index eaa4d4e..29a6065 100644 --- a/YD_Event.Application/Workbench/WorkbenchController.cs +++ b/YD_Event.Application/Workbench/WorkbenchController.cs @@ -1258,7 +1258,15 @@ public class WorkbenchController : IDynamicApiController var assignment = await _assignmentRepository.GetByIdAsync(correction.JudgeAssignmentId); if (assignment == null || assignment.DeleteMark) throw Oops.Bah("原裁判分配不存在,无法下发修正任务"); - + + var originalSheet = await _sheetRepository.GetByIdAsync(correction.OriginalScoreSheetId) + ?? throw Oops.Bah("原评分单不存在,无法下发修正任务"); + var originalTask = originalSheet.JudgeTaskId > 0 + ? await _taskRepository.GetByIdAsync(originalSheet.JudgeTaskId) + : null; + var session = await _sessionRepository.GetByIdAsync(correction.SessionId) + ?? throw Oops.Bah("比赛场次不存在,无法下发修正任务"); + var receiverUserId = await ResolveJudgeUserIdAsync(assignment, originalSheet); var task = new EventJudgeTask { Id = _idGenerator.NextId(), @@ -1268,12 +1276,17 @@ public class WorkbenchController : IDynamicApiController JudgeAssignmentId = correction.JudgeAssignmentId, EventRefereeId = assignment.EventRefereeId, RefereeId = assignment.RefereeId, - JudgeUserId = assignment.JudgeUserId, + JudgeUserId = receiverUserId, JudgeRole = assignment.JudgeRole, JudgeRoleType = assignment.JudgeRoleType, - TaskSnapshotJson = "{}", + ScoreRuleId = originalTask?.ScoreRuleId ?? session.ScoreRuleId, + RuleVersion = originalTask?.RuleVersion ?? originalSheet.RuleVersion, + TaskSnapshotJson = originalTask?.TaskSnapshotJson ?? "{}", TaskType = 1, - TaskStatus = 0, + TaskStatus = 10, + TaskVersion = (originalTask?.TaskVersion ?? 0) + 1, + OriginalTaskId = originalTask?.Id, + DispatchedTime = now, CreatedUserId = currentUserId, CreatedTime = now }; @@ -1283,18 +1296,18 @@ public class WorkbenchController : IDynamicApiController correction.CorrectionTaskId = task.Id; await _correctionRepository.UpdateAsync(correction); - if (assignment.JudgeUserId != null) + if (receiverUserId.HasValue) { var message = new EventJudgeMessage { Id = _idGenerator.NextId(), EventId = correction.EventId, - ReceiverUserId = assignment.JudgeUserId.Value, + ReceiverUserId = receiverUserId.Value, RefereeId = assignment.RefereeId, MessageType = 1, Title = "成绩修正任务通知", Content = $"您有一条成绩修正任务需要处理,申请原因:{correction.ApplyReason}", - RelationType = "ScoreCorrection", + RelationType = nameof(EventScoreCorrection), RelationId = correction.Id, IsRead = false, CreatedUserId = currentUserId, @@ -1323,6 +1336,8 @@ public class WorkbenchController : IDynamicApiController var entry = await _entryRepository.GetFirstAsync(e => e.Id == input.SessionEntryId && !e.DeleteMark) ?? throw Oops.Bah("出场记录不存在"); + var session = await _sessionRepository.GetByIdAsync(entry.SessionId) + ?? throw Oops.Bah("比赛场次不存在"); var sheetIds = input.ScoreSheetIds.Where(id => id > 0).Distinct().ToList(); if (sheetIds.Count == 0) throw Oops.Bah("请至少选择一名裁判"); @@ -1339,7 +1354,8 @@ public class WorkbenchController : IDynamicApiController throw Oops.Bah($"{notSubmitted.JudgeRole}号位评分单当前为“{GetSheetStatusName(notSubmitted.SheetStatus)}”,不能修正"); var pendingSheetIds = (await _correctionRepository.AsQueryable() - .Where(c => !c.DeleteMark && sheetIds.Contains(c.OriginalScoreSheetId) && c.CorrectionStatus < 20) + .Where(c => !c.DeleteMark && sheetIds.Contains(c.OriginalScoreSheetId) + && (c.CorrectionStatus == 0 || c.CorrectionStatus == 10 || c.CorrectionStatus == 30)) .Select(c => c.OriginalScoreSheetId).ToListAsync()).ToHashSet(); var pending = sheets.FirstOrDefault(s => pendingSheetIds.Contains(s.Id)); if (pending != null) @@ -1373,6 +1389,10 @@ public class WorkbenchController : IDynamicApiController }; await _correctionRepository.InsertAsync(correction); + var originalTask = sheet.JudgeTaskId > 0 + ? await _taskRepository.GetByIdAsync(sheet.JudgeTaskId) + : null; + var receiverUserId = await ResolveJudgeUserIdAsync(assignment, sheet); var task = new EventJudgeTask { Id = _idGenerator.NextId(), @@ -1382,12 +1402,17 @@ public class WorkbenchController : IDynamicApiController JudgeAssignmentId = correction.JudgeAssignmentId, EventRefereeId = assignment.EventRefereeId, RefereeId = assignment.RefereeId, - JudgeUserId = assignment.JudgeUserId, + JudgeUserId = receiverUserId, JudgeRole = assignment.JudgeRole, JudgeRoleType = assignment.JudgeRoleType, - TaskSnapshotJson = "{}", + ScoreRuleId = originalTask?.ScoreRuleId ?? session.ScoreRuleId, + RuleVersion = originalTask?.RuleVersion ?? sheet.RuleVersion, + TaskSnapshotJson = originalTask?.TaskSnapshotJson ?? "{}", TaskType = 1, - TaskStatus = 0, + TaskStatus = 10, + TaskVersion = (originalTask?.TaskVersion ?? 0) + 1, + OriginalTaskId = originalTask?.Id, + DispatchedTime = now, CreatedUserId = currentUserId, CreatedTime = now }; @@ -1397,18 +1422,18 @@ public class WorkbenchController : IDynamicApiController await _correctionRepository.UpdateAsync(correction); // 裁判未绑定小程序账号时消息无处投递,只保留修正记录,不阻断主流程 - if (assignment.JudgeUserId.HasValue) + if (receiverUserId.HasValue) { await _messageRepository.InsertAsync(new EventJudgeMessage { Id = _idGenerator.NextId(), EventId = correction.EventId, - ReceiverUserId = assignment.JudgeUserId.Value, + ReceiverUserId = receiverUserId.Value, RefereeId = assignment.RefereeId, MessageType = 1, Title = "成绩修正通知", Content = $"请对{assignment.JudgeRole}号位的评分重新提交,原因:{reason}", - RelationType = "ScoreCorrection", + RelationType = nameof(EventScoreCorrection), RelationId = correction.Id, IsRead = false, CreatedUserId = currentUserId, @@ -2056,6 +2081,20 @@ public class WorkbenchController : IDynamicApiController return reason; } + /// + /// Resolve the App user that currently owns a judge assignment. Older assignments may not + /// have JudgeUserId populated, while the referee profile or submitted sheet still has it. + /// + private async Task ResolveJudgeUserIdAsync(EventJudgeAssignment assignment, + EventJudgeScoreSheet? sheet = null) + { + var receiverUserId = sheet?.JudgeUserId ?? assignment.JudgeUserId; + if (receiverUserId.HasValue) return receiverUserId; + + var referee = await _refereeRepository.GetByIdAsync(assignment.RefereeId); + return referee?.AppUserId; + } + /// /// 同步成绩当前版本的状态,保证 EventResult 与 EventResultVersion 状态一致 /// diff --git a/YD_Event.Application/applicationsettings.json b/YD_Event.Application/applicationsettings.json index e449886..19a219b 100644 --- a/YD_Event.Application/applicationsettings.json +++ b/YD_Event.Application/applicationsettings.json @@ -99,7 +99,7 @@ // 微信小程序配置 "WeChat": { // 小程序码版本:develop=开发版,trial=体验版,release=正式版;上线前请改为 release - "MiniProgramEnvVersion": "develop", + "MiniProgramEnvVersion": "trial", "AppId": "wxf5a3f98d44c3a563", "Secret": "ef6d17e0419700c137e066aa3dce23ca" }, diff --git a/YD_Event.Core/InitData/scorerule.txt b/YD_Event.Core/InitData/scorerule.txt index c75ad90..488365d 100644 --- a/YD_Event.Core/InitData/scorerule.txt +++ b/YD_Event.Core/InitData/scorerule.txt @@ -42,7 +42,7 @@ "Id": 3300, "RuleCode": "ROPE_SHOWCASE", "RuleName": "表演赛计分规则", - "JudgeRoleSchemaJson": "[{\"title\":\"主裁判\",\"slots\":[{\"code\":\"T\",\"name\":\"主裁判-T\",\"min\":1,\"max\":1}]},{\"title\":\"难度裁判\",\"slots\":[{\"code\":\"DGA\",\"name\":\"难度裁判-A组裁判\",\"min\":1,\"max\":3,\"categories\":[\"DP+DM (个人绳)\",\"DA (车轮跳)\",\"DT (交互绳)\",\"DT (旅行跳)\"]},{\"code\":\"DGB\",\"name\":\"难度裁判-B组裁判\",\"min\":1,\"max\":3,\"categories\":[\"DR (个人绳)\",\"DB (车轮跳)\",\"DJ (交互绳)\",\"DL (旅行跳)\"]}]},{\"title\":\"表现裁判\",\"slots\":[{\"code\":\"P\",\"name\":\"表现裁判-P\",\"min\":1,\"max\":3}]}]", + "JudgeRoleSchemaJson": "[{\"title\":\"主裁判\",\"slots\":[{\"code\":\"T\",\"name\":\"主裁判-T\",\"min\":1,\"max\":1}]},{\"title\":\"难度裁判\",\"slots\":[{\"code\":\"DGA\",\"name\":\"难度裁判-A组裁判\",\"min\":1,\"max\":3,\"categories\":[\"DP+DM (个人绳)\",\"DA (车轮跳)\",\"DT (交互绳)\",\"DT (旅行跳)\"]},{\"code\":\"DGB\",\"name\":\"难度裁判-B组裁判\",\"min\":1,\"max\":3,\"categories\":[\"DR (个人绳)\",\"DB (车轮跳)\",\"DJ (交互绳)\",\"DL (长绳)\"]}]},{\"title\":\"表现裁判\",\"slots\":[{\"code\":\"P\",\"name\":\"表现裁判-P\",\"min\":1,\"max\":3}]}]", "RuleConfigJson": "{\"ruleType\":\"SHOWCASE\",\"totalMode\":\"factor\",\"baseScore\":0,\"scoreDecimals\":2,\"difficultyDivisor\":2,\"correctionNeedApproval\":false,\"roleAggregations\":[{\"roleType\":\"DGA\",\"symbol\":\"A\",\"label\":\"A组难度\",\"sourceField\":\"DifficultyScore\",\"targetField\":\"DifficultyScore\",\"aggregate\":\"avg\",\"sign\":1,\"factor\":\"D\",\"factorWeight\":1},{\"roleType\":\"DGB\",\"symbol\":\"B\",\"label\":\"B组难度\",\"sourceField\":\"DifficultyScore\",\"targetField\":\"DifficultyScore\",\"aggregate\":\"avg\",\"sign\":1,\"factor\":\"D\",\"factorWeight\":1},{\"roleType\":\"P\",\"symbol\":\"P\",\"label\":\"表现\",\"sourceField\":\"PerformanceScore\",\"targetField\":\"PerformanceScore\",\"aggregate\":\"avg\",\"sign\":1,\"factor\":\"P\",\"factorWeight\":0.05},{\"roleType\":\"T\",\"symbol\":\"Q\",\"label\":\"规定元素缺失\",\"sourceField\":\"RequiredMissingCount\",\"targetField\":\"RequiredScore\",\"aggregate\":\"max\",\"sign\":1,\"factor\":\"Q\",\"factorWeight\":0.05},{\"roleType\":\"T\",\"symbol\":\"M\",\"label\":\"扣分\",\"sourceField\":\"DeductionScore\",\"targetField\":\"DeductionScore\",\"aggregate\":\"sum\",\"sign\":-1,\"factor\":\"M\",\"factorWeight\":1}],\"tieBreakers\":[\"TotalScore\",\"-DeductionScore\",\"RequiredScore\",\"PerformanceScore\",\"DifficultyScore\"]}", "RuleVersion": 1, "Status": 0, @@ -51,4 +51,4 @@ "CreatedUserId": 1000, "CreatedTime": "2026-08-19T00:00:00" } -] \ No newline at end of file +] diff --git a/YD_Event.Core/InitData/scoreruleitem.txt b/YD_Event.Core/InitData/scoreruleitem.txt index cfa7ec7..5e0817c 100644 --- a/YD_Event.Core/InitData/scoreruleitem.txt +++ b/YD_Event.Core/InitData/scoreruleitem.txt @@ -3263,7 +3263,7 @@ "ItemName": "0 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 0.0, + "UnitValue": 1.0, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -3285,7 +3285,7 @@ "ItemName": "0.5 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 0.12, + "UnitValue": 1.2247, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -3307,7 +3307,7 @@ "ItemName": "1 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 0.15, + "UnitValue": 1.5, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -3329,7 +3329,7 @@ "ItemName": "2 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 0.23, + "UnitValue": 2.25, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -3351,7 +3351,7 @@ "ItemName": "3 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 0.34, + "UnitValue": 3.375, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -3373,7 +3373,7 @@ "ItemName": "4 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 0.51, + "UnitValue": 5.0625, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -3395,7 +3395,7 @@ "ItemName": "5 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 0.76, + "UnitValue": 7.5938, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -3417,7 +3417,7 @@ "ItemName": "6 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 1.14, + "UnitValue": 11.3906, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -3439,7 +3439,7 @@ "ItemName": "7 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 1.71, + "UnitValue": 17.0859, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -3461,7 +3461,7 @@ "ItemName": "8 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 2.56, + "UnitValue": 25.6289, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -4143,7 +4143,7 @@ "ItemName": "0 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 0.0, + "UnitValue": 1.0, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -4165,7 +4165,7 @@ "ItemName": "0.5 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 0.12, + "UnitValue": 1.2247, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -4187,7 +4187,7 @@ "ItemName": "1 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 0.15, + "UnitValue": 1.5, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -4209,7 +4209,7 @@ "ItemName": "2 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 0.23, + "UnitValue": 2.25, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -4231,7 +4231,7 @@ "ItemName": "3 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 0.34, + "UnitValue": 3.375, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -4253,7 +4253,7 @@ "ItemName": "4 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 0.51, + "UnitValue": 5.0625, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -4275,7 +4275,7 @@ "ItemName": "5 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 0.76, + "UnitValue": 7.5938, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -4297,7 +4297,7 @@ "ItemName": "6 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 1.14, + "UnitValue": 11.3906, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -4319,7 +4319,7 @@ "ItemName": "7 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 1.71, + "UnitValue": 17.0859, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -4341,7 +4341,7 @@ "ItemName": "8 级", "ItemType": 1, "ParentItemCode": null, - "UnitValue": 2.56, + "UnitValue": 25.6289, "MinValue": 0.0, "MaxValue": 50.0, "StepValue": 1.0, @@ -5059,4 +5059,4 @@ "CreatedUserId": 1000, "CreatedTime": "2026-08-19T00:00:00" } -] \ No newline at end of file +] diff --git a/二期需求/dbo.sql b/二期需求/dbo.sql index 5988054..c614e0e 100644 --- a/二期需求/dbo.sql +++ b/二期需求/dbo.sql @@ -747,19 +747,27 @@ BEGIN TRY /* ==================================================================================== [4/9] 插入数据 · 初始化种子(统一“存在则更新、缺失才插入”的幂等写法,可重复执行) - 顺序:4.1 计分规则(8条) -> 规则Id映射 -> 4.2 规则明细(334条) -> 4.3 角色 -> 4.4 账号管理按钮 -> 4.5 角色菜单授权 + 顺序:4.1 计分规则(8条) -> 规则Id映射 -> 4.2 规则明细(478条) -> 4.3 角色 -> 4.4 账号管理按钮 -> 4.5 角色菜单授权 ==================================================================================== */ PRINT N'[4/9] 插入数据:初始化计分规则、规则明细、角色与菜单'; /* 4.1 八条计分规则(固定Id:3000规定赛/3100个人花样/3200两人同步花样/3300四人同步花样/3400两人车轮跳花样/3500三人交互绳花样/3600四人交互绳花样/3700表演赛):先按 RuleCode 更新,再插入缺失,Id冲突则报错 */ CREATE TABLE #RuleSeed(SourceId BIGINT PRIMARY KEY,RuleCode NVARCHAR(64),RuleName NVARCHAR(128),JudgeRoleSchemaJson NVARCHAR(2000),RuleConfigJson NVARCHAR(4000),RuleVersion INT,Status INT,Sort INT,DeleteMark BIT,CreatedUserId BIGINT,CreatedTime DATETIME2(3)); INSERT #RuleSeed VALUES (3000,N'ROPE_PRESCRIBED',N'规定赛',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判","min":1,"max":1}]},{"title":"创意编排裁判","slots":[{"code":"CJ","name":"创意编排裁判","min":1,"max":3}]},{"title":"完成质量裁判","slots":[{"code":"CQ","name":"完成质量裁判","min":1,"max":3}]}]',N'{"ruleType":"PRESCRIBED","baseScore":100,"scoreDecimals":2,"deductionUnit":5,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"CJ","symbol":"T1","label":"创意分","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1},{"roleType":"CQ","symbol":"T2","label":"完成分","sourceField":"RequiredScore","targetField":"RequiredScore","aggregate":"avg","sign":1},{"roleType":"T","symbol":"T3","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1}],"tieBreakers":["TotalScore","RequiredScore","PerformanceScore"]}',1,0,1,0,1000,N'2026-08-19T00:00:00'), - (3100,N'ROPE_FREESTYLE_SINGLE',N'个人花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_SINGLE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"Q","label":"规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"max","sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,2,0,1000,N'2026-08-19T00:00:00'), - (3200,N'ROPE_FREESTYLE_DOUBLE_SYNC',N'两人同步花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_DOUBLE_SYNC","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"Q","label":"规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"max","sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,3,0,1000,N'2026-08-19T00:00:00'), - (3300,N'ROPE_FREESTYLE_QUAD_SYNC',N'四人同步花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_QUAD_SYNC","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"Q","label":"规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"max","sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,4,0,1000,N'2026-08-19T00:00:00'), + (3100,N'ROPE_FREESTYLE_SINGLE',N'个人花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_SINGLE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DP","symbol":"qP","label":"力量体操规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DM","symbol":"qM","label":"多摇规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DR","symbol":"qR","label":"绳子运用规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,2,0,1000,N'2026-08-19T00:00:00'), + (3200,N'ROPE_FREESTYLE_DOUBLE_SYNC',N'两人同步花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_DOUBLE_SYNC","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DP","symbol":"qP","label":"力量体操规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DM","symbol":"qM","label":"多摇规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DR","symbol":"qR","label":"绳子运用规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,3,0,1000,N'2026-08-19T00:00:00'), + (3300,N'ROPE_FREESTYLE_QUAD_SYNC',N'四人同步花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_QUAD_SYNC","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DP","symbol":"qP","label":"力量体操规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DM","symbol":"qM","label":"多摇规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DR","symbol":"qR","label":"绳子运用规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,4,0,1000,N'2026-08-19T00:00:00'), (3400,N'ROPE_FREESTYLE_WHEEL_PAIR',N'两人车轮跳花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DA","name":"难度裁判-DA(运动员A难度裁判)","min":1,"max":2},{"code":"DB","name":"难度裁判-DB(运动员B难度裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_WHEEL","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":2,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DA","symbol":"dA","label":"运动员A难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DB","symbol":"dB","label":"运动员B难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"Q","label":"规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"max","sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,5,0,1000,N'2026-08-19T00:00:00'), (3500,N'ROPE_FREESTYLE_WIRE_TRIPLE',N'三人交互绳花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DJ","name":"难度裁判-DJ(跳绳运动员难度裁判)","min":1,"max":2},{"code":"DT","name":"难度裁判-DT(摇绳运动员难度裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_WIRE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":1,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DJ","symbol":"dJ","label":"跳绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1.4},{"roleType":"DT","symbol":"dT","label":"摇绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.033},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","PerformanceScore","DifficultyScore"]}',1,0,6,0,1000,N'2026-08-19T00:00:00'), (3600,N'ROPE_FREESTYLE_WIRE_QUAD',N'四人交互绳花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DJ","name":"难度裁判-DJ(跳绳运动员难度裁判)","min":1,"max":2},{"code":"DT","name":"难度裁判-DT(摇绳运动员难度裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_WIRE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":1,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DJ","symbol":"dJ","label":"跳绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1.4},{"roleType":"DT","symbol":"dT","label":"摇绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.033},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","PerformanceScore","DifficultyScore"]}',1,0,7,0,1000,N'2026-08-19T00:00:00'), - (3700,N'ROPE_SHOWCASE',N'表演赛(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DGA","name":"难度裁判-A组裁判","min":1,"max":3,"categories":["DP+DM (个人绳)","DA (车轮跳)","DT (交互绳)","DT (旅行跳)"]},{"code":"DGB","name":"难度裁判-B组裁判","min":1,"max":3,"categories":["DR (个人绳)","DB (车轮跳)","DJ (交互绳)","DL (旅行跳)"]}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":3}]}]',N'{"ruleType":"SHOWCASE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":2,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DGA","symbol":"A","label":"A组难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DGB","symbol":"B","label":"B组难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"Q","label":"规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"max","sign":1,"factor":"Q","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,8,0,1000,N'2026-08-19T00:00:00'); + (3700,N'ROPE_SHOWCASE',N'表演赛(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DGA","name":"难度裁判-A组裁判","min":1,"max":3,"categories":["DP+DM (个人绳)","DA (车轮跳)","DT (交互绳)","DT (旅行跳)"]},{"code":"DGB","name":"难度裁判-B组裁判","min":1,"max":3,"categories":["DR (个人绳)","DB (车轮跳)","DJ (交互绳)","DL (长绳)"]}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":3}]}]',N'{"ruleType":"SHOWCASE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":2,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DGA","symbol":"A","label":"A组难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DGB","symbol":"B","label":"B组难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"Q","label":"规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"max","sign":1,"factor":"Q","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,8,0,1000,N'2026-08-19T00:00:00'); + + -- 两人/四人同步花样由主裁录入互动配合,缺失数 qI 与 DP/DM/DR 一同参与 Q。 + UPDATE #RuleSeed + SET RuleConfigJson=JSON_MODIFY( + RuleConfigJson, + N'append $.roleAggregations', + JSON_QUERY(N'{"roleType":"T","symbol":"qI","label":"互动配合规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025}')) + WHERE RuleCode IN (N'ROPE_FREESTYLE_DOUBLE_SYNC',N'ROPE_FREESTYLE_QUAD_SYNC'); UPDATE r SET RuleName=s.RuleName,JudgeRoleSchemaJson=s.JudgeRoleSchemaJson,RuleConfigJson=s.RuleConfigJson, RuleVersion=s.RuleVersion,Status=s.Status,Sort=s.Sort,DeleteMark=0,UpdatedUserId=1000,UpdatedTime=SYSUTCDATETIME() @@ -846,10 +854,10 @@ BEGIN TRY (3147,3100,N'T',N'T_FAILURE',N'失误',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode": "count", "unitLabel": "次", "stepDeductions": [0.05, 0.075, 0.1], "remark": "第1次扣0.05,第2次扣0.075,第3次起每次扣0.1"}',47,0,1000,N'2026-08-19T00:00:00'), (3148,3100,N'T',N'T_VIOLATION',N'违例',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode": "count", "unitLabel": "次"}',48,0,1000,N'2026-08-19T00:00:00'), (3149,3100,N'T',N'T_INTERVAL',N'间歇',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode": "count", "unitLabel": "次"}',49,0,1000,N'2026-08-19T00:00:00'), - (3150,3100,N'T',N'REQ_STRENGTH_GYMNASTICS',N'力量和体操',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode": "count", "unitLabel": "个", "requiredAsCategory": true}',50,0,1000,N'2026-08-19T00:00:00'), - (3151,3100,N'T',N'REQ_MULTIPLE_ROPE',N'多摇',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode": "count", "unitLabel": "个", "requiredAsCategory": true}',51,0,1000,N'2026-08-19T00:00:00'), - (3152,3100,N'T',N'REQ_ROPE_MANIPULATION',N'绳子运用',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode": "count", "unitLabel": "个", "requiredAsCategory": true}',52,0,1000,N'2026-08-19T00:00:00'), - (3154,3100,N'T',N'REQUIRED_MISSING',N'规定元素缺失(个)',2,NULL,NULL,0,3,1,0,1,0,0,N'{"inputMode": "score", "isAuto": true, "unitLabel": "个", "requiredTarget": 3.0}',53,0,1000,N'2026-08-19T00:00:00'), + (3150,3100,N'DP',N'REQUIRED_N3_PLUS',N'3级及以上规定元素数',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',11,0,1000,N'2026-08-19T00:00:00'), + (3151,3100,N'DP',N'REQUIRED_N2_MINUS',N'2级及以下规定元素数',2,NULL,0.5,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',12,0,1000,N'2026-08-19T00:00:00'), + (3152,3100,N'DP',N'REQUIRED_MISSING',N'规定元素缺失(个)',2,NULL,NULL,0,4,1,0,1,0,0,N'{"inputMode":"score","isAuto":true,"unitLabel":"个","requiredTarget":4.0}',13,0,1000,N'2026-08-19T00:00:00'), + (3154,3100,N'DM',N'REQUIRED_N3_PLUS',N'3级及以上规定元素数',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',11,0,1000,N'2026-08-19T00:00:00'), (3155,3100,N'T',N'DQ_DISCIPLINE',N'违反赛场纪律',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,54,0,1000,N'2026-08-19T00:00:00'), (3156,3100,N'T',N'DQ_MEMBER_COUNT',N'参赛人员不符合规定(不足或超过)',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,55,0,1000,N'2026-08-19T00:00:00'), (3157,3100,N'T',N'DQ_NO_ROPE_SHOES',N'未穿跳绳鞋',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,56,0,1000,N'2026-08-19T00:00:00'), @@ -858,6 +866,11 @@ BEGIN TRY (3160,3100,N'T',N'DQ_ANTI_OLYMPIC',N'有悖奥林匹克精神的元素(描绘暴力、战争、宗教、色情有关的元素)',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,59,0,1000,N'2026-08-19T00:00:00'), (3161,3100,N'T',N'DQ_LATE_60S',N'运动员(队)被叫超过60秒未上场',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,60,0,1000,N'2026-08-19T00:00:00'), (3162,3100,N'T',N'DQ_TATTOO',N'显露纹身',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,61,0,1000,N'2026-08-19T00:00:00'), + (3163,3100,N'DM',N'REQUIRED_N2_MINUS',N'2级及以下规定元素数',2,NULL,0.5,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',12,0,1000,N'2026-08-19T00:00:00'), + (3164,3100,N'DM',N'REQUIRED_MISSING',N'规定元素缺失(个)',2,NULL,NULL,0,4,1,0,1,0,0,N'{"inputMode":"score","isAuto":true,"unitLabel":"个","requiredTarget":4.0}',13,0,1000,N'2026-08-19T00:00:00'), + (3165,3100,N'DR',N'REQUIRED_N3_PLUS',N'3级及以上规定元素数',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',11,0,1000,N'2026-08-19T00:00:00'), + (3166,3100,N'DR',N'REQUIRED_N2_MINUS',N'2级及以下规定元素数',2,NULL,0.5,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',12,0,1000,N'2026-08-19T00:00:00'), + (3167,3100,N'DR',N'REQUIRED_MISSING',N'规定元素缺失(个)',2,NULL,NULL,0,4,1,0,1,0,0,N'{"inputMode":"score","isAuto":true,"unitLabel":"个","requiredTarget":4.0}',13,0,1000,N'2026-08-19T00:00:00'), (3201,3200,N'DP',N'DIFF_LEVEL_0',N'0 级',1,NULL,0.0,0,50,1,0,0,1,0,N'{"inputMode": "count", "unitLabel": "个"}',1,0,1000,N'2026-08-19T00:00:00'), (3202,3200,N'DP',N'DIFF_LEVEL_0_5',N'0.5 级',1,NULL,0.12,0,50,1,0,0,1,0,N'{"inputMode": "count", "unitLabel": "个"}',2,0,1000,N'2026-08-19T00:00:00'), (3203,3200,N'DP',N'DIFF_LEVEL_1',N'1 级',1,NULL,0.15,0,50,1,0,0,1,0,N'{"inputMode": "count", "unitLabel": "个"}',3,0,1000,N'2026-08-19T00:00:00'), @@ -907,11 +920,11 @@ BEGIN TRY (3247,3200,N'T',N'T_FAILURE',N'失误',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode": "count", "unitLabel": "次", "stepDeductions": [0.05, 0.075, 0.1], "remark": "第1次扣0.05,第2次扣0.075,第3次起每次扣0.1"}',47,0,1000,N'2026-08-19T00:00:00'), (3248,3200,N'T',N'T_VIOLATION',N'违例',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode": "count", "unitLabel": "次"}',48,0,1000,N'2026-08-19T00:00:00'), (3249,3200,N'T',N'T_INTERVAL',N'间歇',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode": "count", "unitLabel": "次"}',49,0,1000,N'2026-08-19T00:00:00'), - (3250,3200,N'T',N'REQ_STRENGTH_GYMNASTICS',N'力量和体操',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode": "count", "unitLabel": "个", "requiredAsCategory": true}',50,0,1000,N'2026-08-19T00:00:00'), - (3251,3200,N'T',N'REQ_MULTIPLE_ROPE',N'多摇',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode": "count", "unitLabel": "个", "requiredAsCategory": true}',51,0,1000,N'2026-08-19T00:00:00'), - (3252,3200,N'T',N'REQ_ROPE_MANIPULATION',N'绳子运用',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode": "count", "unitLabel": "个", "requiredAsCategory": true}',52,0,1000,N'2026-08-19T00:00:00'), - (3253,3200,N'T',N'REQ_INTERACTION',N'互动配合',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode": "count", "unitLabel": "个", "requiredAsCategory": true}',53,0,1000,N'2026-08-19T00:00:00'), - (3254,3200,N'T',N'REQUIRED_MISSING',N'规定元素缺失(个)',2,NULL,NULL,0,4,1,0,1,0,0,N'{"inputMode": "score", "isAuto": true, "unitLabel": "个", "requiredTarget": 4.0}',54,0,1000,N'2026-08-19T00:00:00'), + (3250,3200,N'DP',N'REQUIRED_N3_PLUS',N'3级及以上规定元素数',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',11,0,1000,N'2026-08-19T00:00:00'), + (3251,3200,N'DP',N'REQUIRED_N2_MINUS',N'2级及以下规定元素数',2,NULL,0.5,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',12,0,1000,N'2026-08-19T00:00:00'), + (3252,3200,N'DP',N'REQUIRED_MISSING',N'规定元素缺失(个)',2,NULL,NULL,0,4,1,0,1,0,0,N'{"inputMode":"score","isAuto":true,"unitLabel":"个","requiredTarget":4.0}',13,0,1000,N'2026-08-19T00:00:00'), + (3253,3200,N'T',N'REQ_INTERACTION',N'互动配合',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',53,0,1000,N'2026-08-19T00:00:00'), + (3254,3200,N'DM',N'REQUIRED_N3_PLUS',N'3级及以上规定元素数',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',11,0,1000,N'2026-08-19T00:00:00'), (3255,3200,N'T',N'DQ_DISCIPLINE',N'违反赛场纪律',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,55,0,1000,N'2026-08-19T00:00:00'), (3256,3200,N'T',N'DQ_MEMBER_COUNT',N'参赛人员不符合规定(不足或超过)',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,56,0,1000,N'2026-08-19T00:00:00'), (3257,3200,N'T',N'DQ_NO_ROPE_SHOES',N'未穿跳绳鞋',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,57,0,1000,N'2026-08-19T00:00:00'), @@ -920,6 +933,12 @@ BEGIN TRY (3260,3200,N'T',N'DQ_ANTI_OLYMPIC',N'有悖奥林匹克精神的元素(描绘暴力、战争、宗教、色情有关的元素)',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,60,0,1000,N'2026-08-19T00:00:00'), (3261,3200,N'T',N'DQ_LATE_60S',N'运动员(队)被叫超过60秒未上场',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,61,0,1000,N'2026-08-19T00:00:00'), (3262,3200,N'T',N'DQ_TATTOO',N'显露纹身',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,62,0,1000,N'2026-08-19T00:00:00'), + (3263,3200,N'DM',N'REQUIRED_N2_MINUS',N'2级及以下规定元素数',2,NULL,0.5,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',12,0,1000,N'2026-08-19T00:00:00'), + (3264,3200,N'DM',N'REQUIRED_MISSING',N'规定元素缺失(个)',2,NULL,NULL,0,4,1,0,1,0,0,N'{"inputMode":"score","isAuto":true,"unitLabel":"个","requiredTarget":4.0}',13,0,1000,N'2026-08-19T00:00:00'), + (3265,3200,N'DR',N'REQUIRED_N3_PLUS',N'3级及以上规定元素数',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',11,0,1000,N'2026-08-19T00:00:00'), + (3266,3200,N'DR',N'REQUIRED_N2_MINUS',N'2级及以下规定元素数',2,NULL,0.5,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',12,0,1000,N'2026-08-19T00:00:00'), + (3267,3200,N'DR',N'REQUIRED_MISSING',N'规定元素缺失(个)',2,NULL,NULL,0,4,1,0,1,0,0,N'{"inputMode":"score","isAuto":true,"unitLabel":"个","requiredTarget":4.0}',13,0,1000,N'2026-08-19T00:00:00'), + (3268,3200,N'T',N'REQUIRED_MISSING',N'互动配合规定元素缺失(个)',2,NULL,NULL,0,4,1,0,1,0,0,N'{"inputMode":"score","isAuto":true,"unitLabel":"个","requiredTarget":4.0}',54,0,1000,N'2026-08-19T00:00:00'), (3301,3300,N'DP',N'DIFF_LEVEL_0',N'0 级',1,NULL,0.0,0,50,1,0,0,1,0,N'{"inputMode": "count", "unitLabel": "个"}',1,0,1000,N'2026-08-19T00:00:00'), (3302,3300,N'DP',N'DIFF_LEVEL_0_5',N'0.5 级',1,NULL,0.12,0,50,1,0,0,1,0,N'{"inputMode": "count", "unitLabel": "个"}',2,0,1000,N'2026-08-19T00:00:00'), (3303,3300,N'DP',N'DIFF_LEVEL_1',N'1 级',1,NULL,0.15,0,50,1,0,0,1,0,N'{"inputMode": "count", "unitLabel": "个"}',3,0,1000,N'2026-08-19T00:00:00'), @@ -969,11 +988,11 @@ BEGIN TRY (3347,3300,N'T',N'T_FAILURE',N'失误',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode": "count", "unitLabel": "次", "stepDeductions": [0.05, 0.075, 0.1], "remark": "第1次扣0.05,第2次扣0.075,第3次起每次扣0.1"}',47,0,1000,N'2026-08-19T00:00:00'), (3348,3300,N'T',N'T_VIOLATION',N'违例',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode": "count", "unitLabel": "次"}',48,0,1000,N'2026-08-19T00:00:00'), (3349,3300,N'T',N'T_INTERVAL',N'间歇',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode": "count", "unitLabel": "次"}',49,0,1000,N'2026-08-19T00:00:00'), - (3350,3300,N'T',N'REQ_STRENGTH_GYMNASTICS',N'力量和体操',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode": "count", "unitLabel": "个", "requiredAsCategory": true}',50,0,1000,N'2026-08-19T00:00:00'), - (3351,3300,N'T',N'REQ_MULTIPLE_ROPE',N'多摇',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode": "count", "unitLabel": "个", "requiredAsCategory": true}',51,0,1000,N'2026-08-19T00:00:00'), - (3352,3300,N'T',N'REQ_ROPE_MANIPULATION',N'绳子运用',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode": "count", "unitLabel": "个", "requiredAsCategory": true}',52,0,1000,N'2026-08-19T00:00:00'), - (3353,3300,N'T',N'REQ_INTERACTION',N'互动配合',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode": "count", "unitLabel": "个", "requiredAsCategory": true}',53,0,1000,N'2026-08-19T00:00:00'), - (3354,3300,N'T',N'REQUIRED_MISSING',N'规定元素缺失(个)',2,NULL,NULL,0,4,1,0,1,0,0,N'{"inputMode": "score", "isAuto": true, "unitLabel": "个", "requiredTarget": 4.0}',54,0,1000,N'2026-08-19T00:00:00'), + (3350,3300,N'DP',N'REQUIRED_N3_PLUS',N'3级及以上规定元素数',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',11,0,1000,N'2026-08-19T00:00:00'), + (3351,3300,N'DP',N'REQUIRED_N2_MINUS',N'2级及以下规定元素数',2,NULL,0.5,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',12,0,1000,N'2026-08-19T00:00:00'), + (3352,3300,N'DP',N'REQUIRED_MISSING',N'规定元素缺失(个)',2,NULL,NULL,0,4,1,0,1,0,0,N'{"inputMode":"score","isAuto":true,"unitLabel":"个","requiredTarget":4.0}',13,0,1000,N'2026-08-19T00:00:00'), + (3353,3300,N'T',N'REQ_INTERACTION',N'互动配合',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',53,0,1000,N'2026-08-19T00:00:00'), + (3354,3300,N'DM',N'REQUIRED_N3_PLUS',N'3级及以上规定元素数',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',11,0,1000,N'2026-08-19T00:00:00'), (3355,3300,N'T',N'DQ_DISCIPLINE',N'违反赛场纪律',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,55,0,1000,N'2026-08-19T00:00:00'), (3356,3300,N'T',N'DQ_MEMBER_COUNT',N'参赛人员不符合规定(不足或超过)',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,56,0,1000,N'2026-08-19T00:00:00'), (3357,3300,N'T',N'DQ_NO_ROPE_SHOES',N'未穿跳绳鞋',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,57,0,1000,N'2026-08-19T00:00:00'), @@ -982,6 +1001,12 @@ BEGIN TRY (3360,3300,N'T',N'DQ_ANTI_OLYMPIC',N'有悖奥林匹克精神的元素(描绘暴力、战争、宗教、色情有关的元素)',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,60,0,1000,N'2026-08-19T00:00:00'), (3361,3300,N'T',N'DQ_LATE_60S',N'运动员(队)被叫超过60秒未上场',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,61,0,1000,N'2026-08-19T00:00:00'), (3362,3300,N'T',N'DQ_TATTOO',N'显露纹身',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,62,0,1000,N'2026-08-19T00:00:00'), + (3363,3300,N'DM',N'REQUIRED_N2_MINUS',N'2级及以下规定元素数',2,NULL,0.5,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',12,0,1000,N'2026-08-19T00:00:00'), + (3364,3300,N'DM',N'REQUIRED_MISSING',N'规定元素缺失(个)',2,NULL,NULL,0,4,1,0,1,0,0,N'{"inputMode":"score","isAuto":true,"unitLabel":"个","requiredTarget":4.0}',13,0,1000,N'2026-08-19T00:00:00'), + (3365,3300,N'DR',N'REQUIRED_N3_PLUS',N'3级及以上规定元素数',2,NULL,1,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',11,0,1000,N'2026-08-19T00:00:00'), + (3366,3300,N'DR',N'REQUIRED_N2_MINUS',N'2级及以下规定元素数',2,NULL,0.5,0,50,1,0,0,3,0,N'{"inputMode":"count","unitLabel":"个"}',12,0,1000,N'2026-08-19T00:00:00'), + (3367,3300,N'DR',N'REQUIRED_MISSING',N'规定元素缺失(个)',2,NULL,NULL,0,4,1,0,1,0,0,N'{"inputMode":"score","isAuto":true,"unitLabel":"个","requiredTarget":4.0}',13,0,1000,N'2026-08-19T00:00:00'), + (3368,3300,N'T',N'REQUIRED_MISSING',N'互动配合规定元素缺失(个)',2,NULL,NULL,0,4,1,0,1,0,0,N'{"inputMode":"score","isAuto":true,"unitLabel":"个","requiredTarget":4.0}',54,0,1000,N'2026-08-19T00:00:00'), (3401,3400,N'DA',N'DIFF_LEVEL_0',N'0 级',1,NULL,0,0,50,1,0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"A"}',1,0,1000,N'2026-08-19T00:00:00'), (3402,3400,N'DA',N'DIFF_LEVEL_0_5',N'0.5 级',1,NULL,0.12,0,50,1,0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"A"}',2,0,1000,N'2026-08-19T00:00:00'), (3403,3400,N'DA',N'DIFF_LEVEL_1',N'1 级',1,NULL,0.15,0,50,1,0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"A"}',3,0,1000,N'2026-08-19T00:00:00'), @@ -1158,16 +1183,16 @@ BEGIN TRY (3728,3700,N'DGA',N'DT_INTERACTION_DIFF_LEVEL_6',N'6 级',1,NULL,1.14,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_INTERACTION","subjectName":"DT(交互绳)"}',28,0,1000,N'2026-08-19T00:00:00'), (3729,3700,N'DGA',N'DT_INTERACTION_DIFF_LEVEL_7',N'7 级',1,NULL,1.71,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_INTERACTION","subjectName":"DT(交互绳)"}',29,0,1000,N'2026-08-19T00:00:00'), (3730,3700,N'DGA',N'DT_INTERACTION_DIFF_LEVEL_8',N'8 级',1,NULL,2.56,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_INTERACTION","subjectName":"DT(交互绳)"}',30,0,1000,N'2026-08-19T00:00:00'), - (3731,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_0',N'0 级',1,NULL,0.0,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',31,0,1000,N'2026-08-19T00:00:00'), - (3732,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_0_5',N'0.5 级',1,NULL,0.12,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',32,0,1000,N'2026-08-19T00:00:00'), - (3733,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_1',N'1 级',1,NULL,0.15,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',33,0,1000,N'2026-08-19T00:00:00'), - (3734,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_2',N'2 级',1,NULL,0.23,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',34,0,1000,N'2026-08-19T00:00:00'), - (3735,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_3',N'3 级',1,NULL,0.34,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',35,0,1000,N'2026-08-19T00:00:00'), - (3736,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_4',N'4 级',1,NULL,0.51,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',36,0,1000,N'2026-08-19T00:00:00'), - (3737,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_5',N'5 级',1,NULL,0.76,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',37,0,1000,N'2026-08-19T00:00:00'), - (3738,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_6',N'6 级',1,NULL,1.14,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',38,0,1000,N'2026-08-19T00:00:00'), - (3739,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_7',N'7 级',1,NULL,1.71,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',39,0,1000,N'2026-08-19T00:00:00'), - (3740,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_8',N'8 级',1,NULL,2.56,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',40,0,1000,N'2026-08-19T00:00:00'), + (3731,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_0',N'0 级',1,NULL,1.0,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',31,0,1000,N'2026-08-19T00:00:00'), + (3732,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_0_5',N'0.5 级',1,NULL,1.2247,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',32,0,1000,N'2026-08-19T00:00:00'), + (3733,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_1',N'1 级',1,NULL,1.5,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',33,0,1000,N'2026-08-19T00:00:00'), + (3734,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_2',N'2 级',1,NULL,2.25,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',34,0,1000,N'2026-08-19T00:00:00'), + (3735,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_3',N'3 级',1,NULL,3.375,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',35,0,1000,N'2026-08-19T00:00:00'), + (3736,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_4',N'4 级',1,NULL,5.0625,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',36,0,1000,N'2026-08-19T00:00:00'), + (3737,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_5',N'5 级',1,NULL,7.5938,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',37,0,1000,N'2026-08-19T00:00:00'), + (3738,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_6',N'6 级',1,NULL,11.3906,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',38,0,1000,N'2026-08-19T00:00:00'), + (3739,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_7',N'7 级',1,NULL,17.0859,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',39,0,1000,N'2026-08-19T00:00:00'), + (3740,3700,N'DGA',N'DT_TRAVEL_DIFF_LEVEL_8',N'8 级',1,NULL,25.6289,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DT_TRAVEL","subjectName":"DT(旅行跳)"}',40,0,1000,N'2026-08-19T00:00:00'), (3741,3700,N'DGB',N'DR_DIFF_LEVEL_0',N'0 级',1,NULL,0.0,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DR","subjectName":"DR(个人绳)"}',41,0,1000,N'2026-08-19T00:00:00'), (3742,3700,N'DGB',N'DR_DIFF_LEVEL_0_5',N'0.5 级',1,NULL,0.12,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DR","subjectName":"DR(个人绳)"}',42,0,1000,N'2026-08-19T00:00:00'), (3743,3700,N'DGB',N'DR_DIFF_LEVEL_1',N'1 级',1,NULL,0.15,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DR","subjectName":"DR(个人绳)"}',43,0,1000,N'2026-08-19T00:00:00'), @@ -1198,16 +1223,16 @@ BEGIN TRY (3768,3700,N'DGB',N'DJ_DIFF_LEVEL_6',N'6 级',1,NULL,1.14,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DJ","subjectName":"DJ(交互绳)"}',68,0,1000,N'2026-08-19T00:00:00'), (3769,3700,N'DGB',N'DJ_DIFF_LEVEL_7',N'7 级',1,NULL,1.71,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DJ","subjectName":"DJ(交互绳)"}',69,0,1000,N'2026-08-19T00:00:00'), (3770,3700,N'DGB',N'DJ_DIFF_LEVEL_8',N'8 级',1,NULL,2.56,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DJ","subjectName":"DJ(交互绳)"}',70,0,1000,N'2026-08-19T00:00:00'), - (3771,3700,N'DGB',N'DL_DIFF_LEVEL_0',N'0 级',1,NULL,0.0,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',71,0,1000,N'2026-08-19T00:00:00'), - (3772,3700,N'DGB',N'DL_DIFF_LEVEL_0_5',N'0.5 级',1,NULL,0.12,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',72,0,1000,N'2026-08-19T00:00:00'), - (3773,3700,N'DGB',N'DL_DIFF_LEVEL_1',N'1 级',1,NULL,0.15,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',73,0,1000,N'2026-08-19T00:00:00'), - (3774,3700,N'DGB',N'DL_DIFF_LEVEL_2',N'2 级',1,NULL,0.23,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',74,0,1000,N'2026-08-19T00:00:00'), - (3775,3700,N'DGB',N'DL_DIFF_LEVEL_3',N'3 级',1,NULL,0.34,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',75,0,1000,N'2026-08-19T00:00:00'), - (3776,3700,N'DGB',N'DL_DIFF_LEVEL_4',N'4 级',1,NULL,0.51,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',76,0,1000,N'2026-08-19T00:00:00'), - (3777,3700,N'DGB',N'DL_DIFF_LEVEL_5',N'5 级',1,NULL,0.76,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',77,0,1000,N'2026-08-19T00:00:00'), - (3778,3700,N'DGB',N'DL_DIFF_LEVEL_6',N'6 级',1,NULL,1.14,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',78,0,1000,N'2026-08-19T00:00:00'), - (3779,3700,N'DGB',N'DL_DIFF_LEVEL_7',N'7 级',1,NULL,1.71,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',79,0,1000,N'2026-08-19T00:00:00'), - (3780,3700,N'DGB',N'DL_DIFF_LEVEL_8',N'8 级',1,NULL,2.56,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',80,0,1000,N'2026-08-19T00:00:00'), + (3771,3700,N'DGB',N'DL_DIFF_LEVEL_0',N'0 级',1,NULL,1.0,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',71,0,1000,N'2026-08-19T00:00:00'), + (3772,3700,N'DGB',N'DL_DIFF_LEVEL_0_5',N'0.5 级',1,NULL,1.2247,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',72,0,1000,N'2026-08-19T00:00:00'), + (3773,3700,N'DGB',N'DL_DIFF_LEVEL_1',N'1 级',1,NULL,1.5,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',73,0,1000,N'2026-08-19T00:00:00'), + (3774,3700,N'DGB',N'DL_DIFF_LEVEL_2',N'2 级',1,NULL,2.25,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',74,0,1000,N'2026-08-19T00:00:00'), + (3775,3700,N'DGB',N'DL_DIFF_LEVEL_3',N'3 级',1,NULL,3.375,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',75,0,1000,N'2026-08-19T00:00:00'), + (3776,3700,N'DGB',N'DL_DIFF_LEVEL_4',N'4 级',1,NULL,5.0625,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',76,0,1000,N'2026-08-19T00:00:00'), + (3777,3700,N'DGB',N'DL_DIFF_LEVEL_5',N'5 级',1,NULL,7.5938,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',77,0,1000,N'2026-08-19T00:00:00'), + (3778,3700,N'DGB',N'DL_DIFF_LEVEL_6',N'6 级',1,NULL,11.3906,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',78,0,1000,N'2026-08-19T00:00:00'), + (3779,3700,N'DGB',N'DL_DIFF_LEVEL_7',N'7 级',1,NULL,17.0859,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',79,0,1000,N'2026-08-19T00:00:00'), + (3780,3700,N'DGB',N'DL_DIFF_LEVEL_8',N'8 级',1,NULL,25.6289,0.0,50.0,1.0,0.0,0,1,0,N'{"inputMode":"count","unitLabel":"个","subjectCode":"DL","subjectName":"DL(长绳)"}',80,0,1000,N'2026-08-19T00:00:00'), (3781,3700,N'P',N'MUSIC_PLUS',N'音乐(加数量)',3,NULL,1.0,0.0,50.0,1.0,0.0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"MUSIC","adjustSign":1}',81,0,1000,N'2026-08-19T00:00:00'), (3782,3700,N'P',N'MUSIC_MINUS',N'音乐(减数量)',3,NULL,1.0,0.0,50.0,1.0,0.0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"MUSIC","adjustSign":-1}',82,0,1000,N'2026-08-19T00:00:00'), (3783,3700,N'P',N'MUSIC_SCORE',N'音乐',3,NULL,1.0,0.0,24.0,1.0,12.0,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"MUSIC","dimensionWeight":0.20,"baseValue":12.0}',83,0,1000,N'2026-08-19T00:00:00'), @@ -1449,7 +1474,7 @@ SELECT r.RuleCode,COUNT(i.Id) AS ItemCount FROM dbo.ScoreRule r LEFT JOIN dbo.Sc (N'INDEX',N'二期索引',CASE WHEN (SELECT COUNT(*) FROM sys.indexes WHERE name IN(N'UX_Referee_Mobile_Active',N'UX_EventReferee_Event_Referee_Active',N'UX_EventVenue_Event_Code_Active',N'UX_EventSession_Event_No_Active',N'UX_EventJudgeScoreSheet_Idempotency',N'UX_EventResultVersion_Result_Version'))=6 THEN 1 ELSE 0 END,N'6个关键索引'), (N'CONSTRAINT',N'二期外键',CASE WHEN (SELECT COUNT(*) FROM sys.foreign_keys WHERE name LIKE 'FK[_]%' AND parent_object_id IN(SELECT OBJECT_ID(N'dbo.'+QUOTENAME(Name)) FROM @ExpectedTables))>=20 THEN 1 ELSE 0 END,CONVERT(NVARCHAR(20),(SELECT COUNT(*) FROM sys.foreign_keys WHERE name LIKE 'FK[_]%' AND parent_object_id IN(SELECT OBJECT_ID(N'dbo.'+QUOTENAME(Name)) FROM @ExpectedTables)))), (N'SEED',N'计分规则',CASE WHEN (SELECT COUNT(DISTINCT r.RuleCode) FROM dbo.ScoreRule r JOIN #RuleSeed s ON s.RuleCode=r.RuleCode WHERE r.DeleteMark=0)=8 THEN 1 ELSE 0 END,N'期望8条'), - (N'SEED',N'计分规则明细',CASE WHEN (SELECT COUNT(*) FROM #ItemSeed s JOIN #RuleMap m ON m.SourceId=s.SourceRuleId JOIN dbo.ScoreRuleItem i ON i.ScoreRuleId=m.TargetId AND i.JudgeRoleType=s.JudgeRoleType AND i.ItemCode=s.ItemCode AND i.DeleteMark=0)=463 THEN 1 ELSE 0 END,N'期望463条'), + (N'SEED',N'计分规则明细',CASE WHEN (SELECT COUNT(*) FROM #ItemSeed s JOIN #RuleMap m ON m.SourceId=s.SourceRuleId JOIN dbo.ScoreRuleItem i ON i.ScoreRuleId=m.TargetId AND i.JudgeRoleType=s.JudgeRoleType AND i.ItemCode=s.ItemCode AND i.DeleteMark=0)=478 THEN 1 ELSE 0 END,N'期望478条'), (N'SEED',N'角色与菜单',CASE WHEN EXISTS(SELECT 1 FROM dbo.SysRole WHERE Id=1003 AND Code='scoringunit' AND DeleteMark=0) AND (SELECT COUNT(*) FROM dbo.SysMenu WHERE Id IN(1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,2010) AND DeleteMark=0)=12 AND EXISTS(SELECT 1 FROM dbo.SysMenu WHERE Id=1080 AND Code='system:unit' AND ParentId=1070 AND DeleteMark=0)