Skip to content

Commit

Permalink
Merge pull request #38 from ProjectBARO/feat/add-average-score
Browse files Browse the repository at this point in the history
[close #37] μ£Όκ°„ μ’…ν•© 점수 μ™Έ λ‹€λ₯Έ μ‚¬λžŒλ“€μ˜ 평균 점수 μΆ”κ°€ 및 ν…ŒμŠ€νŠΈ μ½”λ“œ μž‘μ„±
  • Loading branch information
YehyeokBang authored Feb 5, 2024
2 parents 8c8207a + e32553d commit 1dc2b08
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 26 deletions.
30 changes: 23 additions & 7 deletions app/report/repositories/report_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (repo *ReportRepository) FindAll() ([]models.Report, error) {
}

func (repo *ReportRepository) FindRankAtAgeAndGender(user *users.User, start, end time.Time) (types.ResponseRank, error) {
var userAvgScore float64
var userAvgScore, allAvgScore float64
var totalUsers, rank int64
ageGroup := user.Age / 10 * 10

Expand All @@ -87,6 +87,19 @@ func (repo *ReportRepository) FindRankAtAgeAndGender(user *users.User, start, en
return types.ResponseRank{}, err
}

// calculate average score for all users in the same age group and gender
err = repo.DB.Table("reports").
Select("avg(score)").
Joins("inner join users on users.id = reports.user_id").
Where("users.age >= ? AND users.age < ?", ageGroup, ageGroup+10).
Where("users.gender = ?", user.Gender).
Where("reports.created_at BETWEEN ? AND ?", start, end).
Scan(&allAvgScore).Error

if err != nil {
return types.ResponseRank{}, err
}

// calculate rank
sql := `
SELECT COUNT(*) as rank_count
Expand All @@ -110,13 +123,16 @@ func (repo *ReportRepository) FindRankAtAgeAndGender(user *users.User, start, en
rank = totalUsers - rank

normalRatio := fmt.Sprintf("%.2f", float64(rank)/float64(totalUsers)*100.00)
averageScore := fmt.Sprintf("%.2f", userAvgScore)
allAvgScoreStr := fmt.Sprintf("%.2f", allAvgScore)

return types.ResponseRank{
UserID: user.ID,
Nickname: user.Nickname,
Age: user.Age,
Gender: user.Gender,
NormalRatio: normalRatio,
AverageScore: userAvgScore,
UserID: user.ID,
Nickname: user.Nickname,
Age: user.Age,
Gender: user.Gender,
NormalRatio: normalRatio,
AverageScore: averageScore,
AllAverageScore: allAvgScoreStr,
}, nil
}
80 changes: 79 additions & 1 deletion app/report/repositories/report_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,7 @@ func TestReportRepository_FindRankAtAgeAndGender(t *testing.T) {

ageGroup := 20
userAvgScore := 80.0
allAvgScore := 90.0

// Set up expectations for the mock DB to return the sample report
mock.ExpectQuery("SELECT avg\\(score\\) FROM `reports` inner join users on users.id = reports.user_id WHERE reports.user_id = \\? AND \\(reports.created_at BETWEEN \\? AND \\?\\)").
Expand All @@ -645,6 +646,12 @@ func TestReportRepository_FindRankAtAgeAndGender(t *testing.T) {
WillReturnRows(sqlmock.NewRows([]string{"count"}).
AddRow("100"))

// Set up expectations for the mock DB to return average score for all users in the same age group and gender
mock.ExpectQuery("SELECT avg\\(score\\) FROM `reports` inner join users on users.id = reports.user_id WHERE \\(users.age >= \\? AND users.age < \\?\\) AND users.gender = \\? AND \\(reports.created_at BETWEEN \\? AND \\?\\)").
WithArgs(ageGroup, ageGroup+10, user.Gender, start, end).
WillReturnRows(sqlmock.NewRows([]string{"avg"}).
AddRow(allAvgScore))

// Set up expectations for the mock DB to return rank
mock.ExpectQuery("SELECT COUNT\\(\\*\\) as rank_count FROM \\(\\s*SELECT reports.user_id, AVG\\(score\\) as average_score FROM reports INNER JOIN users\\s+on\\s+users.id = reports.user_id WHERE users.age >= \\? AND users.age < \\? AND users.gender = \\? AND reports.created_at BETWEEN \\? AND \\? GROUP BY reports.user_id\\s*\\) as subquery WHERE average_score > \\?").
WithArgs(ageGroup, ageGroup+10, user.Gender, start, end, userAvgScore).
Expand All @@ -666,7 +673,8 @@ func TestReportRepository_FindRankAtAgeAndGender(t *testing.T) {
assert.Equal(t, user.Age, responseRank.Age)
assert.Equal(t, user.Gender, responseRank.Gender)
assert.Equal(t, "80.00", responseRank.NormalRatio)
assert.Equal(t, 80.0, responseRank.AverageScore)
assert.Equal(t, "80.00", responseRank.AverageScore)
assert.Equal(t, "90.00", responseRank.AllAverageScore)
}

func TestReportRepository_FindRankAtAgeAndGender_Error(t *testing.T) {
Expand Down Expand Up @@ -809,8 +817,72 @@ func TestReportRepository_FindRankAtAgeAndGender_Error3(t *testing.T) {
start := time.Now().AddDate(0, 0, -30)
end := time.Now()

ageGroup := 20

// Set up expectations for the mock DB to return the sample report
mock.ExpectQuery("SELECT avg\\(score\\) FROM `reports` inner join users on users.id = reports.user_id WHERE reports.user_id = \\? AND \\(reports.created_at BETWEEN \\? AND \\?\\)").
WithArgs(user.ID, start, end).
WillReturnRows(sqlmock.NewRows([]string{"avg"}).
AddRow("80.0"))

// Set up expectations for the mock DB to return total users
mock.ExpectQuery("SELECT count\\(\\*\\) FROM `users` WHERE \\(age >= \\? AND age < \\?\\) AND gender = \\?").
WithArgs(ageGroup, ageGroup+10, user.Gender).
WillReturnRows(sqlmock.NewRows([]string{"count"}).
AddRow("100"))

// Set up expectations for the mock DB to return average score for all users in the same age group and gender
mock.ExpectQuery("SELECT avg\\(score\\) FROM `reports` inner join users on users.id = reports.user_id WHERE \\(users.age >= \\? AND users.age < \\?\\) AND users.gender = \\? AND \\(reports.created_at BETWEEN \\? AND \\?\\)").
WithArgs(ageGroup, ageGroup+10, user.Gender, start, end).
WillReturnError(err)

// Call the method under test
_, err = reportRepository.FindRankAtAgeAndGender(&user, start, end)
if err == nil {
t.Fatalf("Error finding rank: %v", err)
}

// Check that the expectations were met
assert.NoError(t, mock.ExpectationsWereMet())
}

func TestReportRepository_FindRankAtAgeAndGender_Error4(t *testing.T) {
// Create mock DB
db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("Error creating mock DB: %v", err)
}

// Set up expectations for the mock DB (ex: SELECT VERSION())
mock.ExpectQuery("SELECT VERSION()").
WillReturnRows(sqlmock.NewRows([]string{"VERSION"}).
AddRow("8.0.0"))

// Create gorm.DB
gormDB, err := gorm.Open(mysql.New(mysql.Config{Conn: db}), &gorm.Config{})
if err != nil {
t.Fatalf("Error creating gorm.DB: %v", err)
}

// Create ReportRepository
reportRepository := repositories.NewReportRepository(gormDB)

// Create sample user for the test
user := usermodel.User{
ID: 1,
Name: "test",
Nickname: "test",
Email: "[email protected]",
Age: 20,
Gender: "male",
}

start := time.Now().AddDate(0, 0, -30)
end := time.Now()

ageGroup := 20
userAvgScore := 80.0
allAvgScore := 90.0

// Set up expectations for the mock DB to return the sample report
mock.ExpectQuery("SELECT avg\\(score\\) FROM `reports` inner join users on users.id = reports.user_id WHERE reports.user_id = \\? AND \\(reports.created_at BETWEEN \\? AND \\?\\)").
Expand All @@ -824,6 +896,12 @@ func TestReportRepository_FindRankAtAgeAndGender_Error3(t *testing.T) {
WillReturnRows(sqlmock.NewRows([]string{"count"}).
AddRow("100"))

// Set up expectations for the mock DB to return average score for all users in the same age group and gender
mock.ExpectQuery("SELECT avg\\(score\\) FROM `reports` inner join users on users.id = reports.user_id WHERE \\(users.age >= \\? AND users.age < \\?\\) AND users.gender = \\? AND \\(reports.created_at BETWEEN \\? AND \\?\\)").
WithArgs(ageGroup, ageGroup+10, user.Gender, start, end).
WillReturnRows(sqlmock.NewRows([]string{"avg"}).
AddRow(allAvgScore))

// Set up expectations for the mock DB to return rank
mock.ExpectQuery("SELECT COUNT\\(\\*\\) as rank_count FROM \\(\\s*SELECT reports.user_id, AVG\\(score\\) as average_score FROM reports INNER JOIN users\\s+on\\s+users.id = reports.user_id WHERE users.age >= \\? AND users.age < \\? AND users.gender = \\? AND reports.created_at BETWEEN \\? AND \\? GROUP BY reports.user_id\\s*\\) as subquery WHERE average_score > \\?").
WithArgs(ageGroup, ageGroup+10, user.Gender, start, end, userAvgScore).
Expand Down
13 changes: 7 additions & 6 deletions app/report/services/report_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,12 +363,13 @@ func (service *ReportService) FindRankAtAgeAndGender(c *gin.Context) (types.Resp
rank, _ := service.ReportRepository.FindRankAtAgeAndGender(user, time.Now().AddDate(0, 0, -30), time.Now())

responseRank := types.ResponseRank{
UserID: rank.UserID,
Nickname: user.Nickname,
Age: rank.Age,
Gender: rank.Gender,
NormalRatio: rank.NormalRatio,
AverageScore: rank.AverageScore,
UserID: rank.UserID,
Nickname: user.Nickname,
Age: rank.Age,
Gender: rank.Gender,
NormalRatio: rank.NormalRatio,
AverageScore: rank.AverageScore,
AllAverageScore: rank.AllAverageScore,
}

return responseRank, nil
Expand Down
13 changes: 7 additions & 6 deletions app/report/services/report_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -832,12 +832,13 @@ func TestFindRankAtAgeAndGender(t *testing.T) {

// Set up sample rank for the test
rank := types.ResponseRank{
UserID: 1,
Nickname: "test",
Age: 20,
Gender: "male",
NormalRatio: "90.00",
AverageScore: 90.000,
UserID: 1,
Nickname: "test",
Age: 20,
Gender: "male",
NormalRatio: "90.00",
AverageScore: "90.00",
AllAverageScore: "90.00",
}

// Set up expectations for the mock repository and util
Expand Down
13 changes: 7 additions & 6 deletions app/report/types/response_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ type ResponseReport struct {
}

type ResponseRank struct {
UserID uint `json:"user_id"`
Nickname string `json:"nickname"`
Gender string `json:"gender"`
Age int `json:"age"`
NormalRatio string `json:"normal_ratio"`
AverageScore float64 `json:"average_score"`
UserID uint `json:"user_id"`
Nickname string `json:"nickname"`
Gender string `json:"gender"`
Age int `json:"age"`
NormalRatio string `json:"normal_ratio"`
AverageScore string `json:"average_score"`
AllAverageScore string `json:"all_average_score"`
}

0 comments on commit 1dc2b08

Please sign in to comment.