ruleset

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 27, 2026 License: MIT Imports: 7 Imported by: 0

README

internal/ruleset

JSON parser and semantic validator for AWS GameLift FlexMatch rule sets.

Responsibility

Turn a []byte containing the FlexMatch rule set JSON document — the same payload accepted by AWS's CreateMatchmakingRuleSet API (RuleSetBody) — into a typed *RuleSet and return descriptive errors for anything that is malformed or contradictory.

This package only describes the rule set; it does not evaluate any rules. The evaluator packages (expr, rule, algorithm, expansion) consume the structures defined here.

Contents

  • RuleSet, Team, PlayerAttribute, Algorithm, Rule, Expansion, ExpansionStep — the parsed structures that mirror the FlexMatch JSON schema. RuleSet also carries the top-level AcceptanceRequired / AcceptanceTimeoutSeconds fields that drive the player-acceptance flow, and RequestTimeoutSeconds which bounds a ticket's overall time in matchmaking, in the public package.
  • RuleType and its constants (RuleComparison, RuleDistance, …, RuleDistanceSort, RuleCompound) for switching on rule kind.
  • CompoundNode and ParseCompound(s string) — parser for a compound rule's statement string (e.g. "or(and(A,B), not(C))") into a tree of and/or/not/xor operators and leaf rule references.
  • Parse(body []byte) (*RuleSet, error) — entry point. Returns errors that wrap ErrInvalidRuleSet.
  • (*RuleSet).Validate() — the semantic checks Parse runs after JSON decoding (uniqueness, references, enum values, expansion target shape, etc.). Exposed for tests and for callers that build a RuleSet by hand.

Design notes

  • Fields whose value type varies across rule kinds (most notably referenceValue) are kept as json.RawMessage. Each rule evaluator decodes the raw bytes when it knows the expected shape.
  • Optional numeric fields are pointer types (*float64, *int) so the validator and evaluators can distinguish "absent" from "zero".
  • Unknown JSON fields are silently ignored on purpose — AWS may add new optional fields and we don't want a strict decoder to reject them.
  • Compound rule references are validated against the set of rule names in a second pass, so forward references work.

Documentation

Overview

Package ruleset parses and validates AWS GameLift FlexMatch rule set JSON documents (the same payload accepted by CreateMatchmakingRuleSet).

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidRuleSet = errors.New("flexi: invalid rule set")

ErrInvalidRuleSet is returned when the rule set JSON is malformed or fails semantic validation.

Functions

func ParseNumber added in v0.2.0

func ParseNumber(raw []byte) (float64, error)

ParseNumber decodes a JSON number, additionally accepting a string-encoded number such as "500". A JSON null or empty input yields an error.

Types

type Algorithm

type Algorithm struct {
	Strategy              string   `json:"strategy,omitempty"`
	BatchingPreference    string   `json:"batchingPreference,omitempty"`
	BalancedAttribute     string   `json:"balancedAttribute,omitempty"`
	SortByAttributes      []string `json:"sortByAttributes,omitempty"`
	BackfillPriority      string   `json:"backfillPriority,omitempty"`
	ExpansionAgeSelection string   `json:"expansionAgeSelection,omitempty"`
}

Algorithm captures the rule set's algorithm block.

type CompoundNode added in v0.2.0

type CompoundNode struct {
	Op   string
	Rule string
	Args []*CompoundNode
}

CompoundNode is a parsed compound-rule statement. A leaf references another rule by name (Rule set, Op empty); an internal node combines arguments with a logical operator (Op in {and, or, not, xor}).

func ParseCompound added in v0.2.0

func ParseCompound(s string) (*CompoundNode, error)

ParseCompound parses a compound statement string such as "or(and(A, B), not(C))" into a CompoundNode tree.

func (*CompoundNode) RuleNames added in v0.2.0

func (n *CompoundNode) RuleNames() []string

RuleNames returns the names of all leaf rules referenced by the statement.

type Expansion

type Expansion struct {
	Target string          `json:"target"`
	Steps  []ExpansionStep `json:"steps"`
}

Expansion declares a time-driven loosening of a target value.

type ExpansionStep

type ExpansionStep struct {
	WaitTimeSeconds int             `json:"waitTimeSeconds"`
	Value           json.RawMessage `json:"value"`
}

ExpansionStep applies Value once WaitTimeSeconds have elapsed.

type PlayerAttribute

type PlayerAttribute struct {
	Name    string          `json:"name"`
	Type    string          `json:"type"`
	Default json.RawMessage `json:"default,omitempty"`
}

PlayerAttribute declares a player attribute the rule set will reference.

type Rule

type Rule struct {
	Name        string   `json:"name"`
	Description string   `json:"description,omitempty"`
	Type        RuleType `json:"type"`

	// comparison / distance / collection
	Measurements   []string        `json:"measurements,omitempty"`
	ReferenceValue json.RawMessage `json:"referenceValue,omitempty"`

	// comparison
	Operation string `json:"operation,omitempty"`

	// distance / batchDistance / latency
	MaxDistance *float64 `json:"maxDistance,omitempty"`
	// distance only
	MinDistance *float64 `json:"minDistance,omitempty"`

	// absoluteSort / distanceSort
	SortDirection string `json:"sortDirection,omitempty"`
	SortAttribute string `json:"sortAttribute,omitempty"`
	MapKey        string `json:"mapKey,omitempty"` // minValue | maxValue for map attrs

	// batchDistance
	BatchAttribute string `json:"batchAttribute,omitempty"`

	// partyAggregation applies to most rule types: min | max | avg (default
	// avg), or union | intersection for collection rules (default union).
	PartyAggregation string `json:"partyAggregation,omitempty"`

	// collection
	MinCount *int `json:"minCount,omitempty"`
	MaxCount *int `json:"maxCount,omitempty"`

	// latency
	MaxLatency        *int   `json:"maxLatency,omitempty"`
	DistanceReference string `json:"distanceReference,omitempty"` // min | avg

	// compound: a logical statement string, e.g. "or(and(A,B), not(C))".
	Statement string `json:"statement,omitempty"`
}

Rule is a single rule entry. Fields not relevant to the rule's Type are zero. referenceValue may be a literal number/string OR a property expression string, hence kept as RawMessage to preserve fidelity until evaluation.

func (*Rule) UnmarshalJSON added in v0.2.0

func (r *Rule) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes a Rule, additionally accepting string-encoded numbers for maxDistance/minDistance. The FlexMatch documentation is internally inconsistent about these fields — the schema page shows them as numbers while the rule-type examples show quoted strings (e.g. "maxDistance":"500") — so we accept both forms.

type RuleSet

type RuleSet struct {
	Name                string            `json:"name"`
	RuleLanguageVersion string            `json:"ruleLanguageVersion"`
	PlayerAttributes    []PlayerAttribute `json:"playerAttributes,omitempty"`
	Algorithm           Algorithm         `json:"algorithm"`
	Teams               []Team            `json:"teams"`
	Rules               []Rule            `json:"rules,omitempty"`
	Expansions          []Expansion       `json:"expansions,omitempty"`

	// AcceptanceRequired, when true, holds matches formed by the engine in
	// REQUIRES_ACCEPTANCE state until every player on every matched ticket
	// has accepted via Matchmaker.Accept. Mirrors the FlexMatch field of the
	// same name on MatchmakingConfiguration.
	AcceptanceRequired bool `json:"acceptanceRequired,omitempty"`

	// AcceptanceTimeoutSeconds bounds how long a proposed match may sit in
	// REQUIRES_ACCEPTANCE. When the deadline passes without full acceptance,
	// the proposal is discarded: tickets whose every player had accepted return
	// to SEARCHING, and the rest move to CANCELLED (matching FlexMatch, which
	// cancels tickets that reject or fail to respond to a proposed match).
	// Zero means no timeout. Ignored when AcceptanceRequired is false.
	AcceptanceTimeoutSeconds int `json:"acceptanceTimeoutSeconds,omitempty"`

	// RequestTimeoutSeconds bounds how long a matchmaking request (ticket) may
	// stay in matchmaking before it fails. When a queued or re-queued
	// (SEARCHING) ticket has waited this long, measured from its original
	// enqueue time, it moves to TIMED_OUT. Zero means no timeout. Mirrors the
	// FlexMatch field of the same name on MatchmakingConfiguration; unlike
	// AcceptanceTimeoutSeconds it applies regardless of AcceptanceRequired.
	RequestTimeoutSeconds int `json:"requestTimeoutSeconds,omitempty"`
}

RuleSet is the parsed top-level FlexMatch rule set.

func Parse

func Parse(body []byte) (*RuleSet, error)

Parse parses a FlexMatch rule set JSON document and validates it.

func (*RuleSet) Validate

func (rs *RuleSet) Validate() error

Validate performs semantic checks beyond JSON well-formedness.

type RuleType

type RuleType string

RuleType enumerates the FlexMatch rule kinds.

const (
	RuleComparison    RuleType = "comparison"
	RuleDistance      RuleType = "distance"
	RuleAbsoluteSort  RuleType = "absoluteSort"
	RuleDistanceSort  RuleType = "distanceSort"
	RuleBatchDistance RuleType = "batchDistance"
	RuleCollection    RuleType = "collection"
	RuleLatency       RuleType = "latency"
	RuleCompound      RuleType = "compound"
)

type Team

type Team struct {
	Name       string `json:"name"`
	MinPlayers int    `json:"minPlayers"`
	MaxPlayers int    `json:"maxPlayers"`
	Quantity   int    `json:"quantity,omitempty"`
}

Team describes one team slot. Quantity > 1 means the team is created multiple times in a single match.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL