App-RoboBot
view release on metacpan or search on metacpan
lib/App/RoboBot/Plugin/Fun/Markov.pm view on Meta::CPAN
sub find_neighbor {
my ($self, $nick_ids, $source, $neighbor_pos) = @_;
my $res = $self->bot->config->db->do(q{
select p.phrase
from markov_phrases s
left join markov_neighbors n on (n.phrase_id = s.id)
left join markov_phrases p on (p.id = n.neighbor_id)
where s.phrase = ? and s.nick_id in ??? and p.structure = ?
order by log(coalesce(occurrences + 1, 1)) + random() desc
limit 1
}, $source, $nick_ids, $neighbor_pos);
return $res->[0] if $res && $res->next;
$res = $self->bot->config->db->do(q{
select p.phrase
from markov_phrases p
where p.nick_id in ??? and p.structure = ?
}, $nick_ids, $neighbor_pos);
return $res->[0] if $res && $res->next;
return '';
}
sub split_form_on_seed {
my ($self, $form, $seed) = @_;
my @f = split(/\s+/, $form);
my @candidates;
for (my $i = 0; $i <= $#f; $i++) {
push(@candidates, $i) if $f[$i] eq $seed->{'structure'};
}
my $pos = (shuffle @candidates)[0];
my ($l, $r) = ([],[]);
if ($pos > 0) {
$l = [@f[0..($pos-1)]];
}
if ($pos < $#f) {
$r = [@f[($pos+1)..$#f]];
}
return ($l,$r);
}
sub save_phrases {
my ($self, $message, $phrases) = @_;
foreach my $phrase (@{$phrases}) {
my $res = $self->bot->config->db->do(q{
update markov_phrases
set used_count = used_count + 1,
updated_at = now()
where nick_id = ? and phrase = ?
returning id
}, $message->sender->id, $phrase->{'phrase'});
next if $res && $res->next;
$res = $self->bot->config->db->do(q{
insert into markov_phrases ??? returning id
}, { nick_id => $message->sender->id,
structure => $phrase->{'structure'},
phrase => $phrase->{'phrase'},
used_count => 1,
});
}
return 1;
}
sub save_neighbors {
my ($self, $message, $phrases) = @_;
my ($res, %phrase_ids);
PHRASE:
foreach my $phrase (@{$phrases}) {
next unless exists $phrase->{'phrase'} && $phrase->{'phrase'} =~ m{\w+}o;
my $phrase_id;
if (exists $phrase_ids{$phrase->{'phrase'}}) {
$phrase_id = $phrase_ids{$phrase->{'phrase'}};
} else {
$res = $self->bot->config->db->do(q{
select id
from markov_phrases
where nick_id = ? and phrase ilike ?
order by length(phrase) asc
limit 1
}, $message->sender->id, '%' . $phrase->{'phrase'});
next PHRASE unless $res && $res->next;
$phrase_id = $phrase_ids{$phrase->{'phrase'}} = $res->{'id'};
}
NEIGHBOR:
foreach my $neighbor (@{$phrase->{'neighbors'}}) {
next unless defined $neighbor && $neighbor =~ m{\w+}o;
my $neighbor_id;
if (exists $phrase_ids{$neighbor}) {
$neighbor_id = $phrase_ids{$neighbor};
} else {
$res = $self->bot->config->db->do(q{
select id
from markov_phrases
where nick_id = ? and phrase ilike ?
order by length(phrase) asc
limit 1
}, $message->sender->id, '%' . $neighbor);
next NEIGHBOR unless $res && $res->next;
$neighbor_id = $phrase_ids{$neighbor} = $res->{'id'};
}
$res = $self->bot->config->db->do(q{
update markov_neighbors
set occurrences = occurrences + 1,
updated_at = now()
where phrase_id = ? and neighbor_id = ?
}, $phrase_id, $neighbor_id);
next NEIGHBOR if $res && $res->count > 0;
$res = $self->bot->config->db->do(q{
insert into markov_neighbors ???
}, {
phrase_id => $phrase_id,
neighbor_id => $neighbor_id,
occurrences => 1,
});
}
}
}
sub save_sentence_form {
my ($self, $message, $form) = @_;
return unless defined $form;
my @parts_of_speech = $form =~ m{\b([A-Z]+)\b}og;
$form = join(' ', @parts_of_speech);
my $res = $self->bot->config->db->do(q{
update markov_sentence_forms
set used_count = used_count + 1,
updated_at = now()
where nick_id = ? and structure = ?
returning id
}, $message->sender->id, $form);
return 1 if $res && $res->next;
$res = $self->bot->config->db->do(q{
insert into markov_sentence_forms ??? returning id
}, { nick_id => $message->sender->id,
structure => $form,
structure_jsonb => encode_json([split(/\s+/, $form)]),
used_count => 1,
});
return 1;
}
sub compute_neighbors {
my ($self, $message, $phrases, $text) = @_;
foreach my $phrase (@{$phrases}) {
if ($text =~ m{ (?:\s(\S+)\s)? $phrase->{'phrase'} (?:\s(\S+)\s)? }ix) {
my ($l, $r) = ($1, $2);
$phrase->{'neighbors'} = []
unless exists $phrase->{'neighbors'}
&& ref($phrase->{'neighbors'}) eq 'ARRAY';
push(@{$phrase->{'neighbors'}}, $l) if defined $l && $l =~ m{\w+}o;
push(@{$phrase->{'neighbors'}}, $r) if defined $r && $r =~ m{\w+}o;
}
}
}
sub parse_phrases {
my ($self, $tagged) = @_;
my @phrases = ();
push(@phrases, $self->parse_nouns($tagged));
push(@phrases, $self->parse_verbs($tagged));
push(@phrases, $self->parse_descriptives($tagged));
push(@phrases, $self->parse_misc($tagged));
return @phrases;
}
sub parse_nouns {
my ($self, $text) = @_;
return unless defined $$text;
my @phrases = ();
my @np = $$text =~ m{
\b(
(?: \w+/NNS? \s*)+
)\b
}ogx;
( run in 2.445 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )