diff --git a/frontend/src/components/editor/Step2FuzzyModeling.jsx b/frontend/src/components/editor/Step2FuzzyModeling.jsx index 34ba6f8..dcc3d18 100644 --- a/frontend/src/components/editor/Step2FuzzyModeling.jsx +++ b/frontend/src/components/editor/Step2FuzzyModeling.jsx @@ -11,7 +11,8 @@ export default function Step2FuzzyModeling({ handleFinalSubmit, onBack, subscales, - onOpenSubscale + onOpenSubscale, + submitError }) { const scaleKeys = Object.keys(baseScale); @@ -51,6 +52,20 @@ export default function Step2FuzzyModeling({ colors={CHART_COLORS} /> + {submitError && ( +
+
+ ⚠️ +
+

Error de validación al generar la gráfica

+
+ {submitError} +
+
+
+
+ )} + { +const Step3FinalGraph = ({ data, criterionName }) => { const sortedResults = useMemo(() => { - if (!data || !data.results) return []; + const rawItems = data?.levels || data?.results || []; - const withPermanentColors = data.results.map((item, index) => ({ - ...item, - color: CHART_COLORS[index % CHART_COLORS.length] - })); + const processed = rawItems.map((item, index) => { + const isType2 = !!item.lower && !!item.upper; + const color = CHART_COLORS[index % CHART_COLORS.length] || '#333'; - return withPermanentColors.sort((a, b) => { - const coreA = Array.isArray(a.core) ? Number(a.core[0]) : 0; - const coreB = Array.isArray(b.core) ? Number(b.core[0]) : 0; - return coreA - coreB; + let lineData = []; + let coreVal = 0; + let termName = item.term || (item.lower && item.lower.term) || `Termino ${index}`; + + if (isType2) { + const lowerNodes = [...(item.lower.left_nodes || []), ...(item.lower.right_nodes || [])]; + const upperNodes = [...(item.upper.left_nodes || []), ...(item.upper.right_nodes || [])]; + + lineData = lowerNodes.map((lNode, i) => { + const uNode = upperNodes[i]; + const lowerY = Number(lNode[1]); + const upperY = Number(uNode ? uNode[1] : lNode[1]); + return { x: Number(lNode[0]), lowerY, upperY, range: [lowerY, upperY] }; + }); + coreVal = Array.isArray(item.lower.core) ? Number(item.lower.core[0]) : 0; + } else { + const nodes = [...(item.left_nodes || []), ...(item.right_nodes || [])]; + lineData = nodes.map(node => ({ x: Number(node[0]), y: Number(node[1]) })); + coreVal = Array.isArray(item.core) ? Number(item.core[0]) : 0; + } + + return { ...item, term: termName, isType2, lineData, color, coreVal }; }); + + return processed.sort((a, b) => a.coreVal - b.coreVal); }, [data]); - if (!data || !data.results) { + if (!data || (!data.levels && !data.results)) { return

Cargando gráfico final...

; } return (
-

Espectro Difuso Final

+ + {/* Título */} +

+ {criterionName ? `Criterio: ${criterionName}` : 'Espectro Difuso Final'} +

{/* Gráfica */}
- + - + [Number(value).toFixed(3), name]} + formatter={(value, name) => Array.isArray(value) ? [`[${Number(value[0]).toFixed(3)}, ${Number(value[1]).toFixed(3)}]`, name] : [Number(value).toFixed(3), name]} labelFormatter={(label) => `X: ${Number(label).toFixed(3)}`} contentStyle={{ borderRadius: '12px', border: 'none', boxShadow: '0 10px 15px -3px rgb(0 0 0 / 0.1)' }} /> {sortedResults.map((item) => { - const lineData = [...(item.left_nodes || []), ...(item.right_nodes || [])].map(node => ({ - x: Number(node[0]), - y: Number(node[1]) - })); - - return ( - - ); + if (item.isType2) { + return ( + + + + + + ); + } else { + return ; + } })} - +
@@ -80,22 +86,11 @@ const Step3FinalGraph = ({ data }) => {
{sortedResults.map((item) => (
- - - - - {item.term} - + + {item.term}
))}
-
); }; diff --git a/frontend/src/components/membershipFunction/Controls.jsx b/frontend/src/components/membershipFunction/Controls.jsx index f879c4a..565cc84 100644 --- a/frontend/src/components/membershipFunction/Controls.jsx +++ b/frontend/src/components/membershipFunction/Controls.jsx @@ -22,7 +22,6 @@ export default function Controls({
- {/* Lado izquierdo (Pendiente ascendente) */}
- {/* Botón subescala izquierda */}
- {/* Lado derecho (Pendiente descendente) */}
-
- - updateCurrentMf('coreEnd', e.target.value)} className="w-full cursor-pointer h-1.5" style={{ accentColor: selectedColor }} /> -
updateCurrentMf('supportEnd', e.target.value)} className="w-full cursor-pointer h-1.5" style={{ accentColor: selectedColor, opacity: 0.7 }} />
+
+ + updateCurrentMf('coreEnd', e.target.value)} className="w-full cursor-pointer h-1.5" style={{ accentColor: selectedColor }} /> +
- {/* Botón subescala derecha */}