feat: improve record grouping and display
This commit is contained in:
@@ -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(
|
String _getDifferingInfo(
|
||||||
TrainRecord record, TrainRecord latest, GroupBy groupBy) {
|
TrainRecord record, TrainRecord latest, GroupBy groupBy) {
|
||||||
final train = record.train.trim();
|
final train = record.train.trim();
|
||||||
final loco = record.loco.trim();
|
final loco = record.loco.trim();
|
||||||
|
final locoType = record.locoType.trim();
|
||||||
final latestTrain = latest.train.trim();
|
final latestTrain = latest.train.trim();
|
||||||
final latestLoco = latest.loco.trim();
|
final latestLoco = latest.loco.trim();
|
||||||
|
final latestLocoType = latest.locoType.trim();
|
||||||
|
|
||||||
switch (groupBy) {
|
switch (groupBy) {
|
||||||
case GroupBy.trainOnly:
|
case GroupBy.trainOnly:
|
||||||
return loco != latestLoco && loco.isNotEmpty ? loco : "";
|
if (loco != latestLoco && loco.isNotEmpty) {
|
||||||
|
return _formatLocoInfo(record);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
case GroupBy.locoOnly:
|
case GroupBy.locoOnly:
|
||||||
return train != latestTrain && train.isNotEmpty ? train : "";
|
return train != latestTrain && train.isNotEmpty ? train : "";
|
||||||
case GroupBy.trainOrLoco:
|
case GroupBy.trainOrLoco:
|
||||||
if (train.isNotEmpty && train != latestTrain) return train;
|
final trainDiff = train.isNotEmpty && train != latestTrain ? train : "";
|
||||||
if (loco.isNotEmpty && loco != latestLoco) return loco;
|
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 "";
|
return "";
|
||||||
case GroupBy.trainAndLoco:
|
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 "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ class MergeService {
|
|||||||
static String? _generateGroupKey(TrainRecord record, GroupBy groupBy) {
|
static String? _generateGroupKey(TrainRecord record, GroupBy groupBy) {
|
||||||
final train = record.train.trim();
|
final train = record.train.trim();
|
||||||
final loco = record.loco.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>";
|
final hasLoco = loco.isNotEmpty && loco != "<NUL>";
|
||||||
|
|
||||||
switch (groupBy) {
|
switch (groupBy) {
|
||||||
@@ -14,8 +15,13 @@ class MergeService {
|
|||||||
case GroupBy.locoOnly:
|
case GroupBy.locoOnly:
|
||||||
return hasLoco ? loco : null;
|
return hasLoco ? loco : null;
|
||||||
case GroupBy.trainOrLoco:
|
case GroupBy.trainOrLoco:
|
||||||
if (hasTrain) return train;
|
if (hasTrain && hasLoco) {
|
||||||
if (hasLoco) return loco;
|
return "train:$train|loco:$loco";
|
||||||
|
} else if (hasTrain) {
|
||||||
|
return "train:$train";
|
||||||
|
} else if (hasLoco) {
|
||||||
|
return "loco:$loco";
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
case GroupBy.trainAndLoco:
|
case GroupBy.trainAndLoco:
|
||||||
return (hasTrain && hasLoco) ? "${train}_$loco" : null;
|
return (hasTrain && hasLoco) ? "${train}_$loco" : null;
|
||||||
@@ -39,6 +45,13 @@ class MergeService {
|
|||||||
settings.timeWindow.duration!)
|
settings.timeWindow.duration!)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
|
validRecords
|
||||||
|
.sort((a, b) => b.receivedTimestamp.compareTo(a.receivedTimestamp));
|
||||||
|
|
||||||
|
if (settings.groupBy == GroupBy.trainOrLoco) {
|
||||||
|
return _groupByTrainOrLoco(validRecords);
|
||||||
|
}
|
||||||
|
|
||||||
final groupedRecords = <String, List<TrainRecord>>{};
|
final groupedRecords = <String, List<TrainRecord>>{};
|
||||||
for (final record in validRecords) {
|
for (final record in validRecords) {
|
||||||
final key = _generateGroupKey(record, settings.groupBy);
|
final key = _generateGroupKey(record, settings.groupBy);
|
||||||
@@ -52,13 +65,10 @@ class MergeService {
|
|||||||
|
|
||||||
groupedRecords.forEach((key, group) {
|
groupedRecords.forEach((key, group) {
|
||||||
if (group.length >= 2) {
|
if (group.length >= 2) {
|
||||||
group
|
|
||||||
.sort((a, b) => b.receivedTimestamp.compareTo(a.receivedTimestamp));
|
|
||||||
final latestRecord = group.first;
|
|
||||||
mergedRecords.add(MergedTrainRecord(
|
mergedRecords.add(MergedTrainRecord(
|
||||||
groupKey: key,
|
groupKey: key,
|
||||||
records: group,
|
records: group,
|
||||||
latestRecord: latestRecord,
|
latestRecord: group.first,
|
||||||
));
|
));
|
||||||
for (final record in group) {
|
for (final record in group) {
|
||||||
mergedRecordIds.add(record.uniqueId);
|
mergedRecordIds.add(record.uniqueId);
|
||||||
@@ -66,8 +76,9 @@ class MergeService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
final singleRecords =
|
final singleRecords = validRecords
|
||||||
allRecords.where((r) => !mergedRecordIds.contains(r.uniqueId)).toList();
|
.where((r) => !mergedRecordIds.contains(r.uniqueId))
|
||||||
|
.toList();
|
||||||
|
|
||||||
final List<Object> mixedList = [...mergedRecords, ...singleRecords];
|
final List<Object> mixedList = [...mergedRecords, ...singleRecords];
|
||||||
mixedList.sort((a, b) {
|
mixedList.sort((a, b) {
|
||||||
@@ -82,4 +93,77 @@ class MergeService {
|
|||||||
|
|
||||||
return mixedList;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user