From 00f7da64e2dec75ee090fefd8c70ebfc7089b9a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E6=A2=93=E5=BD=AD?= Date: Thu, 8 Oct 2026 15:55:07 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=AA=E4=BA=BA=E8=8A=B1=E6=A0=B7=E8=AE=A1?= =?UTF-8?q?=E7=AE=97=E9=80=BB=E8=BE=91=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controllers/scoring_controller.dart | 13 ++++---- lib/modules/scoring/views/scoring_page.dart | 27 +++++----------- test/competition_rule_calculator_test.dart | 32 ++++++++----------- test/scoring_dialogs_test.dart | 19 +++++++++++ 4 files changed, 47 insertions(+), 44 deletions(-) diff --git a/lib/modules/scoring/controllers/scoring_controller.dart b/lib/modules/scoring/controllers/scoring_controller.dart index dc0348c..80be93d 100644 --- a/lib/modules/scoring/controllers/scoring_controller.dart +++ b/lib/modules/scoring/controllers/scoring_controller.dart @@ -802,13 +802,10 @@ class ScoringController extends GetxController { int performanceMinusCount(String item) => performanceMinusCounts[item] ?? 0; - /// 个人及同步花样的减数量仅显示人工减;公式另外扣一次失误。 - int get performanceLinkedErrorCount => - profile.competition == CompetitionKind.individual - ? 0 - : performanceErrorCount.value; + /// 页面减数量同时展示人工减与失误联动减;持久化时仍分开保存,避免重复扣分。 + int get performanceLinkedErrorCount => performanceErrorCount.value; - /// 其他花样项目仍展示人工减号与失误自动减号之和。 + /// 所有花样项目展示人工减号与失误自动减号之和。 int performanceEffectiveMinusCount(String item) => performanceMinusCount(item) + performanceLinkedErrorCount; @@ -836,7 +833,9 @@ class ScoringController extends GetxController { } void setPerformanceEffectiveMinusCount(String item, int count) { - performanceMinusCounts[item] = count.clamp(0, 50).toInt(); + performanceMinusCounts[item] = (count - performanceLinkedErrorCount) + .clamp(0, 50) + .toInt(); _syncPerformanceItemScore(item); recalculate(); } diff --git a/lib/modules/scoring/views/scoring_page.dart b/lib/modules/scoring/views/scoring_page.dart index c7e2116..b4e3226 100644 --- a/lib/modules/scoring/views/scoring_page.dart +++ b/lib/modules/scoring/views/scoring_page.dart @@ -674,6 +674,7 @@ class _DifficultyPanel extends StatelessWidget { : () async { final value = await showQuantityPicker( current: entry.value, + includeZero: true, ); if (value != null) { controller.setDifficultyCount(entry.key, value); @@ -788,6 +789,7 @@ class _DifficultyPanel extends StatelessWidget { : () async { final value = await showQuantityPicker( current: entry.value, + includeZero: true, ); if (value != null) { controller.setDifficultyCount(entry.key, value); @@ -1177,17 +1179,8 @@ class _PerformancePanel extends StatelessWidget { children: [ _PerformanceMarkCount( value: minusCount, - semanticLabel: - controller.profile.competition == - CompetitionKind.individual - ? '${entry.key}人工减数量' - : '${entry.key}减数量(含失误自动扣减)', - color: - hasErrors && - controller.profile.competition != - CompetitionKind.individual - ? AppColors.danger - : AppColors.primary, + semanticLabel: '${entry.key}减数量(含失误自动扣减)', + color: hasErrors ? AppColors.danger : AppColors.primary, onTap: controller.isReadOnly ? null : () async { @@ -2453,21 +2446,17 @@ List _submissionScoreDetails( ), ]; case ScoreRole.presentation: - final isIndividual = - controller.profile.competition == CompetitionKind.individual; return [ for (final item in controller.performanceItems.keys) SubmissionScoreDetail( label: item, - description: isIndividual - ? '人工减 ${controller.performanceMinusCount(item)} / 加 ${controller.performancePlusCount(item)}' - : '人工减 ${controller.performanceMinusCount(item)}、失误自动减 ${controller.performanceErrorCount.value} / 加 ${controller.performancePlusCount(item)}', + description: + '人工减 ${controller.performanceMinusCount(item)}、失误自动减 ${controller.performanceErrorCount.value} / 加 ${controller.performancePlusCount(item)}', ), SubmissionScoreDetail( label: '失误', - description: isIndividual - ? '已记录 ${controller.performanceErrorCount.value} 次;不计入表现分,单独参与最终扣分' - : '已记录 ${controller.performanceErrorCount.value} 次,计分时从五个表现类别各减去该次数', + description: + '已记录 ${controller.performanceErrorCount.value} 次,计分时从五个表现类别各减去该次数,并上传参与综合扣分', ), ]; case ScoreRole.creative: diff --git a/test/competition_rule_calculator_test.dart b/test/competition_rule_calculator_test.dart index b8b850c..24ff947 100644 --- a/test/competition_rule_calculator_test.dart +++ b/test/competition_rule_calculator_test.dart @@ -2,43 +2,39 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:yd_pattern_scoring_system/core/rule_engine/calculators/competition_rule_calculator.dart'; void main() { - test('个人花样失误独立记录,不改变表现维度分和未录入时的零分', () { + test('个人花样失误联动扣减五个表现维度', () { const plus = {'音乐': 3, '完成质量': 3}; const minus = {'音乐': 1}; final withoutFailure = CompetitionRuleCalculator.performanceRecordedRaw( plus, minusCounts: minus, errors: 0, - includeErrors: false, ); final withFailure = CompetitionRuleCalculator.performanceRecordedRaw( plus, minusCounts: minus, errors: 3, - includeErrors: false, ); - expect(withFailure, withoutFailure); + expect(withFailure, closeTo(withoutFailure - 3, .000001)); expect( CompetitionRuleCalculator.performanceRecordedRaw( const {}, minusCounts: const {}, errors: 3, - includeErrors: false, ), - 0, + 9, ); expect( CompetitionRuleCalculator.performanceItemScore( plusCount: 3, minusCount: 1, errors: 3, - includeErrors: false, ), - 14, + 11, ); }); - test('表现裁判未录入显示0,失误一次联动减号后再独立扣一次', () { + test('表现裁判未录入显示0,失误一次使五个维度各减一分', () { const empty = {}; expect( CompetitionRuleCalculator.performanceRecordedRaw( @@ -54,7 +50,7 @@ void main() { minusCounts: empty, errors: 1, ), - closeTo(10, .000001), + closeTo(11, .000001), ); }); @@ -65,18 +61,18 @@ void main() { errors: 1, ); - expect(score, closeTo(13.4, .0001)); + expect(score, closeTo(14.4, .0001)); }); test('表演赛表现裁判的手工减数量与失误次数分别扣减', () { final score = CompetitionRuleCalculator.performanceRaw( const {'音乐': 0, '完成质量': 0, '娱乐': 0, '创意': 0, '多样性': 0}, - // 页面减数量已含两次失误联动,再按公式单独扣两次失误。 + // minusCounts 只保存人工减,失误在公式中对每个维度扣一次。 minusCounts: const {'音乐': 1, '完成质量': 2, '娱乐': 2, '创意': 0, '多样性': 2}, errors: 2, ); - expect(score, closeTo(6.5, .000001)); + expect(score, closeTo(8.5, .000001)); }); test('单项表现分按12加加号减页面减数量再减失误并限制在0至24', () { @@ -86,7 +82,7 @@ void main() { minusCount: 2, errors: 2, ), - 9, + 11, ); expect( CompetitionRuleCalculator.performanceItemScore( @@ -106,7 +102,7 @@ void main() { ); }); - test('已有手工减数量时,失误联动减号及独立失误项均扣减', () { + test('已有人工减数量时,失误仍对每个维度扣减一次', () { final withoutError = CompetitionRuleCalculator.performanceRaw( const {'音乐': 3, '完成质量': 3, '娱乐': 3, '创意': 3, '多样性': 3}, minusCounts: const {'音乐': 2, '完成质量': 2, '娱乐': 2, '创意': 2, '多样性': 2}, @@ -118,17 +114,17 @@ void main() { errors: 2, ); expect(withoutError, closeTo(13, .000001)); - expect(withTwoErrors, closeTo(9, .000001)); + expect(withTwoErrors, closeTo(11, .000001)); }); - test('人工减2且失误2时页面减数量为4,单项按6分计算', () { + test('人工减2且失误2时页面减数量为4,单项按8分计算', () { expect( CompetitionRuleCalculator.performanceItemScore( plusCount: 0, minusCount: 2, errors: 2, ), - 6, + 8, ); }); diff --git a/test/scoring_dialogs_test.dart b/test/scoring_dialogs_test.dart index bca2048..9037077 100644 --- a/test/scoring_dialogs_test.dart +++ b/test/scoring_dialogs_test.dart @@ -18,4 +18,23 @@ void main() { expect(await result, 0); }); + + testWidgets('难度数量选择器可以选择并返回 0', (tester) async { + Get.testMode = true; + await tester.pumpWidget(const GetMaterialApp(home: Scaffold())); + + final result = showQuantityPicker( + current: 3, + maximum: 8, + includeZero: true, + ); + await tester.pumpAndSettle(); + + expect(find.text('0'), findsOneWidget); + await tester.tap(find.text('0')); + await tester.tap(find.text('确认选择')); + await tester.pumpAndSettle(); + + expect(await result, 0); + }); }