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

Last change on this file since 2162 was 2162, checked in by pharms, 7 years ago
  • changes for first VR oriented usability evaluation
File size: 7.4 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.ArrayList;
18import java.util.HashMap;
19import java.util.LinkedList;
20import java.util.List;
21import java.util.Map;
22import java.util.Set;
23
24import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
25
26import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskInstanceTraversingVisitor;
27import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
28import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
29import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance;
30import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
31import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel;
32import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
33import de.ugoe.cs.autoquest.tasktrees.treeifc.TaskTreeUtils;
34
35/**
36 * TODO comment
37 *
38 * @version $Revision: $ $Date: 16.07.2012$
39 * @author 2012, last modified by $Author: pharms$
40 */
41public class CommonTaskRateRule implements UsabilityEvaluationRule {
42
43    /*
44     * (non-Javadoc)
45     *
46     * @see de.ugoe.cs.usability.UsabilityEvaluationRule#evaluate(TaskTree)
47     */
48    @Override
49    public UsabilityEvaluationResult evaluate(ITaskModel taskModel) {
50        SummaryStatistics statistics = new SummaryStatistics();
51        SummaryStatistics mpStatistics = new SummaryStatistics();
52        int allObserved = calculateStatistics
53            (taskModel.getUserSessions(), TaskTreeUtils.getMostProminentTasks(taskModel),
54             statistics, mpStatistics);
55
56        UsabilityEvaluationResult results = new UsabilityEvaluationResult(taskModel);
57        analyzeStatistics(statistics, false, allObserved, results);
58        analyzeStatistics(mpStatistics, true, allObserved, results);
59
60        return results;
61    }
62
63    /**
64     *
65     */
66    private void analyzeStatistics(SummaryStatistics         statistics,
67                                   boolean                   mostProminentSequencesOnly,
68                                   int                       allObserved,
69                                   UsabilityEvaluationResult results)
70    {
71        // the mean indicates how many different root nodes 10 subsequent actions have.
72        // The mean should tend to 0.1 (all subsequent 10 actions are covered by the same root task).
73        // The ratio must be similar, i.e., if the mean is 0.1 the ratio is 0, if the mean is 1.0
74        // the ratio is 1000
75       
76        if (statistics.getN() > 0) {
77            double mean = statistics.getMean();
78            int ratio = (int) (10000 * (mean - 0.1) / 9);
79
80            UsabilitySmellIntensity intensity =
81                UsabilitySmellIntensity.getIntensity(ratio, allObserved, -1);
82
83            if (intensity != null) {
84                Map<String, Object> parameters = new HashMap<String, Object>();
85                parameters.put("ratio", ((float) Math.round(mean * 100)) / 10);
86               
87                if (mostProminentSequencesOnly) {
88                    parameters.put("tasksType", "representative tasks");
89                }
90                else {
91                    parameters.put("tasksType", "tasks");
92                }
93
94                results.addSmell(intensity, UsabilitySmellDescription.COMMON_TASK_RATE, parameters);
95            }
96        }
97    }
98
99
100    /**
101     *
102     */
103    private int calculateStatistics(List<IUserSession>      sessions,
104                                    final Set<ISequence>    mostProminentTasks,
105                                    final SummaryStatistics statistics,
106                                    final SummaryStatistics mpStatistics)
107    {
108        final LinkedList<ITaskInstance> rootNodes = new LinkedList<>();
109        final LinkedList<ITaskInstance> mpRootNodes = new LinkedList<>();
110        final List<IEventTaskInstance> leafNodes = new ArrayList<>();
111       
112        // determine for always 10 subsequent actions the root tasks performed for them.
113        // then determine, the ratio of different root tasks to 10.
114        for (IUserSession session : sessions) {
115            rootNodes.clear();
116            mpRootNodes.clear();
117           
118            for (final ITaskInstance currentRoot : session) {
119                currentRoot.accept(new DefaultTaskInstanceTraversingVisitor() {
120                    private ITaskInstance currentMpRoot = null;
121 
122                    @Override
123                    public void visit(ISequenceInstance sequenceInstance) {
124                        boolean currentInstancesIsMpRoot = false;
125                        if (mostProminentTasks.contains(sequenceInstance.getSequence())) {
126                            if (currentMpRoot == null) {
127                                currentMpRoot = sequenceInstance;
128                                currentInstancesIsMpRoot = true;
129                            }
130                            // else already detected most prominent root task
131                        }
132                        super.visit(sequenceInstance);
133                       
134                        if (currentInstancesIsMpRoot) {
135                            // if the current instance is also the root instance considering only
136                            // most prominent sequences, then reset the stored instance to null
137                            // after traversing this task
138                            currentMpRoot = null;
139                        }
140                    }
141
142                    @Override
143                    public void visit(IEventTaskInstance eventTaskInstance) {
144                        rootNodes.add(currentRoot);
145                        mpRootNodes.add(currentMpRoot != null ? currentMpRoot : currentRoot);
146                        leafNodes.add(eventTaskInstance);
147
148                        if (rootNodes.size() >= 10) {
149                            statistics.addValue(getTaskCoverageMeasure(rootNodes));
150                           
151                            while (rootNodes.size() >= 10) {
152                                rootNodes.removeFirst();
153                            }
154                        }
155                       
156                        if (mpRootNodes.size() >= 10) {
157                            mpStatistics.addValue(getTaskCoverageMeasure(mpRootNodes));
158                           
159                            while (mpRootNodes.size() >= 10) {
160                                mpRootNodes.removeFirst();
161                            }
162                        }
163                    }
164                });
165            }
166        }
167       
168        return leafNodes.size();
169    }
170
171    /**
172     *
173     */
174    private double getTaskCoverageMeasure(LinkedList<ITaskInstance> rootNodes) {
175        int noOfDiffRoots = 0;
176        ITaskInstance prevRoot = null;
177       
178        for (ITaskInstance root : rootNodes) {
179            if (!root.equals(prevRoot)) {
180                noOfDiffRoots++;
181            }
182           
183            prevRoot = root;
184        }
185       
186        return (double) noOfDiffRoots / rootNodes.size();
187    }
188
189}
Note: See TracBrowser for help on using the repository browser.