Merge branch 'master' of github.com:duckduckgo/zeroclickinfo-goodies

master
Dylan Lloyd 2012-05-29 16:48:44 -04:00
commit af94139778
40 changed files with 207 additions and 66 deletions

View File

@ -14,7 +14,6 @@ Math::Int2Base = 1.00
Data::GUID = 0.046
IO::All = 0.44
File::ShareDir::ProjectDistDir = 0.2.0
HTML::Entities = 3.69
Text::Unidecode = 0.04
Date::Calc = 6.3
DateTime = 0.74
@ -26,6 +25,9 @@ Number::UN = 0.002
Locale::Language = 3.21
; ParseCron
Schedule::Cron::Events = 0
Convert::Color = 0.08
Convert::Color::Library = 0.03
Convert::Morse = 0.05
[Prereqs / TestRequires]
Test::More = 0.98

View File

@ -1,4 +1,5 @@
package DDG::Goodie::ABC;
# ABSTRACT: Randomly pick one of different choices splitted by "or"
use DDG::Goodie;

View File

@ -1,10 +1,12 @@
package DDG::Goodie::Ascii;
# ABSTRACT: ASCII
use DDG::Goodie;
triggers end => "ascii";
zci answer_type => "ascii_conversion";
zci is_cached => 1;
triggers end => "ascii";
handle remainder => sub {
my $ascii = pack("B*", $1) if /^(([0-1]{8})*)\s+(in|to)$/;

View File

@ -3,15 +3,13 @@ package DDG::Goodie::AspectRatio;
use DDG::Goodie;
triggers start => "aspect ratio";
zci is_cached => 1;
zci answer_type => "aspect_ratio";
triggers start => "aspect";
handle query_parts => sub {
shift;
return unless lc(shift) eq "ratio";
my $input = join(' ', @_);
handle remainder => sub {
my $input = $_;
my $result = 0;
my $ratio = 0;

View File

@ -45,7 +45,6 @@ handle query => sub {
$rms /= $len;
$rms = sqrt $rms;
return "Mean: $mean\nMedian: $med\nRoot Mean Square: $rms";
};
1;

View File

@ -1,12 +1,9 @@
package DDG::Goodie::Base;
use 5.010;
use strict;
use warnings;
use Math::Int2Base qw/int2base/;
use DDG::Goodie;
zci answer_type => "conversion";
zci is_cached => 1;
use DDG::Goodie;
use Math::Int2Base qw/int2base/;
use 5.010;
my %base_map = (
hex => 16,
hexadecimal => 16,
@ -14,8 +11,12 @@ my %base_map = (
octal => 8,
binary => 2,
);
triggers any => 'base', keys %base_map;
zci answer_type => "conversion";
zci is_cached => 1;
handle query_clean => sub {
return unless /^([0-9]+)\s*(?:(?:in|as|to)\s+)?(hex|hexadecimal|octal|oct|binary|base\s*([0-9]+))$/;
my $number = $1;

View File

@ -1,11 +1,11 @@
package DDG::Goodie::Binary;
use DDG::Goodie;
use HTML::Entities;
triggers end => "binary";
zci is_cached => 1;
zci answer_type => "binary_conversion";
triggers end => "binary";
sub bin {
my @tex = shift;

View File

@ -1,11 +1,11 @@
package DDG::Goodie::Capitalize;
use DDG::Goodie;
use utf8;
triggers startend => 'capitalize', 'uppercase', 'upper case';
zci is_cached => 1;
zci answer_type => "capitalize";
triggers startend => 'capitalize', 'uppercase';
handle remainder => sub { uc ($_) };

View File

@ -4,10 +4,13 @@ package DDG::Goodie::Chars;
use DDG::Goodie;
triggers start => 'chars';
zci is_cached => 1;
zci answer_type => "chars";
handle remainder => sub {
return "Chars: " .length $_ if $_;
return;
};
1;

View File

@ -0,0 +1,62 @@
package DDG::Goodie::ColorCodes;
use DDG::Goodie;
use Convert::Color;
use Convert::Color::Library;
my %types = ( # hash of keyword => Convert::Color prefix
vga => 'vga',
rgb => 'rgb8',
hsv => 'hsv',
hex => 'rgb8',
html => 'rgb8',
css => 'rgb8',
hsl => 'hsl',
hsv => 'hsv',
cmy => 'cmy',
cmyk => 'cmyk',
cmyb => 'cmyb',
);
my $typestr = join '|', keys %types;
triggers query_raw => qr/^
(?:(.+)\s+(.+)\s+colou?r(?:\s+code)| # handles "rgb red color code", "red rgb color code", etc
(.+)\s+colou?r(?:\s+code)?(?:\s+for)?\s+(.+)| # handles "rgb color code for red", "red color code for html", etc
($typestr)\s*:?\s*\(?\s*(.+?)\s*\)?) # handles "rgb( red )", "rgb:255,0,0", "rgb(255 0 0)", etc
$/ix;
zci is_cached => 1;
zci answer_type => 'color_code';
attribution
twitter => 'crazedpsyc',
cpan => 'CRZEDPSYC'
;
handle matches => sub {
my $type;
my $color;
for (@_) {
next unless defined $_;
my $q = lc($_);
$type = $types{$q} if exists $types{$q};
$color = $q unless defined $type && exists $types{$q};
}
return unless $type && $color;
$color =~ s/,?\s+/,/g;
eval { $color = join(',',Convert::Color::Library->new($color)->as_rgb8->hex); $type = 'rgb8'; };
my $col;
eval { $col = Convert::Color->new("$type:$color"); };
return if $@;
my $rgb = $col->as_rgb8;
my $hsl = $col->as_hsl;
my $text = sprintf("Hex: %s, Red: %d, Green: %d, Blue: %d ~ Hue: %d, Saturation: %.2f, Value: %.2f ~ Cyan: %.2f, Magenta: %.2f, Yellow: %.2f, Black: %.2f", '#'.$rgb->hex, $col->as_rgb8->rgb8, $hsl->hue, $hsl->saturation, $hsl->lightness, $col->as_cmyk->cmyk);
return $text, html => '<div style="background:#'.$rgb->hex.';border:2px solid #999;height:30px;width:30px;margin:5px;margin-right:10px;margin-top:3px;float:left;"></div>'.$text;
};
1;

View File

@ -6,6 +6,7 @@ use Date::Calc qw( Add_Delta_Days Add_Delta_YM Decode_Date_US This_Year );
use Lingua::EN::Numericalize;
triggers any => qw( plus minus + - );
zci is_cached => 1;
zci answer_type => 'date_math';

View File

@ -6,10 +6,10 @@ use Date::Calc qw( Date_to_Days);
use Time::localtime;
triggers start => "days", "daysbetween", "days_between";
zci is_cached => 1;
zci answer_type => "days_between";
handle query_lc => sub {
s/^days(?:\s|_)*between//;

View File

@ -3,7 +3,9 @@ package DDG::Goodie::Dice;
use DDG::Goodie;
triggers start => "roll", "throw";
zci answer_type => "dice_roll";
handle remainder => sub {
if ($_ =~ /^(?:die|(\d{0,2})\s*dice)$/) {
my @output;

View File

@ -2,9 +2,10 @@ package DDG::Goodie::EmToPx;
use DDG::Goodie;
triggers any => "em", "px";
zci is_cached => 1;
zci answer_type => "conversion";
triggers any => "em", "px";
handle query_raw => sub {
s/(?![\.\s])\W//g;

View File

@ -4,7 +4,9 @@ use DDG::Goodie;
use Data::GUID;
triggers start => 'globally', 'universally', 'rfc', 'guid', 'uuid';
zci answer_type => "guid";
my %guid = (
'guid' => 0,
'uuid' => 1,

View File

@ -6,12 +6,10 @@ zci answer_type => "golden_ratio";
zci is_cached => 1;
triggers start => "golden"; # should be "golden ratio"
triggers start => "golden ratio";
handle query_parts => sub {
shift;
return unless lc(shift) eq "ratio";
my $input = join(' ', @_);
handle remainder => sub {
my $input = $_;
my $golden_ratio = (1 + sqrt(5)) / 2;
my $result = 0;

View File

@ -6,10 +6,10 @@ use Locale::Language;
use constant WPHREF => "https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes";
zci answer_type => "iso639";
triggers start => "iso 639", "iso639";
# TODO: support "iso 639" and "iso-639"
triggers start => "iso639";
zci answer_type => "iso639";
zci is_cached => 1;
handle remainder => sub {
my ($lang, $code) = langpair(shift) or return;
@ -32,6 +32,4 @@ sub langpair {
return;
}
zci is_cached => 1;
1;

View File

@ -2,13 +2,15 @@ package DDG::Goodie::JsKeycodes;
# ABSTRACT: Give the equivalent JavaScript Keycode.
use DDG::Goodie;
triggers any => 'keycode', 'keycodes', 'char', 'chars', 'charcode', 'charcodes';
zci is_cached => 1;
my $html;
my $text;
my $key;
my $value;
triggers any => 'keycode', 'keycodes', 'char', 'chars', 'charcode', 'charcodes';
my %keys = ('backspace' => '8',
'tab' => '9',
'enter' => '13',
@ -127,6 +129,4 @@ handle remainder => sub {
return;
};
zci is_cached => 1;
1;

25
lib/DDG/Goodie/Morse.pm Normal file
View File

@ -0,0 +1,25 @@
package DDG::Goodie::Morse;
# ABSTRACT: Converts to/from Morse code
use DDG::Goodie;
use Convert::Morse qw(is_morse as_ascii as_morse);
attribution
web => 'http://und3f.com',
twitter => 'und3f',
github => 'und3f',
cpan => 'UNDEF';
triggers startend => 'morse';
zci is_cached => 1;
zci answer_type => 'chars';
handle remainder => sub {
return unless $_;
my $convertor = is_morse($_) ? \&as_ascii : \&as_morse;
return "Morse: " . $convertor->($_);
};
1;

View File

@ -1,10 +1,10 @@
package DDG::Goodie::NLetterWords;
use DDG::Goodie;
use Lingua::EN::Numericalize;
triggers end => "words", "word";
zci is_cached => 0;
handle query_parts => sub {

View File

@ -6,8 +6,9 @@ use DDG::Goodie;
triggers any => 'palindrome';
handle query => sub {
zci is_cached => 1;
handle query => sub {
#Remove the trigger text from the query.
return unless /^(?:is\s+|)(.*?)\s+an?\s*palindrome\??$/i;
@ -25,6 +26,4 @@ handle query => sub {
return $is_palindrome ? qq("$palindrome" is a palindrome.) : qq("$palindrome" is not a palindrome.);
};
zci is_cached => 1;
1;

View File

@ -13,7 +13,9 @@ my @mon = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
my @day = qw(Mon Tue Wed Thu Fri Sat Sun);
triggers start => 'crontab', 'cron', 'cronjob';
zci is_cached => 0;
handle remainder => sub {
my $crontab = $_;
# We replace Jan,Feb.. and Mon,Tue.. with 1,2..

View File

@ -2,18 +2,16 @@ package DDG::Goodie::PercentError;
use DDG::Goodie;
triggers start => "percent", "%", "percent-error", "% error", "%err";
triggers start => "percent error", "% error", "%err", "%error", "percenterror";
zci answer_type => "percent_error";
zci is_cached => 1;
handle query_parts => sub {
shift;
shift if $_[0] eq 'error' || $_[0] eq 'err';
my $length = @_;
return unless $length == 2;
handle remainder => sub {
my $length = length($_);
#return unless $length == 2;
my ( $acc, $exp ) = @_;
my ( $acc, $exp ) = split ' ', $_;
$acc =~ s/[{},;\s]+//g;
$exp =~ s/[{},;\s]+//g;
return unless $acc =~ /^-?\d+?(?:\.\d+|)$/ && $exp =~ /^-?\d+?(?:\.\d+|)$/;

View File

@ -6,6 +6,7 @@ triggers start => "perimeter", "circumference";
zci is_cached => 1;
zci answer_type => "perimeter";
handle query_lc => sub {
if ($_ =~ m/^(?:circumference (?:of\s|)(?:circle\s|)(\d+(?:\.\d+)?))|(?:(perimeter) (?:of\s|)(?:(square|circle|pentagon|hexagon|octagon) (\d+(?:\.\d+)?)|(rectangle) (\d+(?:\.\d+)?)[,;]?\s(\d+(?:\.\d+)?)|(triangle) (\d+(?:\.\d+)?)[,;]?\s(\d+(?:\.\d+)?)[,;]?\s(\d+(?:\.\d+)?)))$/) {
my %polygons = ("pentagon" => 5, "hexagon" => 6, "octagon" => 8);

View File

@ -2,8 +2,11 @@ package DDG::Goodie::Phonetic;
# ABSTRACT: Take a string and spell it out phonetically using the NATO alphabet
use DDG::Goodie;
triggers start => 'phonetic';
zci is_cached => 1;
handle remainder => sub {
sub components {
$_ = lc($_);
@ -58,6 +61,4 @@ handle remainder => sub {
return;
};
zci is_cached => 1;
1;

View File

@ -5,7 +5,6 @@ use DDG::Goodie;
triggers query_clean => qr/^private (?:network|ip)s?\s*(?:(?:ips?|addresse?s?))?$/i;
zci is_cached => 1;
zci answer_type => "private_network";
handle sub {

View File

@ -7,7 +7,6 @@ use IO::All;
triggers query_clean => qr/^(?:google|opendns|norton|dns advantage)?\s*public dns\s*(?:servers?)?$/i;
zci is_cached => 1;
zci answer_type => "public_dns";
handle sub {

View File

@ -3,9 +3,10 @@ package DDG::Goodie::Reverse;
use DDG::Goodie;
triggers startend => "reverse";
zci is_cached => 1;
zci answer_type => "reverse";
triggers startend => "reverse";
handle remainder => sub { qq|Reversed "$_": | . scalar reverse };

View File

@ -7,6 +7,7 @@ triggers any => "roman", "arabic";
zci is_cached => 1;
zci answer_type => "roman_numeral_conversion";
handle remainder => sub {
s/\s*(?:numeral|number)\s*//i;
return uc(roman($_)) . ' (roman numeral conversion)' if /^\d+$/ && roman($_);

View File

@ -5,17 +5,14 @@ use DDG::Goodie;
triggers start => 'rot13';
zci is_cached => 1;
handle remainder => sub {
if ($_)
{
if ($_) {
$_ =~ tr[a-zA-Z][n-za-mN-ZA-M];
return "ROT13: $_";
};
return;
};
zci is_cached => 1;
1;

View File

@ -8,10 +8,12 @@ triggers start => "rcube";
zci is_cached => 1;
zci answer_type => "rubiks_cube";
handle remainder => sub {
return "F U F R L2 B D' R D2 L D' B R2 L F U F" if lc($_) eq "stripes";
return "F L F U' R U F2 L2 U' L' B D' B' L2 U" if lc($_) eq "cube in a cube";
return "U D' R L' F B' U D'" if lc($_) eq "swap centers";
return;
};
1;

View File

@ -3,8 +3,10 @@ package DDG::Goodie::SigFigs;
use DDG::Goodie;
triggers start => 'sigfigs', 'sigdigs', 'sf', 'sd', 'significant';
zci answer_type => "sig_figs";
zci is_cached => 1;
handle remainder => sub {
$_ =~ s/^(figures|digits)\s*//g;
return unless /^-?\d+(?:\.(?:\d+)?)?$/;

View File

@ -2,9 +2,10 @@ package DDG::Goodie::TitleCase;
use DDG::Goodie;
triggers startend => 'titlecase', 'ucfirst', 'title case';
zci is_cached => 1;
zci answer_type => "title_case";
triggers startend => 'title-case', 'titlecase', 'ucfirst';
handle remainder => sub { join(' ', map { ucfirst $_ } split(/ /, $_))};

View File

@ -8,6 +8,7 @@ use constant WPHREF => "http://en.wikipedia.org/wiki/List_of_UN_numbers_%04d_to_
triggers start => 'un';
zci is_cached => 1;
zci answer_type => 'united_nations';
handle remainder => sub {
@ -27,6 +28,4 @@ sub wphref {
return sprintf WPHREF, $lower, $upper;
}
zci is_cached => 1;
1;

View File

@ -21,7 +21,6 @@ triggers query_raw => CODEPOINT_RE;
triggers query_raw => UNICODE_RE;
zci is_cached => 1;
zci answer_type => "unicode_conversion";
handle sub {

View File

@ -4,10 +4,11 @@ package DDG::Goodie::Unidecode;
use DDG::Goodie;
use Text::Unidecode;
zci is_cached => 1;
zci answer_type => "convert to ascii";
triggers startend => "unidecode";
zci is_cached => 1;
zci answer_type => "convert_to_ascii";
handle remainder => sub {
my $u = unidecode $_;
# unidecode output sometimes contains trailing spaces

View File

@ -3,9 +3,10 @@ package DDG::Goodie::UnixTime;
use DDG::Goodie;
use DateTime;
triggers startend => "unixtime", "time", "timestamp", "datetime", "epoch", "unix time", "unix epoch";
zci answer_type => "time_conversion";
zci is_cached => 1;
triggers startend => "unixtime", "time", "timestamp", "datetime", "epoch";
handle remainder => sub {

22
t/ColorCodes.t Normal file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env perl
use strict;
use warnings;
use Test::More;
use DDG::Test::Goodie;
zci answer_type => 'color_code';
zci is_cached => 1;
ddg_goodie_test(
[qw(
DDG::Goodie::ColorCodes
)],
'hex color code for cyan' => test_zci("Hex: #00ffff, Red: 0, Green: 255, Blue: 255 ~ Hue: 180, Saturation: 1.00, Value: 0.50 ~ Cyan: 1.00, Magenta: 0.00, Yellow: 0.00, Black: 0.00", html => '<div style="background:#00ffff;border:2px solid #999;height:30px;width:30px;margin:5px;margin-right:10px;margin-top:3px;float:left;"></div>Hex: #00ffff, Red: 0, Green: 255, Blue: 255 ~ Hue: 180, Saturation: 1.00, Value: 0.50 ~ Cyan: 1.00, Magenta: 0.00, Yellow: 0.00, Black: 0.00'),
'rgb(173,216,230)' => test_zci("Hex: #add8e6, Red: 173, Green: 216, Blue: 230 ~ Hue: 194, Saturation: 0.53, Value: 0.79 ~ Cyan: 0.25, Magenta: 0.06, Yellow: 0.00, Black: 0.10", html => '<div style="background:#add8e6;border:2px solid #999;height:30px;width:30px;margin:5px;margin-right:10px;margin-top:3px;float:left;"></div>Hex: #add8e6, Red: 173, Green: 216, Blue: 230 ~ Hue: 194, Saturation: 0.53, Value: 0.79 ~ Cyan: 0.25, Magenta: 0.06, Yellow: 0.00, Black: 0.10'),
'hsl 194 0.53 0.79' => test_zci("Hex: #add8e5, Red: 173, Green: 216, Blue: 229 ~ Hue: 194, Saturation: 0.53, Value: 0.79 ~ Cyan: 0.25, Magenta: 0.06, Yellow: 0.00, Black: 0.10", html => '<div style="background:#add8e5;border:2px solid #999;height:30px;width:30px;margin:5px;margin-right:10px;margin-top:3px;float:left;"></div>Hex: #add8e5, Red: 173, Green: 216, Blue: 229 ~ Hue: 194, Saturation: 0.53, Value: 0.79 ~ Cyan: 0.25, Magenta: 0.06, Yellow: 0.00, Black: 0.10'),
);
done_testing;

21
t/Morse.t Normal file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use Test::More;
use DDG::Test::Goodie;
zci answer_type => 'chars';
zci is_cached => 1;
ddg_goodie_test(
[qw(
DDG::Goodie::Morse
)],
'morse ... --- ...' => test_zci('Morse: SOS'),
'morse hello, duck' =>
test_zci('Morse: .... . .-.. .-.. --- --..-- -.. ..- -.-. -.-'),
);
done_testing;

View File

@ -5,7 +5,7 @@ use warnings;
use Test::More;
use DDG::Test::Goodie;
zci answer_type => 'convert to ascii';
zci answer_type => 'convert_to_ascii';
zci is_cached => 1;