refactor: Reimplement calculator logic with new JavaScript and PHP files, removing numerous old Python scripts and related content.

This commit is contained in:
Ben
2026-03-06 19:56:03 -08:00
parent d381cd6610
commit e35fdcb118
34 changed files with 6899 additions and 4099 deletions

156
hdyc-calculators.js Normal file
View File

@@ -0,0 +1,156 @@
(function() {
function init() {
const containers = document.querySelectorAll('.hdyc-calc-container');
if (containers.length === 0) return;
containers.forEach(container => {
const type = container.dataset.hdycType;
const factor = parseFloat(container.dataset.hdycFactor) || 1;
const offset = parseFloat(container.dataset.hdycOffset) || 0;
const in1 = container.querySelector('#input-1');
const in2 = container.querySelector('#input-2');
const in3 = container.querySelector('#input-3');
if (!in1 || !in2) return;
function solve(source) {
let v1 = parseFloat(in1.value);
let v2 = parseFloat(in2.value);
let v3 = in3 ? parseFloat(in3.value) : NaN;
if (type === 'standard') {
if (source === 1) {
if (!isNaN(v1)) in2.value = parseFloat((v1 * factor + offset).toFixed(6));
else in2.value = '';
} else {
if (!isNaN(v2)) in1.value = parseFloat(((v2 - offset) / factor).toFixed(6));
else in1.value = '';
}
} else if (type === 'inverse') {
// Logic: v1 * v2 = factor (constant)
if (source === 1) {
if (!isNaN(v1) && v1 !== 0) in2.value = parseFloat((factor / v1).toFixed(6));
else in2.value = '';
} else {
if (!isNaN(v2) && v2 !== 0) in1.value = parseFloat((factor / v2).toFixed(6));
else in1.value = '';
}
} else if (type === '3col') {
// Standard 3-col: v3 = v1 / v2 (e.g. Watts = Amps * Volts -> in3 = in1 / in2? No, usually Watts is in3)
// Let's look at legacy scripts.
// grams-to-moles: in3 (moles) = in1 (mass) / in2 (molar mass)
// watts-to-amps: in3 (amps) = in1 (watts) / in2 (volts)
if (source === 1 || source === 2) {
if (!isNaN(v1) && !isNaN(v2) && v2 !== 0) in3.value = parseFloat((v1 / v2).toFixed(6));
else in3.value = '';
} else {
if (!isNaN(v3) && !isNaN(v2)) in1.value = parseFloat((v3 * v2).toFixed(6));
else in1.value = '';
}
} else if (type === '3col-mul') {
// v3 = v1 * v2 (e.g. Lux to Lumens: Lumens(3) = Lux(1) * Area(2))
if (source === 1 || source === 2) {
if (!isNaN(v1) && !isNaN(v2)) in3.value = parseFloat((v1 * v2).toFixed(6));
else in3.value = '';
} else {
if (!isNaN(v3) && !isNaN(v2) && v2 !== 0) in1.value = parseFloat((v3 / v2).toFixed(6));
else in1.value = '';
}
} else if (type === 'dms-dd') {
// DD to DMS (in1=DD, in2=DMS text)
if (source === 1) {
if (!isNaN(v1)) {
let d = Math.floor(v1); let md = (v1 - d) * 60; let m = Math.floor(md); let sec = ((md - m) * 60).toFixed(2);
in2.value = `${d}° ${m}' ${sec}"`;
} else in2.value = '';
} else {
let str = in2.value;
let match = str.match(/(?:([0-9.-]+)\s*°)?\s*(?:([0-9.-]+)\s*')?\s*(?:([0-9.-]+)\s*")?/);
if (match) {
let d = parseFloat(match[1]) || 0; let m = parseFloat(match[2]) || 0; let sec = parseFloat(match[3]) || 0;
if (str.trim().length > 0) in1.value = parseFloat((d + m/60 + sec/3600).toFixed(6));
else in1.value = '';
} else in1.value = '';
}
} else if (type === 'dd-dms') {
// DMS to DD inverse?
// Actually the legacy code for "dms-to-dd" has input-1 as DMS and input-2 as DD.
// I'll handle based on the ID mapping in the container.
} else if (type === 'dec-frac') {
function gcd(a, b) { return b ? gcd(b, a % b) : a; }
if (source === 1) {
if (!isNaN(v1)) {
let len = v1.toString().split('.')[1] ? v1.toString().split('.')[1].length : 0;
let den = Math.pow(10, len); let num = v1 * den; let div = gcd(num, den);
in2.value = `${num/div}/${den/div}`;
} else in2.value = '';
} else {
let parts = in2.value.split('/');
if (parts.length === 2 && !isNaN(parts[0]) && !isNaN(parts[1]) && parts[1] != 0) in1.value = parseFloat((parts[0]/parts[1]).toFixed(6));
else { let f = parseFloat(parts[0]); if (!isNaN(f)) in1.value = f; else in1.value = ''; }
}
} else if (type === 'db-int') {
if (source === 1) { if (!isNaN(v1)) in2.value = parseFloat((1e-12 * Math.pow(10, v1/10)).toExponential(6)); else in2.value = ''; }
else { if (!isNaN(v2) && v2 > 0) in1.value = parseFloat((10 * Math.log10(v2 / 1e-12)).toFixed(6)); else in1.value = ''; }
} else if (type === 'db-spl') {
if (source === 1) { if (!isNaN(v1)) in2.value = parseFloat((20 * Math.pow(10, v1/20)).toFixed(6)); else in2.value = ''; }
else { if (!isNaN(v2) && v2 > 0) in1.value = parseFloat((20 * Math.log10(v2 / 20)).toFixed(6)); else in1.value = ''; }
} else if (type === 'db-v') {
if (source === 1) { if (!isNaN(v1)) in2.value = parseFloat((1 * Math.pow(10, v1/20)).toFixed(6)); else in2.value = ''; }
else { if (!isNaN(v2) && v2 > 0) in1.value = parseFloat((20 * Math.log10(v2 / 1)).toFixed(6)); else in1.value = ''; }
} else if (type === 'db-w') {
if (source === 1) { if (!isNaN(v1)) in2.value = parseFloat((1 * Math.pow(10, v1/10)).toFixed(6)); else in2.value = ''; }
else { if (!isNaN(v2) && v2 > 0) in1.value = parseFloat((10 * Math.log10(v2 / 1)).toFixed(6)); else in1.value = ''; }
} else if (type === 'base') {
const fromBase = parseInt(container.dataset.hdycFrom) || 10;
const toBase = parseInt(container.dataset.hdycTo) || 2;
if (source === 1) {
try {
const val = in1.value.trim();
if (val === '') { in2.value = ''; return; }
const dec = parseInt(val, fromBase);
if (!isNaN(dec)) in2.value = dec.toString(toBase).toUpperCase();
else in2.value = 'Invalid';
} catch(e) { in2.value = 'Error'; }
} else {
try {
const val = in2.value.trim();
if (val === '') { in1.value = ''; return; }
const dec = parseInt(val, toBase);
if (!isNaN(dec)) in1.value = dec.toString(fromBase).toUpperCase();
else in1.value = 'Invalid';
} catch(e) { in1.value = 'Error'; }
}
} else if (type === 'text-bin') {
if (source === 1) {
in2.value = in1.value.split('').map(char => char.charCodeAt(0).toString(2).padStart(8, '0')).join(' ');
} else {
try {
in1.value = in2.value.split(' ').map(bin => String.fromCharCode(parseInt(bin, 2))).join('');
} catch(e) { in1.value = 'Error'; }
}
} else if (type === 'bin-text') {
if (source === 1) {
try {
in2.value = in1.value.split(' ').map(bin => String.fromCharCode(parseInt(bin, 2))).join('');
} catch(e) { in2.value = 'Error'; }
} else {
in1.value = in2.value.split('').map(char => char.charCodeAt(0).toString(2).padStart(8, '0')).join(' ');
}
}
}
in1.addEventListener('input', () => solve(1));
in2.addEventListener('input', () => solve(2));
if (in3) in3.addEventListener('input', () => solve(3));
const uParams = new URLSearchParams(window.location.search);
if (uParams.has('v1')) { in1.value = uParams.get('v1'); solve(1); }
else if (uParams.has('v2')) { in2.value = uParams.get('v2'); solve(2); }
else if (uParams.has('v3') && in3) { in3.value = uParams.get('v3'); solve(3); }
});
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
else init();
})();