parent
34a5385224
commit
7d7c44e338
|
@ -1017,7 +1017,7 @@ components:
|
||||||
- profileUrl
|
- profileUrl
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
type: integer
|
$ref: "#/components/schemas/IntId"
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
tag:
|
tag:
|
||||||
|
@ -1097,6 +1097,22 @@ components:
|
||||||
deletedAt:
|
deletedAt:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
|
PlayerMeta:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
- profileUrl
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
$ref: "#/components/schemas/IntId"
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
profileUrl:
|
||||||
|
type: string
|
||||||
|
format: uri
|
||||||
|
tribe:
|
||||||
|
$ref: "#/components/schemas/TribeMeta"
|
||||||
Village:
|
Village:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
|
@ -1149,6 +1165,8 @@ components:
|
||||||
createdAt:
|
createdAt:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
|
player:
|
||||||
|
$ref: "#/components/schemas/PlayerMeta"
|
||||||
Cursor:
|
Cursor:
|
||||||
type: object
|
type: object
|
||||||
x-go-type-skip-optional-pointer: true
|
x-go-type-skip-optional-pointer: true
|
||||||
|
|
|
@ -97,6 +97,33 @@ func (repo *VillageBunRepository) List(
|
||||||
return domain.NewListVillagesResult(separateListResultAndNext(converted, params.Limit()))
|
return domain.NewListVillagesResult(separateListResultAndNext(converted, params.Limit()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (repo *VillageBunRepository) ListWithRelations(
|
||||||
|
ctx context.Context,
|
||||||
|
params domain.ListVillagesParams,
|
||||||
|
) (domain.ListVillagesWithRelationsResult, error) {
|
||||||
|
var villages bunmodel.Villages
|
||||||
|
|
||||||
|
if err := repo.db.NewSelect().
|
||||||
|
Model(&villages).
|
||||||
|
Apply(listVillagesParamsApplier{params: params}.apply).
|
||||||
|
Relation("Player", func(q *bun.SelectQuery) *bun.SelectQuery {
|
||||||
|
return q.Column(bunmodel.PlayerMetaColumns...)
|
||||||
|
}).
|
||||||
|
Relation("Player.Tribe", func(q *bun.SelectQuery) *bun.SelectQuery {
|
||||||
|
return q.Column(bunmodel.TribeMetaColumns...)
|
||||||
|
}).
|
||||||
|
Scan(ctx); err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||||
|
return domain.ListVillagesWithRelationsResult{}, fmt.Errorf("couldn't select players from the db: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
converted, err := villages.ToDomainWithRelations()
|
||||||
|
if err != nil {
|
||||||
|
return domain.ListVillagesWithRelationsResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.NewListVillagesWithRelationsResult(separateListResultAndNext(converted, params.Limit()))
|
||||||
|
}
|
||||||
|
|
||||||
func (repo *VillageBunRepository) Delete(ctx context.Context, serverKey string, ids ...int) error {
|
func (repo *VillageBunRepository) Delete(ctx context.Context, serverKey string, ids ...int) error {
|
||||||
if len(ids) == 0 {
|
if len(ids) == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -38,6 +38,10 @@ type playerRepository interface {
|
||||||
type villageRepository interface {
|
type villageRepository interface {
|
||||||
CreateOrUpdate(ctx context.Context, params ...domain.CreateVillageParams) error
|
CreateOrUpdate(ctx context.Context, params ...domain.CreateVillageParams) error
|
||||||
List(ctx context.Context, params domain.ListVillagesParams) (domain.ListVillagesResult, error)
|
List(ctx context.Context, params domain.ListVillagesParams) (domain.ListVillagesResult, error)
|
||||||
|
ListWithRelations(
|
||||||
|
ctx context.Context,
|
||||||
|
params domain.ListVillagesParams,
|
||||||
|
) (domain.ListVillagesWithRelationsResult, error)
|
||||||
Delete(ctx context.Context, serverKey string, ids ...int) error
|
Delete(ctx context.Context, serverKey string, ids ...int) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ func testVillageRepository(t *testing.T, newRepos func(t *testing.T) repositorie
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("List", func(t *testing.T) {
|
t.Run("List & ListWithRelations", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
repos := newRepos(t)
|
repos := newRepos(t)
|
||||||
|
@ -339,6 +339,15 @@ func testVillageRepository(t *testing.T, newRepos func(t *testing.T) repositorie
|
||||||
res, err := repos.village.List(ctx, params)
|
res, err := repos.village.List(ctx, params)
|
||||||
tt.assertError(t, err)
|
tt.assertError(t, err)
|
||||||
tt.assertResult(t, params, res)
|
tt.assertResult(t, params, res)
|
||||||
|
|
||||||
|
resWithRelations, err := repos.village.ListWithRelations(ctx, params)
|
||||||
|
tt.assertError(t, err)
|
||||||
|
require.Len(t, resWithRelations.Villages(), len(res.Villages()))
|
||||||
|
for i, v := range resWithRelations.Villages() {
|
||||||
|
assert.Equal(t, res.Villages()[i], v.Village())
|
||||||
|
assert.Equal(t, v.Village().PlayerID(), v.Player().V.Player().ID())
|
||||||
|
assert.Equal(t, v.Village().PlayerID() != 0, v.Player().Valid)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -10,6 +10,10 @@ import (
|
||||||
type VillageRepository interface {
|
type VillageRepository interface {
|
||||||
CreateOrUpdate(ctx context.Context, params ...domain.CreateVillageParams) error
|
CreateOrUpdate(ctx context.Context, params ...domain.CreateVillageParams) error
|
||||||
List(ctx context.Context, params domain.ListVillagesParams) (domain.ListVillagesResult, error)
|
List(ctx context.Context, params domain.ListVillagesParams) (domain.ListVillagesResult, error)
|
||||||
|
ListWithRelations(
|
||||||
|
ctx context.Context,
|
||||||
|
params domain.ListVillagesParams,
|
||||||
|
) (domain.ListVillagesWithRelationsResult, error)
|
||||||
Delete(ctx context.Context, serverKey string, ids ...int) error
|
Delete(ctx context.Context, serverKey string, ids ...int) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,3 +123,10 @@ func (svc *VillageService) List(
|
||||||
) (domain.ListVillagesResult, error) {
|
) (domain.ListVillagesResult, error) {
|
||||||
return svc.repo.List(ctx, params)
|
return svc.repo.List(ctx, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (svc *VillageService) ListWithRelations(
|
||||||
|
ctx context.Context,
|
||||||
|
params domain.ListVillagesParams,
|
||||||
|
) (domain.ListVillagesWithRelationsResult, error) {
|
||||||
|
return svc.repo.ListWithRelations(ctx, params)
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ import (
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var PlayerMetaColumns = []string{"id", "name", "profile_url"}
|
||||||
|
|
||||||
type Player struct {
|
type Player struct {
|
||||||
bun.BaseModel `bun:"table:players,alias:player"`
|
bun.BaseModel `bun:"table:players,alias:player"`
|
||||||
|
|
||||||
|
@ -77,6 +79,61 @@ func (p Player) ToDomain() (domain.Player, error) {
|
||||||
return converted, nil
|
return converted, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Player) ToDomainWithRelations() (domain.PlayerWithRelations, error) {
|
||||||
|
converted, err := p.ToDomain()
|
||||||
|
if err != nil {
|
||||||
|
return domain.PlayerWithRelations{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tribe domain.NullTribeMeta
|
||||||
|
|
||||||
|
if p.Tribe.ID > 0 {
|
||||||
|
tribe.Valid = true
|
||||||
|
tribe.V, err = p.Tribe.ToMeta()
|
||||||
|
if err != nil {
|
||||||
|
return domain.PlayerWithRelations{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return converted.WithRelations(tribe), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Player) ToMeta() (domain.PlayerMeta, error) {
|
||||||
|
converted, err := domain.UnmarshalPlayerMetaFromDatabase(
|
||||||
|
p.ID,
|
||||||
|
p.Name,
|
||||||
|
p.ProfileURL,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return domain.PlayerMeta{}, fmt.Errorf(
|
||||||
|
"couldn't construct domain.TribeMeta (id=%d,serverKey=%s): %w",
|
||||||
|
p.ID,
|
||||||
|
p.ServerKey,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return converted, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Player) ToMetaWithRelations() (domain.PlayerMetaWithRelations, error) {
|
||||||
|
converted, err := p.ToMeta()
|
||||||
|
if err != nil {
|
||||||
|
return domain.PlayerMetaWithRelations{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tribe domain.NullTribeMeta
|
||||||
|
|
||||||
|
if p.Tribe.ID > 0 {
|
||||||
|
tribe.Valid = true
|
||||||
|
tribe.V, err = p.Tribe.ToMeta()
|
||||||
|
if err != nil {
|
||||||
|
return domain.PlayerMetaWithRelations{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return converted.WithRelations(tribe), nil
|
||||||
|
}
|
||||||
|
|
||||||
type Players []Player
|
type Players []Player
|
||||||
|
|
||||||
func (ps Players) ToDomain() (domain.Players, error) {
|
func (ps Players) ToDomain() (domain.Players, error) {
|
||||||
|
@ -98,23 +155,12 @@ func (ps Players) ToDomainWithRelations() (domain.PlayersWithRelations, error) {
|
||||||
res := make(domain.PlayersWithRelations, 0, len(ps))
|
res := make(domain.PlayersWithRelations, 0, len(ps))
|
||||||
|
|
||||||
for _, p := range ps {
|
for _, p := range ps {
|
||||||
var err error
|
converted, err := p.ToDomainWithRelations()
|
||||||
var tribe domain.NullTribeMeta
|
|
||||||
|
|
||||||
if p.Tribe.ID > 0 {
|
|
||||||
tribe.Valid = true
|
|
||||||
tribe.V, err = p.Tribe.ToMeta()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
converted, err := p.ToDomain()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
res = append(res, converted.WithRelations(tribe))
|
res = append(res, converted)
|
||||||
}
|
}
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
|
|
|
@ -51,6 +51,25 @@ func (v Village) ToDomain() (domain.Village, error) {
|
||||||
return converted, nil
|
return converted, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v Village) ToDomainWithRelations() (domain.VillageWithRelations, error) {
|
||||||
|
converted, err := v.ToDomain()
|
||||||
|
if err != nil {
|
||||||
|
return domain.VillageWithRelations{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tribe domain.NullPlayerMetaWithRelations
|
||||||
|
|
||||||
|
if v.Player.ID > 0 {
|
||||||
|
tribe.Valid = true
|
||||||
|
tribe.V, err = v.Player.ToMetaWithRelations()
|
||||||
|
if err != nil {
|
||||||
|
return domain.VillageWithRelations{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return converted.WithRelations(tribe), nil
|
||||||
|
}
|
||||||
|
|
||||||
type Villages []Village
|
type Villages []Village
|
||||||
|
|
||||||
func (vs Villages) ToDomain() (domain.Villages, error) {
|
func (vs Villages) ToDomain() (domain.Villages, error) {
|
||||||
|
@ -67,3 +86,18 @@ func (vs Villages) ToDomain() (domain.Villages, error) {
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (vs Villages) ToDomainWithRelations() (domain.VillagesWithRelations, error) {
|
||||||
|
res := make(domain.VillagesWithRelations, 0, len(vs))
|
||||||
|
|
||||||
|
for _, v := range vs {
|
||||||
|
converted, err := v.ToDomainWithRelations()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res = append(res, converted)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
|
@ -122,23 +122,19 @@ func NewPlayer(tb TestingTB, opts ...func(cfg *PlayerConfig)) domain.Player {
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlayerWithRelationsConfig struct {
|
type PlayerWithRelationsConfig struct {
|
||||||
TribeID int
|
PlayerOptions []func(cfg *PlayerConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPlayerWithRelations(tb TestingTB, opts ...func(cfg *PlayerWithRelationsConfig)) domain.PlayerWithRelations {
|
func NewPlayerWithRelations(tb TestingTB, opts ...func(cfg *PlayerWithRelationsConfig)) domain.PlayerWithRelations {
|
||||||
tb.Helper()
|
tb.Helper()
|
||||||
|
|
||||||
cfg := &PlayerWithRelationsConfig{
|
cfg := &PlayerWithRelationsConfig{}
|
||||||
TribeID: RandID(),
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(cfg)
|
opt(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
p := NewPlayer(tb, func(playerCfg *PlayerConfig) {
|
p := NewPlayer(tb, cfg.PlayerOptions...)
|
||||||
playerCfg.TribeID = cfg.TribeID
|
|
||||||
})
|
|
||||||
|
|
||||||
var tribeMeta domain.TribeMeta
|
var tribeMeta domain.TribeMeta
|
||||||
if p.TribeID() > 0 {
|
if p.TribeID() > 0 {
|
||||||
|
|
|
@ -70,3 +70,29 @@ func NewVillage(tb TestingTB, opts ...func(cfg *VillageConfig)) domain.Village {
|
||||||
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VillageWithRelationsConfig struct {
|
||||||
|
PlayerOptions []func(cfg *PlayerWithRelationsConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVillageWithRelations(tb TestingTB, opts ...func(cfg *VillageWithRelationsConfig)) domain.VillageWithRelations {
|
||||||
|
tb.Helper()
|
||||||
|
|
||||||
|
cfg := &VillageWithRelationsConfig{}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
v := NewVillage(tb)
|
||||||
|
|
||||||
|
var playerMeta domain.PlayerMetaWithRelations
|
||||||
|
if v.PlayerID() > 0 {
|
||||||
|
playerMeta = NewPlayerWithRelations(tb, cfg.PlayerOptions...).Meta()
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.WithRelations(domain.NullPlayerMetaWithRelations{
|
||||||
|
V: playerMeta,
|
||||||
|
Valid: !playerMeta.IsZero(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -188,6 +188,27 @@ func (p Player) WithRelations(tribe NullTribeMeta) PlayerWithRelations {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Player) ToCursor() (PlayerCursor, error) {
|
||||||
|
return NewPlayerCursor(
|
||||||
|
p.id,
|
||||||
|
p.serverKey,
|
||||||
|
p.od.scoreAtt,
|
||||||
|
p.od.scoreDef,
|
||||||
|
p.od.scoreSup,
|
||||||
|
p.od.scoreTotal,
|
||||||
|
p.points,
|
||||||
|
p.deletedAt,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Player) Meta() PlayerMeta {
|
||||||
|
return PlayerMeta{
|
||||||
|
id: p.id,
|
||||||
|
name: p.name,
|
||||||
|
profileURL: p.profileURL,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p Player) Base() BasePlayer {
|
func (p Player) Base() BasePlayer {
|
||||||
return BasePlayer{
|
return BasePlayer{
|
||||||
id: p.id,
|
id: p.id,
|
||||||
|
@ -261,8 +282,96 @@ func (p PlayerWithRelations) Tribe() NullTribeMeta {
|
||||||
return p.tribe
|
return p.tribe
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p PlayerWithRelations) Meta() PlayerMetaWithRelations {
|
||||||
|
return PlayerMetaWithRelations{
|
||||||
|
player: p.player.Meta(),
|
||||||
|
tribe: p.tribe,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p PlayerWithRelations) IsZero() bool {
|
func (p PlayerWithRelations) IsZero() bool {
|
||||||
return p.player.IsZero() && p.tribe.IsZero()
|
return p.player.IsZero()
|
||||||
|
}
|
||||||
|
|
||||||
|
type PlayersWithRelations []PlayerWithRelations
|
||||||
|
|
||||||
|
type PlayerMeta struct {
|
||||||
|
id int
|
||||||
|
name string
|
||||||
|
profileURL *url.URL
|
||||||
|
}
|
||||||
|
|
||||||
|
const playerMetaModelName = "PlayerMeta"
|
||||||
|
|
||||||
|
// UnmarshalPlayerMetaFromDatabase unmarshals PlayerMeta from the database.
|
||||||
|
//
|
||||||
|
// It should be used only for unmarshalling from the database!
|
||||||
|
// You can't use UnmarshalPlayerMetaFromDatabase as constructor - It may put domain into the invalid state!
|
||||||
|
func UnmarshalPlayerMetaFromDatabase(id int, name string, rawProfileURL string) (PlayerMeta, error) {
|
||||||
|
if err := validateIntInRange(id, 1, math.MaxInt); err != nil {
|
||||||
|
return PlayerMeta{}, ValidationError{
|
||||||
|
Model: playerMetaModelName,
|
||||||
|
Field: "id",
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
profileURL, err := parseURL(rawProfileURL)
|
||||||
|
if err != nil {
|
||||||
|
return PlayerMeta{}, ValidationError{
|
||||||
|
Model: playerMetaModelName,
|
||||||
|
Field: "profileURL",
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PlayerMeta{id: id, name: name, profileURL: profileURL}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PlayerMeta) ID() int {
|
||||||
|
return p.id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PlayerMeta) Name() string {
|
||||||
|
return p.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PlayerMeta) ProfileURL() *url.URL {
|
||||||
|
return p.profileURL
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PlayerMeta) IsZero() bool {
|
||||||
|
return p == PlayerMeta{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PlayerMeta) WithRelations(tribe NullTribeMeta) PlayerMetaWithRelations {
|
||||||
|
return PlayerMetaWithRelations{
|
||||||
|
player: p,
|
||||||
|
tribe: tribe,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PlayerMetaWithRelations struct {
|
||||||
|
player PlayerMeta
|
||||||
|
tribe NullTribeMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PlayerMetaWithRelations) Player() PlayerMeta {
|
||||||
|
return p.player
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PlayerMetaWithRelations) Tribe() NullTribeMeta {
|
||||||
|
return p.tribe
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PlayerMetaWithRelations) IsZero() bool {
|
||||||
|
return p.player.IsZero()
|
||||||
|
}
|
||||||
|
|
||||||
|
type NullPlayerMetaWithRelations NullValue[PlayerMetaWithRelations]
|
||||||
|
|
||||||
|
func (p NullPlayerMetaWithRelations) IsZero() bool {
|
||||||
|
return !p.Valid
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreatePlayerParams struct {
|
type CreatePlayerParams struct {
|
||||||
|
@ -277,8 +386,6 @@ type CreatePlayerParams struct {
|
||||||
lastActivityAt time.Time
|
lastActivityAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlayersWithRelations []PlayerWithRelations
|
|
||||||
|
|
||||||
const createPlayerParamsModelName = "CreatePlayerParams"
|
const createPlayerParamsModelName = "CreatePlayerParams"
|
||||||
|
|
||||||
// NewCreatePlayerParams constructs a slice of CreatePlayerParams based on the given parameters.
|
// NewCreatePlayerParams constructs a slice of CreatePlayerParams based on the given parameters.
|
||||||
|
@ -934,17 +1041,7 @@ func NewListPlayersResult(players Players, next Player) (ListPlayersResult, erro
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(players) > 0 {
|
if len(players) > 0 {
|
||||||
od := players[0].OD()
|
res.self, err = players[0].ToCursor()
|
||||||
res.self, err = NewPlayerCursor(
|
|
||||||
players[0].ID(),
|
|
||||||
players[0].ServerKey(),
|
|
||||||
od.ScoreAtt(),
|
|
||||||
od.ScoreDef(),
|
|
||||||
od.ScoreSup(),
|
|
||||||
od.ScoreTotal(),
|
|
||||||
players[0].Points(),
|
|
||||||
players[0].DeletedAt(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ListPlayersResult{}, ValidationError{
|
return ListPlayersResult{}, ValidationError{
|
||||||
Model: listPlayersResultModelName,
|
Model: listPlayersResultModelName,
|
||||||
|
@ -955,17 +1052,7 @@ func NewListPlayersResult(players Players, next Player) (ListPlayersResult, erro
|
||||||
}
|
}
|
||||||
|
|
||||||
if !next.IsZero() {
|
if !next.IsZero() {
|
||||||
od := next.OD()
|
res.next, err = next.ToCursor()
|
||||||
res.next, err = NewPlayerCursor(
|
|
||||||
next.ID(),
|
|
||||||
next.ServerKey(),
|
|
||||||
od.ScoreAtt(),
|
|
||||||
od.ScoreDef(),
|
|
||||||
od.ScoreSup(),
|
|
||||||
od.ScoreTotal(),
|
|
||||||
next.Points(),
|
|
||||||
next.DeletedAt(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ListPlayersResult{}, ValidationError{
|
return ListPlayersResult{}, ValidationError{
|
||||||
Model: listPlayersResultModelName,
|
Model: listPlayersResultModelName,
|
||||||
|
@ -1008,18 +1095,7 @@ func NewListPlayersWithRelationsResult(
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(players) > 0 {
|
if len(players) > 0 {
|
||||||
player := players[0].Player()
|
res.self, err = players[0].Player().ToCursor()
|
||||||
od := player.OD()
|
|
||||||
res.self, err = NewPlayerCursor(
|
|
||||||
player.ID(),
|
|
||||||
player.ServerKey(),
|
|
||||||
od.ScoreAtt(),
|
|
||||||
od.ScoreDef(),
|
|
||||||
od.ScoreSup(),
|
|
||||||
od.ScoreTotal(),
|
|
||||||
player.Points(),
|
|
||||||
player.DeletedAt(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ListPlayersWithRelationsResult{}, ValidationError{
|
return ListPlayersWithRelationsResult{}, ValidationError{
|
||||||
Model: listPlayersWithRelationsResultModelName,
|
Model: listPlayersWithRelationsResultModelName,
|
||||||
|
@ -1030,18 +1106,7 @@ func NewListPlayersWithRelationsResult(
|
||||||
}
|
}
|
||||||
|
|
||||||
if !next.IsZero() {
|
if !next.IsZero() {
|
||||||
player := next.Player()
|
res.next, err = next.Player().ToCursor()
|
||||||
od := player.OD()
|
|
||||||
res.next, err = NewPlayerCursor(
|
|
||||||
player.ID(),
|
|
||||||
player.ServerKey(),
|
|
||||||
od.ScoreAtt(),
|
|
||||||
od.ScoreDef(),
|
|
||||||
od.ScoreSup(),
|
|
||||||
od.ScoreTotal(),
|
|
||||||
player.Points(),
|
|
||||||
player.DeletedAt(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ListPlayersWithRelationsResult{}, ValidationError{
|
return ListPlayersWithRelationsResult{}, ValidationError{
|
||||||
Model: listPlayersWithRelationsResultModelName,
|
Model: listPlayersWithRelationsResultModelName,
|
||||||
|
|
|
@ -195,8 +195,8 @@ func (s Server) EnnoblementDataSyncedAt() time.Time {
|
||||||
return s.ennoblementDataSyncedAt
|
return s.ennoblementDataSyncedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Server) IsZero() bool {
|
func (s Server) ToCursor() (ServerCursor, error) {
|
||||||
return s == Server{}
|
return NewServerCursor(s.key, s.open)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Server) Base() BaseServer {
|
func (s Server) Base() BaseServer {
|
||||||
|
@ -207,6 +207,10 @@ func (s Server) Base() BaseServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s Server) IsZero() bool {
|
||||||
|
return s == Server{}
|
||||||
|
}
|
||||||
|
|
||||||
type Servers []Server
|
type Servers []Server
|
||||||
|
|
||||||
// Close finds all servers with Server.Open returning true that are not in the given slice with open servers
|
// Close finds all servers with Server.Open returning true that are not in the given slice with open servers
|
||||||
|
@ -796,7 +800,7 @@ func NewListServersResult(servers Servers, next Server) (ListServersResult, erro
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(servers) > 0 {
|
if len(servers) > 0 {
|
||||||
res.self, err = NewServerCursor(servers[0].Key(), servers[0].Open())
|
res.self, err = servers[0].ToCursor()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ListServersResult{}, ValidationError{
|
return ListServersResult{}, ValidationError{
|
||||||
Model: listServersResultModelName,
|
Model: listServersResultModelName,
|
||||||
|
@ -807,7 +811,7 @@ func NewListServersResult(servers Servers, next Server) (ListServersResult, erro
|
||||||
}
|
}
|
||||||
|
|
||||||
if !next.IsZero() {
|
if !next.IsZero() {
|
||||||
res.next, err = NewServerCursor(next.Key(), next.Open())
|
res.next, err = next.ToCursor()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ListServersResult{}, ValidationError{
|
return ListServersResult{}, ValidationError{
|
||||||
Model: listServersResultModelName,
|
Model: listServersResultModelName,
|
||||||
|
|
|
@ -197,8 +197,17 @@ func (t Tribe) DeletedAt() time.Time {
|
||||||
return t.deletedAt
|
return t.deletedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tribe) IsDeleted() bool {
|
func (t Tribe) ToCursor() (TribeCursor, error) {
|
||||||
return !t.deletedAt.IsZero()
|
return NewTribeCursor(
|
||||||
|
t.id,
|
||||||
|
t.serverKey,
|
||||||
|
t.od.scoreAtt,
|
||||||
|
t.od.scoreDef,
|
||||||
|
t.od.scoreTotal,
|
||||||
|
t.points,
|
||||||
|
t.dominance,
|
||||||
|
t.deletedAt,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tribe) Base() BaseTribe {
|
func (t Tribe) Base() BaseTribe {
|
||||||
|
@ -225,6 +234,10 @@ func (t Tribe) Meta() TribeMeta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t Tribe) IsDeleted() bool {
|
||||||
|
return !t.deletedAt.IsZero()
|
||||||
|
}
|
||||||
|
|
||||||
func (t Tribe) IsZero() bool {
|
func (t Tribe) IsZero() bool {
|
||||||
return t == Tribe{}
|
return t == Tribe{}
|
||||||
}
|
}
|
||||||
|
@ -931,17 +944,7 @@ func NewListTribesResult(tribes Tribes, next Tribe) (ListTribesResult, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(tribes) > 0 {
|
if len(tribes) > 0 {
|
||||||
od := tribes[0].OD()
|
res.self, err = tribes[0].ToCursor()
|
||||||
res.self, err = NewTribeCursor(
|
|
||||||
tribes[0].ID(),
|
|
||||||
tribes[0].ServerKey(),
|
|
||||||
od.ScoreAtt(),
|
|
||||||
od.ScoreDef(),
|
|
||||||
od.ScoreTotal(),
|
|
||||||
tribes[0].Points(),
|
|
||||||
tribes[0].Dominance(),
|
|
||||||
tribes[0].DeletedAt(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ListTribesResult{}, ValidationError{
|
return ListTribesResult{}, ValidationError{
|
||||||
Model: listTribesResultModelName,
|
Model: listTribesResultModelName,
|
||||||
|
@ -952,17 +955,7 @@ func NewListTribesResult(tribes Tribes, next Tribe) (ListTribesResult, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !next.IsZero() {
|
if !next.IsZero() {
|
||||||
od := next.OD()
|
res.next, err = next.ToCursor()
|
||||||
res.next, err = NewTribeCursor(
|
|
||||||
next.ID(),
|
|
||||||
next.ServerKey(),
|
|
||||||
od.ScoreAtt(),
|
|
||||||
od.ScoreDef(),
|
|
||||||
od.ScoreTotal(),
|
|
||||||
next.Points(),
|
|
||||||
next.Dominance(),
|
|
||||||
next.DeletedAt(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ListTribesResult{}, ValidationError{
|
return ListTribesResult{}, ValidationError{
|
||||||
Model: listTribesResultModelName,
|
Model: listTribesResultModelName,
|
||||||
|
|
|
@ -88,6 +88,10 @@ func (v Version) URL() *url.URL {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v Version) ToCursor() (VersionCursor, error) {
|
||||||
|
return NewVersionCursor(v.code)
|
||||||
|
}
|
||||||
|
|
||||||
func (v Version) IsZero() bool {
|
func (v Version) IsZero() bool {
|
||||||
return v == Version{}
|
return v == Version{}
|
||||||
}
|
}
|
||||||
|
@ -297,7 +301,7 @@ func NewListVersionsResult(versions Versions, next Version) (ListVersionsResult,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(versions) > 0 {
|
if len(versions) > 0 {
|
||||||
res.self, err = NewVersionCursor(versions[0].Code())
|
res.self, err = versions[0].ToCursor()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ListVersionsResult{}, ValidationError{
|
return ListVersionsResult{}, ValidationError{
|
||||||
Model: listVersionsResultModelName,
|
Model: listVersionsResultModelName,
|
||||||
|
@ -308,7 +312,7 @@ func NewListVersionsResult(versions Versions, next Version) (ListVersionsResult,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !next.IsZero() {
|
if !next.IsZero() {
|
||||||
res.next, err = NewVersionCursor(next.Code())
|
res.next, err = next.ToCursor()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ListVersionsResult{}, ValidationError{
|
return ListVersionsResult{}, ValidationError{
|
||||||
Model: listVersionsResultModelName,
|
Model: listVersionsResultModelName,
|
||||||
|
|
|
@ -137,6 +137,17 @@ func (v Village) CreatedAt() time.Time {
|
||||||
return v.createdAt
|
return v.createdAt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v Village) WithRelations(player NullPlayerMetaWithRelations) VillageWithRelations {
|
||||||
|
return VillageWithRelations{
|
||||||
|
village: v,
|
||||||
|
player: player,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Village) ToCursor() (VillageCursor, error) {
|
||||||
|
return NewVillageCursor(v.id, v.serverKey)
|
||||||
|
}
|
||||||
|
|
||||||
func (v Village) Base() BaseVillage {
|
func (v Village) Base() BaseVillage {
|
||||||
return BaseVillage{
|
return BaseVillage{
|
||||||
id: v.id,
|
id: v.id,
|
||||||
|
@ -183,6 +194,25 @@ func (vs Villages) Delete(serverKey string, active BaseVillages) []int {
|
||||||
return toDelete
|
return toDelete
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VillageWithRelations struct {
|
||||||
|
village Village
|
||||||
|
player NullPlayerMetaWithRelations
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v VillageWithRelations) Village() Village {
|
||||||
|
return v.village
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v VillageWithRelations) Player() NullPlayerMetaWithRelations {
|
||||||
|
return v.player
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v VillageWithRelations) IsZero() bool {
|
||||||
|
return v.village.IsZero()
|
||||||
|
}
|
||||||
|
|
||||||
|
type VillagesWithRelations []VillageWithRelations
|
||||||
|
|
||||||
type CreateVillageParams struct {
|
type CreateVillageParams struct {
|
||||||
base BaseVillage
|
base BaseVillage
|
||||||
serverKey string
|
serverKey string
|
||||||
|
@ -482,7 +512,7 @@ func NewListVillagesResult(villages Villages, next Village) (ListVillagesResult,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(villages) > 0 {
|
if len(villages) > 0 {
|
||||||
res.self, err = NewVillageCursor(villages[0].ID(), villages[0].ServerKey())
|
res.self, err = villages[0].ToCursor()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ListVillagesResult{}, ValidationError{
|
return ListVillagesResult{}, ValidationError{
|
||||||
Model: listVillagesResultModelName,
|
Model: listVillagesResultModelName,
|
||||||
|
@ -493,7 +523,7 @@ func NewListVillagesResult(villages Villages, next Village) (ListVillagesResult,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !next.IsZero() {
|
if !next.IsZero() {
|
||||||
res.next, err = NewVillageCursor(next.ID(), next.ServerKey())
|
res.next, err = next.ToCursor()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ListVillagesResult{}, ValidationError{
|
return ListVillagesResult{}, ValidationError{
|
||||||
Model: listVillagesResultModelName,
|
Model: listVillagesResultModelName,
|
||||||
|
@ -517,3 +547,57 @@ func (res ListVillagesResult) Self() VillageCursor {
|
||||||
func (res ListVillagesResult) Next() VillageCursor {
|
func (res ListVillagesResult) Next() VillageCursor {
|
||||||
return res.next
|
return res.next
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ListVillagesWithRelationsResult struct {
|
||||||
|
villages VillagesWithRelations
|
||||||
|
self VillageCursor
|
||||||
|
next VillageCursor
|
||||||
|
}
|
||||||
|
|
||||||
|
const listVillagesWithRelationsResultModelName = "ListVillagesWithRelationsResult"
|
||||||
|
|
||||||
|
func NewListVillagesWithRelationsResult(
|
||||||
|
villages VillagesWithRelations,
|
||||||
|
next VillageWithRelations,
|
||||||
|
) (ListVillagesWithRelationsResult, error) {
|
||||||
|
var err error
|
||||||
|
res := ListVillagesWithRelationsResult{
|
||||||
|
villages: villages,
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(villages) > 0 {
|
||||||
|
res.self, err = villages[0].Village().ToCursor()
|
||||||
|
if err != nil {
|
||||||
|
return ListVillagesWithRelationsResult{}, ValidationError{
|
||||||
|
Model: listVillagesWithRelationsResultModelName,
|
||||||
|
Field: "self",
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !next.IsZero() {
|
||||||
|
res.next, err = next.Village().ToCursor()
|
||||||
|
if err != nil {
|
||||||
|
return ListVillagesWithRelationsResult{}, ValidationError{
|
||||||
|
Model: listVillagesWithRelationsResultModelName,
|
||||||
|
Field: "next",
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (res ListVillagesWithRelationsResult) Villages() VillagesWithRelations {
|
||||||
|
return res.villages
|
||||||
|
}
|
||||||
|
|
||||||
|
func (res ListVillagesWithRelationsResult) Self() VillageCursor {
|
||||||
|
return res.self
|
||||||
|
}
|
||||||
|
|
||||||
|
func (res ListVillagesWithRelationsResult) Next() VillageCursor {
|
||||||
|
return res.next
|
||||||
|
}
|
||||||
|
|
|
@ -612,3 +612,47 @@ func TestNewListVillagesResult(t *testing.T) {
|
||||||
assert.True(t, res.Next().IsZero())
|
assert.True(t, res.Next().IsZero())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewListVillagesWithRelationsResult(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
villages := domain.VillagesWithRelations{
|
||||||
|
domaintest.NewVillageWithRelations(t),
|
||||||
|
domaintest.NewVillageWithRelations(t),
|
||||||
|
domaintest.NewVillageWithRelations(t),
|
||||||
|
}
|
||||||
|
next := domaintest.NewVillageWithRelations(t)
|
||||||
|
|
||||||
|
t.Run("OK: with next", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
res, err := domain.NewListVillagesWithRelationsResult(villages, next)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, villages, res.Villages())
|
||||||
|
assert.Equal(t, villages[0].Village().ID(), res.Self().ID())
|
||||||
|
assert.Equal(t, villages[0].Village().ServerKey(), res.Self().ServerKey())
|
||||||
|
assert.Equal(t, next.Village().ID(), res.Next().ID())
|
||||||
|
assert.Equal(t, next.Village().ServerKey(), res.Next().ServerKey())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("OK: without next", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
res, err := domain.NewListVillagesWithRelationsResult(villages, domain.VillageWithRelations{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, villages, res.Villages())
|
||||||
|
assert.Equal(t, villages[0].Village().ID(), res.Self().ID())
|
||||||
|
assert.Equal(t, villages[0].Village().ServerKey(), res.Self().ServerKey())
|
||||||
|
assert.True(t, res.Next().IsZero())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("OK: 0 villages", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
res, err := domain.NewListVillagesWithRelationsResult(nil, domain.VillageWithRelations{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Zero(t, res.Villages())
|
||||||
|
assert.True(t, res.Self().IsZero())
|
||||||
|
assert.True(t, res.Next().IsZero())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ func (h *apiHTTPHandler) ListVillages(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := h.villageSvc.List(r.Context(), domainParams)
|
res, err := h.villageSvc.ListWithRelations(r.Context(), domainParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.errorRenderer.render(w, r, err)
|
h.errorRenderer.render(w, r, err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -46,6 +46,26 @@ func NewPlayer(withRelations domain.PlayerWithRelations) Player {
|
||||||
return converted
|
return converted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewPlayerMeta(withRelations domain.PlayerMetaWithRelations) PlayerMeta {
|
||||||
|
p := withRelations.Player()
|
||||||
|
return PlayerMeta{
|
||||||
|
Id: p.ID(),
|
||||||
|
Name: p.Name(),
|
||||||
|
ProfileUrl: p.ProfileURL().String(),
|
||||||
|
Tribe: NewNullTribeMeta(withRelations.Tribe()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNullPlayerMeta(p domain.NullPlayerMetaWithRelations) *PlayerMeta {
|
||||||
|
if !p.Valid {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
converted := NewPlayerMeta(p.V)
|
||||||
|
|
||||||
|
return &converted
|
||||||
|
}
|
||||||
|
|
||||||
func NewListPlayersResponse(res domain.ListPlayersWithRelationsResult) ListPlayersResponse {
|
func NewListPlayersResponse(res domain.ListPlayersWithRelationsResult) ListPlayersResponse {
|
||||||
players := res.Players()
|
players := res.Players()
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@ import (
|
||||||
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
|
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewVillage(v domain.Village) Village {
|
func NewVillage(withRelations domain.VillageWithRelations) Village {
|
||||||
|
v := withRelations.Village()
|
||||||
return Village{
|
return Village{
|
||||||
Bonus: v.Bonus(),
|
Bonus: v.Bonus(),
|
||||||
Continent: v.Continent(),
|
Continent: v.Continent(),
|
||||||
|
@ -16,10 +17,11 @@ func NewVillage(v domain.Village) Village {
|
||||||
ProfileUrl: v.ProfileURL().String(),
|
ProfileUrl: v.ProfileURL().String(),
|
||||||
X: v.X(),
|
X: v.X(),
|
||||||
Y: v.Y(),
|
Y: v.Y(),
|
||||||
|
Player: NewNullPlayerMeta(withRelations.Player()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewListVillagesResponse(res domain.ListVillagesResult) ListVillagesResponse {
|
func NewListVillagesResponse(res domain.ListVillagesWithRelationsResult) ListVillagesResponse {
|
||||||
versions := res.Villages()
|
versions := res.Villages()
|
||||||
|
|
||||||
resp := ListVillagesResponse{
|
resp := ListVillagesResponse{
|
||||||
|
|
Loading…
Reference in New Issue