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   419754 use 5.010;
  2         8  
5 2     2   12 use strict;
  2         5  
  2         54  
6 2     2   9 use warnings;
  2         27  
  2         6059  
7              
8             our $VERSION = '1.06'; # VERSION
9              
10             sub new {
11 1     1 1 166195 my $self = shift;
12 1   33     102 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 6657   50 6657   11137 my $high = shift || 5;
101 6657   100     11402 my $low = shift || 1;
102 6657         12434 return int( rand( $high - $low + 1 ) ) + $low;
103             }
104              
105             sub words {
106 466     466 1 673 my ( $self, $meta ) = @_;
107              
108             # deal with "maybe_n/n_word" meta words
109 466         1584 while ( $meta =~ /maybe[_-](\d+)\/(\d+)[_-](\w+)\S*/ ) {
110 1215 100       1542 my $word = ( _random( $2, $1 ) == $1 ) ? $3 : '';
111 1215 100       1567 if ($word) {
112 446         2472 $meta =~ s/maybe[_-]\d+\/\d+[_-]\w+(\S*)/$word$1/;
113             }
114             else {
115 769         3273 $meta =~ s/maybe[_-]\d+\/\d+[_-]\w+\S*\s*//;
116             }
117             }
118              
119             # convert "phrase" into phrase meta words
120 466         1502 $meta =~ s/(\w)\s+phrase/$1, phrase/g;
121 466         763 $meta =~ s/phrase/conjuntor article noun to_be power_word/g;
122              
123 466         1425 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 4653         7850 my ( $t1, $t2 ) = ( $1, $1 );
129 4653 100       6061 $t2 = 'verb' if ( $t1 eq 'adverb' );
130 4653         6296 my $word = $self->{ $t2 . 's' }[ _random( $#{ $self->{ $t2 . 's' } }, 0 ) ];
  4653         7112  
131 4653 100       6283 $word =~ s/[e]*$/ing/ if ( $t1 eq 'adverb' );
132 4653         40146 $meta =~ s/$t1/$word/;
133             }
134              
135             # convert "to_be" into the proper conjugated form
136 466         1987 while ( $meta =~ /\b(\w+)\s+to_be/ ) {
137 111 100       319 if ( $1 =~ /ess$/ ) {
    100          
138 3         12 $meta =~ s/to_be/is/;
139             }
140             elsif ( $1 =~ /s$/ ) {
141 2         10 $meta =~ s/to_be/are/;
142             }
143             else {
144 106         389 $meta =~ s/to_be/is/;
145             }
146             }
147              
148 466         5236 $meta =~ s/^\s+|\s+$//;
149 466         1821 $meta =~ s/\b(a)(\s[aeiouy])/$1n$2/i;
150              
151 466         2600 return $meta;
152             }
153              
154             sub sentence {
155 390     390 1 1398 my ( $self, $is_first ) = @_;
156              
157 390         798 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 390         533 my $meta = $meta[ _random( 6, 0 ) ];
177 390 100       708 $meta = 'maybe_1/4_conj_adverb, ' . $meta if ( not $is_first );
178              
179 390         538 return ucfirst( $self->words($meta) ) . '.';
180             }
181              
182             sub paragraph {
183 83     83 1 1429 my ( $self, $low, $high ) = @_;
184 83         98 my $count = 0;
185 83 100       146 if ( not defined $low ) {
    100          
186 63         113 $count = _random( 7, 4 );
187             }
188             elsif ( not defined $high ) {
189 4         6 $count = $low;
190             }
191             else {
192 16         42 $count = _random( $high, $low );
193             }
194 83         99 $count--;
195 83         135 return join( ' ', $self->sentence(1), map { $self->sentence } ( 1 .. $count ) );
  305         553  
196             }
197              
198             sub paragraphs {
199 76     76 1 412 my $self = shift;
200 76   50     155 my $count = shift || 2;
201 76         193 my ( $low, $high ) = @_;
202 76         140 return map { $self->paragraph( $low, $high ) } ( 1 .. $count );
  79         132  
203             }
204              
205             sub bullets {
206 34     34 1 54 my ( $self, $meta ) = ( shift, '' );
207 34   100     61 my $count = shift || 5;
208              
209 34         61 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 34         66 return map { ucfirst $self->words( $bullet_forms[ _random( @bullet_forms - 1, 0 ) ] ) } ( 1 .. $count );
  40         62  
217             }
218              
219             sub body {
220 35     35 1 75 my ( $self, $params ) = @_;
221              
222 35 100       104 $params->{p_min} = 1 if ( not exists $params->{p_min} );
223 35 100       100 $params->{p_max} = 3 if ( not exists $params->{p_max} );
224 35 100       92 $params->{b_freq} = 25 if ( not exists $params->{b_freq} );
225 35 100       93 $params->{b_min} = 3 if ( not exists $params->{b_min} );
226 35 100       76 $params->{b_max} = 6 if ( not exists $params->{b_max} );
227              
228 35         48 my @data = ();
229 35         75 my $p_count = _random( $params->{p_max}, $params->{p_min} );
230              
231 35         94 foreach ( 1 .. $p_count ) {
232             push @data, {
233             type => 'paragraph',
234 73         220 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 73 100 100     269 if (
239             ( $_ != $p_count ) and
240             ( _random(100, 1 ) < $params->{b_freq} )
241             ) {
242 8         17 my $type = _random( 4, 1 );
243             push @data, {
244             type => 'bullet',
245             text => $self->bullets( 1, $type )
246 8         19 } foreach ( 1 .. _random( $params->{b_max}, $params->{b_min} ) );
247             }
248             }
249              
250 35         299 return \@data;
251             }
252              
253             sub header {
254 35     35 1 81 my ( $self, $level ) = @_;
255              
256 35         115 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 35 100       114 $meta = $meta->[ $level - 1 ] if ($level);
269 35         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 35 50       73 join( '-', map { ( $_ !~ /^(of|and|or)$/ ) ? ucfirst : $_ } split('-') )
  85         149  
  92         422  
274             } split( ' ', $self->words($meta) ) );
275             }
276              
277             sub structure {
278 4     4 1 10 my ( $self, $depth, $last_push ) = ( shift, 1, 0 );
279 4   100     15 my $block_limit = shift || 3;
280 4   100     11 my $depth_limit = shift || 3;
281 4   100     11 my $mimimum_length = shift || 10;
282 4         8 my @structure = ();
283              
284 4         6 my $structure;
285             $structure = sub {
286 34     34   53 my $block = 0;
287 34   66     39 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         71 push( @structure, $depth );
293 58         69 my $last_push = $depth;
294 58         52 $block++;
295 58 100 100     81 if (
296             ( $depth < $depth_limit ) and
297             ( _random( 5, 1 ) > 1 )
298             # 1/5 chance of not nesting
299             ) {
300 26         25 $depth++;
301 26         42 $structure->();
302             }
303             }
304 34         50 $depth--;
305 4         20 };
306              
307 4         9 while ( @structure < $mimimum_length ) {
308 8         10 ( $last_push, $depth ) = ( 0, 1 );
309 8         13 $structure->();
310             }
311 4         17 return @structure;
312             }
313              
314             sub document {
315 3     3 1 7 my $self = shift;
316 3   100     16 my $structure = shift || [ $self->structure ];
317 3   100     10 my $params = shift || undef;
318              
319             return [ map {
320             {
321             type => 'header' . $_,
322             text => $self->header($_)
323 33         176 }, @{ $self->body($params) }
  33         80  
324 3         6 } ( @{$structure} ) ];
  3         8  
325             }
326              
327             sub to_html {
328 1     1 1 4 my ( $self, $data ) = @_;
329 1         3 my ( $inside_list, $output ) = ( 0, '' );
330              
331 1         2 for ( @{$data} ) {
  1         3  
332 71 100 100     186 if ( ( $_->{type} ne 'bullet' ) and ($inside_list) ) {
333 5         6 $inside_list = 0;
334 5         7 $output .= "\n";
335             }
336              
337 71 100       144 if ( $_->{type} =~ /header(\d+)/ ) {
    100          
    50          
338 18         63 $output .= '' . $_->{text} . '\n";
339             }
340             elsif ( $_->{type} eq 'paragraph' ) {
341 35         95 $output .= '

' . $_->{text} . "

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