|
|
@ -1,6 +1,6 @@
|
|
|
|
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
|
|
import {useEffect, useLayoutEffect, useRef, useState} from 'react';
|
|
|
|
import { GradeResultInterface, MeritProfileInterface } from '@services/type';
|
|
|
|
import {GradeResultInterface, MeritProfileInterface} from '@services/type';
|
|
|
|
import { getMajorityGrade } from '@services/majorityJudgment';
|
|
|
|
import {getMajorityGrade} from '@services/majorityJudgment';
|
|
|
|
|
|
|
|
|
|
|
|
interface ParamsInterface {
|
|
|
|
interface ParamsInterface {
|
|
|
|
numVotes: number;
|
|
|
|
numVotes: number;
|
|
|
@ -14,7 +14,7 @@ interface GradeBarInterface {
|
|
|
|
params: ParamsInterface;
|
|
|
|
params: ParamsInterface;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const GradeBar = ({ index, grade, size, params }: GradeBarInterface) => {
|
|
|
|
const GradeBar = ({index, grade, size, params}: GradeBarInterface) => {
|
|
|
|
const width = `${size * 100}%`;
|
|
|
|
const width = `${size * 100}%`;
|
|
|
|
const textWidth = Math.floor(100 * size);
|
|
|
|
const textWidth = Math.floor(100 * size);
|
|
|
|
|
|
|
|
|
|
|
@ -59,14 +59,14 @@ const DashedMedian = () => {
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
<div
|
|
|
|
className="position-relative d-flex justify-content-center"
|
|
|
|
className="position-relative d-flex justify-content-center"
|
|
|
|
style={{ top: '60px', height: '50px' }}
|
|
|
|
style={{top: '60px', height: '50px'}}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<div className="border h-100 border-1 border-dark border-opacity-75 border-dashed"></div>
|
|
|
|
<div className="border h-100 border-1 border-dark border-opacity-75 border-dashed"></div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const MajorityGrade = ({ grade, left }) => {
|
|
|
|
const MajorityGrade = ({grade, left}) => {
|
|
|
|
// const spanRef = useRef<HTMLDivElement>();
|
|
|
|
// const spanRef = useRef<HTMLDivElement>();
|
|
|
|
const spanRef = useRef<HTMLDivElement>();
|
|
|
|
const spanRef = useRef<HTMLDivElement>();
|
|
|
|
|
|
|
|
|
|
|
@ -81,7 +81,7 @@ const MajorityGrade = ({ grade, left }) => {
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
<div
|
|
|
|
style={{ left: `calc(${left * 100}% - ${width / 2}px)` }}
|
|
|
|
style={{left: `calc(${left * 100}% - ${width / 2}px)`}}
|
|
|
|
className="position-relative"
|
|
|
|
className="position-relative"
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<div
|
|
|
|
<div
|
|
|
@ -121,8 +121,8 @@ interface MeritProfileBarInterface {
|
|
|
|
grades: Array<GradeResultInterface>;
|
|
|
|
grades: Array<GradeResultInterface>;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const MeritProfileBar = ({ profile, grades }: MeritProfileBarInterface) => {
|
|
|
|
const MeritProfileBar = ({profile, grades}: MeritProfileBarInterface) => {
|
|
|
|
const gradesByValue: { [key: number]: GradeResultInterface } = {};
|
|
|
|
const gradesByValue: {[key: number]: GradeResultInterface} = {};
|
|
|
|
grades.forEach((g) => (gradesByValue[g.value] = g));
|
|
|
|
grades.forEach((g) => (gradesByValue[g.value] = g));
|
|
|
|
|
|
|
|
|
|
|
|
const numVotes = Object.values(profile).reduce((a, b) => a + b, 0);
|
|
|
|
const numVotes = Object.values(profile).reduce((a, b) => a + b, 0);
|
|
|
@ -167,32 +167,37 @@ const MeritProfileBar = ({ profile, grades }: MeritProfileBarInterface) => {
|
|
|
|
left={proponentWidth + normalized[majorityValue] / 2}
|
|
|
|
left={proponentWidth + normalized[majorityValue] / 2}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
<div className="d-flex">
|
|
|
|
<div className="d-flex">
|
|
|
|
<div
|
|
|
|
{proponentWidth > 1e-5 ? (
|
|
|
|
className={`d-flex border border-${
|
|
|
|
<div
|
|
|
|
proponentMajority ? 2 : 1
|
|
|
|
className={`d-flex border border-${proponentMajority ? 2 : 1
|
|
|
|
} border-success`}
|
|
|
|
} border-success`}
|
|
|
|
style={{ flexBasis: `${proponentWidth * 100}%` }}
|
|
|
|
style={{flexBasis: `${proponentWidth * 100}%`}}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
{values
|
|
|
|
{values
|
|
|
|
.filter((v) => v > majorityGrade.value)
|
|
|
|
.filter((v) => v > majorityGrade.value)
|
|
|
|
.map((v) => {
|
|
|
|
.map((v) => {
|
|
|
|
const index = values.indexOf(v);
|
|
|
|
const index = values.indexOf(v);
|
|
|
|
const size =
|
|
|
|
const size =
|
|
|
|
proponentWidth < 1e-3 ? 0 : normalized[index] / proponentWidth;
|
|
|
|
proponentWidth < 1e-3 ? 0 : normalized[index] / proponentWidth;
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<GradeBar
|
|
|
|
<GradeBar
|
|
|
|
index={index}
|
|
|
|
index={index}
|
|
|
|
params={params}
|
|
|
|
params={params}
|
|
|
|
grade={gradesByValue[v]}
|
|
|
|
grade={gradesByValue[v]}
|
|
|
|
key={index}
|
|
|
|
key={index}
|
|
|
|
size={size}
|
|
|
|
size={size}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
})}
|
|
|
|
</div>
|
|
|
|
</div>) : (
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
|
|
|
className="d-flex"
|
|
|
|
|
|
|
|
style={{flexBasis: `${proponentWidth * 100}%`}}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
</div>)}
|
|
|
|
<div
|
|
|
|
<div
|
|
|
|
className="border border-2 border-primary"
|
|
|
|
className="border border-2 border-primary"
|
|
|
|
style={{ flexBasis: `${normalized[majorityValue] * 100}%` }}
|
|
|
|
style={{flexBasis: `${normalized[majorityValue] * 100}%`}}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
{values
|
|
|
|
{values
|
|
|
|
.filter((v) => v === majorityGrade.value)
|
|
|
|
.filter((v) => v === majorityGrade.value)
|
|
|
@ -209,29 +214,32 @@ const MeritProfileBar = ({ profile, grades }: MeritProfileBarInterface) => {
|
|
|
|
);
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
})}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
{opponentWidth > 1e-5 ? (
|
|
|
|
className={`d-flex border border-${
|
|
|
|
<div
|
|
|
|
proponentMajority ? 1 : 2
|
|
|
|
className={`d-flex border border-${proponentMajority ? 1 : 2
|
|
|
|
} border-danger`}
|
|
|
|
} border-danger`}
|
|
|
|
style={{ flexBasis: `${opponentWidth * 100}%` }}
|
|
|
|
style={{flexBasis: `${opponentWidth * 100}%`}}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
{values
|
|
|
|
{values
|
|
|
|
.filter((v) => v < majorityGrade.value)
|
|
|
|
.filter((v) => v < majorityGrade.value)
|
|
|
|
.map((v) => {
|
|
|
|
.map((v) => {
|
|
|
|
const index = values.indexOf(v);
|
|
|
|
const index = values.indexOf(v);
|
|
|
|
const size =
|
|
|
|
const size =
|
|
|
|
opponentWidth < 1e-3 ? 0 : normalized[index] / opponentWidth;
|
|
|
|
opponentWidth < 1e-3 ? 0 : normalized[index] / opponentWidth;
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<GradeBar
|
|
|
|
<GradeBar
|
|
|
|
index={index}
|
|
|
|
index={index}
|
|
|
|
params={params}
|
|
|
|
params={params}
|
|
|
|
grade={gradesByValue[v]}
|
|
|
|
grade={gradesByValue[v]}
|
|
|
|
key={index}
|
|
|
|
key={index}
|
|
|
|
size={size}
|
|
|
|
size={size}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
})}
|
|
|
|
</div>
|
|
|
|
</div>) : (
|
|
|
|
|
|
|
|
<div className="d-flex" style={{flexBasis: `${opponentWidth * 100}%`}} >
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{/* <div className='median dash'> </div> */}
|
|
|
|
{/* <div className='median dash'> </div> */}
|
|
|
|
</>
|
|
|
|
</>
|
|
|
|