diff --git a/lib/screens/history_screen.dart b/lib/screens/history_screen.dart index 1d58bf5..f2ae913 100644 --- a/lib/screens/history_screen.dart +++ b/lib/screens/history_screen.dart @@ -459,23 +459,64 @@ class HistoryScreenState extends State { ); } + String _formatLocoInfo(TrainRecord record) { + final locoType = record.locoType.trim(); + final loco = record.loco.trim(); + + if (locoType.isNotEmpty && loco.isNotEmpty) { + final shortLoco = + loco.length > 5 ? loco.substring(loco.length - 5) : loco; + return "$locoType-$shortLoco"; + } else if (locoType.isNotEmpty) { + return locoType; + } else if (loco.isNotEmpty) { + return loco; + } + return ""; + } + String _getDifferingInfo( TrainRecord record, TrainRecord latest, GroupBy groupBy) { final train = record.train.trim(); final loco = record.loco.trim(); + final locoType = record.locoType.trim(); final latestTrain = latest.train.trim(); final latestLoco = latest.loco.trim(); + final latestLocoType = latest.locoType.trim(); switch (groupBy) { case GroupBy.trainOnly: - return loco != latestLoco && loco.isNotEmpty ? loco : ""; + if (loco != latestLoco && loco.isNotEmpty) { + return _formatLocoInfo(record); + } + return ""; case GroupBy.locoOnly: return train != latestTrain && train.isNotEmpty ? train : ""; case GroupBy.trainOrLoco: - if (train.isNotEmpty && train != latestTrain) return train; - if (loco.isNotEmpty && loco != latestLoco) return loco; + final trainDiff = train.isNotEmpty && train != latestTrain ? train : ""; + final locoDiff = loco.isNotEmpty && loco != latestLoco + ? _formatLocoInfo(record) + : ""; + + if (trainDiff.isNotEmpty && locoDiff.isNotEmpty) { + return "$trainDiff $locoDiff"; + } else if (trainDiff.isNotEmpty) { + return trainDiff; + } else if (locoDiff.isNotEmpty) { + return locoDiff; + } return ""; case GroupBy.trainAndLoco: + if (train.isNotEmpty && train != latestTrain) { + final locoInfo = _formatLocoInfo(record); + if (locoInfo.isNotEmpty) { + return "$train $locoInfo"; + } + return train; + } + if (loco.isNotEmpty && loco != latestLoco) { + return _formatLocoInfo(record); + } return ""; } } diff --git a/lib/services/merge_service.dart b/lib/services/merge_service.dart index 8665e01..4b7274b 100644 --- a/lib/services/merge_service.dart +++ b/lib/services/merge_service.dart @@ -5,7 +5,8 @@ class MergeService { static String? _generateGroupKey(TrainRecord record, GroupBy groupBy) { final train = record.train.trim(); final loco = record.loco.trim(); - final hasTrain = train.isNotEmpty && train != "" && !train.contains("-----"); + final hasTrain = + train.isNotEmpty && train != "" && !train.contains("-----"); final hasLoco = loco.isNotEmpty && loco != ""; switch (groupBy) { @@ -14,8 +15,13 @@ class MergeService { case GroupBy.locoOnly: return hasLoco ? loco : null; case GroupBy.trainOrLoco: - if (hasTrain) return train; - if (hasLoco) return loco; + if (hasTrain && hasLoco) { + return "train:$train|loco:$loco"; + } else if (hasTrain) { + return "train:$train"; + } else if (hasLoco) { + return "loco:$loco"; + } return null; case GroupBy.trainAndLoco: return (hasTrain && hasLoco) ? "${train}_$loco" : null; @@ -39,6 +45,13 @@ class MergeService { settings.timeWindow.duration!) .toList(); + validRecords + .sort((a, b) => b.receivedTimestamp.compareTo(a.receivedTimestamp)); + + if (settings.groupBy == GroupBy.trainOrLoco) { + return _groupByTrainOrLoco(validRecords); + } + final groupedRecords = >{}; for (final record in validRecords) { final key = _generateGroupKey(record, settings.groupBy); @@ -52,13 +65,10 @@ class MergeService { groupedRecords.forEach((key, group) { if (group.length >= 2) { - group - .sort((a, b) => b.receivedTimestamp.compareTo(a.receivedTimestamp)); - final latestRecord = group.first; mergedRecords.add(MergedTrainRecord( groupKey: key, records: group, - latestRecord: latestRecord, + latestRecord: group.first, )); for (final record in group) { mergedRecordIds.add(record.uniqueId); @@ -66,8 +76,9 @@ class MergeService { } }); - final singleRecords = - allRecords.where((r) => !mergedRecordIds.contains(r.uniqueId)).toList(); + final singleRecords = validRecords + .where((r) => !mergedRecordIds.contains(r.uniqueId)) + .toList(); final List mixedList = [...mergedRecords, ...singleRecords]; mixedList.sort((a, b) { @@ -82,4 +93,77 @@ class MergeService { return mixedList; } + + static List _groupByTrainOrLoco(List records) { + final List mergedRecords = []; + final Set usedRecordIds = {}; + + for (int i = 0; i < records.length; i++) { + final record = records[i]; + if (usedRecordIds.contains(record.uniqueId)) continue; + + final group = [record]; + usedRecordIds.add(record.uniqueId); + + for (int j = i + 1; j < records.length; j++) { + final otherRecord = records[j]; + if (usedRecordIds.contains(otherRecord.uniqueId)) continue; + + final recordTrain = record.train.trim(); + final otherTrain = otherRecord.train.trim(); + final recordLoco = record.loco.trim(); + final otherLoco = otherRecord.loco.trim(); + + final trainMatch = recordTrain.isNotEmpty && + recordTrain != "" && + !recordTrain.contains("-----") && + otherTrain.isNotEmpty && + otherTrain != "" && + !otherTrain.contains("-----") && + recordTrain == otherTrain; + + final locoMatch = recordLoco.isNotEmpty && + recordLoco != "" && + otherLoco.isNotEmpty && + otherLoco != "" && + recordLoco == otherLoco; + + final bothTrainEmpty = (recordTrain.isEmpty || + recordTrain == "" || + recordTrain.contains("----")) && + (otherTrain.isEmpty || + otherTrain == "" || + otherTrain.contains("----")); + + if (trainMatch || locoMatch || (bothTrainEmpty && locoMatch)) { + group.add(otherRecord); + usedRecordIds.add(otherRecord.uniqueId); + } + } + + if (group.length >= 2) { + mergedRecords.add(MergedTrainRecord( + groupKey: "train_or_loco_group", + records: group, + latestRecord: group.first, + )); + } + } + + final singleRecords = + records.where((r) => !usedRecordIds.contains(r.uniqueId)).toList(); + + final List result = [...mergedRecords, ...singleRecords]; + result.sort((a, b) { + final aTime = a is MergedTrainRecord + ? a.latestRecord.receivedTimestamp + : (a as TrainRecord).receivedTimestamp; + final bTime = b is MergedTrainRecord + ? b.latestRecord.receivedTimestamp + : (b as TrainRecord).receivedTimestamp; + return bTime.compareTo(aTime); + }); + + return result; + } }