parent
34a5385224
commit
7d7c44e338
|
@ -1017,7 +1017,7 @@ components:
|
|||
- profileUrl
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
$ref: "#/components/schemas/IntId"
|
||||
name:
|
||||
type: string
|
||||
tag:
|
||||
|
@ -1097,6 +1097,22 @@ components:
|
|||
deletedAt:
|
||||
type: string
|
||||
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:
|
||||
type: object
|
||||
required:
|
||||
|
@ -1149,6 +1165,8 @@ components:
|
|||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
player:
|
||||
$ref: "#/components/schemas/PlayerMeta"
|
||||
Cursor:
|
||||
type: object
|
||||
x-go-type-skip-optional-pointer: true
|
||||
|
|
|
@ -97,6 +97,33 @@ func (repo *VillageBunRepository) List(
|
|||
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 {
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
|
|
|
@ -38,6 +38,10 @@ type playerRepository interface {
|
|||
type villageRepository interface {
|
||||
CreateOrUpdate(ctx context.Context, params ...domain.CreateVillageParams) 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
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
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)
|
||||
tt.assertError(t, err)
|
||||
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 {
|
||||
CreateOrUpdate(ctx context.Context, params ...domain.CreateVillageParams) 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
|
||||
}
|
||||
|
||||
|
@ -119,3 +123,10 @@ func (svc *VillageService) List(
|
|||
) (domain.ListVillagesResult, error) {
|
||||
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"
|
||||
)
|
||||
|
||||
var PlayerMetaColumns = []string{"id", "name", "profile_url"}
|
||||
|
||||
type Player struct {
|
||||
bun.BaseModel `bun:"table:players,alias:player"`
|
||||
|
||||
|
@ -77,6 +79,61 @@ func (p Player) ToDomain() (domain.Player, error) {
|
|||
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
|
||||
|
||||
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))
|
||||
|
||||
for _, p := range ps {
|
||||
var err error
|
||||
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()
|
||||
converted, err := p.ToDomainWithRelations()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = append(res, converted.WithRelations(tribe))
|
||||
res = append(res, converted)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
|
|
|
@ -51,6 +51,25 @@ func (v Village) ToDomain() (domain.Village, error) {
|
|||
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
|
||||
|
||||
func (vs Villages) ToDomain() (domain.Villages, error) {
|
||||
|
@ -67,3 +86,18 @@ func (vs Villages) ToDomain() (domain.Villages, error) {
|
|||
|
||||
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 {
|
||||
TribeID int
|
||||
PlayerOptions []func(cfg *PlayerConfig)
|
||||
}
|
||||
|
||||
func NewPlayerWithRelations(tb TestingTB, opts ...func(cfg *PlayerWithRelationsConfig)) domain.PlayerWithRelations {
|
||||
tb.Helper()
|
||||
|
||||
cfg := &PlayerWithRelationsConfig{
|
||||
TribeID: RandID(),
|
||||
}
|
||||
cfg := &PlayerWithRelationsConfig{}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(cfg)
|
||||
}
|
||||
|
||||
p := NewPlayer(tb, func(playerCfg *PlayerConfig) {
|
||||
playerCfg.TribeID = cfg.TribeID
|
||||
})
|
||||
p := NewPlayer(tb, cfg.PlayerOptions...)
|
||||
|
||||
var tribeMeta domain.TribeMeta
|
||||
if p.TribeID() > 0 {
|
||||
|
|
|
@ -70,3 +70,29 @@ func NewVillage(tb TestingTB, opts ...func(cfg *VillageConfig)) domain.Village {
|
|||
|
||||
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 {
|
||||
return BasePlayer{
|
||||
id: p.id,
|
||||
|
@ -261,8 +282,96 @@ func (p PlayerWithRelations) Tribe() NullTribeMeta {
|
|||
return p.tribe
|
||||
}
|
||||
|
||||
func (p PlayerWithRelations) Meta() PlayerMetaWithRelations {
|
||||
return PlayerMetaWithRelations{
|
||||
player: p.player.Meta(),
|
||||
tribe: p.tribe,
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -277,8 +386,6 @@ type CreatePlayerParams struct {
|
|||
lastActivityAt time.Time
|
||||
}
|
||||
|
||||
type PlayersWithRelations []PlayerWithRelations
|
||||
|
||||
const createPlayerParamsModelName = "CreatePlayerParams"
|
||||
|
||||
// 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 {
|
||||
od := players[0].OD()
|
||||
res.self, err = NewPlayerCursor(
|
||||
players[0].ID(),
|
||||
players[0].ServerKey(),
|
||||
od.ScoreAtt(),
|
||||
od.ScoreDef(),
|
||||
od.ScoreSup(),
|
||||
od.ScoreTotal(),
|
||||
players[0].Points(),
|
||||
players[0].DeletedAt(),
|
||||
)
|
||||
res.self, err = players[0].ToCursor()
|
||||
if err != nil {
|
||||
return ListPlayersResult{}, ValidationError{
|
||||
Model: listPlayersResultModelName,
|
||||
|
@ -955,17 +1052,7 @@ func NewListPlayersResult(players Players, next Player) (ListPlayersResult, erro
|
|||
}
|
||||
|
||||
if !next.IsZero() {
|
||||
od := next.OD()
|
||||
res.next, err = NewPlayerCursor(
|
||||
next.ID(),
|
||||
next.ServerKey(),
|
||||
od.ScoreAtt(),
|
||||
od.ScoreDef(),
|
||||
od.ScoreSup(),
|
||||
od.ScoreTotal(),
|
||||
next.Points(),
|
||||
next.DeletedAt(),
|
||||
)
|
||||
res.next, err = next.ToCursor()
|
||||
if err != nil {
|
||||
return ListPlayersResult{}, ValidationError{
|
||||
Model: listPlayersResultModelName,
|
||||
|
@ -1008,18 +1095,7 @@ func NewListPlayersWithRelationsResult(
|
|||
}
|
||||
|
||||
if len(players) > 0 {
|
||||
player := players[0].Player()
|
||||
od := player.OD()
|
||||
res.self, err = NewPlayerCursor(
|
||||
player.ID(),
|
||||
player.ServerKey(),
|
||||
od.ScoreAtt(),
|
||||
od.ScoreDef(),
|
||||
od.ScoreSup(),
|
||||
od.ScoreTotal(),
|
||||
player.Points(),
|
||||
player.DeletedAt(),
|
||||
)
|
||||
res.self, err = players[0].Player().ToCursor()
|
||||
if err != nil {
|
||||
return ListPlayersWithRelationsResult{}, ValidationError{
|
||||
Model: listPlayersWithRelationsResultModelName,
|
||||
|
@ -1030,18 +1106,7 @@ func NewListPlayersWithRelationsResult(
|
|||
}
|
||||
|
||||
if !next.IsZero() {
|
||||
player := next.Player()
|
||||
od := player.OD()
|
||||
res.next, err = NewPlayerCursor(
|
||||
player.ID(),
|
||||
player.ServerKey(),
|
||||
od.ScoreAtt(),
|
||||
od.ScoreDef(),
|
||||
od.ScoreSup(),
|
||||
od.ScoreTotal(),
|
||||
player.Points(),
|
||||
player.DeletedAt(),
|
||||
)
|
||||
res.next, err = next.Player().ToCursor()
|
||||
if err != nil {
|
||||
return ListPlayersWithRelationsResult{}, ValidationError{
|
||||
Model: listPlayersWithRelationsResultModelName,
|
||||
|
|
|
@ -195,8 +195,8 @@ func (s Server) EnnoblementDataSyncedAt() time.Time {
|
|||
return s.ennoblementDataSyncedAt
|
||||
}
|
||||
|
||||
func (s Server) IsZero() bool {
|
||||
return s == Server{}
|
||||
func (s Server) ToCursor() (ServerCursor, error) {
|
||||
return NewServerCursor(s.key, s.open)
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// 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 {
|
||||
res.self, err = NewServerCursor(servers[0].Key(), servers[0].Open())
|
||||
res.self, err = servers[0].ToCursor()
|
||||
if err != nil {
|
||||
return ListServersResult{}, ValidationError{
|
||||
Model: listServersResultModelName,
|
||||
|
@ -807,7 +811,7 @@ func NewListServersResult(servers Servers, next Server) (ListServersResult, erro
|
|||
}
|
||||
|
||||
if !next.IsZero() {
|
||||
res.next, err = NewServerCursor(next.Key(), next.Open())
|
||||
res.next, err = next.ToCursor()
|
||||
if err != nil {
|
||||
return ListServersResult{}, ValidationError{
|
||||
Model: listServersResultModelName,
|
||||
|
|
|
@ -197,8 +197,17 @@ func (t Tribe) DeletedAt() time.Time {
|
|||
return t.deletedAt
|
||||
}
|
||||
|
||||
func (t Tribe) IsDeleted() bool {
|
||||
return !t.deletedAt.IsZero()
|
||||
func (t Tribe) ToCursor() (TribeCursor, error) {
|
||||
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 {
|
||||
|
@ -225,6 +234,10 @@ func (t Tribe) Meta() TribeMeta {
|
|||
}
|
||||
}
|
||||
|
||||
func (t Tribe) IsDeleted() bool {
|
||||
return !t.deletedAt.IsZero()
|
||||
}
|
||||
|
||||
func (t Tribe) IsZero() bool {
|
||||
return t == Tribe{}
|
||||
}
|
||||
|
@ -931,17 +944,7 @@ func NewListTribesResult(tribes Tribes, next Tribe) (ListTribesResult, error) {
|
|||
}
|
||||
|
||||
if len(tribes) > 0 {
|
||||
od := tribes[0].OD()
|
||||
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(),
|
||||
)
|
||||
res.self, err = tribes[0].ToCursor()
|
||||
if err != nil {
|
||||
return ListTribesResult{}, ValidationError{
|
||||
Model: listTribesResultModelName,
|
||||
|
@ -952,17 +955,7 @@ func NewListTribesResult(tribes Tribes, next Tribe) (ListTribesResult, error) {
|
|||
}
|
||||
|
||||
if !next.IsZero() {
|
||||
od := next.OD()
|
||||
res.next, err = NewTribeCursor(
|
||||
next.ID(),
|
||||
next.ServerKey(),
|
||||
od.ScoreAtt(),
|
||||
od.ScoreDef(),
|
||||
od.ScoreTotal(),
|
||||
next.Points(),
|
||||
next.Dominance(),
|
||||
next.DeletedAt(),
|
||||
)
|
||||
res.next, err = next.ToCursor()
|
||||
if err != nil {
|
||||
return ListTribesResult{}, ValidationError{
|
||||
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 {
|
||||
return v == Version{}
|
||||
}
|
||||
|
@ -297,7 +301,7 @@ func NewListVersionsResult(versions Versions, next Version) (ListVersionsResult,
|
|||
}
|
||||
|
||||
if len(versions) > 0 {
|
||||
res.self, err = NewVersionCursor(versions[0].Code())
|
||||
res.self, err = versions[0].ToCursor()
|
||||
if err != nil {
|
||||
return ListVersionsResult{}, ValidationError{
|
||||
Model: listVersionsResultModelName,
|
||||
|
@ -308,7 +312,7 @@ func NewListVersionsResult(versions Versions, next Version) (ListVersionsResult,
|
|||
}
|
||||
|
||||
if !next.IsZero() {
|
||||
res.next, err = NewVersionCursor(next.Code())
|
||||
res.next, err = next.ToCursor()
|
||||
if err != nil {
|
||||
return ListVersionsResult{}, ValidationError{
|
||||
Model: listVersionsResultModelName,
|
||||
|
|
|
@ -137,6 +137,17 @@ func (v Village) CreatedAt() time.Time {
|
|||
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 {
|
||||
return BaseVillage{
|
||||
id: v.id,
|
||||
|
@ -183,6 +194,25 @@ func (vs Villages) Delete(serverKey string, active BaseVillages) []int {
|
|||
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 {
|
||||
base BaseVillage
|
||||
serverKey string
|
||||
|
@ -482,7 +512,7 @@ func NewListVillagesResult(villages Villages, next Village) (ListVillagesResult,
|
|||
}
|
||||
|
||||
if len(villages) > 0 {
|
||||
res.self, err = NewVillageCursor(villages[0].ID(), villages[0].ServerKey())
|
||||
res.self, err = villages[0].ToCursor()
|
||||
if err != nil {
|
||||
return ListVillagesResult{}, ValidationError{
|
||||
Model: listVillagesResultModelName,
|
||||
|
@ -493,7 +523,7 @@ func NewListVillagesResult(villages Villages, next Village) (ListVillagesResult,
|
|||
}
|
||||
|
||||
if !next.IsZero() {
|
||||
res.next, err = NewVillageCursor(next.ID(), next.ServerKey())
|
||||
res.next, err = next.ToCursor()
|
||||
if err != nil {
|
||||
return ListVillagesResult{}, ValidationError{
|
||||
Model: listVillagesResultModelName,
|
||||
|
@ -517,3 +547,57 @@ func (res ListVillagesResult) Self() VillageCursor {
|
|||
func (res ListVillagesResult) Next() VillageCursor {
|
||||
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())
|
||||
})
|
||||
}
|
||||
|
||||
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 {
|
||||
h.errorRenderer.render(w, r, err)
|
||||
return
|
||||
|
|
|
@ -46,6 +46,26 @@ func NewPlayer(withRelations domain.PlayerWithRelations) Player {
|
|||
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 {
|
||||
players := res.Players()
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@ import (
|
|||
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
|
||||
)
|
||||
|
||||
func NewVillage(v domain.Village) Village {
|
||||
func NewVillage(withRelations domain.VillageWithRelations) Village {
|
||||
v := withRelations.Village()
|
||||
return Village{
|
||||
Bonus: v.Bonus(),
|
||||
Continent: v.Continent(),
|
||||
|
@ -16,10 +17,11 @@ func NewVillage(v domain.Village) Village {
|
|||
ProfileUrl: v.ProfileURL().String(),
|
||||
X: v.X(),
|
||||
Y: v.Y(),
|
||||
Player: NewNullPlayerMeta(withRelations.Player()),
|
||||
}
|
||||
}
|
||||
|
||||
func NewListVillagesResponse(res domain.ListVillagesResult) ListVillagesResponse {
|
||||
func NewListVillagesResponse(res domain.ListVillagesWithRelationsResult) ListVillagesResponse {
|
||||
versions := res.Villages()
|
||||
|
||||
resp := ListVillagesResponse{
|
||||
|
|
Loading…
Reference in New Issue