/** * 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); } }
/** * Send a submit to remote, and store the judge result * @param bott Submit info * @param filename File store the result */ void VirtualJudger::judge(Bott * bott, string filename) { // login if (!logged_in) { // Not logged in, try login clearCookies(); login(); log("Logged in."); logged_in = true; } // submit int submit_status = submit(bott); if (submit_status == SUBMIT_OTHER_ERROR) { // first time fail, blame login status... log((string) "Submit error. Assume not logged in."); logged_in = false; clearCookies(); login(); log("Logged in."); logged_in = true; submit_status = submit(bott); if (submit_status == SUBMIT_OTHER_ERROR) { // second time fail, blame frequency if (info->GetOj() == "CodeChef") { // CodeChef's restriction is harsh... 30 seconds cool down required log("Submit error. Assume should sleep for a while, " "sleeping 30 seconds."); sleep(30); } else { log("Submit error. Assume should sleep for a while, sleeping " + intToString(VirtualJudger::SLEEP_INTERVAL) + " seconds."); sleep(VirtualJudger::SLEEP_INTERVAL); } submit_status = submit(bott); } } else if (submit_status == SUBMIT_INVALID_LANGUAGE && (info->GetOj() == "SPOJ" || info->GetOj() == "CodeChef") && convertLanguage(bott->Getlanguage()) == "41") { // Special HACK for Invalid Language on SPOJ/CodeChef, since they have two // C++ types and each covers a certain subset of problems log((string) "Try another C++ for SPOJ/CodeChef"); bott->Setlanguage(1); submit_status = submit(bott); } if (submit_status != SUBMIT_OTHER_ERROR) log("Submitted."); // check submit status sleep(1); // sleep 1 second, just in case remote status table is not refreshed Bott * result; if (submit_status == SUBMIT_NORMAL) { // get status result = getStatus(bott); result->Setrunid(bott->Getrunid()); if (result->Getresult() == "Compile Error") { try { result->Setce_info(getCEinfo(result)); } catch (...) { log("Failed to get CE info, use empty one instead."); result->Setce_info(""); } } } else { result = new Bott; result->Setrunid(bott->Getrunid()); switch (submit_status) { case SUBMIT_SAME_CODE: generateSpecialResult(result, "Judge Error (Same Code)"); break; case SUBMIT_INVALID_LANGUAGE: generateSpecialResult(result, "Judge Error (Invalid Language)"); break; case SUBMIT_COMPILE_ERROR: generateSpecialResult(result, "Compile Error"); break; default: log("Submit Error."); generateSpecialResult(result, "Judge Error"); } } result->Setout_filename(filename); result->save(); log("Done judging. Result: " + result->Getresult() + ", remote runid: " + result->Getremote_runid()); delete result; }