`;
renderGrid();
}
function renderGrid() {
const gridContainer = document.getElementById('matrixGridContainer');
if (!gridContainer) return;
let html = `
`;
for (let i = 0; i < currentSize; i++) {
for (let j = 0; j < currentSize; j++) {
html += ``;
}
}
html += '
';
gridContainer.innerHTML = html;
}
function getMatrix() {
const M = [];
let hasEmpty = false;
for (let i = 0; i < currentSize; i++) {
const row = [];
for (let j = 0; j < currentSize; j++) {
const cell = document.getElementById(`cell-${i}-${j}`);
if (!cell) return null;
const val = cell.value.trim();
if (val === '') {
cell.classList.add('matrix-grid__cell--error');
hasEmpty = true;
} else {
cell.classList.remove('matrix-grid__cell--error');
}
const num = parseFloat(val);
if (isNaN(num)) {
cell.classList.add('matrix-grid__cell--error');
hasEmpty = true;
}
row.push(num || 0);
}
M.push(row);
}
if (hasEmpty) {
showError('Completá todas las celdas con valores numéricos.');
return null;
}
hideError();
return M;
}
function showError(msg) {
const el = document.getElementById('matrixError');
if (el) {
el.textContent = msg;
el.classList.add('error-message--visible');
}
}
function hideError() {
const el = document.getElementById('matrixError');
if (el) el.classList.remove('error-message--visible');
}
function showResult(title, value, steps) {
const resultEl = document.getElementById('matrixResult');
const titleEl = document.getElementById('resultTitle');
const valueEl = document.getElementById('resultValue');
const stepsEl = document.getElementById('resultSteps');
titleEl.textContent = title;
resultEl.classList.add('matrix-result--visible');
// Render value
if (typeof value === 'number') {
if (typeof KatexRenderer !== 'undefined') {
KatexRenderer.renderDisplay(valueEl, `\\text{${title}} = ${MathEngine.fmtNum(value)}`);
} else {
valueEl.textContent = `${title} = ${value}`;
}
} else if (Array.isArray(value) && Array.isArray(value[0])) {
if (typeof KatexRenderer !== 'undefined') {
KatexRenderer.renderDisplay(valueEl, MathEngine.matToLatex(value));
} else {
valueEl.textContent = JSON.stringify(value);
}
} else if (Array.isArray(value)) {
if (typeof KatexRenderer !== 'undefined') {
KatexRenderer.renderDisplay(valueEl, MathEngine.vecToLatex(value));
} else {
valueEl.textContent = JSON.stringify(value);
}
} else if (typeof value === 'object' && value !== null) {
valueEl.textContent = JSON.stringify(value);
} else if (typeof KatexRenderer !== 'undefined') {
KatexRenderer.renderDisplay(valueEl, String(value));
} else {
valueEl.textContent = String(value);
}
// Render steps
stepsEl.innerHTML = '';
if (steps && steps.length > 0) {
const ol = document.createElement('ol');
ol.className = 'matrix-result__steps';
steps.forEach((step, idx) => {
const li = document.createElement('li');
li.className = 'matrix-result__step';
const descDiv = document.createElement('div');
descDiv.textContent = step.desc;
const exprDiv = document.createElement('div');
if (typeof KatexRenderer !== 'undefined') {
KatexRenderer.renderDisplay(exprDiv, step.latex || step.expression || '');
} else {
exprDiv.textContent = step.latex || step.expression || '';
}
li.appendChild(descDiv);
li.appendChild(exprDiv);
ol.appendChild(li);
});
stepsEl.appendChild(ol);
}
}
function executeOperation(op) {
const M = getMatrix();
if (!M) return;
let result;
try {
const ME = MathEngine;
switch (op) {
case 'determinant':
if (currentSize === 2) result = ME.determinant.det2x2(M);
else if (currentSize === 3) result = ME.determinant.det3x3Sarrus(M);
else result = ME.determinant.det(M);
break;
case 'det-sarrus':
if (currentSize !== 3) { showError('Sarrus solo aplica a matrices 3×3.'); return; }
result = ME.determinant.det3x3Sarrus(M);
break;
case 'det-triangular':
result = ME.determinant.detByTriangularization(M);
break;
case 'transpose':
result = ME.matrix.transpose(M);
break;
case 'trace':
result = ME.matrix.trace(M);
break;
case 'rank':
result = ME.system.rank(M);
break;
case 'inverse':
if (currentSize === 2) result = ME.inverse.inverse2x2(M);
else result = ME.inverse.inverse(M);
break;
default:
showError('Operación no reconocida.');
return;
}
if (result.error) {
showError(result.error);
return;
}
const titles = {
'determinant': 'Determinante',
'det-sarrus': 'Determinante (Sarrus)',
'det-triangular': 'Determinante (Triangularización)',
'transpose': 'Traspuesta',
'trace': 'Traza',
'rank': 'Rango',
'inverse': 'Inversa'
};
showResult(titles[op] || op, result.value, result.steps);
} catch (e) {
showError('Error: ' + e.message);
}
}
function clearGrid() {
for (let i = 0; i < currentSize; i++)
for (let j = 0; j < currentSize; j++) {
const cell = document.getElementById(`cell-${i}-${j}`);
if (cell) { cell.value = ''; cell.classList.remove('matrix-grid__cell--error'); }
}
const resultEl = document.getElementById('matrixResult');
if (resultEl) resultEl.classList.remove('matrix-result--visible');
hideError();
}
function fillExample() {
const examples = {
2: [[1, 2], [3, 4]],
3: [[1, 2, 3], [4, 5, 2], [6, 3, 1]],
4: [[1, 2, 0, 1], [3, 0, 1, 2], [1, 1, 2, 0], [2, 3, 1, 1]]
};
const ex = examples[currentSize];
for (let i = 0; i < currentSize; i++)
for (let j = 0; j < currentSize; j++) {
const cell = document.getElementById(`cell-${i}-${j}`);
if (cell) cell.value = ex[i][j];
}
}
function handleSizeChange(e) {
currentSize = parseInt(e.target.value);
renderGrid();
const resultEl = document.getElementById('matrixResult');
if (resultEl) resultEl.classList.remove('matrix-result--visible');
hideError();
}
function handleOpClick(e) {
const btn = e.target.closest('[data-op]');
if (!btn) return;
executeOperation(btn.dataset.op);
}
function handleActionClick(e) {
const btn = e.target.closest('[data-action]');
if (!btn) return;
const action = btn.dataset.action;
if (action === 'clear') clearGrid();
else if (action === 'example') fillExample();
}
function init(el) {
container = el;
render();
container.addEventListener('change', (e) => {
if (e.target.id === 'matrixSize') handleSizeChange(e);
});
container.addEventListener('click', handleOpClick);
container.addEventListener('click', handleActionClick);
}
function destroy() {
if (container) {
container.innerHTML = '';
}
container = null;
}
return { init, destroy, clearGrid, fillExample };
})();