2014-07-28 06:29:05 +02:00
|
|
|
#!/usr/bin/env perl
|
|
|
|
|
|
|
|
use warnings;
|
|
|
|
use strict;
|
|
|
|
|
|
|
|
use Text::Levenshtein qw(fastdistance);
|
2014-08-04 08:25:56 +02:00
|
|
|
use Time::HiRes qw(gettimeofday);
|
2014-07-28 06:29:05 +02:00
|
|
|
|
|
|
|
my $CJEOPARDY_DATA = 'cjeopardy.dat';
|
2014-07-29 19:30:12 +02:00
|
|
|
my $CJEOPARDY_HINT = 'cjeopardy.hint';
|
2014-08-04 08:25:56 +02:00
|
|
|
my $CJEOPARDY_LAST_ANSWER = 'cjeopardy.last_ans';
|
2014-07-28 06:29:05 +02:00
|
|
|
|
2014-08-04 00:20:54 +02:00
|
|
|
my $hint_only_mode = 0;
|
|
|
|
|
2014-07-28 06:29:05 +02:00
|
|
|
my $channel = shift @ARGV;
|
2014-08-04 08:25:56 +02:00
|
|
|
my $nick = shift @ARGV;
|
2014-07-28 06:29:05 +02:00
|
|
|
my $text = join(' ', @ARGV);
|
|
|
|
|
|
|
|
sub encode { my $str = shift; $str =~ s/\\(.)/{sprintf "\\%03d", ord($1)}/ge; return $str; }
|
|
|
|
sub decode { my $str = shift; $str =~ s/\\(\d{3})/{"\\" . chr($1)}/ge; return $str }
|
|
|
|
|
|
|
|
if ($channel !~ /^#/) {
|
2014-08-31 22:21:09 +02:00
|
|
|
print "Sorry, C Jeopardy must be played in a channel. Feel free to join #cjeopardy.\n";
|
2014-07-28 06:29:05 +02:00
|
|
|
exit;
|
|
|
|
}
|
|
|
|
|
2014-12-30 08:19:32 +01:00
|
|
|
while($text =~ s/^\s*(is|are|the|a|an)\s+//i){};
|
2014-07-29 19:30:12 +02:00
|
|
|
$text =~ s/\s*\?*$//;
|
|
|
|
$text =~ s/^\s+//;
|
|
|
|
$text =~ s/\s+$//;
|
2014-08-04 00:20:54 +02:00
|
|
|
my $lctext = lc $text;
|
2014-07-29 19:30:12 +02:00
|
|
|
|
2014-08-04 00:20:54 +02:00
|
|
|
if (not length $lctext) {
|
2014-07-29 19:30:12 +02:00
|
|
|
print "What?\n";
|
|
|
|
exit;
|
|
|
|
}
|
2014-07-28 06:29:05 +02:00
|
|
|
|
|
|
|
my @data;
|
2014-08-04 08:25:56 +02:00
|
|
|
|
|
|
|
my $ret = open my $fh, "<", "$CJEOPARDY_LAST_ANSWER-$channel";
|
|
|
|
if (defined $ret) {
|
|
|
|
my $last_nick = <$fh>;
|
|
|
|
my $last_answers = <$fh>;
|
|
|
|
my $last_timestamp = <$fh>;
|
|
|
|
close $fh;
|
|
|
|
|
|
|
|
chomp $last_nick;
|
|
|
|
|
|
|
|
if(scalar gettimeofday - $last_timestamp <= 15) {
|
|
|
|
$ret = open $fh, "<", "$CJEOPARDY_DATA-$channel";
|
|
|
|
if (defined $ret) {
|
|
|
|
@data = <$fh>;
|
|
|
|
close $fh;
|
|
|
|
}
|
|
|
|
|
|
|
|
my @current_answers = map { decode $_ } split /\|/, encode $data[1] if @data;
|
|
|
|
my @valid_answers = map { decode $_ } split /\|/, encode $last_answers;
|
|
|
|
|
|
|
|
foreach my $answer (@valid_answers) {
|
|
|
|
chomp $answer;
|
|
|
|
$answer =~ s/\\\|/|/g;
|
|
|
|
$answer =~ s/\s*{.*}\s*//;
|
|
|
|
|
|
|
|
my $skip_last;
|
|
|
|
if (@current_answers) {
|
|
|
|
foreach my $current_answer (@current_answers) {
|
|
|
|
chomp $current_answer;
|
|
|
|
$current_answer =~ s/\\\|/|/g;
|
|
|
|
$current_answer =~ s/\s*{.*}\s*//;
|
|
|
|
|
|
|
|
my $distance = fastdistance(lc $answer, lc $current_answer);
|
|
|
|
my $length = (length($answer) > length($current_answer)) ? length $answer : length $current_answer;
|
|
|
|
|
|
|
|
if ($distance / $length < 0.15) {
|
|
|
|
$skip_last = 1;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
last if $skip_last;
|
|
|
|
|
|
|
|
my $distance = fastdistance($lctext, lc $answer);
|
|
|
|
my $length = (length($lctext) > length($answer)) ? length $lctext : length $answer;
|
|
|
|
|
|
|
|
if ($distance / $length < 0.15) {
|
|
|
|
if ($last_nick eq $nick) {
|
|
|
|
print "Er, you already correctly answered that question.\n";
|
|
|
|
} else {
|
|
|
|
print "Too slow! $last_nick got the correct answer.\n";
|
|
|
|
}
|
|
|
|
exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not @data) {
|
|
|
|
open $fh, "<", "$CJEOPARDY_DATA-$channel" or print "There is no open C Jeopardy question. Use `cjeopardy` to get a question.\n" and exit;
|
|
|
|
@data = <$fh>;
|
|
|
|
close $fh;
|
|
|
|
}
|
2014-07-28 06:29:05 +02:00
|
|
|
|
2014-07-29 21:00:06 +02:00
|
|
|
my @valid_answers = map { decode $_ } split /\|/, encode $data[1];
|
2014-07-28 06:29:05 +02:00
|
|
|
|
2014-08-31 22:21:09 +02:00
|
|
|
my $incorrect_percentage = 100;
|
|
|
|
|
2014-07-28 06:29:05 +02:00
|
|
|
foreach my $answer (@valid_answers) {
|
|
|
|
chomp $answer;
|
|
|
|
$answer =~ s/\\\|/|/g;
|
|
|
|
|
2014-08-04 00:20:54 +02:00
|
|
|
my $supplemental_text;
|
|
|
|
if ($answer =~ s/\s*{(.*)}\s*$//) {
|
|
|
|
$supplemental_text = $1;
|
|
|
|
}
|
|
|
|
|
|
|
|
my $distance = fastdistance($lctext, lc $answer);
|
|
|
|
my $length = (length($lctext) > length($answer)) ? length $lctext : length $answer;
|
2014-07-28 06:29:05 +02:00
|
|
|
|
2014-08-31 22:21:09 +02:00
|
|
|
my $percentage = $distance / $length * 100;
|
|
|
|
|
|
|
|
if ($percentage < $incorrect_percentage) {
|
|
|
|
$incorrect_percentage = $percentage;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($percentage < 15) {
|
2014-07-28 06:29:05 +02:00
|
|
|
if ($distance == 0) {
|
2014-08-04 00:20:54 +02:00
|
|
|
print "'$answer' is correct!";
|
|
|
|
} else {
|
|
|
|
print "'$text' is close enough to '$answer'. You are correct!"
|
|
|
|
}
|
|
|
|
|
|
|
|
if (defined $supplemental_text) {
|
|
|
|
print " $supplemental_text\n";
|
2014-07-28 06:29:05 +02:00
|
|
|
} else {
|
2014-08-04 00:20:54 +02:00
|
|
|
print "\n";
|
2014-07-28 06:29:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
unlink "$CJEOPARDY_DATA-$channel";
|
2014-07-29 19:30:12 +02:00
|
|
|
unlink "$CJEOPARDY_HINT-$channel";
|
2014-07-28 06:29:05 +02:00
|
|
|
|
2014-08-04 08:25:56 +02:00
|
|
|
open $fh, ">", "$CJEOPARDY_LAST_ANSWER-$channel" or die "Couldn't open $CJEOPARDY_LAST_ANSWER-$channel: $!";
|
|
|
|
my $time = scalar gettimeofday;
|
|
|
|
print $fh "$nick\n$data[1]$time\n";
|
|
|
|
close $fh;
|
|
|
|
|
2014-07-28 06:29:05 +02:00
|
|
|
if ($channel eq '#cjeopardy') {
|
|
|
|
my $question = `./cjeopardy.pl $channel`;
|
2014-08-04 00:20:54 +02:00
|
|
|
|
|
|
|
if ($hint_only_mode) {
|
|
|
|
my $hint = `./cjeopardy_hint.pl $channel`;
|
|
|
|
$hint =~ s/^Hint: //;
|
|
|
|
print "Next hint: $hint\n";
|
|
|
|
} else {
|
|
|
|
print "Next question: $question\n";
|
|
|
|
}
|
2014-07-28 06:29:05 +02:00
|
|
|
}
|
|
|
|
exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-31 22:21:09 +02:00
|
|
|
my $correct_percentage = 100 - $incorrect_percentage;
|
|
|
|
if ($correct_percentage >= 80) {
|
|
|
|
printf "Sorry, '$text' is %.1f%% correct. So close!\n", $correct_percentage;
|
|
|
|
} elsif ($correct_percentage >= 70) {
|
|
|
|
printf "Sorry, '$text' is %.1f%% correct. Almost.\n", $correct_percentage;
|
|
|
|
} elsif ($correct_percentage >= 50) {
|
|
|
|
printf "Sorry, '$text' is only %.1f%% correct.\n", $correct_percentage;
|
|
|
|
} else {
|
|
|
|
print "Sorry, '$text' is incorrect.\n";
|
|
|
|
}
|