// Package valueobjects provides domain value objects for the KnowFoolery application. package valueobjects import ( "regexp" "strings" "knowfoolery/backend/shared/domain/errors" ) const ( // MinPlayerNameLength is the minimum length of a player name. MinPlayerNameLength = 2 // MaxPlayerNameLength is the maximum length of a player name. MaxPlayerNameLength = 50 ) // playerNamePattern matches alphanumeric characters, spaces, hyphens, underscores, and dots. var playerNamePattern = regexp.MustCompile(`^[a-zA-Z0-9\s\-_.]+$`) // PlayerName represents a validated player name. type PlayerName struct { value string } // NewPlayerName creates a new PlayerName with validation. func NewPlayerName(name string) (PlayerName, error) { // Trim whitespace name = strings.TrimSpace(name) // Validate length if len(name) < MinPlayerNameLength { return PlayerName{}, errors.Wrap( errors.CodeInvalidPlayerName, "player name too short", nil, ) } if len(name) > MaxPlayerNameLength { return PlayerName{}, errors.Wrap( errors.CodeInvalidPlayerName, "player name too long", nil, ) } // Validate characters if !playerNamePattern.MatchString(name) { return PlayerName{}, errors.Wrap( errors.CodeInvalidPlayerName, "player name contains invalid characters", nil, ) } // Normalize multiple spaces to single space spaceRegex := regexp.MustCompile(`\s+`) name = spaceRegex.ReplaceAllString(name, " ") return PlayerName{value: name}, nil } // String returns the string representation of the player name. func (p PlayerName) String() string { return p.value } // Equals checks if two player names are equal. func (p PlayerName) Equals(other PlayerName) bool { return strings.EqualFold(p.value, other.value) } // IsEmpty checks if the player name is empty. func (p PlayerName) IsEmpty() bool { return p.value == "" }