diff --git a/internal/tester/delivery/rest/handlers.go b/internal/tester/delivery/rest/handlers.go index fc7fdf5..16dfeb1 100644 --- a/internal/tester/delivery/rest/handlers.go +++ b/internal/tester/delivery/rest/handlers.go @@ -99,6 +99,15 @@ func (h *TesterHandlers) GetContest(c *fiber.Ctx, id int32) error { return c.SendStatus(pkg.ToREST(err)) } + var participantId int32 = 2 + + solutions, err := h.contestsUC.ReadBestSolutions(c.Context(), id, participantId) + + m := make(map[int32]*models.Solution) + + for i := 0; i < len(solutions); i++ { + m[solutions[i].TaskPosition] = solutions[i] + } resp := testerv1.GetContestResponse{ Contest: C2C(*contest), Tasks: make([]struct { @@ -108,11 +117,15 @@ func (h *TesterHandlers) GetContest(c *fiber.Ctx, id int32) error { } for i, task := range tasks { + solution := testerv1.Solution{} + if sol, ok := m[task.Position]; ok { + solution = S2S(*sol) + } resp.Tasks[i] = struct { Solution testerv1.Solution `json:"solution"` Task testerv1.TasksListItem `json:"task"` }{ - Solution: testerv1.Solution{}, + Solution: solution, Task: TLI2TLI(*task), } } diff --git a/internal/tester/pg_repository.go b/internal/tester/pg_repository.go index 81883ca..78b29cf 100644 --- a/internal/tester/pg_repository.go +++ b/internal/tester/pg_repository.go @@ -49,4 +49,5 @@ type ContestRepository interface { ListSolutions(ctx context.Context, filter models.SolutionsFilter) (*models.SolutionsList, error) ReadTask(ctx context.Context, id int32) (*models.Task, error) ReadMonitor(ctx context.Context, id int32) (*models.Monitor, error) + ReadBestSolutions(ctx context.Context, contestId int32, participantId int32) ([]*models.Solution, error) } diff --git a/internal/tester/repository/pg_contests_repository.go b/internal/tester/repository/pg_contests_repository.go index ec73a08..94c34e2 100644 --- a/internal/tester/repository/pg_contests_repository.go +++ b/internal/tester/repository/pg_contests_repository.go @@ -626,3 +626,65 @@ func (r *ContestRepository) ReadMonitor(ctx context.Context, contestId int32) (* return &monitor, nil } + +const ( + // state=5 - AC + readBestSolutions = ` + WITH contest_tasks AS ( + SELECT t.id AS task_id, + t.position AS task_position, + t.contest_id, + t.problem_id, + t.created_at, + t.updated_at, + p.title AS task_title, + c.title AS contest_title + FROM tasks t + LEFT JOIN problems p ON p.id = t.problem_id + LEFT JOIN contests c ON c.id = t.contest_id + WHERE t.contest_id = ? +), + best_solutions AS ( + SELECT DISTINCT ON (s.task_id) + * + FROM solutions s + WHERE s.participant_id = ? + ORDER BY s.task_id, s.score DESC, s.created_at DESC + ) +SELECT + s.id, + s.participant_id, + p.name AS participant_name, + s.solution, + s.state, + s.score, + s.penalty, + s.time_stat, + s.memory_stat, + s.language, + ct.task_id, + ct.task_position, + ct.task_title, + ct.contest_id, + ct.contest_title, + s.updated_at, + s.created_at +FROM contest_tasks ct + LEFT JOIN best_solutions s ON s.task_id = ct.task_id + LEFT JOIN participants p ON p.id = s.participant_id WHERE s.id IS NOT NULL +ORDER BY ct.task_position +` +) + +func (r *ContestRepository) ReadBestSolutions(ctx context.Context, contestId int32, participantId int32) ([]*models.Solution, error) { + const op = "ContestRepository.ReadBestSolutions" + var solutions []*models.Solution + query := r.db.Rebind(readBestSolutions) + err := r.db.SelectContext(ctx, &solutions, query, contestId, participantId) + + if err != nil { + return nil, handlePgErr(err, op) + } + + return solutions, nil +} diff --git a/internal/tester/usecase.go b/internal/tester/usecase.go index 9ddf235..a473dca 100644 --- a/internal/tester/usecase.go +++ b/internal/tester/usecase.go @@ -31,4 +31,5 @@ type ContestUseCase interface { ListSolutions(ctx context.Context, filter models.SolutionsFilter) (*models.SolutionsList, error) ReadTask(ctx context.Context, id int32) (*models.Task, error) ReadMonitor(ctx context.Context, id int32) (*models.Monitor, error) + ReadBestSolutions(ctx context.Context, contestId int32, participantId int32) ([]*models.Solution, error) } diff --git a/internal/tester/usecase/contests_usecase.go b/internal/tester/usecase/contests_usecase.go index 414c9a2..28761dd 100644 --- a/internal/tester/usecase/contests_usecase.go +++ b/internal/tester/usecase/contests_usecase.go @@ -85,3 +85,7 @@ func (uc *ContestUseCase) ReadTask(ctx context.Context, id int32) (*models.Task, func (uc *ContestUseCase) ReadMonitor(ctx context.Context, contestId int32) (*models.Monitor, error) { return uc.contestRepo.ReadMonitor(ctx, contestId) } + +func (uc *ContestUseCase) ReadBestSolutions(ctx context.Context, contestId int32, participantId int32) ([]*models.Solution, error) { + return uc.contestRepo.ReadBestSolutions(ctx, contestId, participantId) +}