import { Collection } from "@gouvernathor/python/collections/abc";
import { Approval, Ranked, Score, Single } from "./ballot";
export interface DisagreementFunction<T, U> {
    (t: T, u: U): number;
}
export interface VotingToBallot<Voter, Candidate, Ballot> {
    (voter: Voter, candidates: Collection<Candidate>): Ballot;
}
/**
 * The most basic and widespread voting system :
 * the voter chooses one of the available candidates,
 * or (not implemented here) for none of them.
 */
export declare function singleVote<Voter, Candidate>({ disagree }: {
    disagree: DisagreementFunction<Voter, Candidate>;
}): VotingToBallot<Voter, Candidate, Single<Candidate>>;
/**
 * The voter ranks all, or (not implemented here) some, of the candidates.
 */
export declare function orderingVote<Voter, Candidate>({ disagree }: {
    disagree: DisagreementFunction<Voter, Candidate>;
}): VotingToBallot<Voter, Candidate, Ranked<Candidate>>;
/**
 * The voter gives a score (or a grade) to each candidate.
 * The number of grades must be provided to the constructor.
 *
 * The implementation of this voting method is not as straightforward as the two previous ones,
 * even setting strategic voting aside.
 * What is to be considered to be the range of grades to cover ?
 * From nazis to angels, or from the worst present candidate to the best ?
 * The answer lies only in the minds of the voters.
 * The latter is more akin to orderingVote, so I implemented the former,
 * but it causes issues for lower grades so approvalVote uses the latter.
 *
 * In this implementation, the voter gives to each candidate
 * a score proportional to the raw disagreement.
 * This may yield situations where every party is graded 0,
 * especially with low nScores values.
 */
export declare function cardinalVote<Voter, Candidate>({ nScores, disagree }: {
    nScores: number;
    disagree: DisagreementFunction<Voter, Candidate>;
}): VotingToBallot<Voter, Candidate, Score<Candidate>>;
/**
 * Alternative implementation of cardinalVote.
 * The candidate(s) the least disagreed with are given the maximum score (which is nScores-1),
 * the candidate(s) the most disagreed with (unless all candidates have the same raw disagreement) gets 0,
 * and the score of the other candidates is proportional (well, affine) between those values.
 */
export declare function balancedCardinalVote<Voter, Candidate>({ nScores, disagree }: {
    nScores: number;
    disagree: DisagreementFunction<Voter, Candidate>;
}): VotingToBallot<Voter, Candidate, Score<Candidate>>;
/**
 * The voter approves or disapproves each of the candidates.
 *
 * Technically a special case of a cardinal/score vote where scores are 0 and 1,
 * but this one makes it open to additional attribution methods
 * (proportional ones for instance).
 * That's why the format it returns is not the same as with the cardinal vote.
 * If you want a scores-like ballot, use balancedCardinalVote({ nScores: 2 }) instead.
 */
export declare function approvalVote<Voter, Candidate>({ disagree }: {
    disagree: DisagreementFunction<Voter, Candidate>;
}): VotingToBallot<Voter, Candidate, Approval<Candidate>>;
