manifold/web/components/charts/contract/numeric.tsx
Marshall Polaris e0d9b4d335
Rewrite contract graphs (#935)
* Fiddle around with everything, WIP FR charts

* Implement numeric chart

* Reorganize everything into neat little files

* Add `AreaWithTopStroke` helper

* Tidying, don't gratuitously use d3.format

* Remove duplicate code

* Better tooltip bisection

* `NumericPoint` -> `DistributionPoint`

* Add numeric market tooltip

* Make numeric chart bucket points less wrong

* Clean up numeric bucket computation

* Clean up a bunch of tooltip stuff, add FR legend tooltips

* Fix a dumb bug

* Implement basic time selection

* Fix fishy Date.now inconsistency bugs

* Might as well show all the FR outcomes now

* Make tooltips accurate on curveStepAfter charts

* Make log scale PN charts work properly

* Adjust x-axis tick count

* Display tooltip on charts only for mouse

* Fix up deps

* Tighter chart tooltips

* Adjustments to chart time range management

* Better date formatting

* Continue tweaking time selection handling to be perfect

* Make FR charts taller by default
2022-09-27 20:24:42 -07:00

53 lines
1.7 KiB
TypeScript

import { useMemo, useRef } from 'react'
import { max, range } from 'lodash'
import { scaleLinear } from 'd3'
import { getDpmOutcomeProbabilities } from 'common/calculate-dpm'
import { NumericContract } from 'common/contract'
import { NUMERIC_GRAPH_COLOR } from 'common/numeric-constants'
import { useIsMobile } from 'web/hooks/use-is-mobile'
import { MARGIN_X, MARGIN_Y } from '../helpers'
import { SingleValueDistributionChart } from '../generic-charts'
import { useElementWidth } from 'web/hooks/use-element-width'
const getNumericChartData = (contract: NumericContract) => {
const { totalShares, bucketCount, min, max } = contract
const step = (max - min) / bucketCount
const bucketProbs = getDpmOutcomeProbabilities(totalShares)
return range(bucketCount).map(
(i) => [min + step * (i + 0.5), bucketProbs[`${i}`]] as const
)
}
export const NumericContractChart = (props: {
contract: NumericContract
height?: number
}) => {
const { contract } = props
const data = useMemo(() => getNumericChartData(contract), [contract])
const isMobile = useIsMobile(800)
const containerRef = useRef<HTMLDivElement>(null)
const width = useElementWidth(containerRef) ?? 0
const height = props.height ?? (isMobile ? 150 : 250)
const maxY = max(data.map((d) => d[1])) as number
const xScale = scaleLinear(
[contract.min, contract.max],
[0, width - MARGIN_X]
)
const yScale = scaleLinear([0, maxY], [height - MARGIN_Y, 0])
return (
<div ref={containerRef}>
{width && (
<SingleValueDistributionChart
w={width}
h={height}
xScale={xScale}
yScale={yScale}
data={data}
color={NUMERIC_GRAPH_COLOR}
/>
)}
</div>
)
}