From aa6c01076ad6e2b615d4c87be17ec06f0a47243d Mon Sep 17 00:00:00 2001 From: lzear Date: Sat, 9 Jan 2021 03:03:18 +0100 Subject: [PATCH 1/6] feat: add Coombs' method --- README.md | 21 +++++++----- codecov.yml | 4 +-- package.json | 3 -- src/methods/approbation/approbation.test.ts | 2 +- src/methods/borda/index.ts | 3 +- src/methods/coombs/index.ts | 33 ++++++++++++++++++ src/methods/first-past-the-post/fptp.test.ts | 2 +- src/methods/first-past-the-post/index.ts | 3 +- src/methods/index.ts | 2 ++ .../two-round-runoff/two-round-runoff.test.ts | 2 +- src/types.ts | 1 + src/utils/makeMatrix.test.ts | 2 +- src/utils/normalize.test.ts | 12 +++---- src/utils/sanity.test.ts | 34 +++++++++++++++---- src/utils/scores.test.ts | 2 +- src/votes.test.ts | 23 +++++++------ 16 files changed, 105 insertions(+), 44 deletions(-) create mode 100644 src/methods/coombs/index.ts diff --git a/README.md b/README.md index 568e4c5..ba47a9e 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![version](https://img.shields.io/npm/v/votes)](https://www.npmjs.com/package/votes) ![bundle size](https://img.shields.io/bundlephobia/min/votes) +[![Known Vulnerabilities](https://snyk.io/test/github/lzear/votes/badge.svg?targetFile=package.json)](https://snyk.io/test/github/lzear/votes?targetFile=package.json) ![downloads](https://img.shields.io/npm/dm/votes) ![Semantic release](https://github.com/lzear/votes/workflows/Semantic%20release/badge.svg) [![Build Status](https://travis-ci.com/lzear/votes.svg?branch=master)](https://travis-ci.com/lzear/votes) @@ -9,6 +10,7 @@ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/08af655918d741d1bffca7ec12ba72be)](https://app.codacy.com/gh/lzear/votes?utm_source=github.com&utm_medium=referral&utm_content=lzear/votes&utm_campaign=Badge_Grade_Settings) [![CodeClimate Coverage](https://api.codeclimate.com/v1/badges/0a98aa30f16e04bc3eac/test_coverage)](https://codeclimate.com/github/lzear/votes/test_coverage) [![CodeClimate Maintainability](https://api.codeclimate.com/v1/badges/0a98aa30f16e04bc3eac/maintainability)](https://codeclimate.com/github/lzear/votes/maintainability) +[![CodeFactor](https://www.codefactor.io/repository/github/lzear/votes/badge)](https://www.codefactor.io/repository/github/lzear/votes) ![codecov](https://codecov.io/gh/lzear/votes/branch/master/graph/badge.svg?token=Fd9Jk4FeBY) ![last commit](https://img.shields.io/github/last-commit/lzear/votes) ![language](https://img.shields.io/github/languages/top/lzear/votes) @@ -49,11 +51,10 @@ See [Comparison of electoral systems (Wikipedia)](https://en.wikipedia.org/wiki/Comparison_of_electoral_systems) for more information. -**⚠️Maximal lotteries & Randomized Condorcet⚠️** (Errors included): -Returns probabilities for each candidate that should be used for a lottery -between the Candidates. If a candidate is the Condorcet winner, its -probability will be 1. Despite being non-deterministic, -those methods are the most fair. +**⚠️Maximal lotteries & Randomized Condorcet⚠️** (Errors included): Returns +probabilities for each candidate that should be used for a lottery between the +Candidates. If a candidate is the Condorcet winner, its probability will be 1. +Despite being non-deterministic, those methods are the most fair. **Ranked pairs**: Using the duel results as edges, build an acyclic graph starting by the strongest score differences. The roots of the graph are the @@ -81,12 +82,16 @@ The winner is the most-approved candidate. **Borda's count**: For each voter, every candidate is given a number of points which equals the number of candidates ranked lower in the voter's preference. -**Instant runoff**: Considering only the top choice of each voter, the candidate +**Instant-runoff**: Considering only the top choice of each voter, the candidate with the fewest votes is eliminated. The election repeats until there is a winner. This voting system is very similar to single transferable vote method. -**Two-round system**: If no candidate receives 50% of the votes in the first -round, then a second round of voting is held with only the top two candidates. +**Coombs' method**: Each round, the candidate with the most last rank is +eliminated. The election repeats until there is a winner. + +**Contingent vote** (immediate **Two-round system**): If no candidate receives +50% of the votes in the first round, then a second round of voting is held with +only the top two candidates. **Plurality**: Simple voting method where only the preferred candidate of each voter gets 1 point. AKA first-past-the-post. diff --git a/codecov.yml b/codecov.yml index bdd41f4..117bf19 100644 --- a/codecov.yml +++ b/codecov.yml @@ -2,8 +2,8 @@ coverage: status: project: default: - target: 90% # the required coverage value - threshold: 1% # the leniency in hitting the target + target: 90% # the required coverage value + threshold: 1% # the leniency in hitting the target patch: default: target: 80% diff --git a/package.json b/package.json index 5633e6b..990a256 100644 --- a/package.json +++ b/package.json @@ -16,9 +16,6 @@ "url": "https://github.com/lzear/votes.git" }, "license": "MIT", - "engines": { - "node": ">=6.0.0" - }, "scripts": { "eslint": "eslint --ext .js --ext .ts .", "fix:prettier": "prettier --write \"**/*.*\"", diff --git a/src/methods/approbation/approbation.test.ts b/src/methods/approbation/approbation.test.ts index aa50cdf..c1205bd 100644 --- a/src/methods/approbation/approbation.test.ts +++ b/src/methods/approbation/approbation.test.ts @@ -3,5 +3,5 @@ import { approbation } from '.' it('skips empty votes', () => { expect( approbation.computeFromBallots([{ weight: 1, ranking: [] }], ['a']), - ).toMatchObject({}) + ).toStrictEqual({ a: 0 }) }) diff --git a/src/methods/borda/index.ts b/src/methods/borda/index.ts index 6efac35..e01677c 100644 --- a/src/methods/borda/index.ts +++ b/src/methods/borda/index.ts @@ -5,12 +5,13 @@ import { Ballot, } from '../../types' import { scoresZero } from '../../utils/scoresZero' +import { normalizeBallots } from '../../utils' export const borda: SystemUsingRankings = { type: VotingSystem.Borda, computeFromBallots(ballots: Ballot[], candidates: string[]): ScoreObject { const result: ScoreObject = scoresZero(candidates) - ballots.forEach((ballot) => { + normalizeBallots(ballots, candidates).forEach((ballot) => { let voteValue = candidates.length - 1 ballot.ranking.forEach((candidatesAtRank) => { const value = voteValue - (candidatesAtRank.length - 1) / 2 diff --git a/src/methods/coombs/index.ts b/src/methods/coombs/index.ts new file mode 100644 index 0000000..96a3900 --- /dev/null +++ b/src/methods/coombs/index.ts @@ -0,0 +1,33 @@ +import difference from 'lodash/difference' +import { + SystemUsingRankings, + ScoreObject, + VotingSystem, + Ballot, +} from '../../types' +import { firstPastThePost } from '../first-past-the-post' +import { scoresToRanking } from '../../utils' + +export const coombs: SystemUsingRankings = { + type: VotingSystem.Coombs, + computeFromBallots(ballots: Ballot[], candidates: string[]): ScoreObject { + const score: ScoreObject = {} + const reversedBallots = ballots.map((ballot) => ({ + ranking: [...ballot.ranking].reverse(), + weight: ballot.weight, + })) + let remainingCandidates = [...candidates] + let points = 0 + while (remainingCandidates.length > 0) { + const fptpScore = firstPastThePost.computeFromBallots( + reversedBallots, + remainingCandidates, + ) + const ranking = scoresToRanking(fptpScore) + for (const winner of ranking[0]) score[winner] = points + remainingCandidates = difference(remainingCandidates, ranking[0]) + points++ + } + return score + }, +} diff --git a/src/methods/first-past-the-post/fptp.test.ts b/src/methods/first-past-the-post/fptp.test.ts index 78dbea3..eb1a3b2 100644 --- a/src/methods/first-past-the-post/fptp.test.ts +++ b/src/methods/first-past-the-post/fptp.test.ts @@ -3,5 +3,5 @@ import { firstPastThePost } from '.' it('skips empty votes', () => { expect( firstPastThePost.computeFromBallots([{ weight: 1, ranking: [] }], ['a']), - ).toMatchObject({}) + ).toStrictEqual({ a: 0 }) }) diff --git a/src/methods/first-past-the-post/index.ts b/src/methods/first-past-the-post/index.ts index f759e26..401432e 100644 --- a/src/methods/first-past-the-post/index.ts +++ b/src/methods/first-past-the-post/index.ts @@ -5,6 +5,7 @@ import { Ballot, } from '../../types' import { scoresZero } from '../../utils/scoresZero' +import { normalizeBallots } from '../../utils' export const iterateFirstChoices = ( ballots: Ballot[], @@ -12,7 +13,7 @@ export const iterateFirstChoices = ( compute: (rank: string[]) => number, ): ScoreObject => { const result: ScoreObject = scoresZero(candidates) - ballots.forEach((ballot) => { + normalizeBallots(ballots, candidates).forEach((ballot) => { if (ballot.ranking.length) { const votes = ballot.ranking[0].filter((c) => candidates.includes(c)) votes.forEach( diff --git a/src/methods/index.ts b/src/methods/index.ts index 4c8182f..8ead42d 100644 --- a/src/methods/index.ts +++ b/src/methods/index.ts @@ -1,6 +1,7 @@ import { VotingSystem } from '../types' import { approbation } from './approbation' import { borda } from './borda' +import { coombs } from './coombs' import { copeland } from './copeland' import { firstPastThePost } from './first-past-the-post' import { instantRunoff } from './instant-runoff' @@ -15,6 +16,7 @@ import { twoRoundRunoff } from './two-round-runoff' export const methods = { [VotingSystem.Approbation]: approbation, [VotingSystem.Borda]: borda, + [VotingSystem.Coombs]: coombs, [VotingSystem.Copeland]: copeland, [VotingSystem.FirstPastThePost]: firstPastThePost, [VotingSystem.InstantRunoff]: instantRunoff, diff --git a/src/methods/two-round-runoff/two-round-runoff.test.ts b/src/methods/two-round-runoff/two-round-runoff.test.ts index 97e005c..ecb436a 100644 --- a/src/methods/two-round-runoff/two-round-runoff.test.ts +++ b/src/methods/two-round-runoff/two-round-runoff.test.ts @@ -3,5 +3,5 @@ import { twoRoundRunoff } from '.' it('skips empty votes', () => { expect( twoRoundRunoff.computeFromBallots([{ weight: 1, ranking: [] }], ['a']), - ).toMatchObject({}) + ).toStrictEqual({ a: 0 }) }) diff --git a/src/types.ts b/src/types.ts index 324f7b1..ae5739b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -9,6 +9,7 @@ export type ScoreObject = { [candidate: string]: number } export enum VotingSystem { Approbation = 'APPROBATION', Borda = 'BORDA', + Coombs = 'COOMBS', Copeland = 'COPELAND', FirstPastThePost = 'FIRST_PAST_THE_POST', Kemeny = 'KEMENY', diff --git a/src/utils/makeMatrix.test.ts b/src/utils/makeMatrix.test.ts index bd2b53f..93bde9c 100644 --- a/src/utils/makeMatrix.test.ts +++ b/src/utils/makeMatrix.test.ts @@ -2,7 +2,7 @@ import { makeAntisymetric, matrixFromBallots } from '.' import { abcde, balinski } from '../test/testUtils' it('makes antisymetric', () => { - expect(makeAntisymetric(matrixFromBallots(balinski, abcde))).toMatchObject({ + expect(makeAntisymetric(matrixFromBallots(balinski, abcde))).toStrictEqual({ array: [ [0, -34, -34, -34, -28], [34, 0, -2, 58, 4], diff --git a/src/utils/normalize.test.ts b/src/utils/normalize.test.ts index 46acd7d..102e20a 100644 --- a/src/utils/normalize.test.ts +++ b/src/utils/normalize.test.ts @@ -18,7 +18,7 @@ it('groups ballots', () => { { weight: 4, ranking: [['d', 'b'], ['c']] }, { weight: 5, ranking: [['a', 'b'], ['c']] }, ]), - ).toMatchObject([ + ).toStrictEqual([ { weight: 8, ranking: [['a', 'b'], ['c']] }, { weight: 4, ranking: [['d', 'b'], ['c']] }, ]) @@ -31,13 +31,13 @@ it('throw on duplicated candidates', () => { }) it('removes duplicated candidates', () => { - expect(removeDuplicatedCandidates([['a', 'b'], ['a']])).toMatchObject([ + expect(removeDuplicatedCandidates([['a', 'b'], ['a']])).toStrictEqual([ ['a', 'b'], ]) }) it('normalizes rankinput', () => { - expect(normalizeRankinput([['a', 'b'], 'c', 'd', ['e']])).toMatchObject([ + expect(normalizeRankinput([['a', 'b'], 'c', 'd', ['e']])).toStrictEqual([ ['a', 'b'], ['c'], ['d'], @@ -52,7 +52,7 @@ it('gets candidates from ballots', () => { { weight: 4, ranking: [['d', 'b'], ['c']] }, { weight: 5, ranking: [['a', 'b'], ['c']] }, ]), - ).toMatchObject(['a', 'b', 'c', 'd']) + ).toStrictEqual(['a', 'b', 'c', 'd']) }) it('normalizes ballots', () => { @@ -62,7 +62,7 @@ it('normalizes ballots', () => { { weight: 4, ranking: [['d', 'b'], [], ['c']] }, { weight: 5, ranking: [['a', 'b'], ['c']] }, ]), - ).toMatchObject([ + ).toStrictEqual([ { weight: 3, ranking: [['a', 'b'], ['c']] }, { weight: 4, ranking: [['d', 'b'], ['c']] }, { weight: 5, ranking: [['a', 'b'], ['c']] }, @@ -76,7 +76,7 @@ it('normalizes ballots', () => { ], ['a', 'b', 'c'], ), - ).toMatchObject([ + ).toStrictEqual([ { weight: 3, ranking: [['a', 'b'], ['c']] }, { weight: 4, ranking: [['b'], ['c']] }, { weight: 5, ranking: [['a', 'b'], ['c']] }, diff --git a/src/utils/sanity.test.ts b/src/utils/sanity.test.ts index e530f44..f340373 100644 --- a/src/utils/sanity.test.ts +++ b/src/utils/sanity.test.ts @@ -4,11 +4,31 @@ import { scoresFromBallots, scoresToRanking } from '.' describe('sanity check', () => { it.each(Object.values(VotingSystem) as VotingSystem[])( - 'empty list %p', + 'empty list and empty candidates %p', + (system) => { + expect(scoresToRanking(scoresFromBallots([], [], system))).toStrictEqual( + [], + ) + }, + ) + it.each(Object.values(VotingSystem) as VotingSystem[])( + 'empty ballot list %p', (system) => { expect( scoresToRanking(scoresFromBallots([], ['a', 'b', 'c'], system))[0], - ).toMatchObject(['a', 'b', 'c']) + ).toStrictEqual(['a', 'b', 'c']) + }, + ) + it.each(Object.values(VotingSystem) as VotingSystem[])( + 'empty candidates list %p', + (system) => { + expect( + scoresFromBallots( + [{ ranking: [['a'], ['b'], ['c']], weight: 1 }], + [], + system, + ), + ).toStrictEqual({}) }, ) it.each(Object.values(VotingSystem) as VotingSystem[])( @@ -22,7 +42,7 @@ describe('sanity check', () => { system, ), )[0], - ).toMatchObject(['a']) + ).toStrictEqual(['a']) }, ) @@ -37,7 +57,7 @@ describe('sanity check', () => { system, ), )[0], - ).toMatchObject(['a', 'd']) + ).toStrictEqual(['a', 'd']) }, ) @@ -56,7 +76,7 @@ describe('sanity check', () => { system, ), )[0], - ).toMatchObject(['a', 'b', 'c']) + ).toStrictEqual(['a', 'b', 'c']) }, ) it.each(Object.values(VotingSystem) as VotingSystem[])( @@ -64,7 +84,7 @@ describe('sanity check', () => { (system) => { expect( scoresToRanking(scoresFromBallots(dummyProfile, abcde, system))[0], - ).toMatchObject(['a']) + ).toStrictEqual(['a']) }, ) it.each(Object.values(VotingSystem) as VotingSystem[])( @@ -72,7 +92,7 @@ describe('sanity check', () => { (system) => { expect( scoresToRanking(scoresFromBallots(dummyProfile10, abcde, system))[0], - ).toMatchObject(['a']) + ).toStrictEqual(['a']) }, ) }) diff --git a/src/utils/scores.test.ts b/src/utils/scores.test.ts index d87c822..52d3b30 100644 --- a/src/utils/scores.test.ts +++ b/src/utils/scores.test.ts @@ -1,7 +1,7 @@ import { scoresToRanking } from './scores' it('convert scores to ranking', () => { - expect(scoresToRanking({ a: 10, b: 5, c: 15 })).toMatchObject([ + expect(scoresToRanking({ a: 10, b: 5, c: 15 })).toStrictEqual([ ['c'], ['a'], ['b'], diff --git a/src/votes.test.ts b/src/votes.test.ts index cc7f0d1..0cdf297 100644 --- a/src/votes.test.ts +++ b/src/votes.test.ts @@ -40,6 +40,7 @@ describe('Test all methods', () => { expect(allResults).toStrictEqual({ APPROBATION: ['a'], BORDA: ['a'], + COOMBS: ['a'], FIRST_PAST_THE_POST: ['a'], INSTANT_RUNOFF: ['a'], TWO_ROUND_RUNOFF: ['a'], @@ -73,7 +74,7 @@ describe('Test all methods', () => { Object.values(allResults).forEach((v) => expect(v).toStrictEqual(['a'])) }) it('votes with approbation', () => { - expect(approbation.computeFromBallots(balinski, abcde)).toMatchObject({ + expect(approbation.computeFromBallots(balinski, abcde)).toStrictEqual({ a: 33, b: 16, c: 11, @@ -82,7 +83,7 @@ describe('Test all methods', () => { }) }) it('votes with borda', () => { - expect(borda.computeFromBallots(balinski, abcde)).toMatchObject({ + expect(borda.computeFromBallots(balinski, abcde)).toStrictEqual({ a: 135, b: 247, c: 244, @@ -91,7 +92,7 @@ describe('Test all methods', () => { }) }) it('votes with FPTP', () => { - expect(firstPastThePost.computeFromBallots(balinski, abcde)).toMatchObject({ + expect(firstPastThePost.computeFromBallots(balinski, abcde)).toStrictEqual({ a: 33, b: 16, c: 11, @@ -100,7 +101,7 @@ describe('Test all methods', () => { }) }) it('votes with instant runoff', () => { - expect(instantRunoff.computeFromBallots(balinski, abcde)).toMatchObject({ + expect(instantRunoff.computeFromBallots(balinski, abcde)).toStrictEqual({ a: 33, b: 16, c: 11, @@ -109,7 +110,7 @@ describe('Test all methods', () => { }) }) it('votes with two-round runoff', () => { - expect(twoRoundRunoff.computeFromBallots(balinski, abcde)).toMatchObject({ + expect(twoRoundRunoff.computeFromBallots(balinski, abcde)).toStrictEqual({ a: 36, b: 16, c: 11, @@ -120,7 +121,7 @@ describe('Test all methods', () => { it('votes with copeland', () => { expect( copeland.computeFromMatrix(matrixFromBallots(balinski, abcde)), - ).toMatchObject({ + ).toStrictEqual({ a: -4, b: 1.76, c: 3.84, @@ -131,7 +132,7 @@ describe('Test all methods', () => { it('votes with kemeny', () => { expect( kemeny.computeFromMatrix(matrixFromBallots(balinski, abcde)), - ).toMatchObject({ + ).toStrictEqual({ a: 0, b: 3, c: 4, @@ -142,7 +143,7 @@ describe('Test all methods', () => { it('votes with schulze', () => { expect( schulze.computeFromMatrix(matrixFromBallots(sW, abcde)), - ).toMatchObject({ + ).toStrictEqual({ a: 3, b: 1, c: 2, @@ -153,7 +154,7 @@ describe('Test all methods', () => { it('votes with minimax', () => { expect( minimax.computeFromMatrix(matrixFromBallots(sW, abcde)), - ).toMatchObject({ + ).toStrictEqual({ a: -5, b: -13, c: -11, @@ -165,7 +166,7 @@ describe('Test all methods', () => { it('votes with maximal lotteries', () => { expect( maximalLotteries.computeFromMatrix(matrixFromBallots(sW, abcde)), - ).toMatchObject({ + ).toStrictEqual({ a: 0.6428571428571428, b: 0, c: 0, @@ -176,7 +177,7 @@ describe('Test all methods', () => { it('votes with ranked pairs', () => { expect( rankedPairs.computeFromMatrix(matrixFromBallots(sW, abcde)), - ).toMatchObject({ + ).toStrictEqual({ a: 5, b: 2, c: 4, From cd86fba7def8bc2d55314eec6ce291ed341cbea7 Mon Sep 17 00:00:00 2001 From: lzear Date: Tue, 12 Jan 2021 23:10:42 +0100 Subject: [PATCH 2/6] feat: add Nanson method and Baldwin method --- README.md | 10 +- package.json | 25 ++--- src/methods/baldwin/index.ts | 27 +++++ src/methods/coombs/index.ts | 2 +- src/methods/index.ts | 22 ++++ src/methods/nanson/index.ts | 33 ++++++ src/types.ts | 2 + src/votes.test.ts | 68 +++++++++++-- src/votes.ts | 42 +++++++- typedoc.js | 2 - yarn.lock | 191 +++++++++++++++++++---------------- 11 files changed, 304 insertions(+), 120 deletions(-) create mode 100644 src/methods/baldwin/index.ts create mode 100644 src/methods/nanson/index.ts diff --git a/README.md b/README.md index ba47a9e..16fd9db 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ for more information. **⚠️Maximal lotteries & Randomized Condorcet⚠️** (Errors included): Returns probabilities for each candidate that should be used for a lottery between the Candidates. If a candidate is the Condorcet winner, its probability will be 1. -Despite being non-deterministic, those methods are the most fair. +Despite being non-deterministic, those methods are the fairest. **Ranked pairs**: Using the duel results as edges, build an acyclic graph starting by the strongest score differences. The roots of the graph are the @@ -79,9 +79,15 @@ candidates. **Approval voting**: Each voter can select (“approve”) any number of candidates. The winner is the most-approved candidate. -**Borda's count**: For each voter, every candidate is given a number of points +**Borda count**: For each voter, every candidate is given a number of points which equals the number of candidates ranked lower in the voter's preference. +**Nanson method**: Iterative Borda count in which, each round, candidates scoring +the average score or less are eliminated. + +**Baldwin method**: Iterative Borda count in which, each round, candidates scoring +the lowest score are eliminated. + **Instant-runoff**: Considering only the top choice of each voter, the candidate with the fewest votes is eliminated. The election repeats until there is a winner. This voting system is very similar to single transferable vote method. diff --git a/package.json b/package.json index 990a256..118aeaf 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "module": "dist/votes.es5.js", "types": "dist/votes.d.ts", "files": [ - "dist" + "dist", + "src" ], "author": "lzear", "repository": { @@ -20,7 +21,7 @@ "eslint": "eslint --ext .js --ext .ts .", "fix:prettier": "prettier --write \"**/*.*\"", "prebuild": "rimraf dist", - "build": "rollup -c rollup.config.js && typedoc", + "build": "rollup -c rollup.config.js && npx typedoc src/votes.ts", "build:watch": "tsc --module commonjs && rollup -c rollup.config.js -w", "test": "jest --coverage", "test:watch": "jest --coverage --watch", @@ -53,26 +54,26 @@ "@rollup/plugin-commonjs": "^17.0.0", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^11.0.1", - "@types/jest": "^26.0.19", - "@types/lodash": "^4.14.165", - "@types/node": "^14.14.14", - "@typescript-eslint/eslint-plugin": "^4.11.0", - "@typescript-eslint/parser": "^4.11.0", + "@types/jest": "^26.0.20", + "@types/lodash": "^4.14.167", + "@types/node": "^14.14.20", + "@typescript-eslint/eslint-plugin": "^4.13.0", + "@typescript-eslint/parser": "^4.13.0", "commitizen": "^4.2.2", "dotenv": "^8.2.0", - "eslint": "^7.16.0", + "eslint": "^7.17.0", "eslint-config-prettier": "^7.1.0", - "eslint-plugin-prettier": "^3.3.0", - "husky": "^4.3.6", + "eslint-plugin-prettier": "^3.3.1", + "husky": "^4.3.7", "jest": "^26.6.3", "lint-staged": "^10.5.3", "prettier": "^2.2.1", "rimraf": "^3.0.2", - "rollup": "^2.35.1", + "rollup": "^2.36.1", "rollup-plugin-sizes": "^1.0.3", "rollup-plugin-sourcemaps": "^0.6.3", "rollup-plugin-typescript2": "^0.29.0", - "semantic-release": "^17.3.0", + "semantic-release": "^17.3.1", "shelljs": "^0.8.4", "travis-deploy-once": "^5.0.11", "ts-jest": "^26.4.4", diff --git a/src/methods/baldwin/index.ts b/src/methods/baldwin/index.ts new file mode 100644 index 0000000..3f89ebf --- /dev/null +++ b/src/methods/baldwin/index.ts @@ -0,0 +1,27 @@ +import difference from 'lodash/difference' +import { + SystemUsingRankings, + ScoreObject, + VotingSystem, + Ballot, +} from '../../types' +import { borda } from '../borda' +import { scoresToRanking } from '../../utils' + +export const baldwin: SystemUsingRankings = { + type: VotingSystem.Baldwin, + computeFromBallots(ballots: Ballot[], candidates: string[]): ScoreObject { + const score: ScoreObject = {} + let remainingCandidates = candidates + let points = 0 + while (remainingCandidates.length > 0) { + const bordaScores = borda.computeFromBallots(ballots, remainingCandidates) + const ranking = scoresToRanking(bordaScores) + const losers = ranking[ranking.length - 1] + for (const loser of losers) score[loser] = points + remainingCandidates = difference(remainingCandidates, losers) + points++ + } + return score + }, +} diff --git a/src/methods/coombs/index.ts b/src/methods/coombs/index.ts index 96a3900..7218de8 100644 --- a/src/methods/coombs/index.ts +++ b/src/methods/coombs/index.ts @@ -16,7 +16,7 @@ export const coombs: SystemUsingRankings = { ranking: [...ballot.ranking].reverse(), weight: ballot.weight, })) - let remainingCandidates = [...candidates] + let remainingCandidates = candidates let points = 0 while (remainingCandidates.length > 0) { const fptpScore = firstPastThePost.computeFromBallots( diff --git a/src/methods/index.ts b/src/methods/index.ts index 8ead42d..0b31afb 100644 --- a/src/methods/index.ts +++ b/src/methods/index.ts @@ -1,5 +1,6 @@ import { VotingSystem } from '../types' import { approbation } from './approbation' +import { baldwin } from './baldwin' import { borda } from './borda' import { coombs } from './coombs' import { copeland } from './copeland' @@ -8,6 +9,7 @@ import { instantRunoff } from './instant-runoff' import { kemeny } from './kemeny' import { maximalLotteries } from './maximal-lotteries' import { minimax } from './minimax' +import { nanson } from './nanson' import { rankedPairs } from './ranked-pairs' import { randomizedCondorcet } from './randomized-condorcet' import { schulze } from './schulze' @@ -15,6 +17,7 @@ import { twoRoundRunoff } from './two-round-runoff' export const methods = { [VotingSystem.Approbation]: approbation, + [VotingSystem.Baldwin]: baldwin, [VotingSystem.Borda]: borda, [VotingSystem.Coombs]: coombs, [VotingSystem.Copeland]: copeland, @@ -23,8 +26,27 @@ export const methods = { [VotingSystem.Kemeny]: kemeny, [VotingSystem.MaximalLotteries]: maximalLotteries, [VotingSystem.Minimax]: minimax, + [VotingSystem.NANSON]: nanson, [VotingSystem.RankedPairs]: rankedPairs, [VotingSystem.RandomizedCondorcet]: randomizedCondorcet, [VotingSystem.Schulze]: schulze, [VotingSystem.TwoRoundRunoff]: twoRoundRunoff, } + +export { + approbation, + baldwin, + borda, + coombs, + copeland, + firstPastThePost, + instantRunoff, + kemeny, + maximalLotteries, + minimax, + nanson, + rankedPairs, + randomizedCondorcet, + schulze, + twoRoundRunoff, +} diff --git a/src/methods/nanson/index.ts b/src/methods/nanson/index.ts new file mode 100644 index 0000000..30d8ee5 --- /dev/null +++ b/src/methods/nanson/index.ts @@ -0,0 +1,33 @@ +import sum from 'lodash/sum' +import difference from 'lodash/difference' +import { + SystemUsingRankings, + ScoreObject, + VotingSystem, + Ballot, +} from '../../types' +import { borda } from '../borda' + +export const nanson: SystemUsingRankings = { + type: VotingSystem.NANSON, + computeFromBallots(ballots: Ballot[], candidates: string[]): ScoreObject { + const score: ScoreObject = {} + let remainingCandidates = candidates + let points = 0 + while (remainingCandidates.length > 0) { + const bordaScores = borda.computeFromBallots(ballots, remainingCandidates) + const scores = Object.values(bordaScores) + const avg = sum(scores) / scores.length + const losers = remainingCandidates.filter((c) => bordaScores[c] <= avg) + let maxPoints = points + 1 + for (const loser of losers) { + const p = points + bordaScores[loser] + 1 + score[loser] = p + if (p > maxPoints) maxPoints = p + } + remainingCandidates = difference(remainingCandidates, losers) + points = maxPoints + } + return score + }, +} diff --git a/src/types.ts b/src/types.ts index ae5739b..5361cfb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -8,6 +8,7 @@ export type ScoreObject = { [candidate: string]: number } export enum VotingSystem { Approbation = 'APPROBATION', + Baldwin = 'BALDWIN', Borda = 'BORDA', Coombs = 'COOMBS', Copeland = 'COPELAND', @@ -16,6 +17,7 @@ export enum VotingSystem { InstantRunoff = 'INSTANT_RUNOFF', MaximalLotteries = 'MAXIMAL_LOTTERIES', Minimax = 'MINIMAX', + NANSON = 'NANSON', RandomizedCondorcet = 'RANDOMIZED_CONDORCET', RankedPairs = 'RANKED_PAIRS', Schulze = 'SCHULZE', diff --git a/src/votes.test.ts b/src/votes.test.ts index 0cdf297..56c15a6 100644 --- a/src/votes.test.ts +++ b/src/votes.test.ts @@ -1,17 +1,23 @@ import { methods, SystemUsingMatrix, SystemUsingRankings, utils } from './votes' import { VotingSystem } from './types' import { matrixFromBallots } from './utils' -import { approbation } from './methods/approbation' -import { borda } from './methods/borda' -import { copeland } from './methods/copeland' -import { firstPastThePost } from './methods/first-past-the-post' -import { instantRunoff } from './methods/instant-runoff' -import { kemeny } from './methods/kemeny' -import { maximalLotteries } from './methods/maximal-lotteries' -import { minimax } from './methods/minimax' -import { rankedPairs } from './methods/ranked-pairs' -import { schulze } from './methods/schulze' -import { twoRoundRunoff } from './methods/two-round-runoff' +import { + approbation, + baldwin, + borda, + coombs, + copeland, + firstPastThePost, + instantRunoff, + kemeny, + maximalLotteries, + minimax, + nanson, + randomizedCondorcet, + rankedPairs, + schulze, + twoRoundRunoff, +} from './votes' import { abcde, balinski, dummyProfile, sW } from './test/testUtils' describe('Test all methods', () => { @@ -39,10 +45,12 @@ describe('Test all methods', () => { }, {}) expect(allResults).toStrictEqual({ APPROBATION: ['a'], + BALDWIN: ['a'], BORDA: ['a'], COOMBS: ['a'], FIRST_PAST_THE_POST: ['a'], INSTANT_RUNOFF: ['a'], + NANSON: ['a'], TWO_ROUND_RUNOFF: ['a'], }) Object.values(allResults).forEach((v) => expect(v).toStrictEqual(['a'])) @@ -82,6 +90,15 @@ describe('Test all methods', () => { e: 22, }) }) + it('votes with baldwin', () => { + expect(baldwin.computeFromBallots(balinski, abcde)).toStrictEqual({ + a: 0, + b: 3, + c: 4, + d: 2, + e: 1, + }) + }) it('votes with borda', () => { expect(borda.computeFromBallots(balinski, abcde)).toStrictEqual({ a: 135, @@ -91,6 +108,15 @@ describe('Test all methods', () => { e: 182, }) }) + it('votes with coombs', () => { + expect(coombs.computeFromBallots(balinski, abcde)).toStrictEqual({ + a: 0, + b: 3, + c: 4, + d: 2, + e: 1, + }) + }) it('votes with FPTP', () => { expect(firstPastThePost.computeFromBallots(balinski, abcde)).toStrictEqual({ a: 33, @@ -109,6 +135,15 @@ describe('Test all methods', () => { e: 30, }) }) + it('votes with instant nanson', () => { + expect(nanson.computeFromBallots(balinski, abcde)).toStrictEqual({ + a: 136, + b: 243, + c: 244, + d: 193, + e: 183, + }) + }) it('votes with two-round runoff', () => { expect(twoRoundRunoff.computeFromBallots(balinski, abcde)).toStrictEqual({ a: 36, @@ -140,6 +175,17 @@ describe('Test all methods', () => { e: 1, }) }) + it('votes with randomizedCondorcet', () => { + expect( + randomizedCondorcet.computeFromMatrix(matrixFromBallots(sW, abcde)), + ).toStrictEqual({ + a: 0.3333333333333333, + b: 0, + c: 0.3333333333333333, + d: 0, + e: 0.3333333333333333, + }) + }) it('votes with schulze', () => { expect( schulze.computeFromMatrix(matrixFromBallots(sW, abcde)), diff --git a/src/votes.ts b/src/votes.ts index 7d35a1f..5ee3792 100644 --- a/src/votes.ts +++ b/src/votes.ts @@ -1,4 +1,21 @@ -import { methods } from './methods' +import { + approbation, + baldwin, + borda, + coombs, + copeland, + firstPastThePost, + instantRunoff, + kemeny, + maximalLotteries, + minimax, + nanson, + rankedPairs, + randomizedCondorcet, + schulze, + twoRoundRunoff, + methods, +} from './methods' import { System, VotingSystem, @@ -11,13 +28,32 @@ import { import * as utils from './utils' export { - methods, + // enum VotingSystem, + // All methods: + methods, + approbation, + baldwin, + borda, + coombs, + copeland, + firstPastThePost, + instantRunoff, + kemeny, + maximalLotteries, + minimax, + nanson, + rankedPairs, + randomizedCondorcet, + schulze, + twoRoundRunoff, + // utils + utils, + // types System, SystemUsingRankings, SystemUsingMatrix, Matrix, ScoreObject, Ballot, - utils, } diff --git a/typedoc.js b/typedoc.js index 9996f13..b0b5078 100644 --- a/typedoc.js +++ b/typedoc.js @@ -2,8 +2,6 @@ module.exports = { out: './docs', includes: './src', exclude: ['**/*.test.ts', '**/test/**/*'], - mode: 'file', excludeExternals: true, - excludeNotExported: true, excludePrivate: true, } diff --git a/yarn.lock b/yarn.lock index 91d75f3..d8beb08 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1560,10 +1560,10 @@ jest-diff "^26.0.0" pretty-format "^26.0.0" -"@types/jest@^26.0.19": - version "26.0.19" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.19.tgz#e6fa1e3def5842ec85045bd5210e9bb8289de790" - integrity sha512-jqHoirTG61fee6v6rwbnEuKhpSKih0tuhqeFbCmMmErhtu3BYlOZaXWjffgOstMM4S/3iQD31lI5bGLTrs97yQ== +"@types/jest@^26.0.20": + version "26.0.20" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.20.tgz#cd2f2702ecf69e86b586e1f5223a60e454056307" + integrity sha512-9zi2Y+5USJRxd0FsahERhBwlcvFh6D2GLQnY2FH2BzK8J9s9omvNHIbvABwIluXa0fD8XVKMLTO0aOEuUfACAA== dependencies: jest-diff "^26.0.0" pretty-format "^26.0.0" @@ -1573,10 +1573,10 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== -"@types/lodash@^4.14.165": - version "4.14.165" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.165.tgz#74d55d947452e2de0742bad65270433b63a8c30f" - integrity sha512-tjSSOTHhI5mCHTy/OOXYIhi2Wt1qcbHmuXD1Ha7q70CgI/I71afO4XtLb/cVexki1oVYchpul/TOuu3Arcdxrg== +"@types/lodash@^4.14.167": + version "4.14.167" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.167.tgz#ce7d78553e3c886d4ea643c37ec7edc20f16765e" + integrity sha512-w7tQPjARrvdeBkX/Rwg95S592JwxqOjmms3zWQ0XZgSyxSLdzWaYH3vErBhdVS/lRBX7F8aBYcYJYTr5TMGOzw== "@types/minimist@^1.2.0": version "1.2.0" @@ -1588,10 +1588,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.6.tgz#146d3da57b3c636cc0d1769396ce1cfa8991147f" integrity sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw== -"@types/node@^14.14.14": - version "14.14.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.14.tgz#f7fd5f3cc8521301119f63910f0fb965c7d761ae" - integrity sha512-UHnOPWVWV1z+VV8k6L1HhG7UbGBgIdghqF3l9Ny9ApPghbjICXkUJSd/b9gOgQfjM1r+37cipdw/HJ3F6ICEnQ== +"@types/node@^14.14.20": + version "14.14.20" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.20.tgz#f7974863edd21d1f8a494a73e8e2b3658615c340" + integrity sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -1637,61 +1637,62 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.11.0.tgz#bc6c1e4175c0cf42083da4314f7931ad12f731cc" - integrity sha512-x4arJMXBxyD6aBXLm3W7mSDZRiABzy+2PCLJbL7OPqlp53VXhaA1HKK7R2rTee5OlRhnUgnp8lZyVIqjnyPT6g== +"@typescript-eslint/eslint-plugin@^4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.13.0.tgz#5f580ea520fa46442deb82c038460c3dd3524bb6" + integrity sha512-ygqDUm+BUPvrr0jrXqoteMqmIaZ/bixYOc3A4BRwzEPTZPi6E+n44rzNZWaB0YvtukgP+aoj0i/fyx7FkM2p1w== dependencies: - "@typescript-eslint/experimental-utils" "4.11.0" - "@typescript-eslint/scope-manager" "4.11.0" + "@typescript-eslint/experimental-utils" "4.13.0" + "@typescript-eslint/scope-manager" "4.13.0" debug "^4.1.1" functional-red-black-tree "^1.0.1" + lodash "^4.17.15" regexpp "^3.0.0" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.11.0.tgz#d1a47cc6cfe1c080ce4ead79267574b9881a1565" - integrity sha512-1VC6mSbYwl1FguKt8OgPs8xxaJgtqFpjY/UzUYDBKq4pfQ5lBvN2WVeqYkzf7evW42axUHYl2jm9tNyFsb8oLg== +"@typescript-eslint/experimental-utils@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.13.0.tgz#9dc9ab375d65603b43d938a0786190a0c72be44e" + integrity sha512-/ZsuWmqagOzNkx30VWYV3MNB/Re/CGv/7EzlqZo5RegBN8tMuPaBgNK6vPBCQA8tcYrbsrTdbx3ixMRRKEEGVw== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.11.0" - "@typescript-eslint/types" "4.11.0" - "@typescript-eslint/typescript-estree" "4.11.0" + "@typescript-eslint/scope-manager" "4.13.0" + "@typescript-eslint/types" "4.13.0" + "@typescript-eslint/typescript-estree" "4.13.0" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.11.0.tgz#1dd3d7e42708c10ce9f3aa64c63c0ab99868b4e2" - integrity sha512-NBTtKCC7ZtuxEV5CrHUO4Pg2s784pvavc3cnz6V+oJvVbK4tH9135f/RBP6eUA2KHiFKAollSrgSctQGmHbqJQ== +"@typescript-eslint/parser@^4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.13.0.tgz#c413d640ea66120cfcc37f891e8cb3fd1c9d247d" + integrity sha512-KO0J5SRF08pMXzq9+abyHnaGQgUJZ3Z3ax+pmqz9vl81JxmTTOUfQmq7/4awVfq09b6C4owNlOgOwp61pYRBSg== dependencies: - "@typescript-eslint/scope-manager" "4.11.0" - "@typescript-eslint/types" "4.11.0" - "@typescript-eslint/typescript-estree" "4.11.0" + "@typescript-eslint/scope-manager" "4.13.0" + "@typescript-eslint/types" "4.13.0" + "@typescript-eslint/typescript-estree" "4.13.0" debug "^4.1.1" -"@typescript-eslint/scope-manager@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.11.0.tgz#2d906537db8a3a946721699e4fc0833810490254" - integrity sha512-6VSTm/4vC2dHM3ySDW9Kl48en+yLNfVV6LECU8jodBHQOhO8adAVizaZ1fV0QGZnLQjQ/y0aBj5/KXPp2hBTjA== +"@typescript-eslint/scope-manager@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.13.0.tgz#5b45912a9aa26b29603d8fa28f5e09088b947141" + integrity sha512-UpK7YLG2JlTp/9G4CHe7GxOwd93RBf3aHO5L+pfjIrhtBvZjHKbMhBXTIQNkbz7HZ9XOe++yKrXutYm5KmjWgQ== dependencies: - "@typescript-eslint/types" "4.11.0" - "@typescript-eslint/visitor-keys" "4.11.0" + "@typescript-eslint/types" "4.13.0" + "@typescript-eslint/visitor-keys" "4.13.0" -"@typescript-eslint/types@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.11.0.tgz#86cf95e7eac4ccfd183f9fcf1480cece7caf4ca4" - integrity sha512-XXOdt/NPX++txOQHM1kUMgJUS43KSlXGdR/aDyEwuAEETwuPt02Nc7v+s57PzuSqMbNLclblQdv3YcWOdXhQ7g== +"@typescript-eslint/types@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.13.0.tgz#6a7c6015a59a08fbd70daa8c83dfff86250502f8" + integrity sha512-/+aPaq163oX+ObOG00M0t9tKkOgdv9lq0IQv/y4SqGkAXmhFmCfgsELV7kOCTb2vVU5VOmVwXBXJTDr353C1rQ== -"@typescript-eslint/typescript-estree@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.11.0.tgz#1144d145841e5987d61c4c845442a24b24165a4b" - integrity sha512-eA6sT5dE5RHAFhtcC+b5WDlUIGwnO9b0yrfGa1mIOIAjqwSQCpXbLiFmKTdRbQN/xH2EZkGqqLDrKUuYOZ0+Hg== +"@typescript-eslint/typescript-estree@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.13.0.tgz#cf6e2207c7d760f5dfd8d18051428fadfc37b45e" + integrity sha512-9A0/DFZZLlGXn5XA349dWQFwPZxcyYyCFX5X88nWs2uachRDwGeyPz46oTsm9ZJE66EALvEns1lvBwa4d9QxMg== dependencies: - "@typescript-eslint/types" "4.11.0" - "@typescript-eslint/visitor-keys" "4.11.0" + "@typescript-eslint/types" "4.13.0" + "@typescript-eslint/visitor-keys" "4.13.0" debug "^4.1.1" globby "^11.0.1" is-glob "^4.0.1" @@ -1699,12 +1700,12 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.11.0.tgz#906669a50f06aa744378bb84c7d5c4fdbc5b7d51" - integrity sha512-tRYKyY0i7cMk6v4UIOCjl1LhuepC/pc6adQqJk4Is3YcC6k46HvsV9Wl7vQoLbm9qADgeujiT7KdLrylvFIQ+A== +"@typescript-eslint/visitor-keys@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.13.0.tgz#9acb1772d3b3183182b6540d3734143dce9476fe" + integrity sha512-6RoxWK05PAibukE7jElqAtNMq+RWZyqJ6Q/GdIxaiUj2Ept8jh8+FUVlbq9WxMYxkmEOPvCE5cRSyupMpwW31g== dependencies: - "@typescript-eslint/types" "4.11.0" + "@typescript-eslint/types" "4.13.0" eslint-visitor-keys "^2.0.0" JSONStream@^1.0.4, JSONStream@^1.3.4, JSONStream@^1.3.5: @@ -3346,10 +3347,10 @@ eslint-config-prettier@^7.1.0: resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-7.1.0.tgz#5402eb559aa94b894effd6bddfa0b1ca051c858f" integrity sha512-9sm5/PxaFG7qNJvJzTROMM1Bk1ozXVTKI0buKOyb0Bsr1hrwi0H/TzxF/COtf1uxikIK8SwhX7K6zg78jAzbeA== -eslint-plugin-prettier@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.0.tgz#61e295349a65688ffac0b7808ef0a8244bdd8d40" - integrity sha512-tMTwO8iUWlSRZIwS9k7/E4vrTsfvsrcM5p1eftyuqWH25nKsz/o6/54I7jwQ/3zobISyC7wMy9ZsFwgTxOcOpQ== +eslint-plugin-prettier@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz#7079cfa2497078905011e6f82e8dd8453d1371b7" + integrity sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ== dependencies: prettier-linter-helpers "^1.0.0" @@ -3378,10 +3379,10 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== -eslint@^7.16.0: - version "7.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.16.0.tgz#a761605bf9a7b32d24bb7cde59aeb0fd76f06092" - integrity sha512-iVWPS785RuDA4dWuhhgXTNrGxHHK3a8HLSMBgbbU59ruJDubUraXN8N5rn7kb8tG6sjg74eE0RA3YWT51eusEw== +eslint@^7.17.0: + version "7.17.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.17.0.tgz#4ccda5bf12572ad3bf760e6f195886f50569adb0" + integrity sha512-zJk08MiBgwuGoxes5sSQhOtibZ75pz0J35XTRlZOk9xMffhpA9BTbQZxoXZzOl5zMbleShbGwtw+1kGferfFwQ== dependencies: "@babel/code-frame" "^7.0.0" "@eslint/eslintrc" "^0.2.2" @@ -3779,12 +3780,12 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -find-versions@^3.0.0, find-versions@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.2.0.tgz#10297f98030a786829681690545ef659ed1d254e" - integrity sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww== +find-versions@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-4.0.0.tgz#3c57e573bf97769b8cb8df16934b627915da4965" + integrity sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ== dependencies: - semver-regex "^2.0.0" + semver-regex "^3.1.2" findup-sync@^3.0.0: version "3.0.0" @@ -4268,9 +4269,9 @@ has@^1.0.3: function-bind "^1.1.1" highlight.js@^10.2.0: - version "10.4.1" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.4.1.tgz#d48fbcf4a9971c4361b3f95f302747afe19dbad0" - integrity sha512-yR5lWvNz7c85OhVAEAeFhVCc/GV4C30Fjzc/rCP0aCWzc1UUOPUk55dK/qdwTZHBvMZo+eZ2jpk62ndX/xMFlg== + version "10.5.0" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.5.0.tgz#3f09fede6a865757378f2d9ebdcbc15ba268f98f" + integrity sha512-xTmvd9HiIHR6L53TMC7TKolEj65zG1XU+Onr8oi86mYa+nLcIbxTTWkpW7CsEwv/vK7u1zb8alZIMLDqqN6KTw== homedir-polyfill@^1.0.1: version "1.0.3" @@ -4372,18 +4373,18 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -husky@^4.3.6: - version "4.3.6" - resolved "https://registry.yarnpkg.com/husky/-/husky-4.3.6.tgz#ebd9dd8b9324aa851f1587318db4cccb7665a13c" - integrity sha512-o6UjVI8xtlWRL5395iWq9LKDyp/9TE7XMOTvIpEVzW638UcGxTmV5cfel6fsk/jbZSTlvfGVJf2svFtybcIZag== +husky@^4.3.7: + version "4.3.7" + resolved "https://registry.yarnpkg.com/husky/-/husky-4.3.7.tgz#ca47bbe6213c1aa8b16bbd504530d9600de91e88" + integrity sha512-0fQlcCDq/xypoyYSJvEuzbDPHFf8ZF9IXKJxlrnvxABTSzK1VPT2RKYQKrcgJ+YD39swgoB6sbzywUqFxUiqjw== dependencies: chalk "^4.0.0" ci-info "^2.0.0" compare-versions "^3.6.0" cosmiconfig "^7.0.0" - find-versions "^3.2.0" + find-versions "^4.0.0" opencollective-postinstall "^2.0.2" - pkg-dir "^4.2.0" + pkg-dir "^5.0.0" please-upgrade-node "^3.2.0" slash "^3.0.0" which-pm-runs "^1.0.0" @@ -6051,11 +6052,16 @@ marked-terminal@^4.0.0: node-emoji "^1.10.0" supports-hyperlinks "^2.1.0" -marked@^1.0.0, marked@^1.1.1: +marked@^1.0.0: version "1.2.2" resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.2.tgz#5d77ffb789c4cb0ae828bfe76250f7140b123f70" integrity sha512-5jjKHVl/FPo0Z6ocP3zYhKiJLzkwJAw4CZoLjv57FkvbUuwOX4LIBBGGcXjAY6ATcd1q9B8UTj5T9Umauj0QYQ== +marked@^1.1.1: + version "1.2.7" + resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.7.tgz#6e14b595581d2319cdcf033a24caaf41455a01fb" + integrity sha512-No11hFYcXr/zkBvL6qFmAp1z6BKY3zqLMHny/JN/ey+al7qwCM2+CMBL9BOgqMxZU36fz4cCWfn2poWIf7QRXA== + meant@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/meant/-/meant-1.0.2.tgz#5d0c78310a3d8ae1408a16be0fe0bd42a969f560" @@ -7181,6 +7187,13 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +pkg-dir@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760" + integrity sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA== + dependencies: + find-up "^5.0.0" + please-upgrade-node@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" @@ -7825,10 +7838,10 @@ rollup-plugin-typescript2@^0.29.0: resolve "1.17.0" tslib "2.0.1" -rollup@^2.35.1: - version "2.35.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.35.1.tgz#e6bc8d10893556a638066f89e8c97f422d03968c" - integrity sha512-q5KxEyWpprAIcainhVy6HfRttD9kutQpHbeqDTWnqAFNJotiojetK6uqmcydNMymBEtC4I8bCYR+J3mTMqeaUA== +rollup@^2.36.1: + version "2.36.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.36.1.tgz#2174f0c25c7b400d57b05628d0e732c7ae8d2178" + integrity sha512-eAfqho8dyzuVvrGqpR0ITgEdq0zG2QJeWYh+HeuTbpcaXk8vNFc48B7bJa1xYosTCKx0CuW+447oQOW8HgBIZQ== optionalDependencies: fsevents "~2.1.2" @@ -7905,10 +7918,10 @@ saxes@^5.0.0: dependencies: xmlchars "^2.2.0" -semantic-release@^17.3.0: - version "17.3.0" - resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-17.3.0.tgz#121252b5bb6acc1048d7657111173b03d47502c5" - integrity sha512-enhDayMZRP4nWcWAMBFHHB7THRaIcRdUAZv3lxd65pXs2ttzay7IeCvRRrGayRWExtnY0ulwRz5Ycp88Dv/UeQ== +semantic-release@^17.3.1: + version "17.3.1" + resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-17.3.1.tgz#8904ef1ca8e704394de0e204b284f6c252284da4" + integrity sha512-NSdxvnBTklrRBYRexVUx44Hri9sTu9b8x+1HfWDGIWemDTFQfWOTbT1N3oy5l8WcZHodhRvtyI7gm50SfAa3Fg== dependencies: "@semantic-release/commit-analyzer" "^8.0.0" "@semantic-release/error" "^2.2.0" @@ -7921,7 +7934,7 @@ semantic-release@^17.3.0: env-ci "^5.0.0" execa "^4.0.0" figures "^3.0.0" - find-versions "^3.0.0" + find-versions "^4.0.0" get-stream "^5.0.0" git-log-parser "^1.2.0" hook-std "^2.0.0" @@ -7958,10 +7971,10 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -semver-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" - integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== +semver-regex@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-3.1.2.tgz#34b4c0d361eef262e07199dbef316d0f2ab11807" + integrity sha512-bXWyL6EAKOJa81XG1OZ/Yyuq+oT0b2YLlxx7c+mrdYPaPbnj6WgVULXhinMIeZGufuUBu/eVRqXEhiv4imfwxA== "semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", "semver@^2.3.0 || 3.x || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.1: version "5.7.1" From c1cafcfc074c020396e05d58c3f4122db53d76b8 Mon Sep 17 00:00:00 2001 From: lzear Date: Wed, 13 Jan 2021 18:11:01 +0100 Subject: [PATCH 3/6] fix: fix Nanson enum, attempt to fix treeshaking --- src/methods/approbation/index.ts | 2 +- src/methods/baldwin/index.ts | 2 +- src/methods/borda/index.ts | 2 +- src/methods/coombs/index.ts | 2 +- src/methods/first-past-the-post/index.ts | 21 +----- .../iterateFirstChoices.ts | 21 ++++++ src/methods/index.ts | 20 +----- src/methods/instant-runoff/index.ts | 2 +- src/methods/maximal-lotteries/index.ts | 2 +- .../maximal-lotteries.test.ts | 2 +- src/methods/nanson/index.ts | 2 +- src/methods/randomized-condorcet/index.ts | 2 +- .../randomized-condorcet.test.ts | 4 +- src/methods/two-round-runoff/index.ts | 2 +- .../utils.ts => test/matrixString.ts} | 0 src/types.ts | 2 +- src/utils/index.ts | 19 ++--- src/utils/normalize.test.ts | 6 +- src/utils/normalize.ts | 2 +- src/utils/scores.ts | 14 ---- src/utils/scoresFromBallots.ts | 14 ++++ src/votes.test.ts | 10 +-- src/votes.ts | 69 +++++-------------- 23 files changed, 88 insertions(+), 134 deletions(-) create mode 100644 src/methods/first-past-the-post/iterateFirstChoices.ts rename src/{simplex/utils.ts => test/matrixString.ts} (100%) create mode 100644 src/utils/scoresFromBallots.ts diff --git a/src/methods/approbation/index.ts b/src/methods/approbation/index.ts index 8ba8b71..4baf538 100644 --- a/src/methods/approbation/index.ts +++ b/src/methods/approbation/index.ts @@ -4,7 +4,7 @@ import { VotingSystem, Ballot, } from '../../types' -import { iterateFirstChoices } from '../first-past-the-post' +import { iterateFirstChoices } from '../first-past-the-post/iterateFirstChoices' export const approbation: SystemUsingRankings = { type: VotingSystem.Approbation, diff --git a/src/methods/baldwin/index.ts b/src/methods/baldwin/index.ts index 3f89ebf..388e308 100644 --- a/src/methods/baldwin/index.ts +++ b/src/methods/baldwin/index.ts @@ -6,7 +6,7 @@ import { Ballot, } from '../../types' import { borda } from '../borda' -import { scoresToRanking } from '../../utils' +import { scoresToRanking } from '../../utils/scores' export const baldwin: SystemUsingRankings = { type: VotingSystem.Baldwin, diff --git a/src/methods/borda/index.ts b/src/methods/borda/index.ts index e01677c..a18d42f 100644 --- a/src/methods/borda/index.ts +++ b/src/methods/borda/index.ts @@ -5,7 +5,7 @@ import { Ballot, } from '../../types' import { scoresZero } from '../../utils/scoresZero' -import { normalizeBallots } from '../../utils' +import { normalizeBallots } from '../../utils/normalize' export const borda: SystemUsingRankings = { type: VotingSystem.Borda, diff --git a/src/methods/coombs/index.ts b/src/methods/coombs/index.ts index 7218de8..09e629d 100644 --- a/src/methods/coombs/index.ts +++ b/src/methods/coombs/index.ts @@ -6,7 +6,7 @@ import { Ballot, } from '../../types' import { firstPastThePost } from '../first-past-the-post' -import { scoresToRanking } from '../../utils' +import { scoresToRanking } from '../../utils/scores' export const coombs: SystemUsingRankings = { type: VotingSystem.Coombs, diff --git a/src/methods/first-past-the-post/index.ts b/src/methods/first-past-the-post/index.ts index 401432e..ca2f437 100644 --- a/src/methods/first-past-the-post/index.ts +++ b/src/methods/first-past-the-post/index.ts @@ -4,26 +4,7 @@ import { VotingSystem, Ballot, } from '../../types' -import { scoresZero } from '../../utils/scoresZero' -import { normalizeBallots } from '../../utils' - -export const iterateFirstChoices = ( - ballots: Ballot[], - candidates: string[], - compute: (rank: string[]) => number, -): ScoreObject => { - const result: ScoreObject = scoresZero(candidates) - normalizeBallots(ballots, candidates).forEach((ballot) => { - if (ballot.ranking.length) { - const votes = ballot.ranking[0].filter((c) => candidates.includes(c)) - votes.forEach( - (candidate, idx, rank) => - (result[candidate] += compute(rank) * ballot.weight), - ) - } - }) - return result -} +import { iterateFirstChoices } from './iterateFirstChoices' export const firstPastThePost: SystemUsingRankings = { type: VotingSystem.FirstPastThePost, diff --git a/src/methods/first-past-the-post/iterateFirstChoices.ts b/src/methods/first-past-the-post/iterateFirstChoices.ts new file mode 100644 index 0000000..6a31b15 --- /dev/null +++ b/src/methods/first-past-the-post/iterateFirstChoices.ts @@ -0,0 +1,21 @@ +import { Ballot, ScoreObject } from '../../types' +import { normalizeBallots } from '../../utils/normalize' +import { scoresZero } from '../../utils/scoresZero' + +export const iterateFirstChoices = ( + ballots: Ballot[], + candidates: string[], + compute: (rank: string[]) => number, +): ScoreObject => { + const result: ScoreObject = scoresZero(candidates) + normalizeBallots(ballots, candidates).forEach((ballot) => { + if (ballot.ranking.length) { + const votes = ballot.ranking[0].filter((c) => candidates.includes(c)) + votes.forEach( + (candidate, idx, rank) => + (result[candidate] += compute(rank) * ballot.weight), + ) + } + }) + return result +} diff --git a/src/methods/index.ts b/src/methods/index.ts index 0b31afb..395fcc6 100644 --- a/src/methods/index.ts +++ b/src/methods/index.ts @@ -26,27 +26,9 @@ export const methods = { [VotingSystem.Kemeny]: kemeny, [VotingSystem.MaximalLotteries]: maximalLotteries, [VotingSystem.Minimax]: minimax, - [VotingSystem.NANSON]: nanson, + [VotingSystem.Nanson]: nanson, [VotingSystem.RankedPairs]: rankedPairs, [VotingSystem.RandomizedCondorcet]: randomizedCondorcet, [VotingSystem.Schulze]: schulze, [VotingSystem.TwoRoundRunoff]: twoRoundRunoff, } - -export { - approbation, - baldwin, - borda, - coombs, - copeland, - firstPastThePost, - instantRunoff, - kemeny, - maximalLotteries, - minimax, - nanson, - rankedPairs, - randomizedCondorcet, - schulze, - twoRoundRunoff, -} diff --git a/src/methods/instant-runoff/index.ts b/src/methods/instant-runoff/index.ts index ab76c00..7073bcf 100644 --- a/src/methods/instant-runoff/index.ts +++ b/src/methods/instant-runoff/index.ts @@ -5,7 +5,7 @@ import { Ballot, } from '../../types' import { firstPastThePost } from '../first-past-the-post' -import { normalizeBallots } from '../../utils' +import { normalizeBallots } from '../../utils/normalize' export const instantRunoff: SystemUsingRankings = { type: VotingSystem.InstantRunoff, diff --git a/src/methods/maximal-lotteries/index.ts b/src/methods/maximal-lotteries/index.ts index 41aa3ab..97b67d8 100644 --- a/src/methods/maximal-lotteries/index.ts +++ b/src/methods/maximal-lotteries/index.ts @@ -6,7 +6,7 @@ import { Matrix, ScoreObject, } from '../../types' -import { makeAntisymetric } from '../../utils' +import { makeAntisymetric } from '../../utils/makeMatrix' import { findCondorcet } from '../../utils/condorcet' export const computeLottery = ( diff --git a/src/methods/maximal-lotteries/maximal-lotteries.test.ts b/src/methods/maximal-lotteries/maximal-lotteries.test.ts index d44ce53..141ddba 100644 --- a/src/methods/maximal-lotteries/maximal-lotteries.test.ts +++ b/src/methods/maximal-lotteries/maximal-lotteries.test.ts @@ -1,5 +1,5 @@ import { performPivots, simplexTableau } from '../../simplex' -import { matrixString } from '../../simplex/utils' +import { matrixString } from '../../test/matrixString' import { maximalLotteries } from './index' const example1 = [ diff --git a/src/methods/nanson/index.ts b/src/methods/nanson/index.ts index 30d8ee5..3e01811 100644 --- a/src/methods/nanson/index.ts +++ b/src/methods/nanson/index.ts @@ -9,7 +9,7 @@ import { import { borda } from '../borda' export const nanson: SystemUsingRankings = { - type: VotingSystem.NANSON, + type: VotingSystem.Nanson, computeFromBallots(ballots: Ballot[], candidates: string[]): ScoreObject { const score: ScoreObject = {} let remainingCandidates = candidates diff --git a/src/methods/randomized-condorcet/index.ts b/src/methods/randomized-condorcet/index.ts index 11e375e..605502b 100644 --- a/src/methods/randomized-condorcet/index.ts +++ b/src/methods/randomized-condorcet/index.ts @@ -4,7 +4,7 @@ import { Matrix, ScoreObject, } from '../../types' -import { makeAntisymetric } from '../../utils' +import { makeAntisymetric } from '../../utils/makeMatrix' import { computeLottery } from '../maximal-lotteries' export const randomizedCondorcet: SystemUsingMatrix = { diff --git a/src/methods/randomized-condorcet/randomized-condorcet.test.ts b/src/methods/randomized-condorcet/randomized-condorcet.test.ts index 4a7feea..2e8ac34 100644 --- a/src/methods/randomized-condorcet/randomized-condorcet.test.ts +++ b/src/methods/randomized-condorcet/randomized-condorcet.test.ts @@ -1,6 +1,6 @@ import { performPivots, simplexTableau } from '../../simplex' -import { matrixString } from '../../simplex/utils' -import { randomizedCondorcet } from './index' +import { matrixString } from '../../test/matrixString' +import { randomizedCondorcet } from '.' const example1 = [ [0, -2, 8], diff --git a/src/methods/two-round-runoff/index.ts b/src/methods/two-round-runoff/index.ts index 819bc39..e28f709 100644 --- a/src/methods/two-round-runoff/index.ts +++ b/src/methods/two-round-runoff/index.ts @@ -4,7 +4,7 @@ import { VotingSystem, Ballot, } from '../../types' -import { normalizeBallots } from '../../utils' +import { normalizeBallots } from '../../utils/normalize' import { firstPastThePost } from '../first-past-the-post' export const twoRoundRunoff: SystemUsingRankings = { diff --git a/src/simplex/utils.ts b/src/test/matrixString.ts similarity index 100% rename from src/simplex/utils.ts rename to src/test/matrixString.ts diff --git a/src/types.ts b/src/types.ts index 5361cfb..b3e3d69 100644 --- a/src/types.ts +++ b/src/types.ts @@ -17,7 +17,7 @@ export enum VotingSystem { InstantRunoff = 'INSTANT_RUNOFF', MaximalLotteries = 'MAXIMAL_LOTTERIES', Minimax = 'MINIMAX', - NANSON = 'NANSON', + Nanson = 'NANSON', RandomizedCondorcet = 'RANDOMIZED_CONDORCET', RankedPairs = 'RANKED_PAIRS', Schulze = 'SCHULZE', diff --git a/src/utils/index.ts b/src/utils/index.ts index e5a9fa1..c4cbfb1 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,17 +1,18 @@ import { - normalizeRanking, + candidatesFromBallots, + checkDuplicatedCandidate, + groupBallots, normalizeBallot, normalizeBallots, - groupBallots, - candidatesFromBallots, - normalizeRankinput, - toWeightedBallots, - removeInvalidCandidates, + normalizeRankInput, + normalizeRanking, removeDuplicatedCandidates, - checkDuplicatedCandidate, + removeInvalidCandidates, + toWeightedBallots, } from './normalize' import { makeAntisymetric, matrixFromBallots } from './makeMatrix' -import { scoresFromBallots, scoresToRanking } from './scores' +import { scoresToRanking } from './scores' +import { scoresFromBallots } from './scoresFromBallots' export { normalizeRanking, @@ -19,7 +20,7 @@ export { normalizeBallots, groupBallots, candidatesFromBallots, - normalizeRankinput, + normalizeRankInput, toWeightedBallots, removeInvalidCandidates, removeDuplicatedCandidates, diff --git a/src/utils/normalize.test.ts b/src/utils/normalize.test.ts index 102e20a..2e354bf 100644 --- a/src/utils/normalize.test.ts +++ b/src/utils/normalize.test.ts @@ -5,11 +5,11 @@ import { normalizeBallot, normalizeBallots, normalizeRanking, - normalizeRankinput, + normalizeRankInput, removeDuplicatedCandidates, removeInvalidCandidates, scoresToRanking, -} from '.' +} from '../utils' it('groups ballots', () => { expect( @@ -37,7 +37,7 @@ it('removes duplicated candidates', () => { }) it('normalizes rankinput', () => { - expect(normalizeRankinput([['a', 'b'], 'c', 'd', ['e']])).toStrictEqual([ + expect(normalizeRankInput([['a', 'b'], 'c', 'd', ['e']])).toStrictEqual([ ['a', 'b'], ['c'], ['d'], diff --git a/src/utils/normalize.ts b/src/utils/normalize.ts index 31da770..8767463 100644 --- a/src/utils/normalize.ts +++ b/src/utils/normalize.ts @@ -10,7 +10,7 @@ import { Ballot } from '../types' export const isBallotEqual = (a: string[][], b: string[][]): boolean => every(a, (rank, k) => isEqual([...rank].sort(), [...b[k]].sort())) -export const normalizeRankinput = ( +export const normalizeRankInput = ( rankinput: (string | string[])[], ): string[][] => rankinput.map((rank) => (typeof rank === 'string' ? [rank] : rank)) diff --git a/src/utils/scores.ts b/src/utils/scores.ts index 2ae8804..5298d61 100644 --- a/src/utils/scores.ts +++ b/src/utils/scores.ts @@ -1,9 +1,6 @@ import groupBy from 'lodash/groupBy' import sortBy from 'lodash/sortBy' import toPairs from 'lodash/toPairs' -import { Ballot, ScoreObject, VotingSystem } from '../types' -import { methods } from '../methods' -import { matrixFromBallots } from './makeMatrix' export const scoresToRanking = (scores: { [candidate: string]: number @@ -12,14 +9,3 @@ export const scoresToRanking = (scores: { groupBy(toPairs(scores), (e) => e[1]), (e) => -e[0][1], ).map((e) => e.map((f) => f[0])) - -export const scoresFromBallots = ( - ballots: Ballot[], - candidates: string[], - system: VotingSystem, -): ScoreObject => { - const method = methods[system] - if ('computeFromBallots' in method) - return method.computeFromBallots(ballots, candidates) - return method.computeFromMatrix(matrixFromBallots(ballots, candidates)) -} diff --git a/src/utils/scoresFromBallots.ts b/src/utils/scoresFromBallots.ts new file mode 100644 index 0000000..34ad34e --- /dev/null +++ b/src/utils/scoresFromBallots.ts @@ -0,0 +1,14 @@ +import { Ballot, ScoreObject, VotingSystem } from '../types' +import { methods } from '../methods' +import { matrixFromBallots } from './makeMatrix' + +export const scoresFromBallots = ( + ballots: Ballot[], + candidates: string[], + system: VotingSystem, +): ScoreObject => { + const method = methods[system] + if ('computeFromBallots' in method) + return method.computeFromBallots(ballots, candidates) + return method.computeFromMatrix(matrixFromBallots(ballots, candidates)) +} diff --git a/src/votes.test.ts b/src/votes.test.ts index 56c15a6..b1ac207 100644 --- a/src/votes.test.ts +++ b/src/votes.test.ts @@ -1,7 +1,5 @@ -import { methods, SystemUsingMatrix, SystemUsingRankings, utils } from './votes' -import { VotingSystem } from './types' -import { matrixFromBallots } from './utils' import { + methods, approbation, baldwin, borda, @@ -17,8 +15,12 @@ import { rankedPairs, schulze, twoRoundRunoff, + VotingSystem, + SystemUsingMatrix, + SystemUsingRankings, } from './votes' import { abcde, balinski, dummyProfile, sW } from './test/testUtils' +import { matrixFromBallots } from './utils' describe('Test all methods', () => { it('works if true is truthy', () => { @@ -62,7 +64,7 @@ describe('Test all methods', () => { const allResults = m.reduce((acc, methodKey) => { const method = methods[methodKey] as SystemUsingMatrix const score = method.computeFromMatrix( - utils.matrixFromBallots(dummyProfile, abcde), + matrixFromBallots(dummyProfile, abcde), ) const maxScore = Math.max(...Object.values(score)) return { diff --git a/src/votes.ts b/src/votes.ts index 5ee3792..3a36b75 100644 --- a/src/votes.ts +++ b/src/votes.ts @@ -1,22 +1,4 @@ -import { - approbation, - baldwin, - borda, - coombs, - copeland, - firstPastThePost, - instantRunoff, - kemeny, - maximalLotteries, - minimax, - nanson, - rankedPairs, - randomizedCondorcet, - schulze, - twoRoundRunoff, - methods, -} from './methods' -import { +export { System, VotingSystem, SystemUsingRankings, @@ -25,35 +7,20 @@ import { ScoreObject, Ballot, } from './types' -import * as utils from './utils' - -export { - // enum - VotingSystem, - // All methods: - methods, - approbation, - baldwin, - borda, - coombs, - copeland, - firstPastThePost, - instantRunoff, - kemeny, - maximalLotteries, - minimax, - nanson, - rankedPairs, - randomizedCondorcet, - schulze, - twoRoundRunoff, - // utils - utils, - // types - System, - SystemUsingRankings, - SystemUsingMatrix, - Matrix, - ScoreObject, - Ballot, -} +export { approbation } from './methods/approbation' +export { baldwin } from './methods/baldwin' +export { borda } from './methods/borda' +export { coombs } from './methods/coombs' +export { copeland } from './methods/copeland' +export { firstPastThePost } from './methods/first-past-the-post' +export { instantRunoff } from './methods/instant-runoff' +export { kemeny } from './methods/kemeny' +export { maximalLotteries } from './methods/maximal-lotteries' +export { minimax } from './methods/minimax' +export { nanson } from './methods/nanson' +export { rankedPairs } from './methods/ranked-pairs' +export { randomizedCondorcet } from './methods/randomized-condorcet' +export { schulze } from './methods/schulze' +export { twoRoundRunoff } from './methods/two-round-runoff' +export { methods } from './methods' +export * as utils from './utils' From f4e03f8eb87d9fae62bfb92f31775899271cd1d8 Mon Sep 17 00:00:00 2001 From: lzear Date: Wed, 13 Jan 2021 23:41:57 +0100 Subject: [PATCH 4/6] fix: use lodash-es --- package.json | 8 +-- src/methods/baldwin/index.ts | 2 +- src/methods/coombs/index.ts | 2 +- src/methods/copeland/index.ts | 4 +- src/methods/kemeny/index.ts | 4 +- src/methods/maximal-lotteries/index.ts | 2 +- src/methods/nanson/index.ts | 4 +- src/methods/ranked-pairs/index.ts | 8 +-- src/methods/schulze/index.ts | 2 +- src/test/matrix.ts | 2 +- src/test/testUtils.ts | 8 +-- src/utils/condorcet.ts | 2 +- src/utils/makeMatrix.ts | 6 +- src/utils/normalize.ts | 12 ++-- src/utils/scores.ts | 6 +- src/utils/scoresZero.ts | 2 +- tsconfig.json | 2 +- yarn.lock | 94 +++++++++++++++++++------- 18 files changed, 107 insertions(+), 63 deletions(-) diff --git a/package.json b/package.json index 118aeaf..64f745e 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^11.0.1", "@types/jest": "^26.0.20", - "@types/lodash": "^4.14.167", + "@types/lodash-es": "^4.17.4", "@types/node": "^14.14.20", "@typescript-eslint/eslint-plugin": "^4.13.0", "@typescript-eslint/parser": "^4.13.0", @@ -73,16 +73,16 @@ "rollup-plugin-sizes": "^1.0.3", "rollup-plugin-sourcemaps": "^0.6.3", "rollup-plugin-typescript2": "^0.29.0", - "semantic-release": "^17.3.1", + "semantic-release": "^17.3.2", "shelljs": "^0.8.4", "travis-deploy-once": "^5.0.11", "ts-jest": "^26.4.4", "ts-node": "^9.1.1", - "typedoc": "^0.19.2", + "typedoc": "^0.20.14", "typescript": "^4.1.3" }, "dependencies": { - "lodash": "^4.17.20" + "lodash-es": "^4.17.20" }, "bugs": { "url": "https://github.com/lzear/votes/issues" diff --git a/src/methods/baldwin/index.ts b/src/methods/baldwin/index.ts index 388e308..504399d 100644 --- a/src/methods/baldwin/index.ts +++ b/src/methods/baldwin/index.ts @@ -1,4 +1,4 @@ -import difference from 'lodash/difference' +import difference from 'lodash-es/difference' import { SystemUsingRankings, ScoreObject, diff --git a/src/methods/coombs/index.ts b/src/methods/coombs/index.ts index 09e629d..4c49c5d 100644 --- a/src/methods/coombs/index.ts +++ b/src/methods/coombs/index.ts @@ -1,4 +1,4 @@ -import difference from 'lodash/difference' +import difference from 'lodash-es/difference' import { SystemUsingRankings, ScoreObject, diff --git a/src/methods/copeland/index.ts b/src/methods/copeland/index.ts index 7100ec9..366fda7 100644 --- a/src/methods/copeland/index.ts +++ b/src/methods/copeland/index.ts @@ -1,6 +1,6 @@ /* eslint-disable no-plusplus */ -import range from 'lodash/range' -import zipObject from 'lodash/zipObject' +import range from 'lodash-es/range' +import zipObject from 'lodash-es/zipObject' import { SystemUsingMatrix, VotingSystem, diff --git a/src/methods/kemeny/index.ts b/src/methods/kemeny/index.ts index bd6de2c..166741c 100644 --- a/src/methods/kemeny/index.ts +++ b/src/methods/kemeny/index.ts @@ -1,5 +1,5 @@ -import zipObject from 'lodash/zipObject' -import range from 'lodash/range' +import zipObject from 'lodash-es/zipObject' +import range from 'lodash-es/range' import { SystemUsingMatrix, VotingSystem, diff --git a/src/methods/maximal-lotteries/index.ts b/src/methods/maximal-lotteries/index.ts index 97b67d8..836203c 100644 --- a/src/methods/maximal-lotteries/index.ts +++ b/src/methods/maximal-lotteries/index.ts @@ -1,4 +1,4 @@ -import zipObject from 'lodash/zipObject' +import zipObject from 'lodash-es/zipObject' import { solve } from '../../simplex' import { SystemUsingMatrix, diff --git a/src/methods/nanson/index.ts b/src/methods/nanson/index.ts index 3e01811..cf33dad 100644 --- a/src/methods/nanson/index.ts +++ b/src/methods/nanson/index.ts @@ -1,5 +1,5 @@ -import sum from 'lodash/sum' -import difference from 'lodash/difference' +import sum from 'lodash-es/sum' +import difference from 'lodash-es/difference' import { SystemUsingRankings, ScoreObject, diff --git a/src/methods/ranked-pairs/index.ts b/src/methods/ranked-pairs/index.ts index e99ec1e..3146d07 100644 --- a/src/methods/ranked-pairs/index.ts +++ b/src/methods/ranked-pairs/index.ts @@ -1,7 +1,7 @@ -import groupBy from 'lodash/groupBy' -import range from 'lodash/range' -import uniq from 'lodash/uniq' -import zipObject from 'lodash/zipObject' +import groupBy from 'lodash-es/groupBy' +import range from 'lodash-es/range' +import uniq from 'lodash-es/uniq' +import zipObject from 'lodash-es/zipObject' import { Matrix, ScoreObject, diff --git a/src/methods/schulze/index.ts b/src/methods/schulze/index.ts index 90e79e9..06c7b5e 100644 --- a/src/methods/schulze/index.ts +++ b/src/methods/schulze/index.ts @@ -1,5 +1,5 @@ /* eslint-disable no-plusplus */ -import range from 'lodash/range' +import range from 'lodash-es/range' import { SystemUsingMatrix, VotingSystem, diff --git a/src/test/matrix.ts b/src/test/matrix.ts index 45baadc..0c1e6a7 100644 --- a/src/test/matrix.ts +++ b/src/test/matrix.ts @@ -1,4 +1,4 @@ -import range from 'lodash/range' +import range from 'lodash-es/range' export const product = (a: number[][], b: number[][]): number[][] => { const dimA = [a.length, a[0].length] diff --git a/src/test/testUtils.ts b/src/test/testUtils.ts index 755e2ab..2a73311 100644 --- a/src/test/testUtils.ts +++ b/src/test/testUtils.ts @@ -1,7 +1,7 @@ -import fill from 'lodash/fill' -import random from 'lodash/random' -import range from 'lodash/range' -import shuffle from 'lodash/shuffle' +import fill from 'lodash-es/fill' +import random from 'lodash-es/random' +import range from 'lodash-es/range' +import shuffle from 'lodash-es/shuffle' import { Ballot } from '../types' import { toWeightedBallots } from '../utils' diff --git a/src/utils/condorcet.ts b/src/utils/condorcet.ts index 0bcdbea..601b6dd 100644 --- a/src/utils/condorcet.ts +++ b/src/utils/condorcet.ts @@ -1,4 +1,4 @@ -import difference from 'lodash/difference' +import difference from 'lodash-es/difference' import { Matrix } from '../types' export const findCondorcet = ({ candidates, array }: Matrix): Matrix => { diff --git a/src/utils/makeMatrix.ts b/src/utils/makeMatrix.ts index 9da0547..ad34597 100644 --- a/src/utils/makeMatrix.ts +++ b/src/utils/makeMatrix.ts @@ -1,6 +1,6 @@ -import difference from 'lodash/difference' -import range from 'lodash/range' -import times from 'lodash/times' +import difference from 'lodash-es/difference' +import range from 'lodash-es/range' +import times from 'lodash-es/times' import { Matrix, Ballot } from '../types' export const matrixFromBallots = ( diff --git a/src/utils/normalize.ts b/src/utils/normalize.ts index 8767463..4d19840 100644 --- a/src/utils/normalize.ts +++ b/src/utils/normalize.ts @@ -1,9 +1,9 @@ -import difference from 'lodash/difference' -import every from 'lodash/every' -import flatten from 'lodash/flatten' -import intersection from 'lodash/intersection' -import isEqual from 'lodash/isEqual' -import uniq from 'lodash/uniq' +import difference from 'lodash-es/difference' +import every from 'lodash-es/every' +import flatten from 'lodash-es/flatten' +import intersection from 'lodash-es/intersection' +import isEqual from 'lodash-es/isEqual' +import uniq from 'lodash-es/uniq' import { Ballot } from '../types' diff --git a/src/utils/scores.ts b/src/utils/scores.ts index 5298d61..5d9b2f7 100644 --- a/src/utils/scores.ts +++ b/src/utils/scores.ts @@ -1,6 +1,6 @@ -import groupBy from 'lodash/groupBy' -import sortBy from 'lodash/sortBy' -import toPairs from 'lodash/toPairs' +import groupBy from 'lodash-es/groupBy' +import sortBy from 'lodash-es/sortBy' +import toPairs from 'lodash-es/toPairs' export const scoresToRanking = (scores: { [candidate: string]: number diff --git a/src/utils/scoresZero.ts b/src/utils/scoresZero.ts index dfe2cfe..2f1cb49 100644 --- a/src/utils/scoresZero.ts +++ b/src/utils/scoresZero.ts @@ -1,4 +1,4 @@ -import zipObject from 'lodash/zipObject' +import zipObject from 'lodash-es/zipObject' import { ScoreObject } from '../types' export const scoresZero = (candidates: string[]): ScoreObject => diff --git a/tsconfig.json b/tsconfig.json index 587d9d7..94b09ba 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "moduleResolution": "node", - "target": "es5", + "target": "esnext", "module": "es2015", "lib": ["es7", "es2015", "es2016", "es2017", "es2019", "esnext", "dom"], "strict": true, diff --git a/yarn.lock b/yarn.lock index d8beb08..685a473 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1573,7 +1573,14 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== -"@types/lodash@^4.14.167": +"@types/lodash-es@^4.17.4": + version "4.17.4" + resolved "https://registry.yarnpkg.com/@types/lodash-es/-/lodash-es-4.17.4.tgz#b2e440d2bf8a93584a9fd798452ec497986c9b97" + integrity sha512-BBz79DCJbD2CVYZH67MBeHZRX++HF+5p8Mo5MzjZi64Wac39S3diedJYHZtScbRVf4DjZyN6LzA0SB0zy+HSSQ== + dependencies: + "@types/lodash" "*" + +"@types/lodash@*": version "4.14.167" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.167.tgz#ce7d78553e3c886d4ea643c37ec7edc20f16765e" integrity sha512-w7tQPjARrvdeBkX/Rwg95S592JwxqOjmms3zWQ0XZgSyxSLdzWaYH3vErBhdVS/lRBX7F8aBYcYJYTr5TMGOzw== @@ -2584,7 +2591,7 @@ colors@1.0.3: resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= -colors@^1.1.2: +colors@^1.1.2, colors@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== @@ -4268,11 +4275,6 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -highlight.js@^10.2.0: - version "10.5.0" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.5.0.tgz#3f09fede6a865757378f2d9ebdcbc15ba268f98f" - integrity sha512-xTmvd9HiIHR6L53TMC7TKolEj65zG1XU+Onr8oi86mYa+nLcIbxTTWkpW7CsEwv/vK7u1zb8alZIMLDqqN6KTw== - homedir-polyfill@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" @@ -5415,7 +5417,7 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json5@2.x, json5@^2.1.2: +json5@2.x, json5@^2.1.0, json5@^2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== @@ -5776,6 +5778,11 @@ lockfile@^1.0.4: dependencies: signal-exit "^3.0.2" +lodash-es@^4.17.20: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.20.tgz#29f6332eefc60e849f869c264bc71126ad61e8f7" + integrity sha512-JD1COMZsq8maT6mnuz1UMV0jvYD0E0aUsSOdrr1/nAG3dhqQXwRRgeW0cSqH1U43INKcqxaiVIQNOUDld7gRDA== + lodash._baseuniq@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" @@ -6057,7 +6064,7 @@ marked@^1.0.0: resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.2.tgz#5d77ffb789c4cb0ae828bfe76250f7140b123f70" integrity sha512-5jjKHVl/FPo0Z6ocP3zYhKiJLzkwJAw4CZoLjv57FkvbUuwOX4LIBBGGcXjAY6ATcd1q9B8UTj5T9Umauj0QYQ== -marked@^1.1.1: +marked@^1.2.5: version "1.2.7" resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.7.tgz#6e14b595581d2319cdcf033a24caaf41455a01fb" integrity sha512-No11hFYcXr/zkBvL6qFmAp1z6BKY3zqLMHny/JN/ey+al7qwCM2+CMBL9BOgqMxZU36fz4cCWfn2poWIf7QRXA== @@ -6778,6 +6785,13 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" +onigasm@^2.2.5: + version "2.2.5" + resolved "https://registry.yarnpkg.com/onigasm/-/onigasm-2.2.5.tgz#cc4d2a79a0fa0b64caec1f4c7ea367585a676892" + integrity sha512-F+th54mPc0l1lp1ZcFMyL/jTs2Tlq4SqIHKIXGZOR/VkHkF9A7Fr5rRr5+ZG/lWeRsyrClLYRq7s/yFQ/XhWCA== + dependencies: + lru-cache "^5.1.1" + opencollective-postinstall@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" @@ -7918,10 +7932,10 @@ saxes@^5.0.0: dependencies: xmlchars "^2.2.0" -semantic-release@^17.3.1: - version "17.3.1" - resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-17.3.1.tgz#8904ef1ca8e704394de0e204b284f6c252284da4" - integrity sha512-NSdxvnBTklrRBYRexVUx44Hri9sTu9b8x+1HfWDGIWemDTFQfWOTbT1N3oy5l8WcZHodhRvtyI7gm50SfAa3Fg== +semantic-release@^17.3.2: + version "17.3.2" + resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-17.3.2.tgz#89c793ed64fe00b7bfe1c36bc389fb04855a4df9" + integrity sha512-S8ppLzFFeznDXvRGEvltuwpRT7Tb7o3gBIqaVnahi0sAzrxD/WdWZQoHOpwypzTBD7i9gCxZ+RqVpaHa9WFD3w== dependencies: "@semantic-release/commit-analyzer" "^8.0.0" "@semantic-release/error" "^2.2.0" @@ -8063,6 +8077,31 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== +shiki-languages@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/shiki-languages/-/shiki-languages-0.2.7.tgz#7230b675b96d37a36ac1bf995525375ce69f3924" + integrity sha512-REmakh7pn2jCn9GDMRSK36oDgqhh+rSvJPo77sdWTOmk44C5b0XlYPwJZcFOMJWUZJE0c7FCbKclw4FLwUKLRw== + dependencies: + vscode-textmate "^5.2.0" + +shiki-themes@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/shiki-themes/-/shiki-themes-0.2.7.tgz#6e04451d832152e0fc969876a7bd926b3963c1f2" + integrity sha512-ZMmboDYw5+SEpugM8KGUq3tkZ0vXg+k60XX6NngDK7gc1Sv6YLUlanpvG3evm57uKJvfXsky/S5MzSOTtYKLjA== + dependencies: + json5 "^2.1.0" + vscode-textmate "^5.2.0" + +shiki@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.2.7.tgz#d2547548ed8742673730e1e4bbe792a77c445540" + integrity sha512-bwVc7cdtYYHEO9O+XJ8aNOskKRfaQd5Y4ovLRfbQkmiLSUaR+bdlssbZUUhbQ0JAFMYcTcJ5tjG5KtnufttDHQ== + dependencies: + onigasm "^2.2.5" + shiki-languages "^0.2.7" + shiki-themes "^0.2.7" + vscode-textmate "^5.2.0" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" @@ -8898,27 +8937,27 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typedoc-default-themes@^0.11.4: - version "0.11.4" - resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.11.4.tgz#1bc55b7c8d1132844616ff6f570e1e2cd0eb7343" - integrity sha512-Y4Lf+qIb9NTydrexlazAM46SSLrmrQRqWiD52593g53SsmUFioAsMWt8m834J6qsp+7wHRjxCXSZeiiW5cMUdw== +typedoc-default-themes@0.12.1: + version "0.12.1" + resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.12.1.tgz#6c4a759f9dc365b4021579587b3773deb6fb6eeb" + integrity sha512-6PEvV+/kWAJeUwEtrKgIsZQSbybW5DGCr6s2mMjHsDplpgN8iBHI52UbA+2C+c2TMCxBNMK9TMS6pdeIdwsLSw== -typedoc@^0.19.2: - version "0.19.2" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.19.2.tgz#842a63a581f4920f76b0346bb80eb2a49afc2c28" - integrity sha512-oDEg1BLEzi1qvgdQXc658EYgJ5qJLVSeZ0hQ57Eq4JXy6Vj2VX4RVo18qYxRWz75ifAaYuYNBUCnbhjd37TfOg== +typedoc@^0.20.14: + version "0.20.14" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.20.14.tgz#894ff71841a4abbe8f46cf52f3cc96c9d68328dc" + integrity sha512-9bsZp5/qkl+gDSv9DRvHbfbY8Sr0tD8fKx7hNIvcluxeAFzBCEo9o0qDCdLUZw+/axbfd9TaqHvSuCVRu+YH6Q== dependencies: + colors "^1.4.0" fs-extra "^9.0.1" handlebars "^4.7.6" - highlight.js "^10.2.0" lodash "^4.17.20" lunr "^2.3.9" - marked "^1.1.1" + marked "^1.2.5" minimatch "^3.0.0" progress "^2.0.3" - semver "^7.3.2" shelljs "^0.8.4" - typedoc-default-themes "^0.11.4" + shiki "^0.2.7" + typedoc-default-themes "0.12.1" typescript@^4.1.3: version "4.1.3" @@ -9163,6 +9202,11 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +vscode-textmate@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" + integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ== + w3c-hr-time@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" From b03e2375da07b20c077b633bd5b82c55c31c897c Mon Sep 17 00:00:00 2001 From: lzear Date: Mon, 18 Jan 2021 23:47:52 +0100 Subject: [PATCH 5/6] fix: use lodash-es --- README.md | 8 +- jest.config.js | 3 + package.json | 22 +-- src/methods/baldwin/index.ts | 2 +- src/methods/coombs/index.ts | 2 +- src/methods/copeland/index.ts | 3 +- src/methods/kemeny/index.ts | 3 +- src/methods/maximal-lotteries/index.ts | 2 +- src/methods/nanson/index.ts | 3 +- src/methods/ranked-pairs/index.ts | 5 +- src/methods/schulze/index.ts | 2 +- src/test/matrix.ts | 2 +- src/test/testUtils.ts | 5 +- src/utils/condorcet.ts | 2 +- src/utils/makeMatrix.ts | 4 +- src/utils/normalize.ts | 14 +- src/utils/scores.ts | 4 +- src/utils/scoresZero.ts | 2 +- tsconfig.json | 2 +- yarn.lock | 218 ++++++++++++++----------- 20 files changed, 167 insertions(+), 141 deletions(-) diff --git a/README.md b/README.md index 16fd9db..8b0a197 100644 --- a/README.md +++ b/README.md @@ -82,11 +82,11 @@ The winner is the most-approved candidate. **Borda count**: For each voter, every candidate is given a number of points which equals the number of candidates ranked lower in the voter's preference. -**Nanson method**: Iterative Borda count in which, each round, candidates scoring -the average score or less are eliminated. +**Nanson method**: Iterative Borda count in which, each round, candidates +scoring the average score or less are eliminated. -**Baldwin method**: Iterative Borda count in which, each round, candidates scoring -the lowest score are eliminated. +**Baldwin method**: Iterative Borda count in which, each round, candidates +scoring the lowest score are eliminated. **Instant-runoff**: Considering only the top choice of each voter, the candidate with the fewest votes is eliminated. The election repeats until there is a diff --git a/jest.config.js b/jest.config.js index 6579506..bee9b33 100644 --- a/jest.config.js +++ b/jest.config.js @@ -2,6 +2,9 @@ module.exports = { transform: { '.(ts|tsx)': 'ts-jest', }, + moduleNameMapper: { + '^lodash-es$': 'lodash', + }, testEnvironment: 'node', testRegex: '(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$', moduleFileExtensions: ['ts', 'tsx', 'js'], diff --git a/package.json b/package.json index 64f745e..a22a769 100644 --- a/package.json +++ b/package.json @@ -53,32 +53,32 @@ "@commitlint/cli": "^11.0.0", "@rollup/plugin-commonjs": "^17.0.0", "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^11.0.1", + "@rollup/plugin-node-resolve": "^11.1.0", "@types/jest": "^26.0.20", "@types/lodash-es": "^4.17.4", - "@types/node": "^14.14.20", - "@typescript-eslint/eslint-plugin": "^4.13.0", - "@typescript-eslint/parser": "^4.13.0", - "commitizen": "^4.2.2", + "@types/node": "^14.14.21", + "@typescript-eslint/eslint-plugin": "^4.14.0", + "@typescript-eslint/parser": "^4.14.0", + "commitizen": "^4.2.3", "dotenv": "^8.2.0", - "eslint": "^7.17.0", - "eslint-config-prettier": "^7.1.0", + "eslint": "^7.18.0", + "eslint-config-prettier": "^7.2.0", "eslint-plugin-prettier": "^3.3.1", - "husky": "^4.3.7", + "husky": "^4.3.8", "jest": "^26.6.3", "lint-staged": "^10.5.3", "prettier": "^2.2.1", "rimraf": "^3.0.2", - "rollup": "^2.36.1", + "rollup": "^2.36.2", "rollup-plugin-sizes": "^1.0.3", "rollup-plugin-sourcemaps": "^0.6.3", "rollup-plugin-typescript2": "^0.29.0", - "semantic-release": "^17.3.2", + "semantic-release": "^17.3.3", "shelljs": "^0.8.4", "travis-deploy-once": "^5.0.11", "ts-jest": "^26.4.4", "ts-node": "^9.1.1", - "typedoc": "^0.20.14", + "typedoc": "^0.20.16", "typescript": "^4.1.3" }, "dependencies": { diff --git a/src/methods/baldwin/index.ts b/src/methods/baldwin/index.ts index 504399d..126092b 100644 --- a/src/methods/baldwin/index.ts +++ b/src/methods/baldwin/index.ts @@ -1,4 +1,4 @@ -import difference from 'lodash-es/difference' +import { difference } from 'lodash-es' import { SystemUsingRankings, ScoreObject, diff --git a/src/methods/coombs/index.ts b/src/methods/coombs/index.ts index 4c49c5d..0216dfb 100644 --- a/src/methods/coombs/index.ts +++ b/src/methods/coombs/index.ts @@ -1,4 +1,4 @@ -import difference from 'lodash-es/difference' +import { difference } from 'lodash-es' import { SystemUsingRankings, ScoreObject, diff --git a/src/methods/copeland/index.ts b/src/methods/copeland/index.ts index 366fda7..d226f49 100644 --- a/src/methods/copeland/index.ts +++ b/src/methods/copeland/index.ts @@ -1,6 +1,5 @@ /* eslint-disable no-plusplus */ -import range from 'lodash-es/range' -import zipObject from 'lodash-es/zipObject' +import { range, zipObject } from 'lodash-es' import { SystemUsingMatrix, VotingSystem, diff --git a/src/methods/kemeny/index.ts b/src/methods/kemeny/index.ts index 166741c..c60978f 100644 --- a/src/methods/kemeny/index.ts +++ b/src/methods/kemeny/index.ts @@ -1,5 +1,4 @@ -import zipObject from 'lodash-es/zipObject' -import range from 'lodash-es/range' +import { range, zipObject } from 'lodash-es' import { SystemUsingMatrix, VotingSystem, diff --git a/src/methods/maximal-lotteries/index.ts b/src/methods/maximal-lotteries/index.ts index 836203c..8422df0 100644 --- a/src/methods/maximal-lotteries/index.ts +++ b/src/methods/maximal-lotteries/index.ts @@ -1,4 +1,4 @@ -import zipObject from 'lodash-es/zipObject' +import { zipObject } from 'lodash-es' import { solve } from '../../simplex' import { SystemUsingMatrix, diff --git a/src/methods/nanson/index.ts b/src/methods/nanson/index.ts index cf33dad..7c2b796 100644 --- a/src/methods/nanson/index.ts +++ b/src/methods/nanson/index.ts @@ -1,5 +1,4 @@ -import sum from 'lodash-es/sum' -import difference from 'lodash-es/difference' +import { sum, difference } from 'lodash-es' import { SystemUsingRankings, ScoreObject, diff --git a/src/methods/ranked-pairs/index.ts b/src/methods/ranked-pairs/index.ts index 3146d07..3405095 100644 --- a/src/methods/ranked-pairs/index.ts +++ b/src/methods/ranked-pairs/index.ts @@ -1,7 +1,4 @@ -import groupBy from 'lodash-es/groupBy' -import range from 'lodash-es/range' -import uniq from 'lodash-es/uniq' -import zipObject from 'lodash-es/zipObject' +import { groupBy, range, uniq, zipObject } from 'lodash-es' import { Matrix, ScoreObject, diff --git a/src/methods/schulze/index.ts b/src/methods/schulze/index.ts index 06c7b5e..cfc1956 100644 --- a/src/methods/schulze/index.ts +++ b/src/methods/schulze/index.ts @@ -1,5 +1,5 @@ /* eslint-disable no-plusplus */ -import range from 'lodash-es/range' +import { range } from 'lodash-es' import { SystemUsingMatrix, VotingSystem, diff --git a/src/test/matrix.ts b/src/test/matrix.ts index 0c1e6a7..0dbcf26 100644 --- a/src/test/matrix.ts +++ b/src/test/matrix.ts @@ -1,4 +1,4 @@ -import range from 'lodash-es/range' +import { range } from 'lodash-es' export const product = (a: number[][], b: number[][]): number[][] => { const dimA = [a.length, a[0].length] diff --git a/src/test/testUtils.ts b/src/test/testUtils.ts index 2a73311..ca56549 100644 --- a/src/test/testUtils.ts +++ b/src/test/testUtils.ts @@ -1,7 +1,4 @@ -import fill from 'lodash-es/fill' -import random from 'lodash-es/random' -import range from 'lodash-es/range' -import shuffle from 'lodash-es/shuffle' +import { fill, random, range, shuffle } from 'lodash-es' import { Ballot } from '../types' import { toWeightedBallots } from '../utils' diff --git a/src/utils/condorcet.ts b/src/utils/condorcet.ts index 601b6dd..a44dec8 100644 --- a/src/utils/condorcet.ts +++ b/src/utils/condorcet.ts @@ -1,4 +1,4 @@ -import difference from 'lodash-es/difference' +import { difference } from 'lodash-es' import { Matrix } from '../types' export const findCondorcet = ({ candidates, array }: Matrix): Matrix => { diff --git a/src/utils/makeMatrix.ts b/src/utils/makeMatrix.ts index ad34597..4b3cf44 100644 --- a/src/utils/makeMatrix.ts +++ b/src/utils/makeMatrix.ts @@ -1,6 +1,4 @@ -import difference from 'lodash-es/difference' -import range from 'lodash-es/range' -import times from 'lodash-es/times' +import { difference, range, times } from 'lodash-es' import { Matrix, Ballot } from '../types' export const matrixFromBallots = ( diff --git a/src/utils/normalize.ts b/src/utils/normalize.ts index 4d19840..1d44f3a 100644 --- a/src/utils/normalize.ts +++ b/src/utils/normalize.ts @@ -1,9 +1,11 @@ -import difference from 'lodash-es/difference' -import every from 'lodash-es/every' -import flatten from 'lodash-es/flatten' -import intersection from 'lodash-es/intersection' -import isEqual from 'lodash-es/isEqual' -import uniq from 'lodash-es/uniq' +import { + every, + difference, + flatten, + intersection, + uniq, + isEqual, +} from 'lodash-es' import { Ballot } from '../types' diff --git a/src/utils/scores.ts b/src/utils/scores.ts index 5d9b2f7..a81ed4e 100644 --- a/src/utils/scores.ts +++ b/src/utils/scores.ts @@ -1,6 +1,4 @@ -import groupBy from 'lodash-es/groupBy' -import sortBy from 'lodash-es/sortBy' -import toPairs from 'lodash-es/toPairs' +import { groupBy, sortBy, toPairs } from 'lodash-es' export const scoresToRanking = (scores: { [candidate: string]: number diff --git a/src/utils/scoresZero.ts b/src/utils/scoresZero.ts index 2f1cb49..ea551e9 100644 --- a/src/utils/scoresZero.ts +++ b/src/utils/scoresZero.ts @@ -1,4 +1,4 @@ -import zipObject from 'lodash-es/zipObject' +import { zipObject } from 'lodash-es' import { ScoreObject } from '../types' export const scoresZero = (candidates: string[]): ScoreObject => diff --git a/tsconfig.json b/tsconfig.json index 94b09ba..587d9d7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "moduleResolution": "node", - "target": "esnext", + "target": "es5", "module": "es2015", "lib": ["es7", "es2015", "es2016", "es2017", "es2019", "esnext", "dom"], "strict": true, diff --git a/yarn.lock b/yarn.lock index 685a473..41d8e0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -999,10 +999,10 @@ resolved "https://registry.yarnpkg.com/@commitlint/types/-/types-11.0.0.tgz#719cf05fcc1abb6533610a2e0f5dd1e61eac14fe" integrity sha512-VoNqai1vR5anRF5Tuh/+SWDFk7xi7oMwHrHrbm1BprYXjB2RJsWLhUrStMssDxEl5lW/z3EUdg8RvH/IUBccSQ== -"@eslint/eslintrc@^0.2.2": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.2.tgz#d01fc791e2fc33e88a29d6f3dc7e93d0cd784b76" - integrity sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ== +"@eslint/eslintrc@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.3.0.tgz#d736d6963d7003b6514e6324bec9c602ac340318" + integrity sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg== dependencies: ajv "^6.12.4" debug "^4.1.1" @@ -1011,7 +1011,7 @@ ignore "^4.0.6" import-fresh "^3.2.1" js-yaml "^3.13.1" - lodash "^4.17.19" + lodash "^4.17.20" minimatch "^3.0.4" strip-json-comments "^3.1.1" @@ -1356,10 +1356,10 @@ dependencies: "@rollup/pluginutils" "^3.0.8" -"@rollup/plugin-node-resolve@^11.0.1": - version "11.0.1" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.0.1.tgz#d3765eec4bccf960801439a999382aed2dca959b" - integrity sha512-ltlsj/4Bhwwhb+Nb5xCz/6vieuEj2/BAkkqVIKmZwC7pIdl8srmgmglE4S0jFlZa32K4qvdQ6NHdmpRKD/LwoQ== +"@rollup/plugin-node-resolve@^11.1.0": + version "11.1.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.1.0.tgz#fa0f888297b3aebcd6534e8aba4e6fe01997649a" + integrity sha512-ouBBppRdWJKCllDXGzJ7ZIkYbaq+5TmyP0smt1vdJCFfoZhLi31vhpmjLhyo8lreHf4RoeSNllaWrvSqHpHRog== dependencies: "@rollup/pluginutils" "^3.1.0" "@types/resolve" "1.17.1" @@ -1595,10 +1595,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.6.tgz#146d3da57b3c636cc0d1769396ce1cfa8991147f" integrity sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw== -"@types/node@^14.14.20": - version "14.14.20" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.20.tgz#f7974863edd21d1f8a494a73e8e2b3658615c340" - integrity sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A== +"@types/node@^14.14.21": + version "14.14.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.21.tgz#d934aacc22424fe9622ebf6857370c052eae464e" + integrity sha512-cHYfKsnwllYhjOzuC5q1VpguABBeecUp24yFluHpn/BQaVxB1CuQ1FSRZCzrPxrkIfWISXV2LbeoBthLWg0+0A== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -1611,9 +1611,9 @@ integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== "@types/prettier@^2.0.0": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.5.tgz#b6ab3bba29e16b821d84e09ecfaded462b816b00" - integrity sha512-UEyp8LwZ4Dg30kVU2Q3amHHyTn1jEdhCIE59ANed76GaT1Vp76DD3ZWSAxgCrw6wJ0TqeoBpqmfUHiUDPs//HQ== + version "2.1.6" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.6.tgz#f4b1efa784e8db479cdb8b14403e2144b1e9ff03" + integrity sha512-6gOkRe7OIioWAXfnO/2lFiv+SJichKVSys1mSsgyrYHSEjk8Ctv4tSR/Odvnu+HWlH2C8j53dahU03XmQdd5fA== "@types/resolve@1.17.1": version "1.17.1" @@ -1644,13 +1644,13 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.13.0.tgz#5f580ea520fa46442deb82c038460c3dd3524bb6" - integrity sha512-ygqDUm+BUPvrr0jrXqoteMqmIaZ/bixYOc3A4BRwzEPTZPi6E+n44rzNZWaB0YvtukgP+aoj0i/fyx7FkM2p1w== +"@typescript-eslint/eslint-plugin@^4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.14.0.tgz#92db8e7c357ed7d69632d6843ca70b71be3a721d" + integrity sha512-IJ5e2W7uFNfg4qh9eHkHRUCbgZ8VKtGwD07kannJvM5t/GU8P8+24NX8gi3Hf5jST5oWPY8kyV1s/WtfiZ4+Ww== dependencies: - "@typescript-eslint/experimental-utils" "4.13.0" - "@typescript-eslint/scope-manager" "4.13.0" + "@typescript-eslint/experimental-utils" "4.14.0" + "@typescript-eslint/scope-manager" "4.14.0" debug "^4.1.1" functional-red-black-tree "^1.0.1" lodash "^4.17.15" @@ -1658,48 +1658,48 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.13.0.tgz#9dc9ab375d65603b43d938a0786190a0c72be44e" - integrity sha512-/ZsuWmqagOzNkx30VWYV3MNB/Re/CGv/7EzlqZo5RegBN8tMuPaBgNK6vPBCQA8tcYrbsrTdbx3ixMRRKEEGVw== +"@typescript-eslint/experimental-utils@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.14.0.tgz#5aa7b006736634f588a69ee343ca959cd09988df" + integrity sha512-6i6eAoiPlXMKRbXzvoQD5Yn9L7k9ezzGRvzC/x1V3650rUk3c3AOjQyGYyF9BDxQQDK2ElmKOZRD0CbtdkMzQQ== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.13.0" - "@typescript-eslint/types" "4.13.0" - "@typescript-eslint/typescript-estree" "4.13.0" + "@typescript-eslint/scope-manager" "4.14.0" + "@typescript-eslint/types" "4.14.0" + "@typescript-eslint/typescript-estree" "4.14.0" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.13.0.tgz#c413d640ea66120cfcc37f891e8cb3fd1c9d247d" - integrity sha512-KO0J5SRF08pMXzq9+abyHnaGQgUJZ3Z3ax+pmqz9vl81JxmTTOUfQmq7/4awVfq09b6C4owNlOgOwp61pYRBSg== +"@typescript-eslint/parser@^4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.14.0.tgz#62d4cd2079d5c06683e9bfb200c758f292c4dee7" + integrity sha512-sUDeuCjBU+ZF3Lzw0hphTyScmDDJ5QVkyE21pRoBo8iDl7WBtVFS+WDN3blY1CH3SBt7EmYCw6wfmJjF0l/uYg== dependencies: - "@typescript-eslint/scope-manager" "4.13.0" - "@typescript-eslint/types" "4.13.0" - "@typescript-eslint/typescript-estree" "4.13.0" + "@typescript-eslint/scope-manager" "4.14.0" + "@typescript-eslint/types" "4.14.0" + "@typescript-eslint/typescript-estree" "4.14.0" debug "^4.1.1" -"@typescript-eslint/scope-manager@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.13.0.tgz#5b45912a9aa26b29603d8fa28f5e09088b947141" - integrity sha512-UpK7YLG2JlTp/9G4CHe7GxOwd93RBf3aHO5L+pfjIrhtBvZjHKbMhBXTIQNkbz7HZ9XOe++yKrXutYm5KmjWgQ== +"@typescript-eslint/scope-manager@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.14.0.tgz#55a4743095d684e1f7b7180c4bac2a0a3727f517" + integrity sha512-/J+LlRMdbPh4RdL4hfP1eCwHN5bAhFAGOTsvE6SxsrM/47XQiPSgF5MDgLyp/i9kbZV9Lx80DW0OpPkzL+uf8Q== dependencies: - "@typescript-eslint/types" "4.13.0" - "@typescript-eslint/visitor-keys" "4.13.0" + "@typescript-eslint/types" "4.14.0" + "@typescript-eslint/visitor-keys" "4.14.0" -"@typescript-eslint/types@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.13.0.tgz#6a7c6015a59a08fbd70daa8c83dfff86250502f8" - integrity sha512-/+aPaq163oX+ObOG00M0t9tKkOgdv9lq0IQv/y4SqGkAXmhFmCfgsELV7kOCTb2vVU5VOmVwXBXJTDr353C1rQ== +"@typescript-eslint/types@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.14.0.tgz#d8a8202d9b58831d6fd9cee2ba12f8a5a5dd44b6" + integrity sha512-VsQE4VvpldHrTFuVPY1ZnHn/Txw6cZGjL48e+iBxTi2ksa9DmebKjAeFmTVAYoSkTk7gjA7UqJ7pIsyifTsI4A== -"@typescript-eslint/typescript-estree@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.13.0.tgz#cf6e2207c7d760f5dfd8d18051428fadfc37b45e" - integrity sha512-9A0/DFZZLlGXn5XA349dWQFwPZxcyYyCFX5X88nWs2uachRDwGeyPz46oTsm9ZJE66EALvEns1lvBwa4d9QxMg== +"@typescript-eslint/typescript-estree@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.14.0.tgz#4bcd67486e9acafc3d0c982b23a9ab8ac8911ed7" + integrity sha512-wRjZ5qLao+bvS2F7pX4qi2oLcOONIB+ru8RGBieDptq/SudYwshveORwCVU4/yMAd4GK7Fsf8Uq1tjV838erag== dependencies: - "@typescript-eslint/types" "4.13.0" - "@typescript-eslint/visitor-keys" "4.13.0" + "@typescript-eslint/types" "4.14.0" + "@typescript-eslint/visitor-keys" "4.14.0" debug "^4.1.1" globby "^11.0.1" is-glob "^4.0.1" @@ -1707,12 +1707,12 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.13.0.tgz#9acb1772d3b3183182b6540d3734143dce9476fe" - integrity sha512-6RoxWK05PAibukE7jElqAtNMq+RWZyqJ6Q/GdIxaiUj2Ept8jh8+FUVlbq9WxMYxkmEOPvCE5cRSyupMpwW31g== +"@typescript-eslint/visitor-keys@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.14.0.tgz#b1090d9d2955b044b2ea2904a22496849acbdf54" + integrity sha512-MeHHzUyRI50DuiPgV9+LxcM52FCJFYjJiWHtXlbyC27b80mfOwKeiKI+MHOTEpcpfmoPFm/vvQS88bYIx6PZTA== dependencies: - "@typescript-eslint/types" "4.13.0" + "@typescript-eslint/types" "4.14.0" eslint-visitor-keys "^2.0.0" JSONStream@^1.0.4, JSONStream@^1.3.4, JSONStream@^1.3.5: @@ -2616,7 +2616,7 @@ commander@^6.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75" integrity sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q== -commitizen@^4.0.3, commitizen@^4.2.2: +commitizen@^4.0.3: version "4.2.2" resolved "https://registry.yarnpkg.com/commitizen/-/commitizen-4.2.2.tgz#1a93dd07208521ea1ebbf832593542dac714cc79" integrity sha512-uz+E6lGsDBDI2mYA4QfOxFeqdWUYwR1ky11YmLgg2BnEEP3YbeejpT4lxzGjkYqumnXr062qTOGavR9NtX/iwQ== @@ -2636,6 +2636,26 @@ commitizen@^4.0.3, commitizen@^4.2.2: strip-bom "4.0.0" strip-json-comments "3.0.1" +commitizen@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/commitizen/-/commitizen-4.2.3.tgz#088d0ef72500240d331b11e02e288223667c1475" + integrity sha512-pYlYEng7XMV2TW4xtjDKBGqeJ0Teq2zyRSx2S3Ml1XAplHSlJZK8vm1KdGclpMEZuGafbS5TeHXIVnHk8RWIzQ== + dependencies: + cachedir "2.2.0" + cz-conventional-changelog "3.2.0" + dedent "0.7.0" + detect-indent "6.0.0" + find-node-modules "2.0.0" + find-root "1.1.0" + fs-extra "8.1.0" + glob "7.1.4" + inquirer "6.5.2" + is-utf8 "^0.2.1" + lodash "^4.17.20" + minimist "1.2.5" + strip-bom "4.0.0" + strip-json-comments "3.0.1" + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -2891,6 +2911,20 @@ cyclist@^1.0.1: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= +cz-conventional-changelog@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cz-conventional-changelog/-/cz-conventional-changelog-3.2.0.tgz#6aef1f892d64113343d7e455529089ac9f20e477" + integrity sha512-yAYxeGpVi27hqIilG1nh4A9Bnx4J3Ov+eXy4koL3drrR+IO9GaWPsKjik20ht608Asqi8TQPf0mczhEeyAtMzg== + dependencies: + chalk "^2.4.1" + commitizen "^4.0.3" + conventional-commit-types "^3.0.0" + lodash.map "^4.5.1" + longest "^2.0.1" + word-wrap "^1.0.3" + optionalDependencies: + "@commitlint/load" ">6.1.1" + cz-conventional-changelog@3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/cz-conventional-changelog/-/cz-conventional-changelog-3.3.0.tgz#9246947c90404149b3fe2cf7ee91acad3b7d22d2" @@ -3349,10 +3383,10 @@ escodegen@^1.14.1: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-7.1.0.tgz#5402eb559aa94b894effd6bddfa0b1ca051c858f" - integrity sha512-9sm5/PxaFG7qNJvJzTROMM1Bk1ozXVTKI0buKOyb0Bsr1hrwi0H/TzxF/COtf1uxikIK8SwhX7K6zg78jAzbeA== +eslint-config-prettier@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz#f4a4bd2832e810e8cc7c1411ec85b3e85c0c53f9" + integrity sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg== eslint-plugin-prettier@^3.3.1: version "3.3.1" @@ -3386,13 +3420,13 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== -eslint@^7.17.0: - version "7.17.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.17.0.tgz#4ccda5bf12572ad3bf760e6f195886f50569adb0" - integrity sha512-zJk08MiBgwuGoxes5sSQhOtibZ75pz0J35XTRlZOk9xMffhpA9BTbQZxoXZzOl5zMbleShbGwtw+1kGferfFwQ== +eslint@^7.18.0: + version "7.18.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.18.0.tgz#7fdcd2f3715a41fe6295a16234bd69aed2c75e67" + integrity sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ== dependencies: "@babel/code-frame" "^7.0.0" - "@eslint/eslintrc" "^0.2.2" + "@eslint/eslintrc" "^0.3.0" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" @@ -3416,7 +3450,7 @@ eslint@^7.17.0: js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" - lodash "^4.17.19" + lodash "^4.17.20" minimatch "^3.0.4" natural-compare "^1.4.0" optionator "^0.9.1" @@ -4375,10 +4409,10 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -husky@^4.3.7: - version "4.3.7" - resolved "https://registry.yarnpkg.com/husky/-/husky-4.3.7.tgz#ca47bbe6213c1aa8b16bbd504530d9600de91e88" - integrity sha512-0fQlcCDq/xypoyYSJvEuzbDPHFf8ZF9IXKJxlrnvxABTSzK1VPT2RKYQKrcgJ+YD39swgoB6sbzywUqFxUiqjw== +husky@^4.3.8: + version "4.3.8" + resolved "https://registry.yarnpkg.com/husky/-/husky-4.3.8.tgz#31144060be963fd6850e5cc8f019a1dfe194296d" + integrity sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow== dependencies: chalk "^4.0.0" ci-info "^2.0.0" @@ -7852,10 +7886,10 @@ rollup-plugin-typescript2@^0.29.0: resolve "1.17.0" tslib "2.0.1" -rollup@^2.36.1: - version "2.36.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.36.1.tgz#2174f0c25c7b400d57b05628d0e732c7ae8d2178" - integrity sha512-eAfqho8dyzuVvrGqpR0ITgEdq0zG2QJeWYh+HeuTbpcaXk8vNFc48B7bJa1xYosTCKx0CuW+447oQOW8HgBIZQ== +rollup@^2.36.2: + version "2.36.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.36.2.tgz#883fc793c70c8481ad604f1065cd79ab0a4e9c49" + integrity sha512-qjjiuJKb+/8n0EZyQYVW+gFU4bNRBcZaXVzUgSVrGw0HlQBlK2aWyaOMMs1Ufic1jV69b9kW3u3i9B+hISDm3A== optionalDependencies: fsevents "~2.1.2" @@ -7932,10 +7966,10 @@ saxes@^5.0.0: dependencies: xmlchars "^2.2.0" -semantic-release@^17.3.2: - version "17.3.2" - resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-17.3.2.tgz#89c793ed64fe00b7bfe1c36bc389fb04855a4df9" - integrity sha512-S8ppLzFFeznDXvRGEvltuwpRT7Tb7o3gBIqaVnahi0sAzrxD/WdWZQoHOpwypzTBD7i9gCxZ+RqVpaHa9WFD3w== +semantic-release@^17.3.3: + version "17.3.3" + resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-17.3.3.tgz#8f3d2909e9570d9053ef195c138d8d15d7fe5815" + integrity sha512-StUBghTuh98O0XpDWj5aRLmZwY9zV6gGgbXnw5faon3Br1fRk8r2VSaYozfQTx8o5C8Mtem+a0KWEiTTd4Iylw== dependencies: "@semantic-release/commit-analyzer" "^8.0.0" "@semantic-release/error" "^2.2.0" @@ -8357,9 +8391,9 @@ ssri@^6.0.0, ssri@^6.0.1: figgy-pudding "^3.5.1" stack-utils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.2.tgz#5cf48b4557becb4638d0bc4f21d23f5d19586593" - integrity sha512-0H7QK2ECz3fyZMzQ8rH0j2ykpfbnd20BFtfg/SqVC2+sCTtcw0aDTGB7dk+de4U4uUeuz6nOtJcrkFFLG1B0Rg== + version "2.0.3" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277" + integrity sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw== dependencies: escape-string-regexp "^2.0.0" @@ -8937,15 +8971,15 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typedoc-default-themes@0.12.1: - version "0.12.1" - resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.12.1.tgz#6c4a759f9dc365b4021579587b3773deb6fb6eeb" - integrity sha512-6PEvV+/kWAJeUwEtrKgIsZQSbybW5DGCr6s2mMjHsDplpgN8iBHI52UbA+2C+c2TMCxBNMK9TMS6pdeIdwsLSw== +typedoc-default-themes@^0.12.4: + version "0.12.4" + resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.12.4.tgz#5cbb79c1d6421f1274e86b1b542934eb557abd4f" + integrity sha512-EZiXBUpogsYWe0dLgy47J8yRZCd+HAn9woGzO28XJxxSCSwZRYGKeQiw1KjyIcm3cBtLWUXiPD5+Bgx24GgZjg== -typedoc@^0.20.14: - version "0.20.14" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.20.14.tgz#894ff71841a4abbe8f46cf52f3cc96c9d68328dc" - integrity sha512-9bsZp5/qkl+gDSv9DRvHbfbY8Sr0tD8fKx7hNIvcluxeAFzBCEo9o0qDCdLUZw+/axbfd9TaqHvSuCVRu+YH6Q== +typedoc@^0.20.16: + version "0.20.16" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.20.16.tgz#c845d32883af905439607ba03c9667b81cdbeb22" + integrity sha512-xqIL8lT6ZE3QpP0GN30ckeTR05NSEkrP2pXQlNhC0OFkbvnjqJtDUcWSmCO15BuYyu4qsEbZT+tKYFEAt9Jxew== dependencies: colors "^1.4.0" fs-extra "^9.0.1" @@ -8957,7 +8991,7 @@ typedoc@^0.20.14: progress "^2.0.3" shelljs "^0.8.4" shiki "^0.2.7" - typedoc-default-themes "0.12.1" + typedoc-default-themes "^0.12.4" typescript@^4.1.3: version "4.1.3" From 43100f8d2fdb4ba941c9d2dc1901635a9739fcfc Mon Sep 17 00:00:00 2001 From: lzear Date: Wed, 20 Jan 2021 00:30:20 +0100 Subject: [PATCH 6/6] fix: es-import bug --- jest.config.js | 3 - package.json | 10 +- src/methods/baldwin/index.ts | 2 +- src/methods/coombs/index.ts | 2 +- src/methods/copeland/index.ts | 3 +- src/methods/kemeny/index.ts | 3 +- src/methods/maximal-lotteries/index.ts | 2 +- .../maximal-lotteries.test.ts | 2 +- src/methods/nanson/index.ts | 3 +- .../randomized-condorcet.test.ts | 2 +- src/methods/ranked-pairs/index.ts | 5 +- src/methods/schulze/index.ts | 2 +- src/test/matrix.ts | 2 +- src/test/matrixString.ts | 19 ---- src/test/testUtils.ts | 5 +- src/utils/condorcet.ts | 2 +- src/utils/makeMatrix.ts | 4 +- src/utils/normalize.ts | 14 ++- src/utils/scores.ts | 4 +- src/utils/scoresZero.ts | 2 +- yarn.lock | 91 ++++++++++++------- 21 files changed, 100 insertions(+), 82 deletions(-) delete mode 100644 src/test/matrixString.ts diff --git a/jest.config.js b/jest.config.js index bee9b33..6579506 100644 --- a/jest.config.js +++ b/jest.config.js @@ -2,9 +2,6 @@ module.exports = { transform: { '.(ts|tsx)': 'ts-jest', }, - moduleNameMapper: { - '^lodash-es$': 'lodash', - }, testEnvironment: 'node', testRegex: '(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$', moduleFileExtensions: ['ts', 'tsx', 'js'], diff --git a/package.json b/package.json index a22a769..7920640 100644 --- a/package.json +++ b/package.json @@ -55,8 +55,8 @@ "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^11.1.0", "@types/jest": "^26.0.20", - "@types/lodash-es": "^4.17.4", - "@types/node": "^14.14.21", + "@types/lodash": "^4.14.168", + "@types/node": "^14.14.22", "@typescript-eslint/eslint-plugin": "^4.14.0", "@typescript-eslint/parser": "^4.14.0", "commitizen": "^4.2.3", @@ -69,11 +69,11 @@ "lint-staged": "^10.5.3", "prettier": "^2.2.1", "rimraf": "^3.0.2", - "rollup": "^2.36.2", + "rollup": "^2.37.0", "rollup-plugin-sizes": "^1.0.3", "rollup-plugin-sourcemaps": "^0.6.3", "rollup-plugin-typescript2": "^0.29.0", - "semantic-release": "^17.3.3", + "semantic-release": "^17.3.4", "shelljs": "^0.8.4", "travis-deploy-once": "^5.0.11", "ts-jest": "^26.4.4", @@ -82,7 +82,7 @@ "typescript": "^4.1.3" }, "dependencies": { - "lodash-es": "^4.17.20" + "lodash": "^4.17.20" }, "bugs": { "url": "https://github.com/lzear/votes/issues" diff --git a/src/methods/baldwin/index.ts b/src/methods/baldwin/index.ts index 126092b..388e308 100644 --- a/src/methods/baldwin/index.ts +++ b/src/methods/baldwin/index.ts @@ -1,4 +1,4 @@ -import { difference } from 'lodash-es' +import difference from 'lodash/difference' import { SystemUsingRankings, ScoreObject, diff --git a/src/methods/coombs/index.ts b/src/methods/coombs/index.ts index 0216dfb..09e629d 100644 --- a/src/methods/coombs/index.ts +++ b/src/methods/coombs/index.ts @@ -1,4 +1,4 @@ -import { difference } from 'lodash-es' +import difference from 'lodash/difference' import { SystemUsingRankings, ScoreObject, diff --git a/src/methods/copeland/index.ts b/src/methods/copeland/index.ts index d226f49..7100ec9 100644 --- a/src/methods/copeland/index.ts +++ b/src/methods/copeland/index.ts @@ -1,5 +1,6 @@ /* eslint-disable no-plusplus */ -import { range, zipObject } from 'lodash-es' +import range from 'lodash/range' +import zipObject from 'lodash/zipObject' import { SystemUsingMatrix, VotingSystem, diff --git a/src/methods/kemeny/index.ts b/src/methods/kemeny/index.ts index c60978f..bd6de2c 100644 --- a/src/methods/kemeny/index.ts +++ b/src/methods/kemeny/index.ts @@ -1,4 +1,5 @@ -import { range, zipObject } from 'lodash-es' +import zipObject from 'lodash/zipObject' +import range from 'lodash/range' import { SystemUsingMatrix, VotingSystem, diff --git a/src/methods/maximal-lotteries/index.ts b/src/methods/maximal-lotteries/index.ts index 8422df0..97b67d8 100644 --- a/src/methods/maximal-lotteries/index.ts +++ b/src/methods/maximal-lotteries/index.ts @@ -1,4 +1,4 @@ -import { zipObject } from 'lodash-es' +import zipObject from 'lodash/zipObject' import { solve } from '../../simplex' import { SystemUsingMatrix, diff --git a/src/methods/maximal-lotteries/maximal-lotteries.test.ts b/src/methods/maximal-lotteries/maximal-lotteries.test.ts index 141ddba..8cb4ddb 100644 --- a/src/methods/maximal-lotteries/maximal-lotteries.test.ts +++ b/src/methods/maximal-lotteries/maximal-lotteries.test.ts @@ -1,5 +1,5 @@ import { performPivots, simplexTableau } from '../../simplex' -import { matrixString } from '../../test/matrixString' +import { matrixString } from '../../test/testUtils' import { maximalLotteries } from './index' const example1 = [ diff --git a/src/methods/nanson/index.ts b/src/methods/nanson/index.ts index 7c2b796..27f946f 100644 --- a/src/methods/nanson/index.ts +++ b/src/methods/nanson/index.ts @@ -1,4 +1,5 @@ -import { sum, difference } from 'lodash-es' +import difference from 'lodash/difference' +import sum from 'lodash/sum' import { SystemUsingRankings, ScoreObject, diff --git a/src/methods/randomized-condorcet/randomized-condorcet.test.ts b/src/methods/randomized-condorcet/randomized-condorcet.test.ts index 2e8ac34..229d0b4 100644 --- a/src/methods/randomized-condorcet/randomized-condorcet.test.ts +++ b/src/methods/randomized-condorcet/randomized-condorcet.test.ts @@ -1,5 +1,5 @@ import { performPivots, simplexTableau } from '../../simplex' -import { matrixString } from '../../test/matrixString' +import { matrixString } from '../../test/testUtils' import { randomizedCondorcet } from '.' const example1 = [ diff --git a/src/methods/ranked-pairs/index.ts b/src/methods/ranked-pairs/index.ts index 3405095..e99ec1e 100644 --- a/src/methods/ranked-pairs/index.ts +++ b/src/methods/ranked-pairs/index.ts @@ -1,4 +1,7 @@ -import { groupBy, range, uniq, zipObject } from 'lodash-es' +import groupBy from 'lodash/groupBy' +import range from 'lodash/range' +import uniq from 'lodash/uniq' +import zipObject from 'lodash/zipObject' import { Matrix, ScoreObject, diff --git a/src/methods/schulze/index.ts b/src/methods/schulze/index.ts index cfc1956..90e79e9 100644 --- a/src/methods/schulze/index.ts +++ b/src/methods/schulze/index.ts @@ -1,5 +1,5 @@ /* eslint-disable no-plusplus */ -import { range } from 'lodash-es' +import range from 'lodash/range' import { SystemUsingMatrix, VotingSystem, diff --git a/src/test/matrix.ts b/src/test/matrix.ts index 0dbcf26..45baadc 100644 --- a/src/test/matrix.ts +++ b/src/test/matrix.ts @@ -1,4 +1,4 @@ -import { range } from 'lodash-es' +import range from 'lodash/range' export const product = (a: number[][], b: number[][]): number[][] => { const dimA = [a.length, a[0].length] diff --git a/src/test/matrixString.ts b/src/test/matrixString.ts deleted file mode 100644 index 4bf5365..0000000 --- a/src/test/matrixString.ts +++ /dev/null @@ -1,19 +0,0 @@ -export const matrixString = (matrix: number[][]): string => { - const size = 6 - - return ( - '\n' + - matrix - .map((r) => - r - .map((c) => - (Math.round(c * 1000) / 1000) - .toString() - .padStart(size, ' ') - .substr(0, size), - ) - .join(' '), - ) - .join('\n') - ) -} diff --git a/src/test/testUtils.ts b/src/test/testUtils.ts index ca56549..755e2ab 100644 --- a/src/test/testUtils.ts +++ b/src/test/testUtils.ts @@ -1,4 +1,7 @@ -import { fill, random, range, shuffle } from 'lodash-es' +import fill from 'lodash/fill' +import random from 'lodash/random' +import range from 'lodash/range' +import shuffle from 'lodash/shuffle' import { Ballot } from '../types' import { toWeightedBallots } from '../utils' diff --git a/src/utils/condorcet.ts b/src/utils/condorcet.ts index a44dec8..0bcdbea 100644 --- a/src/utils/condorcet.ts +++ b/src/utils/condorcet.ts @@ -1,4 +1,4 @@ -import { difference } from 'lodash-es' +import difference from 'lodash/difference' import { Matrix } from '../types' export const findCondorcet = ({ candidates, array }: Matrix): Matrix => { diff --git a/src/utils/makeMatrix.ts b/src/utils/makeMatrix.ts index 4b3cf44..9da0547 100644 --- a/src/utils/makeMatrix.ts +++ b/src/utils/makeMatrix.ts @@ -1,4 +1,6 @@ -import { difference, range, times } from 'lodash-es' +import difference from 'lodash/difference' +import range from 'lodash/range' +import times from 'lodash/times' import { Matrix, Ballot } from '../types' export const matrixFromBallots = ( diff --git a/src/utils/normalize.ts b/src/utils/normalize.ts index 1d44f3a..8767463 100644 --- a/src/utils/normalize.ts +++ b/src/utils/normalize.ts @@ -1,11 +1,9 @@ -import { - every, - difference, - flatten, - intersection, - uniq, - isEqual, -} from 'lodash-es' +import difference from 'lodash/difference' +import every from 'lodash/every' +import flatten from 'lodash/flatten' +import intersection from 'lodash/intersection' +import isEqual from 'lodash/isEqual' +import uniq from 'lodash/uniq' import { Ballot } from '../types' diff --git a/src/utils/scores.ts b/src/utils/scores.ts index a81ed4e..5298d61 100644 --- a/src/utils/scores.ts +++ b/src/utils/scores.ts @@ -1,4 +1,6 @@ -import { groupBy, sortBy, toPairs } from 'lodash-es' +import groupBy from 'lodash/groupBy' +import sortBy from 'lodash/sortBy' +import toPairs from 'lodash/toPairs' export const scoresToRanking = (scores: { [candidate: string]: number diff --git a/src/utils/scoresZero.ts b/src/utils/scoresZero.ts index ea551e9..dfe2cfe 100644 --- a/src/utils/scoresZero.ts +++ b/src/utils/scoresZero.ts @@ -1,4 +1,4 @@ -import { zipObject } from 'lodash-es' +import zipObject from 'lodash/zipObject' import { ScoreObject } from '../types' export const scoresZero = (candidates: string[]): ScoreObject => diff --git a/yarn.lock b/yarn.lock index 41d8e0e..3b4a7fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1573,17 +1573,10 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== -"@types/lodash-es@^4.17.4": - version "4.17.4" - resolved "https://registry.yarnpkg.com/@types/lodash-es/-/lodash-es-4.17.4.tgz#b2e440d2bf8a93584a9fd798452ec497986c9b97" - integrity sha512-BBz79DCJbD2CVYZH67MBeHZRX++HF+5p8Mo5MzjZi64Wac39S3diedJYHZtScbRVf4DjZyN6LzA0SB0zy+HSSQ== - dependencies: - "@types/lodash" "*" - -"@types/lodash@*": - version "4.14.167" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.167.tgz#ce7d78553e3c886d4ea643c37ec7edc20f16765e" - integrity sha512-w7tQPjARrvdeBkX/Rwg95S592JwxqOjmms3zWQ0XZgSyxSLdzWaYH3vErBhdVS/lRBX7F8aBYcYJYTr5TMGOzw== +"@types/lodash@^4.14.168": + version "4.14.168" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.168.tgz#fe24632e79b7ade3f132891afff86caa5e5ce008" + integrity sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q== "@types/minimist@^1.2.0": version "1.2.0" @@ -1595,10 +1588,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.6.tgz#146d3da57b3c636cc0d1769396ce1cfa8991147f" integrity sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw== -"@types/node@^14.14.21": - version "14.14.21" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.21.tgz#d934aacc22424fe9622ebf6857370c052eae464e" - integrity sha512-cHYfKsnwllYhjOzuC5q1VpguABBeecUp24yFluHpn/BQaVxB1CuQ1FSRZCzrPxrkIfWISXV2LbeoBthLWg0+0A== +"@types/node@^14.14.22": + version "14.14.22" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.22.tgz#0d29f382472c4ccf3bd96ff0ce47daf5b7b84b18" + integrity sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -2519,6 +2512,15 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + clone-response@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" @@ -4012,7 +4014,7 @@ get-caller-file@^1.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== -get-caller-file@^2.0.1: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -5812,11 +5814,6 @@ lockfile@^1.0.4: dependencies: signal-exit "^3.0.2" -lodash-es@^4.17.20: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.20.tgz#29f6332eefc60e849f869c264bc71126ad61e8f7" - integrity sha512-JD1COMZsq8maT6mnuz1UMV0jvYD0E0aUsSOdrr1/nAG3dhqQXwRRgeW0cSqH1U43INKcqxaiVIQNOUDld7gRDA== - lodash._baseuniq@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" @@ -7886,10 +7883,10 @@ rollup-plugin-typescript2@^0.29.0: resolve "1.17.0" tslib "2.0.1" -rollup@^2.36.2: - version "2.36.2" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.36.2.tgz#883fc793c70c8481ad604f1065cd79ab0a4e9c49" - integrity sha512-qjjiuJKb+/8n0EZyQYVW+gFU4bNRBcZaXVzUgSVrGw0HlQBlK2aWyaOMMs1Ufic1jV69b9kW3u3i9B+hISDm3A== +rollup@^2.37.0: + version "2.37.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.37.0.tgz#5baf631dc224a56d7eb88dd11b20aa28c1e8dc6f" + integrity sha512-cbxuxkMGCQV+TnVh+yZSUerbVb5i8soRydbzHYoMNojgt7MMi+jDLLs24U9HHCssKkwkXmsj+LXcOZMldTbz2w== optionalDependencies: fsevents "~2.1.2" @@ -7966,10 +7963,10 @@ saxes@^5.0.0: dependencies: xmlchars "^2.2.0" -semantic-release@^17.3.3: - version "17.3.3" - resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-17.3.3.tgz#8f3d2909e9570d9053ef195c138d8d15d7fe5815" - integrity sha512-StUBghTuh98O0XpDWj5aRLmZwY9zV6gGgbXnw5faon3Br1fRk8r2VSaYozfQTx8o5C8Mtem+a0KWEiTTd4Iylw== +semantic-release@^17.3.4: + version "17.3.4" + resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-17.3.4.tgz#62bd16e4f7d600ba7c44b371b3973f733e2db001" + integrity sha512-rifRJU2am90uheTG5j3cXFaoS9aoROsQmijCxalE/C28dom6qkb1vzQbNKdPK0oKn6VGZ+HVojJLPlJQuEsRvw== dependencies: "@semantic-release/commit-analyzer" "^8.0.0" "@semantic-release/error" "^2.2.0" @@ -7998,7 +7995,7 @@ semantic-release@^17.3.3: semver "^7.3.2" semver-diff "^3.1.1" signale "^1.2.1" - yargs "^15.0.1" + yargs "^16.2.0" semver-compare@^1.0.0: version "1.0.0" @@ -9388,6 +9385,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -9447,6 +9453,11 @@ y18n@^3.2.1: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== +y18n@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18" + integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg== + yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" @@ -9496,6 +9507,11 @@ yargs-parser@^18.1.2, yargs-parser@^18.1.3: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^20.2.2: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + yargs-parser@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" @@ -9538,7 +9554,7 @@ yargs@^14.2.3: y18n "^4.0.0" yargs-parser "^15.0.1" -yargs@^15.0.1, yargs@^15.1.0, yargs@^15.4.1: +yargs@^15.1.0, yargs@^15.4.1: version "15.4.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== @@ -9555,6 +9571,19 @@ yargs@^15.0.1, yargs@^15.1.0, yargs@^15.4.1: y18n "^4.0.0" yargs-parser "^18.1.2" +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + yargs@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360"