Merge pull request #6318 from GabrielInTheWorld/fix-candidate-percentbase
Fixes percentbase of candidates in assignments
This commit is contained in:
commit
31f59e069d
@ -41,7 +41,7 @@
|
|||||||
<div class="single-result" [ngClass]="getVoteClass(vote)">
|
<div class="single-result" [ngClass]="getVoteClass(vote)">
|
||||||
<span>
|
<span>
|
||||||
<span *ngIf="vote.showPercent">
|
<span *ngIf="vote.showPercent">
|
||||||
{{ getVoteAmount(vote, row) | pollPercentBase: poll:'assignment' }}
|
{{ getVoteAmount(vote, row) | pollPercentBase: poll:row:'assignment' }}
|
||||||
</span>
|
</span>
|
||||||
<span *ngIf="row.class === 'user'">
|
<span *ngIf="row.class === 'user'">
|
||||||
{{ getVoteAmount(vote, row) | parsePollNumber }}
|
{{ getVoteAmount(vote, row) | parsePollNumber }}
|
||||||
@ -59,7 +59,7 @@
|
|||||||
<td class="result">
|
<td class="result">
|
||||||
<div class="single-result">
|
<div class="single-result">
|
||||||
<span>
|
<span>
|
||||||
{{ poll.entitled_users_at_stop.length | pollPercentBase: poll:'assignment' }}
|
{{ poll.entitled_users_at_stop.length | pollPercentBase: poll:row:'assignment' }}
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
{{ poll.entitled_users_at_stop.length }}
|
{{ poll.entitled_users_at_stop.length }}
|
||||||
|
@ -3,6 +3,7 @@ import { Pipe, PipeTransform } from '@angular/core';
|
|||||||
import { AssignmentPollService } from 'app/site/assignments/modules/assignment-poll/services/assignment-poll.service';
|
import { AssignmentPollService } from 'app/site/assignments/modules/assignment-poll/services/assignment-poll.service';
|
||||||
import { MotionPollService } from 'app/site/motions/services/motion-poll.service';
|
import { MotionPollService } from 'app/site/motions/services/motion-poll.service';
|
||||||
import { PollData } from 'app/site/polls/services/poll.service';
|
import { PollData } from 'app/site/polls/services/poll.service';
|
||||||
|
import { PollDataOption, PollTableData } from '../../site/polls/services/poll.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses a number and a ViewPoll-object.
|
* Uses a number and a ViewPoll-object.
|
||||||
@ -26,7 +27,12 @@ export class PollPercentBasePipe implements PipeTransform {
|
|||||||
private motionPollService: MotionPollService
|
private motionPollService: MotionPollService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public transform(value: number, poll: PollData, type: 'motion' | 'assignment'): string | null {
|
public transform(
|
||||||
|
value: number,
|
||||||
|
poll: PollData,
|
||||||
|
row: PollDataOption | PollTableData,
|
||||||
|
type: 'motion' | 'assignment'
|
||||||
|
): string | null {
|
||||||
// logic handles over the pollService to avoid circular dependencies
|
// logic handles over the pollService to avoid circular dependencies
|
||||||
let voteValueInPercent: string;
|
let voteValueInPercent: string;
|
||||||
|
|
||||||
@ -36,9 +42,9 @@ export class PollPercentBasePipe implements PipeTransform {
|
|||||||
* we cannot expect the projector to work with real types for now, we need to provice the type
|
* we cannot expect the projector to work with real types for now, we need to provice the type
|
||||||
*/
|
*/
|
||||||
if (type === 'assignment') {
|
if (type === 'assignment') {
|
||||||
voteValueInPercent = this.assignmentPollService.getVoteValueInPercent(value, poll);
|
voteValueInPercent = this.assignmentPollService.getVoteValueInPercent(value, { poll, row });
|
||||||
} else {
|
} else {
|
||||||
voteValueInPercent = this.motionPollService.getVoteValueInPercent(value, poll);
|
voteValueInPercent = this.motionPollService.getVoteValueInPercent(value, { poll, row });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (voteValueInPercent) {
|
if (voteValueInPercent) {
|
||||||
|
@ -196,33 +196,26 @@ export class AssignmentPollService extends PollService {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private sumOptionsYN(poll: PollData): number {
|
private sumOptionsYN(option: PollDataOption): number {
|
||||||
return poll.options.reduce((o, n) => {
|
return (option?.yes ?? 0) + (option?.no ?? 0);
|
||||||
o += n.yes > 0 ? n.yes : 0;
|
|
||||||
o += n.no > 0 ? n.no : 0;
|
|
||||||
return o;
|
|
||||||
}, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private sumOptionsYNA(poll: PollData): number {
|
private sumOptionsYNA(option: PollDataOption): number {
|
||||||
return poll.options.reduce((o, n) => {
|
return this.sumOptionsYN(option) + (option?.abstain ?? 0);
|
||||||
o += n.abstain > 0 ? n.abstain : 0;
|
|
||||||
return o;
|
|
||||||
}, this.sumOptionsYN(poll));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPercentBase(poll: PollData): number {
|
public getPercentBase(poll: PollData, row: PollDataOption): number {
|
||||||
const base: AssignmentPollPercentBase = poll.onehundred_percent_base as AssignmentPollPercentBase;
|
const base: AssignmentPollPercentBase = poll.onehundred_percent_base as AssignmentPollPercentBase;
|
||||||
let totalByBase: number;
|
let totalByBase: number;
|
||||||
switch (base) {
|
switch (base) {
|
||||||
case AssignmentPollPercentBase.YN:
|
case AssignmentPollPercentBase.YN:
|
||||||
totalByBase = this.sumOptionsYN(poll);
|
totalByBase = this.sumOptionsYN(row);
|
||||||
break;
|
break;
|
||||||
case AssignmentPollPercentBase.YNA:
|
case AssignmentPollPercentBase.YNA:
|
||||||
totalByBase = this.sumOptionsYNA(poll);
|
totalByBase = this.sumOptionsYNA(row);
|
||||||
break;
|
break;
|
||||||
case AssignmentPollPercentBase.Y:
|
case AssignmentPollPercentBase.Y:
|
||||||
totalByBase = this.sumOptionsYNA(poll);
|
totalByBase = this.sumOptionsYNA(row);
|
||||||
break;
|
break;
|
||||||
case AssignmentPollPercentBase.Valid:
|
case AssignmentPollPercentBase.Valid:
|
||||||
totalByBase = poll.votesvalid;
|
totalByBase = poll.votesvalid;
|
||||||
@ -246,7 +239,7 @@ export class AssignmentPollService extends PollService {
|
|||||||
const voteValue = option[field];
|
const voteValue = option[field];
|
||||||
const votingKey = this.translate.instant(this.pollKeyVerbose.transform(field));
|
const votingKey = this.translate.instant(this.pollKeyVerbose.transform(field));
|
||||||
const resultValue = this.parsePollNumber.transform(voteValue);
|
const resultValue = this.parsePollNumber.transform(voteValue);
|
||||||
const resultInPercent = this.getVoteValueInPercent(voteValue, poll);
|
const resultInPercent = this.getVoteValueInPercent(voteValue, { poll, row: option });
|
||||||
let resultLabel = `${votingKey}: ${resultValue}`;
|
let resultLabel = `${votingKey}: ${resultValue}`;
|
||||||
|
|
||||||
// 0 is a valid number in this case
|
// 0 is a valid number in this case
|
||||||
|
@ -241,7 +241,12 @@ export class AssignmentPdfService {
|
|||||||
.map((singleResult: VotingResult) => {
|
.map((singleResult: VotingResult) => {
|
||||||
const votingKey = this.translate.instant(this.pollKeyVerbose.transform(singleResult.vote));
|
const votingKey = this.translate.instant(this.pollKeyVerbose.transform(singleResult.vote));
|
||||||
const resultValue = this.parsePollNumber.transform(singleResult.amount);
|
const resultValue = this.parsePollNumber.transform(singleResult.amount);
|
||||||
const resultInPercent = this.pollPercentBase.transform(singleResult.amount, poll, 'assignment');
|
const resultInPercent = this.pollPercentBase.transform(
|
||||||
|
singleResult.amount,
|
||||||
|
poll,
|
||||||
|
votingResult,
|
||||||
|
'assignment'
|
||||||
|
);
|
||||||
return `${votingKey}${!!votingKey ? ': ' : ''}${resultValue} ${
|
return `${votingKey}${!!votingKey ? ': ' : ''}${resultValue} ${
|
||||||
singleResult.showPercent && resultInPercent ? resultInPercent : ''
|
singleResult.showPercent && resultInPercent ? resultInPercent : ''
|
||||||
}`;
|
}`;
|
||||||
|
@ -385,7 +385,10 @@ export class MotionPdfService {
|
|||||||
const resultValue = this.parsePollNumber.transform(value.amount);
|
const resultValue = this.parsePollNumber.transform(value.amount);
|
||||||
column1.push(`${votingOption}:`);
|
column1.push(`${votingOption}:`);
|
||||||
if (value.showPercent) {
|
if (value.showPercent) {
|
||||||
const resultInPercent = this.motionPollService.getVoteValueInPercent(value.amount, poll);
|
const resultInPercent = this.motionPollService.getVoteValueInPercent(value.amount, {
|
||||||
|
poll,
|
||||||
|
row: votingResult
|
||||||
|
});
|
||||||
// hard check for "null" since 0 is a valid number in this case
|
// hard check for "null" since 0 is a valid number in this case
|
||||||
if (resultInPercent !== null) {
|
if (resultInPercent !== null) {
|
||||||
column2.push(`(${resultInPercent})`);
|
column2.push(`(${resultInPercent})`);
|
||||||
|
@ -161,6 +161,13 @@ export interface VotingResult {
|
|||||||
|
|
||||||
const PollChartBarThickness = 20;
|
const PollChartBarThickness = 20;
|
||||||
|
|
||||||
|
function isPollTableData(value: any): value is PollTableData {
|
||||||
|
if (!value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !!value.votingOption && !!value.value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shared service class for polls. Used by child classes {@link MotionPollService}
|
* Shared service class for polls. Used by child classes {@link MotionPollService}
|
||||||
* and {@link AssignmentPollService}
|
* and {@link AssignmentPollService}
|
||||||
@ -215,10 +222,14 @@ export abstract class PollService {
|
|||||||
/**
|
/**
|
||||||
* return the total number of votes depending on the selected percent base
|
* return the total number of votes depending on the selected percent base
|
||||||
*/
|
*/
|
||||||
public abstract getPercentBase(poll: PollData): number;
|
public abstract getPercentBase(poll: PollData, row: PollDataOption): number;
|
||||||
|
|
||||||
public getVoteValueInPercent(value: number, poll: PollData): string | null {
|
public getVoteValueInPercent(
|
||||||
const totalByBase = this.getPercentBase(poll);
|
value: number,
|
||||||
|
{ poll, row }: { poll: PollData; row: PollDataOption | PollTableData }
|
||||||
|
): string | null {
|
||||||
|
const option = isPollTableData(row) ? this.transformToOptionData(row) : row;
|
||||||
|
const totalByBase = this.getPercentBase(poll, option);
|
||||||
if (totalByBase && totalByBase > 0) {
|
if (totalByBase && totalByBase > 0) {
|
||||||
const percentNumber = (value / totalByBase) * 100;
|
const percentNumber = (value / totalByBase) * 100;
|
||||||
if (percentNumber >= 0) {
|
if (percentNumber >= 0) {
|
||||||
@ -342,6 +353,17 @@ export abstract class PollService {
|
|||||||
return isAssignment ? this.getPollDataFieldsByMethod(poll) : this.getPollDataFieldsByPercentBase(poll);
|
return isAssignment ? this.getPollDataFieldsByMethod(poll) : this.getPollDataFieldsByPercentBase(poll);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected transformToOptionData(data: PollTableData): PollDataOption {
|
||||||
|
const yes = data.value.find(vote => vote.vote === `yes`);
|
||||||
|
const no = data.value.find(vote => vote.vote === `no`);
|
||||||
|
const abstain = data.value.find(vote => vote.vote === `abstain`);
|
||||||
|
return {
|
||||||
|
yes: yes?.amount,
|
||||||
|
no: no?.amount,
|
||||||
|
abstain: abstain?.amount
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private getPollDataFieldsByMethod(poll: PollData | ViewBasePoll): CalculablePollKey[] {
|
private getPollDataFieldsByMethod(poll: PollData | ViewBasePoll): CalculablePollKey[] {
|
||||||
switch (poll.pollmethod) {
|
switch (poll.pollmethod) {
|
||||||
case AssignmentPollMethod.YNA: {
|
case AssignmentPollMethod.YNA: {
|
||||||
|
@ -2,7 +2,7 @@ black
|
|||||||
coverage
|
coverage
|
||||||
flake8
|
flake8
|
||||||
isort<5.0.0
|
isort<5.0.0
|
||||||
mypy
|
mypy<0.920
|
||||||
pytest<5.4.2
|
pytest<5.4.2
|
||||||
pytest-django<3.9.0
|
pytest-django<3.9.0
|
||||||
pytest-asyncio<0.11.0
|
pytest-asyncio<0.11.0
|
||||||
|
Loading…
Reference in New Issue
Block a user