core/internal/domain/ennoblement.go

699 lines
15 KiB
Go

package domain
import (
"fmt"
"math"
"time"
)
const EnnoblementRetentionForClosedServers = 365 * 24 * time.Hour
type Ennoblement struct {
id int
serverKey string
villageID int
newOwnerID int
newTribeID int
oldOwnerID int
oldTribeID int
points int
createdAt time.Time
}
const ennoblementModelName = "Ennoblement"
// UnmarshalEnnoblementFromDatabase unmarshals Ennoblement from the database.
//
// It should be used only for unmarshalling from the database!
// You can't use UnmarshalEnnoblementFromDatabase as constructor - It may put domain into the invalid state!
func UnmarshalEnnoblementFromDatabase(
id int,
serverKey string,
villageID int,
newOwnerID int,
newTribeID int,
oldOwnerID int,
oldTribeID int,
points int,
createdAt time.Time,
) (Ennoblement, error) {
if err := validateIntInRange(id, 1, math.MaxInt); err != nil {
return Ennoblement{}, ValidationError{
Model: ennoblementModelName,
Field: "id",
Err: err,
}
}
if err := validateServerKey(serverKey); err != nil {
return Ennoblement{}, ValidationError{
Model: ennoblementModelName,
Field: "serverKey",
Err: err,
}
}
return Ennoblement{
id: id,
serverKey: serverKey,
villageID: villageID,
newOwnerID: newOwnerID,
newTribeID: newTribeID,
oldOwnerID: oldOwnerID,
oldTribeID: oldTribeID,
points: points,
createdAt: createdAt,
}, nil
}
func (e Ennoblement) ID() int {
return e.id
}
func (e Ennoblement) ServerKey() string {
return e.serverKey
}
func (e Ennoblement) VillageID() int {
return e.villageID
}
func (e Ennoblement) NewOwnerID() int {
return e.newOwnerID
}
func (e Ennoblement) NewTribeID() int {
return e.newTribeID
}
func (e Ennoblement) OldOwnerID() int {
return e.oldOwnerID
}
func (e Ennoblement) OldTribeID() int {
return e.oldTribeID
}
func (e Ennoblement) Points() int {
return e.points
}
func (e Ennoblement) CreatedAt() time.Time {
return e.createdAt
}
func (e Ennoblement) WithRelations(
village VillageMeta,
newOwner PlayerMeta,
newTribe NullTribeMeta,
oldOwner NullPlayerMeta,
oldTribe NullTribeMeta,
) EnnoblementWithRelations {
return EnnoblementWithRelations{
ennoblement: e,
village: village,
newOwner: newOwner,
newTribe: newTribe,
oldOwner: oldOwner,
oldTribe: oldTribe,
}
}
func (e Ennoblement) ToCursor() (EnnoblementCursor, error) {
return NewEnnoblementCursor(e.id, e.serverKey, e.createdAt)
}
func (e Ennoblement) Base() BaseEnnoblement {
return BaseEnnoblement{
villageID: e.villageID,
newOwnerID: e.newOwnerID,
newTribeID: e.newTribeID,
oldOwnerID: e.oldOwnerID,
oldTribeID: e.oldTribeID,
points: e.points,
createdAt: e.createdAt,
}
}
func (e Ennoblement) IsZero() bool {
return e == Ennoblement{}
}
type Ennoblements []Ennoblement
type EnnoblementWithRelations struct {
ennoblement Ennoblement
village VillageMeta
newOwner PlayerMeta
newTribe NullTribeMeta
oldOwner NullPlayerMeta
oldTribe NullTribeMeta
}
func (e EnnoblementWithRelations) Ennoblement() Ennoblement {
return e.ennoblement
}
func (e EnnoblementWithRelations) Village() VillageMeta {
return e.village
}
func (e EnnoblementWithRelations) NewOwner() PlayerMeta {
return e.newOwner
}
func (e EnnoblementWithRelations) NewTribe() NullTribeMeta {
return e.newTribe
}
func (e EnnoblementWithRelations) OldOwner() NullPlayerMeta {
return e.oldOwner
}
func (e EnnoblementWithRelations) OldTribe() NullTribeMeta {
return e.oldTribe
}
func (e EnnoblementWithRelations) IsZero() bool {
return e.ennoblement.IsZero()
}
type EnnoblementsWithRelations []EnnoblementWithRelations
type CreateEnnoblementParams struct {
base BaseEnnoblement
serverKey string
}
const createEnnoblementParamsModelName = "CreateEnnoblementParams"
func NewCreateEnnoblementParams(serverKey string, ennoblements BaseEnnoblements) ([]CreateEnnoblementParams, error) {
if err := validateServerKey(serverKey); err != nil {
return nil, ValidationError{
Model: createEnnoblementParamsModelName,
Field: "serverKey",
Err: err,
}
}
params := make([]CreateEnnoblementParams, 0, len(ennoblements))
for i, e := range ennoblements {
if e.IsZero() {
return nil, fmt.Errorf("ennoblements[%d] is an empty struct", i)
}
params = append(params, CreateEnnoblementParams{
base: e,
serverKey: serverKey,
})
}
return params, nil
}
func (params CreateEnnoblementParams) Base() BaseEnnoblement {
return params.base
}
func (params CreateEnnoblementParams) ServerKey() string {
return params.serverKey
}
type EnnoblementSort uint8
const (
EnnoblementSortCreatedAtASC EnnoblementSort = iota + 1
EnnoblementSortCreatedAtDESC
EnnoblementSortIDASC
EnnoblementSortIDDESC
EnnoblementSortServerKeyASC
EnnoblementSortServerKeyDESC
)
// IsInConflict returns true if two sorts can't be used together (e.g. EnnoblementSortIDASC and EnnoblementSortIDDESC).
func (s EnnoblementSort) IsInConflict(s2 EnnoblementSort) bool {
return isSortInConflict(s, s2)
}
//nolint:gocyclo
func (s EnnoblementSort) String() string {
switch s {
case EnnoblementSortCreatedAtASC:
return "createdAt:ASC"
case EnnoblementSortCreatedAtDESC:
return "createdAt:DESC"
case EnnoblementSortIDASC:
return "id:ASC"
case EnnoblementSortIDDESC:
return "id:DESC"
case EnnoblementSortServerKeyASC:
return "serverKey:ASC"
case EnnoblementSortServerKeyDESC:
return "serverKey:DESC"
default:
return "unknown ennoblement sort"
}
}
type EnnoblementCursor struct {
id int
serverKey string
createdAt time.Time
}
const ennoblementCursorModelName = "EnnoblementCursor"
func NewEnnoblementCursor(id int, serverKey string, createdAt time.Time) (EnnoblementCursor, error) {
if err := validateIntInRange(id, 1, math.MaxInt); err != nil {
return EnnoblementCursor{}, ValidationError{
Model: ennoblementCursorModelName,
Field: "id",
Err: err,
}
}
if err := validateServerKey(serverKey); err != nil {
return EnnoblementCursor{}, ValidationError{
Model: ennoblementCursorModelName,
Field: "serverKey",
Err: err,
}
}
return EnnoblementCursor{
id: id,
serverKey: serverKey,
createdAt: createdAt,
}, nil
}
//nolint:gocyclo
func decodeEnnoblementCursor(encoded string) (EnnoblementCursor, error) {
m, err := decodeCursor(encoded)
if err != nil {
return EnnoblementCursor{}, err
}
id, err := m.int("id")
if err != nil {
return EnnoblementCursor{}, ErrInvalidCursor
}
serverKey, err := m.string("serverKey")
if err != nil {
return EnnoblementCursor{}, ErrInvalidCursor
}
createdAt, err := m.time("createdAt")
if err != nil {
return EnnoblementCursor{}, ErrInvalidCursor
}
ec, err := NewEnnoblementCursor(
id,
serverKey,
createdAt,
)
if err != nil {
return EnnoblementCursor{}, ErrInvalidCursor
}
return ec, nil
}
func (ec EnnoblementCursor) ID() int {
return ec.id
}
func (ec EnnoblementCursor) ServerKey() string {
return ec.serverKey
}
func (ec EnnoblementCursor) CreatedAt() time.Time {
return ec.createdAt
}
func (ec EnnoblementCursor) IsZero() bool {
return ec == EnnoblementCursor{}
}
func (ec EnnoblementCursor) Encode() string {
if ec.IsZero() {
return ""
}
return encodeCursor([]keyValuePair{
{"id", ec.id},
{"serverKey", ec.serverKey},
{"createdAt", ec.createdAt},
})
}
type ListEnnoblementsParams struct {
serverKeys []string
villageIDs []int
playerIDs []int // Ennoblement.NewOwnerID or Ennoblement.OldOwnerID
tribeIDs []int // Ennoblement.NewTribeID or Ennoblement.OldTribeID
since NullTime
before NullTime
sort []EnnoblementSort
cursor EnnoblementCursor
limit int
}
const (
EnnoblementListMaxLimit = 500
listEnnoblementsParamsModelName = "ListEnnoblementsParams"
)
func NewListEnnoblementsParams() ListEnnoblementsParams {
return ListEnnoblementsParams{
sort: []EnnoblementSort{
EnnoblementSortServerKeyASC,
EnnoblementSortCreatedAtASC,
EnnoblementSortIDASC,
},
limit: EnnoblementListMaxLimit,
}
}
func (params *ListEnnoblementsParams) ServerKeys() []string {
return params.serverKeys
}
func (params *ListEnnoblementsParams) SetServerKeys(serverKeys []string) error {
for i, sk := range serverKeys {
if err := validateServerKey(sk); err != nil {
return SliceElementValidationError{
Model: listEnnoblementsParamsModelName,
Field: "serverKeys",
Index: i,
Err: err,
}
}
}
params.serverKeys = serverKeys
return nil
}
func (params *ListEnnoblementsParams) VillageIDs() []int {
return params.villageIDs
}
func (params *ListEnnoblementsParams) SetVillageIDs(villageIDs []int) error {
for i, id := range villageIDs {
if err := validateIntInRange(id, 1, math.MaxInt); err != nil {
return SliceElementValidationError{
Model: listEnnoblementsParamsModelName,
Field: "villageIDs",
Index: i,
Err: err,
}
}
}
params.villageIDs = villageIDs
return nil
}
func (params *ListEnnoblementsParams) PlayerIDs() []int {
return params.playerIDs
}
func (params *ListEnnoblementsParams) SetPlayerIDs(playerIDs []int) error {
for i, id := range playerIDs {
if err := validateIntInRange(id, 1, math.MaxInt); err != nil {
return SliceElementValidationError{
Model: listEnnoblementsParamsModelName,
Field: "playerIDs",
Index: i,
Err: err,
}
}
}
params.playerIDs = playerIDs
return nil
}
func (params *ListEnnoblementsParams) TribeIDs() []int {
return params.tribeIDs
}
func (params *ListEnnoblementsParams) SetTribeIDs(tribeIDs []int) error {
for i, id := range tribeIDs {
if err := validateIntInRange(id, 1, math.MaxInt); err != nil {
return SliceElementValidationError{
Model: listEnnoblementsParamsModelName,
Field: "tribeIDs",
Index: i,
Err: err,
}
}
}
params.tribeIDs = tribeIDs
return nil
}
func (params *ListEnnoblementsParams) Since() NullTime {
return params.since
}
func (params *ListEnnoblementsParams) SetSince(since NullTime) error {
params.since = since
return nil
}
func (params *ListEnnoblementsParams) Before() NullTime {
return params.before
}
func (params *ListEnnoblementsParams) SetBefore(before NullTime) error {
params.before = before
return nil
}
func (params *ListEnnoblementsParams) Sort() []EnnoblementSort {
return params.sort
}
const (
ennoblementSortMinLength = 0
ennoblementSortMaxLength = 3
)
func (params *ListEnnoblementsParams) SetSort(sort []EnnoblementSort) error {
if err := validateSort(sort, ennoblementSortMinLength, ennoblementSortMaxLength); err != nil {
return ValidationError{
Model: listEnnoblementsParamsModelName,
Field: "sort",
Err: err,
}
}
params.sort = sort
return nil
}
func (params *ListEnnoblementsParams) PrependSort(sort []EnnoblementSort) error {
if len(sort) == 0 {
return nil
}
if err := validateSliceLen(sort, 0, max(ennoblementSortMaxLength-len(params.sort), 0)); err != nil {
return ValidationError{
Model: listEnnoblementsParamsModelName,
Field: "sort",
Err: err,
}
}
return params.SetSort(append(sort, params.sort...))
}
func (params *ListEnnoblementsParams) PrependSortString(sort []string, allowed []EnnoblementSort, maxLength int) error {
if len(sort) == 0 {
return nil
}
if err := validateSliceLen(sort, 0, max(min(ennoblementSortMaxLength-len(params.sort), maxLength), 0)); err != nil {
return ValidationError{
Model: listEnnoblementsParamsModelName,
Field: "sort",
Err: err,
}
}
toPrepend := make([]EnnoblementSort, 0, len(sort))
for i, s := range sort {
converted, err := newSortFromString(s, allowed...)
if err != nil {
return SliceElementValidationError{
Model: listEnnoblementsParamsModelName,
Field: "sort",
Index: i,
Err: err,
}
}
toPrepend = append(toPrepend, converted)
}
return params.SetSort(append(toPrepend, params.sort...))
}
func (params *ListEnnoblementsParams) Cursor() EnnoblementCursor {
return params.cursor
}
func (params *ListEnnoblementsParams) SetCursor(cursor EnnoblementCursor) error {
params.cursor = cursor
return nil
}
func (params *ListEnnoblementsParams) SetEncodedCursor(encoded string) error {
decoded, err := decodeEnnoblementCursor(encoded)
if err != nil {
return ValidationError{
Model: listEnnoblementsParamsModelName,
Field: "cursor",
Err: err,
}
}
params.cursor = decoded
return nil
}
func (params *ListEnnoblementsParams) Limit() int {
return params.limit
}
func (params *ListEnnoblementsParams) SetLimit(limit int) error {
if err := validateIntInRange(limit, 1, EnnoblementListMaxLimit); err != nil {
return ValidationError{
Model: listEnnoblementsParamsModelName,
Field: "limit",
Err: err,
}
}
params.limit = limit
return nil
}
type ListEnnoblementsResult struct {
ennoblements Ennoblements
self EnnoblementCursor
next EnnoblementCursor
}
const listEnnoblementsResultModelName = "ListEnnoblementsResult"
func NewListEnnoblementsResult(ennoblements Ennoblements, next Ennoblement) (ListEnnoblementsResult, error) {
var err error
res := ListEnnoblementsResult{
ennoblements: ennoblements,
}
if len(ennoblements) > 0 {
res.self, err = ennoblements[0].ToCursor()
if err != nil {
return ListEnnoblementsResult{}, ValidationError{
Model: listEnnoblementsResultModelName,
Field: "self",
Err: err,
}
}
}
if !next.IsZero() {
res.next, err = next.ToCursor()
if err != nil {
return ListEnnoblementsResult{}, ValidationError{
Model: listEnnoblementsResultModelName,
Field: "next",
Err: err,
}
}
}
return res, nil
}
func (res ListEnnoblementsResult) Ennoblements() Ennoblements {
return res.ennoblements
}
func (res ListEnnoblementsResult) Self() EnnoblementCursor {
return res.self
}
func (res ListEnnoblementsResult) Next() EnnoblementCursor {
return res.next
}
type ListEnnoblementsWithRelationsResult struct {
ennoblements EnnoblementsWithRelations
self EnnoblementCursor
next EnnoblementCursor
}
const listEnnoblementsWithRelationsResultModelName = "ListEnnoblementsWithRelationsResult"
func NewListEnnoblementsWithRelationsResult(
ennoblements EnnoblementsWithRelations,
next EnnoblementWithRelations,
) (ListEnnoblementsWithRelationsResult, error) {
var err error
res := ListEnnoblementsWithRelationsResult{
ennoblements: ennoblements,
}
if len(ennoblements) > 0 {
res.self, err = ennoblements[0].Ennoblement().ToCursor()
if err != nil {
return ListEnnoblementsWithRelationsResult{}, ValidationError{
Model: listEnnoblementsWithRelationsResultModelName,
Field: "self",
Err: err,
}
}
}
if !next.IsZero() {
res.next, err = next.Ennoblement().ToCursor()
if err != nil {
return ListEnnoblementsWithRelationsResult{}, ValidationError{
Model: listEnnoblementsWithRelationsResultModelName,
Field: "next",
Err: err,
}
}
}
return res, nil
}
func (res ListEnnoblementsWithRelationsResult) Ennoblements() EnnoblementsWithRelations {
return res.ennoblements
}
func (res ListEnnoblementsWithRelationsResult) Self() EnnoblementCursor {
return res.self
}
func (res ListEnnoblementsWithRelationsResult) Next() EnnoblementCursor {
return res.next
}