302 lines
6.5 KiB
Go
302 lines
6.5 KiB
Go
|
package domain
|
||
|
|
||
|
import (
|
||
|
"cmp"
|
||
|
"fmt"
|
||
|
"math"
|
||
|
"slices"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type TribeChange struct {
|
||
|
id int
|
||
|
serverKey string
|
||
|
playerID int
|
||
|
oldTribeID int
|
||
|
newTribeID int
|
||
|
createdAt time.Time
|
||
|
}
|
||
|
|
||
|
const tribeChangeModelName = "TribeChange"
|
||
|
|
||
|
// UnmarshalTribeChangeFromDatabase unmarshals TribeChange from the database.
|
||
|
//
|
||
|
// It should be used only for unmarshalling from the database!
|
||
|
// You can't use UnmarshalTribeChangeFromDatabase as constructor - It may put domain into the invalid state!
|
||
|
func UnmarshalTribeChangeFromDatabase(
|
||
|
id int,
|
||
|
serverKey string,
|
||
|
playerID int,
|
||
|
oldTribeID int,
|
||
|
newTribeID int,
|
||
|
createdAt time.Time,
|
||
|
) (TribeChange, error) {
|
||
|
if err := validateIntInRange(id, 1, math.MaxInt); err != nil {
|
||
|
return TribeChange{}, ValidationError{
|
||
|
Model: tribeChangeModelName,
|
||
|
Field: "id",
|
||
|
Err: err,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if err := validateServerKey(serverKey); err != nil {
|
||
|
return TribeChange{}, ValidationError{
|
||
|
Model: tribeChangeModelName,
|
||
|
Field: "serverKey",
|
||
|
Err: err,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TribeChange{
|
||
|
id: id,
|
||
|
playerID: playerID,
|
||
|
oldTribeID: oldTribeID,
|
||
|
newTribeID: newTribeID,
|
||
|
serverKey: serverKey,
|
||
|
createdAt: createdAt,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func (tc TribeChange) ID() int {
|
||
|
return tc.id
|
||
|
}
|
||
|
|
||
|
func (tc TribeChange) PlayerID() int {
|
||
|
return tc.playerID
|
||
|
}
|
||
|
|
||
|
func (tc TribeChange) OldTribeID() int {
|
||
|
return tc.oldTribeID
|
||
|
}
|
||
|
|
||
|
func (tc TribeChange) NewTribeID() int {
|
||
|
return tc.newTribeID
|
||
|
}
|
||
|
|
||
|
func (tc TribeChange) ServerKey() string {
|
||
|
return tc.serverKey
|
||
|
}
|
||
|
|
||
|
func (tc TribeChange) CreatedAt() time.Time {
|
||
|
return tc.createdAt
|
||
|
}
|
||
|
|
||
|
type TribeChanges []TribeChange
|
||
|
|
||
|
type CreateTribeChangeParams struct {
|
||
|
serverKey string
|
||
|
playerID int
|
||
|
newTribeID int
|
||
|
oldTribeID int
|
||
|
}
|
||
|
|
||
|
const createTribeChangeParamsModelName = "CreateTribeChangeParams"
|
||
|
|
||
|
func NewCreateTribeChangeParams(
|
||
|
serverKey string,
|
||
|
playerID int,
|
||
|
oldTribeID int,
|
||
|
newTribeID int,
|
||
|
) (CreateTribeChangeParams, error) {
|
||
|
if err := validateServerKey(serverKey); err != nil {
|
||
|
return CreateTribeChangeParams{}, ValidationError{
|
||
|
Model: createTribeChangeParamsModelName,
|
||
|
Field: "serverKey",
|
||
|
Err: err,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if err := validateIntInRange(playerID, 1, math.MaxInt); err != nil {
|
||
|
return CreateTribeChangeParams{}, ValidationError{
|
||
|
Model: createTribeChangeParamsModelName,
|
||
|
Field: "playerID",
|
||
|
Err: err,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if err := validateIntInRange(oldTribeID, 0, math.MaxInt); err != nil {
|
||
|
return CreateTribeChangeParams{}, ValidationError{
|
||
|
Model: createTribeChangeParamsModelName,
|
||
|
Field: "oldTribeID",
|
||
|
Err: err,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if err := validateIntInRange(newTribeID, 0, math.MaxInt); err != nil {
|
||
|
return CreateTribeChangeParams{}, ValidationError{
|
||
|
Model: createTribeChangeParamsModelName,
|
||
|
Field: "newTribeID",
|
||
|
Err: err,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return CreateTribeChangeParams{
|
||
|
serverKey: serverKey,
|
||
|
playerID: playerID,
|
||
|
oldTribeID: oldTribeID,
|
||
|
newTribeID: newTribeID,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
// NewCreateTribeChangeParamsFromPlayers constructs a slice of CreatePlayerParams based on the given parameters.
|
||
|
// Both slices must be sorted in ascending order by ID
|
||
|
// + if storedPlayers contains players from different servers. they must be sorted in ascending order by server key.
|
||
|
func NewCreateTribeChangeParamsFromPlayers(
|
||
|
serverKey string,
|
||
|
players BasePlayers,
|
||
|
storedPlayers Players,
|
||
|
) ([]CreateTribeChangeParams, error) {
|
||
|
// tribe changes happens now and then, there is no point in prereallocating this slice
|
||
|
//nolint:prealloc
|
||
|
var params []CreateTribeChangeParams
|
||
|
|
||
|
for i, player := range players {
|
||
|
if player.IsZero() {
|
||
|
return nil, fmt.Errorf("players[%d] is an empty struct", i)
|
||
|
}
|
||
|
|
||
|
var old Player
|
||
|
idx, found := slices.BinarySearchFunc(storedPlayers, player, func(a Player, b BasePlayer) int {
|
||
|
if res := cmp.Compare(a.ServerKey(), serverKey); res != 0 {
|
||
|
return res
|
||
|
}
|
||
|
return cmp.Compare(a.ID(), b.ID())
|
||
|
})
|
||
|
if found {
|
||
|
old = storedPlayers[idx]
|
||
|
}
|
||
|
|
||
|
if (old.ID() > 0 && old.TribeID() == player.TribeID()) || (old.ID() == 0 && player.TribeID() == 0) {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
p, err := NewCreateTribeChangeParams(
|
||
|
serverKey,
|
||
|
player.ID(),
|
||
|
old.TribeID(),
|
||
|
player.TribeID(),
|
||
|
)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
params = append(params, p)
|
||
|
}
|
||
|
|
||
|
return params, nil
|
||
|
}
|
||
|
|
||
|
func (params CreateTribeChangeParams) ServerKey() string {
|
||
|
return params.serverKey
|
||
|
}
|
||
|
|
||
|
func (params CreateTribeChangeParams) PlayerID() int {
|
||
|
return params.playerID
|
||
|
}
|
||
|
|
||
|
func (params CreateTribeChangeParams) OldTribeID() int {
|
||
|
return params.oldTribeID
|
||
|
}
|
||
|
|
||
|
func (params CreateTribeChangeParams) NewTribeID() int {
|
||
|
return params.newTribeID
|
||
|
}
|
||
|
|
||
|
type TribeChangeSort uint8
|
||
|
|
||
|
const (
|
||
|
TribeChangeSortCreatedAtASC TribeChangeSort = iota + 1
|
||
|
TribeChangeSortCreatedAtDESC
|
||
|
TribeChangeSortServerKeyASC
|
||
|
TribeChangeSortServerKeyDESC
|
||
|
)
|
||
|
|
||
|
const TribeChangeListMaxLimit = 200
|
||
|
|
||
|
type ListTribeChangesParams struct {
|
||
|
serverKeys []string
|
||
|
sort []TribeChangeSort
|
||
|
limit int
|
||
|
offset int
|
||
|
}
|
||
|
|
||
|
const listTribeChangesParamsModelName = "ListTribeChangesParams"
|
||
|
|
||
|
func NewListTribeChangesParams() ListTribeChangesParams {
|
||
|
return ListTribeChangesParams{
|
||
|
sort: []TribeChangeSort{
|
||
|
TribeChangeSortServerKeyASC,
|
||
|
TribeChangeSortCreatedAtASC,
|
||
|
},
|
||
|
limit: TribeChangeListMaxLimit,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (params *ListTribeChangesParams) ServerKeys() []string {
|
||
|
return params.serverKeys
|
||
|
}
|
||
|
|
||
|
func (params *ListTribeChangesParams) SetServerKeys(serverKeys []string) error {
|
||
|
params.serverKeys = serverKeys
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (params *ListTribeChangesParams) Sort() []TribeChangeSort {
|
||
|
return params.sort
|
||
|
}
|
||
|
|
||
|
const (
|
||
|
tribeChangeSortMinLength = 1
|
||
|
tribeChangeSortMaxLength = 2
|
||
|
)
|
||
|
|
||
|
func (params *ListTribeChangesParams) SetSort(sort []TribeChangeSort) error {
|
||
|
if err := validateSliceLen(sort, tribeChangeSortMinLength, tribeChangeSortMaxLength); err != nil {
|
||
|
return ValidationError{
|
||
|
Model: listTribeChangesParamsModelName,
|
||
|
Field: "sort",
|
||
|
Err: err,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
params.sort = sort
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (params *ListTribeChangesParams) Limit() int {
|
||
|
return params.limit
|
||
|
}
|
||
|
|
||
|
func (params *ListTribeChangesParams) SetLimit(limit int) error {
|
||
|
if err := validateIntInRange(limit, 1, TribeChangeListMaxLimit); err != nil {
|
||
|
return ValidationError{
|
||
|
Model: listTribeChangesParamsModelName,
|
||
|
Field: "limit",
|
||
|
Err: err,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
params.limit = limit
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (params *ListTribeChangesParams) Offset() int {
|
||
|
return params.offset
|
||
|
}
|
||
|
|
||
|
func (params *ListTribeChangesParams) SetOffset(offset int) error {
|
||
|
if err := validateIntInRange(offset, 0, math.MaxInt); err != nil {
|
||
|
return ValidationError{
|
||
|
Model: listTribeChangesParamsModelName,
|
||
|
Field: "offset",
|
||
|
Err: err,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
params.offset = offset
|
||
|
|
||
|
return nil
|
||
|
}
|