test_conf.py revision f11c971f67f255d8093e5cee05e5da0e6446d900
1# -*- coding: utf-8 -*-
2#
3# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""This configuration file defines the gestures to perform."""
8
9from collections import defaultdict
10from firmware_constants import DEV, GV, VAL
11from validators import (CountPacketsValidator,
12                        CountTrackingIDNormalFingerValidator,
13                        CountTrackingIDFatFingerValidator,
14                        DragLatencyValidator,
15                        DrumrollValidator,
16                        HysteresisValidator,
17                        LinearityFatFingerValidator,
18                        LinearityNormalFingerValidator,
19                        NoGapValidator,
20                        NoReversedMotionValidator,
21                        PhysicalClickValidator,
22                        PinchValidator,
23                        RangeValidator,
24                        ReportRateValidator,
25                        StationaryValidator,
26                        StationaryFingerValidator,
27                        StationaryTapValidator,
28)
29
30
31# Define which score aggregator is to be used. A score aggregator collects
32# the scores from every tests and calculates the final score for the touch
33# firmware test suite.
34score_aggregator = 'fuzzy.average'
35
36
37# Define some common criteria
38count_packets_criteria = '>= 3, ~ -3'
39drumroll_criteria = '<= 2.0'
40# linearity_criteria is used for strictly straight line drawn with a ruler.
41linearity_criteria = '<= 0.8, ~ +2.4'
42# relaxed_linearity_criteria is used for lines drawn with thumb edge or
43# fat fingers which are allowed to be curvy to some extent.
44relaxed_linearity_criteria = '<= 1.5, ~ +3.0'
45no_gap_criteria = '<= 1.8, ~ +1.0'
46no_level_jump_criteria = '<= 10, ~ +30'
47no_reversed_motion_criteria = '<= 5, ~ +30'
48pinch_criteria = '>= 200, ~ -100'
49range_criteria = '<= 0.01, ~ +0.07'
50min_report_rate = 60
51max_report_interval = 1.0 / min_report_rate * 1000
52report_rate_criteria = '>= %d' % min_report_rate
53stationary_finger_criteria = '<= 1.0'
54stationary_tap_criteria = '<= 1.0'
55hysteresis_criteria = '<= 2.0'
56drag_latency_criteria = '<= 28.0'
57
58MIN_MOVING_DISTANCE = 20
59
60
61# Define filenames and paths
62docroot = '/tmp'
63report_basename = 'touch_firmware_report'
64html_ext = '.html'
65ENVIRONMENT_REPORT_HTML_NAME = 'REPORT_HTML_NAME'
66log_root_dir = '/var/tmp/touch_firmware_test'
67fw_prefix = 'fw_'
68device_description_dir = 'tests/device'
69version_filename = '.version'
70
71
72# Define parameters for GUI
73score_colors = ((0.9, 'blue'), (0.8, 'orange'), (0.0, 'red'))
74num_chars_per_row = 28
75
76
77# Define the validators that are shown only when there are failures.
78validators_hidden_when_no_failures = ['PinchValidator',
79                                      'CountTrackingIDNormalFingerValidator',
80                                      'CountTrackingIDFatFingerValidator',
81                                      'CountPacketsValidator']
82
83
84# Define the parent validators from which the derived validators should be
85# merged in the top-level summary table.
86merged_validators = [StationaryValidator,]
87
88
89# Define the path to find the robot gestures library path
90robot_lib_path_local = '/usr/local/lib*'
91robot_lib_path = '/usr/lib*'
92python_package = 'python*\.*'
93gestures_sub_path = 'site-packages/touchbotII'
94
95
96# Define the gesture names
97NOISE_LINE = 'noise_line'
98NOISE_STATIONARY = 'noise_stationary'
99NOISE_STATIONARY_EXTENDED = 'noise_stationary_extended'
100ONE_FINGER_TRACKING = 'one_finger_tracking'
101ONE_FINGER_TO_EDGE = 'one_finger_to_edge'
102TWO_FINGER_TRACKING = 'two_finger_tracking'
103FINGER_CROSSING = 'finger_crossing'
104ONE_FINGER_SWIPE = 'one_finger_swipe'
105TWO_FINGER_SWIPE = 'two_finger_swipe'
106PINCH_TO_ZOOM = 'pinch_to_zoom'
107ONE_FINGER_TAP = 'one_finger_tap'
108TWO_FINGER_TAP = 'two_finger_tap'
109ONE_FINGER_PHYSICAL_CLICK = 'one_finger_physical_click'
110TWO_FINGER_PHYSICAL_CLICK = 'two_fingers_physical_click'
111THREE_FINGER_PHYSICAL_CLICK = 'three_fingers_physical_click'
112FOUR_FINGER_PHYSICAL_CLICK = 'four_fingers_physical_click'
113FIVE_FINGER_PHYSICAL_CLICK = 'five_fingers_physical_click'
114STATIONARY_FINGER_NOT_AFFECTED_BY_2ND_FINGER_TAPS = \
115        'stationary_finger_not_affected_by_2nd_finger_taps'
116FAT_FINGER_MOVE_WITH_RESTING_FINGER = 'fat_finger_move_with_resting_finger'
117DRAG_EDGE_THUMB = 'drag_edge_thumb'
118TWO_CLOSE_FINGERS_TRACKING = 'two_close_fingers_tracking'
119RESTING_FINGER_PLUS_2ND_FINGER_MOVE = 'resting_finger_plus_2nd_finger_move'
120TWO_FAT_FINGERS_TRACKING = 'two_fat_fingers_tracking'
121FIRST_FINGER_TRACKING_AND_SECOND_FINGER_TAPS = \
122        'first_finger_tracking_and_second_finger_taps'
123DRUMROLL = 'drumroll'
124RAPID_TAPS = 'rapid_taps_20'
125ONE_FINGER_TRACKING_FROM_CENTER = 'one_finger_tracking_from_center'
126DRAG_LATENCY = 'drag_latency'
127# This following gesture is for pressure calibration.
128PRESSURE_CALIBRATION = 'pressure_calibration'
129
130# The gaps in MM required between fingertips for these tests
131FINGER_CROSSING_GAP_MM = 1
132FAT_FINGER_AND_STATIONARY_FINGER_GAP_MM = 1
133
134# This denotes the list of the numbers of fingers for physical click tests.
135# It corresponds to ONE/TWO/THREE/FOUR/FIVE_FINGER_PHYSICAL_CLICK defined above.
136fingers_physical_click = [1, 2, 3, 4, 5]
137
138
139# Define the complete list
140gesture_names_complete = {
141    DEV.TOUCHPAD: [
142        NOISE_LINE,
143        NOISE_STATIONARY,
144        ONE_FINGER_TRACKING,
145        ONE_FINGER_TO_EDGE,
146        TWO_FINGER_TRACKING,
147        FINGER_CROSSING,
148        ONE_FINGER_SWIPE,
149        ONE_FINGER_TRACKING_FROM_CENTER,
150        TWO_FINGER_SWIPE,
151        PINCH_TO_ZOOM,
152        ONE_FINGER_TAP,
153        TWO_FINGER_TAP,
154        ONE_FINGER_PHYSICAL_CLICK,
155        TWO_FINGER_PHYSICAL_CLICK,
156        THREE_FINGER_PHYSICAL_CLICK,
157        FOUR_FINGER_PHYSICAL_CLICK,
158        FIVE_FINGER_PHYSICAL_CLICK,
159        STATIONARY_FINGER_NOT_AFFECTED_BY_2ND_FINGER_TAPS,
160        FAT_FINGER_MOVE_WITH_RESTING_FINGER,
161        DRAG_EDGE_THUMB,
162        TWO_CLOSE_FINGERS_TRACKING,
163        RESTING_FINGER_PLUS_2ND_FINGER_MOVE,
164        TWO_FAT_FINGERS_TRACKING,
165        FIRST_FINGER_TRACKING_AND_SECOND_FINGER_TAPS,
166        DRUMROLL,
167        RAPID_TAPS,
168        DRAG_LATENCY,
169    ],
170    DEV.TOUCHSCREEN: [
171        NOISE_LINE,
172        NOISE_STATIONARY,
173        ONE_FINGER_TRACKING,
174        ONE_FINGER_TO_EDGE,
175        TWO_FINGER_TRACKING,
176        FINGER_CROSSING,
177        ONE_FINGER_SWIPE,
178        ONE_FINGER_TRACKING_FROM_CENTER,
179        TWO_FINGER_SWIPE,
180        PINCH_TO_ZOOM,
181        ONE_FINGER_TAP,
182        TWO_FINGER_TAP,
183        STATIONARY_FINGER_NOT_AFFECTED_BY_2ND_FINGER_TAPS,
184        FAT_FINGER_MOVE_WITH_RESTING_FINGER,
185        DRAG_EDGE_THUMB,
186        TWO_CLOSE_FINGERS_TRACKING,
187        RESTING_FINGER_PLUS_2ND_FINGER_MOVE,
188        TWO_FAT_FINGERS_TRACKING,
189        FIRST_FINGER_TRACKING_AND_SECOND_FINGER_TAPS,
190        DRUMROLL,
191        RAPID_TAPS,
192        DRAG_LATENCY,
193    ],
194}
195
196
197# Define what gestures the robot can perform.
198# This also defines the order for the robot to perform the gestures.
199# Basically, two-fingers gestures follow one-finger gestures.
200robot_capability_list = [
201    NOISE_LINE,
202    NOISE_STATIONARY,
203    ONE_FINGER_TRACKING,
204    ONE_FINGER_TO_EDGE,
205    ONE_FINGER_SWIPE,
206    ONE_FINGER_TRACKING_FROM_CENTER,
207    ONE_FINGER_TAP,
208    RAPID_TAPS,
209    TWO_FINGER_TRACKING,
210    TWO_CLOSE_FINGERS_TRACKING,
211    TWO_FINGER_SWIPE,
212    TWO_FINGER_TAP,
213    STATIONARY_FINGER_NOT_AFFECTED_BY_2ND_FINGER_TAPS,
214    FIRST_FINGER_TRACKING_AND_SECOND_FINGER_TAPS,
215    RESTING_FINGER_PLUS_2ND_FINGER_MOVE,
216    FINGER_CROSSING,
217    PINCH_TO_ZOOM,
218    DRUMROLL,
219    TWO_FAT_FINGERS_TRACKING,
220    FAT_FINGER_MOVE_WITH_RESTING_FINGER,
221    ONE_FINGER_PHYSICAL_CLICK,
222    TWO_FINGER_PHYSICAL_CLICK,
223    THREE_FINGER_PHYSICAL_CLICK,
224    FOUR_FINGER_PHYSICAL_CLICK,
225]
226
227NO_FINGER = None
228TINY_FINGER = 0
229NORMAL_FINGER = 1
230LARGE_FINGER = 2
231FAT_FINGER = 3
232ALL_FINGERTIP_SIZES = [TINY_FINGER, NORMAL_FINGER, LARGE_FINGER, FAT_FINGER]
233FINGERTIP_DIAMETER_MM = {TINY_FINGER: 8, NORMAL_FINGER: 10,
234                         LARGE_FINGER: 12, FAT_FINGER: 14}
235
236custom_tips_required = {
237    DRAG_LATENCY: [NO_FINGER, NO_FINGER, FAT_FINGER, NO_FINGER],
238    ONE_FINGER_PHYSICAL_CLICK: [NORMAL_FINGER, NO_FINGER, NO_FINGER, NO_FINGER],
239    TWO_FINGER_PHYSICAL_CLICK: [NO_FINGER, NORMAL_FINGER, NO_FINGER,
240                                NORMAL_FINGER],
241    THREE_FINGER_PHYSICAL_CLICK: [NO_FINGER, NORMAL_FINGER, NORMAL_FINGER,
242                                  NORMAL_FINGER],
243    TWO_FAT_FINGERS_TRACKING: [FAT_FINGER, FAT_FINGER, FAT_FINGER, FAT_FINGER],
244    FAT_FINGER_MOVE_WITH_RESTING_FINGER: [NORMAL_FINGER, NO_FINGER,
245                                          FAT_FINGER, NO_FINGER],
246    FINGER_CROSSING: [NORMAL_FINGER, NO_FINGER, NORMAL_FINGER, NO_FINGER],
247    NOISE_LINE: [NO_FINGER, NORMAL_FINGER, NO_FINGER, NO_FINGER],
248    NOISE_STATIONARY: [NORMAL_FINGER, NO_FINGER, NO_FINGER, NO_FINGER],
249    NOISE_STATIONARY_EXTENDED: [NORMAL_FINGER, NO_FINGER, NO_FINGER, NO_FINGER],
250}
251default_tips_required = [NORMAL_FINGER, NORMAL_FINGER,
252                         NORMAL_FINGER, NORMAL_FINGER]
253finger_tips_required = defaultdict(lambda:default_tips_required,
254                                   custom_tips_required)
255
256def get_gesture_names_for_robot(device):
257    """Get the gesture names that a robot can do for a specified device."""
258    return [gesture for gesture in robot_capability_list
259                    if gesture in gesture_names_complete[device]]
260
261
262# Define the list of one-finger and two-finger gestures to test using the robot.
263gesture_names_robot = {
264    DEV.TOUCHPAD: get_gesture_names_for_robot(DEV.TOUCHPAD),
265    DEV.TOUCHSCREEN: get_gesture_names_for_robot(DEV.TOUCHSCREEN),
266}
267
268gesture_names_quickstep = [DRAG_LATENCY]
269
270# Define the list of gestures that require equipment our vendors may not have.
271gesture_names_equipment_required = [NOISE_LINE, NOISE_STATIONARY,
272                                    NOISE_STATIONARY_EXTENDED]
273
274# Define the list of gestures to test in NOISE mode.
275gesture_names_noise_extended = [NOISE_STATIONARY_EXTENDED]
276
277# Define the manual list which is gesture_names_complete - gesture_names_robot - gesture_names_equipment_required
278gesture_names_manual = {}
279for dev in DEV.DEVICE_TYPE_LIST:
280    complete_gesture_list = gesture_names_complete[dev]
281    manual_set = set(complete_gesture_list) - set(gesture_names_robot[dev])
282    gesture_names_manual[dev] = [gesture for gesture in complete_gesture_list
283                                 if gesture in manual_set
284                                 and gesture not in gesture_names_equipment_required]
285
286
287# Define the gesture for pressure calibration
288gesture_names_calibration = [PRESSURE_CALIBRATION,]
289
290# Define the relative segment weights of a validator.
291# For example, LinearityMiddleValidator : LinearityBothEndsValidator = 7 : 3
292segment_weights = {VAL.BEGIN: 0.15,
293                   VAL.MIDDLE: 0.7,
294                   VAL.END: 0.15,
295                   VAL.BOTH_ENDS: 0.15 + 0.15,
296                   VAL.WHOLE: 0.15 + 0.7 + 0.15,
297}
298
299
300# Define the validator score weights
301weight_rare = 1
302weight_common = 2
303weight_critical = 3
304validator_weights = {'CountPacketsValidator': weight_common,
305                     'CountTrackingIDNormalFingerValidator': weight_critical,
306                     'CountTrackingIDFatFingerValidator': weight_rare,
307                     'DragLatencyValidator': weight_critical,
308                     'DrumrollValidator': weight_rare,
309                     'LinearityNormalFingerValidator': weight_common,
310                     'LinearityFatFingerValidator': weight_rare,
311                     'NoGapValidator': weight_common,
312                     'NoReversedMotionValidator': weight_common,
313                     'PhysicalClickValidator': weight_critical,
314                     'PinchValidator': weight_common,
315                     'RangeValidator': weight_common,
316                     'ReportRateValidator': weight_common,
317                     'HysteresisValidator': weight_common,
318                     'StationaryFingerValidator': weight_common,
319                     'StationaryTapValidator': weight_common,
320}
321
322
323# Define the gesture list that the user needs to perform in the test suite.
324def get_gesture_dict():
325    """Define the dictionary for all gestures."""
326    gesture_dict = {
327        NOISE_STATIONARY:
328        Gesture(
329            name=NOISE_STATIONARY,
330            variations=((GV.LOW_FREQUENCY, GV.MED_FREQUENCY, GV.HIGH_FREQUENCY),
331                        (GV.HALF_AMPLITUDE, GV.MAX_AMPLITUDE),
332                        (GV.SQUARE_WAVE,),
333                        (GV.TL, GV.TR, GV.BL, GV.BR, GV.TS, GV.BS, GV.LS, GV.RS,
334                         GV.CENTER),
335            ),
336            prompt='Hold one finger on the {3} of the touch surface with a {0} {1} {2} in noise.',
337            subprompt={
338                GV.TL: ('top left corner',),
339                GV.TR: ('top right corner',),
340                GV.BL: ('bottom left corner',),
341                GV.BR: ('bottom right corner',),
342                GV.TS: ('top edge',),
343                GV.BS: ('bottom side',),
344                GV.LS: ('left hand side',),
345                GV.RS: ('right hand side',),
346                GV.CENTER: ('center',),
347                GV.LOW_FREQUENCY: ('5kHz',),
348                GV.MED_FREQUENCY: ('500kHz',),
349                GV.HIGH_FREQUENCY: ('1MHz',),
350                GV.HALF_AMPLITUDE: ('10Vpp',),
351                GV.MAX_AMPLITUDE: ('20Vpp',),
352                GV.SQUARE_WAVE: ('square wave',),
353            },
354            validators=(
355                CountTrackingIDNormalFingerValidator('== 1'),
356                StationaryTapValidator(stationary_tap_criteria, slot=0),
357            ),
358        ),
359        NOISE_LINE:
360        Gesture(
361            name=NOISE_LINE,
362            variations=((GV.LOW_FREQUENCY, GV.MED_FREQUENCY, GV.HIGH_FREQUENCY),
363                        (GV.HALF_AMPLITUDE, GV.MAX_AMPLITUDE),
364                        (GV.SQUARE_WAVE,),
365                        (GV.BLTR,),
366                        (GV.NORMAL,),
367            ),
368            prompt='Draw a straight line from {3} with a {0} {1} {2} in noise.',
369            subprompt={
370                GV.LOW_FREQUENCY: ('5kHz',),
371                GV.MED_FREQUENCY: ('500kHz',),
372                GV.HIGH_FREQUENCY: ('1MHz',),
373                GV.HALF_AMPLITUDE: ('10Vpp',),
374                GV.MAX_AMPLITUDE: ('20Vpp',),
375                GV.SQUARE_WAVE: ('square wave',),
376                GV.NORMAL: ('',),
377                GV.BLTR: ('bottom left to top right',),
378            },
379            validators=(
380                CountTrackingIDNormalFingerValidator('== 1'),
381                LinearityNormalFingerValidator(linearity_criteria, finger=0,
382                                               segments=VAL.MIDDLE),
383                NoGapValidator(no_gap_criteria, slot=0),
384                NoReversedMotionValidator(no_reversed_motion_criteria, slots=0,
385                                          segments=VAL.MIDDLE),
386                NoReversedMotionValidator(no_reversed_motion_criteria, slots=0,
387                                          segments=VAL.BOTH_ENDS),
388                ReportRateValidator(report_rate_criteria),
389            ),
390        ),
391        NOISE_STATIONARY_EXTENDED:
392        Gesture(
393            name=NOISE_STATIONARY_EXTENDED,
394            variations=(tuple(GV.EXTENDED_FREQUENCIES),
395                        (GV.MAX_AMPLITUDE,),
396                        (GV.SQUARE_WAVE,),
397                        (GV.CENTER,),
398            ),
399            prompt='Hold one finger on the {3} of the touch surface with a {0} {1} {2} in noise.',
400            subprompt=dict({
401                GV.CENTER: ('center',),
402                GV.MAX_AMPLITUDE: ('20Vpp',),
403                GV.SQUARE_WAVE: ('square wave',),
404            }.items() + {freq: (freq,) for freq in GV.EXTENDED_FREQUENCIES}.items()),
405            validators=(
406                CountTrackingIDNormalFingerValidator('== 1'),
407                StationaryTapValidator(stationary_tap_criteria, slot=0),
408            ),
409        ),
410        ONE_FINGER_TRACKING:
411        Gesture(
412            name=ONE_FINGER_TRACKING,
413            variations=((GV.LR, GV.RL, GV.TB, GV.BT, GV.BLTR, GV.TRBL),
414                        (GV.SLOW, GV.NORMAL),
415            ),
416            prompt='Take {2} to draw a straight, {0} line {1} using a ruler.',
417            subprompt={
418                GV.LR: ('horizontal', 'from left to right',),
419                GV.RL: ('horizontal', 'from right to left',),
420                GV.TB: ('vertical', 'from top to bottom',),
421                GV.BT: ('vertical', 'from bottom to top',),
422                GV.BLTR: ('diagonal', 'from bottom left to top right',),
423                GV.TRBL: ('diagonal', 'from top right to bottom left',),
424                GV.SLOW: ('3 seconds',),
425                GV.NORMAL: ('1 second',),
426            },
427            validators=(
428                CountTrackingIDNormalFingerValidator('== 1'),
429                LinearityNormalFingerValidator(linearity_criteria, finger=0,
430                                               segments=VAL.MIDDLE),
431                NoGapValidator(no_gap_criteria, slot=0),
432                NoReversedMotionValidator(no_reversed_motion_criteria, slots=0,
433                                          segments=VAL.MIDDLE),
434                NoReversedMotionValidator(no_reversed_motion_criteria, slots=0,
435                                          segments=VAL.BOTH_ENDS),
436                ReportRateValidator(report_rate_criteria),
437            ),
438        ),
439
440        ONE_FINGER_TO_EDGE:
441        Gesture(
442            name=ONE_FINGER_TO_EDGE,
443            variations=((GV.CL, GV.CR, GV.CT, GV.CB),
444                        (GV.SLOW,),
445            ),
446            prompt='Take {2} to draw a striaght {0} line {1}.',
447            subprompt={
448                GV.CL: ('horizontal', 'from the center off left edge',),
449                GV.CR: ('horizontal', 'from the center off right edge',),
450                GV.CT: ('vertical', 'from the center  off top edge',),
451                GV.CB: ('vertical', 'from the center off bottom edge',),
452                GV.SLOW: ('2 seconds',),
453            },
454            validators=(
455                CountTrackingIDNormalFingerValidator('== 1'),
456                LinearityNormalFingerValidator(linearity_criteria, finger=0,
457                                               segments=VAL.MIDDLE),
458                NoGapValidator(no_gap_criteria, slot=0),
459                NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
460                RangeValidator(range_criteria),
461                ReportRateValidator(report_rate_criteria),
462            ),
463        ),
464
465        TWO_FINGER_TRACKING:
466        Gesture(
467            name=TWO_FINGER_TRACKING,
468            variations=((GV.LR, GV.RL, GV.TB, GV.BT, GV.BLTR, GV.TRBL),
469                        (GV.SLOW, GV.NORMAL),
470            ),
471            prompt='Take {2} to draw a {0} line {1} using a ruler '
472                   'with TWO fingers at the same time.',
473            subprompt={
474                GV.LR: ('horizontal', 'from left to right',),
475                GV.RL: ('horizontal', 'from right to left',),
476                GV.TB: ('vertical', 'from top to bottom',),
477                GV.BT: ('vertical', 'from bottom to top',),
478                GV.BLTR: ('diagonal', 'from bottom left to top right',),
479                GV.TRBL: ('diagonal', 'from top right to bottom left',),
480                GV.SLOW: ('3 seconds',),
481                GV.NORMAL: ('1 second',),
482            },
483            validators=(
484                CountTrackingIDNormalFingerValidator('== 2'),
485                LinearityNormalFingerValidator(linearity_criteria, finger=0,
486                                               segments=VAL.MIDDLE),
487                LinearityNormalFingerValidator(linearity_criteria, finger=1,
488                                               segments=VAL.MIDDLE),
489                NoGapValidator(no_gap_criteria, slot=0),
490                NoGapValidator(no_gap_criteria, slot=1),
491                NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
492                NoReversedMotionValidator(no_reversed_motion_criteria, slots=1),
493                ReportRateValidator(report_rate_criteria),
494            ),
495        ),
496
497        FINGER_CROSSING:
498        Gesture(
499            # also covers stationary_finger_not_affected_by_2nd_moving_finger
500            name=FINGER_CROSSING,
501            variations=((GV.LR, GV.RL, GV.TB, GV.BT, GV.BLTR, GV.TRBL),
502                        (GV.SLOW, GV.NORMAL),
503            ),
504            prompt='Place one stationary finger near the center of the '
505                   'touch surface, then take {2} to draw a straight line '
506                   '{0} {1} with a second finger',
507            subprompt={
508                GV.LR: ('from left to right', 'above the stationary finger'),
509                GV.RL: ('from right to left', 'below the stationary finger'),
510                GV.TB: ('from top to bottom',
511                        'on the right to the stationary finger'),
512                GV.BT: ('from bottom to top',
513                        'on the left to the stationary finger'),
514                GV.BLTR: ('from the bottom left to the top right',
515                          'above the stationary finger',),
516                GV.TRBL: ('from the top right to the bottom left',
517                          'below the stationary finger'),
518                GV.SLOW: ('3 seconds',),
519                GV.NORMAL: ('1 second',),
520            },
521            validators=(
522                CountTrackingIDNormalFingerValidator('== 2'),
523                NoGapValidator(no_gap_criteria, slot=1),
524                NoReversedMotionValidator(no_reversed_motion_criteria, slots=1),
525                ReportRateValidator(report_rate_criteria, finger=1),
526                StationaryFingerValidator(stationary_finger_criteria, slot=0),
527            ),
528        ),
529
530        ONE_FINGER_SWIPE:
531        Gesture(
532            name=ONE_FINGER_SWIPE,
533            variations=(GV.BLTR, GV.TRBL),
534            prompt='Use ONE finger to quickly swipe {0}.',
535            subprompt={
536                GV.BLTR: ('from the bottom left to the top right',),
537                GV.TRBL: ('from the top right to the bottom left',),
538            },
539            validators=(
540                CountPacketsValidator(count_packets_criteria, slot=0),
541                CountTrackingIDNormalFingerValidator('== 1'),
542                NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
543                ReportRateValidator(report_rate_criteria),
544            ),
545        ),
546
547        TWO_FINGER_SWIPE:
548        Gesture(
549            name=TWO_FINGER_SWIPE,
550            variations=(GV.TB, GV.BT),
551            prompt='Use TWO fingers to quickly swipe {0}.',
552            subprompt={
553                GV.TB: ('from top to bottom',),
554                GV.BT: ('from bottom to top',),
555            },
556            validators=(
557                CountPacketsValidator(count_packets_criteria, slot=0),
558                CountPacketsValidator(count_packets_criteria, slot=1),
559                CountTrackingIDNormalFingerValidator('== 2'),
560                NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
561                NoReversedMotionValidator(no_reversed_motion_criteria, slots=1),
562                ReportRateValidator(report_rate_criteria),
563            ),
564        ),
565
566        PINCH_TO_ZOOM:
567        Gesture(
568            name=PINCH_TO_ZOOM,
569            variations=(GV.ZOOM_IN, GV.ZOOM_OUT),
570            prompt='Using two fingers, preform a "{0}" pinch by bringing'
571                   'your fingers {1}.',
572            subprompt={
573                GV.ZOOM_IN: ('zoom in', 'farther apart'),
574                GV.ZOOM_OUT: ('zoom out', 'closer together'),
575            },
576            validators=(
577                CountTrackingIDNormalFingerValidator('== 2'),
578                PinchValidator(pinch_criteria),
579                ReportRateValidator(report_rate_criteria),
580            ),
581        ),
582
583        ONE_FINGER_TAP:
584        Gesture(
585            name=ONE_FINGER_TAP,
586            variations=(GV.TL, GV.TR, GV.BL, GV.BR, GV.TS, GV.BS, GV.LS, GV.RS,
587                        GV.CENTER),
588            prompt='Use one finger to tap on the {0} of the touch surface.',
589            subprompt={
590                GV.TL: ('top left corner',),
591                GV.TR: ('top right corner',),
592                GV.BL: ('bottom left corner',),
593                GV.BR: ('bottom right corner',),
594                GV.TS: ('top edge',),
595                GV.BS: ('bottom side',),
596                GV.LS: ('left hand side',),
597                GV.RS: ('right hand side',),
598                GV.CENTER: ('center',),
599            },
600            validators=(
601                CountTrackingIDNormalFingerValidator('== 1'),
602                StationaryTapValidator(stationary_tap_criteria, slot=0),
603            ),
604        ),
605
606        TWO_FINGER_TAP:
607        Gesture(
608            name=TWO_FINGER_TAP,
609            variations=(GV.HORIZONTAL, GV.VERTICAL, GV.DIAGONAL),
610            prompt='Use two fingers aligned {0} to tap the center of the '
611                   'touch surface.',
612            subprompt={
613                GV.HORIZONTAL: ('horizontally',),
614                GV.VERTICAL: ('vertically',),
615                GV.DIAGONAL: ('diagonally',),
616            },
617            validators=(
618                CountTrackingIDNormalFingerValidator('== 2'),
619                StationaryTapValidator(stationary_tap_criteria, slot=0),
620                StationaryTapValidator(stationary_tap_criteria, slot=1),
621            ),
622        ),
623
624        ONE_FINGER_PHYSICAL_CLICK:
625        Gesture(
626            name=ONE_FINGER_PHYSICAL_CLICK,
627            variations=(GV.CENTER, GV.BL, GV.BS, GV.BR),
628            prompt='Use one finger to physically click the {0} of the '
629                   'touch surface.',
630            subprompt={
631                GV.CENTER: ('center',),
632                GV.BL: ('bottom left corner',),
633                GV.BS: ('bottom side',),
634                GV.BR: ('bottom right corner',),
635            },
636            validators=(
637                CountTrackingIDNormalFingerValidator('== 1'),
638                PhysicalClickValidator('== 1', fingers=1),
639                StationaryTapValidator(stationary_tap_criteria, slot=0),
640            ),
641        ),
642
643        TWO_FINGER_PHYSICAL_CLICK:
644        Gesture(
645            name=TWO_FINGER_PHYSICAL_CLICK,
646            variations=None,
647            prompt='Use two fingers physically click the center of the '
648                   'touch surface.',
649            subprompt=None,
650            validators=(
651                CountTrackingIDNormalFingerValidator('== 2'),
652                PhysicalClickValidator('== 1', fingers=2),
653                StationaryTapValidator(stationary_tap_criteria, slot=0),
654                StationaryTapValidator(stationary_tap_criteria, slot=1),
655            ),
656        ),
657
658        THREE_FINGER_PHYSICAL_CLICK:
659        Gesture(
660            name=THREE_FINGER_PHYSICAL_CLICK,
661            variations=None,
662            prompt='Use three fingers to physically click '
663                   'the center of the touch surface.',
664            subprompt=None,
665            validators=(
666                CountTrackingIDNormalFingerValidator('== 3'),
667                PhysicalClickValidator('== 1', fingers=3),
668            ),
669        ),
670
671        FOUR_FINGER_PHYSICAL_CLICK:
672        Gesture(
673            name=FOUR_FINGER_PHYSICAL_CLICK,
674            variations=None,
675            prompt='Use four fingers to physically click '
676                   'the center of the touch surface.',
677            subprompt=None,
678            validators=(
679                CountTrackingIDNormalFingerValidator('== 4'),
680                PhysicalClickValidator('== 1', fingers=4),
681            ),
682        ),
683
684        FIVE_FINGER_PHYSICAL_CLICK:
685        Gesture(
686            name=FIVE_FINGER_PHYSICAL_CLICK,
687            variations=None,
688            prompt='Use five fingers to physically click '
689                   'the center of the touch surface.',
690            subprompt=None,
691            validators=(
692                CountTrackingIDNormalFingerValidator('== 5'),
693                PhysicalClickValidator('== 1', fingers=5),
694            ),
695        ),
696
697        STATIONARY_FINGER_NOT_AFFECTED_BY_2ND_FINGER_TAPS:
698        Gesture(
699            name=STATIONARY_FINGER_NOT_AFFECTED_BY_2ND_FINGER_TAPS,
700            variations=(GV.AROUND,),
701            prompt='Place your one stationary finger in the middle of the '
702                   'touch surface, and use a second finger to tap '
703                   'all around it many times (50)',
704            subprompt=None,
705            validators=(
706                CountTrackingIDNormalFingerValidator('>= 25'),
707                StationaryFingerValidator(stationary_finger_criteria, slot=0),
708            ),
709        ),
710
711        FAT_FINGER_MOVE_WITH_RESTING_FINGER:
712        Gesture(
713            name=FAT_FINGER_MOVE_WITH_RESTING_FINGER,
714            variations=(GV.LR, GV.RL, GV.TB, GV.BT),
715            prompt='With a stationary finger on the {0} of the touch surface, '
716                   'draw a straight line with a FAT finger {1} {2} it.',
717            subprompt={
718                GV.LR: ('center', 'from left to right', 'below'),
719                GV.RL: ('bottom edge', 'from right to left', 'above'),
720                GV.TB: ('center', 'from top to bottom', 'on the right to'),
721                GV.BT: ('center', 'from bottom to top', 'on the left to'),
722            },
723            validators=(
724                CountTrackingIDFatFingerValidator('== 2'),
725                LinearityFatFingerValidator(relaxed_linearity_criteria,
726                                            finger=1, segments=VAL.MIDDLE),
727                NoGapValidator(no_gap_criteria, slot=1),
728                NoReversedMotionValidator(no_reversed_motion_criteria, slots=1),
729                ReportRateValidator(report_rate_criteria, finger=1),
730                StationaryFingerValidator(stationary_finger_criteria, slot=0),
731            ),
732        ),
733
734        DRAG_EDGE_THUMB:
735        Gesture(
736            name=DRAG_EDGE_THUMB,
737            variations=(GV.LR, GV.RL, GV.TB, GV.BT),
738            prompt='Drag the edge of your thumb {0} in a straight line '
739                   'across the touch surface',
740            subprompt={
741                GV.LR: ('horizontally from left to right',),
742                GV.RL: ('horizontally from right to left',),
743                GV.TB: ('vertically from top to bottom',),
744                GV.BT: ('vertically from bottom to top',),
745            },
746            validators=(
747                CountTrackingIDFatFingerValidator('== 1'),
748                LinearityFatFingerValidator(relaxed_linearity_criteria,
749                                            finger=0, segments=VAL.MIDDLE),
750                NoGapValidator(no_gap_criteria, slot=0),
751                NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
752                ReportRateValidator(report_rate_criteria),
753            ),
754        ),
755
756        TWO_CLOSE_FINGERS_TRACKING:
757        Gesture(
758            name=TWO_CLOSE_FINGERS_TRACKING,
759            variations=(GV.LR, GV.TB, GV.TLBR),
760            prompt='With two fingers close together (lightly touching each '
761                   'other) in a two finger scrolling gesture, draw a {0} '
762                   'line {1}.',
763            subprompt={
764                GV.LR: ('horizontal', 'from left to right',),
765                GV.TB: ('vertical', 'from top to bottom',),
766                GV.TLBR: ('diagonal', 'from the top left to the bottom right',),
767            },
768            validators=(
769                CountTrackingIDFatFingerValidator('== 2'),
770                LinearityFatFingerValidator(relaxed_linearity_criteria,
771                                            finger=0, segments=VAL.MIDDLE),
772                LinearityFatFingerValidator(relaxed_linearity_criteria,
773                                            finger=1, segments=VAL.MIDDLE),
774                NoGapValidator(no_gap_criteria, slot=0),
775                NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
776                ReportRateValidator(report_rate_criteria),
777            ),
778        ),
779
780        RESTING_FINGER_PLUS_2ND_FINGER_MOVE:
781        Gesture(
782            name=RESTING_FINGER_PLUS_2ND_FINGER_MOVE,
783            variations=((GV.TLBR, GV.BRTL),
784                        (GV.SLOW,),
785            ),
786            prompt='With a stationary finger in the bottom left corner, take '
787                   '{1} to draw a straight line {0} with a second finger.',
788            subprompt={
789                GV.TLBR: ('from the top left to the bottom right',),
790                GV.BRTL: ('from the bottom right to the top left',),
791                GV.SLOW: ('3 seconds',),
792            },
793            validators=(
794                CountTrackingIDNormalFingerValidator('== 2'),
795                LinearityFatFingerValidator(relaxed_linearity_criteria,
796                                            finger=1, segments=VAL.MIDDLE),
797                NoGapValidator(no_gap_criteria, slot=1),
798                NoReversedMotionValidator(no_reversed_motion_criteria, slots=1),
799                ReportRateValidator(report_rate_criteria, finger=1),
800                StationaryFingerValidator(stationary_finger_criteria, slot=0),
801            ),
802        ),
803
804        TWO_FAT_FINGERS_TRACKING:
805        Gesture(
806            name=TWO_FAT_FINGERS_TRACKING,
807            variations=(GV.LR, GV.RL),
808            prompt='Use two FAT fingers separated by about 1cm to draw '
809                   'a straight line {0}.',
810            subprompt={
811                GV.LR: ('from left to right',),
812                GV.RL: ('from right to left',),
813            },
814            validators=(
815                CountTrackingIDFatFingerValidator('== 2'),
816                LinearityFatFingerValidator(relaxed_linearity_criteria,
817                                            finger=0, segments=VAL.MIDDLE),
818                LinearityFatFingerValidator(relaxed_linearity_criteria,
819                                            finger=1, segments=VAL.MIDDLE),
820                NoGapValidator(no_gap_criteria, slot=0),
821                NoGapValidator(no_gap_criteria, slot=1),
822                NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
823                NoReversedMotionValidator(no_reversed_motion_criteria, slots=1),
824                ReportRateValidator(report_rate_criteria),
825            ),
826        ),
827
828        FIRST_FINGER_TRACKING_AND_SECOND_FINGER_TAPS:
829        Gesture(
830            name=FIRST_FINGER_TRACKING_AND_SECOND_FINGER_TAPS,
831            variations=(GV.TLBR, GV.BRTL),
832            prompt='While drawing a straight line {0} slowly (~3 seconds), '
833                   'tap the bottom left corner with a second finger '
834                   'gently 3 times.',
835            subprompt={
836                GV.TLBR: ('from top left to bottom right',),
837                GV.BRTL: ('from bottom right to top left',),
838            },
839            validators=(
840                CountTrackingIDNormalFingerValidator('== 4'),
841                LinearityFatFingerValidator(relaxed_linearity_criteria,
842                                            finger=0, segments=VAL.MIDDLE),
843                NoGapValidator(no_gap_criteria, slot=0),
844                NoReversedMotionValidator(no_reversed_motion_criteria, slots=0),
845                ReportRateValidator(report_rate_criteria),
846            ),
847        ),
848
849        DRUMROLL:
850        Gesture(
851            name=DRUMROLL,
852            variations=(GV.FAST, ),
853            prompt='Use the index and middle finger of one hand to make a '
854                   '"drum roll" {0} by alternately tapping each finger '
855                   'for 5 seconds.',
856            subprompt={
857                GV.FAST: ('as fast as possible',),
858            },
859            validators=(
860                CountTrackingIDNormalFingerValidator('>= 5'),
861                DrumrollValidator(drumroll_criteria),
862            ),
863            timeout = 2000,
864        ),
865
866        RAPID_TAPS:
867        Gesture(
868            name=RAPID_TAPS,
869            variations=(GV.TL, GV.BR, GV.CENTER),
870            prompt='Tap the {0} of the touch surface 20 times quickly',
871            subprompt={
872                GV.TL: ('top left corner',),
873                GV.TS: ('top edge',),
874                GV.TR: ('top right corner',),
875                GV.LS: ('left edge',),
876                GV.CENTER: ('center',),
877                GV.RS: ('right edge',),
878                GV.BL: ('bottom left corner',),
879                GV.BS: ('bottom edge',),
880                GV.BR: ('bottom right corner',),
881            },
882            validators=(
883                CountTrackingIDNormalFingerValidator('== 20'),
884            ),
885            timeout = 2000,
886        ),
887
888        ONE_FINGER_TRACKING_FROM_CENTER:
889        Gesture(
890            name=ONE_FINGER_TRACKING_FROM_CENTER,
891            variations=((GV.CR, GV.CT, GV.CUL, GV.CLL),
892                        (GV.SLOW, GV.NORMAL),
893            ),
894            prompt='Place a stationary finger on the center of the touch '
895                   'surface for about 1 second, and then take {2} to draw a '
896                   '{0} line {1}.',
897            subprompt={
898                GV.CR: ('horizontal', 'to the right',),
899                GV.CT: ('vertical', 'to the top',),
900                GV.CUL: ('diagonal', 'to the upper left',),
901                GV.CLL: ('diagonal', 'to the lower left',),
902                GV.SLOW: ('2 seconds',),
903                GV.NORMAL: ('1 second',),
904            },
905            validators=(
906                HysteresisValidator(hysteresis_criteria, finger=0),
907            ),
908        ),
909
910        DRAG_LATENCY:
911        Gesture(
912            name=DRAG_LATENCY,
913            variations=None,
914            prompt='Run one finger back and forth across the pad making sure '
915                   'to break the laser completely on each pass.  Make at least '
916                   'twenty passes.',
917            subprompt=None,
918            validators=(
919                CountTrackingIDNormalFingerValidator('== 1'),
920                DragLatencyValidator(drag_latency_criteria),
921            ),
922        ),
923
924        PRESSURE_CALIBRATION:
925        Gesture(
926            name=PRESSURE_CALIBRATION,
927            variations=(GV.SIZE0, GV.SIZE1, GV.SIZE2, GV.SIZE3, GV.SIZE4,
928                        GV.SIZE5, GV.SIZE6, ),
929            prompt='Draw circles continuously for 5 seconds '
930                   'using the metal finger of size {0}.',
931            subprompt={
932                GV.SIZE0: ('0 (the smallest size)',),
933                GV.SIZE1: ('1',),
934                GV.SIZE2: ('2',),
935                GV.SIZE3: ('3',),
936                GV.SIZE4: ('4',),
937                GV.SIZE5: ('5',),
938                GV.SIZE6: ('6 (the largest size)',),
939            },
940            validators=(
941                CountTrackingIDNormalFingerValidator('== 1'),
942            ),
943        ),
944    }
945    return gesture_dict
946
947
948class FileName:
949    """A dummy class to hold the attributes in a test file name."""
950    pass
951filename = FileName()
952filename.sep = '-'
953filename.ext = 'dat'
954
955
956class Gesture:
957    """A class defines the structure of Gesture."""
958    # define the default timeout (in milli-seconds) when performing a gesture.
959    # A gesture is considered done when finger is lifted for this time interval.
960    TIMEOUT = int(1000/80*10)
961
962    def __init__(self, name=None, variations=None, prompt=None, subprompt=None,
963                 validators=None, timeout=TIMEOUT):
964        self.name = name
965        self.variations = variations
966        self.prompt = prompt
967        self.subprompt = subprompt
968        self.validators = validators
969        self.timeout = timeout
970