From e3b524f63b266593c924351e527cdb41d7597d72 Mon Sep 17 00:00:00 2001 From: slhmy Date: Fri, 23 Aug 2024 09:16:07 +0800 Subject: [PATCH] Support getting solved status while querying problems --- cmd/web_server/handler/problem.go | 4 +-- models/judge/judge.go | 14 +++++------ models/judge/judge_db.go | 41 ++++++++++++++++++------------- models/problem/problem.go | 2 +- services/judge/judge.go | 7 +++++- services/judge/judge_result.go | 2 +- services/judge/judge_task.go | 4 +-- services/judge/judge_test.go | 3 ++- services/problem/problem_info.go | 32 +++++++++++++++++++++++- 9 files changed, 76 insertions(+), 33 deletions(-) diff --git a/cmd/web_server/handler/problem.go b/cmd/web_server/handler/problem.go index 844b9c8..f0abfd0 100644 --- a/cmd/web_server/handler/problem.go +++ b/cmd/web_server/handler/problem.go @@ -102,8 +102,8 @@ func getProblemInfoList(ginCtx *gin.Context) { problemInfoList, total, err := problem_service.GetProblemInfoList( ginCtx, - &limit, - &offset, + nil, + &limit, &offset, ) if err != nil { gin_utils.NewInternalError(ginCtx, err.Error()) diff --git a/models/judge/judge.go b/models/judge/judge.go index 03cc3e5..e0de1ff 100644 --- a/models/judge/judge.go +++ b/models/judge/judge.go @@ -7,13 +7,13 @@ import ( user_model "github.com/oj-lab/oj-lab-platform/models/user" ) -type JudgeTaskStatus string +type JudgeStatus string const ( - JudgeTaskStatusPending JudgeTaskStatus = "pending" - JudgeTaskStatusWaiting JudgeTaskStatus = "waiting" - JudgeTaskStatusRunning JudgeTaskStatus = "running" - JudgeTaskStatusFinished JudgeTaskStatus = "finished" + JudgeStatusPending JudgeStatus = "pending" + JudgeStatusWaiting JudgeStatus = "waiting" + JudgeStatusRunning JudgeStatus = "running" + JudgeStatusFinished JudgeStatus = "finished" ) type ProgrammingLanguage string @@ -39,7 +39,7 @@ type Judge struct { Problem problem_model.Problem `json:"problem"` Code string `json:"code" gorm:"not null"` Language ProgrammingLanguage `json:"language" gorm:"not null"` - Status JudgeTaskStatus `json:"status" gorm:"default:pending"` + Status JudgeStatus `json:"status" gorm:"default:pending"` ResultCount uint `json:"resultCount"` Results []JudgeResult `json:"results" gorm:"foreignKey:JudgeUID"` Verdict JudgeVerdict `json:"verdict"` @@ -56,7 +56,7 @@ func NewJudge( ProblemSlug: problemSlug, Code: code, Language: language, - Status: JudgeTaskStatusPending, + Status: JudgeStatusPending, } } diff --git a/models/judge/judge_db.go b/models/judge/judge_db.go index f0c2f27..c5db8bf 100644 --- a/models/judge/judge_db.go +++ b/models/judge/judge_db.go @@ -40,15 +40,16 @@ func GetJudge(tx *gorm.DB, uid uuid.UUID) (*Judge, error) { type GetJudgeOptions struct { Selection []string - Statuses []JudgeTaskStatus UserAccount *string - ProblemSlug *string + ProblemSlugs []string + Statuses []JudgeStatus + Verdicts []JudgeVerdict Offset *int Limit *int OrderByColumns []models.OrderByColumnOption } -func buildGetJudgeTXByOptions( +func buildGetJudgesTXByOptions( tx *gorm.DB, options GetJudgeOptions, isCount bool, ) *gorm.DB { tx = tx.Model(&Judge{}). @@ -59,12 +60,15 @@ func buildGetJudgeTXByOptions( if options.UserAccount != nil { tx = tx.Where("user_account = ?", *options.UserAccount) } - if options.ProblemSlug != nil { - tx = tx.Where("problem_slug = ?", *options.ProblemSlug) - } if len(options.Statuses) > 0 { tx = tx.Where("status IN ?", options.Statuses) } + if len(options.Verdicts) > 0 { + tx = tx.Where("verdict IN ?", options.Verdicts) + } + if len(options.ProblemSlugs) > 0 { + tx = tx.Where("problem_slug IN ?", options.ProblemSlugs) + } if !isCount { if options.Offset != nil { @@ -84,24 +88,27 @@ func buildGetJudgeTXByOptions( return tx } +func CountJudgeByOptions(tx *gorm.DB, options GetJudgeOptions) (int64, error) { + tx = buildGetJudgesTXByOptions(tx, options, true) + var count int64 + err := tx.Count(&count).Error + if err != nil { + return 0, err + } + return count, nil +} + func GetJudgeListByOptions( tx *gorm.DB, options GetJudgeOptions, -) ([]*Judge, int64, error) { - tx = buildGetJudgeTXByOptions(tx, options, false) +) ([]*Judge, error) { + tx = buildGetJudgesTXByOptions(tx, options, false) var judges []*Judge err := tx.Find(&judges).Error if err != nil { - return nil, 0, err - } - - tx = buildGetJudgeTXByOptions(tx, options, true) - var count int64 - err = tx.Count(&count).Error - if err != nil { - return nil, 0, err + return nil, err } - return judges, count, nil + return judges, nil } func UpdateJudge(tx *gorm.DB, judge Judge) error { diff --git a/models/problem/problem.go b/models/problem/problem.go index 42564dc..244bb37 100644 --- a/models/problem/problem.go +++ b/models/problem/problem.go @@ -8,7 +8,7 @@ type Problem struct { Title string `json:"title" gorm:"not null"` Description *string `json:"description,omitempty"` Tags []*ProblemTag `json:"tags" gorm:"many2many:problem_problem_tags;"` - Solved bool `json:"solved,omitempty" gorm:"-"` + IsAccepted bool `json:"solved,omitempty" gorm:"-"` } type ProblemTag struct { diff --git a/services/judge/judge.go b/services/judge/judge.go index b4cc326..c2dfa96 100644 --- a/services/judge/judge.go +++ b/services/judge/judge.go @@ -24,7 +24,12 @@ func GetJudgeList( ctx context.Context, options judge_model.GetJudgeOptions, ) ([]*judge_model.Judge, int64, error) { db := gorm_agent.GetDefaultDB() - judges, total, err := judge_model.GetJudgeListByOptions(db, options) + + total, err := judge_model.CountJudgeByOptions(db, options) + if err != nil { + return nil, 0, err + } + judges, err := judge_model.GetJudgeListByOptions(db, options) if err != nil { return nil, 0, err } diff --git a/services/judge/judge_result.go b/services/judge/judge_result.go index 5f80d39..50b8095 100644 --- a/services/judge/judge_result.go +++ b/services/judge/judge_result.go @@ -23,7 +23,7 @@ func CreateJudgeResult( if judge == nil { return nil, ErrJudgeNotFound } - if judge.Status != judge_model.JudgeTaskStatusRunning { + if judge.Status != judge_model.JudgeStatusRunning { return nil, ErrInvalidJudgeStatus } diff --git a/services/judge/judge_task.go b/services/judge/judge_task.go index e152480..655f7aa 100644 --- a/services/judge/judge_task.go +++ b/services/judge/judge_task.go @@ -17,7 +17,7 @@ func PickJudgeTask(ctx context.Context, consumer string) (*judge_model.JudgeTask db := gorm_agent.GetDefaultDB() err = judge_model.UpdateJudge(db, judge_model.Judge{ UID: uuid.MustParse(task.JudgeUID), - Status: judge_model.JudgeTaskStatusRunning, + Status: judge_model.JudgeStatusRunning, }) if err != nil { return nil, err @@ -34,7 +34,7 @@ func ReportJudgeTask( err := judge_model.UpdateJudge(db, judge_model.Judge{ RedisStreamID: streamID, - Status: judge_model.JudgeTaskStatusFinished, + Status: judge_model.JudgeStatusFinished, Verdict: verdict, }) if err != nil { diff --git a/services/judge/judge_test.go b/services/judge/judge_test.go index 7c38d85..a3ac187 100644 --- a/services/judge/judge_test.go +++ b/services/judge/judge_test.go @@ -54,7 +54,8 @@ func TestCreateJudge(t *testing.T) { } db := gorm_agent.GetDefaultDB() - judges, _, err := judge_model.GetJudgeListByOptions(db, judge_model.GetJudgeOptions{OrderByColumns: []models.OrderByColumnOption{{Column: "create_at", Desc: true}}}) + judges, err := judge_model.GetJudgeListByOptions(db, + judge_model.GetJudgeOptions{OrderByColumns: []models.OrderByColumnOption{{Column: "create_at", Desc: true}}}) if err != nil || len(judges) == 0 { t.Error(err) } diff --git a/services/problem/problem_info.go b/services/problem/problem_info.go index 2dda459..5c66643 100644 --- a/services/problem/problem_info.go +++ b/services/problem/problem_info.go @@ -3,11 +3,16 @@ package problem_service import ( "context" + judge_model "github.com/oj-lab/oj-lab-platform/models/judge" problem_model "github.com/oj-lab/oj-lab-platform/models/problem" gorm_agent "github.com/oj-lab/oj-lab-platform/modules/agent/gorm" ) -func GetProblemInfoList(_ context.Context, limit, offset *int) ([]problem_model.Problem, int64, error) { +func GetProblemInfoList( + _ context.Context, + account *string, + limit, offset *int, +) ([]problem_model.Problem, int64, error) { db := gorm_agent.GetDefaultDB() getOptions := problem_model.GetProblemOptions{ Selection: problem_model.ProblemInfoSelection, @@ -24,5 +29,30 @@ func GetProblemInfoList(_ context.Context, limit, offset *int) ([]problem_model. return nil, 0, err } + if account != nil { + problemSlugs := []string{} + for _, problem := range problemList { + problemSlugs = append(problemSlugs, problem.Slug) + } + acceptedJudgeList, err := judge_model.GetJudgeListByOptions(db, judge_model.GetJudgeOptions{ + UserAccount: account, + ProblemSlugs: problemSlugs, + Statuses: []judge_model.JudgeStatus{judge_model.JudgeStatusFinished}, + Verdicts: []judge_model.JudgeVerdict{judge_model.JudgeVerdictAccepted}, + }) + if err != nil { + return nil, 0, err + } + acceptedProblemSlugs := map[string]bool{} + for _, judge := range acceptedJudgeList { + acceptedProblemSlugs[judge.ProblemSlug] = true + } + for i, problem := range problemList { + if _, ok := acceptedProblemSlugs[problem.Slug]; ok { + problemList[i].IsAccepted = true + } + } + } + return problemList, total, nil }