ProyectoSammi/database.js
2026-08-19 17:28:16 -04:00

227 lines
6.9 KiB
JavaScript

const Database = require('better-sqlite3');
const path = require('path');
const { app } = require('electron');
const dbPath = path.join(app.getPath("documents"), "orden-merito.db");
let db;
function initializeDatabase() {
try {
db = new Database(dbPath);
db.pragma('journal_mode = WAL');
db.exec(`
CREATE TABLE IF NOT EXISTS profesionales (
id INTEGER PRIMARY KEY AUTOINCREMENT,
grado TEXT NOT NULL,
nombreApellido TEXT NOT NULL,
cedula TEXT NOT NULL UNIQUE,
condicion TEXT NOT NULL DEFAULT 'No posee novedades actualmente',
conducta INTEGER NOT NULL CHECK (conducta BETWEEN 0 AND 100),
companeros TEXT NOT NULL,
om_a TEXT NOT NULL,
niea REAL NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_condicion ON profesionales (condicion);
CREATE INDEX IF NOT EXISTS idx_niea ON profesionales (niea);
`);
} catch (err) {
console.error("Error inicializando base de datos:", err);
app.quit();
}
}
initializeDatabase();
function insertProfesionales(profesionales) {
const deleteStmt = db.prepare('DELETE FROM profesionales');
const insertStmt = db.prepare(`
INSERT INTO profesionales (
grado, nombreApellido, cedula, condicion,
conducta, companeros, om_a, niea
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`);
const transaction = db.transaction((profesionales) => {
deleteStmt.run();
for (const prof of profesionales) {
// Normalizar el campo companeros
let companeros = prof.companeros?.toString().trim() || '0';
if (companeros === '0' || companeros === '') {
companeros = '0/0'; // Convertir 0 o vacío a 0/0
} else if (!companeros.includes('/')) {
companeros = `${companeros}/90`; // Si solo tiene numerador, asumir denominador 90
}
// Normalizar el campo om_a de la misma manera
let om_a = prof.om_a?.toString().trim() || '0';
if (om_a === '0' || om_a === '') {
om_a = '0/0';
} else if (!om_a.includes('/')) {
om_a = `${om_a}/90`;
}
insertStmt.run(
prof.grado?.toString().trim() || '',
prof.nombreApellido?.toString().trim() || '',
prof.cedula?.toString().trim() || '',
String(prof.condicion || '').trim().toLowerCase() || 'No posee novedades actualmente',
parseFloat(prof.conducta) || 0,
companeros,
om_a,
parseFloat(prof.niea) || 0
);
}
});
try {
transaction(profesionales);
} catch (err) {
console.error("Error insertando profesionales:", err);
throw err;
}
}
function calcularResultado(prof) {
try {
const puntajeConducta = (parseFloat(prof.conducta) || 0) * 0.15;
// Manejo especial para campo "compañeros"
let puntajeCompaneros = 0;
if (prof.companeros && prof.companeros !== '0') {
if (prof.companeros.includes('/')) {
const [posCompaneros, totalCompaneros] = prof.companeros.split('/').map(Number);
puntajeCompaneros = totalCompaneros > 0 ? (1 - (posCompaneros / totalCompaneros)) * 5 : 0;
} else {
// Si no tiene formato de fracción, asumir que es el numerador con denominador 90
const posCompaneros = Number(prof.companeros);
puntajeCompaneros = (1 - (posCompaneros / 90)) * 5;
}
}
// Manejo similar para campo "om_a"
let puntajeOM = 0;
if (prof.om_a && prof.om_a !== '0') {
if (prof.om_a.includes('/')) {
const [posOM, totalOM] = prof.om_a.split('/').map(Number);
puntajeOM = totalOM > 0 ? (1 - (posOM / totalOM)) * 30 : 0;
} else {
const posOM = Number(prof.om_a);
puntajeOM = (1 - (posOM / 90)) * 30;
}
}
const puntajeNIEA = (parseFloat(prof.niea) || 0) * 0.5;
return puntajeConducta + puntajeCompaneros + puntajeOM + puntajeNIEA;
} catch (err) {
console.error("Error calculando resultado:", err);
return 0;
}
}
function getRanking() {
try {
const stmt = db.prepare(`
SELECT *,
CASE
WHEN LOWER(condicion) = 'no posee novedades actualmente' THEN 0
WHEN condicion LIKE '%sancion simple%grados anteriores%' THEN 1
WHEN condicion LIKE '%privado%libertad%' THEN 3
ELSE 2
END AS priority_level,
(CAST(conducta AS REAL) * 0.15 +
(
(1 - (
CAST(SUBSTR(companeros, 1, INSTR(companeros, '/') - 1) AS REAL) /
CAST(SUBSTR(companeros, INSTR(companeros, '/') + 1) AS INTEGER)
)) * 5
) +
(
(1 - (
CAST(SUBSTR(om_a, 1, INSTR(om_a, '/') - 1) AS REAL) /
CAST(SUBSTR(om_a, INSTR(om_a, '/') + 1) AS INTEGER)
)) * 30
) +
(niea * 0.5)
) AS resultado -- Paréntesis de cierre correcto
FROM profesionales
ORDER BY
priority_level ASC,
CASE WHEN condicion LIKE '%privado%libertad%' THEN 1 ELSE 0 END,
resultado DESC
`);
return stmt.all();
} catch (err) {
console.error("Error obteniendo ranking:", err);
return [];
}
}
function getNoRecomendados() {
try {
return getRanking().filter(p => {
const cond = p.condicion.toLowerCase();
// Lógica para sanciones simples (contar ocurrencias)
const sancionesSimples = (cond.match(/(\d+)\s*d[ií]as de sanci[oó]n simple/g) || []).length;
// Lógica mejorada para sanciones severas (sumar días)
const sancionesSeverasMatches = cond.match(/(\d+)\s*d[ií]as de sanci[oó]n severa/g) || [];
let totalDiasSeveros = 0;
for (const match of sancionesSeverasMatches) {
const diasMatch = match.match(/\d+/);
if (diasMatch) totalDiasSeveros += parseInt(diasMatch[0], 10);
}
const investigacionAbierta = /(investigaci[oó]n|juicio).*(abiert|pendiente|vigente)/.test(cond);
const privadoLibertad = /privado de libertad/i.test(cond);
return sancionesSimples >= 15 ||
totalDiasSeveros >= 8 || // Ahora verifica días totales
investigacionAbierta ||
privadoLibertad;
});
} catch (err) {
console.error("Error obteniendo no recomendados:", err);
return [];
}
}
function getTop10() {
try {
const ranking = getRanking()
.filter(p => p.condicion.toLowerCase() === 'no posee novedades actualmente')
.slice(0, 10);
return ranking;
} catch (err) {
console.error("Error obteniendo top 10:", err);
return [];
}
}
app.on("window-all-closed", () => {
if (db) db.close();
});
module.exports = {
insertProfesionales,
getRanking,
getNoRecomendados,
getTop10,
calcularResultado
};