package gcb;
import gcb.plugin.Plugin;
import gcb.plugin.PluginManager;
import gcb.MemberInfo;
import gcb.GCBConfig;
import java.net.*;
import java.io.*;
import java.util.*;
import gcb.plugindb;
import gcb.GChatBot;
public class trivia extends Plugin {
PluginManager manager;
String commandTrigger;
boolean triviaEnabled;
int questionDelay; //ms delay after a question is answered
int triviaDelay; //ms delay in between hints
String questionDifficulty; //null is difficulty off
String questionCategory; //null is category off
// depending on state next operation should be:
// 0: display the question
// 1: display ???? (# characters in answer)
// 2: display ?a?a (stage2 answer)
// 3: display aa?a (stage3 answer)
// 4: display aaaa (display answer) and -> 0
int triviaState;
ArrayList<String> questionAnswers; //acceptable answers to current question
char[] questionUncover; //hint for current question
ArrayList<StoredQuestion> triviaQuestions; //stored questions, with question/answer
long lastTime; //last time an event occurred; used for update loop
boolean terminate = false;
plugindb pdb;
public void init(PluginManager manager) {
this.manager = manager;
commandTrigger = GCBConfig.configuration.getString("gcb.trivia_trigger", "trivia");
triviaEnabled = false;
questionDelay = GCBConfig.configuration.getInt("gcb.trivia_questiondelay", 6000);
triviaDelay = GCBConfig.configuration.getInt("gcb.trivia_delay", 8000);
questionDifficulty = null;
questionCategory = null;
triviaState = 0;
questionAnswers = new ArrayList<String>();
triviaQuestions = new ArrayList<StoredQuestion>();
//initialize plugindb
pdb = new plugindb();
pdb.init(manager);
pdb.setPluginName("trivia");
pdb.dbconnect();
pdb.dbGetScores();
manager.log("[TRIVIA] Loaded " + pdb.dbScoreNum() + " scores!");
}
public void load() {
manager.register(this, "onCommand");
manager.getGarena().registerListener(this);
manager.registerDelayed(this, "updateloop", 0);
}
public void unload() {
manager.deregister(this, "onCommand");
manager.getGarena().deregisterListener(this);
terminate = true;
}
public void chatReceived(MemberInfo player, String text, boolean whisper) {
if(triviaEnabled && triviaState > 0) {
String userAnswer = text.toLowerCase();
if(questionAnswers.contains(userAnswer)) {
pdb.dbScoreAdd(player.username.toLowerCase(), 1);
//get new score
int newScore = pdb.dbGetScore(player.username.toLowerCase());
manager.say("The answer was: " + userAnswer + "; user " + player.username + " got it correct! (points: " + newScore + ")");
//reset
lastTime = System.currentTimeMillis();
triviaState = 0;
}
}
}
public String onCommand(MemberInfo player, String command, String payload, int rank) {
if(command.equals(commandTrigger)) {
String[] parts = payload.split(" ");
if(rank >= GChatBot.LEVEL_ADMIN) {
if(parts[0].equalsIgnoreCase("on")) {
triviaEnabled = true;
triviaState = 0;
lastTime = 0;
manager.log("[TRIVIA] Enabled with category=" + questionCategory + " and diff=" + questionDifficulty);
return "Enabled trivia!";
} else if(parts[0].equalsIgnoreCase("off")) {
triviaEnabled = false;
return "Disabled trivia!";
} else if(parts[0].equals("delay") && parts.length >= 2) {
triviaDelay = Integer.parseInt(parts[1]);
return "Set delay!";
} else if(parts[0].equals("category")) {
if(parts.length >= 2) {
questionCategory = parts[1];
} else {
questionCategory = null;
}
//clear questions since we changed the type
triviaQuestions.clear();
return "Set category!";
} else if(parts[0].equals("difficulty")) {
if(parts.length >= 2) {
questionDifficulty = parts[1];
} else {
questionDifficulty = null;
}
//clear questions since we changed the type
triviaQuestions.clear();
return "Set difficulty!";
}
}
if(parts[0].equals("top")) {
//display top five
return pdb.dbScoreTopStr(5);
} else if(parts[0].equalsIgnoreCase("score")) {
String lowername = player.username.toLowerCase();
if(parts.length >= 2) {
lowername = parts[1].toLowerCase();
}
return lowername + " points: " + pdb.dbGetScore(lowername);
}
}
return null;
}
public void onDelay(String arg) {
if(arg.equals("updateloop")) {
updateLoop();
}
}
public void updateLoop() {
while(!terminate) {
if(triviaEnabled) {
if(triviaState == 0) {
if(System.currentTimeMillis() - lastTime > questionDelay) {
askQuestion();
//reset
triviaState = 1;
lastTime = System.currentTimeMillis();
}
}
else if(triviaState == 1) {
if(System.currentTimeMillis() - lastTime > triviaDelay) {
manager.say("Hint: " + new String(questionUncover));
//reset
triviaState = 2;
lastTime = System.currentTimeMillis();
}
}
else if(triviaState == 2 || triviaState == 3) {
if(System.currentTimeMillis() - lastTime > triviaDelay) {
uncover();
manager.say("Hint: " + new String(questionUncover));
//reset
triviaState++;
lastTime = System.currentTimeMillis();
}
}
else if(triviaState == 4) {
if(System.currentTimeMillis() - lastTime > triviaDelay) {
//no one answered; let's show them the answer
manager.say("The answer was: " + questionAnswers.get(0));
//reset some things
triviaState = 0;
lastTime = System.currentTimeMillis();
}
}
}
try {
Thread.sleep(200);
} catch(InterruptedException e) {}
}
}
public void uncover() {
//calculate how many to uncover; note that we might uncover same one twice (good thing: more randomness)
//this formula ensures that we don't uncover too many
int num_uncover = (int) Math.round(0.33 * (double) questionUncover.length);
if(questionUncover.length < 2) {
num_uncover = 0;
} else if(questionUncover.length < 4) {
num_uncover = 1;
}
for(int i = 0; i < num_uncover; i++) {
int index = (int) (Math.random() * questionUncover.length);
questionUncover[index] = questionAnswers.get(0).charAt(index);
}
}
public void askQuestion() {
//make sure there are questions available
if(triviaQuestions.isEmpty()) {
addQuestions();
}
StoredQuestion storedQuestion = triviaQuestions.remove(0);
questionAnswers = storedQuestion.answers;
//generate trivia_uncover
String firstAnswer = questionAnswers.get(0);
questionUncover = new char[firstAnswer.length()];
for(int i = 0; i < questionUncover.length; i++) {
if(firstAnswer.charAt(i) != ' ')
questionUncover[i] = '_';
else
questionUncover[i] = firstAnswer.charAt(i);
}
manager.say(storedQuestion.question + " (category: " + storedQuestion.category + ")");
}
public void addQuestions() {
String target = "http://snapnjacks.com/getq.php?client=plugins/pychop/trivia";
String content = null;
try {
//quote custom parameters to replace with %XX
if(questionDifficulty != null) {
target += "&dif=" + URLEncoder.encode(questionDifficulty, "UTF-8");
}
if(questionCategory != null) {
target += "&ctg=" + URLEncoder.encode(questionCategory, "UTF-8");
}
manager.log("[TRIVIA] Reading questions from " + target);
URL targetURL = new URL(target);
BufferedReader in = new BufferedReader(new InputStreamReader(targetURL.openStream()));
content = in.readLine();
in.close();
}
catch(IOException ioe) {
manager.log("[TRIVIA] Error: unable to read " + target + ":" + ioe.getLocalizedMessage());
StoredQuestion errorQuestion = new StoredQuestion();
errorQuestion.question = "Unable to load questions! You won't be able to answer this question D:";
errorQuestion.answers.add("error");
triviaQuestions.add(errorQuestion);
//disable trivia
triviaEnabled = false;
return;
}
String[] questionSplit = content.split("\\*\\*");
for(String questionString : questionSplit) {
StoredQuestion question = new StoredQuestion();
String[] parts = questionString.split("\\|");
if(parts.length < 7) {
continue;
}
String[] unformattedAnswers = parts[1].split("\\/");
for(String x : unformattedAnswers) {
//remove whitespace and convert to lowercase
question.answers.add(x.toLowerCase().trim());
}
//parts[0] is question, parts[6] is category
question.question = parts[0];
question.category = parts[6];
triviaQuestions.add(question);
manager.log("[TRIVIA] Appended question: " + question.question + "; storing " + triviaQuestions.size() + " questions now");
}
}
}
class StoredQuestion {
String question;
ArrayList<String> answers;
String category;
public StoredQuestion() {
question = "";
answers = new ArrayList<String>();
category = "";
}
}