(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(); })();