-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.ts
57 lines (50 loc) · 1.71 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import { MatrixScoreMethod } from '../../classes/matrix-score-method'
import type { Matrix, ScoreObject } from '../../types'
export enum MinimaxVariant {
WinningVotes = 'WINNING_VOTES',
Margins = 'MARGINS',
PairwiseOpposition = 'PAIRWISE_OPPOSITION',
}
const scoreXY = {
[MinimaxVariant.Margins]: (xOverY: number, yOverX: number) => xOverY - yOverX, // default
[MinimaxVariant.PairwiseOpposition]: (xOverY: number) => xOverY,
[MinimaxVariant.WinningVotes]: (xOverY: number, yOverX: number) =>
xOverY > yOverX ? xOverY : 0,
}
const computeScores = (
matrix: Matrix,
variant: MinimaxVariant,
excludeTies: boolean,
): ScoreObject => {
const s: ScoreObject = {}
for (const [c1Index, candidate] of matrix.candidates.entries()) {
s[candidate] = -Math.max(
...(matrix.array[c1Index]
.map((yOverX, c2Index) => {
const xOverY = matrix.array[c2Index][c1Index]
return xOverY === yOverX && excludeTies
? null
: scoreXY[variant](xOverY, yOverX)
})
.filter((_, c2Index) => c2Index !== c1Index)
.filter((v) => v !== null) as number[]),
)
}
return s
}
/**
* #### Wikipedia: [Minimax Condorcet method](https://en.wikipedia.org/wiki/Minimax_Condorcet_method)
*/
export class Minimax extends MatrixScoreMethod {
public minimaxVariant: MinimaxVariant
public excludeTies: boolean
public static Variants = MinimaxVariant
constructor(i: Matrix & { variant?: MinimaxVariant; excludeTies?: boolean }) {
super(i)
this.minimaxVariant = i.variant || MinimaxVariant.Margins
this.excludeTies = i.excludeTies || false
}
public scores(): ScoreObject {
return computeScores(this.matrix, this.minimaxVariant, this.excludeTies)
}
}