source: trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/DataEntryMethodChangeRule.java @ 1960

Last change on this file since 1960 was 1960, checked in by pharms, 9 years ago
  • correction in smell detection
File size: 6.6 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.usability;
16
17import java.util.Collection;
18import java.util.HashMap;
19import java.util.LinkedList;
20import java.util.List;
21import java.util.Map;
22
23import de.ugoe.cs.autoquest.eventcore.IEventType;
24import de.ugoe.cs.autoquest.eventcore.gui.KeyInteraction;
25import de.ugoe.cs.autoquest.eventcore.gui.MouseInteraction;
26import de.ugoe.cs.autoquest.eventcore.gui.Scroll;
27import de.ugoe.cs.autoquest.eventcore.gui.TextInput;
28import de.ugoe.cs.autoquest.eventcore.gui.TextSelection;
29import de.ugoe.cs.autoquest.eventcore.gui.ValueSelection;
30import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskInstanceTraversingVisitor;
31import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
32import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
33import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
34import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
35import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel;
36
37/**
38 * TODO comment
39 *
40 * @version $Revision: $ $Date: 16.07.2012$
41 * @author 2012, last modified by $Author: pharms$
42 */
43public class DataEntryMethodChangeRule implements UsabilityEvaluationRule {
44
45    /*
46     * (non-Javadoc)
47     *
48     * @see de.ugoe.cs.usability.UsabilityEvaluationRule#evaluate(TaskTree)
49     */
50    @Override
51    public UsabilityEvaluationResult evaluate(ITaskModel taskModel) {
52        UsabilityEvaluationResult results = new UsabilityEvaluationResult(taskModel);
53
54        Map<ITask, Integer> smellingTasks = getDataEntryMethodChangeRatios(taskModel.getTasks());
55        analyzeDataEntryMethodChangeRatios(smellingTasks, results, taskModel);
56
57        return results;
58    }
59
60    /**
61     *
62     */
63    private void analyzeDataEntryMethodChangeRatios(Map<ITask, Integer>       smellingTasks,
64                                                    UsabilityEvaluationResult results,
65                                                    ITaskModel                taskModel)
66    {
67
68        for (Map.Entry<ITask, Integer> entry : smellingTasks.entrySet()) {
69            // data entry method change ratio of an instance is the sum of data entry method
70            // changes between subsequent events divided by the number of events minus one. The
71            // data entry method change ratio of a tasks is the average of the ratios of the
72            // instances. If this ratio is 0 no changes are done at all. If it is higher, it should
73            // be informed.
74           
75            UsabilitySmellIntensity intensity =
76                UsabilitySmellIntensity.getIntensity(entry.getValue(), entry.getKey(), taskModel);
77
78            if (intensity != null) {
79                Map<String, Object> parameters = new HashMap<String, Object>();
80
81                parameters.put("task", entry.getKey());
82                parameters.put("ratio", (float) entry.getValue() / 10);
83               
84                results.addSmell(entry.getKey(), intensity,
85                                 UsabilitySmellDescription.DATA_ENTRY_METHOD_CHANGE, parameters);
86            }
87        }
88    }
89
90    /**
91     *
92     */
93    private Map<ITask, Integer> getDataEntryMethodChangeRatios(Collection<ITask> tasks) {
94        Map<ITask, Integer> methodChangeRatios = new HashMap<ITask, Integer>();
95       
96        for (ITask task : tasks) {
97            if (task instanceof ISequence)  {
98                int ratio = getAverageDataEntryMethodChangeRatio((ISequence) task);
99               
100                if (ratio > 0) {
101                    methodChangeRatios.put(task, ratio);
102                }
103            }
104        }
105       
106        return methodChangeRatios;
107    }
108
109    /**
110     *
111     */
112    private int getAverageDataEntryMethodChangeRatio(ISequence task) {
113        if (task.getInstances().size() > 0) {
114            int cummulativeDataEntryMethodChangeRatio = 0;
115            for (ITaskInstance instance : task.getInstances()) {
116                cummulativeDataEntryMethodChangeRatio += getDataEntryMethodChangeRatio(instance);
117            }
118
119            return cummulativeDataEntryMethodChangeRatio / task.getInstances().size();
120        }
121        else {
122            return 0;
123        }
124    }
125
126    /**
127     *
128     */
129    private long getDataEntryMethodChangeRatio(ITaskInstance instance) {
130        final List<IEventTaskInstance> terminalNodes = new LinkedList<>();
131       
132        instance.accept(new DefaultTaskInstanceTraversingVisitor() {
133            @Override
134            public void visit(IEventTaskInstance eventTaskInstance) {
135                terminalNodes.add(eventTaskInstance);
136            }
137        });
138       
139        if (terminalNodes.size() > 1) {
140            IEventTaskInstance previous = null;
141            int changeCount = 0;
142
143            for (IEventTaskInstance current : terminalNodes) {
144                if ((previous != null) && (dataEntryMethodChanges(previous, current))) {
145                    changeCount++;
146                }
147               
148                previous = current;
149            }
150
151            return changeCount * 1000 / (terminalNodes.size() - 1);
152        }
153        else {
154            return 0;
155        }
156    }
157
158
159    /**
160     *
161     */
162    private boolean dataEntryMethodChanges(IEventTaskInstance first, IEventTaskInstance second) {
163        IEventType firstEventType = first.getEvent().getType();
164        IEventType secondEventType = second.getEvent().getType();
165       
166        boolean hasKeyboardInteraction =
167            isKeyboardInteraction(firstEventType) || isKeyboardInteraction(secondEventType);
168       
169        boolean hasMouseInteraction =
170            isMouseInteraction(firstEventType) || isMouseInteraction(secondEventType);
171       
172        return hasKeyboardInteraction && hasMouseInteraction;
173    }
174
175    /**
176     *
177     */
178    private boolean isKeyboardInteraction(IEventType eventType) {
179        return (eventType instanceof KeyInteraction) || (eventType instanceof TextInput);
180    }
181
182    /**
183     *
184     */
185    private boolean isMouseInteraction(IEventType eventType) {
186        return (eventType instanceof MouseInteraction) || (eventType instanceof ValueSelection) ||
187            (eventType instanceof TextSelection) || (eventType instanceof Scroll);
188    }
189}
Note: See TracBrowser for help on using the repository browser.