Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement contest-dump admin task #661

Merged
merged 1 commit into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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