-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #99 from oj-lab/zztrans/rank
Rank design and implement, in progress.
- Loading branch information
Showing
17 changed files
with
733 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package handler | ||
|
||
import ( | ||
"github.com/gin-gonic/gin" | ||
gin_utils "github.com/oj-lab/oj-lab-platform/modules/utils/gin" | ||
judge_service "github.com/oj-lab/oj-lab-platform/services/judge" | ||
) | ||
|
||
func SetupRankRouter(baseRoute *gin.RouterGroup) { | ||
g := baseRoute.Group("/rank") | ||
{ | ||
g.GET("", getRankList) | ||
// g.GET("/:account", getUserRank) | ||
} | ||
} | ||
|
||
// getUserRank | ||
// | ||
// @Router /rank/{account} [get] | ||
// @Summary Get a user rank | ||
// @Description Get a rank for user | ||
// @Tags problem | ||
// @Accept json | ||
// @Success 200 | ||
// func getUserRank(ginCtx *gin.Context) { | ||
|
||
// } | ||
|
||
// getRankList | ||
// | ||
// @Router /rank [get] | ||
// @Summary Get rank list | ||
// @Description Get rank list | ||
// @Tags rank | ||
// @Accept json | ||
// @Success 200 | ||
func getRankList(ginCtx *gin.Context) { | ||
limit, err := gin_utils.QueryInt(ginCtx, "limit", 100) | ||
if err != nil { | ||
gin_utils.NewInvalidParamError(ginCtx, "limit", err.Error()) | ||
return | ||
} | ||
offset, err := gin_utils.QueryInt(ginCtx, "offset", 0) | ||
if err != nil { | ||
gin_utils.NewInvalidParamError(ginCtx, "offset", err.Error()) | ||
return | ||
} | ||
|
||
rankInfoList, err := judge_service.GetRankList( | ||
ginCtx, | ||
nil, | ||
&limit, &offset, | ||
) | ||
if err != nil { | ||
gin_utils.NewInternalError(ginCtx, err.Error()) | ||
return | ||
} | ||
|
||
ginCtx.JSON(200, rankInfoList) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package judge_model | ||
|
||
import "github.com/oj-lab/oj-lab-platform/models" | ||
|
||
type JudgeRank struct { | ||
Rank int | ||
AvatarURL string | ||
Name string | ||
Points int | ||
TotalSubmissions int | ||
AcceptRate float32 | ||
} | ||
|
||
var RankInfoSelection = append([]string{"user_account", "points", "total_submissions"}, models.MetaFieldsSelection...) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package judge_model | ||
|
||
import ( | ||
"github.com/oj-lab/oj-lab-platform/models" | ||
user_model "github.com/oj-lab/oj-lab-platform/models/user" | ||
) | ||
|
||
// user contest summary rank info | ||
type JudgeRankCache struct { | ||
models.MetaFields | ||
UserAccount string `json:"userAccount" gorm:"primaryKey"` | ||
User user_model.User `json:"user"` | ||
Points int `json:"points"` | ||
TotalSubmissions int `json:"totalSubmissions"` | ||
} | ||
|
||
func NewJudgeRankCache(userAccount string) JudgeRankCache { | ||
return JudgeRankCache{ | ||
UserAccount: userAccount, | ||
Points: 0, | ||
TotalSubmissions: 0, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package judge_model | ||
|
||
import ( | ||
"errors" | ||
|
||
"github.com/oj-lab/oj-lab-platform/models" | ||
"gorm.io/gorm" | ||
) | ||
|
||
func CreateJudgeRankCache(tx *gorm.DB, rankCache JudgeRankCache) (*JudgeRankCache, error) { | ||
rankCache.MetaFields = models.NewMetaFields() | ||
return &rankCache, tx.Create(&rankCache).Error | ||
} | ||
|
||
func DeleteJudgeRankCache(tx *gorm.DB, userAccount string) error { | ||
var judgeRankCache JudgeRankCache | ||
if err := tx.Where("user_account = ?", userAccount).First(&judgeRankCache).Error; err != nil { | ||
return err | ||
} | ||
return tx.Delete(&judgeRankCache).Error | ||
} | ||
|
||
func GetJudgeRankCache(tx *gorm.DB, userAccount string) (*JudgeRankCache, error) { | ||
rankCache := JudgeRankCache{} | ||
err := tx.Model(&JudgeRankCache{}). | ||
Where("user_account = ?", userAccount). | ||
First(&rankCache).Error | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &rankCache, nil | ||
} | ||
|
||
func UpdateJudgeRankCache(tx *gorm.DB, rankCache JudgeRankCache) error { | ||
return tx.Model(&rankCache).Updates(rankCache).Error | ||
} | ||
|
||
func (rankCache *JudgeRankCache) BeforeSave(tx *gorm.DB) (err error) { | ||
if rankCache.Points > rankCache.TotalSubmissions { | ||
return errors.New("TotalSubmissions must >= Points") | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package judge_model | ||
|
||
import "gorm.io/gorm" | ||
|
||
type GetRankOptions struct { | ||
Selection []string | ||
UserAccount *string | ||
Offset *int | ||
Limit *int | ||
} | ||
|
||
func buildGetRankCacheTXByOptions(tx *gorm.DB, options GetRankOptions, isCount bool) *gorm.DB { | ||
tx = tx.Model(&JudgeRankCache{}) | ||
if len(options.Selection) > 0 { | ||
tx = tx.Select(options.Selection) | ||
} | ||
if options.UserAccount != nil { | ||
tx = tx.Where("user_account = ?", *options.UserAccount) | ||
} | ||
|
||
tx = tx.Distinct().Preload("User") | ||
if !isCount { | ||
if options.Offset != nil { | ||
tx = tx.Offset(*options.Offset) | ||
} | ||
if options.Limit != nil { | ||
tx = tx.Limit(*options.Limit) | ||
} | ||
} | ||
|
||
tx = tx.Order("points DESC, total_submissions ASC") | ||
return tx | ||
} | ||
|
||
func GetRankCacheListByOptions(tx *gorm.DB, options GetRankOptions) ([]JudgeRankCache, error) { | ||
rankInfoList := []JudgeRankCache{} | ||
tx = buildGetRankCacheTXByOptions(tx, options, false) | ||
err := tx.Find(&rankInfoList).Error | ||
if err != nil { | ||
return nil, err | ||
} | ||
return rankInfoList, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package judge_model | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/oj-lab/oj-lab-platform/models" | ||
problem_model "github.com/oj-lab/oj-lab-platform/models/problem" | ||
user_model "github.com/oj-lab/oj-lab-platform/models/user" | ||
) | ||
|
||
// user contest problem summary score info | ||
type JudgeScoreCache struct { | ||
models.MetaFields | ||
UserAccount string `json:"userAccount" gorm:"primaryKey"` | ||
User user_model.User `json:"user"` | ||
ProblemSlug string `json:"problemSlug" gorm:"primaryKey"` | ||
Problem problem_model.Problem `json:"problem"` | ||
SubmissionCount int `json:"submissionCount" gorm:"default:0"` // judge create time < solvetime will be counted | ||
IsAccepted bool `json:"isAccepted" gorm:"default:false"` | ||
SolveTime *time.Time `json:"solveAt" gorm:"default:null"` // ac time < solveTime, update submissionCount | ||
} | ||
|
||
func NewJudgeScoreCache(userAccount string, problemSlug string) JudgeScoreCache { | ||
return JudgeScoreCache{ | ||
UserAccount: userAccount, | ||
ProblemSlug: problemSlug, | ||
SubmissionCount: 0, | ||
IsAccepted: false, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package judge_model | ||
|
||
import ( | ||
"github.com/oj-lab/oj-lab-platform/models" | ||
"gorm.io/gorm" | ||
) | ||
|
||
func CreateJudgeScoreCache(tx *gorm.DB, scoreCache JudgeScoreCache) (*JudgeScoreCache, error) { | ||
scoreCache.MetaFields = models.NewMetaFields() | ||
return &scoreCache, tx.Create(&scoreCache).Error | ||
} | ||
|
||
func GetJudgeScoreCache(tx *gorm.DB, userAccount string, problemSlug string) (*JudgeScoreCache, error) { | ||
scoreCache := JudgeScoreCache{} | ||
err := tx.Model(&JudgeScoreCache{}). | ||
Where("user_account = ?", userAccount). | ||
Where("problem_slug = ?", problemSlug). | ||
First(&scoreCache).Error | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &scoreCache, nil | ||
} | ||
|
||
func UpdateJudgeScoreCache(tx *gorm.DB, scoreCache JudgeScoreCache) error { | ||
return tx.Model(&scoreCache).Updates(scoreCache).Error | ||
} |
Oops, something went wrong.