Acme-Wabby
view release on metacpan or search on metacpan
# sentence starting points. Thus, let's grab a random entry out of the
# 0th element in the list and start there.
$start = ${${$self->{'data'}{'list'}}[0]{'num'}}[int rand scalar @{${$self->{'data'}{'list'}}[0]{'num'}}];
$text = ${$self->{'data'}{'list'}}[$start]{'word'};
}
# Since we're dealing with randomness, we can't always be sure that we'll
# be able to make a sentence of min_len, so we just keep retrying up to
# max_attempts times, relying on sheer dumb luck to help us out. On a
# reasonably-sized body of text, this works perfectly fine.
my $attempts = 0;
my $count = 0;
my $final = "";
my $next = $start;
while ($count < $self->{'conf'}{'min_len'} &&
$attempts < $self->{'conf'}{'max_attempts'}) {
# We start out with one word, and uppercase the first character in our
# starting text.
$count = 1;
$final = "\u$text";
$next = $start;
# Keep adding new words to this sentence until we hit an sentence end
# mark, or we hit max_len
while ($next != -1 && ($count < $self->{'conf'}{'max_len'})) {
# If the word we're on has no transitions, count this as a stopping
# point, since we can't go any further.
if (scalar(@{${$self->{'data'}{'list'}}[$next]{'num'}}) < 1) {
$next = -1;
}
# Otherwise, randomly pick the word we'll visit next out of the
# list of possible transitions from our current word.
else {
$next = ${${$self->{'data'}{'list'}}[$next]{'num'}}[int rand scalar @{${$self->{'data'}{'list'}}[$next]{'num'}}];
}
# If we're not at the end yet, add this word to our collected
# string, increment our word count, and do it all again.
if ($next != -1) {
$final .= " " . ${$self->{'data'}{'list'}}[$next]{'word'};
$count++;
}
}
# If we failed to make a long enough sentence, we need to do something.
if ($count < $self->{'conf'}{'min_len'}) {
# If we haven't yet passed our max number of attempts, try again.
if ($attempts < $self->{'conf'}{'max_attempts'}) {
$attempts++;
next;
}
# If we passed our max number of attempts, we can take one of two
# course of action.
else {
# If we're trying to talk about something in particular, we're
# always going to be stuck with the same starting point. Thus,
# there's not the best chance for continued success, so just
# give up and bail.
if ($directed) {
return undef;
}
# If we're talking about random things, we likely just got
# a bad starting point, so we'll pick a new random starting
# point, and do the whole thing over again.
else {
$attempts = 0;
$start = ${${$self->{'data'}{'list'}}[0]{'num'}}[int rand scalar @{${$self->{'data'}{'list'}}[0]{'num'}}];
$text = ${$self->{'data'}{'list'}}[$start]{'word'};
next;
}
}
}
}
# If we're not case sensitive, make sure any I's by themselves are
# capitalized, for aesthetic purposes. If we are, they probably want
# things to come out the way they are.
# FIXME - Need to be able to configure this so that persons with
# non-english texts can pick values that make sense.
unless ($self->{'conf'}{'case_sensitive'}) {
$final =~ s/(^|[^\w-])i($|[^\w-])/$1I$2/g
}
# Pick a random piece of punctuation to add to the end of the sentence.
$final .= ${$self->{'conf'}{'punctuation'}}[int rand scalar @{$self->{'conf'}{'punctuation'}}];
return $final;
}
# A method for getting some basic information about the current state.
# Arguments: None.
# Returns: In a scalar context, this function returns a string describing the
# current state. In a list context, this function returns a list
# containing two numbers -- the first one is the number of words
# that this object knows about, and the second one is the average
# number of transitions between words.
sub stats {
my $self = shift;
die "Invalid object" unless (ref($self) eq __PACKAGE__);
# Get the number of words in our hash.
my $word_count = scalar keys %{$self->{'data'}{'hash'}};
# If we've got no words, just quit now.
if ($word_count == 0) {
return wantarray ? (0,0) : "I don't know anything!";
}
# Iterate over the list, adding up the number of transitions for each word.
my $average = 0;
foreach (@{$self->{'data'}{'list'}}) {
$average += scalar @{$_->{'num'}} if defined($_->{'num'});
}
# Calculate an average, trim it to two decimal points, and return it.
$average /= $word_count;
$average = sprintf "%.2f", $average;
( run in 1.321 second using v1.01-cache-2.11-cpan-7f9471e7e0a )