File Coverage

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

' . $_->{text} . "

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