diff --git a/internal/models/participant.go b/internal/models/participant.go index 6ed0c83..a5e8fb3 100644 --- a/internal/models/participant.go +++ b/internal/models/participant.go @@ -1,10 +1,21 @@ package models -//type Participant struct { -// Id *int32 `db:"id"` -// UserId *int32 `db:"user_id"` -// ContestId *int32 `db:"contest_id"` -// Name *string `db:"name"` -// CreatedAt *time.Time `db:"created_at"` -// UpdatedAt *time.Time `db:"updated_at"` -//} +import "time" + +type Participant struct { + Id int32 `db:"id"` + UserId int32 `db:"user_id"` + ContestId int32 `db:"contest_id"` + Name string `db:"name"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` +} + +type ParticipantsListItem struct { + Id int32 `db:"id"` + UserId int32 `db:"user_id"` + ContestId int32 `db:"contest_id"` + Name string `db:"name"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` +} diff --git a/internal/tester/delivery.go b/internal/tester/delivery.go index 1764f57..15266da 100644 --- a/internal/tester/delivery.go +++ b/internal/tester/delivery.go @@ -10,12 +10,13 @@ type Handlers interface { CreateContest(c *fiber.Ctx) error DeleteContest(c *fiber.Ctx, id int32) error GetContest(c *fiber.Ctx, id int32) error - DeleteParticipant(c *fiber.Ctx, id int32, params testerv1.DeleteParticipantParams) error - AddParticipant(c *fiber.Ctx, id int32, params testerv1.AddParticipantParams) error - DeleteTask(c *fiber.Ctx, id int32, params testerv1.DeleteTaskParams) error - AddTask(c *fiber.Ctx, id int32, params testerv1.AddTaskParams) error + DeleteParticipant(c *fiber.Ctx, params testerv1.DeleteParticipantParams) error + AddParticipant(c *fiber.Ctx, params testerv1.AddParticipantParams) error + DeleteTask(c *fiber.Ctx, params testerv1.DeleteTaskParams) error + AddTask(c *fiber.Ctx, params testerv1.AddTaskParams) error ListProblems(c *fiber.Ctx, params testerv1.ListProblemsParams) error CreateProblem(c *fiber.Ctx) error DeleteProblem(c *fiber.Ctx, id int32) error GetProblem(c *fiber.Ctx, id int32) error + ListParticipants(c *fiber.Ctx, params testerv1.ListParticipantsParams) error } diff --git a/internal/tester/delivery/rest/handlers.go b/internal/tester/delivery/rest/handlers.go index 0ef381c..208059a 100644 --- a/internal/tester/delivery/rest/handlers.go +++ b/internal/tester/delivery/rest/handlers.go @@ -150,7 +150,7 @@ func (h *TesterHandlers) GetContest(c *fiber.Ctx, id int32) error { return c.JSON(resp) } -func (h *TesterHandlers) DeleteParticipant(c *fiber.Ctx, id int32, params testerv1.DeleteParticipantParams) error { +func (h *TesterHandlers) DeleteParticipant(c *fiber.Ctx, params testerv1.DeleteParticipantParams) error { err := h.contestsUC.DeleteParticipant(c.Context(), params.ParticipantId) if err != nil { return c.SendStatus(pkg.ToREST(err)) @@ -159,8 +159,8 @@ func (h *TesterHandlers) DeleteParticipant(c *fiber.Ctx, id int32, params tester return c.SendStatus(fiber.StatusOK) } -func (h *TesterHandlers) AddParticipant(c *fiber.Ctx, id int32, params testerv1.AddParticipantParams) error { - id, err := h.contestsUC.AddParticipant(c.Context(), id, params.UserId) +func (h *TesterHandlers) AddParticipant(c *fiber.Ctx, params testerv1.AddParticipantParams) error { + id, err := h.contestsUC.AddParticipant(c.Context(), params.ContestId, params.UserId) if err != nil { return c.SendStatus(pkg.ToREST(err)) } @@ -170,7 +170,7 @@ func (h *TesterHandlers) AddParticipant(c *fiber.Ctx, id int32, params testerv1. }) } -func (h *TesterHandlers) DeleteTask(c *fiber.Ctx, id int32, params testerv1.DeleteTaskParams) error { +func (h *TesterHandlers) DeleteTask(c *fiber.Ctx, params testerv1.DeleteTaskParams) error { err := h.contestsUC.DeleteTask(c.Context(), params.TaskId) if err != nil { return c.SendStatus(pkg.ToREST(err)) @@ -179,13 +179,15 @@ func (h *TesterHandlers) DeleteTask(c *fiber.Ctx, id int32, params testerv1.Dele return c.SendStatus(fiber.StatusOK) } -func (h *TesterHandlers) AddTask(c *fiber.Ctx, id int32, params testerv1.AddTaskParams) error { - id, err := h.contestsUC.AddTask(c.Context(), id, params.ProblemId) +func (h *TesterHandlers) AddTask(c *fiber.Ctx, params testerv1.AddTaskParams) error { + id, err := h.contestsUC.AddTask(c.Context(), params.ContestId, params.ProblemId) if err != nil { return c.SendStatus(pkg.ToREST(err)) } - return c.SendStatus(fiber.StatusNotImplemented) + return c.JSON(testerv1.AddTaskResponse{ + Id: id, + }) } func (h *TesterHandlers) CreateProblem(c *fiber.Ctx) error { @@ -231,3 +233,33 @@ func (h *TesterHandlers) GetProblem(c *fiber.Ctx, id int32) error { }}, ) } + +func (h *TesterHandlers) ListParticipants(c *fiber.Ctx, params testerv1.ListParticipantsParams) error { + participants, count, err := h.contestsUC.ListParticipants(c.Context(), params.ContestId, params.Page, params.PageSize) + if err != nil { + return c.SendStatus(pkg.ToREST(err)) + } + + resp := testerv1.ListParticipantsResponse{ + Participants: make([]testerv1.ParticipantsListItem, len(participants)), + Page: params.Page, + MaxPage: func() int32 { + if count%params.PageSize == 0 { + return count / params.PageSize + } + return count/params.PageSize + 1 + }(), + } + + for i, participant := range participants { + resp.Participants[i] = testerv1.ParticipantsListItem{ + Id: participant.Id, + UserId: participant.UserId, + Name: participant.Name, + CreatedAt: participant.CreatedAt, + UpdatedAt: participant.UpdatedAt, + } + } + + return c.JSON(resp) +} diff --git a/internal/tester/pg_repository.go b/internal/tester/pg_repository.go index 0d610c4..1718f85 100644 --- a/internal/tester/pg_repository.go +++ b/internal/tester/pg_repository.go @@ -22,4 +22,5 @@ type ContestRepository interface { DeleteParticipant(ctx context.Context, participantId int32) error ReadRichTasks(ctx context.Context, contestId int32) ([]*models.RichTask, error) ListContests(ctx context.Context, page int32, pageSize int32) ([]*models.ContestsListItem, int32, error) + ListParticipants(ctx context.Context, contestId int32, page int32, pageSize int32) ([]*models.ParticipantsListItem, int32, error) } diff --git a/internal/tester/repository/pg_contests_repository.go b/internal/tester/repository/pg_contests_repository.go index 4325866..b774955 100644 --- a/internal/tester/repository/pg_contests_repository.go +++ b/internal/tester/repository/pg_contests_repository.go @@ -174,11 +174,41 @@ func (r *ContestRepository) ListContests(ctx context.Context, page int32, pageSi return nil, 0, handlePgErr(err, op) } + query = r.db.Rebind(countContestsQuery) var count int32 - err = r.db.GetContext(ctx, &count, countContestsQuery) + err = r.db.GetContext(ctx, &count, query) if err != nil { return nil, 0, handlePgErr(err, op) } return tasks, count, nil } + +const ( + readParticipantsListQuery = `SELECT id, user_id, name, created_at, updated_at FROM participants WHERE contest_id = ? LIMIT ? OFFSET ?` + countParticipantsQuery = "SELECT COUNT(*) FROM participants WHERE contest_id = ?" +) + +func (r *ContestRepository) ListParticipants(ctx context.Context, contestId int32, page int32, pageSize int32) ([]*models.ParticipantsListItem, int32, error) { + const op = "ContestRepository.ReadParticipants" + + if pageSize > 20 { + pageSize = 1 + } + + var participants []*models.ParticipantsListItem + query := r.db.Rebind(readParticipantsListQuery) + err := r.db.SelectContext(ctx, &participants, query, contestId, pageSize, (page-1)*pageSize) + if err != nil { + return nil, 0, handlePgErr(err, op) + } + + query = r.db.Rebind(countParticipantsQuery) + var count int32 + err = r.db.GetContext(ctx, &count, query, contestId) + if err != nil { + return nil, 0, handlePgErr(err, op) + } + + return participants, count, nil +} diff --git a/internal/tester/repository/pg_problems_repository.go b/internal/tester/repository/pg_problems_repository.go index 4108746..400b217 100644 --- a/internal/tester/repository/pg_problems_repository.go +++ b/internal/tester/repository/pg_problems_repository.go @@ -89,8 +89,10 @@ func (r *ProblemRepository) ListProblems(ctx context.Context, page int32, pageSi return nil, 0, handlePgErr(err, op) } + query = r.db.Rebind(CountProblemsQuery) + var count int32 - err = r.db.GetContext(ctx, &count, CountProblemsQuery) + err = r.db.GetContext(ctx, &count, query) if err != nil { return nil, 0, handlePgErr(err, op) } diff --git a/internal/tester/usecase.go b/internal/tester/usecase.go index 7db6c68..e706910 100644 --- a/internal/tester/usecase.go +++ b/internal/tester/usecase.go @@ -22,4 +22,5 @@ type ContestUseCase interface { DeleteParticipant(ctx context.Context, participantId int32) error ReadRichTasks(ctx context.Context, contestId int32) ([]*models.RichTask, error) ListContests(ctx context.Context, page int32, pageSize int32) ([]*models.ContestsListItem, int32, error) + ListParticipants(ctx context.Context, contestId int32, page int32, pageSize int32) ([]*models.ParticipantsListItem, int32, error) } diff --git a/internal/tester/usecase/contests_usecase.go b/internal/tester/usecase/contests_usecase.go index 06759e2..75c495c 100644 --- a/internal/tester/usecase/contests_usecase.go +++ b/internal/tester/usecase/contests_usecase.go @@ -53,3 +53,7 @@ func (uc *ContestUseCase) ReadRichTasks(ctx context.Context, contestId int32) ([ func (uc *ContestUseCase) ListContests(ctx context.Context, page int32, pageSize int32) ([]*models.ContestsListItem, int32, error) { return uc.contestRepo.ListContests(ctx, page, pageSize) } + +func (uc *ContestUseCase) ListParticipants(ctx context.Context, contestId int32, page int32, pageSize int32) ([]*models.ParticipantsListItem, int32, error) { + return uc.contestRepo.ListParticipants(ctx, contestId, page, pageSize) +} diff --git a/proto b/proto index ac0eb56..3913140 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit ac0eb56bb9dee9f0933f858e16d61c9e40c89a29 +Subproject commit 391314039942e437907d9d562d8973a80e290e4e