package controllers;
import com.avaje.ebean.Expr;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import models.Judge;
import models.Problem;
import models.Solution;
import org.zeroturnaround.zip.ZipUtil;
import play.Logger;
import play.libs.Json;
import play.mvc.Result;
import utils.JudgeAccess;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class JudgeController extends OJController {
@JudgeAccess
private static Result responseSolutionToJudge(Solution solution) {
solution.dispatchTime = new Date();
solution.save();
ObjectNode response = Json.newObject();
response.put("solution", solution.id);
response.put("problem", solution.problem.id);
response.put("problem_hash", solution.problem.resourcesHash);
response.put("code", solution.code);
response.put("language", solution.language);
return ok(jsonResponse(0, response));
}
@JudgeAccess
public static Result judgeFetchSolution() {
String[] requestLanguages = request().queryString().get("language");
if (requestLanguages == null || requestLanguages.length == 0) {
return ok(jsonResponse(2, "Supported Language not provided."));
}
List<Integer> languageList = new ArrayList<>();
for (String requestLanguage : requestLanguages) {
languageList.add(Integer.parseInt(requestLanguage));
}
Date now = new Date();
// If a solution is dispatched 3 minutes ago, it will be re-dispatched.
Date expiredTime = new Date(now.getTime() - 3 * 60 * 1000);
List<Solution> solutions = Solution.find.where()
.or(Expr.eq("dispatchTime", null),
Expr.and(Expr.lt("dispatchTime", expiredTime), Expr.eq("judgeTime", null)))
.in("language", languageList)
.orderBy("id").findList();
if (solutions.size() > 0) {
Solution solution = solutions.get(0);
solution.judge = (Judge) ctx().args.get("judge");
solution.save();
return responseSolutionToJudge(solution);
} else {
return ok(jsonResponse(1, "Currently no more solutions to check."));
}
}
@JudgeAccess
public static Result handleJudgeUpdateResult(long solutionId) {
try {
JsonNode in = request().body().asJson();
int result = in.get("result").asInt();
Integer timeUsed = in.get("time").asInt(-1);
Integer memoryUsed = in.get("memory").asInt(-1);
if (timeUsed < 0) timeUsed = null;
if (memoryUsed < 0) memoryUsed = null;
String detail = in.get("detail").asText();
Solution solution = Solution.find.byId(solutionId);
solution.judge = (Judge) ctx().args.get("judge");
solution.result = result;
solution.judgeResponse = detail;
solution.timeUsed = timeUsed;
solution.memoryUsed = memoryUsed;
// When result is greater than 200, there will be no more update.
if (result >= 200) {
solution.judgeTime = new Date();
if (result == 200) {
solution.user.removeSolvedProblemsCache();
}
}
solution.save();
return ok(jsonResponse(0, "Success."));
} catch (NullPointerException e) {
return ok(jsonResponse(2, "Illegal update request."));
}
}
@JudgeAccess
public static Result getProblemResourcesHash(Long id) {
Problem problem = Problem.find.byId(id);
return ok(jsonResponse(0, problem.resourcesHash));
}
@JudgeAccess
public static Result getProblemResourcesZip(Long id) {
String dir = "upload/problem/" + id;
File uploadPath = new File(dir);
if (!uploadPath.exists()) {
return notFound("Problem resources not found.");
}
try {
File zip = File.createTempFile("package", ".zip");
ZipUtil.pack(uploadPath, zip);
return ok(zip);
} catch (IOException e) {
Logger.info("Cannot create temp file.");
e.printStackTrace();
return badRequest("Server Error.");
}
}
}