add questions

This commit is contained in:
2026-09-01 01:01:37 +07:00
parent 4431a4d491
commit 69666ee264
23 changed files with 4151 additions and 368 deletions
+11
View File
@@ -0,0 +1,11 @@
package repos
// TeamAnswer — ответ команды на вопрос дела (вопросы живут в сценарии,
// ответы — в таблице team_answers).
type TeamAnswer struct {
TeamId int
QuestionCode string
Text string
// Score — балл, выставленный организатором; nil — ещё не оценено.
Score *int
}
+163
View File
@@ -0,0 +1,163 @@
package team_answers_repo
import (
"context"
"errors"
"evening_detective_server/internal/repos"
"github.com/jackc/pgx/v5/pgxpool"
)
var (
ErrAnswerNotFound = errors.New("Ответ не найден")
)
type TeamAnswersRepo struct {
pool *pgxpool.Pool
}
func NewTeamAnswersRepo(pool *pgxpool.Pool) *TeamAnswersRepo {
return &TeamAnswersRepo{
pool: pool,
}
}
// UpsertAnswers сохраняет ответы команды: существующие перезаписываются,
// отсутствующие — вставляются (UNIQUE (team_id, question_code)).
func (r *TeamAnswersRepo) UpsertAnswers(
ctx context.Context,
teamId int,
answers []repos.TeamAnswer,
) error {
for _, answer := range answers {
_, err := r.pool.Exec(
ctx,
`INSERT INTO team_answers (team_id, question_code, answer)
VALUES ($1, $2, $3)
ON CONFLICT (team_id, question_code)
DO UPDATE SET
answer = EXCLUDED.answer,
updated_at = NOW()`,
teamId,
answer.QuestionCode,
answer.Text,
)
if err != nil {
return err
}
}
return nil
}
func (r *TeamAnswersRepo) GetAnswersByTeamID(
ctx context.Context,
teamId int,
) ([]*repos.TeamAnswer, error) {
rows, err := r.pool.Query(
ctx,
`SELECT
team_id,
question_code,
answer,
score
FROM team_answers
WHERE team_id = $1
ORDER BY question_code ASC`,
teamId,
)
if err != nil {
return nil, err
}
defer rows.Close()
var answers []*repos.TeamAnswer
for rows.Next() {
answer := &repos.TeamAnswer{}
err := rows.Scan(
&answer.TeamId,
&answer.QuestionCode,
&answer.Text,
&answer.Score,
)
if err != nil {
return nil, err
}
answers = append(answers, answer)
}
if err := rows.Err(); err != nil {
return nil, err
}
return answers, nil
}
// GetAnswersByGameID возвращает ответы всех команд игры (вместе с баллами).
func (r *TeamAnswersRepo) GetAnswersByGameID(
ctx context.Context,
gameId int,
) ([]*repos.TeamAnswer, error) {
rows, err := r.pool.Query(
ctx,
`SELECT
teams.id,
team_answers.question_code,
team_answers.answer,
team_answers.score
FROM team_answers
JOIN teams ON teams.id = team_answers.team_id
WHERE teams.game_id = $1
ORDER BY teams.id ASC, team_answers.question_code ASC`,
gameId,
)
if err != nil {
return nil, err
}
defer rows.Close()
var answers []*repos.TeamAnswer
for rows.Next() {
answer := &repos.TeamAnswer{}
err := rows.Scan(
&answer.TeamId,
&answer.QuestionCode,
&answer.Text,
&answer.Score,
)
if err != nil {
return nil, err
}
answers = append(answers, answer)
}
if err := rows.Err(); err != nil {
return nil, err
}
return answers, nil
}
// SetAnswerScore выставляет балл за ответ; score == nil сбрасывает балл.
func (r *TeamAnswersRepo) SetAnswerScore(
ctx context.Context,
teamId int,
questionCode string,
score *int,
) error {
tag, err := r.pool.Exec(
ctx,
`UPDATE team_answers
SET
score = $1,
updated_at = NOW()
WHERE team_id = $2 AND question_code = $3`,
score,
teamId,
questionCode,
)
if err != nil {
return err
}
if tag.RowsAffected() == 0 {
return ErrAnswerNotFound
}
return nil
}