Index: trunk/autoquest-ui-core/src/main/java/de/ugoe/cs/autoquest/commands/usability/CMDgetTaskModelSimilarity.java
===================================================================
--- trunk/autoquest-ui-core/src/main/java/de/ugoe/cs/autoquest/commands/usability/CMDgetTaskModelSimilarity.java	(revision 1895)
+++ trunk/autoquest-ui-core/src/main/java/de/ugoe/cs/autoquest/commands/usability/CMDgetTaskModelSimilarity.java	(revision 1919)
@@ -84,4 +84,6 @@
         Map<ITaskModel, List<ISequence>> inputTaskModels = new IdentityHashMap<>();
         
+        ITaskModel firstModel = null;
+        
         for (String inputTaskTreeName : inputTaskTreeNames) {
             Object dataObject = GlobalDataContainer.getInstance().getData(inputTaskTreeName);
@@ -104,12 +106,11 @@
             
             inputTaskModels.put((ITaskModel) dataObject, tasksToCompare);
-        }
-        
-        SimilarityStatistics statistics = new SimilarityStatistics();
-        
-        getTaskModelSimilarity(inputTaskModels, statistics);
-        
-        Console.println("\nsimilarity statistics of all comparisons");
-        statistics.dump();
+            
+            if (firstModel == null) {
+                firstModel = (ITaskModel) dataObject;
+            }
+        }
+        
+        getTaskModelSimilarity(firstModel, inputTaskModels);
     }
 
@@ -117,6 +118,6 @@
      *
      */
-    private void getTaskModelSimilarity(Map<ITaskModel, List<ISequence>> inputTaskModels,
-                                        SimilarityStatistics             statistics)
+    private void getTaskModelSimilarity(ITaskModel                       modelToCompare,
+                                        Map<ITaskModel, List<ISequence>> inputTaskModels)
     {
         // create the indexes to not do too many comparisons
@@ -188,15 +189,14 @@
         List<ComparisonRunnable> runnables = new LinkedList<>();
         
-        for (Map.Entry<ITaskModel, List<ISequence>> model1 : inputTaskModels.entrySet()) {
-            for (Map.Entry<ITaskModel, List<ISequence>> model2 : inputTaskModels.entrySet()) {
-                if (model1.getKey() != model2.getKey()) {
-                    runnables.add(new ComparisonRunnable(model1.getKey(), model1.getValue(),
-                                                         model2.getKey(), model2.getValue(),
-                                                         Collections.unmodifiableMap
-                                                             (index1.get(model2.getKey())),
-                                                         Collections.unmodifiableMap(index2),
-                                                         Collections.unmodifiableMap(index3),
-                                                         runnables));
-                }
+        for (Map.Entry<ITaskModel, List<ISequence>> model2 : inputTaskModels.entrySet()) {
+            if (modelToCompare != model2.getKey()) {
+                runnables.add(new ComparisonRunnable(modelToCompare,
+                                                     inputTaskModels.get(modelToCompare),
+                                                     model2.getKey(), model2.getValue(),
+                                                     Collections.unmodifiableMap
+                                                         (index1.get(model2.getKey())),
+                                                     Collections.unmodifiableMap(index2),
+                                                     Collections.unmodifiableMap(index3),
+                                                     runnables));
             }
         }
@@ -250,8 +250,8 @@
         
         for (ComparisonRunnable runnable : runnables) {
-            Console.println("\n similarity statistics of comparison between " + runnable.model1 +
-                            " and " + runnable.model2);
+            Console.println("\nsimilarity statistics of comparison between " + runnable.model1 +
+                            " (" + runnable.tasks1.size() + " tasks) and " + runnable.model2 +
+                            " (" + runnable.tasks2.size() + " tasks)");
             runnable.getStatistics().dump();
-            statistics.mergeWith(runnable.getStatistics());
         }
     }
@@ -263,15 +263,55 @@
         
         /**  */
-        private int taskCounter = 0;
-        
-        /** */
-        private int maxCoverage = 0;
+        private int taskCounter1 = 0;
+        
+        /** */
+        private int maxCoverage1 = 0;
+        
+        /** */
+        private ITaskModel model1 = null;
         
         /**  */
-        private Map<Integer, Integer> coverageCounters = new HashMap<>();
+        private Map<Integer, Integer> coverageCounters1 = new HashMap<>();
+        
+        /**  */
+        private int taskCounter2 = 0;
+        
+        /** */
+        private int maxCoverage2 = 0;
+        
+        /** */
+        private ITaskModel model2 = null;
+        
+        /**  */
+        private Map<Integer, Integer> coverageCounters2 = new HashMap<>();
         
         /**  */
         private Map<Integer, Map<Integer, Map<TaskEquality, Integer>>> equalityCounters =
             new HashMap<>();
+            
+        /**
+         *
+         */
+        private void addCoverageCounter(ITask task, ITaskModel model) {
+            if (model1 == null) {
+                model1 = model;
+            }
+            else if (model2 == null) {
+                model2 = model;
+            }
+            
+            int coverageRatio = model.getTaskInfo(task).getMeasureValue(TaskMetric.EVENT_COVERAGE);
+            
+            if (model == model1) {
+                addToMaps(coverageCounters1, coverageRatio, 1);
+                taskCounter1++;
+                maxCoverage1 = Math.max(maxCoverage1, coverageRatio);
+            }
+            else {
+                addToMaps(coverageCounters2, coverageRatio, 1);
+                taskCounter2++;
+                maxCoverage2 = Math.max(maxCoverage2, coverageRatio);
+            }
+        }
         
         /**
@@ -284,13 +324,9 @@
                            TaskEquality equality)
         {
-            int coverageRatio1 =
-                model.getTaskInfo(task).getMeasureValue(TaskMetric.EVENT_COVERAGE);
+            int coverageRatio1 = model.getTaskInfo(task).getMeasureValue(TaskMetric.EVENT_COVERAGE);
             int coverageRatio2 =
                 otherModel.getTaskInfo(other).getMeasureValue(TaskMetric.EVENT_COVERAGE);
             
-            addToMaps(coverageRatio1, 1);
             addToMaps(coverageRatio1, coverageRatio2, equality, 1);
-            taskCounter++;
-            maxCoverage = Math.max(maxCoverage, coverageRatio1);
         }
         
@@ -299,42 +335,13 @@
          */
         private void store(ITask task, ITaskModel model) {
-            int coverageRatio1 =
-                model.getTaskInfo(task).getMeasureValue(TaskMetric.EVENT_COVERAGE);
-            
-            addToMaps(coverageRatio1, 1);
+            int coverageRatio1 = model.getTaskInfo(task).getMeasureValue(TaskMetric.EVENT_COVERAGE);
+            
             addToMaps(coverageRatio1, 0, TaskEquality.UNEQUAL, 1);
-            taskCounter++;
-            maxCoverage = Math.max(maxCoverage, coverageRatio1);
-        }
-
-        /**
-         *
-         */
-        private void mergeWith(SimilarityStatistics statistics) {
-            for (Map.Entry<Integer, Map<Integer, Map<TaskEquality, Integer>>> entry1 :
-                     statistics.equalityCounters.entrySet())
-            {
-                for (Map.Entry<Integer, Map<TaskEquality, Integer>> entry2 :
-                         entry1.getValue().entrySet())
-                {
-                    for (Map.Entry<TaskEquality, Integer> entry3 : entry2.getValue().entrySet()) {
-                        addToMaps
-                            (entry1.getKey(), entry2.getKey(), entry3.getKey(), entry3.getValue());
-                    }
-                }
-            }
-            
-            for (Map.Entry<Integer, Integer> entry : statistics.coverageCounters.entrySet()) {
-                addToMaps(entry.getKey(), entry.getValue());
-            }
-            
-            taskCounter += statistics.taskCounter;
-            maxCoverage = Math.max(maxCoverage, statistics.taskCounter);
-        }
-
-        /**
-         *
-         */
-        private void addToMaps(int ratio, int increment) {
+        }
+
+        /**
+         *
+         */
+        private void addToMaps(Map<Integer, Integer> coverageCounters, int ratio, int increment) {
             Integer counter = coverageCounters.get(ratio);
 
@@ -382,90 +389,202 @@
             Console.println("========================");
             
-            int[][] bins = getBinsOfAlmostEqualSize();
+            int[][] bins1 = getBinsOfAlmostEqualSize(coverageCounters1, taskCounter1, maxCoverage1);
+            int[][] bins2 = getBinsOfAlmostEqualSize(coverageCounters2, taskCounter2, maxCoverage2);
             int lowerBorder1;
             int higherBorder1;
             int lowerBorder2;
             int higherBorder2;
-            int allEqualitiesOfBin = 0;
+            int lexicalEqualitiesOfBin = 0;
+            int syntacticalEqualitiesOfBin = 0;
+            int semanticalEqualitiesOfBin = 0;
+            int similaritiesOfBin = 0;
             int allEqualities = 0;
             
-            for (int i = bins.length - 1; i >= 0 ; i--) {
+            String[][] outputs = new String[(bins1.length * (bins2.length + 3)) + 1][];
+            int outputIndex = 0;
+            
+            DecimalFormat percentFormat = new DecimalFormat("##0.0%");
+            StringBuffer csvData = new StringBuffer();
+            csvData.append(taskCounter1);
+            csvData.append(';');
+            csvData.append(taskCounter2);
+            
+            for (int i = bins1.length - 1; i >= 0 ; i--) {
                 if (i <= 0) {
                     lowerBorder1 = 0;
                 }
                 else {
-                    lowerBorder1 = bins[i - 1][0] + 1;
-                }
-                
-                higherBorder1 = bins[i][0];
-                
-                allEqualitiesOfBin = 0;
-                
-                Console.println("similarities of " + bins[i][1] + " tasks with " + lowerBorder1 +
-                                " to " + higherBorder1 + "‰ coverage");
-                
-                for (int j = bins.length - 1; j >= 0; j--) {
+                    lowerBorder1 = bins1[i - 1][0] + 1;
+                }
+                
+                higherBorder1 = bins1[i][0];
+                
+                int allInBin1 = countAllInBin(lowerBorder1, higherBorder1);
+                csvData.append(';');
+                csvData.append(allInBin1);
+                
+                lexicalEqualitiesOfBin = 0;
+                syntacticalEqualitiesOfBin = 0;
+                semanticalEqualitiesOfBin = 0;
+                similaritiesOfBin = 0;
+                
+                outputs[outputIndex++] = new String[]
+                        { "similarities of " + bins1[i][1] + " tasks with " + lowerBorder1 +
+                          " to " + higherBorder1 + " covered events", "LEX", "SYN", "SEM",
+                          "ALL EQUAL", "SIM", "ALL" };
+                
+                for (int j = bins2.length - 1; j >= 0; j--) {
                     if (j <= 0) {
                         lowerBorder2 = 0;
                     }
                     else {
-                        lowerBorder2 = bins[j - 1][0] + 1;
-                    }
-                    
-                    higherBorder2 = bins[j][0];
-
-                    Console.print("  --> to " + bins[j][1] + " tasks with " + lowerBorder2 +
-                                  " to " + higherBorder2 + "‰ coverage");
-                    
-                    Console.print("    | ");
-                    int allInBin = countAllInBin(lowerBorder1, higherBorder1);
+                        lowerBorder2 = bins2[j - 1][0] + 1;
+                    }
+                    
+                    higherBorder2 = bins2[j][0];
+                    
+                    int allInBin2 = countAllInBin(lowerBorder2, higherBorder2);
+                    csvData.append(';');
+                    csvData.append(allInBin2);
 
                     int count1 = countEqualities(lowerBorder1, higherBorder1, lowerBorder2,
                                                  higherBorder2, TaskEquality.LEXICALLY_EQUAL);
-                    
-                    dump(count1, allInBin, "LEX");
-                    Console.print("\t| ");
 
                     int count2 = countEqualities(lowerBorder1, higherBorder1, lowerBorder2,
                                                  higherBorder2, TaskEquality.SYNTACTICALLY_EQUAL);
 
-                    dump(count2, allInBin, "SYN");
-                    Console.print("\t| ");
-
                     int count3 = countEqualities(lowerBorder1, higherBorder1, lowerBorder2,
                                                  higherBorder2, TaskEquality.SEMANTICALLY_EQUAL);
                     
-                    dump(count3, allInBin, "SEM");
-                    Console.print("\t|| ");
-
                     int count4 = countEqualities(lowerBorder1, higherBorder1, lowerBorder2,
                                                  higherBorder2, null);
                     
-                    dump(count4, allInBin, "SIM");
-                    Console.print("\t|| ");
-
-                    dump(count1 + count2 + count3 + count4, allInBin, "ALL");
-                    Console.println("");
-                    
-                    allEqualitiesOfBin += count1 + count2 + count3 + count4;
-                }
-                
-                Console.print("  --> to all other tasks\t");
-                dump(allEqualitiesOfBin, taskCounter, "ALL");
-                Console.println("");
-                
-                allEqualities += allEqualitiesOfBin;
-            }
-            
-            Console.println("");
-            Console.print("complete recall is ");
-            dump(allEqualities, taskCounter, "ALL");
-            Console.println("");
-        }
-
-        /**
-         *
-         */
-        private int[][] getBinsOfAlmostEqualSize() {
+                    outputs[outputIndex++] = new String[]
+                            { "--> to " + allInBin2 + " tasks with " + lowerBorder2 +
+                              " to " + higherBorder2 + " covered events", format(count1, allInBin1),
+                              format(count2, allInBin1), format(count3, allInBin1),
+                              format(count1 + count2 + count3, allInBin1), format(count4, allInBin1),
+                              format(count1 + count2 + count3 + count4, allInBin1)
+                            };
+                    
+                    lexicalEqualitiesOfBin += count1;
+                    syntacticalEqualitiesOfBin += count2;
+                    semanticalEqualitiesOfBin += count3;
+                    similaritiesOfBin += count4;
+
+                    csvData.append(';');
+                    csvData.append(percentFormat.format((double) count1 / allInBin1));
+                    csvData.append(';');
+                    csvData.append(percentFormat.format((double) count2 / allInBin1));
+                    csvData.append(';');
+                    csvData.append(percentFormat.format((double) count3 / allInBin1));
+                    csvData.append(';');
+                    csvData.append(percentFormat.format
+                                       ((double) (count1 + count2 + count3) / allInBin1));
+                    csvData.append(';');
+                    csvData.append(percentFormat.format((double) count4 / allInBin1));
+                    csvData.append(';');
+                    csvData.append(percentFormat.format
+                                       ((double) (count1 + count2 + count3 + count4) / allInBin1));
+                }
+                
+                outputs[outputIndex++] = new String[]
+                        { "--> all recalls", format(lexicalEqualitiesOfBin, allInBin1),
+                          format(syntacticalEqualitiesOfBin, allInBin1),
+                          format(semanticalEqualitiesOfBin, allInBin1),
+                          format(lexicalEqualitiesOfBin + syntacticalEqualitiesOfBin +
+                                 semanticalEqualitiesOfBin, allInBin1),
+                          format(similaritiesOfBin, allInBin1),
+                          format(lexicalEqualitiesOfBin + syntacticalEqualitiesOfBin +
+                                 semanticalEqualitiesOfBin + similaritiesOfBin, allInBin1)
+                        };
+                
+
+                csvData.append(';');
+                csvData.append(percentFormat.format((double) lexicalEqualitiesOfBin / allInBin1));
+                csvData.append(';');
+                csvData.append(percentFormat.format((double) syntacticalEqualitiesOfBin / allInBin1));
+                csvData.append(';');
+                csvData.append(percentFormat.format((double) semanticalEqualitiesOfBin / allInBin1));
+                csvData.append(';');
+                csvData.append(percentFormat.format
+                                   ((double) (lexicalEqualitiesOfBin + syntacticalEqualitiesOfBin +
+                                              semanticalEqualitiesOfBin) / allInBin1));
+                csvData.append(';');
+                csvData.append(percentFormat.format((double) similaritiesOfBin / allInBin1));
+                csvData.append(';');
+                csvData.append(percentFormat.format
+                                   ((double) (lexicalEqualitiesOfBin + syntacticalEqualitiesOfBin +
+                                              semanticalEqualitiesOfBin + similaritiesOfBin) /
+                                              allInBin1));
+                
+                allEqualities += lexicalEqualitiesOfBin + syntacticalEqualitiesOfBin +
+                    semanticalEqualitiesOfBin + similaritiesOfBin;
+                
+                outputIndex++;
+            }
+            
+            outputs[outputIndex++] = new String[]
+                    { "complete recall is", null, null, null, null, null,
+                      format(allEqualities, taskCounter1)
+                    };
+            
+            csvData.append(';');
+            csvData.append(percentFormat.format((double) allEqualities / taskCounter1));
+            
+            dump(outputs);
+            Console.println("\nCSV: " + csvData);
+        }
+
+        /**
+         *
+         */
+        private void dump(String[][] outputs) {
+            int[] lengths = new int[outputs[0].length];
+            
+            for (String[] line : outputs) {
+                if (line != null) {
+                    for (int i = 0; i < line.length; i++) {
+                        if (line[i] != null) {
+                            lengths[i] = Math.max(lengths[i], line[i].length());
+                        }
+                    }
+                }
+            }
+            
+            for (String[] line : outputs) {
+                StringBuffer toWrite = new StringBuffer();
+                
+                if (line != null) {
+                    for (int i = 0; i < line.length; i++) {
+                        if (i > 0) {
+                            toWrite.append(" | ");
+                        }
+                    
+                        String text = line[i];
+                    
+                        if (text == null) {
+                            text = "";
+                        }
+                    
+                        for (int j = 0; j < (lengths[i] - text.length()); j++) {
+                            toWrite.append(' ');
+                        }
+                      
+                        toWrite.append(text);
+                    }
+                }
+                
+                Console.println(toWrite.toString());
+            }
+        }
+
+        /**
+         *
+         */
+        private int[][] getBinsOfAlmostEqualSize(Map<Integer, Integer> coverageCounters,
+                                                 int                   taskCounter,
+                                                 int                   maxCoverage)
+        {
             int[][] result = new int[5][];
             
@@ -500,17 +619,18 @@
          *
          */
-        private void dump(int noOfEqualTasks, int noOfAllTasks, String prefix) {
-            Console.print(prefix);
-            Console.print("\t: ");
-
+        private String format(int noOfEqualTasks, int noOfAllTasks) {
+            StringBuffer result = new StringBuffer();
             if (noOfAllTasks > 0) {
                 double value = ((double) (noOfEqualTasks * 100)) / noOfAllTasks;
-                Console.print(noOfEqualTasks + " (");
-                Console.print(new DecimalFormat("###.#").format(value));
-                Console.print("%)");
+                result.append(noOfEqualTasks);
+                result.append(" (");
+                result.append(new DecimalFormat("##0.0").format(value));
+                result.append("%)");
             }
             else {
-                Console.print("n.a.");
-            }
+                result.append("n.a.");
+            }
+            
+            return result.toString();
         }
 
@@ -550,9 +670,9 @@
          *
          */
-        private int countAllInBin(int lowerBorder1, int higherBorder1) {
+        private int countAllInBin(int lowerBorder, int higherBorder) {
             int coverageCounter = 0;
             
-            for (int i = lowerBorder1; i <= higherBorder1; i++) {
-                Integer value = coverageCounters.get(i);
+            for (int i = lowerBorder; i <= higherBorder; i++) {
+                Integer value = coverageCounters1.get(i);
                 
                 if (value != null) {
@@ -631,4 +751,13 @@
             SimilarTasks similarity;
 
+            // store coverage infos for models
+            for (ISequence task : tasks1) {
+                statistics.addCoverageCounter(task, model1);
+            }
+            
+            for (ISequence task : tasks2) {
+                statistics.addCoverageCounter(task, model2);
+            }
+            
             List<ISequence> tasksToCompareWith = new ArrayList<ISequence>();
             StopWatch watch = new StopWatch();
