Add world record support
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-06-23 23:31:24 -04:00
parent 394fef5f6d
commit 5d7f78401a
7 changed files with 278 additions and 1 deletions

View File

@@ -282,6 +282,81 @@ const docTemplate = `{
}
}
},
"/time/worldrecord": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Get a list of world records sorted by most recent first",
"produces": [
"application/json"
],
"tags": [
"times"
],
"summary": "Get world records",
"parameters": [
{
"maximum": 100,
"minimum": 1,
"type": "integer",
"default": 10,
"description": "Page size (max 100)",
"name": "page_size",
"in": "query"
},
{
"minimum": 1,
"type": "integer",
"default": 1,
"description": "Page number",
"name": "page_number",
"in": "query"
},
{
"type": "integer",
"name": "game_id",
"in": "query"
},
{
"type": "integer",
"name": "map_id",
"in": "query"
},
{
"type": "integer",
"name": "mode_id",
"in": "query"
},
{
"type": "integer",
"name": "style_id",
"in": "query"
},
{
"type": "integer",
"name": "user_id",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/PagedResponse-Time"
}
},
"default": {
"description": "General error response",
"schema": {
"$ref": "#/definitions/Error"
}
}
}
}
},
"/time/{id}": {
"get": {
"security": [

View File

@@ -275,6 +275,81 @@
}
}
},
"/time/worldrecord": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Get a list of world records sorted by most recent first",
"produces": [
"application/json"
],
"tags": [
"times"
],
"summary": "Get world records",
"parameters": [
{
"maximum": 100,
"minimum": 1,
"type": "integer",
"default": 10,
"description": "Page size (max 100)",
"name": "page_size",
"in": "query"
},
{
"minimum": 1,
"type": "integer",
"default": 1,
"description": "Page number",
"name": "page_number",
"in": "query"
},
{
"type": "integer",
"name": "game_id",
"in": "query"
},
{
"type": "integer",
"name": "map_id",
"in": "query"
},
{
"type": "integer",
"name": "mode_id",
"in": "query"
},
{
"type": "integer",
"name": "style_id",
"in": "query"
},
{
"type": "integer",
"name": "user_id",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/PagedResponse-Time"
}
},
"default": {
"description": "General error response",
"schema": {
"$ref": "#/definitions/Error"
}
}
}
}
},
"/time/{id}": {
"get": {
"security": [

View File

@@ -372,6 +372,54 @@ paths:
summary: Get time by ID
tags:
- times
/time/worldrecord:
get:
description: Get a list of world records sorted by most recent first
parameters:
- default: 10
description: Page size (max 100)
in: query
maximum: 100
minimum: 1
name: page_size
type: integer
- default: 1
description: Page number
in: query
minimum: 1
name: page_number
type: integer
- in: query
name: game_id
type: integer
- in: query
name: map_id
type: integer
- in: query
name: mode_id
type: integer
- in: query
name: style_id
type: integer
- in: query
name: user_id
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/PagedResponse-Time'
default:
description: General error response
schema:
$ref: '#/definitions/Error'
security:
- ApiKeyAuth: []
summary: Get world records
tags:
- times
/user:
get:
description: Get a list of users

2
go.mod
View File

@@ -4,7 +4,7 @@ go 1.24.0
require (
git.itzana.me/StrafesNET/dev-service v0.0.0-20250622175817-762eaef1771e
git.itzana.me/strafesnet/go-grpc v0.0.0-20250622145054-0c0eb0ba26c7
git.itzana.me/strafesnet/go-grpc v0.0.0-20250624032225-d34f2a27787e
github.com/gin-gonic/gin v1.10.1
github.com/sirupsen/logrus v1.9.3
github.com/swaggo/files v1.0.1

2
go.sum
View File

@@ -4,6 +4,8 @@ git.itzana.me/StrafesNET/dev-service v0.0.0-20250622175817-762eaef1771e h1:XItsI
git.itzana.me/StrafesNET/dev-service v0.0.0-20250622175817-762eaef1771e/go.mod h1:F2M16jggvrfNCQLLxsVgNzwsgWZyev8jXcDCq1BMAnc=
git.itzana.me/strafesnet/go-grpc v0.0.0-20250622145054-0c0eb0ba26c7 h1:k6Skqr00NOo9Do9Z5rxqzRSR+1BR/bY93+Lf86QlFV8=
git.itzana.me/strafesnet/go-grpc v0.0.0-20250622145054-0c0eb0ba26c7/go.mod h1:X7XTRUScRkBWq8q8bplbeso105RPDlnY7J6Wy1IwBMs=
git.itzana.me/strafesnet/go-grpc v0.0.0-20250624032225-d34f2a27787e h1:zU81WAvEKckjrooheDYMFMwuHrheIdnscXjS2Si6PmU=
git.itzana.me/strafesnet/go-grpc v0.0.0-20250624032225-d34f2a27787e/go.mod h1:X7XTRUScRkBWq8q8bplbeso105RPDlnY7J6Wy1IwBMs=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=

View File

@@ -160,3 +160,79 @@ func (h *TimesHandler) List(ctx *gin.Context) {
},
})
}
// @Summary Get world records
// @Description Get a list of world records sorted by most recent first
// @Tags times
// @Produce json
// @Security ApiKeyAuth
// @Param page_size query int false "Page size (max 100)" default(10) minimum(1) maximum(100)
// @Param page_number query int false "Page number" default(1) minimum(1)
// @Param filter query dto.TimeFilter false "Time filter parameters"
// @Success 200 {object} dto.PagedResponse[dto.TimeData]
// @Failure default {object} dto.Error "General error response"
// @Router /time/worldrecord [get]
func (h *TimesHandler) WrList(ctx *gin.Context) {
// Extract and constrain pagination parameters
query := struct {
PageSize int `form:"page_size,default=10" binding:"min=1,max=100"`
PageNumber int `form:"page_number,default=1" binding:"min=1"`
}{}
if err := ctx.ShouldBindQuery(&query); err != nil {
ctx.JSON(http.StatusBadRequest, dto.Error{
Error: err.Error(),
})
return
}
// Get list filter
var filter dto.TimeFilter
if err := ctx.ShouldBindQuery(&filter); err != nil {
ctx.JSON(http.StatusBadRequest, dto.Error{
Error: err.Error(),
})
return
}
// Call the gRPC service
timeList, err := times.NewTimesServiceClient(h.dataClient).ListWr(ctx, &times.WrListRequest{
Filter: &times.TimeFilter{
UserID: filter.UserID,
MapID: filter.MapID,
ModeID: filter.ModeID,
StyleID: filter.StyleID,
GameID: filter.GameID,
},
Page: &times.Pagination{
Size: int32(query.PageSize),
Number: int32(query.PageNumber),
},
})
if err != nil {
ctx.JSON(http.StatusInternalServerError, dto.Error{
Error: "Failed to list world records",
})
log.WithError(err).Error(
"Failed to list world records",
)
return
}
// Convert gRPC TimeResponse objects to dto.TimeData objects
dtoTimes := make([]dto.TimeData, len(timeList.Times))
for i, t := range timeList.Times {
var time dto.TimeData
dtoTimes[i] = *time.FromGRPC(t)
}
// Return the paged response
ctx.JSON(http.StatusOK, dto.PagedResponse[dto.TimeData]{
Data: dtoTimes,
Pagination: dto.Pagination{
Page: query.PageNumber,
PageSize: query.PageSize,
TotalItems: int(timeList.Total),
TotalPages: int(math.Ceil(float64(timeList.Total) / float64(query.PageSize))),
},
})
}

View File

@@ -106,6 +106,7 @@ func setupRoutes(cfg *RouterConfig) (*gin.Engine, error) {
// Times
v1.GET("/time", timesHandler.List)
v1.GET("/time/worldrecord", timesHandler.WrList)
v1.GET("/time/:id", timesHandler.Get)
// Users