Browse Source

refacto: Long → BigInteger

API BREAK
It's okay, we're still in 0.x
pull/4/head
Dominique Merle 1 year ago
parent
commit
13ae5615ab
  1. 17
      src/main/java/fr/mieuxvoter/mj/MajorityJudgmentDeliberator.java
  2. 30
      src/main/java/fr/mieuxvoter/mj/ProposalTally.java
  3. 112
      src/main/java/fr/mieuxvoter/mj/ProposalTallyAnalysis.java
  4. 2
      src/main/java/fr/mieuxvoter/mj/ProposalTallyInterface.java
  5. 17
      src/main/java/fr/mieuxvoter/mj/Tally.java
  6. 12
      src/main/java/fr/mieuxvoter/mj/TallyInterface.java
  7. 14
      src/main/java/fr/mieuxvoter/mj/TallyWithDefaultGrade.java

17
src/main/java/fr/mieuxvoter/mj/MajorityJudgmentDeliberator.java

@ -1,5 +1,6 @@
package fr.mieuxvoter.mj;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Comparator;
@ -24,7 +25,7 @@ public class MajorityJudgmentDeliberator implements DeliberatorInterface {
public ResultInterface deliberate(TallyInterface tally) {
ProposalTallyInterface[] tallies = tally.getProposalsTallies();
Long amountOfJudges = tally.getAmountOfJudges();
BigInteger amountOfJudges = tally.getAmountOfJudges();
Integer amountOfProposals = tally.getAmountOfProposals();
Result result = new Result();
@ -69,13 +70,13 @@ public class MajorityJudgmentDeliberator implements DeliberatorInterface {
return result;
}
public String computeScore(ProposalTallyInterface tally, Long amountOfJudges) {
public String computeScore(ProposalTallyInterface tally, BigInteger amountOfJudges) {
return computeScore(tally, amountOfJudges, true, false);
}
public String computeScore(
ProposalTallyInterface tally,
Long amountOfJudges,
BigInteger amountOfJudges,
Boolean favorContestation,
Boolean onlyNumbers
) {
@ -99,15 +100,19 @@ public class MajorityJudgmentDeliberator implements DeliberatorInterface {
"%0"+digitsForGrade+"d",
analysis.getMedianGrade()
);
if ( ! onlyNumbers) {
score += "_";
}
score += String.format(
"%0"+digitsForGroup+"d",
amountOfJudges + analysis.getSecondMedianGroupSize() * analysis.getSecondMedianGroupSign()
// amountOfJudges + secondMedianGroupSize * secondMedianGroupSign
amountOfJudges.add(
analysis.getSecondMedianGroupSize().multiply(
BigInteger.valueOf(analysis.getSecondMedianGroupSign())
)
)
);
currentTally.moveJudgments(analysis.getMedianGrade(), analysis.getSecondMedianGrade());

30
src/main/java/fr/mieuxvoter/mj/ProposalTally.java

@ -5,30 +5,39 @@ import java.util.Arrays;
public class ProposalTally implements ProposalTallyInterface {
protected Long[] tally;
protected BigInteger[] tally;
// Should we allow this as well?
//public ProposalTally() {}
public ProposalTally(Integer[] tally) {
int tallyLength = tally.length;
Long[] doublesTally = new Long[tallyLength];
BigInteger[] bigTally = new BigInteger[tallyLength];
for (int i = 0 ; i < tallyLength ; i++) {
doublesTally[i] = Long.valueOf(tally[i]);
bigTally[i] = BigInteger.valueOf(tally[i]);
}
setTally(doublesTally);
setTally(bigTally);
}
public ProposalTally(Long[] tally) {
int tallyLength = tally.length;
BigInteger[] bigTally = new BigInteger[tallyLength];
for (int i = 0 ; i < tallyLength ; i++) {
bigTally[i] = BigInteger.valueOf(tally[i]);
}
setTally(bigTally);
}
public ProposalTally(BigInteger[] tally) {
setTally(tally);
}
public void setTally(Long[] tally) {
public void setTally(BigInteger[] tally) {
this.tally = tally;
}
@Override
public Long[] getTally() {
public BigInteger[] getTally() {
return this.tally;
}
@ -39,16 +48,17 @@ public class ProposalTally implements ProposalTallyInterface {
@Override
public void moveJudgments(Integer fromGrade, Integer intoGrade) {
this.tally[intoGrade] += this.tally[fromGrade];
this.tally[fromGrade] = 0L;
// this.tally[intoGrade] += this.tally[fromGrade];
this.tally[intoGrade] = this.tally[intoGrade].add(this.tally[fromGrade]);
this.tally[fromGrade] = BigInteger.ZERO;
}
@Override
public BigInteger getAmountOfJudgments() {
BigInteger sum = BigInteger.valueOf(0);
BigInteger sum = BigInteger.ZERO;
int tallyLength = this.tally.length;
for (int i = 0 ; i < tallyLength ; i++) {
sum = sum.add(BigInteger.valueOf(this.tally[i]));
sum = sum.add(this.tally[i]);
}
return sum;
}

112
src/main/java/fr/mieuxvoter/mj/ProposalTallyAnalysis.java

@ -1,35 +1,42 @@
package fr.mieuxvoter.mj;
import java.math.BigInteger;
/**
* Collect useful data on a proposal tally.
* Does NOT compute the rank, but provides all we need
* Does NOT compute the rank, but provides all we need.
*
* This uses BigInteger because in a normalization scenario we use the
* smallest common multiple of the amounts of judges of proposals.
* It makes the code harder to read and understand, but it allows us
* to bypass the floating-point nightmare of the normalization of merit profiles,
* which is one way to handle default grades on some polls.
*/
public class ProposalTallyAnalysis {
protected ProposalTallyInterface tally;
protected Long totalSize = 0L; // amount of judges
protected BigInteger totalSize = BigInteger.ZERO; // amount of judges
protected Integer medianGrade = 0;
protected Long medianGroupSize = 0L; // amount of judges in the median group
protected BigInteger medianGroupSize = BigInteger.ZERO; // amount of judges in the median group
protected Integer contestationGrade = 0; // "best" grade of the contestation group
protected Long contestationGroupSize = 0L; // of lower grades than median
protected BigInteger contestationGroupSize = BigInteger.ZERO; // of lower grades than median
protected Integer adhesionGrade = 0; // "worst" grade of the adhesion group
protected Long adhesionGroupSize = 0L; // of higher grades than median
protected BigInteger adhesionGroupSize = BigInteger.ZERO; // of higher grades than median
protected Integer secondMedianGrade = 0; // grade of the biggest group out of the median
protected Long secondMedianGroupSize = 0L; // either contestation or adhesion
protected BigInteger secondMedianGroupSize = BigInteger.ZERO; // either contestation or adhesion
protected Integer secondMedianGroupSign = 0; // -1 for contestation, +1 for adhesion, 0 for empty group size
public ProposalTallyAnalysis() {}
public ProposalTallyAnalysis(ProposalTallyInterface tally) {
@ -42,56 +49,58 @@ public class ProposalTallyAnalysis {
public void reanalyze(ProposalTallyInterface tally, Boolean favorContestation) {
this.tally = tally;
this.totalSize = 0L;
this.totalSize = BigInteger.ZERO;
this.medianGrade = 0;
this.medianGroupSize = 0L;
this.medianGroupSize = BigInteger.ZERO;
this.contestationGrade = 0;
this.contestationGroupSize = 0L;
this.contestationGroupSize = BigInteger.ZERO;
this.adhesionGrade = 0;
this.adhesionGroupSize = 0L;
this.adhesionGroupSize = BigInteger.ZERO;
this.secondMedianGrade = 0;
this.secondMedianGroupSize = 0L;
this.secondMedianGroupSize = BigInteger.ZERO;
this.secondMedianGroupSign = 0;
Long[] gradesTallies = this.tally.getTally();
BigInteger[] gradesTallies = this.tally.getTally();
int amountOfGrades = gradesTallies.length;
for (int grade = 0; grade < amountOfGrades; grade++) {
Long gradeTally = gradesTallies[grade];
assert(0 <= gradeTally); // Negative tallies are not allowed.
this.totalSize += gradeTally;
BigInteger gradeTally = gradesTallies[grade];
//assert(0 <= gradeTally); // Negative tallies are not allowed.
this.totalSize = this.totalSize.add(gradeTally);
}
Integer medianOffset = 1;
if ( ! favorContestation) {
medianOffset = 2;
}
Long medianCursor = (long) Math.floor((this.totalSize + medianOffset) / 2.0);
BigInteger medianCursor = this.totalSize.add(BigInteger.valueOf(medianOffset)).divide(BigInteger.TWO);
// Long medianCursor = (long) Math.floor((this.totalSize + medianOffset) / 2.0);
Long tallyBeforeCursor = 0L;
Long tallyCursor = 0L;
BigInteger tallyBeforeCursor = BigInteger.ZERO;
BigInteger tallyCursor = BigInteger.ZERO;
Boolean foundMedian = false;
Integer contestationGrade = 0;
Integer adhesionGrade = 0;
for (int grade = 0; grade < amountOfGrades; grade++) {
Long gradeTally = gradesTallies[grade];
BigInteger gradeTally = gradesTallies[grade];
tallyBeforeCursor = tallyCursor;
tallyCursor += gradeTally;
tallyCursor = tallyCursor.add(gradeTally);
if ( ! foundMedian) {
if (tallyCursor >= medianCursor) {
if (-1 < tallyCursor.compareTo(medianCursor)) { // tallyCursor >= medianCursor
foundMedian = true;
this.medianGrade = grade;
this.contestationGroupSize = tallyBeforeCursor;
this.medianGroupSize = gradeTally;
this.adhesionGroupSize = this.totalSize - this.contestationGroupSize - this.medianGroupSize;
// this.adhesionGroupSize = this.totalSize - this.contestationGroupSize - this.medianGroupSize;
this.adhesionGroupSize = this.totalSize.subtract(this.contestationGroupSize).subtract(this.medianGroupSize);
} else {
if (0 < gradeTally) {
if (1 == gradeTally.compareTo(BigInteger.ZERO)) { // 0 < gradeTally
contestationGrade = grade;
}
}
} else {
if (0 < gradeTally && 0 == adhesionGrade) {
if (1 == gradeTally.compareTo(BigInteger.ZERO) && 0 == adhesionGrade) {
adhesionGrade = grade;
}
}
@ -99,12 +108,15 @@ public class ProposalTallyAnalysis {
this.contestationGrade = contestationGrade;
this.adhesionGrade = adhesionGrade;
this.secondMedianGroupSize = Math.max(this.contestationGroupSize, this.adhesionGroupSize);
// this.secondMedianGroupSize = Math.max(this.contestationGroupSize, this.adhesionGroupSize);
this.secondMedianGroupSize = this.contestationGroupSize.max(this.adhesionGroupSize);
this.secondMedianGroupSign = 0;
if (this.contestationGroupSize < this.adhesionGroupSize) {
// if (this.contestationGroupSize < this.adhesionGroupSize) {
if (1 == this.adhesionGroupSize.compareTo(this.contestationGroupSize)) {
this.secondMedianGrade = this.adhesionGrade;
this.secondMedianGroupSign = 1;
} else if (this.contestationGroupSize > this.adhesionGroupSize) {
// } else if (this.contestationGroupSize > this.adhesionGroupSize) {
} else if (1 == this.contestationGroupSize.compareTo(this.adhesionGroupSize)) {
this.secondMedianGrade = this.contestationGrade;
this.secondMedianGroupSign = -1;
} else {
@ -116,16 +128,16 @@ public class ProposalTallyAnalysis {
this.secondMedianGroupSign = 1;
}
}
if (0 == this.secondMedianGroupSize) {
if (0 == this.secondMedianGroupSize.compareTo(BigInteger.ZERO)) {
this.secondMedianGroupSign = 0;
}
}
public Long getTotalSize() {
public BigInteger getTotalSize() {
return totalSize;
}
public void setTotalSize(Long totalSize) {
public void setTotalSize(BigInteger totalSize) {
this.totalSize = totalSize;
}
@ -136,12 +148,12 @@ public class ProposalTallyAnalysis {
public void setMedianGrade(Integer medianGrade) {
this.medianGrade = medianGrade;
}
public Long getMedianGroupSize() {
public BigInteger getMedianGroupSize() {
return medianGroupSize;
}
public void setMedianGroupSize(Long medianGroupSize) {
public void setMedianGroupSize(BigInteger medianGroupSize) {
this.medianGroupSize = medianGroupSize;
}
@ -153,11 +165,11 @@ public class ProposalTallyAnalysis {
this.contestationGrade = contestationGrade;
}
public Long getContestationGroupSize() {
public BigInteger getContestationGroupSize() {
return contestationGroupSize;
}
public void setContestationGroupSize(Long contestationGroupSize) {
public void setContestationGroupSize(BigInteger contestationGroupSize) {
this.contestationGroupSize = contestationGroupSize;
}
@ -168,15 +180,15 @@ public class ProposalTallyAnalysis {
public void setAdhesionGrade(Integer adhesionGrade) {
this.adhesionGrade = adhesionGrade;
}
public Long getAdhesionGroupSize() {
public BigInteger getAdhesionGroupSize() {
return adhesionGroupSize;
}
public void setAdhesionGroupSize(Long adhesionGroupSize) {
public void setAdhesionGroupSize(BigInteger adhesionGroupSize) {
this.adhesionGroupSize = adhesionGroupSize;
}
public Integer getSecondMedianGrade() {
return secondMedianGrade;
}
@ -185,11 +197,11 @@ public class ProposalTallyAnalysis {
this.secondMedianGrade = secondMedianGrade;
}
public Long getSecondMedianGroupSize() {
public BigInteger getSecondMedianGroupSize() {
return secondMedianGroupSize;
}
public void setSecondMedianGroupSize(Long secondMedianGroupSize) {
public void setSecondMedianGroupSize(BigInteger secondMedianGroupSize) {
this.secondMedianGroupSize = secondMedianGroupSize;
}

2
src/main/java/fr/mieuxvoter/mj/ProposalTallyInterface.java

@ -9,7 +9,7 @@ public interface ProposalTallyInterface {
* the amount of judgments received for each Grade by the Proposal,
* from "worst" ("most conservative") Grade to "best" Grade.
*/
public Long[] getTally();
public BigInteger[] getTally();
/**
* Should be the sum of getTally()

17
src/main/java/fr/mieuxvoter/mj/Tally.java

@ -1,19 +1,26 @@
package fr.mieuxvoter.mj;
import java.math.BigInteger;
public class Tally implements TallyInterface {
protected ProposalTallyInterface[] proposalsTallies;
protected Long amountOfJudges = 0L;
protected BigInteger amountOfJudges = BigInteger.ZERO;
public Tally(ProposalTallyInterface[] proposalsTallies, BigInteger amountOfJudges) {
setProposalsTallies(proposalsTallies);
setAmountOfJudges(amountOfJudges);
}
public Tally(ProposalTallyInterface[] proposalsTallies, Long amountOfJudges) {
setProposalsTallies(proposalsTallies);
setAmountOfJudges(amountOfJudges);
setAmountOfJudges(BigInteger.valueOf(amountOfJudges));
}
public Tally(ProposalTallyInterface[] proposalsTallies, Integer amountOfJudges) {
setProposalsTallies(proposalsTallies);
setAmountOfJudges(Long.valueOf(amountOfJudges));
setAmountOfJudges(BigInteger.valueOf(amountOfJudges));
}
public ProposalTallyInterface[] getProposalsTallies() {
@ -28,11 +35,11 @@ public class Tally implements TallyInterface {
return proposalsTallies.length;
}
public Long getAmountOfJudges() {
public BigInteger getAmountOfJudges() {
return amountOfJudges;
}
public void setAmountOfJudges(Long amountOfJudges) {
public void setAmountOfJudges(BigInteger amountOfJudges) {
this.amountOfJudges = amountOfJudges;
}

12
src/main/java/fr/mieuxvoter/mj/TallyInterface.java

@ -1,11 +1,13 @@
package fr.mieuxvoter.mj;
import java.math.BigInteger;
public interface TallyInterface {
public ProposalTallyInterface[] getProposalsTallies();
public Long getAmountOfJudges();
public BigInteger getAmountOfJudges();
public Integer getAmountOfProposals();
}

14
src/main/java/fr/mieuxvoter/mj/TallyWithDefaultGrade.java

@ -6,7 +6,7 @@ public class TallyWithDefaultGrade extends Tally implements TallyInterface {
protected Integer defaultGrade = 0;
public TallyWithDefaultGrade(ProposalTallyInterface[] proposalsTallies, Integer amountOfJudges, Integer defaultGrade) {
public TallyWithDefaultGrade(ProposalTallyInterface[] proposalsTallies, BigInteger amountOfJudges, Integer defaultGrade) {
super(proposalsTallies, amountOfJudges);
this.defaultGrade = defaultGrade;
fillWithDefaultGrade();
@ -18,16 +18,22 @@ public class TallyWithDefaultGrade extends Tally implements TallyInterface {
fillWithDefaultGrade();
}
public TallyWithDefaultGrade(ProposalTallyInterface[] proposalsTallies, Integer amountOfJudges, Integer defaultGrade) {
super(proposalsTallies, amountOfJudges);
this.defaultGrade = defaultGrade;
fillWithDefaultGrade();
}
protected void fillWithDefaultGrade() {
int amountOfProposals = getAmountOfProposals();
for (int i = 0 ; i < amountOfProposals ; i++) {
ProposalTallyInterface proposal = getProposalsTallies()[i];
BigInteger amountOfJudgments = proposal.getAmountOfJudgments();
BigInteger missingAmount = BigInteger.valueOf(this.amountOfJudges).subtract(amountOfJudgments);
BigInteger missingAmount = this.amountOfJudges.subtract(amountOfJudgments);
int missingSign = missingAmount.compareTo(BigInteger.ZERO);
assert(0 <= missingSign); // More judgments than judges!
assert(0 <= missingSign); // ERROR: More judgments than judges!
if (0 < missingSign) {
proposal.getTally()[this.defaultGrade] = proposal.getTally()[this.defaultGrade] + missingAmount.longValue();
proposal.getTally()[this.defaultGrade] = proposal.getTally()[this.defaultGrade].add(missingAmount);
}
}
}

Loading…
Cancel
Save