Exemple #1
0
        /// <summary>
        /// Produces a DOT GraphViz graph.
        /// </summary>
        /// <returns>DOT GraphViz text.</returns>
        public string WriteMap(ISchematic <TState, TInput> schematic)
        {
            var lines       = new List <string>();
            var actionLines = new List <string>();

            foreach (var state in schematic.States.Values)
            {
                var source = state.Value;

                lines.AddRange(state.Transitions.Values
                               .Select(transition =>
                                       GetTransitionRepresentation(
                                           source.ToString(),
                                           transition.Input.ToString(),
                                           transition.ResultantState.ToString(),
                                           transition.Precondition?.Description)));

                if (state.Action != null)
                {
                    actionLines.Add($" {state.Value} -> \"{state.Action.Description ?? state.Action.ConnectorKey.Identifier}\"" +
                                    " [label=\"executes\" style=dotted];");
                }
            }

            if (actionLines.Count > 0)
            {
                lines.Add(" node [shape=box];");

                lines.AddRange(actionLines);
            }

            return($"digraph {{\r\n{ string.Join("\r\n\t", lines) }\r\n}}");
        }
Exemple #2
0
 public Task <IEnumerable <IStateMachine <TState, TInput> > > BulkCreateMachinesAsync(
     ISchematic <TState, TInput> schematic,
     IEnumerable <IDictionary <string, string> > metadata,
     CancellationToken cancellationToken = default)
 {
     return(BulkCreateMachinesAsync(schematic.Clone(), metadata, cancellationToken));
 }
        public async Task InvokeAsync <TPayload>(
            ISchematic <TState, TInput> schematic,
            IStateMachine <TState, TInput> machine,
            Status <TState> status,
            InputParameters <TInput, TPayload> inputParameters,
            IReadOnlyDictionary <string, string> connectorSettings,
            CancellationToken cancellationToken = default)
        {
            var configuration = _configurations.FindConfiguration(schematic, status);

            var messageBytes = CreateMessageBytes(
                schematic,
                machine,
                status,
                inputParameters,
                connectorSettings,
                cancellationToken);

            var queueClient = new QueueClient(
                new ServiceBusConnectionStringBuilder(configuration.ConnectionString),
                ReceiveMode.PeekLock,
                RetryPolicy.Default);

            await queueClient.SendAsync(new Message(messageBytes));
        }
Exemple #4
0
        public Task <bool> ValidateAsync <TPayload>(
            ISchematic <TypeState, TypeState> schematic,
            IStateMachine <TypeState, TypeState> machine,
            Status <TypeState> status,
            InputParameters <TypeState, TPayload> inputParameters,
            IReadOnlyDictionary <string, string> connectorSettings,
            CancellationToken cancellationToken = default)
        {
            TSignal signal = default;

            if (inputParameters != null)
            {
                if (!(inputParameters.Payload is TSignal castedSignal))
                {
                    throw new ArgumentException(
                              $"Type mismatch for converting to signal: " +
                              $"{typeof(TSignal)} from {typeof(TPayload)}",
                              nameof(inputParameters.Payload));
                }

                signal = castedSignal;
            }

            return(ValidateAsync(
                       new ConnectorContext
            {
                Schematic = new NaturalSchematic(schematic),
                Machine = new NaturalStateMachine(machine),
                Status = status,
                Settings = connectorSettings
            },
                       signal,
                       cancellationToken));
        }
Exemple #5
0
 public static Schematic <TState, TInput> Clone <TState, TInput>(this ISchematic <TState, TInput> schematic) =>
 new Schematic <TState, TInput>(
     schematic.SchematicName,
     schematic.InitialState,
     schematic.StateConflictRetryCount,
     schematic.States.Values
     .Select(Clone)
     .ToArray());
        public Task InvokeAsync <TPayload>(
            ISchematic <TState, TInput> schematic,
            IStateMachine <TState, TInput> machine,
            Status <TState> status,
            InputParameters <TInput, TPayload> inputParameters,
            IReadOnlyDictionary <string, string> connectorSettings,
            CancellationToken cancellationToken = default)
        {
            var configuration = _logConfigurations.FindConfiguration(schematic, status);

            string messageFormat = null;

            connectorSettings?.TryGetValue("messageFormat", out messageFormat);
            const string machineEnteredStateMessage = "Machine {machineId} entered state: {state}.";

            messageFormat = messageFormat ?? machineEnteredStateMessage;

            var logLevel = MapLogLevel(configuration.LogLevel);

            object input   = null;
            object payload = null;

            if (inputParameters != null)
            {
                input   = inputParameters.Input;
                payload = inputParameters.Payload;
            }

            var logParameters = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase)
            {
                [nameof(schematic.SchematicName)] = schematic.SchematicName,
                [nameof(machine.MachineId)]       = machine.MachineId,
                [nameof(status.State)]            = status.State,
                [nameof(inputParameters.Input)]   = input,
                [nameof(inputParameters.Payload)] = payload
            };

            // Get the distinct set of matches including casing.
            var matches = _messageFormatTokensRegex
                          .Matches(messageFormat).Cast <Match>()
                          .Select(match => match.Value)
                          .ToList();

            var parameters = matches.Select(match =>
            {
                logParameters.TryGetValue(match, out var value);

                return(value);
            }).ToArray();

            Logger.LogFormat(logLevel, messageFormat, parameters);

#if NET45
            return(Task.FromResult(0));
#else
            return(Task.CompletedTask);
#endif
        }
Exemple #7
0
        public Task Given_a_Schematic_with_an_initial_state_INITIALSTATE(string schematicName, TState initialState)
        {
            CurrentSchematic = CurrentHost.Agent()
                               .CreateSchematic <TState, TInput>(schematicName)
                               .WithState(initialState, state => state
                                          .AsInitialState())
                               .Build();

            return(Task.CompletedTask);
        }
Exemple #8
0
        /// <summary>
        /// Generates nodes for all components, one node connects all terminals (components) that have the same position or that
        /// are connected through wire(s)
        /// </summary>
        /// <param name="schematic"></param>
        /// <returns></returns>
        public static List <INode> Generate(ISchematic schematic)
        {
            // Generate nodes located on the same position
            var nodes = GenerateSamePositionNodes(new List <IBaseComponent>(schematic.Components));

            // Merge them based on the wire connections
            nodes = MergeNodesConnectedByWires(nodes, new List <IWire>(schematic.Wires));

            return(nodes);
        }
Exemple #9
0
 public async Task Given_a_Machine_exists_with_MachineId_MACHINEID(ISchematic <TState, TInput> schematic, string machineId)
 {
     CurrentMachine = await CurrentHost.Agent()
                      .GetStateEngine <TState, TInput>()
                      .CreateMachineAsync(schematic, machineId, new Dictionary <string, string>
     {
         ["Key1"] = "Value1",
         ["Key2"] = "Value2"
     });
 }
Exemple #10
0
 public async Task When_a_Machine_is_created_from_a_Schematic(ISchematic <TState, TInput> schematic)
 {
     try
     {
         CurrentMachine = await CurrentHost.Agent()
                          .GetStateEngine <TState, TInput>()
                          .CreateMachineAsync(schematic);
     }
     catch (Exception ex)
     {
         CurrentException = ex;
     }
 }
            public Task InvokeAsync <TPayload>(
                ISchematic <string, string> schematic,
                IStateMachine <string, string> machine,
                Status <string> status,
                InputParameters <string, TPayload> inputParameters,
                IReadOnlyDictionary <string, string> connectorSettings,
                CancellationToken cancellationToken = default)
            {
                // Processing
                var engine = Agent.GetStateEngine <string, string>();

                return(Task.CompletedTask);
            }
Exemple #12
0
 public async Task When_a_Machine_is_created_from_a_Schematic_with_a_predefined_MachineId(
     ISchematic <TState, TInput> schematic, string machineId)
 {
     try
     {
         CurrentMachine = await CurrentHost.Agent()
                          .GetStateEngine <TState, TInput>()
                          .CreateMachineAsync(schematic, machineId);
     }
     catch (Exception ex)
     {
         CurrentException = ex;
     }
 }
Exemple #13
0
            public async Task InvokeAsync <TPayload>(
                ISchematic <string, string> schematic,
                IStateMachine <string, string> machine,
                Status <string> status,
                InputParameters <string, TPayload> inputParameters,
                IReadOnlyDictionary <string, string> connectorSettings,
                CancellationToken cancellationToken = default)
            {
                // Processing

                // Move next
                await Task.WhenAll(
                    machine.SendAsync("Continue", cancellationToken),
                    machine.SendAsync("Complete", cancellationToken));
            }
        protected override Task OnMachineCreatedAsync <TState, TInput>(
            ISchematic <TState, TInput> schematic,
            MachineCreationEventData <TState> machineCreationEventData)
        {
            Logger.LogFormat(
                _loggingLevel,
                "Machine {machineId} created in state {state} with commit number of {commitNumber}.",
                machineCreationEventData.InitialStatus.MachineId,
                machineCreationEventData.InitialStatus.State,
                machineCreationEventData.InitialStatus.CommitNumber);

#if NET45
            return(Task.FromResult(0));
#else
            return(Task.CompletedTask);
#endif
        }
Exemple #15
0
        public static TConfiguration FindConfiguration <TConfiguration, TState, TInput>(
            this IEnumerable <TConfiguration> configurations,
            ISchematic <TState, TInput> schematic,
            Status <TState> status)
            where TConfiguration : IConnectorConfiguration
        {
            var connectorKey = schematic.FindConnectorKey(status.State);

            var configuration = configurations.SingleOrDefault(c => c.Identifier == connectorKey.Identifier);

            if (configuration == null)
            {
                throw new ConnectorConfigurationNotFoundException <TState, TInput>(schematic, status, connectorKey);
            }

            return(configuration);
        }
Exemple #16
0
 public async Task When_a_Machine_is_created_from_a_Schematic(ISchematic <TState, TInput> schematic)
 {
     try
     {
         CurrentMachine = await CurrentHost.Agent()
                          .GetStateEngine <TState, TInput>()
                          .CreateMachineAsync(schematic, new Dictionary <string, string>
         {
             ["Key1"] = "Value1",
             ["Key2"] = "Value2"
         });
     }
     catch (Exception ex)
     {
         CurrentException = ex;
     }
 }
Exemple #17
0
        private void NotifyBulkOnMachineCreated(
            ISchematic <TState, TInput> schematic,
            IEnumerable <MachineStatus <TState, TInput> > machineStatuses)
        {
#pragma warning disable 4014
            Task.Run(async() => await Task.WhenAll(
                         _listeners.Select(listener =>
                                           listener.MachineCreatedAsync(
                                               schematic,
                                               machineStatuses.Select(status =>
                                                                      new MachineCreationEventData <TState>(
                                                                          initialStatus: status,
                                                                          metadata: new ReadOnlyDictionary <string, string>(
                                                                              status.Metadata ?? new Dictionary <string, string>(0))
                                                                          )).ToList()))),
                     CancellationToken.None);
#pragma warning restore 4014
        }
Exemple #18
0
        internal REstateMachine(
            IConnectorResolver <TState, TInput> connectorResolver,
            IRepositoryContextFactory <TState, TInput> repositoryContextFactory,
            ICartographer <TState, TInput> cartographer,
            IEnumerable <IEventListener> listeners,
            string machineId,
            ISchematic <TState, TInput> schematic,
            IReadOnlyDictionary <string, string> metadata)
        {
            _connectorResolver        = connectorResolver;
            _repositoryContextFactory = repositoryContextFactory;
            _listeners = listeners.ToList();

            MachineId = machineId;

            CachedValues = new Lazy <Task <(ISchematic <TState, TInput> schematic, IReadOnlyDictionary <string, string> metadata)> >(
                () => Task.FromResult((schematic, metadata)));
        }
Exemple #19
0
        internal REstateMachine(
            IConnectorResolver <TState, TInput> connectorResolver,
            IRepositoryContextFactory <TState, TInput> repositoryContextFactory,
            ICartographer <TState, TInput> cartographer,
            IEnumerable <IEventListener> listeners,
            string machineId,
            ISchematic <TState, TInput> schematic,
            IReadOnlyDictionary <string, string> metadata)
        {
            _connectorResolver        = connectorResolver;
            _repositoryContextFactory = repositoryContextFactory;
            _metadata  = metadata;
            _listeners = listeners.ToList();

            MachineId = machineId;

            Schematic = schematic;
        }
        public virtual byte[] CreateMessageBytes <TPayload>(
            ISchematic <TState, TInput> schematic,
            IStateMachine <TState, TInput> machine,
            Status <TState> status,
            InputParameters <TInput, TPayload> inputParameters,
            IReadOnlyDictionary <string, string> connectorSettings,
            CancellationToken cancellationToken = default)
        {
            var message = new QueueMessage <TState, TInput, TPayload>
            {
                State        = status.State,
                CommitNumber = status.CommitNumber,
                MachineId    = status.MachineId,
                UpdatedTime  = status.UpdatedTime,
                Input        = inputParameters.Input,
                Payload      = inputParameters.Payload
            };

            return(LZ4MessagePackSerializer.Serialize(message, MessagePack.Resolvers.ContractlessStandardResolver.Instance));
        }
Exemple #21
0
        public IStateMachine <TState, TInput> ConstructFromSchematic(
            string machineId,
            ISchematic <TState, TInput> schematic,
            IReadOnlyDictionary <string, string> metadata)
        {
            if (schematic == null)
            {
                throw new ArgumentNullException(nameof(schematic));
            }

            var restateMachine = new REstateMachine <TState, TInput>(
                _connectorResolver,
                _repositoryContextFactory,
                _cartographer,
                _listeners,
                machineId,
                schematic,
                metadata);

            return(restateMachine);
        }
Exemple #22
0
        public async Task <ISchematic <TState, TInput> > GetSchematicAsync(CancellationToken cancellationToken = default)
        {
            if (_machineSchematic != null)
            {
                return(_machineSchematic);
            }

            var response = await _stateMachineService
                           .WithCancellationToken(cancellationToken)
                           .GetMachineSchematicAsync(new GetMachineSchematicRequest
            {
                MachineId = MachineId
            });

            _machineSchematic = MessagePackSerializer
                                .Deserialize <Schematic <TState, TInput> >(
                response.SchematicBytes,
                ContractlessStandardResolver.Instance);

            return(_machineSchematic);
        }
        protected override Task OnTransitionAsync <TState, TInput, TPayload>(
            ISchematic <TState, TInput> schematic,
            Status <TState> status,
            IReadOnlyDictionary <string, string> metadata,
            TInput input,
            TPayload payload)
        {
            Logger.LogFormat(
                _loggingLevel,
                "Machine {machineId} transitioned to {state} with input {input}.",
                status.MachineId,
                status.State,
                input,
                payload,
                status.CommitNumber);

#if NET45
            return(Task.FromResult(0));
#else
            return(Task.CompletedTask);
#endif
        }
        /// <summary>
        /// Measured time, invokes simulation completed event and logs simulation completed event.
        /// Simulation completed message: "Calculated *simulation name* simulation in *measured time*ms".
        /// </summary>
        /// <param name="schematic">Schematic for which to perform the simulation</param>
        /// <param name="simulationLogic">Action that is responsible for performing and saving simulation results</param>
        /// <param name="simulationName">Name to use in simulation ended message</param>
        /// <param name="simulationType">Type of the simulation, for simulation ended event purposes</param>
        private void SimulationRunWrapper(ISchematic schematic, Action <AdmittanceMatrixFactory> simulationLogic, string simulationName,
                                          SimulationType simulationType)
        {
            // Create a stopwatch to measure the duration of simulation
            Stopwatch watch = new Stopwatch();

            // Start measuring time
            watch.Start();

            // Create an admittance matrix factory and use it to invoke passed simulation logic
            simulationLogic(new AdmittanceMatrixFactory(schematic));

            // Stop time measurement
            watch.Stop();

            // Invoke simulation completed event
            SimulationCompleted?.Invoke(this, new SimulationCompletedEventArgs(simulationType));

            // Log the simulation time
            IoC.Log("Completed " + simulationName + $" in {watch.ElapsedMilliseconds}ms",
                    InfoLoggerMessageDuration.Short);
        }
Exemple #25
0
        private async Task InvokeAction(
            ISchematic <TState, TInput> schematic,
            Status <TState> status,
            IStateMachine <TState, TInput> machine,
            CancellationToken cancellationToken)
        {
            var initialAction = schematic.States[schematic.InitialState].Action;

            if (initialAction == null)
            {
                return;
            }

            var connector = ConnectorResolver.ResolveAction(initialAction.ConnectorKey);

            await connector.InvokeAsync <object>(
                schematic,
                machine,
                status,
                null,
                initialAction.Settings,
                cancellationToken);
        }
 /// <summary>
 /// Performs a full ACDC simulation with <see cref="IOpAmp"/> adjustment - every <see cref="IOpAmp"/> is operating in either active or
 /// saturated state so that its output voltage does not exceed its supply voltages.
 /// </summary>
 /// <param name="schematic"></param>
 public void ACDCFullCycleWithOpAmpAdjustment(ISchematic schematic) =>
 SimulationRunWrapper(schematic, (x) => FullCycleLogicWithOpAmpAdjustment(x, true), "ACDC Cycle with op-amp adjustment", SimulationType.AC);
 /// <summary>
 /// Performs an AC cycle simulation - simulation is running for one full period of lowest frequency source in the <paramref name="schematic"/>
 /// </summary>
 /// <param name="schematic"></param>
 public void ACFullCycleWithoutOpAmpAdjustment(ISchematic schematic) =>
 SimulationRunWrapper(schematic, (x) => FullCycleWithoutOpAmpAdjustment(x, false), "AC cycle without op-amp adjustment", SimulationType.AC);
 /// <summary>
 /// Performs a DC bias simulation of the circuit.
 /// </summary>
 /// <param name="schematic"></param>
 public void DCBias(ISchematic schematic) => SimulationRunWrapper(schematic, DCBiasLogic, "DC bias", SimulationType.DC);
Exemple #29
0
 public Task <ISchematic <TState, TInput> > StoreSchematicAsync(
     ISchematic <TState, TInput> schematic,
     CancellationToken cancellationToken = default)
 => StoreSchematicAsync(schematic.Clone(), cancellationToken);
Exemple #30
0
 public Task <IStateMachine <TState, TInput> > CreateMachineAsync(
     ISchematic <TState, TInput> schematic,
     string machineId,
     IDictionary <string, string> metadata = null,
     CancellationToken cancellationToken   = default)
 => CreateMachineAsync(schematic.Clone(), machineId, metadata, cancellationToken);