Package net.bnubot.bot.trivia

Source Code of net.bnubot.bot.trivia.TriviaEventHandler

/**
* This file is distributed under the GPL
* $Id: TriviaEventHandler.java 1893 2014-02-11 09:22:17Z scotta $
*/

package net.bnubot.bot.trivia;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import net.bnubot.core.Connection;
import net.bnubot.core.EventHandler;
import net.bnubot.core.Profile;
import net.bnubot.core.commands.CommandRunnable;
import net.bnubot.db.Account;
import net.bnubot.db.conf.DatabaseContext;
import net.bnubot.logging.Out;
import net.bnubot.settings.GlobalSettings;
import net.bnubot.util.BNetUser;
import net.bnubot.util.UnloggedException;
import net.bnubot.util.crypto.HexDump;

import org.apache.cayenne.ObjectContext;

/**
* @author scotta
*/
public class TriviaEventHandler extends EventHandler {
  private boolean triviaEnabled = false;
  private final List<TriviaItem> trivia = new LinkedList<TriviaItem>();
  private TriviaItem triviaCurrent = null;
  private BNetUser answerUser = null;
  private String answerUsed = null;
  private int unanswered = 0;
  private Connection initializedConnection = null;
  private boolean disposed = false;

  public TriviaEventHandler(Profile profile) {
    super(profile);
    if(DatabaseContext.getContext() == null)
      throw new UnloggedException("Can not enable trivia without a database!");
    initializeCommands();
  }

  private static boolean commandsInitialized = false;
  public static void initializeCommands() {
    if(commandsInitialized)
      return;
    commandsInitialized = true;

    Profile.registerCommand("trivia", new CommandRunnable() {
      @Override
      public void run(Connection source, BNetUser user, String param, String[] params, boolean whisperBack, Account commanderAccount, boolean superUser)
      throws Exception {
        TriviaEventHandler teh = EventHandler.findThis(source, TriviaEventHandler.class);
        if(teh == null) {
          user.sendChat("Trivia is not enabled.", whisperBack);
          return;
        }

        if(teh.triviaEnabled) {
          if("off".equals(param)) {
            teh.triviaOff();
            return;
          }
          user.sendChat("Use: %trigger%trivia off", whisperBack);
        } else {
          if("on".equals(param)) {
            teh.triviaOn(source);
            return;
          } else if("score".equals(param)) {
            teh.showLeaderBoard(source);
            return;
          }
          user.sendChat("Use: %trigger%trivia ( on | score )", whisperBack);
        }
      }});
  }

  private void readFile(String fileName) {
    BufferedReader is = null;
    try {
      File f = new File(fileName);
      if(!f.exists())
        throw new FileNotFoundException(fileName);
      is = new BufferedReader(new FileReader(f));
    } catch (Exception e) {
      Out.fatalException(e);
    }

    String defaultCategory = fileName;
    if(defaultCategory.indexOf('.') != -1)
      defaultCategory = defaultCategory.split("\\.", 2)[0];
    while(defaultCategory.indexOf('/') != -1)
      defaultCategory = defaultCategory.split("\\/", 2)[1];
    while(defaultCategory.indexOf('\\') != -1)
      defaultCategory = defaultCategory.split("\\\\", 2)[1];

    long linenumber = 0;
    do {
      String line = null;
      linenumber++;
      try {
        line = is.readLine();
      } catch (IOException e) {
        Out.fatalException(e);
      }
      if(line == null)
        break;

      line = line.trim();
      if(line.length() == 0)
        continue;

      try {
        trivia.add(new TriviaItem(line, defaultCategory));
      } catch(IllegalArgumentException e) {
        Out.error(getClass(), "Failed to parse line #" + linenumber + " from " + fileName + ": " + line);
      }
    } while(true);

    try { is.close(); } catch (Exception e) {}
  }

  private void reloadTrivia(Connection source) {
    File f = new File("trivia");
    if(!f.exists())
      f.mkdir();
    if(f.isDirectory())
      for(String fname : f.list())
        readFile(f.getPath() + System.getProperty("file.separator") + fname);

    source.dispatchRecieveInfo("Trivia initialized with " + trivia.size() + " questions");
  }

  @Override
  public void bnetConnected(Connection source) {
    triviaEnabled = false;
  }

  @Override
  public void bnetDisconnected(Connection source) {
    triviaEnabled = false;
  }

  private void showLeaderBoard(Connection source) {
    try {
      ObjectContext context = DatabaseContext.getContext();
      if(context == null)
        return;

      List<Account> leaders = Account.getTriviaLeaders();
      if(leaders == null)
        return;
      if(leaders.size() == 0)
        return;

      StringBuilder out = new StringBuilder("Trivia Leader Board: ");
      for(Account a : leaders) {
        out.append(a.getName()).append('(');
        out.append(a.getTriviaCorrect()).append(") ");
      }
      out.append("Total=").append(getTriviaSum());
      source.sendChat(out.toString());
    } catch (Exception e) {
      Out.exception(e);
    }
  }

  private long getTriviaSum() {
    long total = 0;
    for(Account a : Account.getTriviaLeaders())
      total += a.getTriviaCorrect();
    return total;
  }

  private long[] getTriviaTopTwo() {
    List<Account> leaders = Account.getTriviaLeaders();
    if((leaders == null) || (leaders.size() == 0))
      return null;

    if(leaders.size() == 1)
      return new long[] {leaders.get(0).getTriviaCorrect()};

    return null;
  }

  private String resetTrivia() {
    List<Account> leaders = Account.getTriviaLeaders();
    if((leaders != null) && (leaders.size() > 0)) {
      Account winner = leaders.get(0);
      // Increment the winner's wins
      winner.setTriviaWin(winner.getTriviaWin() + 1);
      // Reset all scores to zero
      for(Account a : leaders)
        a.setTriviaCorrect(0);
      try {
        // Save changes
        winner.updateRow();
        // Return the winner's name
        return winner.getName();
      } catch(Exception e) {
        Out.exception(e);
      }
    }
    return null;
  }

  private void triviaLoop(Connection source) {
    while(!disposed) {
      try {
        if(triviaEnabled && source.canSendChat()) {
          if(trivia.size() == 0) {
            source.sendChat("There are no trivia questions left; game over.");
            triviaEnabled = false;
            continue;
          }

          if((DatabaseContext.getContext() != null) && (GlobalSettings.triviaRoundLength > 0)) {
            try {
              long max[] = getTriviaTopTwo();
              if(max != null) {
                final long total = getTriviaSum();
                final long target = GlobalSettings.triviaRoundLength;
                boolean condition = false;
                // There are no questions left
                condition |= (total >= target);
                // First place has half of the points
                condition |= (max[0] > (target/2));
                if(max.length > 1) {
                  long questionsLeft = (target - total);
                  long bestTop2Score = max[1] + questionsLeft;
                  // Second place can't pass first place
                  condition |= (bestTop2Score < max[1]);
                }
                if(condition) {
                  String out = "The trivia round is over! Congratulations to ";
                  out += resetTrivia();
                  out += " for winning the round!";
                  source.sendChat(out);
                }
              }
            } catch (Exception e) {
              Out.exception(e);
            }
          }

          triviaCurrent = trivia.remove((int)(Math.random() * trivia.size()));
          answerUser = null;

          if(true) {
            String q = "/me";
            if(triviaCurrent.getCategory() != null)
              q += " - Category: " + triviaCurrent.getCategory();
            q += " - Question: " + triviaCurrent.getQuestion();
            q += " - Hint: " + triviaCurrent.getHint0();
            source.sendChat(q);
            //c.recieveInfo("Answer: " + ti.getAnswer());
          }

          long timeQuestionAsked = System.currentTimeMillis();
          long timeElapsed = 0;
          int numHints = 0;
          do {
            if(answerUser != null)
              break;

            timeElapsed = System.currentTimeMillis() - timeQuestionAsked;
            timeElapsed /= 1000;

            if((timeElapsed > 10) && (numHints < 1)) {
              source.sendChat("/me - 20 seconds left! Hint: " + triviaCurrent.getHint1());
              numHints++;
            }

            if((timeElapsed > 20) && (numHints < 2)) {
              source.sendChat("/me - 10 seconds left! Hint: " + triviaCurrent.getHint2());
              numHints++;
            }

            Thread.sleep(200);
            Thread.yield();
          } while((timeElapsed < 30) && triviaEnabled);

          if(answerUser != null) {
            unanswered = 0;
            String extra = "!";

            if(DatabaseContext.getContext() != null) {
              try {
                Account answeredBy = Account.get(answerUser);
                if(answeredBy != null) {
                  int score = answeredBy.getTriviaCorrect();
                  score++;
                  answeredBy.setTriviaCorrect(score);
                  answeredBy.updateRow();
                  extra += " Your score is " + score + ".";
                }
              } catch(Exception e) {
                Out.exception(e);
              }
            }

            String[] triviaAnswersAN = triviaCurrent.getAnswersAlphaNumeric();
            if(triviaAnswersAN.length > 1) {
              extra += " Other acceptable answers were: ";
              boolean first = true;
              for(String answer : triviaCurrent.getAnswers()) {
                if(!answer.equals(answerUsed)) {
                  if(first)
                    first = false;
                  else
                    extra += ", or ";
                  extra += "\"" + answer + "\"";
                }
              }
            }

            source.sendChat("/me - \"" + answerUsed + "\" is correct, " + answerUser.toString() + extra);

            if(GlobalSettings.triviaRoundLength > 0)
              showLeaderBoard(source);
          } else {
            String[] triviaAnswers = triviaCurrent.getAnswers();
            String correct = " The correct answer was \"" + triviaAnswers[0] + "\"";
            for(int i = 1; i < triviaAnswers.length; i++)
              correct += ", or \"" + triviaAnswers[i] + "\"";

            if(triviaEnabled) {
              unanswered++;
              source.sendChat("/me - Time's up!" + correct);
            } else {
              source.sendChat("/me - Game over!" + correct);
              continue;
            }
          }

          if(unanswered == 9)
            source.sendChat("Trivia will automaticly shut off after the next question. To extend trivia, type [ trivia on ]");
          if(unanswered >= 10) {
            source.sendChat("Auto-disabling trivia.");
            triviaEnabled = false;
          }
        }

        Thread.sleep(1000);
        Thread.yield();
      } catch (InterruptedException e) {}
    }
  }

  @Override
  public void initialize(final Connection source) {
    if(initializedConnection == null) {
      initializedConnection = source;
      new Thread() {
        @Override
        public void run() {
          triviaLoop(source);
        }
      }.start();
    }
  }
  @Override
  public void disable(final Connection source) {
    if(initializedConnection == source)
      disposed = true;
  }

  public void triviaOn(Connection source) {
    if(trivia.size() == 0)
      reloadTrivia(source);

    unanswered = 0;
    triviaEnabled = true;
  }

  public void triviaOff() {
    triviaEnabled = false;
  }

  @Override
  public void joinedChannel(Connection source, String channel) {
    triviaEnabled = false;
  }

  @Override
  public void recieveChat(Connection source, BNetUser user, String text) {
    if(!triviaEnabled)
      return;
    if(triviaCurrent == null)
      return;
    String textAN = HexDump.getAlphaNumerics(text);
    String[] triviaAnswersAN = triviaCurrent.getAnswersAlphaNumeric();
    for(int i = 0; i < triviaAnswersAN.length; i++) {
      if(triviaAnswersAN[i].equalsIgnoreCase(textAN)) {
        answerUser = user;
        answerUsed = triviaCurrent.getAnswers()[i];
      }
    }
  }
}
TOP

Related Classes of net.bnubot.bot.trivia.TriviaEventHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.