Skip to content

Commit 933fbab

Browse files
Merge pull request #584 from michmela44/CalculatorRewrite
Rewrite Calculator code and moved code to separate js file to make it easier to deal with in VSCode
2 parents 09f318f + 4f678c4 commit 933fbab

File tree

2 files changed

+298
-166
lines changed

2 files changed

+298
-166
lines changed

docs/lowrider/calculator.js

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
// Enum to help keep track of unit systems rather than hard-coded strings throughout the code
2+
const Units = Object.freeze({
3+
Metric: "mm",
4+
Imperial: "inches"
5+
});
6+
7+
// object to hold offsets in a spot that is easy to edit
8+
const offsets = Object.freeze({
9+
xrail_core: 169,
10+
yrail_minus_work: 255,
11+
ytable_minus_work: 313,
12+
xbelt_extra: 180,
13+
ybelt_extra: 200,
14+
xtable_extra: 110,
15+
xrail_cushion: 3
16+
});
17+
18+
// initialize current display unit
19+
var displayUnit = Units.Metric;
20+
21+
// To prevent rounding error creep, we are going to keep the desired size in
22+
// variables instead of relying on the after-conversion number on display in the textboxes
23+
var xUsable = 1220;
24+
var yUsable = 2440;
25+
var xThickness = 6.5;
26+
27+
28+
/**
29+
* Update display.
30+
*
31+
* This updates the visual components on the page with the correct text, etc. to match the selected unit.
32+
*
33+
* @param {Units} currentUnit Current Display unit.
34+
*/
35+
function setUnitDisplay(currentUnit) {
36+
switch (currentUnit) {
37+
case Units.Metric:
38+
// Find all the labels and change them to inches
39+
$(".units").text(Units.Metric);
40+
// Set the step attributes (you can also set other attributes here, like min, max, whatever)
41+
$("input[name=xwork]").attr({
42+
"step": 10.0
43+
});
44+
$("input[name=ywork]").attr({
45+
"step": 10.0
46+
});
47+
$("input[name=xzplate]").attr({
48+
"step": 0.1
49+
});
50+
break;
51+
case Units.Imperial:
52+
// Find all the labels and change them to inches
53+
$(".units").text(Units.Imperial);
54+
55+
// Set the step attributes (you can also set other attributes here, like min, max, whatever)
56+
$("input[name=xwork]").attr({
57+
"step": 0.125
58+
});
59+
$("input[name=ywork]").attr({
60+
"step": 0.125
61+
});
62+
$("input[name=xzplate]").attr({
63+
"step": 0.004
64+
});
65+
break;
66+
}
67+
}
68+
69+
/**
70+
* Switch to Metric
71+
*
72+
* This updates the inputs on the page with the correct text to match the selected unit, and updates the calculator
73+
* Should be called when the unit selector switches to mm
74+
*/
75+
function to_mm() {
76+
var isUnitChanging = displayUnit === Units.Imperial;
77+
displayUnit = Units.Metric;
78+
setUnitDisplay(displayUnit);
79+
80+
// Get the current units
81+
if (isUnitChanging) {
82+
// Change the units.
83+
// If we are changing from inches, round up to the next highest mm to keep display clean
84+
// Underlying values remain the same to preserve calculation and prevent rounding error creep when switching back and forth
85+
$("input[name=xwork]").val(Math.ceil(xUsable));
86+
$("input[name=ywork]").val(Math.ceil(yUsable));
87+
88+
// XZ plate thickness might require a little more accuracy so just display to 2 decimal places. This is more likely a mcahined part
89+
// than wood being cut with simple tools
90+
$("input[name=xzplate]").val(parseFloat(xThickness.toFixed(2)));
91+
}
92+
93+
// Recalculate the rest of the page.
94+
calculate();
95+
}
96+
97+
/**
98+
* Switch to Imperial
99+
*
100+
* This updates the inputs on the page with the correct text to match the selected unit, and updates the calculator
101+
* Should be called when the unit selector switches to inches
102+
*/
103+
function to_inch() {
104+
var isUnitChanging = displayUnit === Units.Metric;
105+
displayUnit = Units.Imperial;
106+
setUnitDisplay(displayUnit);
107+
108+
if (isUnitChanging) {
109+
// Change the units.
110+
$("input[name=xwork]").val(roundToNearest(xUsable / 25.4));
111+
$("input[name=ywork]").val(roundToNearest(yUsable / 25.4));
112+
113+
// XZ plate thickness might require a little more accuracy so just display to 3 decimal places. This is more likely a mcahined part
114+
// than wood being cut with simple tools
115+
$("input[name=xzplate]").val(parseFloat((xThickness / 25.4).toFixed(3)));
116+
}
117+
118+
// Recalculate the rest of the page.
119+
calculate();
120+
}
121+
122+
/**
123+
* Round Up To Nearest 1/8".
124+
*
125+
* Round up the supplied value to the next nearest 1/8" increment. This only affects Imperial measurements as metric values
126+
* should already be rounded to the nearest whole number.
127+
*
128+
* @param {number} value value to be rounded.
129+
*/
130+
function roundUpToNearest(value) {
131+
return Math.ceil(value * 8) / 8; // Round to .125
132+
}
133+
134+
/**
135+
* Round To Nearest 1/8".
136+
*
137+
* Round up the supplied value to the next nearest 1/8" increment. This only affects Imperial measurements as metric values
138+
* should already be rounded to the nearest whole number.
139+
*
140+
* @param {number} value value to be rounded.
141+
*/
142+
function roundToNearest(value) {
143+
return Math.round(value * 8) / 8; // Round to .125
144+
}
145+
146+
/**
147+
* Reset Workspace
148+
*
149+
* Resets inputs back to initial values. Retains selected unit system
150+
*/
151+
function reset_work() {
152+
xUsable = 1220;
153+
yUsable = 2440;
154+
xThickness = 6.5;
155+
156+
switch (displayUnit) {
157+
case Units.Metric:
158+
$("input[name=xwork]").val(xUsable);
159+
$("input[name=ywork]").val(yUsable);
160+
$("input[name=xzplate]").val(xThickness);
161+
break;
162+
case Units.Imperial:
163+
$("input[name=xwork]").val(roundToNearest(xUsable / 25.4));
164+
$("input[name=ywork]").val(roundToNearest(yUsable / 25.4));
165+
166+
// XZ plate thickness might require a little more accuracy so just display to 3 decimal places. This is more likely a mcahined part
167+
// than wood being cut with simple tools
168+
$("input[name=xzplate]").val(parseFloat((xThickness / 25.4).toFixed(3)));
169+
break;
170+
}
171+
172+
calculate();
173+
}
174+
175+
/**
176+
* X Usable Cutting Area changed
177+
*
178+
* Update calculator when X Usable changes. Should be called when the X Usable value is changed in the interface.
179+
*/
180+
function xwork_changed() {
181+
var xwork = parseFloat($("input[name=xwork]").val());
182+
if (!isNaN(xwork)) {
183+
switch (displayUnit) {
184+
case Units.Metric:
185+
xUsable = xwork;
186+
break;
187+
case Units.Imperial:
188+
xUsable = xwork * 25.4;
189+
break;
190+
}
191+
192+
calculate();
193+
}
194+
}
195+
196+
/**
197+
* Y Usable Cutting Area changed
198+
*
199+
* Update calculator when Y Usable changes. Should be called when the Y Usable value is changed in the interface.
200+
*/
201+
function ywork_changed() {
202+
var ywork = parseFloat($("input[name=ywork]").val());
203+
if (!isNaN(ywork)) {
204+
switch (displayUnit) {
205+
case Units.Metric:
206+
yUsable = ywork;
207+
break;
208+
case Units.Imperial:
209+
yUsable = ywork * 25.4;
210+
break;
211+
}
212+
213+
calculate();
214+
}
215+
}
216+
217+
/**
218+
* XZ Plate Thickness changed
219+
*
220+
* Update calculator when XZ Plate changes. Should be called when the XZ Plate Thickness value is changed in the interface.
221+
*/
222+
function xthickness_changed() {
223+
var xzthick = parseFloat($("input[name=xzplate]").val());
224+
if (!isNaN(xzthick)) {
225+
switch (displayUnit) {
226+
case Units.Metric:
227+
xThickness = xzthick;
228+
break;
229+
case Units.Imperial:
230+
xThickness = xzthick * 25.4;
231+
break;
232+
}
233+
234+
calculate();
235+
}
236+
}
237+
238+
/**
239+
* Convert to Display Units.
240+
*
241+
* Convert the supplied value to display units. Currently only affects Imperial display unit, as all values are held in memory in Metric
242+
*
243+
* @param {number} value value to be rounded.
244+
*/
245+
function convertToDisplayUnits(val) {
246+
if (displayUnit === Units.Imperial)
247+
return val / 25.4;
248+
else
249+
return val;
250+
}
251+
252+
/**
253+
* Update Calculated values.
254+
*
255+
* Take the values in memory and update the calculator section of the page with calculated values in the correct display unit
256+
*/
257+
function calculate() {
258+
// Calculate strut plate width first, then use the strut plate dimension to calculate other values
259+
// since this value will be rounded up to the next mm
260+
var xstrut = Math.ceil(xUsable + offsets.xrail_core);
261+
var xbelts = xstrut + offsets.xbelt_extra;
262+
var xtable = xstrut + 2 * xThickness + offsets.xtable_extra;
263+
264+
var yrail = yUsable + offsets.yrail_minus_work;
265+
var ybelts = yrail + offsets.ybelt_extra;
266+
var ytable = yUsable + offsets.ytable_minus_work;
267+
268+
var belt_total = 1 * xbelts + 2 * ybelts;
269+
270+
// handle the xrail special case where we want a little cushion to makes sure the plates don't kick out
271+
// we do this calculation in display units to make sure rounding errors don't cause us to be 0 or 2 increments off
272+
var convertedXStrut = roundUpToNearest(convertToDisplayUnits(xstrut));
273+
var xrails = convertedXStrut - roundUpToNearest(convertToDisplayUnits(offsets.xrail_cushion));
274+
275+
$("span[name=strut]").text(convertedXStrut);
276+
$("span[name=xrails]").text(xrails);
277+
$("span[name=yrail]").text(roundUpToNearest(convertToDisplayUnits(yrail)));
278+
$("span[name=xbelts]").text(roundUpToNearest(convertToDisplayUnits(xbelts)));
279+
$("span[name=ybelts]").text(roundUpToNearest(convertToDisplayUnits(ybelts)));
280+
$("span[name=belt_total]").text(roundUpToNearest(convertToDisplayUnits(belt_total)));
281+
$("span[name=xtable]").text(roundUpToNearest(convertToDisplayUnits(xtable)));
282+
$("span[name=ytable]").text(roundUpToNearest(convertToDisplayUnits(ytable)));
283+
}
284+
285+
// Set these up the first time.
286+
$(window).on('load', function () {
287+
// Get back to mm
288+
$("input[value=mm]").prop('checked', true);
289+
$("input[value=inches]").prop('checked', false);
290+
291+
to_mm();
292+
293+
reset_work();
294+
});

0 commit comments

Comments
 (0)