Untitled

 avatar
unknown
plain_text
3 months ago
36 kB
7
Indexable
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Lab Tools Unified</title>

<style>
/* THEME VARIABLES */
:root {
    --bg: #f2f2f7;
    --text: #3a3a3c; 
    --box-bg: #ffffff;
    --input-bg: #e5e5ea;
    --inner-bg: #d1d1d6;
    --label-color: #8e8e93;
    --secondary-text: #3a3a3c;
    --sun-color: #000;
    --log-border: #e5e5ea; 
    --font-main: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
    --fail-red: #ff3b30; 
    --pass-green: #34c759; 
    --title-color: #000; 
    --log-text-color: #8e8e93;
}

body.dark-mode {
    --bg: #000;
    --text: #fff;
    --box-bg: #333;
    --input-bg: #222;
    --inner-bg: #111;
    --label-color: #777;
    --secondary-text: #ccc;
    --sun-color: #FFD700;
    --log-border: #333; 
    --title-color: #fff;
    --log-text-color: #fff;
}

/* LIVE WALLPAPER CANVAS */
#starCanvas {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: -1; 
    display: none; 
    background: #000;
}

body.dark-mode #starCanvas {
    display: block;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

body {
    margin: 0; background: var(--bg); color: var(--text); font-family: var(--font-main);
    display: flex; flex-direction: column; align-items: center; min-height: 100vh;
    transition: background 0.3s ease, color 0.3s ease; position: relative;
}

#themeToggle {
    position: absolute; top: 25px; right: 25px; font-size: 1.5rem;
    color: var(--sun-color); cursor: pointer; z-index: 1000; user-select: none; line-height: 1;
}

.screen { display: none; width: 100%; flex-direction: column; align-items: center; padding: 0 16px 120px; }
.screen.active { display: flex; }

h1 { font-size: 1.8rem; display: flex; align-items: center; gap: 10px; color: var(--title-color); }
#screenHome h1 { margin: 40px 0 12px; }
#screenTDS h1, #screenTSS h1, #screenTol h1, #screenDup h1, #screenWC h1 { margin: 17px 0 12px; }
#screenWQ h1 { margin: 17px 0 30px; }

.home-icon { font-size: 2.35rem; color: var(--text); cursor: pointer; user-select: none; display: inline-block; line-height: 1; }

/* MAIN PAGE TOOL BOXES - Updated to 20% transparency (0.8 opacity) in Dark Mode */
.tool-box {
    width: 100%; max-width: 360px; 
    background: rgba(51, 51, 51, 0.8); /* 20% Transparency for a more solid look while stars show */
    color: #fff; padding: 16px;
    margin-top: 16px; border-radius: 14px; text-align: center; font-size: 1.3rem; 
    cursor: pointer; user-select: none;
    border: 1px solid rgba(255, 255, 255, 0.05);
}
body.light-mode .tool-box { 
    background: var(--box-bg); 
    color: var(--text); 
    box-shadow: 0 2px 8px rgba(0,0,0,0.1); 
    border: none;
}

/* SUB-PAGE ELEMENTS - Kept as Solid per Instructions */
.input-group, .locked-merged-box { width: 100%; max-width: 360px; margin-bottom: 12px; position: relative; background: var(--input-bg); border-radius: 12px; }
.locked-merged-box { display: none; background: var(--inner-bg); border: 1px solid var(--input-bg); padding: 8px 12px; }

.input-group label {
    position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
    font-size: 1.15rem; color: var(--label-color); pointer-events: none; transition: all 0.2s ease;
}

.result-label { font-size: 0.75rem; color: var(--secondary-text); display: block; margin-bottom: 0px; }
.display-val-large { font-size: 1.15rem; color: var(--text); margin-bottom: 2px; }
.display-val-small { font-size: 0.85rem; color: var(--text); }

.input-group input:focus + label, .input-group input:not(:placeholder-shown) + label {
    top: 8px; font-size: 0.75rem; color: var(--secondary-text); transform: translateY(0);
}

input { width: 100%; font-size: 1.15rem; padding: 22px 12px 6px 12px; border-radius: 12px; border: none; outline: none; background: transparent; color: var(--text); }

#screenWQ .input-group { height: 38px; display: flex; align-items: center; }
#screenWQ .input-group input { padding: 0 12px; height: 100%; }
#screenWQ .input-group input:focus + label, #screenWQ .input-group input:not(:placeholder-shown) + label { opacity: 0; visibility: hidden; }

.print-text { display: none; text-align: center; width: 100%; }

.status-icon { 
    width: 26px; height: 26px; border-radius: 50%; display: flex; align-items: center; 
    justify-content: center; font-weight: 900; color: #ffffff; flex-shrink: 0; visibility: hidden; 
}
.status-icon.pass { background-color: var(--pass-green); visibility: visible; font-size: 14px; }
.status-icon.fail { background-color: var(--fail-red); visibility: visible; font-size: 18px; }

.row { display: flex; gap: 10px; align-items: center; width: 100%; max-width: 360px; }
.btn, .save-btn, .back-btn { padding: 10px 14px; background: #333; color: #fff; border-radius: 10px; font-size: 1rem; text-align: center; cursor: pointer; user-select: none; }
body.light-mode .btn, body.light-mode .save-btn, body.light-mode .back-btn { background: var(--box-bg); color: var(--text); box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
.btn { flex: 1; }
.save-btn { flex: 0 0 auto; display: flex; align-items: center; justify-content: center; align-self: stretch; }
.back-btn { width: 100%; max-width: 360px; margin-top: 20px; display: flex; align-items: center; justify-content: center; gap: 8px; }

.flash { animation: flashAnim 600ms cubic-bezier(0.22, 1, 0.36, 1); }
@keyframes flashAnim { 0% { background-color: #888; color: #000; } 100% { background-color: inherit; color: inherit; } }
.flash-icon { animation: flashIconAnim 600ms cubic-bezier(0.22, 1, 0.36, 1); }
@keyframes flashIconAnim { 0% { color: #000; background-color: #888; border-radius: 8px; } 100% { color: inherit; background-color: transparent; } }

.log-list { display: none; margin-top: 16px; width: 100%; max-width: 360px; background: var(--inner-bg); padding: 8px; border-radius: 12px; }
table { width: 100%; border-collapse: collapse; font-size: 0.85rem; font-weight: bold; }
th { text-align: left; color: var(--log-text-color); border-bottom: 1.5px solid var(--log-border); padding: 6px; }
td { padding: 6px; color: var(--log-text-color); }
.box-separator { border-top: 1px solid var(--log-border); margin: 4px 0; }
.log-pass { color: var(--pass-green); font-weight: bold; }
.log-fail { color: var(--fail-red); font-weight: bold; }

.wq-table { width: 100%; max-width: 360px; border-collapse: collapse; margin-top: 10px; }
.wq-table td { padding: 8px 4px; border-bottom: 1px solid var(--log-border); }
.wq-header-cell { font-size: 0.9rem; font-weight: bold; color: var(--label-color); padding-bottom: 12px !important; }
.wq-spec { font-size: 0.75rem; color: var(--label-color); white-space: nowrap; }
.wq-name { font-weight: 500; font-size: 0.85rem; padding-right: 5px; }

@media print {
    @page { size: A4 portrait; margin: 20mm; }
    body, html { background: #fff !important; color: #000 !important; }
    #starCanvas { display: none !important; }
    #screenWQ.active { display: flex !important; transform: none !important; padding: 0 !important; width: 100% !important; }
    .wq-table { width: 100% !important; max-width: none !important; }
    .input-group { display: none !important; }
    h1, td, .wq-name, .wq-spec, .wq-header-cell, .print-text { color: #000 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    .print-text { display: block !important; font-weight: 500 !important; font-size: 0.85rem !important; }
    .home-icon, .back-btn, .row, #themeToggle, .screen:not(.active) { display: none !important; }
    .status-icon { visibility: visible !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    .status-icon.pass { background-color: #34c759 !important; color: #fff !important; }
    .status-icon.fail { background-color: #ff3b30 !important; color: #fff !important; }
    h1 { justify-content: center !important; margin-bottom: 40px !important; }
}
</style>
</head>
<body class="light-mode">

<canvas id="starCanvas"></canvas>
<div id="themeToggle">🌙</div>

<div id="screenHome" class="screen active">
    <h1>Lab Tools</h1>
    <div class="tool-box" onclick="goTo('screenTDS', this)">TDS</div>
    <div class="tool-box" onclick="goTo('screenTSS', this)">TSS</div>
    <div class="tool-box" onclick="goTo('screenTol', this)">Tolerance</div>
    <div class="tool-box" onclick="goTo('screenDup', this)">Duplicate Check</div>
    <div class="tool-box" onclick="goTo('screenWC', this)">Water Cut</div>
    <div class="tool-box" onclick="goTo('screenWQ', this)">Drinking Water Quality</div>
</div>

<div id="screenTDS" class="screen">
    <h1><span class="home-icon" onclick="goHome(this)">⌂</span> TDS Calculator</h1>
    <div class="input-group"><input id="condInput" type="text" inputmode="decimal" placeholder=" " /><label>Conductivity (µS/cm)</label></div>
    <div class="locked-merged-box" id="tdsFullResBox">
        <span class="result-label">TDS (ppm)</span><div class="display-val-large" id="tdsValDisp">—</div>
        <div class="box-separator" id="tdsSep"></div>
        <span class="result-label" id="tdsMetaLabel">Details</span>
        <div id="tdsMetaDisp" class="display-val-small">—</div>
    </div>
    <div class="row"><div class="btn" id="saveTDS">Save</div><div class="btn" id="clearTDS">Clear All</div></div>
    <div id="tdsLog" class="log-list"><table><thead><tr><th>S/N</th><th>Cond</th><th>TDS</th><th>Time</th></tr></thead><tbody id="tdsBody"></tbody></table></div>
    <div class="back-btn" onclick="goHome(this)">← Back to Menu</div>
</div>

<div id="screenTSS" class="screen">
    <h1><span class="home-icon" onclick="goHome(this)">⌂</span> TSS Calculator</h1>
    <div class="row" style="margin-bottom:12px;"><div class="input-group" style="margin:0;"><input id="tssW1" type="text" inputmode="decimal" placeholder=" "><label>Initial Weight (g)</label></div><div class="save-btn" id="btnSaveW1">Save</div></div>
    <div class="row" style="margin-bottom:12px;"><div class="input-group" style="margin:0;"><input id="tssVol" type="text" inputmode="decimal" placeholder=" "><label>Sample Volume (mL)</label></div><div class="save-btn" id="btnSaveVol">Save</div></div>
    <div class="input-group"><input id="tssW2" type="text" inputmode="decimal" placeholder=" "><label>Final Weight (g)</label></div>
    <div class="locked-merged-box" id="tssFullResBox"><span class="result-label">TSS (mg/L)</span><div class="display-val-large" id="tssValDisp">—</div></div>
    <div class="row"><div class="btn" id="saveAllTSS">Save Result</div><div class="btn" id="clearTSS">Clear All</div></div>
    <div id="tssLog" class="log-list"><table><thead><tr><th>S/N</th><th>Details</th><th>Value</th><th>Time</th></tr></thead><tbody id="tssBody"></tbody></table></div>
    <div class="back-btn" onclick="goHome(this)">← Back to Menu</div>
</div>

<div id="screenWC" class="screen">
    <h1><span class="home-icon" onclick="goHome(this)">⌂</span> Water Cut</h1>
    <div class="input-group"><input id="wcTotal" type="text" inputmode="decimal" placeholder=" " /><label>Total Volume</label></div>
    <div class="input-group"><input id="wcWater" type="text" inputmode="decimal" placeholder=" " /><label>Water Volume</label></div>
    <div class="locked-merged-box" id="wcFullResBox"><span class="result-label">Water Cut (%)</span><div class="display-val-large" id="wcValDisp">—</div></div>
    <div class="row"><div class="btn" id="saveWC">Save Result</div><div class="btn" id="clearWC">Clear All</div></div>
    <div id="wcLog" class="log-list"><table><thead><tr><th>S/N</th><th>Result</th><th>Total Vol</th><th>Water Vol</th></tr></thead><tbody id="wcBody"></tbody></table></div>
    <div class="back-btn" onclick="goHome(this)">← Back to Menu</div>
</div>

<div id="screenTol" class="screen">
    <h1><span class="home-icon" onclick="goHome(this)">⌂</span> Tolerance</h1>
    <div class="input-group"><input id="tolMean" type="text" inputmode="decimal" placeholder=" " /><label>Mean Value</label></div>
    <div class="input-group"><input id="tolErr" type="text" inputmode="decimal" placeholder=" " /><label>Error Percentage (%)</label></div>
    <div class="locked-merged-box" id="tolFullResBox"><span class="result-label" id="tolLabel">Tolerance Range (±)</span><div class="display-val-large" id="tolValDisp">—</div></div>
    <div class="row"><div class="btn" id="saveTol">Save</div><div class="btn" id="clearTol">Clear All</div></div>
    <div id="tolLog" class="log-list"><table><thead><tr><th>S/N</th><th>Tolerance</th><th>Acceptable Range</th></tr></thead><tbody id="tolBody"></tbody></table></div>
    <div class="back-btn" onclick="goHome(this)">← Back to Menu</div>
</div>

<div id="screenDup" class="screen">
    <h1><span class="home-icon" onclick="goHome(this)">⌂</span> Duplicate Check</h1>
    <div class="row" style="margin-bottom:12px;"><div class="input-group" style="margin:0;"><input id="dupR1" type="text" inputmode="decimal" placeholder=" "><label>Result 1</label></div><div class="save-btn" id="btnSaveR1">Save</div></div>
    <div class="row" style="margin-bottom:12px;"><div class="input-group" style="margin:0;"><input id="dupR2" type="text" inputmode="decimal" placeholder=" "><label>Result 2</label></div><div class="save-btn" id="btnSaveR2">Save</div></div>
    <div class="locked-merged-box" id="dupFullResBox">
        <span class="result-label">Difference (%)</span><div class="display-val-large" id="dupDiffDisp" style="text-align: left;">—</div>
        <div class="box-separator"></div><span class="result-label">Status</span><div style="display:flex; align-items:center; justify-content:flex-start; margin-top:5px;"><div class="status-icon" id="dupStatusIcon"></div></div>
        <div id="dupSuggestContainer" style="display:none;"><div class="box-separator"></div><span class="result-label">Suggested Value</span><div class="display-val-large" id="dupSuggestDisp" style="text-align: left;">—</div></div>
    </div>
    <div class="row"><div class="btn" id="saveDup">Save Result</div><div class="btn" id="clearDup">Clear All</div></div>
    <div id="dupLog" class="log-list"><table><thead><tr><th>S/N</th><th>R1</th><th>R2</th><th>Diff</th><th>Stats</th></tr></thead><tbody id="dupBody"></tbody></table></div>
    <div class="back-btn" onclick="goHome(this)">← Back to Menu</div>
</div>

<div id="screenWQ" class="screen">
    <h1><span class="home-icon" onclick="goHome(this)">⌂</span> Drinking Water Quality</h1>
    <table class="wq-table">
        <thead>
            <tr><td class="wq-header-cell" style="text-align:left;">Test</td><td class="wq-header-cell" style="text-align:center;">Result</td><td class="wq-header-cell"></td><td class="wq-header-cell" style="padding-left:20px;">Spec</td></tr>
        </thead>
<tbody id="wqTableBody">
<tr><td class="wq-name">pH</td><td><div class="input-group"><input type="text" inputmode="decimal" placeholder=" " oninput="valWQ(this,7.0,8.0)"><label>Result</label></div><div class="print-text">—</div></td><td><div class="status-icon"></div></td><td class="wq-spec" style="padding-left:20px;">7.0 – 8.0</td></tr>
<tr><td class="wq-name">Conductivity (µS/cm)</td><td><div class="input-group"><input id="wqCond" type="text" inputmode="decimal" placeholder=" " oninput="handleWQTDS(this)"><label>Result</label></div><div class="print-text">—</div></td><td><div class="status-icon"></div></td><td class="wq-spec" style="padding-left:20px;">0 – 1500</td></tr>
<tr><td class="wq-name">TDS (mg/L)</td><td><div class="input-group"><input id="wqTDS" type="text" placeholder=" " readonly><label>Auto</label></div><div class="print-text">—</div></td><td><div class="status-icon"></div></td><td class="wq-spec" style="padding-left:20px;">100 – 200</td></tr>
<tr><td colspan="4" style="font-weight:bold;padding-top:15px;">Anions −</td></tr>
<tr><td class="wq-name">Bicarbonate (HCO₃⁻)</td><td><div class="input-group"><input type="text" inputmode="decimal" placeholder=" " oninput="valWQ(this,5,50)"><label>Result</label></div><div class="print-text">—</div></td><td><div class="status-icon"></div></td><td class="wq-spec" style="padding-left:20px;">5 – 50 mg/L</td></tr>
<tr><td class="wq-name">Chloride (Cl⁻)</td><td><div class="input-group"><input type="text" inputmode="decimal" placeholder=" " oninput="valWQ(this,15,40)"><label>Result</label></div><div class="print-text">—</div></td><td><div class="status-icon"></div></td><td class="wq-spec" style="padding-left:20px;">15 – 40 mg/L</td></tr>
<tr><td class="wq-name">Sulfate (SO₄²⁻)</td><td><div class="input-group"><input type="text" inputmode="decimal" placeholder=" " oninput="valWQ(this,0,50)"><label>Result</label></div><div class="print-text">—</div></td><td><div class="status-icon"></div></td><td class="wq-spec" style="padding-left:20px;">0 – 50 mg/L</td></tr>
<tr><td class="wq-name">Fluoride (F⁻)</td><td><div class="input-group"><input type="text" inputmode="decimal" placeholder=" " oninput="valWQ(this,0.7,1.5)"><label>Result</label></div><div class="print-text">—</div></td><td><div class="status-icon"></div></td><td class="wq-spec" style="padding-left:20px;">0.7 – 1.5 mg/L</td></tr>
<tr><td colspan="4" style="font-weight:bold;padding-top:15px;">Cations +</td></tr>
<tr><td class="wq-name">Sodium (Na⁺)</td><td><div class="input-group"><input type="text" inputmode="decimal" placeholder=" " oninput="valWQ(this,1,20)"><label>Result</label></div><div class="print-text">—</div></td><td><div class="status-icon"></div></td><td class="wq-spec" style="padding-left:20px;">1 – 20 mg/L</td></tr>
<tr><td class="wq-name">Potassium (K⁺)</td><td><div class="input-group"><input type="text" inputmode="decimal" placeholder=" " oninput="valWQ(this,0,5)"><label>Result</label></div><div class="print-text">—</div></td><td><div class="status-icon"></div></td><td class="wq-spec" style="padding-left:20px;">0 – 5 mg/L</td></tr>
<tr><td class="wq-name">Calcium (Ca²⁺)</td><td><div class="input-group"><input id="wqCa" type="text" inputmode="decimal" placeholder=" " oninput="handleHardness(); valWQ(this,5,20)"><label>Result</label></div><div class="print-text">—</div></td><td><div class="status-icon"></div></td><td class="wq-spec" style="padding-left:20px;">5 – 20 mg/L</td></tr>
<tr><td class="wq-name">Magnesium (Mg²⁺)</td><td><div class="input-group"><input id="wqMg" type="text" inputmode="decimal" placeholder=" " oninput="handleHardness(); valWQ(this,1,10)"><label>Result</label></div><div class="print-text">—</div></td><td><div class="status-icon"></div></td><td class="wq-spec" style="padding-left:20px;">1 – 10 mg/L</td></tr>
<tr><td class="wq-name">Total Hardness</td><td><div class="input-group"><input id="wqHard" type="text" placeholder=" " readonly><label>Auto</label></div><div class="print-text">—</div><div id="waterType" style="font-size:13px;color:var(--secondary-text);"></div></td><td><div class="status-icon"></div></td><td class="wq-spec" style="padding-left:20px;">30 – 100 mg/L</td></tr>
<tr><td class="wq-name">Water Type</td><td><div class="input-group"><input id="wqTypeDesc" type="text" placeholder=" " readonly><label>Auto</label></div><div class="print-text">—</div></td><td><div class="status-icon" id="wqTypeIcon"></div></td><td class="wq-spec" style="padding-left:20px;">Classification<br>40-100 mg/L</td></tr>
</tbody>
    </table>
    <div class="row" style="margin-top:20px;"><div class="btn" onclick="window.print()">Generate PDF</div><div class="btn" onclick="clearWQ(this)">Clear All</div></div>
    <div class="back-btn" onclick="goHome(this)">← Back to Menu</div>
</div>

<script>
/* STAR WALLPAPER LOGIC */
const canvas = document.getElementById('starCanvas');
const ctx = canvas.getContext('2d');
let stars = [];
const starCount = 150;

function initStars() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    stars = [];
    for (let i = 0; i < starCount; i++) {
        stars.push({
            x: Math.random() * canvas.width,
            y: Math.random() * canvas.height,
            size: Math.random() * 1.5,
            opacity: Math.random(),
            speed: 0.005 + Math.random() * 0.015,
            direction: Math.random() > 0.5 ? 1 : -1
        });
    }
}

function animateStars() {
    if (!document.body.classList.contains('dark-mode')) {
        requestAnimationFrame(animateStars);
        return;
    }
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = "white";
    stars.forEach(s => {
        s.opacity += s.speed * s.direction;
        if (s.opacity <= 0 || s.opacity >= 1) s.direction *= -1;
        ctx.globalAlpha = Math.max(0, s.opacity);
        ctx.beginPath();
        ctx.arc(s.x, s.y, s.size, 0, Math.PI * 2);
        ctx.fill();
    });
    requestAnimationFrame(animateStars);
}

window.addEventListener('resize', initStars);
initStars();
animateStars();

/* CORE NAVIGATION & THEME */
const themeToggle = document.getElementById('themeToggle');
themeToggle.onclick = () => { 
    document.body.classList.toggle('dark-mode'); 
    document.body.classList.toggle('light-mode'); 
    themeToggle.textContent = document.body.classList.contains('dark-mode') ? '☀' : '🌙'; 
    flash(themeToggle, true); 
};
function flash(el, isIcon = false) { const cls = isIcon ? "flash-icon" : "flash"; el.classList.remove(cls); void el.offsetWidth; el.classList.add(cls); }
function showScreen(id) { document.querySelectorAll('.screen').forEach(s => s.classList.remove('active')); document.getElementById(id).classList.add('active'); themeToggle.style.display = (id === 'screenHome') ? "block" : "none"; }
function goTo(id, btn) { flash(btn); setTimeout(() => showScreen(id), 250); }
function goHome(btn) { flash(btn, true); setTimeout(() => showScreen('screenHome'), 250); }
function getTime() { return new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); }
function translateArabicChars(str) { const map = {'٠':'0','١':'1','٢':'2','٣':'3','٤':'4','٥':'5','٦':'6','٧':'7','٨':'8','٩':'9','٫':'.'}; return str.replace(/[٠-٩٫]/g, d => map[d]); }
function conditionalFormat(val) { const num = parseFloat(val.toString().replace(/,/g, "")); if (isNaN(num)) return val; if (num < 10000) return num.toString(); const parts = num.toString().split("."); parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); return parts.join("."); }
function cleanRoundedDecimal(num) { return Number(num.toFixed(2)); }

/* CALCULATORS - NO CHANGES */
const tdsRanges = [ {min:0, max:25, f:0.495}, {min:25.01, max:100, f:0.549}, {min:100.01, max:1000, f:0.604}, {min:1000.01, max:25000, f:0.638}, {min:25000.01, max:100000, f:0.744}, {min:100000.01, max:150000, f:0.813} ];
let tdsCount = 1;
document.getElementById('condInput').oninput = function() {
    let inputStr = translateArabicChars(this.value).replace(/,/g, ""); 
    let val = parseFloat(inputStr);
    if (!isNaN(val)) this.value = conditionalFormat(inputStr);
    const resBox = document.getElementById('tdsFullResBox'), sep = document.getElementById('tdsSep'), mLabel = document.getElementById('tdsMetaLabel'), mDisp = document.getElementById('tdsMetaDisp');
    if (isNaN(val)) { resBox.style.display="none"; return; }
    if (val > 150000) { document.getElementById('tdsValDisp').textContent = "OUT OF RANGE"; sep.style.display = "none"; mLabel.style.display = "none"; mDisp.style.display = "none"; resBox.style.display = "block"; return; }
    let match = tdsRanges.find(r => val >= r.min && val <= r.max);
    if (match) { document.getElementById('tdsValDisp').textContent = conditionalFormat(Math.round(val * match.f)); mDisp.textContent = `Range: ${match.min}-${match.max} | Factor: ${match.f}`; sep.style.display = "block"; mLabel.style.display = "block"; mDisp.style.display = "block"; resBox.style.display="block"; }
};
document.getElementById('saveTDS').onmousedown = function(e) { e.preventDefault(); flash(this); const inp = document.getElementById('condInput'); if(inp.value) { document.getElementById('tdsLog').style.display="block"; document.getElementById('tdsBody').innerHTML += `<tr><td>${tdsCount++}</td><td>${inp.value}</td><td>${document.getElementById('tdsValDisp').textContent}</td><td>${getTime()}</td></tr>`; inp.value=""; document.getElementById('tdsFullResBox').style.display="none"; inp.focus(); } };
document.getElementById('clearTDS').onclick = function() { flash(this); document.getElementById('condInput').value=""; document.getElementById('tdsFullResBox').style.display="none"; document.getElementById('tdsBody').innerHTML=""; document.getElementById('tdsLog').style.display="none"; tdsCount=1; };

let tssCount = 1;
const w1 = document.getElementById('tssW1'), w2 = document.getElementById('tssW2'), vol = document.getElementById('tssVol');
function updateTSS() { let a = parseFloat(translateArabicChars(w1.value)), b = parseFloat(translateArabicChars(w2.value)), v = parseFloat(translateArabicChars(vol.value)); if (!isNaN(a) && !isNaN(b) && !isNaN(v) && v !== 0) { document.getElementById('tssValDisp').textContent = (((b - a) * 1000000) / v).toFixed(2); document.getElementById('tssFullResBox').style.display = "block"; } else { document.getElementById('tssFullResBox').style.display = "none"; } }
[w1, w2, vol].forEach(el => el.oninput = updateTSS);
function addTSSLog(details, val) { document.getElementById('tssLog').style.display="block"; document.getElementById('tssBody').innerHTML += `<tr><td>${tssCount++}</td><td>${details}</td><td>${val}</td><td>${getTime()}</td></tr>`; }
document.getElementById('btnSaveW1').onmousedown = function(e) { e.preventDefault(); flash(this); if(w1.value) { addTSSLog(`Init Wt`, w1.value+"g"); vol.focus(); } };
document.getElementById('btnSaveVol').onmousedown = function(e) { e.preventDefault(); flash(this); if(vol.value) { addTSSLog(`Volume`, vol.value+"mL"); w2.focus(); } };
document.getElementById('saveAllTSS').onmousedown = function(e) { e.preventDefault(); flash(this); if(document.getElementById('tssFullResBox').style.display === "block") { addTSSLog(`TSS`, document.getElementById('tssValDisp').textContent + " mg/L"); [w1, w2, vol].forEach(i=>i.value=""); document.getElementById('tssFullResBox').style.display="none"; w1.focus(); } };
document.getElementById('clearTSS').onclick = function() { flash(this); [w1, w2, vol].forEach(i=>i.value=""); document.getElementById('tssFullResBox').style.display="none"; document.getElementById('tssBody').innerHTML=""; document.getElementById('tssLog').style.display="none"; tssCount=1; w1.focus(); };

let wcCount = 1;
const wcTotal = document.getElementById('wcTotal'), wcWater = document.getElementById('wcWater');
function updateWC() { let t = parseFloat(translateArabicChars(wcTotal.value)), w = parseFloat(translateArabicChars(wcWater.value)); if (!isNaN(t) && !isNaN(w) && t !== 0) { document.getElementById('wcValDisp').textContent = cleanRoundedDecimal((w/t)*100) + '%'; document.getElementById('wcFullResBox').style.display="block"; } else { document.getElementById('wcFullResBox').style.display="none"; } }
[wcTotal, wcWater].forEach(el => el.oninput = updateWC);
document.getElementById('saveWC').onmousedown = function(e) { e.preventDefault(); flash(this); if(document.getElementById('wcFullResBox').style.display === "block") { document.getElementById('wcLog').style.display="block"; document.getElementById('wcBody').innerHTML += `<tr><td>${wcCount++}</td><td>${document.getElementById('wcValDisp').textContent}</td><td>${wcTotal.value}</td><td>${wcWater.value}</td></tr>`; wcTotal.value=""; wcWater.value=""; document.getElementById('wcFullResBox').style.display="none"; wcTotal.focus(); } };
document.getElementById('clearWC').onclick = function() { flash(this); wcTotal.value=""; wcWater.value=""; document.getElementById('wcFullResBox').style.display="none"; document.getElementById('wcBody').innerHTML=""; document.getElementById('wcLog').style.display="none"; wcCount=1; wcTotal.focus(); };

let tolCount = 1;
const tMean = document.getElementById('tolMean'), tErr = document.getElementById('tolErr');
function updateTol() { let m = parseFloat(translateArabicChars(tMean.value)), e = parseFloat(translateArabicChars(tErr.value)); if (!isNaN(m) && !isNaN(e)) { let d = m * (e/100); let min = cleanRoundedDecimal(m-d), max = cleanRoundedDecimal(m+d); document.getElementById('tolLabel').textContent = `Range (${cleanRoundedDecimal(m)} ± ${cleanRoundedDecimal(d)})`; document.getElementById('tolValDisp').textContent = `${min} - ${max}`; document.getElementById('tolFullResBox').style.display="block"; } else { document.getElementById('tolFullResBox').style.display="none"; } }
[tMean, tErr].forEach(el => el.oninput = updateTol);
document.getElementById('saveTol').onmousedown = function(e) { e.preventDefault(); flash(this); if(tMean.value && tErr.value) { document.getElementById('tolLog').style.display="block"; document.getElementById('tolBody').innerHTML += `<tr><td>${tolCount++}</td><td>${document.getElementById('tolLabel').textContent}</td><td>${document.getElementById('tolValDisp').textContent}</td></tr>`; tMean.value=""; tErr.value=""; document.getElementById('tolFullResBox').style.display="none"; tMean.focus(); } };
document.getElementById('clearTol').onclick = function() { flash(this); tMean.value=""; tErr.value=""; document.getElementById('tolFullResBox').style.display="none"; document.getElementById('tolBody').innerHTML=""; document.getElementById('tolLog').style.display="none"; tolCount=1; tMean.focus(); };

let dupCount = 1;
const dr1 = document.getElementById('dupR1'), dr2 = document.getElementById('dupR2');
function updateDup() { let v1 = parseFloat(translateArabicChars(dr1.value)), v2 = parseFloat(translateArabicChars(dr2.value)); if (!isNaN(v1) && !isNaN(v2) && v1 !== 0) { let diff = ((v2-v1)/v1)*100; document.getElementById('dupDiffDisp').textContent = diff.toFixed(2) + '%'; const icon = document.getElementById('dupStatusIcon'); if (Math.abs(diff) > 10) { icon.innerHTML = "✖"; icon.className = "status-icon fail"; document.getElementById('dupSuggestDisp').textContent = (v1 * 1.05).toFixed(2); document.getElementById('dupSuggestContainer').style.display="block"; } else { icon.innerHTML = "✓"; icon.className = "status-icon pass"; document.getElementById('dupSuggestContainer').style.display="none"; } document.getElementById('dupFullResBox').style.display="block"; } else { document.getElementById('dupFullResBox').style.display="none"; } }
[dr1, dr2].forEach(el => el.oninput = updateDup);
document.getElementById('btnSaveR1').onmousedown = function(e) { e.preventDefault(); flash(this); if(dr1.value) { document.getElementById('dupLog').style.display="block"; document.getElementById('dupBody').innerHTML += `<tr><td>—</td><td>${dr1.value}</td><td>—</td><td>—</td><td>—</td></tr>`; dr2.focus(); } };
document.getElementById('btnSaveR2').onmousedown = function(e) { e.preventDefault(); flash(this); if(dr2.value) { document.getElementById('dupLog').style.display="block"; document.getElementById('dupBody').innerHTML += `<tr><td>—</td><td>—</td><td>${dr2.value}</td><td>—</td><td>—</td></tr>`; } };
document.getElementById('saveDup').onmousedown = function(e) { e.preventDefault(); flash(this); if(document.getElementById('dupFullResBox').style.display === "block") { document.getElementById('dupLog').style.display="block"; const icon = document.getElementById('dupStatusIcon').innerHTML; const cls = icon === "✓" ? "log-pass" : "log-fail"; document.getElementById('dupBody').innerHTML += `<tr><td>${dupCount++}</td><td>${dr1.value}</td><td>${dr2.value}</td><td>${document.getElementById('dupDiffDisp').textContent}</td><td><span class="${cls}">${icon}</span></td></tr>`; dr1.value=""; dr2.value=""; document.getElementById('dupFullResBox').style.display="none"; dr1.focus(); } };
document.getElementById('clearDup').onclick = function() { flash(this); dr1.value=""; dr2.value=""; document.getElementById('dupFullResBox').style.display="none"; document.getElementById('dupBody').innerHTML=""; document.getElementById('dupLog').style.display="none"; dupCount=1; dr1.focus(); };

function valWQ(input, min, max) { input.value = translateArabicChars(input.value); const val = parseFloat(input.value); const cell = input.closest('td'); const printText = cell.querySelector('.print-text'), icon = cell.nextElementSibling.querySelector('.status-icon'); if (input.value === "" || isNaN(val)) { icon.className = "status-icon"; icon.innerHTML = ""; printText.textContent = "—"; return; } const isPass = (val >= min && val <= max); icon.className = isPass ? "status-icon pass" : "status-icon fail"; icon.innerHTML = isPass ? "✓" : "✖"; printText.textContent = input.value; }
function handleWQTDS(condInput) { valWQ(condInput, 0, 1500); const tdsInput = document.getElementById('wqTDS'); const condVal = parseFloat(translateArabicChars(condInput.value).replace(/,/g, "")); if (isNaN(condVal)) { tdsInput.value = ""; valWQ(tdsInput, 100, 200); return; } if (condVal > 150000) { tdsInput.value = "Out of Range"; valWQ(tdsInput, 100, 200); return; } let match = tdsRanges.find(r => condVal >= r.min && condVal <= r.max); if (match) { tdsInput.value = Math.round(condVal * match.f); valWQ(tdsInput, 100, 200); } }
function handleHardness() { 
     const caVal = parseFloat(translateArabicChars(document.getElementById('wqCa').value)), mgVal = parseFloat(translateArabicChars(document.getElementById('wqMg').value)), hardInput = document.getElementById('wqHard'), typeInput = document.getElementById('wqTypeDesc'), typeIcon = document.getElementById('wqTypeIcon');
     if (!isNaN(caVal) && !isNaN(mgVal)) { 
         const totalHard = (caVal * 2.5) + (mgVal * 4.115); hardInput.value = totalHard.toFixed(1); valWQ(hardInput, 30, 100); 
         let type = (totalHard <= 17) ? "Soft" : (totalHard <= 60) ? "Slightly Hard" : (totalHard <= 120) ? "Moderately Hard" : (totalHard <= 180) ? "Hard" : "Very Hard";
         if (typeInput) { typeInput.value = type; const typeCell = typeInput.closest('td'); if (typeCell) { const typePrint = typeCell.querySelector('.print-text'); if (typePrint) typePrint.textContent = type; } }
         if (typeIcon) { if (type === "Slightly Hard" || type === "Moderately Hard") { typeIcon.className = "status-icon pass"; typeIcon.innerHTML = "✓"; } else { typeIcon.className = "status-icon fail"; typeIcon.innerHTML = "✖"; } }
     } else { 
         hardInput.value = ""; valWQ(hardInput, 30, 100); if (typeInput) { typeInput.value = ""; const typeCell = typeInput.closest('td'); if (typeCell) { const typePrint = typeCell.querySelector('.print-text'); if (typePrint) typePrint.textContent = "—"; } }
         if (typeIcon) { typeIcon.className = "status-icon"; typeIcon.innerHTML = ""; }
     } 
}
function clearWQ(btn) { flash(btn); document.querySelectorAll('#screenWQ input').forEach(i => i.value = ""); document.querySelectorAll('#screenWQ .print-text').forEach(p => p.textContent = "—"); document.querySelectorAll('#screenWQ .status-icon').forEach(icon => { icon.className = "status-icon"; icon.innerHTML = ""; }); }
</script>
</body>
</html>
Editor is loading...
Leave a Comment