var numDies = 0; // master counter for our number of dies var outputVisible = 0; // Status of whether the output is displayed or not // Arrays to store values for graphs var dieCount = []; var dataROA = []; var dataElong = []; var dataDelta = []; ///// START OF MATHS FUNCTIONS ///// // This function gets the reduction of area with two provided sizes, and returns it function getReduction(startSize, finalSize) { var startArea = Math.PI * ((startSize / 2) * (startSize / 2)); var finalArea = Math.PI * ((finalSize / 2) * (finalSize / 2)); return ((startArea - finalArea) / startArea) * 100; } // This function gets the elongation function getElongation(startSize, finalSize) { return (Math.pow(startSize / finalSize, 2) - 1) * 100; } function getDelta(startSize, finalSize, angle) { angle = (angle * 0.5) * (Math.PI / 180); // Convert to semi-angle and radians return ((startSize + finalSize) / (startSize - finalSize)) * Math.sin(angle); } function toMillimetres(size) { //convert to mm size = Math.round((size * 100) * 25.4) / 100; return size; } function toInches(size) { //convert to inches size = Math.round((size * 1000) / 25.4) / 1000; return size; } ///// END OF MATHS SECTION ///// ///// START OF DISPLAY SECTION ///// function addReduction() { numDies ++; // Increment our die count // Create the data going into the row var inputLabel = ""; var inputSize = ""; var inputAngle = ""; // create the row var table = document.getElementById("data"); // get table ID var row = table.insertRow(-1); // Insert a new row (the -1 means we add to the END of the table) var cell1 = row.insertCell(0); // Create and add a cell to the table var cell2 = row.insertCell(1); var cell3 = row.insertCell(2); cell1.innerHTML = inputLabel; // Set the values of the cells we've created cell2.innerHTML = inputSize cell3.innerHTML = inputAngle; if (outputVisible == 1) { // Check if out output is visible and update immediately when adding dies doMath(); } } function removeReduction() { // function to remove the last row numDies --; document.getElementById("data").deleteRow(-1); // delete the last row in the table // Remove the last item in each array to remove the tick from the graph dieCount.splice(-1); dataROA.splice(-1); dataElong.splice(-1); dataDelta.splice(-1); if (outputVisible == 1) { // Check if out output is visible and update immediately when adding dies doMath(); } } ///// END OF DISPLAY SECTION ///// ///// START OF ALGORITHMS SECTION ///// function doMath() { outputVisible = 1; // set visible status to enabled outputTable = document.getElementById("output"); // Select our output data table outputTable.innerHTML = ""; // Make the output graph visible outputGraph = document.getElementById("outputChart"); outputGraph.innerHTML = ""; var row = []; row[0] = outputTable.insertRow(0); row[0].id = "outputHeader"; // set the header row var cell1 = row[0].insertCell(0); //blank var cell2 = row[0].insertCell(1); // "Start -> Finish" var cell3 = row[0].insertCell(2); // "ROA" var cell4 = row[0].insertCell(3); // "Elong" var cell5 = row[0].insertCell(4); // "Delta" // Create the header of the table cell1.innerHTML = "Draft"; cell1.id = "reductionNumHeader"; cell2.innerHTML = "Start -> Finish"; cell2.id = "startFinish"; cell3.innerHTML = "ROA (%)"; cell3.id = "roa"; cell4.innerHTML = "Elong (%)"; cell4.id = "elong"; cell5.innerHTML = "Δ Factor"; cell5.id = "delta"; for (var i = 1; i < numDies + 1; i++) { inSize = document.getElementById("die" + (i - 1)).value; // the input size outSize = document.getElementById("die" + i).value; // output size angle = document.getElementById("angle" + i).value; if (i == 1 && document.getElementById("metric").checked == true) { // If this is the first die in the setup, check if it's a metric/rod start and convert it inSize = toInches(inSize); } // Format our numbers to prevent maximum user stupidity if (inSize < 10.0 && inSize > 0) { // If we have a 'proper' number i.e. ".130" inSize = Number(inSize); } else { // re-format the number if it's 'wrong' i.e. "130" inSize = inSize / 1000; } if (outSize < 10.0 && outSize > 0) { // If we have a 'proper' number i.e. ".130" outSize = Number(outSize); } else { // re-format the number if it's 'wrong' i.e. "130" outSize = outSize / 1000; } row[i] = outputTable.insertRow(i); // Add a new row to the END of the table // Add all our cells to the table // We also give them HTML ID's to format things with CSS nicely cell1 = row[i].insertCell(0); cell1.id = "reductionNum"; cell2 = row[i].insertCell(1); cell2.id = "startFinish"; cell3 = row[i].insertCell(2); cell3.id = "roa"; cell4 = row[i].insertCell(3); cell4.id = "elong"; cell5 = row[i].insertCell(4); cell5.id = "delta"; // These next lines calculate and round the data to two decimal places dataROA[i - 1] = (Math.round(getReduction(inSize, outSize) * 100) / 100).toFixed(2); dataElong[i - 1] = (Math.round(getElongation(inSize, outSize) * 100) / 100).toFixed(2); dataDelta[i - 1] = (Math.round(getDelta(inSize, outSize, angle) * 100) / 100).toFixed(2); // Set the values of the cells in our table cell1.innerHTML = "#" + i + ": "; cell2.innerHTML = inSize.toFixed(3) + "\" (" + toMillimetres(inSize) + " mm) -> " + outSize.toFixed(3) + "\" (" + toMillimetres(outSize) + " mm)"; cell3.innerHTML = dataROA[i - 1]; cell4.innerHTML = dataElong[i - 1]; cell5.innerHTML = dataDelta[i - 1]; dieCount[i - 1] = i; } drawGraph(); getStatistics(); // Add spacers document.getElementById("spacer1").style.display = 'block'; document.getElementById("spacer2").style.display = 'block'; document.getElementById("spacer3").style.display = 'block'; } function drawGraph() { // Documentation for the following chart-building command can be found at https://chartjs.org const outputData = new Chart("outputData", { type: "line", data: { labels: dieCount, datasets: [{ data: dataROA, label: "Reduction of Area", borderColor: "green", fill: false, pointStyle: 'circle', pointRadius: 4, pointHoverRadius: 7, yAxisID: 'y', tension: 0 },{ data: dataElong, label: "Elongation", borderColor: "blue", fill: false, pointStyle: 'rect', pointRadius: 5, pointHoverRadius: 8, yAxisID: 'y', tension: 0 },{ data: dataDelta, label: "Δ Factor", borderColor: "red", fill: false, pointStyle: 'triangle', pointRadius: 5, pointHoverRadius: 8, yAxisID: 'y1', tension: 0 }], }, options: { responsive: true, interaction: { mode: 'index', intersect: false, }, stacked: false, plugins: { title: { display: true, text: "Draft Analysis" }, legend: { labels: { usePointStyle: true } } }, scales: { y: { type: 'linear', display: true, position: 'left', title: { display: true, text: "% (RoA/Elong)" }, suggestedMin: 0, suggestedMax: 30, }, y1: { type: 'linear', display: true, position: 'right', title: { display: true, text: "Δ Factor" }, suggestedMin: 0, suggestedMax: 6, grid: { drawOnChartArea: false } }, x: { title: { display: true, text: "Draft #" }, } }, }, }); } function getStatistics() { // Get data from page var div = document.getElementById("statistics"); var startSize = formatCheck(document.getElementById("die0").value); var finalSize = formatCheck(document.getElementById("die" + numDies).value); // Check if the start size is metric/rod and convert to inches if (document.getElementById("metric").checked == true) { startSize = toInches(startSize); } // We'll do a lot of the heavy math-lifting here to make things easier to read below var avgDelta = 0; var avgROA = 0; var avgElong = 0; var totalROA = Math.round(getReduction(startSize, finalSize) * 100) / 100; var totalElong = Math.round(getElongation(startSize, finalSize) * 100) / 100; // Get average ROA for (var i = 0; i < numDies; i++) { avgROA += Number(dataROA[i]); } avgROA = (Math.round((avgROA / numDies) * 100) / 100).toFixed(2); // Get average Elong for (var i = 0; i < numDies; i++) { avgElong += Number(dataElong[i]); } avgElong = (Math.round((avgElong / numDies) * 100) / 100).toFixed(2); // Get average delta for (var i = 0; i < numDies; i++) { avgDelta += Number(dataDelta[i]); } avgDelta = (Math.round((avgDelta / numDies) * 100) / 100).toFixed(2); // Create the table to display statistics div.innerHTML = "