can-log-tools/reader/src/main/java/com/rusefi/can/analysis/ByteRateOfChange.java

193 lines
6.5 KiB
Java
Raw Normal View History

2022-11-12 09:29:20 -08:00
package com.rusefi.can.analysis;
2022-11-10 15:12:02 -08:00
2022-11-12 09:29:20 -08:00
import com.rusefi.can.CANPacket;
2024-02-24 14:46:46 -08:00
import com.rusefi.can.DualSid;
2022-11-10 15:12:02 -08:00
2022-11-12 20:00:51 -08:00
import java.io.*;
2022-11-10 15:12:02 -08:00
import java.util.*;
public class ByteRateOfChange {
2022-11-12 18:12:54 -08:00
static class TraceFileMetaIndex {
2023-07-30 16:52:39 -07:00
final HashMap<ByteId, ByteStatistics> statistics = new HashMap<>();
2022-11-10 15:12:02 -08:00
2023-07-30 16:52:39 -07:00
final Set<Integer> SIDs = new HashSet<>();
2022-11-12 18:12:54 -08:00
}
2022-11-12 10:07:13 -08:00
2022-11-12 18:12:54 -08:00
public static TraceReport process(String reportDestinationFolder, String simpleFileName, List<CANPacket> packets) throws IOException {
TraceFileMetaIndex traceFileMetaIndex = calculateByteStatistics(packets);
2022-11-12 20:00:51 -08:00
writeByteReport(reportDestinationFolder, simpleFileName, traceFileMetaIndex);
2023-07-30 21:01:10 -07:00
return new TraceReport(packets, simpleFileName, traceFileMetaIndex.statistics);
2022-11-12 20:00:51 -08:00
}
private static void writeByteReport(String reportDestinationFolder, String simpleFileName, TraceFileMetaIndex traceFileMetaIndex) throws FileNotFoundException {
2023-10-06 18:17:18 -07:00
String byteChangesFolder = reportDestinationFolder + File.separator + "byte_changes";
new File(byteChangesFolder).mkdirs();
2022-11-12 18:12:54 -08:00
List<ByteStatistics> allStats = new ArrayList<>(traceFileMetaIndex.statistics.values());
2023-10-06 18:17:18 -07:00
allStats.sort((o1, o2) -> o2.getUniqueValuesCount() - o1.getUniqueValuesCount());
2022-11-10 15:12:02 -08:00
2023-10-06 18:17:18 -07:00
writeByteReport(allStats, byteChangesFolder + File.separator + simpleFileName + "byte_rate_of_changes_sorted_counter.txt");
2022-11-10 15:12:02 -08:00
2023-10-06 18:17:18 -07:00
allStats.sort(new Comparator<ByteStatistics>() {
@Override
public int compare(ByteStatistics o1, ByteStatistics o2) {
return o1.key.compareTo(o2.key);
}
});
writeByteReport(allStats, byteChangesFolder + File.separator + simpleFileName + "byte_rate_of_changes_sorted_index.txt");
2022-11-12 20:00:51 -08:00
}
2023-10-06 18:17:18 -07:00
private static void writeByteReport(List<ByteStatistics> allStats, String fileName) throws FileNotFoundException {
System.out.println(new Date() + " Writing byte report to " + fileName);
2023-10-06 18:17:18 -07:00
PrintStream ps = new PrintStream(new FileOutputStream(fileName, false));
2022-11-10 15:12:02 -08:00
for (ByteStatistics byteStatistics : allStats) {
ByteId key = byteStatistics.key;
2024-02-24 14:46:46 -08:00
ps.println(DualSid.dualSid(key.sid) + " byte " + key.getByteIndex() + " has " + byteStatistics.getUniqueValuesCount() + " unique value(s)");
2022-11-10 15:12:02 -08:00
}
2022-11-10 16:23:51 -08:00
ps.close();
2022-11-10 15:12:02 -08:00
}
2022-11-12 18:12:54 -08:00
private static TraceFileMetaIndex calculateByteStatistics(List<CANPacket> packets) {
TraceFileMetaIndex traceFileMetaIndex = new TraceFileMetaIndex();
for (CANPacket packet : packets) {
traceFileMetaIndex.SIDs.add(packet.getId());
2022-11-12 20:00:51 -08:00
for (int byteIndex = 0; byteIndex < packet.getData().length; byteIndex++) {
ByteId key = new ByteId(packet.getId(), byteIndex);
2022-11-12 18:12:54 -08:00
ByteStatistics stats = traceFileMetaIndex.statistics.computeIfAbsent(key, byteId -> new ByteStatistics(key));
2023-10-22 20:37:22 -07:00
stats.registerValue(packet.getData()[byteIndex]);
2022-11-12 18:12:54 -08:00
}
}
return traceFileMetaIndex;
}
private static double getDurationMs(List<CANPacket> packets) {
return packets.isEmpty() ? 0 : packets.get(packets.size() - 1).getTimeStamp() - packets.get(0).getTimeStamp();
}
2022-11-12 09:29:20 -08:00
public static class ByteStatistics {
2023-10-22 20:37:22 -07:00
private final HashSet<Integer> uniqueValues = new HashSet<>();
int totalTransitions;
2022-11-10 15:12:02 -08:00
private final ByteId key;
2023-10-22 20:37:22 -07:00
private int previousValue;
2022-11-10 15:12:02 -08:00
public ByteStatistics(ByteId key) {
this.key = key;
}
2023-10-06 18:17:18 -07:00
public int getUniqueValuesCount() {
2022-11-10 15:12:02 -08:00
return uniqueValues.size();
}
2023-11-12 14:20:04 -08:00
public HashSet<Integer> getUniqueValues() {
return uniqueValues;
}
2023-10-06 18:17:18 -07:00
public ByteId getKey() {
return key;
}
2022-11-10 15:12:02 -08:00
@Override
public String toString() {
return "ByteStatistics{" +
"counter=" + uniqueValues.size() +
2023-11-13 06:59:18 -08:00
", totalTransitions=" + totalTransitions +
2022-11-10 15:12:02 -08:00
", key=" + key +
'}';
}
2023-10-22 20:37:22 -07:00
public void registerValue(int value) {
if (!uniqueValues.isEmpty()) {
if (previousValue != value)
totalTransitions++;
}
previousValue = value;
uniqueValues.add(value);
}
2022-11-10 15:12:02 -08:00
}
2023-07-30 21:01:10 -07:00
public static class ByteId implements Comparable<ByteId> {
2022-11-10 15:12:02 -08:00
final int sid;
2023-10-22 20:13:55 -07:00
final int byteIndex;
2022-11-10 15:12:02 -08:00
2023-10-22 20:13:55 -07:00
public ByteId(int sid, int byteIndex) {
2022-11-10 15:12:02 -08:00
this.sid = sid;
2023-10-22 20:13:55 -07:00
this.byteIndex = byteIndex;
2022-11-10 15:12:02 -08:00
}
2023-01-11 13:20:44 -08:00
public String getLogKey() {
2024-02-24 14:46:46 -08:00
return DualSid.dualSid(sid) + "_byte_" + byteIndex + "_bit_" + (byteIndex * 8);
2022-11-11 22:53:31 -08:00
}
2022-11-10 15:12:02 -08:00
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ByteId byteId = (ByteId) o;
2023-10-22 20:13:55 -07:00
return sid == byteId.sid && byteIndex == byteId.byteIndex;
}
public int getByteIndex() {
return byteIndex;
2022-11-10 15:12:02 -08:00
}
@Override
public int hashCode() {
2023-10-22 20:13:55 -07:00
return Objects.hash(sid, byteIndex);
2022-11-10 15:12:02 -08:00
}
2023-01-01 23:08:45 -08:00
@Override
2023-07-30 21:01:10 -07:00
public int compareTo(ByteId o) {
2023-10-21 20:07:51 -07:00
ByteId other = o;
2023-01-01 23:08:45 -08:00
if (other.sid != sid)
return sid - other.sid;
2023-10-22 20:13:55 -07:00
return byteIndex - other.byteIndex;
2023-01-01 23:08:45 -08:00
}
2022-11-10 15:12:02 -08:00
@Override
public String toString() {
2022-11-11 23:12:28 -08:00
return getLogKey();
2022-11-10 15:12:02 -08:00
}
}
2022-11-10 16:23:51 -08:00
public static class TraceReport extends HashMap<ByteId, ByteStatistics> {
private final String simpleFileName;
private final HashMap<ByteId, ByteStatistics> statistics;
2022-11-12 10:07:13 -08:00
private final double durationMs;
2022-11-10 16:23:51 -08:00
2022-11-12 18:12:54 -08:00
public TraceReport(List<CANPacket> packets, String simpleFileName, HashMap<ByteId, ByteStatistics> statistics) {
2022-11-10 16:23:51 -08:00
this.simpleFileName = simpleFileName;
this.statistics = statistics;
2022-11-12 18:12:54 -08:00
this.durationMs = getDurationMs(packets);
2022-11-12 09:29:20 -08:00
}
String getSummary() {
2022-11-12 20:00:51 -08:00
return getSimpleFileName() + " (duration=" + (int) (durationMs / 1000) + "secs)";
2022-11-10 16:23:51 -08:00
}
public String getSimpleFileName() {
return simpleFileName;
}
public HashMap<ByteId, ByteStatistics> getStatistics() {
return statistics;
}
2022-11-10 20:38:46 -08:00
2023-11-13 06:59:18 -08:00
public void save(String file) throws IOException {
Writer w = new FileWriter(file);
for (Map.Entry<ByteId, ByteStatistics> e : statistics.entrySet()) {
w.append(e.getKey() + " " + e.getValue() + "\r\n");
}
}
2023-01-01 23:08:45 -08:00
}
}