File Coverage

blib/lib/Acme/Mobile/Therbligs.pm
Criterion Covered Total %
statement 78 80 97.5
branch 29 36 80.5
condition 19 22 86.3
subroutine 10 10 100.0
pod 2 2 100.0
total 138 150 92.0


line stmt bran cond sub pod time code
1             =head1 NAME
2            
3             Acme::Mobile::Therbligs - count keystrokes to write mobile text messages
4            
5             =head1 SYNOPSIS
6            
7             use Acme::Mobile::Therbligs;
8            
9             $thurbs = count_therbligs("See u l8r");
10            
11             # $thurbs == 23
12            
13             =head1 DESCRIPTION
14            
15             This module counts the number of I used to write mobile
16             text messages. A therblig is unit used to measure the number of
17             actions (in this case keypresses or pauses) for people who like to
18             optimize industrial processes.
19            
20             So you can use this module to determine useless facts such as that it
21             takes as many keypresses to write "later" or "great" as it does "l8r"
22             and "gr8".
23            
24             The current version is case insensitive and assumes (by default) a
25             particular brand of Nokia phone. (I have no idea which model it is; it
26             was cheap, and it works, which is all I care about.)
27            
28             A description of methods is below.
29            
30             =over
31            
32             =cut
33            
34             package Acme::Mobile::Therbligs;
35            
36 1     1   815 use 5.006;
  1         3  
  1         40  
37 1     1   4 use strict;
  1         2  
  1         25  
38 1     1   15 use warnings;
  1         2  
  1         70  
39            
40             our $VERSION = '0.05';
41            
42 1     1   5 use Exporter;
  1         2  
  1         128  
43            
44             our @ISA = qw( Exporter );
45            
46             our @EXPORT = qw( count_therbligs );
47            
48             our %EXPORT_TAGS = (
49             'all' => [ @EXPORT ],
50             );
51            
52             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
53            
54 1     1   4 use constant DEFAULT_SAME_KEY => 1;
  1         1  
  1         59  
55            
56 1     1   5 use Carp;
  1         1  
  1         58  
57 1     1   706 use YAML qw( Load Dump );
  1         7939  
  1         808  
58            
59             =item new
60            
61             $obj = Acme::Mobile::Therbligs->new();
62            
63             This is used for the object-oriented interface. It is only useful if
64             you want to specify your own keypad or modify the rules:
65            
66             open $fh, 'mykeypad.yml';
67             $obj = Acme::Mobile::Therbligs->new($fh, \%rules );
68            
69             The rule file is in L format that specifies the characters for
70             each key pressed (in the order that they occur for each key press).
71            
72             The optional rules allow one to change the behavior of the counting
73             function:
74            
75             $obj = Acme::Mobile::Therbligs->new($fh,
76             {
77             SAME_KEY => 1,
78             NO_SENTENCE_CAPS => 0,
79             });
80            
81             =over
82            
83             =item SAME_KEY
84            
85             The number of therbligs to count as waiting when having to enter
86             letters which require pressing the same key (as with the word "high").
87             Defaults to C<1>.
88            
89             =item NO_SENTENCE_CAPS
90            
91             By default the initial letter of the message and of each sentence is
92             assumed to be capitalized (when counting in case-sensitive mode). This
93             option disabled that.
94            
95             =back
96            
97             =cut
98            
99             sub new {
100 3     3 1 1051 my $class = shift;
101 3         6 my $self = { };
102 3         7 bless $self, $class;
103 3         9 $self->_initialize(@_);
104 3         11 return $self;
105             }
106            
107             my $Default;
108            
109             sub _initialize {
110 3     3   3 my $self = shift;
111 3         3 my $fh = shift;
112 3   100     14 my $rule = shift || { };
113            
114 3   100     44 $self->{SAME_KEY} = $rule->{SAME_KEY} || DEFAULT_SAME_KEY;
115 3   50     15 $self->{NO_SENTENCE_CAPS} = $rule->{NO_SENTENCE_CAPS} || 0;
116 3   50     13 $self->{NO_SHIFT_CAPS} = $rule->{NO_SHIFT_CAPS} || 0;
117            
118 3 100       16 unless (defined $Default) {
119 1         17 $Default = join("", , "\n");
120             }
121            
122 3 50       10 my $file = (defined $fh) ? join("", <$fh>, "\n") : $Default;
123 3         12 my $keys = Load($file);
124            
125 3         29563 $self->{KEYPAD} = $keys;
126            
127 3         12 foreach my $key (0..9) {
128 30 50       81 croak "Missing $key key",
129             unless (exists $keys->{$key});
130             }
131            
132 3         11 $self->{CHAR} = { };
133            
134 3         14 foreach my $key (keys %$keys) {
135 30         37 my $thurb = 1;
136 30         82 foreach my $char (split //, $keys->{$key}) {
137 225         639 $self->{CHAR}->{$char} = [$key, $thurb++];
138             }
139             }
140            
141 3         11 return $self;
142             }
143            
144             my $Self;
145            
146             {
147             $Self = __PACKAGE__->new(undef, {
148             SAME_KEY => DEFAULT_SAME_KEY,
149             NO_SENTENCE_CAPS => 0,
150             NO_SHIFT_CAPS => 0,
151             });
152             }
153            
154             =item count_therbligs
155            
156             $count = count_therbligs($message, $case_flag);
157            
158             $count = $obj->count_therbligs($message, $case_flag);
159            
160             Returns the number of "therbligs" (keystrokes) used to generate the
161             message. A therblig is either a keystroke, or the pause when one has
162             to wait in order to enter multiple letters from the same key (such as
163             with the word "high").
164            
165             The default number of therbligs for waiting in the same key is
166             C<1>. There is no way to change that value for this version.
167            
168             When C<$case_flag> is true, the number of therbligs includes
169             keystrokes to toggle the shift key. It assumes that the first letter
170             of the message or a sentence is capitalized. (If C<$case_flag> is
171             unspecified, it is assumed to be false.)
172            
173             =cut
174            
175             sub count_therbligs {
176 97     97 1 17981 my $self = shift;
177 97         143 my $text = shift;
178 97         122 my $case = shift;
179 97         104 my $debug = shift; # for diagnostics
180            
181 97 100       235 unless (ref($self)) {
182 9         63 ($debug, $case, $text, $self) = ($case, $text, $self, $Self);
183             }
184            
185 97         117 my $last = ""; # last character
186 97         119 my $shift = 0; # shift flag
187 97         105 my $start = $case; # sentence start flag
188 97         135 my $thurb = 0; # therblig count
189            
190 97         290 foreach my $char (split //, $text) {
191            
192 207 50       366 if ($debug) {
193 0         0 print STDERR
194             "# last=$last char=$char start=$start shift=$shift thurb=$thurb\n";
195             }
196            
197 207 50       541 unless ($self->{NO_SHIFT_CAPS}) {
198            
199             # Note: it assumes characters are lower-case rather than
200             # upper-case without shifting.
201            
202 207 100       575 if ($char ne lc($char)) {
    100          
203 61 100       131 if ($case) {
204 35 100 100     159 unless ($shift||$start) {
205 3         4 $shift = 1;
206 3         3 $thurb ++;
207             }
208             }
209 61         80 $char = lc($char);
210             } elsif ($case) {
211 84 100 66     438 if ((!$self->{NO_SENTENCE_CAPS}) && $start && ($char =~ /[\w]/)) {
      100        
212 10         14 $thurb += 2; # 2 shifts for initial lowercase
213             }
214 84 100 100     209 if ($shift && ($char =~ /[\w]/)) {
215 2         3 $shift = 0;
216 2         4 $thurb ++;
217             }
218             }
219            
220 207 50       521 unless ($self->{NO_SENTENCE_CAPS}) {
221 207 100       796 $start = 0, if ($char =~ /[\w]/);
222 207 100       537 $start = 1, if ($char =~ /[\.\!\?]/);
223             }
224             }
225            
226 207 50       580 croak "Unknown character: $char",
227             unless (exists $self->{CHAR}->{$char});
228 207         457 $thurb += $self->{CHAR}->{$char}->[1];
229 207 100 100     1162 $thurb += $self->{SAME_KEY},
230             if ($self->{CHAR}->{$char}->[0] eq ($self->{CHAR}->{$last}->[0]||""));
231            
232 207         505 $last = $char;
233             }
234            
235 97 50       220 if ($debug) {
236 0         0 print STDERR
237             "# last=$last char= start=$start shift=$shift thurb=$thurb\n";
238             }
239            
240 97         419 return $thurb;
241             }
242            
243            
244             =back
245            
246             =head1 AUTHOR
247            
248             Robert Rothenberg
249            
250             current Maintainer: Rene Schickbauer
251            
252             =head1 REPORTING BUGS
253            
254             We don't know of any bugs, but that doesn't mean there aren't any. Please
255             the CPAN bugtracker or mail Rene Schickbauer directly.
256            
257             =head1 COPYRIGHT AND LICENSE
258            
259             Copyright (C) 2004-2005 by Robert Rothenberg. All Rights Reserved.
260            
261             This library is free software; you can redistribute it and/or modify
262             it under the same terms as Perl itself, either Perl version 5.8.3 or,
263             at your option, any later version of Perl 5 you may have available.
264            
265             Now maintained by Rene Schickbauer, so i guess everything after version 0.01
266             is (C) 2010 Rene Schickbauer
267            
268             =head1 SEE ALSO
269            
270             This module is similar to L.
271            
272             =cut
273            
274             1;
275            
276             __DATA__