File Coverage

blib/lib/Gesture/Simple/Template.pm
Criterion Covered Total %
statement 66 66 100.0
branch 4 4 100.0
condition n/a
subroutine 17 17 100.0
pod 0 5 0.0
total 87 92 94.5


line stmt bran cond sub pod time code
1             package Gesture::Simple::Template;
2 1     1   6 use Any::Moose;
  1         1  
  1         6  
3             extends 'Gesture::Simple::Gesture';
4 1     1   1477 use Scalar::Defer qw/defer force/;
  1         19343  
  1         10  
5              
6 1     1   764 use Gesture::Simple::Match;
  1         2  
  1         37  
7              
8 1     1   10 use constant match_class => 'Gesture::Simple::Match';
  1         1  
  1         236  
9              
10             has name => (
11             is => 'ro',
12             isa => 'Str',
13             required => 1,
14             );
15              
16             sub match {
17 7     7 0 13 my $self = shift;
18 7         13 my $gesture = shift;
19              
20 7         22 my $raw_score = $self->score_match($gesture);
21              
22 7         933 return $self->match_class->new(
23             template => $self,
24             gesture => $gesture,
25             score => $raw_score,
26             );
27             }
28              
29             sub score_match {
30 7     7 0 12 my $self = shift;
31 7         8 my $gesture = shift;
32 7         27 my $distance = $self->distance_at_best_angle($gesture);
33              
34 7         524 my $score = 1 - $distance / (.5 * sqrt(100 ** 2 + 100 ** 2));
35 7         32 return $score * 100;
36             }
37              
38 1     1   6 use constant minimum_angle => -0.785398163; # -45 degrees
  1         2  
  1         57  
39 1     1   5 use constant maximum_angle => 0.785398163; # 45 degrees
  1         2  
  1         47  
40 1     1   5 use constant angle_threshold => 0.034906585; # 2 degrees
  1         2  
  1         486  
41              
42             sub distance_at_best_angle {
43 7     7 0 13 my $self = shift;
44 7         9 my $gesture = shift;
45              
46 7         26 my $theta_a = $self->minimum_angle;
47 7         23 my $theta_b = $self->maximum_angle;
48 7         16 my $threshold = $self->angle_threshold;
49              
50 7         11 my $phi = .61803399; # golden ratio
51              
52 7     88   58 my $x1 = defer { $phi * $theta_a + (1 - $phi) * $theta_b };
  88         654  
53 7     101   392 my $x2 = defer { (1 - $phi) * $theta_a + $phi * $theta_b };
  101         786  
54              
55 7     66   149 my $f1 = defer { $self->distance_at_angle($gesture, force $x1) };
  66         531  
56 7     67   136 my $f2 = defer { $self->distance_at_angle($gesture, force $x2) };
  67         627  
57              
58 7         139 while (abs($theta_b - $theta_a) > $threshold) {
59 56 100       229 if ($f1 < $f2) {
60 34         95 $theta_b = force $x2;
61             }
62             else {
63 22         65 $theta_a = force $x1;
64             }
65             }
66              
67 7 100       28 return $f1 < $f2 ? $f1 : $f2;
68             }
69              
70             sub distance_at_angle {
71 133     133 0 206 my $self = shift;
72 133         135 my $gesture = shift;
73 133         131 my $theta = shift;
74              
75 133         497 my $rotated = $gesture->rotate_by($gesture->points, $theta);
76 133         374 return $self->path_distance($rotated);
77             }
78              
79             sub path_distance {
80 133     133 0 157 my $self = shift;
81 133         146 my $points = shift;
82 133         277 my $template = $self->points;
83              
84 133         140 my $distance = 0;
85              
86 133         318 for (my $i = 0; $i < @$template; ++$i) {
87 8512         20569 my $d = $self->distance($template->[$i], $points->[$i]);
88 8512         19362 $distance += $d;
89             }
90              
91 133         181 $distance /= @$template;
92              
93 133         2022 return $distance;
94             }
95              
96             __PACKAGE__->meta->make_immutable;
97 1     1   7 no Any::Moose;
  1         2  
  1         6  
98              
99             1;
100