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