Autómatas celulares, Aplicación WinCA V
Continúo comentando el código fuente del programa WinCA, dedicado a los autómatas celulares. En este artículo voy a explicar los interfaces y las clases con las que se implementan los estados de las celdas y su edición. Puedes utilizar estos interfaces y clases como base para extender el funcionamiento de la aplicación.
Aquí puedes encontrar el primer artículo de la serie sobre la aplicación WinCA.
En este enlace puedes descargar los ejecutables de la aplicación WinCA, y en este otro puedes descargar el código fuente de la solución WinCA, escrita en CSharp con Visual Studio 2015.
Estados
Los estados de las celdas se implementan mediante el interfaz ICAState, en el espacio de nombres Interfaces de la librería de clases CellularAutomata:
public interface ICAState
{
IPropertyProvider PropertyProvider { get; set; }
string Color { get; set; }
Color StateColor { get; }
string Name { get; set; }
IEnumerable<IObjectProperty> Properties { get; }
IEnumerable<string> Transitions { get; }
object GetValue(string name);
IVariantValue GetVarValue(string name);
void AddProperty(string name);
void RemoveProperty(string name);
void ChangeProperty(string name, IObjectProperty p);
void SetTransition(string toname, string expression);
string GetTransition(string toname);
void CompileTransitions(RuleTable rt, ICAStateProvider statep);
int CheckTransitions();
}
Las propiedades y métodos tienen el siguiente uso:
- ProperyProvider: Obtiene o establece el proveedor de propiedades para el objeto.
- Color: Nombre de la propiedad que establece el color del estado.
- StateColor: Obtiene el color del estado.
- Name: Obtiene o establece el nombre del estado. Los nombres deben ser únicos.
- Properties: Enumera las propiedades del estado.
- Transitions: Enumera las expresiones que disparan el cambio de este estado a otros estados.
- GetValue: Devuelve el valor de la propiedad del estado, como un objeto genérico de tipo object, identificada por su nombre en el parámetro name.
- GetVarValue: Devuelve el valor de la propiedad del estado, como un interfaz IVariantValue, identificada por su nombre en el parámetro name.
- AddProperty: Permite añadir la propiedad con el nombre name al estado.
- RemoveProperty: Elimina la propiedad con el nombre name de la lista de propiedades del estado.
- ChangeProperty: Cambia la propiedad con el nombre name por la proporcionada en el parámetro p.
- SetTransition: Establece la transición al estado con el nombre toname mediante la expresión proporcionada en el parámetro expression.
- GetTransition: Devuelve la expresión de la transición al estado con el nombre toname.
- CompileTransitions: Compila las expresiones de las transiciones, utilizando la tabla de reglas sintácticas rt y el proveedor de estados statep.
- CheckTransition: Comprueba si se cumple alguna de las expresiones de cambio de estado y devuelve el índice del estado final o -1 si no se produce ninguna transición.
Las transiciones entre estados las comentaré en el siguiente artículo de la serie. Existe una implementación básica de este interfaz en la clase BasicState, en el espacio de nombres States de la librería de clases CellularAutomata.
Los estados se gestionan mediante un proveedor de estados, que mantiene una lista interna de todos los estados disponibles. Los proveedores de estados implementan la interfaz ICAStateProvider, en el espacio de nombres Interfaces de la librería CellularAutomata, que define las siguientes propiedades y métodos:
public interface ICAStateProvider
{
string UID { get; }
string Name { get; set; }
int Count { get; }
IPropertyProvider PropertyProvider { get; set; }
IEnumerable<ICAState> States { get; }
Type DefaultStateType { get; set; }
ICAState GetState(string name);
ICAState GetState(int index);
int IndexOf(ICAState s);
int IndexOf(string name);
bool ExistsState(string name);
void AddState(ICAState s);
void AddStates(IEnumerable<ICAState> ss);
void RemoveState(string name);
void RemoveState(ICAState s);
void ChangeState(string name, ICAState s);
ICAState CreateState(string name);
}
Estas propiedades y métodos tienen el siguiente uso:
- UID: Devuelve un identificador único para el proveedor de estados.
- Name: Obtiene o establece el nombre del proveedor de estados.
- Count: Devuelve el número de estados que contiene el objeto.
- PropertyProvider: Proveedor de propiedades que utilizan todos los estados gestionados por el objeto.
- States: Enumera todos los estados gestionados por el objeto.
- DefaultStateType: Obtiene o establece el tipo de estado por defecto. Debe ser un tipo que implemente el interfaz ICAState.
- GetState: Existen dos versiones de este método, una para obtener un estado a partir de su nombre y otra a partir de su índice en la lista de estados interna.
- IndexOf: También existen dos versiones. Devuelven el índice de un estado a partir del propio estado o de su nombre.
- ExistsState: Devuelve true si existe un estado con el nombre dado.
- AddState: Añade un estado a la colección de estados del proveedor.
- AddStates: Añade una lista de estados a partir de un objeto IEnumerable<ICAState>.
- RemoveState: Permite eliminar un estado, bien por su nombre o a partir del estado mismo.
- ChangeState: Cambia el estado con el nombre name por el estado proporcionado en el parámetro s.
- CreateState: Crea un nuevo estado con el nombre name y el tipo indicado en la propiedad DefaultStateType.
También existe una implementación por defecto en la clase BasicStateProvider, en el espacio de nombres States de la librería de clases CellularAutomata.
Editor de estados
El editor de estados está implementado en la aplicación WinCA en el formulario frmStates, en el espacio de nombres Forms. Los editores de estados deben implementar el interfaz ICAStateManager, definido en el espacio de nombres Interfaces de la aplicación WinCA de la siguiente manera:
public interface ICAStateManager
{
event CAStateChangeEventHandler StateChanged;
ICAStateProvider Provider { get; set; }
IPropertyProvider VariableProvider { get; }
IMainForm MainForm { get; set; }
}
StateChanged es un evento que se puede suscribir para recibir notaciones cuando se elimina, añade o se cambia el nombre de alguno de los estados. Provider es el proveedor de estados utilizado por el editor, y VariableProvider es un proveedor de variables. El proveedor de propiedades constantes se obtiene del proveedor de estados. MainForm es el formulario principal de la aplicación.
Los estados se almacenan en archivos, junto con sus propiedades, mediante una clase auxiliar de serialización, StateSerializationContext, definida en el espacio de nombres Utils:
public class StateSerializationContainer
{
public StateSerializationContainer()
{
}
public ICAStateProvider StateProvider { get; set; }
public PropertySerializationContainer Properties { get; set; }
}
En cuanto al interfaz IMainForm, que ya empecé a comentar en el artículo anterior, la propiedad StateManagers enumera todos los formularios abiertos que implementan el interfaz ICAStateManager, mientras que el método CreateStateManager crea un nuevo formulario editor de estados, bien vacío, si se le pasa el parámetro sms con el valor null, o bien a partir de un archivo si se le pasa un objeto StateSerializationContainer y un nombre de archivo.
También se puede suscribir el evento OnStateManagerChanged para recibir notificaciones si se abre o cierra un nuevo formulario editor de estados.
Y eso es todo respecto a los estados, en el próximo artículo trataré las expresiones de cambio de estado.