import React, { useEffect, useMemo, useState } from 'react' import { CategoryScale, Chart, LinearScale, PointElement, LineElement, Title, Tooltip, Legend, } from 'chart.js' import { Line } from 'react-chartjs-2' import { bids as sampleBids } from '../../lib/simulator/sample-bids' import { Entry, makeEntries } from '../../lib/simulator/entries' import { Header } from '../../components/header' // Auto import doesn't work for some reason... // So we manually register ChartJS components instead: Chart.register( CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend ) function TableBody(props: { entries: Entry[] }) { return ( {props.entries.map((entry, i) => ( {i + 1} ))} ) } function TableRowStart(props: { entry: Entry }) { const { entry } = props if (entry.yesBid && entry.noBid) { return ( <>
SEED
{entry.yesBid} / {entry.noBid} ) } else if (entry.yesBid) { return ( <>
YES
{entry.yesBid} ) } else { return ( <>
NO
{entry.noBid} ) } } function TableRowEnd(props: { entry: Entry | null }) { const { entry } = props if (!entry) { return ( <> N/A N/A N/A N/A ) } else if (entry.yesBid && entry.noBid) { return ( <> N/A {entry.prob.toFixed(2)} N/A N/A ) } else if (entry.yesBid) { return ( <> {entry.yesWeight.toFixed(2)} {entry.prob.toFixed(2)} {entry.yesPayout.toFixed(2)} {(entry.yesReturn * 100).toFixed(2)}% ) } else { return ( <> {entry.noWeight.toFixed(2)} {entry.prob.toFixed(2)} {entry.noPayout.toFixed(2)} {(entry.noReturn * 100).toFixed(2)}% ) } } function NewBidTable(props: { steps: number bids: any[] setSteps: (steps: number) => void setBids: (bids: any[]) => void }) { const { steps, bids, setSteps, setBids } = props // Prepare for new bids const [newBid, setNewBid] = useState(0) const [newBidType, setNewBidType] = useState('YES') function makeBid(type: string, bid: number) { return { yesBid: type == 'YES' ? bid : 0, noBid: type == 'YES' ? 0 : bid, } } function submitBid() { if (newBid <= 0) return const bid = makeBid(newBidType, newBid) bids.splice(steps, 0, bid) setBids(bids) setSteps(steps + 1) setNewBid(0) } function toggleBidType() { setNewBidType(newBidType === 'YES' ? 'NO' : 'YES') } let nextEntry: Entry | null = null if (newBid) { const nextBid = makeBid(newBidType, newBid) const fakeBids = [...bids.slice(0, steps), nextBid] const entries = makeEntries(fakeBids) nextEntry = entries[entries.length - 1] } return (
Order # Type Bid Weight Prob Payout Return
{steps + 1}
YES

NO
{/* Note: Would love to make this input smaller... */} setNewBid(parseInt(e.target.value) || 0)} onKeyUp={(e) => { if (e.key === 'Enter') { submitBid() } }} onFocus={(e) => e.target.select()} />
) } // Show a hello world React page export default function Simulator() { const [steps, setSteps] = useState(10) const [bids, setBids] = useState(sampleBids) const entries = useMemo( () => makeEntries(bids.slice(0, steps)), [bids, steps] ) const probs = entries.map((entry) => entry.prob) const chartData = { labels: Array.from({ length: steps }, (_, i) => i + 1), datasets: [ { label: 'Implied probability', data: probs, borderColor: 'rgb(75, 192, 192)', }, ], } return (
{/* Left column */}

Dynamic Parimutuel Market Simulator

{/* Range slider that sets the current step */} setSteps(parseInt(e.target.value))} /> {/* History of bids */}
Order # Type Bid Weight Prob Max Payout Return
{/* Right column */}

Probability of
YES

) }