Esempio n. 1
0
        internal void Remove(Command command)
        {
            if (command == null || !m_commandTable.ContainsKey(command))
            {
                return;
            }

            LinkedListElement e = m_commandTable[command];

            m_commandTable.Remove(command);

            if (e.Equals(m_lastCommand))
            {
                m_lastCommand = e.GetPrevious();
            }
            if (e.Equals(m_firstCommand))
            {
                m_firstCommand = e.GetNext();
            }
            e.Remove();

            var requirements = command.GetRequirements();

            foreach (var requirement in requirements)
            {
                requirement.SetCurrentCommand(null);
            }

            command.Removed();
        }
Esempio n. 2
0
        /// <summary>
        /// Sets the default command.
        /// </summary>
        /// <remarks>If this is not called, or is called with null, then there will be no default
        /// command for the subsystem.
        /// <para/><b>WARNING:</b> This should <b>NOT</b> be called in a constructor if the 
        /// subsystem is a singleton.</remarks>
        /// <param name="command">The default command(or null if there should be none.</param>
        /// <exception cref="IllegalUseOfCommandException">If the command does not require the subsystem.</exception>
        protected internal void SetDefaultCommand(Command command)
        {
            if (command == null)
            {
                m_defaultCommand = null;
            }
            else
            {
                bool found = false;

                foreach (var s in command.GetRequirements())
                {
                    if (s.Equals(this))
                        found = true;
                }
                if (!found)
                {
                    throw new IllegalUseOfCommandException("A default command must require the subsystem");
                }
                m_defaultCommand = command;
            }

            if (Table != null)
            {
                if (m_defaultCommand != null)
                {
                    Table.PutBoolean("hasDefault", true);
                    Table.PutString("default", m_defaultCommand.Name);
                }
                else
                {
                    Table.PutBoolean("hasDefault", false);
                }
            }
        }
Esempio n. 3
0
        private void _Add(Command command)
        {
            if (command == null)
            {
                return;
            }
            if (m_adding)
            {
                Console.Error.WriteLine($"WARNING: Cannot start command from cancel method. Ignoring: {command}");
            }
            if (!m_commandTable.ContainsKey(command))
            {
                IEnumerable <Subsystem> requirements = command.GetRequirements();
                if (requirements.Any(subsystem => subsystem.GetCurrentCommand() != null && !subsystem.GetCurrentCommand().Interruptible))
                {
                    return;
                }

                m_adding     = true;
                requirements = command.GetRequirements();
                foreach (var subsystem in requirements)
                {
                    if (subsystem.GetCurrentCommand() != null)
                    {
                        subsystem.GetCurrentCommand().Cancel();
                        Remove(subsystem.GetCurrentCommand());
                    }
                    subsystem.SetCurrentCommand(command);
                }
                m_adding = false;

                LinkedListElement element = new LinkedListElement();
                element.SetData(command);
                if (m_firstCommand == null)
                {
                    m_firstCommand = m_lastCommand = element;
                }
                else
                {
                    m_lastCommand.Add(element);
                    m_lastCommand = element;
                }
                m_commandTable.Add(command, element);
                m_runningCommandsChanged = true;
                command.StartRunning();
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Creates a new <see cref="ConditionalCommand"/> with given onTrue and onFalse Commands.
        /// </summary>
        /// <param name="onTrue">Command to run when condition is true</param>
        /// <param name="onFalse">Command to run when condition is false</param>
        public ConditionalCommand(Command onTrue, Command onFalse)
        {
            m_onTrue  = onTrue;
            m_onFalse = onFalse;

            foreach (var sys in onTrue.GetRequirements())
            {
                Requires(sys);
            }
            foreach (var sys in onFalse.GetRequirements())
            {
                Requires(sys);
            }
        }
Esempio n. 5
0
 /// <summary>
 /// Adds a new <see cref="Command"/> to the group.
 /// </summary>
 /// <remarks>
 /// The <see cref="Command"/> will be started after all the previously added <see cref="Command">commands</see>.
 /// <para>
 /// Note that any requirements thee given <see cref="Command"/> has will be added to the group. For this reason, a 
 /// <see cref="Command">Command's</see> requirements cannot be changed after being added to a group.
 /// </para>
 /// <para>
 /// It is recommended that this method be called in the constructor.
 /// </para>
 /// </remarks>
 /// <param name="command">The <see cref="Command"/> to be added.</param>
 /// <exception cref="IllegalUseOfCommandException">If the command has been started before or been given to another group.</exception>
 /// <exception cref="ArgumentNullException">If the given <see cref="Command"/> is null</exception>
 public void AddSequential(Command command)
 {
     lock (m_syncRoot)
     {
         Validate("Can not add new command to command group");
         if (command == null)
             throw new ArgumentNullException(nameof(command), "Given null command");
         command.SetParent(this);
         m_commands.Add(new Entry(command, Entry.IN_SEQUENCE));
         foreach (var e in command.GetRequirements())
         {
             Requires(e);
         } 
     }
 }
Esempio n. 6
0
 private void CancelConflicts(Command command)
 {
     for (int i = 0; i < m_children.Count; i++)
     {
         Command child = m_children[i].command;
         foreach (var requirement in command.GetRequirements())
         {
             if (child.DoesRequire(requirement))
             {
                 child._Cancel();
                 child.Removed();
                 m_children.RemoveAt(i--);
             }
         }
     }
 }
Esempio n. 7
0
 /// <summary>
 /// Adds a new <see cref="Command"/> to the group.
 /// </summary>
 /// <remarks>
 /// The <see cref="Command"/> will be started after all the previously added <see cref="Command">commands</see>.
 /// <para>
 /// Note that any requirements thee given <see cref="Command"/> has will be added to the group. For this reason, a
 /// <see cref="Command">Command's</see> requirements cannot be changed after being added to a group.
 /// </para>
 /// <para>
 /// It is recommended that this method be called in the constructor.
 /// </para>
 /// </remarks>
 /// <param name="command">The <see cref="Command"/> to be added.</param>
 /// <exception cref="IllegalUseOfCommandException">If the command has been started before or been given to another group.</exception>
 /// <exception cref="ArgumentNullException">If the given <see cref="Command"/> is null</exception>
 public void AddSequential(Command command)
 {
     lock (m_syncRoot)
     {
         Validate("Can not add new command to command group");
         if (command == null)
         {
             throw new ArgumentNullException(nameof(command), "Given null command");
         }
         command.SetParent(this);
         m_commands.Add(new Entry(command, Entry.IN_SEQUENCE));
         foreach (var e in command.GetRequirements())
         {
             Requires(e);
         }
     }
 }
Esempio n. 8
0
 /// <summary>
 /// Adds a new <see cref="Command"/> to the group.
 /// </summary>
 /// <remarks>
 /// The <see cref="Command"/> will be started after all the previously added <see cref="Command">commands</see>.
 /// <para>
 /// Instead of waiting for the child to finish, a <see cref="CommandGroup"/> will have it run
 /// at the same time as the subsequent <see cref="Command">Commands</see>. The child wil run
 /// either until it finishes, a new child with conflicting requirements is started, or the main
 /// sequence runs a <see cref="Command"/> with conflicting requirements. In the latter two cases,
 /// the child will be canceled even if it says it can't be interrupted.
 /// </para>
 /// <para>
 /// Note that any requirements thee given <see cref="Command"/> has will be added to the group. For this reason, a
 /// <see cref="Command">Command's</see> requirements cannot be changed after being added to a group.
 /// </para>
 /// <para>
 /// It is recommended that this method be called in the constructor.
 /// </para>
 /// </remarks>
 /// <param name="command">The <see cref="Command"/> to be added.</param>
 /// <exception cref="IllegalUseOfCommandException">If the command has been started before or been given to another group.</exception>
 /// <exception cref="ArgumentNullException">If the given <see cref="Command"/> is null</exception>
 public void AddParallel(Command command)
 {
     lock (m_syncRoot)
     {
         Validate("Can not add new command to command group");
         if (command == null)
         {
             throw new ArgumentNullException(nameof(command), "Given null command");
         }
         command.SetParent(this);
         m_commands.Add(new Entry(command, Entry.BRANCH_CHILD));
         foreach (Subsystem e in command.GetRequirements())
         {
             Requires(e);
         }
     }
 }
Esempio n. 9
0
 /// <summary>
 /// Adds a new <see cref="Command"/> to the group with a given timeout.
 /// </summary>
 /// <remarks>
 /// The <see cref="Command"/> will be started after all the previously added <see cref="Command">commands</see>.
 /// <para>
 /// Once the <see cref="Command"/> is started, it will be run until it finishes or the time expires, whichever is sooner.
 /// Note that the give <see cref="Command"/> will have no knowledge that it is on a timer.
 /// </para>
 /// <para>
 /// Note that any requirements thee given <see cref="Command"/> has will be added to the group. For this reason, a
 /// <see cref="Command">Command's</see> requirements cannot be changed after being added to a group.
 /// </para>
 /// <para>
 /// It is recommended that this method be called in the constructor.
 /// </para>
 /// </remarks>
 /// <param name="command">The <see cref="Command"/> to be added.</param>
 /// <param name="timeout">The timeout (in seconds).</param>
 /// <exception cref="IllegalUseOfCommandException">If the group has been started before or been given to another group.</exception>
 /// <exception cref="ArgumentNullException">If the given <see cref="Command"/> is null</exception>
 /// <exception cref="ArgumentOutOfRangeException">If the given timeout is negative.</exception>
 public void AddSequential(Command command, double timeout)
 {
     lock (m_syncRoot)
     {
         Validate("Can not add new command to command group");
         if (command == null)
         {
             throw new ArgumentNullException(nameof(command), "Given null command");
         }
         if (timeout < 0)
         {
             throw new ArgumentOutOfRangeException(nameof(timeout), "Can not be given a negative timeout");
         }
         command.SetParent(this);
         m_commands.Add(new Entry(command, Entry.IN_SEQUENCE, timeout));
         foreach (Subsystem e in command.GetRequirements())
         {
             Requires(e);
         }
     }
 }
Esempio n. 10
0
        /// <summary>
        /// Sets the default command.
        /// </summary>
        /// <remarks>If this is not called, or is called with null, then there will be no default
        /// command for the subsystem.
        /// <para/><b>WARNING:</b> This should <b>NOT</b> be called in a constructor if the
        /// subsystem is a singleton.</remarks>
        /// <param name="command">The default command(or null if there should be none.</param>
        /// <exception cref="IllegalUseOfCommandException">If the command does not require the subsystem.</exception>
        protected internal void SetDefaultCommand(Command command)
        {
            if (command == null)
            {
                m_defaultCommand = null;
            }
            else
            {
                bool found = false;

                foreach (var s in command.GetRequirements())
                {
                    if (s.Equals(this))
                    {
                        found = true;
                    }
                }
                if (!found)
                {
                    throw new IllegalUseOfCommandException("A default command must require the subsystem");
                }
                m_defaultCommand = command;
            }

            if (Table != null)
            {
                if (m_defaultCommand != null)
                {
                    Table.PutBoolean("hasDefault", true);
                    Table.PutString("default", m_defaultCommand.Name);
                }
                else
                {
                    Table.PutBoolean("hasDefault", false);
                }
            }
        }
Esempio n. 11
0
 private void CancelConflicts(Command command)
 {
     for (int i = 0; i < m_children.Count; i++)
     {
         Command child = m_children[i].command;
         foreach (var requirement in command.GetRequirements())
         {
             if (child.DoesRequire(requirement))
             {
                 child._Cancel();
                 child.Removed();
                 m_children.RemoveAt(i--);
             }
         }
     }
 }
Esempio n. 12
0
        /// <summary>
        /// Adds a new <see cref="Command"/> to the group with the given timeout.
        /// </summary>
        /// <remarks>
        /// The <see cref="Command"/> will be started after all the previously added <see cref="Command">commands</see>.
        /// /// <para>
        /// Once the <see cref="Command"/> is started, it will be run until it finishes or the time expires, whichever is sooner.
        /// Note that the give <see cref="Command"/> will have no knowledge that it is on a timer.
        /// </para>
        /// <para>
        /// Instead of waiting for the child to finish, a <see cref="CommandGroup"/> will have it run
        /// at the same time as the subsequent <see cref="Command">Commands</see>. The child wil run
        /// either until it finishes, a new child with conflicting requirements is started, or the main
        /// sequence runs a <see cref="Command"/> with conflicting requirements. In the latter two cases,
        /// the child will be canceled even if it says it can't be interrupted.
        /// </para>
        /// <para>
        /// Note that any requirements thee given <see cref="Command"/> has will be added to the group. For this reason, a 
        /// <see cref="Command">Command's</see> requirements cannot be changed after being added to a group.
        /// </para>
        /// <para>
        /// It is recommended that this method be called in the constructor.
        /// </para>
        /// </remarks>
        /// <param name="command">The <see cref="Command"/> to be added.</param>
        /// <param name="timeout">The timeout (in seconds).</param>
        /// <exception cref="IllegalUseOfCommandException">If the command has been started before or been given to another group.</exception>
        /// <exception cref="ArgumentNullException">If the given <see cref="Command"/> is null</exception>
        /// <exception cref="ArgumentOutOfRangeException">If the given timeout is negative.</exception>
        public void AddParallel(Command command, double timeout)
        {
            lock (m_syncRoot)
            {

                Validate("Can not add new command to command group");
                if (command == null)
                    throw new ArgumentNullException(nameof(command), "Given null command");
                if (timeout < 0)
                    throw new ArgumentOutOfRangeException(nameof(command), "Can not be given a negative timeout");
                command.SetParent(this);

                m_commands.Add(new Entry(command, Entry.BRANCH_CHILD, timeout));
                foreach (Subsystem e in command.GetRequirements())
                {
                    Requires(e);
                } 
            }
        }
Esempio n. 13
0
        private void _Add(Command command)
        {
            if (command == null)
            {
                return;
            }
            if (m_adding)
            {
                Console.Error.WriteLine($"WARNING: Cannot start command from cancel method. Ignoring: {command}");
            }

            if (!m_activeCommands.Contains(command))
            {
                var requirements = command.GetRequirements();

                var currentCommands = requirements.Select(subsystem => subsystem.GetCurrentCommand())
                                                  .Where(x => x != null);

                // If there are any non-interruptible commands on the subsystems required for this command
                if (currentCommands.Any(cmd => !cmd.Interruptible))
                {
                    return;
                }

                m_adding = true;

                foreach (var subsystem in requirements)
                {
                    if (subsystem.GetCurrentCommand() != null)
                    {
                        subsystem.GetCurrentCommand().Cancel();
                        Remove(subsystem.GetCurrentCommand());
                    }
                    subsystem.SetCurrentCommand(command);
                }

                m_adding = false;

                m_activeCommands.Add(command);
                m_runningCommandsChanged = true;
                command.StartRunning();
            }
        }
Esempio n. 14
0
        internal void Remove(Command command)
        {
            if (command == null || !m_activeCommands.Contains(command))
            {
                return;
            }

            m_activeCommands.Remove(command);

            foreach (var requirement in command.GetRequirements())
            {
                requirement.SetCurrentCommand(null);
            }

            command.Removed();
        }
Esempio n. 15
0
        private void _Add(Command command)
        {
            if (command == null)
            {
                return;
            }
            if (m_adding)
            {
                Console.Error.WriteLine($"WARNING: Cannot start command from cancel method. Ignoring: {command}");
            }
            if (!m_commandTable.ContainsKey(command))
            {
                IEnumerable<Subsystem> requirements = command.GetRequirements();
                if (requirements.Any(subsystem => subsystem.GetCurrentCommand() != null && !subsystem.GetCurrentCommand().Interruptible))
                {
                    return;
                }

                m_adding = true;
                requirements = command.GetRequirements();
                foreach (var subsystem in requirements)
                {
                    if (subsystem.GetCurrentCommand() != null)
                    {
                        subsystem.GetCurrentCommand().Cancel();
                        Remove(subsystem.GetCurrentCommand());
                    }
                    subsystem.SetCurrentCommand(command);
                }
                m_adding = false;

                LinkedListElement element = new LinkedListElement();
                element.SetData(command);
                if (m_firstCommand == null)
                {
                    m_firstCommand = m_lastCommand = element;
                }
                else
                {
                    m_lastCommand.Add(element);
                    m_lastCommand = element;
                }
                m_commandTable.Add(command, element);
                m_runningCommandsChanged = true;
                command.StartRunning();
            }
        }
Esempio n. 16
0
        internal void Remove(Command command)
        {
            if (command == null || !m_commandTable.ContainsKey(command))
            {
                return;
            }

            LinkedListElement e = m_commandTable[command];
            m_commandTable.Remove(command);

            if (e.Equals(m_lastCommand))
            {
                m_lastCommand = e.GetPrevious();
            }
            if (e.Equals(m_firstCommand))
            {
                m_firstCommand = e.GetNext();
            }
            e.Remove();

            var requirements = command.GetRequirements();
            foreach (var requirement in requirements)
            {
                requirement.SetCurrentCommand(null);
            }

            command.Removed();
        }