| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- package space.anyi.serve.service.impl;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
- import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import space.anyi.codesandbox.CodeContext;
- import space.anyi.codesandbox.CodeResponse;
- import space.anyi.codesandbox.CodeSandBox;
- import space.anyi.codesandbox.TestCase;
- import space.anyi.serve.entity.contest.Contest;
- import space.anyi.serve.entity.contest.ContestProblem;
- import space.anyi.serve.entity.contest.Submission;
- import space.anyi.serve.entity.contest.SubmissionVo;
- import space.anyi.serve.entity.contest.SubmitDto;
- import space.anyi.serve.entity.problem.Problem;
- import space.anyi.serve.entity.problem.ProblemTest;
- import space.anyi.serve.entity.user.User;
- import space.anyi.serve.mapper.ContestProblemMapper;
- import space.anyi.serve.mapper.ProblemTestMapper;
- import space.anyi.serve.mapper.SubmissionMapper;
- import space.anyi.serve.service.ContestService;
- import space.anyi.serve.service.ProblemService;
- import space.anyi.serve.service.SubmissionService;
- import space.anyi.serve.util.SecurityUtils;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Objects;
- @Service
- public class SubmissionServiceImpl extends ServiceImpl<SubmissionMapper, Submission> implements SubmissionService {
- private final SubmissionMapper submissionMapper;
- private final ProblemTestMapper problemTestMapper;
- private final ContestProblemMapper contestProblemMapper;
- private final ProblemService problemService;
- private final ContestService contestService;
- private final CodeSandBox codeSandBox;
- public SubmissionServiceImpl(SubmissionMapper submissionMapper,
- ProblemTestMapper problemTestMapper,
- ContestProblemMapper contestProblemMapper,
- ProblemService problemService,
- ContestService contestService,
- CodeSandBox codeSandBox) {
- this.submissionMapper = submissionMapper;
- this.problemTestMapper = problemTestMapper;
- this.contestProblemMapper = contestProblemMapper;
- this.problemService = problemService;
- this.contestService = contestService;
- this.codeSandBox = codeSandBox;
- }
- @Override
- @Transactional
- public SubmissionVo submit(SubmitDto dto, Long userId) {
- Problem problem = problemService.getById(dto.getProblemId());
- if (problem == null) {
- throw new IllegalArgumentException("题目不存在");
- }
- if (dto.getContestId() != null) {
- validateContestSubmission(dto.getContestId(), userId);
- }
- List<ProblemTest> problemTests = problemTestMapper.selectList(
- new LambdaQueryWrapper<ProblemTest>()
- .eq(ProblemTest::getProblemId, dto.getProblemId())
- .orderByAsc(ProblemTest::getSortOrder));
- if (problemTests.isEmpty()) {
- throw new IllegalArgumentException("该题目还没有评测用例,无法提交");
- }
- Submission submission = new Submission();
- submission.setProblemId(dto.getProblemId());
- submission.setUserId(userId);
- submission.setContestId(dto.getContestId());
- submission.setCode(dto.getCode());
- submission.setLanguage(dto.getLanguage());
- submission.setStatus(Submission.STATUS_JUDGING);
- submission.setTotalTestCases(problemTests.size());
- submission.setPassedTestCases(0);
- submissionMapper.insert(submission);
- List<TestCase> testCases = new ArrayList<>();
- for (ProblemTest problemTest : problemTests) {
- testCases.add(new TestCase(problemTest.getId(), problemTest.getInput(), problemTest.getOutput()));
- }
- CodeContext context = new CodeContext(submission.getId(), dto.getCode(), dto.getLanguage(),
- problem.getTimeLimitMs().longValue(), problem.getMemoryLimitMb() * 1024L, testCases);
- CodeResponse response = codeSandBox.process(context);
- submission.setStatus(response.status());
- submission.setTimeUsedMs(response.usedTime() == null ? 0 : response.usedTime().intValue());
- submission.setMemoryUsedKb(response.usedMemory() == null ? 0 : response.usedMemory().intValue());
- submission.setJudgeDetail(response.message());
- if (response.testCaseResponses() != null) {
- long passed = response.testCaseResponses().stream()
- .filter(c -> Submission.STATUS_AC.equals(c.status()))
- .count();
- submission.setPassedTestCases((int) passed);
- }
- submission.setScore(resolveScore(dto.getContestId(), submission, problem));
- submissionMapper.updateById(submission);
- problem.setTryCount(problem.getTryCount() == null ? 1 : problem.getTryCount() + 1);
- if (Submission.STATUS_AC.equals(submission.getStatus())) {
- problem.setAcceptedCount(problem.getAcceptedCount() == null ? 1 : problem.getAcceptedCount() + 1);
- }
- problemService.updateById(problem);
- return SubmissionVo.from(submission);
- }
- @Override
- public SubmissionVo getDetail(Long submissionId, Long userId) {
- Submission submission = submissionMapper.selectById(submissionId);
- if (submission == null) {
- throw new IllegalArgumentException("提交记录不存在");
- }
- String role = SecurityUtils.getCurrentRole();
- if (!User.ROLE_ADMIN.equals(role) && !User.ROLE_COACH.equals(role)
- && !Objects.equals(submission.getUserId(), userId)) {
- throw new IllegalArgumentException("无权限查看该提交记录");
- }
- return SubmissionVo.from(submission);
- }
- @Override
- public Page<SubmissionVo> queryMySubmissions(Long userId, Integer pageNum, Integer pageSize) {
- Page<Submission> page = page(new Page<>(pageNum, pageSize),
- new LambdaQueryWrapper<Submission>()
- .eq(Submission::getUserId, userId)
- .orderByDesc(Submission::getCreatedAt));
- return convertToVoPage(page);
- }
- @Override
- public Page<SubmissionVo> queryByProblemId(Long problemId, Integer pageNum, Integer pageSize) {
- Page<Submission> page = page(new Page<>(pageNum, pageSize),
- new LambdaQueryWrapper<Submission>()
- .eq(Submission::getProblemId, problemId)
- .orderByDesc(Submission::getCreatedAt));
- return convertToVoPage(page);
- }
- private void validateContestSubmission(Long contestId, Long userId) {
- Contest contest = contestService.getById(contestId);
- if (contest == null) {
- throw new IllegalArgumentException("比赛不存在");
- }
- if (!Contest.STATUS_RUNNING.equals(contest.getStatus())) {
- throw new IllegalArgumentException("比赛未在进行中");
- }
- if (!contestService.isRegistered(contestId, userId)) {
- throw new IllegalArgumentException("未报名该比赛");
- }
- }
- private Integer resolveScore(Long contestId, Submission submission, Problem problem) {
- if (!Submission.STATUS_AC.equals(submission.getStatus())) {
- return 0;
- }
- if (contestId == null) {
- return 0;
- }
- ContestProblem contestProblem = contestProblemMapper.selectOne(new LambdaQueryWrapper<ContestProblem>()
- .eq(ContestProblem::getContestId, contestId)
- .eq(ContestProblem::getProblemId, submission.getProblemId()));
- return contestProblem == null || contestProblem.getScore() == null ? 0 : contestProblem.getScore();
- }
- private Page<SubmissionVo> convertToVoPage(Page<Submission> page) {
- Page<SubmissionVo> result = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
- result.setRecords(SubmissionVo.from(page.getRecords()));
- return result;
- }
- }
|