Fix & reactify according to James's review

This commit is contained in:
Austin Chen 2021-12-07 14:52:03 -08:00
parent 57e799e8d3
commit 1e236afba7
2 changed files with 61 additions and 53 deletions

View File

@ -13,8 +13,8 @@ export type Entry = {
prob: number prob: number
} }
export function makeEntries(bids: Bid[]): Entry[] { function makeWeights(bids: Bid[]) {
const entries: Entry[] = [] const weights = []
let yesPot = 0 let yesPot = 0
let noPot = 0 let noPot = 0
// First pass: calculate all the weights // First pass: calculate all the weights
@ -28,33 +28,36 @@ export function makeEntries(bids: Bid[]): Entry[] {
noPot += noBid noPot += noBid
const prob = yesPot / (yesPot + noPot) const prob = yesPot / (yesPot + noPot)
entries.push({ weights.push({
yesBid, yesBid,
noBid, noBid,
yesWeight, yesWeight,
noWeight, noWeight,
prob, prob,
// To be filled in below
yesPayout: 0,
noPayout: 0,
yesReturn: 0,
noReturn: 0,
}) })
} }
return weights
}
export function makeEntries(bids: Bid[]): Entry[] {
const YES_SEED = bids[0].yesBid const YES_SEED = bids[0].yesBid
const NO_SEED = bids[0].noBid const NO_SEED = bids[0].noBid
const yesWeightsSum = entries.reduce((sum, entry) => sum + entry.yesWeight, 0) const weights = makeWeights(bids)
const noWeightsSum = entries.reduce((sum, entry) => sum + entry.noWeight, 0) const yesPot = weights.reduce((sum, { yesBid }) => sum + yesBid, 0)
const noPot = weights.reduce((sum, { noBid }) => sum + noBid, 0)
const yesWeightsSum = weights.reduce((sum, entry) => sum + entry.yesWeight, 0)
const noWeightsSum = weights.reduce((sum, entry) => sum + entry.noWeight, 0)
// Second pass: calculate all the payouts // Second pass: calculate all the payouts
for (const entry of entries) { const entries: Entry[] = []
const { yesBid, noBid, yesWeight, noWeight } = entry for (const weight of weights) {
const { yesBid, noBid, yesWeight, noWeight } = weight
// Payout: You get your initial bid back, as well as your share of the // Payout: You get your initial bid back, as well as your share of the
// (noPot - seed) according to your yesWeight // (noPot - seed) according to your yesWeight
entry.yesPayout = yesBid + (yesWeight / yesWeightsSum) * (noPot - NO_SEED) const yesPayout = yesBid + (yesWeight / yesWeightsSum) * (noPot - NO_SEED)
entry.noPayout = noBid + (noWeight / noWeightsSum) * (yesPot - YES_SEED) const noPayout = noBid + (noWeight / noWeightsSum) * (yesPot - YES_SEED)
entry.yesReturn = (entry.yesPayout - yesBid) / yesBid const yesReturn = (yesPayout - yesBid) / yesBid
entry.noReturn = (entry.noPayout - noBid) / noBid const noReturn = (noPayout - noBid) / noBid
entries.push({ ...weight, yesPayout, noPayout, yesReturn, noReturn })
} }
return entries return entries
} }

View File

@ -1,4 +1,4 @@
import React, { Fragment, useEffect, useMemo, useState } from 'react' import React, { useEffect, useMemo, useState } from 'react'
import { import {
CategoryScale, CategoryScale,
Chart, Chart,
@ -26,97 +26,102 @@ Chart.register(
Legend Legend
) )
function toTable(entries: Entry[]) { function TableBody(props: { entries: Entry[] }) {
return entries.map((entry, i) => { return (
return ( <tbody>
<tr key={i}> {props.entries.map((entry, i) => (
<th>{i + 1}</th> <tr key={i}>
{toRowStart(entry)} <th>{i + 1}</th>
{toRowEnd(entry)} <TableRowStart entry={entry} />
</tr> <TableRowEnd entry={entry} />
) </tr>
}) ))}
</tbody>
)
} }
function toRowStart(entry: Entry) { function TableRowStart(props: { entry: Entry }) {
const { entry } = props
if (entry.yesBid && entry.noBid) { if (entry.yesBid && entry.noBid) {
return ( return (
<Fragment> <>
<td> <td>
<div className="badge">SEED</div> <div className="badge">SEED</div>
</td> </td>
<td> <td>
{entry.yesBid} / {entry.noBid} {entry.yesBid} / {entry.noBid}
</td> </td>
</Fragment> </>
) )
} else if (entry.yesBid) { } else if (entry.yesBid) {
return ( return (
<Fragment> <>
<td> <td>
<div className="badge badge-success">YES</div> <div className="badge badge-success">YES</div>
</td> </td>
<td>{entry.yesBid}</td> <td>{entry.yesBid}</td>
</Fragment> </>
) )
} else if (entry.noBid) { } else {
return ( return (
<Fragment> <>
<td> <td>
<div className="badge badge-error">NO</div> <div className="badge badge-error">NO</div>
</td> </td>
<td>{entry.noBid}</td> <td>{entry.noBid}</td>
</Fragment> </>
) )
} }
} }
function toRowEnd(entry: Entry | null) { function TableRowEnd(props: { entry: Entry | null }) {
const { entry } = props
if (!entry) { if (!entry) {
return ( return (
<Fragment> <>
<td>N/A</td> <td>N/A</td>
<td>N/A</td> <td>N/A</td>
<td>N/A</td> <td>N/A</td>
<td>N/A</td> <td>N/A</td>
</Fragment> </>
) )
} else if (entry.yesBid && entry.noBid) { } else if (entry.yesBid && entry.noBid) {
return ( return (
<Fragment> <>
<td>N/A</td> <td>N/A</td>
<td>{entry.prob.toFixed(2)}</td> <td>{entry.prob.toFixed(2)}</td>
<td>N/A</td> <td>N/A</td>
<td>N/A</td> <td>N/A</td>
</Fragment> </>
) )
} else if (entry.yesBid) { } else if (entry.yesBid) {
return ( return (
<Fragment> <>
<td>{entry.yesWeight.toFixed(2)}</td> <td>{entry.yesWeight.toFixed(2)}</td>
<td>{entry.prob.toFixed(2)}</td> <td>{entry.prob.toFixed(2)}</td>
<td>{entry.yesPayout.toFixed(2)}</td> <td>{entry.yesPayout.toFixed(2)}</td>
<td>{(entry.yesReturn * 100).toFixed(2)}%</td> <td>{(entry.yesReturn * 100).toFixed(2)}%</td>
</Fragment> </>
) )
} else { } else {
return ( return (
<Fragment> <>
<td>{entry.noWeight.toFixed(2)}</td> <td>{entry.noWeight.toFixed(2)}</td>
<td>{entry.prob.toFixed(2)}</td> <td>{entry.prob.toFixed(2)}</td>
<td>{entry.noPayout.toFixed(2)}</td> <td>{entry.noPayout.toFixed(2)}</td>
<td>{(entry.noReturn * 100).toFixed(2)}%</td> <td>{(entry.noReturn * 100).toFixed(2)}%</td>
</Fragment> </>
) )
} }
} }
function newBidTable( function NewBidTable(props: {
steps: number, steps: number
bids: any[], bids: any[]
setSteps: (steps: number) => void, setSteps: (steps: number) => void
setBids: (bids: any[]) => void setBids: (bids: any[]) => void
) { }) {
const { steps, bids, setSteps, setBids } = props
// Prepare for new bids // Prepare for new bids
const [newBid, setNewBid] = useState(0) const [newBid, setNewBid] = useState(0)
const [newBidType, setNewBidType] = useState('YES') const [newBidType, setNewBidType] = useState('YES')
@ -204,7 +209,7 @@ function newBidTable(
onFocus={(e) => e.target.select()} onFocus={(e) => e.target.select()}
/> />
</td> </td>
{toRowEnd(nextEntry)} <TableRowEnd entry={nextEntry} />
<td> <td>
<button <button
className="btn btn-primary" className="btn btn-primary"
@ -267,8 +272,7 @@ export default function Simulator() {
onChange={(e) => setSteps(parseInt(e.target.value))} onChange={(e) => setSteps(parseInt(e.target.value))}
/> />
{/* New bid table */} <NewBidTable {...{ steps, bids, setSteps, setBids }} />
{newBidTable(steps, bids, setSteps, setBids)}
{/* History of bids */} {/* History of bids */}
<div className="overflow-x-auto"> <div className="overflow-x-auto">
@ -284,7 +288,8 @@ export default function Simulator() {
<th>Return</th> <th>Return</th>
</tr> </tr>
</thead> </thead>
<tbody>{toTable(entries)}</tbody>
<TableBody entries={entries} />
</table> </table>
</div> </div>
</div> </div>