public IReport GenerateDirectionReport()
        {
            LineReport dirReport = new LineReport(this.EventMgr.CurrentClock, (XYDoubleLocation)this.Location,
                (XYDoubleLocation)this.nextHopCheat, 0, -250, true, -this.id);

            dirReport.Color = ColorEnum.Priority;
            dirReport.IsArrow = true;

            return dirReport;
        }
        private void updateRoutingTable()
        {
            List<VarID> sinkList = new List<VarID>(); // ONE route to each sink...

            _tableRouting.Clear();  // Start fresh. This list is a factor of valid data elsewhere.

            // Get all valid sink IDs
            foreach (PEQTableEntrySubscription subEntry in _tableSubscription)
            {
                if (!sinkList.Contains(subEntry._SinkID))
                    sinkList.Add(subEntry._SinkID);
            }

            // Find the best route to each sink.
            foreach (VarID sinkID in sinkList)
            {
                Byte best_hop = 0xFF; // Ensure that the best subEntry is added to the route.
                double best_time = 0; // Ensure that the most recent entry is used
                PEQTableEntrySubscription best_hopEntry = null;
                foreach (PEQTableEntrySubscription subEntry in _tableSubscription)
                {
                    if (subEntry._HopCount <= best_hop)
                    {
                        if (subEntry._Timestamp >= best_time)
                        {
                            best_hop = subEntry._HopCount;
                            best_time = subEntry._Timestamp;
                            best_hopEntry = subEntry;
                        }
                    }
                }

                if (best_hopEntry != null)
                {
                    PEQTableEntryRouting newRoute = new PEQTableEntryRouting(_NUM_ID_BYTES);
                    newRoute._DestinationID = best_hopEntry._DestinationID;
                    newRoute._SinkID = best_hopEntry._SinkID;
                    newRoute._nextHopCheat = best_hopEntry._nextHopCheat;
                    newRoute._Valid = best_hopEntry._Valid;
                    _tableRouting.Add(newRoute);

                    IGraphicalReport newRouteReport;
                    if (best_hopEntry._CriteriaType == 0x0000)
                        newRouteReport = GenerateDirectionReport(GetMessageLevel(new PEQMessageBuildTree()));
                    else
                        newRouteReport = GenerateDirectionReport(GetMessageLevel(new PEQMessageSubscribe()));
                    if (newRouteReport != null)
                    {
                        if (currentRouteReport != null)
                        {
                            newRouteReport.ReportAction = MNS_Reporting.Action.Modify;
                            newRouteReport.PreviousStatic = currentRouteReport;
                            currentRouteReport = newRouteReport;
                            Notify(newRouteReport);
                        }
                        else
                        {
                            currentRouteReport = GenerateDirectionReport();
                            if (currentRouteReport != null)
                                Notify(currentRouteReport);
                        }
                    }
                    else if (currentRouteReport != null)
                    {
                        LineReport dirReport = new LineReport(_eventManager.CurrentClock,
                        (XYDoubleLocation)_location,
                        (XYDoubleLocation)newRoute._nextHopCheat, 0, -250, true, -_id.GetID());
                        dirReport.PreviousStatic = currentRouteReport;
                        dirReport.ReportAction = MNS_Reporting.Action.Stop;
                        Notify(dirReport);

                        currentRouteReport = null;
                    }
                }
            }
        }
        public IGraphicalReport GenerateDirectionReport(ColorEnum color)
        {
            foreach (PEQTableEntryRouting route in _tableRouting)
            {
                if (route._Valid) // take first valid route
                {
                    int node_dist = (int)_location.Distance(route._nextHopCheat);
                    int dist = -250;
                    if (node_dist/2 < 250)
                        dist = -node_dist/2;
                    LineReport dirReport = new LineReport(_eventManager.CurrentClock,
                        (XYDoubleLocation)_location,
                        (XYDoubleLocation)route._nextHopCheat, 0, dist, true, -_id.GetID());

                    dirReport.Color = color;
                    dirReport.IsArrow = true;

                    return dirReport;
                }
            }
            return null;
        }
        public void SendMessageReport(double startTime, double messageSize, 
            ReportLevel messageLevel, INode RefNode, INode DestNode)
        {
            if (RefNode == DestNode)
                return;
            if (!(RefNode.Location is XYDoubleLocation))
                return;
            if (!(DestNode.Location is XYDoubleLocation))
                return;

            ColorEnum color = ColorEnum.FlashOverride;
            switch (messageLevel)
            {
                case ReportLevel.Routine:
                    color = ColorEnum.Routine;
                    break;
                case ReportLevel.Priority:
                    color = ColorEnum.Priority;
                    break;
                case ReportLevel.Immediate:
                    color = ColorEnum.Immediate;
                    break;
                case ReportLevel.Flash:
                    color = ColorEnum.Flash;
                    break;
                case ReportLevel.FlashOverride:
                    color = ColorEnum.FlashOverride;
                    break;
            }

            double size;
            double width;
            double currentTime = Math.Ceiling(startTime / TimeScale) * TimeScale;
            while (currentTime < startTime + maxBitTime + messageSize / TransmissionSpeed)
            {
                double dist = RefNode.Location.Distance(DestNode.Location);
                if (dist > maxBitDistance)
                    return;

                size = 2 * ((currentTime - startTime)
                     * PropagationSpeed + RefNode.NodeSize / 2);
                if ((currentTime - startTime) * TransmissionSpeed < messageSize)
                    width = (currentTime - startTime) * PropagationSpeed;
                else width = messageSize / TransmissionSpeed * PropagationSpeed;

                LineReport lineReport = new LineReport(currentTime, (XYDoubleLocation)RefNode.Location,
                    (XYDoubleLocation)DestNode.Location, size / 2.0d, width);
                lineReport.MaximumMessageSize = maxBitDistance;
                lineReport.Color = color;
                lineReport.FinalColor = color;
                lineReport.Layer = DrawLayer.Foreground;

                Notify(lineReport);

                currentTime = currentTime + TimeScale;
            }
        }