Skip to content

Commit

Permalink
Merge pull request #10349 from ethereum/localiseQuizStats
Browse files Browse the repository at this point in the history
Localise number formatting in quiz stats
  • Loading branch information
nhsz authored Jun 6, 2023
2 parents 970ffda + e0475c2 commit 2e8627c
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 11 deletions.
28 changes: 18 additions & 10 deletions src/components/Quiz/QuizzesStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@ import {
Text,
} from "@chakra-ui/react"
import { FaTwitter } from "react-icons/fa"
import { useI18next } from "gatsby-plugin-react-i18next"

import Button from "../Button"
import Translation from "../Translation"
import { TrophyIcon } from "../icons/quiz"

import { QuizzesHubContext } from "./context"

// Utils
import {
getFormattedStats,
getNumberOfCompletedQuizzes,
getTotalQuizzesPoints,
shareOnTwitter,
Expand All @@ -42,24 +45,26 @@ const handleShare = ({ score, total }: QuizShareStats) => {
}

const QuizzesStats: React.FC = () => {
const { language } = useI18next()
const {
userStats: { score: userScore, completed, average },
} = useContext(QuizzesHubContext)
const numberOfCompletedQuizzes = getNumberOfCompletedQuizzes(
JSON.parse(completed)
)

const computedAverage =
average.length > 0 ? average.reduce((a, b) => a + b, 0) / average.length : 0
const parsedAverage = Number.isInteger(computedAverage)
? computedAverage
: computedAverage.toFixed(2)

// These values are not fixed but calculated each time, can't be moved to /constants
const totalQuizzesNumber =
ethereumBasicsQuizzes.length + usingEthereumQuizzes.length
const totalQuizzesPoints = getTotalQuizzesPoints()

const {
formattedUserAverageScore,
formattedCollectiveQuestionsAnswered,
formattedCollectiveAverageScore,
formattedCollectiveRetryRate,
} = getFormattedStats(language, average)

return (
<Box flex={1} order={{ base: 1, lg: 2 }} w="full">
<Stack mt={{ base: 0, lg: 12 }} gap={{ base: 8, lg: 4 }}>
Expand Down Expand Up @@ -127,7 +132,7 @@ const QuizzesStats: React.FC = () => {
<Text mr={10} mb={0} mt={{ base: 2, lg: 0 }} color="bodyMedium">
<Translation id="average-score" />{" "}
<Text as="span" color="body">
{parsedAverage}%
{formattedUserAverageScore}
</Text>
</Text>

Expand Down Expand Up @@ -165,7 +170,7 @@ const QuizzesStats: React.FC = () => {
<Translation id="average-score" />
</Text>
{/* Data from Matomo, manually updated */}
<Text color="body">67.4%</Text>
<Text color="body">{formattedCollectiveAverageScore}</Text>
</Stack>

<Stack>
Expand All @@ -174,7 +179,10 @@ const QuizzesStats: React.FC = () => {
</Text>

{/* Data from Matomo, manually updated */}
<Text color="body">100 000+</Text>
<Text color="body">
{formattedCollectiveQuestionsAnswered}
<Text as="span">+</Text>
</Text>
</Stack>

<Stack>
Expand All @@ -183,7 +191,7 @@ const QuizzesStats: React.FC = () => {
</Text>

{/* Data from Matomo, manually updated */}
<Text color="body">15.6%</Text>
<Text color="body">{formattedCollectiveRetryRate}</Text>
</Stack>
</Flex>
</Flex>
Expand Down
49 changes: 48 additions & 1 deletion src/components/Quiz/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { USER_STATS_KEY } from "../../constants"
import { getLocaleForNumberFormat } from "../../utils/translations"
import { Lang } from "../../utils/languages"

import { CompletedQuizzes, QuizShareStats } from "../../types"

import {
TOTAL_QUIZ_AVERAGE_SCORE,
TOTAL_QUIZ_QUESTIONS_ANSWERED,
TOTAL_QUIZ_RETRY_RATE,
USER_STATS_KEY,
} from "../../constants"

import allQuizzesData, {
ethereumBasicsQuizzes,
usingEthereumQuizzes,
Expand Down Expand Up @@ -85,3 +93,42 @@ export const shareOnTwitter = ({ score, total }: QuizShareStats): void => {
`https://twitter.com/intent/tweet?text=${tweet}&hashtags=${hashtags}`
)
}

const mean = (values: number[]) =>
values.length > 0 ? values.reduce((a, b) => a + b, 0) / values.length : 0

export const getFormattedStats = (language, average) => {
const localeForNumbers = getLocaleForNumberFormat(language as Lang)

// Initialize number and percent formatters
const numberFormatter = new Intl.NumberFormat(localeForNumbers, {
style: "decimal",
minimumSignificantDigits: 1,
maximumSignificantDigits: 3,
})

const percentFormatter = new Intl.NumberFormat(localeForNumbers, {
style: "percent",
minimumSignificantDigits: 1,
maximumSignificantDigits: 3,
})

const computedAverage = average.length > 0 ? mean(average) : 0

// Convert collective stats to fraction for percentage format
const normalizedCollectiveAverageScore = TOTAL_QUIZ_AVERAGE_SCORE / 100
const normalizedCollectiveRetryRate = TOTAL_QUIZ_RETRY_RATE / 100

return {
formattedUserAverageScore: percentFormatter.format(computedAverage / 100), // Normalize user average
formattedCollectiveQuestionsAnswered: numberFormatter.format(
TOTAL_QUIZ_QUESTIONS_ANSWERED
),
formattedCollectiveAverageScore: percentFormatter.format(
normalizedCollectiveAverageScore
),
formattedCollectiveRetryRate: percentFormatter.format(
normalizedCollectiveRetryRate
),
}
}
3 changes: 3 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ export const PROGRESS_BAR_GAP = "4px"
export const PASSING_QUIZ_SCORE = 65
export const USER_STATS_KEY = "quizzes-stats"
export const INITIAL_QUIZ = "what-is-ethereum"
export const TOTAL_QUIZ_QUESTIONS_ANSWERED = 100000
export const TOTAL_QUIZ_AVERAGE_SCORE = 67.4
export const TOTAL_QUIZ_RETRY_RATE = 15.6

0 comments on commit 2e8627c

Please sign in to comment.