refactor: mejorar la estructura y funcionalidad del gráfico final, optimizando la carga de datos y la visualización
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import { useMemo } from 'react';
|
||||
import { CHART_COLORS } from '../../../config';
|
||||
|
||||
const interpolateY = (x, nodes) => {
|
||||
if (!nodes || nodes.length === 0) return null;
|
||||
const EPSILON = 1e-5;
|
||||
const MICRO_STEP = 0.0001;
|
||||
const firstX = nodes[0][0];
|
||||
const lastX = nodes[nodes.length - 1][0];
|
||||
|
||||
if (x < firstX - MICRO_STEP - EPSILON) return null;
|
||||
if (x > lastX + MICRO_STEP + EPSILON) return null;
|
||||
if (x < firstX - EPSILON) return 0;
|
||||
if (x > lastX + EPSILON) return 0;
|
||||
|
||||
for (let i = nodes.length - 1; i >= 0; i--) {
|
||||
if (Math.abs(nodes[i][0] - x) < EPSILON) return nodes[i][1];
|
||||
}
|
||||
|
||||
for (let i = 0; i < nodes.length - 1; i++) {
|
||||
const x1 = nodes[i][0];
|
||||
const x2 = nodes[i + 1][0];
|
||||
if (Math.abs(x2 - x1) < EPSILON) continue;
|
||||
if (x >= x1 && x <= x2) {
|
||||
const y1 = nodes[i][1];
|
||||
const y2 = nodes[i + 1][1];
|
||||
return y1 + ((x - x1) * (y2 - y1)) / (x2 - x1);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const useGraphData = (data) => {
|
||||
const sortedResults = useMemo(() => {
|
||||
const rawItems = data?.levels || data?.results || [];
|
||||
const processed = rawItems.map((item, index) => {
|
||||
const isType2 = !!item.lower && !!item.upper;
|
||||
const color = CHART_COLORS[index % CHART_COLORS.length] || '#333';
|
||||
let termName = item.term || (item.lower && item.lower.term) || `Termino ${index}`;
|
||||
|
||||
if (isType2) {
|
||||
const lowerNodes = [...(item.lower.left_nodes || []), ...(item.lower.right_nodes || [])].map(n => [Number(n[0]), Number(n[1])]).sort((a,b)=>a[0]-b[0]);
|
||||
const upperNodes = [...(item.upper.left_nodes || []), ...(item.upper.right_nodes || [])].map(n => [Number(n[0]), Number(n[1])]).sort((a,b)=>a[0]-b[0]);
|
||||
const coreVal = Array.isArray(item.lower.core) ? Number(item.lower.core[0]) : 0;
|
||||
return { ...item, term: termName, isType2, lowerNodes, upperNodes, color, coreVal };
|
||||
} else {
|
||||
const nodes = [...(item.left_nodes || []), ...(item.right_nodes || [])].map(n => [Number(n[0]), Number(n[1])]).sort((a,b)=>a[0]-b[0]);
|
||||
const coreVal = Array.isArray(item.core) ? Number(item.core[0]) : 0;
|
||||
return { ...item, term: termName, isType2, nodes, color, coreVal };
|
||||
}
|
||||
});
|
||||
return processed.sort((a, b) => a.coreVal - b.coreVal);
|
||||
}, [data]);
|
||||
|
||||
const denseData = useMemo(() => {
|
||||
const xSet = new Set();
|
||||
const steps = 1000;
|
||||
for (let i = 0; i <= steps; i++) xSet.add(Number((i / steps).toFixed(4)));
|
||||
|
||||
sortedResults.forEach(item => {
|
||||
const addNodes = (nodes) => nodes.forEach(n => {
|
||||
const x = n[0];
|
||||
xSet.add(Number((x - 0.0001).toFixed(4)));
|
||||
xSet.add(Number(x.toFixed(4)));
|
||||
xSet.add(Number((x + 0.0001).toFixed(4)));
|
||||
});
|
||||
item.isType2 ? (addNodes(item.lowerNodes), addNodes(item.upperNodes)) : addNodes(item.nodes);
|
||||
});
|
||||
|
||||
const xValues = Array.from(xSet).sort((a, b) => a - b);
|
||||
return xValues.map(x => {
|
||||
const point = { x };
|
||||
sortedResults.forEach(item => {
|
||||
if (item.isType2) {
|
||||
const lowerRaw = interpolateY(x, item.lowerNodes);
|
||||
const upperRaw = interpolateY(x, item.upperNodes);
|
||||
point[`${item.term}_lower`] = lowerRaw;
|
||||
point[`${item.term}_upper`] = upperRaw;
|
||||
point[`${item.term}_range`] = (lowerRaw === null && upperRaw === null) ? null : [lowerRaw ?? 0, upperRaw ?? 0];
|
||||
} else {
|
||||
point[item.term] = interpolateY(x, item.nodes);
|
||||
}
|
||||
});
|
||||
return point;
|
||||
});
|
||||
}, [sortedResults]);
|
||||
|
||||
return { sortedResults, denseData };
|
||||
};
|
||||
Reference in New Issue
Block a user