Skip to content

feat: new level calculations and score in leaderboard #1931

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 32 additions & 23 deletions web/src/components/Popup/MiniGuides/JurorLevels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,64 +31,73 @@ const Card = styled(_Card)`
`;

const leftPageContents = [
{
title: "Juror Level 0: Diogenes",
paragraphs: [
"Coherence Score below 25.",
"This level is for new jurors or those frequently voting incoherently. A few coherent votes can help climb out of this level quickly.",
],
},
{
title: "Juror Level 1: Pythagoras",
paragraphs: [
"Jurors are classified into distinct levels according to their performance starting from Level 1.",
"Level 1: Jurors with ≥ 1 case arbitrated with 0-70% of coherent votes.",
"Coherence Score between 25 and 49.",
"Jurors here are gaining experience and starting to build voting reliability.",
],
},
{
title: "Juror Level 2: Socrates",
paragraphs: ["Level 2: Jurors with ≥ 3 cases arbitrated with more than 70% coherent votes."],
paragraphs: [
"Coherence Score between 50 and 69.",
"Mid-tier performance. Jurors at this level have demonstrated reasonable consistency in coherent voting.",
],
},
{
title: "Juror Level 3: Plato",
paragraphs: ["Level 3: Jurors with ≥ 7 cases arbitrated with more than 80% of coherent votes."],
paragraphs: [
"Coherence Score between 70 and 89.",
"Reliable jurors with a consistent track record of coherent votes. Just a few more coherent votes away from reaching the top.",
],
},
{
title: "Juror Level 4: Aristotle",
paragraphs: ["Level 4: Jurors with ≥ 10 cases arbitrated with more than 90% of coherent votes."],
},
{
title: "Juror Level 0: Diogenes",
paragraphs: [
"There's a level for the low-performance/lazy jurors. Level 0: Jurors with ≥ 3 cases arbitrated" +
" with less than 50% of coherent votes.",
"Coherence Score between 90 and 100.",
"Top-tier jurors with excellent coherence. Trusted members of the platform.",
],
},
];

const userLevelData = [
{
level: 0,
title: "Diogenes",
totalCoherentVotes: 2,
totalResolvedVotes: 10,
},
{
level: 1,
title: "Pythagoras",
totalCoherentVotes: 6,
totalResolvedVotes: 10,
totalResolvedVotes: 12,
},
{
level: 2,
title: "Socrates",
totalCoherentVotes: 7,
totalResolvedVotes: 10,
totalCoherentVotes: 22,
totalResolvedVotes: 34,
},
{
level: 3,
title: "Plato",
totalCoherentVotes: 8,
totalResolvedVotes: 10,
totalCoherentVotes: 52,
totalResolvedVotes: 65,
},
{
level: 4,
title: "Aristotle",
totalCoherentVotes: 9,
totalResolvedVotes: 10,
},
{
level: 0,
title: "Diogenes",
totalCoherentVotes: 3,
totalResolvedVotes: 10,
totalCoherentVotes: 90,
totalResolvedVotes: 90,
},
];

Expand Down
9 changes: 4 additions & 5 deletions web/src/pages/Home/TopJurors/Header/Coherence.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const Container = styled.div`
display: flex;
font-size: 12px !important;
&::before {
content: "Coherence";
content: "Coherent\u00a0Votes";
}
color: ${({ theme }) => theme.secondaryText};
align-items: center;
Expand All @@ -25,18 +25,17 @@ const Container = styled.div`
`;

const coherentVotesTooltipMsg =
"This is the percentage of coherent votes made by a juror." +
" Hover to see the ratio of coherent votes: " +
"This is the ratio of coherent votes made by a juror: " +
"the number in the left is the number of times where the juror " +
"voted coherently and the number in the right is the total number of times " +
"the juror voted";
"the juror voted. Hover to see the percentage of coherent votes.";

const Coherence: React.FC = () => {
const isDesktop = useIsDesktop();

return (
<Container>
<WithHelpTooltip place={isDesktop ? "top" : "left"} tooltipMsg={coherentVotesTooltipMsg}></WithHelpTooltip>
<WithHelpTooltip place={isDesktop ? "top" : "right"} tooltipMsg={coherentVotesTooltipMsg}></WithHelpTooltip>
</Container>
);
};
Expand Down
10 changes: 6 additions & 4 deletions web/src/pages/Home/TopJurors/Header/DesktopHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import JurorLevels from "components/Popup/MiniGuides/JurorLevels";

import Coherence from "./Coherence";
import Rewards from "./Rewards";
import Score from "./Score";

const Container = styled.div<{ renderIcon?: boolean }>`
display: none;
Expand All @@ -32,9 +33,9 @@ const Container = styled.div<{ renderIcon?: boolean }>`
() => css`
display: grid;
grid-template-columns: ${renderIcon
? `min-content repeat(3, ${responsiveSize(160, 180, 900)}) auto`
: `repeat(3, ${responsiveSize(160, 180, 900)}) auto`};
column-gap: ${responsiveSize(12, 28, 900)};
? `min-content minmax(160px, 1fr) minmax(60px, 1fr) minmax(80px, 0.8fr) minmax(180px, 1.5fr) minmax(100px, 1fr)`
: `minmax(160px, 1fr) minmax(60px, 1fr) minmax(80px, 0.8fr) minmax(180px, 1.5fr) minmax(100px, 1fr)`};
column-gap: ${responsiveSize(12, 24, 900)};
align-items: center;
`
)}
Expand Down Expand Up @@ -65,8 +66,9 @@ export const DesktopHeader: React.FC = () => {
<Container renderIcon={renderIcon}>
{renderIcon ? <StyledRankingIcon /> : null}
<StyledLabel>Juror</StyledLabel>
<Rewards />
<Score />
<Coherence />
<Rewards />
<HowItWorksContainer>
<HowItWorks
isMiniGuideOpen={isJurorLevelsMiniGuideOpen}
Expand Down
40 changes: 40 additions & 0 deletions web/src/pages/Home/TopJurors/Header/Score.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from "react";
import styled, { css } from "styled-components";

import { landscapeStyle } from "styles/landscapeStyle";

import useIsDesktop from "hooks/useIsDesktop";

import WithHelpTooltip from "components/WithHelpTooltip";

const Container = styled.div`
display: flex;
font-size: 12px !important;
&::before {
content: "Score";
}
color: ${({ theme }) => theme.secondaryText};
align-items: center;

${landscapeStyle(
() => css`
font-size: 14px !important;
justify-content: center;
`
)}
`;

const scoreTooltipMsg =
"A score from 0 to 100 reflecting coherent voting, smoothed " +
"to prevent jurors with low vote counts from ranking too high.";

const Score: React.FC = () => {
const isDesktop = useIsDesktop();

return (
<Container>
<WithHelpTooltip place={isDesktop ? "top" : "right"} tooltipMsg={scoreTooltipMsg}></WithHelpTooltip>
</Container>
);
};
export default Score;
5 changes: 3 additions & 2 deletions web/src/pages/Home/TopJurors/JurorCard/Coherence.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const Container = styled.div`
color: ${({ theme }) => theme.primaryText};
flex-wrap: wrap;
justify-content: center;
margin-top: 2px;
`;

interface ICoherence {
Expand All @@ -24,8 +25,8 @@ const Coherence: React.FC<ICoherence> = ({ totalCoherentVotes, totalResolvedVote

return (
<Container>
<Tooltip text={coherenceRatio}>
{getCoherencePercent(Number(totalCoherentVotes), Number(totalResolvedVotes))}
<Tooltip text={getCoherencePercent(Number(totalCoherentVotes), Number(totalResolvedVotes))}>
{coherenceRatio}
</Tooltip>
</Container>
);
Expand Down
16 changes: 9 additions & 7 deletions web/src/pages/Home/TopJurors/JurorCard/DesktopCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import JurorLevel from "./JurorLevel";
import JurorTitle from "./JurorTitle";
import Rank from "./Rank";
import Rewards from "./Rewards";
import Score from "./Score";

const Container = styled.div<{ renderRank?: boolean }>`
${hoverShortTransitionTiming}
Expand All @@ -26,9 +27,9 @@ const Container = styled.div<{ renderRank?: boolean }>`
() => css`
display: grid;
grid-template-columns: ${renderRank
? `min-content repeat(3, ${responsiveSize(160, 180, 900)}) auto`
: `repeat(3, ${responsiveSize(160, 180, 900)}) auto`};
column-gap: ${responsiveSize(12, 28, 900)};
? `min-content minmax(160px, 1fr) minmax(60px, 1fr) minmax(80px, 0.8fr) minmax(180px, 1.5fr) minmax(100px, 1fr)`
: `minmax(160px, 1fr) minmax(60px, 1fr) minmax(80px, 0.8fr) minmax(180px, 1.5fr) minmax(100px, 1fr)`};
column-gap: ${responsiveSize(12, 24, 900)};
`
)}

Expand All @@ -40,27 +41,28 @@ const Container = styled.div<{ renderRank?: boolean }>`
interface IDesktopCard {
rank?: number;
address: string;
coherenceScore: string;
totalCoherentVotes: string;
totalResolvedVotes: string;
totalResolvedDisputes: string;
}

const DesktopCard: React.FC<IDesktopCard> = ({
rank,
address,
coherenceScore,
totalCoherentVotes,
totalResolvedVotes,
totalResolvedDisputes,
}) => {
const renderRank = !!rank;

return (
<Container renderRank={renderRank}>
{renderRank && <Rank rank={rank} />}
<JurorTitle address={address} />
<Rewards address={address} />
<Score coherenceScore={coherenceScore} />
<Coherence {...{ totalCoherentVotes, totalResolvedVotes }} />
<JurorLevel {...{ totalCoherentVotes, totalResolvedVotes, totalResolvedDisputes }} />
<Rewards address={address} />
<JurorLevel coherenceScore={Number(coherenceScore)} />
</Container>
);
};
Expand Down
10 changes: 3 additions & 7 deletions web/src/pages/Home/TopJurors/JurorCard/JurorLevel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import styled, { css } from "styled-components";
import { landscapeStyle } from "styles/landscapeStyle";

import { getUserLevelData } from "utils/userLevelCalculation";
import { getCoherencePercent } from "utils/getCoherencePercent";

import PixelArt from "pages/Profile/JurorInfo/PixelArt";

Expand Down Expand Up @@ -40,14 +39,11 @@ const StyledLabel = styled.label`
`;

interface IJurorLevel {
totalCoherentVotes: string;
totalResolvedVotes: string;
totalResolvedDisputes: string;
coherenceScore: number;
}

const JurorLevel: React.FC<IJurorLevel> = ({ totalCoherentVotes, totalResolvedVotes, totalResolvedDisputes }) => {
const coherencePercentage = getCoherencePercent(Number(totalCoherentVotes), Number(totalResolvedVotes));
const userLevelData = getUserLevelData(coherencePercentage, Number(totalResolvedDisputes));
const JurorLevel: React.FC<IJurorLevel> = ({ coherenceScore }) => {
const userLevelData = getUserLevelData(coherenceScore);
const level = userLevelData.level;

return (
Expand Down
Loading
Loading