Result PDF for Voting
- Add result PDF for Motion and Assignments - Add "getPercentBase" for Assignment
This commit is contained in:
parent
6044c63c28
commit
93dc78c7d6
@ -1,3 +1,4 @@
|
||||
import { CalculablePollKey } from 'app/site/polls/services/poll.service';
|
||||
import { AssignmentOption } from './assignment-option';
|
||||
import { BasePoll } from '../poll/base-poll';
|
||||
|
||||
@ -23,6 +24,16 @@ export class AssignmentPoll extends BasePoll<AssignmentPoll, AssignmentOption> {
|
||||
public global_abstain: boolean;
|
||||
public description: string;
|
||||
|
||||
public get pollmethodFields(): CalculablePollKey[] {
|
||||
if (this.pollmethod === AssignmentPollMethods.YN) {
|
||||
return ['yes', 'no'];
|
||||
} else if (this.pollmethod === AssignmentPollMethods.YNA) {
|
||||
return ['yes', 'no', 'abstain'];
|
||||
} else if (this.pollmethod === AssignmentPollMethods.Votes) {
|
||||
return ['yes'];
|
||||
}
|
||||
}
|
||||
|
||||
public constructor(input?: any) {
|
||||
super(AssignmentPoll.COLLECTIONSTRING, input);
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { CalculablePollKey } from 'app/site/polls/services/poll.service';
|
||||
import { BasePoll } from '../poll/base-poll';
|
||||
import { MotionOption } from './motion-option';
|
||||
|
||||
@ -16,6 +17,15 @@ export class MotionPoll extends BasePoll<MotionPoll, MotionOption> {
|
||||
public motion_id: number;
|
||||
public pollmethod: MotionPollMethods;
|
||||
|
||||
public get pollmethodFields(): CalculablePollKey[] {
|
||||
const ynField: CalculablePollKey[] = ['yes', 'no'];
|
||||
if (this.pollmethod === MotionPollMethods.YN) {
|
||||
return ynField;
|
||||
} else if (this.pollmethod === MotionPollMethods.YNA) {
|
||||
return ynField.concat(['abstain']);
|
||||
}
|
||||
}
|
||||
|
||||
public constructor(input?: any) {
|
||||
super(MotionPoll.COLLECTIONSTRING, input);
|
||||
}
|
||||
|
@ -24,7 +24,6 @@
|
||||
<div *ngIf="assignment">
|
||||
<!-- PDF -->
|
||||
<button mat-menu-item (click)="onDownloadPdf()">
|
||||
<!-- TODO: results or description. Results if published -->
|
||||
<mat-icon>picture_as_pdf</mat-icon>
|
||||
<span translate>PDF</span>
|
||||
</button>
|
||||
|
@ -2,7 +2,7 @@ import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
import { ChartData } from 'app/shared/components/charts/charts.component';
|
||||
import { AssignmentPoll, AssignmentPollMethods } from 'app/shared/models/assignments/assignment-poll';
|
||||
import { PollColor, PollState } from 'app/shared/models/poll/base-poll';
|
||||
import { PercentBase, PollColor, PollState } from 'app/shared/models/poll/base-poll';
|
||||
import { BaseViewModel } from 'app/site/base/base-view-model';
|
||||
import { ProjectorElementBuildDeskriptor } from 'app/site/base/projectable';
|
||||
import { PollData, ViewBasePoll } from 'app/site/polls/models/view-base-poll';
|
||||
@ -80,7 +80,8 @@ export class ViewAssignmentPoll extends ViewBasePoll<AssignmentPoll> implements
|
||||
yes: candidate.yes,
|
||||
no: candidate.no,
|
||||
abstain: candidate.abstain,
|
||||
user: candidate.user.full_name
|
||||
user: candidate.user.full_name,
|
||||
showPercent: true
|
||||
}))
|
||||
.sort((a, b) => b.yes - a.yes);
|
||||
|
||||
@ -97,8 +98,41 @@ export class ViewAssignmentPoll extends ViewBasePoll<AssignmentPoll> implements
|
||||
return super.getNextStates();
|
||||
}
|
||||
|
||||
private sumOptionsYN(): number {
|
||||
return this.options.reduce((o, n) => {
|
||||
o += n.yes > 0 ? n.yes : 0;
|
||||
o += n.no > 0 ? n.no : 0;
|
||||
return o;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
private sumOptionsYNA(): number {
|
||||
return this.options.reduce((o, n) => {
|
||||
o += n.abstain > 0 ? n.abstain : 0;
|
||||
return o;
|
||||
}, this.sumOptionsYN());
|
||||
}
|
||||
|
||||
public getPercentBase(): number {
|
||||
return 0;
|
||||
const base: PercentBase = this.poll.onehundred_percent_base;
|
||||
let totalByBase: number;
|
||||
switch (base) {
|
||||
case PercentBase.YN:
|
||||
totalByBase = this.sumOptionsYN();
|
||||
break;
|
||||
case PercentBase.YNA:
|
||||
totalByBase = this.sumOptionsYNA();
|
||||
break;
|
||||
case PercentBase.Valid:
|
||||
totalByBase = this.poll.votesvalid;
|
||||
break;
|
||||
case PercentBase.Cast:
|
||||
totalByBase = this.poll.votescast;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return totalByBase;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,12 @@ import { Injectable } from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import { HtmlToPdfService } from 'app/core/pdf-services/html-to-pdf.service';
|
||||
import { ParsePollNumberPipe } from 'app/shared/pipes/parse-poll-number.pipe';
|
||||
import { PollKeyVerbosePipe } from 'app/shared/pipes/poll-key-verbose.pipe';
|
||||
import { PollPercentBasePipe } from 'app/shared/pipes/poll-percent-base.pipe';
|
||||
import { PollData } from 'app/site/polls/models/view-base-poll';
|
||||
import { ViewAssignment } from '../models/view-assignment';
|
||||
import { ViewAssignmentPoll } from '../models/view-assignment-poll';
|
||||
|
||||
/**
|
||||
* Creates a PDF document from a single assignment
|
||||
@ -20,7 +25,13 @@ export class AssignmentPdfService {
|
||||
* @param pdfDocumentService PDF functions
|
||||
* @param htmlToPdfService Convert the assignment detail html text to pdf
|
||||
*/
|
||||
public constructor(private translate: TranslateService, private htmlToPdfService: HtmlToPdfService) {}
|
||||
public constructor(
|
||||
private translate: TranslateService,
|
||||
private htmlToPdfService: HtmlToPdfService,
|
||||
private pollKeyVerbose: PollKeyVerbosePipe,
|
||||
private parsePollNumber: ParsePollNumberPipe,
|
||||
private pollPercentBase: PollPercentBasePipe
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Main function to control the pdf generation.
|
||||
@ -140,44 +151,20 @@ export class AssignmentPdfService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a candidate line in the results table
|
||||
*
|
||||
* @param candidateName The name of the candidate
|
||||
* @param pollOption the poll options (yes, no, maybe [...])
|
||||
* @returns a line in the table
|
||||
*/
|
||||
// TODO: type the result.
|
||||
/*private electedCandidateLine(candidateName: string, pollOption: ViewAssignmentOption): object {
|
||||
if (pollOption.is_elected) {
|
||||
this.showIsElected = true;
|
||||
return {
|
||||
text: candidateName + '*',
|
||||
bold: true
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
text: candidateName
|
||||
};
|
||||
}*
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Creates the poll result table for all published polls
|
||||
*
|
||||
* @param assignment the ViewAssignment to create the document for
|
||||
* @returns the table as pdfmake object
|
||||
*/
|
||||
// TODO: type the result
|
||||
private createPollResultTable(assignment: ViewAssignment): object {
|
||||
/*const resultBody = [];
|
||||
for (let pollIndex = 0; pollIndex < assignment.polls.length; pollIndex++) {
|
||||
const poll = assignment.polls[pollIndex];
|
||||
if (poll.published) {
|
||||
const resultBody = [];
|
||||
for (const poll of assignment.polls) {
|
||||
if (poll.isPublished) {
|
||||
const pollTableBody = [];
|
||||
|
||||
resultBody.push({
|
||||
text: `${this.translate.instant('Ballot')} ${pollIndex + 1}`,
|
||||
text: poll.title,
|
||||
bold: true,
|
||||
style: 'textItem',
|
||||
margin: [0, 15, 0, 0]
|
||||
@ -194,56 +181,22 @@ export class AssignmentPdfService {
|
||||
}
|
||||
]);
|
||||
|
||||
for (let optionIndex = 0; optionIndex < poll.options.length; optionIndex++) {
|
||||
const pollOption = poll.options[optionIndex];
|
||||
const tableData = poll.generateTableData();
|
||||
|
||||
const candidateName = pollOption.user.full_name;
|
||||
const votes = pollOption.votes; // 0 = yes, 1 = no, 2 = abstain0 = yes, 1 = no, 2 = abstain
|
||||
const tableLine = [];
|
||||
tableLine.push(this.electedCandidateLine(candidateName, pollOption));
|
||||
for (const pollResult of tableData) {
|
||||
const resultLine = this.getPollResult(pollResult, poll);
|
||||
|
||||
if (poll.pollmethod === 'votes') {
|
||||
tableLine.push({
|
||||
text: this.parseVoteValue(votes[0].value, votes[0].weight, poll, pollOption)
|
||||
});
|
||||
} else {
|
||||
const resultBlock = votes.map(vote =>
|
||||
this.parseVoteValue(vote.value, vote.weight, poll, pollOption)
|
||||
);
|
||||
|
||||
tableLine.push({
|
||||
text: resultBlock
|
||||
});
|
||||
}
|
||||
pollTableBody.push(tableLine);
|
||||
}
|
||||
|
||||
// push the result lines
|
||||
const summaryLine = this.pollService.getVoteOptionsByPoll(poll).map(key => {
|
||||
// TODO: Refractor into pollService to make this easier.
|
||||
// Return an object with untranslated lable: string, specialLabel: string and (opt) percent: number
|
||||
const conclusionLabel = this.translate.instant(this.pollService.getLabel(key));
|
||||
const specialLabel = this.translate.instant(this.pollService.getSpecialLabel(poll[key]));
|
||||
let percentLabel = '';
|
||||
if (!this.pollService.isAbstractValue(this.pollService.calculationDataFromPoll(poll), key)) {
|
||||
percentLabel = ` (${this.pollService.getValuePercent(
|
||||
this.pollService.calculationDataFromPoll(poll),
|
||||
key
|
||||
)}%)`;
|
||||
}
|
||||
return [
|
||||
const tableLine = [
|
||||
{
|
||||
text: conclusionLabel,
|
||||
style: 'tableConclude'
|
||||
text: pollResult.user
|
||||
},
|
||||
{
|
||||
text: specialLabel + percentLabel,
|
||||
style: 'tableConclude'
|
||||
text: resultLine
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
pollTableBody.push(...summaryLine);
|
||||
pollTableBody.push(tableLine);
|
||||
}
|
||||
|
||||
resultBody.push({
|
||||
table: {
|
||||
@ -256,52 +209,19 @@ export class AssignmentPdfService {
|
||||
}
|
||||
}
|
||||
|
||||
// add the legend to the result body
|
||||
// if (assignment.polls.length > 0 && isElectedSemaphore) {
|
||||
if (assignment.polls.length > 0 && this.showIsElected) {
|
||||
resultBody.push({
|
||||
text: `* = ${this.translate.instant('is elected')}`,
|
||||
margin: [0, 5, 0, 0]
|
||||
});
|
||||
}
|
||||
|
||||
return resultBody;*/
|
||||
throw new Error('TODO');
|
||||
return resultBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a translated voting result with numbers and percent-value depending in the polloptions
|
||||
* I.e: "Yes 25 (22,2%)" or just "10"
|
||||
*
|
||||
* @param optionLabel Usually Yes or No
|
||||
* @param value the amount of votes
|
||||
* @param poll the specific poll
|
||||
* @param option the corresponding poll option
|
||||
* @returns a string a nicer number representation: "Yes 25 (22,2%)" or just "10"
|
||||
* Converts pollData to a printable string representation
|
||||
*/
|
||||
/*private parseVoteValue(
|
||||
optionLabel: PollVoteValue,
|
||||
value: number,
|
||||
poll: ViewAssignmentPoll,
|
||||
option: ViewAssignmentOption
|
||||
): string {
|
||||
let resultString = '';
|
||||
const label = this.translate.instant(this.pollService.getLabel(optionLabel));
|
||||
const valueString = this.pollService.getSpecialLabel(value);
|
||||
const percentNr = this.pollService.getPercent(
|
||||
this.pollService.calculationDataFromPoll(poll),
|
||||
option,
|
||||
optionLabel
|
||||
);
|
||||
|
||||
resultString += `${label} ${valueString}`;
|
||||
if (
|
||||
percentNr &&
|
||||
!this.pollService.isAbstractOption(this.pollService.calculationDataFromPoll(poll), option, optionLabel)
|
||||
) {
|
||||
resultString += ` (${percentNr}%)`;
|
||||
private getPollResult(votingResult: PollData, poll: ViewAssignmentPoll): string {
|
||||
const resultList = poll.pollmethodFields.map(field => {
|
||||
const votingKey = this.translate.instant(this.pollKeyVerbose.transform(field));
|
||||
const resultValue = this.parsePollNumber.transform(votingResult[field]);
|
||||
const resultInPercent = this.pollPercentBase.transform(votingResult[field], poll);
|
||||
return `${votingKey}: ${resultValue} ${resultInPercent ? resultInPercent : ''}`;
|
||||
});
|
||||
return resultList.join('\n');
|
||||
}
|
||||
|
||||
return `${resultString}\n`;
|
||||
}*/
|
||||
}
|
||||
|
@ -68,8 +68,12 @@ export class ViewMotionPoll extends ViewBasePoll<MotionPoll> implements MotionPo
|
||||
}
|
||||
];
|
||||
|
||||
public get result(): ViewMotionOption {
|
||||
return this.options[0];
|
||||
}
|
||||
|
||||
public get hasVotes(): boolean {
|
||||
return !!this.options[0].votes.length;
|
||||
return !!this.result.votes.length;
|
||||
}
|
||||
|
||||
public initChartLabels(): string[] {
|
||||
@ -130,7 +134,7 @@ export class ViewMotionPoll extends ViewBasePoll<MotionPoll> implements MotionPo
|
||||
}
|
||||
|
||||
public anySpecialVotes(): boolean {
|
||||
return this.options[0].yes < 0 || this.options[0].no < 0 || this.options[0].abstain < 0;
|
||||
return this.result.yes < 0 || this.result.no < 0 || this.result.abstain < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -145,23 +149,22 @@ export class ViewMotionPoll extends ViewBasePoll<MotionPoll> implements MotionPo
|
||||
|
||||
public getPercentBase(): number {
|
||||
const base: PercentBase = this.poll.onehundred_percent_base;
|
||||
const options = this.options[0];
|
||||
|
||||
let totalByBase: number;
|
||||
switch (base) {
|
||||
case PercentBase.YN:
|
||||
if (options.yes >= 0 && options.no >= 0) {
|
||||
totalByBase = options.sumYN();
|
||||
if (this.result.yes >= 0 && this.result.no >= 0) {
|
||||
totalByBase = this.result.sumYN();
|
||||
}
|
||||
break;
|
||||
case PercentBase.YNA:
|
||||
if (options.yes >= 0 && options.no >= 0 && options.abstain >= 0) {
|
||||
totalByBase = options.sumYNA();
|
||||
if (this.result.yes >= 0 && this.result.no >= 0 && this.result.abstain >= 0) {
|
||||
totalByBase = this.result.sumYNA();
|
||||
}
|
||||
break;
|
||||
case PercentBase.Valid:
|
||||
// auslagern
|
||||
if (options.yes >= 0 && options.no >= 0 && options.abstain >= 0) {
|
||||
if (this.result.yes >= 0 && this.result.no >= 0 && this.result.abstain >= 0) {
|
||||
totalByBase = this.poll.votesvalid;
|
||||
}
|
||||
break;
|
||||
|
@ -55,7 +55,6 @@ export class MotionPollDetailComponent extends BasePollDetailComponent<ViewMotio
|
||||
|
||||
public openDialog(): void {
|
||||
this.pollDialog.openDialog(this.poll);
|
||||
console.log('this.poll: ', this.poll.hasVotes);
|
||||
}
|
||||
|
||||
protected onDeleted(): void {
|
||||
|
@ -11,6 +11,9 @@ import { StatuteParagraphRepositoryService } from 'app/core/repositories/motions
|
||||
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||
import { LinenumberingService } from 'app/core/ui-services/linenumbering.service';
|
||||
import { ViewUnifiedChange, ViewUnifiedChangeType } from 'app/shared/models/motions/view-unified-change';
|
||||
import { ParsePollNumberPipe } from 'app/shared/pipes/parse-poll-number.pipe';
|
||||
import { PollKeyVerbosePipe } from 'app/shared/pipes/poll-key-verbose.pipe';
|
||||
import { PollPercentBasePipe } from 'app/shared/pipes/poll-percent-base.pipe';
|
||||
import { getRecommendationTypeName } from 'app/shared/utils/recommendation-type-names';
|
||||
import { MotionExportInfo } from './motion-export.service';
|
||||
import { ChangeRecoMode, InfoToExport, LineNumberingMode, PERSONAL_NOTE_ID } from '../motions.constants';
|
||||
@ -61,7 +64,10 @@ export class MotionPdfService {
|
||||
private pdfDocumentService: PdfDocumentService,
|
||||
private htmlToPdfService: HtmlToPdfService,
|
||||
private linenumberingService: LinenumberingService,
|
||||
private commentRepo: MotionCommentSectionRepositoryService
|
||||
private commentRepo: MotionCommentSectionRepositoryService,
|
||||
private pollKeyVerbose: PollKeyVerbosePipe,
|
||||
private pollPercentBase: PollPercentBasePipe,
|
||||
private parsePollNumber: ParsePollNumberPipe
|
||||
) {}
|
||||
|
||||
/**
|
||||
@ -362,31 +368,20 @@ export class MotionPdfService {
|
||||
const column1 = [];
|
||||
const column2 = [];
|
||||
const column3 = [];
|
||||
motion.polls.map((poll, index) => {
|
||||
/*if (poll.has_votes) {
|
||||
if (motion.motion.polls.length > 1) {
|
||||
column1.push(index + 1 + '. ' + this.translate.instant('Vote'));
|
||||
column2.push('');
|
||||
column3.push('');
|
||||
motion.polls.forEach(poll => {
|
||||
if (poll.hasVotes) {
|
||||
const tableData = poll.generateTableData();
|
||||
tableData.forEach(votingResult => {
|
||||
const resultKey = this.translate.instant(this.pollKeyVerbose.transform(votingResult.key));
|
||||
const resultValue = this.parsePollNumber.transform(votingResult.value);
|
||||
column1.push(`${resultKey}:`);
|
||||
column2.push(resultValue);
|
||||
if (votingResult.showPercent) {
|
||||
const resultInPercent = this.pollPercentBase.transform(votingResult.value, poll);
|
||||
column3.push(resultInPercent);
|
||||
}
|
||||
const values: CalculablePollKey[] = ['yes', 'no', 'abstain'];
|
||||
if (poll.votesvalid) {
|
||||
values.push('votesvalid');
|
||||
}
|
||||
if (poll.votesinvalid) {
|
||||
values.push('votesinvalid');
|
||||
}
|
||||
if (poll.votescast) {
|
||||
values.push('votescast');
|
||||
}
|
||||
values.map(value => {
|
||||
column1.push(`${this.translate.instant(this.pollService.getLabel(value))}:`);
|
||||
column2.push(`${this.translate.instant(this.pollService.getSpecialLabel(poll[value]))}`);
|
||||
this.pollService.isAbstractValue(poll, value)
|
||||
? column3.push('')
|
||||
: column3.push(`(${this.pollService.calculatePercentage(poll, value)} %)`);
|
||||
});
|
||||
}*/
|
||||
}
|
||||
});
|
||||
metaTableBody.push([
|
||||
{
|
||||
@ -653,15 +648,6 @@ export class MotionPdfService {
|
||||
margin: [0, 25, 0, 10]
|
||||
});
|
||||
|
||||
// determine the width of the reason depending on line numbering
|
||||
// currently not used
|
||||
// let columnWidth: string;
|
||||
// if (lnMode === LineNumberingMode.Outside) {
|
||||
// columnWidth = '80%';
|
||||
// } else {
|
||||
// columnWidth = '100%';
|
||||
// }
|
||||
|
||||
reason.push(this.htmlToPdfService.addPlainText(motion.reason));
|
||||
|
||||
return reason;
|
||||
|
@ -132,24 +132,6 @@ export abstract class PollService {
|
||||
.subscribe(settings => (this.isElectronicVotingEnabled = settings.ENABLE_ELECTRONIC_VOTING));
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve special labels for a poll value
|
||||
* {@link specialPollVotes}. Positive values will return as string
|
||||
* representation of themselves
|
||||
*
|
||||
* @param value check value for special numbers
|
||||
* @returns the label for a non-positive value, according to
|
||||
*/
|
||||
public getSpecialLabel(value: number): string {
|
||||
// if (value >= 0) {
|
||||
// return value.toString();
|
||||
// // TODO: toLocaleString(lang); but translateService is not usable here, thus lang is not well defined
|
||||
// }
|
||||
// const vote = this.specialPollVotes.find(special => special[0] === value);
|
||||
// return vote ? vote[1] : 'Undocumented special (negative) value';
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the default poll data to the object. To be extended in subclasses
|
||||
* @param poll the poll/object to fill
|
||||
@ -160,140 +142,6 @@ export abstract class PollService {
|
||||
poll.type = PollType.Analog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the percentage the given key reaches.
|
||||
*
|
||||
* @param poll
|
||||
* @param key
|
||||
* @returns a percentage number with two digits, null if the value cannot be calculated (consider 0 !== null)
|
||||
*/
|
||||
public calculatePercentage(poll: ViewBasePoll, key: CalculablePollKey): number | null {
|
||||
const baseNumber = this.getBaseAmount(poll);
|
||||
if (!baseNumber) {
|
||||
return null;
|
||||
}
|
||||
switch (key) {
|
||||
case 'abstain':
|
||||
if (poll.onehundred_percent_base === PercentBase.YN) {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
case 'votesinvalid':
|
||||
if (poll.onehundred_percent_base !== PercentBase.Cast) {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
case 'votesvalid':
|
||||
if (![PercentBase.Cast, PercentBase.Valid].includes(poll.onehundred_percent_base)) {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
case 'votescast':
|
||||
if (poll.onehundred_percent_base !== PercentBase.Cast) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return Math.round(((poll[key] * 100) / baseNumber) * 100) / 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number representing 100 percent for a given MotionPoll, depending
|
||||
* on the configuration and the votes given.
|
||||
*
|
||||
* @param poll
|
||||
* @returns the positive number representing 100 percent of the poll, 0 if
|
||||
* the base cannot be calculated
|
||||
*/
|
||||
public getBaseAmount(poll: ViewBasePoll): number {
|
||||
/*if (!poll) {
|
||||
return 0;
|
||||
}
|
||||
switch (this.percentBase) {
|
||||
case 'CAST':
|
||||
if (!poll.votescast) {
|
||||
return 0;
|
||||
}
|
||||
if (poll.votesinvalid < 0) {
|
||||
return 0;
|
||||
}
|
||||
return poll.votescast;
|
||||
case 'VALID':
|
||||
if (poll.yes < 0 || poll.no < 0 || poll.abstain < 0) {
|
||||
return 0;
|
||||
}
|
||||
return poll.votesvalid ? poll.votesvalid : 0;
|
||||
case 'YES_NO_ABSTAIN':
|
||||
if (poll.yes < 0 || poll.no < 0 || poll.abstain < 0) {
|
||||
return 0;
|
||||
}
|
||||
return poll.yes + poll.no + poll.abstain;
|
||||
case 'YES_NO':
|
||||
if (poll.yes < 0 || poll.no < 0 || poll.abstain === -1) {
|
||||
// It is not allowed to set 'Abstain' to 'majority' but exclude it from calculation.
|
||||
// Setting 'Abstain' to 'undocumented' is possible, of course.
|
||||
return 0;
|
||||
}
|
||||
return poll.yes + poll.no;
|
||||
}*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates which number is needed for the quorum to be surpassed
|
||||
* TODO: Methods still hard coded to mirror the server's.
|
||||
*
|
||||
* @param poll
|
||||
* @param method (optional) majority calculation method. If none is given,
|
||||
* the default as set in the config will be used.
|
||||
* @returns the first integer number larger than the required majority,
|
||||
* undefined if a quorum cannot be calculated.
|
||||
*/
|
||||
public calculateQuorum(poll: ViewBasePoll, method?: string): number {
|
||||
if (!method) {
|
||||
method = this.defaultMajorityMethod;
|
||||
}
|
||||
const baseNumber = this.getBaseAmount(poll);
|
||||
if (!baseNumber) {
|
||||
return undefined;
|
||||
}
|
||||
const calc = PollMajorityMethod.find(m => m.value === method);
|
||||
return calc && calc.calc ? calc.calc(baseNumber) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a value is abstract (percentages cannot be calculated)
|
||||
*
|
||||
* @param poll
|
||||
* @param value
|
||||
* @returns true if the percentages should not be calculated
|
||||
*/
|
||||
public isAbstractValue(poll: ViewBasePoll, value: CalculablePollKey): boolean {
|
||||
// if (this.getBaseAmount(poll) === 0) {
|
||||
// return true;
|
||||
// }
|
||||
// switch (this.percentBase) {
|
||||
// case 'YES_NO':
|
||||
// if (['votescast', 'votesinvalid', 'votesvalid', 'abstain'].includes(value)) {
|
||||
// return true;
|
||||
// }
|
||||
// break;
|
||||
// case 'YES_NO_ABSTAIN':
|
||||
// if (['votescast', 'votesinvalid', 'votesvalid'].includes(value)) {
|
||||
// return true;
|
||||
// }
|
||||
// break;
|
||||
// case 'VALID':
|
||||
// if (['votesinvalid', 'votescast'].includes(value)) {
|
||||
// return true;
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// if (poll[value] < 0) {
|
||||
// return true;
|
||||
// }
|
||||
return false;
|
||||
}
|
||||
|
||||
public getVerboseNameForValue(key: string, value: string): string {
|
||||
switch (key) {
|
||||
case 'majority_method':
|
||||
|
Loading…
Reference in New Issue
Block a user