2023-07-09 06:06:53 +00:00
|
|
|
package domain
|
|
|
|
|
2023-07-13 04:22:52 +00:00
|
|
|
import (
|
|
|
|
"crypto/sha256"
|
|
|
|
"encoding/hex"
|
|
|
|
"fmt"
|
|
|
|
"math"
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2023-07-09 06:06:53 +00:00
|
|
|
type Village struct {
|
2024-05-02 05:57:24 +00:00
|
|
|
ID int
|
2023-07-09 06:06:53 +00:00
|
|
|
FullName string
|
|
|
|
ProfileURL string
|
2024-05-02 05:57:24 +00:00
|
|
|
Points int
|
|
|
|
X int
|
|
|
|
Y int
|
2023-07-09 06:06:53 +00:00
|
|
|
Player NullPlayerMeta
|
|
|
|
}
|
|
|
|
|
2023-07-13 04:22:52 +00:00
|
|
|
func (v Village) Coords() string {
|
|
|
|
return fmt.Sprintf("%d|%d", v.X, v.Y)
|
|
|
|
}
|
|
|
|
|
2023-07-09 06:06:53 +00:00
|
|
|
type VillageMeta struct {
|
2024-05-02 05:57:24 +00:00
|
|
|
ID int
|
2023-07-09 06:06:53 +00:00
|
|
|
FullName string
|
|
|
|
ProfileURL string
|
|
|
|
Player NullPlayerMeta
|
|
|
|
}
|
2023-07-13 04:22:52 +00:00
|
|
|
|
|
|
|
type VillageCoordsStringTooLongError struct {
|
|
|
|
Str string
|
|
|
|
Max int
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ TranslatableError = VillageCoordsStringTooLongError{}
|
|
|
|
|
|
|
|
func (e VillageCoordsStringTooLongError) Error() string {
|
|
|
|
return fmt.Sprintf("coords string is too long (%d/%d)", len(e.Str), e.Max)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e VillageCoordsStringTooLongError) Slug() string {
|
|
|
|
return "village-coords-string-too-long"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e VillageCoordsStringTooLongError) Params() map[string]any {
|
|
|
|
return map[string]any{
|
|
|
|
"Str": e.Str,
|
|
|
|
"Max": e.Max,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type VillageCoordsNotFoundInStringError struct {
|
|
|
|
Str string
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ TranslatableError = VillageCoordsNotFoundInStringError{}
|
|
|
|
|
|
|
|
func (e VillageCoordsNotFoundInStringError) Error() string {
|
|
|
|
return fmt.Sprintf("no coords found in string: '%s'", e.Str)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e VillageCoordsNotFoundInStringError) Slug() string {
|
|
|
|
return "village-coords-not-found-in-string"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e VillageCoordsNotFoundInStringError) Params() map[string]any {
|
|
|
|
return map[string]any{
|
|
|
|
"Str": e.Str,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type TranslateVillageCoordsParams struct {
|
|
|
|
versionCode string
|
|
|
|
serverKey string
|
|
|
|
coords []string
|
2024-05-02 05:57:24 +00:00
|
|
|
perPage int
|
|
|
|
maxPage int
|
2023-07-13 04:22:52 +00:00
|
|
|
sha256 string
|
|
|
|
}
|
|
|
|
|
|
|
|
var villageCoordsRegex = regexp.MustCompile(`(\d+)\|(\d+)`)
|
|
|
|
|
|
|
|
const (
|
|
|
|
VillageCoordsStringMaxLength = 1000
|
|
|
|
translateVillageCoordsMinPerPage = 1
|
|
|
|
)
|
|
|
|
|
2024-05-02 05:57:24 +00:00
|
|
|
func NewTranslateVillageCoordsParams(versionCode, serverKey, coordsStr string, perPage int) (TranslateVillageCoordsParams, error) {
|
2023-07-13 04:22:52 +00:00
|
|
|
if versionCode == "" {
|
|
|
|
return TranslateVillageCoordsParams{}, RequiredError{Field: "VersionCode"}
|
|
|
|
}
|
|
|
|
|
|
|
|
if serverKey == "" {
|
|
|
|
return TranslateVillageCoordsParams{}, RequiredError{Field: "ServerKey"}
|
|
|
|
}
|
|
|
|
|
|
|
|
if perPage < translateVillageCoordsMinPerPage {
|
|
|
|
return TranslateVillageCoordsParams{}, GreaterEqualThanError{
|
|
|
|
Field: "PerPage",
|
|
|
|
Threshold: translateVillageCoordsMinPerPage,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(coordsStr) > VillageCoordsStringMaxLength {
|
|
|
|
return TranslateVillageCoordsParams{}, VillageCoordsStringTooLongError{
|
|
|
|
Max: VillageCoordsStringMaxLength,
|
|
|
|
Str: coordsStr,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
coords := uniq(villageCoordsRegex.FindAllString(coordsStr, -1))
|
|
|
|
if len(coords) == 0 {
|
|
|
|
return TranslateVillageCoordsParams{}, VillageCoordsNotFoundInStringError{
|
|
|
|
Str: coordsStr,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sum256 := sha256.Sum256(fmt.Appendf(nil, "%s-%s-%s-%d", versionCode, serverKey, strings.Join(coords, ","), perPage))
|
|
|
|
|
|
|
|
return TranslateVillageCoordsParams{
|
|
|
|
versionCode: versionCode,
|
|
|
|
serverKey: serverKey,
|
|
|
|
coords: coords,
|
|
|
|
perPage: perPage,
|
2024-05-02 05:57:24 +00:00
|
|
|
maxPage: int(math.Ceil(float64(len(coords)) / float64(perPage))),
|
2023-07-13 04:22:52 +00:00
|
|
|
sha256: hex.EncodeToString(sum256[:]),
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalTranslateVillageCoordsParamsFromDatabase unmarshals TranslateVillageCoordsParams from the database.
|
|
|
|
//
|
|
|
|
// It should be used only for unmarshalling from the database!
|
|
|
|
// You can't use UnmarshalTranslateVillageCoordsParamsFromDatabase as constructor - It may put domain into the invalid state!
|
|
|
|
func UnmarshalTranslateVillageCoordsParamsFromDatabase(
|
|
|
|
versionCode string,
|
|
|
|
serverKey string,
|
|
|
|
coords []string,
|
2024-05-02 05:57:24 +00:00
|
|
|
perPage int,
|
|
|
|
maxPage int,
|
2023-07-13 04:22:52 +00:00
|
|
|
sha256Hash string,
|
|
|
|
) (TranslateVillageCoordsParams, error) {
|
|
|
|
if versionCode == "" {
|
|
|
|
return TranslateVillageCoordsParams{}, RequiredError{Field: "VersionCode"}
|
|
|
|
}
|
|
|
|
|
|
|
|
if serverKey == "" {
|
|
|
|
return TranslateVillageCoordsParams{}, RequiredError{Field: "ServerKey"}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(coords) == 0 {
|
|
|
|
return TranslateVillageCoordsParams{}, LengthTooShortError{
|
|
|
|
Field: "Coords",
|
|
|
|
Threshold: 1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if perPage < translateVillageCoordsMinPerPage {
|
|
|
|
return TranslateVillageCoordsParams{}, GreaterEqualThanError{
|
|
|
|
Field: "PerPage",
|
|
|
|
Threshold: translateVillageCoordsMinPerPage,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if sha256Hash == "" {
|
|
|
|
return TranslateVillageCoordsParams{}, RequiredError{Field: "SHA256"}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TranslateVillageCoordsParams{
|
|
|
|
versionCode: versionCode,
|
|
|
|
serverKey: serverKey,
|
|
|
|
coords: coords,
|
|
|
|
perPage: perPage,
|
|
|
|
maxPage: maxPage,
|
|
|
|
sha256: sha256Hash,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t TranslateVillageCoordsParams) VersionCode() string {
|
|
|
|
return t.versionCode
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t TranslateVillageCoordsParams) ServerKey() string {
|
|
|
|
return t.serverKey
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t TranslateVillageCoordsParams) Coords() []string {
|
|
|
|
return t.coords
|
|
|
|
}
|
|
|
|
|
2024-05-02 05:57:24 +00:00
|
|
|
func (t TranslateVillageCoordsParams) PerPage() int {
|
2023-07-13 04:22:52 +00:00
|
|
|
return t.perPage
|
|
|
|
}
|
|
|
|
|
2024-05-02 05:57:24 +00:00
|
|
|
func (t TranslateVillageCoordsParams) MaxPage() int {
|
2023-07-13 04:22:52 +00:00
|
|
|
return t.maxPage
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t TranslateVillageCoordsParams) SHA256() string {
|
|
|
|
return t.sha256
|
|
|
|
}
|
|
|
|
|
2024-05-02 05:57:24 +00:00
|
|
|
func (t TranslateVillageCoordsParams) IsPageInRange(page int) error {
|
2023-07-13 04:57:17 +00:00
|
|
|
if page < 1 {
|
|
|
|
return GreaterEqualThanError{Field: "page", Threshold: 1}
|
|
|
|
}
|
|
|
|
|
|
|
|
if page > t.maxPage {
|
2024-05-02 05:57:24 +00:00
|
|
|
return LessEqualThanError{Field: "page", Threshold: t.maxPage}
|
2023-07-13 04:57:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-07-13 04:22:52 +00:00
|
|
|
type TranslateVillageCoordsResult struct {
|
|
|
|
Villages []Village
|
|
|
|
NotFound []string
|
|
|
|
HasNext bool
|
|
|
|
HasPrev bool
|
2024-05-02 05:57:24 +00:00
|
|
|
Page int
|
|
|
|
MaxPage int
|
2023-07-13 04:22:52 +00:00
|
|
|
ParamsSHA256 string
|
|
|
|
}
|
|
|
|
|
|
|
|
type TranslateVillageCoordsParamsNotFoundError struct {
|
|
|
|
SHA256 string
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ TranslatableError = TranslateVillageCoordsParamsNotFoundError{}
|
|
|
|
|
|
|
|
func (e TranslateVillageCoordsParamsNotFoundError) Error() string {
|
|
|
|
return fmt.Sprintf("params (SHA256=%s) not found", e.SHA256)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e TranslateVillageCoordsParamsNotFoundError) Slug() string {
|
|
|
|
return "translate-village-coords-params-not-found"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e TranslateVillageCoordsParamsNotFoundError) Params() map[string]any {
|
|
|
|
return map[string]any{
|
|
|
|
"SHA256": e.SHA256,
|
|
|
|
}
|
|
|
|
}
|