<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
<title>ENG-CALC PRO</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
–crt-green: #00ff41;
–crt-dim: #00c032;
–crt-dark: #003a0f;
–crt-bg: #020c03;
–amber: #ffb000;
–amber-dim: #cc8a00;
–red: #ff3a3a;
–blue: #00cfff;
–panel-bg: #0a0f0a;
–border: #1a2e1a;
–bezel: #1c1f1c;
}
html, body {
height: 100%;
background: #0e110e;
display: flex;
align-items: center;
justify-content: center;
font-family: ‘IBM Plex Mono’, monospace;
overflow: hidden;
}
body::before {
content: ”;
position: fixed; inset: 0;
background: repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0,0,0,0.07) 2px, rgba(0,0,0,0.07) 4px);
pointer-events: none; z-index: 9999;
}
body::after {
content: ”;
position: fixed; inset: 0;
background: radial-gradient(ellipse at center, transparent 55%, rgba(0,0,0,0.7) 100%);
pointer-events: none; z-index: 9998;
}
/* BEZEL */
.bezel {
background: linear-gradient(145deg, #252825, #161916, #1e221e);
border-radius: 10px;
padding: 22px 18px 18px;
box-shadow:
0 0 0 2px #2e322e,
0 0 0 4px #111,
0 25px 80px rgba(0,0,0,0.9),
inset 0 1px 0 rgba(255,255,255,0.05);
width: 560px;
position: relative;
}
.bezel-label {
position: absolute;
top: 7px; left: 50%; transform: translateX(-50%);
font-family: ‘Orbitron’, monospace;
font-size: 8px; font-weight: 700;
letter-spacing: 6px; color: #2e342e;
white-space: nowrap;
}
/* SCREEN */
.screen-surround {
background: #070c07;
border-radius: 5px; padding: 3px;
box-shadow: inset 0 0 24px rgba(0,0,0,0.9), 0 0 20px rgba(0,255,65,0.04);
margin-bottom: 14px;
}
.screen {
background: var(–crt-bg);
border-radius: 3px;
padding: 13px 15px 10px;
position: relative; overflow: hidden;
min-height: 148px;
}
.screen::before {
content: ”;
position: absolute; inset: 0;
background: radial-gradient(ellipse at 50% 0%, rgba(0,255,65,0.07) 0%, transparent 70%);
pointer-events: none;
}
.screen-header {
display: flex; justify-content: space-between; align-items: center;
margin-bottom: 9px; padding-bottom: 7px;
border-bottom: 1px solid #0d1e0d;
}
.screen-id {
font-family: ‘VT323’, monospace; font-size: 14px;
color: var(–crt-dim); letter-spacing: 3px;
}
.screen-status { display: flex; gap: 10px; }
.st {
font-size: 9px; letter-spacing: 1px;
color: var(–crt-dark);
}
.st.on { color: var(–crt-dim); }
.st.amb { color: var(–amber-dim); }
.mode-row { display: flex; gap: 5px; margin-bottom: 8px; }
.mode-pill {
font-family: ‘VT323’, monospace; font-size: 13px;
padding: 1px 9px;
border: 1px solid var(–crt-dark); color: var(–crt-dark);
background: none; cursor: pointer; letter-spacing: 1px;
transition: all 0.1s;
}
.mode-pill:hover { color: var(–crt-dim); border-color: var(–crt-dim); }
.mode-pill.active {
border-color: var(–crt-green); color: var(–crt-green);
text-shadow: 0 0 8px var(–crt-green);
background: rgba(0,255,65,0.05);
}
.expr-line {
font-family: ‘VT323’, monospace; font-size: 16px;
color: var(–crt-dim); text-align: right;
min-height: 20px; letter-spacing: 1px;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.result-line {
font-family: ‘VT323’, monospace; font-size: 54px;
color: var(–crt-green); text-align: right; line-height: 1;
letter-spacing: 3px;
text-shadow: 0 0 10px rgba(0,255,65,0.8), 0 0 30px rgba(0,255,65,0.25);
transition: color 0.1s; word-break: break-all;
min-height: 58px; display: flex; align-items: center; justify-content: flex-end;
}
.result-line.error { color: var(–red); font-size: 22px; text-shadow: 0 0 10px rgba(255,58,58,0.5); }
.cursor-block {
display: inline-block; width: 3px; height: 40px;
background: var(–crt-green); margin-left: 3px; vertical-align: middle;
animation: blink 1s step-end infinite;
}
@keyframes blink { 0%,49%{opacity:1} 50%,100%{opacity:0} }
.mem-strip {
display: flex; gap: 14px; margin-top: 5px;
padding-top: 5px; border-top: 1px solid #0d1e0d;
}
.mem-lbl { font-size: 9px; letter-spacing: 1px; color: var(–crt-dark); }
.mem-lbl.lit { color: var(–amber); text-shadow: 0 0 6px var(–amber); }
/* BUTTON GRID */
.btn-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 3px;
}
.key { background: none; border: none; cursor: pointer; padding: 0; }
.key-face {
background: linear-gradient(155deg, #1e231e, #131713, #181c18);
border: 1px solid #262e26;
border-bottom: 3px solid #0c110c;
border-radius: 3px;
padding: 9px 4px 7px;
width: 100%; transition: all 0.06s;
box-shadow: 0 2px 0 #080b08;
}
.key:active .key-face {
transform: translateY(2px);
border-bottom-width: 1px; box-shadow: none;
}
.key:hover .key-face { filter: brightness(1.18); }
.key-top {
font-family: ‘VT323’, monospace; font-size: 9px;
color: var(–crt-dark); letter-spacing: 1px;
display: block; text-align: center; line-height: 1; margin-bottom: 2px;
}
.key-main {
font-family: ‘Orbitron’, monospace; font-size: 10px; font-weight: 600;
display: block; text-align: center; line-height: 1.2;
}
.key.num .key-main { color: #bccbbc; }
.key.op .key-main { color: var(–amber); }
.key.op .key-face { border-color: #2e2400; }
.key.fn .key-main { color: var(–blue); font-size: 9px; letter-spacing: 0.3px; }
.key.fn .key-face { border-color: #00253a; }
.key.eq .key-face { background: linear-gradient(155deg,#003a10,#002a0b,#003010); border-color: var(–crt-green); border-bottom-color: #001a06; }
.key.eq .key-main { color: var(–crt-green); font-size: 18px; text-shadow: 0 0 8px var(–crt-green); }
.key.clr .key-main { color: var(–red); }
.key.clr .key-face { border-color: #3a0000; }
.key.mem .key-main { color: var(–amber); font-size: 9px; }
.key.mem .key-face { background: linear-gradient(155deg,#1a1500,#110f00,#161200); }
.key.span2 { grid-column: span 2; }
/* CONVERTER */
.converter-panel { display: none; }
.converter-panel.active { display: block; }
.cat-strip { display: flex; flex-wrap: wrap; gap: 2px; margin-bottom: 9px; }
.cat-key {
font-family: ‘VT323’, monospace; font-size: 13px;
padding: 2px 10px;
background: #0c100c; border: 1px solid #1a251a;
color: #2a3e2a; cursor: pointer; letter-spacing: 1px; transition: all 0.1s;
}
.cat-key:hover { color: var(–crt-dim); }
.cat-key.active { border-color: var(–amber); color: var(–amber); background: #1a1200; }
.conv-fields {
display: grid;
grid-template-columns: 1fr 26px 1fr;
gap: 5px; align-items: end;
margin-bottom: 6px;
}
.conv-grp { display: flex; flex-direction: column; gap: 3px; }
.conv-lbl { font-family: ‘VT323’, monospace; font-size: 12px; color: var(–crt-dim); letter-spacing: 2px; }
.conv-sel, .conv-inp {
background: var(–crt-bg); border: 1px solid var(–crt-dark);
color: var(–crt-green); font-family: ‘VT323’, monospace; font-size: 18px;
padding: 6px 7px; outline: none; width: 100%;
}
.conv-sel:focus, .conv-inp:focus { border-color: var(–crt-green); }
.conv-sel option { background: #020c03; color: var(–crt-green); }
.conv-arrow-mid { font-family: ‘VT323’, monospace; font-size: 22px; color: var(–crt-dim); text-align: center; padding-bottom: 5px; }
/* FORMULAS */
.formulas-panel { display: none; max-height: 315px; overflow-y: auto; }
.formulas-panel.active { display: block; }
.formulas-panel::-webkit-scrollbar { width: 3px; }
.formulas-panel::-webkit-scrollbar-track { background: #0c100c; }
.formulas-panel::-webkit-scrollbar-thumb { background: var(–crt-dark); }
.fcard {
border: 1px solid #1a251a; margin-bottom: 4px;
cursor: pointer; background: #080c08; transition: border-color 0.15s;
}
.fcard:hover { border-color: var(–crt-dim); }
.fcard.open { border-color: var(–crt-green); }
.fcard-head {
display: flex; justify-content: space-between; align-items: baseline;
padding: 7px 10px;
}
.fcard-title { font-family: ‘Orbitron’, monospace; font-size: 8px; font-weight: 700; color: #7aaa7a; letter-spacing: 1px; text-transform: uppercase; }
.fcard-eq { font-family: ‘VT323’, monospace; font-size: 15px; color: var(–amber); letter-spacing: 1px; }
.fcard-cat { font-family: ‘VT323’, monospace; font-size: 11px; color: var(–blue); letter-spacing: 1px; }
.fcard-body { display: none; padding: 0 10px 10px; display: none; grid-template-columns: 1fr 1fr; gap: 5px; }
.fcard.open .fcard-body { display: grid; }
.finp-grp { display: flex; flex-direction: column; gap: 3px; }
.finp-lbl { font-family: ‘VT323’, monospace; font-size: 11px; color: var(–crt-dim); letter-spacing: 1px; }
.finp {
background: var(–crt-bg); border: 1px solid var(–crt-dark);
color: var(–crt-green); font-family: ‘VT323’, monospace; font-size: 15px;
padding: 4px 7px; outline: none; width: 100%;
}
.finp:focus { border-color: var(–crt-green); }
.fcard-go {
grid-column: span 2; padding: 6px;
background: #001a07; border: 1px solid var(–crt-green); color: var(–crt-green);
font-family: ‘Orbitron’, monospace; font-size: 8px; font-weight: 700;
letter-spacing: 3px; cursor: pointer; transition: all 0.1s;
}
.fcard-go:hover { background: #002e0e; }
.fcard-ans {
grid-column: span 2;
font-family: ‘VT323’, monospace; font-size: 18px; color: var(–amber);
background: #1a1200; border: 1px solid #3a2a00;
padding: 6px 8px; display: none; letter-spacing: 1px;
}
.fcard.has-ans .fcard-ans { display: block; }
/* FOOTER */
.footer {
display: flex; justify-content: space-between; align-items: center;
margin-top: 11px; padding-top: 8px;
border-top: 1px solid #1a221a;
}
.footer-info { font-family: ‘VT323’, monospace; font-size: 13px; color: #2a3e2a; letter-spacing: 2px; }
.angle-toggle { display: flex; gap: 2px; }
.ang-btn {
font-family: ‘VT323’, monospace; font-size: 13px; padding: 2px 10px;
background: #0c100c; border: 1px solid #1a251a; color: #2a3e2a;
cursor: pointer; letter-spacing: 1px; transition: all 0.1s;
}
.ang-btn.active { border-color: var(–crt-green); color: var(–crt-green); }
@keyframes flash { 0%{opacity:1}50%{opacity:0.5}100%{opacity:1} }
.flash { animation: flash 0.15s; }
</style>
</head>
<body>
<div class=”bezel”>
<div class=”bezel-label”>ENG CALC PRO MK-IV</div>
<!– Screen –>
<div class=”screen-surround”>
<div class=”screen”>
<div class=”screen-header”>
<span class=”screen-id”>ENGCALC::4.1</span>
<div class=”screen-status”>
<span class=”st on” id=”angleStatus”>DEG</span>
<span class=”st on”>FLOAT</span>
<span class=”st on” id=”memStatus”>MEM:0</span>
</div>
</div>
<div class=”mode-row”>
<button class=”mode-pill active” onclick=”switchTab(‘calc’)”>CALC</button>
<button class=”mode-pill” onclick=”switchTab(‘units’)”>UNITS</button>
<button class=”mode-pill” onclick=”switchTab(‘formulas’)”>FORMULAS</button>
</div>
<div class=”expr-line” id=”exprLine”> </div>
<div class=”result-line” id=”resultLine”>0<span class=”cursor-block”></span></div>
<div class=”mem-strip”>
<span class=”mem-lbl” id=”memInd”>MEM </span>
<span class=”mem-lbl” id=”ansInd”>ANS </span>
</div>
</div>
</div>
<!– CALCULATOR PANEL –>
<div id=”panel-calc”>
<div class=”btn-grid”>
<button class=”key mem” onclick=”ms()”><div class=”key-face”><span class=”key-top”>MEM</span><span class=”key-main”>MS</span></div></button>
<button class=”key mem” onclick=”mr()”><div class=”key-face”><span class=”key-top”>RCL</span><span class=”key-main”>MR</span></div></button>
<button class=”key mem” onclick=”mc()”><div class=”key-face”><span class=”key-top”>CLR</span><span class=”key-main”>MC</span></div></button>
<button class=”key mem” onclick=”mplus()”><div class=”key-face”><span class=”key-top”>ADD</span><span class=”key-main”>M+</span></div></button>
<button class=”key mem” onclick=”mminus()”><div class=”key-face”><span class=”key-top”>SUB</span><span class=”key-main”>M</span></div></button>
<button class=”key fn” onclick=”ins(‘sin(‘)”><div class=”key-face”><span class=”key-top”>TRIG</span><span class=”key-main”>SIN</span></div></button>
<button class=”key fn” onclick=”ins(‘cos(‘)”><div class=”key-face”><span class=”key-top”>TRIG</span><span class=”key-main”>COS</span></div></button>
<button class=”key fn” onclick=”ins(‘tan(‘)”><div class=”key-face”><span class=”key-top”>TRIG</span><span class=”key-main”>TAN</span></div></button>
<button class=”key fn” onclick=”ins(‘log(‘)”><div class=”key-face”><span class=”key-top”>BASE10</span><span class=”key-main”>LOG</span></div></button>
<button class=”key fn” onclick=”ins(‘ln(‘)”><div class=”key-face”><span class=”key-top”>NAT</span><span class=”key-main”>LN</span></div></button>
<button class=”key fn” onclick=”ins(‘(‘)”><div class=”key-face”><span class=”key-top”>ROOT</span><span class=”key-main”>x</span></div></button>
<button class=”key fn” onclick=”ins(‘^2’)”><div class=”key-face”><span class=”key-top”>SQ</span><span class=”key-main”>x</span></div></button>
<button class=”key fn” onclick=”ins(‘^’)”><div class=”key-face”><span class=”key-top”>PWR</span><span class=”key-main”>x</span></div></button>
<button class=”key fn” onclick=”ins(‘abs(‘)”><div class=”key-face”><span class=”key-top”>ABS</span><span class=”key-main”>|x|</span></div></button>
<button class=”key fn” onclick=”ins(”)”><div class=”key-face”><span class=”key-top”>CONST</span><span class=”key-main”></span></div></button>
<button class=”key clr” onclick=”clearAll()”><div class=”key-face”><span class=”key-top”>RESET</span><span class=”key-main”>AC</span></div></button>
<button class=”key clr” onclick=”ce()”><div class=”key-face”><span class=”key-top”>ENTRY</span><span class=”key-main”>CE</span></div></button>
<button class=”key fn” onclick=”bksp()”><div class=”key-face”><span class=”key-top”>DEL</span><span class=”key-main”></span></div></button>
<button class=”key fn” onclick=”ins(‘%’)”><div class=”key-face”><span class=”key-top”>MOD</span><span class=”key-main”>%</span></div></button>
<button class=”key op” onclick=”ins(‘/’)”><div class=”key-face”><span class=”key-top”>DIV</span><span class=”key-main”></span></div></button>
<button class=”key num” onclick=”ins(‘7’)”><div class=”key-face”><span class=”key-top”> </span><span class=”key-main”>7</span></div></button>
<button class=”key num” onclick=”ins(‘8’)”><div class=”key-face”><span class=”key-top”> </span><span class=”key-main”>8</span></div></button>
<button class=”key num” onclick=”ins(‘9’)”><div class=”key-face”><span class=”key-top”> </span><span class=”key-main”>9</span></div></button>
<button class=”key fn” onclick=”ins(‘e’)”><div class=”key-face”><span class=”key-top”>EULER</span><span class=”key-main”>e</span></div></button>
<button class=”key op” onclick=”ins(‘*’)”><div class=”key-face”><span class=”key-top”>MUL</span><span class=”key-main”></span></div></button>
<button class=”key num” onclick=”ins(‘4’)”><div class=”key-face”><span class=”key-top”> </span><span class=”key-main”>4</span></div></button>
<button class=”key num” onclick=”ins(‘5’)”><div class=”key-face”><span class=”key-top”> </span><span class=”key-main”>5</span></div></button>
<button class=”key num” onclick=”ins(‘6’)”><div class=”key-face”><span class=”key-top”> </span><span class=”key-main”>6</span></div></button>
<button class=”key fn” onclick=”ins(‘(‘)”><div class=”key-face”><span class=”key-top”>OPEN</span><span class=”key-main”>(</span></div></button>
<button class=”key op” onclick=”ins(‘-‘)”><div class=”key-face”><span class=”key-top”>SUB</span><span class=”key-main”></span></div></button>
<button class=”key num” onclick=”ins(‘1’)”><div class=”key-face”><span class=”key-top”> </span><span class=”key-main”>1</span></div></button>
<button class=”key num” onclick=”ins(‘2’)”><div class=”key-face”><span class=”key-top”> </span><span class=”key-main”>2</span></div></button>
<button class=”key num” onclick=”ins(‘3’)”><div class=”key-face”><span class=”key-top”> </span><span class=”key-main”>3</span></div></button>
<button class=”key fn” onclick=”ins(‘)’)”><div class=”key-face”><span class=”key-top”>CLOSE</span><span class=”key-main”>)</span></div></button>
<button class=”key op” onclick=”ins(‘+’)”><div class=”key-face”><span class=”key-top”>ADD</span><span class=”key-main”>+</span></div></button>
<button class=”key num span2″ onclick=”ins(‘0’)”><div class=”key-face” style=”text-align:left;padding-left:16px”><span class=”key-top”> </span><span class=”key-main”>0</span></div></button>
<button class=”key num” onclick=”ins(‘.’)”><div class=”key-face”><span class=”key-top”>DEC</span><span class=”key-main”>.</span></div></button>
<button class=”key fn” onclick=”ins(‘E’)”><div class=”key-face”><span class=”key-top”>SCI</span><span class=”key-main”>EXP</span></div></button>
<button class=”key eq” onclick=”calculate()”><div class=”key-face”><span class=”key-top”>EXEC</span><span class=”key-main”>=</span></div></button>
</div>
</div>
<!– UNIT CONVERTER –>
<div id=”panel-units” class=”converter-panel”>
<div class=”cat-strip” id=”catStrip”></div>
<div class=”conv-fields”>
<div class=”conv-grp”>
<span class=”conv-lbl”>FROM</span>
<select class=”conv-sel” id=”fromUnit” onchange=”doConvert()”></select>
<input class=”conv-inp” type=”number” id=”fromVal” value=”1″ oninput=”doConvert()”>
</div>
<div class=”conv-arrow-mid”></div>
<div class=”conv-grp”>
<span class=”conv-lbl”>TO</span>
<select class=”conv-sel” id=”toUnit” onchange=”doConvert()”></select>
<input class=”conv-inp” type=”text” id=”toVal” readonly>
</div>
</div>
</div>
<!– FORMULAS –>
<div id=”panel-formulas” class=”formulas-panel”></div>
<!– Footer –>
<div class=”footer”>
<span class=”footer-info” id=”statusBar”>READY </span>
<div class=”angle-toggle”>
<button class=”ang-btn active” id=”degBtn” onclick=”setAngle(‘deg’)”>DEG</button>
<button class=”ang-btn” id=”radBtn” onclick=”setAngle(‘rad’)”>RAD</button>
</div>
</div>
</div>
<script>
// STATE
let expr = ”, mem = 0, lastAns = null, angleMode = ‘deg’, hasResult = false;
// DISPLAY
function render() {
document.getElementById(‘memInd’).className = ‘mem-lbl’ + (mem!==0?’ lit’:”);
document.getElementById(‘memInd’).textContent = mem!==0?`MEM ${fmt(mem)}`:’MEM ‘;
document.getElementById(‘ansInd’).textContent = lastAns!==null?`ANS ${fmt(lastAns)}`:’ANS ‘;
document.getElementById(‘memStatus’).textContent = `MEM:${mem!==0?String(fmt(mem)).slice(0,8):’0′}`;
}
function showResult(val, isErr) {
const el = document.getElementById(‘resultLine’);
el.className = ‘result-line’ + (isErr?’ error’:”);
el.innerHTML = val + ‘<span class=”cursor-block”></span>’;
}
function fmt(n) {
if (!isFinite(n)) return ‘OVERFLOW’;
if (Math.abs(n)>=1e13||(Math.abs(n)<1e-7&&n!==0)) return n.toExponential(6).toUpperCase();
return parseFloat(n.toPrecision(10)).toString();
}
// INPUT
function ins(t) {
if (hasResult && /^[0-9e.]$/.test(t)) expr = ”;
hasResult = false;
expr += t;
showResult(expr.slice(-26)||’0′);
render();
}
function clearAll() { expr=”; hasResult=false; showResult(‘0’); render(); setStatus(‘CLEARED’); }
function ce() { expr=expr.slice(0,-1); showResult(expr||’0′); render(); }
function bksp() { ce(); }
// CALCULATE
function calculate() {
if (!expr.trim()) return;
try {
let e = expr;
e = e.replace(//g,’Math.PI’);
e = e.replace(/beb/g,’Math.E’);
if (angleMode===’deg’) {
e = e.replace(/sin(/g,’Math.sin(Math.PI/180*’);
e = e.replace(/cos(/g,’Math.cos(Math.PI/180*’);
e = e.replace(/tan(/g,’Math.tan(Math.PI/180*’);
} else {
e = e.replace(/sin(/g,’Math.sin(‘);
e = e.replace(/cos(/g,’Math.cos(‘);
e = e.replace(/tan(/g,’Math.tan(‘);
}
e = e.replace(/ln(/g,’Math.log(‘);
e = e.replace(/log(/g,’Math.log10(‘);
e = e.replace(/(/g,’Math.sqrt(‘);
e = e.replace(/abs(/g,’Math.abs(‘);
e = e.replace(/^/g,’**’);
e = e.replace(/(d+(?:.d+)?)E(-?d+)/g,(_,a,b)=>`(${a}*1e${b})`);
e = e.replace(/(d+(?:.d+)?)%/g,(_,n)=>`(${n}/100)`);
const r = Function(‘”use strict”;return(‘+e+’)’)();
if (!isFinite(r)) throw 0;
document.getElementById(‘exprLine’).textContent = expr + ‘ =’;
const f = fmt(r);
showResult(f);
lastAns = r; hasResult = true; expr = f;
render();
setStatus(‘OK ‘+new Date().toLocaleTimeString());
document.getElementById(‘resultLine’).classList.add(‘flash’);
setTimeout(()=>document.getElementById(‘resultLine’).classList.remove(‘flash’),180);
} catch(err) {
showResult(‘SYNTAX ERR’,true);
setStatus(‘ERR CHECK INPUT’);
hasResult = false;
}
}
document.addEventListener(‘keydown’, ev => {
const tag = document.activeElement.tagName;
if (tag===’INPUT’||tag===’SELECT’) return;
if (/^[0-9]$/.test(ev.key)) ins(ev.key);
else if (‘+-*/’.includes(ev.key)) ins(ev.key);
else if (ev.key===’.’) ins(‘.’);
else if (ev.key===’Enter’||ev.key===’=’) calculate();
else if (ev.key===’Backspace’) bksp();
else if (ev.key===’Escape’) clearAll();
else if (ev.key==='(‘) ins(‘(‘);
else if (ev.key===’)’) ins(‘)’);
else if (ev.key===’^’) ins(‘^’);
});
// MEMORY
function ms() { if(lastAns!==null){mem=lastAns;render();} }
function mr() { if(mem!==0) ins(String(mem)); }
function mc() { mem=0; render(); }
function mplus() { if(lastAns!==null){mem+=lastAns;render();} }
function mminus() { if(lastAns!==null){mem-=lastAns;render();} }
// ANGLE
function setAngle(m) {
angleMode = m;
document.getElementById(‘degBtn’).className=’ang-btn’+(m===’deg’?’ active’:”);
document.getElementById(‘radBtn’).className=’ang-btn’+(m===’rad’?’ active’:”);
document.getElementById(‘angleStatus’).textContent = m.toUpperCase();
}
function setStatus(msg) { document.getElementById(‘statusBar’).textContent = msg+’ ‘; }
// TABS
function switchTab(name) {
[‘calc’,’units’,’formulas’].forEach((n,i)=>{
document.querySelectorAll(‘.mode-pill’)[i].classList.toggle(‘active’,n===name);
});
document.getElementById(‘panel-calc’).style.display = name===’calc’?”:’none’;
const up = document.getElementById(‘panel-units’);
up.style.display = name===’units’?’block’:’none’;
up.className = name===’units’?’converter-panel active’:’converter-panel’;
const fp = document.getElementById(‘panel-formulas’);
fp.style.display = name===’formulas’?’block’:’none’;
fp.className = name===’formulas’?’formulas-panel active’:’formulas-panel’;
}
// UNIT CONVERTER
const UNITS = {
length: {label:’LENGTH’, u:[‘meter’,’kilometer’,’centimeter’,’millimeter’,’mile’,’yard’,’foot’,’inch’,’nautical mi’],b:[1,1000,.01,.001,1609.344,.9144,.3048,.0254,1852]},
mass: {label:’MASS’, u:[‘kilogram’,’gram’,’milligram’,’tonne’,’pound’,’ounce’],b:[1,.001,1e-6,1000,.453592,.0283495]},
temp: {label:’TEMP’, u:[‘Celsius’,’Fahrenheit’,’Kelvin’],b:null},
area: {label:’AREA’, u:[‘m’,’km’,’cm’,’hectare’,’acre’,’ft’],b:[1,1e6,1e-4,1e4,4046.86,.092903]},
pressure: {label:’PRESSURE’, u:[‘pascal’,’kPa’,’MPa’,’bar’,’psi’,’atm’],b:[1,1000,1e6,1e5,6894.76,101325]},
energy: {label:’ENERGY’, u:[‘joule’,’kJ’,’MJ’,’calorie’,’kcal’,’kWh’,’BTU’],b:[1,1000,1e6,4.184,4184,3.6e6,1055.06]},
power: {label:’POWER’, u:[‘watt’,’kilowatt’,’megawatt’,’horsepower’],b:[1,1000,1e6,745.7]},
speed: {label:’SPEED’, u:[‘m/s’,’km/h’,’mph’,’knot’,’ft/s’],b:[1,.277778,.44704,.514444,.3048]},
};
let curCat = ‘length’;
function buildCatStrip() {
document.getElementById(‘catStrip’).innerHTML = Object.keys(UNITS).map(k=>
`<button class=”cat-key${k===curCat?’ active’:”}” onclick=”setCat(‘${k}’)”>${UNITS[k].label}</button>`
).join(”);
}
function setCat(cat) { curCat=cat; buildCatStrip(); fillUnits(); doConvert(); }
function fillUnits() {
const u = UNITS[curCat].u;
const html = u.map((n,i)=>`<option value=”${i}”>${n}</option>`).join(”);
document.getElementById(‘fromUnit’).innerHTML = html;
document.getElementById(‘toUnit’).innerHTML = html;
document.getElementById(‘toUnit’).value = 1;
}
function doConvert() {
const val = parseFloat(document.getElementById(‘fromVal’).value);
if (isNaN(val)) { document.getElementById(‘toVal’).value=”; return; }
const fi = +document.getElementById(‘fromUnit’).value;
const ti = +document.getElementById(‘toUnit’).value;
const cat = UNITS[curCat];
let r;
if (curCat===’temp’) {
let c = fi===0?val:fi===1?(val-32)*5/9:val-273.15;
r = ti===0?c:ti===1?c*9/5+32:c+273.15;
} else {
r = val*cat.b[fi]/cat.b[ti];
}
document.getElementById(‘toVal’).value = parseFloat(r.toPrecision(8));
}
buildCatStrip(); fillUnits();
// FORMULAS
const FORMULAS = [
{name:”Ohm’s Law”,cat:”ELEC”,eq:”V = I R”,
f:[{id:’I’,l:’Current I (A)’},{id:’R’,l:’Resistance R ()’}],
fn:v=>`V = ${fmt(v.I*v.R)} V`},
{name:”Electric Power”,cat:”ELEC”,eq:”P = V I”,
f:[{id:’V’,l:’Voltage V (V)’},{id:’I’,l:’Current I (A)’}],
fn:v=>`P = ${fmt(v.V*v.I)} W`},
{name:”Capacitor Energy”,cat:”ELEC”,eq:”E = CV”,
f:[{id:’C’,l:’Capacitance C (F)’},{id:’V’,l:’Voltage V (V)’}],
fn:v=>`E = ${fmt(.5*v.C*v.V**2)} J`},
{name:”Kinetic Energy”,cat:”MECH”,eq:”KE = mv”,
f:[{id:’m’,l:’Mass m (kg)’},{id:’v’,l:’Velocity v (m/s)’}],
fn:v=>`KE = ${fmt(.5*v.m*v.v**2)} J`},
{name:”Gravitational PE”,cat:”MECH”,eq:”PE = mgh”,
f:[{id:’m’,l:’Mass m (kg)’},{id:’g’,l:’g (m/s)’},{id:’h’,l:’Height h (m)’}],
fn:v=>`PE = ${fmt(v.m*v.g*v.h)} J`},
{name:”Newton 2nd Law”,cat:”MECH”,eq:”F = ma”,
f:[{id:’m’,l:’Mass m (kg)’},{id:’a’,l:’Accel a (m/s)’}],
fn:v=>`F = ${fmt(v.m*v.a)} N`},
{name:”Torque”,cat:”MECH”,eq:” = F r”,
f:[{id:’F’,l:’Force F (N)’},{id:’r’,l:’Radius r (m)’}],
fn:v=>` = ${fmt(v.F*v.r)} Nm`},
{name:”Pressure”,cat:”FLUID”,eq:”P = F / A”,
f:[{id:’F’,l:’Force F (N)’},{id:’A’,l:’Area A (m)’}],
fn:v=>`P = ${fmt(v.F/v.A)} Pa`},
{name:”Reynolds Number”,cat:”FLUID”,eq:”Re = vL/”,
f:[{id:’rho’,l:’Density (kg/m)’},{id:’v’,l:’Velocity v’},{id:’L’,l:’Length L (m)’},{id:’mu’,l:’Viscosity (Pas)’}],
fn:v=>`Re = ${fmt(v.rho*v.v*v.L/v.mu)}`},
{name:”Stress”,cat:”STRUCT”,eq:” = F / A”,
f:[{id:’F’,l:’Force F (N)’},{id:’A’,l:’Area A (m)’}],
fn:v=>` = ${fmt(v.F/v.A)} Pa`},
{name:”Young’s Modulus”,cat:”STRUCT”,eq:”E = /”,
f:[{id:’sigma’,l:’Stress (Pa)’},{id:’eps’,l:’Strain ‘}],
fn:v=>`E = ${fmt(v.sigma/v.eps)} Pa`},
{name:”Ideal Gas Law”,cat:”THERMO”,eq:”PV = nRT”,
f:[{id:’n’,l:’Moles n’},{id:’T’,l:’Temp T (K)’},{id:’V’,l:’Volume V (m)’}],
fn:v=>`P = ${fmt(v.n*8.314*v.T/v.V)} Pa`},
{name:”Heat Transfer”,cat:”THERMO”,eq:”Q = mcT”,
f:[{id:’m’,l:’Mass m (kg)’},{id:’c’,l:’Sp. heat (J/kgK)’},{id:’dT’,l:’T (K)’}],
fn:v=>`Q = ${fmt(v.m*v.c*v.dT)} J`},
{name:”Decibels”,cat:”SIGNAL”,eq:”dB = 20log(V/V)”,
f:[{id:’V’,l:’Signal V’},{id:’V0′,l:’Reference V’}],
fn:v=>`${fmt(20*Math.log10(v.V/v.V0))} dB`},
];
function buildFormulas() {
document.getElementById(‘panel-formulas’).innerHTML = FORMULAS.map((f,i)=>`
<div class=”fcard” id=”fc${i}” onclick=”toggleF(${i})”>
<div class=”fcard-head”>
<span class=”fcard-title”>${f.name}</span>
<span class=”fcard-eq”>${f.eq}</span>
<span class=”fcard-cat”>${f.cat}</span>
</div>
<div class=”fcard-body” id=”fb${i}”>
${f.f.map(fi=>`
<div class=”finp-grp”>
<span class=”finp-lbl”>${fi.l}</span>
<input class=”finp” type=”number” id=”fi${i}_${fi.id}” onclick=”event.stopPropagation()” oninput=”calcF(${i})”>
</div>`).join(”)}
<button class=”fcard-go” onclick=”event.stopPropagation();calcF(${i})”>CALCULATE</button>
<div class=”fcard-ans” id=”fa${i}”></div>
</div>
</div>`).join(”);
}
function toggleF(i) { document.getElementById(‘fc’+i).classList.toggle(‘open’); }
function calcF(i) {
const f = FORMULAS[i]; const vals = {}; let ok = true;
f.f.forEach(fi=>{ const v=parseFloat(document.getElementById(`fi${i}_${fi.id}`).value); if(isNaN(v)){ok=false;}else vals[fi.id]=v; });
if (!ok) return;
try {
document.getElementById(‘fa’+i).textContent = ‘ ‘+f.fn(vals);
document.getElementById(‘fc’+i).classList.add(‘has-ans’);
} catch(e) {
document.getElementById(‘fa’+i).textContent = ‘ERROR’;
document.getElementById(‘fc’+i).classList.add(‘has-ans’);
}
}
buildFormulas();
render();
</script>
</body>
</html>
The post An engineering calculator first appeared on Best Assignment Doers.
The post An engineering calculator appeared first on Best Assignment Doers.