source: trunk/autoquest-ui-core/src/main/java/de/ugoe/cs/autoquest/commands/usability/CMDusabilityStatistics.java @ 2166

Last change on this file since 2166 was 2166, checked in by pharms, 7 years ago
  • changes for first VR oriented usability evaluation
  • Property svn:mime-type set to text/plain
File size: 17.7 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.commands.usability;
16
17import java.util.ArrayList;
18import java.util.Collections;
19import java.util.HashMap;
20import java.util.HashSet;
21import java.util.LinkedList;
22import java.util.List;
23import java.util.ListIterator;
24import java.util.Map;
25import java.util.Set;
26import java.util.TreeMap;
27import java.util.TreeSet;
28
29import com.google.common.collect.Sets;
30
31import de.ugoe.cs.autoquest.CommandHelpers;
32import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
33import de.ugoe.cs.autoquest.tasktrees.treeifc.TaskTreeUtils;
34import de.ugoe.cs.autoquest.usability.UsabilityEvaluationResult;
35import de.ugoe.cs.autoquest.usability.UsabilitySmell;
36import de.ugoe.cs.autoquest.usability.UsabilitySmell.ManualLabel;
37import de.ugoe.cs.util.console.Command;
38import de.ugoe.cs.util.console.GlobalDataContainer;
39
40/**
41 * <p>
42 * TODO comment
43 * </p>
44 *
45 * @author Patrick Harms
46 * @version 1.0
47 */
48public class CMDusabilityStatistics implements Command {
49   
50    private static int COUNT = 0;
51    private static int DUPLICATES = 1;
52    private static int INTENSITY_LVL = 2;
53    private static int TRUE_POSITIVE = 3;
54    private static int TRUE_POSITIVE_DUPLICATES = 4;
55    private static int TRUE_POSITIVE_INTENSITY_LVL = 5;
56    private static int UNASSESSED = 6;
57    private static int MP_COUNT = 7;
58    private static int MP_DUPLICATES = 8;
59    private static int MP_INTENSITY_LVL = 9;
60    private static int MP_TRUE_POSITIVE = 10;
61    private static int MP_TRUE_POSITIVE_DUPLICATES = 11;
62    private static int MP_TRUE_POSITIVE_INTENSITY_LVL = 12;
63    private static int MP_UNASSESSED = 13;
64
65    /*
66     * (non-Javadoc)
67     *
68     * @see de.ugoe.cs.util.console.Command#run(java.util.List)
69     */
70    @Override
71    public void run(List<Object> parameters) {
72        List<String> usabilityResultNames = new ArrayList<>(parameters.size());
73        try {
74            for (Object parameter : parameters) {
75                usabilityResultNames.add((String) parameter);
76            }
77        }
78        catch (Exception e) {
79            throw new IllegalArgumentException();
80        }
81
82        List<UsabilityEvaluationResult> usabilityResults = new ArrayList<>(usabilityResultNames.size());
83       
84        for (String usabilityResultName : usabilityResultNames) {
85            Object dataObject = GlobalDataContainer.getInstance().getData(usabilityResultName);
86            if (dataObject == null) {
87                CommandHelpers.objectNotFoundMessage(usabilityResultName);
88                return;
89            }
90            if (!(dataObject instanceof UsabilityEvaluationResult)) {
91                CommandHelpers.objectNotType(usabilityResultName, "UsabilityEvaluationResult");
92                return;
93            }
94           
95            usabilityResults.add((UsabilityEvaluationResult) dataObject);
96        }
97       
98        // analyse all smells
99        Map<String, List<UsabilitySmell>> allSmells = new TreeMap<>();
100        Map<String, Set<ISequence>> mostProminentSequences = new TreeMap<>();
101        Set<String> smellTypes = new TreeSet<>();
102       
103        for (int i = 0; i < usabilityResults.size(); i++) {
104            String usabilityResultName = usabilityResultNames.get(i);
105            allSmells.put(usabilityResultName, usabilityResults.get(i).getAllSmells());
106           
107            for (UsabilitySmell smell : usabilityResults.get(i).getAllSmells()) {
108                smellTypes.add(smell.getBriefDescription());
109            }
110           
111            if (!mostProminentSequences.containsKey(usabilityResultName)) {
112                mostProminentSequences.put(usabilityResultName,
113                                           TaskTreeUtils.getMostProminentTasks
114                                               (usabilityResults.get(i).getTaskModel()));
115            }
116        }
117       
118        analyseAndDump("all smells", allSmells, mostProminentSequences);
119       
120        for (String smellType : smellTypes) {
121            Map<String, List<UsabilitySmell>> relevantSmells = new TreeMap<>();
122            for (int i = 0; i < usabilityResults.size(); i++) {
123                List<UsabilitySmell> smellList = new LinkedList<>();
124               
125                for (UsabilitySmell smell : usabilityResults.get(i).getAllSmells()) {
126                    if (smellType.equals(smell.getBriefDescription())) {
127                        smellList.add(smell);
128                    }
129                }
130               
131                relevantSmells.put(usabilityResultNames.get(i), smellList);
132            }
133               
134            analyseAndDump(smellType, relevantSmells, mostProminentSequences);
135        }
136    }
137
138    /**
139     *
140     */
141    private void analyseAndDump(String                            setName,
142                                Map<String, List<UsabilitySmell>> smells,
143                                Map<String, Set<ISequence>>       mostProminentSequences)
144    {
145        System.out.println("\n\n###################################################################");
146        System.out.println("usability statistics for " + setName + "\n");
147       
148        // determine statistics
149        int[][] basicResultData = new int[14][];
150
151        for (int i = 0; i < basicResultData.length; i++) {
152            basicResultData[i] = new int[smells.size()];
153        }
154       
155        Map<String, Map<String, List<UsabilitySmell>>> tagCounters = new TreeMap<>();
156        List<String> columnNames = new LinkedList<>();
157
158       
159        int index = 0;
160        for (Map.Entry<String, List<UsabilitySmell>> smellGroup : smells.entrySet()) {
161            String usabilityResultName = smellGroup.getKey();
162            columnNames.add(usabilityResultName);
163           
164            basicResultData[COUNT][index] = smellGroup.getValue().size();
165            basicResultData[DUPLICATES][index] = getDuplicates(smellGroup.getValue());
166            basicResultData[INTENSITY_LVL][index] = getIntensityLevel(smellGroup.getValue());
167           
168            List<UsabilitySmell> truePositives = new LinkedList<>();
169            List<UsabilitySmell> unassessed = new LinkedList<>();
170           
171            List<UsabilitySmell> mps = new LinkedList<>();
172            List<UsabilitySmell> mpTruePositives = new LinkedList<>();
173            List<UsabilitySmell> mpUnassessed = new LinkedList<>();
174           
175            for (UsabilitySmell smell : smellGroup.getValue()) {
176                if (smell.getManualLabel() == ManualLabel.TRUE_POSITIVE) {
177                    truePositives.add(smell);
178                }
179                else if (smell.getManualLabel() == ManualLabel.UNCHECKED) {
180                    unassessed.add(smell);
181                }
182               
183                if (mostProminentSequences.get(smellGroup.getKey()).contains(smell.getSmellingTask())) {
184                    mps.add(smell);
185                   
186                    if (smell.getManualLabel() == ManualLabel.TRUE_POSITIVE) {
187                        mpTruePositives.add(smell);
188                    }
189                    else if (smell.getManualLabel() == ManualLabel.UNCHECKED) {
190                        mpUnassessed.add(smell);
191                    }
192                }
193               
194                Set<String> tagList = new HashSet<>(smell.getTags());
195               
196                Set<Set<String>> powerSetTags = Sets.powerSet(tagList);
197               
198                for (Set<String> tagSet : powerSetTags) {
199                    List<String> tags = new LinkedList<>(tagSet);
200                    //{List<String> tags = new LinkedList<>(tagList);
201                    Collections.sort(tags);
202                    String tagCombinationKey = tags.toString();
203                   
204                    Map<String, List<UsabilitySmell>> counterMap = tagCounters.get(tagCombinationKey);
205                   
206                    if (counterMap == null) {
207                        counterMap = new HashMap<>();
208                        tagCounters.put(tagCombinationKey, counterMap);
209                    }
210                   
211                    List<UsabilitySmell> smellWithSameTagCombination =
212                        counterMap.get(usabilityResultName);
213                   
214                    if (smellWithSameTagCombination == null) {
215                        smellWithSameTagCombination = new LinkedList<>();
216                        counterMap.put(usabilityResultName, smellWithSameTagCombination);
217                    }
218                   
219                    smellWithSameTagCombination.add(smell);
220                }
221            }
222           
223            basicResultData[TRUE_POSITIVE][index] = truePositives.size();
224            basicResultData[TRUE_POSITIVE_DUPLICATES][index] = getDuplicates(truePositives);
225            basicResultData[TRUE_POSITIVE_INTENSITY_LVL][index] = getIntensityLevel(truePositives);
226            basicResultData[UNASSESSED][index] = unassessed.size();
227           
228            basicResultData[MP_COUNT][index] = mps.size();
229            basicResultData[MP_DUPLICATES][index] = getDuplicates(mps);
230            basicResultData[MP_INTENSITY_LVL][index] = getIntensityLevel(mps);
231            basicResultData[MP_TRUE_POSITIVE][index] = mpTruePositives.size();
232            basicResultData[MP_TRUE_POSITIVE_DUPLICATES][index] = getDuplicates(mpTruePositives);
233            basicResultData[MP_TRUE_POSITIVE_INTENSITY_LVL][index] = getIntensityLevel(mpTruePositives);
234            basicResultData[MP_UNASSESSED][index] = mpUnassessed.size();
235           
236            index++;
237        }
238       
239        int maxTagNameLength = 0;
240        for (String tagCombination : tagCounters.keySet()) {
241            maxTagNameLength = Math.max(maxTagNameLength, tagCombination.length());
242        }
243
244        maxTagNameLength = Math.max(maxTagNameLength, "    intensity level".length());
245
246        List<StringBuffer> lines = new LinkedList<>();
247       
248        lines.add(createBorderLine(maxTagNameLength, columnNames));
249        lines.add(new StringBuffer("overall"));
250        lines.add(createDataLine("  count", maxTagNameLength, basicResultData[COUNT], columnNames));
251        lines.add(createDataLine("    duplicates", maxTagNameLength, basicResultData[DUPLICATES], columnNames));
252        lines.add(createDataLine("    intensity level", maxTagNameLength, basicResultData[INTENSITY_LVL], columnNames));
253        lines.add(createDataLine("  true positives", maxTagNameLength, basicResultData[TRUE_POSITIVE], columnNames));
254        lines.add(createDataLine("    duplicates", maxTagNameLength, basicResultData[TRUE_POSITIVE_DUPLICATES], columnNames));
255        lines.add(createDataLine("    intensity level", maxTagNameLength, basicResultData[TRUE_POSITIVE_INTENSITY_LVL], columnNames));
256        lines.add(createDataLine("  unassessed", maxTagNameLength, basicResultData[UNASSESSED], columnNames));
257        lines.add(createBorderLine(maxTagNameLength, columnNames));
258        lines.add(new StringBuffer("most prominent"));
259        lines.add(createDataLine("  count", maxTagNameLength, basicResultData[MP_COUNT], columnNames));
260        lines.add(createDataLine("    duplicates", maxTagNameLength, basicResultData[MP_DUPLICATES], columnNames));
261        lines.add(createDataLine("    intensity level", maxTagNameLength, basicResultData[MP_INTENSITY_LVL], columnNames));
262        lines.add(createDataLine("  true positives", maxTagNameLength, basicResultData[MP_TRUE_POSITIVE], columnNames));
263        lines.add(createDataLine("    duplicates", maxTagNameLength, basicResultData[MP_TRUE_POSITIVE_DUPLICATES], columnNames));
264        lines.add(createDataLine("    intensity level", maxTagNameLength, basicResultData[MP_TRUE_POSITIVE_INTENSITY_LVL], columnNames));
265        lines.add(createDataLine("  unassessed", maxTagNameLength, basicResultData[MP_UNASSESSED], columnNames));
266        lines.add(createBorderLine(maxTagNameLength, columnNames));
267       
268        for (Map.Entry<String, Map<String, List<UsabilitySmell>>> tagStats : tagCounters.entrySet()) {
269            StringBuffer line = new StringBuffer();
270            line.append(tagStats.getKey());
271           
272            for (int i = tagStats.getKey().length(); i < maxTagNameLength; i++) {
273                line.append(' ');
274            }
275           
276            for (String columnName : columnNames) {
277                String numberStr = "";
278               
279                if (tagStats.getValue().get(columnName) != null) {
280                    numberStr += tagStats.getValue().get(columnName).size();
281                   
282                    while (numberStr.length() < 5) {
283                        numberStr += ' ';
284                    }
285                   
286                    numberStr += "(" + getIntensityLevel(tagStats.getValue().get(columnName)) + ")";
287                }
288               
289                line.append(" | ");
290                line.append(numberStr);
291               
292                for (int i = numberStr.length(); i < columnName.length(); i++) {
293                    line.append(' ');
294                }
295            }
296           
297            lines.add(line);
298        }
299       
300        for (int i = 0; i < maxTagNameLength; i++) {
301            System.out.print(' ');
302        }
303       
304        for (String columnName : columnNames) {
305            System.out.print(" | " + columnName);
306        }
307       
308        System.out.println();
309       
310        for (StringBuffer line : lines) {
311            System.out.println(line);
312        }
313    }
314
315    /**
316     *
317     */
318    private StringBuffer createBorderLine(int firstColumnWith, List<String> columnNames) {
319        StringBuffer line = new StringBuffer();
320       
321        for (int i = 0; i < firstColumnWith; i++) {
322            line.append('-');
323        }
324       
325        for (String columnName : columnNames) {
326            line.append("-|-");
327            for (int j = 0; j < columnName.length(); j++) {
328                line.append('-');
329            }
330        }
331       
332        return line;
333    }
334
335    /**
336     *
337     */
338    private StringBuffer createDataLine(String       lineName,
339                                        int          firstColumnWith,
340                                        int[]        values,
341                                        List<String> columnNames)
342    {
343        StringBuffer line = new StringBuffer();
344       
345        line.append(lineName);
346       
347        for (int i = lineName.length(); i < firstColumnWith; i++) {
348            line.append(' ');
349        }
350       
351        for (int i = 0; i < values.length; i++) {
352            String numberStr = "" + values[i];
353
354            line.append(" | ");
355            line.append(numberStr);
356           
357            for (int j = numberStr.length(); j < columnNames.get(i).length(); j++) {
358                line.append(' ');
359            }
360        }
361       
362        return line;
363    }
364
365    /**
366     *
367     */
368    private int getDuplicates(List<UsabilitySmell> allSmells) {
369        int duplicateCount = 0;
370       
371        for (UsabilitySmell smell1 : allSmells) {
372            if (smell1.getSmellingTask() != null) {
373                for (UsabilitySmell smell2 : allSmells) {
374                    if ((smell2.getSmellingTask() != null) &&
375                        (smell1.getSmellingTask() != smell2.getSmellingTask()) &&
376                        (TaskTreeUtils.isChild(smell1.getSmellingTask(), smell2.getSmellingTask())))
377                    {
378                        duplicateCount++;
379                        break;
380                    }
381                }
382            }
383        }
384       
385        return duplicateCount;
386    }
387
388    /**
389     *
390     */
391    private int getIntensityLevel(List<UsabilitySmell> smellList) {
392        if (smellList.size() <= 0) {
393            return -1;
394        }
395       
396        LinkedList<UsabilitySmell> smellsToConsider = new LinkedList<>();
397       
398        // determine the smells with the highest intensity
399        for (UsabilitySmell smell : smellList) {
400            boolean added = false;
401            ListIterator<UsabilitySmell> it = smellsToConsider.listIterator();
402           
403            while (it.hasNext()) {
404                if (it.next().getIntensity().getRatio() < smell.getIntensity().getRatio()) {
405                    it.previous();
406                    it.add(smell);
407                    added = true;
408                    break;
409                }
410            }
411           
412            if (!added) {
413                smellsToConsider.add(smell);
414            }
415           
416            while (smellsToConsider.size() > 5) {
417                smellsToConsider.removeLast();
418            }
419        }
420       
421        // calculate the average intensity of the smells with the highest intensity
422        int cummulativeIntensity = 0;
423        for (UsabilitySmell smell : smellsToConsider) {
424            cummulativeIntensity += smell.getIntensity().getRatio();
425        }
426       
427        return cummulativeIntensity / smellsToConsider.size();
428    }
429   /*
430     * (non-Javadoc)
431     *
432     * @see de.ugoe.cs.util.console.Command#help()
433     */
434    @Override
435    public String help() {
436        return "usabilityStatistics [<usabilityEvaluationResultName>]*";
437    }
438
439}
Note: See TracBrowser for help on using the repository browser.