lexswiss

package
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Apr 13, 2026 License: Apache-2.0 Imports: 2 Imported by: 0

Documentation

Overview

Package lexswiss provides shared data structures and algorithms for lexicographic Swiss pairing systems. Both the Double-Swiss (C.04.5) and Team Swiss (C.04.6) engines build on this foundation.

The lexicographic approach enumerates all legal pairings of a bracket in lexicographic order and selects the first one satisfying all criteria. This is fundamentally different from Dutch/Burstein/Dubov which use Blossom matching or transposition-based approaches.

Key shared components:

  • ParticipantState: player/team state for pairing
  • BuildScoreGroups: scoregroup construction
  • AssignPAB: bye assignment (Art. 3.4)
  • SelectUpfloaters: upfloater selection (Art. 3.5)
  • PairBracket: lexicographic bracket pairing (Art. 3.6)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func HasPlayed

func HasPlayed(a, b *ParticipantState) bool

HasPlayed returns true if participant a has played against participant b (based on opponent history, which excludes forfeits).

func NeedsBye

func NeedsBye(count int) bool

NeedsBye returns true if the participant count is odd.

func PairBracket

func PairBracket(participants []*ParticipantState, forbidden map[[2]string]bool, criteriaFn CriteriaFunc) [][2]*ParticipantState

PairBracket pairs all participants in a bracket using the lexicographic algorithm described in Art. 3.6 (shared by Double-Swiss and Team Swiss).

The algorithm enumerates all legal pairings in lexicographic order and selects the first one satisfying all criteria. Lexicographic order means: the participant with the lowest TPN is paired with the lowest-TPN available partner first. If that leads to a dead end (remaining participants can't all be paired), the algorithm backtracks and tries the next partner.

Absolute criteria enforced by PairBracket:

  • C1: No two participants play each other more than once
  • Forbidden pairs are not paired

Additional criteria are checked via the CriteriaFunc parameter. If criteriaFn is nil, only C1 and forbidden pairs are checked.

Parameters:

  • participants: sorted by TPN ascending
  • forbidden: forbidden pairs map (nil if none)
  • criteriaFn: additional criteria function (nil = no extra criteria)

Returns the list of pairs (each pair is [lower-TPN, higher-TPN]). If no complete pairing is possible, returns the best partial pairing (as many pairs as possible in lexicographic order).

Types

type Color

type Color int

Color represents a participant's colour assignment in a round.

const (
	ColorNone Color = iota // bye, absent, or no game
	ColorWhite
	ColorBlack
)

func (Color) Opposite

func (c Color) Opposite() Color

Opposite returns the opposite colour (White↔Black). None returns None.

func (Color) String

func (c Color) String() string

String returns the colour name for debugging.

type CriteriaFunc

type CriteriaFunc func(a, b *ParticipantState) bool

CriteriaFunc is a function that checks whether a proposed pair satisfies system-specific criteria. Returns true if the pair is acceptable.

The function is called for each candidate pair during the lexicographic enumeration. If it returns false, the pair is skipped and the next candidate is tried.

Double-Swiss uses this for C8 (colour preferences). Team Swiss uses this for C8-C10 (colour preferences).

type ParticipantState

type ParticipantState struct {
	ID           string
	DisplayName  string
	InitialRank  int      // starting rank (by rating desc, then name asc), 1-based
	TPN          int      // Tournament Pairing Number, 1-based (re-ranked each round)
	Score        float64  // cumulative pairing score (standard 1-½-0)
	ColorHistory []Color  // colour per round (index 0 = round 1)
	Opponents    []string // IDs of opponents faced (forfeits excluded)
	ByeReceived  bool     // already received a PAB
	Active       bool
	Rating       int
}

ParticipantState holds the computed state of a single participant (player or team) for the lexicographic pairing algorithm. Built once per Pair() call from the engine's TournamentState.

This is deliberately simpler than swisslib.PlayerState because the lexicographic systems don't need float history, Blossom criteria weights, or the three-tier colour preference system.

func AssignPAB

func AssignPAB(participants []*ParticipantState) *ParticipantState

AssignPAB selects the participant to receive the pairing-allocated bye per Art. 3.4 (shared by Double-Swiss and Team Swiss):

  1. Lowest score
  2. Among ties: highest TPN (lowest ranking)
  3. Must not have already received a PAB

Returns nil if all participants have already received a PAB.

func BuildParticipantStates

func BuildParticipantStates(state *chesspairing.TournamentState) []ParticipantState

BuildParticipantStates converts a TournamentState into a sorted slice of ParticipantState values ready for the pairing algorithm.

Active participants only. Sorted by score (desc), then initial rank (asc). TPN assigned sequentially after sorting.

Pairing scores use standard 1-½-0 regardless of tournament scoring system. Forfeit games are excluded from opponent history (participants can be paired again).

func SelectUpfloater

func SelectUpfloater(bracket []*ParticipantState, targetBracket []*ParticipantState, forbidden map[[2]string]bool) *ParticipantState

SelectUpfloater selects the participant to float up from a bracket to the bracket above, per Art. 3.5 (shared by Double-Swiss and Team Swiss).

The upfloater is the lowest-ranked participant (highest TPN) who has at least one compatible opponent in the target bracket. Compatibility means: (1) not already played, and (2) not a forbidden pair.

Parameters:

  • bracket: participants in the current bracket (odd count)
  • targetBracket: participants in the bracket above (where floater goes)
  • forbidden: forbidden pairs map (nil if none)

Returns nil if no valid upfloater can be selected (all have played everyone in the target bracket).

type ScoreGroup

type ScoreGroup struct {
	Score        float64
	Participants []*ParticipantState // ordered by TPN ascending
}

ScoreGroup holds all participants with the same pairing score. Participants are ordered by TPN ascending within the group.

func BuildScoreGroups

func BuildScoreGroups(participants []ParticipantState) []ScoreGroup

BuildScoreGroups creates score groups from participant states. Participants are grouped by Score and each group is sorted by TPN ascending. Returns groups in descending score order. Input need not be pre-sorted.

Jump to

Keyboard shortcuts

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