Implementación de un contexto limpio por evaluación, garantizando que cada modificación reevalúe todo desde cero. Se eliminan opciones de menú obsoletas relacionadas con la limpieza de variables y ecuaciones. Se añade la funcionalidad para limpiar el historial de entradas y se actualiza la documentación para reflejar estos cambios.
This commit is contained in:
parent
449d503213
commit
589bab03b2
|
@ -0,0 +1,150 @@
|
||||||
|
# Solución: Contexto Limpio en Cada Evaluación
|
||||||
|
|
||||||
|
## Problema Identificado
|
||||||
|
|
||||||
|
La aplicación tenía un comportamiento inesperado donde al evaluar una secuencia como:
|
||||||
|
```
|
||||||
|
x
|
||||||
|
x=1
|
||||||
|
y+x
|
||||||
|
x=x+1
|
||||||
|
x
|
||||||
|
```
|
||||||
|
|
||||||
|
El primer `x` ya mostraba un valor (en este caso `2[Integer]`) cuando debería estar indefinido inicialmente.
|
||||||
|
|
||||||
|
## Causa Raíz REAL
|
||||||
|
|
||||||
|
El problema **NO era solo el historial**, sino que la aplicación mantenía el contexto de variables entre evaluaciones. Cuando el usuario modificaba cualquier línea, la aplicación reevaluaba **manteniendo las variables previamente definidas**, en lugar de construir el contexto desde cero.
|
||||||
|
|
||||||
|
Esto significaba que:
|
||||||
|
1. Si había `x=1` en alguna línea anterior
|
||||||
|
2. Y luego el usuario añadía una línea `x` al principio
|
||||||
|
3. El `x` del principio usaba el valor de la evaluación anterior en lugar de iniciar limpio
|
||||||
|
|
||||||
|
## Solución Implementada
|
||||||
|
|
||||||
|
### Modificación Principal: Contexto Limpio en Cada Evaluación
|
||||||
|
|
||||||
|
**Antes:**
|
||||||
|
```python
|
||||||
|
def _evaluate_and_update(self):
|
||||||
|
"""Evalúa todas las líneas y actualiza la salida"""
|
||||||
|
try:
|
||||||
|
input_content = self.input_text.get("1.0", tk.END)
|
||||||
|
if not input_content.strip():
|
||||||
|
self._clear_output()
|
||||||
|
return
|
||||||
|
|
||||||
|
lines = input_content.splitlines()
|
||||||
|
self._evaluate_lines(lines) # ← Mantenía contexto anterior
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self._show_error(f"Error durante evaluación: {e}")
|
||||||
|
```
|
||||||
|
|
||||||
|
**Después:**
|
||||||
|
```python
|
||||||
|
def _evaluate_and_update(self):
|
||||||
|
"""Evalúa todas las líneas y actualiza la salida"""
|
||||||
|
try:
|
||||||
|
input_content = self.input_text.get("1.0", tk.END)
|
||||||
|
if not input_content.strip():
|
||||||
|
self._clear_output()
|
||||||
|
return
|
||||||
|
|
||||||
|
# NUEVO: Limpiar completamente el contexto antes de cada evaluación
|
||||||
|
# Esto garantiza que cada modificación reevalúe todo desde cero
|
||||||
|
self.engine.clear_all()
|
||||||
|
|
||||||
|
lines = input_content.splitlines()
|
||||||
|
self._evaluate_lines(lines)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self._show_error(f"Error durante evaluación: {e}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cambios Adicionales
|
||||||
|
|
||||||
|
1. **Eliminación de llamadas redundantes**: Los métodos `clear_variables()`, `clear_equations()` y `clear_all()` ya no llaman a `_evaluate_and_update()` porque ahora cada evaluación limpia automáticamente.
|
||||||
|
|
||||||
|
2. **Limpieza del historial**: También se limpió el historial, pero esto era secundario al problema real.
|
||||||
|
|
||||||
|
3. **Opción manual para limpiar historial**: Se añadió en el menú **Editar → Limpiar historial**.
|
||||||
|
|
||||||
|
## Comportamiento Resultante
|
||||||
|
|
||||||
|
Ahora **cada vez que se modifica cualquier línea**:
|
||||||
|
|
||||||
|
1. **Se limpia completamente el contexto** - `engine.clear_all()`
|
||||||
|
2. **Se reevalúa TODO desde la línea 1** - construcción paso a paso
|
||||||
|
3. **El contexto se construye de arriba hacia abajo** - sin memoria de evaluaciones anteriores
|
||||||
|
4. **Variables solo existen si están definidas en líneas anteriores** - comportamiento predictible
|
||||||
|
|
||||||
|
## Prueba de Verificación
|
||||||
|
|
||||||
|
El script `test_contexto_limpio.py` confirma el comportamiento:
|
||||||
|
|
||||||
|
```
|
||||||
|
=== PRUEBA DE CONTEXTO LIMPIO POR EVALUACIÓN ===
|
||||||
|
|
||||||
|
--- PRIMERA EVALUACIÓN: x solo ---
|
||||||
|
Resultado: x # ← Símbolo puro, sin valor
|
||||||
|
Variables después: {} # ← Contexto limpio
|
||||||
|
|
||||||
|
--- TERCERA EVALUACIÓN: x, x=1, y+x ---
|
||||||
|
x (antes de asignar): x # ← Siempre símbolo puro al inicio
|
||||||
|
x=1: 1 # ← Se asigna
|
||||||
|
y+x: y + 1 # ← Usa el x=1 asignado arriba
|
||||||
|
Variables después: {'x': 1} # ← Contexto construido paso a paso
|
||||||
|
```
|
||||||
|
|
||||||
|
## Beneficios de la Solución Real
|
||||||
|
|
||||||
|
- ✅ **Contexto predecible**: Cada evaluación inicia completamente limpia
|
||||||
|
- ✅ **Construcción desde arriba**: Las variables solo existen si se definen arriba
|
||||||
|
- ✅ **Sin memoria persistente**: No hay variables "fantasma" de evaluaciones anteriores
|
||||||
|
- ✅ **Comportamiento intuitivo**: Lo que ves es lo que tienes
|
||||||
|
- ✅ **Reevaluación completa**: Cada cambio reconstruye todo desde cero
|
||||||
|
|
||||||
|
## Archivos Modificados
|
||||||
|
|
||||||
|
1. `main_calc_app.py` - Método `_evaluate_and_update()` con limpieza automática
|
||||||
|
2. `main_calc_app.py` - Métodos `clear_*()` simplificados
|
||||||
|
3. `main_calc_app.py` - **Menús simplificados**: Eliminadas opciones redundantes
|
||||||
|
4. `hybrid_calc_history.txt` - Limpiado (cambio menor)
|
||||||
|
5. `test_contexto_limpio.py` - Script de prueba (nuevo)
|
||||||
|
|
||||||
|
### Cambios en la Interfaz de Usuario
|
||||||
|
|
||||||
|
**Opciones ELIMINADAS del menú (ya no tienen sentido):**
|
||||||
|
|
||||||
|
- **Menú Editar**:
|
||||||
|
- ❌ "Limpiar variables"
|
||||||
|
- ❌ "Limpiar ecuaciones"
|
||||||
|
- ❌ "Limpiar todo"
|
||||||
|
|
||||||
|
- **Menú CAS completo**:
|
||||||
|
- ❌ "Mostrar variables"
|
||||||
|
- ❌ "Mostrar ecuaciones"
|
||||||
|
- ❌ "Resolver sistema"
|
||||||
|
|
||||||
|
**Opciones CONSERVADAS (aún útiles):**
|
||||||
|
|
||||||
|
- **Menú Editar**:
|
||||||
|
- ✅ "Limpiar entrada" - limpia el editor de texto
|
||||||
|
- ✅ "Limpiar salida" - limpia el panel de resultados
|
||||||
|
- ✅ "Limpiar historial" - elimina el archivo de historial
|
||||||
|
|
||||||
|
- **Menú Archivo**:
|
||||||
|
- ✅ "Nuevo" - inicia sesión nueva (limpia entrada y salida)
|
||||||
|
- ✅ "Cargar..." / "Guardar como..." - manejo de archivos
|
||||||
|
|
||||||
|
**La solución real no era el historial, sino garantizar que cada evaluación construye el contexto completamente desde cero.**
|
||||||
|
|
||||||
|
## Impacto en la Experiencia de Usuario
|
||||||
|
|
||||||
|
**✅ Interfaz más limpia**: Sin opciones confusas que no funcionan como se espera
|
||||||
|
**✅ Comportamiento predecible**: Lo que ves en el editor es exactamente lo que tienes
|
||||||
|
**✅ Simplicidad**: Menos opciones que manejar, enfoque en la funcionalidad principal
|
||||||
|
**✅ Consistencia**: El comportamiento es coherente con la filosofía "de arriba hacia abajo"
|
|
@ -9,6 +9,7 @@ Este documento describe el estado actual y los objetivos de desarrollo para la *
|
||||||
- Integrar todas las funciones de SymPy directamente
|
- Integrar todas las funciones de SymPy directamente
|
||||||
- SymPy maneja toda la evaluación algebraica y ecuaciones
|
- SymPy maneja toda la evaluación algebraica y ecuaciones
|
||||||
- Cada linea de ingreso corresponde a una sola linea de resultados
|
- Cada linea de ingreso corresponde a una sola linea de resultados
|
||||||
|
- **CONTEXTO LIMPIO POR EVALUACIÓN**: Cada vez que se hace una evaluación se comienza con el contexto completamente limpio y se evalúa desde arriba hacia abajo, línea por línea. Esto garantiza comportamiento predecible sin "memoria" de evaluaciones anteriores.
|
||||||
- La interfaz de usuario se divide en 2 columnas, a la izquierda el area de ingreso de datos y equaciones a ser evaluadas, a la derecha el area de resultados que se colorean segun cada tipo de respuesta.
|
- La interfaz de usuario se divide en 2 columnas, a la izquierda el area de ingreso de datos y equaciones a ser evaluadas, a la derecha el area de resultados que se colorean segun cada tipo de respuesta.
|
||||||
|
|
||||||
### 2. **Sintaxis Simplificada con Corchetes (Única)**
|
### 2. **Sintaxis Simplificada con Corchetes (Única)**
|
||||||
|
@ -454,6 +455,47 @@ else:
|
||||||
- **eval/exec opcional**: Solo disponible con sintaxis especial (ej: `@eval: código_python`)
|
- **eval/exec opcional**: Solo disponible con sintaxis especial (ej: `@eval: código_python`)
|
||||||
- **Contexto unificado**: Un solo namespace SymPy para toda la sesión
|
- **Contexto unificado**: Un solo namespace SymPy para toda la sesión
|
||||||
|
|
||||||
|
### **Comportamiento de Contexto Limpio (IMPLEMENTADO)**
|
||||||
|
|
||||||
|
**Principio fundamental**: Cada modificación del usuario resulta en una evaluación completa desde cero.
|
||||||
|
|
||||||
|
#### Implementación
|
||||||
|
- **Limpieza automática**: Cada evaluación inicia con `engine.clear_all()`
|
||||||
|
- **Construcción incremental**: El contexto se construye línea por línea, de arriba hacia abajo
|
||||||
|
- **Sin persistencia**: No hay variables "fantasma" de evaluaciones anteriores
|
||||||
|
- **Predictibilidad total**: El primer `x` en cualquier secuencia siempre es un símbolo puro
|
||||||
|
- **Evaluación inicial del historial**: Al cargar la aplicación, se evalúa el historial una vez para mostrar resultados
|
||||||
|
|
||||||
|
#### Ejemplo de Comportamiento
|
||||||
|
```python
|
||||||
|
# Primera evaluación: solo "x"
|
||||||
|
x # → Symbol('x') puro, sin valor
|
||||||
|
|
||||||
|
# Segunda evaluación: "x, x=1"
|
||||||
|
x # → Symbol('x') puro (contexto limpio)
|
||||||
|
x=1 # → Asigna x=1
|
||||||
|
|
||||||
|
# Tercera evaluación: "x, x=1, y+x"
|
||||||
|
x # → Symbol('x') puro (contexto limpio)
|
||||||
|
x=1 # → Asigna x=1
|
||||||
|
y+x # → y + 1 (usa x=1 definido arriba)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Implicaciones para el Desarrollo
|
||||||
|
- **No necesidad de gestión manual de contexto**: El sistema lo maneja automáticamente
|
||||||
|
- **Comportamiento determinista**: Misma entrada → mismo resultado, siempre
|
||||||
|
- **Simplicidad de debugging**: El estado siempre es predecible
|
||||||
|
- **Eliminación de opciones de menú obsoletas**: "Limpiar variables/ecuaciones" no tienen sentido
|
||||||
|
|
||||||
|
#### Cambios en la Interfaz de Usuario
|
||||||
|
**Opciones ELIMINADAS (redundantes):**
|
||||||
|
- Menú CAS completo (variables, ecuaciones, resolver sistema)
|
||||||
|
- "Limpiar variables", "Limpiar ecuaciones", "Limpiar todo"
|
||||||
|
|
||||||
|
**Opciones CONSERVADAS (útiles):**
|
||||||
|
- "Limpiar entrada/salida" (afecta interfaz visual)
|
||||||
|
- "Limpiar historial" (afecta archivo persistente)
|
||||||
|
|
||||||
## Métricas de Éxito
|
## Métricas de Éxito
|
||||||
|
|
||||||
- [X] Sintaxis `Class[args]` funciona consistentemente (`bracket_parser.py`, `hybrid_base_types.py`).
|
- [X] Sintaxis `Class[args]` funciona consistentemente (`bracket_parser.py`, `hybrid_base_types.py`).
|
||||||
|
|
|
@ -1,26 +1,10 @@
|
||||||
Hex[FF]
|
|
||||||
ip=IP4[110.1.30.70/24]
|
|
||||||
|
|
||||||
ip.NetworkAddress()
|
|
||||||
|
|
||||||
|
|
||||||
500/25
|
x=12
|
||||||
|
a=x
|
||||||
|
|
||||||
Dec[Hex[ff]]
|
x=2
|
||||||
|
b=x
|
||||||
|
|
||||||
Hex[ff]
|
a
|
||||||
|
b
|
||||||
Hex[ff].toDecimal()
|
|
||||||
|
|
||||||
n=IP4[110.1.30.70;255.255.255.0]
|
|
||||||
|
|
||||||
n.mask()
|
|
||||||
|
|
||||||
m=IP4Mask[23]
|
|
||||||
|
|
||||||
IP4Mask[22].to_hex()
|
|
||||||
|
|
||||||
n=IP4[110.1.30.70;255.255.255.0]
|
|
||||||
|
|
||||||
latex[x**z/rr]
|
|
||||||
latex(x**z/rr)
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"window_geometry": "1020x700+238+107",
|
"window_geometry": "1020x700+144+161",
|
||||||
"sash_pos_x": 355,
|
"sash_pos_x": 355,
|
||||||
"symbolic_mode": true,
|
"symbolic_mode": true,
|
||||||
"show_numeric_approximation": true,
|
"show_numeric_approximation": true,
|
||||||
|
|
132
main_calc_app.py
132
main_calc_app.py
|
@ -339,17 +339,7 @@ CLASES DISPONIBLES:
|
||||||
edit_menu.add_command(label="Limpiar entrada", command=self.clear_input)
|
edit_menu.add_command(label="Limpiar entrada", command=self.clear_input)
|
||||||
edit_menu.add_command(label="Limpiar salida", command=self.clear_output)
|
edit_menu.add_command(label="Limpiar salida", command=self.clear_output)
|
||||||
edit_menu.add_separator()
|
edit_menu.add_separator()
|
||||||
edit_menu.add_command(label="Limpiar variables", command=self.clear_variables)
|
edit_menu.add_command(label="Limpiar historial", command=self.clear_history)
|
||||||
edit_menu.add_command(label="Limpiar ecuaciones", command=self.clear_equations)
|
|
||||||
edit_menu.add_command(label="Limpiar todo", command=self.clear_all)
|
|
||||||
|
|
||||||
# Menú CAS
|
|
||||||
cas_menu = Menu(menubar, tearoff=0)
|
|
||||||
menubar.add_cascade(label="CAS", menu=cas_menu)
|
|
||||||
cas_menu.add_command(label="Mostrar variables", command=self.show_variables)
|
|
||||||
cas_menu.add_command(label="Mostrar ecuaciones", command=self.show_equations)
|
|
||||||
cas_menu.add_separator()
|
|
||||||
cas_menu.add_command(label="Resolver sistema", command=self.solve_system)
|
|
||||||
|
|
||||||
# Menú Configuración
|
# Menú Configuración
|
||||||
config_menu = Menu(menubar, tearoff=0, bg="#3c3c3c", fg="white")
|
config_menu = Menu(menubar, tearoff=0, bg="#3c3c3c", fg="white")
|
||||||
|
@ -690,6 +680,10 @@ CLASES DISPONIBLES:
|
||||||
self._clear_output()
|
self._clear_output()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# NUEVO: Limpiar completamente el contexto antes de cada evaluación
|
||||||
|
# Esto garantiza que cada modificación reevalúe todo desde cero
|
||||||
|
self.engine.clear_all()
|
||||||
|
|
||||||
lines = input_content.splitlines()
|
lines = input_content.splitlines()
|
||||||
self._evaluate_lines(lines)
|
self._evaluate_lines(lines)
|
||||||
|
|
||||||
|
@ -920,7 +914,6 @@ CLASES DISPONIBLES:
|
||||||
"""Inicia nueva sesión"""
|
"""Inicia nueva sesión"""
|
||||||
self.clear_input()
|
self.clear_input()
|
||||||
self.clear_output()
|
self.clear_output()
|
||||||
self.engine.clear_all()
|
|
||||||
|
|
||||||
def load_file(self):
|
def load_file(self):
|
||||||
"""Carga archivo en el editor"""
|
"""Carga archivo en el editor"""
|
||||||
|
@ -977,20 +970,14 @@ CLASES DISPONIBLES:
|
||||||
"""Limpia panel de salida"""
|
"""Limpia panel de salida"""
|
||||||
self._clear_output()
|
self._clear_output()
|
||||||
|
|
||||||
def clear_variables(self):
|
def clear_history(self):
|
||||||
"""Limpia variables del motor"""
|
"""Limpia el archivo de historial"""
|
||||||
self.engine.clear_variables()
|
try:
|
||||||
self._evaluate_and_update()
|
if os.path.exists(self.HISTORY_FILE):
|
||||||
|
os.remove(self.HISTORY_FILE)
|
||||||
def clear_equations(self):
|
messagebox.showinfo("Éxito", "Historial limpiado correctamente.")
|
||||||
"""Limpia ecuaciones del motor"""
|
except Exception as e:
|
||||||
self.engine.clear_equations()
|
messagebox.showerror("Error", f"No se pudo limpiar el historial:\n{e}")
|
||||||
self._evaluate_and_update()
|
|
||||||
|
|
||||||
def clear_all(self):
|
|
||||||
"""Limpia variables y ecuaciones"""
|
|
||||||
self.engine.clear_all()
|
|
||||||
self._evaluate_and_update()
|
|
||||||
|
|
||||||
def copy_output(self):
|
def copy_output(self):
|
||||||
"""Copia el contenido de la salida al portapapeles"""
|
"""Copia el contenido de la salida al portapapeles"""
|
||||||
|
@ -999,95 +986,6 @@ CLASES DISPONIBLES:
|
||||||
self.root.clipboard_clear()
|
self.root.clipboard_clear()
|
||||||
self.root.clipboard_append(content)
|
self.root.clipboard_append(content)
|
||||||
|
|
||||||
def show_variables(self):
|
|
||||||
"""Muestra ventana con variables definidas"""
|
|
||||||
variables = self.engine.symbol_table
|
|
||||||
|
|
||||||
window = tk.Toplevel(self.root)
|
|
||||||
window.title("Variables Definidas")
|
|
||||||
window.geometry("500x400")
|
|
||||||
window.configure(bg="#2b2b2b")
|
|
||||||
|
|
||||||
text_widget = scrolledtext.ScrolledText(
|
|
||||||
window,
|
|
||||||
font=("Consolas", 11),
|
|
||||||
bg="#1e1e1e",
|
|
||||||
fg="#d4d4d4"
|
|
||||||
)
|
|
||||||
text_widget.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
|
|
||||||
|
|
||||||
if variables:
|
|
||||||
content = "Variables definidas:\n\n"
|
|
||||||
for name, value in variables.items():
|
|
||||||
content += f"{name} = {value}\n"
|
|
||||||
else:
|
|
||||||
content = "No hay variables definidas."
|
|
||||||
|
|
||||||
text_widget.insert("1.0", content)
|
|
||||||
text_widget.config(state="disabled")
|
|
||||||
|
|
||||||
def show_equations(self):
|
|
||||||
"""Muestra ventana con ecuaciones definidas"""
|
|
||||||
equations = self.engine.equations
|
|
||||||
|
|
||||||
window = tk.Toplevel(self.root)
|
|
||||||
window.title("Ecuaciones Definidas")
|
|
||||||
window.geometry("500x400")
|
|
||||||
window.configure(bg="#2b2b2b")
|
|
||||||
|
|
||||||
text_widget = scrolledtext.ScrolledText(
|
|
||||||
window,
|
|
||||||
font=("Consolas", 11),
|
|
||||||
bg="#1e1e1e",
|
|
||||||
fg="#d4d4d4"
|
|
||||||
)
|
|
||||||
text_widget.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
|
|
||||||
|
|
||||||
if equations:
|
|
||||||
content = "Ecuaciones en el sistema:\n\n"
|
|
||||||
for i, eq in enumerate(equations, 1):
|
|
||||||
content += f"{i}. {eq}\n"
|
|
||||||
else:
|
|
||||||
content = "No hay ecuaciones en el sistema."
|
|
||||||
|
|
||||||
text_widget.insert("1.0", content)
|
|
||||||
text_widget.config(state="disabled")
|
|
||||||
|
|
||||||
def solve_system(self):
|
|
||||||
"""Resuelve el sistema de ecuaciones"""
|
|
||||||
try:
|
|
||||||
if not self.engine.equations:
|
|
||||||
messagebox.showinfo("Info", "No hay ecuaciones para resolver.")
|
|
||||||
return
|
|
||||||
|
|
||||||
solutions = self.engine.solve_system()
|
|
||||||
|
|
||||||
window = tk.Toplevel(self.root)
|
|
||||||
window.title("Soluciones del Sistema")
|
|
||||||
window.geometry("500x400")
|
|
||||||
window.configure(bg="#2b2b2b")
|
|
||||||
|
|
||||||
text_widget = scrolledtext.ScrolledText(
|
|
||||||
window,
|
|
||||||
font=("Consolas", 11),
|
|
||||||
bg="#1e1e1e",
|
|
||||||
fg="#d4d4d4"
|
|
||||||
)
|
|
||||||
text_widget.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
|
|
||||||
|
|
||||||
content = "Soluciones del sistema:\n\n"
|
|
||||||
if isinstance(solutions, dict):
|
|
||||||
for var, value in solutions.items():
|
|
||||||
content += f"{var} = {value}\n"
|
|
||||||
else:
|
|
||||||
content += str(solutions)
|
|
||||||
|
|
||||||
text_widget.insert("1.0", content)
|
|
||||||
text_widget.config(state="disabled")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
messagebox.showerror("Error", f"Error resolviendo sistema:\n{e}")
|
|
||||||
|
|
||||||
def show_types_syntax(self):
|
def show_types_syntax(self):
|
||||||
"""Muestra sintaxis de tipos disponibles - NUEVA FUNCIÓN"""
|
"""Muestra sintaxis de tipos disponibles - NUEVA FUNCIÓN"""
|
||||||
try:
|
try:
|
||||||
|
@ -1295,7 +1193,7 @@ programación y análisis numérico.
|
||||||
text_widget.config(state="disabled")
|
text_widget.config(state="disabled")
|
||||||
|
|
||||||
def load_history(self):
|
def load_history(self):
|
||||||
"""Carga historial de entrada"""
|
"""Carga historial de entrada y realiza evaluación inicial"""
|
||||||
try:
|
try:
|
||||||
if os.path.exists(self.HISTORY_FILE):
|
if os.path.exists(self.HISTORY_FILE):
|
||||||
with open(self.HISTORY_FILE, "r", encoding="utf-8") as f:
|
with open(self.HISTORY_FILE, "r", encoding="utf-8") as f:
|
||||||
|
@ -1303,6 +1201,8 @@ programación y análisis numérico.
|
||||||
|
|
||||||
if content.strip():
|
if content.strip():
|
||||||
self.input_text.insert("1.0", content)
|
self.input_text.insert("1.0", content)
|
||||||
|
# Hacer evaluación inicial para mostrar resultados del historial
|
||||||
|
# Esto mantiene el comportamiento de contexto limpio pero muestra resultados
|
||||||
self.root.after_idle(self._evaluate_and_update)
|
self.root.after_idle(self._evaluate_and_update)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error cargando historial: {e}")
|
print(f"Error cargando historial: {e}")
|
||||||
|
|
36
readme.md
36
readme.md
|
@ -10,6 +10,7 @@ Sistema de Álgebra Computacional (CAS) que combina SymPy con clases especializa
|
||||||
- **Sistema de tipos dinámico**: Auto-descubrimiento desde `custom_types/`
|
- **Sistema de tipos dinámico**: Auto-descubrimiento desde `custom_types/`
|
||||||
- **Sintaxis simplificada**: `Tipo[args]` en lugar de `Tipo("args")`
|
- **Sintaxis simplificada**: `Tipo[args]` en lugar de `Tipo("args")`
|
||||||
- **Detección automática de ecuaciones**: Sin sintaxis especial
|
- **Detección automática de ecuaciones**: Sin sintaxis especial
|
||||||
|
- **Contexto limpio por evaluación**: Cada modificación evalúa todo desde cero, garantizando comportamiento predecible
|
||||||
- **Resultados interactivos**: Elementos clickeables para plots, matrices y listas
|
- **Resultados interactivos**: Elementos clickeables para plots, matrices y listas
|
||||||
- **Autocompletado inteligente**: Basado en tipos registrados dinámicamente
|
- **Autocompletado inteligente**: Basado en tipos registrados dinámicamente
|
||||||
|
|
||||||
|
@ -106,6 +107,33 @@ y = x + 2 # y es 7 (evaluado)
|
||||||
z = x + a # z es Symbol('x') + Symbol('a') (simbólico)
|
z = x + a # z es Symbol('x') + Symbol('a') (simbólico)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Comportamiento de Contexto Limpio
|
||||||
|
|
||||||
|
**Principio fundamental**: Cada vez que modifica cualquier línea, la aplicación reevalúa **todo** desde cero.
|
||||||
|
|
||||||
|
#### Ventajas
|
||||||
|
- **Predecible**: El primer `x` en cualquier secuencia siempre es un símbolo puro
|
||||||
|
- **Sin sorpresas**: No hay variables "fantasma" de evaluaciones anteriores
|
||||||
|
- **Contextual**: Las variables solo existen si están definidas en líneas anteriores
|
||||||
|
- **Determinista**: Misma entrada → mismo resultado, siempre
|
||||||
|
|
||||||
|
#### Ejemplo
|
||||||
|
```python
|
||||||
|
# Al escribir esta secuencia línea por línea:
|
||||||
|
x # → Symbol('x') puro (sin valor)
|
||||||
|
x=1 # → Asigna x=1
|
||||||
|
y+x # → y + 1 (usa x=1 definido arriba)
|
||||||
|
x=x+1 # → Incrementa x a 2
|
||||||
|
x # → Muestra 2
|
||||||
|
```
|
||||||
|
|
||||||
|
**Importante**: Cada modificación reconstruye el contexto desde la línea 1 hacia abajo.
|
||||||
|
|
||||||
|
#### Carga de Historial
|
||||||
|
- Al abrir la aplicación, se carga el historial anterior y se evalúa una vez para mostrar resultados
|
||||||
|
- A partir de ese momento, cada modificación limpia el contexto y reevalúa todo desde cero
|
||||||
|
- El historial se guarda automáticamente al cerrar la aplicación
|
||||||
|
|
||||||
## Interfaz de Usuario
|
## Interfaz de Usuario
|
||||||
|
|
||||||
### Paneles
|
### Paneles
|
||||||
|
@ -119,11 +147,13 @@ z = x + a # z es Symbol('x') + Symbol('a') (simbólico)
|
||||||
|
|
||||||
### Menús
|
### Menús
|
||||||
- **Archivo**: Nuevo, Cargar, Guardar
|
- **Archivo**: Nuevo, Cargar, Guardar
|
||||||
- **Editar**: Limpiar, operaciones CAS
|
- **Editar**: Limpiar entrada/salida, Limpiar historial
|
||||||
- **CAS**: Variables, ecuaciones, resolver sistema
|
- **Configuración**: Modos simbólicos, Recargar tipos personalizados
|
||||||
- **Tipos**: Información de tipos, recargar sistema
|
- **Tipos**: Información de tipos, Sintaxis de tipos
|
||||||
- **Ayuda**: Guías y referencia
|
- **Ayuda**: Guías y referencia
|
||||||
|
|
||||||
|
**Nota**: Se han eliminado las opciones relacionadas con limpiar variables/ecuaciones ya que el contexto se limpia automáticamente en cada evaluación.
|
||||||
|
|
||||||
## Sistema de Tipos Dinámico
|
## Sistema de Tipos Dinámico
|
||||||
|
|
||||||
### Auto-descubrimiento
|
### Auto-descubrimiento
|
||||||
|
|
Loading…
Reference in New Issue