Classroom伙伴平台自动判题场景调用实例
引导式阅读
Java
Classroom伙伴平台自动判题场景调用实例
作者
C***
上架时间
2023-11-14 06:35:14

1. 版本说明

本示例基于华为云SDK V3.0版本开发。

2. 产品优势

华为云面向合作伙伴开放实时的、多语言的、高并发的自动判题能力,通过安全、便捷的API集成方式帮助合作伙伴解决频繁、复杂、高成本的判题问题;

  • 1、集成方式简单:可通过简单的配置和调试,集成判题接口,开启代码编译与评判的便捷调用。用户还可以通过API Explorer查看更加详尽的参数说明和配置用法,简单快速完成搭建。
  • 2、判题语言多样:我们提供了C、C++、Java、Python多种业界流行的编程语言编译评判能力,同时支持返回结果、返回文件、图片等多种方式,并提供查看及下载文件接口,全方位满足开发者在不同场景下的诉求。
  • 3、编译处理实时:全流程自动编译运行代码和触发判题,能够快速响应业务需要。编译判题支持多种错误类型反馈,更好的指导代码调整;回调功能可使伙伴企业的调用更加安全可靠。
  • 4、并发自主控制:合作伙伴可根据自有平台的并发需要灵活购买【专享型】判题节点,单节点提供每月不少于8k次的执行能力。同时我们提供了判题记录与详情查看,为伙伴价值保驾护航。

3. 产品应用场景

  • 1、支持合作伙伴平台面向开发者的体验式编程、简单代码片段补全等题型。利用直接返回运行结果,快速帮助初级开发者完成简单编程题目的作答和反馈。
  • 2、通过配置不同的判题返回类型帮助伙伴应对多种主流语言类型开发场景,满足中级开发者进行更复杂程序题目的作答和结果查看。
  • 3、支持主流语言的多类型返回格式,包括人工智能编程及数据可视化相关的编码制图等能力,并提供高效的查看及下载方式,全方位覆盖伙伴平台的题目诉求。

4. 功能介绍

华为云提供了Classroom服务端SDK,您可以直接集成服务端SDK来调用Classroom的相关API,从而实现对Classroom的快速操作。 该示例展示了如何通过java版SDK来体验Classroom教学平台判题使能功能。

5. 前置条件

  • 1、获取华为云开发工具包(SDK),您也可以查看安装JAVA SDK。
  • 2、您需要拥有华为云租户账号以及该账号对应的 Access Key(AK)和 Secret Access Key(SK)请在华为云控制台“我的凭证 > 访问密钥”页面上创建和查看您的AK/SK。具体请参见 访问密钥
  • 3、华为云 Java SDK 支持 Java JDK 1.8 及其以上版本。
  • 4、用户需要Classroom平台中申请体验判题赋能功能,且配置好回调地址和回调秘钥,前往伙伴赋能平台申请

6. 安装SDK

您可以通过Maven方式获取和安装SDK,您只需要在Java项目的pom.xml文件中加入相应的依赖项即可。

具体的SDK版本号请参见 SDK开发中心

<dependencies> <dependency> <groupId>com.huaweicloud.sdk</groupId> <artifactId>huaweicloud-sdk-core</artifactId> <version>3.0.65</version> </dependency> <dependency> <groupId>com.huaweicloud.sdk</groupId> <artifactId>huaweicloud-sdk-classroom</artifactId> <version>3.0.65</version> </dependency> </dependencies>

7. 伙伴平台判题调用实例

合作伙伴在购买判题服务后,可通过自有平台向华为云申请自动判题的API接口 ,在工程里面引用判题接口,并下发判题任务获取判题结果

  • 实例一:请尝试用Java语言输出Hello world!

    伙伴平台判题的代码://用base64加密生成字符串

public class Main { public static void main(String[] args) { System.out.println("Hello world!"); } }

开始调用:

public static void main(String[] args) { /** * 1、状态基础认证信息: * - your Access Key: 华为云账号Access Key * - your Secret Key: 华为云账号Secret Access Key * - evs_endpoint: 华为云Classroom服务访问网关地址 * 认证用的ak和sk直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全; * 本示例以ak和sk保存在环境变量中来实现身份验证为例,运行本示例前请先在本地环境中设置环境变量HUAWEICLOUD_SDK_AK和HUAWEICLOUD_SDK_SK。 */ BasicCredentials credentials = new BasicCredentials().withAk(System.getenv("HUAWEICLOUD_SDK_AK")).withSk(System.getenv("HUAWEICLOUD_SDK_SK")); ClassroomClient classroomClient = ClassroomClient.newBuilder() .withCredential(credentials) .withEndpoint("*** evs_endpoint ***") .build(); try { // 2、调用下发判题任务接口(对参数中的代码判断进行编译及运行) ApplyJudgementResponse applyJudgementResponse = classroomClient.applyJudgement(getApplyJudgementResponseBody()); LOGGER.info(applyJudgementResponse.toString()); // 3、获取下发判题任务返回值,获取判题id,用于后续判题结果查询 String judgementId = applyJudgementResponse.getJudgementId(); // 4、根据判题id来获取判题结果详情(注:判题执行需要时间,因此此方法可循环调用,直到判题执行完毕方可查询判题最终执行结果) ShowJudgementDetailResponse showJudgementDetailResponse = classroomClient.showJudgementDetail(getJudgementDetailRequestParam(judgementId)); LOGGER.info(showJudgementDetailResponse.toString()); } catch (ClientRequestException e) { LOGGER.error(String.valueOf(e.getHttpStatusCode())); LOGGER.error(e.toString()); } catch (ServerResponseException e) { LOGGER.error(String.valueOf(e.getHttpStatusCode())); LOGGER.error(e.getMessage()); } } /** * 构建下发判题任务参数 * * @return 触发判题请求参数 */ private static ApplyJudgementRequest getApplyJudgementResponseBody() { ApplyJudgementRequest applyJudgementRequest = new ApplyJudgementRequest(); JudgementTaskRequestBody judgementTaskRequestBody = new JudgementTaskRequestBody(); judgementTaskRequestBody.setNotifyUrl("*** call back url ***");//替换伙伴赋能平台中配置的回调地址 judgementTaskRequestBody.setCodeType(JudgementTaskRequestBody.CodeTypeEnum.INLINE); judgementTaskRequestBody.setSourceCode("*** java code for base64 ***"); //将伙伴平台的判题代码用base64加密成字符串来替换 judgementTaskRequestBody.setDescription("java code description"); judgementTaskRequestBody.setRuntimeType(JudgementTaskRequestBody.RuntimeTypeEnum.JAVA); judgementTaskRequestBody.setTimeout(60); // 代码运行超时时间1~60s judgementTaskRequestBody.setOutputType(JudgementTaskRequestBody.OutputTypeEnum.CASEOUT); applyJudgementRequest.setBody(judgementTaskRequestBody); return applyJudgementRequest; } /** * 构建获取判题结果详情参数 * * @param judgementId 判题任务id * @return 查询判题结果请求参数 */ private static ShowJudgementDetailRequest getJudgementDetailRequestParam(String judgementId) { ShowJudgementDetailRequest showJudgementDetailRequest = new ShowJudgementDetailRequest(); showJudgementDetailRequest.setJudgementId(judgementId); return showJudgementDetailRequest; }
  • 实例二:请利用程序绘制一个五角星:

    语言类型:Python

    返回类型:返回生成的图片文件

伙伴平台判题的代码://用base64加密生成字符串

#!/usr/bin/python # -*- coding: UTF-8 -*- import cv2 import numpy as np import math # 定义画布,构造518*518全0数组 img = np.zeros((518, 518, 3), np.uint8) # 使用白色填充图片区域 img.fill(255) # 用于保存填充点 points = [] # 使五角星位于图片中央 base = (259, 259) # 使五角星正放 startAngle = 18 # 调整五角星的大小 initalX = 180 # 用于确定每次填充点的位置,分五次确定 initalY = initalX / (math.cos(0.2 * math.pi) + math.sin(0.2 * math.pi) / math.tan(0.1 * math.pi)) def getPoint(angle, d, base): # 获取填充点的角度值,使用弧度制 angle = angle / 180.0 * math.pi # 获取填充点坐标 pointX = math.cos(angle) * d pointY = math.sin(angle) * d return [base[0] + pointX, base[1] - pointY] # 获取十个填充点,每次获取两个,最后十个填充点围成的图片即为五角星 for i in range(5): # 确定第一个填充点 points.append(getPoint(startAngle, initalX, base)) # 五角星的内角为36度 startAngle += 36 # 确定第二个填充点 points.append(getPoint(startAngle, initalY, base)) # 用于确定下个填充点的角度 startAngle += 36 # 十个填充点坐标 points = np.array([points], np.int32) # 绘制五角星 cv2.fillPoly(img, points, (255, 204, 102), cv2.LINE_AA) cv2.imwrite("/projects/output/img.png", img)

开始调用:(本实例相较于实例一增加图片id及下载文件的接口)

public static void main(String[] args) { /** * 1、状态基础认证信息: * - your Access Key: 华为云账号Access Key * - your Secret Key: 华为云账号Secret Access Key * - evs_endpoint: 华为云Classroom服务访问网关地址 * 认证用的ak和sk直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全; * 本示例以ak和sk保存在环境变量中来实现身份验证为例,运行本示例前请先在本地环境中设置环境变量HUAWEICLOUD_SDK_AK和HUAWEICLOUD_SDK_SK。 */ BasicCredentials credentials = new BasicCredentials().withAk(System.getenv("HUAWEICLOUD_SDK_AK")).withSk(System.getenv("HUAWEICLOUD_SDK_SK")); ClassroomClient classroomClient = ClassroomClient.newBuilder() .withCredential(credentials) .withEndpoint("*** evs_endpoint ***") .build(); try { // 2、调用下发判题任务接口(对参数中的代码判断进行编译及运行) ApplyJudgementResponse applyJudgementResponse = classroomClient.applyJudgement(getApplyJudgementResponseBody()); LOGGER.info(applyJudgementResponse.toString()); // 3、获取下发判题任务返回值,获取判题id,用于后续判题结果查询 String judgementId = applyJudgementResponse.getJudgementId(); // 4、根据判题id来获取判题结果详情(注:判题执行需要时间,因此此方法可循环调用,直到判题执行完毕方可查询判题最终执行结果) ShowJudgementDetailResponse showJudgementDetailResponse = classroomClient.showJudgementDetail(getJudgementDetailRequestParam(judgementId)); LOGGER.info(showJudgementDetailResponse.toString()); // 5、获取判题结果中的图片id String imageId = showJudgementDetailResponse.getResult().getImageId(); // 6、根据图片id下载文件 ShowJudgementFileResponse showJudgementFileResponse = classroomClient.showJudgementFile(getJudgementFileRequestParam(imageId)); // 7、以下代码为计算并打印文件流大小(注:用户可根据此接口自行处理下载文件) showJudgementFileResponse.consumeDownloadStream(inputStream -> { byte[] bytes = new byte[4 * 1024]; int len; int totalLen = 0; try { while ((len = inputStream.read(bytes)) != -1) { totalLen = totalLen + len; } LOGGER.info("image size: " + totalLen); } catch (IOException e) { LOGGER.error("Download file error ", e); } }); } catch (ClientRequestException e) { LOGGER.error(String.valueOf(e.getHttpStatusCode())); LOGGER.error(e.toString()); } catch (ServerResponseException e) { LOGGER.error(String.valueOf(e.getHttpStatusCode())); LOGGER.error(e.getMessage()); } } /** * 构建下发判题任务参数 * * @return 触发判题请求参数 */ private static ApplyJudgementRequest getApplyJudgementResponseBody() { ApplyJudgementRequest applyJudgementRequest = new ApplyJudgementRequest(); JudgementTaskRequestBody judgementTaskRequestBody = new JudgementTaskRequestBody(); judgementTaskRequestBody.setNotifyUrl("*** call back url ***");//替换伙伴赋能平台中配置的回调地址 judgementTaskRequestBody.setCodeType(JudgementTaskRequestBody.CodeTypeEnum.INLINE); judgementTaskRequestBody.setSourceCode("*** java code for base64 ***");//将伙伴平台的判题代码用base64加密成字符串来替换 judgementTaskRequestBody.setDescription("java code description"); judgementTaskRequestBody.setRuntimeType(JudgementTaskRequestBody.RuntimeTypeEnum.JAVA); judgementTaskRequestBody.setTimeout(60); // 代码运行超时时间1~60s judgementTaskRequestBody.setOutputType(JudgementTaskRequestBody.OutputTypeEnum.IMGOUT); applyJudgementRequest.setBody(judgementTaskRequestBody); return applyJudgementRequest; } /** * 构建获取判题结果详情参数 * * @param judgementId 判题任务id * @return 查询判题结果请求参数 */ private static ShowJudgementDetailRequest getJudgementDetailRequestParam(String judgementId) { ShowJudgementDetailRequest showJudgementDetailRequest = new ShowJudgementDetailRequest(); showJudgementDetailRequest.setJudgementId(judgementId); return showJudgementDetailRequest; } /** * 下载判题结果文件 * * @param fileId 文件id * @return 下载文件请求参数 */ private static ShowJudgementFileRequest getJudgementFileRequestParam(String fileId) { ShowJudgementFileRequest showJudgementFileRequest = new ShowJudgementFileRequest(); showJudgementFileRequest.setFileId(fileId); return showJudgementFileRequest; }

8. 返回示例

下发判题任务执行后会返回一个ID值,伙伴平台可以根据ID值查询判题执行的状态及结果

{ "judgement_id": "9a780fd55cd64333b668ba26132629d2" }

获取判题结果详情

{ "task_status": "callback_success", "status": "success", "judgement_id": "933b85316de54cea9e650d5f4f6b7ad2", "start_time": "2021-07-15 19:49:22", "end_time": "2021-07-15 19:49:28", "result": { "case_count": 2, "executed_count": 1, "testcases": [ { "output": "actual output", "case_status": "pass" } ] } }

9. 接口及参数说明

8. 参考

更多示例信息请参考Classroom

9. 修订记录

发布日期 文档版本 修订说明
2022-07-21 1.0 文档首次发布