void dointeractive() {
  LOG("Runid: " + Inttostring(bott->Getrunid()) + " Type: Interactive");

  retbott.Settype(RESULT_REPORT);
  retbott.Setrunid(bott->Getrunid());
  Interactive * usrprogram = new Interactive;
  usrprogram->Setlanguage(bott->Getlanguage());
  usrprogram->Setsource(bott->Getsrc());
  problem = new PConfig(bott->Getpid(), "interactive");
  usrprogram->SetValidator_source(
      Loadallfromfile(problem->Getvalidator_filename()));
  usrprogram->SetValidator_language(problem->Getvalidator_language());

  usrprogram->Setcase_time_limit(bott->Getcase_limit());
  usrprogram->Settotal_time_limit(bott->Gettime_limit());
  usrprogram->Setmemory_limit(bott->Getmemory_limit());
  usrprogram->Setout_filename(CONFIG->GetTmpfile_path() + tmpnam());

  usrprogram->Run();
  retbott.Setce_info(usrprogram->Getce_info());
  retbott.Settime_used(usrprogram->Gettime_used());
  retbott.Setmemory_used(usrprogram->Getmemory_used());
  retbott.Setresult(usrprogram->Getresult());

  retbott.Setout_filename("results/" + Inttostring(retbott.Getrunid()));
  retbott.toFile();
  delete usrprogram;
  delete problem;
  send_result(retbott.Getout_filename());
}
/**
 * Start virtual judger
 */
void VirtualJudger::run() {
  log("Judger started");
  initHandShake();
  while (true) {
    socket->receiveFile(tmpfilename);
    Bott * bott = new Bott(tmpfilename);
    log((string) "Received a new task, problem: " + bott->Getvid() + ".");
    string result_filename = Bott::RESULTS_DIRECTORY +
        intToString(bott->Getrunid());
    if (bott->Gettype() == NEED_JUDGE) {
      // Currently for vjudge, only NEED_JUDGE is supported
      try {
        if (bott->Getsrc().length() < MIN_SOURCE_LENGTH) {
          // source code too short, may cause problem in remote OJ, such as PKU
          bott->Setout_filename(result_filename);
          generateSpecialResult(bott, "Compile Error");
          bott->Setce_info("Source code too short, minimum length: " +
              intToString(MIN_SOURCE_LENGTH));
          bott->save();
        } else {
          judge(bott, result_filename);
        }
      } catch (Exception & e) {
        // Exception occurs, set to Judge Error
        log((string) "Judge error! Reason: " + e.what());

        // reuse bott file
        bott->Setout_filename(result_filename);
        generateSpecialResult(bott, "Judge Error");
        bott->save();
      } catch (exception & e) {
        // Exception occurs, set to Judge Error
        log((string) "Judge error! Reason: " + e.what());

        // reuse bott file
        bott->Setout_filename(result_filename);
        generateSpecialResult(bott, "Judge Error");
        bott->save();
      }
      delete bott;
    } else {
      delete bott;
      throw Exception("Type not supported.");
    }
    socket->sendFile(result_filename);
  }
}
void dojudge(int type) {
  LOG("Runid: " + Inttostring(bott->Getrunid()) + " Type: " +
      Inttostring(type));
  vector <string> in_files;
  if (!getalldata(bott->Getpid(), in_files, type) || in_files.size() == 0) {
    retbott.Settype(RESULT_REPORT);
    retbott.Setrunid(bott->Getrunid());
    retbott.Settime_used(0);
    retbott.Setmemory_used(0);
    retbott.Setresult("Judge Error (No Data)");
    retbott.Setout_filename("results/" + Inttostring(retbott.Getrunid()));
    retbott.toFile();
    send_result(retbott.Getout_filename());
    return;
  }
  string inpfile = CONFIG->GetTmpfile_path() + tmpnam();
  string stdout_file = CONFIG->GetTmpfile_path() + tmpnam();
  retbott.Settype(RESULT_REPORT);
  retbott.Setrunid(bott->Getrunid());
  usrprogram = new Program;
  usrprogram->Setlanguage(bott->Getlanguage());
  usrprogram->Setsource(bott->Getsrc());
  usrprogram->Sethas_input(true);
  usrprogram->Setin_filename(inpfile);
  usrprogram->Setout_filename(CONFIG->GetTmpfile_path() + tmpnam());
  usrprogram->Seterr_filename(CONFIG->GetTmpfile_path() + tmpnam());
  if (type == NEED_JUDGE)
    usrprogram->Settotal_time_limit(bott->Gettime_limit());
  else usrprogram->Settotal_time_limit(bott->Getcase_limit() * in_files.size());
  usrprogram->Setcase_time_limit(bott->Getcase_limit());
  usrprogram->Setmemory_limit(bott->Getmemory_limit());
  bool aced, peed, jeed = false, has = false;
  aced = peed = true;
  cmp = new Comparator;
  cmp->Setin_filename(inpfile);
  cmp->Setout_filename(usrprogram->Getout_filename());
  cmp->Setisspj(bott->Getspj());
  cmp->Setpid(bott->Getpid());
  for (unsigned int i = 0; i < in_files.size(); i++) {
    system(((string) "cp " + in_files[i] + ".in " + inpfile).c_str());
    LOG((string) "Do " + in_files[i]);
    usrprogram->Run();
    if (usrprogram->Getresult() != "Normal") {
      retbott.Setresult(usrprogram->Getresult());
      has = true;
      break;
    } else {
      system(((string) "cp " + in_files[i] + ".out " + stdout_file).c_str());
      system(((string) "chmod 755 " + stdout_file).c_str());
      system(((string) "chmod 755 " + inpfile).c_str());
      cmp->Setstdout_filename(stdout_file);
      cmp->Setsrc_filename(usrprogram->Getsrc_filename());
      int cres = cmp->Compare();
      system(((string) "rm " + stdout_file).c_str());
      system(((string) "chmod 600 " + inpfile).c_str());
      if (cres == PE_STATUS) aced = false;
      else if (cres == JE_STATUS) {
        jeed = false;
        break;
      } else if (cres != AC_STATUS) {
        aced = peed = false;
        break;
      }
    }
  }
  retbott.Setce_info(usrprogram->Getce_info());
  retbott.Settime_used(usrprogram->Gettime_used());
  retbott.Setmemory_used(usrprogram->Getmemory_used());
  if (has) retbott.Setresult(usrprogram->Getresult());
  else if (jeed) retbott.Setresult("Judge Error (No SPJ)");
  else if (aced) {
    if (type == DO_PRETEST) retbott.Setresult("Pretest Passed");
    else retbott.Setresult("Accepted");
  } else if (peed) retbott.Setresult("Presentation Error");
  else retbott.Setresult("Wrong Answer");
  retbott.Setout_filename("results/" + Inttostring(retbott.Getrunid()));
  retbott.toFile();
  delete cmp;
  delete usrprogram;
  send_result(retbott.Getout_filename());
}