Пример #1
0
        public void ContinuesAfterFailure()
        {
            // three children: failure, success, and another
            // index should continue after failure and tick success
            // index should restart after success and failure should be ticked again
            // a successful fallback should halt all children
            var failure = new ReturnXNode(NodeStatus.FAILURE);
            var success = new ReturnXNode(NodeStatus.SUCCESS);
            var other   = new ReturnXNode(NodeStatus.SUCCESS);
            var node    = new FallbackNode(new List <INode>
            {
                failure,
                success,
                other,
            });

            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.SUCCESS));
            Assert.That(failure.Ticks, Is.EqualTo(1));
            Assert.That(success.Ticks, Is.EqualTo(1));
            Assert.That(other.Ticks, Is.EqualTo(0));
            Assert.That(failure.Halts, Is.EqualTo(1));
            Assert.That(success.Halts, Is.EqualTo(1));
            Assert.That(other.Halts, Is.EqualTo(1));

            status = node.Tick();
            Assert.That(status, Is.EqualTo(NodeStatus.SUCCESS));
            Assert.That(failure.Ticks, Is.EqualTo(2));
            Assert.That(success.Ticks, Is.EqualTo(2));
            Assert.That(other.Ticks, Is.EqualTo(0));
            Assert.That(failure.Halts, Is.EqualTo(2));
            Assert.That(success.Halts, Is.EqualTo(2));
            Assert.That(other.Halts, Is.EqualTo(2));
        }
        public void ResumesFromRunning()
        {
            // three children: failure, running, other
            // index should continue after failure and tick running
            // index should not restart after running and failure should not be ticked again
            // halts should not be called on incomplete fallbacks
            var failure = new ReturnXNode(NodeStatus.FAILURE);
            var running = new ReturnXNode(NodeStatus.RUNNING);
            var other   = new ReturnXNode(NodeStatus.SUCCESS);
            var node    = new FallbackWithMemoryNode(new List <INode>
            {
                failure,
                running,
                other,
            });

            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.RUNNING));
            Assert.That(failure.Ticks, Is.EqualTo(1));
            Assert.That(running.Ticks, Is.EqualTo(1));
            Assert.That(other.Ticks, Is.EqualTo(0));
            Assert.That(failure.Halts, Is.EqualTo(0));
            Assert.That(running.Halts, Is.EqualTo(0));
            Assert.That(other.Halts, Is.EqualTo(0));

            status = node.Tick();
            Assert.That(status, Is.EqualTo(NodeStatus.RUNNING));
            Assert.That(failure.Ticks, Is.EqualTo(1));
            Assert.That(running.Ticks, Is.EqualTo(2));
            Assert.That(other.Ticks, Is.EqualTo(0));
            Assert.That(failure.Halts, Is.EqualTo(0));
            Assert.That(running.Halts, Is.EqualTo(0));
            Assert.That(other.Halts, Is.EqualTo(0));
        }
Пример #3
0
        public void ContinuesAfterSuccess()
        {
            // three children: success, failure, other
            // index should continue after success and tick failure
            // index should restart after failure and success should be ticked again
            // halt should be called on all children after each failure
            var alwaysSuccessChild = new ReturnXNode(NodeStatus.SUCCESS);
            var alwaysFailureChild = new ReturnXNode(NodeStatus.FAILURE);
            var otherChild         = new ReturnXNode(NodeStatus.SUCCESS);
            var node = new SequenceNode(new List <INode>
            {
                alwaysSuccessChild,
                alwaysFailureChild,
                otherChild,
            });

            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.FAILURE));
            Assert.That(alwaysSuccessChild.Ticks, Is.EqualTo(1));
            Assert.That(alwaysFailureChild.Ticks, Is.EqualTo(1));
            Assert.That(otherChild.Ticks, Is.EqualTo(0));
            Assert.That(alwaysSuccessChild.Halts, Is.EqualTo(1));
            Assert.That(alwaysFailureChild.Halts, Is.EqualTo(1));
            Assert.That(otherChild.Halts, Is.EqualTo(1));

            status = node.Tick();
            Assert.That(status, Is.EqualTo(NodeStatus.FAILURE));
            Assert.That(alwaysSuccessChild.Ticks, Is.EqualTo(2));
            Assert.That(alwaysFailureChild.Ticks, Is.EqualTo(2));
            Assert.That(otherChild.Ticks, Is.EqualTo(0));
            Assert.That(alwaysSuccessChild.Halts, Is.EqualTo(2));
            Assert.That(alwaysFailureChild.Halts, Is.EqualTo(2));
            Assert.That(otherChild.Halts, Is.EqualTo(2));
        }
Пример #4
0
        public void RestartsAfterRunning()
        {
            // three children: success, running, other
            // index should continue after success and tick running
            // index should restart after running, and success should be ticked again
            // halts should not be called on incomplete sequences
            var success = new ReturnXNode(NodeStatus.SUCCESS);
            var running = new ReturnXNode(NodeStatus.RUNNING);
            var other   = new ReturnXNode(NodeStatus.SUCCESS);
            var node    = new SequenceNode(new List <INode>
            {
                success,
                running,
                other,
            });

            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.RUNNING));
            Assert.That(success.Ticks, Is.EqualTo(1));
            Assert.That(running.Ticks, Is.EqualTo(1));
            Assert.That(other.Ticks, Is.EqualTo(0));
            Assert.That(success.Halts, Is.EqualTo(0));
            Assert.That(running.Halts, Is.EqualTo(0));
            Assert.That(other.Halts, Is.EqualTo(0));

            status = node.Tick();
            Assert.That(status, Is.EqualTo(NodeStatus.RUNNING));
            Assert.That(success.Ticks, Is.EqualTo(2));
            Assert.That(running.Ticks, Is.EqualTo(2));
            Assert.That(other.Ticks, Is.EqualTo(0));
            Assert.That(success.Halts, Is.EqualTo(0));
            Assert.That(running.Halts, Is.EqualTo(0));
            Assert.That(other.Halts, Is.EqualTo(0));
        }
Пример #5
0
        public void HaltChildCallsChildHalt()
        {
            var children = new ReturnXNode[]
            {
                new ReturnXNode(NodeStatus.SUCCESS),
                new ReturnXNode(NodeStatus.FAILURE),
                new ReturnXNode(NodeStatus.RUNNING),
            };

            var node = new ReturnXControlNode(NodeStatus.SUCCESS, children);

            // halt each child in turn, assert no other halts were called
            for (int haltIndex = 0; haltIndex < children.Length; haltIndex++)
            {
                node.HaltChild(haltIndex);

                for (int i = 0; i < children.Length; i++)
                {
                    var child = children[i];
                    if (i <= haltIndex)
                    {
                        Assert.That(child.Halts, Is.EqualTo(1));
                    }
                    else
                    {
                        Assert.That(child.Halts, Is.EqualTo(0));
                    }
                }
            }
        }
        public void RestartsAfterSuccess()
        {
            // three children: failure, success, other
            // index should continue after failure and tick success
            // index should restart after success and failure should be ticked again
            // halt should be called on all children after each success
            var failure = new ReturnXNode(NodeStatus.FAILURE);
            var success = new ReturnXNode(NodeStatus.SUCCESS);
            var other   = new ReturnXNode(NodeStatus.SUCCESS);
            var node    = new FallbackWithMemoryNode(new List <INode>
            {
                failure,
                success,
                other,
            });

            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.SUCCESS));
            Assert.That(failure.Ticks, Is.EqualTo(1));
            Assert.That(success.Ticks, Is.EqualTo(1));
            Assert.That(other.Ticks, Is.EqualTo(0));
            Assert.That(success.Halts, Is.EqualTo(1));
            Assert.That(failure.Halts, Is.EqualTo(1));
            Assert.That(other.Halts, Is.EqualTo(1));

            status = node.Tick();
            Assert.That(status, Is.EqualTo(NodeStatus.SUCCESS));
            Assert.That(failure.Ticks, Is.EqualTo(2));
            Assert.That(success.Ticks, Is.EqualTo(2));
            Assert.That(other.Ticks, Is.EqualTo(0));
            Assert.That(success.Halts, Is.EqualTo(2));
            Assert.That(failure.Halts, Is.EqualTo(2));
            Assert.That(other.Halts, Is.EqualTo(2));
        }
        public void ResumesFromRunning()
        {
            // three children: success, running, other
            // index should continue after success and tick running
            // index should not restart after running and success should not be ticked again
            // halts should not be called on incomplete sequences
            var alwaysSuccessChild = new ReturnXNode(NodeStatus.SUCCESS);
            var alwaysRunningChild = new ReturnXNode(NodeStatus.RUNNING);
            var otherChild         = new ReturnXNode(NodeStatus.SUCCESS);
            var node = new SequenceWithMemoryNode(new List <INode>
            {
                alwaysSuccessChild,
                alwaysRunningChild,
                otherChild,
            });

            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.RUNNING));
            Assert.That(alwaysSuccessChild.Ticks, Is.EqualTo(1));
            Assert.That(alwaysRunningChild.Ticks, Is.EqualTo(1));
            Assert.That(otherChild.Ticks, Is.EqualTo(0));
            Assert.That(alwaysSuccessChild.Halts, Is.EqualTo(0));
            Assert.That(alwaysRunningChild.Halts, Is.EqualTo(0));
            Assert.That(otherChild.Halts, Is.EqualTo(0));

            status = node.Tick();
            Assert.That(status, Is.EqualTo(NodeStatus.RUNNING));
            Assert.That(alwaysSuccessChild.Ticks, Is.EqualTo(1));
            Assert.That(alwaysRunningChild.Ticks, Is.EqualTo(2));
            Assert.That(otherChild.Ticks, Is.EqualTo(0));
            Assert.That(alwaysSuccessChild.Halts, Is.EqualTo(0));
            Assert.That(alwaysRunningChild.Halts, Is.EqualTo(0));
            Assert.That(otherChild.Halts, Is.EqualTo(0));
        }
        public void HaltCallsChildHalt()
        {
            var child = new ReturnXNode(NodeStatus.FAILURE);
            var node  = new RepeatUntilFailureNode(child);

            node.Halt();
            Assert.That(child.Halts, Is.EqualTo(1));
        }
Пример #9
0
        public void RunningChildReturnsRunning()
        {
            var child  = new ReturnXNode(NodeStatus.RUNNING);
            var node   = new InverterNode(child);
            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.RUNNING));
        }
        public void ReturnsAppropriateStatus(NodeStatus expectedChildStatus, NodeStatus expectedParentStatus)
        {
            var child  = new ReturnXNode(expectedChildStatus);
            var node   = new RepeatUntilFailureNode(child);
            var status = node.Tick();

            Assert.That(status, Is.EqualTo(expectedParentStatus));
        }
        public void HaltsOnChildFailure()
        {
            var child  = new ReturnXNode(NodeStatus.FAILURE);
            var node   = new RepeatUntilFailureNode(child);
            var status = node.Tick();

            Assert.That(child.Halts, Is.EqualTo(1));
        }
Пример #12
0
        public void ReturnsSuccessImmediately()
        {
            var n      = new InMemoryVariable <int>(0);
            var child  = new ReturnXNode(NodeStatus.SUCCESS);
            var node   = new RetryNode(child, n);
            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.SUCCESS));
            Assert.That(child.Ticks, Is.EqualTo(1));
        }
Пример #13
0
        public void HaltsAfterSuccess()
        {
            var n      = new InMemoryVariable <int>(0);
            var child  = new ReturnXNode(NodeStatus.SUCCESS);
            var node   = new RetryNode(child, n);
            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.SUCCESS));
            Assert.That(child.Halts, Is.EqualTo(1));
        }
Пример #14
0
        public void HaltsAfterFailure()
        {
            var n      = new InMemoryVariable <int>(0);
            var child  = new ReturnXNode(NodeStatus.FAILURE);
            var node   = new RetryNode(child, n);
            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.FAILURE));
            Assert.That(child.Halts, Is.EqualTo(1));
        }
Пример #15
0
        public void ReturnsFailureImmediately()
        {
            var n      = new InMemoryVariable <int>(0);
            var child  = new ReturnXNode(NodeStatus.FAILURE);
            var node   = new RepeatNode(child, n);
            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.FAILURE));
            Assert.That(child.Ticks, Is.EqualTo(1));
        }
        public void TicksChildOncePerTick(int n)
        {
            var child = new ReturnXNode(NodeStatus.SUCCESS);
            var node  = new RepeatUntilFailureNode(child);

            for (int i = 0; i < n; i++)
            {
                node.Tick();
            }

            Assert.That(child.Ticks, Is.EqualTo(n));
        }
Пример #17
0
        public void ReturnsX([Values] NodeStatus childStatus, [Values] NodeStatus expectedStatus)
        {
            // always ignores childStatus and simply returns expectedStatus
            var child = new ReturnXNode(childStatus);
            var node  = new ReturnXControlNode(expectedStatus, new INode[]
            {
                child,
            });

            var actualStatus = node.Tick();

            Assert.That(actualStatus, Is.EqualTo(expectedStatus));
        }
Пример #18
0
        public void TicksChild(NodeStatus expectedStatus, int expectedTicks)
        {
            var child = new ReturnXNode(expectedStatus);
            var node  = new ForwardToChildNode(child);

            Assert.That(child.Ticks, Is.EqualTo(0));
            for (int i = 0; i < expectedTicks; i++)
            {
                var status = node.Tick();
            }

            Assert.That(child.Ticks, Is.EqualTo(expectedTicks));
        }
Пример #19
0
        public void HaltsChild(int expectedHalts)
        {
            var child = new ReturnXNode(NodeStatus.SUCCESS);
            var node  = new ForwardToChildNode(child);

            Assert.That(child.Halts, Is.EqualTo(0));
            for (int i = 0; i < expectedHalts; i++)
            {
                node.Halt();
            }

            Assert.That(node.Halts, Is.EqualTo(expectedHalts));
            Assert.That(child.Halts, Is.EqualTo(expectedHalts));
        }
Пример #20
0
        public void DoesNotHaltAfterRunning(int n)
        {
            var child = new ReturnXNode(NodeStatus.RUNNING);
            var node  = new RetryNode(child, new InMemoryVariable <int>(n));

            for (int i = 0; i < n; i++)
            {
                var status = node.Tick();
                Assert.That(status, Is.EqualTo(NodeStatus.RUNNING));
            }

            Assert.That(child.Ticks, Is.EqualTo(n));
            Assert.That(child.Halts, Is.EqualTo(0));
        }
Пример #21
0
        public void RunningAfterHaltAfterRunningDoesNotHaltPreviouslyChildren()
        {
            // four children: flip_flop, failure, running, and other
            // the fallback is ticked, halted, and ticked
            // flip_flop will return failure on the first tick, running on the second tick
            // normally, after flip_flop returns running, failure and running should be halted
            // since the fallback is halted between the first and second tick, they should not be halted
            var flip_flop = new ReturnStatusFromCollectionNode(NodeStatus.FAILURE, NodeStatus.RUNNING);
            var failure   = new ReturnXNode(NodeStatus.FAILURE);
            var running   = new ReturnXNode(NodeStatus.RUNNING);
            var other     = new ReturnXNode(NodeStatus.SUCCESS);
            var node      = new FallbackNode(new List <INode>
            {
                flip_flop,
                failure,
                running,
                other,
            });

            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.RUNNING));
            Assert.That(flip_flop.Ticks, Is.EqualTo(1));
            Assert.That(failure.Ticks, Is.EqualTo(1));
            Assert.That(running.Ticks, Is.EqualTo(1));
            Assert.That(other.Ticks, Is.EqualTo(0));
            Assert.That(flip_flop.Halts, Is.EqualTo(0));
            Assert.That(failure.Halts, Is.EqualTo(0));
            Assert.That(running.Halts, Is.EqualTo(0));
            Assert.That(other.Halts, Is.EqualTo(0));

            node.Halt();
            Assert.That(flip_flop.Halts, Is.EqualTo(1));
            Assert.That(failure.Halts, Is.EqualTo(1));
            Assert.That(running.Halts, Is.EqualTo(1));
            Assert.That(other.Halts, Is.EqualTo(1));

            // prime flip_flop so that it's next tick, the one from fallback, is running
            flip_flop.Tick();

            status = node.Tick();
            Assert.That(status, Is.EqualTo(NodeStatus.RUNNING));
            Assert.That(flip_flop.Ticks, Is.EqualTo(3)); // two from fallback, one from primer
            Assert.That(failure.Ticks, Is.EqualTo(1));
            Assert.That(running.Ticks, Is.EqualTo(1));
            Assert.That(flip_flop.Halts, Is.EqualTo(1));
            Assert.That(failure.Halts, Is.EqualTo(1));
            Assert.That(running.Halts, Is.EqualTo(1));
            Assert.That(other.Halts, Is.EqualTo(1));
        }
Пример #22
0
        public void ReturnsSuccessAfterNSuccesses(int n)
        {
            var child = new ReturnXNode(NodeStatus.SUCCESS);
            var node  = new RepeatNode(child, new InMemoryVariable <int>(n));

            for (int i = 0; i < n; i++)
            {
                Assert.That(node.Tick(), Is.EqualTo(NodeStatus.RUNNING));
            }

            Assert.That(node.Tick(), Is.EqualTo(NodeStatus.SUCCESS));

            // ticked once at the beginning and once more for every tick that returned success until n
            Assert.That(child.Ticks, Is.EqualTo(n + 1));
        }
Пример #23
0
        public void HaltsChild(int expectedHalts)
        {
            // ForwardToChild simply calls the base class halt (DecoratorNode)
            // the default implementation should call the child's halt
            var child = new ReturnXNode(NodeStatus.SUCCESS);
            var node  = new ForwardToChildNode(child);

            Assert.That(child.Halts, Is.EqualTo(0));
            for (int i = 0; i < expectedHalts; i++)
            {
                node.Halt();
            }

            Assert.That(child.Halts, Is.EqualTo(expectedHalts));
        }
Пример #24
0
        public void ReturnsFailureAfterNFailures(int n)
        {
            var child = new ReturnXNode(NodeStatus.FAILURE);
            var node  = new RetryNode(child, new InMemoryVariable <int>(n));

            for (int i = 0; i < n; i++)
            {
                Assert.That(node.Tick(), Is.EqualTo(NodeStatus.RUNNING));
            }

            Assert.That(node.Tick(), Is.EqualTo(NodeStatus.FAILURE));

            // ticked once at the beginning and once more for every tick that returned failure until n
            Assert.That(child.Ticks, Is.EqualTo(n + 1));
        }
Пример #25
0
        public void RepeatedRunningDoesNotHalt()
        {
            // two children: success and running
            // both nodes should not be halted
            var success = new ReturnXNode(NodeStatus.SUCCESS);
            var running = new ReturnXNode(NodeStatus.RUNNING);
            var node    = new SequenceNode(new List <INode>
            {
                success,
                running,
            });

            node.Tick();
            node.Tick();

            Assert.That(success.Ticks, Is.EqualTo(2));
            Assert.That(running.Ticks, Is.EqualTo(2));
            Assert.That(success.Halts, Is.EqualTo(0));
            Assert.That(running.Halts, Is.EqualTo(0));
        }
Пример #26
0
        public void RepeatedRunningDoesNotHalt()
        {
            // two children: failure and running
            // both nodes should not be halted
            var failure = new ReturnXNode(NodeStatus.FAILURE);
            var running = new ReturnXNode(NodeStatus.RUNNING);
            var node    = new FallbackNode(new List <INode>
            {
                failure,
                running,
            });

            node.Tick();
            node.Tick();

            Assert.That(failure.Ticks, Is.EqualTo(2));
            Assert.That(running.Ticks, Is.EqualTo(2));
            Assert.That(failure.Halts, Is.EqualTo(0));
            Assert.That(running.Halts, Is.EqualTo(0));
        }
Пример #27
0
        public void HaltsChildrenAfterNewChildReturnsRunning()
        {
            // four children: flip_flop, failure, running, and other
            // flip_flop returns failure on its first tick, running on its second tick
            // after flip_flop returns running, failure and running should be halted
            // after flip_flop returns running, other should not be halted
            // after flip_flop returns running, flip_flop should not be halted
            var flip_flop = new ReturnStatusFromCollectionNode(NodeStatus.FAILURE, NodeStatus.RUNNING);
            var failure   = new ReturnXNode(NodeStatus.FAILURE);
            var running   = new ReturnXNode(NodeStatus.RUNNING);
            var other     = new ReturnXNode(NodeStatus.SUCCESS);
            var node      = new FallbackNode(new List <INode>
            {
                flip_flop,
                failure,
                running,
                other,
            });

            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.RUNNING));
            Assert.That(flip_flop.Ticks, Is.EqualTo(1));
            Assert.That(failure.Ticks, Is.EqualTo(1));
            Assert.That(running.Ticks, Is.EqualTo(1));
            Assert.That(other.Ticks, Is.EqualTo(0));
            Assert.That(flip_flop.Halts, Is.EqualTo(0));
            Assert.That(failure.Halts, Is.EqualTo(0));
            Assert.That(running.Halts, Is.EqualTo(0));
            Assert.That(other.Halts, Is.EqualTo(0));

            status = node.Tick();
            Assert.That(status, Is.EqualTo(NodeStatus.RUNNING));
            Assert.That(flip_flop.Ticks, Is.EqualTo(2));
            Assert.That(failure.Ticks, Is.EqualTo(1));
            Assert.That(running.Ticks, Is.EqualTo(1));
            Assert.That(flip_flop.Halts, Is.EqualTo(0));
            Assert.That(failure.Halts, Is.EqualTo(1));
            Assert.That(running.Halts, Is.EqualTo(1));
            Assert.That(other.Halts, Is.EqualTo(0));
        }
Пример #28
0
        public void ChildrenAfterRunningNotTicked()
        {
            // two children: running and another
            // other should not be ticked
            // a running fallback should not halt any children yet
            var running = new ReturnXNode(NodeStatus.RUNNING);
            var other   = new ReturnXNode(NodeStatus.SUCCESS);
            var node    = new FallbackNode(new List <INode>
            {
                running,
                other,
            });

            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.RUNNING));
            Assert.That(running.Ticks, Is.EqualTo(1));
            Assert.That(other.Ticks, Is.EqualTo(0));
            Assert.That(running.Halts, Is.EqualTo(0));
            Assert.That(other.Halts, Is.EqualTo(0));
        }
        public void ChildrenAfterSuccessNotTicked()
        {
            // two children, one that always succeeds and another
            // the other should never be ticked
            // halt should be called on all children after a success
            var success = new ReturnXNode(NodeStatus.SUCCESS);
            var other   = new ReturnXNode(NodeStatus.SUCCESS);
            var node    = new FallbackWithMemoryNode(new List <INode>
            {
                success,
                other,
            });

            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.SUCCESS));
            Assert.That(success.Ticks, Is.EqualTo(1));
            Assert.That(other.Ticks, Is.EqualTo(0));
            Assert.That(success.Halts, Is.EqualTo(1));
            Assert.That(other.Halts, Is.EqualTo(1));
        }
        public void ChildrenAfterRunningNotTicked()
        {
            // two children, one that returns running and another
            // the other should never be ticked
            // since the fallback is incomplete, halt should not be called yet
            var running = new ReturnXNode(NodeStatus.RUNNING);
            var other   = new ReturnXNode(NodeStatus.SUCCESS);
            var node    = new FallbackWithMemoryNode(new List <INode>
            {
                running,
                other,
            });

            var status = node.Tick();

            Assert.That(status, Is.EqualTo(NodeStatus.RUNNING));
            Assert.That(running.Ticks, Is.EqualTo(1));
            Assert.That(other.Ticks, Is.EqualTo(0));
            Assert.That(running.Halts, Is.EqualTo(0));
            Assert.That(other.Halts, Is.EqualTo(0));
        }