From 0d025a90af9a7da0f714130c5922b02058bd990a Mon Sep 17 00:00:00 2001 From: Daniel Dunn Date: Wed, 2 Apr 2025 00:13:17 -0600 Subject: [PATCH] Initial work on generating tools from equations and descriptions --- .../omni-tools/src/pages/tools/index.ts | 1 + .../pages/tools/number/calculators/index.ts | 1 + .../src/pages/tools/number/index.ts | 1 + package-lock.json | 9 + package.json | 1 + .../generic-calc/generic-calc.service.test.ts | 6 + src/pages/tools/number/generic-calc/index.tsx | 196 ++++++++++++++++++ src/pages/tools/number/generic-calc/meta.ts | 17 ++ .../tools/number/generic-calc/service.ts | 5 + src/pages/tools/number/generic-calc/types.ts | 10 + src/pages/tools/number/index.ts | 9 +- 11 files changed, 254 insertions(+), 2 deletions(-) create mode 100644 home/daniel/Projects/omni-tools/src/pages/tools/index.ts create mode 100644 home/daniel/Projects/omni-tools/src/pages/tools/number/calculators/index.ts create mode 100644 home/daniel/Projects/omni-tools/src/pages/tools/number/index.ts create mode 100644 src/pages/tools/number/generic-calc/generic-calc.service.test.ts create mode 100644 src/pages/tools/number/generic-calc/index.tsx create mode 100644 src/pages/tools/number/generic-calc/meta.ts create mode 100644 src/pages/tools/number/generic-calc/service.ts create mode 100644 src/pages/tools/number/generic-calc/types.ts diff --git a/home/daniel/Projects/omni-tools/src/pages/tools/index.ts b/home/daniel/Projects/omni-tools/src/pages/tools/index.ts new file mode 100644 index 0000000..71e8eea --- /dev/null +++ b/home/daniel/Projects/omni-tools/src/pages/tools/index.ts @@ -0,0 +1 @@ +export const toolsTools = []; diff --git a/home/daniel/Projects/omni-tools/src/pages/tools/number/calculators/index.ts b/home/daniel/Projects/omni-tools/src/pages/tools/number/calculators/index.ts new file mode 100644 index 0000000..f7a9c9d --- /dev/null +++ b/home/daniel/Projects/omni-tools/src/pages/tools/number/calculators/index.ts @@ -0,0 +1 @@ +export const calculatorsTools = []; diff --git a/home/daniel/Projects/omni-tools/src/pages/tools/number/index.ts b/home/daniel/Projects/omni-tools/src/pages/tools/number/index.ts new file mode 100644 index 0000000..90c9f0e --- /dev/null +++ b/home/daniel/Projects/omni-tools/src/pages/tools/number/index.ts @@ -0,0 +1 @@ +export const numberTools = []; diff --git a/package-lock.json b/package-lock.json index b2074f9..6511848 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "lodash": "^4.17.21", "mime": "^4.0.6", "morsee": "^1.0.9", + "nerdamer": "^1.1.13", "notistack": "^3.0.1", "omggif": "^1.0.10", "pdf-lib": "^1.17.1", @@ -7820,6 +7821,14 @@ "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": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", diff --git a/package.json b/package.json index 68dfa2d..cd950ab 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "lodash": "^4.17.21", "mime": "^4.0.6", "morsee": "^1.0.9", + "nerdamer": "^1.1.13", "notistack": "^3.0.1", "omggif": "^1.0.10", "pdf-lib": "^1.17.1", diff --git a/src/pages/tools/number/generic-calc/generic-calc.service.test.ts b/src/pages/tools/number/generic-calc/generic-calc.service.test.ts new file mode 100644 index 0000000..4152224 --- /dev/null +++ b/src/pages/tools/number/generic-calc/generic-calc.service.test.ts @@ -0,0 +1,6 @@ +import { expect, describe, it } from 'vitest'; +// import { main } from './service'; +// +// describe('generic-calc', () => { +// +// }) diff --git a/src/pages/tools/number/generic-calc/index.tsx b/src/pages/tools/number/generic-calc/index.tsx new file mode 100644 index 0000000..4cabf41 --- /dev/null +++ b/src/pages/tools/number/generic-calc/index.tsx @@ -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 { + const initialValues: InitialValuesType = { + outputVariable: '', + vars: {} + }; + + return function GenericCalc({ title }: ToolComponentProps) { + const [result, setResult] = useState(''); + const [shortResult, setShortResult] = useState(''); + + const updateVarField = ( + name: string, + value: number, + values: InitialValuesType, + updateFieldFunc: UpdateField + ) => { + // Make copy + const newVars = { ...values.vars }; + newVars[name] = { + value, + unit: values.vars[name]?.unit || '' + }; + updateFieldFunc('vars', newVars); + }; + + const handleSelectedTargetChange = ( + varName: string, + updateFieldFunc: UpdateField + ) => { + updateFieldFunc('outputVariable', varName); + }; + + return ( + + } + initialValues={initialValues} + toolInfo={{ + title: 'Common Equations', + description: + 'Common mathematical equations that can be used in calculations.' + }} + getGroups={({ values, updateField }) => [ + { + title: 'Input Variables', + component: ( + + + + Variable + Value + Unit + Solve For + + + + {ohmsLawCalc.variables.map((variable) => ( + + {variable.name} + + + updateVarField( + variable.name, + parseFloat(val), + values, + updateField + ) + } + type="number" + /> + + {variable.unit} + + + + handleSelectedTargetChange( + variable.name, + updateField + ) + } + /> + + + ))} + +
+ ) + } + ]} + 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(''); + } + }} + /> + ); + }; +} diff --git a/src/pages/tools/number/generic-calc/meta.ts b/src/pages/tools/number/generic-calc/meta.ts new file mode 100644 index 0000000..aff3a72 --- /dev/null +++ b/src/pages/tools/number/generic-calc/meta.ts @@ -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) +}); diff --git a/src/pages/tools/number/generic-calc/service.ts b/src/pages/tools/number/generic-calc/service.ts new file mode 100644 index 0000000..886ff10 --- /dev/null +++ b/src/pages/tools/number/generic-calc/service.ts @@ -0,0 +1,5 @@ +import { InitialValuesType } from './types'; + +export function main(input: string, options: InitialValuesType): string { + return input + 'pp'; +} diff --git a/src/pages/tools/number/generic-calc/types.ts b/src/pages/tools/number/generic-calc/types.ts new file mode 100644 index 0000000..8953230 --- /dev/null +++ b/src/pages/tools/number/generic-calc/types.ts @@ -0,0 +1,10 @@ +export type InitialValuesType = { + vars: { + [key: string]: { + value: number; + unit: string; + }; + }; + + outputVariable: string; +}; diff --git a/src/pages/tools/number/index.ts b/src/pages/tools/number/index.ts index c2ca546..c03df53 100644 --- a/src/pages/tools/number/index.ts +++ b/src/pages/tools/number/index.ts @@ -1,5 +1,10 @@ import { tool as numberSum } from './sum/meta'; import { tool as numberGenerate } from './generate/meta'; import { tool as numberArithmeticSequence } from './arithmetic-sequence/meta'; - -export const numberTools = [numberSum, numberGenerate, numberArithmeticSequence]; +import { tool as genericCalc } from './generic-calc/meta'; +export const numberTools = [ + numberSum, + numberGenerate, + numberArithmeticSequence, + genericCalc +];