package org.iatoki.judgels.uriel.controllers; import com.google.common.collect.ImmutableList; import com.google.gson.Gson; import org.iatoki.judgels.play.IdentityUtils; import org.iatoki.judgels.play.InternalLink; import org.iatoki.judgels.play.LazyHtml; import org.iatoki.judgels.play.views.html.layouts.headingLayout; import org.iatoki.judgels.play.views.html.layouts.headingWithActionLayout; import org.iatoki.judgels.play.views.html.layouts.tabLayout; import org.iatoki.judgels.uriel.Contest; import org.iatoki.judgels.uriel.ContestConfiguration; import org.iatoki.judgels.uriel.ContestContestant; import org.iatoki.judgels.uriel.PublicContestScopeConfig; import org.iatoki.judgels.uriel.ContestTeam; import org.iatoki.judgels.uriel.VirtualContestTypeConfig; import org.iatoki.judgels.uriel.VirtualContestTypeConfigStartTrigger; import org.iatoki.judgels.uriel.UrielUtils; import org.iatoki.judgels.uriel.services.ContestContestantService; import org.iatoki.judgels.uriel.services.ContestManagerService; import org.iatoki.judgels.uriel.services.ContestContestantPasswordService; import org.iatoki.judgels.uriel.services.ContestService; import org.iatoki.judgels.uriel.services.ContestSupervisorService; import org.iatoki.judgels.uriel.services.ContestTeamService; import org.iatoki.judgels.uriel.views.html.contest.contestTimeLayout; import play.i18n.Messages; import play.mvc.Controller; import play.mvc.Result; import play.mvc.Results; import java.util.Date; import java.util.concurrent.TimeUnit; public final class ContestControllerUtils { private ContestService contestService; private ContestContestantService contestContestantService; private ContestSupervisorService contestSupervisorService; private ContestManagerService contestManagerService; private ContestTeamService contestTeamService; private ContestContestantPasswordService contestContestantPasswordService; static ContestControllerUtils INSTANCE; private ContestControllerUtils(ContestService contestService, ContestContestantService contestContestantService, ContestSupervisorService contestSupervisorService, ContestManagerService contestManagerService, ContestTeamService contestTeamService, ContestContestantPasswordService contestContestantPasswordService) { this.contestService = contestService; this.contestContestantService = contestContestantService; this.contestSupervisorService = contestSupervisorService; this.contestManagerService = contestManagerService; this.contestTeamService = contestTeamService; this.contestContestantPasswordService = contestContestantPasswordService; } public static synchronized void buildInstance(ContestService contestService, ContestContestantService contestContestantService, ContestSupervisorService contestSupervisorService, ContestManagerService contestManagerService, ContestTeamService contestTeamService, ContestContestantPasswordService contestPasswordService) { if (INSTANCE != null) { throw new UnsupportedOperationException("ContestControllerUtils instance has already been built"); } INSTANCE = new ContestControllerUtils(contestService, contestContestantService, contestSupervisorService, contestManagerService, contestTeamService, contestPasswordService); } public static ContestControllerUtils getInstance() { if (INSTANCE == null) { throw new UnsupportedOperationException("ContestControllerUtils instance has not been built"); } return INSTANCE; } void setCurrentStatementLanguage(String languageCode) { Controller.session("currentStatementLanguage", languageCode); } String getCurrentStatementLanguage() { String lang = Controller.session("currentStatementLanguage"); if (lang == null) { return "en-US"; } else { return lang; } } boolean isManager(Contest contest) { return contestManagerService.isContestManagerInContestByUserJid(contest.getJid(), IdentityUtils.getUserJid()); } boolean isSupervisor(Contest contest) { return contestSupervisorService.isContestSupervisorInContestByUserJid(contest.getJid(), IdentityUtils.getUserJid()); } boolean isCoach(Contest contest) { return contestTeamService.isUserCoachInAnyTeamByContestJid(contest.getJid(), IdentityUtils.getUserJid()); } boolean isContestant(Contest contest) { return contestContestantService.isContestContestantInContestByUserJid(contest.getJid(), IdentityUtils.getUserJid()); } boolean isSupervisorOrAbove(Contest contest) { return ControllerUtils.getInstance().isAdmin() || isManager(contest) || (isSupervisor(contest)); } boolean isCoachOrAbove(Contest contest) { return isCoach(contest) || isSupervisorOrAbove(contest); } boolean hasContestBegun(Contest contest) { return (!new Date().before(contest.getStartTime())); } boolean hasContestEnded(Contest contest) { return (!new Date().before(contest.getEndTime())); } boolean hasContestStarted(Contest contest) { if (contest.isStandard()) { return hasContestBegun(contest); } else if (isContestant(contest)) { ContestContestant contestContestant = contestContestantService.findContestContestantByContestJidAndContestContestantJid(contest.getJid(), IdentityUtils.getUserJid()); return contestContestant.getContestStartTime() != 0; } return false; } boolean hasContestFinished(Contest contest) { if ((contest.isVirtual()) && (isContestant(contest))) { ContestContestant contestContestant = contestContestantService.findContestContestantByContestJidAndContestContestantJid(contest.getJid(), IdentityUtils.getUserJid()); ContestConfiguration contestConfiguration = contestService.findContestConfigurationByContestJid(contest.getJid()); VirtualContestTypeConfig virtualContestTypeConfig = new Gson().fromJson(contestConfiguration.getTypeConfig(), VirtualContestTypeConfig.class); return contestContestant.getContestStartTime() != 0 && (System.currentTimeMillis() > (contestContestant.getContestStartTime() + virtualContestTypeConfig.getContestDuration())); } else { return hasContestEnded(contest); } } boolean isAllowedToViewContest(Contest contest) { return contest.isPublic() || isCoachOrAbove(contest) || isContestant(contest); } boolean isAllowedToManageContest(Contest contest) { return ControllerUtils.getInstance().isAdmin() || isManager(contest); } boolean isAllowedToRegisterContest(Contest contest) { if (isSupervisorOrAbove(contest)) { return false; } boolean result = !isContestant(contest) && !hasContestEnded(contest); if (contest.isPublic()) { ContestConfiguration contestConfiguration = contestService.findContestConfigurationByContestJid(contest.getJid()); PublicContestScopeConfig publicContestScopeConfig = new Gson().fromJson(contestConfiguration.getScopeConfig(), PublicContestScopeConfig.class); result = result && (publicContestScopeConfig.getRegisterStartTime() < System.currentTimeMillis()) && (publicContestScopeConfig.getRegisterEndTime() > System.currentTimeMillis()) && ((publicContestScopeConfig.getMaxRegistrants() == 0) || (contestContestantService.getContestContestantCount(contest.getJid()) < publicContestScopeConfig.getMaxRegistrants())); } else { result = false; } return result; } boolean isAllowedToUnregisterContest(Contest contest) { return isContestant(contest) && contest.isPublic() && !hasContestStarted(contest); } boolean isAllowedToViewEnterContestButton(Contest contest) { if (isCoachOrAbove(contest)) { return true; } if (!isContestant(contest)) { return false; } if (contest.isStandard()) { return hasContestBegun(contest); } else { ContestConfiguration contestConfiguration = contestService.findContestConfigurationByContestJid(contest.getJid()); VirtualContestTypeConfig virtualContestTypeConfig = new Gson().fromJson(contestConfiguration.getTypeConfig(), VirtualContestTypeConfig.class); if (virtualContestTypeConfig.getStartTrigger().equals(VirtualContestTypeConfigStartTrigger.CONTESTANT)) { return (isContestant(contest) && (hasContestStarted(contest))); } else { return ((hasContestStarted(contest)) && (isCoach(contest) || (isContestant(contest) && (contestContestantService.isContestStarted(contest.getJid(), IdentityUtils.getUserJid()))))); } } } boolean isAllowedToEnterContest(Contest contest) { if (!isAllowedToViewEnterContestButton(contest)) { return false; } if (isCoachOrAbove(contest)) { return true; } if (!isContestant(contest)) { return false; } if (contest.requiresPassword() && !UrielUtils.trullyHasRole("admin")) { String password = contestContestantPasswordService.getContestantPassword(contest.getJid(), IdentityUtils.getUserJid()); return ((password == null) && (hasEstablishedContestWithPasswordCookie(password))); } return true; } boolean requiresPasswordToEnterContest(Contest contest) { if (UrielUtils.trullyHasRole("admin")) { return false; } if (isSupervisorOrAbove(contest)) { return false; } return contest.requiresPassword(); } boolean isAllowedToStartContestAsContestant(Contest contest) { if (!hasContestBegun(contest) || hasContestEnded(contest)) { return false; } if (isSupervisorOrAbove(contest)) { return false; } if (!contest.isVirtual() || !isContestant(contest)) { return false; } ContestConfiguration contestConfiguration = contestService.findContestConfigurationByContestJid(contest.getJid()); VirtualContestTypeConfig virtualContestTypeConfig = new Gson().fromJson(contestConfiguration.getTypeConfig(), VirtualContestTypeConfig.class); if (virtualContestTypeConfig.getStartTrigger().equals(VirtualContestTypeConfigStartTrigger.CONTESTANT)) { return !hasContestStarted(contest); } else { return false; } } boolean isAllowedToStartAnyContestAsCoach(Contest contest) { if (!hasContestBegun(contest) || hasContestEnded(contest)) { return false; } if (isSupervisorOrAbove(contest)) { return true; } if (!contest.isVirtual() || !isCoach(contest)) { return false; } ContestConfiguration contestConfiguration = contestService.findContestConfigurationByContestJid(contest.getJid()); VirtualContestTypeConfig virtualContestTypeConfig = new Gson().fromJson(contestConfiguration.getTypeConfig(), VirtualContestTypeConfig.class); if (virtualContestTypeConfig.getStartTrigger().equals(VirtualContestTypeConfigStartTrigger.COACH)) { return !hasContestStarted(contest); } else { return false; } } boolean isAllowedToStartContestAsCoach(Contest contest, ContestTeam contestTeam) { if (!hasContestBegun(contest) || hasContestEnded(contest)) { return false; } if (isSupervisorOrAbove(contest)) { return true; } if (!contest.isVirtual() || !contestTeamService.isUserCoachByUserJidAndTeamJid(IdentityUtils.getUserJid(), contestTeam.getJid())) { return false; } ContestConfiguration contestConfiguration = contestService.findContestConfigurationByContestJid(contest.getJid()); VirtualContestTypeConfig virtualContestTypeConfig = new Gson().fromJson(contestConfiguration.getTypeConfig(), VirtualContestTypeConfig.class); if (virtualContestTypeConfig.getStartTrigger().equals(VirtualContestTypeConfigStartTrigger.COACH)) { return !hasContestStarted(contest); } else { return false; } } boolean isAllowedToDoContest(Contest contest) { if (isSupervisorOrAbove(contest)) { return true; } return isAllowedToEnterContest(contest) && hasContestStarted(contest) && !hasContestFinished(contest); } Result tryEnteringContest(Contest contest) { if (isAllowedToEnterContest(contest)) { return Results.redirect(routes.ContestAnnouncementController.viewPublishedAnnouncements(contest.getId())); } else { return Results.redirect(routes.ContestController.viewContest(contest.getId())); } } void establishContestWithPasswordCookie(String contestPassword) { Controller.response().setCookie(contestPassword, "true", (int)TimeUnit.SECONDS.convert(5, TimeUnit.HOURS)); } boolean hasEstablishedContestWithPasswordCookie(String contestPassword) { return Controller.request().cookie(contestPassword) != null; } void appendTabsLayout(LazyHtml content, Contest contest) { final Date contestEndTime; if ((contest.isVirtual()) && (isContestant(contest))) { ContestContestant contestContestant = contestContestantService.findContestContestantByContestJidAndContestContestantJid(contest.getJid(), IdentityUtils.getUserJid()); ContestConfiguration contestConfiguration = contestService.findContestConfigurationByContestJid(contest.getJid()); VirtualContestTypeConfig virtualContestTypeConfig = new Gson().fromJson(contestConfiguration.getTypeConfig(), VirtualContestTypeConfig.class); contestEndTime = new Date(Math.min(contestContestant.getContestStartTime() + virtualContestTypeConfig.getContestDuration(), contest.getEndTime().getTime())); } else { contestEndTime = contest.getEndTime(); } ImmutableList.Builder<InternalLink> internalLinkBuilder = ImmutableList.builder(); internalLinkBuilder.add(new InternalLink(Messages.get("announcement.announcements"), routes.ContestController.jumpToAnnouncements(contest.getId()))); internalLinkBuilder.add(new InternalLink(Messages.get("problem.problems"), routes.ContestController.jumpToProblems(contest.getId()))); if (!isCoach(contest)) { internalLinkBuilder.add(new InternalLink(Messages.get("submission.submissions"), routes.ContestController.jumpToSubmissions(contest.getId()))); } internalLinkBuilder.add(new InternalLink(Messages.get("clarification.clarifications"), routes.ContestController.jumpToClarifications(contest.getId()))); if (contest.isUsingScoreboard()) { internalLinkBuilder.add(new InternalLink(Messages.get("scoreboard.scoreboard"), routes.ContestController.jumpToScoreboard(contest.getId()))); } if (isCoachOrAbove(contest)) { internalLinkBuilder.add(new InternalLink(Messages.get("contestant.contestants"), routes.ContestController.jumpToContestants(contest.getId()))); } if (isSupervisorOrAbove(contest)) { internalLinkBuilder.add(new InternalLink(Messages.get("supervisor.supervisors"), routes.ContestController.jumpToSupervisors(contest.getId()))); internalLinkBuilder.add(new InternalLink(Messages.get("manager.managers"), routes.ContestController.jumpToManagers(contest.getId()))); internalLinkBuilder.add(new InternalLink(Messages.get("file.files"), routes.ContestController.jumpToFiles(contest.getId()))); } content.appendLayout(c -> contestTimeLayout.render(contest.getStartTime(), contestEndTime, c)); content.appendLayout(c -> tabLayout.render(internalLinkBuilder.build(), c)); if (isAllowedToManageContest(contest)) { content.appendLayout(c -> headingWithActionLayout.render(contest.getName(), new InternalLink(Messages.get("contest.update"), routes.ContestController.updateContestGeneralConfig(contest.getId())), c)); } else { content.appendLayout(c -> headingLayout.render(contest.getName(), c)); } } ImmutableList.Builder<InternalLink> getContestBreadcrumbsBuilder(Contest contest) { ImmutableList.Builder<InternalLink> internalLinks = ImmutableList.builder(); internalLinks .add(new InternalLink(Messages.get("contest.contests"), routes.ContestController.index())) .add(new InternalLink(contest.getName(), routes.ContestController.viewContest(contest.getId()))); return internalLinks; } }