You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
3.4 KiB
Go
156 lines
3.4 KiB
Go
package database
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
)
|
|
|
|
// QuestionRepository handles question operations
|
|
type QuestionRepository struct {
|
|
client *Client
|
|
}
|
|
|
|
// NewQuestionRepository creates a new question repository
|
|
func NewQuestionRepository(client *Client) *QuestionRepository {
|
|
return &QuestionRepository{client: client}
|
|
}
|
|
|
|
// Create creates a new question
|
|
func (r *QuestionRepository) Create(ctx context.Context, question *Question) error {
|
|
query := `
|
|
INSERT INTO questions (id, theme, text, answer, hint, difficulty, is_active, created_at, updated_at)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
|
`
|
|
|
|
_, err := r.client.db.ExecContext(ctx, query,
|
|
question.ID,
|
|
question.Theme,
|
|
question.Text,
|
|
question.Answer,
|
|
question.Hint,
|
|
question.Difficulty,
|
|
question.IsActive,
|
|
question.CreatedAt,
|
|
question.UpdatedAt,
|
|
)
|
|
|
|
return err
|
|
}
|
|
|
|
// GetByID retrieves a question by ID
|
|
func (r *QuestionRepository) GetByID(ctx context.Context, id string) (*Question, error) {
|
|
query := `
|
|
SELECT id, theme, text, answer, hint, difficulty, is_active, created_at, updated_at
|
|
FROM questions
|
|
WHERE id = $1
|
|
`
|
|
|
|
var question Question
|
|
err := r.client.db.QueryRowContext(ctx, query, id).Scan(
|
|
&question.ID,
|
|
&question.Theme,
|
|
&question.Text,
|
|
&question.Answer,
|
|
&question.Hint,
|
|
&question.Difficulty,
|
|
&question.IsActive,
|
|
&question.CreatedAt,
|
|
&question.UpdatedAt,
|
|
)
|
|
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, fmt.Errorf("question not found: %s", id)
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
return &question, nil
|
|
}
|
|
|
|
// GetByTheme retrieves questions by theme
|
|
func (r *QuestionRepository) GetByTheme(ctx context.Context, theme string) ([]*Question, error) {
|
|
query := `
|
|
SELECT id, theme, text, answer, hint, difficulty, is_active, created_at, updated_at
|
|
FROM questions
|
|
WHERE theme = $1 AND is_active = true
|
|
ORDER BY created_at DESC
|
|
`
|
|
|
|
rows, err := r.client.db.QueryContext(ctx, query, theme)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var questions []*Question
|
|
for rows.Next() {
|
|
var question Question
|
|
err := rows.Scan(
|
|
&question.ID,
|
|
&question.Theme,
|
|
&question.Text,
|
|
&question.Answer,
|
|
&question.Hint,
|
|
&question.Difficulty,
|
|
&question.IsActive,
|
|
&question.CreatedAt,
|
|
&question.UpdatedAt,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
questions = append(questions, &question)
|
|
}
|
|
|
|
return questions, rows.Err()
|
|
}
|
|
|
|
// GetRandom retrieves a random question
|
|
func (r *QuestionRepository) GetRandom(ctx context.Context, theme string, difficulty string) (*Question, error) {
|
|
query := `
|
|
SELECT id, theme, text, answer, hint, difficulty, is_active, created_at, updated_at
|
|
FROM questions
|
|
WHERE is_active = true
|
|
`
|
|
|
|
args := []interface{}{}
|
|
argIndex := 1
|
|
|
|
if theme != "" {
|
|
query += fmt.Sprintf(" AND theme = $%d", argIndex)
|
|
args = append(args, theme)
|
|
argIndex++
|
|
}
|
|
|
|
if difficulty != "" {
|
|
query += fmt.Sprintf(" AND difficulty = $%d", argIndex)
|
|
args = append(args, difficulty)
|
|
argIndex++
|
|
}
|
|
|
|
query += " ORDER BY RANDOM() LIMIT 1"
|
|
|
|
var question Question
|
|
err := r.client.db.QueryRowContext(ctx, query, args...).Scan(
|
|
&question.ID,
|
|
&question.Theme,
|
|
&question.Text,
|
|
&question.Answer,
|
|
&question.Hint,
|
|
&question.Difficulty,
|
|
&question.IsActive,
|
|
&question.CreatedAt,
|
|
&question.UpdatedAt,
|
|
)
|
|
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, fmt.Errorf("no questions found for theme: %s, difficulty: %s", theme, difficulty)
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
return &question, nil
|
|
} |