import React, { useMemo, useState } from 'react' import { DatumValue } from '@nivo/core' import { ResponsiveLine } from '@nivo/line' import { Entry, makeEntries } from 'web/lib/simulator/entries' import { Col } from 'web/components/layout/col' function TableBody(props: { entries: Entry[] }) { return ( {props.entries.map((entry, i) => ( {props.entries.length - i} ))} ) } function TableRowStart(props: { entry: Entry }) { const { entry } = props if (entry.yesBid && entry.noBid) { return ( <>
ANTE
${entry.yesBid} / ${entry.noBid} ) } else if (entry.yesBid) { return ( <>
YES
${entry.yesBid} ) } else { return ( <>
NO
${entry.noBid} ) } } function TableRowEnd(props: { entry: Entry | null; isNew?: boolean }) { const { entry } = props if (!entry) { return ( <> 0 0 {!props.isNew && ( <> N/A N/A )} ) } else if (entry.yesBid && entry.noBid) { return ( <> {(entry.prob * 100).toFixed(1)}% N/A {!props.isNew && ( <> N/A N/A )} ) } else if (entry.yesBid) { return ( <> {(entry.prob * 100).toFixed(1)}% ${entry.yesWeight.toFixed(0)} {!props.isNew && ( <> ${entry.yesPayout.toFixed(0)} {(entry.yesReturn * 100).toFixed(0)}% )} ) } else { return ( <> {(entry.prob * 100).toFixed(1)}% ${entry.noWeight.toFixed(0)} {!props.isNew && ( <> ${entry.noPayout.toFixed(0)} {(entry.noReturn * 100).toFixed(0)}% )} ) } } type Bid = { yesBid: number; noBid: number } function NewBidTable(props: { steps: number bids: Array setSteps: (steps: number) => void setBids: (bids: Array) => 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') } const nextBid = makeBid(newBidType, newBid) const fakeBids = [...bids.slice(0, steps), nextBid] const entries = makeEntries(fakeBids) const nextEntry = entries[entries.length - 1] function randomBid() { const bidType = Math.random() < 0.5 ? 'YES' : 'NO' // const p = bidType === 'YES' ? nextEntry.prob : 1 - nextEntry.prob const amount = Math.floor(Math.random() * 300) + 1 const bid = makeBid(bidType, amount) bids.splice(steps, 0, bid) setBids(bids) setSteps(steps + 1) setNewBid(0) } return ( <>
Order # Type Bet Prob Est Payout
{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(1) const [bids, setBids] = useState([{ yesBid: 100, noBid: 100 }]) const entries = useMemo( () => makeEntries(bids.slice(0, steps)), [bids, steps] ) const reversedEntries = [...entries].reverse() const probs = entries.map((entry) => entry.prob) const points = probs.map((prob, i) => ({ x: i + 1, y: prob * 100 })) const data = [{ id: 'Yes', data: points, color: '#11b981' }] const tickValues = [0, 25, 50, 75, 100] return (
{/* Left column */}

Dynamic Parimutuel Market Simulator

{/* History of bids */}
Order # Type Bet Prob Est Payout Payout Return
{/* Right column */}

Probability of
YES

{/* Range slider that sets the current step */} setSteps(parseInt(e.target.value))} />
) } function formatPercent(y: DatumValue) { return `${Math.round(+y.toString())}%` }