{"id":26413005,"url":"https://github.com/mieuxvoter/majority-judgment-library-typescript","last_synced_at":"2026-05-18T18:36:39.690Z","repository":{"id":43674493,"uuid":"458478035","full_name":"MieuxVoter/majority-judgment-library-typescript","owner":"MieuxVoter","description":"Resolve Majority Judgment Polls in Typescript using a fast and robust algorithm","archived":false,"fork":false,"pushed_at":"2022-03-23T20:19:13.000Z","size":437,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-03-08T01:18:43.743Z","etag":null,"topics":["library","majority-judgment","typescript","vote"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MieuxVoter.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-02-12T09:37:35.000Z","updated_at":"2022-07-14T10:25:57.000Z","dependencies_parsed_at":"2022-08-23T04:00:56.487Z","dependency_job_id":null,"html_url":"https://github.com/MieuxVoter/majority-judgment-library-typescript","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MieuxVoter%2Fmajority-judgment-library-typescript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MieuxVoter%2Fmajority-judgment-library-typescript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MieuxVoter%2Fmajority-judgment-library-typescript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MieuxVoter%2Fmajority-judgment-library-typescript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MieuxVoter","download_url":"https://codeload.github.com/MieuxVoter/majority-judgment-library-typescript/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244123624,"owners_count":20401627,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["library","majority-judgment","typescript","vote"],"created_at":"2025-03-17T22:53:45.983Z","updated_at":"2026-05-18T18:36:39.649Z","avatar_url":"https://github.com/MieuxVoter.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Majority Judgment for Typescript\n\n[![MIT](https://img.shields.io/github/license/MieuxVoter/majority-judgment-library-typescript?style=for-the-badge)](LICENSE)\n[![Release](https://img.shields.io/github/v/release/MieuxVoter/majority-judgment-library-typescript?include_prereleases\u0026style=for-the-badge)](https://github.com/MieuxVoter/majority-judgment-library-typescript/releases)\n[![Build Status](https://img.shields.io/github/workflow/status/MieuxVoter/majority-judgment-library-typescript/NPM%20publish%20CD%20workflow?style=for-the-badge)](https://github.com/MieuxVoter/majority-judgment-library-typescript/actions/workflows/cd.yml)\n[![Code Quality](https://img.shields.io/codefactor/grade/github/MieuxVoter/majority-judgment-library-typescript?style=for-the-badge)](https://www.codefactor.io/repository/github/mieuxvoter/majority-judgment-library-typescript)\n![LoC](https://img.shields.io/tokei/lines/github/MieuxVoter/majority-judgment-library-typescript?style=for-the-badge)\n[![Discord Chat](https://img.shields.io/discord/705322981102190593.svg?style=for-the-badge)](https://discord.gg/rAAQG9S)\n\nThis typescript package helps to resolve polls using [Majority Judgment](https://fr.wikipedia.org/wiki/Jugement_majoritaire).\n\n## Features\n\n-   Efficient Majority Judgment algorithm, scales well to billions of participants\n-   Configure whether to favor _adhesion_ or _contestation_ (default)\n-   Balance proposal tallies using a static default grade or the median grade\n-   Room for Central Judgment and Usual Judgment\n-   Unit-tested (run `npm run converage`)\n\n## Install\n\n`npm install scalable-majority-judgment`\n\n## Get started\n\n### Majority judgment from ballots\n\n```typescript\nimport {\n    TallyCollector,\n    MajorityJudgmentDeliberator,\n    IDeliberator,\n    IResult,\n} from \"majority-judgment\";\n\nconst proposalAmount: number = 5;\nconst mentionAmount: number = 7;\nconst voterAmount: number = 1000;\nconst tally: TallyCollector = new TallyCollector(proposalAmount, mentionAmount);\nfillTallyCollectorWithRandomVote(tally, voterAmount);\n\nconst deliberator: IDeliberator = new MajorityJudgmentDeliberator();\nconst result: IResult = deliberator.deliberate(tally);\n\nfor (let i: number = 0; i \u003c proposalAmount; i++)\n    console.log(\n        `Proposal at index ${i} obtains the rank ${result.proposalResults[i].rank} with the majority mention at index ${result.proposalResults[i].analysis.medianMentionIndex}`\n    );\n\nfunction fillTallyCollectorWithRandomVote(tally: TallyCollector, voterAmount: number): void {\n    const applyRandomVoteForEachProposal = () =\u003e {\n        let randomProposalIndex: number;\n        let randomMentionIndex: number;\n\n        for (let i: number = 0; i \u003c proposalAmount; i++) {\n            randomProposalIndex = Math.floor(Math.random() * proposalAmount);\n            randomMentionIndex = Math.floor(Math.random() * mentionAmount);\n            tally.collect(randomProposalIndex, randomMentionIndex);\n        }\n    };\n\n    for (let i: number = 0; i \u003c voterAmount; i++) applyRandomVoteForEachProposal();\n}\n```\n\n### Known datas\n\n```typescript\nimport {\n    MajorityJudgmentDeliberator,\n    IDeliberator,\n    IResult,\n    ITally,\n    Tally,\n    Proposal,\n} from \"majority-judgment\";\n\nconst meritProfileSample: bigint[] = [4n, 0n, 2n, 1n];\n// index 0 = worst mention, 4 vote\n// max index (3) = best mention, 1 vote\n\nconst tally: ITally = new Tally([\n    new Proposal(meritProfileSample),\n    new Proposal([2n, 1n, 0n, 4n]),\n    new Proposal([3n, 2n, 1n, 1n]),\n]);\n\nconst deliberator: IDeliberator = new MajorityJudgmentDeliberator();\nconst result: IResult = deliberator.deliberate(tally);\nconst proposalAmount: number = tally.proposalAmount;\n\nfor (let i: number = 0; i \u003c proposalAmount; i++)\n    console.log(\n        `Proposal at index ${i} obtains the rank ${result.proposalResults[i].rank} with the majority mention at index ${result.proposalResults[i].analysis.medianMentionIndex}`\n    );\n\n// Note: the sum vote in proposal must be equal. If not, the deliberator will throw an error.\n```\n\n### Majority judgment where voters did not vote for every proposal\n\n```typescript\nimport { ITally, Proposal, NormalizedTally } from \"majority-judgment\";\n\n// If the sum vote in proposal are not equal. You can use NormalizedTally.\nconst tally: ITally = new NormalizedTally([\n    new Proposal([4n, 0n, 2n, 10n]),\n    new Proposal([20n, 10n, 0n, 4n]),\n    new Proposal([3n, 200n, 100n, 1n]),\n]);\n\n// (...) Same logic\n```\n\n## Contribute\n\nUsual git flow: clone, tinker, request a merge.\n\n## Authors\n\nThis package was made by [MieuxVoter](https://mieuxvoter.fr/), a French nonprofit.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmieuxvoter%2Fmajority-judgment-library-typescript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmieuxvoter%2Fmajority-judgment-library-typescript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmieuxvoter%2Fmajority-judgment-library-typescript/lists"}