Per-kind rule evaluators. Given a parsed ruleset.Rule, this package builds
an Evaluator that answers "does this candidate match satisfy me?".
Responsibility
Convert the declarative ruleset.Rule records into runnable filters that
the algorithm consults while assembling matches. Each rule kind lives in
its own file so the implementations stay small and obvious.
Contents
Build(r *ruleset.Rule, compounds map[string]Evaluator) (Evaluator, error)
— the factory dispatched by rule type. compounds carries the already
built evaluators that compound rules can reference.
Candidate — the tentative match passed to evaluators: full player
roster, per-team roster, and (optionally) a chosen region for latency
evaluation.
compound.go (parses the statement string via
ruleset.ParseCompound and evaluates and/or/not/xor)
party.go (collapses multi-player tickets per partyAggregation
before evaluation: numeric min/max/avg, or union/intersection for
collection rules)
absoluteSort and distanceSort are built by Build as "always pass"
evaluators — they affect ordering, which is the algorithm's concern
(see internal/algorithm/sort.go), not admission.
Design notes
Evaluators are pure functions of *Candidate: no internal state, no
side effects. This makes them trivially safe to share across goroutines
and easy to test in isolation.
A false return means "this candidate does not pass right now". An
error means the rule was misconfigured in a way the validator did not
catch (e.g. an attribute referenced by the wrong type).
Rules that reference team aggregates (most distance and comparison
rules) tolerate empty teams: when the underlying expression returns
expr.KindNone, the rule is skipped rather than failed. This is what
lets the algorithm grow a partial candidate without prematurely
rejecting it.
Latency is evaluated by trying every region present in the candidate's
players when Candidate.Region is empty; if any region satisfies the
threshold for every player, the rule passes. Set Candidate.Region
when you want to pin evaluation to a single region.
type Candidate struct {
Players []core.Player Teams map[string][]core.Player// TeamOrder lists the actual team (slot) names in deterministic order, used// to expand teams[*] expressions. TeamOrder []string Parties [][]core.Player// TeamParties groups each team's parties (one sub-slice per ticket) by team// name, used to apply partyAggregation per team. TeamParties map[string][][]core.Player Region string}
Candidate is a tentative match: the full player roster grouped by team.
Region, when set, names the region the latency rule should evaluate against.
Parties groups players by their originating ticket; used by batchDistance
partyAggregation. When nil, each player is treated as its own party.