Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added sampleCount field to Calculator.make #2353

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/hip-carrots-laugh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@quri/squiggle-lang": patch
"@quri/squiggle-components": patch
---

Added sampleCount field to Calculator.make
28 changes: 21 additions & 7 deletions packages/components/src/components/Calculator/asyncActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,21 @@ import {
allFieldValuesAreValid,
} from "./calculatorReducer.js";

const getEnvironment = (
modelEnvironment: Env,
calculator: SqCalculator
): Env => ({
sampleCount: calculator.sampleCount || modelEnvironment.sampleCount,
xyPointLength: modelEnvironment.xyPointLength,
});

const runSquiggleCode = async (
code: string,
environment: Env
environment: Env,
calculator: SqCalculator
): Promise<result<SqValue, SqError>> => {
const project = SqProject.create();
if (environment) {
project.setEnvironment(environment);
}
project.setEnvironment(getEnvironment(environment, calculator));
const sourceId = "calculator";
project.setSource(sourceId, code);
await project.run(sourceId);
Expand Down Expand Up @@ -55,7 +62,10 @@ export const updateFnValue = ({
throw new Error("Invalid result encountered.");
}
});
finalResult = calculator.run(results, environment);
finalResult = calculator.run(
results,
getEnvironment(environment, calculator)
);
} else {
finalResult = undefined;
}
Expand Down Expand Up @@ -83,7 +93,11 @@ export async function processAllFieldCodes({
let _state = state;
for (const name of state.fieldNames) {
const field = state.fields[name];
const valueResult = await runSquiggleCode(field.code, environment);
const valueResult = await runSquiggleCode(
field.code,
environment,
calculator
);
const _action: CalculatorAction = {
type: "SET_FIELD_VALUE",
payload: { name, value: valueResult, path },
Expand Down Expand Up @@ -119,7 +133,7 @@ export async function updateAndProcessFieldCode({
dispatch(setCodeAction);
let _state = calculatorReducer(state, setCodeAction);

const valueResult = await runSquiggleCode(code, environment);
const valueResult = await runSquiggleCode(code, environment, calculator);
const setValueAction: CalculatorAction = {
type: "SET_FIELD_VALUE",
payload: { path, name: name, value: valueResult },
Expand Down
21 changes: 21 additions & 0 deletions packages/components/src/components/Calculator/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
initialCalculatorState,
} from "./calculatorReducer.js";
import { CalculatorUI } from "./calculatorUI.js";
import { ErrorAlert } from "../Alert.js";
import { SAMPLE_COUNT_MAX, SAMPLE_COUNT_MIN } from "../../lib/constants.js";

type Props = {
value: SqCalculator;
Expand Down Expand Up @@ -101,7 +103,7 @@

useEffect(() => {
_processAllFieldCodes();
}, []);

Check warning on line 106 in packages/components/src/components/Calculator/index.tsx

View workflow job for this annotation

GitHub Actions / Build, test, lint

React Hook useEffect has a missing dependency: '_processAllFieldCodes'. Either include it or remove the dependency array

//We want to reset the calculator state if the calculator changes
useEffect(() => {
Expand Down Expand Up @@ -129,7 +131,7 @@
});
}
setPrevCalculator(calculator);
}, [calculator]);

Check warning on line 134 in packages/components/src/components/Calculator/index.tsx

View workflow job for this annotation

GitHub Actions / Build, test, lint

React Hook useEffect has missing dependencies: '_processAllFieldCodes', 'calculatorState', 'environment', 'path', and 'prevCalculator'. Either include them or remove the dependency array

const onChange =
(name: string) =>
Expand Down Expand Up @@ -163,3 +165,22 @@
)
);
};

export const ShowErrorIfInvalid: React.FC<{
calculator: SqCalculator;
children: React.ReactNode;
}> = ({ calculator, children }) => {
const { sampleCount } = calculator;

const sampleCountIsInvalid =
sampleCount &&
(sampleCount < SAMPLE_COUNT_MIN || sampleCount > SAMPLE_COUNT_MAX);

return sampleCountIsInvalid ? (
<ErrorAlert
heading={`Calculator sampleCount must be between ${SAMPLE_COUNT_MIN} and ${SAMPLE_COUNT_MAX}. It is set to ${sampleCount}.`}
/>
) : (
children
);
};
3 changes: 2 additions & 1 deletion packages/components/src/components/PlaygroundSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import { CheckboxFormField, NumberFormField, RadioFormField } from "@quri/ui";
import { functionChartDefaults } from "./FunctionChart/utils.js";
import { FormComment } from "./ui/FormComment.js";
import { FormSection } from "./ui/FormSection.js";
import { SAMPLE_COUNT_MAX, SAMPLE_COUNT_MIN } from "../lib/constants.js";

export const environmentSchema = z.object({
sampleCount: z.number().int().gte(10).lte(1000000),
sampleCount: z.number().int().gte(SAMPLE_COUNT_MIN).lte(SAMPLE_COUNT_MAX),
xyPointLength: z.number().int().gte(10).lte(10000),
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { TableChart } from "../TableChart/index.js";
import { DistPreview } from "../DistributionsChart/DistPreview.js";
import { TableCellsIcon } from "@quri/ui";
import ReactMarkdown from "react-markdown";
import { Calculator } from "../Calculator/index.js";
import { Calculator, ShowErrorIfInvalid } from "../Calculator/index.js";

// We use an extra left margin for some elements to align them with parent variable name
const leftMargin = "ml-1.5";
Expand Down Expand Up @@ -143,15 +143,17 @@ export const getBoxProps = (
const calculator: SqCalculator = value.value;
return {
children: (settings) => (
<Calculator
value={calculator}
valueWithContext={value}
environment={environment}
settings={settings}
renderValue={(value, settings) =>
getBoxProps(value).children(settings)
}
/>
<ShowErrorIfInvalid calculator={calculator}>
<Calculator
value={calculator}
valueWithContext={value}
environment={environment}
settings={settings}
renderValue={(value, settings) =>
getBoxProps(value).children(settings)
}
/>
</ShowErrorIfInvalid>
),
};
}
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/lib/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const SAMPLE_COUNT_MAX = 1000000;
export const SAMPLE_COUNT_MIN = 10;
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ Calculator.make(
{
fn: f,
description: a,
sampleCount: 10000,
fields: [
{
name: "Variable 1",
Expand Down
5 changes: 4 additions & 1 deletion packages/squiggle-lang/src/fr/calculator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
frString,
frOptional,
frNumberOrString,
frNumber,
} from "../library/registry/frTypes.js";
import { FnFactory } from "../library/registry/helpers.js";
import { vCalculator } from "../value/index.js";
Expand Down Expand Up @@ -37,6 +38,7 @@ export const library = [
["fn", frLambda],
["title", frOptional(frString)],
["description", frOptional(frString)],
["sampleCount", frOptional(frNumber)],
[
"fields",
frArray(
Expand All @@ -49,11 +51,12 @@ export const library = [
]
),
],
([{ fn, title, description, fields }]) => {
([{ fn, title, description, sampleCount, fields }]) => {
const calc = vCalculator({
fn,
title: title || undefined,
description: description || undefined,
sampleCount: sampleCount || undefined,
fields: fields.map((vars) => ({
name: vars.name,
default: convertFieldDefault(vars.default),
Expand Down
12 changes: 11 additions & 1 deletion packages/squiggle-lang/src/public/SqValue/SqCalculator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,23 @@ export class SqCalculator {
return this._value.description;
}

get sampleCount(): number | undefined {
return this._value.sampleCount;
}

// This function is used to determine if a calculator has changed.
// It's obviously not perfect - it doesn't capture changes within the calculator function, but this would be much more complicated.

get hashString(): string {
const rowData = JSON.stringify(this._value.fields);
const paramData = this._value.fn.toString() || "";
return rowData + paramData + this._value.description;
return (
rowData +
paramData +
this._value.description +
this._value.title +
this._value.sampleCount
);
}

get fields(): {
Expand Down
1 change: 1 addition & 0 deletions packages/squiggle-lang/src/value/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ export type Calculator = {
fields: { name: string; default: string; description?: string }[];
description?: string;
title?: string;
sampleCount?: number;
};

class VCalculator extends BaseValue {
Expand Down
2 changes: 2 additions & 0 deletions packages/website/src/pages/docs/Api/Calculator.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Calculator.make: ({
fn: ...arguments => any,
title?: string,
description?: string,
sampleCount?: number,
fields: list<{
name: string,
default?: string | number,
Expand All @@ -35,6 +36,7 @@ Examples:
fn: {|a, b|a + b},
title: "Sum()"
description: "This takes in two arguments, and outputs the sum of those two arguments.",
sampleCount: 1000,
fields: [
{
name: "First Param",
Expand Down
Loading