|
@@ -1,349 +1,33 @@
|
|
|
-import React, { useState, useEffect, useRef } from "react";
|
|
|
-import { confirmAlert } from 'react-confirm-alert';
|
|
|
-import "./App.css";
|
|
|
-
|
|
|
-let imdtRes;
|
|
|
-let imdtResIdx;
|
|
|
-let resArr = [];
|
|
|
-
|
|
|
-function App() {
|
|
|
- const [input, setInput] = useState(""); // initial user input like 34+56.7
|
|
|
- const [result, setResult] = 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 handleInput = (e) => {
|
|
|
- setInput(e.target.value);
|
|
|
- // TODO: reset results, etc.
|
|
|
- }
|
|
|
-
|
|
|
- const handleResChange = (e, nosLeft) => {
|
|
|
- if(typeof e === "string"){
|
|
|
- imdtRes = e;
|
|
|
- let carryArrCopy = [...carryArr]
|
|
|
- carryArrCopy[nosLeft] = carryArrCopy[nosLeft+1]
|
|
|
- setCarryArr(carryArrCopy)
|
|
|
- }else{
|
|
|
- imdtRes = e.target.value;
|
|
|
- }
|
|
|
-
|
|
|
- resArr.unshift(imdtRes);
|
|
|
-
|
|
|
- if(nosLeft === 0){
|
|
|
- checkOrSave();
|
|
|
-
|
|
|
-// addResultToDiv(resArr);
|
|
|
-
|
|
|
-
|
|
|
- let resCalc = resArr.join("");
|
|
|
- resCalc = parseFloat(resCalc);
|
|
|
-
|
|
|
-// if(resCalc === result){
|
|
|
-// alert("success")
|
|
|
-// resCalc = 0;
|
|
|
-// }else{
|
|
|
-// alert("error")
|
|
|
-// resCalc = 0;
|
|
|
-// }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- 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) => {
|
|
|
- setInput("1,3+22,450");
|
|
|
- startCalculation();
|
|
|
- e.preventDefault(); // avoid page reload
|
|
|
- }
|
|
|
-
|
|
|
- const afterCommaLen = (number) => {
|
|
|
- let noStrList = number.toString().split(".");
|
|
|
- if (noStrList.length > 1){
|
|
|
- return noStrList[1].length
|
|
|
- }
|
|
|
- return 0
|
|
|
- }
|
|
|
-
|
|
|
- const addNumbersToDiv = (numbers, noOfDigits) => {
|
|
|
- for (let idx in numbers){
|
|
|
- let no = numbers[idx].join("")
|
|
|
- if(idx===numbers.length-1){
|
|
|
- no = "+ " + no
|
|
|
- }
|
|
|
- let pNo = "<p>" + no + "</p>"
|
|
|
- document.getElementById("overview").innerHTML += pNo;
|
|
|
- }
|
|
|
- document.getElementById("overview").innerHTML += carryArr.join("");
|
|
|
- document.getElementById("overview").innerHTML += "<hr>";
|
|
|
- }
|
|
|
-
|
|
|
- const addResultToDiv = () => {
|
|
|
- let res = "<p>" + resArr.join("") + "</p>"
|
|
|
- document.getElementById("overview").innerHTML += res;
|
|
|
- }
|
|
|
-
|
|
|
- const checkOrSave = () => {
|
|
|
- confirmAlert({
|
|
|
- title: "Do you want to submit",
|
|
|
- message: "review or submit your result",
|
|
|
- buttons: [
|
|
|
- {
|
|
|
- label: "review",
|
|
|
- onClick: () => showIdmtResults()
|
|
|
- },
|
|
|
- {
|
|
|
- label: "submit",
|
|
|
- onClick: () => addResultToDiv()
|
|
|
- }
|
|
|
- ]
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- function numbersToArrOfArr(numbers) {
|
|
|
- let befComma = Math.max(...numbers).toString().split(".")[0].length;
|
|
|
- let afterComma = Math.max(...numbers.map(x => afterCommaLen(x)));
|
|
|
- let withComma = Math.max(...numbers.map(x => x.toString().indexOf(".")));
|
|
|
-
|
|
|
- let arrLength;
|
|
|
- if(withComma < 0){ // no comma found
|
|
|
- arrLength = befComma;
|
|
|
- }else{
|
|
|
- arrLength = befComma + afterComma + 1; // add comma and after comma len
|
|
|
- }
|
|
|
-
|
|
|
- let numbersArr = numbers.map(x => x.toString().split(""));
|
|
|
- for (let numArr of numbersArr){
|
|
|
- let commaIdx = numArr.indexOf(".");
|
|
|
-
|
|
|
- // without comma, add before
|
|
|
- while(commaIdx===-1 && numArr.length < befComma){
|
|
|
- numArr.unshift(" "); // add " " before comma
|
|
|
- }
|
|
|
- // without comma, add after
|
|
|
- while(commaIdx===-1 && numArr.length < arrLength){
|
|
|
- numArr.push(" "); // add " " after comma
|
|
|
- }
|
|
|
- // with comma, add before
|
|
|
- while(commaIdx>-1 && commaIdx!==befComma){
|
|
|
- numArr.unshift(" "); // add " " before comma
|
|
|
- commaIdx = numArr.indexOf(".");
|
|
|
- }
|
|
|
- // with comma, add after
|
|
|
- while(numArr.length < arrLength){
|
|
|
- numArr.push(" "); // add " " after comma
|
|
|
- }
|
|
|
- numArr.unshift(" "); // for carry
|
|
|
- }
|
|
|
-
|
|
|
- document.getElementById("overview").innerHTML = "";
|
|
|
- setNumbers(numbersArr);
|
|
|
- setCommaIdx(befComma+1);
|
|
|
- addNumbersToDiv(numbersArr, arrLength);
|
|
|
-
|
|
|
- // TODO: assert all have same length and comma at same index?
|
|
|
+import React from "react";
|
|
|
+import {BrowserRouter, Route, Switch } from "react-router-dom";
|
|
|
|
|
|
- return [numbersArr, befComma]
|
|
|
- }
|
|
|
+import Home from "./Home.js";
|
|
|
+import Addition from "./Addition.js";
|
|
|
+import Subtraction from "./Subtraction.js";
|
|
|
|
|
|
+import Navigation from "./Navigation.js";
|
|
|
+import Footer from "./Footer.js";
|
|
|
+import Error from "./Error.js";
|
|
|
|
|
|
+import "bootstrap/dist/css/bootstrap.min.css";
|
|
|
+import "./App.css";
|
|
|
|
|
|
- const startCalculation = () => {
|
|
|
- if (input.includes("+")){
|
|
|
- let numbers = input.split("+").map(x => parseFloat(x.replace(",",".")));
|
|
|
- let commaIdx = -1;
|
|
|
- setResult(numbers.reduce((x,y) => x+y, 0));
|
|
|
- [numbers, commaIdx] = numbersToArrOfArr(numbers);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- 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;
|
|
|
- let noOfDigits = 0;
|
|
|
- let carryText = "Übertrag = ";
|
|
|
-
|
|
|
- if(typeof numbers === "object" && imdtResIdx !== -1){
|
|
|
- if(typeof imdtResIdx === "undefined"){
|
|
|
- noOfDigits = Math.min(...numbers.map(n => n.length));
|
|
|
- imdtResIdx = noOfDigits-1;
|
|
|
- }
|
|
|
-
|
|
|
- if(imdtResIdx === commaIdx){
|
|
|
- handleResChange(".", nosLeft)
|
|
|
- imdtResIdx = imdtResIdx - 1;
|
|
|
- }
|
|
|
- for (let n in numbers){ // iterate numbers
|
|
|
- if(nosLeft === 1 && carryArr[1] === "0"){
|
|
|
- nosLeft = 0;
|
|
|
- imdtResIdx = -1;
|
|
|
- handleResChange(" ", 0)
|
|
|
- return <></>
|
|
|
- }
|
|
|
- let no = numbers[parseInt(n)][imdtResIdx];
|
|
|
- if(no === "" || no === " "){
|
|
|
- no = 0;
|
|
|
- }
|
|
|
- labelText += no;
|
|
|
-
|
|
|
- if (parseInt(n) === numbers.length - 1){
|
|
|
- if(carryArr[imdtResIdx+1]!=="undefind" && carryArr[imdtResIdx+1] > 0){
|
|
|
- labelText += " + " + carryArr[imdtResIdx+1].toString();
|
|
|
- }
|
|
|
- labelText += " = ";
|
|
|
- }else{
|
|
|
- labelText += " + "; // TODO: replace with -/* etc.
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(carryArr[imdtResIdx] > -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 = () => {
|
|
|
- let realResArr = result.toString().split("");
|
|
|
- while(realResArr.length < resArr.length){
|
|
|
- realResArr.unshift(" "); // 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;
|
|
|
- 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 realSum = 0;
|
|
|
- for (let j=0; j<numbers.length; j++) {
|
|
|
- let no = numbers[j][idxNumbers];
|
|
|
- if (no!=="." && no!==" "){
|
|
|
- trueNumbers = true;
|
|
|
- realSum += parseInt(no);
|
|
|
- }
|
|
|
- text += no
|
|
|
- if (j<numbers.length-1){
|
|
|
- text += " + "
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // ignore indexes without real digits
|
|
|
- if (resArr[idxNumbers]!==" " || carries[idxCarry]!==" "){
|
|
|
- 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"){
|
|
|
- realSum += parseInt(carries[idxCarry]);
|
|
|
- text += " + " + carries[idxCarry] + " Übertrag"
|
|
|
- }
|
|
|
-
|
|
|
- let realCarry = parseInt(realSum/10).toString()
|
|
|
- realSum = (realSum % 10).toString()
|
|
|
- text += " = "
|
|
|
-
|
|
|
- if (trueNumbers){
|
|
|
- text += resArr[idxNumbers]
|
|
|
- text = text.replace(" ", "0")
|
|
|
- text += resArr[idxNumbers]===realSum && carries[idxCarry-1]===realCarry ? "\t\tRichtig" : "\t\tFalsch";
|
|
|
-
|
|
|
- let paragraph = document.createElement("p");
|
|
|
- paragraph.innerHTML = text
|
|
|
- document.getElementById("idmtResultSteps").appendChild(paragraph);
|
|
|
-
|
|
|
- let btn = document.createElement("button");
|
|
|
- btn.innerHTML = "return to step " + text;
|
|
|
- btn.addEventListener("click", () => startOver(i));
|
|
|
- document.getElementById("idmtResultSteps").appendChild(btn);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+function App() {
|
|
|
+ return (
|
|
|
+ <div id="wrapper">
|
|
|
|
|
|
- const startOver = (idx) => {
|
|
|
- console.log("clicked at " + idx)
|
|
|
- }
|
|
|
+ <BrowserRouter>
|
|
|
+ <Navigation />
|
|
|
+ <Switch>
|
|
|
+ <Route exact path="/" component={Home} />
|
|
|
+ <Route path="/addition" component={Addition} />
|
|
|
+ <Route path="/subtraction" component={Subtraction} />
|
|
|
+ <Route component={Error} />
|
|
|
+ </Switch>
|
|
|
+ </BrowserRouter>
|
|
|
|
|
|
+ <Footer/>
|
|
|
|
|
|
- return (
|
|
|
- <div className="App">
|
|
|
- <form onSubmit={(e) => handleSubmit(e)}>
|
|
|
- <input
|
|
|
- type="text"
|
|
|
- onChange={(e) => handleInput(e)}
|
|
|
- aria-label="your calculation"
|
|
|
- aria-required="true"/>
|
|
|
- <input type="submit" value="calculate"/>
|
|
|
- </form>
|
|
|
- <div id="overview"></div>
|
|
|
- <div id="calculation">
|
|
|
- <ResultCarryForm
|
|
|
- handleResChange={handleResChange}
|
|
|
- handleCarryChange={handleCarryChange}/>
|
|
|
- </div>
|
|
|
- <div id="idmtResultSteps"></div>
|
|
|
</div>
|
|
|
);
|
|
|
}
|