diff --git a/lib/core/models/scoring_task.dart b/lib/core/models/scoring_task.dart index 6c7c753..7552f98 100644 --- a/lib/core/models/scoring_task.dart +++ b/lib/core/models/scoring_task.dart @@ -61,7 +61,12 @@ class ScoringTask { final DateTime scheduledAt; final PrescribedEntryType prescribedEntryType; - String get displayOrder => orderNo.toString().padLeft(2, '0'); + String get displayOrder { + final sessionMatch = RegExp(r'第\s*(\d+)\s*场').firstMatch(session); + final sessionOrder = int.tryParse(sessionMatch?.group(1) ?? ''); + return (sessionOrder ?? orderNo).toString().padLeft(2, '0'); + } + String get venueLabel => '$fieldId-$displayOrder'; Map toJson() => { diff --git a/lib/core/network/api_models.dart b/lib/core/network/api_models.dart index e87a0e8..59410ce 100644 --- a/lib/core/network/api_models.dart +++ b/lib/core/network/api_models.dart @@ -187,6 +187,7 @@ class JudgeEntry { required this.sessionEntryId, required this.entryNo, required this.playOrder, + this.sessionOrder = 0, required this.participantName, required this.groupName, required this.entryStatus, @@ -202,6 +203,7 @@ class JudgeEntry { final String sessionEntryId; final String entryNo; final int playOrder; + final int sessionOrder; final String participantName; final String groupName; final int entryStatus; @@ -217,6 +219,7 @@ class JudgeEntry { sessionEntryId: _string(json['sessionEntryId']), entryNo: _string(json['entryNo']), playOrder: _int(json['playOrder']), + sessionOrder: _int(json['sessionOrder']), participantName: _string(json['participantName']), groupName: _string(json['groupName']), entryStatus: _int(json['entryStatus']), @@ -233,6 +236,7 @@ class JudgeEntry { 'sessionEntryId': sessionEntryId, 'entryNo': entryNo, 'playOrder': playOrder, + 'sessionOrder': sessionOrder, 'participantName': participantName, 'groupName': groupName, 'entryStatus': entryStatus, diff --git a/lib/core/network/remote_scoring_adapter.dart b/lib/core/network/remote_scoring_adapter.dart index a1b9014..048496b 100644 --- a/lib/core/network/remote_scoring_adapter.dart +++ b/lib/core/network/remote_scoring_adapter.dart @@ -70,8 +70,10 @@ abstract final class RemoteScoringAdapter { /// /// [JudgeEntry.playOrder] is the entry order inside an EventSession. The /// arrangement order identifies the first business session represented by - /// that EventSession, so both values are needed for a stable display number. + /// that EventSession. Newer APIs provide [JudgeEntry.sessionOrder] directly + /// so rematches can keep the source entry's business session number. static int sessionDisplayOrder(JudgeSession session, JudgeEntry entry) { + if (entry.sessionOrder > 0) return entry.sessionOrder; final playOrder = entry.playOrder > 0 ? entry.playOrder : 1; final arrangementOrder = session.arrangementOrder; return arrangementOrder > 0 && arrangementOrder < 0x7fffffff diff --git a/test/api_models_test.dart b/test/api_models_test.dart index c11022c..3d411fd 100644 --- a/test/api_models_test.dart +++ b/test/api_models_test.dart @@ -61,6 +61,7 @@ void main() { 'sessionEntryId': 201, 'entryNo': 'A01', 'playOrder': 1, + 'sessionOrder': 7, 'participantName': '跃动一队', 'groupName': '青年男子组', 'entryStatus': 30, @@ -148,6 +149,7 @@ void main() { expect(session.judgeRoleType, 'DP'); expect(entry.scoreStatusName, '草稿'); + expect(entry.sessionOrder, 7); expect(sheet.items.single.currentValue, 2); expect(sheet.sheetVersion, 2); expect(sheet.preview.steps.single.formula, '2×0.34'); diff --git a/test/remote_scoring_adapter_test.dart b/test/remote_scoring_adapter_test.dart index 3e170bc..331da22 100644 --- a/test/remote_scoring_adapter_test.dart +++ b/test/remote_scoring_adapter_test.dart @@ -297,6 +297,37 @@ void main() { ), '第2场-1号场地', ); + + const rematchEntry = JudgeEntry( + sessionEntryId: 'entry-3', + entryNo: '01-R', + playOrder: 3, + sessionOrder: 1, + participantName: '测试队', + groupName: '青年组', + entryStatus: 0, + isRematch: true, + scoreStatus: 0, + scoreStatusName: '待评分', + isDisqualified: false, + scoreSheetId: '', + ); + + expect( + RemoteScoringAdapter.sessionDisplayOrder(firstSession, rematchEntry), + 1, + ); + expect( + RemoteScoringAdapter.taskSessionVenueLabel(firstSession, rematchEntry), + '第1场-1号场地', + ); + final rematchTask = RemoteScoringAdapter.taskFor( + firstSession, + rematchEntry, + _sheet(role: 'DJ1', roleType: 'DJ'), + ); + expect(rematchTask.orderNo, 3); + expect(rematchTask.displayOrder, '01'); }); }