1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
package Bucky::Poetaster;
use Digest::MD5;
use Rest;
# Maximum distance to indent a line of text
my $MAX_INDENT = 3;
# Maximum number of words per line
my $MAX_WORD_COUNT = 6;
# Maximum number of letters per line
my $MAX_CHAR_COUNT = 36;
# Number of spaces to print per level of indentation
my $INDENT_WIDTH = 2;
sub new
{
my ($class, $self) = @_;
$self ||= {};
$self->{'indent'} = 0;
bless $self, $class;
return $self;
}
# Given a big block of text, reformat it to resemble a poem
sub poem
{
my ($self, $text) = @_;
# Split the text into words
my @words = split / /, $text;
# Initialize all counters to zero
$self->{'indent'} = 0;
my $word_count = 0;
my $char_count = 0;
# variable to dump all data onto
my $stanza = '';
# loop over all words in the block
foreach my $word (@words)
{
# if word is undefined, skip it (two spaces next to each other)
next unless $word;
# if word starts with non-alphanumeric character
# make a new line and then print the word
if ($word =~ /^[^a-z0-9<>]/i)
{
$word_count = 1;
$char_count = length $word;
$stanza .= $self->indent;
$stanza .= $word;
next;
}
# if word ends with non-alphanumeric character,
# print the word and THEN start a new line
if ($word =~ /([^a-z<>])$/i)
{
my $punct = $1;
# if the word ends with a period, start a new stanza
if ($punct eq "." || $punct eq "?")
{ $self->{'indent'} = 0; }
$word_count = 0;
$char_count = 0;
$stanza .= " " . $word;
$stanza .= $self->indent;
next;
}
# otherwise, print the word
$stanza .= " ". $word;
# tally the line length and number of words on the line
$word_count += 1;
$char_count += length($word)+ 1;
# if we've printed a whole line's worth, start a new line
if ($char_count > $MAX_CHAR_COUNT || $word_count > $MAX_WORD_COUNT)
{
$stanza .= $self->indent;
$word_count = 0;
$char_count = 0;
}
}
# return the new poem cuz we're done
return $stanza;
}
# Modify the current indentation depth,
# and return a string constituting the indent
sub indent
{
my ($self) = @_;
# if we've already indented as far as we'd like, pull back
if ($self->{'indent'} > $MAX_INDENT)
{
$self->{'indent'} -= 1;
}
# otherwise, indent one notch further
else
{
$self->{'indent'} += 1;
}
# print a newline, then indent according to the indentation width
return "\n" . " " x ( $self->{'indent'} * $INDENT_WIDTH );
}
sub url_cache
{
my ($self, $url) = @_;
my $hash = md5_hex($url);
my $path = $self->url_cache_path($hash);
while (-e $path)
{
open P, $path or last;
my @lines = <P>;
close P;
return join "", @lines;
}
my $data = Rest->new->rest_get_raw($url);
open P, ">$path" or return $data;
print P $data;
close $p;
return $data;
}
sub url_cache_path
{
my ($self, $hash) = @_;
my $path = $self->bucky_data_path . "/poetaster/" . $hash;
return $path;
}
sub log
{
my ($self, $date) = @_;
my $criteria = {};
$criteria->{'date'} = $date if $date;
return $self->db->select("poetaster_log", $criteria);
}
sub log_query
{
my ($self, $query, $total) = @_;
return unless $query;
my $date = time;
$matches ||= '0';
$self->db->insert("poetaster_log", { query => $query, date => $date, matches => $total });
}
1;
|