// Copyright 2012 Georg-August-Universität Göttingen, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package de.ugoe.cs.autoquest.commands.sequences; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List; import de.ugoe.cs.autoquest.CommandHelpers; import de.ugoe.cs.autoquest.SequenceInstanceOf; import de.ugoe.cs.autoquest.eventcore.Event; import de.ugoe.cs.autoquest.eventcore.IHierarchicalEventTarget; import de.ugoe.cs.autoquest.eventcore.gui.MouseButtonDown; import de.ugoe.cs.autoquest.eventcore.gui.MouseButtonInteraction; import de.ugoe.cs.autoquest.eventcore.gui.MouseClick; import de.ugoe.cs.autoquest.eventcore.gui.MouseDoubleClick; import de.ugoe.cs.autoquest.eventcore.gui.ValueSelection; import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement; import de.ugoe.cs.util.console.Command; import de.ugoe.cs.util.console.Console; import de.ugoe.cs.util.console.GlobalDataContainer; /** *

* TODO comment *

* * @author Patrick Harms * @version 1.0 */ public class CMDremoveEventDuplicates implements Command { /* * (non-Javadoc) * * @see de.ugoe.cs.util.console.Command#help() */ @Override public String help() { return "removeEventDuplicates {}"; } /* * (non-Javadoc) * * @see de.ugoe.cs.util.console.Command#run(java.util.List) */ @SuppressWarnings("unchecked") @Override public void run(List parameters) { String sequencesName; String newSequencesName; try { sequencesName = (String) parameters.get(0); if (parameters.size() > 1) { newSequencesName = (String) parameters.get(1); } else { newSequencesName = sequencesName; } } catch (Exception e) { throw new IllegalArgumentException("must provide a sequences name"); } Object dataObject = GlobalDataContainer.getInstance().getData(sequencesName); if (dataObject == null) { CommandHelpers.objectNotFoundMessage(sequencesName); return; } if (!SequenceInstanceOf.isCollectionOfSequences(dataObject)) { CommandHelpers.objectNotType(sequencesName, "Collection>>"); return; } Collection> newSequences = removeEventDuplicates((Collection>) dataObject); if (GlobalDataContainer.getInstance().addData(newSequencesName, newSequences)) { CommandHelpers.dataOverwritten(newSequencesName); } } /** * */ private Collection> removeEventDuplicates(Collection> sequences) { Collection> newSequences = new LinkedList>(); //long[] diffCounter = new long[1000]; //Map diffCounterForPairs = new HashMap<>(); int eventsRemoved = 0; for (List sequence : sequences) { Event predecessor = null; List result = new ArrayList(); System.out.println("sequence"); for (Event event : sequence) { long diff = (predecessor != null) ? (event.getTimestamp() - predecessor.getTimestamp()) : Long.MAX_VALUE; System.out.println(" " + event.getType() + "\t" + ((IHierarchicalEventTarget) event.getTarget()).getSpecification().toString() + "\t" + event.getTimestamp() + "\t" + diff); /*if (diff < diffCounter.length) { diffCounter[(int) diff]++; long[] specCounter = diffCounterForPairs.get(getKey(predecessor, event)); if (specCounter == null) { specCounter = new long[diffCounter.length]; diffCounterForPairs.put(getKey(predecessor, event), specCounter); } specCounter[(int) diff]++; }*/ // this border of 30 milliseconds was determined by plotting the time differences // and seeing that there is a real drop of time differences above 30 milliseconds. // And 30 milliseconds is still small enough to expect, that this is not triggered // by a human. if (diff < 30) { Event toPrefer = getEventToPrefer(predecessor, event); if (toPrefer != null) { result.set(result.size() - 1, toPrefer); eventsRemoved++; } else { // do not prefer any of them result.add(event); } } else { result.add(event); } predecessor = result.get(result.size() - 1); } newSequences.add(result); } /*for (int i = 0; i < diffCounter.length; i++) { System.out.print((i + 1) + "ms :\t "); for (int j = 0; j < diffCounter[i]; j = j + 10) { System.out.print('|'); } System.out.println(); } for (Map.Entry entry : diffCounterForPairs.entrySet()) { System.out.println("\n\n" + entry.getKey()); for (int i = 0; i < entry.getValue().length; i++) { if (entry.getValue()[i] > 0) { System.out.print((i + 1) + "ms :\t "); for (int j = 0; j < entry.getValue()[i]; j = j + 10) { System.out.print('|'); } System.out.println(); } } }*/ Console.println("removed " + eventsRemoved + " events"); return newSequences; } /** * */ /*private String getKey(Event event1, Event event2) { return event1.getType().getClass().getSimpleName() + " on " + event1.getTarget().getClass() + " --> " + event2.getType().getClass().getSimpleName() + " on " + event2.getTarget().getClass(); }*/ /** * */ private Event getEventToPrefer(Event event1, Event event2) { Event result = null; if (!isSameEventType(event1, event2)) { if (isSameEventTarget(event1, event2) || oneIsParentTargetOfOtherTarget(event1, event2)) { // in a combination of click and value selection on the same element or an element // and its parent, prefer the value selection as it is triggered by the click if (isLeftMouseButtonInteraction(event1) && isValueSelection(event2)) { result = event2; } else if (isLeftMouseButtonInteraction(event2) && isValueSelection(event1)) { result = event1; } } } return result; } /** * */ private boolean isSameEventType(Event event1, Event event2) { return event1.getType().getName().equals(event2.getType().getName()); } /** * */ private boolean isSameEventTarget(Event event1, Event event2) { return event1.getTarget().equals(event2.getTarget()); } /** * */ private boolean oneIsParentTargetOfOtherTarget(Event event1, Event event2) { if ((event1.getTarget() instanceof IGUIElement) && (event2.getTarget() instanceof IGUIElement)) { IGUIElement elem1 = (IGUIElement) event1.getTarget(); IGUIElement elem2 = (IGUIElement) event2.getTarget(); return isParent(elem1, elem2) || isParent(elem2, elem1); } return false; } /** * */ private boolean isParent(IGUIElement elem1, IGUIElement elem2) { IGUIElement parent = elem2.getParent(); while (parent != null) { if (parent.equals(elem1)) { return true; } parent = parent.getParent(); } return false; } /** * */ private boolean isLeftMouseButtonInteraction(Event event) { if (((event.getType() instanceof MouseClick) || (event.getType() instanceof MouseDoubleClick) || (event.getType() instanceof MouseButtonDown)) && (((MouseButtonInteraction) event.getType()).getButton() == MouseButtonInteraction.Button.LEFT)) { return true; } else { return false; } } /** * */ private boolean isValueSelection(Event event) { return event.getType() instanceof ValueSelection; } }