declare class Player {
    id: string;
    elo: number;
    constructor(id: string, elo: number);
    static create(id: string, elo: number): Player;
    getExpectedResult(opponentElo: number): number;
    calculate(opponentElo: number, won: boolean, kFactor: number): number;
}

declare class Team {
    id: string;
    players: Map<string, Player>;
    constructor(id: string, players?: Player[]);
    static create(id: string, players?: Player[]): Team;
    addPlayer(player: Player): this;
    addPlayers(...players: Player[]): this;
    getAverageElo(): number;
}

interface Options {
    kFactor?: number;
    minContestants?: number;
    maxContestants?: number;
}

interface PlayerResult {
    id: string;
    elo: number;
}
interface TeamResult {
    id: string;
    players: PlayerResult[];
}
type Results = PlayerResult[] | TeamResult[];

type Contestant = Player | Team;
declare abstract class Match {
    private _contestants;
    private _completed;
    protected readonly minContestants: number;
    protected readonly maxContestants: number;
    protected readonly kFactor: number;
    constructor(options?: Options);
    get contestants(): Map<string, Contestant>;
    get size(): number;
    get completed(): boolean;
    protected set completed(completed: boolean);
    protected contestantMapToEloMap(): Map<string, number>;
    protected contestantMapToResults<T extends Results>(): T;
    protected findOpponentElos(contestantId: string, contestants: Map<string, number>): number[];
    protected addContestant(contestant: Contestant): void;
    getResults(): Results;
    abstract calculate(contestantIds: string | string[]): Results;
}

type DuelOptions = Partial<Pick<Options, 'kFactor'>>;
declare class Duel extends Match {
    constructor(players?: Player[], options?: DuelOptions);
    static create(players?: Player[], options?: DuelOptions): Duel;
    addPlayer(player: Player): this;
    addPlayers(...players: Player[]): this;
    calculate(playerId: string): PlayerResult[];
}

interface FreeForAllOptions extends Partial<Pick<Options, 'kFactor'>> {
    minPlayers?: number;
    maxPlayers?: number;
}
declare class FreeForAll extends Match {
    constructor(players?: Player[], options?: FreeForAllOptions);
    static create(players?: Player[], options?: FreeForAllOptions): FreeForAll;
    addPlayer(player: Player): this;
    addPlayers(...players: Player[]): this;
    calculate(playerIds: string[]): PlayerResult[];
}

type TeamDuelOptions = Partial<Pick<Options, 'kFactor'>>;
declare class TeamDuel extends Match {
    constructor(teams?: Team[], options?: TeamDuelOptions);
    static create(teams?: Team[], options?: TeamDuelOptions): TeamDuel;
    addTeam(team: Team): this;
    addTeams(...teams: Team[]): this;
    calculate(teamId: string): TeamResult[];
}

interface TeamFreeForAllOptions extends Partial<Pick<Options, 'kFactor'>> {
    minTeams?: number;
    maxTeams?: number;
}
declare class TeamFreeForAll extends Match {
    constructor(teams?: Team[], options?: TeamFreeForAllOptions);
    static create(teams?: Team[], options?: TeamFreeForAllOptions): TeamFreeForAll;
    addTeam(team: Team): this;
    addTeams(...teams: Team[]): this;
    calculate(teamIds: string[]): TeamResult[];
}

export { Duel, FreeForAll, Player, Team, TeamDuel, TeamFreeForAll };
