51f4623b09ca611b6531aab6654eaea1e9b0b676
[pingpong.git] / Code / Projects / SmartPlugDetector / src / main / java / edu / uci / iotproject / evaluation / DetectionResultsAnalyzer.java
1 package edu.uci.iotproject.evaluation;
2
3 import edu.uci.iotproject.analysis.TriggerTrafficExtractor;
4 import edu.uci.iotproject.analysis.UserAction;
5 import edu.uci.iotproject.io.TriggerTimesFileReader;
6
7 import java.io.BufferedReader;
8 import java.io.File;
9 import java.io.FileReader;
10 import java.io.IOException;
11 import java.time.Instant;
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.Optional;
15
16 /**
17  * Utility for comparing detected events to logged (actual) events.
18  *
19  * @author Janus Varmarken {@literal <jvarmark@uci.edu>}
20  * @author Rahmadi Trimananda {@literal <rtrimana@uci.edu>}
21  */
22 public class DetectionResultsAnalyzer {
23
24     public static void main(String[] args) throws IOException {
25         // -------------------------------------- Parse the input files --------------------------------------
26
27         String triggerTimesFile = args[0];
28         // Read the trigger times.
29         // The trigger times file does not contain event types as we initially assumed that we would just be alternating
30         // between ON and OFF.
31         List<Instant> triggerTimestamps = new TriggerTimesFileReader().readTriggerTimes(triggerTimesFile, false);
32         // Now generate user actions based on this alternating ON/OFF pattern.
33         List<UserAction> triggers = new ArrayList<>();
34         for (int i = 0; i < triggerTimestamps.size(); i++) {
35             // NOTE: assumes triggers alternate between ON and OFF
36             UserAction.Type actionType = i % 2 == 0 ? UserAction.Type.TOGGLE_ON : UserAction.Type.TOGGLE_OFF;
37             triggers.add(new UserAction(actionType, triggerTimestamps.get(i)));
38         }
39         // Read the detection output file, assuming a format as specified in UserAction.toString()
40         File detectionOutputFile = new File(args[1]);
41         List<UserAction> detectedEvents = new ArrayList<>();
42         try (BufferedReader br = new BufferedReader(new FileReader(detectionOutputFile))) {
43             String s;
44             while ((s = br.readLine()) != null) {
45                 if (s.startsWith("#")) {
46                     // Ignore comments.
47                     continue;
48                 }
49                 detectedEvents.add(UserAction.fromString(s));
50             }
51         }
52
53         // -----------------  Now ready to compare the detected events with the logged events -----------------
54
55         // To contain all detected events that could be mapped to a trigger
56         List<UserAction> truePositives = new ArrayList<>();
57         for (UserAction detectedEvent : detectedEvents) {
58             Optional<UserAction> matchingTrigger = triggers.stream()
59                     .filter(t -> t.getType() == detectedEvent.getType() &&
60                             t.getTimestamp().isBefore(detectedEvent.getTimestamp()) &&
61                             t.getTimestamp().plusMillis(TriggerTrafficExtractor.INCLUSION_WINDOW_MILLIS).
62                                     isAfter(detectedEvent.getTimestamp())
63                     ).findFirst();
64             matchingTrigger.ifPresent(mt -> {
65                 // We've consumed the trigger (matched it with a detected event), so remove it so we don't match with
66                 // another detected event.
67                 triggers.remove(mt);
68                 // The current detected event was a true positive as we could match it with a trigger.
69                 truePositives.add(detectedEvent);
70             });
71         }
72         // Now the false positives are those elements in detectedEvents that are not in truePositives
73         List<UserAction> falsePositives = new ArrayList<>();
74         falsePositives.addAll(detectedEvents);
75         falsePositives.removeAll(truePositives);
76         // Print the results...
77         System.out.println("---------- False negatives (events that where not detected) ----------");
78         for (UserAction missing : triggers) {
79             System.out.println(missing);
80         }
81         System.out.println("Total of " + Integer.toString(triggers.size()));
82         System.out.println();
83         System.out.println("---------- False positives (detected, but no matching trigger) ----------");
84         for (UserAction fp : falsePositives) {
85             System.out.println(fp);
86         }
87         System.out.println("Total of " + Integer.toString(falsePositives.size()));
88     }
89
90 }