Exemple #1
0
 /// <summary><see cref="TorXakisConnector.InputReceived"/></summary>
 private void Connector_InputReceived(TorXakisAction action)
 {
     if (action.Type == ActionType.Input && action.Channel == TorXakisModel.InputChannel)
     {
         ModelAction input = ModelAction.Deserialize(action.Data);
         HandleModelInput(input);
     }
 }
        /// <summary>
        /// Deserializes the given string into an object instance.
        /// </summary>
        public static ModelAction Deserialize(string str)
        {
            string[] parts = str.Split('(');

            // Map the type name back to a class defined in the models assembly.
            string typeName = parts[0];
            Type   type     = null;

            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                if (assembly.FullName.StartsWith(ModelsAssemblyName))
                {
                    type = assembly.GetType(ModelsAssemblyName + "." + typeName);
                }
            }

            // Instantiate an object of this type.
            ModelAction action = (ModelAction)Activator.CreateInstance(type);

            // Assign the serialized property values on the new instance.
            if (parts.Length > 1)
            {
                PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
                string[]       values     = parts[1].TrimEnd(')').Split(',');
                for (int i = 0; i < properties.Length; i++)
                {
                    PropertyInfo property = properties[i];
                    string       value    = values[i];

                    if (property.PropertyType == typeof(bool))
                    {
                        property.SetValue(action, bool.Parse(value));
                    }
                    else if (property.PropertyType == typeof(int))
                    {
                        property.SetValue(action, int.Parse(value));
                    }
                    else if (property.PropertyType == typeof(string))
                    {
                        property.SetValue(action, value);
                    }
                }
            }

            return(action);
        }
Exemple #3
0
        /// <summary>
        /// Sends the given <see cref="ModelAction"/> output.
        /// </summary>
        public void SendModelOutput(ModelAction modelOutput)
        {
            lock (locker)
            {
                // Pre-filter incompatible types.
                if (modelOutput is null)
                {
                    throw new ArgumentNullException(nameof(modelOutput));
                }
                if (!ModelOutputs.Contains(modelOutput.GetType()))
                {
                    return;
                }

                Log.Debug(this, nameof(SendModelOutput) + ": " + modelOutput);
                string         serialized = modelOutput.Serialize();
                TorXakisAction output     = TorXakisAction.FromOutput(TorXakisModel.OutputChannel, serialized);
                Connector.SendOutput(output);
            }
        }
Exemple #4
0
        /// <summary>
        /// Handles the given <see cref="ModelAction"/> input.
        /// </summary>
        public void HandleModelInput(ModelAction modelInput)
        {
            lock (locker)
            {
                // Pre-filter incompatible types.
                if (modelInput is null)
                {
                    throw new ArgumentNullException(nameof(modelInput));
                }
                if (!ModelInputs.Contains(modelInput.GetType()))
                {
                    return;
                }

                Log.Debug(this, nameof(HandleModelInput) + ": " + modelInput);
                inputs.Enqueue(modelInput);

                // This must now be called manually from the thread that should perform the operations.
                //CheckSystems();
            }
        }
Exemple #5
0
        /// <summary>
        /// Checks the <see cref="inputs"/> and <see cref="events"/> queues.
        /// Determines if the <see cref="CurrentSystem"/> can be advanced.
        /// Determines if one of the <see cref="Systems"/> can be started.
        /// </summary>
        public void CheckSystems()
        {
            Log.Debug(this, nameof(CheckSystems) + " inputs: " + inputs.Count + " commands: " + events.Count + "\n" + this);

            bool transitioned = false;

            // If proactive transitions are possible, trigger them!
            if (!transitioned)
            {
                HashSet <Tuple <TransitionSystem, ProactiveTransition> > proactives = PossibleProactiveTransitions();
                if (proactives.Count > 0)
                {
                    Log.Debug(this, "Possible proactive transitions: " + string.Join(", ", proactives.Select(x => x.Item1.ModelAction.Name + ": " + x.Item2).ToArray()));
                    Tuple <TransitionSystem, ProactiveTransition> selected = proactives.Random();
                    Log.Debug(this, "Selected proactive transition: " + selected.Item1.ModelAction.Name + ": " + selected.Item2);
                    IAction generated = ExecuteProactiveTransition(selected);

                    if (generated is ModelAction modelOutput)
                    {
                        SendModelOutput(modelOutput);
                    }
                    else if (generated is ISystemAction systemCommand)
                    {
                        SendSystemCommand(systemCommand);
                    }

                    transitioned = true;
                }
            }

            // If reactive transitions are possible, due to system events, trigger them!
            if (!transitioned)
            {
                if (events.Count > 0)
                {
                    ISystemAction systemEvent = events.Dequeue();
                    Log.Debug(this, "Dequeueing system event: " + systemEvent);
                    HashSet <Tuple <TransitionSystem, ReactiveTransition> > reactives = PossibleReactiveTransitions(systemEvent);
                    if (reactives.Count > 0)
                    {
                        Log.Debug(this, "Possible reactive transitions: " + string.Join(", ", reactives.Select(x => x.Item1.ModelAction.Name + ": " + x.Item2).ToArray()));
                        Tuple <TransitionSystem, ReactiveTransition> selected = reactives.Random();
                        Log.Debug(this, "Selected reactive transition: " + selected.Item1.ModelAction.Name + ": " + selected.Item2);
                        ExecuteReactiveTransition(systemEvent, selected);

                        transitioned = true;
                    }
                    else
                    {
                        // Since all system events are being looped through this, not being able to handle one is not an error per se. (TPE)
                        Log.Warn(this, "No reactive transition possible for system event: " + systemEvent);
                    }
                }
            }

            // If reactive transitions are possible, due to model inputs, trigger them!
            if (!transitioned)
            {
                if (inputs.Count > 0)
                {
                    ModelAction modelInput = inputs.Dequeue();
                    Log.Debug(this, "Dequeueing model input: " + modelInput);
                    HashSet <Tuple <TransitionSystem, ReactiveTransition> > reactives = PossibleReactiveTransitions(modelInput);
                    if (reactives.Count > 0)
                    {
                        Log.Debug(this, "Possible reactive transitions: " + string.Join(", ", reactives.Select(x => x.Item1.ModelAction.Name + ": " + x.Item2).ToArray()));
                        Tuple <TransitionSystem, ReactiveTransition> selected = reactives.Random();
                        Log.Debug(this, "Selected reactive transition: " + selected.Item1.ModelAction.Name + ": " + selected.Item2);
                        ExecuteReactiveTransition(modelInput, selected);

                        transitioned = true;
                    }
                    else
                    {
                        Log.Error(this, "No reactive transition possible for model input: " + modelInput);
                    }
                }
            }

            // If a transition was taken, re-evaluate immediately!
            if (transitioned)
            {
                if (CurrentSystem.CurrentState == CurrentSystem.InitialState)
                {
                    Log.Debug(this, "System has looped: " + CurrentSystem);
                    CurrentSystem = null;
                }
                CheckSystems();
            }
            // If no transition was taken (due to ignored input or event), we still need to check the next input or event.
            else if (inputs.Count > 0 || events.Count > 0)
            {
                CheckSystems();
            }
        }