Merge pull request #11 from foretold-app/improvements/1086

Improvements/1086
This commit is contained in:
Ozzie Gooen 2020-02-28 20:39:47 +00:00 committed by GitHub
commit 6a86346b23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 116 additions and 84 deletions

View File

@ -1,7 +1,10 @@
// "mm(floor(uniform(30,35)), normal(50,20), [.25,.5])",
// "mm(floor(normal(28,4)), normal(32,2), uniform(20,24), [.5,.2,.1])",
// Examples:
// mm(floor(uniform(30,35)), normal(50,20), [.25,.5])
// mm(floor(normal(28,4)), normal(32,2), uniform(20,24), [.5,.2,.1])
// mm(5 to 20, floor(normal(20,2)), [.5, .5])"
// floor(3 to 4)
// uniform(0,1) > 0.3 ? lognormal(6.652, -0.41): 0
// "mm(5 to 20, floor(normal(20,2)), [.5, .5])",
let timeDist =
DistPlusIngredients.make(
~guesstimatorString="(floor(10 to 15))",
@ -36,4 +39,4 @@ let distributions = () =>
</div>
</div>;
let entry = EntryTypes.(entry(~title="Pdf", ~render=distributions));
let entry = EntryTypes.(entry(~title="Pdf", ~render=distributions));

View File

@ -375,60 +375,68 @@ let make = () => {
}
/>
</Col>
<Col span=4>
<Form.Field
field=FormConfig.Zero
render={({handleChange, value}) =>
<Antd.Form.Item label={"Zero Point" |> E.ste}>
<Antd_DatePicker
value
onChange={e => {
e |> handleChange;
_ => ();
}}
/>
</Antd.Form.Item>
}
/>
</Col>
<Col span=4>
<Form.Field
field=FormConfig.Unit
render={({handleChange, value}) =>
<Antd.Form.Item label={"Unit" |> E.ste}>
<Antd.Select value onChange={e => e |> handleChange}>
<Antd.Select.Option value="days">
{"Days" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="hours">
{"Hours" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="milliseconds">
{"Milliseconds" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="minutes">
{"Minutes" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="months">
{"Months" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="quarters">
{"Quarters" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="seconds">
{"Seconds" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="weeks">
{"Weeks" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="years">
{"Years" |> E.ste}
</Antd.Select.Option>
</Antd.Select>
</Antd.Form.Item>
}
/>
</Col>
{<>
<Col span=4>
<Form.Field
field=FormConfig.Zero
render={({handleChange, value}) =>
<Antd.Form.Item label={"Zero Point" |> E.ste}>
<Antd_DatePicker
value
onChange={e => {
e |> handleChange;
_ => ();
}}
/>
</Antd.Form.Item>
}
/>
</Col>
<Col span=4>
<Form.Field
field=FormConfig.Unit
render={({handleChange, value}) =>
<Antd.Form.Item label={"Unit" |> E.ste}>
<Antd.Select value onChange={e => e |> handleChange}>
<Antd.Select.Option value="days">
{"Days" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="hours">
{"Hours" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="milliseconds">
{"Milliseconds" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="minutes">
{"Minutes" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="months">
{"Months" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="quarters">
{"Quarters" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="seconds">
{"Seconds" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="weeks">
{"Weeks" |> E.ste}
</Antd.Select.Option>
<Antd.Select.Option value="years">
{"Years" |> E.ste}
</Antd.Select.Option>
</Antd.Select>
</Antd.Form.Item>
}
/>
</Col>
</>
|> E.showIf(
E.L.contains(
reform.state.values.unitType,
["TimeDistribution"],
),
)}
</Row>
<Row _type=`flex className=Styles.rows>
<Col span=4>
@ -453,4 +461,4 @@ let make = () => {
</Antd.Card>
<div className=Styles.spacer />
</div>;
};
};

View File

@ -34,8 +34,7 @@ module Styles = {
module DemoDist = {
[@react.component]
let make = (~guesstimatorString: string) => {
let (ys, xs) =
DistEditor.getPdfFromUserInput("normal(1, 1) / normal(10, 1)");
let (ys, xs) = DistEditor.getPdfFromUserInput(guesstimatorString);
let continuous: DistTypes.xyShape = {xs, ys};
<Antd.Card title={"Distribution" |> E.ste}>
<div className=Styles.spacer />

View File

@ -109,22 +109,28 @@ export class CdfChartD3 {
`translate(${this.calc.chartLeftMargin}, ${this.calc.chartTopMargin})`,
);
const common = this.getCommonThings();
if (this.hasDate('continuous')) {
const distributionChart = this.addDistributionChart();
if (this.hasDate('discrete')) {
this.addLollipopsChart(distributionChart);
}
this.addDistributionChart(common);
}
if (this.hasDate('discrete')) {
this.addLollipopsChart(common);
}
return this;
}
addDistributionChart() {
const areaColorRange = d3.scaleOrdinal().range(this.attrs.areaColors);
const dataPoints = [this.getDataPoints('continuous')];
/**
* @returns {*}
*/
getCommonThings() {
// Boundaries.
const xMin = this.attrs.minX || d3.min(this.attrs.data.continuous.xs) || d3.min(this.attrs.data.discrete.xs);
const xMax = this.attrs.maxX || d3.max(this.attrs.data.continuous.xs) || d3.max(this.attrs.data.discrete.xs);
const xMin = this.attrs.minX
|| d3.min(this.attrs.data.continuous.xs)
|| d3.min(this.attrs.data.discrete.xs);
const xMax = this.attrs.maxX
|| d3.max(this.attrs.data.continuous.xs)
|| d3.max(this.attrs.data.discrete.xs);
const yMin = d3.min(this.attrs.data.continuous.ys);
const yMax = d3.max(this.attrs.data.continuous.ys);
@ -150,6 +156,21 @@ export class CdfChartD3 {
.domain([yMinDomain, yMaxDomain])
.range([this.calc.chartHeight, 0]);
return {
xMin, xMax,
xScale, yScale,
};
}
/**
* @param common
*/
addDistributionChart(common) {
const areaColorRange = d3.scaleOrdinal().range(this.attrs.areaColors);
const dataPoints = [this.getDataPoints('continuous')];
const { xMin, xMax, xScale, yScale } = common;
// X-axis.
let xAxis = null;
if (!!this.attrs.timeScale) {
@ -287,16 +308,14 @@ export class CdfChartD3 {
.on('mousemove', mouseover)
.on('mouseout', mouseout);
}
return { xScale, yScale };
}
/**
* @param {object} distributionChart
* @param {object} distributionChart.xScale
* @param {object} distributionChart.yScale
* @param {object} common
* @param {object} common.xScale
* @param {object} common.yScale
*/
addLollipopsChart(distributionChart) {
addLollipopsChart(common) {
const data = this.getDataPoints('discrete');
const _yMin = d3.min(this.attrs.data.discrete.ys);
@ -306,7 +325,7 @@ export class CdfChartD3 {
this.chart.append('g')
.attr('class', 'lollipops-x-axis')
.attr('transform', `translate(0, ${this.calc.chartHeight})`)
.call(d3.axisBottom(distributionChart.xScale));
.call(d3.axisBottom(common.xScale));
// Y-domain.
const yMaxDomainFactor = _.get(this.attrs, 'yMaxDiscreteDomainFactor', 1);
@ -333,7 +352,7 @@ export class CdfChartD3 {
tooltip.transition()
.style('opacity', .9);
tooltip.html(`X: ${d.x}, Y: ${d.y}`)
.style('left', (distributionChart.xScale(d.x) + 60) + 'px')
.style('left', (common.xScale(d.x) + 60) + 'px')
.style('top', yScale(d.y) + 'px');
}
@ -354,8 +373,8 @@ export class CdfChartD3 {
.append('line')
.attr('class', 'lollipops-line')
.attr('id', d => 'lollipops-line-' + d.id)
.attr('x1', d => distributionChart.xScale(d.x))
.attr('x2', d => distributionChart.xScale(d.x))
.attr('x1', d => common.xScale(d.x))
.attr('x2', d => common.xScale(d.x))
.attr('y1', d => yScale(d.y))
.attr('y2', yScale(0));
@ -371,7 +390,7 @@ export class CdfChartD3 {
.append('circle')
.attr('class', 'lollipops-circle')
.attr('id', d => 'lollipops-circle-' + d.id)
.attr('cx', d => distributionChart.xScale(d.x))
.attr('cx', d => common.xScale(d.x))
.attr('cy', d => yScale(d.y))
.attr('r', '4');
@ -382,7 +401,7 @@ export class CdfChartD3 {
.append('rect')
.attr('width', 30)
.attr('height', this.calc.chartHeight)
.attr('x', d => distributionChart.xScale(d.x) - 15)
.attr('x', d => common.xScale(d.x) - 15)
.attr('y', 0)
.attr('opacity', 0)
.attr('pointer-events', 'all')
@ -439,7 +458,10 @@ export class CdfChartD3 {
const len = data.xs.length;
for (let i = 0; i < len; i++) {
dt.push({ x: data.xs[i], y: data.ys[i], id: i });
const x = data.xs[i];
const y = data.ys[i];
const id = i;
dt.push({ x, y, id });
}
return dt;