3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-12-25 12:12:34 +01:00
pbot/modules/cjeopardy/cjeopardy.pl
Tomasz Kramkowski b5d8f72254 License project under MPL2
This patch adds the file LICENSE which is the verbatim copy of the
Mozilla Public License Version 2.0 as retreived from
https://www.mozilla.org/media/MPL/2.0/index.815ca599c9df.txt on
2017-03-05.

This patch also places license headers for the MPL2 type A variant of
the license header in the following files:

PBot/AntiFlood.pm
PBot/BanTracker.pm
PBot/BlackList.pm
PBot/BotAdminCommands.pm
PBot/BotAdmins.pm
PBot/ChanOpCommands.pm
PBot/ChanOps.pm
PBot/Channels.pm
PBot/Commands.pm
PBot/DualIndexHashObject.pm
PBot/EventDispatcher.pm
PBot/FactoidCommands.pm
PBot/FactoidModuleLauncher.pm
PBot/Factoids.pm
PBot/HashObject.pm
PBot/IRCHandlers.pm
PBot/IgnoreList.pm
PBot/IgnoreListCommands.pm
PBot/Interpreter.pm
PBot/LagChecker.pm
PBot/Logger.pm
PBot/MessageHistory.pm
PBot/MessageHistory_SQLite.pm
PBot/NickList.pm
PBot/PBot.pm
PBot/Plugins.pm
PBot/Plugins/AntiAway.pm
PBot/Plugins/AntiKickAutoRejoin.pm
PBot/Plugins/AntiRepeat.pm
PBot/Plugins/AntiTwitter.pm
PBot/Plugins/AutoRejoin.pm
PBot/Plugins/Counter.pm
PBot/Plugins/Quotegrabs.pm
PBot/Plugins/Quotegrabs/Quotegrabs_Hashtable.pm
PBot/Plugins/Quotegrabs/Quotegrabs_SQLite.pm
PBot/Plugins/UrlTitles.pm
PBot/Plugins/_Example.pm
PBot/Refresher.pm
PBot/Registerable.pm
PBot/Registry.pm
PBot/RegistryCommands.pm
PBot/SQLiteLogger.pm
PBot/SQLiteLoggerLayer.pm
PBot/SelectHandler.pm
PBot/StdinReader.pm
PBot/Timer.pm
PBot/Utils/ParseDate.pm
PBot/VERSION.pm
build/update-version.pl
modules/acronym.pl
modules/ago.pl
modules/c11std.pl
modules/c2english.pl
modules/c2english/CGrammar.pm
modules/c2english/c2eng.pl
modules/c99std.pl
modules/cdecl.pl
modules/cfaq.pl
modules/cjeopardy/IRCColors.pm
modules/cjeopardy/QStatskeeper.pm
modules/cjeopardy/Scorekeeper.pm
modules/cjeopardy/cjeopardy.pl
modules/cjeopardy/cjeopardy_answer.pl
modules/cjeopardy/cjeopardy_filter.pl
modules/cjeopardy/cjeopardy_hint.pl
modules/cjeopardy/cjeopardy_qstats.pl
modules/cjeopardy/cjeopardy_scores.pl
modules/cjeopardy/cjeopardy_show.pl
modules/codepad.pl
modules/compiler_block.pl
modules/compiler_client.pl
modules/compiler_vm/Diff.pm
modules/compiler_vm/cc
modules/compiler_vm/compiler_client.pl
modules/compiler_vm/compiler_server.pl
modules/compiler_vm/compiler_server_vbox_win32.pl
modules/compiler_vm/compiler_server_watchdog.pl
modules/compiler_vm/compiler_vm_client.pl
modules/compiler_vm/compiler_vm_server.pl
modules/compiler_vm/compiler_watchdog.pl
modules/compiler_vm/languages/_c_base.pm
modules/compiler_vm/languages/_default.pm
modules/compiler_vm/languages/bash.pm
modules/compiler_vm/languages/bc.pm
modules/compiler_vm/languages/bf.pm
modules/compiler_vm/languages/c11.pm
modules/compiler_vm/languages/c89.pm
modules/compiler_vm/languages/c99.pm
modules/compiler_vm/languages/clang.pm
modules/compiler_vm/languages/clang11.pm
modules/compiler_vm/languages/clang89.pm
modules/compiler_vm/languages/clang99.pm
modules/compiler_vm/languages/clangpp.pm
modules/compiler_vm/languages/clisp.pm
modules/compiler_vm/languages/cpp.pm
modules/compiler_vm/languages/freebasic.pm
modules/compiler_vm/languages/go.pm
modules/compiler_vm/languages/haskell.pm
modules/compiler_vm/languages/java.pm
modules/compiler_vm/languages/javascript.pm
modules/compiler_vm/languages/ksh.pm
modules/compiler_vm/languages/lua.pm
modules/compiler_vm/languages/perl.pm
modules/compiler_vm/languages/python.pm
modules/compiler_vm/languages/python3.pm
modules/compiler_vm/languages/qbasic.pm
modules/compiler_vm/languages/scheme.pm
modules/compiler_vm/languages/server/_c_base.pm
modules/compiler_vm/languages/server/_default.pm
modules/compiler_vm/languages/server/c11.pm
modules/compiler_vm/languages/server/c89.pm
modules/compiler_vm/languages/server/c99.pm
modules/compiler_vm/languages/server/clang.pm
modules/compiler_vm/languages/server/clang11.pm
modules/compiler_vm/languages/server/clang89.pm
modules/compiler_vm/languages/server/clang99.pm
modules/compiler_vm/languages/server/cpp.pm
modules/compiler_vm/languages/server/freebasic.pm
modules/compiler_vm/languages/server/haskell.pm
modules/compiler_vm/languages/server/java.pm
modules/compiler_vm/languages/server/qbasic.pm
modules/compiler_vm/languages/server/tendra.pm
modules/compiler_vm/languages/sh.pm
modules/compiler_vm/languages/tendra.pm
modules/compliment
modules/cstd.pl
modules/define.pl
modules/dice_roll.pl
modules/excuse.sh
modules/expand_macros.pl
modules/fnord.pl
modules/funnyish_quote.pl
modules/g.pl
modules/gdefine.pl
modules/gen_cfacts.pl
modules/gencstd.pl
modules/get_title.pl
modules/getcfact.pl
modules/google.pl
modules/gspy.pl
modules/gtop10.pl
modules/gtop15.pl
modules/headlines.pl
modules/horoscope
modules/horrorscope
modules/ideone.pl
modules/insult.pl
modules/love_quote.pl
modules/man.pl
modules/map.pl
modules/math.pl
modules/prototype.pl
modules/qalc.pl
modules/random_quote.pl
modules/seen.pl
modules/urban
modules/weather.pl
modules/wikipedia.pl
pbot.pl
pbot.sh

It is highly recommended that this list of files is reviewed to ensure
that all files are the copyright of the sole maintainer of the
repository. If any files with license headers contain the intellectual
property of anyone else, it is recommended that a request is made to
revise this patch or that the explicit permission of the co-author is
gained to allow for the license of the work to be changed.

I (Tomasz Kramkowski), the contributor, take no responsibility for any
legal action taken against the maintainer of this repository for
incorrectly claiming copyright to any work not owned by the maintainer
of this repository.
2017-03-06 00:31:15 +00:00

212 lines
5.4 KiB
Perl
Executable File

#!/usr/bin/env perl
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
use warnings;
use strict;
use Time::HiRes qw/gettimeofday/;
use Time::Duration qw/duration/;
use Fcntl qw(:flock);
use IRCColors;
use QStatskeeper;
my $CJEOPARDY_FILE = 'cjeopardy.txt';
my $CJEOPARDY_DATA = 'data/cjeopardy.dat';
my $CJEOPARDY_FILTER = 'data/cjeopardy.filter';
my $CJEOPARDY_HINT = 'data/cjeopardy.hint';
my $CJEOPARDY_SHUFFLE = 'data/cjeopardy.shuffle';
my $TIMELIMIT = 300;
my $channel = shift @ARGV;
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 !~ /^#/) {
print "Sorry, C Jeopardy must be played in a channel. Feel free to join #cjeopardy.\n";
exit;
}
open my $semaphore, ">", "$CJEOPARDY_DATA-$channel.lock" or die "Couldn't create semaphore lock: $!";
flock $semaphore, LOCK_EX;
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);
print "$color{magneta}The current question is$color{reset}: $last_question";
print "$color{red}You may request a new question in $duration.$color{reset}\n";
close $fh;
exit;
}
close $fh;
}
my $filter_regex;
my $filter_text;
$ret = open $fh, "<", "$CJEOPARDY_FILTER-$channel";
if (defined $ret) {
my $words = <$fh>;
close $fh;
chomp $words;
$filter_text = $words;
$filter_text =~ s/,/, /g;
$filter_text =~ s/, ([^,]+)$/ or $1/;
print "[Filter active! To view or change, use the `filter` command.]\n";
my @w = split /,/, $words;
my $sep = '';
$filter_regex .= '(?:';
foreach my $word (@w) {
$filter_regex .= $sep;
$filter_regex .= $word =~ m/^[a-zA-Z0-9]/ ? '\b' : '\B';
$filter_regex .= quotemeta $word;
$filter_regex .= $word =~ m/[a-zA-Z0-9]$/ ? '\b' : '\B';
$sep = '|';
}
$filter_regex .= ')';
}
my $question_index;
my $shuffles = 0;
NEXT_QUESTION:
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) {
print "$color{teal}(Shuffling.)$color{reset}\n";
shuffle_questions(0);
$shuffles++;
} 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 {
print "$color{teal}(Shuffling!)$color{reset}\n";
$question_index = shuffle_questions(1);
$shuffles++;
}
}
my @questions;
open $fh, "<", $CJEOPARDY_FILE or die "Could not open $CJEOPARDY_FILE: $!";
while (my $question = <$fh>) {
my ($question_only) = map { decode $_ } split /\|/, encode($question), 2;
$question_only =~ s/\\\|/|/g;
next if length $text and $question_only !~ /\Q$text\E/i;
next if defined $filter_regex and $question_only =~ /$filter_regex/i;
push @questions, $question;
}
close $fh;
if (not @questions) {
if (length $text) {
print "No questions containing '$text' found.\n";
} else {
if ($shuffles <= 1) {
goto NEXT_QUESTION;
} else {
print "No questions available.\n";
}
}
exit;
}
if (length $text) {
$question_index = int rand(@questions);
}
my $question = $questions[$question_index];
if (not defined $question) {
goto NEXT_QUESTION;
}
my ($q, $a) = map { decode $_ } split /\|/, encode($question), 2;
chomp $q;
chomp $a;
$q =~ s/\\\|/|/g;
$q =~ s/^(\d+)\) \[.*?\]\s+/$1) /;
my $id = $1;
$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;
print "$q\n";
open $fh, ">", "$CJEOPARDY_DATA-$channel" or die "Could not open $CJEOPARDY_DATA-$channel: $!";
print $fh "$q\n";
print $fh "$a\n";
print $fh scalar gettimeofday, "\n";
close $fh;
unlink "$CJEOPARDY_HINT-$channel";
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;
close $semaphore;
=cut
my $hint = `./cjeopardy_hint.pl candide $channel`;
print $hint;
=cut
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;
open $fh, ">", "$CJEOPARDY_SHUFFLE-$channel" or die "Could not open $CJEOPARDY_SHUFFLE-$channel: $!";
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;
}