package org.psjava.judgesubmit;
import org.psjava.ds.map.KeysInMap;
import org.psjava.ds.map.Map;
import org.psjava.ds.map.MutableMap;
import org.psjava.ds.set.Set;
import org.psjava.ds.set.SetFromIterable;
import org.psjava.goods.GoodMutableMapFactory;
import org.puredevteam.httpclient.SocketConnectionData;
import java.io.IOException;
import java.util.TreeMap;
class TJU implements JudgeSite {
public static final String ENCODING = "UTF-8";
public static final SocketConnectionData CONNECTION_DATA = new SocketConnectionData(false, "acm.tju.edu.cn", 80);
@Override
public String getName() {
return "Tianjin University Online Judge";
}
@Override
public SocketConnectionData getSocketConnectionData() {
return CONNECTION_DATA;
}
@Override
public Set<Language> getSupportedLanguageSet() {
return SetFromIterable.create(KeysInMap.get(getLanguageMap()));
}
@Override
public Submitter getSubmitter() {
return new Submitter() {
@Override
public String submitAndGetId(JudgeHttpClient hc, String problemId, String userId, String password, Language language, String sourceCode) throws IOException, InvalidInputException, SiteParsingException, JudgeServiceException {
int lastSubmitIdOrZero = receiveLastSubmitIdOrZero(hc, userId);
submit(hc, problemId, userId, password, language, sourceCode);
int newId = receiveLastSubmitIdOrZero(hc, userId);
SiteParsingUtil.assertTrue(newId != lastSubmitIdOrZero);
return newId + "";
}
private void submit(JudgeHttpClient hc, String problemId, String userId, String password, Language language, String sourceCode) throws IOException, JudgeServiceException, InvalidInputException, SiteParsingException {
TreeMap<String, String> param = new TreeMap<String, String>();
param.put("user_id", userId);
param.put("passwd", password);
param.put("prob_id", problemId);
param.put("language", getLanguageMap().get(language));
param.put("source", sourceCode + "\n");
String html = hc.receivePostBodyString("/toj/submit_process.php", param, ENCODING);
if (html.contains("Invalid password!") || html.contains("No such user!"))
throw InvalidLogInDataException.create("");
if (!html.contains("Your source code has been submitted"))
throw new InvalidInputException(SiteParsingUtil.extractMiddleString(html, 0, "<H1><center>", "</center><br>"));
}
};
}
public static int receiveLastSubmitIdOrZero(JudgeHttpClient client, String userId) throws IOException, SiteParsingException, JudgeServiceException {
String html = client.receiveGetBodyString("/toj/status.php?user=" + userId, ENCODING);
String start = "height=30><td>";
if(!html.contains(start))
return 0;
return SiteParsingUtil.parseInt(SiteParsingUtil.extractMiddleString(html, 0, start, "</td>"));
}
private static Map<Language, String> getLanguageMap() {
MutableMap<Language, String> map = GoodMutableMapFactory.getInstance().create();
map.put(Language.JAVA, "2");
map.put(Language.CPP, "1");
map.put(Language.C, "0");
return map;
}
@Override
public SubmitStatusReceiver getSubmitStatusReceiver() {
return new SubmitStatusReceiver() {
@Override
public SubmitStatus receive(JudgeHttpClient client, String submitId) throws IOException, SiteParsingException, InvalidInputException, JudgeServiceException {
String html = client.receiveGetBodyString("/toj/status.php?start=" + submitId, ENCODING);
String part = SiteParsingUtil.extractMiddleString(html, 0, "<tr align=center height=30>", "<tr align=center height=30>");
String[] lines = part.split("\n");
SubmitStatusCode code = getCode(lines[1]);
SiteParsingUtil.assertTrue(lines.length == 5);
String timeString = SiteParsingUtil.extractMiddleString(lines[3], 10, "<td>", "<");
int min = SiteParsingUtil.parseInt(SiteParsingUtil.extractMiddleString(timeString, 0, "", "'"));
int sec = SiteParsingUtil.parseInt(SiteParsingUtil.extractMiddleString(timeString, 0, "'", "."));
int csec = SiteParsingUtil.parseInt(SiteParsingUtil.extractMiddleString(timeString, 0, ".", "\""));
long time = min * 60 * 1000 + sec * 1000 + csec * 10;
long mem = SiteParsingUtil.parseInt(SiteParsingUtil.extractMiddleString(lines[4], 0, "<td>", "K")) * 1024L;
return new SubmitStatus(0, code, mem, time, null);
}
};
}
private static SubmitStatusCode getCode(String judgeString) throws SiteParsingException {
if (judgeString.indexOf("Accepted") != -1) {
return SubmitStatusCode.ACCEPTED;
} else if (judgeString.indexOf("Presentation Error") != -1) {
return SubmitStatusCode.PRESENTATION_ERROR;
} else if (judgeString.indexOf("Runtime Error") != -1) {
return SubmitStatusCode.RUNTIME_ERROR;
} else if (judgeString.indexOf("Wrong Answer") != -1) {
return SubmitStatusCode.WRONG_ANSWER;
} else if (judgeString.indexOf("Time Limit") != -1) {
return SubmitStatusCode.TIME_LIMIT_EXCEED;
} else if (judgeString.indexOf("Memory Limit") != -1) {
return SubmitStatusCode.MEMORY_LIMITE_EXCEED;
} else if (judgeString.indexOf("Running") != -1) {
return SubmitStatusCode.RUNNING;
} else if (judgeString.indexOf("Output Limit") != -1) {
return SubmitStatusCode.OUTPUT_LIMIT_EXCEED;
} else if (judgeString.indexOf("Restricted Function") != -1) {
return SubmitStatusCode.RESTRICTED_FUNCTION;
} else if (judgeString.indexOf("Compilation Error") != -1) {
return SubmitStatusCode.COMPILE_ERROR;
} else if (judgeString.indexOf("Compiling") != -1) {
return SubmitStatusCode.COMPILING;
} else if (judgeString.indexOf("Judging") != -1) {
return SubmitStatusCode.JUDGING;
} else if (judgeString.indexOf("Internal Error ") != -1) {
return SubmitStatusCode.SYSTEM_ERROR;
} else {
throw new SiteParsingException("Unknown TJU Judge Status Code (" + judgeString + ")");
}
}
@Override
public CompileErrorMessageReceiver getCompileErrorMessageReceiver() {
return new CompileErrorMessageReceiver() {
@Override
public String receive(JudgeHttpClient client, String id, String password, String submitId) throws IOException, SiteParsingException, InvalidInputException, JudgeServiceException {
String html = client.receiveGetBodyString("/toj/show_cerror.php?id=" + submitId, ENCODING);
String msg = SiteParsingUtil.extractMiddleString(html, 0, "<pre>", "</pre>").trim();
return msg;
}
};
}
}