figbertmath

[RADIOACTIVE] miscellaneous math programs in website form
git clone git://git.figbert.com/figbertmath.git
Log | Files | Refs | README

commit 60558fceaadc3c4e14da859e640b916ad1eff6f3
parent 9cb6c4d47604b813dbbe73ea034cdbe23f149bfe
Author: therealFIGBERT <figbertwelner@gmail.com>
Date:   Mon,  2 Dec 2019 13:10:51 -0800

Add feature solving systems of equations with 2, 3, or 4 variables.

The feature is still buggy, and doesn't work on certain problems, though it works on most. The fix is in progress. The largeButton and pad files have been edited to allow for equations to be displayed.

Diffstat:
Msrc/components/App.js | 3+++
Asrc/components/highLevel/simultaneousEquation.js | 437+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/components/lowLevel/largeButton/index.js | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/components/lowLevel/largeButton/styles.module.css | 29+++++++++++++++++++++++++++++
Msrc/components/lowLevel/pad/index.js | 4++--
5 files changed, 590 insertions(+), 4 deletions(-)

diff --git a/src/components/App.js b/src/components/App.js @@ -4,6 +4,7 @@ import { SimpleCalc } from "./highLevel/simpleCalc"; import { AngSizeCalc } from "./highLevel/angSize"; import { ConsecNumCalc } from "./highLevel/consecNum"; import { PolygonAngle } from "./highLevel/polygonAngle"; +import { SimultaneousEquation } from "./highLevel/simultaneousEquation"; export class App extends React.Component { constructor(props) { @@ -30,6 +31,8 @@ export class App extends React.Component { return <ConsecNumCalc mode={this.state.mode} onModeChange={this.changeMode}/>; } else if (this.state.mode === 'polyAng') { return <PolygonAngle mode={this.state.mode} onModeChange={this.changeMode} />; + } else if (this.state.mode === 'simultaneousEQ') { + return <SimultaneousEquation mode={this.state.mode} onModeChange={this.changeMode} />; } else { return <ModeSelect mode={this.state.mode} onButtonPress={this.changeMode} />; } diff --git a/src/components/highLevel/simultaneousEquation.js b/src/components/highLevel/simultaneousEquation.js @@ -0,0 +1,436 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { CalcOut } from "../lowLevel/calcOut"; +import { Pad } from "../lowLevel/pad"; + +export class SimultaneousEquation extends React.Component { + constructor(props) { + super(props); + this.state = { + output: '', + type: 'Two Variables', + amount: '2', + wOne: '', + xOne: '', + yOne: '', + zOne: '', + answerOne: '', + wTwo: '', + xTwo: '', + yTwo: '', + zTwo: '', + answerTwo: '', + wThree: '', + xThree: '', + yThree: '', + zThree: '', + answerThree: '', + wFour: '', + xFour: '', + yFour: '', + zFour: '', + answerFour: '' + }; + this.onClick = this.onClick.bind(this); + this.onChange = this.onChange.bind(this); + this.shouldCalculate = this.shouldCalculate.bind(this); + } + + onClick() { + switch(this.state.type) { + case "Two Variables": + this.setState({ + type: 'Three Variables', + amount: '3' + }); + break; + case "Three Variables": + this.setState({ + type: 'Four Variables', + amount: '4' + }); + break; + default: + this.setState({ + type: 'Two Variables', + amount: '2' + }); + break; + } + } + + onChange(object) { + const value = object.target.value, + name = object.target.name; + switch (name) { + case 'wOne': + this.setState({ wOne: value }, () => { + this.shouldCalculate() + }); + break; + case 'xOne': + this.setState({ xOne: value }, () => { + this.shouldCalculate() + }); + break; + case 'yOne': + this.setState({ yOne: value }, () => { + this.shouldCalculate() + }); + break; + case 'zOne': + this.setState({ zOne: value }, () => { + this.shouldCalculate() + }); + break; + case 'answerOne': + this.setState({ answerOne: value }, () => { + this.shouldCalculate() + }); + break; + case 'wTwo': + this.setState({ wTwo: value }, () => { + this.shouldCalculate() + }); + break; + case 'xTwo': + this.setState({ xTwo: value }, () => { + this.shouldCalculate() + }); + break; + case 'yTwo': + this.setState({ yTwo: value }, () => { + this.shouldCalculate() + }); + break; + case 'zTwo': + this.setState({ zTwo: value }, () => { + this.shouldCalculate() + }); + break; + case 'answerTwo': + this.setState({ answerTwo: value }, () => { + this.shouldCalculate() + }); + break; + case 'wThree': + this.setState({ wThree: value }, () => { + this.shouldCalculate() + }); + break; + case 'xThree': + this.setState({ xThree: value }, () => { + this.shouldCalculate() + }); + break; + case 'yThree': + this.setState({ yThree: value }, () => { + this.shouldCalculate() + }); + break; + case 'zThree': + this.setState({ zThree: value }, () => { + this.shouldCalculate() + }); + break; + case 'answerThree': + this.setState({ answerThree: value }, () => { + this.shouldCalculate() + }); + break; + case 'wFour': + this.setState({ wFour: value }, () => { + this.shouldCalculate() + }); + break; + case 'xFour': + this.setState({ xFour: value }, () => { + this.shouldCalculate() + }); + break; + case 'yFour': + this.setState({ yFour: value }, () => { + this.shouldCalculate() + }); + break; + case 'zFour': + this.setState({ zFour: value }, () => { + this.shouldCalculate() + }); + break; + case 'answerFour': + this.setState({ answerFour: value }, () => { + this.shouldCalculate() + }); + break; + default: + this.setState({ + output: 'ERROR' + }); + } + } + + shouldCalculate() { + let calc; + switch (this.state.amount) { + case '2': + calc = + (this.state.xOne !== '' && this.state.yOne !== '' && this.state.answerOne !== '') + && + (this.state.xTwo !== '' && this.state.yTwo !== '' && this.state.answerTwo !== ''); + break; + case '3': + calc = + (this.state.xOne !== '' && this.state.yOne !== '' && this.state.zOne !== '' && this.state.answerOne !== '') + && + (this.state.xTwo !== '' && this.state.yTwo !== '' && this.state.zTwo !== '' && this.state.answerTwo !== '') + && + (this.state.xThree !== '' && this.state.yThree !== '' && this.state.zThree !== '' && this.state.answerThree !== ''); + break; + case '4': + calc = + (this.state.wOne !== '' && this.state.xOne !== '' && this.state.yOne !== '' && this.state.zOne !== '' && this.state.answerOne !== '') + && + (this.state.wTwo !== '' && this.state.xTwo !== '' && this.state.yTwo !== '' && this.state.zTwo !== '' && this.state.answerTwo !== '') + && + (this.state.wThree !== '' && this.state.xThree !== '' && this.state.yThree !== '' && this.state.zThree !== '' && this.state.answerThree !== '') + && + (this.state.wFour !== '' && this.state.xFour !== '' && this.state.yFour !== '' && this.state.zFour !== '' && this.state.answerFour !== ''); + break; + default: + this.setState({ + output: 'ERROR' + }); + } + if (calc) { + this.calc() + } + } + + calc() { + const lcm = (a, b) => { + let c = a; + while (c % b !== 0) { + c += a; + } + return c; + }; + const invertArray = (array) => { + for (let i = 0; i < array.length; i++) { + array[i] = array[i] * -1; + } + return array; + }; + + const simplify = (amount, eqArray) => { + if (amount === 2) { + const a = eqArray[0], + b = eqArray[1], + multOne = lcm(a[0], b[0]) / a[0], + multTwo = lcm(a[0], b[0]) / b[0]; + for (let i = 0; i < b.length; i++) { + a[i] *= multOne; + b[i] *= multTwo; + } + if (a[0] + b[0] !== 0) { + invertArray(a); + } + for (let i = 0; i < b.length; i++) { + b[i] += a[i]; + } + return b; + } else if (amount === 3) { + const a = eqArray[0], + b = eqArray[1], + c = eqArray[2], + simpleTwo = simplify(2, [a, b]), + simpleThree = simplify(2, [a, c]), + multTwo = lcm(simpleTwo[1], simpleThree[1]) / simpleTwo[1], + multThree = lcm(simpleTwo[1], simpleThree[1]) / simpleThree[1]; + for (let a = 0; a < simpleThree.length; a++) { + simpleTwo[a] *= multTwo; + simpleThree[a] *= multThree; + } + if (simpleTwo[1] + simpleThree[1] !== 0) { + invertArray(simpleTwo); + } + for (let a = 0; a < simpleThree.length; a++) { + simpleThree[a] += simpleTwo[a]; + } + return [simpleTwo, simpleThree]; + } else if (amount === 4) { + const a = eqArray[0], + b = eqArray[1], + c = eqArray[2], + d = eqArray[3], + simpleTwoThree = simplify(3, [a, b, c]), + simpleFour = simplify(2, [a, d]), + changingTwo = simpleTwoThree[0], + changingThree = simpleTwoThree[1], + multTwo = lcm(changingTwo[1], simpleFour[1]) / changingTwo[1], + firstMultFour = lcm(changingTwo[1], simpleFour[1]) / simpleFour[1]; + for (let a = 0; a < simpleFour.length; a++) { + simpleFour[a] *= firstMultFour; + changingTwo[a] *= multTwo; + } + if (simpleFour[1] + changingTwo[1] !== 0) { + invertArray(changingTwo); + } + for (let a = 0; a < simpleFour.length; a++) { + simpleFour[a] += changingTwo[a]; + } + const multThree = lcm(changingThree[2], simpleFour[2]) / changingThree[2], + secondMultFour = lcm(changingThree[2], simpleFour[2]) / simpleFour[2]; + for (let a = 0; a < simpleFour.length; a++) { + changingThree[a] *= multThree; + simpleFour[a] *= secondMultFour; + } + if (simpleFour[2] + changingThree[2] !== 0) { + invertArray(changingThree); + } + for (let a = 0; a < simpleFour.length; a++) { + simpleFour[a] += changingThree[a]; + } + return [simpleTwoThree[0], simpleTwoThree[1], simpleFour]; + } + }; + + const answer = (amount, eqArray) => { + if (amount === 2) { + const a = eqArray[0], + b = eqArray[1], + y = b[2] / b[1], + x = (a[2] - a[1] * y) / a[0]; + return [x, y]; + } else if (amount === 3) { + const a = eqArray[0], + b = eqArray[1], + c = eqArray[2], + z = c[3] / c[2], + y = (b[3] - b[2] * z) / b[1], + x = (a[3] - (a[2] * z + a[1] * y)) / a[0]; + return [x, y, z]; + } else if (amount === 4) { + const a = eqArray[0], + b = eqArray[1], + c = eqArray[2], + d = eqArray[3], + z = d[4] / d[3], + y = (c[4] - c[3] * z) / c[2], + x = (b[4] - (b[3] * z + b[2] * y)) / b[1], + w = (a[4] - (a[3] * z + a[2] * y + a[1] * x)) / a[0]; + return [w, x, y, z]; + } + }; + + const dimension = Number(this.state.amount); + if (dimension === 2) { + const eqOne = [this.state.xOne, this.state.yOne, this.state.answerOne], + eqTwo = [this.state.xTwo, this.state.yTwo, this.state.answerTwo], + simpleY = simplify(2, [eqOne, eqTwo]), + valuesXY = answer(2, [eqOne, simpleY]); + this.setState({ + output: 'x = ' + valuesXY[0] + '\ny = ' + valuesXY[1] + }); + } else if (dimension === 3) { + const eqOne = [this.state.xOne, this.state.yOne, this.state.zOne, this.state.answerOne], + eqTwo = [this.state.xTwo, this.state.yTwo, this.state.zTwo, this.state.answerTwo], + eqThree = [this.state.xThree, this.state.yThree, this.state.zThree, this.state.answerThree], + simpleYZ = simplify(3, [eqOne, eqTwo, eqThree]), + valuesXYZ = answer(3, [eqOne, simpleYZ[0], simpleYZ[1]]); + this.setState({ + output: 'x = ' + valuesXYZ[0] + '\ny = ' + valuesXYZ[1] + '\nz = ' + valuesXYZ[2] + }); + } else if (dimension === 4) { + const eqOne = [this.state.wOne, this.state.xOne, this.state.yOne, this.state.zOne, this.state.answerOne], + eqTwo = [this.state.wTwo, this.state.xTwo, this.state.yTwo, this.state.zTwo, this.state.answerTwo], + eqThree = [this.state.wThree, this.state.xThree, this.state.yThree, this.state.zThree, this.state.answerThree], + eqFour = [this.state.wFour, this.state.xFour, this.state.yFour, this.state.zFour, this.state.answerFour], + simpleXYZ = simplify(4, [eqOne, eqTwo, eqThree, eqFour]), + valuesXYZ = answer(4, [eqOne, simpleXYZ[0], simpleXYZ[1], simpleXYZ[2]]); + this.setState({ + output: 'w = ' + valuesXYZ[0] + '\nx = ' + valuesXYZ[1] + '\ny = ' + valuesXYZ[2] + '\nz = ' + valuesXYZ[3] + }); + } else { + this.setState({ + output: 'ERROR' + }); + } + } + + render() { + let buttonValues, displayValues, textValues; + switch(this.state.type) { + case "Two Variables": + buttonValues = [ + 'type', + ['xOne', 'yOne', 'answerOne'], + ['xTwo', 'yTwo', 'answerTwo'], + 'select' + ]; + displayValues = [this.state.type, '2', '2', '…']; + textValues = [ + '', + [this.state.xOne, this.state.yOne, this.state.answerOne], + [this.state.xTwo, this.state.yTwo, this.state.answerTwo], + '' + ]; + break; + case "Three Variables": + buttonValues = [ + 'type', + ['xOne', 'yOne', 'zOne', 'answerOne'], + ['xTwo', 'yTwo', 'zTwo', 'answerTwo'], + ['xThree', 'yThree', 'zThree', 'answerThree'], + 'select' + ]; + displayValues = [this.state.type, '3', '3', '3', '…']; + textValues = [ + '', + [this.state.xOne, this.state.yOne, this.state.zOne, this.state.answerOne], + [this.state.xTwo, this.state.yTwo, this.state.zTwo, this.state.answerTwo], + [this.state.xThree, this.state.yThree, this.state.zThree, this.state.answerThree], + '' + ]; + break; + default: + buttonValues = [ + 'type', + ['wOne', 'xOne', 'yOne', 'zOne', 'answerOne'], + ['wTwo', 'xTwo', 'yTwo', 'zTwo', 'answerTwo'], + ['wThree', 'xThree', 'yThree', 'zThree', 'answerThree'], + ['wFour', 'xFour', 'yFour', 'zFour', 'answerFour'], + 'select' + ]; + displayValues = [this.state.type, '4', '4', '4', '4', '…']; + textValues = [ + '', + [this.state.wOne, this.state.xOne, this.state.yOne, this.state.zOne, this.state.answerOne], + [this.state.wTwo, this.state.xTwo, this.state.yTwo, this.state.zTwo, this.state.answerTwo], + [this.state.wThree, this.state.xThree, this.state.yThree, this.state.zThree, this.state.answerThree], + [this.state.wFour, this.state.xFour, this.state.yFour, this.state.zFour, this.state.answerFour], + '' + ]; + break; + } + return ( + <div> + <CalcOut mode={this.props.mode} output={this.state.output} /> + <Pad + type={'large'} + mode={this.props.mode} + buttonValues={buttonValues} + displayValues={displayValues} + textValues={textValues} + onClick={this.onClick} + onChange={this.onChange} + onModeClick={this.props.onModeChange} + /> + </div> + ); + } +} +SimultaneousEquation.propTypes = { + mode: PropTypes.string.isRequired, + onModeChange: PropTypes.func.isRequired +}; +\ No newline at end of file diff --git a/src/components/lowLevel/largeButton/index.js b/src/components/lowLevel/largeButton/index.js @@ -4,7 +4,8 @@ import styles from './styles.module.css'; export class LargeButton extends React.Component { render() { - const canBeDisabled = this.props.mode === 'angSize', + const equationForm = this.props.mode === 'simultaneousEQ', + canBeDisabled = this.props.mode === 'angSize', acceptsInput = this.props.mode !== 'select'; if (this.props.value === 'select') { return ( @@ -29,7 +30,123 @@ export class LargeButton extends React.Component { </button> ); } - if (canBeDisabled) { + if (equationForm) { + if (this.props.displayValue === '2') { + return ( + <div className={styles.EQButton}> + <span className={styles.closeText}> + <input + type='number' + name={this.props.value[0]} + value={this.props.textValue[0]} + onChange={this.props.onChange} + /> + x + </span> + + <span className={styles.closeText}> + <input + type='number' + name={this.props.value[1]} + value={this.props.textValue[1]} + onChange={this.props.onChange} + /> + y + </span> = + <input + type='number' + name={this.props.value[2]} + value={this.props.textValue[2]} + onChange={this.props.onChange} + /> + </div> + ); + } else if (this.props.displayValue === '3') { + return ( + <div className={styles.EQButton}> + <span className={styles.closeText}> + <input + type='number' + name={this.props.value[0]} + value={this.props.textValue[0]} + onChange={this.props.onChange} + /> + x + </span> + + <span className={styles.closeText}> + <input + type='number' + name={this.props.value[1]} + value={this.props.textValue[1]} + onChange={this.props.onChange} + /> + y + </span> + + <span className={styles.closeText}> + <input + type='number' + name={this.props.value[2]} + value={this.props.textValue[2]} + onChange={this.props.onChange} + /> + z + </span> = + <input + type='number' + name={this.props.value[3]} + value={this.props.textValue[3]} + onChange={this.props.onChange} + /> + </div> + ); + } else if (this.props.displayValue === '4') { + return ( + <div className={styles.EQButton}> + <span className={styles.closeText}> + <input + type='number' + name={this.props.value[0]} + value={this.props.textValue[0]} + onChange={this.props.onChange} + /> + w + </span> + + <span className={styles.closeText}> + <input + type='number' + name={this.props.value[1]} + value={this.props.textValue[1]} + onChange={this.props.onChange} + /> + x + </span> + + <span className={styles.closeText}> + <input + type='number' + name={this.props.value[2]} + value={this.props.textValue[2]} + onChange={this.props.onChange} + /> + y + </span> + + <span className={styles.closeText}> + <input + type='number' + name={this.props.value[3]} + value={this.props.textValue[3]} + onChange={this.props.onChange} + /> + z + </span> = + <input + type='number' + name={this.props.value[4]} + value={this.props.textValue[4]} + onChange={this.props.onChange} + /> + </div> + ); + } + } else if (canBeDisabled) { if (!this.props.disabledTruth) { return ( <button className={styles.disabled} value={this.props.value} onClick={this.props.onClick}> diff --git a/src/components/lowLevel/largeButton/styles.module.css b/src/components/lowLevel/largeButton/styles.module.css @@ -43,4 +43,33 @@ input { flex-direction: column; justify-content: space-evenly; align-items: center; +} + +.EQButton { + background: #ac1a2d; + color: rgba(255, 255, 255, .7); + font-family: Tomorrow, -apple-system, sans-serif; + width: 30vmax; + height: 5vmax; + margin-top: 1vmax; + margin-left: 1vmax; + margin-right: 1vmax; + font-size: 2vmax; + text-align: center; + border-radius: 1vmax; + display: flex; + flex-direction: row; + justify-content: space-evenly; + align-items: center; +} + +.EQButton input { + width: 2vmax; +} + +.closeText { + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; } \ No newline at end of file diff --git a/src/components/lowLevel/pad/index.js b/src/components/lowLevel/pad/index.js @@ -13,7 +13,7 @@ export class Pad extends React.Component { disabledTruths = this.props.disabledTruths, displayValues = this.props.displayValues, textValues = this.props.textValues; - let rows = []; + let rows; if (this.props.type === 'small') { rows = this.props.buttonValues.map(function (array, index, _) { return <SmallButtonRow @@ -52,7 +52,7 @@ Pad.propTypes = { PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)), PropTypes.arrayOf(PropTypes.string) ]).isRequired, - onClick: PropTypes.func.isRequired, + onClick: PropTypes.func, mode: PropTypes.string, onChange: PropTypes.func, onModeClick: PropTypes.func,