Quellcode durchsuchen

added first version of subtraction

Bernadette Elena Hammerle vor 4 Jahren
Ursprung
Commit
7d793a7a94
3 geänderte Dateien mit 336 neuen und 6 gelöschten Zeilen
  1. 1 2
      src/Addition.js
  2. 332 1
      src/Subtraction.js
  3. 3 3
      src/helpers.js

+ 1 - 2
src/Addition.js

@@ -74,7 +74,7 @@ function Addition() {
       setNumbers(numbersArr);
       setCommaIdx(commaIdx);
 
-      setNumbersGrid(addNumbersToGrid(numbersArr));
+      setNumbersGrid(addNumbersToGrid(numbersArr, "+"));
     }
   }
 
@@ -208,7 +208,6 @@ function Addition() {
       }
       if (foundComma){
         idxCarry += 1;
-        continue;
       }
 
       // add carry only if > 0

+ 332 - 1
src/Subtraction.js

@@ -1,9 +1,340 @@
-import React from "react";
+import React, {useState, useEffect, useRef} from "react";
+import DataGrid, {Column} from "devextreme-react/data-grid";
+import {Alert} from "./AlertDialog.js";
+import {addNumbersToGrid, numbersToArrOfArr} from "./helpers.js";
+import "./App.css";
+
+let imdtRes;
+let imdtResIdx;
+let resArr = [];
+let noOfDigits = 0;
 
 function Subtraction() {
+  const [input, setInput] = useState(""); // initial user input like 34+56.7
+  const [realResult, setRealResult] = useState(0); // real result of calculation
+  const [carryArr, setCarryArr] = useState([]); // array of carries [1","0"]
+  const [commaIdx, setCommaIdx] = useState(0); // int: comma position
+  const [numbers, setNumbers] = useState(0); // array of arrays with input numbers
+  const [showAlert, setShowAlert] = useState(false);
+  const [numbersGrid, setNumbersGrid] = useState([{id: 1, number: ""}]);
+  const [resultsGrid, setResultsGrid] = useState([{id: 1, number: ""}]);
+  const [stepsGrid, setStepsGrid] = useState([{id: 1, step: ""}]);
+
+  // focus the input field
+  let calculationInput = useRef(null);
+  useEffect(()=>{
+    if(calculationInput.current && calculationInput.current.value === ""){
+      calculationInput.current.focus();
+    }
+  },[])
+
+  const handleInput = (e) => {
+    setInput(e.target.value);
+  }
+
+  const handleResChange = (e, nosLeft) => {
+    if(typeof e === "string"){
+      imdtRes = e;
+    }else{
+      imdtRes = e.target.value;
+    }
+
+    // remove deleted input
+    if(imdtRes === ""){
+      resArr.shift();
+    }else{
+      // add input number to result array
+      resArr.unshift(imdtRes);
+      if(nosLeft === 0){
+        setShowAlert(true);
+      }
+    }
+  }
+
+  const handleCarryChange = (e, noOfDigits, idx) => {
+    if(typeof carryArr === "undefined"){
+       setCarryArr(Array(noOfDigits).fill("-"));
+    }
+    let carryArrCopy = [...carryArr]
+    carryArrCopy[idx] = e.target.value
+    setCarryArr(carryArrCopy);
+  }
+
+  const handleSubmit = (e) => {
+    startCalculation();
+    e.preventDefault(); // avoid page reload
+  }
+
+  const startCalculation = () => {
+    if (input.includes("-")){
+      let numbers = input.split("-").map(x => parseFloat(x.replace(",",".")));
+      let realRes = numbers[0]
+      for (let i=1; i<numbers.length; i++){
+        realRes -= numbers[i]
+      }
+      setRealResult(realRes);
+
+      let [numbersArr, commaIdx] = numbersToArrOfArr(numbers);
+      setNumbers(numbersArr);
+      setCommaIdx(commaIdx);
+
+      setNumbersGrid(addNumbersToGrid(numbersArr, "-"));
+    }
+  }
+
+  const ResultCarryForm = ({handleResChange, handleCarryChange}) => {
+    let resInputField = useRef(null);
+    let carryInputField = useRef(null);
+
+    // focus the input field
+    useEffect(()=>{
+      if(resInputField.current && resInputField.current.value === ""){
+        resInputField.current.focus();
+      }
+    },[])
+
+    let labelText = "";
+    let nosLeft = imdtResIdx + 1;
+    let carryText = "Übertrag = ";
+    let carryOffset = 0;
+
+    if(typeof numbers === "object" && imdtResIdx !== -1){
+      if(typeof imdtResIdx === "undefined" || imdtResIdx === null){
+        noOfDigits = Math.min(...numbers.map(n => n.length));
+        imdtResIdx = noOfDigits-1;
+      }
+      if(imdtResIdx === commaIdx){
+        handleResChange(".", nosLeft)
+        imdtResIdx = imdtResIdx - 1;
+        carryOffset = 1;
+      }
+
+      for (let n in numbers){ // iterate numbers
+        if(nosLeft === 1 && carryArr[0] === "0"){
+          nosLeft = 0;
+          imdtResIdx = -1;
+          handleResChange("&nbsp;", 0)
+          return <></>
+        }
+        let digit = numbers[parseInt(n)][imdtResIdx];
+        if(digit === "" || digit === "&nbsp;"){
+          digit = 0;
+        }
+        labelText += digit;
+
+        if (parseInt(n) === numbers.length - 1){
+          if(carryArr[imdtResIdx+carryOffset]!=="undefind" && carryArr[imdtResIdx+carryOffset] > 0){
+            labelText += " + " + carryArr[imdtResIdx+carryOffset].toString();
+          }
+          labelText += " = ";
+        }else{
+          labelText += " - ";
+        }
+      }
+
+      if(carryArr[imdtResIdx+carryOffset] > -1 || imdtResIdx === noOfDigits-1){
+        imdtRes = -1;
+        imdtResIdx = imdtResIdx - 1;
+        nosLeft = nosLeft - 1;
+      }
+
+      return (
+        <form>
+          <label htmlFor="input_result" id="input_result_label">
+            {labelText}
+          </label>
+          <input
+            onChange={(e) => handleResChange(e, nosLeft)}
+            type="text" id="input_result" size="2" tabIndex={1}
+            aria-labelledby="input_result_label" aria-required="true"
+            ref={resInputField}/>
+          <br/>
+          <label htmlFor="input_carry" id="input_carry_label">
+            {carryText}
+          </label>
+          <input
+            onChange={(e) => handleCarryChange(e, noOfDigits, imdtResIdx)}
+            type="text" id="input_carry" size="2" tabIndex={2}
+            aria-labelledby="input_carry_label" aria-required="true"
+            ref={carryInputField}/>
+        </form>
+      );
+    }else{
+      return (
+        <>
+        </>
+      );
+    }
+  }
+
+  const showIdmtResults = () => {
+    setShowAlert(false);
+    let realResArr = realResult.toString().split("");
+    while(realResArr.length < resArr.length){
+      realResArr.unshift("&nbsp;"); // add " " before
+    }
+
+    let carries = carryArr.map(x => x || "0")
+    carries.push("0");
+    while(carries.length < resArr.length){
+      carries.unshift("0"); // add "0" before
+    }
+
+    let foundComma = false;
+    let stepsGridCopy = [];
+    for (let i=0; i<resArr.length-1; i++) {
+      let text = "";
+      let trueNumbers = false;
+      let idxNumbers = resArr.length - i - 1;
+      let idxCarry = carries.length - i - 1;
+
+      let realDigitRes = 0;
+      for (let j=0; j<numbers.length; j++) {
+        let no = numbers[j][idxNumbers];
+
+        if (j === 0){
+          realDigitRes = parseInt(no);
+        }
+        else if (no!=="." && no!=="&nbsp;"){
+          trueNumbers = true;
+          realDigitRes -= parseInt(no);
+        }
+
+        text += no
+        if (j<numbers.length-1){
+          text += " - "
+        }
+      }
+
+      // ignore indexes without real digits
+      if (resArr[idxNumbers]!=="&nbsp;" || carries[idxCarry]!=="&nbsp;"){
+        trueNumbers = true;
+      }
+
+      // carry array has no "."
+      if (resArr[idxNumbers] === "."){
+        foundComma = true;
+        trueNumbers = false;
+      }
+      if (foundComma){
+        idxCarry += 1;
+      }
+
+      // add carry only if > 0
+      if (carries[idxCarry]!=="0"){
+        realDigitRes -= parseInt(carries[idxCarry]);
+        text += " - " + carries[idxCarry] // + " Übertrag"
+      }
+      console.log(realDigitRes)
+      let realCarry = Math.abs(parseInt(realDigitRes/10)).toString()
+      realDigitRes = (realDigitRes % 10)
+      if (realDigitRes < 0){
+        realDigitRes = realDigitRes + 10
+      }
+      realDigitRes = realDigitRes.toString()
+      text += " = "
+
+      if (trueNumbers){
+        text += resArr[idxNumbers]
+        text += " und " + carries[idxCarry-1] + " Übertrag "
+        text = text.replace(/&nbsp;/g, "0")
+        text += resArr[idxNumbers]===realDigitRes && carries[idxCarry-1]===realCarry ? "(Richtig)" : "(Falsch)";
+        stepsGridCopy.push({step: text});
+      }
+    }
+
+    setStepsGrid(stepsGridCopy);
+    let btnSubmit = document.createElement("button");
+    btnSubmit.innerHTML = "Ergebnis abgeben";
+    btnSubmit.addEventListener("click", finishCalculation);
+    document.getElementById("idmtResultSteps").appendChild(btnSubmit);
+  }
+
+  const finishCalculation = () => {
+    setShowAlert(false);
+    document.getElementById("idmtResultSteps").innerHTML = "";
+    let resCalc = resArr.filter(n => n !== "&nbsp;").join("");
+    setResultsGrid([{number: resCalc}]);
+    resCalc = parseFloat(resCalc);
+
+    let message = "";
+    console.log(resCalc, realResult);
+    if(resCalc === realResult){
+      message = "Richtig!";
+    }else{
+      message = "Das ist leider falsch.";
+    }
+    message = "<p>" + message + "</p>";
+    document.getElementById("finishCalculation").innerHTML = message;
+  }
+
   return (
     <div id="content">
+
       <h1>Subtraction</h1>
+
+      <form onSubmit={(e) => handleSubmit(e)}>
+        <label htmlFor="calculationInput">
+          Rechnung:
+        </label>
+        <input
+          type="text"
+          id="calculationInput"
+          onChange={(e) => handleInput(e)}
+          aria-label="Rechnung"
+          aria-required="true"
+          ref={calculationInput}/>
+        <input type="submit" value="berechnen"/>
+      </form>
+
+      <div id="overview">
+        <DataGrid
+          dataSource={numbersGrid}
+          keyExpr="id"
+          focusedRowEnabled={true}
+          showBorders={true}
+          showColumnHeaders={false}
+        >
+          <Column dataField="number" />
+        </DataGrid>
+
+        <hr></hr>
+
+        <DataGrid
+          dataSource={resultsGrid}
+          focusedRowEnabled={true}
+          showBorders={true}
+          showColumnHeaders={false}
+        >
+          <Column dataField="number" />
+        </DataGrid>
+      </div>
+
+      <div id="calculation">
+        <ResultCarryForm
+          handleResChange={handleResChange}
+          handleCarryChange={handleCarryChange}/>
+      </div>
+
+      <div id="finishCalculation"></div>
+
+      <div id="idmtResultSteps">
+        <DataGrid
+          dataSource={stepsGrid}
+          focusedRowEnabled={true}
+          showBorders={true}
+          showColumnHeaders={false}
+        >
+          <Column dataField="step" />
+        </DataGrid>
+      </div>
+
+      <Alert
+        showAlert={showAlert}
+        finishCalc={finishCalculation}
+        showIdmtResults={showIdmtResults}
+      />
+
     </div>
   );
 }

+ 3 - 3
src/helpers.js

@@ -1,9 +1,9 @@
- export const addNumbersToGrid = (numbersArr) => {
+ export const addNumbersToGrid = (numbersArr, sign) => {
   const nrGrid = []
   for (let noIdx in numbersArr){
     let nr = numbersArr[noIdx].join("").replace(/&nbsp;/g, " ");
-    if (noIdx == numbersArr.length-1){
-      nr = "+ " + nr;
+    if (parseInt(noIdx) === numbersArr.length-1){
+      nr = sign + " " + nr;
     }
     nrGrid.push({id: parseInt(noIdx)+3, number: nr});
   }