// Copyright 2012 Georg-August-Universität Göttingen, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package de.ugoe.cs.autoquest.plugin.usability2.rules.patterns; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import com.google.common.base.Optional; import de.ugoe.cs.autoquest.eventcore.Event; import de.ugoe.cs.autoquest.eventcore.IEventTarget; import de.ugoe.cs.autoquest.eventcore.IEventType; import de.ugoe.cs.autoquest.eventcore.gui.MouseClick; import de.ugoe.cs.autoquest.eventcore.gui.Scroll; import de.ugoe.cs.autoquest.usability.EvaluationMethodCaller; import de.ugoe.cs.autoquest.usability.result.UsabilityProblemDescription; import de.ugoe.cs.autoquest.usability.result.UsabilityProblemDescriptionResolver; import de.ugoe.cs.autoquest.usability.rules.UsabilityRule; import de.ugoe.cs.autoquest.usability.rules.UsabilityUsageProblem; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel; /** *

* Test Rule to see if new pattern method may be used for problem checking *

* * @author Konni Hartmann */ public class SessionPatternProblem extends UsabilityRule implements UsabilityUsageProblem { private final Collection> sessions; /** *

* TODO: comment *

* * @param taskTree */ public SessionPatternProblem(ITaskModel taskModel, Collection> sessions) { super(taskModel); this.sessions = sessions; this.name = "PatternProblem"; this.defect = new UsabilityProblemDescriptionResolver().descriptionFor("PatternProblem"); initUsagePattern(); } /** *

* TODO: comment *

* */ private void initUsagePattern() { } private class Statistics implements Comparable { private IEventTarget target; private int match; private int all; public Statistics(IEventTarget target) { this.target = target; } int matchCount() { return match; } int allCount() { return all; } float percent() { return ((float) matchCount()) / allCount(); } @Override public int compareTo(Statistics o) { float thisPcnt = percent(); float otherPcnt = o.percent(); if (thisPcnt < otherPcnt) return -1; if (thisPcnt > otherPcnt) return 1; return 0; } @Override public String toString() { StringBuilder str = new StringBuilder(); str.append(target.getStringIdentifier()); str.append(" (").append(percent()).append(')'); return str.toString(); } public void increaseCount() { this.all++; } public void increaseMatchCount() { this.match++; } } /* * (non-Javadoc) * * @see de.ugoe.cs.autoquest.usability.rules.UsabilityRule#check() */ @Override public Optional check() { Optional present = Optional.absent(); System.out.println("--"); System.out.println("PP:"); Map results = new HashMap(); int cnt = 0, click=0, scroll=0; for (List events : this.sessions) { IEventType last = null; for (Event event : events) { IEventType type = event.getType(); if (type instanceof MouseClick) { click++; IEventTarget target = event.getTarget(); Statistics statistics = results.get(target); if (statistics == null) { statistics = new Statistics(target); results.put(target, statistics); } statistics.increaseCount(); if(last != null && last instanceof Scroll) { scroll++; statistics.increaseMatchCount(); } } last = type; cnt++; } } System.out.printf("Analyzed %d events with %d clicks and %d scrolls before clicks.\n", cnt, click, scroll); analyzeResults(results); /* * System.out.println("PATTERN2:"); for (ITask task : tasks) { IResult result = * this.pattern2.match(task); * * result = this.pattern2.match(task); * * if (result.isPresent()) { present = Optional.of(this.defect); * System.out.printf("2: %s, %s, %d\n", task.getId(), task.getDescription(), task * .getInstances().size()); } } */ System.out.println("Finished Pattern analysis"); return present; } private void analyzeResults(Map results) { List pcnt95 = new LinkedList(); List pcnt75 = new LinkedList(); List pcnt50 = new LinkedList(); List pcnt25 = new LinkedList(); List pcnt05 = new LinkedList(); for (Statistics s : results.values()) { float percent = s.percent(); if (percent >= 0.95) pcnt95.add(s); else if (percent >= 0.75) pcnt75.add(s); else if (percent >= 0.50) pcnt50.add(s); else if (percent >= 0.25) pcnt25.add(s); else if (percent >= 0.05) pcnt05.add(s); } Comparator reverse = new Comparator() { @Override public int compare(Statistics o1, Statistics o2) { return o2.matchCount() - o1.matchCount(); } }; Collections.sort(pcnt95, reverse); Collections.sort(pcnt75, reverse); Collections.sort(pcnt50, reverse); Collections.sort(pcnt25, reverse); Collections.sort(pcnt05, reverse); printFirstN(pcnt95, 3, 0.95); printFirstN(pcnt75, 3, 0.75); printFirstN(pcnt50, 3, 0.50); printFirstN(pcnt25, 3, 0.25); printFirstN(pcnt05, 3, 0.05); } private void printFirstN(List list, int i, double margin) { if (!list.isEmpty()) { System.out.printf(">= %f :\n", margin); for (int j = 0; j < list.size() && j < i; j++) { Statistics s = list.get(j); System.out.printf("%d [%d]: %s\n", j + 1, s.matchCount(), s); } if (list.size() >= i) { Statistics s = list.get(list.size() - 1); System.out.printf("%d [%d]: %s\n", list.size() - 1, s.matchCount(), s); } } } /* * (non-Javadoc) * * @see * de.ugoe.cs.autoquest.usability.rules.UsabilityRule#callEvaluationMetho(de.ugoe.cs.autoquest * .usability.EvaluationMethodCaller) */ @Override public Optional callEvaluationMethod(EvaluationMethodCaller evaluationMethodCaller) { return evaluationMethodCaller.check(this); } }