丰富前端操作,增加POJ的vjudge判题

This commit is contained in:
Himit_ZH 2021-06-25 11:14:24 +08:00
parent 270d10d96b
commit 8329f0d420
36 changed files with 686 additions and 86 deletions

View File

@ -85,6 +85,7 @@ docker ps # 查看当前运行的容器状态
| 2021-06-08 | 添加后台i18n,路由懒加载 | Himit_ZH |
| 2021-06-12 | 完善比赛赛制,具体请看在线文档 | Himit_ZH |
| 2021-06-14 | 完善后台管理员权限控制恢复CF的vjudge判题 | Himit_ZH |
| 2021-06-25 | 丰富前端操作增加POJ的vjudge判题 | Himit_ZH |

View File

@ -142,6 +142,7 @@ problem表
| open_case_result | boolean | | 是否默认开启该题目的测试样例结果查看 |
| caseVersion | String | | 题目测试数据的版本号 |
| is_upload_case | boolean | | 是否是上传zip评测数据的 |
| modified_user | String | | 最新修改题目的用户 |
| gmt_create | datetime | | 创建时间 |
| gmt_modified | datetime | | 修改时间 |
@ -529,6 +530,7 @@ discussion表
| view_num | int | | 浏览数量 |
| like_num | int | | 点赞数量 |
| top_priority | boolean | | 优先级,是否置顶 |
| comment_num | int | | 评论数量 |
| status | int | | 是否封禁或逻辑删除该讨论 |
| gmt_create | datetime | | 创建时间 |
| gmt_modified | datetime | | 修改时间 |

View File

@ -126,6 +126,12 @@
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>com.vdurmont</groupId>
<artifactId>emoji-java</artifactId>
<version>4.0.0</version>
</dependency>
<!--redis整合-->
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@ -105,6 +105,12 @@ public class StartupRunner implements CommandLineRunner {
@Value("${CF_ACCOUNT_PASSWORD_LIST:}")
private List<String> cfPasswordList;
@Value("${POJ_ACCOUNT_USERNAME_LIST:}")
private List<String> pojUsernameList;
@Value("${POJ_ACCOUNT_PASSWORD_LIST:}")
private List<String> pojPasswordList;
@Value("${spring.profiles.active}")
private String profile;
@ -151,6 +157,10 @@ public class StartupRunner implements CommandLineRunner {
configVo.setCfUsernameList(cfUsernameList);
configVo.setCfPasswordList(cfPasswordList);
configVo.setPojUsernameList(pojUsernameList);
configVo.setPojPasswordList(pojPasswordList);
configService.sendNewConfigToNacos();
if (openRemoteJudge.equals("true")) {
@ -203,6 +213,22 @@ public class StartupRunner implements CommandLineRunner {
log.error("Codeforces账号添加失败------------>{}", "请检查配置文件,然后重新启动!");
}
}
List<RemoteJudgeAccount> pojRemoteAccountList = new LinkedList<>();
for (int i = 0; i < pojUsernameList.size(); i++) {
pojRemoteAccountList.add(new RemoteJudgeAccount()
.setUsername(pojUsernameList.get(i))
.setPassword(pojPasswordList.get(i))
.setStatus(true)
.setVersion(0L)
.setOj("POJ"));
}
if (pojRemoteAccountList.size()>0) {
boolean addPOJOk = remoteJudgeAccountService.saveOrUpdateBatch(pojRemoteAccountList);
if (!addPOJOk) {
log.error("POJ账号添加失败------------>{}", "请检查配置文件,然后重新启动!");
}
}
}
}

View File

@ -326,7 +326,11 @@ public class AdminContestController {
if (problem != null && problem.getId().longValue() != problemDto.getProblem().getId()) {
return CommonResult.errorResponse("当前的Problem ID 已被使用,请重新更换新的!", CommonResult.STATUS_FAIL);
}
// 获取当前登录的用户
HttpSession session = request.getSession();
UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo");
// 记录修改题目的用户
problemDto.getProblem().setModifiedUser(userRolesVo.getUsername());
boolean result = problemService.adminUpdateProblem(problemDto);
if (result) { // 更新成功
return CommonResult.successResponse(null, "修改成功!");

View File

@ -144,7 +144,7 @@ public class AdminProblemController {
@RequiresAuthentication
@RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
@Transactional
public CommonResult updateProblem(@RequestBody ProblemDto problemDto) {
public CommonResult updateProblem(@RequestBody ProblemDto problemDto, HttpServletRequest request) {
QueryWrapper<Problem> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("problem_id", problemDto.getProblem().getProblemId().toUpperCase());
@ -154,6 +154,11 @@ public class AdminProblemController {
if (problem != null && problem.getId().longValue() != problemDto.getProblem().getId()) {
return CommonResult.errorResponse("当前的Problem ID 已被使用,请重新更换新的!", CommonResult.STATUS_FAIL);
}
// 获取当前登录的用户
HttpSession session = request.getSession();
UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo");
// 记录修改题目的用户
problemDto.getProblem().setModifiedUser(userRolesVo.getUsername());
boolean result = problemService.adminUpdateProblem(problemDto);
if (result) { // 更新成功

View File

@ -12,13 +12,16 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import top.hcode.hoj.common.result.CommonResult;
import top.hcode.hoj.pojo.dto.ReplyDto;
import top.hcode.hoj.pojo.entity.Comment;
import top.hcode.hoj.pojo.entity.CommentLike;
import top.hcode.hoj.pojo.entity.Discussion;
import top.hcode.hoj.pojo.entity.Reply;
import top.hcode.hoj.pojo.vo.CommentsVo;
import top.hcode.hoj.pojo.vo.UserRolesVo;
import top.hcode.hoj.service.impl.CommentLikeServiceImpl;
import top.hcode.hoj.service.impl.CommentServiceImpl;
import top.hcode.hoj.service.impl.DiscussionServiceImpl;
import top.hcode.hoj.service.impl.ReplyServiceImpl;
import javax.servlet.http.HttpServletRequest;
@ -45,6 +48,9 @@ public class CommentController {
@Autowired
private ReplyServiceImpl replyService;
@Autowired
private DiscussionServiceImpl discussionService;
@GetMapping("/comments")
public CommonResult getComments(@RequestParam(value = "cid", required = false) Long cid,
@ -126,6 +132,13 @@ public class CommentController {
commentsVo.setLikeNum(0);
commentsVo.setGmtCreate(comment.getGmtCreate());
commentsVo.setReplyList(new LinkedList<>());
// 如果是讨论区的回复发布成功需要添加统计该讨论的回复数
if (comment.getDid() != null) {
UpdateWrapper<Discussion> discussionUpdateWrapper = new UpdateWrapper<>();
discussionUpdateWrapper.eq("id", comment.getDid())
.setSql("comment_num=comment_num+1");
discussionService.update(discussionUpdateWrapper);
}
return CommonResult.successResponse(commentsVo, "评论成功");
} else {
return CommonResult.errorResponse("评论失败,请重新尝试!");
@ -151,6 +164,13 @@ public class CommentController {
replyService.remove(new UpdateWrapper<Reply>().eq("comment_id", comment.getId()));
if (isDeleteComment) {
// 如果是讨论区的回复删除成功需要减少统计该讨论的回复数
if (comment.getDid() != null) {
UpdateWrapper<Discussion> discussionUpdateWrapper = new UpdateWrapper<>();
discussionUpdateWrapper.eq("id", comment.getDid())
.setSql("comment_num=comment_num-1");
discussionService.update(discussionUpdateWrapper);
}
return CommonResult.successResponse(null, "删除成功");
} else {
return CommonResult.errorResponse("删除失败,请重新尝试");
@ -222,11 +242,11 @@ public class CommentController {
@PostMapping("/reply")
@RequiresPermissions("reply_add")
@RequiresAuthentication
public CommonResult addReply(@RequestBody Reply reply, HttpServletRequest request) {
public CommonResult addReply(@RequestBody ReplyDto replyDto, HttpServletRequest request) {
// 获取当前登录的用户
HttpSession session = request.getSession();
UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo");
Reply reply = replyDto.getReply();
reply.setFromAvatar(userRolesVo.getAvatar())
.setFromName(userRolesVo.getUsername())
.setFromUid(userRolesVo.getUid());
@ -244,6 +264,13 @@ public class CommentController {
boolean isOk = replyService.saveOrUpdate(reply);
if (isOk) {
// 如果是讨论区的回复发布成功需要增加统计该讨论的回复数
if (replyDto.getDid() != null) {
UpdateWrapper<Discussion> discussionUpdateWrapper = new UpdateWrapper<>();
discussionUpdateWrapper.eq("id", replyDto.getDid())
.setSql("comment_num=comment_num+1");
discussionService.update(discussionUpdateWrapper);
}
return CommonResult.successResponse(reply, "评论成功");
} else {
return CommonResult.errorResponse("评论失败,请重新尝试!");
@ -252,19 +279,24 @@ public class CommentController {
@DeleteMapping("/reply")
@RequiresAuthentication
public CommonResult deleteReply(@RequestBody Reply reply, HttpServletRequest request) {
public CommonResult deleteReply(@RequestBody ReplyDto replyDto, HttpServletRequest request) {
// 获取当前登录的用户
HttpSession session = request.getSession();
UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo");
Reply reply = replyDto.getReply();
// 如果不是评论本人 或者不是管理员 无权限删除该评论
if (reply.getFromUid().equals(userRolesVo.getUid()) || SecurityUtils.getSubject().hasRole("root")
|| SecurityUtils.getSubject().hasRole("admin") || SecurityUtils.getSubject().hasRole("problem_admin")) {
// 删除该数据
boolean isOk = replyService.removeById(reply.getId());
if (isOk) {
// 如果是讨论区的回复删除成功需要减少统计该讨论的回复数
if (replyDto.getDid() != null) {
UpdateWrapper<Discussion> discussionUpdateWrapper = new UpdateWrapper<>();
discussionUpdateWrapper.eq("id", replyDto.getDid())
.setSql("comment_num=comment_num-1");
discussionService.update(discussionUpdateWrapper);
}
return CommonResult.successResponse(null, "删除成功");
} else {
return CommonResult.errorResponse("删除失败,请重新尝试");

View File

@ -0,0 +1,58 @@
package top.hcode.hoj.crawler.problem;
import cn.hutool.core.util.ReUtil;
import org.jsoup.Connection;
import org.jsoup.nodes.Document;
import org.springframework.util.Assert;
import top.hcode.hoj.pojo.entity.Problem;
import top.hcode.hoj.utils.JsoupUtils;
/**
* @Author: Himit_ZH
* @Date: 2021/6/24 23:27
* @Description:
*/
public class POJProblemStrategy extends ProblemStrategy {
public static final String JUDGE_NAME = "POJ";
public static final String HOST = "http://poj.org";
public static final String PROBLEM_URL = "/problem?id=%s";
@Override
public RemoteProblemInfo getProblemInfo(String problemId, String author) throws Exception {
// 验证题号是否符合规范
Assert.isTrue(problemId.matches("[1-9]\\d*"), "POJ题号格式错误");
Problem info = new Problem();
String url = HOST + String.format(PROBLEM_URL, problemId);
Connection connection = JsoupUtils.getConnectionFromUrl(url, null, null);
Document document = JsoupUtils.getDocument(connection, null);
String html = document.html();
html = html.replaceAll("<br>", "\n");
info.setProblemId(JUDGE_NAME + "-" + problemId);
info.setTitle(ReUtil.get("<title>\\d{3,} -- ([\\s\\S]*?)</title>", html, 1).trim());
info.setTimeLimit(Integer.parseInt(ReUtil.get("<b>Time Limit:</b> (\\d{3,})MS</td>", html, 1)));
info.setMemoryLimit(Integer.parseInt(ReUtil.get("<b>Memory Limit:</b> (\\d{2,})K</td>", html, 1)) / 1024);
info.setDescription(ReUtil.get("<p class=\"pst\">Description</p><div class=.*?>([\\s\\S]*?)</div><p class=\"pst\">", html, 1)
.replaceAll("src=\"../../", "src=\"" + HOST + "/"));
info.setInput(ReUtil.get("<p class=\"pst\">Input</p><div class=.*?>([\\s\\S]*?)</div><p class=\"pst\">", html, 1));
info.setOutput(ReUtil.get("<p class=\"pst\">Output</p><div class=.*?>([\\s\\S]*?)</div><p class=\"pst\">", html, 1));
StringBuilder sb = new StringBuilder("<input>");
sb.append(ReUtil.get("<p class=\"pst\">Sample Input</p><pre class=.*?>([\\s\\S]*?)</pre><p class=\"pst\">", html, 1));
sb.append("</input><output>");
sb.append(ReUtil.get("<p class=\"pst\">Sample Output</p><pre class=.*?>([\\s\\S]*?)</pre><p class=\"pst\">", html, 1))
.append("</output>");
info.setExamples(sb.toString());
info.setHint(ReUtil.get("<p class=.*?>Hint</p><div class=.*?>([\\s\\S]*?)</div><p class=\"pst\">", html, 1));
info.setIsRemote(true);
info.setSource(String.format("<a style='color:#1A5CC8' href='http://poj.org/problem?id=%s'>%s</a>", problemId, JUDGE_NAME + "-" + problemId));
info.setType(0)
.setAuth(1)
.setAuthor(author)
.setOpenCaseResult(false)
.setIsRemoveEndBlank(false)
.setDifficulty(1); // 默认为简单
return new RemoteProblemInfo().setProblem(info).setTagList(null);
}
}

View File

@ -0,0 +1,19 @@
package top.hcode.hoj.pojo.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import top.hcode.hoj.pojo.entity.Reply;
/**
* @Author: Himit_ZH
* @Date: 2021/6/24 17:00
* @Description:
*/
@Data
@Accessors(chain = true)
public class ReplyDto {
private Reply reply;
private Long did;
}

View File

@ -119,4 +119,10 @@ public class ConfigVo {
@Value("${hoj.cf.account.password:}")
private List<String> cfPasswordList;
@Value("${hoj.poj.account.username:}")
private List<String> pojUsernameList;
@Value("${hoj.poj.account.password:}")
private List<String> pojPasswordList;
}

View File

@ -19,10 +19,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.yaml.snakeyaml.Yaml;
import top.hcode.hoj.crawler.problem.CFProblemStrategy;
import top.hcode.hoj.crawler.problem.HDUProblemStrategy;
import top.hcode.hoj.crawler.problem.ProblemContext;
import top.hcode.hoj.crawler.problem.ProblemStrategy;
import top.hcode.hoj.crawler.problem.*;
import top.hcode.hoj.pojo.dto.ProblemDto;
import top.hcode.hoj.pojo.entity.*;
import top.hcode.hoj.pojo.vo.ImportProblemVo;
@ -544,6 +541,9 @@ public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> impl
case "CF":
problemStrategy = new CFProblemStrategy();
break;
case "POJ":
problemStrategy = new POJProblemStrategy();
break;
default:
throw new Exception("未知的OJ的名字暂时不支持");
}

View File

@ -72,7 +72,11 @@ public class ConfigUtils {
" cf:\n" +
" account:\n" +
" username: " + listToStr(configVo.getCfUsernameList()) + "\n" +
" password: " + listToStr(configVo.getCfPasswordList());
" password: " + listToStr(configVo.getCfPasswordList()) + "\n" +
" poj:\n" +
" account:\n" +
" username: " + listToStr(configVo.getPojUsernameList()) + "\n" +
" password: " + listToStr(configVo.getPojPasswordList());
}
private String listToStr(List<String> list) {

View File

@ -58,7 +58,8 @@ public class Constants {
public enum RemoteOJ {
HDU("HDU"),
CODEFORCES("CF");
CODEFORCES("CF"),
POJ("POJ");
private final String name;

View File

@ -32,8 +32,7 @@ public class RemoteJudgeGetResult {
@Transactional
public void sendTask(String remoteJudge, String username, Long submitId, String uid,
Long cid, Long pid, Long resultSubmitId, String token,
HashMap<String, String> cookies) {
Long cid, Long pid, Long resultSubmitId, String cookies) {
RemoteJudgeStrategy remoteJudgeStrategy = RemoteJudgeFactory.selectJudge(remoteJudge);
@ -47,7 +46,7 @@ public class RemoteJudgeGetResult {
public void run() {
count.getAndIncrement();
try {
Map<String, Object> result = remoteJudgeStrategy.result(resultSubmitId, username, token, cookies);
Map<String, Object> result = remoteJudgeStrategy.result(resultSubmitId, username, cookies);
Integer status = (Integer) result.getOrDefault("status", Constants.Judge.STATUS_SYSTEM_ERROR.getStatus());
if (status.intValue() != Constants.Judge.STATUS_PENDING.getStatus() &&
status.intValue() != Constants.Judge.STATUS_JUDGING.getStatus()) {

View File

@ -87,17 +87,16 @@ public class RemoteJudgeToSubmit {
return;
}
// 提交成功顺便更新状态为-->STATUS_JUDGING 判题...
// 提交成功顺便更新状态为-->STATUS_PENDING 等待...
judgeService.updateById(new Judge()
.setSubmitId(submitId)
.setStatus(Constants.Judge.STATUS_JUDGING.getStatus())
.setStatus(Constants.Judge.STATUS_PENDING.getStatus())
.setJudger(name)
);
// 调用获取远程判题结果
remoteJudgeGetResult.sendTask(remoteJudge, username, submitId, uid, cid, pid,
(Long) submitResult.get("runId"), (String) submitResult.get("token"),
(HashMap<String, String>) submitResult.get("cookies"));
(Long) submitResult.get("runId"), (String) submitResult.get("cookies"));
}
}

View File

@ -14,7 +14,6 @@ import com.gargoylesoftware.htmlunit.SilentCssErrorHandler;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.*;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Connection;
import top.hcode.hoj.remoteJudge.task.RemoteJudgeStrategy;
import top.hcode.hoj.util.Constants;
@ -73,16 +72,15 @@ public class CodeForcesJudge implements RemoteJudgeStrategy {
// 获取提交的题目id
Long maxRunId = getMaxRunId(null, username, problemId);
Long maxRunId = getMaxRunId(username, problemId);
return MapUtil.builder(new HashMap<String, Object>())
.put("runId", maxRunId)
.put("token", "")
.put("cookies", new HashMap<String, String>())
.put("cookies", null)
.map();
}
private Long getMaxRunId(Connection connection, String username, String problemId) throws InterruptedException {
private Long getMaxRunId(String username, String problemId) throws InterruptedException {
int retryNum = 0;
String url = String.format(SUBMISSION_RESULT_URL, username);
HttpRequest httpRequest = HttpUtil.createGet(HOST + url);
@ -118,7 +116,7 @@ public class CodeForcesJudge implements RemoteJudgeStrategy {
}
@Override
public Map<String, Object> result(Long submitId, String username, String token, HashMap<String, String> cookies) throws Exception {
public Map<String, Object> result(Long submitId, String username, String cookies) {
String url = HOST + String.format(SUBMISSION_RESULT_URL, username);

View File

@ -2,15 +2,13 @@ package top.hcode.hoj.remoteJudge.task.Impl;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.http.HtmlUtil;
import cn.hutool.http.*;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Connection;
import org.jsoup.helper.Validate;
import org.jsoup.nodes.Document;
import top.hcode.hoj.pojo.entity.Problem;
import top.hcode.hoj.remoteJudge.task.RemoteJudgeStrategy;
import top.hcode.hoj.util.Constants;
import top.hcode.hoj.util.JsoupUtils;
import java.util.HashMap;
import java.util.Map;
@ -31,6 +29,7 @@ public class HduJudge implements RemoteJudgeStrategy {
.put("Host", "acm.hdu.edu.cn")
.put("origin", "http://acm.hdu.edu.cn")
.put("referer", "http://acm.hdu.edu.cn")
.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36")
.map();
/**
@ -45,39 +44,46 @@ public class HduJudge implements RemoteJudgeStrategy {
return null;
}
Map<String, Object> loginUtils = getLoginUtils(username, password);
Map<String, String> loginCookie = (Map<String, String>) loginUtils.get("cookie");
Connection connection = JsoupUtils.getConnectionFromUrl(HOST + SUBMIT_URL, headers, loginCookie);
Connection.Response response = JsoupUtils.postResponse(connection, MapUtil
.builder(new HashMap<String, String>())
String cookies = (String) loginUtils.get("cookie");
HttpRequest request = HttpUtil.createPost(HOST + SUBMIT_URL)
.addHeaders(headers)
.cookie(cookies);
HttpResponse response = request.form(MapUtil
.builder(new HashMap<String, Object>())
.put("check", "0")
.put("language", getLanguage(language))
.put("problemid", problemId)
.put("usercode", userCode)
.map());
if (response.statusCode() != 200) {
.map())
.execute();
if (response.getStatus() != 200) {
log.error("进行题目提交时发生错误:提交题目失败," + HduJudge.class.getName() + ",题号:" + problemId);
return null;
}
// 下面的请求都是GET
request.setMethod(Method.GET);
// 获取提交的题目id
Long maxRunId = getMaxRunId(connection, username, problemId);
Long maxRunId = getMaxRunId(request, username, problemId);
if (maxRunId == -1L) { // 等待2s再次查询如果还是失败则表明提交失败了
TimeUnit.SECONDS.sleep(2);
maxRunId = getMaxRunId(connection, username, problemId);
maxRunId = getMaxRunId(request, username, problemId);
}
return MapUtil.builder(new HashMap<String, Object>())
.put("token", null)
.put("cookies", loginCookie)
.put("cookies", cookies)
.put("runId", maxRunId)
.map();
}
@Override
public Map<String, Object> result(Long submitId, String username, String token, HashMap<String, String> cookies) throws Exception {
public Map<String, Object> result(Long submitId, String username, String cookies) throws Exception {
String url = HOST + String.format(QUERY_URL, submitId);
Connection connection = JsoupUtils.getConnectionFromUrl(url, headers, null);
Connection.Response response = JsoupUtils.getResponse(connection, null);
HttpRequest request = HttpUtil.createGet(url)
.cookie(cookies)
.addHeaders(headers);
HttpResponse response = request.execute();
// 1提交时间 2结果 3执行时间 4执行空间 5代码长度
// 一般情况下 代码长度和提交时间不需要想要也行自行添加
Pattern pattern = Pattern.compile(">" + submitId + "</td><td>([\\s\\S]*?)</td><td>([\\s\\S]*?)</td><td>[\\s\\S]*?</td><td>(\\d*?)MS</td><td>(\\d*?)K</td><td>(\\d*?)B</td>");
@ -100,9 +106,9 @@ public class HduJudge implements RemoteJudgeStrategy {
result.put("memory", Integer.parseInt(executionMemory));
// 如果CE了则还需要获得错误信息
if (statusType == Constants.Judge.STATUS_COMPILE_ERROR) {
connection.url(HOST + String.format(ERROR_URL, submitId));
response = JsoupUtils.getResponse(connection, null);
String compilationErrorInfo = ReUtil.get("<pre>([\\s\\S]*?)</pre>", response.body(), 1);
request.setUrl(HOST + String.format(ERROR_URL, submitId));
String CEHtml = request.execute().body();
String compilationErrorInfo = ReUtil.get("<pre>([\\s\\S]*?)</pre>", CEHtml, 1);
result.put("CEInfo", HtmlUtil.unescape(compilationErrorInfo));
}
return result;
@ -110,14 +116,16 @@ public class HduJudge implements RemoteJudgeStrategy {
@Override
public Map<String, Object> getLoginUtils(String username, String password) throws Exception {
Connection connection = JsoupUtils.getConnectionFromUrl(HOST + LOGIN_URL, headers, null);
Connection.Response response = JsoupUtils.postResponse(connection, MapUtil
.builder(new HashMap<String, String>())
public Map<String, Object> getLoginUtils(String username, String password){
HttpRequest request = HttpUtil.createPost(HOST + LOGIN_URL).addHeaders(headers);
HttpResponse response = request.form(MapUtil
.builder(new HashMap<String, Object>())
.put("username", username)
.put("login", "Sign In")
.put("userpass", password).map());
return MapUtil.builder(new HashMap<String, Object>()).put("cookie", response.cookies()).map();
.put("userpass", password).map())
.execute();
return MapUtil.builder(new HashMap<String, Object>()).put("cookie", response.getCookieStr()).map();
}
@Override
@ -144,10 +152,9 @@ public class HduJudge implements RemoteJudgeStrategy {
}
public Long getMaxRunId(Connection connection, String userName, String problemId) throws Exception {
public Long getMaxRunId(HttpRequest request, String userName, String problemId){
String url = String.format(STATUS_URL, userName, problemId);
connection.url(HOST + url);
Connection.Response response = JsoupUtils.getResponse(connection, null);
HttpResponse response = request.setUrl(url).execute();
Matcher matcher = Pattern.compile("<td height=22px>(\\d+)").matcher(response.body());
return matcher.find() ? Long.parseLong(matcher.group(1)) : -1L;
}

View File

@ -0,0 +1,178 @@
package top.hcode.hoj.remoteJudge.task.Impl;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.http.*;
import lombok.extern.slf4j.Slf4j;
import top.hcode.hoj.remoteJudge.task.RemoteJudgeStrategy;
import top.hcode.hoj.util.Constants;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @Author: Himit_ZH
* @Date: 2021/6/24 21:19
* @Description:
*/
@Slf4j(topic = "hoj")
public class POJJudge implements RemoteJudgeStrategy {
public static final String HOST = "http://poj.org";
public static final String LOGIN_URL = "/login";
public static final String SUBMIT_URL = "/submit";
public static final String STATUS_URL = "/status?user_id=%s&problem_id=%s";
public static final String QUERY_URL = "/showsource?solution_id=%s";
public static final String ERROR_URL = "/showcompileinfo?solution_id=%s";
public static Map<String, String> headers = MapUtil
.builder(new HashMap<String, String>())
.put("Host", "poj.org")
.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36")
.map();
/**
* @param problemId 提交的题目id
* @param language
* @param userCode 用户代码
* @return
*/
@Override
public Map<String, Object> submit(String username, String password, String problemId, String language, String userCode) throws Exception {
if (problemId == null || userCode == null) {
return null;
}
Map<String, Object> loginUtils = getLoginUtils(username, password);
String cookies = (String) loginUtils.get("cookie");
HttpRequest request = HttpUtil.createPost(HOST + SUBMIT_URL)
.addHeaders(headers)
.cookie(cookies);
HttpResponse response = request.form(MapUtil.builder(new HashMap<String, Object>())
.put("language", getLanguage(language))
.put("submit", "Submit")
.put("problem_id", problemId)
.put("source", Base64.encode(userCode))
.put("encoded", 1).map())
.execute();
if (response.getStatus() != 302) {
log.error("进行题目提交时发生错误:提交题目失败," + POJJudge.class.getName() + ",题号:" + problemId);
return null;
}
// 下面的请求都是GET
request.setMethod(Method.GET);
// 获取提交的题目id
Long maxRunId = getMaxRunId(request, username, problemId);
if (maxRunId == -1L) { // 等待2s再次查询如果还是失败则表明提交失败了
TimeUnit.SECONDS.sleep(2);
maxRunId = getMaxRunId(request, username, problemId);
}
return MapUtil.builder(new HashMap<String, Object>())
.put("cookies", cookies)
.put("runId", maxRunId)
.map();
}
@Override
public Map<String, Object> result(Long submitId, String username, String cookies) {
String url = HOST + String.format(QUERY_URL, submitId);
HttpRequest request = HttpUtil.createGet(url)
.cookie(cookies)
.addHeaders(headers);
HttpResponse response = request.execute();
String statusStr = ReUtil.get("<b>Result:</b>(.+?)</td>", response.body(), 1)
.replaceAll("<.*?>", "")
.trim();
Constants.Judge statusType = statusTypeMap.getOrDefault(statusStr, null);
if (statusType == null) {
return MapUtil.builder(new HashMap<String, Object>())
.put("status", Constants.Judge.STATUS_PENDING).build();
}
// 返回的结果map
Map<String, Object> result = MapUtil.builder(new HashMap<String, Object>())
.put("status", statusType.getStatus()).build();
// 如果CE了需要获得错误信息
if (statusType == Constants.Judge.STATUS_COMPILE_ERROR) {
request.setUrl(HOST + String.format(ERROR_URL, submitId));
String CEHtml = request.execute().body();
String compilationErrorInfo = ReUtil.get("<pre>([\\s\\S]*?)</pre>", CEHtml, 1);
result.put("CEInfo", HtmlUtil.unescape(compilationErrorInfo));
} else {
// 如果不是CE,获取其他信息
String executionTime = ReUtil.get("<b>Memory:</b> ([-\\d]+)", response.body(), 1);
result.put("time", Integer.parseInt(executionTime));
String executionMemory = ReUtil.get("<b>Time:</b> ([-\\d]+)", response.body(), 1);
result.put("memory", Integer.parseInt(executionMemory));
}
return result;
}
@Override
public Map<String, Object> getLoginUtils(String username, String password) {
HttpRequest request = HttpUtil.createPost(HOST + LOGIN_URL);
HttpResponse response = request.form(MapUtil.builder(new HashMap<String, Object>())
.put("user_id1", username)
.put("B1", "login")
.put("url", ".")
.put("password1", password).map()).execute();
return MapUtil.builder(new HashMap<String, Object>()).put("cookie", response.getCookieStr()).map();
}
@Override
public String getLanguage(String language) {
switch (language) {
case "G++":
return "0";
case "GCC":
return "1";
case "Java":
return "2";
case "Pascal":
return "3";
case "C++":
return "4";
case "C":
return "5";
case "Fortran":
return "6";
default:
// TODO 抛出没有这个语言的异常
return null;
}
}
public Long getMaxRunId(HttpRequest request, String userName, String problemId) {
String url = String.format(STATUS_URL, userName, problemId);
request.setUrl(HOST + url);
String html = request.execute().body();
Matcher matcher = Pattern.compile("<tr align=center><td>(\\d+)").matcher(html);
return matcher.find() ? Long.parseLong(matcher.group(1)) : -1L;
}
// TODO 添加结果对应的状态
private static final Map<String, Constants.Judge> statusTypeMap = new HashMap<String, Constants.Judge>() {
{
put("Compiling", Constants.Judge.STATUS_COMPILING);
put("Accepted", Constants.Judge.STATUS_ACCEPTED);
put("Presentation Error", Constants.Judge.STATUS_PRESENTATION_ERROR);
put("Time Limit Exceeded", Constants.Judge.STATUS_TIME_LIMIT_EXCEEDED);
put("Memory Limit Exceeded", Constants.Judge.STATUS_MEMORY_LIMIT_EXCEEDED);
put("Wrong Answer", Constants.Judge.STATUS_WRONG_ANSWER);
put("Runtime Error", Constants.Judge.STATUS_RUNTIME_ERROR);
put("Output Limit Exceeded", Constants.Judge.STATUS_RUNTIME_ERROR);
put("Compile Error", Constants.Judge.STATUS_COMPILE_ERROR);
}
};
}

View File

@ -2,6 +2,7 @@ package top.hcode.hoj.remoteJudge.task;
import top.hcode.hoj.remoteJudge.task.Impl.CodeForcesJudge;
import top.hcode.hoj.remoteJudge.task.Impl.HduJudge;
import top.hcode.hoj.remoteJudge.task.Impl.POJJudge;
import top.hcode.hoj.util.Constants;
@ -14,6 +15,8 @@ public class RemoteJudgeFactory {
return new HduJudge();
case CF_JUDGE:
return new CodeForcesJudge();
case POJ_JUDGE:
return new POJJudge();
default:
return null;
}

View File

@ -22,7 +22,7 @@ public interface RemoteJudgeStrategy {
* @param username 题库的提交者的账号
* @return 返回结果
*/
Map<String, Object> result(Long submitId, String username, String token, HashMap<String,String> cookies) throws Exception;
Map<String, Object> result(Long submitId, String username, String cookies) throws Exception;
Map<String, Object> getLoginUtils(String username, String password) throws Exception;

View File

@ -67,6 +67,8 @@ public class Constants {
CF_JUDGE("CF"),
POJ_JUDGE("POJ"),
HDU_REMOTE_JUDGE_ACCOUNT("Hdu Remote Judge Account"),
CF_REMOTE_JUDGE_ACCOUNT("Codeforces Remote Judge Account");

View File

@ -88,4 +88,6 @@ public class JudgeServerApplicationTests {
"}");
System.out.println(result);
}
}

View File

@ -56,7 +56,10 @@ public class Discussion {
private Integer viewNum;
@ApiModelProperty(value = "点赞数量")
private String likeNum;
private Integer likeNum;
@ApiModelProperty(value = "评论数量,包括其评论及其回复数")
private Integer commentNum;
@ApiModelProperty(value = "优先级,是否置顶")
private Boolean topPriority;

View File

@ -45,7 +45,7 @@ public class Problem implements Serializable {
@ApiModelProperty(value = "单位ms")
private Integer timeLimit;
@ApiModelProperty(value = "单位kb")
@ApiModelProperty(value = "单位mb")
private Integer memoryLimit;
@ApiModelProperty(value = "单位mb")
@ -104,6 +104,9 @@ public class Problem implements Serializable {
@ApiModelProperty(value = "题目测试数据的版本号")
private String caseVersion;
@ApiModelProperty(value = "修改题目的管理员用户名")
private String modifiedUser;
@TableField(fill = FieldFill.INSERT)
private Date gmtCreate;

View File

@ -151,7 +151,8 @@ export const PROBLEM_LEVEL_RESERVE={
export const REMOTE_OJ = [
{name:'HDU',key:"HDU"},
{name:"Codeforces",key:"CF"}
{name:"Codeforces",key:"CF"},
{name:"POJ",key:"POJ"},
]
export const CONTEST_STATUS = {

View File

@ -622,7 +622,10 @@ export default {
return;
}
this.replyObj.content = this.replyInputComment;
let replyData = Object.assign({}, this.replyObj);
let replyData = {
reply: this.replyObj,
did: this.did,
};
api.addReply(replyData).then((res) => {
for (let i = 0; i < this.comments.length; i++) {
if (this.comments[i].id == this.replyObj.commentId) {
@ -715,6 +718,7 @@ export default {
.then(() => {
let replyDeleteData = {
id: reply.id,
did: this.did,
fromUid: reply.fromUid,
};
api.deleteReply(replyDeleteData).then((res) => {

View File

@ -1,14 +1,14 @@
<template>
<div style="margin: 0px 0px 15px 0px;font-size: 14px;">
<el-row class="header">
<el-col :xs="24" :sm="14" :md="14" :lg="14">
<el-col :xs="24" :sm="15" :md="15" :lg="15">
<div class="select-row">
<span>{{ $t('m.Lang') }}:</span>
<span>
<el-select
:value="this.language"
@change="onLangChange"
class="adjust"
class="left-adjust"
size="small"
>
<el-option v-for="item in languages" :key="item" :value="item"
@ -44,13 +44,13 @@
</span>
</div>
</el-col>
<el-col :xs="24" :sm="10" :md="10" :lg="10">
<el-col :xs="24" :sm="9" :md="9" :lg="9">
<div class="select-row fl-right">
<span>{{ $t('m.Theme') }}:</span>
<el-select
:value="this.theme"
@change="onThemeChange"
class="adjust"
class="right-adjust"
size="small"
>
<el-option
@ -104,6 +104,7 @@ import 'codemirror/mode/php/php.js'; //php
import 'codemirror/mode/ruby/ruby.js'; //ruby
import 'codemirror/mode/rust/rust.js'; //rust
import 'codemirror/mode/javascript/javascript.js'; //javascript
import 'codemirror/mode/fortran/fortran.js'; //fortran
// active-line.js
import 'codemirror/addon/selection/active-line.js';
@ -260,10 +261,15 @@ export default {
margin-right: 5px;
margin-left: 5px;
}
.header .adjust {
.header .left-adjust {
width: 170px;
margin-left: 5px;
}
.header .right-adjust {
width: 140px;
margin-left: 5px;
}
.select-row {
margin-top: 4px;
}

View File

@ -126,6 +126,7 @@ export const m = {
Add_Rmote_OJ_Problem:'Add Remote OJ Problem',
Add_From_Public_Problem:'Add From Public Problem',
Auth:'Auth',
Modified_User:'Modified User',
Public_Problem:'Public Problem',
Private_Problem:'Private Problem',
Contest_Problem:'Contest Problem',

View File

@ -126,6 +126,7 @@ export const m = {
Add_Rmote_OJ_Problem:'添加远程OJ题目',
Add_From_Public_Problem:'从公共题库添加题目',
Auth:'权限',
Modified_User:'最近修改者',
Public_Problem:'公开题目',
Private_Problem:'隐藏题目',
Contest_Problem:'比赛题目',

View File

@ -164,6 +164,10 @@ export const m = {
Good_luck_to_you:'Good luck to you!',
// /views/oj/problem/Problem.vue
Shrink_Sidebar:'Shrink Sidebar',
View_Problem_Content:'View Problem Content',
Only_View_Problem:'Only View Problem',
Put_away_the_full_screen_and_write_the_code:'Put away the full screen and write the code',
Contest_Problem:'Contest Problem',
Show_Tags:'Show tags',
No_tag:'No tag',

View File

@ -165,6 +165,10 @@ export const m = {
Good_luck_to_you:'祝你好运!',
// /views/oj/problem/Problem.vue
Shrink_Sidebar:'收缩侧边栏',
View_Problem_Content:'查看题目内容',
Only_View_Problem:'只看题目内容',
Put_away_the_full_screen_and_write_the_code:'收起全屏,编写代码',
Contest_Problem:'比赛题目',
Show_Tags:'显示标签',
No_tag:'暂无标签',
@ -243,7 +247,7 @@ export const m = {
OI_Ranklist: 'OI 排行榜',
// /views/oj/discussion/discussionList.vue
Created_Time:'创建时间',
Created_Time:'发布时间',
Likes:'点赞',
Views:'浏览',
Edit:'编辑',

View File

@ -60,7 +60,7 @@
</vxe-table-column>
<vxe-table-column
field="author"
min-width="150"
min-width="130"
:title="$t('m.Author')"
>
</vxe-table-column>
@ -73,6 +73,12 @@
{{ row.gmtCreate | localtime }}
</template>
</vxe-table-column>
<vxe-table-column
field="modifiedUser"
min-width="130"
:title="$t('m.Modified_User')"
>
</vxe-table-column>
<vxe-table-column min-width="130" field="auth" :title="$t('m.Auth')">
<template v-slot="{ row }">
<el-select

View File

@ -66,6 +66,7 @@
{{ discussion.title }}
</h1>
</a>
<a
@click="toDiscussionDetail(discussion.id)"
class="article-hlink2"
@ -101,30 +102,30 @@
>ADM</span
>
</span>
<span class="pr pl hidden-xs-only"
><label class="fw"><i class="fa fa-clock-o"></i></label
<span class="pr pl"
><label class="fw"><i class="el-icon-chat-round"></i></label
><span>
{{ $t('m.Created_Time') }}<el-tooltip
:content="discussion.gmtCreate | localtime"
placement="top"
>
<span>{{ discussion.gmtCreate | fromNow }}</span>
</el-tooltip></span
<span class="hidden-xs-only"> {{ $t('m.Comment') }}:</span>
{{ discussion.commentNum }}</span
></span
>
<span class="pr"
><label class="fw"><i class="fa fa-thumbs-o-up"></i></label
><span>
{{ $t('m.Likes') }}{{ discussion.likeNum }}</span
<span class="hidden-xs-only"> {{ $t('m.Likes') }}:</span>
{{ discussion.likeNum }}</span
></span
>
<span class="pr"
><label class="fw"><i class="fa fa-eye"></i></label
><span>
{{ $t('m.Views') }}{{ discussion.viewNum }}</span
<span class="hidden-xs-only"> {{ $t('m.Views') }}:</span>
{{ discussion.viewNum }}</span
></span
>
<span
<span class="pr"
><label class="fw"><i class="el-icon-folder-opened"></i></label>
<a
@click="
@ -139,6 +140,18 @@
>
</span>
<span class="pr pl hidden-xs-only">
<label class="fw"><i class="fa fa-clock-o"></i></label
><span>
{{ $t('m.Created_Time') }}<el-tooltip
:content="discussion.gmtCreate | localtime"
placement="top"
>
<span>{{ discussion.gmtCreate | fromNow }}</span>
</el-tooltip></span
>
</span>
<el-dropdown
style="float:right;"
class="hidden-xs-only"

View File

@ -2,8 +2,8 @@
<div>
<div id="problem-main">
<!--problem main-->
<el-row>
<el-col :sm="24" :md="24" :lg="12">
<el-row class="problem-box">
<el-col :sm="24" :md="24" :lg="12" class="problem-left">
<el-card :padding="10" shadow class="problem-detail">
<div slot="header" class="panel-title">
<span>{{ problemData.problem.title }}</span
@ -172,7 +172,42 @@
</div>
</el-card>
</el-col>
<el-col :sm="24" :md="24" :lg="12">
<div
class="problem-resize hidden-md-and-down"
:title="$t('m.Shrink_Sidebar')"
>
<span></span>
<el-tooltip
:content="
toWatchProblem
? $t('m.View_Problem_Content')
: $t('m.Only_View_Problem')
"
placement="right"
>
<el-button
icon="el-icon-caret-right"
circle
class="right-fold fold"
@click.native="onlyWatchProblem"
size="mini"
></el-button>
</el-tooltip>
<el-tooltip
:content="$t('m.Put_away_the_full_screen_and_write_the_code')"
placement="left"
>
<el-button
icon="el-icon-caret-left"
circle
class="left-fold fold"
@click.native="resetWatch(false)"
size="mini"
v-show="toResetWatch"
></el-button>
</el-tooltip>
</div>
<el-col :sm="24" :md="24" :lg="12" class="problem-right">
<el-card
:padding="10"
id="submit-code"
@ -432,6 +467,8 @@ export default {
JUDGE_STATUS_RESERVE: {},
PROBLEM_LEVEL: {},
RULE_TYPE: {},
toResetWatch: false,
toWatchProblem: false,
};
},
//
@ -449,6 +486,7 @@ export default {
next();
}
},
created() {
this.JUDGE_STATUS_RESERVE = Object.assign({}, JUDGE_STATUS_RESERVE);
this.PROBLEM_LEVEL = Object.assign({}, PROBLEM_LEVEL);
@ -456,9 +494,95 @@ export default {
},
mounted() {
this.init();
this.dragControllerDiv();
},
methods: {
...mapActions(['changeDomTitle']),
dragControllerDiv() {
var resize = document.getElementsByClassName('problem-resize');
var left = document.getElementsByClassName('problem-left');
var right = document.getElementsByClassName('problem-right');
var box = document.getElementsByClassName('problem-box');
const _this = this;
for (let i = 0; i < resize.length; i++) {
//
resize[i].onmousedown = function(e) {
//
resize[i].style.background = '#818181';
var startX = e.clientX;
//
document.onmousemove = function(e) {
resize[i].left = startX;
var endX = e.clientX;
var moveLen = resize[i].left + (endX - startX); // endx-startx=resize[i].left+=
var maxT = box[i].clientWidth - resize[i].offsetWidth; // - =
if (moveLen < 420) moveLen = 0; // 420px
if (moveLen > maxT - 580) moveLen = maxT - 580; //580px
resize[i].style.left = moveLen; //
for (let j = 0; j < left.length; j++) {
left[j].style.width = moveLen + 'px';
let tmp = box[i].clientWidth - moveLen - 11;
right[j].style.width = tmp + 'px';
if (tmp > 0) {
_this.toResetWatch = false;
}
if (moveLen == 0) {
_this.toWatchProblem = true;
}
}
};
//
document.onmouseup = function(evt) {
//
resize[i].style.background = '#d6d6d6';
document.onmousemove = null;
document.onmouseup = null;
resize[i].releaseCapture && resize[i].releaseCapture(); //ReleaseCapture()
};
resize[i].setCapture && resize[i].setCapture(); //线
return false;
};
}
},
onlyWatchProblem() {
if (this.toWatchProblem) {
this.resetWatch(true);
this.toWatchProblem = false;
return;
}
var resize = document.getElementsByClassName('problem-resize');
var left = document.getElementsByClassName('problem-left');
var right = document.getElementsByClassName('problem-right');
var box = document.getElementsByClassName('problem-box');
for (let i = 0; i < resize.length; i++) {
resize[i].style.left = box[i].clientWidth - 11;
for (let j = 0; j < left.length; j++) {
left[j].style.width = box[i].clientWidth - 11 + 'px';
right[j].style.width = '0px';
}
}
this.toResetWatch = true;
},
resetWatch(minLeft = false) {
var resize = document.getElementsByClassName('problem-resize');
var left = document.getElementsByClassName('problem-left');
var right = document.getElementsByClassName('problem-right');
var box = document.getElementsByClassName('problem-box');
for (let i = 0; i < resize.length; i++) {
let leftWidth = 0;
if (minLeft) {
leftWidth = 431; // 420px+11px
} else {
leftWidth = box[i].clientWidth - 580; // 580px
}
resize[i].style.left = leftWidth - 11;
for (let j = 0; j < left.length; j++) {
left[j].style.width = leftWidth - 11 + 'px';
right[j].style.width = box[i].clientWidth - leftWidth + 'px';
}
}
this.toResetWatch = false;
},
init() {
if (this.$route.params.contestID) {
this.contestID = this.$route.params.contestID;
@ -890,6 +1014,7 @@ export default {
#problem-main {
flex: auto;
}
.problem-menu {
float: left;
}
@ -941,6 +1066,81 @@ a {
}
}
@media screen and (min-width: 1050px) {
.problem-box {
width: 100%;
height: 100%;
overflow: hidden;
}
.problem-left {
width: calc(50% - 10px); /*左侧初始化宽度*/
height: 100%;
overflow-y: auto;
overflow-x: hidden;
float: left;
}
.problem-resize {
cursor: col-resize;
float: left;
position: relative;
top: 330px;
background-color: #d6d6d6;
border-radius: 5px;
margin-top: -10px;
width: 10px;
height: 50px;
background-size: cover;
background-position: center;
/*z-index: 99999;*/
font-size: 32px;
color: white;
}
.problem-resize:hover .right-fold {
display: block;
}
.problem-resize:hover .fold:before {
content: '';
position: absolute;
display: block;
width: 6px;
height: 24px;
left: -6px;
}
.right-fold {
position: absolute;
display: none;
font-weight: bolder;
margin-left: 15px;
margin-top: -35px;
cursor: pointer;
z-index: 1000;
text-align: center;
}
.left-fold {
position: absolute;
font-weight: bolder;
margin-left: -40px;
margin-top: 10px;
cursor: pointer;
z-index: 1000;
text-align: center;
}
.fold:hover {
color: #409eff;
background: #fff;
}
/*拖拽区鼠标悬停样式*/
.problem-resize:hover {
color: #444444;
}
.problem-right {
height: 100%;
float: left;
width: 50%;
}
}
@media screen and (max-width: 1080px) {
.submit-detail {
padding-top: 20px;

File diff suppressed because one or more lines are too long

View File

@ -217,7 +217,7 @@ CREATE TABLE `permissions` (
UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
);
insert into `config_info`(`id`,`data_id`,`group_id`,`content`,`md5`,`gmt_create`,`gmt_modified`,`src_user`,`src_ip`,`app_name`,`tenant_id`,`c_desc`,`c_use`,`effect`,`type`,`c_schema`) values (1,'hoj-prod.yml','DEFAULT_GROUP','hoj:\n jwt:\n # 加密秘钥\n secret: hoj-secret-init\n # token默认为24小时 86400s\n expire: 86400\n checkRefreshExpire: 43200\n header: token\n judge:\n # 调用判题服务器的token\n token: hoj-judge-token-init\n db:\n host: 172.20.0.3\n public-host: 172.20.0.3\n port: 3306\n name: hoj\n username: root\n password: hoj123456\n mail:\n ssl: true\n username: your_email_username\n password: your_email_password\n host: smtp.qq.com\n port: 465\n background-img: https://cdn.jsdelivr.net/gh/HimitZH/CDN/images/HCODE.png\n redis:\n host: 172.20.0.2\n port: 6379\n password: hoj123456\n web-config:\n base-url: your_web_url\n name: Hcode Online Judge\n short-name: hoj\n description: Hcode Online Judge\n register: true\n footer:\n record:\n name: 2020-2021\n url: your_record_url\n project:\n name: HOJ\n url: https://gitee.com/himitzh0730/hoj\n hdu:\n account:\n username: \n password: \n cf:\n account:\n username: \n password: ','c83735964d6e700fffa073f3798556a0','2021-05-18 11:29:38','2021-05-18 11:40:41',NULL,'14.211.16.41','','','hoj配置','','','yaml','');
insert into `config_info`(`id`,`data_id`,`group_id`,`content`,`md5`,`gmt_create`,`gmt_modified`,`src_user`,`src_ip`,`app_name`,`tenant_id`,`c_desc`,`c_use`,`effect`,`type`,`c_schema`) values (1,'hoj-prod.yml','DEFAULT_GROUP','hoj:\n jwt:\n # 加密秘钥\n secret: hoj-secret-init\n # token默认为24小时 86400s\n expire: 86400\n checkRefreshExpire: 43200\n header: token\n judge:\n # 调用判题服务器的token\n token: hoj-judge-token-init\n db:\n host: 172.20.0.3\n public-host: 172.20.0.3\n port: 3306\n name: hoj\n username: root\n password: hoj123456\n mail:\n ssl: true\n username: your_email_username\n password: your_email_password\n host: smtp.qq.com\n port: 465\n background-img: https://cdn.jsdelivr.net/gh/HimitZH/CDN/images/HCODE.png\n redis:\n host: 172.20.0.2\n port: 6379\n password: hoj123456\n web-config:\n base-url: your_web_url\n name: Hcode Online Judge\n short-name: hoj\n description: Hcode Online Judge\n register: true\n footer:\n record:\n name: 2020-2021\n url: your_record_url\n project:\n name: HOJ\n url: https://gitee.com/himitzh0730/hoj\n hdu:\n account:\n username: \n password: \n cf:\n account:\n username: \n password: \n poj:\n account:\n username: \n password: ','c83735964d6e700fffa073f3798556a0','2021-05-18 11:29:38','2021-05-18 11:40:41',NULL,'14.211.16.41','','','hoj配置','','','yaml','');
delete from `users`;