Changeset 2042


Ignore:
Timestamp:
10/20/15 10:11:04 (9 years ago)
Author:
pharms
Message:
  • finalized smell detection for phd thesis
Location:
trunk/autoquest-core-usability/src/main
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/CheckBoxMultipleSelectionRule.java

    r1918 r2042  
    1515package de.ugoe.cs.autoquest.usability; 
    1616 
     17import java.util.ArrayList; 
    1718import java.util.Collection; 
    1819import java.util.HashMap; 
    1920import java.util.HashSet; 
     21import java.util.LinkedList; 
    2022import java.util.List; 
    2123import java.util.Map; 
    2224import java.util.Set; 
    2325 
     26import de.ugoe.cs.autoquest.eventcore.IEventTarget; 
     27import de.ugoe.cs.autoquest.eventcore.gui.MouseClick; 
     28import de.ugoe.cs.autoquest.eventcore.gui.ValueSelection; 
    2429import de.ugoe.cs.autoquest.eventcore.guimodel.ICheckBox; 
    2530import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement; 
    26 import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskTraversingVisitor; 
     31import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIView; 
     32import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskInstanceTraversingVisitor; 
    2733import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask; 
    2834import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance; 
    29 import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship; 
    30 import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship; 
    3135import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; 
    3236import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance; 
    3337import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel; 
    34 import de.ugoe.cs.autoquest.tasktrees.treeifc.TaskMetric; 
     38import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession; 
    3539 
    3640/** 
     
    6872                                   UsabilityEvaluationResult results) 
    6973    { 
     74        System.out.println("\n\n########################################\n"); 
     75        final List<List<IEventTaskInstance>> actionInstancesInSameView = new LinkedList<>(); 
     76         
     77        for (IUserSession session : taskModel.getUserSessions()) { 
     78            for (ITaskInstance instance : session) { 
     79                final LinkedList<IEventTaskInstance> currentList = new LinkedList<>(); 
     80                 
     81                instance.accept(new DefaultTaskInstanceTraversingVisitor() { 
     82                    @Override 
     83                    public void visit(IEventTaskInstance eventTaskInstance) { 
     84                        if (eventTaskInstance.getEvent().getTarget() instanceof IGUIElement) { 
     85                            IEventTarget target = eventTaskInstance.getEvent().getTarget(); 
     86                            IGUIView currentView = ((IGUIElement) target).getView(); 
     87                             
     88                            IGUIView previousView = null; 
     89                            if (currentList.size() > 0) { 
     90                                target = currentList.getLast().getEvent().getTarget(); 
     91                                previousView = ((IGUIElement) target).getView(); 
     92                            } 
     93                             
     94                            if ((previousView == currentView) || 
     95                                ((previousView != null) && (previousView.equals(currentView)))) 
     96                            { 
     97                                currentList.add(eventTaskInstance); 
     98                            } 
     99                            else { 
     100                                if (currentList.size() > 0) { 
     101                                    actionInstancesInSameView.add(new ArrayList<>(currentList)); 
     102                                } 
     103                                currentList.clear(); 
     104                                currentList.add(eventTaskInstance); 
     105                            } 
     106                        } 
     107                    } 
     108                }); 
     109                 
     110                if (currentList.size() > 0) { 
     111                    actionInstancesInSameView.add(new ArrayList<>(currentList)); 
     112                } 
     113            } 
     114        } 
     115 
     116         
    70117        Map<IGUIElement, List<IGUIElement>> checkBoxGroups = statistics.getCheckBoxGroups(); 
    71118         
    72         CHECK_NEXT_GROUP: 
    73         for (List<IGUIElement> group : checkBoxGroups.values()) { 
    74             Set<ITask> tasksUsingGroup = new HashSet<>(); 
    75              
    76             for (IGUIElement checkBox : group) { 
    77                 Set<ITask> tasksUsingCheckBox = getTasksUsingCheckBox(checkBox, taskModel); 
     119        for (Map.Entry<IGUIElement, List<IGUIElement>> group : checkBoxGroups.entrySet()) { 
     120            IGUIView currentView = group.getKey().getView(); 
     121            int noOfEvents = 0; 
     122            int noOfGroupUsages = 0; 
     123            int noOfSingleCheckBoxUsages = 0; 
     124             
     125            for (List<IEventTaskInstance> actionInstanceList : actionInstancesInSameView) { 
     126                IEventTarget target = actionInstanceList.get(0).getEvent().getTarget(); 
     127                IGUIView viewOfList = ((IGUIElement) target).getView(); 
    78128                 
    79                 for (ITask taskUsingCheckBox : tasksUsingCheckBox) { 
    80                     if (tasksUsingGroup.contains(taskUsingCheckBox)) { 
    81                         continue CHECK_NEXT_GROUP; 
    82                     } 
    83                     else { 
    84                         tasksUsingGroup.add(taskUsingCheckBox); 
     129                if ((viewOfList == currentView) || 
     130                    ((viewOfList != null) && (viewOfList.equals(currentView)))) 
     131                { 
     132                    noOfGroupUsages++; 
     133                    boolean[] checkBoxUsages = new boolean[group.getValue().size()]; 
     134                     
     135                    for (IEventTaskInstance actionInstance : actionInstanceList) { 
     136                        int index = 0; 
     137                        for (IGUIElement checkBox : group.getValue()) { 
     138                            if ((("JFC".equals(actionInstance.getEvent().getTarget().getPlatform())) && 
     139                                 (actionInstance.getEvent().getType() instanceof MouseClick) && 
     140                                 (actionInstance.getEvent().getTarget().equals(checkBox))) || 
     141                                ((actionInstance.getEvent().getType() instanceof ValueSelection<?>) && 
     142                                 (actionInstance.getEvent().getTarget().equals(checkBox)))) 
     143                            { 
     144                                checkBoxUsages[index] = !checkBoxUsages[index]; 
     145                                noOfEvents++; 
     146                            } 
     147                            index++; 
     148                        } 
     149                    } 
     150                     
     151                    int noOfCheckedBoxes = 0; 
     152                     
     153                    for (int i = 0; i < checkBoxUsages.length; i++) { 
     154                        if (checkBoxUsages[i]) { 
     155                            noOfCheckedBoxes++; 
     156                        } 
     157                    } 
     158                     
     159                    if (noOfCheckedBoxes == 1) { 
     160                        noOfSingleCheckBoxUsages++; 
    85161                    } 
    86162                } 
    87163            } 
    88164             
    89             if (tasksUsingGroup.size() > 0) { 
    90                 int eventCoverage = 0; 
    91                 int allRecordedEvents = 0; 
    92                  
    93                 for (ITask task : tasksUsingGroup) { 
    94                     if (task instanceof IEventTask) { 
    95                         eventCoverage += 
    96                             taskModel.getTaskInfo(task).getMeasureValue(TaskMetric.EVENT_COVERAGE); 
    97                     } 
    98                 } 
    99                  
    100                 for (ITask task : taskModel.getTasks()) { 
    101                     if (task instanceof IEventTask) { 
    102                         allRecordedEvents += 
    103                             taskModel.getTaskInfo(task).getMeasureValue(TaskMetric.EVENT_COVERAGE); 
    104                     } 
    105                 } 
    106                  
    107                  
    108                 UsabilitySmellIntensity intensity = UsabilitySmellIntensity.getIntensity 
    109                     ((int) (1000 * eventCoverage / allRecordedEvents), eventCoverage, -1); 
    110                      
    111                 if (intensity != null) { 
    112                     Map<String, Object> parameters = new HashMap<String, Object>(); 
    113                     parameters.put("radioButtons", group); 
    114  
    115                     results.addSmell 
    116                         (intensity, UsabilitySmellDescription.CHECK_BOX_SINGLE_SELECTION, 
    117                          parameters); 
    118                 } 
    119             } 
    120         } 
    121     } 
    122  
    123     /** 
    124      *  
    125      */ 
    126     private Set<ITask> getTasksUsingCheckBox(final IGUIElement checkBox, ITaskModel taskModel) { 
    127         final Set<ITask> tasksUsingCheckBox = new HashSet<ITask>(); 
    128          
    129         for (ITask candidate : taskModel.getTasks()) { 
    130             candidate.accept(new DefaultTaskTraversingVisitor() { 
    131                 @Override 
    132                 public void visit(IEventTask eventTask) { 
    133                     if (!eventTask.getInstances().isEmpty()) { 
    134                         IEventTaskInstance instance = 
    135                             (IEventTaskInstance) eventTask.getInstances().iterator().next(); 
    136                          
    137                         if (checkBox.equals(instance.getEvent().getTarget())) { 
    138                             tasksUsingCheckBox.add(eventTask); 
    139                         } 
    140                     } 
    141                 } 
    142                  
    143                 @Override 
    144                 public void visit(IStructuringTemporalRelationship relationship) { 
    145                     if (tasksUsingCheckBox.contains(relationship)) { 
    146                         return; 
    147                     } 
    148                     else { 
    149                         for (ITask child : relationship.getChildren()) { 
    150                             if (tasksUsingCheckBox.contains(child)) { 
    151                                 tasksUsingCheckBox.add(relationship); 
    152                                 return; 
    153                             } 
    154                         } 
    155                          
    156                         super.visit(relationship); 
    157                          
    158                         for (ITask child : relationship.getChildren()) { 
    159                             if (tasksUsingCheckBox.contains(child)) { 
    160                                 tasksUsingCheckBox.add(relationship); 
    161                                 break; 
    162                             } 
    163                         } 
    164                     } 
    165                 } 
    166  
    167                 @Override 
    168                 public void visit(IMarkingTemporalRelationship relationship) { 
    169                     if (tasksUsingCheckBox.contains(relationship)) { 
    170                         return; 
    171                     } 
    172                     else { 
    173                         if (tasksUsingCheckBox.contains(relationship.getMarkedTask())) { 
    174                             tasksUsingCheckBox.add(relationship); 
    175                             return; 
    176                         } 
    177                          
    178                         super.visit(relationship); 
    179                          
    180                         if (tasksUsingCheckBox.contains(relationship.getMarkedTask())) { 
    181                             tasksUsingCheckBox.add(relationship); 
    182                             return; 
    183                         } 
    184                     } 
    185                 } 
    186             }); 
    187         } 
    188          
    189         return tasksUsingCheckBox; 
     165            // get a value that is 1 if for one group usage there is on average one check box usage 
     166            // get a value of 0 if for one group usage there is on average two check box usages 
     167             
     168            int ratio = noOfGroupUsages > 0 ? 1000 * noOfSingleCheckBoxUsages / noOfGroupUsages : 0; 
     169             
     170            System.out.println(currentView + "  " + ratio + "  " + noOfGroupUsages + "  " + 
     171                               noOfSingleCheckBoxUsages); 
     172             
     173            UsabilitySmellIntensity intensity = UsabilitySmellIntensity.getIntensity 
     174                (ratio, noOfEvents, -1); 
     175                     
     176            if (intensity != null) { 
     177                Map<String, Object> parameters = new HashMap<String, Object>(); 
     178                parameters.put("allUsages", noOfGroupUsages); 
     179                parameters.put("singleUsages", noOfSingleCheckBoxUsages); 
     180                parameters.put("ratio", 100 * noOfSingleCheckBoxUsages / noOfGroupUsages); 
     181                parameters.put("radioButtons", group.getValue()); 
     182 
     183                results.addSmell 
     184                    (intensity, UsabilitySmellDescription.CHECK_BOX_SINGLE_SELECTION, parameters); 
     185            } 
     186        } 
    190187    } 
    191188 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/DataEntryMethodChangeRule.java

    r1960 r2042  
    2929import de.ugoe.cs.autoquest.eventcore.gui.ValueSelection; 
    3030import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskInstanceTraversingVisitor; 
     31import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskTraversingVisitor; 
     32import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask; 
    3133import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance; 
    3234import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence; 
     
    98100                int ratio = getAverageDataEntryMethodChangeRatio((ISequence) task); 
    99101                 
    100                 if (ratio > 0) { 
     102                if ((ratio > 0) && (getLeafNodes(task) > 2)) { 
    101103                    methodChangeRatios.put(task, ratio); 
    102104                } 
     
    105107         
    106108        return methodChangeRatios; 
     109    } 
     110 
     111    /** 
     112     * 
     113     */ 
     114    private int getLeafNodes(ITask task) { 
     115        final int[] counter = new int[1]; 
     116         
     117        task.accept(new DefaultTaskTraversingVisitor() { 
     118            @Override 
     119            public void visit(IEventTask eventTask) { 
     120                counter[0]++; 
     121            } 
     122        }); 
     123         
     124        return counter[0]; 
    107125    } 
    108126 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/DefaultValueRule.java

    r1941 r2042  
    2929 
    3030import de.ugoe.cs.autoquest.eventcore.Event; 
     31import de.ugoe.cs.autoquest.eventcore.gui.MouseClick; 
    3132import de.ugoe.cs.autoquest.eventcore.gui.TextInput; 
    3233import de.ugoe.cs.autoquest.eventcore.gui.ValueSelection; 
    3334import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModel; 
    3435import de.ugoe.cs.autoquest.eventcore.guimodel.ICheckBox; 
     36import de.ugoe.cs.autoquest.eventcore.guimodel.IComboBox; 
    3537import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement; 
    3638import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec; 
     
    136138            maxObserved = Math.max(maxObserved, selectedValue.getValue()); 
    137139             
    138             if (mostOftenSelected.size() > 0) { 
    139                 ListIterator<Object> iterator = mostOftenSelected.listIterator(); 
    140                 while (iterator.hasNext()) { 
    141                     if (selectedValues.get(iterator.next()) < selectedValue.getValue()) { 
    142                         iterator.previous(); 
    143                         iterator.add(selectedValue.getKey()); 
    144                      
    145                         while (mostOftenSelected.size() > 5) { 
    146                             mostOftenSelected.removeLast(); 
    147                         } 
    148                      
    149                         break; 
    150                     } 
    151                 } 
    152             } 
    153             else { 
     140            boolean added = false; 
     141            ListIterator<Object> iterator = mostOftenSelected.listIterator(); 
     142            while (iterator.hasNext()) { 
     143                if (selectedValues.get(iterator.next()) < selectedValue.getValue()) { 
     144                    iterator.previous(); 
     145                    iterator.add(selectedValue.getKey()); 
     146                    added = true; 
     147                    break; 
     148                } 
     149            } 
     150             
     151            if (!added) { 
    154152                mostOftenSelected.add(selectedValue.getKey()); 
     153            } 
     154             
     155            while (mostOftenSelected.size() > 5) { 
     156                mostOftenSelected.removeLast(); 
    155157            } 
    156158        } 
     
    163165        } 
    164166         
    165         if ((expected.length == 1) || 
     167        if ((expected.length > 1) && 
    166168            (new ChiSquareTest().chiSquareTest(expected, observed, 0.05))) 
    167169        { 
     
    218220     */ 
    219221    private boolean isValueSelection(ITaskInstance instance) { 
    220         return (instance instanceof IEventTaskInstance) && 
    221             ((((IEventTaskInstance) instance).getEvent().getType() instanceof TextInput) || 
    222              (((IEventTaskInstance) instance).getEvent().getType() instanceof ValueSelection)); 
     222        if (instance instanceof IEventTaskInstance) { 
     223            Event event = ((IEventTaskInstance) instance).getEvent(); 
     224         
     225            if ((event.getType() instanceof TextInput) || 
     226                (event.getType() instanceof ValueSelection)) 
     227            { 
     228                return true; 
     229            } 
     230             
     231            if (("JFC".equals(event.getTarget().getPlatform())) && 
     232                (event.getTarget() instanceof ICheckBox) && 
     233                (event.getType() instanceof MouseClick)) 
     234            { 
     235                return true; 
     236            } 
     237        } 
     238         
     239        return false; 
    223240    } 
    224241 
     
    439456                        ((ValueSelection<?>) valueChange.getEvent().getType()).getSelectedValue(); 
    440457                     
    441                     if ((target instanceof IRadioButton) || (target instanceof ICheckBox)) { 
     458                    if ((target.target instanceof IRadioButton) || 
     459                        (target.target instanceof ICheckBox)) 
     460                    { 
    442461                        selectedValue = selectedValue + " (" + target + ")"; 
     462                    } 
     463                    else if (target.target instanceof IComboBox) { 
     464                        if (selectedValue == null) { 
     465                            // this may have happened due to the recording issue that selected 
     466                            // values of combo boxes are not logged correctly. In this case, 
     467                            // pretend to have the a random value selected 
     468                            selectedValue = "randomValueDueToRecordingBug_" + Math.random();  
     469                        } 
     470                    } 
     471                } 
     472                else if (valueChange.getEvent().getType() instanceof MouseClick) { 
     473                    if ((target.target instanceof IRadioButton) || 
     474                        (target.target instanceof ICheckBox)) 
     475                    { 
     476                        selectedValue = target.toString(); 
     477                    } 
     478                    else { 
     479                        throw new IllegalStateException("the implementation needs to be extended " + 
     480                                                        "to fully support clicks as value changes"); 
    443481                    } 
    444482                } 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/MisleadingClickCueRule.java

    r1918 r2042  
    2424import de.ugoe.cs.autoquest.eventcore.gui.MouseClick; 
    2525import de.ugoe.cs.autoquest.eventcore.gui.MouseDoubleClick; 
     26import de.ugoe.cs.autoquest.eventcore.guimodel.IButton; 
    2627import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement; 
    2728import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIView; 
     
    6566                                   UsabilityEvaluationResult results) 
    6667    { 
    67         for (Map.Entry<IGUIView, Map<IGUIElement, Integer>> uselessClickCounter : 
     68        for (Map.Entry<IGUIElement, Map<IGUIView, Integer>> uselessClickCounter : 
    6869                statistics.getUselessClickCounters().entrySet()) 
    6970        { 
    70             for (Map.Entry<IGUIElement, Integer> counter : uselessClickCounter.getValue().entrySet()) 
    71             { 
    72                 int uselessClicks = counter.getValue(); 
    73                 int noOfViewDisplays = statistics.getViewOpenedCount(uselessClickCounter.getKey()); 
    74  
    75                 int ratio = Math.min(1000, 1000 * uselessClicks / noOfViewDisplays); 
    76  
    77                 UsabilitySmellIntensity intensity = 
    78                     UsabilitySmellIntensity.getIntensity(ratio, uselessClicks, -1); 
    79  
    80                 if (intensity != null) { 
    81                     Map<String, Object> parameters = new HashMap<String, Object>(); 
    82                     parameters.put("noOfViewDisplays", noOfViewDisplays); 
    83                     parameters.put("uselessClicks", uselessClicks); 
    84                     parameters.put("element", counter.getKey()); 
    85                     parameters.put("view", uselessClickCounter.getKey()); 
    86  
    87                     results.addSmell 
    88                         (intensity, UsabilitySmellDescription.MISLEADING_CLICK_CUE, parameters); 
    89                 } 
     71            int uselessClicks = 0; 
     72            int noOfViewDisplays = 0; 
     73             
     74            for (Map.Entry<IGUIView, Integer> counter : uselessClickCounter.getValue().entrySet()) { 
     75                uselessClicks += counter.getValue(); 
     76                noOfViewDisplays += statistics.getViewOpenedCount(counter.getKey()); 
     77            } 
     78 
     79            int ratio = Math.min(1000, 1000 * uselessClicks / noOfViewDisplays); 
     80 
     81            UsabilitySmellIntensity intensity = 
     82                UsabilitySmellIntensity.getIntensity(ratio, uselessClicks, -1); 
     83 
     84            if (intensity != null) { 
     85                Map<String, Object> parameters = new HashMap<String, Object>(); 
     86                parameters.put("noOfViewDisplays", noOfViewDisplays); 
     87                parameters.put("uselessClicks", uselessClicks); 
     88                parameters.put("element", uselessClickCounter.getKey()); 
     89 
     90                results.addSmell 
     91                    (intensity, UsabilitySmellDescription.MISLEADING_CLICK_CUE, parameters); 
    9092            } 
    9193        } 
     
    155157            (target instanceof IText)) 
    156158        { 
    157             return true; 
     159            // check if the parent is a button 
     160            IGUIElement parent = target; 
     161            while ((parent != null) && !(parent instanceof IButton)) { 
     162                parent = parent.getParent(); 
     163            } 
     164             
     165            return !(parent instanceof IButton); 
    158166        } 
    159167        else { 
     
    171179         
    172180        /** */ 
    173         private Map<IGUIView, Map<IGUIElement, Integer>> uselessClickCounters = new HashMap<>(); 
     181        private Map<IGUIElement, Map<IGUIView, Integer>> uselessClickCounters = new HashMap<>(); 
    174182 
    175183        /** 
     
    199207         */ 
    200208        private void addUselessClick(IEventTaskInstance eventTaskInstance) { 
    201             Map<IGUIElement, Integer> counterMap = uselessClickCounters.get 
    202                 (((IGUIElement) eventTaskInstance.getEvent().getTarget()).getView()); 
     209            IGUIElement target = (IGUIElement) eventTaskInstance.getEvent().getTarget(); 
     210             
     211            Map<IGUIView, Integer> counterMap = uselessClickCounters.get(target); 
    203212             
    204213            if (counterMap == null) { 
    205214                counterMap = new HashMap<>(); 
    206                 uselessClickCounters.put 
    207                     (((IGUIElement) eventTaskInstance.getEvent().getTarget()).getView(), counterMap); 
    208             } 
    209              
    210             Integer counter = counterMap.get(eventTaskInstance.getEvent().getTarget()); 
     215                uselessClickCounters.put(target, counterMap); 
     216            } 
     217             
     218            Integer counter = counterMap.get(target.getView()); 
    211219             
    212220            if (counter == null) { 
    213                 counterMap.put((IGUIElement) eventTaskInstance.getEvent().getTarget(), 1); 
     221                counterMap.put(target.getView(), 1); 
    214222            } 
    215223            else { 
    216                 counterMap.put((IGUIElement) eventTaskInstance.getEvent().getTarget(), counter + 1); 
    217             } 
    218         } 
    219  
    220         /** 
    221          * 
    222          */ 
    223         private Map<IGUIView, Map<IGUIElement, Integer>> getUselessClickCounters() { 
     224                counterMap.put(target.getView(), counter + 1); 
     225            } 
     226        } 
     227 
     228        /** 
     229         * 
     230         */ 
     231        private Map<IGUIElement, Map<IGUIView, Integer>> getUselessClickCounters() { 
    224232            return uselessClickCounters; 
    225233        } 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/MissingFeedbackRule.java

    r1918 r2042  
    195195         
    196196        if (clicksOnIdenticalButton != null) { 
     197            if (clicksOnIdenticalButton.size() > 1) { 
     198                //throw new IllegalStateException("not described in dissertation"); 
     199            } 
     200             
    197201            long cummulativeImpatience = 0; 
    198202             
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/TextInputStatisticsRule.java

    r1918 r2042  
    107107            int noOfUsagesOfTextField1 = statistics.getUsageCount(entry.textField1); 
    108108            int noOfUsagesOfTextField2 = statistics.getUsageCount(entry.textField2); 
    109             int noOfUsagesOfTextField1WithSameTextInTextField2 = entry.enteredTexts.size(); 
    110              
    111             int ratioTextField1 =  
    112                 1000 * noOfUsagesOfTextField1WithSameTextInTextField2 / noOfUsagesOfTextField1; 
    113              
    114             int ratioTextField2 = 
    115                 1000 * noOfUsagesOfTextField1WithSameTextInTextField2 / noOfUsagesOfTextField2; 
    116  
    117             createTextFieldEntryRepetitionSmell(ratioTextField1, entry.textField1, 
    118                                                  entry.textField2, results); 
    119              
    120             createTextFieldEntryRepetitionSmell(ratioTextField2, entry.textField2, 
    121                                                  entry.textField1, results); 
    122              
    123         } 
    124     } 
    125  
    126     /** 
    127      * 
    128      */ 
    129     private void createTextFieldEntryRepetitionSmell(int                       ratioOfEqualEntries, 
    130                                                       ITextField                textField1, 
    131                                                       ITextField                textField2, 
    132                                                       UsabilityEvaluationResult results) 
    133     { 
     109            int numberOfEqualEntries = entry.enteredTexts.size(); 
     110             
     111            createTextFieldEntryRepetitionSmell(noOfUsagesOfTextField1, numberOfEqualEntries, 
     112                                                entry.textField1, entry.textField2, results); 
     113             
     114            createTextFieldEntryRepetitionSmell(noOfUsagesOfTextField2, numberOfEqualEntries, 
     115                                                entry.textField2, entry.textField1, results); 
     116             
     117        } 
     118    } 
     119 
     120    /** 
     121     * 
     122     */ 
     123    private void createTextFieldEntryRepetitionSmell(int                       allEntries, 
     124                                                     int                       numberOfEqualEntries, 
     125                                                     ITextField                textField1, 
     126                                                     ITextField                textField2, 
     127                                                     UsabilityEvaluationResult results) 
     128    { 
     129        int ratio = 1000 * numberOfEqualEntries / allEntries; 
     130         
    134131        UsabilitySmellIntensity severity = 
    135             UsabilitySmellIntensity.getIntensity(ratioOfEqualEntries); 
     132            UsabilitySmellIntensity.getIntensity(ratio, allEntries, -1); 
    136133         
    137134        if (severity != null) { 
    138135            Map<String, Object> parameters = new HashMap<String, Object>(); 
    139             parameters.put("textRepetitionRatio", (ratioOfEqualEntries / 10)); 
     136            parameters.put("numberOfEqualEntries", numberOfEqualEntries); 
     137            parameters.put("numberOfAllEntries", allEntries); 
     138            parameters.put("textRepetitionRatio", (ratio / 10)); 
    140139            parameters.put("textField1", textField1); 
    141140            parameters.put("textField2", textField2); 
     
    169168            int ratio = 1000 * noLetterOrDigitCount / allCharactersCount; 
    170169 
    171             UsabilitySmellIntensity severity = UsabilitySmellIntensity.getIntensity(ratio); 
     170            UsabilitySmellIntensity severity = UsabilitySmellIntensity.getIntensity 
     171                (ratio, statistics.getAllInputsInto(textField).size(), -1); 
    172172 
    173173            if (severity != null) { 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UnusedGUIElementsRule.java

    r1918 r2042  
    1515package de.ugoe.cs.autoquest.usability; 
    1616 
     17import java.util.ArrayList; 
    1718import java.util.HashMap; 
    1819import java.util.HashSet; 
     
    2829import de.ugoe.cs.autoquest.eventcore.guimodel.IComboBox; 
    2930import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement; 
     31import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIView; 
    3032import de.ugoe.cs.autoquest.eventcore.guimodel.IListBox; 
    3133import de.ugoe.cs.autoquest.eventcore.guimodel.IMenuButton; 
    3234import de.ugoe.cs.autoquest.eventcore.guimodel.ITextArea; 
    3335import de.ugoe.cs.autoquest.eventcore.guimodel.ITextField; 
     36import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskInstanceTraversingVisitor; 
    3437import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask; 
    3538import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance; 
     
    3740import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance; 
    3841import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel; 
     42import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession; 
    3943 
    4044/** 
     
    5458    public UsabilityEvaluationResult evaluate(ITaskModel taskModel) { 
    5559        UsabilityEvaluationResult results = new UsabilityEvaluationResult(taskModel); 
    56  
    57         GUIModel guiModel = getGUIModel(taskModel); 
    58         Set<IGUIElement> allGUIElements = getAllGUIElements(guiModel); 
    59         Set<IGUIElement> usedGUIElements = getUsedGUIElements(taskModel); 
    60         List<IGUIElement> unusedGUIElements = getUnusedGUIElements(usedGUIElements, allGUIElements); 
    61         handleUnusedGUIElements(unusedGUIElements, allGUIElements, results); 
     60         
     61        Map<IGUIView, List<Set<IGUIElement>>> viewDisplays = 
     62            getViewDisplays(taskModel.getUserSessions()); 
     63         
     64        Map<IGUIView, Set<IGUIElement>> allGUIElements = getAllGUIElements(taskModel); 
     65         
     66        for (Map.Entry<IGUIView, List<Set<IGUIElement>>> viewDisplay : viewDisplays.entrySet()) { 
     67            handleUnusedGUIElements 
     68                (allGUIElements, viewDisplay.getKey(), viewDisplay.getValue(), results); 
     69        } 
    6270 
    6371        return results; 
     
    6573 
    6674    /** 
    67      * <p> 
    68      * TODO: comment 
    69      * </p> 
     75     * @param results  
    7076     * 
    71      * @param unusedGUIElements 
    72      * @param results 
    73      */ 
    74     private void handleUnusedGUIElements(List<IGUIElement>         unusedGUIElements, 
    75                                          Set<IGUIElement>          allGUIElements, 
    76                                          UsabilityEvaluationResult results) 
     77     */ 
     78    private void handleUnusedGUIElements(Map<IGUIView, Set<IGUIElement>> usedGUIElements, 
     79                                         IGUIView                        view, 
     80                                         List<Set<IGUIElement>>          viewUsages, 
     81                                         UsabilityEvaluationResult       results) 
    7782    { 
    78         int ratio = 1000 * unusedGUIElements.size() / allGUIElements.size(); 
    79          
    80         UsabilitySmellIntensity severity = UsabilitySmellIntensity.getIntensity(ratio); 
    81  
    82         if (severity != null) { 
    83             Map<String, Object> parameters = new HashMap<String, Object>(); 
    84  
    85             parameters.put("ratio", ratio / 10); 
    86             parameters.put("noOfUnused", unusedGUIElements.size()); 
    87             parameters.put("noOfAll", allGUIElements.size()); 
    88             parameters.put("unusedGuiElements", unusedGUIElements); 
    89              
    90             results.addSmell 
    91                 (severity, UsabilitySmellDescription.UNUSED_GUI_ELEMENTS, parameters); 
    92         } 
    93      } 
    94  
    95     /** 
    96      * <p> 
    97      * TODO: comment 
    98      * </p> 
     83        Set<IGUIElement> allElementsInView = usedGUIElements.get(view); 
     84         
     85        if (allElementsInView == null) { 
     86            return; 
     87        } 
     88         
     89        Map<Integer, List<IGUIElement>> usageCounters = new HashMap<>(); 
     90         
     91        for (IGUIElement relevantElement : allElementsInView) { 
     92            int usageCounter = 0; 
     93             
     94            for (Set<IGUIElement> viewUsage : viewUsages) { 
     95                if (viewUsage.contains(relevantElement)) { 
     96                    usageCounter++; 
     97                } 
     98            } 
     99             
     100            List<IGUIElement> elementsWithSameUsage = usageCounters.get(usageCounter); 
     101             
     102            if (elementsWithSameUsage == null) { 
     103                elementsWithSameUsage = new LinkedList<>(); 
     104                usageCounters.put(usageCounter, elementsWithSameUsage); 
     105            } 
     106             
     107            elementsWithSameUsage.add(relevantElement); 
     108        } 
     109         
     110        int cumulativeGuiElementUsage = 0; 
     111        for (Set<IGUIElement> viewUsage : viewUsages) { 
     112            cumulativeGuiElementUsage += viewUsage.size(); 
     113        } 
     114         
     115        List<IGUIElement> unusedElements = usageCounters.get(0); 
     116         
     117        if (unusedElements != null) { 
     118            int ratio = 1000 * unusedElements.size() / allElementsInView.size(); 
     119 
     120            UsabilitySmellIntensity severity = UsabilitySmellIntensity.getIntensity 
     121                (ratio, cumulativeGuiElementUsage, -1); 
     122 
     123            if (severity != null) { 
     124                Map<String, Object> parameters = new HashMap<String, Object>(); 
     125 
     126                parameters.put("ratio", ratio / 10); 
     127                parameters.put("allDisplays", viewUsages.size()); 
     128                parameters.put("view", view); 
     129                parameters.put("unusedGuiElements", unusedElements); 
     130                parameters.put("allGuiElements", allElementsInView.size()); 
     131 
     132                results.addSmell 
     133                    (severity, UsabilitySmellDescription.UNUSED_GUI_ELEMENTS, parameters); 
     134            } 
     135        } 
     136    } 
     137 
     138    /** 
    99139     * 
    100      * @param taskModel 
    101      * @return 
    102      */ 
    103     private GUIModel getGUIModel(ITaskModel taskModel) { 
     140     */ 
     141    private Map<IGUIView, Set<IGUIElement>> getAllGUIElements(ITaskModel taskModel) { 
     142        Map<IGUIView, Set<IGUIElement>> result = new HashMap<>(); 
     143         
    104144        for (ITask task : taskModel.getTasks()) { 
    105145            if (task instanceof IEventTask) { 
     
    107147                    Event event = ((IEventTaskInstance) instance).getEvent(); 
    108148                     
    109                     if (event.getTarget() instanceof IGUIElement) { 
    110                         return ((IGUIElement) event.getTarget()).getGUIModel(); 
     149                    if ((event.getTarget() instanceof IGUIElement) && 
     150                        (isRelevant((IGUIElement) event.getTarget()))) 
     151                    { 
     152                        IGUIView view = ((IGUIElement) event.getTarget()).getView(); 
     153                         
     154                        Set<IGUIElement> elements = result.get(view); 
     155                         
     156                        if (elements == null) { 
     157                            elements = new HashSet<>(); 
     158                            result.put(view, elements); 
     159                        } 
     160                         
     161                        elements.add((IGUIElement) event.getTarget()); 
    111162                    } 
    112163                } 
     
    114165        } 
    115166         
    116         return null; 
    117     } 
    118  
    119     /** 
    120      * <p> 
    121      * TODO: comment 
    122      * </p> 
    123      * 
    124      * @param taskModel 
    125      */ 
    126     private Set<IGUIElement> getUsedGUIElements(ITaskModel taskModel) { 
    127         Set<IGUIElement> usedGUIElements = new HashSet<IGUIElement>(); 
    128          
    129         for (ITask task : taskModel.getTasks()) { 
    130             if (task instanceof IEventTask) { 
    131                 for (ITaskInstance instance : task.getInstances()) { 
    132                     Event event = ((IEventTaskInstance) instance).getEvent(); 
    133                      
    134                     if (event.getTarget() instanceof IGUIElement) { 
    135                         usedGUIElements.add((IGUIElement) event.getTarget()); 
     167        // the problem is, that using the GUI model does not allow to find all in a specific view 
     168        // as the GUI model may return a merged element instead. But anyway, we can add those, which 
     169        // are in the GUI model and have the same view. 
     170         
     171        GUIModel model = result.values().iterator().next().iterator().next().getGUIModel(); 
     172         
     173        GUIModel.Traverser traverser = model.getTraverser(); 
     174 
     175        IGUIElement currentGUIElement = null; 
     176        do { 
     177            if (traverser.hasFirstChild()) { 
     178                currentGUIElement = traverser.firstChild(); 
     179            } 
     180            else if (traverser.hasNextSibling()) { 
     181                currentGUIElement = traverser.nextSibling(); 
     182            } 
     183            else { 
     184                while (currentGUIElement != null) { 
     185                    currentGUIElement = traverser.parent(); 
     186                    if (traverser.hasNextSibling()) { 
     187                        currentGUIElement = traverser.nextSibling(); 
     188                        break; 
    136189                    } 
    137190                } 
    138191            } 
    139         } 
    140          
    141         return usedGUIElements; 
    142     } 
    143      
    144     /** 
    145      * <p> 
    146      * TODO: comment 
    147      * </p> 
    148      * 
    149      * @param taskModel 
    150      */ 
    151     private Set<IGUIElement> getAllGUIElements(GUIModel guiModel) { 
    152         Set<IGUIElement> allGUIElements = new HashSet<IGUIElement>(); 
    153          
    154         if (guiModel != null) { 
    155             GUIModel.Traverser traverser = guiModel.getTraverser(); 
    156  
    157             IGUIElement currentGUIElement = null; 
    158             do { 
    159                 if (traverser.hasFirstChild()) { 
    160                     currentGUIElement = traverser.firstChild(); 
    161                 } 
    162                 else if (traverser.hasNextSibling()) { 
    163                     currentGUIElement = traverser.nextSibling(); 
    164                 } 
    165                 else { 
    166                     while (currentGUIElement != null) { 
    167                         currentGUIElement = traverser.parent(); 
    168                         if (traverser.hasNextSibling()) { 
    169                             currentGUIElement = traverser.nextSibling(); 
    170                             break; 
     192 
     193            if (isRelevant(currentGUIElement)) { 
     194                IGUIView view = currentGUIElement.getView(); 
     195                 
     196                Set<IGUIElement> elements = result.get(view); 
     197                 
     198                if (elements == null) { 
     199                    elements = new HashSet<>(); 
     200                    result.put(view, elements); 
     201                } 
     202                 
     203                elements.add(currentGUIElement); 
     204            } 
     205        } 
     206        while (currentGUIElement != null); 
     207         
     208        return result; 
     209    } 
     210 
     211    /** 
     212     *  
     213     */ 
     214    private Map<IGUIView, List<Set<IGUIElement>>> getViewDisplays(List<IUserSession> sessions) { 
     215        final IGUIView[] currentView = new IGUIView[1]; 
     216        final List<IEventTaskInstance> actionInstances = new ArrayList<>(); 
     217        final Map<IGUIView, List<Set<IGUIElement>>> result = new HashMap<>(); 
     218         
     219        for (IUserSession session : sessions) { 
     220            currentView[0] = null; 
     221            actionInstances.clear(); 
     222             
     223            for (final ITaskInstance currentRoot : session) { 
     224                currentRoot.accept(new DefaultTaskInstanceTraversingVisitor() { 
     225                    @Override 
     226                    public void visit(IEventTaskInstance eventTaskInstance) { 
     227                        if (eventTaskInstance.getEvent().getTarget() instanceof IGUIElement) { 
     228                            IGUIView view = 
     229                                ((IGUIElement) eventTaskInstance.getEvent().getTarget()).getView(); 
     230                             
     231                            if ((currentView[0] == null) && (view != null)) { 
     232                                currentView[0] = view; 
     233                                actionInstances.clear(); 
     234                            } 
     235                            else if ((currentView[0] != null) && (!currentView[0].equals(view))) { 
     236                                addRelevantTargets(currentView[0], actionInstances, result); 
     237                                 
     238                                currentView[0] = view; 
     239                                actionInstances.clear(); 
     240                            } 
     241                        } 
     242                         
     243                        if (eventTaskInstance.getEvent().getTarget() instanceof IGUIElement) { 
     244                            actionInstances.add(eventTaskInstance); 
    171245                        } 
    172246                    } 
    173                 } 
    174  
    175                 if (isRelevant(currentGUIElement)) { 
    176                     allGUIElements.add(currentGUIElement); 
    177                 } 
    178             } 
    179             while (currentGUIElement != null); 
    180         } 
    181          
    182         return allGUIElements; 
    183     } 
    184      
    185     /** 
    186      * <p> 
    187      * TODO: comment 
    188      * </p> 
     247                }); 
     248            } 
     249             
     250            // add the used GUI elements of the last shown view in the session 
     251            if (currentView[0] != null) { 
     252                addRelevantTargets(currentView[0], actionInstances, result); 
     253            } 
     254        } 
     255         
     256        return result; 
     257    } 
     258 
     259    /** 
    189260     * 
    190      * @param taskModel 
    191      */ 
    192     private List<IGUIElement> getUnusedGUIElements(Set<IGUIElement> usedGUIElements, 
    193                                                    Set<IGUIElement> allGUIElements) 
     261     */ 
     262    private void addRelevantTargets(IGUIView                              view, 
     263                                    List<IEventTaskInstance>              actionInstances, 
     264                                    Map<IGUIView, List<Set<IGUIElement>>> result) 
    194265    { 
    195         List<IGUIElement> unusedGUIElements = new LinkedList<IGUIElement>(); 
    196         for (IGUIElement currentGUIElement : allGUIElements) { 
    197             if (isRelevant(currentGUIElement) && 
    198                 !belongsToUsedGUIElements(currentGUIElement, usedGUIElements)) 
    199             { 
    200                 unusedGUIElements.add(currentGUIElement); 
    201             } 
    202         } 
    203          
    204         return unusedGUIElements; 
    205     } 
    206  
    207     /** 
    208      * <p> 
    209      * TODO: comment 
    210      * </p> 
     266        List<Set<IGUIElement>> usedGUIElements = result.get(view); 
     267         
     268        if (usedGUIElements == null) { 
     269            usedGUIElements = new LinkedList<>(); 
     270            result.put(view, usedGUIElements); 
     271        } 
     272         
     273        Set<IGUIElement> elementsInViewDisplay = new HashSet<>(); 
     274         
     275        for (IEventTaskInstance actionInstance : actionInstances) { 
     276            IGUIElement element = (IGUIElement) actionInstance.getEvent().getTarget(); 
     277             
     278            while (element != null) { 
     279                if (isRelevant(element)) { 
     280                    elementsInViewDisplay.add(element); 
     281                } 
     282                 
     283                element = element.getParent(); 
     284            } 
     285        } 
     286         
     287        usedGUIElements.add(elementsInViewDisplay); 
     288    } 
     289 
     290    /** 
    211291     * 
    212      * @param currentGUIElement 
    213      * @param usedGUIElements 
    214      * @return 
    215      */ 
    216     private boolean belongsToUsedGUIElements(IGUIElement      relevantGUIElement, 
    217                                              Set<IGUIElement> usedGUIElements) 
    218     { 
    219         if (usedGUIElements.contains(relevantGUIElement)) { 
    220             return true; 
    221         } 
    222         else { 
    223             // in some cases, the events are recorded for the children of the relevant GUI elements 
    224             // therefore, check the children, as well. 
    225             List<IGUIElement> children = 
    226                 relevantGUIElement.getGUIModel().getChildren(relevantGUIElement); 
    227              
    228             if (children != null) { 
    229                 for (IGUIElement child : children) { 
    230                     if (belongsToUsedGUIElements(child, usedGUIElements)) { 
    231                         return true; 
    232                     } 
    233                 } 
    234             } 
    235         } 
    236          
    237         return false; 
    238     } 
    239  
    240     /** 
    241      * <p> 
    242      * TODO: comment 
    243      * </p> 
    244      * 
    245      * @param currentGUIElement 
    246      * @return 
    247292     */ 
    248293    private boolean isRelevant(IGUIElement currentGUIElement) { 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityEvaluationManager.java

    r1918 r2042  
    1616 
    1717import java.util.ArrayList; 
     18import java.util.HashMap; 
     19import java.util.LinkedList; 
    1820import java.util.List; 
     21import java.util.ListIterator; 
     22import java.util.Map; 
    1923import java.util.logging.Level; 
    2024 
     
    4852     */ 
    4953    private void init() { 
    50         rules.add(new TaskTreeTestRule()); 
    51 //        rules.add(new TextInputStatisticsRule()); 
    52 //        rules.add(new MissingFeedbackRule()); 
    53 //        rules.add(new EventCoverageRatioRule()); 
    54 //        rules.add(new TargetDistanceRule()); 
    55 //        rules.add(new RequiredInefficientActionsRule()); 
    56 //        rules.add(new DataEntryMethodChangeRule()); 
     54//        rules.add(new TaskTreeTestRule()); 
     55         
     56        rules.add(new EventCoverageRatioRule()); 
     57        rules.add(new RequiredInefficientActionsRule()); 
     58        rules.add(new TargetDistanceRule()); 
     59        rules.add(new MissingFeedbackRule()); 
     60        rules.add(new DataEntryMethodChangeRule()); 
     61        rules.add(new CommonTaskRateRule()); 
     62        rules.add(new TextInputStatisticsRule()); 
     63        rules.add(new CheckBoxMultipleSelectionRule()); 
     64        rules.add(new MisleadingClickCueRule()); 
     65        rules.add(new DefaultCursorPositioningRule()); 
    5766        rules.add(new DefaultValueRule()); 
    58 //        rules.add(new CheckBoxMultipleSelectionRule()); 
    59 //        rules.add(new CommonTaskRateRule()); 
    60 //        rules.add(new MisleadingClickCueRule()); 
    61 //        rules.add(new DefaultCursorPositioningRule()); 
    62 //        rules.add(new UnusedGUIElementsRule()); 
     67        rules.add(new UnusedGUIElementsRule()); 
     68         
    6369//        rules.add(new TaskCooccurrenceRule()); 
    6470    } 
     
    6773     * 
    6874     */ 
    69     public UsabilityEvaluationResult evaluateUsability(ITaskModel taskModel) { 
     75    public UsabilityEvaluationResult evaluateUsability(ITaskModel taskModel, int maxCount) { 
    7076        Console.traceln(Level.INFO, "evaluating usability of task model " + taskModel); 
    7177 
     
    7379 
    7480        for (UsabilityEvaluationRule rule : rules) { 
    75             Console.traceln(Level.INFO, "applying rule " + rule.getClass().getSimpleName()); 
     81            Console.traceln(Level.INFO, "\napplying rule " + rule.getClass().getSimpleName()); 
    7682            UsabilityEvaluationResult result = rule.evaluate(taskModel); 
    77             interimResults.add(result); 
    78             Console.traceln(Level.INFO, "the rule found " + result.getAllSmells().size() + 
    79                             " usability smells."); 
    80              
    81             List<ITask> referredTasks = new ArrayList<ITask>(); 
    82  
     83 
     84            Map<String, List<UsabilitySmell>> smellGroups = new HashMap<>(); 
     85             
    8386            for (UsabilitySmell smell : result.getAllSmells()) { 
    84                 if (smell.getSmellingTask() != null) { 
    85                     referredTasks.add(smell.getSmellingTask()); 
    86                 } 
    87             } 
    88                  
    89             int counter = 0; 
    90             for (int i = 0; i < referredTasks.size(); i++) { 
    91                 for (int j = 0; j < referredTasks.size(); j++) { 
    92                     if (isChildOf(referredTasks.get(i), referredTasks.get(j))) { 
    93                         counter++; 
    94                         break; 
     87                List<UsabilitySmell> smellGroup = smellGroups.get(smell.getBriefDescription()); 
     88                 
     89                if (smellGroup == null) { 
     90                    smellGroup = new LinkedList<>(); 
     91                    smellGroups.put(smell.getBriefDescription(), smellGroup); 
     92                } 
     93                 
     94                smellGroup.add(smell); 
     95            } 
     96             
     97            for (Map.Entry<String, List<UsabilitySmell>> smellGroup : smellGroups.entrySet()) { 
     98                Console.traceln(Level.INFO, "the rule found " + smellGroup.getValue().size() + 
     99                                " usability smells of type \"" + smellGroup.getKey() + "\""); 
     100                 
     101                result = new UsabilityEvaluationResult(taskModel, smellGroup.getValue()); 
     102                 
     103                checkDuplicates(result); 
     104                 
     105                if (maxCount < result.getAllSmells().size()) { 
     106                    Console.traceln(Level.INFO, "filtering for " + maxCount + 
     107                                    " smells of same type with highest event coverage."); 
     108                 
     109                    LinkedList<UsabilitySmell> sortedSmells = new LinkedList<>(); 
     110                     
     111                    for (UsabilitySmell smell : result.getAllSmells()) { 
     112                        ListIterator<UsabilitySmell> iterator = sortedSmells.listIterator(); 
     113 
     114                        boolean added = false; 
     115                         
     116                        while (iterator.hasNext()) { 
     117                            if (iterator.next().getIntensity().getEventCoverage() < 
     118                                    smell.getIntensity().getEventCoverage()) 
     119                            { 
     120                                iterator.previous(); 
     121                                iterator.add(smell); 
     122                                added = true; 
     123                                break; 
     124                            } 
     125                        } 
     126                     
     127                        if (!added) { 
     128                            sortedSmells.add(smell); 
     129                        } 
     130                     
     131                        while (sortedSmells.size() > maxCount) { 
     132                            sortedSmells.removeLast(); 
     133                        } 
    95134                    } 
    96                 } 
    97             } 
    98                  
    99             if (counter > 0) { 
    100                 Console.traceln(Level.INFO, counter + " of the findings are duplicates in " + 
    101                                 "that they refer to tasks whose parent tasks are also " + 
    102                                 "referred by the findings"); 
     135                 
     136                    result = new UsabilityEvaluationResult(taskModel, sortedSmells); 
     137                    checkDuplicates(result); 
     138                } 
     139             
     140                interimResults.add(result); 
    103141            } 
    104142        } 
     
    112150 
    113151    /** 
    114      * <p> 
    115      * TODO: comment 
    116      * </p> 
    117152     * 
    118      * @param iTask 
    119      * @param iTask2 
    120      * @return 
     153     */ 
     154    private void checkDuplicates(UsabilityEvaluationResult result) { 
     155        List<ITask> referredTasks = new ArrayList<ITask>(); 
     156 
     157        for (UsabilitySmell smell : result.getAllSmells()) { 
     158            if (smell.getSmellingTask() != null) { 
     159                referredTasks.add(smell.getSmellingTask()); 
     160            } 
     161        } 
     162             
     163        int counter = 0; 
     164        for (int i = 0; i < referredTasks.size(); i++) { 
     165            for (int j = 0; j < referredTasks.size(); j++) { 
     166                if (isChildOf(referredTasks.get(i), referredTasks.get(j))) { 
     167                    counter++; 
     168                    break; 
     169                } 
     170            } 
     171        } 
     172             
     173        if (counter > 0) { 
     174            Console.traceln(Level.INFO, counter + " of the findings are duplicates in " + 
     175                            "that they refer to tasks whose parent tasks are also " + 
     176                            "referred by the findings"); 
     177        } 
     178    } 
     179 
     180    /** 
     181     * 
    121182     */ 
    122183    private boolean isChildOf(final ITask potChild, ITask potParent) { 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityEvaluationResult.java

    r1918 r2042  
    1616 
    1717import java.util.ArrayList; 
     18import java.util.Collection; 
    1819import java.util.List; 
    1920import java.util.Map; 
     
    4142    public UsabilityEvaluationResult(ITaskModel taskModel) { 
    4243        this.taskModel = taskModel; 
     44    } 
     45 
     46    /** 
     47     * 
     48     */ 
     49    public UsabilityEvaluationResult(ITaskModel                 taskModel, 
     50                                     Collection<UsabilitySmell> smells) 
     51    { 
     52        this.taskModel = taskModel; 
     53        for (UsabilitySmell smell : smells) { 
     54            this.smells.add(smell); 
     55        } 
    4356    } 
    4457 
  • trunk/autoquest-core-usability/src/main/resources/smellDescriptions_en.xml

    r1950 r2042  
    2121      In 
    2222    </textFragment> 
     23    <parameterFragment parameterName="numberOfEqualEntries" /> 
     24    <textFragment> 
     25      of 
     26    </textFragment> 
     27    <parameterFragment parameterName="numberOfAllEntries" /> 
     28    <textFragment> 
     29      times (  
     30    </textFragment> 
    2331    <parameterFragment parameterName="textRepetitionRatio" /> 
    2432    <textFragment> 
    25       % of entering text into text field  
     33      %) of entering text into text field  
    2634    </textFragment> 
    2735    <parameterFragment parameterName="textField1" /> 
     
    173181   
    174182  <smellDescription smellId="UNUSED_GUI_ELEMENTS" briefText="unused GUI elements"> 
    175     <parameterFragment parameterName="ratio" /> 
    176     <textFragment> 
    177       % of the GUI elements ( 
    178     </textFragment> 
    179     <parameterFragment parameterName="noOfUnused" /> 
    180     <textFragment> 
    181       of 
    182     </textFragment> 
    183     <parameterFragment parameterName="noOfAll" /> 
    184     <textFragment> 
    185       ) are not used. This can have several reasons. Either they are not 
    186       visible to the user or they are not required. If they are important, they may not be 
    187       recognized by the user. This can be caused by visual design or because they are too hidden. 
    188       If they are less important, they can either be removed from the GUI or relocated to a less 
    189       prominent position. The unused GUI elements are: 
     183    <textFragment> 
     184      In 
     185    </textFragment> 
     186    <parameterFragment parameterName="allDisplays" /> 
     187    <textFragment> 
     188      times the view 
     189    </textFragment> 
     190    <parameterFragment parameterName="view" /> 
     191    <textFragment> 
     192      is displayed, the following GUI elements belonging to the view were never used. They make up 
     193    </textFragment> 
     194    <parameterFragment parameterName="ratio" /> 
     195    <textFragment> 
     196      % of all 
     197    </textFragment> 
     198    <parameterFragment parameterName="allGuiElements" /> 
     199    <textFragment> 
     200      interaction elements in that view. This indicates, that they are not required and 
     201      can, therefore, be removed. The unused GUI elements are: 
    190202    </textFragment> 
    191203    <parameterFragment parameterName="unusedGuiElements" /> 
     
    227239  <smellDescription smellId="CHECK_BOX_SINGLE_SELECTION" briefText="check box single selection"> 
    228240    <textFragment> 
    229       Found a group of check boxes of which only one is usually selected. In this case, radio 
    230       buttons should be used instead, if the alternatives are mutually exclusive. The check boxes 
     241      Found a group of check boxes of which only one is usually selected. In 
     242    </textFragment> 
     243    <parameterFragment parameterName="allUsages" /> 
     244    <textFragment> 
     245      usages of the check box group, 
     246    </textFragment> 
     247    <parameterFragment parameterName="singleUsages" /> 
     248    <textFragment> 
     249      times ( 
     250    </textFragment> 
     251    <parameterFragment parameterName="ratio" /> 
     252    <textFragment> 
     253      %) only one of all check boxes was selected finally by the user (considering, that all 
     254      check boxes are always unchecked when they are displayed). If the alternatives represented by 
     255      the check boxes are mutually exclusive, radio buttons should be used instead. The check boxes 
    231256      belonging to the group are: 
    232257    </textFragment> 
     
    255280    <parameterFragment parameterName="noOfViewDisplays" /> 
    256281    <textFragment> 
    257       times the view 
    258     </textFragment> 
    259     <parameterFragment parameterName="view" /> 
    260     <textFragment> 
    261       has been displayed, the element 
     282      times it has been displayed to users, the element 
    262283    </textFragment> 
    263284    <parameterFragment parameterName="element" /> 
Note: See TracChangeset for help on using the changeset viewer.