Colourcodes: new query patterns (#4453)
* ColorCodes: Cleaning out comments and some minor refactoring * ColorCodes: Tabs -> spaces and failing test for #190 * ColorCodes: We need more control over the actual query handling so I want the raw query * ColorCodes: red: \d green: \d blue: \d queries now work * ColorCodes: refactoring out the need for capturing the inversion words * ColorCodes: Removing unnecessary hash * ColourCodes: Attempting to push as much limiting and protection as early as possible * ColourCodes: Layout tinkering * ColorCodes: Matches can be wider now we're planning to use named captures * ColorCodes: Adding named captures for loop removal * ColorCodes: Converting to use just the named captures; tests failing * ColorCodes: need to map the type for cmyk * ColorCodes: Layout * ColorCodes: RGBA can be implemented as an alias now in the regex :D * ColorCodes: Will now respond to bluishblack html not just html bluishblack! * ColorCodes: This regex case seems to make no difference to passing tests or query patterns * ColorCodes: Types are case sensitive! * ColorCodes: Using the matches we can construct a colour without hacking the input query * ColorCodes: We can use the matches for detecting inversion * ColorCodes: Rearranging * ColorCodes: Removing unused * ColorCodes: Bit of cleaning * ColorCodes: Don't need to do this in the else anymore, we can do it before! * ColorCodes: show -> to flip the ternary * ColorCodes: Adding tests for #3758 * ColourCodes: Switching to query_lc * ColourCodes: Regex refactormaster
parent
781856b4e0
commit
85f28710a6
|
@ -13,6 +13,7 @@ use Math::Round;
|
|||
use Try::Tiny;
|
||||
|
||||
my %types = ( # hash of keyword => Convert::Color prefix
|
||||
rgba => 'rgb8',
|
||||
rgb => 'rgb8',
|
||||
hex => 'rgb8',
|
||||
html => 'rgb8',
|
||||
|
@ -23,7 +24,7 @@ my %types = ( # hash of keyword => Convert::Color prefix
|
|||
cmy => 'cmy',
|
||||
cmyk => 'cmyk',
|
||||
cmyb => 'cmyk',
|
||||
);
|
||||
);
|
||||
|
||||
# Eliminate NBS_ISCC sub-dictionaries from our lookups.
|
||||
# They contain "idiosyncratic" color names (including 'email' in NBS_ISCC::M) which will
|
||||
|
@ -31,88 +32,70 @@ my %types = ( # hash of keyword => Convert::Color prefix
|
|||
my $color_dictionaries = join(',', grep { $_ !~ /^nbs-iscc-/ } map { $_->id } Color::Library->dictionaries);
|
||||
|
||||
my $typestr = join '|', sort { length $b <=> length $a } keys %types;
|
||||
$typestr =~ s/([#\^\$\*\+\?])/\\$1/g;
|
||||
|
||||
triggers query_raw => qr/^
|
||||
my $inverse_words = qr/inverse|negative|opposite/;
|
||||
|
||||
my $trigger_and_guard = qr/^
|
||||
(?:what(?:\si|'?)s \s* (?:the)? \s+)? # what's the, whats the, what is the, what's, what is, whats
|
||||
(?:(inverse|negative|opposite)\s+(?:of)?)?
|
||||
(?<inv>$inverse_words\s+(?:of)?(?:\s?the\s?)?)?
|
||||
(?:
|
||||
(.*?)\s*(.+?)\bcolou?r(?:\s+code)?| # handles "rgb red color code", "red rgb color code", etc
|
||||
(.*?)\s*(.+?)\brgb(?:\s+code)?| # handles "red rgb code", etc
|
||||
(.*?)\s*colou?r(?:\s+code)?(?:\s+for)?\s+(.+?)| # handles "rgb color code for red", "red color code for html", etc
|
||||
(.*?)(rgba)\s*:?\s*\(?\s*(.+?)\s*\)?| # handles "rgba( red )", "rgba:255,0,0", "rgba(255 0 0)", etc
|
||||
([^\s]*?)\s*($typestr)\s*:?\s*\(?\s*(.+?)\s*\)?|# handles "rgb( red )", "rgb:255,0,0", "rgb(255 0 0)", etc
|
||||
\#?([0-9a-f]{6})|\#([0-9a-f]{3}) # handles #00f, #0000ff, etc
|
||||
red:\s*(?<r>[0-9]{1,3})\s*green:\s*(?<g>[0-9]{1,3})\s*blue:\s*(?<b>[0-9]{1,3})| # handles red: x green: y blue: z
|
||||
(?<type>$typestr)\s*colou?r(?:\s+code)?(?:\s+for)?\s+(?<color>.+?)| # handles "rgb color code for red", "red color code for html", etc
|
||||
(?<type>$typestr)\s*:?\s*\(?\s*(?<color>.+?)\s*\)?| # handles "rgb( red )", "rgb:255,0,0", "rgb(255 0 0)", etc
|
||||
(?<color>.+?)\b(rgb|css|html)(?:\s+code)?| # handles "red rgb code", etc
|
||||
\#?(?<color>[0-9a-f]{6})|\#(?<color>[0-9a-f]{3}) # handles #00f, #0000ff, etc
|
||||
)
|
||||
(?:(?:'?s)?\s+(inverse|negative|opposite))?
|
||||
(?<inv>(?:'?s)?\s+$inverse_words)?
|
||||
(?:\sto\s(?:$typestr))?
|
||||
$/ix;
|
||||
$/ix;
|
||||
|
||||
triggers query_raw => $trigger_and_guard;
|
||||
|
||||
zci is_cached => 1;
|
||||
zci answer_type => 'color_code';
|
||||
|
||||
my %trigger_invert = map { $_ => 1 } (qw( inverse negative opposite ));
|
||||
my %trigger_filler = map { $_ => 1 } (qw( code ));
|
||||
|
||||
my $color_mix = Color::Mix->new;
|
||||
|
||||
sub percentify {
|
||||
my @out;
|
||||
push @out, ($_ <= 1 ? round(($_ * 100))."%" : round($_)) for @_;
|
||||
return @out;
|
||||
return map { ($_ <= 1 ? round(($_ * 100))."%" : round($_)) } @_;
|
||||
}
|
||||
|
||||
handle matches => sub {
|
||||
handle query_lc => sub {
|
||||
|
||||
my $color;
|
||||
my $filler_count;
|
||||
my $inverse;
|
||||
|
||||
my $type = 'rgb8'; # Default type, can be overridden below.
|
||||
my @matches = @_;
|
||||
|
||||
s/\sto\s(?:$typestr)//;
|
||||
|
||||
$filler_count = 0;
|
||||
foreach my $q (map { lc $_ } grep { defined $_ } @matches) {
|
||||
# $q now contains the defined normalized matches which can be:
|
||||
if (exists $types{$q}) {
|
||||
$type = $types{$q}; # - One of our types.
|
||||
} elsif ($trigger_invert{$q}) {
|
||||
$inverse = 1; # - An inversion trigger
|
||||
} elsif (!$trigger_filler{$q}) { # - A filler word for more natural querying
|
||||
if ($q =~ /(?:^[a-z]+\s)+/) {
|
||||
$filler_count = $filler_count + 1;
|
||||
} else {
|
||||
$color = $q; # - A presumed color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return unless $color; # Need a color to continue!
|
||||
$color =~ s/\sto\s//;
|
||||
|
||||
return if $filler_count;
|
||||
|
||||
my $alpha = "1";
|
||||
$color =~ s/(,\s*|\s+)/,/g; # Spaces to commas for things like "hsl 194 0.53 0.79"
|
||||
if ($color =~ s/#?([0-9a-f]{3,6})$/$1/) { # Color looks like a hex code, strip the leading #
|
||||
$color = join('', map { $_ . $_ } (split '', $color)) if (length($color) == 3); # Make three char hex into six chars by repeating each in turn
|
||||
$type = 'rgb8';
|
||||
} elsif ($color =~ s/([0-9]+,[0-9]+,[0-9]+),([0]?\.[0-9]+)/$alpha = $2; $1/e) { #hack rgba into rgb and extract alpha
|
||||
my $inverse = 0;
|
||||
my $type = 'rgb8';
|
||||
|
||||
s/\sto\s(?:$typestr)?//g;
|
||||
|
||||
$_ =~ $trigger_and_guard;
|
||||
|
||||
$type = lc $+{'type'} if defined $+{'type'} and exists $types{lc $+{'type'}};
|
||||
|
||||
$color = "$+{'r'} $+{'g'} $+{'b'}" if defined $+{'r'} and defined $+{'g'} and defined $+{'b'};
|
||||
$color = lc $+{'color'} if defined $+{'color'};
|
||||
|
||||
$inverse = 1 if defined $+{'inv'};
|
||||
|
||||
$color =~ s/,?\s+/,/g;
|
||||
$color =~ s/([0-9]+,[0-9]+,[0-9]+),([0]?\.[0-9]+)/$alpha = $2; $1/e;
|
||||
|
||||
if ($color =~ s/#?([0-9a-f]{3,6})$/$1/) {
|
||||
$color = join('', map { $_ . $_ } (split '', $color)) if (length($color) == 3);
|
||||
$type = 'rgb8';
|
||||
} else {
|
||||
try {
|
||||
# See if we can find the color in one of our dictionaries.
|
||||
$color = join(',', Convert::Color::Library->new($color_dictionaries . '/' . $color)->as_rgb8->hex);
|
||||
$type = 'rgb8'; # We asked for rgb8 from our dictionary, so make sure our type matches.
|
||||
$type = 'rgb8';
|
||||
};
|
||||
}
|
||||
|
||||
my $col = try { Convert::Color->new("$type:$color") }; # Everything should be ready for conversion now.
|
||||
return unless $col; # Guess not.
|
||||
my $col = try { Convert::Color->new("$type:$color") };
|
||||
|
||||
return unless $col;
|
||||
|
||||
if ($inverse) { # We triggered on the inverse, so do the flip.
|
||||
if ($inverse) {
|
||||
my $orig_rgb = $col->as_rgb8;
|
||||
$col = Convert::Color::RGB8->new(255 - $orig_rgb->red, 255 - $orig_rgb->green, 255 - $orig_rgb->blue);
|
||||
}
|
||||
|
@ -138,13 +121,9 @@ handle matches => sub {
|
|||
$complementary = uc($complementary);
|
||||
|
||||
#greyscale colours have no hue and saturation
|
||||
my $show_column_2 = !($hsl[0] eq 0 && $hsl[1] eq '0%');
|
||||
my $hide_column_2 = ($hsl[0] eq 0 && $hsl[1] eq '0%');
|
||||
|
||||
my $column_2 = '';
|
||||
|
||||
if ($show_column_2) {
|
||||
$column_2 = "\n" . "Complementary: #$complementary" . "\n" . "Analogous: #$analogous[0], #$analogous[1]";
|
||||
}
|
||||
my $column_2 = $hide_column_2 ? "" : "\nComplementary: #$complementary\nAnalogous: #$analogous[0], #$analogous[1]";
|
||||
|
||||
return "$hexc ~ $rgb ~ $rgb_pct ~ $hslc ~ $cmyb$column_2",
|
||||
structured_answer => {
|
||||
|
@ -154,7 +133,7 @@ handle matches => sub {
|
|||
rgb => $rgb,
|
||||
hslc => $hslc,
|
||||
cmyb => $cmyb,
|
||||
show_column_2 => $show_column_2,
|
||||
show_column_2 => !$hide_column_2,
|
||||
analogous => \@analogous,
|
||||
complementary => $complementary,
|
||||
},
|
||||
|
|
|
@ -9,7 +9,6 @@ use DDG::Test::Goodie;
|
|||
zci answer_type => 'color_code';
|
||||
zci is_cached => 1;
|
||||
|
||||
|
||||
my $green_answer = 'Hex: #00FF00 ~ RGBA(0, 255, 0, 1) ~ RGB(0%, 100%, 0%) ~ HSL(120, 100%, 50%) ~ CMYB(100%, 0%, 100%, 0%)'."\n".'Complementary: #FF00FF'."\n".'Analogous: #00FF80, #80FF00';
|
||||
|
||||
my %basic_answer = (
|
||||
|
@ -48,7 +47,7 @@ sub green_args {
|
|||
|
||||
|
||||
ddg_goodie_test(
|
||||
[qw(DDG::Goodie::ColorCodes)],
|
||||
[qw(DDG::Goodie::ColorCodes)],
|
||||
'hex color code for cyan' => test_zci(
|
||||
'Hex: #00FFFF ~ RGBA(0, 255, 255, 1) ~ RGB(0%, 100%, 100%) ~ HSL(180, 100%, 50%) ~ CMYB(100%, 0%, 0%, 0%)'."\n".'Complementary: #FF0000'."\n".'Analogous: #0080FF, #00FF80',
|
||||
%basic_answer
|
||||
|
@ -77,6 +76,10 @@ ddg_goodie_test(
|
|||
'Hex: #202428 ~ RGBA(32, 36, 40, 1) ~ RGB(13%, 14%, 16%) ~ HSL(210, 11%, 14%) ~ CMYB(20%, 10%, 0%, 84%)'."\n".'Complementary: #292521'."\n".'Analogous: #212129, #212929',
|
||||
%basic_answer
|
||||
),
|
||||
'bluishblack html' => test_zci(
|
||||
'Hex: #202428 ~ RGBA(32, 36, 40, 1) ~ RGB(13%, 14%, 16%) ~ HSL(210, 11%, 14%) ~ CMYB(20%, 10%, 0%, 84%)'."\n".'Complementary: #292521'."\n".'Analogous: #212129, #212929',
|
||||
%basic_answer
|
||||
),
|
||||
# Single full HTML check.
|
||||
'red html code' => test_zci(
|
||||
'Hex: #FF0000 ~ RGBA(255, 0, 0, 1) ~ RGB(100%, 0%, 0%) ~ HSL(0, 100%, 50%) ~ CMYB(0%, 100%, 100%, 0%)'."\n".'Complementary: #00FFFF'."\n".'Analogous: #FF8000, #FF0080',
|
||||
|
@ -86,18 +89,26 @@ ddg_goodie_test(
|
|||
'Hex: #633CB0 ~ RGBA(99, 60, 176, 0.5) ~ RGB(39%, 24%, 69%) ~ HSL(260, 49%, 46%) ~ CMYB(44%, 66%, 0%, 31%)'."\n".'Complementary: #89B03C'."\n".'Analogous: #9D3CB0, #3C4FB0',
|
||||
%basic_answer
|
||||
),
|
||||
'#dc5f3c' => test_zci(
|
||||
'Hex: #DC5F3C ~ RGBA(220, 95, 60, 1) ~ RGB(86%, 37%, 24%) ~ HSL(13, 70%, 55%) ~ CMYB(0%, 57%, 73%, 14%)'."\n".'Complementary: #3BB9DB'."\n".'Analogous: #DBAE3B, #DB3B69',
|
||||
'#dc5f3c' => test_zci(
|
||||
'Hex: #DC5F3C ~ RGBA(220, 95, 60, 1) ~ RGB(86%, 37%, 24%) ~ HSL(13, 70%, 55%) ~ CMYB(0%, 57%, 73%, 14%)'."\n".'Complementary: #3BB9DB'."\n".'Analogous: #DBAE3B, #DB3B69',
|
||||
%basic_answer
|
||||
),
|
||||
#Colours with no hue shouldn't have complements or analogs
|
||||
),
|
||||
#Colours with no hue shouldn't have complements or analogs
|
||||
'#000000' => test_zci(
|
||||
'Hex: #000000 ~ RGBA(0, 0, 0, 1) ~ RGB(0%, 0%, 0%) ~ HSL(0, 0%, 0%) ~ CMYB(0%, 0%, 0%, 100%)',
|
||||
%basic_answer
|
||||
),
|
||||
'#FFFFFF' => test_zci(
|
||||
'#FFFFFF' => test_zci(
|
||||
'Hex: #FFFFFF ~ RGBA(255, 255, 255, 1) ~ RGB(100%, 100%, 100%) ~ HSL(0, 0%, 100%) ~ CMYB(0%, 0%, 0%, 0%)',
|
||||
%basic_answer
|
||||
%basic_answer
|
||||
),
|
||||
'red: 255 green: 255 blue: 255' => test_zci(
|
||||
'Hex: #FFFFFF ~ RGBA(255, 255, 255, 1) ~ RGB(100%, 100%, 100%) ~ HSL(0, 0%, 100%) ~ CMYB(0%, 0%, 0%, 0%)',
|
||||
%basic_answer
|
||||
),
|
||||
'red: 99 green: 60 blue: 176' => test_zci(
|
||||
'Hex: #633CB0 ~ RGBA(99, 60, 176, 1) ~ RGB(39%, 24%, 69%) ~ HSL(260, 49%, 46%) ~ CMYB(44%, 66%, 0%, 31%)'."\n".'Complementary: #89B03C'."\n".'Analogous: #9D3CB0, #3C4FB0',
|
||||
%basic_answer
|
||||
),
|
||||
# Check the content of the structured answer. Just once.
|
||||
'hsl 194 0.53 0.79' => test_zci(
|
||||
|
@ -106,13 +117,14 @@ ddg_goodie_test(
|
|||
),
|
||||
|
||||
# Queries to ignore.
|
||||
'bluishblack html' => undef,
|
||||
'HTML email' => undef,
|
||||
'wield color' => undef,
|
||||
'whats the symbolism of the color red' => undef,
|
||||
'red color porsche 911' => undef,
|
||||
'yoda lightsaber green color' => undef,
|
||||
'product red color iphone' => undef,
|
||||
'w3 html5.1' => undef,
|
||||
'w3c html5.1' => undef
|
||||
);
|
||||
|
||||
done_testing;
|
||||
|
|
Loading…
Reference in New Issue