diff --git a/frontend/biochem.html b/frontend/biochem.html index a6dec9b..eb94541 100644 --- a/frontend/biochem.html +++ b/frontend/biochem.html @@ -1925,21 +1925,53 @@ function renderBalanceChallenge(data) { wrap.style.display = ''; const reactants = data.reactants || []; const products = data.products || []; - const count = reactants.length + products.length; + wrap._reactants = reactants; + wrap._products = products; let html = '
'; reactants.forEach((f,i) => { if (i > 0) html += '+'; - html += ``; + html += ``; html += `${escHtml(f)}`; }); html += ''; products.forEach((f,i) => { if (i > 0) html += '+'; - html += ``; + html += ``; html += `${escHtml(f)}`; }); html += '
'; + // живая поэлементная проверка сохранения атомов + html += '
'; wrap.innerHTML = html; + updateBalanceFeedback(); +} + +// Живой счётчик атомов слева/справа по каждому элементу (через BIO.parseFormula) +function updateBalanceFeedback() { + const wrap = document.getElementById('bp-chal-balance'); + const fb = document.getElementById('bal-feedback'); + if (!wrap || !fb || !window.BIO) return; + const reactants = wrap._reactants || [], products = wrap._products || []; + const coefs = Array.from(wrap.querySelectorAll('.bal-coef')).map(i => parseInt(i.value) || 0); + const sideCounts = (formulas, offset) => { + const tot = {}; + formulas.forEach((f, i) => { + const k = coefs[offset + i] || 0; + const c = BIO.parseFormula(f); + for (const el in c) tot[el] = (tot[el] || 0) + c[el] * k; + }); + return tot; + }; + const L = sideCounts(reactants, 0); + const R = sideCounts(products, reactants.length); + const els = [...new Set([...Object.keys(L), ...Object.keys(R)])].sort(); + let allOk = els.length > 0; + fb.innerHTML = els.map(el => { + const l = L[el] || 0, r = R[el] || 0, ok = l === r; + if (!ok) allOk = false; + const col = ok ? '#4ade80' : '#f87171'; + return `${el}: ${l}=${r} ${ok ? '✓' : '✗'}`; + }).join('') + (allOk ? 'сбалансировано' : ''); } // Keyboard shortcuts