对接LeetCode-完成代码提交校验

视频地址

视频地址

QQ机器人相关指令-对接LeetCode

去网页上截取相关请求路由信息

LeetCode基础URI: https://leetcode-cn.com

提交code的URL

POST /problems/{problem}/submit/
请求参数: problem 对应题目的slug,如longest-substring-without-repeating-characters
请求体

{
    "question_id": "142",
    "lang": "java",
    "typed_code": "/**\\n * Definition for singly-linked list.\\n * class ListNode {\\n *     int val;\\n *     ListNode next;\\n *     ListNode(int x) {\\n *         val = x;\\n *         next = null;\\n *     }\\n * }\\n */\\npublic class Solution {\\n  public ListNode detectCycle(ListNode head) {\\n        if (head == null) return null;\\n        ListNode fast = head, slow = head;\\n        while (fast != null && fast.next != null) {\\n            slow = slow.next;\\n            fast = fast.next.next;\\n            if (fast == slow) {\\n                break;\\n            }\\n        }\\n        // 上面的代码类似 hasCycle 函数\\n        if (fast == null || fast.next == null) {\\n            // fast 遇到空指针说明没有环\\n            return null;\\n        }\\n        // 将快指针置回头部,慢指针每次走一步,快指针也每次走一步,直到相遇\\n        fast = head;\\n        // 快慢指针同步前进,相交点就是环起点\\n        while (fast != slow) {\\n            fast = fast.next;\\n            slow = slow.next;\\n        }\\n        return fast;\\n    }\\n}",
    "test_mode": false,
    "test_judger": "amet ea ut laboris ad",
    "questionSlug": "linked-list-cycle-ii"
}

响应参数

{
    "submission_id": 296959889
}

检查code的URL

POST /submissions/detail/{submission_id}/check/
请求参数: submission_id,前面一个URL成功响应后的submission_id
响应参数

# 编译成功 

{
    "status_code": 10,
    "lang": "java",
    "run_success": true,
    "status_runtime": "0 ms",
    "memory": 42612000,
    "display_runtime": "0",
    "question_id": "142",
    "elapsed_time": 167,
    "compare_result": "1111111111111111",
    "code_output": "",
    "std_output": "",
    "last_testcase": "",
    "expected_output": "",
    "task_finish_time": 1649410089047,
    "task_name": "judger.judgetask.Judge",
    "finished": true,
    "status_msg": "Accepted",
    "state": "SUCCESS",
    "fast_submit": false,
    "total_correct": 16,
    "total_testcases": 16,
    "submission_id": "296871548",
    "runtime_percentile": 100,
    "status_memory": "41.6 MB",
    "memory_percentile": 48.99469999999997,
    "pretty_lang": "Java"
}

# 编译出错
{
    "status_code": 20,
    "lang": "java",
    "run_success": false,
    "compile_error": "Line 16: error: reached end of file while parsing",
    "full_compile_error": "Line 16: error: reached end of file while parsing\n}\n ^",
    "status_runtime": "N/A",
    "memory": 0,
    "question_id": "142",
    "task_finish_time": 1649410107119,
    "elapsed_time": 0,
    "task_name": "judger.judgetask.Judge",
    "finished": true,
    "status_msg": "Compile Error",
    "state": "SUCCESS",
    "fast_submit": false,
    "total_correct": null,
    "total_testcases": null,
    "submission_id": "296871728",
    "runtime_percentile": null,
    "status_memory": "N/A",
    "memory_percentile": null,
    "pretty_lang": "Java"
}



# 解答错误

{
    "status_code": 11,
    "lang": "java",
    "run_success": true,
    "status_runtime": "N/A",
    "memory": 42788000,
    "display_runtime": "0",
    "question_id": "142",
    "elapsed_time": 150,
    "compare_result": "0101100000000000",
    "code_output": "tail connects to node index 0",
    "std_output": "",
    "last_testcase": "[3,2,0,-4]\n1",
    "expected_output": "tail connects to node index 1",
    "task_finish_time": 1649410173548,
    "task_name": "judger.judgetask.Judge",
    "finished": true,
    "status_msg": "Wrong Answer",
    "state": "SUCCESS",
    "fast_submit": false,
    "total_correct": 3,
    "total_testcases": 16,
    "submission_id": "296872413",
    "runtime_percentile": null,
    "status_memory": "N/A",
    "memory_percentile": null,
    "pretty_lang": "Java",
    "input_formatted": "[3,2,0,-4], 1",
    "input": "[3,2,0,-4]\n1"
}

定义LeetCode常量

public interface LeetCodeConstants {
/**
 * 基础路由
 */
String BASIC_URI = "https://leetcode-cn.com";
 /**
  * Cookie
  */
 String COOKIE = "";

编写请求的测试用例

@Slf4j
@SpringBootTest
public class LeetCodeTest {
    String template = """
            ===============================================================
                        
            提交结果        执行用时  内存消耗        语言   提交时间
            %s      %s ms       %s      %s  %s
                        
            ===============================================================
            """;

    /**
     * Gson和FastJson数据转换的坑
     * problem: https://blog.csdn.net/JoeBig7/article/details/90233358?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_aa&utm_relevant_index=2
     */
    @Test
    public void testSubmitQuestion() {
        String json = "{\n" +
                "  "question_id": "142",\n" +
                "  "lang": "java",\n" +
                "  "typed_code": "/**\n * Definition for singly-linked list.\n * class ListNode {\n *     int val;\n *     ListNode next;\n *     ListNode(int x) {\n *         val = x;\n *         next = null;\n *     }\n * }\n */\npublic class Solution {\n  public ListNode detectCycle(ListNode head) {\n        if (head == null) return null;\n        ListNode fast = head, slow = head;\n        while (fast != null && fast.next != null) {\n            slow = slow.next;\n            fast = fast.next.next;\n            if (fast == slow) {\n                break;\n            }\n        }\n        // 上面的代码类似 hasCycle 函数\n        if (fast == null || fast.next == null) {\n            // fast 遇到空指针说明没有环\n            return null;\n        }\n        // 将快指针置回头部,慢指针每次走一步,快指针也每次走一步,直到相遇\n        fast = head;\n        // 快慢指针同步前进,相交点就是环起点\n        while (fast != slow) {\n            fast = fast.next;\n            slow = slow.next;\n        }\n        return fast;\n    }\n}",\n" +
                "  "test_mode": false,\n" +
                "  "test_judger": "",\n" +
                "  "questionSlug": "linked-list-cycle-ii"\n" +
                "}";
        // 题目名称
        String problem = "linked-list-cycle-ii";
        // 发送http请求
        String submitJson = HttpClient.textBody(LeetCodeConstants.BASIC_URI + "/problems/" + problem + "/submit/")
                .json(json)
                .header("cookie", LeetCodeConstants.COOKIE)
                .header("origin", LeetCodeConstants.BASIC_URI)
                .asString();
        JSON.DEFAULT_PARSER_FEATURE &= ~Feature.UseBigDecimal.getMask();
        Map<?, ?> submitMap = JSON.parseObject(submitJson, Map.class);
        String submissionId = String.valueOf(submitMap.get("submission_id"));
        System.out.println(submissionId);
        String statusCode;
        Map<?, ?> checkMap;
        do {
            String checkJson = HttpClient.get(LeetCodeConstants.BASIC_URI + "/submissions/detail/" + submissionId + "/check/")
                    .header("cookie", LeetCodeConstants.COOKIE)
                    .header("origin", LeetCodeConstants.BASIC_URI)
                    .asString();
            checkMap = JSON.parseObject(checkJson, Map.class);
            statusCode = String.valueOf(checkMap.get("status_code"));
            System.out.println(statusCode);
        } while (!statusCode.equals("10"));
        System.out.println(checkMap);
        System.out.println("======================");
        String result = String.valueOf(checkMap.get("state"));
        Integer displayRuntime = Integer.valueOf(String.valueOf(checkMap.get("display_runtime")));
        String statusMemory = String.valueOf(checkMap.get("status_memory"));
        String lang = String.valueOf(checkMap.get("lang"));
        long taskFinishTime = Long.parseLong(String.valueOf(checkMap.get("task_finish_time")));
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String taskFinishTimeStr = sdf.format(new Date(taskFinishTime));
        System.out.println(String.format(template, result, displayRuntime, statusMemory, lang, taskFinishTimeStr, submissionId));
        System.out.println("======================");
    }
}

image.png

定义提交检查指令

想实现的效果

check_leetcode_problem reverse-linked-list #
public class Solution {
  public ListNode detectCycle(ListNode head) {
        if (head == null) return null;
        ListNode fast = head, slow = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (fast == slow) {
                break;
            }
        }
        // 上面的代码类似 hasCycle 函数
        if (fast == null || fast.next == null) {
            // fast 遇到空指针说明没有环
            return null;
        }
        // 将快指针置回头部,慢指针每次走一步,快指针也每次走一步,直到相遇
        fast = head;
        // 快慢指针同步前进,相交点就是环起点
        while (fast != slow) {
            fast = fast.next;
            slow = slow.next;
        }
        return fast;
    }
}
#

定义QQ机器指令: check_leetcode_problem\s(?.{1,100})\s#(?[\s\S]+)#$

测试指令

@Slf4j
@Component("simpleBotLeetCodeEvent")
public class SimpleBotLeetCodeEvent {

    @Value("${qq.owner}")
    private String ownerCode;
    @Value("${qq.group}")
    private String groupCode;


    @OnPrivate
    @Filter(value = "check_leetcode_problem\s(?<problem>.{1,100})\s#(?<code>[\s\S]+)#$", matchType = MatchType.REGEX_MATCHES, trim = true)
    public void doPrivateMsg(PrivateMsg event, MsgSender sender, @FilterValue("problem") String problem, @FilterValue("code") String code) {
        AccountInfo accountInfo = event.getAccountInfo();
        if (ownerCode.equals(accountInfo.getAccountCode())) {
            System.out.println(code);
            System.out.println(problem);
        }
    }
}

image.png

完成指令调用API-编译成功情况

@Slf4j
@Component("simpleBotLeetCodeEvent")
public class SimpleBotLeetCodeEvent {

    @Value("${qq.owner}")
    private String ownerCode;
    @Value("${qq.group}")
    private String groupCode;


    @OnPrivate
    @Filter(value = "check_leetcode_problem\s(?<problem>.{1,100})\s#(?<code>[\s\S]+)#$", matchType = MatchType.REGEX_MATCHES, trim = true)
    public void doPrivateMsg(PrivateMsg event, MsgSender sender, @FilterValue("problem") String problem, @FilterValue("code") String code) {
        AccountInfo accountInfo = event.getAccountInfo();
        if (ownerCode.equals(accountInfo.getAccountCode())) {
            System.out.println(code);
            System.out.println(problem);

            Map<String, Object> submitRequestMap = new HashMap<>(8);
            /**
             * TODO
             */
            submitRequestMap.put("question_id", "142");
            submitRequestMap.put("lang", "java");
            submitRequestMap.put("false", false);
            submitRequestMap.put("test_judger", "amet ea ut laboris ad");
            submitRequestMap.put("questionSlug", "problem");
            submitRequestMap.put("typed_code", code);
            // 发送http请求
            String submitJson = HttpClient.textBody(LeetCodeConstants.BASIC_URI + "/problems/" + problem + "/submit/")
                    .json(JSON.toJSONString(submitRequestMap))
                    .header("cookie", LeetCodeConstants.COOKIE)
                    .header("origin", LeetCodeConstants.BASIC_URI)
                    .asString();
            JSON.DEFAULT_PARSER_FEATURE &= ~Feature.UseBigDecimal.getMask();
            Map<?, ?> submitMap = JSON.parseObject(submitJson, Map.class);
            String submissionId = String.valueOf(submitMap.get("submission_id"));
            String statusCode;
            Map<?, ?> checkMap;
            do {
                String checkJson = HttpClient.get(LeetCodeConstants.BASIC_URI + "/submissions/detail/" + submissionId + "/check/")
                        .header("cookie", LeetCodeConstants.COOKIE)
                        .header("origin", LeetCodeConstants.BASIC_URI)
                        .asString();
                checkMap = JSON.parseObject(checkJson, Map.class);
                statusCode = String.valueOf(checkMap.get("status_code"));
                System.out.println(statusCode);
            } while (!statusCode.equals("10"));
            String template = """
                    ===============================================================
                                
                    提交结果        执行用时  内存消耗        语言   提交时间
                    %s      %s ms       %s      %s  %s
                                
                    ===============================================================
                    """;
            String result = String.valueOf(checkMap.get("state"));
            Integer displayRuntime = Integer.valueOf(String.valueOf(checkMap.get("display_runtime")));
            String statusMemory = String.valueOf(checkMap.get("status_memory"));
            String lang = String.valueOf(checkMap.get("lang"));
            long taskFinishTime = Long.parseLong(String.valueOf(checkMap.get("task_finish_time")));
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String taskFinishTimeStr = sdf.format(new Date(taskFinishTime));
            sender.SENDER.sendPrivateMsgAsync(ownerCode, String.format(template, result, displayRuntime, statusMemory, lang, taskFinishTimeStr, submissionId));
        }
    }
}

image.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫吹过的柚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值