{"id":26413002,"url":"https://github.com/mieuxvoter/majority-judgment-library-java","last_synced_at":"2026-04-25T08:05:00.929Z","repository":{"id":50248728,"uuid":"361344966","full_name":"MieuxVoter/majority-judgment-library-java","owner":"MieuxVoter","description":"Deliberate using Majority Judgment in Java, with a score-based algorithm for performance.","archived":false,"fork":false,"pushed_at":"2025-03-10T17:43:22.000Z","size":162,"stargazers_count":2,"open_issues_count":4,"forks_count":3,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-10T18:45:59.786Z","etag":null,"topics":["java","majority-judgment","voting"],"latest_commit_sha":null,"homepage":"https://mieuxvoter.fr","language":"Java","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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-25T06:06:06.000Z","updated_at":"2025-03-10T17:42:38.000Z","dependencies_parsed_at":"2025-02-16T22:18:45.371Z","dependency_job_id":"1d5f13b7-4dff-41b3-b4c7-805b4ef882a5","html_url":"https://github.com/MieuxVoter/majority-judgment-library-java","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MieuxVoter%2Fmajority-judgment-library-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MieuxVoter%2Fmajority-judgment-library-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MieuxVoter%2Fmajority-judgment-library-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MieuxVoter%2Fmajority-judgment-library-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MieuxVoter","download_url":"https://codeload.github.com/MieuxVoter/majority-judgment-library-java/tar.gz/refs/heads/master","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":["java","majority-judgment","voting"],"created_at":"2025-03-17T22:53:45.816Z","updated_at":"2026-04-25T08:05:00.910Z","avatar_url":"https://github.com/MieuxVoter.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Majority Judgment Library for Java\n\n[![MIT](https://img.shields.io/github/license/MieuxVoter/majority-judgment-library-java?style=for-the-badge)](./LICENSE)\n[![Release](https://img.shields.io/github/v/release/MieuxVoter/majority-judgment-library-java?sort=semver\u0026style=for-the-badge)](https://github.com/MieuxVoter/majority-judgment-library-java/releases)\n[![Build Status](https://img.shields.io/github/actions/workflow/status/MieuxVoter/majority-judgment-library-java/maven.yml?style=for-the-badge)](https://github.com/MieuxVoter/majority-judgment-library-java/actions)\n[![Code Quality](https://img.shields.io/codefactor/grade/github/MieuxVoter/majority-judgment-library-java?style=for-the-badge)](https://www.codefactor.io/repository/github/mieuxvoter/majority-judgment-library-java)\n\u003c!--\n[![Tests](https://img.shields.io/sonar/tests/fr.mieuxvoter.mj%3Amajority-judgment?server=https%3A%2F%2Fsonarcloud.io\u0026compact_message\u0026style=for-the-badge)](https://github.com/MieuxVoter/majority-judgment-library-java/tree/master/src/test/java/fr/mieuxvoter/mj)\n[![Coverage](https://img.shields.io/sonar/coverage/fr.mieuxvoter.mj%3Amajority-judgment?server=https%3A%2F%2Fsonarcloud.io\u0026style=for-the-badge)](https://sonarcloud.io/dashboard?id=MieuxVoter_majority-judgment-library-java)\n[![Violations](https://img.shields.io/sonar/violations/fr.mieuxvoter.mj%3Amajority-judgment?server=https%3A%2F%2Fsonarcloud.io\u0026style=for-the-badge)](https://sonarcloud.io/project/issues?issueStatuses=OPEN%2CCONFIRMED\u0026id=MieuxVoter_majority-judgment-library-java)\n[![Quality Gate](https://img.shields.io/sonar/quality_gate/fr.mieuxvoter.mj%3Amajority-judgment?server=https%3A%2F%2Fsonarcloud.io\u0026style=for-the-badge)](https://sonarcloud.io/dashboard?id=MieuxVoter_majority-judgment-library-java)\n![Tech Debt](https://img.shields.io/sonar/tech_debt/fr.mieuxvoter.mj%3Amajority-judgment?server=https%3A%2F%2Fsonarcloud.io\u0026style=for-the-badge)\n--\u003e\n[![Join the Discord chat at https://discord.gg/rAAQG9S](https://img.shields.io/discord/705322981102190593.svg?style=for-the-badge)](https://discord.gg/rAAQG9S)\n\nTest-driven java library to help deliberate (rank proposals) using [Majority Judgment](https://mieuxvoter.fr/index.php/decouvrir/?lang=en).\n\nThe goal is to be **scalable**, **reliable**, fast and extensible.\nWe therefore use a _score-based algorithm_ and _no floating-point arithmetic_ whatsoever.\n\n\n## Features\n\n- Supports billions of participants\n- Supports thousands of proposals\n- Handles default grades (static or normalized)\n- No floating-point arithmetic\n- Room for other deliberation resolvers (central, usual)\n- Computes the merit of proposals (JM-Score and an approximation of Merit from Absolute Rank)\n\n\n## Example Usage\n\nCollect the **tallies** for each Proposal (aka. Candidate) by your own means,\nprovide them to the `MajorityJudgmentDeliberator`, and get back the **rank** of each Proposal.\n\nLet's say you have the following tally:\n\n|            | To Reject | Poor | Passable | Somewhat Good | Good | Very Good | Excellent |\n|------------|-----------|------|----------|---------------|------|-----------|-----------|\n| Proposal A |     4     |   5  |     2    |       1       |   3  |     1     |     2     |\n| Proposal B |     3     |   6  |     2    |       2       |   2  |     1     |     2     |\n|     …      |           |      |          |               |      |           |           |\n|            |           |      |          |               |      |           |           |\n\n\u003e A _Tally_ is the amount of judgments received per grade, by each proposal.\n\n``` java\nDeliberatorInterface mj = new MajorityJudgmentDeliberator();\nTallyInterface tally = new Tally(new ProposalTallyInterface[] {\n        // Amounts of judgments received for each grade, from \"worst\" grade to \"best\" grade\n        new ProposalTally(new Integer[]{4, 5, 2, 1, 3, 1, 2}),  // Proposal A\n        new ProposalTally(new Integer[]{3, 6, 2, 1, 3, 1, 2}),  // Proposal B\n        // …\n}, 18);\nResultInterface result = mj.deliberate(tally);\n\n// Each proposal result has a rank, and results are returned by input order\nassert(2 == result.getProposalResults().length);\nassert(2 == result.getProposalResults()[0].getRank());  // Proposal A\nassert(1 == result.getProposalResults()[1].getRank());  // Proposal B\n```\n\nGot more than 2³² judges?  Use a `Long[]` in a `ProposalTally`.\n\nGot even more than that ?  Use `BigInteger`s !\n\n\n### Using a static default grade\n\nWant to set a static default grade ?  Use a `StaticDefaultTally` instead of a `Tally`.\n\n```java\nInteger amountOfJudges = 18;\nInteger defaultGrade = 0;  // \"worst\" grade (usually \"to reject\")\nTallyInterface tally = new StaticDefaultTally(new ProposalTallyInterface[] {\n        // Amounts of judgments received of each grade, from \"worst\" grade to \"best\" grade\n        new ProposalTally(new Integer[]{4, 5, 2, 1, 3, 1, 2}),  // Proposal A\n        new ProposalTally(new Integer[]{3, 6, 2, 1, 3, 1, 2}),  // Proposal B\n        // …\n}, amountOfJudges, defaultGrade);\n```\n\n\n### Using normalized tallies\n\nIn some polls with a very high amount of proposals, where participants cannot be expected to judge every last one of them, it may make sense to normalize the tallies instead of using a default grade.\n\nTo that effect, use a `NormalizedTally` instead of a `Tally`.\n\n```java\nTallyInterface tally = new NormalizedTally(new ProposalTallyInterface[] {\n        // Amounts of judgments received of each grade, from \"worst\" grade to \"best\" grade\n        new ProposalTally(new Integer[]{4, 5, 2, 1, 3, 1, 2}),  // Proposal A\n        new ProposalTally(new Integer[]{3, 6, 2, 1, 3, 1, 2}),  // Proposal B\n        // …\n});\n```\n\n\u003e This normalization uses the Least Common Multiple, in order to skip floating-point arithmetic.\n\n\n### Collect a Tally from judgments\n\nIt's usually best to use structured queries (eg: in SQL) directly in your database to collect the tallies, since it scales better with high amounts of participants, but if you must, you can collect the tally directly from individual judgments, with a `CollectedTally`.\n\n```java\nInteger amountOfProposals = 2;\nInteger amountOfGrades = 4;\nDeliberatorInterface mj = new MajorityJudgmentDeliberator();\nCollectedTally tally = new CollectedTally(amountOfProposals, amountOfGrades);\n\nInteger firstProposal = 0;\nInteger secondProposal = 1;\nInteger gradeReject = 0;\nInteger gradePassable = 1;\nInteger gradeGood = 2;\nInteger gradeExcellent = 3;\n\n// Collect the judgments, one-by-one, with `collect()`\ntally.collect(firstProposal, gradeReject);\ntally.collect(firstProposal, gradeReject);\ntally.collect(firstProposal, gradePassable);\ntally.collect(firstProposal, gradePassable);\ntally.collect(firstProposal, gradePassable);\ntally.collect(firstProposal, gradeExcellent);\ntally.collect(firstProposal, gradeExcellent);\n\ntally.collect(secondProposal, gradeReject);\ntally.collect(secondProposal, gradeReject);\ntally.collect(secondProposal, gradeGood);\ntally.collect(secondProposal, gradeGood);\ntally.collect(secondProposal, gradeGood);\ntally.collect(secondProposal, gradeExcellent);\ntally.collect(secondProposal, gradeExcellent);\n\n// …\n\nResultInterface result = mj.deliberate(tally);\n```\n\n\n## Run the test-suite\n\nInstall [maven](https://maven.apache.org), and run:\n\n    mvn test -DtrimStackTrace=false\n\n\u003e Maven is available as a debian package: `apt install maven`\n\nYou can also use a runner in Eclipse.  (`CTRL+F11` to rerun)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmieuxvoter%2Fmajority-judgment-library-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmieuxvoter%2Fmajority-judgment-library-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmieuxvoter%2Fmajority-judgment-library-java/lists"}