Ignore:
Timestamp:
04/11/14 11:21:45 (11 years ago)
Author:
pharms
Message:
  • state of the HCSE 2014 Paper. An appropriate tag will follow.
Location:
trunk/autoquest-core-usability/src/main
Files:
7 added
8 edited
1 moved

Legend:

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

    r1335 r1493  
    1515package de.ugoe.cs.autoquest.usability; 
    1616 
    17 import java.text.DecimalFormat; 
    1817import java.util.Collection; 
    1918import java.util.HashMap; 
    2019import java.util.Map; 
    2120 
    22 import de.ugoe.cs.autoquest.eventcore.IEventType; 
     21import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; 
     22 
     23import de.ugoe.cs.autoquest.eventcore.Event; 
    2324import de.ugoe.cs.autoquest.eventcore.gui.Scroll; 
     25import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskInstanceTraversingVisitor; 
     26import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask; 
    2427import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance; 
    25 import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance; 
    26 import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptionalInstance; 
    27 import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance; 
    28 import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence; 
    29 import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance; 
     28import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship; 
    3029import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; 
    3130import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance; 
     
    3837 * @author 2012, last modified by $Author: pharms$ 
    3938 */ 
    40 public class RequiredScrollRule implements UsabilityEvaluationRule { 
     39public class RequiredInefficientActionsRule implements UsabilityEvaluationRule { 
    4140 
    4241    /* 
     
    4746    @Override 
    4847    public UsabilityEvaluationResult evaluate(ITaskModel taskModel) { 
    49         Map<ITask, Integer> smellingTasks = getTasksStartingWithScroll(taskModel.getTasks()); 
     48        UsabilityEvaluationResult results = new UsabilityEvaluationResult(taskModel); 
    5049 
    51         UsabilityEvaluationResult results = new UsabilityEvaluationResult(); 
    52         analyzeTasksStartingWithScroll(smellingTasks, results); 
     50        Map<ITask, double[]> smellingTasks = getInefficientActionStatistics(taskModel.getTasks()); 
     51        analyzeTasksWithInefficientActions(smellingTasks, results, taskModel); 
    5352 
    5453        return results; 
     
    5857     * 
    5958     */ 
    60     private void analyzeTasksStartingWithScroll(Map<ITask, Integer>       smellingTasks, 
    61                                                 UsabilityEvaluationResult results) 
     59    private void analyzeTasksWithInefficientActions(Map<ITask, double[]>      smellingTasks, 
     60                                                    UsabilityEvaluationResult results, 
     61                                                    ITaskModel                taskModel) 
    6262    { 
    6363 
    64         for (Map.Entry<ITask, Integer> entry : smellingTasks.entrySet()) { 
    65             float ratio = entry.getValue() / (float) entry.getKey().getInstances().size(); 
     64        for (Map.Entry<ITask, double[]> entry : smellingTasks.entrySet()) { 
     65            DescriptiveStatistics stats = new DescriptiveStatistics(entry.getValue()); 
     66             
     67            int ratio = (int) (1000 * stats.getMean()); 
    6668 
    67             UsabilityDefectSeverity severity = null; 
    68             if (ratio > 0.9) { 
    69                 severity = UsabilityDefectSeverity.HIGH; 
    70             } 
    71             else if (ratio > 0.6) { 
    72                 severity = UsabilityDefectSeverity.MEDIUM; 
    73             } 
    74             else if (ratio > 0.4) { 
    75                 severity = UsabilityDefectSeverity.LOW; 
    76             } 
    77             else if (ratio > 0.2) { 
    78                 severity = UsabilityDefectSeverity.INFO; 
    79             } 
     69            UsabilityDefectSeverity severity = UsabilityDefectSeverity.getSeverity 
     70                (ratio, 500, 300, 200, 100, entry.getKey(), taskModel); 
    8071 
    8172            if (severity != null) { 
    82                 Map<String, String> parameters = new HashMap<String, String>(); 
    83                 parameters.put("task", entry.getKey().toString()); 
    84                 parameters.put("scrollRatio", DecimalFormat.getInstance().format(ratio * 100)); 
     73                Map<String, Object> parameters = new HashMap<String, Object>(); 
     74                parameters.put("task", entry.getKey()); 
     75                parameters.put("ratio", (ratio / 10)); 
    8576 
    86                 results.addDefect(severity, UsabilityDefectDescription.SCROLL_REQUIRED, parameters); 
     77                results.addDefect 
     78                    (severity, UsabilityDefectDescription.INEFFICIENT_ACTIONS, parameters); 
    8779            } 
    8880        } 
     
    9284     *  
    9385     */ 
    94     private Map<ITask, Integer> getTasksStartingWithScroll(Collection<ITask> tasks) { 
    95         Map<ITask, Integer> scrollCounts = new HashMap<ITask, Integer>(); 
     86    private Map<ITask, double[]> getInefficientActionStatistics(Collection<ITask> tasks) { 
     87        Map<ITask, double[]> inefficientActionRatios = new HashMap<ITask, double[]>(); 
    9688         
    9789        for (ITask task : tasks) { 
    98             // only sequences are important for required scrolls 
    99             if (task instanceof ISequence) { 
    100                 int count = countInstancesStartingWithScroll(task); 
    101                 if (count > 0) { 
    102                     scrollCounts.put(task, count); 
     90            if (taskMustBeChecked(task))  { 
     91                double[] ratios = getRatiosOfInefficientActionsInInstances(task); 
     92                 
     93                for (int i = 0; i < ratios.length; i++) { 
     94                    if (ratios[i] > 0) { 
     95                        // there is at least on inefficient action 
     96                        inefficientActionRatios.put(task, ratios); 
     97                        break; 
     98                    } 
    10399                } 
    104100            } 
    105101        } 
    106102         
    107         return scrollCounts; 
     103        return inefficientActionRatios; 
    108104    } 
    109105 
     
    111107     * 
    112108     */ 
    113     private int countInstancesStartingWithScroll(ITask task) { 
    114         Collection<ITaskInstance> instances = task.getInstances(); 
    115          
    116         int counter = 0; 
    117         for (ITaskInstance instance : instances) { 
    118             if (startsWithScroll(instance)) { 
    119                 counter++; 
    120             } 
     109    private boolean taskMustBeChecked(ITask task) { 
     110        if ((task instanceof IEventTask) || (task instanceof IMarkingTemporalRelationship)) { 
     111            // event tasks are not considered 
     112            // marking temporal relationships have a child, that is more important, but it will 
     113            // be checked independently as all tasks of a task model are checked separately 
     114            return false; 
    121115        } 
    122          
    123         return counter; 
     116        else { 
     117            return true; 
     118        } 
    124119    } 
    125120 
     
    127122     * 
    128123     */ 
    129     private boolean startsWithScroll(ITaskInstance instance) { 
    130         if (instance instanceof ISequenceInstance) { 
    131             ITaskInstance firstChild = ((ISequenceInstance) instance).size() > 1 ? 
    132                 ((ISequenceInstance) instance).get(0) : null; 
    133  
    134             if (firstChild == null) { 
    135                 throw new IllegalArgumentException 
    136                     ("instance of a sequence must have at least two children"); 
    137             } 
    138  
    139             if (startsWithScroll(firstChild)) { 
    140                 return true; 
    141             } 
    142         } 
    143         else if (instance instanceof ISelectionInstance) { 
    144             ITaskInstance child = ((ISelectionInstance) instance).getChild(); 
    145              
    146             if (child != null) { 
    147                 return startsWithScroll(child); 
    148             } 
    149             else { 
    150                 throw new IllegalArgumentException("instance of a selection must have a child"); 
    151             } 
    152         } 
    153         else if (instance instanceof IIterationInstance) { 
    154             ITaskInstance firstChild = ((IIterationInstance) instance).size() > 0 ? 
    155                 ((IIterationInstance) instance).get(0) : null; 
    156  
    157             if (firstChild == null) { 
    158                 throw new IllegalArgumentException 
    159                     ("instance of an iteration must have at least one child"); 
    160             } 
    161  
    162             if (startsWithScroll(firstChild)) { 
    163                 return true; 
    164             } 
    165         } 
    166         else if (instance instanceof IOptionalInstance) { 
    167             ITaskInstance child = ((IOptionalInstance) instance).getChild(); 
    168              
    169             if (child != null) { 
    170                 return startsWithScroll(child); 
    171             } 
    172         } 
    173         else if (isScroll(instance)) { 
    174             return true; 
     124    private double[] getRatiosOfInefficientActionsInInstances(ITask task) { 
     125        Collection<ITaskInstance> instances = task.getInstances(); 
     126         
     127        double[] ratios = new double[instances.size()]; 
     128        int index = 0; 
     129        for (ITaskInstance instance : instances) { 
     130            ratios[index++] = getRatioOfInefficientActionsInInstance(instance); 
    175131        } 
    176132         
    177         return false; 
     133        return ratios; 
    178134    } 
    179135 
    180136    /** 
    181      * @param firstChild 
    182      * @return 
     137     * 
    183138     */ 
    184     private boolean isScroll(ITaskInstance instance) { 
    185         ITaskInstance instanceToCheck = instance; 
     139    private double getRatioOfInefficientActionsInInstance(ITaskInstance instance) { 
     140        final int[] count = new int[2]; 
     141        count[0] = 0; 
     142        count[1] = 0; 
    186143         
    187         if (instanceToCheck instanceof IIterationInstance) { 
    188             instanceToCheck = ((IIterationInstance) instanceToCheck).size() > 0 ? 
    189                 ((IIterationInstance) instanceToCheck).get(0) : null; 
     144        instance.accept(new DefaultTaskInstanceTraversingVisitor() { 
     145            @Override 
     146            public void visit(IEventTaskInstance eventTaskInstance) { 
     147                if (isInefficientAction(eventTaskInstance.getEvent())) { 
     148                    count[0]++; 
     149                } 
     150                 
     151                count[1]++; 
     152            } 
     153             
     154        }); 
     155         
     156        return (double) count[0] / count[1]; 
     157    } 
    190158 
    191             if (instanceToCheck == null) { 
    192                 throw new IllegalArgumentException 
    193                     ("instance of an iteration must have at least one child"); 
    194             } 
    195         } 
    196          
    197         if (instanceToCheck instanceof IEventTaskInstance) { 
    198             IEventType type = ((IEventTaskInstance) instanceToCheck).getEvent().getType(); 
    199              
    200             return (type instanceof Scroll); 
    201         } 
    202          
    203         return false; 
     159    /** 
     160     * 
     161     */ 
     162    private boolean isInefficientAction(Event event) { 
     163        return (event.getType() instanceof Scroll); 
    204164    } 
    205165 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/TextInputStatisticsRule.java

    r1335 r1493  
    1515package de.ugoe.cs.autoquest.usability; 
    1616 
    17 import java.text.DecimalFormat; 
    1817import java.util.ArrayList; 
    1918import java.util.Collection; 
     
    5756        calculateStatistics(taskModel.getUserSessions(), statistics); 
    5857 
    59         UsabilityEvaluationResult results = new UsabilityEvaluationResult(); 
     58        UsabilityEvaluationResult results = new UsabilityEvaluationResult(taskModel); 
    6059        analyzeStatistics(statistics, results); 
    6160 
     
    8079                                     UsabilityEvaluationResult results) 
    8180    { 
    82         float allTextFieldInputs = 
     81        int allTextFieldInputs = 
    8382            statistics.getNoOfTextFieldInputs() + statistics.getNoOfTextAreaInputs(); 
    8483 
    85         float ratio = allTextFieldInputs / (float) statistics.getNoOfAllEvents(); 
    86  
    87         UsabilityDefectSeverity severity = null; 
    88         if (ratio > 0.9) { 
    89             severity = UsabilityDefectSeverity.HIGH; 
    90         } 
    91         else if (ratio > 0.7) { 
    92             severity = UsabilityDefectSeverity.MEDIUM; 
    93         } 
    94         else if (ratio > 0.5) { 
    95             severity = UsabilityDefectSeverity.LOW; 
    96         } 
    97         else if (ratio > 0.3) { 
    98             severity = UsabilityDefectSeverity.INFO; 
    99         } 
    100  
     84        int ratio = 1000 * allTextFieldInputs / statistics.getNoOfAllEvents(); 
     85 
     86        // TODO comment magic numbers 
     87        UsabilityDefectSeverity severity = UsabilityDefectSeverity.getSeverity 
     88            (ratio, 900, 700, 500, 300); 
     89         
    10190        if (severity != null) { 
    102             Map<String, String> parameters = new HashMap<String, String>(); 
    103             parameters.put("textInputRatio", DecimalFormat.getInstance().format(ratio * 100)); 
     91            Map<String, Object> parameters = new HashMap<String, Object>(); 
     92            parameters.put("textInputRatio", (ratio / 10)); 
    10493 
    10594            results.addDefect 
     
    122111            int noOfUsagesOfTextField1WithSameTextInTextField2 = entry.enteredTexts.size(); 
    123112             
    124             float ratioTextField1 = 
    125                 noOfUsagesOfTextField1WithSameTextInTextField2 / (float) noOfUsagesOfTextField1; 
    126              
    127             float ratioTextField2 = 
    128                 noOfUsagesOfTextField1WithSameTextInTextField2 / (float) noOfUsagesOfTextField2; 
    129              
    130             createTextFieldEntryRepetitionDefect 
    131                 (ratioTextField1, entry.textField1, entry.textField2, results); 
    132              
    133             createTextFieldEntryRepetitionDefect 
    134                 (ratioTextField2, entry.textField2, entry.textField1, results); 
    135              
    136         } 
    137     } 
    138  
    139     /** 
    140      * 
    141      */ 
    142     private void createTextFieldEntryRepetitionDefect(float                     ratioOfEqualEntries, 
     113            int ratioTextField1 =  
     114                1000 * noOfUsagesOfTextField1WithSameTextInTextField2 / noOfUsagesOfTextField1; 
     115             
     116            int ratioTextField2 = 
     117                1000 * noOfUsagesOfTextField1WithSameTextInTextField2 / noOfUsagesOfTextField2; 
     118 
     119            createTextFieldEntryRepetitionDefect(ratioTextField1, entry.textField1, 
     120                                                entry.textField2, results); 
     121             
     122            createTextFieldEntryRepetitionDefect(ratioTextField2, entry.textField2, 
     123                                                entry.textField1, results); 
     124             
     125        } 
     126    } 
     127 
     128    /** 
     129     * 
     130     */ 
     131    private void createTextFieldEntryRepetitionDefect(int                       ratioOfEqualEntries, 
    143132                                                      ITextField                textField1, 
    144133                                                      ITextField                textField2, 
    145134                                                      UsabilityEvaluationResult results) 
    146135    { 
    147         UsabilityDefectSeverity severity = null; 
    148         if (ratioOfEqualEntries > 0.9) { 
    149             severity = UsabilityDefectSeverity.HIGH; 
    150         } 
    151         else if (ratioOfEqualEntries > 0.5) { 
    152             severity = UsabilityDefectSeverity.MEDIUM; 
    153         } 
    154         else if (ratioOfEqualEntries > 0.2) { 
    155             severity = UsabilityDefectSeverity.LOW; 
    156         } 
    157         else if (ratioOfEqualEntries > 0.1) { 
    158             severity = UsabilityDefectSeverity.INFO; 
    159         } 
     136        // TODO comment magic numbers 
     137        UsabilityDefectSeverity severity = UsabilityDefectSeverity.getSeverity 
     138            (ratioOfEqualEntries, 900, 500, 200, 100); 
    160139         
    161140        if (severity != null) { 
    162             Map<String, String> parameters = new HashMap<String, String>(); 
    163             parameters.put("textRepetitionRatio", 
    164                            DecimalFormat.getInstance().format(ratioOfEqualEntries * 100)); 
    165             parameters.put("textField1", textField1.toString()); 
    166             parameters.put("textField2", textField2.toString()); 
     141            Map<String, Object> parameters = new HashMap<String, Object>(); 
     142            parameters.put("textRepetitionRatio", (ratioOfEqualEntries / 10)); 
     143            parameters.put("textField1", textField1); 
     144            parameters.put("textField2", textField2); 
    167145 
    168146            results.addDefect 
     
    192170            } 
    193171 
    194             float ratio = (float) noLetterOrDigitCount / (float) allCharactersCount; 
    195  
    196             UsabilityDefectSeverity severity = null; 
    197             if (ratio > 0.1) { // every 10th sign 
    198                 severity = UsabilityDefectSeverity.HIGH; 
    199             } 
    200             else if (ratio > 0.05) { // every 20th sign 
    201                 severity = UsabilityDefectSeverity.MEDIUM; 
    202             } 
    203             else if (ratio > 0.02) { // every 50th sign 
    204                 severity = UsabilityDefectSeverity.LOW; 
    205             } 
    206             else if (ratio > 0.01) { // every 100th sign 
    207                 severity = UsabilityDefectSeverity.INFO; 
    208             } 
     172            int ratio = 1000 * noLetterOrDigitCount / allCharactersCount; 
     173 
     174            UsabilityDefectSeverity severity = 
     175                UsabilityDefectSeverity.getSeverity(ratio, 
     176                                                    100, // every 10th sign 
     177                                                    50, // every 20th sign 
     178                                                    20, // every 50th sign 
     179                                                    10 // every 100th sign 
     180                                                    ); 
    209181 
    210182            if (severity != null) { 
    211                 Map<String, String> parameters = new HashMap<String, String>(); 
    212                 parameters.put("textField", textField.toString()); 
    213                 parameters.put("noLetterOrDigitRatio", 
    214                                DecimalFormat.getInstance().format(ratio * 100)); 
     183                Map<String, Object> parameters = new HashMap<String, Object>(); 
     184                parameters.put("textField", textField); 
     185                parameters.put("noLetterOrDigitRatio", (ratio / 10)); 
    215186 
    216187                results.addDefect 
    217                     (severity, UsabilityDefectDescription.TEXT_FIELD_NO_LETTER_OR_DIGIT_RATIO, parameters); 
     188                    (severity, UsabilityDefectDescription.TEXT_FIELD_NO_LETTER_OR_DIGIT_RATIO, 
     189                     parameters); 
    218190            } 
    219191        } 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityDefect.java

    r1335 r1493  
    1515package de.ugoe.cs.autoquest.usability; 
    1616 
     17import java.util.List; 
    1718import java.util.Map; 
    1819 
     
    3233 
    3334    /** */ 
    34     private Map<String, String> descriptionParameters; 
     35    private Map<String, Object> descriptionParameters; 
    3536 
    3637    /** 
    3738     * 
    3839     */ 
    39     UsabilityDefect(UsabilityDefectSeverity severity, UsabilityDefectDescription description) 
    40     { 
     40    UsabilityDefect(UsabilityDefectSeverity severity, UsabilityDefectDescription description) { 
    4141        this(severity, description, null); 
    4242    } 
     
    4747    UsabilityDefect(UsabilityDefectSeverity    severity, 
    4848                    UsabilityDefectDescription description, 
    49                     Map<String, String>        parameters) 
     49                    Map<String, Object>        parameters) 
    5050    { 
    5151        this.severity = severity; 
     
    8080    public String getParameterizedDescription() { 
    8181        return description.toString(descriptionParameters); 
     82    } 
     83 
     84    /** 
     85     *  
     86     */ 
     87    public List<Object> getDescriptionFragments() { 
     88        return description.toFragmentList(descriptionParameters); 
     89    } 
     90 
     91    /* 
     92     */ 
     93    public String getBriefDescription() { 
     94        return description.getBriefDescription(); 
    8295    } 
    8396 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityDefectDescription.java

    r1335 r1493  
    1818import java.io.InputStream; 
    1919import java.util.ArrayList; 
     20import java.util.Collection; 
    2021import java.util.List; 
    2122import java.util.Map; 
     
    3334public enum UsabilityDefectDescription { 
    3435     
    35     SCROLL_REQUIRED, 
     36    INEFFICIENT_ACTIONS, 
    3637    TEXT_FIELD_INPUT_RATIO, 
    3738    TEXT_FIELD_INPUT_REPETITIONS, 
    38     TEXT_FIELD_NO_LETTER_OR_DIGIT_RATIO; 
     39    TEXT_FIELD_NO_LETTER_OR_DIGIT_RATIO, 
     40    COOCCURENCE_SUCCEED, 
     41    COOCCURENCE_PRECED, 
     42    HIGH_EVENT_COVERAGE, 
     43    HIGH_TARGET_DISTANCE, 
     44    MISSING_FEEDBACK, 
     45    UNUSED_GUI_ELEMENTS; 
    3946 
    4047    /** */ 
     
    122129     *  
    123130     */ 
    124     public String toString(Map<String, String> parameters) throws IllegalArgumentException { 
     131    public String toString(Map<String, Object> parameters) throws IllegalArgumentException { 
    125132        StringBuffer result = new StringBuffer(); 
    126133 
     
    131138 
    132139            if (fragment instanceof ParameterFragment) { 
    133                 String value = null; 
     140                Object value = null; 
    134141                if (parameters != null) { 
    135142                    value = parameters.get(((ParameterFragment) fragment).getParameterName()); 
     
    137144 
    138145                if (value != null) { 
    139                     result.append(value); 
     146                    if (value instanceof Collection<?>) { 
     147                        int counter = 1; 
     148                        for (Object elem : ((Collection<?>) value)) { 
     149                            result.append('\n'); 
     150                            result.append(counter++); 
     151                            result.append(".: "); 
     152                            result.append(elem); 
     153                        } 
     154                    } 
     155                    else { 
     156                        result.append(value.toString()); 
     157                    } 
    140158                } 
    141159                else { 
     
    154172    } 
    155173 
     174    /** 
     175     *  
     176     */ 
     177    public List<Object> toFragmentList(Map<String, Object> parameters) 
     178        throws IllegalArgumentException 
     179    { 
     180        List<Object> result = new ArrayList<Object>(); 
     181 
     182        for (Object fragment : defectDescription.getTextFragmentOrParameterFragment()) { 
     183            if (fragment instanceof ParameterFragment) { 
     184                Object value = null; 
     185                if (parameters != null) { 
     186                    value = parameters.get(((ParameterFragment) fragment).getParameterName()); 
     187                } 
     188 
     189                if (value != null) { 
     190                    result.add(value); 
     191                } 
     192                else { 
     193                    throw new IllegalArgumentException 
     194                        ("required parameter \"" + 
     195                         ((ParameterFragment) fragment).getParameterName() + 
     196                         "\" for usability defect description " + this.name() + " not provided"); 
     197                } 
     198            } 
     199            else { 
     200                result.add(getFragmentString(fragment)); 
     201            } 
     202        } 
     203 
     204        return result; 
     205    } 
     206     
     207    /** 
     208     *  
     209     */ 
     210    public String getBriefDescription() { 
     211        return defectDescription.briefText; 
     212    } 
     213 
    156214    /* 
    157215     * (non-Javadoc) 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityDefectSeverity.java

    r927 r1493  
    1515package de.ugoe.cs.autoquest.usability; 
    1616 
     17import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; 
     18import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo; 
     19import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel; 
     20import de.ugoe.cs.autoquest.tasktrees.treeifc.TaskMetric; 
     21 
    1722/** 
    1823 * TODO comment 
     
    2429     
    2530    INFO, LOW, MEDIUM, HIGH; 
     31     
     32    /** */ 
     33    static int defaultCoverageQuantile = 950; 
    2634 
     35    /** 
     36     *  
     37     */ 
     38    static UsabilityDefectSeverity getSeverity(int ratio, 
     39                                               int highRatioLevel, 
     40                                               int mediumRatioLevel, 
     41                                               int lowRatioLevel, 
     42                                               int infoRatioLevel) 
     43    { 
     44        return getSeverity(ratio, highRatioLevel, mediumRatioLevel, lowRatioLevel, infoRatioLevel, 
     45                           defaultCoverageQuantile); 
     46    } 
     47 
     48    /** 
     49     *  
     50     */ 
     51    static UsabilityDefectSeverity getSeverity(int        ratio, 
     52                                               int        highRatioLevel, 
     53                                               int        mediumRatioLevel, 
     54                                               int        lowRatioLevel, 
     55                                               int        infoRatioLevel, 
     56                                               ITask      taskWithDefect, 
     57                                               ITaskModel wholeTaskModel) 
     58    { 
     59        ITaskInfo taskInfo = wholeTaskModel.getTaskInfo(taskWithDefect); 
     60        int eventCoverageQuantile = taskInfo.getMeasureValue(TaskMetric.EVENT_COVERAGE_QUANTILE); 
     61        return getSeverity(ratio, highRatioLevel, mediumRatioLevel, lowRatioLevel, infoRatioLevel, 
     62                           eventCoverageQuantile); 
     63    } 
     64 
     65    /** 
     66     *  
     67     */ 
     68    static UsabilityDefectSeverity getSeverity(int ratio, 
     69                                               int highRatioLevel, 
     70                                               int mediumRatioLevel, 
     71                                               int lowRatioLevel, 
     72                                               int infoRatioLevel, 
     73                                               int coverageQuantile) 
     74    { 
     75        int effectiveRatio = ratio; 
     76         
     77        // event coverage ratio is in per mille. The more executed events a task covers, the more 
     78        // important a related usability defect. 
     79        /*if (eventCoverageRatio < 1) { 
     80            // one per mille, so one of thousand events is covered 
     81            effectiveRatio *= 0.2; 
     82        } 
     83        else if (eventCoverageRatio < 5) { 
     84            // 5 per mille, so one of 250 events is covered 
     85            effectiveRatio *= 0.4; 
     86        } 
     87        else if (eventCoverageRatio < 10) { 
     88            // 1 percent, so one of 100 events is covered 
     89            effectiveRatio *= 0.5; 
     90        } 
     91        else if (eventCoverageRatio < 20) { 
     92            // 2 percent, so one of 50 events is covered 
     93            effectiveRatio *= 0.6; 
     94        } 
     95        else if (eventCoverageRatio < 30) { 
     96            // 3 percent, so one of 33 events is covered 
     97            effectiveRatio *= 0.7; 
     98        } 
     99        else if (eventCoverageRatio < 40) { 
     100            // 4 percent, so one of 28 events is covered 
     101            effectiveRatio *= 0.8; 
     102        } 
     103        else if (eventCoverageRatio < 50) { 
     104            // 5 percent, so one of 25 events is covered 
     105            effectiveRatio *= 0.9; 
     106        }*/ 
     107        //else { 
     108            // more than 5 percent, so 1 of 20 events, do not change ratio 
     109        //} 
     110        if (coverageQuantile >= defaultCoverageQuantile) { 
     111            if (effectiveRatio >= highRatioLevel) { 
     112                return UsabilityDefectSeverity.HIGH; 
     113            } 
     114            else if (effectiveRatio >= mediumRatioLevel) { 
     115                return UsabilityDefectSeverity.MEDIUM; 
     116            } 
     117            else if (effectiveRatio >= lowRatioLevel) { 
     118                return UsabilityDefectSeverity.LOW; 
     119            } 
     120            else if (effectiveRatio >= infoRatioLevel) { 
     121                return UsabilityDefectSeverity.INFO; 
     122            } 
     123        } 
     124         
     125        return null; 
     126    } 
    27127} 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityEvaluationManager.java

    r1335 r1493  
    1919import java.util.logging.Level; 
    2020 
     21import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship; 
     22import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship; 
     23import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; 
    2124import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel; 
    2225import de.ugoe.cs.util.console.Console; 
     
    4548     */ 
    4649    private void init() { 
    47         rules.add(new TextInputStatisticsRule()); 
    48         rules.add(new RequiredScrollRule()); 
     50        //rules.add(new TextInputStatisticsRule()); 
     51        rules.add(new MissingFeedbackRule()); 
     52        rules.add(new EventCoverageRatioRule()); 
     53        rules.add(new RequiredInefficientActionsRule()); 
     54        //rules.add(new TaskCooccurrenceRule()); 
     55        rules.add(new TargetDistanceRule()); 
     56        //rules.add(new UnusedGUIElementsRule()); 
     57        //rules.add(new TaskTreeTestRule()); 
    4958    } 
    5059 
     
    6473                            " usability defects, of which " + result.getSevereDefects().size() + 
    6574                            " are severe."); 
     75             
     76            if ((rule instanceof EventCoverageRatioRule) || 
     77                (rule instanceof RequiredInefficientActionsRule) || 
     78                (rule instanceof TargetDistanceRule)) 
     79            { 
     80                ITask[] referredTasks = new ITask[result.getAllDefects().size()]; 
     81 
     82                for (int i = 0; i < result.getAllDefects().size(); i++) { 
     83                    referredTasks[i] = 
     84                        (ITask) result.getAllDefects().get(i).getDescriptionFragments().get(1); 
     85                } 
     86                 
     87                int counter = 0; 
     88                for (int i = 0; i < referredTasks.length; i++) { 
     89                    for (int j = 0; j < referredTasks.length; j++) { 
     90                        if (isChildOf(referredTasks[i], referredTasks[j])) { 
     91                            counter++; 
     92                            break; 
     93                        } 
     94                    } 
     95                } 
     96                 
     97                if (counter > 0) { 
     98                    Console.traceln(Level.INFO, counter + " of the findings are duplicates in " + 
     99                                    "that they refer to tasks whose parent tasks are also " + 
     100                                    "referred by the findings"); 
     101                } 
     102            } 
    66103        } 
    67104 
    68         UsabilityEvaluationResult result = new UsabilityEvaluationResult(interimResults); 
     105        UsabilityEvaluationResult result = new UsabilityEvaluationResult(taskModel, interimResults); 
    69106        Console.println("the evaluation result contains " + result.getAllDefects().size() + 
    70107                        " defects, of which " + result.getSevereDefects().size() + " are severe."); 
    71  
    72         List<UsabilityDefect> defects = result.getAllDefects(); 
    73         for (int i = 0; i < defects.size(); i++) { 
    74             Console.println((i + 1) + ": " + defects.get(i).getParameterizedDescription()); 
    75         } 
    76108 
    77109        return result; 
    78110    } 
    79111 
     112    /** 
     113     * <p> 
     114     * TODO: comment 
     115     * </p> 
     116     * 
     117     * @param iTask 
     118     * @param iTask2 
     119     * @return 
     120     */ 
     121    private boolean isChildOf(final ITask potChild, ITask potParent) { 
     122         
     123        if (potParent instanceof IStructuringTemporalRelationship) { 
     124            for (ITask child : ((IStructuringTemporalRelationship) potParent).getChildren()) { 
     125                if ((child == potChild) || isChildOf(potChild, child)) { 
     126                    return true; 
     127                } 
     128            } 
     129        } 
     130        else if (potParent instanceof IMarkingTemporalRelationship) { 
     131            ITask child = ((IMarkingTemporalRelationship) potParent).getMarkedTask(); 
     132            if ((child == potChild) || isChildOf(potChild, child)) { 
     133                return true; 
     134            } 
     135        } 
     136         
     137        return false; 
     138    } 
     139 
    80140} 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityEvaluationResult.java

    r1335 r1493  
    1919import java.util.Map; 
    2020 
     21import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel; 
     22 
    2123/** 
    2224 * TODO comment 
     
    2830     
    2931    /** */ 
     32    private ITaskModel taskModel; 
     33     
     34    /** */ 
    3035    private List<UsabilityDefect> defects = new ArrayList<UsabilityDefect>(); 
    3136 
     
    3338     * 
    3439     */ 
    35     public UsabilityEvaluationResult() { 
    36         // default constructor 
     40    public UsabilityEvaluationResult(ITaskModel taskModel) { 
     41        this.taskModel = taskModel; 
    3742    } 
    3843 
     
    4045     * 
    4146     */ 
    42     public UsabilityEvaluationResult(List<UsabilityEvaluationResult> results) { 
     47    public UsabilityEvaluationResult(ITaskModel                      taskModel, 
     48                                     List<UsabilityEvaluationResult> results) 
     49    { 
     50        this.taskModel = taskModel; 
    4351        for (UsabilityEvaluationResult result : results) { 
    4452            for (UsabilityDefect defect : result.getAllDefects()) { 
     
    5361    public void addDefect(UsabilityDefectSeverity    severity, 
    5462                          UsabilityDefectDescription description, 
    55                           Map<String, String>        parameters) 
     63                          Map<String, Object>        parameters) 
    5664    { 
    5765        defects.add(new UsabilityDefect(severity, description, parameters)); 
     
    8088    } 
    8189 
     90    /** 
     91     * @return the taskModel 
     92     */ 
     93    public ITaskModel getTaskModel() { 
     94        return taskModel; 
     95    } 
     96 
    8297} 
  • trunk/autoquest-core-usability/src/main/resources/defectDescriptions.xsd

    r442 r1493  
    11<?xml version="1.0" encoding="UTF-8"?> 
    22<xsd:schema 
    3   targetNamespace="http://quest" 
    4   xmlns:tns="http://quest" 
     3  targetNamespace="http://autoquest.informatik.uni-goettingen.de" 
     4  xmlns:tns="http://autoquest.informatik.uni-goettingen.de" 
    55  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    66  xmlns:jxb="http://java.sun.com/xml/ns/jaxb" 
     
    2222    </xsd:choice> 
    2323    <xsd:attribute name="defectId" type="xsd:string" use="required" /> 
     24    <xsd:attribute name="briefText" type="xsd:string" use="required" /> 
    2425  </xsd:complexType> 
    2526 
  • trunk/autoquest-core-usability/src/main/resources/defectDescriptions_en.xml

    r1335 r1493  
    11<?xml version="1.0" encoding="UTF-8"?> 
    22<defectDescriptions 
    3   xmlns="http://quest" 
     3  xmlns="http://autoquest.informatik.uni-goettingen.de" 
    44  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    5   xsi:schemaLocation="http://quest defectDescriptions.xsd"> 
     5  xsi:schemaLocation="http://autoquest.informatik.uni-goettingen.de defectDescriptions.xsd"> 
    66   
    7   <defectDescription defectId="TEXT_FIELD_INPUT_RATIO"> 
     7  <defectDescription defectId="TEXT_FIELD_INPUT_RATIO" briefText="many text inputs"> 
    88    <textFragment> 
    99      The ratio of interactions that enter text into text fields is relatively high in comparison 
     
    1717  </defectDescription> 
    1818   
    19   <defectDescription defectId="TEXT_FIELD_INPUT_REPETITIONS"> 
     19  <defectDescription defectId="TEXT_FIELD_INPUT_REPETITIONS" briefText="many text repetitions"> 
    2020    <textFragment> 
    2121      In 
     
    3636  </defectDescription> 
    3737   
    38   <defectDescription defectId="TEXT_FIELD_NO_LETTER_OR_DIGIT_RATIO"> 
     38  <defectDescription defectId="TEXT_FIELD_NO_LETTER_OR_DIGIT_RATIO" briefText="many special signs"> 
    3939    <parameterFragment parameterName="noLetterOrDigitRatio" /> 
    4040    <textFragment> 
     
    5050  </defectDescription> 
    5151   
    52   <defectDescription defectId="SCROLL_REQUIRED"> 
     52  <defectDescription defectId="HIGH_EVENT_COVERAGE" briefText="often executed"> 
     53    <textFragment> 
     54      The task 
     55    </textFragment> 
     56    <parameterFragment parameterName="task" /> 
     57    <textFragment> 
     58      covers 
     59    </textFragment> 
     60    <parameterFragment parameterName="ratio" /> 
     61    <textFragment> 
     62      % of all recorded user actions. Therefore, it should be executed with a high efficiency. 
     63      You should consider making the task more efficient, by minimizing the number of actions to 
     64      be executed by users for fulfilling this task. 
     65    </textFragment> 
     66  </defectDescription> 
     67   
     68  <defectDescription defectId="INEFFICIENT_ACTIONS" briefText="inefficient actions"> 
     69    <textFragment> 
     70      For executing task 
     71    </textFragment> 
     72    <parameterFragment parameterName="task" /> 
     73    <textFragment> 
     74      , the user has to execute a high number of inefficient actions ( 
     75    </textFragment> 
     76    <parameterFragment parameterName="ratio" /> 
     77    <textFragment> 
     78      % in average). Such actions are, e.g., scrolls. The number of inefficient actions should 
     79      be as minimal as possible to increase the users efficiency in executing a task. Please 
     80      check the task structure for occurrences of the following event tasks and consider to prevent 
     81      them: scrolling. 
     82    </textFragment> 
     83  </defectDescription> 
     84   
     85  <defectDescription defectId="COOCCURENCE_SUCCEED" briefText="usual cooccurrence"> 
    5386    <textFragment> 
    5487      In 
    5588    </textFragment> 
    56     <parameterFragment parameterName="scrollRatio" /> 
     89    <parameterFragment parameterName="ratio" /> 
    5790    <textFragment> 
    5891      % of all occurrences, the task 
    5992    </textFragment> 
     93    <parameterFragment parameterName="task1" /> 
     94    <textFragment> 
     95      is succeeded by 
     96    </textFragment> 
     97    <parameterFragment parameterName="task2" /> 
     98    <textFragment> 
     99      . This shows, that both tasks are likely used in combination. Please consider to support the 
     100      execution of both tasks in one user action, e.g., by providing an appropriate button, to 
     101      reduce the number of actions to be performed by the user. 
     102    </textFragment> 
     103  </defectDescription> 
     104   
     105  <defectDescription defectId="COOCCURENCE_PRECED" briefText="usual cooccurrence"> 
     106    <textFragment> 
     107      In 
     108    </textFragment> 
     109    <parameterFragment parameterName="ratio" /> 
     110    <textFragment> 
     111      % of all occurrences, the task 
     112    </textFragment> 
     113    <parameterFragment parameterName="task2" /> 
     114    <textFragment> 
     115      is preceded by 
     116    </textFragment> 
     117    <parameterFragment parameterName="task1" /> 
     118    <textFragment> 
     119      . This shows, that both tasks are likely used in combination. Please consider to support the 
     120      execution of both tasks in one user action, e.g., by providing an appropriate button, to 
     121      reduce the number of actions to be performed by the user. 
     122    </textFragment> 
     123  </defectDescription> 
     124   
     125  <defectDescription defectId="HIGH_TARGET_DISTANCE" briefText="long way to go"> 
     126    <textFragment> 
     127      For executing the task 
     128    </textFragment> 
    60129    <parameterFragment parameterName="task" /> 
    61130    <textFragment> 
    62       is started with a scroll. This should be prevented as scrolling decreases the efficiency of 
    63       the user and indicates, that not all required information is visible at once in the 
    64       respective view. However, scrolling for reading of texts is no problem. 
     131      , the user utilizes 
     132    </textFragment> 
     133    <parameterFragment parameterName="noOfGUIElements" /> 
     134    <textFragment> 
     135      GUI elements on average. As these GUI elements have a high distance to each other ( 
     136    </textFragment> 
     137    <parameterFragment parameterName="distance" /> 
     138    <textFragment> 
     139      on average ), they should be more colocated to ease the execution of the task for the user. 
    65140    </textFragment> 
    66141  </defectDescription> 
     142   
     143  <defectDescription defectId="MISSING_FEEDBACK" briefText="missing feedback"> 
     144    <textFragment> 
     145      A click on the button 
     146    </textFragment> 
     147    <parameterFragment parameterName="button" /> 
     148    <textFragment> 
     149      seems to be missing user feedback. In 
     150    </textFragment> 
     151    <parameterFragment parameterName="multipleClickCount" /> 
     152    <textFragment> 
     153      of 
     154    </textFragment> 
     155    <parameterFragment parameterName="allClickCount" /> 
     156    <textFragment> 
     157      uses, the button was clicked several times. The average waiting time between two subsequent 
     158      clicks is 
     159    </textFragment> 
     160    <parameterFragment parameterName="averageWaitingTime" /> 
     161    <textFragment> 
     162      seconds. This is typical user behavior if the user does not see progress following his 
     163      actions. Please consider showing the user some progress after he performed the 
     164      first click. This is especially important if the operation triggered with the click usually 
     165      takes longer than one second. This defect was observed based on task 
     166    </textFragment> 
     167    <parameterFragment parameterName="task" /> 
     168    <textFragment> 
     169      . 
     170    </textFragment> 
     171  </defectDescription> 
     172   
     173  <defectDescription defectId="UNUSED_GUI_ELEMENTS" briefText="unused GUI elements"> 
     174    <parameterFragment parameterName="ratio" /> 
     175    <textFragment> 
     176      % of the GUI elements ( 
     177    </textFragment> 
     178    <parameterFragment parameterName="noOfUnused" /> 
     179    <textFragment> 
     180      of 
     181    </textFragment> 
     182    <parameterFragment parameterName="noOfAll" /> 
     183    <textFragment> 
     184      ) are not used. This can have several reasons. Either they are not 
     185      visible to the user or they are not required. If they are important, they may not be 
     186      recognized by the user. This can be caused by visual design or because they are too hidden. 
     187      If they are less important, they can either be removed from the GUI or relocated to a less 
     188      prominent position. The unused GUI elements are: 
     189    </textFragment> 
     190    <parameterFragment parameterName="unusedGuiElements" /> 
     191  </defectDescription> 
    67192</defectDescriptions> 
Note: See TracChangeset for help on using the changeset viewer.