npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@echecs/round-robin

v3.0.0

Published

Round-robin chess tournament pairings following FIDE Berger tables (C.05 Annex 1). Supports 3-16 players with correct color assignment and bye handling. Zero dependencies.

Readme

Round Robin

npm Test Coverage License: MIT

Round Robin is a TypeScript library for round-robin (all-play-all) chess tournament pairings, following the official FIDE Berger tables (Handbook C.05, Annex 1). Supports 3 to 16 players. Zero runtime dependencies.

Pairings are generated from hardcoded FIDE tables — no algorithmic generation. This guarantees bit-exact compliance with the published FIDE specification.

Installation

npm install @echecs/round-robin

Quick Start

import { pair } from '@echecs/round-robin';
import type { Player } from '@echecs/round-robin';

const players: Player[] = [
  { id: 'alice' },
  { id: 'bob' },
  { id: 'carol' },
  { id: 'dave' },
];

// Get pairings for round 1 (no previous games)
const round1 = pair(players, []);
console.log(round1.pairings);
// [{ white: 'alice', black: 'dave' }, { white: 'bob', black: 'carol' }]

// After recording round-1 results, pair round 2
// games[n] = round n+1; Game has no `round` field
const games = [
  [
    { white: 'alice', black: 'dave', result: 1 },
    { white: 'bob', black: 'carol', result: 0.5 },
  ],
];
const round2 = pair(players, games); // next round = games.length + 1 = 2

API

pair(players, games)

function pair(players: Player[], games: Game[][]): PairingResult;

Returns pairings for the next round.

  • players — all registered players, ordered by seed (index 0 = seed 1)
  • games — completed games grouped by round: games[0] = round 1, games[1] = round 2, … The round to pair is games.length + 1. The games parameter is accepted for interface compatibility with @echecs/swiss but is ignored — pairings are fully determined by seeding order and round index.

The Game type has no round field — round is encoded by array position.

Throws RangeError if:

  • Fewer than 3 or more than 16 players
  • games.length + 1 exceeds the total number of rounds
interface PairingResult {
  byes: Bye[]; // players with no opponent this round
  pairings: Pairing[]; // white/black assignments
}

interface Pairing {
  black: string;
  white: string;
}

interface Bye {
  player: string;
}

Number of rounds

| Players | Rounds | | ------- | ------ | | 3-4 | 3 | | 5-6 | 5 | | 7-8 | 7 | | 9-10 | 9 | | 11-12 | 11 | | 13-14 | 13 | | 15-16 | 15 |

Odd player counts are padded to the next even number. The total number of rounds is always effectiveSize - 1.

Seeding

Seeding is determined by array position — index 0 is seed 1, index 1 is seed 2, etc. The caller controls seed order by arranging the players array before calling the pairing function.

// Seed by rating (highest first)
const seeded = players.sort((a, b) => (b.rating ?? 0) - (a.rating ?? 0));
const round1 = pair(seeded, []);

Byes

For odd player counts, one player receives a bye each round. Per FIDE rules, the highest-numbered seed is the bye seat — so the player paired against that seat gets the bye.

const players: Player[] = [{ id: 'alice' }, { id: 'bob' }, { id: 'carol' }];

const round1 = pair(players, []);
console.log(round1.byes);
// [{ player: 'alice' }]
console.log(round1.pairings);
// [{ white: 'bob', black: 'carol' }]

Unified Pairing Interface

The pair function shares the same signature as Swiss pairing functions in @echecs/swiss:

type PairingSystem = (players: Player[], games: Game[][]) => PairingResult;

This enables @echecs/tournament to consume any pairing system through a single interface. The games parameter is accepted but ignored.

import { pair as dutch } from '@echecs/swiss';
import { pair as roundRobin } from '@echecs/round-robin';
import type { PairingResult, Player, Game } from '@echecs/round-robin';

type PairingSystem = (players: Player[], games: Game[][]) => PairingResult;

// Both work as a PairingSystem
const system: PairingSystem = useSwiss ? dutch : roundRobin;
const pairings = system(players, games);

Types

interface Player {
  id: string;
  rating?: number;
}

interface Game {
  black: string;
  result: Result;
  white: string;
  // No `round` field — round is encoded by position in Game[][]
}

type Result = 0 | 0.5 | 1;

FIDE References

License

MIT