You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
majority-judgment-library-java/src/main/java/fr/mieuxvoter/mj/ProposalTallyAnalysis.java

205 lines
5.4 KiB

package fr.mieuxvoter.mj;
/**
* Collect useful data on a proposal tally.
* Does NOT compute the rank, but provides all we need
*/
public class ProposalTallyAnalysis {
protected ProposalTallyInterface tally;
protected Long totalSize = 0L; // amount of judges
protected Integer medianGrade = 0;
protected Long medianGroupSize = 0L; // 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 Integer adhesionGrade = 0; // "worst" grade of the adhesion group
protected Long adhesionGroupSize = 0L; // 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 Integer secondMedianGroupSign = 0; // -1 for contestation, +1 for adhesion, 0 for empty group size
public ProposalTallyAnalysis() {}
public ProposalTallyAnalysis(ProposalTallyInterface tally) {
reanalyze(tally);
}
public void reanalyze(ProposalTallyInterface tally) {
reanalyze(tally, true);
}
public void reanalyze(ProposalTallyInterface tally, Boolean favorContestation) {
this.tally = tally;
this.totalSize = 0L;
this.medianGrade = 0;
this.medianGroupSize = 0L;
this.contestationGrade = 0;
this.contestationGroupSize = 0L;
this.adhesionGrade = 0;
this.adhesionGroupSize = 0L;
this.secondMedianGrade = 0;
this.secondMedianGroupSize = 0L;
this.secondMedianGroupSign = 0;
Long[] 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;
}
Integer medianOffset = 1;
if ( ! favorContestation) {
medianOffset = 2;
}
Long medianCursor = (long) Math.floor((this.totalSize + medianOffset) / 2.0);
Long tallyBeforeCursor = 0L;
Long tallyCursor = 0L;
Boolean foundMedian = false;
Integer contestationGrade = 0;
Integer adhesionGrade = 0;
for (int grade = 0; grade < amountOfGrades; grade++) {
Long gradeTally = gradesTallies[grade];
tallyBeforeCursor = tallyCursor;
tallyCursor += gradeTally;
if ( ! foundMedian) {
if (tallyCursor >= medianCursor) {
foundMedian = true;
this.medianGrade = grade;
this.contestationGroupSize = tallyBeforeCursor;
this.medianGroupSize = gradeTally;
this.adhesionGroupSize = this.totalSize - this.contestationGroupSize - this.medianGroupSize;
} else {
if (0 < gradeTally) {
contestationGrade = grade;
}
}
} else {
if (0 < gradeTally && 0 == adhesionGrade) {
adhesionGrade = grade;
}
}
}
this.contestationGrade = contestationGrade;
this.adhesionGrade = adhesionGrade;
this.secondMedianGroupSize = Math.max(this.contestationGroupSize, this.adhesionGroupSize);
this.secondMedianGroupSign = 0;
if (this.contestationGroupSize < this.adhesionGroupSize) {
this.secondMedianGrade = this.adhesionGrade;
this.secondMedianGroupSign = 1;
} else if (this.contestationGroupSize > this.adhesionGroupSize) {
this.secondMedianGrade = this.contestationGrade;
this.secondMedianGroupSign = -1;
} else {
if (favorContestation) {
this.secondMedianGrade = this.contestationGrade;
this.secondMedianGroupSign = -1;
} else {
this.secondMedianGrade = this.adhesionGrade;
this.secondMedianGroupSign = 1;
}
}
if (0 == this.secondMedianGroupSize) {
this.secondMedianGroupSign = 0;
}
}
public Long getTotalSize() {
return totalSize;
}
public void setTotalSize(Long totalSize) {
this.totalSize = totalSize;
}
public Integer getMedianGrade() {
return medianGrade;
}
public void setMedianGrade(Integer medianGrade) {
this.medianGrade = medianGrade;
}
public Long getMedianGroupSize() {
return medianGroupSize;
}
public void setMedianGroupSize(Long medianGroupSize) {
this.medianGroupSize = medianGroupSize;
}
public Integer getContestationGrade() {
return contestationGrade;
}
public void setContestationGrade(Integer contestationGrade) {
this.contestationGrade = contestationGrade;
}
public Long getContestationGroupSize() {
return contestationGroupSize;
}
public void setContestationGroupSize(Long contestationGroupSize) {
this.contestationGroupSize = contestationGroupSize;
}
public Integer getAdhesionGrade() {
return adhesionGrade;
}
public void setAdhesionGrade(Integer adhesionGrade) {
this.adhesionGrade = adhesionGrade;
}
public Long getAdhesionGroupSize() {
return adhesionGroupSize;
}
public void setAdhesionGroupSize(Long adhesionGroupSize) {
this.adhesionGroupSize = adhesionGroupSize;
}
public Integer getSecondMedianGrade() {
return secondMedianGrade;
}
public void setSecondMedianGrade(Integer secondMedianGrade) {
this.secondMedianGrade = secondMedianGrade;
}
public Long getSecondMedianGroupSize() {
return secondMedianGroupSize;
}
public void setSecondMedianGroupSize(Long secondMedianGroupSize) {
this.secondMedianGroupSize = secondMedianGroupSize;
}
public Integer getSecondMedianGroupSign() {
return secondMedianGroupSign;
}
public void setSecondMedianGroupSign(Integer sign) {
this.secondMedianGroupSign = sign;
}
}