feat: improve record grouping and display

This commit is contained in:
Nedifinita
2025-09-26 21:21:37 +08:00
parent 77501af2f5
commit b1d8d5e029
2 changed files with 137 additions and 12 deletions

View File

@@ -459,23 +459,64 @@ class HistoryScreenState extends State<HistoryScreen> {
);
}
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 "";
}
}

View File

@@ -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 != "<NUL>" && !train.contains("-----");
final hasTrain =
train.isNotEmpty && train != "<NUL>" && !train.contains("-----");
final hasLoco = loco.isNotEmpty && loco != "<NUL>";
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 = <String, List<TrainRecord>>{};
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<Object> mixedList = [...mergedRecords, ...singleRecords];
mixedList.sort((a, b) {
@@ -82,4 +93,77 @@ class MergeService {
return mixedList;
}
static List<Object> _groupByTrainOrLoco(List<TrainRecord> records) {
final List<MergedTrainRecord> mergedRecords = [];
final Set<String> usedRecordIds = {};
for (int i = 0; i < records.length; i++) {
final record = records[i];
if (usedRecordIds.contains(record.uniqueId)) continue;
final group = <TrainRecord>[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 != "<NUL>" &&
!recordTrain.contains("-----") &&
otherTrain.isNotEmpty &&
otherTrain != "<NUL>" &&
!otherTrain.contains("-----") &&
recordTrain == otherTrain;
final locoMatch = recordLoco.isNotEmpty &&
recordLoco != "<NUL>" &&
otherLoco.isNotEmpty &&
otherLoco != "<NUL>" &&
recordLoco == otherLoco;
final bothTrainEmpty = (recordTrain.isEmpty ||
recordTrain == "<NUL>" ||
recordTrain.contains("----")) &&
(otherTrain.isEmpty ||
otherTrain == "<NUL>" ||
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<Object> 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;
}
}