package org.iatoki.judgels.uriel.services.impls; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import org.iatoki.judgels.FileSystemProvider; import org.iatoki.judgels.play.IdentityUtils; import org.iatoki.judgels.play.JudgelsPlayUtils; import org.iatoki.judgels.play.Page; import org.iatoki.judgels.uriel.ContestTeam; import org.iatoki.judgels.uriel.ContestTeamCoach; import org.iatoki.judgels.uriel.ContestTeamCoachNotFoundException; import org.iatoki.judgels.uriel.ContestTeamMember; import org.iatoki.judgels.uriel.ContestTeamMemberNotFoundException; import org.iatoki.judgels.uriel.ContestTeamNotFoundException; import org.iatoki.judgels.uriel.UrielProperties; import org.iatoki.judgels.uriel.config.TeamAvatarFile; import org.iatoki.judgels.uriel.models.daos.ContestContestantDao; import org.iatoki.judgels.uriel.models.daos.ContestDao; import org.iatoki.judgels.uriel.models.daos.ContestTeamCoachDao; import org.iatoki.judgels.uriel.models.daos.ContestTeamDao; import org.iatoki.judgels.uriel.models.daos.ContestTeamMemberDao; import org.iatoki.judgels.uriel.models.entities.ContestContestantModel; import org.iatoki.judgels.uriel.models.entities.ContestModel; import org.iatoki.judgels.uriel.models.entities.ContestTeamCoachModel; import org.iatoki.judgels.uriel.models.entities.ContestTeamCoachModel_; import org.iatoki.judgels.uriel.models.entities.ContestTeamMemberModel; import org.iatoki.judgels.uriel.models.entities.ContestTeamModel; import org.iatoki.judgels.uriel.models.entities.ContestTeamModel_; import org.iatoki.judgels.uriel.services.ContestTeamService; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import javax.persistence.metamodel.SingularAttribute; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.Date; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.stream.Collectors; @Singleton @Named("contestTeamService") public final class ContestTeamServiceImpl implements ContestTeamService { private final ContestDao contestDao; private final ContestContestantDao contestContestantDao; private final ContestTeamDao contestTeamDao; private final ContestTeamCoachDao contestTeamCoachDao; private final ContestTeamMemberDao contestTeamMemberDao; private final FileSystemProvider teamAvatarFileSystemProvider; @Inject public ContestTeamServiceImpl(ContestDao contestDao, ContestContestantDao contestContestantDao, ContestTeamDao contestTeamDao, ContestTeamCoachDao contestTeamCoachDao, ContestTeamMemberDao contestTeamMemberDao, @TeamAvatarFile FileSystemProvider teamAvatarFileSystemProvider) { this.contestDao = contestDao; this.contestContestantDao = contestContestantDao; this.contestTeamDao = contestTeamDao; this.contestTeamCoachDao = contestTeamCoachDao; this.contestTeamMemberDao = contestTeamMemberDao; this.teamAvatarFileSystemProvider = teamAvatarFileSystemProvider; if (!teamAvatarFileSystemProvider.fileExists(ImmutableList.of("team-default.png"))) { try { teamAvatarFileSystemProvider.uploadFileFromStream(ImmutableList.of(), getClass().getResourceAsStream("/public/images/team/team-default.png"), "team-default.png"); teamAvatarFileSystemProvider.makeFilePublic(ImmutableList.of("team-default.png")); } catch (IOException e) { throw new IllegalStateException("Cannot create default avatar."); } } } @Override public boolean isUserInAnyTeamByContestJid(String contestJid, String userJid) { List<String> teamJids = contestTeamDao.findTeamJidsByContestJid(contestJid); return ((contestTeamCoachDao.isUserRegisteredAsCoachInTeams(userJid, teamJids)) || (contestTeamMemberDao.isUserRegisteredAsMemberInAnyTeam(userJid, teamJids))); } @Override public boolean isUserCoachInAnyTeamByContestJid(String contestJid, String coachJid) { List<String> teamJids = contestTeamDao.findTeamJidsByContestJid(contestJid); return (contestTeamCoachDao.isUserRegisteredAsCoachInTeams(coachJid, teamJids)); } @Override public boolean isUserCoachByUserJidAndTeamJid(String userJid, String teamJid) { return contestTeamCoachDao.isUserCoachByUserJidAndTeamJid(userJid, teamJid); } @Override public ContestTeam findContestTeamByContestTeamId(long contestTeamId) throws ContestTeamNotFoundException { ContestTeamModel contestTeamModel = contestTeamDao.findById(contestTeamId); if (contestTeamModel != null) { List<ContestTeamCoachModel> contestTeamCoachesModel = contestTeamCoachDao.findContestTeamCoachesByTeamJid(contestTeamModel.jid); List<ContestTeamMemberModel> contestTeamMemberModels = contestTeamMemberDao.findContestTeamMembersInTeam(contestTeamModel.jid); return createContestTeamFromModel(contestTeamModel, contestTeamCoachesModel, contestTeamMemberModels); } else { throw new ContestTeamNotFoundException("Contest Team not found"); } } @Override public ContestTeamCoach findContestTeamCoachByContestTeamCoachId(long contestTeamCoachId) throws ContestTeamCoachNotFoundException { ContestTeamCoachModel contestTeamCoachModel = contestTeamCoachDao.findById(contestTeamCoachId); if (contestTeamCoachModel != null) { return createContestTeamCoachFromModel(contestTeamCoachModel); } else { throw new ContestTeamCoachNotFoundException("Contest Team Coach not found."); } } @Override public ContestTeamMember findContestTeamMemberByContestTeamMemberId(long contestTeamMemberId) throws ContestTeamMemberNotFoundException { ContestTeamMemberModel contestTeamMemberModel = contestTeamMemberDao.findById(contestTeamMemberId); if (contestTeamMemberModel != null) { return createContestTeamMemberFromModel(contestTeamMemberModel); } else { throw new ContestTeamMemberNotFoundException("Contest Team Member not found."); } } @Override public Page<ContestTeam> pageContestTeamsByContestJid(String contestJid, long pageIndex, long pageSize, String orderBy, String orderDir, String filterString) { long totalPages = contestTeamDao.countByFilters(filterString, ImmutableMap.of(ContestTeamModel_.contestJid, contestJid), ImmutableMap.of()); List<ContestTeamModel> contestTeamModels = contestTeamDao.findSortedByFilters(orderBy, orderDir, filterString, ImmutableMap.of(ContestTeamModel_.contestJid, contestJid), ImmutableMap.of(), pageIndex * pageSize, pageSize); ImmutableList.Builder<ContestTeam> contestTeamBuilder = ImmutableList.builder(); for (ContestTeamModel contestTeamModel : contestTeamModels) { List<ContestTeamCoachModel> contestTeamCoachesModel = contestTeamCoachDao.findContestTeamCoachesByTeamJid(contestTeamModel.jid); List<ContestTeamMemberModel> contestTeamMemberModels = contestTeamMemberDao.findContestTeamMembersInTeam(contestTeamModel.jid); contestTeamBuilder.add(createContestTeamFromModel(contestTeamModel, contestTeamCoachesModel, contestTeamMemberModels)); } return new Page<>(contestTeamBuilder.build(), totalPages, pageIndex, pageSize); } @Override public Page<ContestTeam> pageContestTeamsByContestJidAndCoachJid(String contestJid, String coachJid, long pageIndex, long pageSize, String orderBy, String orderDir) { List<String> teamJidsInContest = contestTeamDao.findTeamJidsByContestJid(contestJid); Map<SingularAttribute<? super ContestTeamCoachModel, String>, String> filterColumns = ImmutableMap.of(ContestTeamCoachModel_.coachJid, coachJid); Map<SingularAttribute<? super ContestTeamCoachModel, String>, List<String>> filterColumnsIn = ImmutableMap.of(ContestTeamCoachModel_.teamJid, teamJidsInContest); long totalRows = contestTeamCoachDao.countByFilters("", filterColumns, filterColumnsIn); List<ContestTeamCoachModel> contestTeamCoachModels = contestTeamCoachDao.findSortedByFilters(orderBy, orderDir, "", filterColumns, filterColumnsIn, pageIndex * pageSize, pageSize); List<String> teamJids = Lists.transform(contestTeamCoachModels, m -> m.teamJid); List<ContestTeamModel> contestTeamModels = contestTeamDao.findByJids(teamJids); ImmutableList.Builder<ContestTeam> contestTeamBuilder = ImmutableList.builder(); for (ContestTeamModel contestTeamModel : contestTeamModels) { List<ContestTeamCoachModel> contestTeamCoachesModel = contestTeamCoachDao.findContestTeamCoachesByTeamJid(contestTeamModel.jid); List<ContestTeamMemberModel> contestTeamMemberModels = contestTeamMemberDao.findContestTeamMembersInTeam(contestTeamModel.jid); contestTeamBuilder.add(createContestTeamFromModel(contestTeamModel, contestTeamCoachesModel, contestTeamMemberModels)); } return new Page<>(contestTeamBuilder.build(), totalRows, pageIndex, pageSize); } @Override public List<ContestTeam> findAllContestTeams(String contestJid) { List<ContestTeamModel> contestTeamModels = contestTeamDao.findSortedByFilters("id", "asc", "", ImmutableMap.of(ContestTeamModel_.contestJid, contestJid), ImmutableMap.of(), 0, -1); ImmutableList.Builder<ContestTeam> contestTeamBuilder = ImmutableList.builder(); for (ContestTeamModel contestTeamModel : contestTeamModels) { List<ContestTeamCoachModel> contestTeamCoachesModel = contestTeamCoachDao.findContestTeamCoachesByTeamJid(contestTeamModel.jid); List<ContestTeamMemberModel> contestTeamMemberModels = contestTeamMemberDao.findContestTeamMembersInTeam(contestTeamModel.jid); contestTeamBuilder.add(createContestTeamFromModel(contestTeamModel, contestTeamCoachesModel, contestTeamMemberModels)); } return contestTeamBuilder.build(); } @Override public List<ContestTeam> findContestTeamsByContestJidAndCoachJid(String contestJid, String coachJid) { List<String> teamJidsInContest = contestTeamDao.findTeamJidsByContestJid(contestJid); List<ContestTeamCoachModel> coaches = contestTeamCoachDao.findContestTeamCoachesByCoachJidInTeams(coachJid, teamJidsInContest); List<ContestTeamModel> teamModels = contestTeamDao.findByJids(Lists.transform(coaches, m -> m.teamJid)); ImmutableList.Builder<ContestTeam> teams = ImmutableList.builder(); for (ContestTeamModel teamModel : teamModels) { List<ContestTeamCoachModel> contestTeamCoachesModel = contestTeamCoachDao.findContestTeamCoachesByTeamJid(teamModel.jid); List<ContestTeamMemberModel> contestTeamMemberModels = contestTeamMemberDao.findContestTeamMembersInTeam(teamModel.jid); teams.add(createContestTeamFromModel(teamModel, contestTeamCoachesModel, contestTeamMemberModels)); } return teams.build(); } @Override public List<ContestTeamCoach> findContestTeamCoachesByTeamJid(String contestTeamJid) { List<ContestTeamCoachModel> contestTeamCoachModels = contestTeamCoachDao.findContestTeamCoachesByTeamJid(contestTeamJid); return Lists.transform(contestTeamCoachModels, m -> createContestTeamCoachFromModel(m)); } @Override public List<ContestTeamMember> findContestTeamMembersByContestJidAndCoachJid(String contestJid, String coachJid) { List<String> teamJids = contestTeamDao.findTeamJidsByContestJid(contestJid); List<ContestTeamCoachModel> contestTeamCoachModels = contestTeamCoachDao.findContestTeamCoachesByCoachJidInTeams(coachJid, teamJids); List<ContestTeamModel> contestTeamModels = contestTeamDao.findByJids(Lists.transform(contestTeamCoachModels, m -> m.teamJid)); List<ContestTeamMemberModel> contestTeamMemberModels = contestTeamMemberDao.findContestTeamMembersInTeams(Lists.transform(contestTeamModels, m -> m.jid)); return Lists.transform(contestTeamMemberModels, m -> createContestTeamMemberFromModel(m)); } @Override public List<ContestTeamMember> findContestTeamMembersByTeamJid(String contestTeamJid) { List<ContestTeamMemberModel> contestTeamMemberModels = contestTeamMemberDao.findContestTeamMembersInTeam(contestTeamJid); return Lists.transform(contestTeamMemberModels, m -> createContestTeamMemberFromModel(m)); } @Override public String getTeamAvatarImageURL(String imageName) { return teamAvatarFileSystemProvider.getURL(ImmutableList.of(imageName)); } @Override public void createContestTeam(long contestId, String name) { ContestModel contestModel = contestDao.findById(contestId); ContestTeamModel contestTeamModel = new ContestTeamModel(); contestTeamModel.contestJid = contestModel.jid; contestTeamModel.name = name; contestTeamModel.teamImageName = "team-default.png"; contestTeamDao.persist(contestTeamModel, IdentityUtils.getUserJid(), IdentityUtils.getIpAddress()); } @Override public void createContestTeam(long contestId, String name, File teamImage, String extension) throws IOException { ContestModel contestModel = contestDao.findById(contestId); ContestTeamModel contestTeamModel = new ContestTeamModel(); contestTeamModel.contestJid = contestModel.jid; contestTeamModel.name = name; contestTeamModel.teamImageName = "team-default.png"; contestTeamDao.persist(contestTeamModel, IdentityUtils.getUserJid(), IdentityUtils.getIpAddress()); String newImageName = contestTeamModel.jid + "-" + JudgelsPlayUtils.hashMD5(UUID.randomUUID().toString()) + "." + extension; teamAvatarFileSystemProvider.uploadFile(ImmutableList.of(), teamImage, newImageName); teamAvatarFileSystemProvider.makeFilePublic(ImmutableList.of(newImageName)); contestTeamModel.teamImageName = newImageName; contestTeamDao.edit(contestTeamModel, IdentityUtils.getUserJid(), IdentityUtils.getIpAddress()); } @Override public void updateContestTeam(long contestTeamId, String name) { ContestTeamModel contestTeamModel = contestTeamDao.findById(contestTeamId); contestTeamModel.name = name; contestTeamDao.edit(contestTeamModel, IdentityUtils.getUserJid(), IdentityUtils.getIpAddress()); } @Override public void updateContestTeam(long contestTeamId, String name, File teamImage, String extension) throws IOException { ContestTeamModel contestTeamModel = contestTeamDao.findById(contestTeamId); String newImageName = contestTeamModel.jid + "-" + JudgelsPlayUtils.hashMD5(UUID.randomUUID().toString()) + "." + extension; teamAvatarFileSystemProvider.uploadFile(ImmutableList.of(), teamImage, newImageName); teamAvatarFileSystemProvider.makeFilePublic(ImmutableList.of(newImageName)); contestTeamModel.name = name; contestTeamModel.teamImageName = newImageName; contestTeamDao.edit(contestTeamModel, IdentityUtils.getUserJid(), IdentityUtils.getIpAddress()); } @Override public void createContestTeamCoach(String contestTeamJid, String coachJid) { ContestTeamCoachModel contestTeamCoachModel = new ContestTeamCoachModel(); contestTeamCoachModel.teamJid = contestTeamJid; contestTeamCoachModel.coachJid = coachJid; contestTeamCoachDao.persist(contestTeamCoachModel, IdentityUtils.getUserJid(), IdentityUtils.getIpAddress()); } @Override public void removeContestTeamCoachByContestTeamCoachId(long contestTeamCoachId) { ContestTeamCoachModel contestTeamCoachModel = contestTeamCoachDao.findById(contestTeamCoachId); contestTeamCoachDao.remove(contestTeamCoachModel); } @Override public void createContestTeamMember(String contestTeamJid, String memberJid) { ContestTeamMemberModel contestTeamMemberModel = new ContestTeamMemberModel(); contestTeamMemberModel.teamJid = contestTeamJid; contestTeamMemberModel.memberJid = memberJid; contestTeamMemberDao.persist(contestTeamMemberModel, IdentityUtils.getUserJid(), IdentityUtils.getIpAddress()); } @Override public void removeContestTeamMemberByContestTeamMemberId(long contestTeamMemberId) { ContestTeamMemberModel contestTeamMemberModel = contestTeamMemberDao.findById(contestTeamMemberId); contestTeamMemberDao.remove(contestTeamMemberModel); } @Override public void startTeamAsCoach(String contestJid, String teamJid) { long now = System.currentTimeMillis(); ContestTeamModel contestTeamModel = contestTeamDao.findByJid(teamJid); contestTeamModel.contestStartTime = now; contestTeamDao.edit(contestTeamModel, IdentityUtils.getUserJid(), IdentityUtils.getIpAddress()); List<ContestTeamMemberModel> contestTeamMemberModels = contestTeamMemberDao.findContestTeamMembersInTeam(teamJid); for (ContestTeamMemberModel contestTeamMemberModel : contestTeamMemberModels) { ContestContestantModel contestContestantModel = contestContestantDao.findByContestJidAndContestantJid(contestJid, contestTeamMemberModel.memberJid); contestContestantModel.contestStartTime = now; contestContestantDao.edit(contestContestantModel, IdentityUtils.getUserJid(), IdentityUtils.getIpAddress()); } } private ContestTeam createContestTeamFromModel(ContestTeamModel contestTeamModel, List<ContestTeamCoachModel> contestTeamCoachModels, List<ContestTeamMemberModel> contestTeamMemberModels) { return new ContestTeam(contestTeamModel.id, contestTeamModel.jid, contestTeamModel.contestJid, contestTeamModel.name, getTeamImageURLFromImageName(contestTeamModel.teamImageName), new Date(contestTeamModel.contestStartTime), contestTeamCoachModels.stream().map(ctc -> createContestTeamCoachFromModel(ctc)).collect(Collectors.toList()), contestTeamMemberModels.stream().map(ctm -> createContestTeamMemberFromModel(ctm)).collect(Collectors.toList())); } private ContestTeamCoach createContestTeamCoachFromModel(ContestTeamCoachModel contestTeamCoachModel) { return new ContestTeamCoach(contestTeamCoachModel.id, contestTeamCoachModel.teamJid, contestTeamCoachModel.coachJid); } private ContestTeamMember createContestTeamMemberFromModel(ContestTeamMemberModel contestTeamMemberModel) { return new ContestTeamMember(contestTeamMemberModel.id, contestTeamMemberModel.teamJid, contestTeamMemberModel.memberJid); } private URL getTeamImageURLFromImageName(String imageName) { try { return new URL(UrielProperties.getInstance().getUrielBaseUrl() + org.iatoki.judgels.uriel.controllers.apis.routes.ContestAPIController.renderTeamAvatarImage(imageName)); } catch (MalformedURLException e) { throw new RuntimeException(e); } } }