Make log scale PN charts work properly

This commit is contained in:
Marshall Polaris 2022-09-27 15:25:34 -07:00
parent 2eba78bf2b
commit 681c572ef2
2 changed files with 28 additions and 14 deletions

View File

@ -11,14 +11,23 @@ import { MARGIN_X, MARGIN_Y, getDateRange } from '../helpers'
import { SingleValueHistoryChart } from '../generic-charts' import { SingleValueHistoryChart } from '../generic-charts'
import { useElementWidth } from 'web/hooks/use-element-width' import { useElementWidth } from 'web/hooks/use-element-width'
// mqp: note that we have an idiosyncratic version of 'log scale'
// contracts. the values are stored "linearly" and can include zero.
// as a result, we have to do some weird-looking stuff in this code
const getChartData = ( const getChartData = (
contract: PseudoNumericContract, contract: PseudoNumericContract,
bets: Bet[], bets: Bet[],
start: Date, start: Date,
end: Date end: Date
) => { ) => {
const { min, max } = contract const { min, max, isLogScale } = contract
const getY = (p: number) => p * (max - min) + min const getY = (p: number) =>
isLogScale
? 10 ** (p * Math.log10(contract.max - contract.min + 1)) +
contract.min -
1
: p * (max - min) + min
const sortedBets = sortBy(bets, (b) => b.createdTime) const sortedBets = sortBy(bets, (b) => b.createdTime)
const startProb = getInitialProbability(contract) const startProb = getInitialProbability(contract)
const endProb = getProbability(contract) const endProb = getProbability(contract)
@ -46,9 +55,14 @@ export const PseudoNumericContractChart = (props: {
const containerRef = useRef<HTMLDivElement>(null) const containerRef = useRef<HTMLDivElement>(null)
const width = useElementWidth(containerRef) ?? 0 const width = useElementWidth(containerRef) ?? 0
const height = props.height ?? (isMobile ? 150 : 250) const height = props.height ?? (isMobile ? 150 : 250)
const scaleType = contract.isLogScale ? scaleLog : scaleLinear
const xScale = scaleTime([start, end], [0, width - MARGIN_X]) const xScale = scaleTime([start, end], [0, width - MARGIN_X])
const yScale = scaleType([contract.min, contract.max], [height - MARGIN_Y, 0]) const yScale = contract.isLogScale
? scaleLog(
[Math.max(contract.min, 1), contract.max],
[height - MARGIN_Y, 0]
).clamp(true) // make sure zeroes go to the bottom
: scaleLinear([contract.min, contract.max], [height - MARGIN_Y, 0])
return ( return (
<div ref={containerRef}> <div ref={containerRef}>
{width && ( {width && (

View File

@ -115,7 +115,7 @@ export const SingleValueDistributionChart = (props: {
useState<PositionValue<DistributionPoint>>() useState<PositionValue<DistributionPoint>>()
const px = useCallback((p: DistributionPoint) => xScale(p[0]), [xScale]) const px = useCallback((p: DistributionPoint) => xScale(p[0]), [xScale])
const py0 = yScale(0) const py0 = yScale(yScale.domain()[0])
const py1 = useCallback((p: DistributionPoint) => yScale(p[1]), [yScale]) const py1 = useCallback((p: DistributionPoint) => yScale(p[1]), [yScale])
const xBisector = bisector((p: DistributionPoint) => p[0]) const xBisector = bisector((p: DistributionPoint) => p[0])
@ -209,11 +209,11 @@ export const MultiValueHistoryChart = (props: {
const fmtY = (n: number) => (pct ? formatPct(n, 0) : formatLargeNumber(n)) const fmtY = (n: number) => (pct ? formatPct(n, 0) : formatLargeNumber(n))
const [min, max] = yScale.domain() const [min, max] = yScale.domain()
const tickValues = getTickValues(min, max, h < 200 ? 3 : 5) const pctTickValues = getTickValues(min, max, h < 200 ? 3 : 5)
const xAxis = axisBottom<Date>(xScale) const xAxis = axisBottom<Date>(xScale)
const yAxis = axisLeft<number>(yScale) const yAxis = pct
.tickValues(tickValues) ? axisLeft<number>(yScale).tickValues(pctTickValues).tickFormat(fmtY)
.tickFormat(fmtY) : axisLeft<number>(yScale)
return { fmtX, fmtY, xAxis, yAxis } return { fmtX, fmtY, xAxis, yAxis }
}, [h, pct, xScale, yScale]) }, [h, pct, xScale, yScale])
@ -311,7 +311,7 @@ export const SingleValueHistoryChart = (props: {
const [mouseState, setMouseState] = useState<PositionValue<HistoryPoint>>() const [mouseState, setMouseState] = useState<PositionValue<HistoryPoint>>()
const px = useCallback((p: HistoryPoint) => xScale(p[0]), [xScale]) const px = useCallback((p: HistoryPoint) => xScale(p[0]), [xScale])
const py0 = yScale(0) const py0 = yScale(yScale.domain()[0])
const py1 = useCallback((p: HistoryPoint) => yScale(p[1]), [yScale]) const py1 = useCallback((p: HistoryPoint) => yScale(p[1]), [yScale])
const xBisector = bisector((p: HistoryPoint) => p[0]) const xBisector = bisector((p: HistoryPoint) => p[0])
@ -321,11 +321,11 @@ export const SingleValueHistoryChart = (props: {
const fmtY = (n: number) => (pct ? formatPct(n, 0) : formatLargeNumber(n)) const fmtY = (n: number) => (pct ? formatPct(n, 0) : formatLargeNumber(n))
const [min, max] = yScale.domain() const [min, max] = yScale.domain()
const tickValues = getTickValues(min, max, h < 200 ? 3 : 5) const pctTickValues = getTickValues(min, max, h < 200 ? 3 : 5)
const xAxis = axisBottom<Date>(xScale) const xAxis = axisBottom<Date>(xScale)
const yAxis = axisLeft<number>(yScale) const yAxis = pct
.tickValues(tickValues) ? axisLeft<number>(yScale).tickValues(pctTickValues).tickFormat(fmtY)
.tickFormat(fmtY) : axisLeft<number>(yScale)
return { fmtX, fmtY, xAxis, yAxis } return { fmtX, fmtY, xAxis, yAxis }
}, [h, pct, xScale, yScale]) }, [h, pct, xScale, yScale])