Skip to content

Commit

Permalink
Add name recognition table
Browse files Browse the repository at this point in the history
  • Loading branch information
ArendPeter committed Dec 12, 2024
1 parent 55d9f9b commit 5dd69e5
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 16 deletions.
6 changes: 3 additions & 3 deletions packages/frontend/src/components/Election/Results/Results.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { Candidate } from "@equal-vote/star-vote-shared/domain_model/Candidate";
import VoterIntentWidget from "./components/VoterIntentWidget";
import SupportBlurb from "../SupportBlurb";
import ColumnDistributionWidget from "./components/ColumnDistributionWidget";
import NameRecognitionWidget from "./components/NameRecognitionWidget";

function STARResultsViewer({ filterRandomFromLogs }: {filterRandomFromLogs: boolean }) {
let i = 0;
Expand Down Expand Up @@ -61,6 +62,7 @@ function STARResultsViewer({ filterRandomFromLogs }: {filterRandomFromLogs: bool
<HeadToHeadWidget candidates={sortedCandidates}/>
<VoterProfileWidget candidates={sortedCandidates} topScore={5} frontRunners={sortedCandidates.slice(0, 2) as [Candidate, Candidate]}/>
<ColumnDistributionWidget/>
<NameRecognitionWidget/>
</WidgetContainer>
</DetailExpander>
</DetailExpander>
Expand Down Expand Up @@ -212,14 +214,12 @@ function IRVResultsViewer() {
<DetailExpander level={1}>
<WidgetContainer>
<VoterIntentWidget eliminationOrderById={eliminationOrderById} winnerId={sortedCandidates[0].candidate_id}/>
<ColumnDistributionWidget/>
</WidgetContainer>
<WidgetContainer>
<HeadToHeadWidget ranked candidates={sortedCandidates}/>
<VoterProfileWidget candidates={sortedCandidates} topScore={1} ranked frontRunners={sortedCandidates.slice(0, 2) as [Candidate, Candidate]}/>
</WidgetContainer>
<WidgetContainer>
<ColumnDistributionWidget/>
</WidgetContainer>
</DetailExpander>
</DetailExpander>
</ResultsViewer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ export default () => {
const {ballotsForRace} = useAnonymizedBallots();
const {t, race} = useRace();

// How many columns were used?
// Which columns were used?

let numColumns = [];
let whichColumns = [];
let totalColumns = 0;
Expand Down Expand Up @@ -44,7 +41,7 @@ export default () => {
<Typography variant='h6'>{t(`results.column_distribution_num_title`)}</Typography>
<ResultsBarChart data={numColumns} xKey='count' percentage={true} sortFunc={false}/>
<Divider/>
{race.voting_method == 'STAR' && <>
{(race.voting_method == 'STAR' || race.voting_method == 'STAR_PR') && <>
<Typography variant='h6'>{t('results.column_distribution_which_title')}</Typography>
<ResultsBarChart data={whichColumns} xKey='count' percentage={true} sortFunc={false} percentDenominator={b.length}/>
</>}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import useAnonymizedBallots from "~/components/AnonymizedBallotsContextProvider";
import Widget from "./Widget";
import useRace from "~/components/RaceContextProvider";
import { Divider, Typography } from "@mui/material";
import ResultsBarChart from "./ResultsBarChart";

// candidates helps define the order
export default () => {
const {ballotsForRace} = useAnonymizedBallots();
const {t, race} = useRace();

console.log(race.candidates)
let numActive = Object.fromEntries(race.candidates.map(c => [c.candidate_id, {
name: c.candidate_name,
count: 0,
}]))

let b = ballotsForRace()
b.forEach((scores) => {
scores.forEach(score => {
if(score.score == null || score.score == undefined) return;
numActive[score.candidate_id].count++;
})
})

return <Widget title={t(`results.name_recognition_title`)}>
<Typography variant='h6'>{t(`results.name_recognition_sub_title`)}</Typography>
<ResultsBarChart data={Object.values(numActive).sort((a, b) => -(a.count-b.count))} xKey='count' percentage={true} percentDenominator={b.length}/>
<Typography>{t(`results.name_recognition_blank_warning`)}</Typography>
</Widget>
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const ElectionContext = createContext<IElectionContext>({
refreshElection: () => false,
updateElection: () => false,
permissions: [],
t: () => {}
t: () => undefined
})

export const ElectionContextProvider = ({ id, children }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ export default () => {
}</strong></StepLabel>
<StepContent>
<Typography>{t('election_creation.term_question')}
<Tip name='polls_vs_elections' electionTermType={election.settings.term_type}/>
<Tip name='polls_vs_elections'/>
</Typography>
<RadioGroup row>
{['poll', 'election'].map( (type, i) =>
Expand Down Expand Up @@ -273,7 +273,6 @@ export default () => {
<StepContent>
<Typography>
{t('election_creation.restricted_question')}
<Tip name='restricted' electionTermType={election.settings.term_type}/>
</Typography>

<RadioGroup row>
Expand Down
13 changes: 11 additions & 2 deletions packages/frontend/src/components/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,23 @@ import { useState } from "react";
import en from './en.yaml';
import { useSubstitutedTranslation } from "./util";
import { TermType } from "@equal-vote/star-vote-shared/domain_model/ElectionSettings";
import useRace from "./RaceContextProvider";
import useElection from "./ElectionContextProvider";

// this doesn't work yet, I filed a github issue
// https://github.com/Modyfi/vite-plugin-yaml/issues/27
type TipName = keyof typeof en.tips;


export const Tip = (props: {name: TipName, electionTermType: TermType | undefined}) => {
const {t} = useSubstitutedTranslation(props.electionTermType ?? 'election');
export const Tip = (props: {name: TipName}) => {
// TODO: maybe I can insert useElection and useRace within useSubstitutedTranslation?
const {t: ts} = useSubstitutedTranslation('election');
const {t: te} = useElection();
const {t: tr} = useRace();
let t = (tr() !== undefined) ? tr : (
(te() !== undefined) ? te : ts
);

const [clicked, setClicked] = useState(false);
const [hovered, setHovered] = useState(false);
return <ClickAwayListener onClickAway={() => setClicked(false)}>
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/components/util.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export const useSubstitutedTranslation = (electionTermType='election', v={}) =>
if(typeof txt !== 'string') return txt;
return txt.split(rTip).map((str, i) => {
if(i%2 == 0) return str;
return <Tip key={`tip_${keyPrefix}_${i}`} name={str} electionTermType={electionTermType as TermType}/>
return <Tip key={`tip_${keyPrefix}_${i}`} name={str}/>
})
}

Expand Down
13 changes: 10 additions & 3 deletions packages/frontend/src/i18n/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ election_creation:
title_question: What's the title for your {{election}}? !tip(election_title) # TERM will be replaced with election or poll

restricted_title: Restricted?
restricted_question: Would you like your {{election}} to be restricted to a pre-defined voter list?
restricted_question: Would you like your {{election}} to be restricted to a pre-defined voter list? !tip(restricted)

template_title: Choose Voters
template_prompt: (You can change this later, if needed.)
Expand Down Expand Up @@ -445,6 +445,13 @@ results:
column_distribution_num_title: Number of {{preferences}} given !tip(columns_given)
column_distribution_which_title: Which {{preferences}} were used? !tip(columns_used)

name_recognition_title: Name Recognition
name_recognition_sub_title: Percent of voters who listed a non-blank score for each candidate
name_recognition_blank_warning: >
Choosing not to score a candidate is identical to giving that candidate a zero.
However the voter's decision still gives us sense for the candidates they're
most familiar with.
candidate_selector: '{{capital_candidate}}'

win_count: '{{count}} Wins'
Expand Down Expand Up @@ -599,8 +606,8 @@ election_state:
# Info bubbles
tips:
columns_given:
title: Number of scores or ranks given
description: Percentage over voters who gave each number of scores/ranks
title: Number of {{preferences}} given
description: Percentage over voters who gave each number of {{preferences}}

columns_used:
title: Which scores were used
Expand Down

0 comments on commit 5dd69e5

Please sign in to comment.