package-ize things, make NASA_TLX work as a standalone
[rmh3093.git] / motsim / ryanhope / us / nasatlx / NASA_TLX.java
blobbe924ec357e327afd42a0c78d7c99c7e5f7c47a4
1 /**
2 * NASA_TLX.java
3 */
5 /**
6 * NASA-TLX is a subjective workload assessment tool.
7 *
8 * NASA-TLX allows users to perform subjective workload assessments on
9 * operator(s) working with various human-machine systems. NASA-TLX is a
10 * multi-dimensional rating procedure that derives an overall workload score
11 * based on a weighted average of ratings on six subscales.
13 * These subscales include Mental Demands, Physical Demands, Temporal Demands,
14 * Own Performance, Effort and Frustration. It can be used to assess workload
15 * in various human-machine environments such as aircraft cockpits, command,
16 * control, and communication (C3) workstations; supervisory and process
17 * control environments; simulations and laboratory tests.
19 * http://humansystems.arc.nasa.gov/groups/TLX/downloads/NASA-TLXChapter.pdf
21 * Hart, S.G. & Staveland, L.E. (1988). Development of NASA-TLX
22 * (Task Load Index): Results of empirical and theoretical research. In
23 * P.A. Hancock & N. Meshkati (Eds.), Human Mental Workload (pp. 239-250).
24 * Amsterdam: North Holland Press.
27 * @author Ryan M. Hope <rmh3093@gmail.com>
31 package ryanhope.us.nasatlx;
33 import java.awt.Dimension;
34 import java.awt.FlowLayout;
35 import java.awt.GridLayout;
36 import java.awt.event.ActionEvent;
37 import java.awt.event.ActionListener;
38 import java.util.Collections;
39 import java.util.TreeMap;
40 import java.util.TreeSet;
41 import java.util.Vector;
43 import javax.swing.JButton;
44 import javax.swing.JFrame;
45 import javax.swing.JPanel;
47 import ryanhope.us.util.CombinationGenerator;
49 import jargs.gnu.CmdLineParser;
51 public class NASA_TLX {
53 static String[] default_subscales = {
54 "Mental Demand",
55 "Physical Demand",
56 "Temporal Demand",
57 "Own Performance",
58 "Effort",
59 "Fustration"
62 int tasks = 0;
63 boolean verbose = false;
64 String[] subscales;
65 Integer[][] subscale_pairs;
66 TreeMap<String, Integer> biasTally;
67 TreeMap<String, Integer>[] taskRatings;
69 public void printBiasTally() {
70 for (String s : subscales)
71 System.out.println(s + " = " + biasTally.get(s));
74 private Integer[][] generateComparisons(String[] elements) {
75 int[] indices;
76 Vector<Integer[]> pairs = new Vector<Integer[]>();
77 CombinationGenerator cg =
78 new CombinationGenerator(elements.length, 2);
79 while (cg.hasMore()) {
80 indices = cg.getNext();
81 Integer[] pair = {indices[0],indices[1]};
82 pairs.add(pair);
84 Integer[][] subscale_pairs = new Integer[pairs.size()][];
85 for (int i=0; i<pairs.size(); i++) {
86 Integer[] p = pairs.get(i);
87 subscale_pairs[i] = p;
89 return subscale_pairs;
92 @SuppressWarnings("serial")
93 public class PairWiseComparison
94 extends JFrame implements ActionListener {
96 PWCPanel[] panels;
97 int pair = 0;
99 private class PWCPanel extends JPanel {
101 JButton b1,b2;
103 public PWCPanel(String subscale1, String subscale2, ActionListener al) {
104 setLayout(new GridLayout(2,1,15,15));
105 b1 = new JButton(subscale1);
106 b1.setActionCommand(subscale1);
107 b1.addActionListener(al);
108 b1.setPreferredSize(new Dimension(150,40));
109 b1.setFocusable(false);
110 b2 = new JButton(subscale2);
111 b2.setActionCommand(subscale2);
112 b2.addActionListener(al);
113 b2.setPreferredSize(new Dimension(200,40));
114 b2.setFocusable(false);
115 add(b1);
116 add(b2);
117 setVisible(false);
123 * Participant selects the member of each pair that provides the most
124 * significant source of workload variation in the tasks
126 * @param verbose If true the results will be printed to stdout.
128 public PairWiseComparison () {
129 subscale_pairs = generateComparisons(subscales);
130 biasTally = new TreeMap<String, Integer>();
131 for (String s : subscales) biasTally.put(s, 0);
132 setTitle("Pair-wise Comparison");
133 setLocationRelativeTo(null);
134 setResizable(false);
135 setPreferredSize(new Dimension(250,90));
136 setLayout(new FlowLayout(FlowLayout.CENTER,10,10));
137 panels = new PWCPanel[subscale_pairs.length];
138 for (int i=0; i<subscale_pairs.length; i++) {
139 panels[i] = new PWCPanel(subscales[subscale_pairs[i][0]],
140 subscales[subscale_pairs[i][1]],this);
141 add(panels[i]);
143 panels[pair].setVisible(true);
144 pack();
145 setVisible(true);
149 public void actionPerformed(ActionEvent e) {
150 int oldval = biasTally.get(e.getActionCommand());
151 biasTally.put(e.getActionCommand(), oldval+1);
152 panels[pair].setVisible(false);
153 pair++;
154 if (pair<subscale_pairs.length)
155 panels[pair].setVisible(true);
156 else {
157 if (verbose) printBiasTally();
158 dispose();
163 private void printUsage() {
164 System.err.println("Usage: NASA_TLX [OPTIONS]\n");
165 System.err.println("Option\t\tGNU long option\t\tMeaning");
166 System.err.println("-v\t\t--verbose\t\tEnable verbose output");
167 System.err.println("-t\t\t--tasks number\t\tThe number of subtasks");
168 System.err.println("-d\t\t--disable subscale\tDisable a subscale");
169 System.err.println("\nAvailable subscales:");
170 for (int i=0; i<default_subscales.length; i++)
171 System.err.println(" " + (i+1) + ". " + default_subscales[i]);
174 public NASA_TLX(String[] args) {
176 CmdLineParser parser = new CmdLineParser();
177 CmdLineParser.Option tasks = parser.addIntegerOption('t', "tasks");
178 CmdLineParser.Option disable = parser.addIntegerOption('d', "disable");
179 CmdLineParser.Option verbose = parser.addBooleanOption('v', "verbose");
180 CmdLineParser.Option help = parser.addBooleanOption('h', "help");
182 try {
183 parser.parse(args);
185 catch ( CmdLineParser.OptionException e ) {
186 System.err.println(e.getMessage());
187 printUsage();
188 System.exit(2);
191 if ((Boolean)parser.getOptionValue(help, false)) {
192 printUsage();
193 System.exit(2);
195 this.tasks = (Integer)parser.getOptionValue(tasks, 1);
196 this.verbose = (Boolean)parser.getOptionValue(verbose, false);
197 Vector<Integer> disabled_subscales = parser.getOptionValues(disable);
198 if (disabled_subscales.isEmpty())
199 subscales = default_subscales;
200 else {
201 subscales =
202 new String[default_subscales.length-disabled_subscales.size()];
203 boolean found;
204 int index = 0;
205 for (int i=0; i<default_subscales.length; i++) {
206 found = false;
207 int idx = 0;
208 while (!found && idx<disabled_subscales.size()) {
209 if ((disabled_subscales.get(idx)-1)==i) found = true;
210 else idx++;
212 if (!found) {
213 subscales[index] = default_subscales[i];
214 index++;
218 subscale_pairs = generateComparisons(subscales);
219 new PairWiseComparison();
223 * @param args
225 public static void main(String[] args) {
226 new NASA_TLX(args);