https://github.com/echecsjs/tunx
Parse and stringify SwissManager TUNX binary tournament files. Zero dependencies, strict TypeScript, full round-trip fidelity.
https://github.com/echecsjs/tunx
chess parser swissmanager typescript
Last synced: about 12 hours ago
JSON representation
Parse and stringify SwissManager TUNX binary tournament files. Zero dependencies, strict TypeScript, full round-trip fidelity.
- Host: GitHub
- URL: https://github.com/echecsjs/tunx
- Owner: echecsjs
- License: mit
- Created: 2026-03-29T19:05:45.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-06-29T14:01:04.000Z (2 days ago)
- Last Synced: 2026-06-29T15:24:57.038Z (2 days ago)
- Topics: chess, parser, swissmanager, typescript
- Language: TypeScript
- Homepage: https://github.com/echecsjs/tunx#readme
- Size: 886 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# @echecs/tunx
Parse [Swiss-Manager](https://swiss-manager.at/) `.TUNX` binary tournament
files. Zero dependencies, strict TypeScript. Output types align with
[`@echecs/trf`](https://www.npmjs.com/package/@echecs/trf).
## Installation
```bash
npm install @echecs/tunx
```
## Quick Start
```typescript
import { parse } from '@echecs/tunx';
import { readFileSync } from 'node:fs';
// Parse a TUNX file
const buffer = new Uint8Array(readFileSync('tournament.TUNX'));
const tournament = parse(buffer);
if (tournament) {
console.log(tournament.name); // "IV Elllobregat Open Chess Tmnt Grupo A"
console.log(tournament.rounds); // 9
console.log(tournament.players.length); // 210
// Player data
const player = tournament.players[0];
console.log(player.name); // "Fedoseev, Vladimir"
console.log(player.rating); // 2675
console.log(player.fideId); // "24130737"
console.log(player.title); // "GM"
console.log(player.points); // 6.5
console.log(player.rank); // 1
}
```
## API
### `parse(input, options?)`
Decode a TUNX binary buffer into a `Tournament` object.
```typescript
function parse(
input: Uint8Array,
options?: ParseOptions,
): Tournament | undefined;
```
- Returns `undefined` for unrecoverable failures (bad magic, missing markers).
- Calls `options.onError` before returning `undefined`.
- Calls `options.onWarning` for recoverable issues — parsing continues.
- Never throws.
### `ParseOptions`
```typescript
interface ParseOptions {
onError?: (error: ParseError) => void;
onWarning?: (warning: ParseWarning) => void;
}
```
### `ParseError`
```typescript
interface ParseError {
message: string;
offset?: number;
}
```
### `ParseWarning`
```typescript
interface ParseWarning {
message: string;
offset?: number;
}
```
## Types
Output types are compatible with
[`@echecs/trf`](https://www.npmjs.com/package/@echecs/trf).
### `Tournament`
```typescript
interface Tournament {
// TRF-compatible fields
chiefArbiter?: string;
city?: string;
deputyArbiters?: string[];
endDate?: string;
federation?: string;
name?: string;
numberOfPlayers?: number;
players: Player[];
roundDates?: string[];
rounds: number;
startDate?: string;
tiebreaks?: string[];
timeControl?: string;
tournamentType?: string;
// TUNX-specific extensions
currentRound?: number;
header?: Header;
pairings?: Pairing[][];
roundTimes?: string[];
subtitle?: string;
venue?: string;
}
```
### `Player`
```typescript
interface Player {
birthDate?: string;
federation?: string;
fideId?: string;
name: string;
nationalRatings?: NationalRating[];
pairingNumber: number;
points: number;
rank: number;
rating?: number;
results: RoundResult[];
sex?: Sex;
title?: Title;
}
```
### `RoundResult`
```typescript
interface RoundResult {
color: '-' | 'b' | 'w';
opponentId: number | null;
result: ResultCode;
round: number;
}
```
### `Pairing`
Per-board pairing record, grouped by round in `Tournament.pairings`.
```typescript
interface Pairing {
black: number;
board: number;
result?: ResultCode;
white: number;
}
```
### `Header`
TUNX-specific header metadata. Available on `Tournament.header`.
```typescript
interface Header {
installSignature: Uint8Array;
installedAt?: Date;
licenseHash: Uint8Array;
savedAt?: Date;
tournamentId: number;
}
```
### `NationalRating`
```typescript
interface NationalRating {
birthDate?: string;
classification?: string;
federation: string;
name?: string;
nationalId?: string;
origin?: string;
pairingNumber: number;
rating: number;
sex?: Sex;
}
```
### `ResultCode`
```typescript
type ResultCode =
| '+'
| '-'
| '0'
| '1'
| '='
| 'D'
| 'F'
| 'H'
| 'L'
| 'U'
| 'W'
| 'Z';
```
| Code | Meaning |
| ---- | ------------------------- |
| `1` | Win |
| `0` | Loss |
| `=` | Draw |
| `+` | Forfeit win |
| `-` | Forfeit loss |
| `D` | Draw by forfeit |
| `F` | Full-point bye |
| `H` | Half-point bye |
| `L` | Loss by forfeit (special) |
| `W` | Win by forfeit (special) |
| `Z` | Zero-point bye / unpaired |
| `U` | Unplayed |
### `Sex`
```typescript
type Sex = 'm' | 'w';
```
### `Tiebreak`
Known tiebreak identifiers used as values in `Tournament.tiebreaks`.
```typescript
type Tiebreak =
| 'average-rating'
| 'buchholz'
| 'buchholz-cut-1'
| 'buchholz-cut-2'
| 'buchholz-cut-3'
| 'direct-encounter'
| 'koya'
| 'median-buchholz'
| 'number-of-wins'
| 'performance-rating'
| 'progressive'
| 'sonneborn-berger';
```
### `Title`
```typescript
type Title = 'CM' | 'FM' | 'GM' | 'IM' | 'WCM' | 'WFM' | 'WGM' | 'WIM';
```
## TUNX Format
TUNX is the proprietary binary format used by
[Swiss-Manager](https://swiss-manager.at/). The format uses little-endian
integers and UTF-16LE strings with U16LE length prefixes.
### File Structure
1. **Header** (108 bytes) — magic `93 FF 89 44`, tournament ID, license data
2. **Metadata strings** — name, subtitle, arbiters, city, time control
3. **Config section** (`95 FF 89 44`) — rounds, players, dates, tiebreaks
4. **A3 sub-section** (`A3 FF 89 44`) — per-round schedule (dates, times)
5. **Player records** (`A5 FF 89 44`) — 30 strings + 110-byte numeric block
6. **Pairings** (`B3 FF 89 44`) — 21-byte records per pairing
7. **D3 section** (`D3 FF 89 44`) — section offset table
8. **E3 section** (`E3 FF 89 44`) — file terminator
## License
MIT