/lib/DDG/Goodie/ABC.pm

https://gitlab.com/0072016/zeroclickinfo-goodies · Perl · 75 lines · 42 code · 16 blank · 17 comment · 7 complexity · 0dda986575b94dcf1a57247f143305e1 MD5 · raw file

  1. package DDG::Goodie::ABC;
  2. # ABSTRACT: Randomly pick one of several different choices delimited by "or"
  3. use DDG::Goodie;
  4. use List::AllUtils qw/none/;
  5. triggers startend => qw/choose pick select/;
  6. zci answer_type => "rand";
  7. zci is_cached => 0;
  8. primary_example_queries 'choose yes or no';
  9. secondary_example_queries 'choose heads or tails', 'pick this or that or none';
  10. description 'make a random choice';
  11. name 'ABC';
  12. code_url 'https://github.com/duckduckgo/zeroclickinfo-goodies/blob/master/lib/DDG/Goodie/ABC.pm';
  13. category 'random';
  14. topics 'trivia';
  15. attribution twitter => 'crazedpsyc',
  16. cpan => 'CRZEDPSYC',
  17. twitter => 'kablamo_',
  18. cpan => 'KABLAMO',
  19. github => 'kablamo',
  20. web => ["http://kablamo.org", "Eric Johnson"] ;
  21. handle remainder => sub {
  22. # Ensure rand is seeded for each process
  23. srand();
  24. my $query = $_;
  25. # split the query on whitespace and rm whitespace
  26. my @words = grep { length } split /\s+/, $query;
  27. return if query_is_malformed(@words);
  28. # rm every 'or' from the list
  29. my @choices = grep { lc $_ ne 'or' } @words;
  30. # Easter egg. For queries like:
  31. # 'choose duckduckgo or google or bing or something'
  32. if (my @duck = grep { / \A (?: duck (?: duckgo )? | ddg ) \z /ix } @choices) {
  33. return $duck[0]." (not random)", answer_type => 'egg';
  34. }
  35. # Choose randomly
  36. my $index = int rand scalar @choices;
  37. return $choices[$index]." (random)";
  38. };
  39. # The query must look like
  40. # '<choice> or <choice> or <choice>'
  41. #
  42. # Note this method also prevents choices from being > 1 word long as this
  43. # generates false positives for queries such as
  44. # 'choose from a selection of products like venison, turkey, quail, or fish'
  45. #
  46. # Returns 0 if the query looks good
  47. # Returns 1 if the query looks malformed
  48. sub query_is_malformed {
  49. my @words = @_;
  50. return 1 if none { lc $_ eq 'or' } @words; # ignore queries like 'i choose'
  51. return 1 if @words <= 1; # ignore queries like 'choose or'
  52. # Ensure every other element of @$words is 'or'
  53. foreach my $i (1..$#words) {
  54. next if $i % 2 == 0; # skip even indices
  55. return 1 if lc $words[$i] ne 'or';
  56. }
  57. return 0;
  58. }
  59. 1;