Index: trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/ActionClassifier.java
===================================================================
--- trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/ActionClassifier.java	(revision 2162)
+++ trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/ActionClassifier.java	(revision 2162)
@@ -0,0 +1,60 @@
+//   Copyright 2015 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.usability;
+
+import de.ugoe.cs.autoquest.eventcore.Event;
+import de.ugoe.cs.autoquest.eventcore.gui.Scroll;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class ActionClassifier {
+
+    /**
+     * convenience method to classify an action as inefficient
+     */
+    public static boolean isInefficient(Event event) {
+        return (event.getType() instanceof Scroll) ||
+               ("headMoved".equals(event.getType().toString())) ||
+               ("headRotated".equals(event.getType().toString()));
+    }
+
+    /**
+     * convenience method to classify an event task instance as inefficient
+     */
+    public static boolean isInefficient(IEventTaskInstance eventTaskInstance) {
+        return isInefficient(eventTaskInstance.getEvent());
+    }
+
+    /**
+     * convenience method to classify an event task as inefficient
+     */
+    public static boolean isInefficient(IEventTask eventTask) {
+        for (ITaskInstance instance : eventTask.getInstances()) {
+            if (isInefficient((IEventTaskInstance) instance)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
Index: trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/CommonTaskRateRule.java
===================================================================
--- trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/CommonTaskRateRule.java	(revision 2146)
+++ trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/CommonTaskRateRule.java	(revision 2162)
@@ -15,5 +15,4 @@
 package de.ugoe.cs.autoquest.usability;
 
-import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -21,4 +20,5 @@
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
@@ -26,7 +26,10 @@
 import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskInstanceTraversingVisitor;
 import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance;
 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel;
 import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.TaskTreeUtils;
 
 /**
@@ -46,8 +49,12 @@
     public UsabilityEvaluationResult evaluate(ITaskModel taskModel) {
         SummaryStatistics statistics = new SummaryStatistics();
-        int allObserved = calculateStatistics(taskModel.getUserSessions(), statistics);
+        SummaryStatistics mpStatistics = new SummaryStatistics();
+        int allObserved = calculateStatistics
+            (taskModel.getUserSessions(), TaskTreeUtils.getMostProminentTasks(taskModel),
+             statistics, mpStatistics);
 
         UsabilityEvaluationResult results = new UsabilityEvaluationResult(taskModel);
-        analyzeStatistics(statistics, allObserved, results);
+        analyzeStatistics(statistics, false, allObserved, results);
+        analyzeStatistics(mpStatistics, true, allObserved, results);
 
         return results;
@@ -58,4 +65,5 @@
      */
     private void analyzeStatistics(SummaryStatistics         statistics,
+                                   boolean                   mostProminentSequencesOnly,
                                    int                       allObserved,
                                    UsabilityEvaluationResult results)
@@ -75,5 +83,12 @@
             if (intensity != null) {
                 Map<String, Object> parameters = new HashMap<String, Object>();
-                parameters.put("ratio", new DecimalFormat("#.##").format(mean * 10));
+                parameters.put("ratio", ((float) Math.round(mean * 100)) / 10);
+                
+                if (mostProminentSequencesOnly) {
+                    parameters.put("tasksType", "representative tasks");
+                }
+                else {
+                    parameters.put("tasksType", "tasks");
+                }
 
                 results.addSmell(intensity, UsabilitySmellDescription.COMMON_TASK_RATE, parameters);
@@ -87,7 +102,10 @@
      */
     private int calculateStatistics(List<IUserSession>      sessions,
-                                    final SummaryStatistics statistics)
+                                    final Set<ISequence>    mostProminentTasks,
+                                    final SummaryStatistics statistics,
+                                    final SummaryStatistics mpStatistics)
     {
         final LinkedList<ITaskInstance> rootNodes = new LinkedList<>();
+        final LinkedList<ITaskInstance> mpRootNodes = new LinkedList<>();
         final List<IEventTaskInstance> leafNodes = new ArrayList<>();
         
@@ -96,10 +114,34 @@
         for (IUserSession session : sessions) {
             rootNodes.clear();
+            mpRootNodes.clear();
             
             for (final ITaskInstance currentRoot : session) {
                 currentRoot.accept(new DefaultTaskInstanceTraversingVisitor() {
+                    private ITaskInstance currentMpRoot = null;
+ 
+                    @Override
+                    public void visit(ISequenceInstance sequenceInstance) {
+                        boolean currentInstancesIsMpRoot = false;
+                        if (mostProminentTasks.contains(sequenceInstance.getSequence())) {
+                            if (currentMpRoot == null) {
+                                currentMpRoot = sequenceInstance;
+                                currentInstancesIsMpRoot = true;
+                            }
+                            // else already detected most prominent root task
+                        }
+                        super.visit(sequenceInstance);
+                        
+                        if (currentInstancesIsMpRoot) {
+                            // if the current instance is also the root instance considering only
+                            // most prominent sequences, then reset the stored instance to null
+                            // after traversing this task
+                            currentMpRoot = null;
+                        }
+                    }
+
                     @Override
                     public void visit(IEventTaskInstance eventTaskInstance) {
                         rootNodes.add(currentRoot);
+                        mpRootNodes.add(currentMpRoot != null ? currentMpRoot : currentRoot);
                         leafNodes.add(eventTaskInstance);
 
@@ -109,4 +151,12 @@
                             while (rootNodes.size() >= 10) {
                                 rootNodes.removeFirst();
+                            }
+                        }
+                        
+                        if (mpRootNodes.size() >= 10) {
+                            mpStatistics.addValue(getTaskCoverageMeasure(mpRootNodes));
+                            
+                            while (mpRootNodes.size() >= 10) {
+                                mpRootNodes.removeFirst();
                             }
                         }
Index: trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/RequiredInefficientActionsRule.java
===================================================================
--- trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/RequiredInefficientActionsRule.java	(revision 2146)
+++ trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/RequiredInefficientActionsRule.java	(revision 2162)
@@ -17,11 +17,13 @@
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
 
-import de.ugoe.cs.autoquest.eventcore.Event;
-import de.ugoe.cs.autoquest.eventcore.gui.Scroll;
 import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskInstanceTraversingVisitor;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskTraversingVisitor;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
 import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
 import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
@@ -90,11 +92,13 @@
         for (ITask task : tasks) {
             if (task instanceof ISequence)  {
-                double[] ratios = getRatiosOfInefficientActionsInInstances((ISequence) task);
-                
-                for (int i = 0; i < ratios.length; i++) {
-                    if (ratios[i] > 0) {
-                        // there is at least on inefficient action
-                        inefficientActionRatios.put((ISequence) task, ratios);
-                        break;
+                if (countEfficientActions((ISequence) task) > 1) {
+                    double[] ratios = getRatiosOfInefficientActionsInInstances((ISequence) task);
+                    
+                    for (int i = 0; i < ratios.length; i++) {
+                        if (ratios[i] > 0) {
+                            // there is at least on inefficient action
+                            inefficientActionRatios.put((ISequence) task, ratios);
+                            break;
+                        }
                     }
                 }
@@ -103,4 +107,22 @@
         
         return inefficientActionRatios;
+    }
+
+    /**
+     * 
+     */
+    private int countEfficientActions(ISequence task) {
+        final List<IEventTask> efficientActions = new LinkedList<>();
+        
+        task.accept(new DefaultTaskTraversingVisitor() {
+            @Override
+            public void visit(IEventTask eventTask) {
+                if (!ActionClassifier.isInefficient(eventTask)) {
+                    efficientActions.add(eventTask);
+                }
+            }
+        });
+        
+        return efficientActions.size();
     }
 
@@ -131,5 +153,5 @@
             @Override
             public void visit(IEventTaskInstance eventTaskInstance) {
-                if (isInefficientAction(eventTaskInstance.getEvent())) {
+                if (ActionClassifier.isInefficient(eventTaskInstance.getEvent())) {
                     count[0]++;
                 }
@@ -143,10 +165,3 @@
     }
 
-    /**
-     *
-     */
-    private boolean isInefficientAction(Event event) {
-        return (event.getType() instanceof Scroll);
-    }
-
 }
Index: trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/TargetDistanceRule.java
===================================================================
--- trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/TargetDistanceRule.java	(revision 2146)
+++ trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/TargetDistanceRule.java	(revision 2162)
@@ -19,7 +19,8 @@
 import java.util.List;
 import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
-import de.ugoe.cs.autoquest.eventcore.IEventTarget;
-import de.ugoe.cs.autoquest.eventcore.gui.Scroll;
+import de.ugoe.cs.autoquest.eventcore.Event;
 import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement;
 import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskInstanceTraversingVisitor;
@@ -37,4 +38,8 @@
  */
 public class TargetDistanceRule implements UsabilityEvaluationRule {
+    
+    /** pattern for parsing target position parameter values */
+    private Pattern targetPositionPattern = Pattern.compile
+            ("\\(\\s*(-?\\d*(\\.\\d*)?),\\s*(-?\\d*(\\.\\d*)?),\\s*(-?\\d*(\\.\\d*)?)\\s*\\)");
 
     /*
@@ -78,15 +83,15 @@
      */
     private int[] getTargetDistance(ITaskInstance instance) {
-        List<IEventTarget> eventTargets = new LinkedList<IEventTarget>();
-        getEventTargets(instance, eventTargets);
-        int noOfGUIElements = eventTargets.size();
+        List<Event> events = new LinkedList<Event>();
+        getEvents(instance, events);
+        int noOfEvents = events.size();
         int distance = 0;
         
-        while (eventTargets.size() > 1) {
-            distance += getDistance(eventTargets.get(0), eventTargets.get(1));
-            eventTargets.remove(0);
+        while (events.size() > 1) {
+            distance += getDistance(events.get(0), events.get(1));
+            events.remove(0);
         }
         
-        return new int[] { noOfGUIElements, distance };
+        return new int[] { noOfEvents, distance };
     }
 
@@ -94,15 +99,43 @@
      *
      */
-    private int getDistance(IEventTarget eventTarget1, IEventTarget eventTarget2) {
-        if ((eventTarget1 instanceof IGUIElement) && (eventTarget2 instanceof IGUIElement)) {
-            return (int)
-                (1000 * (((IGUIElement) eventTarget1).getDistanceTo((IGUIElement) eventTarget2)));
+    private int getDistance(Event event1, Event event2) {
+        String location1 = event1.getParameter("targetPosition");
+        String location2 = event2.getParameter("targetPosition");
+        
+        if ((location1 != null) && (location2 != null)) {
+            Matcher matcher1 = targetPositionPattern.matcher(location1);
+            Matcher matcher2 = targetPositionPattern.matcher(location2);
+            if (matcher1.matches() && matcher2.matches()) {
+                try {
+                    double x =
+                        Double.parseDouble(matcher2.group(1)) - Float.parseFloat(matcher1.group(1));
+                    
+                    double y =
+                        Double.parseDouble(matcher2.group(3)) - Float.parseFloat(matcher1.group(3));
+                    
+                    double z =
+                        Double.parseDouble(matcher2.group(5)) - Float.parseFloat(matcher1.group(5));
+                    
+                    return (int) (100 * Math.sqrt(x*x + y*y + z*z));
+                }
+                catch (NumberFormatException e) {
+                    // ignore and just continue with other variants.
+                }
+            }
         }
-        else if (eventTarget1.equals(eventTarget2)) {
+        
+        if ((event1.getTarget() instanceof IGUIElement) &&
+            (event2.getTarget() instanceof IGUIElement))
+        {
+            IGUIElement target1 = (IGUIElement) event1.getTarget();
+            IGUIElement target2 = (IGUIElement) event2.getTarget();
+            return (int) (1000 * target1.getDistanceTo(target2));
+        }
+        
+        if (event1.getTarget().equals(event2.getTarget())) {
             return 0;
         }
-        else {
-            return 1000;
-        }
+        
+        return 1000;
     }
 
@@ -110,10 +143,10 @@
      *
      */
-    private void getEventTargets(ITaskInstance instance, final List<IEventTarget> eventTargets) {
+    private void getEvents(ITaskInstance instance, final List<Event> events) {
         instance.accept(new DefaultTaskInstanceTraversingVisitor() {
             @Override
             public void visit(IEventTaskInstance eventTaskInstance) {
-                if (!(eventTaskInstance.getEvent().getType() instanceof Scroll)) {
-                    eventTargets.add(eventTaskInstance.getEvent().getTarget());
+                if (!(ActionClassifier.isInefficient(eventTaskInstance.getEvent()))) {
+                    events.add(eventTaskInstance.getEvent());
                 }
             }
Index: trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/TaskRetryRule.java
===================================================================
--- trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/TaskRetryRule.java	(revision 2162)
+++ trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/TaskRetryRule.java	(revision 2162)
@@ -0,0 +1,172 @@
+//   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.usability;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskTraversingVisitor;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 16.07.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class TaskRetryRule implements UsabilityEvaluationRule {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.usability.UsabilityEvaluationRule#evaluate(TaskTree)
+     */
+    @Override
+    public UsabilityEvaluationResult evaluate(ITaskModel taskModel) {
+        UsabilityEvaluationResult results = new UsabilityEvaluationResult(taskModel);
+
+        Map<IIteration, Integer> smellingTasks = getTasksWithRetries(taskModel.getTasks());
+        analyzeTasksWithRetries(smellingTasks, results, taskModel);
+
+        return results;
+    }
+
+    /**
+     *
+     */
+    private void analyzeTasksWithRetries(Map<IIteration, Integer>  smellingTasks,
+                                         UsabilityEvaluationResult results,
+                                         ITaskModel                taskModel)
+    {
+
+        for (Map.Entry<IIteration, Integer> entry : smellingTasks.entrySet()) {
+            UsabilitySmellIntensity intensity =
+                UsabilitySmellIntensity.getIntensity(entry.getValue(), entry.getKey(), taskModel);
+
+            if (intensity != null) {
+                Map<String, Object> parameters = new HashMap<String, Object>();
+
+                int instances = 0;
+                int numberOfRepeatedInstances = 0;
+                int cummulativeRepetitions = 0;
+                
+                for (ITaskInstance instance : entry.getKey().getInstances()) {
+                    instances++;
+                    
+                    if (((IIterationInstance) instance).size() > 1) {
+                        numberOfRepeatedInstances++;
+                        cummulativeRepetitions += ((IIterationInstance) instance).size() - 1;
+                    }
+                }
+                
+                parameters.put("repeatedInstanceRatio",
+                               (((float) instances) / numberOfRepeatedInstances));
+                parameters.put("averageRepetitionRatio",
+                               (((float) cummulativeRepetitions) / numberOfRepeatedInstances));
+                parameters.put("task", entry.getKey().getMarkedTask());
+                
+                results.addSmell(entry.getKey().getMarkedTask(), intensity,
+                                 UsabilitySmellDescription.TASK_RETRIED, parameters);
+            }
+        }
+    }
+
+    /**
+     * 
+     */
+    private Map<IIteration, Integer> getTasksWithRetries(Collection<ITask> tasks) {
+        Map<IIteration, Integer> retryRatios = new HashMap<IIteration, Integer>();
+        
+        for (ITask task : tasks) {
+            if (isTaskOfConsideration(task))  {
+                int rate = getRetryRate((IIteration) task);
+                
+                if (rate > 0) {
+                    retryRatios.put((IIteration) task, rate);
+                }
+            }
+        }
+        
+        return retryRatios;
+    }
+
+    /**
+     * check if a task must be considered. A task is relevant, if it is an iteration of a sequence
+     * which has at least two non-inefficient actions as leaf nodes.
+     */
+    private boolean isTaskOfConsideration(ITask task) {
+        if (!(task instanceof IIteration)) {
+            return false;
+        }
+        
+        if (!(((IIteration) task).getMarkedTask() instanceof ISequence)) {
+            return false;
+        }
+        
+        ISequence childTask = (ISequence) ((IIteration) task).getMarkedTask();
+        
+        if ((childTask.getInstances() != null) && (childTask.getInstances().size() > 0)) {
+            return getSemanticActions(childTask).size() > 1;
+        }
+        else {
+            return false;
+        }
+    }
+
+    /**
+     * 
+     */
+    private List<IEventTask> getSemanticActions(ITask task) {
+        final List<IEventTask> semanticEventTasks = new LinkedList<>();
+
+        task.accept(new DefaultTaskTraversingVisitor() {
+            @Override
+            public void visit(IEventTask eventTask) {
+                if (!ActionClassifier.isInefficient(eventTask)) {
+                    semanticEventTasks.add(eventTask);
+                }
+            }
+
+        });
+
+        return semanticEventTasks;
+    }
+
+    /**
+     *
+     */
+    private int getRetryRate(IIteration task) {
+        if (task.getInstances().size() > 0) {
+            int numberOfRepetitions = 0;
+            for (ITaskInstance instance : task.getInstances()) {
+                numberOfRepetitions += ((IIterationInstance) instance).size() - 1;
+            }
+            
+            return numberOfRepetitions * getSemanticActions(task).size();
+        }
+        else {
+            return 0;
+        }
+    }
+}
Index: trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityEvaluationManager.java
===================================================================
--- trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityEvaluationManager.java	(revision 2146)
+++ trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityEvaluationManager.java	(revision 2162)
@@ -17,13 +17,19 @@
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
+import java.util.Set;
 import java.util.logging.Level;
 
+import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskInstanceTraversingVisitor;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
 import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
 import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship;
 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel;
 import de.ugoe.cs.util.console.Console;
@@ -58,4 +64,5 @@
         rules.add(new TargetDistanceRule());
         rules.add(new MissingFeedbackRule());
+        rules.add(new TaskRetryRule());
         rules.add(new DataEntryMethodChangeRule());
         rules.add(new CommonTaskRateRule());
@@ -73,16 +80,20 @@
      *
      */
-    public UsabilityEvaluationResult evaluateUsability(ITaskModel taskModel, int maxCount) {
+    public UsabilityEvaluationResult evaluateUsability(ITaskModel taskModel,
+                                                       int        maxCount,
+                                                       boolean    onlyMostRepresentative)
+    {
         Console.traceln(Level.INFO, "evaluating usability of task model " + taskModel);
 
         List<UsabilityEvaluationResult> interimResults = new ArrayList<UsabilityEvaluationResult>();
+        Set<ITask> mostRepresentativeTasks = null;
 
         for (UsabilityEvaluationRule rule : rules) {
             Console.traceln(Level.INFO, "\napplying rule " + rule.getClass().getSimpleName());
-            UsabilityEvaluationResult result = rule.evaluate(taskModel);
+            UsabilityEvaluationResult ruleResult = rule.evaluate(taskModel);
 
             Map<String, List<UsabilitySmell>> smellGroups = new HashMap<>();
             
-            for (UsabilitySmell smell : result.getAllSmells()) {
+            for (UsabilitySmell smell : ruleResult.getAllSmells()) {
                 List<UsabilitySmell> smellGroup = smellGroups.get(smell.getBriefDescription());
                 
@@ -99,15 +110,27 @@
                                 " usability smells of type \"" + smellGroup.getKey() + "\"");
                 
-                result = new UsabilityEvaluationResult(taskModel, smellGroup.getValue());
-                
-                checkDuplicates(result);
-                
-                if (maxCount < result.getAllSmells().size()) {
-                    Console.traceln(Level.INFO, "filtering for " + maxCount +
-                                    " smells of same type with highest event coverage.");
-                
+                ruleResult = new UsabilityEvaluationResult(taskModel, smellGroup.getValue());
+                
+                checkDuplicates(ruleResult);
+                
+                if ((onlyMostRepresentative) || (maxCount < ruleResult.getAllSmells().size())) {
                     LinkedList<UsabilitySmell> sortedSmells = new LinkedList<>();
                     
-                    for (UsabilitySmell smell : result.getAllSmells()) {
+                    if (onlyMostRepresentative) {
+                        Console.traceln(Level.INFO, "filtering for smells that refer to only most " +
+                                        "representative tasks.");
+                    }
+                    
+                    for (UsabilitySmell smell : ruleResult.getAllSmells()) {
+                        if (onlyMostRepresentative && (smell.getSmellingTask() != null)) {
+                            if (mostRepresentativeTasks == null) {
+                                mostRepresentativeTasks = getMostRepresentativeSequences(taskModel);
+                            }
+                            
+                            if (!mostRepresentativeTasks.contains(smell.getSmellingTask())) {
+                                continue;
+                            }
+                        }
+                        
                         ListIterator<UsabilitySmell> iterator = sortedSmells.listIterator();
 
@@ -116,5 +139,5 @@
                         while (iterator.hasNext()) {
                             if (iterator.next().getIntensity().getEventCoverage() <
-                                    smell.getIntensity().getEventCoverage())
+                                smell.getIntensity().getEventCoverage())
                             {
                                 iterator.previous();
@@ -129,4 +152,10 @@
                         }
                     
+                    }
+                    
+                    if (maxCount < ruleResult.getAllSmells().size()) {
+                        Console.traceln(Level.INFO, "filtering for " + maxCount +
+                                " smells of same type with highest event coverage.");
+                        
                         while (sortedSmells.size() > maxCount) {
                             sortedSmells.removeLast();
@@ -134,9 +163,10 @@
                     }
                 
-                    result = new UsabilityEvaluationResult(taskModel, sortedSmells);
-                    checkDuplicates(result);
-                }
-            
-                interimResults.add(result);
+                    Console.traceln(Level.INFO, sortedSmells.size() + " remaining.");
+                    ruleResult = new UsabilityEvaluationResult(taskModel, sortedSmells);
+                    checkDuplicates(ruleResult);
+                }
+            
+                interimResults.add(ruleResult);
             }
         }
@@ -147,4 +177,66 @@
 
         return result;
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param taskModel
+     * @return
+     */
+    private Set<ITask> getMostRepresentativeSequences(ITaskModel taskModel) {
+        Map<Integer, List<ISequence>> coverageCounts = new HashMap<>();
+        Map<ISequence, Set<IEventTaskInstance>> coverages = new HashMap<>();
+        int maxCoverage = 0;
+
+        for (ITask task : taskModel.getTasks()) {
+            if (task instanceof ISequence) {
+                final Set<IEventTaskInstance> coveredEvents = new HashSet<>();
+
+                for (ITaskInstance instance : task.getInstances()) {
+                    instance.accept(new DefaultTaskInstanceTraversingVisitor() {
+                        @Override
+                        public void visit(IEventTaskInstance eventTaskInstance) {
+                            coveredEvents.add(eventTaskInstance);
+                        }
+                    });
+                }
+
+                coverages.put((ISequence) task, coveredEvents);
+
+                List<ISequence> tasksWithSameCoverage = coverageCounts.get(coveredEvents.size());
+
+                if (tasksWithSameCoverage == null) {
+                    tasksWithSameCoverage = new LinkedList<>();
+                    coverageCounts.put(coveredEvents.size(), tasksWithSameCoverage);
+                }
+
+                tasksWithSameCoverage.add((ISequence) task);
+
+                maxCoverage = Math.max(maxCoverage, coveredEvents.size());
+            }
+        }
+
+        Set<ITask> mostRepresentativeSequences = new HashSet<>();
+
+        for (int i = maxCoverage; i > 0; i--) {
+            List<ISequence> sequencesWithSameCoverage = coverageCounts.get(i);
+
+            if (sequencesWithSameCoverage == null) {
+                continue;
+            }
+
+            for (ISequence sequence : sequencesWithSameCoverage) {
+                mostRepresentativeSequences.add(sequence);
+            }
+            
+            if ((100 * mostRepresentativeSequences.size() / coverages.size()) > 20) {
+                break;
+            }
+        }
+
+        return mostRepresentativeSequences;
     }
 
Index: trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityEvaluationResult.java
===================================================================
--- trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityEvaluationResult.java	(revision 2146)
+++ trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityEvaluationResult.java	(revision 2162)
@@ -15,4 +15,5 @@
 package de.ugoe.cs.autoquest.usability;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -29,6 +30,9 @@
  * @author 2012, last modified by $Author: pharms$
  */
-public class UsabilityEvaluationResult {
+public class UsabilityEvaluationResult implements Serializable {
     
+    /**  */
+    private static final long serialVersionUID = 1L;
+
     /** */
     private ITaskModel taskModel;
Index: trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilitySmell.java
===================================================================
--- trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilitySmell.java	(revision 2146)
+++ trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilitySmell.java	(revision 2162)
@@ -15,4 +15,7 @@
 package de.ugoe.cs.autoquest.usability;
 
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -26,5 +29,8 @@
  * @author 2012, last modified by $Author: pharms$
  */
-public class UsabilitySmell {
+public class UsabilitySmell implements Serializable {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
 
     /** */
@@ -39,4 +45,10 @@
     /** */
     private Map<String, Object> descriptionParameters;
+    
+    /** */
+    private List<String> tags;
+    
+    /** */
+    private ManualLabel manualLabel = ManualLabel.UNCHECKED;
 
     /**
@@ -124,7 +136,56 @@
 
     /*
+     * 
      */
     public String getBriefDescription() {
         return description.getBriefDescription();
+    }
+
+    /**
+     *
+     */
+    public void addTag(String tag) {
+        if (this.tags == null) {
+            this.tags = new LinkedList<>();
+        }
+        
+        if (!this.tags.contains(tag)) {
+            this.tags.add(tag);
+        }
+    }
+
+    /**
+     *
+     */
+    public void removeTag(String tag) {
+        if (this.tags != null) {
+            this.tags.remove(tag);
+        }
+    }
+
+    /**
+     * @param manualLabel the manualLabel to set
+     */
+    public void setManualLabel(ManualLabel manualLabel) {
+        this.manualLabel = manualLabel;
+    }
+
+    /**
+     * @return the tags
+     */
+    public List<String> getTags() {
+        if (tags != null) {
+            return Collections.unmodifiableList(tags);
+        }
+        else {
+            return Collections.emptyList();
+        }
+    }
+
+    /**
+     * @return the manualLabel
+     */
+    public ManualLabel getManualLabel() {
+        return manualLabel;
     }
 
@@ -170,3 +231,7 @@
     }
 
+    /** */
+    public static enum ManualLabel {
+        UNCHECKED, TRUE_POSITIVE, FALSE_POSITIVE;
+    }
 }
Index: trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilitySmellDescription.java
===================================================================
--- trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilitySmellDescription.java	(revision 2146)
+++ trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilitySmellDescription.java	(revision 2162)
@@ -17,4 +17,5 @@
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -32,5 +33,5 @@
  * @author 2012, last modified by $Author: pharms$
  */
-public enum UsabilitySmellDescription {
+public enum UsabilitySmellDescription implements Serializable {
     
     INEFFICIENT_ACTIONS,
@@ -43,4 +44,5 @@
     HIGH_TARGET_DISTANCE,
     MISSING_FEEDBACK,
+    TASK_RETRIED,
     UNUSED_GUI_ELEMENTS,
     DATA_ENTRY_METHOD_CHANGE,
Index: trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilitySmellIntensity.java
===================================================================
--- trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilitySmellIntensity.java	(revision 2146)
+++ trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilitySmellIntensity.java	(revision 2162)
@@ -15,4 +15,6 @@
 package de.ugoe.cs.autoquest.usability;
 
+import java.io.Serializable;
+
 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo;
@@ -26,6 +28,9 @@
  * @author 2012, last modified by $Author: pharms$
  */
-public class UsabilitySmellIntensity {
+public class UsabilitySmellIntensity implements Serializable {
     
+    /**  */
+    private static final long serialVersionUID = 1L;
+
     /** */
     private int ratio;
Index: trunk/autoquest-core-usability/src/main/resources/smellDescriptions_en.xml
===================================================================
--- trunk/autoquest-core-usability/src/main/resources/smellDescriptions_en.xml	(revision 2146)
+++ trunk/autoquest-core-usability/src/main/resources/smellDescriptions_en.xml	(revision 2162)
@@ -180,4 +180,26 @@
   </smellDescription>
   
+  <smellDescription smellId="TASK_RETRIED" briefText="task retried">
+    <textFragment>
+      The task 
+    </textFragment>
+    <parameterFragment parameterName="task" />
+    <textFragment>
+      is often retried, i.e., repeated subsequently. On average, every
+    </textFragment>
+    <parameterFragment parameterName="repeatedInstanceRatio" />
+    <textFragment>
+      th instance is followed by one or more repetitions of the task and the average repetition
+      ratio when a task is repeated is
+    </textFragment>
+    <parameterFragment parameterName="averageRepetitionRatio" />
+    <textFragment>
+      additional repetitions. This can be task retries and may indicate, that the task is hard to
+      be performed. Hence, it should be eased up. This can be done by checking, why the task is
+      retried and then adapting the implementation so that the task can be finalized with its
+      initial execution.
+    </textFragment>
+  </smellDescription>
+  
   <smellDescription smellId="UNUSED_GUI_ELEMENTS" briefText="unused GUI elements">
     <textFragment>
@@ -266,5 +288,9 @@
     <parameterFragment parameterName="ratio" />
     <textFragment>
-      different determined tasks. In the worst case, each action is its own task. In the best case,
+      different determined
+    </textFragment>
+    <parameterFragment parameterName="tasksType" />
+    <textFragment>
+      . In the worst case, each action is its own task. In the best case,
       all actions are described by the same tasks. This indicates, that the users act relatively
       different as otherwise, all their actions would be described by only a few tasks. Hence,
