2014-07-28 06:29:05 +02:00
|
|
|
#!/usr/bin/env perl
|
|
|
|
|
|
|
|
use warnings;
|
|
|
|
use strict;
|
|
|
|
|
|
|
|
use Time::HiRes qw/gettimeofday/;
|
2014-07-28 09:45:05 +02:00
|
|
|
use Time::Duration qw/duration/;
|
2015-01-30 06:55:46 +01:00
|
|
|
use Fcntl qw(:flock);
|
2014-07-28 06:29:05 +02:00
|
|
|
|
2015-01-28 09:40:40 +01:00
|
|
|
use IRCColors;
|
2015-05-23 11:27:53 +02:00
|
|
|
use QStatskeeper;
|
2015-01-28 09:40:40 +01:00
|
|
|
|
2014-07-28 17:25:54 +02:00
|
|
|
my $CJEOPARDY_FILE = 'cjeopardy.txt';
|
2015-01-28 09:40:40 +01:00
|
|
|
my $CJEOPARDY_DATA = 'data/cjeopardy.dat';
|
|
|
|
my $CJEOPARDY_SHUFFLE = 'data/cjeopardy.shuffle';
|
2014-07-28 06:29:05 +02:00
|
|
|
|
2014-07-28 09:45:05 +02:00
|
|
|
my $TIMELIMIT = 300;
|
|
|
|
|
2014-07-28 06:29:05 +02:00
|
|
|
my $channel = shift @ARGV;
|
|
|
|
my $text = join(' ', @ARGV);
|
|
|
|
|
2014-08-04 00:20:54 +02:00
|
|
|
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 }
|
|
|
|
|
2014-07-28 06:29:05 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-01-30 06:55:46 +01:00
|
|
|
open my $semaphore, ">", "$CJEOPARDY_DATA-$channel.lock" or die "Couldn't create semaphore lock: $!";
|
|
|
|
flock $semaphore, LOCK_EX;
|
|
|
|
|
2014-07-28 09:45:05 +02:00
|
|
|
my $ret = open my $fh, "<", "$CJEOPARDY_DATA-$channel";
|
|
|
|
if (defined $ret) {
|
|
|
|
my $last_question = <$fh>;
|
|
|
|
my $last_answer = <$fh>;
|
|
|
|
my $last_timestamp = <$fh>;
|
|
|
|
|
|
|
|
if (scalar gettimeofday - $last_timestamp <= $TIMELIMIT) {
|
|
|
|
my $duration = duration($TIMELIMIT - scalar gettimeofday - $last_timestamp);
|
2015-01-31 03:40:19 +01:00
|
|
|
print "$color{magneta}The current question is$color{reset}: $last_question";
|
2015-01-28 09:40:40 +01:00
|
|
|
print "$color{red}You may request a new question in $duration.$color{reset}\n";
|
2014-07-28 09:45:05 +02:00
|
|
|
close $fh;
|
|
|
|
exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-28 17:25:54 +02:00
|
|
|
my $question_index;
|
|
|
|
|
|
|
|
if (not length $text) {
|
|
|
|
$ret = open $fh, "<", "$CJEOPARDY_SHUFFLE-$channel";
|
|
|
|
if (defined $ret) {
|
|
|
|
my @indices = <$fh>;
|
|
|
|
$question_index = shift @indices;
|
|
|
|
close $fh;
|
|
|
|
|
|
|
|
if (not @indices) {
|
2015-01-28 09:40:40 +01:00
|
|
|
print "$color{teal}(Shuffling.)$color{reset}\n";
|
2014-07-28 17:25:54 +02:00
|
|
|
shuffle_questions(0);
|
|
|
|
} else {
|
|
|
|
open my $fh, ">", "$CJEOPARDY_SHUFFLE-$channel" or print "Failed to shuffle questions.\n" and exit;
|
|
|
|
foreach my $index (@indices) {
|
|
|
|
print $fh $index;
|
|
|
|
}
|
|
|
|
close $fh;
|
|
|
|
}
|
|
|
|
} else {
|
2015-01-28 09:40:40 +01:00
|
|
|
print "$color{teal}(Shuffling!)$color{reset}\n";
|
2014-07-28 17:25:54 +02:00
|
|
|
$question_index = shuffle_questions(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-28 06:29:05 +02:00
|
|
|
my @questions;
|
2014-07-28 09:45:05 +02:00
|
|
|
open $fh, "<", $CJEOPARDY_FILE or die "Could not open $CJEOPARDY_FILE: $!";
|
2014-07-28 06:29:05 +02:00
|
|
|
while (my $question = <$fh>) {
|
2014-08-04 00:20:54 +02:00
|
|
|
my ($question_only) = map { decode $_ } split /\|/, encode($question), 2;
|
|
|
|
$question_only =~ s/\\\|/|/g;
|
2014-07-28 06:29:05 +02:00
|
|
|
next if length $text and $question_only !~ /\Q$text\E/i;
|
|
|
|
push @questions, $question;
|
|
|
|
}
|
|
|
|
close $fh;
|
|
|
|
|
|
|
|
if (not @questions) {
|
|
|
|
print "No questions containing '$text' found.\n";
|
|
|
|
exit;
|
|
|
|
}
|
|
|
|
|
2014-07-28 17:25:54 +02:00
|
|
|
if (length $text) {
|
|
|
|
$question_index = int rand(@questions);
|
|
|
|
}
|
|
|
|
|
|
|
|
my $question = $questions[$question_index];
|
2014-07-28 06:29:05 +02:00
|
|
|
|
2014-08-04 00:20:54 +02:00
|
|
|
my ($q, $a) = map { decode $_ } split /\|/, encode($question), 2;
|
2014-07-28 06:29:05 +02:00
|
|
|
chomp $q;
|
|
|
|
chomp $a;
|
|
|
|
|
2014-08-04 00:20:54 +02:00
|
|
|
$q =~ s/\\\|/|/g;
|
2015-05-23 11:27:53 +02:00
|
|
|
$q =~ s/^(\d+)\) \[.*?\]\s+/$1) /;
|
|
|
|
my $id = $1;
|
2014-08-04 00:20:54 +02:00
|
|
|
|
2015-05-22 12:58:28 +02:00
|
|
|
$q =~ s/\b(this keyword|this operator|this behavior|this preprocessing directive|this escape sequence|this mode|this function specifier|this function|this macro|this predefined macro|this header|this pragma|this fprintf length modifier|this storage duration|this type qualifier|this type|this value|this operand|this many|this|these)\b/$color{bold}$1$color{reset}/gi;
|
2014-07-28 06:29:05 +02:00
|
|
|
print "$q\n";
|
|
|
|
|
|
|
|
open $fh, ">", "$CJEOPARDY_DATA-$channel" or die "Could not open $CJEOPARDY_DATA-$channel: $!";
|
2014-07-28 09:45:05 +02:00
|
|
|
print $fh "$q\n";
|
2014-07-28 06:29:05 +02:00
|
|
|
print $fh "$a\n";
|
2014-07-28 09:45:05 +02:00
|
|
|
print $fh scalar gettimeofday, "\n";
|
2014-07-28 06:29:05 +02:00
|
|
|
close $fh;
|
2014-07-28 17:25:54 +02:00
|
|
|
|
2015-05-23 11:27:53 +02:00
|
|
|
my $qstats = QStatskeeper->new;
|
|
|
|
$qstats->begin;
|
|
|
|
|
|
|
|
my $qdata = $qstats->get_question_data($id);
|
|
|
|
|
|
|
|
$qdata->{asked_count}++;
|
|
|
|
$qdata->{last_asked} = gettimeofday;
|
|
|
|
$qdata->{last_touched} = gettimeofday;
|
|
|
|
$qdata->{wrong_streak} = 0;
|
|
|
|
|
|
|
|
$qstats->update_question_data($id, $qdata);
|
|
|
|
$qstats->end;
|
|
|
|
|
2014-07-28 17:25:54 +02:00
|
|
|
|
|
|
|
sub shuffle_questions {
|
|
|
|
my $return_index = shift @_;
|
|
|
|
|
|
|
|
open my $fh, "<", $CJEOPARDY_FILE or die "Could not open $CJEOPARDY_FILE: $!";
|
|
|
|
my (@indices, $i);
|
|
|
|
while (<$fh>) {
|
|
|
|
push @indices, $i++;
|
|
|
|
}
|
|
|
|
close $fh;
|
|
|
|
|
2014-07-28 18:28:11 +02:00
|
|
|
open $fh, ">", "$CJEOPARDY_SHUFFLE-$channel" or die "Could not open $CJEOPARDY_SHUFFLE-$channel: $!";
|
2014-07-28 17:25:54 +02:00
|
|
|
while (@indices) {
|
|
|
|
my $random_index = int rand(@indices);
|
|
|
|
my $index = $indices[$random_index];
|
|
|
|
print $fh "$index\n";
|
|
|
|
splice @indices, $random_index, 1;
|
|
|
|
|
|
|
|
if ($return_index and @indices == 1) {
|
|
|
|
close $fh;
|
|
|
|
return $indices[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close $fh;
|
|
|
|
}
|
|
|
|
|
|
|
|
|