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 1     1   211652 use 5.008;
  1         8  
5 1     1   4 use strict;
  1         1  
  1         26  
6 1     1   5 use warnings;
  1         1  
  1         1867  
7              
8             our $VERSION = '1.03'; # VERSION
9              
10             sub new {
11 1     1 1 76 my $self = shift;
12 1   33     75 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 7945   50 7945   14786 my $high = shift || 5;
101 7945   100     15931 my $low = shift || 1;
102 7945         17059 return int( rand( $high - $low + 1 ) ) + $low;
103             }
104              
105             sub words {
106 559     559 1 867 my ( $self, $meta ) = @_;
107              
108             # deal with "maybe_n/n_word" meta words
109 559         1865 while ( $meta =~ /maybe[_-](\d+)\/(\d+)[_-](\w+)\S*/ ) {
110 1446 100       2269 my $word = ( _random( $2, $1 ) == $1 ) ? $3 : '';
111 1446 100       2130 if ($word) {
112 560         3459 $meta =~ s/maybe[_-]\d+\/\d+[_-]\w+(\S*)/$word$1/;
113             }
114             else {
115 886         4458 $meta =~ s/maybe[_-]\d+\/\d+[_-]\w+\S*\s*//;
116             }
117             }
118              
119             # convert "phrase" into phrase meta words
120 559         1903 $meta =~ s/(\w)\s+phrase/$1, phrase/g;
121 559         917 $meta =~ s/phrase/conjuntor article noun to_be power_word/g;
122              
123 559         1874 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 5604         12229 my ( $t1, $t2 ) = ( $1, $1 );
129 5604 100       8624 $t2 = 'verb' if ( $t1 eq 'adverb' );
130 5604         8532 my $word = $self->{ $t2 . 's' }[ _random( $#{ $self->{ $t2 . 's' } }, 0 ) ];
  5604         10208  
131 5604 100       9130 $word =~ s/[e]*$/ing/ if ( $t1 eq 'adverb' );
132 5604         58112 $meta =~ s/$t1/$word/;
133             }
134              
135             # convert "to_be" into the proper conjugated form
136 559         2306 while ( $meta =~ /\b(\w+)\s+to_be/ ) {
137 147 100       407 if ( $1 =~ /ess$/ ) {
    100          
138 15         60 $meta =~ s/to_be/is/;
139             }
140             elsif ( $1 =~ /s$/ ) {
141 4         19 $meta =~ s/to_be/are/;
142             }
143             else {
144 128         500 $meta =~ s/to_be/is/;
145             }
146             }
147              
148 559         5636 $meta =~ s/^\s+|\s+$//;
149 559         2256 $meta =~ s/\b(a)(\s[aeiouy])/$1n$2/i;
150              
151 559         2856 return $meta;
152             }
153              
154             sub sentence {
155 456     456 1 1614 my ( $self, $is_first ) = @_;
156              
157 456         1177 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 456         697 my $meta = $meta[ _random( 6, 0 ) ];
177 456 100       995 $meta = 'maybe_1/4_conj_adverb, ' . $meta if ( not $is_first );
178              
179 456         779 return ucfirst( $self->words($meta) ) . '.';
180             }
181              
182             sub paragraph {
183 93     93 1 1574 my ( $self, $low, $high ) = @_;
184 93         127 my $count = 0;
185 93 100       196 if ( not defined $low ) {
    100          
186 76         110 $count = _random( 7, 4 );
187             }
188             elsif ( not defined $high ) {
189 4         5 $count = $low;
190             }
191             else {
192 13         25 $count = _random( $high, $low );
193             }
194 93         112 $count--;
195 93         150 return join( ' ', $self->sentence(1), map { $self->sentence } ( 1 .. $count ) );
  361         649  
196             }
197              
198             sub paragraphs {
199 86     86 1 424 my $self = shift;
200 86   50     151 my $count = shift || 2;
201 86         210 my ( $low, $high ) = @_;
202 86         153 return map { $self->paragraph( $low, $high ) } ( 1 .. $count );
  89         143  
203             }
204              
205             sub bullets {
206 54     54 1 102 my ( $self, $meta ) = ( shift, '' );
207 54   100     92 my $count = shift || 5;
208              
209 54         93 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 54         83 return map { ucfirst $self->words( $bullet_forms[ _random( @bullet_forms - 1, 0 ) ] ) } ( 1 .. $count );
  60         111  
217             }
218              
219             sub body {
220 42     42 1 74 my ( $self, $params ) = @_;
221              
222 42 100       118 $params->{p_min} = 1 if ( not exists $params->{p_min} );
223 42 100       80 $params->{p_max} = 3 if ( not exists $params->{p_max} );
224 42 100       99 $params->{b_freq} = 25 if ( not exists $params->{b_freq} );
225 42 100       75 $params->{b_min} = 3 if ( not exists $params->{b_min} );
226 42 100       74 $params->{b_max} = 6 if ( not exists $params->{b_max} );
227              
228 42         60 my @data = ();
229 42         69 my $p_count = _random( $params->{p_max}, $params->{p_min} );
230              
231 42         97 foreach ( 1 .. $p_count ) {
232             push @data, {
233             type => 'paragraph',
234 83         258 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 83 100 100     305 if (
239             ( $_ != $p_count ) and
240             ( _random(100, 1 ) < $params->{b_freq} )
241             ) {
242 12         19 my $type = _random( 4, 1 );
243             push @data, {
244             type => 'bullet',
245             text => $self->bullets( 1, $type )
246 12         22 } foreach ( 1 .. _random( $params->{b_max}, $params->{b_min} ) );
247             }
248             }
249              
250 42         247 return \@data;
251             }
252              
253             sub header {
254 42     42 1 77 my ( $self, $level ) = @_;
255              
256 42         134 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 42 100       104 $meta = $meta->[ $level - 1 ] if ($level);
269 42         112 $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 42 50       78 join( '-', map { ( $_ !~ /^(of|and|or)$/ ) ? ucfirst : $_ } split('-') )
  108         182  
  113         534  
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     14 my $block_limit = shift || 3;
280 4   100     11 my $depth_limit = shift || 3;
281 4   100     10 my $mimimum_length = shift || 10;
282 4         7 my @structure = ();
283              
284 4         5 my $structure;
285             $structure = sub {
286 30     30   33 my $block = 0;
287 30   66     42 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 58         95 push( @structure, $depth );
293 58         64 my $last_push = $depth;
294 58         60 $block++;
295 58 100 100     113 if (
296             ( $depth < $depth_limit ) and
297             ( _random( 5, 1 ) > 1 )
298             # 1/5 chance of not nesting
299             ) {
300 24         27 $depth++;
301 24         38 $structure->();
302             }
303             }
304 30         49 $depth--;
305 4         20 };
306              
307 4         12 while ( @structure < $mimimum_length ) {
308 6         11 ( $last_push, $depth ) = ( 0, 1 );
309 6         11 $structure->();
310             }
311 4         36 return @structure;
312             }
313              
314             sub document {
315 3     3 1 7 my $self = shift;
316 3   100     13 my $structure = shift || [ $self->structure ];
317 3   100     15 my $params = shift || undef;
318              
319             return [ map {
320             {
321             type => 'header' . $_,
322             text => $self->header($_)
323 40         120 }, @{ $self->body($params) }
  40         91  
324 3         5 } ( @{$structure} ) ];
  3         6  
325             }
326              
327             sub to_html {
328 1     1 1 6 my ( $self, $data ) = @_;
329 1         4 my ( $inside_list, $output ) = ( 0, '' );
330              
331 1         2 for ( @{$data} ) {
  1         4  
332 65 100 100     159 if ( ( $_->{type} ne 'bullet' ) and ($inside_list) ) {
333 5         7 $inside_list = 0;
334 5         7 $output .= "\n";
335             }
336              
337 65 100       133 if ( $_->{type} =~ /header(\d+)/ ) {
    100          
    50          
338 14         48 $output .= '' . $_->{text} . '\n";
339             }
340             elsif ( $_->{type} eq 'paragraph' ) {
341 31         90 $output .= '

' . $_->{text} . "

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