private Result showEditProblem( Form<ContestProblemEditForm> contestProblemEditForm, Contest contest, ContestProblem contestProblem) { LazyHtml content = new LazyHtml( editProblemView.render(contest.getId(), contestProblem, contestProblemEditForm)); content.appendLayout( c -> heading3Layout.render( Messages.get("problem.update") + " " + contestProblem.getAlias(), c)); appendSubtabsLayout(content, contest); ContestControllerUtils.getInstance() .appendTabsLayout(content, contest, IdentityUtils.getUserJid()); UrielControllerUtils.getInstance().appendSidebarLayout(content); appendBreadcrumbsLayout( content, contest, new InternalLink( Messages.get("status.supervisor"), routes.ContestProblemController.viewProblems(contest.getId())), new InternalLink( Messages.get("problem.update"), routes.ContestProblemController.editProblem(contest.getId(), contestProblem.getId()))); UrielControllerUtils.getInstance().appendTemplateLayout(content, "Contest - Problem - Update"); return UrielControllerUtils.getInstance().lazyOk(content); }
@Transactional public Result refreshProblems(long contestId) throws ContestNotFoundException, ContestProblemNotFoundException { Contest contest = contestService.findContestById(contestId); if (contest.isLocked() || !ContestControllerUtils.getInstance() .isManagerOrAbove(contest, IdentityUtils.getUserJid())) { return ContestControllerUtils.getInstance() .tryEnteringContest(contest, IdentityUtils.getUserJid()); } for (ContestProblem problem : contestProblemService.getOpenedProblemsInContest(contest.getJid())) { SandalphonProblem sandalphonProblem; try { sandalphonProblem = sandalphonClientAPI.findClientProblem( problem.getProblemJid(), problem.getProblemSecret()); } catch (JudgelsAPIClientException e) { continue; } JidCacheServiceImpl.getInstance() .putDisplayName( problem.getProblemJid(), sandalphonProblem.getDisplayName(), IdentityUtils.getUserJid(), IdentityUtils.getIpAddress()); } return redirect(routes.ContestProblemController.viewProblems(contest.getId())); }
private void appendSubtabsLayout(LazyHtml content, Contest contest) { content.appendLayout( c -> accessTypeByStatusLayout.render( routes.ContestProblemController.viewUsedProblems(contest.getId()), routes.ContestProblemController.viewProblems(contest.getId()), c)); }
@Transactional(readOnly = true) public Result listUsedProblems(long contestId, long pageIndex) throws ContestNotFoundException { Contest contest = contestService.findContestById(contestId); if (!ContestControllerUtils.getInstance() .isAllowedToEnterContest(contest, IdentityUtils.getUserJid())) { return ContestControllerUtils.getInstance() .tryEnteringContest(contest, IdentityUtils.getUserJid()); } Page<ContestProblem> pageOfContestProblems = contestProblemService.getPageOfUsedProblemsInContest( contest.getJid(), pageIndex, PAGE_SIZE); ImmutableList.Builder<ContestProblem> replacementBuilder = ImmutableList.builder(); for (ContestProblem contestProblem : pageOfContestProblems.getData()) { contestProblem.setTotalSubmissions( programmingSubmissionService.countProgrammingSubmissionsByUserJid( contest.getJid(), contestProblem.getProblemJid(), IdentityUtils.getUserJid())); replacementBuilder.add(contestProblem); } pageOfContestProblems = new Page<>( replacementBuilder.build(), pageOfContestProblems.getTotalRowsCount(), pageOfContestProblems.getPageIndex(), pageOfContestProblems.getPageSize()); List<String> problemJids = pageOfContestProblems .getData() .stream() .map(cp -> cp.getProblemJid()) .collect(Collectors.toList()); Map<String, String> problemTitlesMap = SandalphonResourceDisplayNameUtils.buildTitlesMap( JidCacheServiceImpl.getInstance().getDisplayNames(problemJids), ContestControllerUtils.getInstance().getCurrentStatementLanguage()); LazyHtml content = new LazyHtml( listUsedProblemsView.render( contest.getId(), pageOfContestProblems, pageIndex, problemTitlesMap)); content.appendLayout(c -> heading3Layout.render(Messages.get("problem.problems"), c)); if (isAllowedToSuperviseProblems(contest)) { appendSubtabsLayout(content, contest); } ContestControllerUtils.getInstance() .appendTabsLayout(content, contest, IdentityUtils.getUserJid()); UrielControllerUtils.getInstance().appendSidebarLayout(content); appendBreadcrumbsLayout( content, contest, new InternalLink( Messages.get("problem.list"), routes.ContestProblemController.viewUsedProblems(contest.getId()))); UrielControllerUtils.getInstance().appendTemplateLayout(content, "Contest - Problems"); return UrielControllerUtils.getInstance().lazyOk(content); }
private long computeSubmissionPenaltyInMilliseconds( Contest contest, Date contestStartTime, Date submissionTime) { if (contestStartTime != null) { return submissionTime.getTime() - contestStartTime.getTime(); } if (!contest.containsModule(ContestModules.DURATION)) { return 0; } ContestDurationModule contestDurationModule = (ContestDurationModule) contest.getModule(ContestModules.DURATION); return submissionTime.getTime() - contestDurationModule.getBeginTime().getTime(); }
@Transactional(readOnly = true) public Result renderImage(long contestId, long contestProblemId, String imageFilename) throws ContestNotFoundException, ContestProblemNotFoundException { Contest contest = contestService.findContestById(contestId); ContestProblem contestProblem = contestProblemService.findContestProblemById(contestProblemId); if (!contest.getJid().equals(contestProblem.getContestJid())) { return notFound(); } String imageUrl = sandalphonClientAPI.getProblemStatementMediaRenderAPIEndpoint( contestProblem.getProblemJid(), imageFilename); return redirect(imageUrl); }
@Transactional(readOnly = true) @AddCSRFToken public Result addProblem(long contestId) throws ContestNotFoundException { Contest contest = contestService.findContestById(contestId); if (contest.isLocked() || !isAllowedToSuperviseProblems(contest)) { return ContestControllerUtils.getInstance() .tryEnteringContest(contest, IdentityUtils.getUserJid()); } ContestProblemAddForm contestProblemAddData = new ContestProblemAddForm(); contestProblemAddData.submissionsLimit = 0; Form<ContestProblemAddForm> contestProblemAddForm = Form.form(ContestProblemAddForm.class); contestProblemAddForm = contestProblemAddForm.fill(contestProblemAddData); return showAddProblem(contestProblemAddForm, contest); }
@Transactional public Result removeProblem(long contestId, long contestProblemId) throws ContestNotFoundException, ContestProblemNotFoundException { Contest contest = contestService.findContestById(contestId); ContestProblem contestProblem = contestProblemService.findContestProblemById(contestProblemId); if (contest.isLocked() || !ContestControllerUtils.getInstance() .isManagerOrAbove(contest, IdentityUtils.getUserJid()) || !contestProblem.getContestJid().equals(contest.getJid())) { return ContestControllerUtils.getInstance() .tryEnteringContest(contest, IdentityUtils.getUserJid()); } contestProblemService.deleteContestProblem(contestProblem.getId()); UrielControllerUtils.getInstance() .addActivityLog( BasicActivityKeys.REMOVE_FROM.construct( CONTEST, contest.getJid(), contest.getName(), PROBLEM, contestProblem.getProblemJid(), SandalphonResourceDisplayNameUtils.parseSlugByLanguage( JidCacheServiceImpl.getInstance() .getDisplayName(contestProblem.getProblemJid())))); return redirect(routes.ContestProblemController.viewProblems(contest.getId())); }
@Transactional(readOnly = true) @AddCSRFToken public Result editProblem(long contestId, long contestProblemId) throws ContestNotFoundException, ContestProblemNotFoundException { Contest contest = contestService.findContestById(contestId); ContestProblem contestProblem = contestProblemService.findContestProblemById(contestProblemId); if (contest.isLocked() || !isAllowedToSuperviseProblems(contest) || !contestProblem.getContestJid().equals(contest.getJid())) { return ContestControllerUtils.getInstance() .tryEnteringContest(contest, IdentityUtils.getUserJid()); } ContestProblemEditForm contestProblemEditData = new ContestProblemEditForm(); contestProblemEditData.alias = contestProblem.getAlias(); contestProblemEditData.submissionsLimit = contestProblem.getSubmissionsLimit(); contestProblemEditData.status = contestProblem.getStatus().name(); Form<ContestProblemEditForm> contestProblemEditForm = Form.form(ContestProblemEditForm.class).fill(contestProblemEditData); return showEditProblem(contestProblemEditForm, contest, contestProblem); }
private void appendBreadcrumbsLayout( LazyHtml content, Contest contest, InternalLink... lastLinks) { UrielControllerUtils.getInstance() .appendBreadcrumbsLayout( content, ContestControllerUtils.getInstance() .getContestBreadcrumbsBuilder(contest) .add( new InternalLink( Messages.get("problem.problems"), org.iatoki.judgels.uriel.contest.routes.ContestController.jumpToProblems( contest.getId()))) .addAll(Arrays.asList(lastLinks)) .build()); }
@Transactional @RequireCSRFCheck public Result postEditProblem(long contestId, long contestProblemId) throws ContestNotFoundException, ContestProblemNotFoundException { Contest contest = contestService.findContestById(contestId); ContestProblem contestProblem = contestProblemService.findContestProblemById(contestProblemId); if (contest.isLocked() || !isAllowedToSuperviseProblems(contest) || !contestProblem.getContestJid().equals(contest.getJid())) { return ContestControllerUtils.getInstance() .tryEnteringContest(contest, IdentityUtils.getUserJid()); } Form<ContestProblemEditForm> contestProblemEditForm = Form.form(ContestProblemEditForm.class).bindFromRequest(); if (formHasErrors(contestProblemEditForm)) { return showEditProblem(contestProblemEditForm, contest, contestProblem); } ContestProblemEditForm contestProblemEditData = contestProblemEditForm.get(); contestProblemService.updateContestProblem( contestProblem.getId(), contestProblemEditData.alias, contestProblemEditData.submissionsLimit, ContestProblemStatus.valueOf(contestProblemEditData.status), IdentityUtils.getUserJid(), IdentityUtils.getIpAddress()); UrielControllerUtils.getInstance() .addActivityLog( BasicActivityKeys.EDIT_IN.construct( CONTEST, contest.getJid(), contest.getName(), PROBLEM, contestProblem.getProblemJid(), SandalphonResourceDisplayNameUtils.parseSlugByLanguage( JidCacheServiceImpl.getInstance() .getDisplayName(contestProblem.getProblemJid())))); return redirect(routes.ContestProblemController.viewProblems(contest.getId())); }
private boolean isAllowedToViewProblem(Contest contest, ContestProblem contestProblem) { return contestProblem.getContestJid().equals(contest.getJid()) && contestProblem.getStatus() != ContestProblemStatus.UNUSED; }
@Transactional @RequireCSRFCheck public Result postAddProblem(long contestId) throws ContestNotFoundException { Contest contest = contestService.findContestById(contestId); if (contest.isLocked() || !isAllowedToSuperviseProblems(contest)) { return ContestControllerUtils.getInstance() .tryEnteringContest(contest, IdentityUtils.getUserJid()); } Form<ContestProblemAddForm> contestProblemCreateForm = Form.form(ContestProblemAddForm.class).bindFromRequest(); if (formHasErrors(contestProblemCreateForm)) { return showAddProblem(contestProblemCreateForm, contest); } ContestProblemAddForm contestProblemAddData = contestProblemCreateForm.get(); if (contestProblemService.isProblemInContestByJidOrAlias( contest.getJid(), contestProblemAddData.problemJid, contestProblemAddData.alias)) { contestProblemCreateForm.reject("error.problem.create.problemJidOrAliasUsed"); return showAddProblem(contestProblemCreateForm, contest); } SandalphonProblem sandalphonProblem; try { sandalphonProblem = sandalphonClientAPI.findClientProblem( contestProblemAddData.problemJid, contestProblemAddData.problemSecret); } catch (JudgelsAPIClientException e) { if (e.getStatusCode() >= Http.Status.INTERNAL_SERVER_ERROR) { contestProblemCreateForm.reject("error.system.sandalphon.connection"); } else { contestProblemCreateForm.reject("error.problem.create.problemJidOrSecretInvalid"); } return showAddProblem(contestProblemCreateForm, contest); } contestProblemService.createContestProblem( contest.getJid(), contestProblemAddData.problemJid, contestProblemAddData.problemSecret, contestProblemAddData.alias, contestProblemAddData.submissionsLimit, ContestProblemStatus.valueOf(contestProblemAddData.status), IdentityUtils.getUserJid(), IdentityUtils.getIpAddress()); JidCacheServiceImpl.getInstance() .putDisplayName( contestProblemAddData.problemJid, sandalphonProblem.getDisplayName(), IdentityUtils.getUserJid(), IdentityUtils.getIpAddress()); UrielControllerUtils.getInstance() .addActivityLog( BasicActivityKeys.ADD_IN.construct( CONTEST, contest.getJid(), contest.getName(), PROBLEM, contestProblemAddData.problemJid, sandalphonProblem.getSlug())); return redirect(routes.ContestProblemController.viewProblems(contest.getId())); }
@Transactional(readOnly = true) public Result listProblems( long contestId, long page, String sortBy, String orderBy, String filterString) throws ContestNotFoundException { Contest contest = contestService.findContestById(contestId); if (!isAllowedToSuperviseProblems(contest)) { return ContestControllerUtils.getInstance() .tryEnteringContest(contest, IdentityUtils.getUserJid()); } boolean canDelete = ContestControllerUtils.getInstance().isManagerOrAbove(contest, IdentityUtils.getUserJid()); Page<ContestProblem> pageOfContestProblems = contestProblemService.getPageOfProblemsInContest( contest.getJid(), page, PAGE_SIZE, sortBy, orderBy, filterString, null); List<String> problemJids = pageOfContestProblems .getData() .stream() .map(cp -> cp.getProblemJid()) .collect(Collectors.toList()); Map<String, String> problemSlugsMap = SandalphonResourceDisplayNameUtils.buildSlugsMap( JidCacheServiceImpl.getInstance().getDisplayNames(problemJids)); LazyHtml content = new LazyHtml( listProblemsView.render( contest.getId(), pageOfContestProblems, page, sortBy, orderBy, filterString, canDelete, problemSlugsMap)); content.appendLayout( c -> heading3WithActionsLayout.render( Messages.get("problem.list"), new InternalLink[] { new InternalLink( Messages.get("commons.create"), routes.ContestProblemController.addProblem(contestId)), new InternalLink( Messages.get("problem.refresh"), routes.ContestProblemController.refreshProblems(contestId)) }, c)); appendSubtabsLayout(content, contest); ContestControllerUtils.getInstance() .appendTabsLayout(content, contest, IdentityUtils.getUserJid()); UrielControllerUtils.getInstance().appendSidebarLayout(content); appendBreadcrumbsLayout( content, contest, new InternalLink( Messages.get("problem.list"), routes.ContestProblemController.viewProblems(contest.getId()))); UrielControllerUtils.getInstance().appendTemplateLayout(content, "Contest - Problems"); return UrielControllerUtils.getInstance().lazyOk(content); }
@Transactional(readOnly = true) public Result viewProblem(long contestId, long contestProblemId) throws ContestNotFoundException, ContestProblemNotFoundException { Contest contest = contestService.findContestById(contestId); ContestProblem contestProblem = contestProblemService.findContestProblemById(contestProblemId); if (!ContestControllerUtils.getInstance() .isAllowedToEnterContest(contest, IdentityUtils.getUserJid()) || !isAllowedToViewProblem(contest, contestProblem)) { return ContestControllerUtils.getInstance() .tryEnteringContest(contest, IdentityUtils.getUserJid()); } long submissionsLeft = -1; if (contestProblem.getSubmissionsLimit() != 0) { submissionsLeft = contestProblem.getSubmissionsLimit() - programmingSubmissionService.countProgrammingSubmissionsByUserJid( contest.getJid(), contestProblem.getProblemJid(), IdentityUtils.getUserJid()); } SandalphonProgrammingProblemStatementRenderRequestParam param = new SandalphonProgrammingProblemStatementRenderRequestParam(); param.setProblemSecret(contestProblem.getProblemSecret()); param.setCurrentMillis(System.currentTimeMillis()); param.setStatementLanguage(ContestControllerUtils.getInstance().getCurrentStatementLanguage()); param.setSwitchStatementLanguageUrl( routes.ContestProblemController.switchLanguage(contestId, contestProblemId) .absoluteURL(request(), request().secure())); param.setPostSubmitUrl( org.iatoki.judgels.uriel.contest.submission.programming.routes .ContestProgrammingSubmissionController.postSubmitProblem( contest.getId(), contestProblem.getProblemJid()) .absoluteURL(request(), request().secure())); param.setReasonNotAllowedToSubmit(null); Set<String> allowedGradingLanguages; if (contest.isICPC()) { allowedGradingLanguages = ((ICPCContestStyleConfig) contest.getStyleConfig()) .getLanguageRestriction() .getAllowedLanguageNames(); } else { allowedGradingLanguages = ((IOIContestStyleConfig) contest.getStyleConfig()) .getLanguageRestriction() .getAllowedLanguageNames(); } param.setAllowedGradingLanguages(StringUtils.join(allowedGradingLanguages, ",")); String requestUrl = sandalphonClientAPI.getProgrammingProblemStatementRenderAPIEndpoint( contestProblem.getProblemJid()); String requestBody = sandalphonClientAPI.constructProgrammingProblemStatementRenderAPIRequestBody( contestProblem.getProblemJid(), param); LazyHtml content; if (UrielProperties.getInstance().isContestCritial(contest.getJid())) { content = new LazyHtml( viewProblemCriticalView.render( requestUrl, requestBody, submissionsLeft, contestProblem.getStatus() == ContestProblemStatus.CLOSED, contest, contestProblem)); } else { content = new LazyHtml( viewProblemView.render( requestUrl, requestBody, submissionsLeft, contestProblem.getStatus() == ContestProblemStatus.CLOSED)); } ContestControllerUtils.getInstance() .appendTabsLayout(content, contest, IdentityUtils.getUserJid()); UrielControllerUtils.getInstance().appendSidebarLayout(content); appendBreadcrumbsLayout( content, contest, new InternalLink( Messages.get("status.contestant"), routes.ContestProblemController.viewUsedProblems(contest.getId())), new InternalLink( contestProblem.getAlias(), routes.ContestProblemController.viewProblem(contest.getId(), contestProblem.getId()))); UrielControllerUtils.getInstance().appendTemplateLayout(content, "Contest - Problem - View"); return UrielControllerUtils.getInstance().lazyOk(content); }
@Override public ScoreboardContent computeScoreboardContent( Contest contest, ScoreboardState state, List<ProgrammingSubmission> submissions, Map<String, Date> contestantStartTimes, Map<String, URL> userJidToImageMap) { ICPCContestStyleConfig icpcStyleConfig = (ICPCContestStyleConfig) contest.getStyleConfig(); ScoreboardEntryComparator<ICPCScoreboardEntry> comparator = new ICPCScoreboardEntryComparator(); Map<String, Map<String, Integer>> attemptsMap = Maps.newHashMap(); Map<String, Map<String, Long>> penaltyMap = Maps.newHashMap(); Map<String, Map<String, Integer>> problemStateMap = Maps.newHashMap(); Map<String, Long> lastAcceptedPenaltyMap = Maps.newHashMap(); Set<String> acceptedProblemJids = Sets.newHashSet(); for (String contestantJid : state.getContestantJids()) { attemptsMap.put(contestantJid, Maps.newHashMap()); penaltyMap.put(contestantJid, Maps.newHashMap()); problemStateMap.put(contestantJid, Maps.newHashMap()); for (String problemJid : state.getProblemJids()) { attemptsMap.get(contestantJid).put(problemJid, 0); penaltyMap.get(contestantJid).put(problemJid, 0L); lastAcceptedPenaltyMap.put(contestantJid, 0L); problemStateMap .get(contestantJid) .put(problemJid, ICPCScoreboardEntry.State.NOT_ACCEPTED.ordinal()); } } for (ProgrammingSubmission submission : submissions) { String contestantJid = submission.getAuthorJid(); String problemJid = submission.getProblemJid(); if (!attemptsMap.containsKey(contestantJid)) { continue; } if (!attemptsMap.get(contestantJid).containsKey(problemJid)) { continue; } if (problemStateMap.get(contestantJid).get(problemJid) != ICPCScoreboardEntry.State.NOT_ACCEPTED.ordinal()) { continue; } Verdict verdict = submission.getLatestVerdict(); if (verdict.getCode().equals("?")) { continue; } int attempts = attemptsMap.get(contestantJid).get(problemJid); attemptsMap.get(contestantJid).put(problemJid, attempts + 1); long penaltyInMilliseconds = computeSubmissionPenaltyInMilliseconds( contest, contestantStartTimes.get(contestantJid), submission.getTime()); penaltyMap.get(contestantJid).put(problemJid, convertPenaltyToMinutes(penaltyInMilliseconds)); if (verdict.getCode().equals("AC")) { if (acceptedProblemJids.contains(problemJid)) { problemStateMap .get(contestantJid) .put(problemJid, ICPCScoreboardEntry.State.ACCEPTED.ordinal()); } else { problemStateMap .get(contestantJid) .put(problemJid, ICPCScoreboardEntry.State.FIRST_ACCEPTED.ordinal()); acceptedProblemJids.add(problemJid); } lastAcceptedPenaltyMap.put(contestantJid, penaltyInMilliseconds); } } List<ICPCScoreboardEntry> entries = Lists.newArrayList(); for (String contestantJid : state.getContestantJids()) { ICPCScoreboardEntry entry = new ICPCScoreboardEntry(); entry.contestantJid = contestantJid; entry.imageURL = userJidToImageMap.get(contestantJid); for (String problemJid : state.getProblemJids()) { int attempts = attemptsMap.get(contestantJid).get(problemJid); long penalty = penaltyMap.get(contestantJid).get(problemJid); long lastAcceptedPenalty = lastAcceptedPenaltyMap.get(contestantJid); int problemState = problemStateMap.get(contestantJid).get(problemJid); entry.attemptsList.add(attempts); entry.penaltyList.add(penalty); entry.lastAcceptedPenalty = lastAcceptedPenalty; entry.problemStateList.add(problemState); if (problemState != ICPCScoreboardEntry.State.NOT_ACCEPTED.ordinal()) { entry.totalAccepted++; entry.totalPenalties += icpcStyleConfig.getWrongSubmissionPenalty() * (attempts - 1) + penalty; } } entries.add(entry); } sortEntriesAndAssignRanks(comparator, entries); return new ICPCScoreboardContent(entries); }