package org.psjava.judgesubmit;
import java.io.IOException;
import org.json.JSONArray;
import org.json.JSONObject;
public class SPOJSubmitStatusReceiver implements SubmitStatusReceiver {
@Override
public SubmitStatus receive(JudgeHttpClient client, String submitId) throws IOException, SiteParsingException, InvalidInputException, JudgeServiceException {
client.clearCookie();
String jsonString = client.receivePostBodyString("/status/ajax=1,ajaxdiff=1", StringMapFromVarargs.create("ids", submitId), SPOJ.ENCODING);
JSONArray array = new JSONArray(jsonString);
if (array.length() == 0)
throw InvalidSubmitIdException.create(submitId);
if (array.length() > 1)
throw new SiteParsingException();
JSONObject json = array.getJSONObject(0);
int status = json.getInt("status");
String statusDescription = json.getString("status_description");
String time = json.getString("time");
String mem = json.getString("mem");
SubmitStatusCode code = converToCode(status, statusDescription);
String messageOrNull = extractMessageOrNull(code, statusDescription);
long memoryUsageOrZero = convertToMemoryUsageOrZero(mem);
long timeUsageOrZero = convertToTimeUsageOrZero(time);
return new SubmitStatus(-1, code, memoryUsageOrZero, timeUsageOrZero, messageOrNull);
}
private long convertToMemoryUsageOrZero(String mem) throws SiteParsingException {
long memoryUsageOrZero;
if (mem.equals("-")) {
return 0;
} else {
String trimmed = mem.trim();
String numPart = trimmed.substring(0, trimmed.length() - 1);
long unit = extractMemoryUnit(trimmed);
memoryUsageOrZero = (long) (SiteParsingUtil.parseDouble(numPart) * unit);
return memoryUsageOrZero;
}
}
private long extractMemoryUnit(String trimmedMemString) throws SiteParsingException {
switch (trimmedMemString.charAt(trimmedMemString.length() - 1)) {
case 'M':
return 1024 * 1024;
case 'k':
case 'K':
return 1024;
default:
throw new SiteParsingException(trimmedMemString);
}
}
private long convertToTimeUsageOrZero(String timeString) throws SiteParsingException {
if (timeString.equals("-")) {
return 0;
} else {
String sec = SiteParsingUtil.extractMiddleString(timeString, 0, ">", "<");
return (long) (SiteParsingUtil.parseDouble(sec) * 1000);
}
}
private SubmitStatusCode converToCode(int status, String statusDescription) throws SiteParsingException {
switch (status) {
case 0:
return SubmitStatusCode.WAITING;
case 1:
return SubmitStatusCode.COMPILING;
case 3:
return SubmitStatusCode.RUNNING;
case 5:
return SubmitStatusCode.JUDGING;
case 11:
return SubmitStatusCode.COMPILE_ERROR;
case 12:
return SubmitStatusCode.RUNTIME_ERROR;
case 13:
return SubmitStatusCode.TIME_LIMIT_EXCEED;
case 14:
return SubmitStatusCode.WRONG_ANSWER;
case 15:
return SubmitStatusCode.ACCEPTED;
default:
throw new SiteParsingException("unknown status: " + status + "," + statusDescription.trim());
}
}
private String extractMessageOrNull(SubmitStatusCode code, String statusDescription) throws SiteParsingException {
if (code == SubmitStatusCode.RUNTIME_ERROR) {
if (statusDescription.contains("<"))
return SiteParsingUtil.extractMiddleString(statusDescription, 0, ">", "<");
else
return SiteParsingUtil.extractMiddleString(statusDescription, 0, "(", ")");
} else {
return null;
}
}
}