Merge pull request #2642 from duckduckgo/gd/caesar-cipher-trigger-info

CaesarCipher: Add 'How to decode?' response
master
Rob Emery 2016-02-28 12:36:45 +00:00
commit 0ef3075361
4 changed files with 114 additions and 6 deletions

View File

@ -4,9 +4,10 @@ package DDG::Goodie::CaesarCipher;
use strict; use strict;
use DDG::Goodie; use DDG::Goodie;
triggers start => "caesar cipher", "caesar", triggers startend => "caesar cipher",
"ceasar", "ceasar cipher", "ceasar cipher",
"shift cipher"; "shift cipher";
triggers start => 'caesar', 'ceasar';
zci is_cached => 1; zci is_cached => 1;
zci answer_type => "caesar_cipher"; zci answer_type => "caesar_cipher";
@ -15,9 +16,53 @@ my @alphabet = ('a' ... 'z');
my $string_alphabet = join '', @alphabet; my $string_alphabet = join '', @alphabet;
handle remainder => sub { sub build_infobox_element {
return unless $_ =~ /(\-?\d+)\s+([[:ascii:]]+)$/; my $query = shift;
my ($shift_val, $to_cipher) = ($1, $2); my @split = split ' ', $query;
return {
label => $query,
url => 'https://duckduckgo.com/?q=' . (join '+', @split) . '&ia=answer',
};
}
my $infobox = [ { heading => "Example Queries", },
build_infobox_element('caesar cipher 2 text'),
build_infobox_element('shift cipher -2 vgzv'),
build_infobox_element('caesar cipher 33 secret'),
build_infobox_element('caesar cipher -7 zljyla'),
];
my @description_pars = split "\n\n",
share('description.txt')->slurp();
my $decode_response = {
id => 'caesar_cipher',
name => 'Answer',
data => {
title => "How to decode the caesar cipher",
infoboxData => $infobox,
description_pars => \@description_pars,
},
meta => {
sourceUrl => 'https://en.wikipedia.org/wiki/Caesar_cipher',
sourceName => 'Wikipedia',
},
templates => {
group => 'info',
options => {
content => 'DDH.caesar_cipher.content',
chompContent => 1,
},
},
};
sub wants_decode {
my $query = shift;
return $query =~ /^how to ((de|en)(code|crypt)|use)( (a|the))?|(de|en)(coder?|crypt(er)?)$/i;
}
sub perform_caesar {
my ($to_cipher, $shift_val) = @_;
my $amount = $shift_val % 26; my $amount = $shift_val % 26;
# This creates the cipher by shifting the alphabet. # This creates the cipher by shifting the alphabet.
@ -33,6 +78,18 @@ handle remainder => sub {
} }
$result .= $char; $result .= $char;
} }
return $result;
}
handle remainder => sub {
my $remainder = shift;
my $wants_decode = wants_decode($remainder);
return "Caesar Cipher", structured_answer => $decode_response if $wants_decode;
return unless $remainder =~ /(\-?\d+)\s+([[:ascii:]]+)$/;
my ($shift_val, $to_cipher) = ($1, $2);
my $result = perform_caesar($to_cipher, $shift_val);
return "$result", return "$result",
structured_answer => { structured_answer => {

View File

@ -0,0 +1,3 @@
{{#each description_pars}}
<p>{{this}}</p>
{{/each}}

View File

@ -0,0 +1,17 @@
The Caesar cipher (named after Julius Caesar) is one of the most basic
ciphers. It is a form of substitution cipher in which each letter of
the alphabet is replaced with another letter a fixed number of places
before or after it.
If you are given the key for a Caesar cipher, then decrypting the
message is easy: first take 26 away from the key until you are left
with a number between 0 and 25 (add 26 each time for negative keys),
then shift each letter by the resulting number in the opposite
direction. For example, if you had the text "zljyla", and you knew the
key was 33, then taking 26 away from 33 you get 7 - which is between 0
and 25. Replacing each letter of the message with that 7 places before
it you get the decrypted message "secret".
If you don't know the key you can perform frequency analysis on the
encrypted message or just try every possible key (there's only 26
combinations!).

View File

@ -8,6 +8,27 @@ use DDG::Test::Goodie;
zci answer_type => 'caesar_cipher'; zci answer_type => 'caesar_cipher';
zci is_cached => 1; zci is_cached => 1;
my $decode_response = {
id => 'caesar_cipher',
name => 'Answer',
data => '-ANY-', # We only need to check it is the right template.
meta => {
sourceUrl => 'https://en.wikipedia.org/wiki/Caesar_cipher',
sourceName => 'Wikipedia',
},
templates => {
group => 'info',
options => {
content => 'DDH.caesar_cipher.content',
chompContent => 1,
},
},
};
sub decode_response {
return "Caesar Cipher", structured_answer => $decode_response;
}
sub build_structured_answer { sub build_structured_answer {
my ($result, $amount, $to_cipher) = @_; my ($result, $amount, $to_cipher) = @_;
return "$result", return "$result",
@ -26,6 +47,7 @@ sub build_structured_answer {
} }
sub build_test { test_zci(build_structured_answer(@_)) } sub build_test { test_zci(build_structured_answer(@_)) }
sub decode_test { test_zci(decode_response()) }
ddg_goodie_test( ddg_goodie_test(
[qw( DDG::Goodie::CaesarCipher )], [qw( DDG::Goodie::CaesarCipher )],
@ -41,6 +63,15 @@ ddg_goodie_test(
'shift cipher 7 Mxlm mxqm' => build_test('Test text', 7, 'Mxlm mxqm'), 'shift cipher 7 Mxlm mxqm' => build_test('Test text', 7, 'Mxlm mxqm'),
'caesar cipher hello' => undef, 'caesar cipher hello' => undef,
'caesar cipher' => undef, 'caesar cipher' => undef,
# Decoding information tests
'how to decode a caesar cipher?' => decode_test(),
'How to decode a Caesar cipher?' => decode_test(),
'how to use a shift cipher' => decode_test(),
'how to encrypt the caesar cipher' => decode_test(),
'caesar cipher decoder' => decode_test(),
'shift cipher encrypter' => decode_test(),
'shift cipher decrypt' => decode_test(),
'how to decode caesar' => undef,
); );
done_testing; done_testing;