add diffectly

This commit is contained in:
2026-10-03 14:52:40 +07:00
parent 4631c443e0
commit 7d4361a315
13 changed files with 200 additions and 103 deletions
+29 -26
View File
@@ -23,15 +23,16 @@ var (
// Review describes a game review.
type Review struct {
ID int
GameID int
GameName string
TeamID int
TeamName string
Rating int32
Text string
Status string
CreatedAt time.Time
ID int
GameID int
GameName string
TeamID int
TeamName string
Rating int32
Difficulty int32
Text string
Status string
CreatedAt time.Time
}
// Repo persists game reviews.
@@ -41,13 +42,13 @@ type Repo struct{ pool *pgxpool.Pool }
func NewGameReviewsRepo(pool *pgxpool.Pool) *Repo { return &Repo{pool: pool} }
// Create stores a review.
func (r *Repo) Create(ctx context.Context, gameID, teamID int, rating int32, text string) (*Review, error) {
func (r *Repo) Create(ctx context.Context, gameID, teamID int, rating, difficulty int32, text string) (*Review, error) {
review := &Review{}
err := r.pool.QueryRow(
ctx,
`
INSERT INTO game_reviews (game_id, team_id, rating, text)
SELECT $1, t.id, $3, $4
INSERT INTO game_reviews (game_id, team_id, rating, difficulty, text)
SELECT $1, t.id, $3, $4, $5
FROM teams t
WHERE t.id = $2 AND t.game_id = $1
ON CONFLICT (game_id, team_id) DO NOTHING
@@ -55,9 +56,10 @@ func (r *Repo) Create(ctx context.Context, gameID, teamID int, rating int32, tex
gameID,
teamID,
rating,
difficulty,
text,
).Scan(
&review.ID, &review.GameID, &review.TeamID, &review.Rating, &review.Text, &review.Status, &review.CreatedAt)
&review.ID, &review.GameID, &review.TeamID, &review.Rating, &review.Difficulty, &review.Text, &review.Status, &review.CreatedAt)
if errors.Is(err, pgx.ErrNoRows) {
var exists bool
if err := r.pool.QueryRow(
@@ -89,7 +91,7 @@ func (r *Repo) GetByID(ctx context.Context, id int) (*Review, error) {
func (r *Repo) List(ctx context.Context, gameID int, all bool) ([]*Review, float64, int32, error) {
rows, err := r.pool.Query(
ctx,
`SELECT r.id, r.game_id, r.team_id, t.name, g.name, r.rating, r.text, r.status, r.created_at
`SELECT r.id, r.game_id, r.team_id, t.name, g.name, r.rating, r.difficulty, r.text, r.status, r.created_at
FROM game_reviews r
JOIN teams t ON t.id = r.team_id
JOIN games g ON g.id = r.game_id
@@ -105,7 +107,7 @@ func (r *Repo) List(ctx context.Context, gameID int, all bool) ([]*Review, float
var reviews []*Review
for rows.Next() {
review := &Review{}
if err := rows.Scan(&review.ID, &review.GameID, &review.TeamID, &review.TeamName, &review.GameName, &review.Rating, &review.Text, &review.Status, &review.CreatedAt); err != nil {
if err := rows.Scan(&review.ID, &review.GameID, &review.TeamID, &review.TeamName, &review.GameName, &review.Rating, &review.Difficulty, &review.Text, &review.Status, &review.CreatedAt); err != nil {
return nil, 0, 0, err
}
reviews = append(reviews, review)
@@ -131,7 +133,7 @@ func (r *Repo) List(ctx context.Context, gameID int, all bool) ([]*Review, float
func (r *Repo) ListForModeration(ctx context.Context) ([]*Review, error) {
rows, err := r.pool.Query(
ctx,
`SELECT r.id, r.game_id, r.team_id, t.name, g.name, r.rating, r.text, r.status, r.created_at
`SELECT r.id, r.game_id, r.team_id, t.name, g.name, r.rating, r.difficulty, r.text, r.status, r.created_at
FROM game_reviews r
JOIN teams t ON t.id = r.team_id
JOIN games g ON g.id = r.game_id
@@ -144,7 +146,7 @@ func (r *Repo) ListForModeration(ctx context.Context) ([]*Review, error) {
var reviews []*Review
for rows.Next() {
review := &Review{}
if err := rows.Scan(&review.ID, &review.GameID, &review.TeamID, &review.TeamName, &review.GameName, &review.Rating, &review.Text, &review.Status, &review.CreatedAt); err != nil {
if err := rows.Scan(&review.ID, &review.GameID, &review.TeamID, &review.TeamName, &review.GameName, &review.Rating, &review.Difficulty, &review.Text, &review.Status, &review.CreatedAt); err != nil {
return nil, err
}
reviews = append(reviews, review)
@@ -175,25 +177,26 @@ func (r *Repo) Moderate(ctx context.Context, id int, status string) (*Review, er
}
// ScenarioRating returns aggregate ratings for a scenario.
func (r *Repo) ScenarioRating(ctx context.Context, scenarioID int) (float64, int32, error) {
func (r *Repo) ScenarioRating(ctx context.Context, scenarioID int) (float64, int32, float64, error) {
var average float64
var averageDifficulty float64
var count int64
err := r.pool.QueryRow(
ctx,
`SELECT COALESCE(AVG(r.rating), 0), COUNT(*)
`SELECT COALESCE(AVG(r.rating), 0), COUNT(*), COALESCE(AVG(r.difficulty), 0)
FROM game_reviews r
JOIN games g ON g.id = r.game_id
WHERE g.scenario_id = $1 AND g.status = 'finish' AND r.status = 'approved'`,
scenarioID,
).Scan(&average, &count)
return average, int32(count), err
).Scan(&average, &count, &averageDifficulty)
return average, int32(count), averageDifficulty, err
}
// ListByScenario returns reviews and aggregate ratings for a scenario.
func (r *Repo) ListByScenario(ctx context.Context, scenarioID int) ([]*Review, float64, int32, error) {
rows, err := r.pool.Query(
ctx,
`SELECT r.id, r.game_id, r.team_id, t.name, g.name, r.rating, r.text, r.status, r.created_at
`SELECT r.id, r.game_id, r.team_id, t.name, g.name, r.rating, r.difficulty, r.text, r.status, r.created_at
FROM game_reviews r
JOIN teams t ON t.id = r.team_id
JOIN games g ON g.id = r.game_id
@@ -208,7 +211,7 @@ func (r *Repo) ListByScenario(ctx context.Context, scenarioID int) ([]*Review, f
var reviews []*Review
for rows.Next() {
review := &Review{}
if err := rows.Scan(&review.ID, &review.GameID, &review.TeamID, &review.TeamName, &review.GameName, &review.Rating, &review.Text, &review.Status, &review.CreatedAt); err != nil {
if err := rows.Scan(&review.ID, &review.GameID, &review.TeamID, &review.TeamName, &review.GameName, &review.Rating, &review.Difficulty, &review.Text, &review.Status, &review.CreatedAt); err != nil {
return nil, 0, 0, err
}
reviews = append(reviews, review)
@@ -216,7 +219,7 @@ func (r *Repo) ListByScenario(ctx context.Context, scenarioID int) ([]*Review, f
if err := rows.Err(); err != nil {
return nil, 0, 0, err
}
average, count, err := r.ScenarioRating(ctx, scenarioID)
average, count, _, err := r.ScenarioRating(ctx, scenarioID)
return reviews, average, count, err
}
@@ -224,14 +227,14 @@ func (r *Repo) queryOne(ctx context.Context, id int) (*Review, error) {
review := &Review{}
err := r.pool.QueryRow(
ctx,
`SELECT r.id, r.game_id, r.team_id, t.name, g.name, r.rating, r.text, r.status, r.created_at
`SELECT r.id, r.game_id, r.team_id, t.name, g.name, r.rating, r.difficulty, r.text, r.status, r.created_at
FROM game_reviews r
JOIN teams t ON t.id = r.team_id
JOIN games g ON g.id = r.game_id
WHERE r.id = $1`,
id,
).Scan(
&review.ID, &review.GameID, &review.TeamID, &review.TeamName, &review.GameName, &review.Rating, &review.Text, &review.Status, &review.CreatedAt)
&review.ID, &review.GameID, &review.TeamID, &review.TeamName, &review.GameName, &review.Rating, &review.Difficulty, &review.Text, &review.Status, &review.CreatedAt)
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrReviewNotFound
}