Ignore:
Timestamp:
01/24/14 13:50:29 (10 years ago)
Author:
pharms
Message:
  • corrected and extended usability evaluations
  • checking now more text field specific for required input formats and word repetitions
  • checking also for required scrolls
Location:
trunk/autoquest-core-usability/src/main
Files:
1 added
6 edited

Legend:

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

    r1301 r1335  
    1919import java.util.Collection; 
    2020import java.util.HashMap; 
     21import java.util.HashSet; 
     22import java.util.LinkedList; 
    2123import java.util.List; 
    2224import java.util.Map; 
     25import java.util.Set; 
    2326 
    2427import de.ugoe.cs.autoquest.eventcore.IEventTarget; 
     
    2730import de.ugoe.cs.autoquest.eventcore.guimodel.ITextArea; 
    2831import de.ugoe.cs.autoquest.eventcore.guimodel.ITextField; 
    29 import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask; 
    3032import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance; 
    31 import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship; 
    32 import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship; 
    33 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; 
     33import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance; 
     34import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptionalInstance; 
     35import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance; 
     36import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance; 
    3437import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance; 
    3538import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel; 
     39import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession; 
    3640 
    3741/** 
     
    4145 * @author 2012, last modified by $Author: pharms$ 
    4246 */ 
    43 public class TextInputStatisticsRule implements de.ugoe.cs.autoquest.usability.UsabilityEvaluationRule { 
     47public class TextInputStatisticsRule implements UsabilityEvaluationRule { 
    4448 
    4549    /* 
     
    5155    public UsabilityEvaluationResult evaluate(ITaskModel taskModel) { 
    5256        TextInputStatistics statistics = new TextInputStatistics(); 
    53         calculateStatistics(taskModel.getTasks(), statistics); 
     57        calculateStatistics(taskModel.getUserSessions(), statistics); 
    5458 
    5559        UsabilityEvaluationResult results = new UsabilityEvaluationResult(); 
     
    97101        if (severity != null) { 
    98102            Map<String, String> parameters = new HashMap<String, String>(); 
    99             parameters.put("textInputRatio", DecimalFormat.getInstance().format(ratio * 100) + "%"); 
     103            parameters.put("textInputRatio", DecimalFormat.getInstance().format(ratio * 100)); 
    100104 
    101105            results.addDefect 
    102                 (new UsabilityDefect(severity, UsabilityDefectDescription.TEXT_FIELD_INPUT_RATIO, 
    103                                      parameters)); 
     106                (severity, UsabilityDefectDescription.TEXT_FIELD_INPUT_RATIO, parameters); 
    104107        } 
    105108    } 
     
    111114                                                UsabilityEvaluationResult results) 
    112115    { 
    113         Map<String, Integer> words = new HashMap<String, Integer>(); 
    114         int numberOfRepeatedWords = 0; 
    115         int maxRepetitions = 0; 
    116  
    117         for (int i = 0; i < statistics.getNoOfTextFieldInputs(); i++) { 
    118             String[] fragments = statistics.getTextFieldInputFragments(i); 
    119             for (String fragment : fragments) { 
    120                 if (!"".equals(fragment.trim())) { 
    121                     Integer count = words.get(fragment); 
    122                     if (count == null) { 
    123                         words.put(fragment, 1); 
    124                     } 
    125                     else { 
    126                         count++; 
    127                         words.put(fragment, count); 
    128                         maxRepetitions = Math.max(count, maxRepetitions); 
    129  
    130                         if (count == 2) { 
    131                             // do not calculate repeated words several times 
    132                             numberOfRepeatedWords++; 
    133                         } 
    134                     } 
    135                 } 
    136             } 
    137         } 
    138  
     116        List<TextFieldCorrelation> textFieldCorrelations = 
     117            statistics.determineTextFieldCorrelations(); 
     118         
     119        for (TextFieldCorrelation entry : textFieldCorrelations) { 
     120            int noOfUsagesOfTextField1 = statistics.getUsageCount(entry.textField1); 
     121            int noOfUsagesOfTextField2 = statistics.getUsageCount(entry.textField2); 
     122            int noOfUsagesOfTextField1WithSameTextInTextField2 = entry.enteredTexts.size(); 
     123             
     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, 
     143                                                      ITextField                textField1, 
     144                                                      ITextField                textField2, 
     145                                                      UsabilityEvaluationResult results) 
     146    { 
    139147        UsabilityDefectSeverity severity = null; 
    140         if ((numberOfRepeatedWords > 10) || (maxRepetitions > 10)) { 
     148        if (ratioOfEqualEntries > 0.9) { 
    141149            severity = UsabilityDefectSeverity.HIGH; 
    142150        } 
    143         else if ((numberOfRepeatedWords > 4) || (maxRepetitions > 4)) { 
     151        else if (ratioOfEqualEntries > 0.5) { 
    144152            severity = UsabilityDefectSeverity.MEDIUM; 
    145153        } 
    146         else if ((numberOfRepeatedWords > 2) || (maxRepetitions > 2)) { 
     154        else if (ratioOfEqualEntries > 0.2) { 
    147155            severity = UsabilityDefectSeverity.LOW; 
    148156        } 
    149         else if ((numberOfRepeatedWords > 1) || (maxRepetitions > 1)) { 
     157        else if (ratioOfEqualEntries > 0.1) { 
    150158            severity = UsabilityDefectSeverity.INFO; 
    151159        } 
    152  
     160         
    153161        if (severity != null) { 
    154162            Map<String, String> parameters = new HashMap<String, String>(); 
    155             parameters.put("textRepetitionRatio", numberOfRepeatedWords + 
    156                            " repeated tokens, up to " + maxRepetitions + " repetitions per token"); 
     163            parameters.put("textRepetitionRatio", 
     164                           DecimalFormat.getInstance().format(ratioOfEqualEntries * 100)); 
     165            parameters.put("textField1", textField1.toString()); 
     166            parameters.put("textField2", textField2.toString()); 
    157167 
    158168            results.addDefect 
    159                 (new UsabilityDefect(severity, 
    160                                      UsabilityDefectDescription.TEXT_FIELD_INPUT_REPETITIONS, 
    161                                      parameters)); 
     169                (severity, UsabilityDefectDescription.TEXT_FIELD_INPUT_REPETITIONS, parameters); 
    162170        } 
    163171    } 
     
    169177                                                     UsabilityEvaluationResult results) 
    170178    { 
    171         int allCharactersCount = 0; 
    172         int noLetterOrDigitCount = 0; 
    173  
    174         for (int i = 0; i < statistics.getNoOfTextFieldInputs(); i++) { 
    175             String[] fragments = statistics.getTextFieldInputFragments(i); 
    176             for (String fragment : fragments) { 
    177                 String effectiveFragment = fragment.trim(); 
    178                 for (int j = 0; j < effectiveFragment.length(); j++) { 
    179                     if (!Character.isWhitespace(effectiveFragment.charAt(j))) { 
    180                         if (!Character.isLetterOrDigit(effectiveFragment.charAt(j))) { 
     179        for (ITextField textField : statistics.getAllTextFields()) { 
     180            int allCharactersCount = 0; 
     181            int noLetterOrDigitCount = 0; 
     182 
     183            for (String textInput : statistics.getAllInputsInto(textField)) { 
     184                for (int j = 0; j < textInput.length(); j++) { 
     185                    if (!Character.isWhitespace(textInput.charAt(j))) { 
     186                        if (!Character.isLetterOrDigit(textInput.charAt(j))) { 
    181187                            noLetterOrDigitCount++; 
    182188                        } 
     
    185191                } 
    186192            } 
    187         } 
    188  
    189         float ratio = (float) noLetterOrDigitCount / (float) allCharactersCount; 
    190  
    191         UsabilityDefectSeverity severity = null; 
    192         if (ratio > 0.1) // every 10th sign 
    193         { 
    194             severity = UsabilityDefectSeverity.HIGH; 
    195         } 
    196         else if (ratio > 0.05) // every 20th sign 
    197         { 
    198             severity = UsabilityDefectSeverity.MEDIUM; 
    199         } 
    200         else if (ratio > 0.02) // every 50th sign 
    201         { 
    202             severity = UsabilityDefectSeverity.LOW; 
    203         } 
    204         else if (ratio > 0.01) // every 100th sign 
    205         { 
    206             severity = UsabilityDefectSeverity.INFO; 
    207         } 
    208  
    209         if (severity != null) { 
    210             Map<String, String> parameters = new HashMap<String, String>(); 
    211             parameters.put("noLetterOrDigitRatio", allCharactersCount + " entered characters of " + 
    212                            "which " + noLetterOrDigitCount + " were no letter or digit"); 
    213  
    214             results.addDefect 
    215                 (new UsabilityDefect(severity, 
    216                                      UsabilityDefectDescription.TEXT_FIELD_NO_LETTER_OR_DIGIT_RATIO, 
    217                                      parameters)); 
     193 
     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            } 
     209 
     210            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)); 
     215 
     216                results.addDefect 
     217                    (severity, UsabilityDefectDescription.TEXT_FIELD_NO_LETTER_OR_DIGIT_RATIO, parameters); 
     218            } 
    218219        } 
    219220    } 
     
    222223     *  
    223224     */ 
    224     private void calculateStatistics(Collection<ITask> tasks, TextInputStatistics statistics) { 
    225         for (ITask task : tasks) { 
    226             calculateStatistics(task, statistics); 
    227         } 
    228     } 
    229  
    230     /** 
    231      * 
    232      */ 
    233     private void calculateStatistics(ITask task, TextInputStatistics statistics) { 
    234          
    235         if (isTextInput(task)) { 
    236             calculateStatistics((IEventTask) task, statistics); 
     225    private void calculateStatistics(Collection<IUserSession> sessions, 
     226                                     TextInputStatistics      statistics) 
     227    { 
     228        System.out.print("calculating statistics ... "); 
     229        for (IUserSession session : sessions) { 
     230            for (ITaskInstance taskInstance : session) { 
     231                calculateStatistics(taskInstance, session, statistics); 
     232            } 
     233        } 
     234        System.out.println("done"); 
     235    } 
     236 
     237    /** 
     238     * 
     239     */ 
     240    private void calculateStatistics(ITaskInstance       taskInstance, 
     241                                     IUserSession        session, 
     242                                     TextInputStatistics statistics) 
     243    { 
     244        if (isTextInput(taskInstance)) { 
     245            calculateStatistics((IEventTaskInstance) taskInstance, session, statistics); 
    237246        } 
    238247        else { 
    239             if (task instanceof IStructuringTemporalRelationship) { 
    240                 for (ITask child : ((IStructuringTemporalRelationship) task).getChildren()) { 
    241                     calculateStatistics(child, statistics); 
    242                 } 
    243             } 
    244             else if (task instanceof IMarkingTemporalRelationship) { 
     248            if (taskInstance instanceof ISequenceInstance) { 
     249                for (ITaskInstance child : (ISequenceInstance) taskInstance) { 
     250                    calculateStatistics(child, session, statistics); 
     251                } 
     252            } 
     253            else if (taskInstance instanceof IIterationInstance) { 
     254                for (ITaskInstance child : (IIterationInstance) taskInstance) { 
     255                    calculateStatistics(child, session, statistics); 
     256                } 
     257            } 
     258            else if (taskInstance instanceof ISelectionInstance) { 
    245259                calculateStatistics 
    246                     (((IMarkingTemporalRelationship) task).getMarkedTask(), statistics); 
    247             } 
    248             else { 
     260                    (((ISelectionInstance) taskInstance).getChild(), session, statistics); 
     261            } 
     262            else if (taskInstance instanceof IOptionalInstance) { 
     263                calculateStatistics 
     264                    (((IOptionalInstance) taskInstance).getChild(), session, statistics); 
     265            } 
     266            else{ 
    249267                statistics.incrementNoOfOtherEventTasks(); 
    250268            } 
     
    255273     * 
    256274     */ 
    257     private boolean isTextInput(ITask task) { 
    258         if (task.getInstances().size() > 0) { 
    259             ITaskInstance instance = task.getInstances().iterator().next(); 
    260             if (instance instanceof IEventTaskInstance) { 
    261                 return ((IEventTaskInstance) instance).getEvent().getType() instanceof TextInput; 
    262             } 
     275    private boolean isTextInput(ITaskInstance taskInstance) { 
     276        if (taskInstance instanceof IEventTaskInstance) { 
     277            return ((IEventTaskInstance) taskInstance).getEvent().getType() instanceof TextInput; 
    263278        } 
    264279 
     
    269284     * 
    270285     */ 
    271     private void calculateStatistics(IEventTask node, TextInputStatistics statistics) { 
    272          
    273         for (ITaskInstance instance : node.getInstances()) { 
    274             IEventType type = ((IEventTaskInstance) instance).getEvent().getType(); 
    275             IEventTarget target = ((IEventTaskInstance) instance).getEvent().getTarget(); 
    276  
    277             if (type instanceof TextInput) { 
    278                 String[] fragments = 
    279                     determineTextFragments(((TextInput) type).getEnteredText()); 
    280                  
    281                 if (target instanceof ITextField) { 
    282                     statistics.addTextFieldInput(node, fragments); 
    283                 } 
    284                 else if (target instanceof ITextArea) { 
    285                     statistics.addTextAreaInput(node, fragments); 
    286                 } 
    287             } 
    288         } 
    289     } 
    290  
    291     /** 
    292      * 
    293      */ 
    294     private String[] determineTextFragments(String enteredText) { 
     286    private void calculateStatistics(IEventTaskInstance  taskInstance, 
     287                                     IUserSession        session, 
     288                                     TextInputStatistics statistics) 
     289    { 
     290        IEventType type = taskInstance.getEvent().getType(); 
     291        IEventTarget target = taskInstance.getEvent().getTarget(); 
     292 
     293        if (type instanceof TextInput) { 
     294            if (target instanceof ITextField) { 
     295                statistics.addTextFieldInput(taskInstance, session); 
     296            } 
     297            else if (target instanceof ITextArea) { 
     298                statistics.addTextAreaInput(taskInstance, session); 
     299            } 
     300        } 
     301    } 
     302 
     303    /** 
     304     * 
     305     */ 
     306/*    private static String[] determineTextFragments(String enteredText) { 
    295307        List<String> fragments = new ArrayList<String>(); 
    296308 
     
    304316                // the previous fragment ended. so finalize it and start a new one 
    305317                if ((fragment != null) && (fragment.length() > 0)) { 
    306                     fragments.add(fragment.toString()); 
     318                    String fragmentStr = fragment.toString().trim(); 
     319                     
     320                    if (!"".equals(fragmentStr)) { 
     321                        fragments.add(fragmentStr); 
     322                    } 
     323                     
    307324                    fragment = new StringBuffer(); 
    308325                } 
     
    314331 
    315332        if ((fragment != null) && (fragment.length() > 0)) { 
    316             fragments.add(fragment.toString()); 
     333            String fragmentStr = fragment.toString().trim(); 
     334             
     335            if (!"".equals(fragmentStr)) { 
     336                fragments.add(fragmentStr); 
     337            } 
    317338        } 
    318339 
     
    323344     * 
    324345     */ 
    325     private boolean isEqualCharacterType(char char1, char char2) { 
     346/*    private static boolean isEqualCharacterType(char char1, char char2) { 
    326347        return 
    327348            ((char1 == char2) || 
     
    330351            (Character.isLetter(char1) && Character.isLetter(char2)) || 
    331352            (Character.isJavaIdentifierPart(char1) && Character.isJavaIdentifierPart(char2))); 
    332     } 
    333  
    334     /** 
    335      * TODO comment 
     353    }*/ 
     354 
     355    /** 
     356     * 
     357     */ 
     358    private static class TextInputStatistics { 
     359         
     360        /** */ 
     361        private List<IEventTaskInstance> textFieldInputs = new ArrayList<IEventTaskInstance>(); 
     362         
     363        /** */ 
     364        private Map<ITextField, List<String>> textFields = new HashMap<ITextField, List<String>>(); 
     365 
     366        /** */ 
     367        private List<IEventTaskInstance> textAreaInputs = new ArrayList<IEventTaskInstance>(); 
     368 
     369        /** */ 
     370        private Map<IUserSession, Map<String, TextEntryData>> textEntries = 
     371            new HashMap<IUserSession, Map<String, TextEntryData>>(); 
     372 
     373        /** */ 
     374        private int otherEventsCount; 
     375 
     376        /** 
     377         * 
     378         */ 
     379        private void addTextFieldInput(IEventTaskInstance instance, IUserSession session) { 
     380            String enteredText = ((TextInput) instance.getEvent().getType()).getEnteredText(); 
     381             
     382            if ((enteredText != null) && (!"".equals(enteredText.trim()))) { 
     383                enteredText = enteredText.trim(); 
     384                 
     385                textFieldInputs.add(instance); 
     386 
     387                // store text entries into text fields 
     388                List<String> entries = textFields.get(instance.getEvent().getTarget()); 
     389 
     390                if (entries == null) { 
     391                    entries = new LinkedList<String>(); 
     392                    textFields.put((ITextField) instance.getEvent().getTarget(), entries); 
     393                } 
     394                 
     395                entries.add(enteredText); 
     396 
     397                // writing down all text entries in text fields to check later for cooccurrences in 
     398                // same session 
     399                Map<String, TextEntryData> sessionTextEntries = textEntries.get(session); 
     400 
     401                if (sessionTextEntries == null) { 
     402                    sessionTextEntries = new HashMap<String, TextEntryData>(); 
     403                    textEntries.put(session, sessionTextEntries); 
     404                } 
     405 
     406                TextEntryData data = sessionTextEntries.get(enteredText); 
     407 
     408                if (data == null) { 
     409                    data = new TextEntryData(enteredText); 
     410                    sessionTextEntries.put(enteredText, data); 
     411                } 
     412 
     413                data.addTaskInstance(instance); 
     414            } 
     415        } 
     416         
     417        /** 
     418         * 
     419         */ 
     420        public List<String> getAllInputsInto(ITextField textField) { 
     421            return textFields.get(textField); 
     422        } 
     423 
     424        /** 
     425         * 
     426         */ 
     427        private int getUsageCount(ITextField textField) { 
     428            List<String> entries = textFields.get(textField); 
     429             
     430            if (entries == null) { 
     431                return 0; 
     432            } 
     433            else { 
     434                return entries.size(); 
     435            } 
     436        } 
     437 
     438        /** 
     439         * 
     440         */ 
     441        private List<TextFieldCorrelation> determineTextFieldCorrelations() { 
     442            System.out.print("determining text field correlations of " + textFields.size() + 
     443                             " text fields ... "); 
     444            List<TextFieldCorrelation> correlations = new ArrayList<TextFieldCorrelation>(); 
     445             
     446            // we need an ordered list of text fields to be able compare all with each other 
     447            // through a nested loop 
     448            List<ITextField> textFieldList = getAllTextFields(); 
     449             
     450            List<TextEntryData> relevantTextEntryData = new LinkedList<TextEntryData>(); 
     451             
     452            for (Map<String, TextEntryData> sessionSpecEntries : textEntries.values()) { 
     453                for (TextEntryData data : sessionSpecEntries.values()) { 
     454                    if (data.textFields.size() > 1) { 
     455                        relevantTextEntryData.add(data); 
     456                    } 
     457                } 
     458            } 
     459             
     460            for (int i = 0; i < (textFieldList.size() - 1); i++) { 
     461                for (int j = i + 1; j < textFieldList.size(); j++) { 
     462                    // count the number of times, in which the same text was entered in both 
     463                    // text fields within the same session 
     464                    List<String> sameEnteredTexts = new LinkedList<String>(); 
     465 
     466                    for (TextEntryData data : relevantTextEntryData) { 
     467                        if (data.textFields.contains(textFieldList.get(i)) && 
     468                            data.textFields.contains(textFieldList.get(j))) 
     469                        { 
     470                            sameEnteredTexts.add(data.enteredText); 
     471                        } 
     472                    } 
     473 
     474                    if (sameEnteredTexts.size() > 0) { 
     475                        // for the checked combination of text fields, there is at least once 
     476                        // the same text entered into both text fields during the same session 
     477                        correlations.add(new TextFieldCorrelation(textFieldList.get(i), 
     478                                                                  textFieldList.get(j), 
     479                                                                  sameEnteredTexts)); 
     480                    } 
     481                } 
     482            } 
     483             
     484            System.out.println("done"); 
     485             
     486            return correlations; 
     487        } 
     488 
     489        /** 
     490         * 
     491         */ 
     492        private void addTextAreaInput(IEventTaskInstance instance, IUserSession session) { 
     493            textAreaInputs.add(instance); 
     494        } 
     495 
     496        /** 
     497         * 
     498         */ 
     499        private int getNoOfAllEvents() { 
     500            return textFieldInputs.size() + textAreaInputs.size() + otherEventsCount; 
     501        } 
     502 
     503        /** 
     504         * 
     505         */ 
     506        private int getNoOfTextFieldInputs() { 
     507            return textFieldInputs.size(); 
     508        } 
     509 
     510        /** 
     511         * 
     512         */ 
     513        private int getNoOfTextAreaInputs() { 
     514            return textAreaInputs.size(); 
     515        } 
     516 
     517        /** 
     518         * 
     519         */ 
     520        private void incrementNoOfOtherEventTasks() { 
     521            otherEventsCount++; 
     522        } 
     523 
     524        /** 
     525         *  
     526         */ 
     527        private List<ITextField> getAllTextFields() { 
     528            List<ITextField> textFieldList = new ArrayList<ITextField>(textFields.size()); 
     529             
     530            for (ITextField textField : textFields.keySet()) { 
     531                textFieldList.add(textField); 
     532            } 
     533             
     534            return textFieldList; 
     535        } 
     536    } 
     537     
     538    /** 
    336539     *  
    337      * @version $Revision: $ $Date: 16.07.2012$ 
    338      * @author 2012, last modified by $Author: pharms$ 
    339      */ 
    340     public static class TextInputStatistics { 
    341          
    342         /** */ 
    343         private List<Object[]> textFieldInputs = new ArrayList<Object[]>(); 
    344  
    345         /** */ 
    346         private List<Object[]> textAreaInputs = new ArrayList<Object[]>(); 
    347  
    348         /** */ 
    349         private int otherEventsCount; 
    350  
    351         /** 
    352          * 
    353          */ 
    354         public void addTextFieldInput(IEventTask node, String[] fragments) { 
    355             textFieldInputs.add(new Object[] { node, fragments }); 
    356         } 
    357  
    358         /** 
    359          * 
    360          */ 
    361         public void addTextAreaInput(IEventTask node, String[] fragments) { 
    362             textAreaInputs.add(new Object[] { node, fragments }); 
    363         } 
    364  
    365         /** 
    366          * 
    367          */ 
    368         public int getNoOfAllEvents() { 
    369             return textFieldInputs.size() + textAreaInputs.size() + otherEventsCount; 
    370         } 
    371  
    372         /** 
    373          * 
    374          */ 
    375         public int getNoOfTextFieldInputs() { 
    376             return textFieldInputs.size(); 
    377         } 
    378  
    379         /** 
    380          * 
    381          */ 
    382         public String[] getTextFieldInputFragments(int index) { 
    383             return (String[]) textFieldInputs.get(index)[1]; 
    384         } 
    385  
    386         /** 
    387          * 
    388          */ 
    389         public int getNoOfTextAreaInputs() { 
    390             return textAreaInputs.size(); 
    391         } 
    392  
    393         /** 
    394          * 
    395          */ 
    396         public String[] getTextAreaInputFragments(int index) { 
    397             return (String[]) textAreaInputs.get(index)[1]; 
    398         } 
    399  
    400         /** 
    401          * 
    402          */ 
    403         public void incrementNoOfOtherEventTasks() { 
    404             otherEventsCount++; 
     540     */ 
     541    private static class TextEntryData { 
     542         
     543        /** */ 
     544        private String enteredText; 
     545         
     546        /** */ 
     547        private List<IEventTaskInstance> respectiveTaskInstances = 
     548            new LinkedList<IEventTaskInstance>(); 
     549 
     550        /** */ 
     551        private Set<ITextField> textFields = new HashSet<ITextField>(); 
     552         
     553        /** 
     554         * 
     555         */ 
     556        private TextEntryData(String text) { 
     557            this.enteredText = text; 
     558        } 
     559 
     560        /** 
     561         * 
     562         */ 
     563        private void addTaskInstance(IEventTaskInstance instance) { 
     564            respectiveTaskInstances.add(instance); 
     565            textFields.add((ITextField) instance.getEvent().getTarget()); 
     566        } 
     567         
     568    } 
     569 
     570    /** 
     571     *  
     572     */ 
     573    private static class TextFieldCorrelation { 
     574         
     575        /** */ 
     576        private List<String> enteredTexts = new LinkedList<String>(); 
     577 
     578        /** */ 
     579        private ITextField textField1; 
     580         
     581        /** */ 
     582        private ITextField textField2; 
     583         
     584        /** 
     585         * 
     586         */ 
     587        private TextFieldCorrelation(ITextField   textField1, 
     588                                     ITextField   textField2, 
     589                                     List<String> enteredTexts) 
     590        { 
     591            this.textField1 = textField1; 
     592            this.textField2 = textField2; 
     593            this.enteredTexts = enteredTexts; 
    405594        } 
    406595 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityDefect.java

    r1301 r1335  
    3737     * 
    3838     */ 
    39     public UsabilityDefect(UsabilityDefectSeverity severity, UsabilityDefectDescription description) 
     39    UsabilityDefect(UsabilityDefectSeverity severity, UsabilityDefectDescription description) 
    4040    { 
    4141        this(severity, description, null); 
     
    4545     * 
    4646     */ 
    47     public UsabilityDefect(UsabilityDefectSeverity    severity, 
    48                            UsabilityDefectDescription description, 
    49                            Map<String, String>        parameters) 
     47    UsabilityDefect(UsabilityDefectSeverity    severity, 
     48                    UsabilityDefectDescription description, 
     49                    Map<String, String>        parameters) 
    5050    { 
    5151        this.severity = severity; 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityDefectDescription.java

    r1301 r1335  
    3333public enum UsabilityDefectDescription { 
    3434     
     35    SCROLL_REQUIRED, 
    3536    TEXT_FIELD_INPUT_RATIO, 
    3637    TEXT_FIELD_INPUT_REPETITIONS, 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityEvaluationManager.java

    r1301 r1335  
    4646    private void init() { 
    4747        rules.add(new TextInputStatisticsRule()); 
     48        rules.add(new RequiredScrollRule()); 
    4849    } 
    4950 
     
    5455        Console.traceln(Level.INFO, "evaluating usability of task model " + taskModel); 
    5556 
    56         List<UsabilityEvaluationResult> results = new ArrayList<UsabilityEvaluationResult>(); 
     57        List<UsabilityEvaluationResult> interimResults = new ArrayList<UsabilityEvaluationResult>(); 
    5758 
    5859        for (UsabilityEvaluationRule rule : rules) { 
    5960            Console.traceln(Level.INFO, "applying rule " + rule.getClass().getSimpleName()); 
    6061            UsabilityEvaluationResult result = rule.evaluate(taskModel); 
    61             results.add(result); 
     62            interimResults.add(result); 
    6263            Console.traceln(Level.INFO, "the rule found " + result.getAllDefects().size() + 
    6364                            " usability defects, of which " + result.getSevereDefects().size() + 
     
    6566        } 
    6667 
    67         UsabilityEvaluationResult result = mergeResults(results); 
     68        UsabilityEvaluationResult result = new UsabilityEvaluationResult(interimResults); 
    6869        Console.println("the evaluation result contains " + result.getAllDefects().size() + 
    6970                        " defects, of which " + result.getSevereDefects().size() + " are severe."); 
    70         return result; 
    71     } 
    7271 
    73     /** 
    74      * 
    75      */ 
    76     private UsabilityEvaluationResult mergeResults(List<UsabilityEvaluationResult> results) { 
    77         UsabilityEvaluationResult result = new UsabilityEvaluationResult(); 
    78  
    79         for (UsabilityEvaluationResult ruleResult : results) { 
    80             for (UsabilityDefect defect : ruleResult.getAllDefects()) { 
    81                 result.addDefect(defect); 
    82             } 
     72        List<UsabilityDefect> defects = result.getAllDefects(); 
     73        for (int i = 0; i < defects.size(); i++) { 
     74            Console.println((i + 1) + ": " + defects.get(i).getParameterizedDescription()); 
    8375        } 
    8476 
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UsabilityEvaluationResult.java

    r1301 r1335  
    1717import java.util.ArrayList; 
    1818import java.util.List; 
     19import java.util.Map; 
    1920 
    2021/** 
     
    3233     * 
    3334     */ 
    34     public void addDefect(UsabilityDefect defect) { 
    35         defects.add(defect); 
     35    public UsabilityEvaluationResult() { 
     36        // default constructor 
     37    } 
     38 
     39    /** 
     40     * 
     41     */ 
     42    public UsabilityEvaluationResult(List<UsabilityEvaluationResult> results) { 
     43        for (UsabilityEvaluationResult result : results) { 
     44            for (UsabilityDefect defect : result.getAllDefects()) { 
     45                defects.add(defect); 
     46            } 
     47        } 
     48    } 
     49 
     50    /** 
     51     * 
     52     */ 
     53    public void addDefect(UsabilityDefectSeverity    severity, 
     54                          UsabilityDefectDescription description, 
     55                          Map<String, String>        parameters) 
     56    { 
     57        defects.add(new UsabilityDefect(severity, description, parameters)); 
    3658    } 
    3759 
  • trunk/autoquest-core-usability/src/main/resources/defectDescriptions_en.xml

    r496 r1335  
    1212    <parameterFragment parameterName="textInputRatio" /> 
    1313    <textFragment> 
    14       ). This should be reduced. As an example, entering data can also be done using check boxes 
     14      %). This should be reduced. As an example, entering data can also be done using check boxes 
    1515      or combo boxes in the case predefined values must be entered. 
    1616    </textFragment> 
     
    1919  <defectDescription defectId="TEXT_FIELD_INPUT_REPETITIONS"> 
    2020    <textFragment> 
    21       Several interactions that enter text into text fields repeat tokens such as words or 
    22       specific signs ( 
     21      In 
    2322    </textFragment> 
    2423    <parameterFragment parameterName="textRepetitionRatio" /> 
    2524    <textFragment> 
    26       ). This is an indicator that the same data must be entered several times. This could be 
    27       better supported by using e.g. automatic filling of input fields, provision of combo 
    28       boxes or lists prefilled with data that was already entered previously.  
     25      % of entering text into text field  
     26    </textFragment> 
     27    <parameterFragment parameterName="textField1" /> 
     28    <textFragment> 
     29      , the same text was also entered into text field 
     30    </textFragment> 
     31    <parameterFragment parameterName="textField2" /> 
     32    <textFragment> 
     33      during the same session. Perhaps this can be automated, so that the user does not have to 
     34      reenter the same text several times into different text fields. 
    2935    </textFragment> 
    3036  </defectDescription> 
    3137   
    3238  <defectDescription defectId="TEXT_FIELD_NO_LETTER_OR_DIGIT_RATIO"> 
    33     <textFragment> 
    34       Much of the text entered into text fields contains signs other than letters or digits ( 
    35     </textFragment> 
    3639    <parameterFragment parameterName="noLetterOrDigitRatio" /> 
    3740    <textFragment> 
    38       ). This is an indicator that the entered data has to follow a specific syntax. This should 
    39       be supported by syntax checking, auto completion or even providing the text fields in a way 
    40       that does not require the entering of special signs as they are already included at the right 
    41       positions. 
     41      % of the text entered into text field 
     42    </textFragment> 
     43    <parameterFragment parameterName="textField" /> 
     44    <textFragment> 
     45      was no letter or digit. This is an indicator that the entered data has to follow a specific 
     46      syntax. This should be supported by syntax checking, auto completion or even providing the 
     47      text fields in a way that does not require the entering of special signs as they are already 
     48      included at the right positions. 
     49    </textFragment> 
     50  </defectDescription> 
     51   
     52  <defectDescription defectId="SCROLL_REQUIRED"> 
     53    <textFragment> 
     54      In 
     55    </textFragment> 
     56    <parameterFragment parameterName="scrollRatio" /> 
     57    <textFragment> 
     58      % of all occurrences, the task 
     59    </textFragment> 
     60    <parameterFragment parameterName="task" /> 
     61    <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. 
    4265    </textFragment> 
    4366  </defectDescription> 
Note: See TracChangeset for help on using the changeset viewer.