Files
pairgoth/CLAUDE.md
Claude Brisson 662f438cee Update documentation for API, configuration, and model
API.md:
- Add export formats (JSON, XML, EGF, FFG, CSV)
- Document /explain endpoint for pairing analysis
- Add PUT /standings for freezing
- Improve parameter documentation
- Fix typos (regitration -> registration, #tip -> #tid)

configuration.md:
- Add property loading hierarchy
- Document SSL/TLS configuration
- Add OAuth provider configuration
- Add ratings.path property
- Include example configurations

model.md:
- Complete entity diagram with Team, external IDs
- Document all tournament types (PAIRGO, RENGO, TEAM)
- Add TimeSystem types and parameters
- Document all pairing parameters
- List all 39 tiebreak criteria
- Add external database (AGA, EGF, FFG) documentation
2025-11-29 08:05:53 +01:00

4.9 KiB

Pairgoth Project

Purpose

Pairgoth is a modern Go tournament pairing engine - successor to OpenGotha. It manages tournaments using Swiss and MacMahon pairing systems, handling player registration, automatic pairing, results entry, and standings calculation.

Version: 0.20 | License: org.jeudego (French Go Association)

Tech Stack

  • Backend: Kotlin 2.1 + Maven + Jetty 10
  • Frontend: Fomantic UI CSS 2.9.2 + Vanilla JavaScript (no jQuery/React)
  • Templates: Apache Velocity 2.4
  • Storage: File-based XML (no database required)
  • JDK: 11+

Project Structure

pairgoth/
├── pairgoth-common/     # Shared utilities (JSON, XML, crypto, logging)
├── api-webapp/          # REST API backend (port 8085)
│   └── model/           #   Domain: Tournament, Player, Game, Pairing
│   └── pairing/         #   Solvers: Swiss, MacMahon algorithms
│   └── store/           #   Persistence: File/Memory storage
│   └── api/             #   Handlers: Tournament, Player, Results, etc.
│   └── ext/             #   OpenGotha import/export
├── view-webapp/         # Web UI frontend (port 8080)
│   └── webapp/js/       #   Vanilla JS: domhelper, api, main, tour-*.inc
│   └── webapp/sass/     #   Styles: main, tour, explain, index
│   └── templates/       #   Velocity: index, tour, explain, login
│   └── kotlin/          #   Servlets, OAuth, Ratings integration
├── webserver/           # Standalone Jetty launcher
├── application/         # Final JAR packaging
└── docker/              # Container deployment

Architecture

Dual-Webapp Pattern

[Browser] <--8080--> [view-webapp] <--8085--> [api-webapp]
              │              │                     │
        Velocity HTML    ApiClient.kt         REST JSON
        + vanilla JS                          + FileStore
  • api-webapp - Pure REST API, business logic, pairing engine
  • view-webapp - Web UI, proxies API calls, handles auth/i18n/ratings

Key Architectural Decisions

  1. No JS Framework - 2200 lines of vanilla JS vs typical 50KB+ bundle
  2. Fomantic CSS Only - Using CSS framework without its jQuery-dependent JS
  3. CSS @layer - Clean cascade: semantic layer < pairgoth layer
  4. File Storage - XML files for portability, no database setup needed
  5. Read/Write Locks - Simple concurrency on API servlet
  6. SSE Events - Real-time updates via Server-Sent Events

Domain Model

Tournament (sealed class)
├── IndividualTournament
├── PairTournament
├── TeamTournament
└── RengoTournament

Player → Pairable (interface)
Game { white, black, result, handicap }
Pairing { Swiss | MacMahon }
TimeSystem { ByoYomi | SuddenDeath | Canadian | Fischer }
Rules { French | Japanese | AGA | Chinese }

Pairing Engine

Location: api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/

  • SwissSolver - Swiss system pairing algorithm
  • MacMahonSolver - MacMahon bands system
  • HistoryHelper - Criteria: wins, SOS, SOSOS, colors, CUSS, etc.
  • PairingListener - Progress callbacks for UI

Key Files

Purpose Path
DOM utilities view-webapp/.../js/domhelper.js
API client view-webapp/.../js/api.js
Core UI view-webapp/.../js/main.js
Main styles view-webapp/.../sass/main.scss
Tournament model api-webapp/.../model/Tournament.kt
Swiss solver api-webapp/.../pairing/solver/SwissSolver.kt
API router api-webapp/.../server/ApiServlet.kt
App launcher webserver/.../application/Pairgoth.kt

Build & Run

# Build
mvn clean package

# Run standalone (both webapps)
java -jar application/target/pairgoth-engine.jar

# Or separate:
# API: localhost:8085/api
# UI:  localhost:8080/

Configuration

File: pairgoth.properties (user) or pairgoth.default.properties (defaults)

webapp.port = 8080
api.port = 8085
store = file                    # file | memory
store.file.path = tournamentfiles
auth = none                     # none | oauth | sesame

Frontend Patterns

State via CSS Classes

  • .active - tabs, accordions, visible elements
  • .shown - modals/popups
  • .hidden / .disabled / .selected / .dimmed

Component Communication

// Custom events
box.dispatchEvent(new CustomEvent('listitem-dblclk', { detail: id }));

// jQuery-like API (domhelper.js)
$('.item').addClass('active').on('click', handler);

API Integration

api.getJson('/tour/123/players')
   .then(players => render(players))
   .catch(err => error(err));

External Integrations

  • Ratings: FFG (French), EGF (European), AGA (Australian)
  • OAuth: FFG, Google, Facebook, Twitter, Instagram
  • Import/Export: OpenGotha XML format compatibility

i18n

Translations in view-webapp/.../WEB-INF/translations/

  • English (default)
  • French (fr)
  • German (de)
  • Korean (ko)