package cn.edu.sjtu.omnilab.syslogcleanser.ppefilter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class PPDetector2 {
public PPDetector2(){}
public static List<APRecord> removePingPong (
List<String> tmp_ap_list, List<Long> tmp_start_times,
List<Long> tmp_durations, List<Boolean> tmp_flags)
/*
* @Param: tmp_ap_list: sequence of APs with potential ping-pong
* @Param: tmp_start_times: sequence of AP session starting time aligned to AP list
* @Param: tmp_durations: sequence of AP durations aligned to AP list
* @Param: tmp_flags: sequence of AP flags that indicate to accumulate the AP duration or not.
*/
{
List<String> ap_list = tmp_ap_list;
List<Long> ap_start_time_list = tmp_start_times;
List<Long> ap_duration_list = tmp_durations;
List<Boolean> ap_flag_list = tmp_flags;
int ap_count = ap_duration_list.size();
if ( DebugFlag.debug ){
System.out.println("\nPing-pong len: " + ap_count);
for (int i=0; i<ap_count; i++) {
System.out.println(ap_list.get(i)+"\t"+ap_duration_list.get(i)+"\t"+ap_flag_list.get(i));
}
}
List<APRecord> filtered_records = new ArrayList<APRecord>();
List<PPPair> pp_pairs_list = new ArrayList<PPPair>();
if ( ap_count >= 3) {
// Only sequence of longer than 3 are processed...
// Step 1: find ping-pong pairs of AP sequence
for ( int i = 0; i< ap_count; i++) {
for ( int j = i+1; j< ap_count; j++) {
if ( ap_list.get(j).equals(ap_list.get(i))) {
if ( j-i < 4) {
pp_pairs_list.add(new PPPair(i, j-i));
}
break;
} else if ( j-i >= 4) {
break;
}
}
}
if (DebugFlag.debug) {
System.out.println("\nPing-pong pairs:");
for ( PPPair pair : pp_pairs_list){
System.out.println(pair.offset+","+(pair.offset+pair.distance)+" ");
}
}
// Step 2: merge several ping-pong pairs into ping-pong segment
/*
* For AP pair set {Pi | i > 0}, we define a valid ping-pong segment as:
* for any AP pair Pi, there is at least one Pj to make c(Pi, Pj) > 0, where
* c(.) is the function to calculate the coverage of two AP pairs.
* Here we define c(.) as dist(i) - |offset(i) - offset(j)| where i < j;
*/
List<List<PPPair>> pp_segment_list = new ArrayList<List<PPPair>>();
for ( PPPair candPair : pp_pairs_list){
boolean found = false;
for ( List<PPPair> pp_segment : pp_segment_list) {
for ( PPPair pp_pair: pp_segment ) {
if ( candPair.coverage(pp_pair) > 0) {
found = true;
break;
}
}
if ( found == true) {
pp_segment.add(candPair);
break;
}
}
if ( found == false) {
List<PPPair> new_segment = new ArrayList<PPPair>();
new_segment.add(candPair);
pp_segment_list.add(new_segment);
}
}
// Step 3: construct new AP sequence from ping-pong segments
List<PPPair> ppps = new ArrayList<PPPair>();
for ( List<PPPair> segment : pp_segment_list){
int new_head = ap_count+1;
int new_tail = 0;
for ( PPPair ppp : segment ) {
new_head = (ppp.offset < new_head) ? ppp.offset : new_head;
new_tail = ppp.offset+ppp.distance > new_tail ? ppp.offset+ppp.distance : new_tail;
}
ppps.add(new PPPair(new_head, new_tail-new_head));
}
if (DebugFlag.debug) {
System.out.println("\nMerged ping-pong segments:");
for ( PPPair pair : ppps){
System.out.println(pair.offset+","+(pair.offset+pair.distance)+" ");
}
}
for ( PPPair pair : ppps ){
String fap_name = "";
//****************************************
// To generate final AP name as concatenating
// all present APs
Set<String> fap_name_set = new HashSet<String>();
//****************************************
//****************************************
// To generate final AP name as the AP with
// longest duration
// Map<String, Long> fap_name_map = new HashMap();
//****************************************
// start time
long fap_start_time = -1;
// duration
long fap_duration = 0;
for ( int i = pair.offset; i<=pair.offset + pair.distance; i++) {
// NOTE: we accumulate the durations from start to stop and without the
// stop, to avoid the repeated addition of the item when two segments
// have the covered number (==1)
String ap_name = ap_list.get(i);
boolean ap_flag = ap_flag_list.get(i);
long ap_start_time = ap_start_time_list.get(i);
long ap_duration = ap_duration_list.get(i);
//****************************************
// To generate final AP name as concatenating
// all present APs
fap_name_set.add(ap_name);
//****************************************
//****************************************
// To generate final AP name as the AP with
// longest duration.
// Accumulate duration time for each AP
// if ( fap_name_map.containsKey(ap_name) ){
// fap_name_map.put(ap_name, fap_name_map.get(ap_name) + ap_duration);
// } else {
// fap_name_map.put(ap_name, ap_duration);
// }
//****************************************
// Update Ping-ping start time
if ( fap_start_time == -1 && ap_flag == true )
fap_start_time = ap_start_time;
// Update flags
if ( ap_flag == true){
fap_duration += ap_duration;
ap_flag_list.set(i, false);
}
}
//****************************************
// To generate final AP name as concatenating
// all present APs
for ( String s : fap_name_set) {
if ( fap_name.equals(""))
fap_name += s;
else
fap_name += (","+s);
}
//****************************************
//****************************************
// To generate final AP name as the AP with
// longest duration.
// Accumulate duration time for each AP
// long longest_duration = -1;
// for ( String ap : fap_name_map.keySet()) {
// if ( fap_name_map.get(ap) >= longest_duration ){
// fap_name = ap;
// longest_duration = fap_name_map.get(ap);
// }
// }
//****************************************
// Add this new record
filtered_records.add(new APRecord(fap_name, fap_start_time, fap_duration));
if (DebugFlag.debug){
System.out.println("Merged result:");
System.out.println(fap_name+"\t"+fap_start_time+"\t"+fap_duration);
}
}
}
// Add the left records which are not contained by the ping-pong segments
for ( int j=0; j<ap_flag_list.size(); j++)
if ( ap_flag_list.get(j) == true)
filtered_records.add(new APRecord(ap_list.get(j), ap_start_time_list.get(j), ap_duration_list.get(j)));
// Order the records by start_time
Collections.sort(filtered_records,new Comparator<APRecord>(){
public int compare(APRecord arg0, APRecord arg1) {
return new Long(arg0.start_time).compareTo(new Long(arg1.start_time));
}
});
return filtered_records;
}
}