Skip to content
This repository has been archived by the owner on Oct 15, 2022. It is now read-only.

Commit

Permalink
Improved readability a bit for DDG::Goodie::ABC. Added more tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
kablamo committed Mar 8, 2014
1 parent d0a2817 commit 1fb4f83
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 34 deletions.
65 changes: 39 additions & 26 deletions lib/DDG/Goodie/ABC.pm
Expand Up @@ -18,38 +18,51 @@ attribution twitter => 'crazedpsyc',
cpan => 'CRZEDPSYC' ;

handle query_parts => sub {
my @parts = @_; # $query split on word boundaries; includes triggers
my $query = $_; # the entire query

return unless $query =~ /or/;

my @choices;
my @collected_parts;

foreach my $part (@parts) {
next if $part eq 'choose';

if ( lc($part) eq 'or' ) {
return unless @collected_parts;
push @choices, join(' ', @collected_parts);
my $length = @collected_parts;
return if $length > 1;
@collected_parts = ();
} elsif ( $part ) {
push @collected_parts, $part;
}
}
my @query_parts = @_; # query split on word boundaries; includes triggers
my $query = $_; # the entire query

# Remove the trigger word
@query_parts = grep { lc $_ ne 'choose' } @query_parts;

push @choices, join(' ', @collected_parts) if @choices && @collected_parts;
return if scalar(@choices) <= 1;
my $choice = int(rand(@choices));
# Return if the query is malformed
return if query_is_malformed(\@query_parts, $query);

# Gather choices
my @choices = grep { lc $_ ne 'or' } @query_parts;

# Easter egg. For queries like:
# 'choose duckduckgo or google or bing or something'
if (my @duck = grep { / \A (?: duck (?: duckgo )? | ddg ) \z /ix } @choices) {
return $duck[0]." (not random)", answer_type => 'egg';
}

return $choices[$choice]." (random)";
return;
# Choose randomly
my $index = int rand scalar @choices;
return $choices[$index]." (random)";
};

# The query -- minus the trigger word -- must look like
# '<choice> or <choice> or <choice>'
#
# Note this method also prevents choices from being > 1 word long as this
# generates too many false positives.
#
# Returns 1 if the query looks good
# Returns 0 if the query looks malformed
sub query_is_malformed {
my $query_parts = shift;
my $query = shift;

return 1 unless $query =~ /or/i; # handle a query like 'i choose'
return 1 if @$query_parts <= 1; # handle a query like 'choose or'

# Ensure every other element of @$query_parts is 'or'
foreach my $i (1..$#$query_parts) {
next if $i % 2 == 0; # skip even indices
return 1 if lc $query_parts->[$i] ne 'or';
}

return 0;
}

1;
20 changes: 12 additions & 8 deletions t/ABC.t
Expand Up @@ -6,17 +6,21 @@ use Test::More;
use DDG::Test::Goodie;

zci answer_type => 'rand';
zci is_cached => 0;
zci is_cached => 0;

ddg_goodie_test(
[qw(
DDG::Goodie::ABC
)],
'choose yes or no' => test_zci(qr/(yes|no) \(random\)/),
'choose this or that or none' => test_zci(qr/(this|that|none) \(random\)/),
[qw( DDG::Goodie::ABC )],
'choose' => undef,
'i choose' => undef,
'choose or' => undef,
'choose my house or your house' => undef,
'choose his or her house' => undef,
'choose his or or her house' => undef,
'choose yes or no' => test_zci(qr/(yes|no) \(random\)/),
'choose this or that or none' => test_zci(qr/(this|that|none) \(random\)/),
'choose heads or tails' => test_zci(qr/(heads|tails) \(random\)/),
'choose duckduckgo or google or bing or something' => test_zci("duckduckgo (not random)", answer_type => 'egg'),
'choose DuckDuckGo OR Google OR Bing or SOMETHING' => test_zci("DuckDuckGo (not random)", answer_type => 'egg'),
'choose heads or tails' => test_zci(qr/(heads|tails) \(random\)/),
'choose DuckDuckGo OR Google OR Bing OR SOMETHING' => test_zci("DuckDuckGo (not random)", answer_type => 'egg'),
);

done_testing;
Expand Down

0 comments on commit 1fb4f83

Please sign in to comment.