Initial work on generating tools from equations and descriptions

This commit is contained in:
Daniel Dunn
2025-04-02 00:13:17 -06:00
parent 08e43b8a42
commit 0d025a90af
11 changed files with 254 additions and 2 deletions

View File

@@ -0,0 +1 @@
export const toolsTools = [];

View File

@@ -0,0 +1 @@
export const calculatorsTools = [];

View File

@@ -0,0 +1 @@
export const numberTools = [];

9
package-lock.json generated
View File

@@ -30,6 +30,7 @@
"lodash": "^4.17.21", "lodash": "^4.17.21",
"mime": "^4.0.6", "mime": "^4.0.6",
"morsee": "^1.0.9", "morsee": "^1.0.9",
"nerdamer": "^1.1.13",
"notistack": "^3.0.1", "notistack": "^3.0.1",
"omggif": "^1.0.10", "omggif": "^1.0.10",
"pdf-lib": "^1.17.1", "pdf-lib": "^1.17.1",
@@ -7820,6 +7821,14 @@
"is-buffer": "^1.0.2" "is-buffer": "^1.0.2"
} }
}, },
"node_modules/nerdamer": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/nerdamer/-/nerdamer-1.1.13.tgz",
"integrity": "sha512-kQGQYd42eQpKDOnU8ZnRKF47c+gK6jVC46eUchrABsovtFruHvsjyjBO32jck8QnpZE5z5R8HQw72hQX9Oq2MQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/node-fetch": { "node_modules/node-fetch": {
"version": "2.7.0", "version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",

View File

@@ -47,6 +47,7 @@
"lodash": "^4.17.21", "lodash": "^4.17.21",
"mime": "^4.0.6", "mime": "^4.0.6",
"morsee": "^1.0.9", "morsee": "^1.0.9",
"nerdamer": "^1.1.13",
"notistack": "^3.0.1", "notistack": "^3.0.1",
"omggif": "^1.0.10", "omggif": "^1.0.10",
"pdf-lib": "^1.17.1", "pdf-lib": "^1.17.1",

View File

@@ -0,0 +1,6 @@
import { expect, describe, it } from 'vitest';
// import { main } from './service';
//
// describe('generic-calc', () => {
//
// })

View File

@@ -0,0 +1,196 @@
import {
Box,
InputLabel,
Radio,
Table,
TableBody,
TableCell,
TableHead,
TableRow
} from '@mui/material';
import React, { useState } from 'react';
import ToolContent from '@components/ToolContent';
import { ToolComponentProps } from '@tools/defineTool';
import ToolTextResult from '@components/result/ToolTextResult';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import { GetGroupsType, UpdateField } from '@components/options/ToolOptions';
import { InitialValuesType } from './types';
import nerdamer from 'nerdamer';
import 'nerdamer/Algebra';
import 'nerdamer/Solve';
import 'nerdamer/Calculus';
const ohmsLawCalc: {
name: string;
formula: string;
variables: {
name: string;
title: string;
unit: string;
}[];
} = {
name: "Ohm's Law Calculator",
formula: 'V = I * R',
variables: [
{
name: 'V',
title: 'Voltage',
unit: 'V'
},
{
name: 'I',
title: 'Current',
unit: 'A'
},
{
name: 'R',
title: 'Resistance',
unit: 'Ω'
}
]
};
export default function makeTool(): React.JSXElementConstructor<ToolComponentProps> {
const initialValues: InitialValuesType = {
outputVariable: '',
vars: {}
};
return function GenericCalc({ title }: ToolComponentProps) {
const [result, setResult] = useState<string>('');
const [shortResult, setShortResult] = useState<string>('');
const updateVarField = (
name: string,
value: number,
values: InitialValuesType,
updateFieldFunc: UpdateField<InitialValuesType>
) => {
// Make copy
const newVars = { ...values.vars };
newVars[name] = {
value,
unit: values.vars[name]?.unit || ''
};
updateFieldFunc('vars', newVars);
};
const handleSelectedTargetChange = (
varName: string,
updateFieldFunc: UpdateField<InitialValuesType>
) => {
updateFieldFunc('outputVariable', varName);
};
return (
<ToolContent
title={title}
inputComponent={null}
resultComponent={
<ToolTextResult title={ohmsLawCalc.name} value={result} />
}
initialValues={initialValues}
toolInfo={{
title: 'Common Equations',
description:
'Common mathematical equations that can be used in calculations.'
}}
getGroups={({ values, updateField }) => [
{
title: 'Input Variables',
component: (
<Table>
<TableHead>
<TableRow>
<TableCell>Variable</TableCell>
<TableCell>Value</TableCell>
<TableCell>Unit</TableCell>
<TableCell>Solve For</TableCell>
</TableRow>
</TableHead>
<TableBody>
{ohmsLawCalc.variables.map((variable) => (
<TableRow key={variable.name}>
<TableCell>{variable.name}</TableCell>
<TableCell>
<TextFieldWithDesc
title={variable.title}
sx={{ width: '25ch' }}
description=""
value={
values.outputVariable === variable.name
? shortResult
: values.vars[variable.name]?.value || NaN
}
disabled={values.outputVariable === variable.name}
onOwnChange={(val) =>
updateVarField(
variable.name,
parseFloat(val),
values,
updateField
)
}
type="number"
/>
</TableCell>
<TableCell>{variable.unit}</TableCell>
<TableCell>
<Radio
value={variable.name}
checked={values.outputVariable === variable.name}
onClick={() =>
handleSelectedTargetChange(
variable.name,
updateField
)
}
/>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
)
}
]}
compute={(values) => {
if (values.outputVariable === '') {
setResult('Please select a solve for variable');
return;
}
let expr = nerdamer(ohmsLawCalc.formula);
Object.keys(values.vars).forEach((key) => {
if (key === values.outputVariable) return;
expr = expr.sub(key, values.vars[key].value.toString());
});
let result: nerdamer.Expression = expr.solveFor(
values.outputVariable
);
// Sometimes the result is an array
if (result.toDecimal === undefined) {
result = (result as unknown as nerdamer.Expression[])[0];
}
setResult(result.toString());
if (result) {
if (values.vars[values.outputVariable] != undefined) {
values.vars[values.outputVariable].value = parseFloat(
result.toDecimal()
);
}
setShortResult(result.toDecimal());
} else {
setShortResult('');
}
}}
/>
);
};
}

View File

@@ -0,0 +1,17 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
async function importComponent() {
const x = await import('./index');
return { default: x.default() };
}
export const tool = defineTool('number', {
name: 'Generic calc',
path: 'generic-calc',
icon: '',
description: '',
shortDescription: '',
keywords: ['generic', 'calc'],
longDescription: '',
component: lazy(importComponent)
});

View File

@@ -0,0 +1,5 @@
import { InitialValuesType } from './types';
export function main(input: string, options: InitialValuesType): string {
return input + 'pp';
}

View File

@@ -0,0 +1,10 @@
export type InitialValuesType = {
vars: {
[key: string]: {
value: number;
unit: string;
};
};
outputVariable: string;
};

View File

@@ -1,5 +1,10 @@
import { tool as numberSum } from './sum/meta'; import { tool as numberSum } from './sum/meta';
import { tool as numberGenerate } from './generate/meta'; import { tool as numberGenerate } from './generate/meta';
import { tool as numberArithmeticSequence } from './arithmetic-sequence/meta'; import { tool as numberArithmeticSequence } from './arithmetic-sequence/meta';
import { tool as genericCalc } from './generic-calc/meta';
export const numberTools = [numberSum, numberGenerate, numberArithmeticSequence]; export const numberTools = [
numberSum,
numberGenerate,
numberArithmeticSequence,
genericCalc
];