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 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
  @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()));
  }
  @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);
  }