import { QuestionFragment } from "../../../fragments.generated"; import { Stars } from "../Stars"; type QualityIndicator = QuestionFragment["qualityIndicators"]; type IndicatorName = keyof QualityIndicator; // this duplication can probably be simplified with typescript magic, but this is good enough for now export type UsedIndicatorName = // | "numForecasts" // | "stars" | "volume" | "numForecasters" | "spread" | "sharesVolume" | "liquidity" | "tradeVolume" | "openInterest"; export const qualityIndicatorLabels: { [k in UsedIndicatorName]: string } = { // numForecasts: "Number of forecasts", // stars: "Stars", // yesBid: "Yes bid", // yesAsk: "Yes ask", volume: "Volume", numForecasters: "Forecasters", spread: "Spread", sharesVolume: "Shares vol.", liquidity: "Liquidity", tradeVolume: "Volume", openInterest: "Interest", }; const isUsedIndicatorName = (name: string): name is UsedIndicatorName => { return name in qualityIndicatorLabels; }; const formatNumber = (num: number) => { if (num < 1000) { return num.toFixed(0); } else if (num < 10000) { return (num / 1000).toFixed(1) + "k"; } else { return (num / 1000).toFixed(0) + "k"; } }; /* Display functions*/ const getPercentageSymbolIfNeeded = ({ indicator, platform, }: { indicator: UsedIndicatorName; platform: string; }) => { let indicatorsWhichNeedPercentageSymbol: IndicatorName[] = ["spread"]; if (indicatorsWhichNeedPercentageSymbol.includes(indicator)) { return "%"; } else { return ""; } }; const getCurrencySymbolIfNeeded = ({ indicator, platform, }: { indicator: UsedIndicatorName; platform: string; }) => { const indicatorsWhichNeedCurrencySymbol: IndicatorName[] = [ "volume", "tradeVolume", "openInterest", "liquidity", ]; let dollarPlatforms = ["predictit", "kalshi", "polymarket", "insight"]; if (indicatorsWhichNeedCurrencySymbol.includes(indicator)) { if (dollarPlatforms.includes(platform)) { return "$"; } else { return "£"; } } else { return ""; } }; const FirstQualityIndicator: React.FC<{ question: QuestionFragment; }> = ({ question }) => { if (question.qualityIndicators.numForecasts) { return (
Forecasts:  {Number(question.qualityIndicators.numForecasts).toFixed(0)}
); } else { return null; } }; export const formatIndicatorValue = ( value: number, indicator: UsedIndicatorName, platform: string ): string => { return `${getCurrencySymbolIfNeeded({ indicator, platform: platform, })}${formatNumber(value)}${getPercentageSymbolIfNeeded({ indicator, platform: platform, })}`; }; const QualityIndicatorsList: React.FC<{ question: QuestionFragment; }> = ({ question }) => { return (
{Object.entries(question.qualityIndicators).map( ([indicator, value], i) => { if (!isUsedIndicatorName(indicator)) return; const indicatorLabel = qualityIndicatorLabels[indicator]; if (!indicatorLabel || value === null) return; return (
{indicatorLabel}:  {formatIndicatorValue( Number(value), indicator, question.platform.id )}
); } )}
); }; interface Props { question: QuestionFragment; expandFooterToFullWidth: boolean; } export const QuestionFooter: React.FC = ({ question, expandFooterToFullWidth, }) => { return (
{question.platform.label .replace("Good Judgment Open", "GJOpen") .replace(/ /g, "\u00a0")}
); };