Fix & reactify according to James's review
This commit is contained in:
parent
57e799e8d3
commit
1e236afba7
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
{props.entries.map((entry, i) => (
|
||||||
<tr key={i}>
|
<tr key={i}>
|
||||||
<th>{i + 1}</th>
|
<th>{i + 1}</th>
|
||||||
{toRowStart(entry)}
|
<TableRowStart entry={entry} />
|
||||||
{toRowEnd(entry)}
|
<TableRowEnd entry={entry} />
|
||||||
</tr>
|
</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>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user