feat: api - GET /api/v2/versions/{versionCode}/servers/{serverKey}/players - new sort option
ci/woodpecker/push/govulncheck Pipeline was successful Details
ci/woodpecker/push/test Pipeline was successful Details

This commit is contained in:
Dawid Wysokiński 2024-03-03 07:43:07 +01:00
parent c4d8a380c3
commit 82d313d2ae
Signed by: Kichiyaki
GPG Key ID: B5445E357FB8B892
7 changed files with 116 additions and 28 deletions

View File

@ -1162,6 +1162,8 @@ components:
- odScoreAtt:DESC
- odScoreDef:ASC
- odScoreDef:DESC
- odScoreSup:ASC
- odScoreSup:DESC
- odScoreTotal:ASC
- odScoreTotal:DESC
- points:ASC

View File

@ -198,6 +198,10 @@ func (a listPlayersParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery {
q = q.Order("player.score_def ASC")
case domain.PlayerSortODScoreDefDESC:
q = q.Order("player.score_def DESC")
case domain.PlayerSortODScoreSupASC:
q = q.Order("player.score_sup ASC")
case domain.PlayerSortODScoreSupDESC:
q = q.Order("player.score_sup DESC")
case domain.PlayerSortODScoreTotalASC:
q = q.Order("player.score_total ASC")
case domain.PlayerSortODScoreTotalDESC:
@ -247,62 +251,58 @@ func (a listPlayersParamsApplier) applyCursor(q *bun.SelectQuery) *bun.SelectQue
el.direction = sortDirectionDESC
case domain.PlayerSortServerKeyASC:
el.value = cursor.ServerKey()
el.unique = false
el.column = "player.server_key"
el.direction = sortDirectionASC
case domain.PlayerSortServerKeyDESC:
el.value = cursor.ServerKey()
el.unique = false
el.column = "player.server_key"
el.direction = sortDirectionDESC
case domain.PlayerSortODScoreAttASC:
el.value = cursor.ODScoreAtt()
el.unique = false
el.column = "player.score_att"
el.direction = sortDirectionASC
case domain.PlayerSortODScoreAttDESC:
el.value = cursor.ODScoreAtt()
el.unique = false
el.column = "player.score_att"
el.direction = sortDirectionDESC
case domain.PlayerSortODScoreDefASC:
el.value = cursor.ODScoreDef()
el.unique = false
el.column = "player.score_def"
el.direction = sortDirectionASC
case domain.PlayerSortODScoreDefDESC:
el.value = cursor.ODScoreDef()
el.unique = false
el.column = "player.score_def"
el.direction = sortDirectionDESC
case domain.PlayerSortODScoreSupASC:
el.value = cursor.ODScoreSup()
el.column = "player.score_sup"
el.direction = sortDirectionASC
case domain.PlayerSortODScoreSupDESC:
el.value = cursor.ODScoreSup()
el.column = "player.score_sup"
el.direction = sortDirectionDESC
case domain.PlayerSortODScoreTotalASC:
el.value = cursor.ODScoreTotal()
el.unique = false
el.column = "player.score_total"
el.direction = sortDirectionASC
case domain.PlayerSortODScoreTotalDESC:
el.value = cursor.ODScoreTotal()
el.unique = false
el.column = "player.score_total"
el.direction = sortDirectionDESC
case domain.PlayerSortPointsASC:
el.value = cursor.Points()
el.unique = false
el.column = "player.points"
el.direction = sortDirectionASC
case domain.PlayerSortPointsDESC:
el.value = cursor.Points()
el.unique = false
el.column = "player.points"
el.direction = sortDirectionDESC
case domain.PlayerSortDeletedAtASC:
el.value = cursor.DeletedAt()
el.unique = false
el.column = "COALESCE(player.deleted_at, '0001-01-01 00:00:00+00:00')"
el.direction = sortDirectionASC
case domain.PlayerSortDeletedAtDESC:
el.value = cursor.DeletedAt()
el.unique = false
el.column = "COALESCE(player.deleted_at, '0001-01-01 00:00:00+00:00')"
el.direction = sortDirectionDESC
default:

View File

@ -248,72 +248,58 @@ func (a listTribesParamsApplier) applyCursor(q *bun.SelectQuery) *bun.SelectQuer
el.direction = sortDirectionDESC
case domain.TribeSortServerKeyASC:
el.value = cursor.ServerKey()
el.unique = false
el.column = "tribe.server_key"
el.direction = sortDirectionASC
case domain.TribeSortServerKeyDESC:
el.value = cursor.ServerKey()
el.unique = false
el.column = "tribe.server_key"
el.direction = sortDirectionDESC
case domain.TribeSortODScoreAttASC:
el.value = cursor.ODScoreAtt()
el.unique = false
el.column = "tribe.score_att"
el.direction = sortDirectionASC
case domain.TribeSortODScoreAttDESC:
el.value = cursor.ODScoreAtt()
el.unique = false
el.column = "tribe.score_att"
el.direction = sortDirectionDESC
case domain.TribeSortODScoreDefASC:
el.value = cursor.ODScoreDef()
el.unique = false
el.column = "tribe.score_def"
el.direction = sortDirectionASC
case domain.TribeSortODScoreDefDESC:
el.value = cursor.ODScoreDef()
el.unique = false
el.column = "tribe.score_def"
el.direction = sortDirectionDESC
case domain.TribeSortODScoreTotalASC:
el.value = cursor.ODScoreTotal()
el.unique = false
el.column = "tribe.score_total"
el.direction = sortDirectionASC
case domain.TribeSortODScoreTotalDESC:
el.value = cursor.ODScoreTotal()
el.unique = false
el.column = "tribe.score_total"
el.direction = sortDirectionDESC
case domain.TribeSortPointsASC:
el.value = cursor.Points()
el.unique = false
el.column = "tribe.points"
el.direction = sortDirectionASC
case domain.TribeSortPointsDESC:
el.value = cursor.Points()
el.unique = false
el.column = "tribe.points"
el.direction = sortDirectionDESC
case domain.TribeSortDominanceASC:
el.value = cursor.Dominance()
el.unique = false
el.column = "tribe.dominance"
el.direction = sortDirectionASC
case domain.TribeSortDominanceDESC:
el.value = cursor.Dominance()
el.unique = false
el.column = "tribe.dominance"
el.direction = sortDirectionDESC
case domain.TribeSortDeletedAtASC:
el.value = cursor.DeletedAt()
el.unique = false
el.column = "COALESCE(tribe.deleted_at, '0001-01-01 00:00:00+00:00')"
el.direction = sortDirectionASC
case domain.TribeSortDeletedAtDESC:
el.value = cursor.DeletedAt()
el.unique = false
el.column = "COALESCE(tribe.deleted_at, '0001-01-01 00:00:00+00:00')"
el.direction = sortDirectionDESC
default:

View File

@ -217,6 +217,35 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
require.NoError(t, err)
},
},
{
name: "OK: sort=[scoreSup DESC, serverKey ASC, id ASC]",
params: func(t *testing.T) domain.ListPlayersParams {
t.Helper()
params := domain.NewListPlayersParams()
require.NoError(t, params.SetSort([]domain.PlayerSort{
domain.PlayerSortODScoreSupDESC,
domain.PlayerSortServerKeyASC,
domain.PlayerSortIDASC,
}))
return params
},
assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) {
t.Helper()
players := res.Players()
assert.NotEmpty(t, len(players))
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or(
cmp.Compare(a.OD().ScoreSup(), b.OD().ScoreSup())*-1,
cmp.Compare(a.ServerKey(), b.ServerKey()),
cmp.Compare(a.ID(), b.ID()),
)
}))
},
assertError: func(t *testing.T, err error) {
t.Helper()
require.NoError(t, err)
},
},
{
name: "OK: sort=[scoreTotal DESC, serverKey ASC, id ASC]",
params: func(t *testing.T) domain.ListPlayersParams {

View File

@ -14,6 +14,7 @@ type PlayerCursorConfig struct {
ServerKey string
ODScoreAtt int
ODScoreDef int
ODScoreSup int
ODScoreTotal int
Points int
DeletedAt time.Time
@ -27,6 +28,7 @@ func NewPlayerCursor(tb TestingTB, opts ...func(cfg *PlayerCursorConfig)) domain
ServerKey: RandServerKey(),
ODScoreAtt: gofakeit.IntRange(0, math.MaxInt),
ODScoreDef: gofakeit.IntRange(0, math.MaxInt),
ODScoreSup: gofakeit.IntRange(0, math.MaxInt),
ODScoreTotal: gofakeit.IntRange(0, math.MaxInt),
Points: gofakeit.IntRange(0, math.MaxInt),
DeletedAt: time.Time{},
@ -41,6 +43,7 @@ func NewPlayerCursor(tb TestingTB, opts ...func(cfg *PlayerCursorConfig)) domain
cfg.ServerKey,
cfg.ODScoreAtt,
cfg.ODScoreDef,
cfg.ODScoreSup,
cfg.ODScoreTotal,
cfg.Points,
cfg.DeletedAt,

View File

@ -402,6 +402,8 @@ const (
PlayerSortODScoreAttDESC
PlayerSortODScoreDefASC
PlayerSortODScoreDefDESC
PlayerSortODScoreSupASC
PlayerSortODScoreSupDESC
PlayerSortODScoreTotalASC
PlayerSortODScoreTotalDESC
PlayerSortPointsASC
@ -437,6 +439,10 @@ func (s PlayerSort) String() string {
return "odScoreDef:ASC"
case PlayerSortODScoreDefDESC:
return "odScoreDef:DESC"
case PlayerSortODScoreSupASC:
return "odScoreSup:ASC"
case PlayerSortODScoreSupDESC:
return "odScoreSup:DESC"
case PlayerSortODScoreTotalASC:
return "odScoreTotal:ASC"
case PlayerSortODScoreTotalDESC:
@ -460,6 +466,8 @@ func newPlayerSortFromString(s string) (PlayerSort, error) {
PlayerSortODScoreAttDESC,
PlayerSortODScoreDefASC,
PlayerSortODScoreDefDESC,
PlayerSortODScoreSupASC,
PlayerSortODScoreSupDESC,
PlayerSortODScoreTotalASC,
PlayerSortODScoreTotalDESC,
PlayerSortPointsASC,
@ -484,6 +492,7 @@ type PlayerCursor struct {
serverKey string
odScoreAtt int
odScoreDef int
odScoreSup int
odScoreTotal int
points int
deletedAt time.Time
@ -496,6 +505,7 @@ func NewPlayerCursor(
serverKey string,
odScoreAtt int,
odScoreDef int,
odScoreSup int,
odScoreTotal int,
points int,
deletedAt time.Time,
@ -532,6 +542,14 @@ func NewPlayerCursor(
}
}
if err := validateIntInRange(odScoreSup, 0, math.MaxInt); err != nil {
return PlayerCursor{}, ValidationError{
Model: playerCursorModelName,
Field: "odScoreSup",
Err: err,
}
}
if err := validateIntInRange(odScoreTotal, 0, math.MaxInt); err != nil {
return PlayerCursor{}, ValidationError{
Model: playerCursorModelName,
@ -553,6 +571,7 @@ func NewPlayerCursor(
serverKey: serverKey,
odScoreAtt: odScoreAtt,
odScoreDef: odScoreDef,
odScoreSup: odScoreSup,
odScoreTotal: odScoreTotal,
points: points,
deletedAt: deletedAt,
@ -586,6 +605,11 @@ func decodePlayerCursor(encoded string) (PlayerCursor, error) {
return PlayerCursor{}, ErrInvalidCursor
}
odScoreSup, err := m.int("odScoreSup")
if err != nil {
return PlayerCursor{}, ErrInvalidCursor
}
odScoreTotal, err := m.int("odScoreTotal")
if err != nil {
return PlayerCursor{}, ErrInvalidCursor
@ -606,6 +630,7 @@ func decodePlayerCursor(encoded string) (PlayerCursor, error) {
serverKey,
odScoreAtt,
odScoreDef,
odScoreSup,
odScoreTotal,
points,
deletedAt,
@ -633,6 +658,10 @@ func (pc PlayerCursor) ODScoreDef() int {
return pc.odScoreDef
}
func (pc PlayerCursor) ODScoreSup() int {
return pc.odScoreSup
}
func (pc PlayerCursor) ODScoreTotal() int {
return pc.odScoreTotal
}
@ -659,6 +688,7 @@ func (pc PlayerCursor) Encode() string {
{"serverKey", pc.serverKey},
{"odScoreAtt", pc.odScoreAtt},
{"odScoreDef", pc.odScoreDef},
{"odScoreSup", pc.odScoreSup},
{"odScoreTotal", pc.odScoreTotal},
{"points", pc.points},
{"deletedAt", pc.deletedAt},
@ -888,6 +918,7 @@ func NewListPlayersResult(players Players, next Player) (ListPlayersResult, erro
players[0].ServerKey(),
od.ScoreAtt(),
od.ScoreDef(),
od.ScoreSup(),
od.ScoreTotal(),
players[0].Points(),
players[0].DeletedAt(),
@ -908,6 +939,7 @@ func NewListPlayersResult(players Players, next Player) (ListPlayersResult, erro
next.ServerKey(),
od.ScoreAtt(),
od.ScoreDef(),
od.ScoreSup(),
od.ScoreTotal(),
next.Points(),
next.DeletedAt(),
@ -961,6 +993,7 @@ func NewListPlayersWithRelationsResult(
player.ServerKey(),
od.ScoreAtt(),
od.ScoreDef(),
od.ScoreSup(),
od.ScoreTotal(),
player.Points(),
player.DeletedAt(),
@ -983,6 +1016,7 @@ func NewListPlayersWithRelationsResult(
player.ServerKey(),
od.ScoreAtt(),
od.ScoreDef(),
od.ScoreSup(),
od.ScoreTotal(),
player.Points(),
player.DeletedAt(),

View File

@ -331,6 +331,7 @@ func TestNewPlayerCursor(t *testing.T) {
serverKey string
odScoreAtt int
odScoreDef int
odScoreSup int
odScoreTotal int
points int
deletedAt time.Time
@ -350,6 +351,7 @@ func TestNewPlayerCursor(t *testing.T) {
serverKey: validPlayerCursor.ServerKey(),
odScoreAtt: validPlayerCursor.ODScoreAtt(),
odScoreDef: validPlayerCursor.ODScoreDef(),
odScoreSup: validPlayerCursor.ODScoreSup(),
odScoreTotal: validPlayerCursor.ODScoreTotal(),
points: validPlayerCursor.Points(),
deletedAt: validPlayerCursor.DeletedAt(),
@ -363,6 +365,7 @@ func TestNewPlayerCursor(t *testing.T) {
serverKey: validPlayerCursor.ServerKey(),
odScoreAtt: validPlayerCursor.ODScoreAtt(),
odScoreDef: validPlayerCursor.ODScoreDef(),
odScoreSup: validPlayerCursor.ODScoreSup(),
odScoreTotal: validPlayerCursor.ODScoreTotal(),
points: validPlayerCursor.Points(),
deletedAt: validPlayerCursor.DeletedAt(),
@ -383,6 +386,7 @@ func TestNewPlayerCursor(t *testing.T) {
serverKey: validPlayerCursor.ServerKey(),
odScoreAtt: -1,
odScoreDef: validPlayerCursor.ODScoreDef(),
odScoreSup: validPlayerCursor.ODScoreSup(),
odScoreTotal: validPlayerCursor.ODScoreTotal(),
points: validPlayerCursor.Points(),
deletedAt: validPlayerCursor.DeletedAt(),
@ -403,6 +407,7 @@ func TestNewPlayerCursor(t *testing.T) {
serverKey: validPlayerCursor.ServerKey(),
odScoreAtt: validPlayerCursor.ODScoreAtt(),
odScoreDef: -1,
odScoreSup: validPlayerCursor.ODScoreSup(),
odScoreTotal: validPlayerCursor.ODScoreTotal(),
points: validPlayerCursor.Points(),
deletedAt: validPlayerCursor.DeletedAt(),
@ -416,6 +421,27 @@ func TestNewPlayerCursor(t *testing.T) {
},
},
},
{
name: "ERR: odScoreSup < 0",
args: args{
id: validPlayerCursor.ID(),
serverKey: validPlayerCursor.ServerKey(),
odScoreAtt: validPlayerCursor.ODScoreAtt(),
odScoreDef: validPlayerCursor.ODScoreDef(),
odScoreSup: -1,
odScoreTotal: validPlayerCursor.ODScoreTotal(),
points: validPlayerCursor.Points(),
deletedAt: validPlayerCursor.DeletedAt(),
},
expectedErr: domain.ValidationError{
Model: "PlayerCursor",
Field: "odScoreSup",
Err: domain.MinGreaterEqualError{
Min: 0,
Current: -1,
},
},
},
{
name: "ERR: odScoreTotal < 0",
args: args{
@ -423,6 +449,7 @@ func TestNewPlayerCursor(t *testing.T) {
serverKey: validPlayerCursor.ServerKey(),
odScoreAtt: validPlayerCursor.ODScoreAtt(),
odScoreDef: validPlayerCursor.ODScoreDef(),
odScoreSup: validPlayerCursor.ODScoreSup(),
odScoreTotal: -1,
points: validPlayerCursor.Points(),
deletedAt: validPlayerCursor.DeletedAt(),
@ -443,6 +470,7 @@ func TestNewPlayerCursor(t *testing.T) {
serverKey: validPlayerCursor.ServerKey(),
odScoreAtt: validPlayerCursor.ODScoreAtt(),
odScoreDef: validPlayerCursor.ODScoreDef(),
odScoreSup: validPlayerCursor.ODScoreSup(),
odScoreTotal: validPlayerCursor.ODScoreTotal(),
points: -1,
deletedAt: validPlayerCursor.DeletedAt(),
@ -487,6 +515,7 @@ func TestNewPlayerCursor(t *testing.T) {
tt.args.serverKey,
tt.args.odScoreAtt,
tt.args.odScoreDef,
tt.args.odScoreSup,
tt.args.odScoreTotal,
tt.args.points,
tt.args.deletedAt,
@ -499,6 +528,7 @@ func TestNewPlayerCursor(t *testing.T) {
assert.Equal(t, tt.args.serverKey, tc.ServerKey())
assert.Equal(t, tt.args.odScoreAtt, tc.ODScoreAtt())
assert.Equal(t, tt.args.odScoreDef, tc.ODScoreDef())
assert.Equal(t, tt.args.odScoreSup, tc.ODScoreSup())
assert.Equal(t, tt.args.odScoreTotal, tc.ODScoreTotal())
assert.Equal(t, tt.args.points, tc.Points())
assert.Equal(t, tt.args.deletedAt, tc.DeletedAt())
@ -879,27 +909,31 @@ func TestListPlayersParams_PrependSortString(t *testing.T) {
},
},
{
name: "OK: [points:ASC, deletedAt:ASC]",
name: "OK: [odScoreSup:ASC, points:ASC, deletedAt:ASC]",
args: args{
sort: []string{
"odScoreSup:ASC",
"points:ASC",
"deletedAt:ASC",
},
},
expectedSort: []domain.PlayerSort{
domain.PlayerSortODScoreSupASC,
domain.PlayerSortPointsASC,
domain.PlayerSortDeletedAtASC,
},
},
{
name: "OK: [points:DESC, deletedAt:DESC]",
name: "OK: [odScoreSup:DESC, points:DESC, deletedAt:DESC]",
args: args{
sort: []string{
"odScoreSup:DESC",
"points:DESC",
"deletedAt:DESC",
},
},
expectedSort: []domain.PlayerSort{
domain.PlayerSortODScoreSupDESC,
domain.PlayerSortPointsDESC,
domain.PlayerSortDeletedAtDESC,
},