Skip to content

Commit

Permalink
Implement contest-dump admin task (#661)
Browse files Browse the repository at this point in the history
  • Loading branch information
fushar committed Sep 5, 2024
1 parent 1925c5e commit 5aaafb6
Show file tree
Hide file tree
Showing 30 changed files with 617 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ private void runUriel(JudgelsServerApplicationConfiguration config, Environment
"uriel-grading-response-poller",
component.gradingResponsePoller());
}

env.admin().addTask(component.contestDumpTask());
}

private void runJerahmeel(JudgelsServerApplicationConfiguration config, Environment env) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import io.dropwizard.hibernate.AbstractDAO;
import java.time.Clock;
import java.time.Instant;
import java.util.Collection;
import java.util.Optional;
import javax.persistence.metamodel.SingularAttribute;
Expand Down Expand Up @@ -76,4 +77,42 @@ protected static <M> CriteriaPredicate<M> columnIn(SingularAttribute<? super M,
}
return (cb, cq, root) -> root.get(column).in(values);
}

protected static String escape(String val) {
if (val == null) {
return "NULL";
}
return "'" + val
.replace("\\", "\\\\")
.replace("'", "\\'")
.replace("\"", "\\\"")
.replace("\t", "\\t")
.replace("\r", "\\r")
.replace("\n", "\\n")
+ "'";
}

protected static String escape(Integer val) {
if (val == null) {
return "NULL";
}
return "" + val;
}

protected static String escape(long val) {
return "" + val;
}

protected static String escape(boolean val) {
return "b'" + (val ? '1' : '0') + "'";
}

protected static String escape(Instant val) {
if (val == null) {
return "NULL";
}

String valString = val.toString().replace("T", " ").replace("Z", "");
return "'" + valString + "'";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -88,4 +89,32 @@ public Map<String, M> selectAllLatestWithDetailsBySubmissionJids(Collection<Stri

return ImmutableMap.copyOf(result);
}

@Override
public void dump(PrintWriter output, Collection<String> submissionJids) {
List<M> results = select().where(columnIn(AbstractProgrammingGradingModel_.submissionJid, submissionJids)).orderBy(Model_.ID, OrderDir.ASC).all();
if (results.isEmpty()) {
return;
}

output.write("INSERT IGNORE INTO uriel_contest_programming_grading (jid, submissionJid, verdictCode, verdictName, score, details, createdBy, createdAt, updatedAt) VALUES\n");

for (int i = 0; i < results.size(); i++) {
M m = results.get(i);
if (i > 0) {
output.write(",\n");
}
output.write(String.format("(%s, %s, %s, %s, %s, %s, %s, %s, %s)",
escape(m.jid),
escape(m.submissionJid),
escape(m.verdictCode),
escape(""),
escape(m.score),
escape(m.details),
escape(m.createdBy),
escape(m.createdAt),
escape(m.updatedAt)));
}
output.write(";\n");
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package judgels.sandalphon.hibernate;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.persistence.Tuple;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import judgels.persistence.JudgelsModel_;
import judgels.persistence.Model_;
import judgels.persistence.UnmodifiableModel_;
import judgels.persistence.api.OrderDir;
import judgels.persistence.hibernate.HibernateDaoData;
import judgels.persistence.hibernate.HibernateQueryBuilder;
import judgels.persistence.hibernate.JudgelsHibernateDao;
Expand Down Expand Up @@ -57,6 +62,37 @@ public Map<String, Long> selectCounts(String containerJid, String userJid, Colle
.collect(Collectors.toMap(tuple -> tuple.get(0, String.class), tuple -> tuple.get(1, Long.class)));
}

@Override
public Collection<String> dump(PrintWriter output, String containerJid) {
List<M> results = select().whereContainerIs(containerJid).orderBy(Model_.ID, OrderDir.ASC).all();
if (results.isEmpty()) {
return List.of();
}

output.write("INSERT IGNORE INTO uriel_contest_programming_submission (jid, problemJid, containerJid, gradingEngine, gradingLanguage, createdBy, createdAt, updatedBy, updatedAt) VALUES\n");

List<String> submissionJids = new ArrayList<>();
for (int i = 0; i < results.size(); i++) {
M m = results.get(i);
if (i > 0) {
output.write(",\n");
}
output.write(String.format("(%s, %s, %s, %s, %s, %s, %s, %s, %s)",
escape(m.jid),
escape(m.problemJid),
escape(m.containerJid),
escape(m.gradingEngine),
escape(m.gradingLanguage),
escape(m.createdBy),
escape(m.createdAt),
escape(m.updatedBy),
escape(m.updatedAt)));
submissionJids.add(m.jid);
}
output.write(";\n");
return submissionJids;
}

private static class AbstractProgrammingSubmissionHibernateQueryBuilder<M extends AbstractProgrammingSubmissionModel> extends HibernateQueryBuilder<M> implements BaseProgrammingSubmissionQueryBuilder<M> {
AbstractProgrammingSubmissionHibernateQueryBuilder(Session currentSession, Class<M> entityClass) {
super(currentSession, entityClass);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package judgels.sandalphon.persistence;

import java.io.PrintWriter;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
Expand All @@ -11,4 +12,5 @@ public interface BaseProgrammingGradingDao<M extends AbstractProgrammingGradingM
Optional<M> selectLatestBySubmissionJid(String submissionJid);
Map<String, M> selectAllLatestBySubmissionJids(Collection<String> submissionJids);
Map<String, M> selectAllLatestWithDetailsBySubmissionJids(Collection<String> submissionJids);
void dump(PrintWriter output, Collection<String> submissionJids);
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package judgels.sandalphon.persistence;

import java.io.PrintWriter;
import java.util.Collection;
import java.util.Map;
import judgels.persistence.JudgelsDao;
import judgels.persistence.QueryBuilder;

public interface BaseProgrammingSubmissionDao<M extends AbstractProgrammingSubmissionModel> extends JudgelsDao<M> {
M createSubmissionModel();

BaseProgrammingSubmissionQueryBuilder<M> select();
Map<String, Long> selectCounts(String containerJid, String userJid, Collection<String> problemJids);
Collection<String> dump(PrintWriter output, String containerJid);

interface BaseProgrammingSubmissionQueryBuilder<M extends AbstractProgrammingSubmissionModel> extends QueryBuilder<M> {
BaseProgrammingSubmissionQueryBuilder<M> whereContainerIs(String containerJid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import judgels.uriel.contest.announcement.ContestAnnouncementResource;
import judgels.uriel.contest.clarification.ContestClarificationResource;
import judgels.uriel.contest.contestant.ContestContestantResource;
import judgels.uriel.contest.dump.ContestDumpModule;
import judgels.uriel.contest.dump.ContestDumpTask;
import judgels.uriel.contest.editorial.ContestEditorialResource;
import judgels.uriel.contest.file.ContestFileResource;
import judgels.uriel.contest.history.ContestHistoryResource;
Expand Down Expand Up @@ -65,7 +67,9 @@
SubmissionModule.class,
ItemSubmissionModule.class,
ContestLogModule.class,
ContestScoreboardUpdaterModule.class})
ContestScoreboardUpdaterModule.class,

ContestDumpModule.class})
@Singleton
public interface UrielComponent {
ContestAnnouncementResource contestAnnouncementResource();
Expand All @@ -90,4 +94,6 @@ public interface UrielComponent {
ContestLogPoller contestLogPoller();
ContestScoreboardPoller contestScoreboardPoller();
GradingResponsePoller gradingResponsePoller();

ContestDumpTask contestDumpTask();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package judgels.uriel.contest.dump;

import dagger.Module;
import dagger.Provides;
import io.dropwizard.hibernate.UnitOfWorkAwareProxyFactory;
import javax.inject.Singleton;
import judgels.uriel.persistence.ContestAnnouncementDao;
import judgels.uriel.persistence.ContestClarificationDao;
import judgels.uriel.persistence.ContestContestantDao;
import judgels.uriel.persistence.ContestDao;
import judgels.uriel.persistence.ContestLogDao;
import judgels.uriel.persistence.ContestManagerDao;
import judgels.uriel.persistence.ContestModuleDao;
import judgels.uriel.persistence.ContestProblemDao;
import judgels.uriel.persistence.ContestProgrammingGradingDao;
import judgels.uriel.persistence.ContestProgrammingSubmissionDao;
import judgels.uriel.persistence.ContestScoreboardDao;
import judgels.uriel.persistence.ContestSupervisorDao;

@Module
public class ContestDumpModule {
private ContestDumpModule() {}

@Provides
@Singleton
static ContestDumpTask contestDumpTask(
UnitOfWorkAwareProxyFactory unitOfWorkAwareProxyFactory,
ContestDao contestDao,
ContestModuleDao moduleDao,
ContestManagerDao managerDao,
ContestSupervisorDao supervisorDao,
ContestContestantDao contestantDao,
ContestProblemDao problemDao,
ContestAnnouncementDao announcementDao,
ContestClarificationDao clarificationDao,
ContestScoreboardDao scoreboardDao,
ContestLogDao logDao,
ContestProgrammingSubmissionDao programmingSubmissionDao,
ContestProgrammingGradingDao programmingGradingDao) {

return unitOfWorkAwareProxyFactory.create(
ContestDumpTask.class,
new Class<?>[] {
ContestDao.class,
ContestModuleDao.class,
ContestManagerDao.class,
ContestSupervisorDao.class,
ContestContestantDao.class,
ContestProblemDao.class,
ContestAnnouncementDao.class,
ContestClarificationDao.class,
ContestScoreboardDao.class,
ContestLogDao.class,
ContestProgrammingSubmissionDao.class,
ContestProgrammingGradingDao.class},
new Object[] {
contestDao,
moduleDao,
managerDao,
supervisorDao,
contestantDao,
problemDao,
announcementDao,
clarificationDao,
scoreboardDao,
logDao,
programmingSubmissionDao,
programmingGradingDao});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package judgels.uriel.contest.dump;

import io.dropwizard.hibernate.UnitOfWork;
import io.dropwizard.servlets.tasks.Task;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import judgels.uriel.persistence.ContestAnnouncementDao;
import judgels.uriel.persistence.ContestClarificationDao;
import judgels.uriel.persistence.ContestContestantDao;
import judgels.uriel.persistence.ContestDao;
import judgels.uriel.persistence.ContestLogDao;
import judgels.uriel.persistence.ContestManagerDao;
import judgels.uriel.persistence.ContestModel;
import judgels.uriel.persistence.ContestModuleDao;
import judgels.uriel.persistence.ContestProblemDao;
import judgels.uriel.persistence.ContestProgrammingGradingDao;
import judgels.uriel.persistence.ContestProgrammingSubmissionDao;
import judgels.uriel.persistence.ContestScoreboardDao;
import judgels.uriel.persistence.ContestSupervisorDao;

public class ContestDumpTask extends Task {
private final ContestDao contestDao;
private final ContestModuleDao moduleDao;
private final ContestManagerDao managerDao;
private final ContestSupervisorDao supervisorDao;
private final ContestContestantDao contestantDao;
private final ContestProblemDao problemDao;
private final ContestAnnouncementDao announcementDao;
private final ContestClarificationDao clarificationDao;
private final ContestProgrammingSubmissionDao programmingSubmissionDao;
private final ContestProgrammingGradingDao programmingGradingDao;
private final ContestScoreboardDao scoreboardDao;
private final ContestLogDao logDao;

public ContestDumpTask(
ContestDao contestDao,
ContestModuleDao moduleDao,
ContestManagerDao managerDao,
ContestSupervisorDao supervisorDao,
ContestContestantDao contestantDao,
ContestProblemDao problemDao,
ContestAnnouncementDao announcementDao,
ContestClarificationDao clarificationDao,
ContestScoreboardDao scoreboardDao,
ContestLogDao logDao,
ContestProgrammingSubmissionDao programmingSubmissionDao,
ContestProgrammingGradingDao programmingGradingDao) {

super("contest-dump");

this.contestDao = contestDao;
this.moduleDao = moduleDao;
this.managerDao = managerDao;
this.supervisorDao = supervisorDao;
this.contestantDao = contestantDao;
this.problemDao = problemDao;
this.announcementDao = announcementDao;
this.clarificationDao = clarificationDao;
this.scoreboardDao = scoreboardDao;
this.logDao = logDao;
this.programmingSubmissionDao = programmingSubmissionDao;
this.programmingGradingDao = programmingGradingDao;
}

@Override
@UnitOfWork(readOnly = true)
public void execute(Map<String, List<String>> parameters, PrintWriter output) {
List<String> contestSlugs = parameters.get("contestSlug");
if (contestSlugs == null || contestSlugs.isEmpty()) {
return;
}
String contestSlug = contestSlugs.get(0);
Optional<ContestModel> maybeModel = contestDao.selectBySlug(contestSlug);
if (maybeModel.isEmpty()) {
return;
}

String contestJid = maybeModel.get().jid;

contestDao.dump(output, contestJid);
moduleDao.dump(output, contestJid);
managerDao.dump(output, contestJid);
supervisorDao.dump(output, contestJid);
contestantDao.dump(output, contestJid);
problemDao.dump(output, contestJid);
announcementDao.dump(output, contestJid);
clarificationDao.dump(output, contestJid);
scoreboardDao.dump(output, contestJid);
logDao.dump(output, contestJid);

Collection<String> submissionJids = programmingSubmissionDao.dump(output, contestJid);
programmingGradingDao.dump(output, submissionJids);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ private static ContestLog fromModel(ContestLogModel model) {
.problemJid(Optional.ofNullable(model.problemJid))
.userJid(model.createdBy)
.time(model.createdAt)
.ipAddress(model.createdIp)
.ipAddress(Optional.ofNullable(model.createdIp))
.build();
}
}
Loading

0 comments on commit 5aaafb6

Please sign in to comment.