Bugfixes, including removing elements from the graph when removing entries, and three-decimal formatting our inches. Layout changes, in both code and webpage. Some edits to the print layout to improve printing and readability
494 lines
16 KiB
JavaScript
494 lines
16 KiB
JavaScript
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 = "<label for=\"die" + numDies + "\" style=\"text-align:right;\">#" + (numDies) + ": </label>";
|
||
var inputSize = "<input id=\"die" + numDies + "\" type=\"text\" autocomplete=\"off\" value=\"0.000\" size=\"4\" onchange=\"doMath()\" />";
|
||
var inputAngle = "<input id=\"angle" + numDies + "\" type=\"text\" autocomplete=\"off\" value=\"16\" size=\"2\" onchange=\"doMath()\" style=\"text-align:center;\"/>";
|
||
|
||
// 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 = "<canvas id=\"outputData\"></canvas>";
|
||
|
||
|
||
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 = "<p></p><h5 align=\"center\" id=\"statsSummaryHeader\">Summary</h5><table id=\"statsTable\"></table>";
|
||
|
||
var statsTable = document.getElementById("statsTable");
|
||
|
||
|
||
//// ROW 1 ////
|
||
var row = statsTable.insertRow(0);
|
||
|
||
var c1 = row.insertCell(0);
|
||
var c2 = row.insertCell(1);
|
||
var c3 = row.insertCell(2);
|
||
var c4 = row.insertCell(3);
|
||
var c5 = row.insertCell(4);
|
||
|
||
// COL 1
|
||
c1.innerHTML = "# Of Reductions: ";
|
||
c1.id = "statsCol1";
|
||
c2.innerHTML = numDies;
|
||
c2.id = "statsCol2";
|
||
//
|
||
c3.innerHTML = " ";
|
||
c3.id = "statsCol3";
|
||
// COL 2
|
||
c4.innerHTML = "Avg. Δ Factor: ";
|
||
c4.id = "statsCol4";
|
||
c5.innerHTML = avgDelta;
|
||
c5.id = "statsCol5";
|
||
|
||
|
||
//// ROW 2 ////
|
||
row = statsTable.insertRow(1);
|
||
|
||
c1 = row.insertCell(0);
|
||
c2 = row.insertCell(1);
|
||
c3 = row.insertCell(2);
|
||
c4 = row.insertCell(3);
|
||
c5 = row.insertCell(4);
|
||
|
||
// COL 1
|
||
c1.innerHTML = "Total R. Of Diameter: ";
|
||
c1.id = "statsCol4";
|
||
c2.innerHTML = (Math.round((startSize - finalSize) * 1000) / 1000).toFixed(3) + "\"";
|
||
c2.id = "statsCol5";
|
||
//
|
||
c3.innerHTML = " ";
|
||
c3.id = "statsCol3";
|
||
// COL 2
|
||
c4.innerHTML = "------";
|
||
c4.id = "statsCol4";
|
||
c5.innerHTML = "---";
|
||
c5.id = "statsCol5";
|
||
|
||
|
||
//// ROW 3 ////
|
||
row = statsTable.insertRow(2);
|
||
|
||
c1 = row.insertCell(0);
|
||
c2 = row.insertCell(1);
|
||
c3 = row.insertCell(2);
|
||
c4 = row.insertCell(3);
|
||
c5 = row.insertCell(4);
|
||
|
||
// COL 1
|
||
c1.innerHTML = "Total R. Of Area: ";
|
||
c1.id = "statsCol1";
|
||
c2.innerHTML = totalROA + "%";
|
||
c2.id = "statsCol2";
|
||
//
|
||
c3.innerHTML = " ";
|
||
c3.id = "statsCol3";
|
||
// COL 2
|
||
c4.innerHTML = "Avg. R. of Area: ";
|
||
c4.id = "statsCol4";
|
||
c5.innerHTML = avgROA + "%";
|
||
c5.id = "statsCol5";
|
||
|
||
|
||
//// ROW 4 ////
|
||
row = statsTable.insertRow(3);
|
||
|
||
c1 = row.insertCell(0);
|
||
c2 = row.insertCell(1);
|
||
c3 = row.insertCell(2);
|
||
c4 = row.insertCell(3);
|
||
c5 = row.insertCell(4);
|
||
|
||
// COL 1
|
||
c1.innerHTML = "Total Elong.: ";
|
||
c1.id = "statsCol1";
|
||
c2.innerHTML = totalElong + "%";
|
||
c2.id = "statsCol2";
|
||
//
|
||
c3.innerHTML = " ";
|
||
c3.id = "statsCol3";
|
||
// COL 2
|
||
c4.innerHTML = "Avg. Elongation: ";
|
||
c4.id = "statsCol4";
|
||
c5.innerHTML = avgElong + "%";
|
||
c5.id = "statsCol5";
|
||
|
||
}
|
||
|
||
function clearScreen() {
|
||
// Reset variables back to defaults
|
||
numDies = 0;
|
||
outputVisible = 0;
|
||
|
||
// Clear and reset inputs
|
||
var inputStart = document.getElementById("die0");
|
||
inputStart.value = "0.0";
|
||
var unitsType = document.getElementById("metric");
|
||
unitsType.checked = true;
|
||
var inputTable = document.getElementById("data");
|
||
inputTable.innerHTML = "<tr style=\"font-size: 75%;\"><td><p></p>Draft<p></p></td><td>Exit Dia.</td><td>Angle (2α)</td></tr>";
|
||
|
||
// Delete the output table
|
||
var outputTable = document.getElementById("output");
|
||
outputTable.innerHTML = "";
|
||
|
||
// Delete the output graph
|
||
outputGraph = document.getElementById("outputChart");
|
||
outputGraph.innerHTML = "";
|
||
|
||
statistics = document.getElementById("statistics");
|
||
statistics.innerHTML = "";
|
||
|
||
// Delete the spacers
|
||
document.getElementById("spacer1").style.display = 'none';
|
||
document.getElementById("spacer2").style.display = 'none';
|
||
document.getElementById("spacer3").style.display = 'none';
|
||
|
||
// Add two fresh entries
|
||
addReduction();
|
||
addReduction();
|
||
}
|
||
|
||
|
||
///// END OF ALGORITHMS SECTION /////
|
||
|
||
///// EXTRA SECTION /////
|
||
|
||
function printScreen() {
|
||
var subtitle = document.getElementById("subtitle");
|
||
var reductionCount = document.getElementById("numReductions");
|
||
|
||
// Get input size, and format it
|
||
var inputSize = document.getElementById("die0").value;
|
||
|
||
|
||
// If our start size is metric show that, otherwise swap them to show 'murican first
|
||
if (document.getElementById("metric").checked) {
|
||
var inputText = inputSize + " mm (" + toInches(inputSize) + "\")";
|
||
} else {
|
||
var inputText = formatCheck(inputSize) + "\" (" + toMillimetres(formatCheck(inputSize)) + " mm)";
|
||
}
|
||
|
||
|
||
// Get the final size and format it
|
||
var outputSize = document.getElementById("die" + numDies).value;
|
||
outputSize = formatCheck(outputSize).toFixed(3);
|
||
var outputText = (outputSize) + "\" (" + toMillimetres(outputSize) + " mm)";
|
||
|
||
// Create and set the header
|
||
subtitle.innerHTML = "For " + inputText + " to " + outputText;
|
||
|
||
// Change the name of the window to save the file with the same
|
||
var pageTitle = document.getElementById("pageTitle");
|
||
var title = pageTitle.innerHTML;
|
||
pageTitle.innerHTML = "Draft Analysis for " + inputSize + " to " + outputSize;
|
||
|
||
// Let the browser handle printing
|
||
window.print();
|
||
|
||
// Reset the page title back to normal
|
||
pageTitle.innerHTML = title;
|
||
}
|
||
|
||
function formatCheck(value) {
|
||
if (value < 10.0 && value > 0) { // If we have a 'proper' number i.e. ".130"
|
||
value = Number(value);
|
||
} else { // re-format the number if it's 'wrong' i.e. "130"
|
||
value = value / 1000;
|
||
}
|
||
return value;
|
||
}
|