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   188426 use 5.008;
  1         8  
5 1     1   5 use strict;
  1         2  
  1         15  
6 1     1   4 use warnings;
  1         2  
  1         1873  
7              
8             our $VERSION = '1.04'; # VERSION
9              
10             sub new {
11 1     1 1 75 my $self = shift;
12 1   33     61 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 7493   50 7493   13809 my $high = shift || 5;
101 7493   100     14329 my $low = shift || 1;
102 7493         15963 return int( rand( $high - $low + 1 ) ) + $low;
103             }
104              
105             sub words {
106 535     535 1 805 my ( $self, $meta ) = @_;
107              
108             # deal with "maybe_n/n_word" meta words
109 535         1830 while ( $meta =~ /maybe[_-](\d+)\/(\d+)[_-](\w+)\S*/ ) {
110 1314 100       2146 my $word = ( _random( $2, $1 ) == $1 ) ? $3 : '';
111 1314 100       1945 if ($word) {
112 511         3208 $meta =~ s/maybe[_-]\d+\/\d+[_-]\w+(\S*)/$word$1/;
113             }
114             else {
115 803         3966 $meta =~ s/maybe[_-]\d+\/\d+[_-]\w+\S*\s*//;
116             }
117             }
118              
119             # convert "phrase" into phrase meta words
120 535         1494 $meta =~ s/(\w)\s+phrase/$1, phrase/g;
121 535         828 $meta =~ s/phrase/conjuntor article noun to_be power_word/g;
122              
123 535         1887 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 5287         12044 my ( $t1, $t2 ) = ( $1, $1 );
129 5287 100       8038 $t2 = 'verb' if ( $t1 eq 'adverb' );
130 5287         8483 my $word = $self->{ $t2 . 's' }[ _random( $#{ $self->{ $t2 . 's' } }, 0 ) ];
  5287         9389  
131 5287 100       8828 $word =~ s/[e]*$/ing/ if ( $t1 eq 'adverb' );
132 5287         51799 $meta =~ s/$t1/$word/;
133             }
134              
135             # convert "to_be" into the proper conjugated form
136 535         2154 while ( $meta =~ /\b(\w+)\s+to_be/ ) {
137 141 100       381 if ( $1 =~ /ess$/ ) {
    100          
138 9         36 $meta =~ s/to_be/is/;
139             }
140             elsif ( $1 =~ /s$/ ) {
141 3         14 $meta =~ s/to_be/are/;
142             }
143             else {
144 129         510 $meta =~ s/to_be/is/;
145             }
146             }
147              
148 535         6415 $meta =~ s/^\s+|\s+$//;
149 535         2060 $meta =~ s/\b(a)(\s[aeiouy])/$1n$2/i;
150              
151 535         2681 return $meta;
152             }
153              
154             sub sentence {
155 452     452 1 1563 my ( $self, $is_first ) = @_;
156              
157 452         1240 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 452         673 my $meta = $meta[ _random( 6, 0 ) ];
177 452 100       972 $meta = 'maybe_1/4_conj_adverb, ' . $meta if ( not $is_first );
178              
179 452         798 return ucfirst( $self->words($meta) ) . '.';
180             }
181              
182             sub paragraph {
183 91     91 1 1544 my ( $self, $low, $high ) = @_;
184 91         108 my $count = 0;
185 91 100       158 if ( not defined $low ) {
    100          
186 74         103 $count = _random( 7, 4 );
187             }
188             elsif ( not defined $high ) {
189 4         7 $count = $low;
190             }
191             else {
192 13         16 $count = _random( $high, $low );
193             }
194 91         126 $count--;
195 91         142 return join( ' ', $self->sentence(1), map { $self->sentence } ( 1 .. $count ) );
  359         651  
196             }
197              
198             sub paragraphs {
199 84     84 1 409 my $self = shift;
200 84   50     141 my $count = shift || 2;
201 84         188 my ( $low, $high ) = @_;
202 84         151 return map { $self->paragraph( $low, $high ) } ( 1 .. $count );
  87         150  
203             }
204              
205             sub bullets {
206 33     33 1 67 my ( $self, $meta ) = ( shift, '' );
207 33   100     63 my $count = shift || 5;
208              
209 33         58 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 33         61 return map { ucfirst $self->words( $bullet_forms[ _random( @bullet_forms - 1, 0 ) ] ) } ( 1 .. $count );
  39         69  
217             }
218              
219             sub body {
220 43     43 1 78 my ( $self, $params ) = @_;
221              
222 43 100       114 $params->{p_min} = 1 if ( not exists $params->{p_min} );
223 43 100       92 $params->{p_max} = 3 if ( not exists $params->{p_max} );
224 43 100       72 $params->{b_freq} = 25 if ( not exists $params->{b_freq} );
225 43 100       88 $params->{b_min} = 3 if ( not exists $params->{b_min} );
226 43 100       73 $params->{b_max} = 6 if ( not exists $params->{b_max} );
227              
228 43         61 my @data = ();
229 43         77 my $p_count = _random( $params->{p_max}, $params->{p_min} );
230              
231 43         87 foreach ( 1 .. $p_count ) {
232             push @data, {
233             type => 'paragraph',
234 81         235 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 81 100 100     310 if (
239             ( $_ != $p_count ) and
240             ( _random(100, 1 ) < $params->{b_freq} )
241             ) {
242 6         12 my $type = _random( 4, 1 );
243             push @data, {
244             type => 'bullet',
245             text => $self->bullets( 1, $type )
246 6         14 } foreach ( 1 .. _random( $params->{b_max}, $params->{b_min} ) );
247             }
248             }
249              
250 43         224 return \@data;
251             }
252              
253             sub header {
254 43     43 1 79 my ( $self, $level ) = @_;
255              
256 43         117 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 43 100       112 $meta = $meta->[ $level - 1 ] if ($level);
269 43         121 $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 43 50       81 join( '-', map { ( $_ !~ /^(of|and|or)$/ ) ? ucfirst : $_ } split('-') )
  102         207  
  113         509  
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     14 my $block_limit = shift || 3;
280 4   100     10 my $depth_limit = shift || 3;
281 4   100     18 my $mimimum_length = shift || 10;
282 4         8 my @structure = ();
283              
284 4         4 my $structure;
285             $structure = sub {
286 38     38   47 my $block = 0;
287 38   66     50 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 67         106 push( @structure, $depth );
293 67         74 my $last_push = $depth;
294 67         69 $block++;
295 67 100 100     113 if (
296             ( $depth < $depth_limit ) and
297             ( _random( 5, 1 ) > 1 )
298             # 1/5 chance of not nesting
299             ) {
300 30         41 $depth++;
301 30         47 $structure->();
302             }
303             }
304 38         58 $depth--;
305 4         18 };
306              
307 4         11 while ( @structure < $mimimum_length ) {
308 8         11 ( $last_push, $depth ) = ( 0, 1 );
309 8         14 $structure->();
310             }
311 4         20 return @structure;
312             }
313              
314             sub document {
315 3     3 1 7 my $self = shift;
316 3   100     12 my $structure = shift || [ $self->structure ];
317 3   100     16 my $params = shift || undef;
318              
319             return [ map {
320             {
321             type => 'header' . $_,
322             text => $self->header($_)
323 41         119 }, @{ $self->body($params) }
  41         82  
324 3         5 } ( @{$structure} ) ];
  3         7  
325             }
326              
327             sub to_html {
328 1     1 1 3 my ( $self, $data ) = @_;
329 1         2 my ( $inside_list, $output ) = ( 0, '' );
330              
331 1         2 for ( @{$data} ) {
  1         3  
332 79 100 100     193 if ( ( $_->{type} ne 'bullet' ) and ($inside_list) ) {
333 4         5 $inside_list = 0;
334 4         5 $output .= "\n";
335             }
336              
337 79 100       167 if ( $_->{type} =~ /header(\d+)/ ) {
    100          
    50          
338 20         63 $output .= '' . $_->{text} . '\n";
339             }
340             elsif ( $_->{type} eq 'paragraph' ) {
341 40         104 $output .= '

' . $_->{text} . "

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