码学堂教师用户使用帮助
教师如何在码学堂上组织教学活动?
如何在码学堂上开通教师权限?
如何注册码学堂账号?
如何登录码学堂?
如何在码学堂上建立学生组(班级)?
如何添加学生到学生组(班级)中?
如何在码学堂上创建课程?
如何在码学堂的课程中添加章节信息?
如何在码学堂上创建课程组?
如何在码学堂的课程中添加知识点?
如何在码学堂上备课?
如何在码学堂上出题?
如何上传程序题目测试数据?
如何在码学堂上安排课程导学?
如何在码学堂组织练习、考试、竞赛?
如何使用码学堂考试系统进行考试?
如何在码学堂上组织学习任务?
如何在码学堂上管理学生考勤?
如何在码学堂上设置学生学习绩效?
如何与学生进行问答互动?
如何使用码学堂AI公式识别助手?
在码学堂如何出SQL题目?
码学堂编译器版本
授课中如何录制视频?
教师如何加入授权商户机构?
如何开放码学堂智能助教讲题权限?
码学堂公式编辑器操作文档
更多教学工具
码学堂上如何自动出题?
码学堂上如何批量导入题目?
如何快速在码学堂上组织学生训练与竞赛?
码学堂中组织练习、考试、竞赛如何设置固定时长与指定独立完成时间?
如何在码学堂中进行图形化编程(Scratch OJ)教学?
码学堂更新日志
如何在智能体中连接码学堂?
1.码学堂API Key
2.题目加载接口
3. 提交判题接口指南
4. 测评结果查询接口指南
5. 知识点加载接口指南
6. 知识点管理接口指南
7. 码学堂题目管理接口指南
选项格式说明
支持编程语言对应说明
8. 编程题、函数题、程序填空题批量上传测试数据集
-
+
首页
2.题目加载接口
# 2.1 题目类型 码学堂提供8种类型题目,题目类型编号与题目类型描述如下: | 题目类型编号 | 题目类型 | | :----: | :----: | |1|判断题| |2|单选题| |3|多选题| |4|填空题| |5|程序填空题| |6|函数题| |7|编程题| |8|主观题| # 2.2 接入错误代码 | 错误代码 | 描述 | | :----: | :----: | | 602 | 没有提供签名 | | 603 | 无效的用户 | | 605 | 签名失败 | | 606 | 已经过期 | | 607 | 题目类型错误 | | 608 | 未找到此题目 | | 609 | 没有此题目的访问权限 | | 610 | 没有查询此老师题目的权限 | | 611 | 没有提供题目ID | | 612 | 没有提供商户提交ID | | 613 | 没有提供答案 | | 614 | 答案格式错误 | | 615 | 没有提供方案ID | | 616 | 没有此方案 | | 617 | 没有此方案的查询权限 | | 618 | 今日提交次数已达上限 | | 619 | 至少提供知识点ID或知识点父亲ID | |620 | 程序填空题的答案数与方案数不一致| |621|答案太长了| |700|教师email不能为空| |701|教师email不在商户的教师列表中| |702|课程或章节名称没能为空| |703|课程或章节名级别验证失败,1表示创建一门新的课程,2表示章,3表示节| |704|当创建章时,所属课程ID不能为空| |705|当创建节时,所属章ID不能为空| |706|提供的email(教师账号)与kp_id(知识点ID)不匹配| |707|课程或章节插入失败| |708|课程或章节更新失败| |709|具有子项,不能删除| |710|课程描述太长了,最多1000字| |711|题目所属知识点至少1个,最多10个| |712|题目所属知识点中存在不是节的ID或没访问知识权限| |800|题目选项为空或选项不规范| |801|没有设定分数| |802|没有操作权限,请检查题目ID是否有误| |803|主观题目必须提供得分点| |804|得分点格式错误,示例:{"0":"10","1":"10"}| |805|样例格式错误| |806|测试数据格式错误| |807|测试数据只对编程题、程序填空题、函数题有效| |808|没有测试数据| # 2.3 题目加载接口指南 ## 2.3.1 概述 通过码学堂提供的题库接口,用户可以直接引用码堂平台中,指定教师所出的或公开的题目。 ## 2.3.2 请求参数说明 | 序号 | 参数 | 名称 | 是否必须提供 |描述 | | :----: | :----: | :----: | :----: |:---- | | 01 | email | 教师登录账号 | 是 | | | 02 | ptype | 题目类型 | 是| {1,2,3,...,8},1:判断题、2:单项选择题、3:多项选择题、4:填空题、5:程序函数题、6:程序填空题、7:编程题、8:主观题| | 03 | sign | 签名 | 是 | SHA256签名 | | 04 | pid | 题目ID | 是 | 整型,指定时仅返回当前题目 | | 05 | kp_level | 知识点级别|否|1为一级,2为二级,3为三级| | 06 | kp_id | 知识点ID|否|整型,指定时仅返回当前知识点下的题目,有这个参数时,kp_level不能为空| | 07 | start | 分页 | 否 |不指定时默认为0,表示第1页,每页10条数据| | 08 |timestamp|时间戳|否|长整型数| ## 2.3.3 请求地址及方式 请求地址:`https://mp.api.maxuetang.cn/problem` 请求方式:`POST` ## 2.3.4 返回JSON参数说明 | 序号 | 参数 | 名称 | 描述 | | :---- | :----: | :----: |:---- | |01|success|成功标识|true 或 false| |02|msg|消息|返回执行消息| |03|data|数据|返回数据对象| |04|memory|内存大小|编程题目时返回内存大小要求| |05|time|时间要求|编程题目时返回内存大小要求,单位为秒| |06|in|输入|编程题目时返回输入要求说明| |07|out|输出|编程题目时返回输出要求说明| |08|src|题目来源| | |09|ans|题目解析| JSON对象,文本描述为desc,编程题目程序模板为列表,元素对象为{"language":"language","source":"code"}| |10|pid|题目ID| | |11|diff|题目难度|{1,2,3,4,5}| |12|ptype|题目类型|{1,2,3,...,8}| |13|source|题目资源信息|标准答案json格式字符串,选择题返回:{"0":{"key":"A","value":"optionA","ans":0},"1":{"key":"B","value":"optionA","ans":1},"length":2};程序填空题时返回填空程序段 | |14|title|题目名称|| |15|sample_in|样例输入|编程题目时返回| |16|sample_out|样例输出|编程题目时返回| |17|other_in_out|其他样例输入输出列表|编程题目时返回| |18|tip|提示| | |19|desc|题目题面描述|填空题时返回字符串中包含“填空”的标识信息@@{答案}(分数),可以作正则表达式解析后生成“填空”| |20|uid|所属教师ID|非公开题目时返回| |21|status|题目公开标识|2表示公开| |22|score|分数|| |23|teacher|教师| | |24|score_json|分数分布|程序题目时返回各测试数据分数JSON,主观题时返回得分点JSON| |25|start|分页|数据为列表时返回| |26|limit|分页大小|数据为列表时返回| |27|rows|数据总条数|数据为列表时返回| ## 2.3.5 接入示例 POST请求: ```java problem?pid=1008&ptype=7&email=33..3@qq.com&sign=8dd82f52c26...dd60731012f0 ``` 示例返回如下: ```json { "success": true, "msg": "OK", "data": { "memory": "64", "in": "输入的每行有两个输入数据。第一个是十进制数;第二个是负进制数的基数", "src": "第六届全国青少年信息学(计算机)奥林匹克分区联赛[2000年12月2日]", "ans": { "list": [ { "language": "cc", "source": "#include<iostream>\nusing namespace std;\nconst int N=1e5;\nint n,r,num=-1;\nint a[N];\nchar alp[10]={'A','B','C','D','E','F','G','H','I'};\nvoid print(int x){\n if(x<10) cout<<x;\n else cout<<alp[x-10];\n}\nint main(){\n cin>>n>>r;\n cout<<n<<\"=\";\n while(n!=0){\n a[++num]=n%r;\n n/=r;\n if(a[num]<0) a[num]-=r,n++;\n //cout<<a[num]<<\"\\n\";\n }\n for(int j=num;j>=0;j--) if(a[j]!=0||j!=num) print(a[j]);\n cout<<\"(base\"<<r<<\")\";\n}\n\n" } ], "desc": "答案解析" }, "pid": "1008", "diff": "3", "ptype": "7", "source": "", "title": "[2000年NOIP提高组] 进制转换", "sample_in": "30000 -2\n-20000 -7\n28800 -16\n-25000 -16", "out": "<p>结果显示在屏幕上,相对于输入,应输出此负进制数及其基数", "uid": "", "score": "15", "teacher": "向老师", "sample_out": "30000=1101101010111000(base-2)\n-20000=1111011000100000(base-2)\n28800=19180(base-16)\n-25000=7FB8(base-16)", "score_json": {"0":{"score":3,"desc":"fjz1"},"1":{"score":3,"desc":"fjz3"},"2":{"score":3,"desc":"fjz4"},"3":{"score":3,"desc":"fjz5"},"test":{"score":3,"desc":"test"}}, "other_in_out": [], "tip": "每个测试数据不超过1000", "time": "1", "desc": "我们可以用这样的方式来表示一个十进制数:将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数...底数的幂之和的形式。", "status": "2" } } ``` ### 2.3.5.1 Java接入示例 (1) SHA256加密算法 ```java package com.mxt.sign; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class SHA256Util { public static String createSHA256Str(String s) { if(s==null)return null; try { MessageDigest d = MessageDigest.getInstance("SHA-256"); d.update(s.getBytes("UTF-8")); return hexSHA256(d.digest()); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } private static String hexSHA256(byte[] b) { StringBuffer sub = new StringBuffer(); for(int i = 0; i < b.length; ++i) { String t = Integer.toHexString(b[i] & 0xFF); sub.append(t.length() == 1? "0"+t:t); } return sub.toString(); } } ``` (2) 签名算法 ```java package com.mxt.sign; import java.util.Iterator; import java.util.Map; /** * 签名 * @author maxuetang.cn * @date 2022-04-06 */ public class SignHelper { /** * 生成签名 * @param map:TreeMap * @param key:码学堂API Key * @return 签名字符串 */ public static String sign(Map map, String key){ map.remove("sign"); Iterator <String>iter = map.keySet().iterator(); StringBuffer sb = new StringBuffer(); while(iter.hasNext()){ sb.append(map.get(iter.next())); } return SHA256Util.createSHA256Str(sb.toString() + key); } /** * 签名验证 * @param map:TreeMap * @param key:码学堂API Key * @param sign:签名字符串 * @return */ public static boolean checkSign(Map map, String key, String sign){ if(map==null)return false; map.remove("sign"); Iterator <String>iter = map.keySet().iterator(); StringBuffer sb = new StringBuffer(); while(iter.hasNext()){ sb.append(map.get(iter.next())); } if(sb.length()<1)return false; return sign.equalsIgnoreCase(SHA256Util.createSHA256Str(sb.toString() + key)); } } ``` (3) 请求算法 ```java package com.mxt.problem.load; import java.util.Map; import java.util.TreeMap; import com.mxt.sign.SignHelper; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONObject; public class ProblemRemote { public static final String EMAIL="登录账号"; public static final String MERCHANT_KEY="码学堂API Key"; public static final String SERVER_HOST = "https://mp.api.maxuetang.cn/problem"; //按列表读取题目 public static JSONObject getProblems(int ptype, int start) { Map params = new TreeMap(); params.put("merchant_id", 0); params.put("email" , EMAIL); params.put("ptype" , ptype); params.put("start" , start); params.put("timestamp" , System.currentTimeMillis()); params.put("sign" , SignHelper.sign(params, MERCHANT_KEY)); return new JSONObject(HttpUtil.post(SERVER_HOST, params)); } //按题目号读取题目 public static JSONObject getProblem(int ptype, int pid) { Map params = new TreeMap(); params.put("merchant_id", 0); params.put("email" , EMAIL); params.put("ptype" , ptype); params.put("pid" , pid); params.put("timestamp" , System.currentTimeMillis()); params.put("sign" , SignHelper.sign(params, MxtApiConfig.MERCHANT_KEY)); return new JSONObject(HttpUtil.post(MxtApiConfig.PROBLEM_LOAD_API, params)); } public static void main(String []args) { System.out.println(getProblems(1,0)); } } ``` ## 2.3.6 注意事项 (1) 码学堂具有题目的管理功能,所以在显示题目时,需要在页面中加上样式: ```html <link rel="stylesheet" href="https://www.maxuetang.cn/lxojres/mxt-editor/css/mxt-editor.min.css?v=20220406"/> ``` (2) 填空题解析 ```java /** * 功能:将题目描述中的@@{答案}(分数)通过正则表达式轮换为带“空”的html * 参数:h为题目题目描述 * 返回:html代码,包含填空对应的input标签 */ var convertFillOutHtml=(h)=>{ var patt1 = /@@\{(.+?)\}\(([0-9]+\.{0,1}[0-9]{0,2})\)+/g; var patt2 = /@@\{(.+?)\}\(([0-9]+\.{0,1}[0-9]{0,2})\)/; var mm = h.match(patt1); for(var i=0;i<mm.length;i++){ var jj = mm[i].match(patt2); h = h.replace("@@{"+jj[1]+"}("+jj[2]+")","<input class='fill-out-ipt' type='text' value=''/><span>("+jj[2]+"分)</span>"); } return h; } ``` (3) 程序填空题解析 ```java /** * 功能:将题目裁判样例中的@@{答案}(分数)通过正则表达式轮换为带“空”的html * 参数:h为题目裁判样例,pid为题目ID * 返回:html代码,包含填空对应的input标签 */ var convertFillOutHtml=(h,pid)=>{ h = h.replace(new RegExp("<","g"),"<").replace(new RegExp(">","g"),">");; var patt1 = /@@\{(.+?)\}\(([0-9]+\.{0,1}[0-9]{0,2})\)+/g; var patt2 = /@@\{(.+?)\}\(([0-9]+\.{0,1}[0-9]{0,2})\)/; var mm = h.match(patt1); var obj = []; for(var i=0;i<mm.length;i++){ var jj = mm[i].match(patt2); h = h.replace("@@{"+jj[1]+"}("+jj[2]+")","<input data-id='"+pid+"' class='problem-input' type='text' value=''/><span>("+jj[2]+"分)</span>"); obj.push("("+(i+1)+") "+jj[1]+" "); } return {h:h, a:obj.join("")}; } ```
码学堂管理员
2026年9月5日 17:55
分享文档
收藏文档
上一篇
下一篇
微信扫一扫
复制链接
手机扫一扫进行分享
复制链接
关于 MrDoc
觅思文档MrDoc
是
州的先生
开发并开源的在线文档系统,其适合作为个人和小型团队的云笔记、文档和知识库管理工具。
如果觅思文档给你或你的团队带来了帮助,欢迎对作者进行一些打赏捐助,这将有力支持作者持续投入精力更新和维护觅思文档,感谢你的捐助!
>>>捐助鸣谢列表
微信
支付宝
QQ
PayPal
Markdown文件
分享
链接
类型
密码
更新密码