File Coverage

blib/lib/Lingua/ManagementSpeak.pm
Criterion Covered Total %
statement 122 123 99.1
branch 44 46 95.6
condition 31 36 86.1
subroutine 16 16 100.0
pod 11 11 100.0
total 224 232 96.5


line stmt bran cond sub pod time code
1             package Lingua::ManagementSpeak;
2             # ABSTRACT: Tool to generate managerial-sounding text and full documents
3              
4 2     2   443948 use 5.010;
  2         9  
5 2     2   12 use strict;
  2         2  
  2         53  
6 2     2   9 use warnings;
  2         25  
  2         6189  
7              
8             our $VERSION = '1.07'; # VERSION
9              
10             sub new {
11 1     1 1 149466 my $self = shift;
12 1   33     74 return bless( {
13             pronouns => [ qw( I we they ) ],
14             articles => [ qw( the your my our its ) ],
15             conj_adverbs => [ qw( however moreover nevertheless consequently ) ],
16             conjuntors => [ 'though', 'although', 'notwithstanding that', 'yet', 'still' ],
17             sub_conjuncs => [
18             'after', 'although', 'as', 'as if', 'as long as', 'as though', 'because',
19             'before', 'even if', 'even though', 'if', 'if only', 'in order that',
20             'now that', 'once', 'since', 'so that', 'though',
21             'unless', 'until', 'when', 'whenever', 'where', 'whereas', 'wherever',
22             'while'
23             ],
24             power_words => [ qw(
25             accomplished dealt implemented projected achieved debated improved
26             promoted acquired decided included proofed adjusted defined increased
27             purchased administered delegated indicated qualified advised delivered
28             initiated questioned analyzed demonstrated inspected rated applied
29             designed instructed received appraised determined insured recognized
30             arranged developed interpreted recommended assessed devised interviewed
31             recorded assisted directed introduced recruited assured discovered
32             investigated reduced awarded dispensed joined rehabilitated bought
33             displayed kept related briefed distributed launched renovated brought
34             earned led repaired budgeted edited located reported calculated educated
35             maintained represented cataloged elected managed researched chaired
36             encouraged maximized reviewed changed enlisted measured revised
37             classified ensured mediated selected closed entertained modified served
38             coached established motivated simplified combined evaluated named
39             sketched communicated examined negotiated sold compared excelled
40             observed solved completed executed obtained spearheaded computed
41             exhibited operated specified conceived expanded ordered started
42             concluded expedited organized streamlined conducted explained paid
43             strengthened confronted facilitated participated studied constructed
44             financed perceived suggested continued forecast performed summarized
45             contracted formulated persuaded supervised controlled gained placed
46             targeted convinced gathered planned taught coordinated graded predicted
47             tested corrected greeted prepared trained corresponded guided presented
48             translated counseled handled processed treated created helped produced
49             updated critiqued identified programmed wrote
50             ) ],
51             verbs => [ qw(
52             aggregate architect benchmark brand cultivate deliver deploy
53             disintermediate drive e-enable embrace empower enable engage engineer
54             enhance envision evolve expedite exploit extend facilitate generate grow
55             implement incentivize incubate innovate integrate iterate
56             leverage maximize mesh monetize morph optimize orchestrate
57             recontextualize reintermediate reinvent repurpose revolutionize scale
58             seize strategize streamline syndicate synergize synthesize target
59             transform transition unleash utilize visualize whiteboard
60             ) ],
61             aux_verbs => [
62             'will', 'shall', 'may', 'might', 'can', 'could', 'must',
63             'ought to', 'should', 'would', 'need to'
64             ],
65             adjectives => [ qw (
66             24/365 24/7 B2B B2C back-end best-of-breed bleeding-edge
67             bricks-and-click clicks-and-mortar collaborative compelling
68             cross-platform cross-media customized cutting-edge
69             distributed dot-com dynamic e-business efficient
70             end-to-end enterprise extensible frictionless front-end
71             global granular holistic impactful innovative integrated interactive
72             intuitive killer leading-edge magnetic mission-critical next-generation
73             one-to-one open-source out-of-the-box plug-and-play proactive real-time
74             revolutionary robust scalable seamless sexy sticky strategic synergistic
75             transparent turn-key ubiquitous user-centric value-added vertical
76             viral virtual visionary web-enabled wireless world-class
77             )],
78             nouns => [ qw(
79             action-item application architecture bandwidth channel community
80             content convergence deliverable e-business e-commerce e-market
81             e-service e-tailer experiences functionality infomediary
82             infrastructure initiative interface market methodology metric
83             mindshare model network niche paradigm partnership platform
84             portal relationship ROI synergy web-readiness schema solution
85             supply-chain system technology user
86             ) ],
87             nounss => [ qw(
88             action-items applications architectures channels communities
89             convergences deliverables e-businesses e-commerces e-markets
90             e-services e-tailers experiences eyeballs functionalities infomediaries
91             infrastructures initiatives interfaces markets methodologies metrics
92             models networks niches paradigms partnerships platforms
93             portals relationships synergies schemas solutions
94             supply-chains systems technologies users vortals
95             ) ],
96             }, ref($self) || $self );
97             }
98              
99             sub _random {
100 5948   50 5948   10653 my $high = shift || 5;
101 5948   100     11575 my $low = shift || 1;
102 5948         11383 return int( rand( $high - $low + 1 ) ) + $low;
103             }
104              
105             sub words {
106 438     438 1 648 my ( $self, $meta ) = @_;
107              
108             # deal with "maybe_n/n_word" meta words
109 438         1530 while ( $meta =~ /maybe[_-](\d+)\/(\d+)[_-](\w+)\S*/ ) {
110 1025 100       1366 my $word = ( _random( $2, $1 ) == $1 ) ? $3 : '';
111 1025 100       1396 if ($word) {
112 350         1984 $meta =~ s/maybe[_-]\d+\/\d+[_-]\w+(\S*)/$word$1/;
113             }
114             else {
115 675         2977 $meta =~ s/maybe[_-]\d+\/\d+[_-]\w+\S*\s*//;
116             }
117             }
118              
119             # convert "phrase" into phrase meta words
120 438         1539 $meta =~ s/(\w)\s+phrase/$1, phrase/g;
121 438         746 $meta =~ s/phrase/conjuntor article noun to_be power_word/g;
122              
123 438         1350 while ( $meta =~ /(
124             pronoun|article|sub_conjuc|power_word|verb|aux_verb|
125             adjective|noun|conj_adverb|conjuntor|sub_conjunc|adverb
126             )/x ) {
127             # if the word is an adverb, we have to pick a verb and add "ing" to it
128 4191         7576 my ( $t1, $t2 ) = ( $1, $1 );
129 4191 100       6091 $t2 = 'verb' if ( $t1 eq 'adverb' );
130 4191         6215 my $word = $self->{ $t2 . 's' }[ _random( $#{ $self->{ $t2 . 's' } }, 0 ) ];
  4191         6546  
131 4191 100       6406 $word =~ s/[e]*$/ing/ if ( $t1 eq 'adverb' );
132 4191         39176 $meta =~ s/$t1/$word/;
133             }
134              
135             # convert "to_be" into the proper conjugated form
136 438         1962 while ( $meta =~ /\b(\w+)\s+to_be/ ) {
137 118 100       357 if ( $1 =~ /ess$/ ) {
    100          
138 5         20 $meta =~ s/to_be/is/;
139             }
140             elsif ( $1 =~ /s$/ ) {
141 5         16 $meta =~ s/to_be/are/;
142             }
143             else {
144 108         411 $meta =~ s/to_be/is/;
145             }
146             }
147              
148 438         5425 $meta =~ s/^\s+|\s+$//;
149 438         1809 $meta =~ s/\b(a)(\s[aeiouy])/$1n$2/i;
150              
151 438         2278 return $meta;
152             }
153              
154             sub sentence {
155 358     358 1 1423 my ( $self, $is_first ) = @_;
156              
157 358         769 my @meta = (
158             'article noun to_be power_word sub_conjunc pronoun verb ' .
159             'article maybe_1/2_adjective noun maybe_1/3_phrase',
160             'sub_conjunc pronoun power_word article maybe_1/2_adjective ' .
161             'noun, article maybe_1/2_adjective noun power_word article ' .
162             'maybe_1/2_adjective noun maybe_1/4_phrase',
163             'pronoun aux_verb verb article maybe_1/2_adjective noun ' .
164             'sub_conjunc article adjective noun aux_verb verb article ' .
165             'maybe_1/2_adjective noun maybe_1/5_phrase',
166             'sub_conjunc pronoun verb article maybe_1/2_adjective noun, ' .
167             'pronoun can verb article ' .
168             'maybe_1/2_adjective noun maybe_1/4_phrase',
169             'pronoun aux_verb verb article maybe_1/2_adjective noun ' .
170             'sub_conjunc pronoun verb article ' .
171             'maybe_1/2_adjective noun maybe_1/5_phrase',
172             'article noun verbs adjective noun',
173             'article noun to_be a adjective noun, sub_conjunc article noun verbs article noun',
174             );
175              
176 358         492 my $meta = $meta[ _random( 6, 0 ) ];
177 358 100       648 $meta = 'maybe_1/4_conj_adverb, ' . $meta if ( not $is_first );
178              
179 358         568 return ucfirst( $self->words($meta) ) . '.';
180             }
181              
182             sub paragraph {
183 78     78 1 1421 my ( $self, $low, $high ) = @_;
184 78         151 my $count = 0;
185 78 100       151 if ( not defined $low ) {
    100          
186 62         86 $count = _random( 7, 4 );
187             }
188             elsif ( not defined $high ) {
189 4         5 $count = $low;
190             }
191             else {
192 12         19 $count = _random( $high, $low );
193             }
194 78         101 $count--;
195 78         123 return join( ' ', $self->sentence(1), map { $self->sentence } ( 1 .. $count ) );
  278         467  
196             }
197              
198             sub paragraphs {
199 71     71 1 530 my $self = shift;
200 71   50     123 my $count = shift || 2;
201 71         184 my ( $low, $high ) = @_;
202 71         121 return map { $self->paragraph( $low, $high ) } ( 1 .. $count );
  74         132  
203             }
204              
205             sub bullets {
206 39     39 1 68 my ( $self, $meta ) = ( shift, '' );
207 39   100     86 my $count = shift || 5;
208              
209 39         74 my @bullet_forms = (
210             'power_word article adjective noun',
211             'power_word adjective noun',
212             'power_word adjective noun and power_word adjective noun',
213             'power_word article noun power_word by article noun',
214             );
215              
216 39         66 return map { ucfirst $self->words( $bullet_forms[ _random( @bullet_forms - 1, 0 ) ] ) } ( 1 .. $count );
  45         80  
217             }
218              
219             sub body {
220 34     34 1 57 my ( $self, $params ) = @_;
221              
222 34 100       86 $params->{p_min} = 1 if ( not exists $params->{p_min} );
223 34 100       62 $params->{p_max} = 3 if ( not exists $params->{p_max} );
224 34 100       65 $params->{b_freq} = 25 if ( not exists $params->{b_freq} );
225 34 100       71 $params->{b_min} = 3 if ( not exists $params->{b_min} );
226 34 100       69 $params->{b_max} = 6 if ( not exists $params->{b_max} );
227              
228 34         45 my @data = ();
229 34         59 my $p_count = _random( $params->{p_max}, $params->{p_min} );
230              
231 34         74 foreach ( 1 .. $p_count ) {
232             push @data, {
233             type => 'paragraph',
234 68         200 text => $self->paragraphs (1, $params->{p_s_min}, $params->{p_s_max} ),
235             };
236              
237             # a bulletted list should never be first in a body block
238 68 100 100     230 if (
239             ( $_ != $p_count ) and
240             ( _random(100, 1 ) < $params->{b_freq} )
241             ) {
242 9         15 my $type = _random( 4, 1 );
243             push @data, {
244             type => 'bullet',
245             text => $self->bullets( 1, $type )
246 9         20 } foreach ( 1 .. _random( $params->{b_max}, $params->{b_min} ) );
247             }
248             }
249              
250 34         224 return \@data;
251             }
252              
253             sub header {
254 34     34 1 63 my ( $self, $level ) = @_;
255              
256 34         87 my $meta = [
257             [
258             'noun and noun',
259             'noun',
260             'article noun',
261             ],
262             'power_word noun',
263             'adverb power_word noun',
264             'adverb power_word adjective noun',
265             'power_word adjective noun adverb noun',
266             ];
267              
268 34 100       82 $meta = $meta->[ $level - 1 ] if ($level);
269 34         89 $meta = $meta->[ _random( @$meta - 1, 0 ) ] while ( ref($meta) );
270              
271             # capitalize every word with the exception of: of, and, or
272             return join( ' ', map {
273 34 50       58 join( '-', map { ( $_ !~ /^(of|and|or)$/ ) ? ucfirst : $_ } split('-') )
  76         141  
  82         395  
274             } split( ' ', $self->words($meta) ) );
275             }
276              
277             sub structure {
278 4     4 1 11 my ( $self, $depth, $last_push ) = ( shift, 1, 0 );
279 4   100     20 my $block_limit = shift || 3;
280 4   100     12 my $depth_limit = shift || 3;
281 4   100     12 my $mimimum_length = shift || 10;
282 4         8 my @structure = ();
283              
284 4         5 my $structure;
285             $structure = sub {
286 27     27   34 my $block = 0;
287 27   66     52 while (
      100        
288             ( $block < _random( $block_limit, 1 ) ) and
289             ( ( _random( 4, 1 ) > 1 ) or ( $last_push ne $depth ) )
290             # 1/4 chance of exiting early
291             ) {
292 52         100 push( @structure, $depth );
293 52         76 my $last_push = $depth;
294 52         63 $block++;
295 52 100 100     120 if (
296             ( $depth < $depth_limit ) and
297             ( _random( 5, 1 ) > 1 )
298             # 1/5 chance of not nesting
299             ) {
300 22         31 $depth++;
301 22         46 $structure->();
302             }
303             }
304 27         59 $depth--;
305 4         25 };
306              
307 4         13 while ( @structure < $mimimum_length ) {
308 5         41 ( $last_push, $depth ) = ( 0, 1 );
309 5         11 $structure->();
310             }
311 4         28 return @structure;
312             }
313              
314             sub document {
315 3     3 1 6 my $self = shift;
316 3   100     12 my $structure = shift || [ $self->structure ];
317 3   100     13 my $params = shift || undef;
318              
319             return [ map {
320             {
321             type => 'header' . $_,
322             text => $self->header($_)
323 32         95 }, @{ $self->body($params) }
  32         61  
324 3         5 } ( @{$structure} ) ];
  3         8  
325             }
326              
327             sub to_html {
328 1     1 1 2 my ( $self, $data ) = @_;
329 1         3 my ( $inside_list, $output ) = ( 0, '' );
330              
331 1         1 for ( @{$data} ) {
  1         16  
332 64 100 100     129 if ( ( $_->{type} ne 'bullet' ) and ($inside_list) ) {
333 5         6 $inside_list = 0;
334 5         6 $output .= "\n";
335             }
336              
337 64 100       121 if ( $_->{type} =~ /header(\d+)/ ) {
    100          
    50          
338 14         40 $output .= '' . $_->{text} . '\n";
339             }
340             elsif ( $_->{type} eq 'paragraph' ) {
341 31         101 $output .= '

' . $_->{text} . "

\n";
342             }
343             elsif ( $_->{type} eq 'bullet' ) {
344 19 100       23 my $ul = (not $inside_list) ? "
    \n" : '';
345 19         17 $inside_list++;
346 19         24 $output .= $ul . '
  • ' . $_->{text} . "
  • \n";
    347             }
    348             else {
    349 0         0 $output .= '
    ' . $_->{text} . "
    \n";
    350             }
    351             }
    352              
    353 1         30 return $output;
    354             }
    355              
    356             1;
    357              
    358             __END__