فهرست منبع

finish judge client

Bay 5 سال پیش
والد
کامیت
deecb1a6b0

+ 19 - 0
codejudge-client/pom.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>judgement</artifactId>
+        <groupId>cn.seecoder</groupId>
+        <version>0.1.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>codejudge-client</artifactId>
+
+    <properties>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+    </properties>
+
+</project>

+ 16 - 0
codejudge-client/src/main/java/cn/seecoder/codejudge/client/CodeJudgeApi.java

@@ -0,0 +1,16 @@
+package cn.seecoder.codejudge.client;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author kunduin
+ */
+public interface CodeJudgeApi {
+    /**
+     * 代码题判题
+     *
+     * @param judgeDTO 判题信息
+     * @return 判题结果
+     */
+    JudgeResult judge(@NotNull JudgeDTO judgeDTO);
+}

+ 141 - 0
codejudge-client/src/main/java/cn/seecoder/codejudge/client/CodeJudgeClient.java

@@ -0,0 +1,141 @@
+package cn.seecoder.codejudge.client;
+
+import cn.seecoder.bok.client.SeecoderBokConstants;
+import cn.seecoder.bok.client.SeecoderBokException;
+import cn.seecoder.bok.common.vo.QuestionVO;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
+import okhttp3.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.validation.constraints.NotNull;
+import java.io.IOException;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Function;
+
+/**
+ * @author kunduin
+ */
+public class CodeJudgeClient implements CodeJudgeApi {
+
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    private final OkHttpClient client;
+    private final ObjectMapper mapper;
+
+    private final String CONFIG_HOST;
+
+    /**
+     * 创建client
+     *
+     * @param host code judge 地址,示例:{@code "http://codejudge.seec.seecoder.cn"}
+     */
+    public CodeJudgeClient(String host) {
+        this.CONFIG_HOST = host;
+        client = new OkHttpClient();
+        mapper = JsonMapper.builder()
+                .addModule(new ParameterNamesModule())
+                .addModule(new Jdk8Module())
+                .addModule(new JavaTimeModule())
+                .build();
+    }
+
+    /**
+     * 判题接口
+     *
+     * @param judgeDTO 判题信息
+     * @return 判题结果
+     */
+    @Override
+    public JudgeResult judge(@NotNull JudgeDTO judgeDTO) {
+        HttpUrl httpUrl = createUrlBuilder("/api/judge").build();
+        Response response = post(httpUrl, writeRequestBody(judgeDTO));
+        return getResponseBody(response, JudgeResult.class)
+                .map(judgeResult -> {
+                    if (judgeResult.getMessage() == null) {
+                        return judgeResult;
+                    } else {
+                        throw new CodeJudgeSystemException(judgeResult.getMessage());
+                    }
+                }).orElseThrow(() -> SeecoderBokException.UNWRAP_EXCEPTION);
+    }
+
+
+    private HttpUrl.Builder createUrlBuilder(final String path) {
+        return Objects.requireNonNull(HttpUrl.parse(CONFIG_HOST + path)).newBuilder();
+    }
+
+    private Response post(HttpUrl httpUrl, RequestBody requestBody) {
+        return requestWithMethod("POST", httpUrl, requestBody);
+    }
+
+    private Response requestWithMethod(String method, HttpUrl httpUrl, RequestBody requestBody) {
+        Request request = new Request.Builder().url(httpUrl).method(method, requestBody).build();
+        try {
+            return client.newCall(request).execute();
+        } catch (IOException e) {
+            logger.error("IOException.", e);
+            throw SeecoderBokException.IO_EXCEPTION;
+        }
+    }
+
+    private <T> Optional<T> getResponseBody(Response response, Class<T> tClass) {
+        return getResponseBody(
+                response,
+                bodyString -> {
+                    try {
+                        return mapper.readValue(bodyString, tClass);
+                    } catch (JsonProcessingException e) {
+                        logger.error("JsonProcessingException.", e);
+                        throw SeecoderBokException.JSON_EXCEPTION;
+                    }
+                });
+    }
+
+    private <T> Optional<T> getResponseBody(Response response, TypeReference<T> typeReference) {
+        return getResponseBody(
+                response,
+                bodyString -> {
+                    try {
+                        return mapper.readValue(bodyString, typeReference);
+                    } catch (JsonProcessingException e) {
+                        logger.error("JsonProcessingException.", e);
+                        throw SeecoderBokException.JSON_EXCEPTION;
+                    }
+                });
+    }
+
+    private <T> Optional<T> getResponseBody(Response response, Function<String, T> mapType) {
+        return Optional.ofNullable(response.body())
+                .map(body -> {
+                    try {
+                        String bodyString = body.string();
+                        return mapType.apply(bodyString);
+                    } catch (IOException e) {
+                        logger.error("IOException.", e);
+                        throw SeecoderBokException.IO_EXCEPTION;
+                    }
+                });
+    }
+
+    private <T> RequestBody writeRequestBody(T obj) {
+        if (obj == null) {
+            return null;
+        }
+
+        try {
+            return RequestBody.create(CodeJudgeConstants.JSON, mapper.writeValueAsString(obj));
+        } catch (JsonProcessingException e) {
+            logger.error("JsonProcessingException.", e);
+            throw SeecoderBokException.JSON_EXCEPTION;
+        }
+    }
+
+}

+ 13 - 0
codejudge-client/src/main/java/cn/seecoder/codejudge/client/CodeJudgeConstants.java

@@ -0,0 +1,13 @@
+package cn.seecoder.codejudge.client;
+
+import okhttp3.MediaType;
+
+/**
+ * @author kunduin
+ */
+public class CodeJudgeConstants {
+    public final static int PAGE_START = 0;
+
+    public static final MediaType JSON
+            = MediaType.parse("application/json; charset=utf-8");
+}

+ 28 - 0
codejudge-client/src/main/java/cn/seecoder/codejudge/client/CodeJudgeException.java

@@ -0,0 +1,28 @@
+package cn.seecoder.codejudge.client;
+
+import cn.seecoder.bok.client.SeecoderBokException;
+
+/**
+ * @author kunduin
+ */
+public class CodeJudgeException extends RuntimeException {
+
+    public static final CodeJudgeException JSON_EXCEPTION = new CodeJudgeException("JSON exception", 101);
+
+    public static final CodeJudgeException IO_EXCEPTION = new CodeJudgeException("IO exception", 102);
+
+    public static final CodeJudgeException UNWRAP_EXCEPTION = new CodeJudgeException("Return false", 102);
+
+    public static final String BIZ_ERROR_CODE = "100";
+
+    private final int code;
+
+    public CodeJudgeException(String message, int code) {
+        super(message);
+        this.code = code;
+    }
+
+    public int getCode() {
+        return code;
+    }
+}

+ 15 - 0
codejudge-client/src/main/java/cn/seecoder/codejudge/client/CodeJudgeSystemException.java

@@ -0,0 +1,15 @@
+package cn.seecoder.codejudge.client;
+
+/**
+ * @author kunduin
+ */
+public class CodeJudgeSystemException extends RuntimeException {
+
+    public CodeJudgeSystemException(String message) {
+        super(message);
+    }
+
+    public int getCode() {
+        return 500;
+    }
+}

+ 99 - 0
codejudge-client/src/main/java/cn/seecoder/codejudge/client/JudgeDTO.java

@@ -0,0 +1,99 @@
+package cn.seecoder.codejudge.client;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author kunduin
+ */
+public class JudgeDTO {
+    /**
+     * 源代码
+     */
+    private String code;
+
+    /**
+     * 编程语言 {cpp, java, c, python}
+     */
+    private String language;
+
+    /**
+     * 时间限制
+     */
+    private Integer timeLimit;
+
+    /**
+     * 内存限制
+     */
+    private Integer memoryLimit;
+
+    /**
+     * 输入表
+     */
+    private List<String> inputList;
+
+    /**
+     * 输出表
+     */
+    private List<String> outputList;
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getLanguage() {
+        return language;
+    }
+
+    public void setLanguage(String language) {
+        this.language = language;
+    }
+
+    public Integer getTimeLimit() {
+        return timeLimit;
+    }
+
+    public void setTimeLimit(Integer timeLimit) {
+        this.timeLimit = timeLimit;
+    }
+
+    public Integer getMemoryLimit() {
+        return memoryLimit;
+    }
+
+    public void setMemoryLimit(Integer memoryLimit) {
+        this.memoryLimit = memoryLimit;
+    }
+
+    public List<String> getInputList() {
+        return inputList;
+    }
+
+    public void setInputList(List<String> inputList) {
+        this.inputList = inputList;
+    }
+
+    public List<String> getOutputList() {
+        return outputList;
+    }
+
+    public void setOutputList(List<String> outputList) {
+        this.outputList = outputList;
+    }
+
+    @Override
+    public String toString() {
+        return "JudgeDTO{" +
+                "code='" + code + '\'' +
+                ", language='" + language + '\'' +
+                ", timeLimit=" + timeLimit +
+                ", memoryLimit=" + memoryLimit +
+                ", inputList=" + inputList +
+                ", outputList=" + outputList +
+                '}';
+    }
+}

+ 90 - 0
codejudge-client/src/main/java/cn/seecoder/codejudge/client/JudgeResult.java

@@ -0,0 +1,90 @@
+package cn.seecoder.codejudge.client;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+
+/**
+ * @author kunduin
+ */
+public class JudgeResult {
+
+    private String message;
+
+    @JsonProperty("result_list")
+    private List<Item> resultList;
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public List<Item> getResultList() {
+        return resultList;
+    }
+
+    public void setResultList(List<Item> resultList) {
+        this.resultList = resultList;
+    }
+
+    @Override
+    public String toString() {
+        return "JudgeResult{" +
+                "message='" + message + '\'' +
+                ", resultList=" + resultList +
+                '}';
+    }
+
+    public static class Item {
+
+        private JudgeResultType result;
+
+        /**
+         * 单位毫秒
+         */
+        @JsonProperty("timeused")
+        private Integer timeUsed;
+
+        /**
+         * 单位kb
+         */
+        @JsonProperty("memoryused")
+        private Integer memoryUsed;
+
+        public JudgeResultType getResult() {
+            return result;
+        }
+
+        public void setResult(JudgeResultType result) {
+            this.result = result;
+        }
+
+        public Integer getTimeUsed() {
+            return timeUsed;
+        }
+
+        public void setTimeUsed(Integer timeUsed) {
+            this.timeUsed = timeUsed;
+        }
+
+        public Integer getMemoryUsed() {
+            return memoryUsed;
+        }
+
+        public void setMemoryUsed(Integer memoryUsed) {
+            this.memoryUsed = memoryUsed;
+        }
+
+        @Override
+        public String toString() {
+            return "Item{" +
+                    "result=" + result +
+                    ", timeUsed=" + timeUsed +
+                    ", memoryUsed=" + memoryUsed +
+                    '}';
+        }
+    }
+}

+ 38 - 0
codejudge-client/src/main/java/cn/seecoder/codejudge/client/JudgeResultType.java

@@ -0,0 +1,38 @@
+package cn.seecoder.codejudge.client;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * @author kunduin
+ */
+public enum JudgeResultType {
+    /**
+     * 正确
+     */
+    @JsonProperty("Accepted")
+    ACCEPT,
+
+    @JsonProperty("Presentation Error")
+    PRESENTATION_ERROR,
+
+    @JsonProperty("Time Limit Exceeded")
+    TIME_LIMIT_EXCEEDED,
+
+    @JsonProperty("Memory Limit Exceeded")
+    MEMORY_LIMIT_EXCEEDED,
+
+    @JsonProperty("Wrong Answer")
+    WRONG_ANSWER,
+
+    @JsonProperty("Runtime Error")
+    RUNTIME_ERROR,
+
+    @JsonProperty("Output Limit Exceeded")
+    OUTPUT_LIMIT_EXCEEDED,
+
+    @JsonProperty("Compile Error")
+    COMPILE_ERROR,
+
+    @JsonProperty("System Error")
+    SYSTEM_ERROR
+}

+ 33 - 0
codejudge-client/src/test/java/cn/seecoder/codejudge/client/CodeJudgeClientTest.java

@@ -0,0 +1,33 @@
+package cn.seecoder.codejudge.client;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * @author kunduin
+ */
+class CodeJudgeClientTest {
+
+    @Test
+    void judge() {
+        CodeJudgeClient client = new CodeJudgeClient("http://172.19.240.207:5000");
+        JudgeDTO judgeDTO = new JudgeDTO();
+        judgeDTO.setCode("import java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        while (scanner.hasNext()){\n            int t = scanner.nextInt();\n            for (int i=0;i<t;i++){\n                long power = scanner.nextLong();\n                long num = 1;\n                power-=num*num;\n                while (power>=0){\n                    num++;\n                    power-=num*num;\n                }\n                System.out.println(num-1);\n            }\n        }\n    }\n}\n\n");
+        judgeDTO.setTimeLimit(1000);
+        judgeDTO.setLanguage("java");
+        judgeDTO.setMemoryLimit(30000);
+        judgeDTO.setInputList(Arrays.asList("1\n14","2\n14\n10"));
+        judgeDTO.setOutputList(Arrays.asList("3\n","3\n2\n"));
+        JudgeResult judge = client.judge(judgeDTO);
+        System.out.println(judge);
+
+        judgeDTO.setOutputList(Collections.singletonList("3\n"));
+        JudgeResult judge1 = client.judge(judgeDTO);
+        System.out.println(judge1);
+    }
+}

+ 1 - 0
pom.xml

@@ -7,6 +7,7 @@
         <module>judgement-client</module>
         <module>judgement-server</module>
         <module>judgement-common</module>
+        <module>codejudge-client</module>
     </modules>
     <parent>
         <groupId>org.springframework.boot</groupId>