public object Clone()
 {
     // Makes an exact copy of the object without simply providing a reference to the object.
     NodeTimerEvent clone = new NodeTimerEvent();
     clone.time = time;
     clone.node = node;
     clone.Event = (IEvent)Event.Clone();
     return clone;
 }
        void resetHelloTimer()
        {
            // Set the Hello Timer and insert into the Event Queue
            NodeTimerEvent outputTimer;
            FloodingQueryMessage message = new FloodingQueryMessage(this.id, 0xffff, FloodingQueryMessage.MessageType.hello);
            message.SourceLoc = this.Location;
            MessageEvent e = new MessageEvent(message);
            double Clock = this.EventMgr.CurrentClock;
            Clock += 30;

            outputTimer = new NodeTimerEvent();
            outputTimer.Event = e;
            outputTimer.node = this;
            outputTimer.Time = Clock;
            this.EventMgr.AddEvent(outputTimer);
        }
        void processQueryMessage(FloodingQueryMessage message)
        {
            // Called when a Query Message has been received
            NodeTimerEvent outputTimer;
            MessageEvent outputEvent;

            if (this.isSink) return;

            // Create a string uniquely identifying the message
            string idString = message.OriginatorID.ToString() + "-" + message.MessageID.ToString();

            if (!_messagesHeard.ContainsKey(idString)) // (For fun, get rid of this check and watch the broadcast storm!)
            { // If the _messagesHeard hash table doesn't contain the unique packet identifying string...
                _messagesHeard.Add(idString, null);         // Add the unique message string to the hash table
                if (message.Hops < this.distance)           // If the query we got is better than our previous
                {
                    this.nextHop = message.SourceID;        // Update the path back to the sink
                    this.distance = message.Hops;           // Update the distance back to the sink
                    this.nextHopCheat = ((FloodingQueryMessage)message).SourceLoc;  // ONLY FOR DISPLAY PURPOSES
                    Notify(GenerateDirectionReport());
                }
                message.UpdateSource(this.id);              // Update the message source to be the current node
                message.SourceLoc = this.Location;          // Update the message location to the current node.
                message.IncrementHops();                    // Increment the number of hops back to the sink

                outputEvent = new MessageEvent(message);    // create a new event to send out
                outputEvent.Referrer = this;

                outputTimer = new NodeTimerEvent();
                outputTimer.Event = outputEvent;
                outputTimer.node = this;
                     // Wait up to 2 seconds before sending (stand-off time).
                outputTimer.Time = this.EventMgr.CurrentClock + 2 * this.randomizer.NextDouble();
                this.EventMgr.AddEvent(outputTimer);

                //this.PhysProc.ExecuteAction(outputEvent);   // Send the event to our Physical Processor
            } // ELSE DROP MESSAGE
        }
        void processDataMessage(FloodingQueryMessage message)
        {
            // Called when a Data Message has been received
            NodeTimerEvent outputTimer;
            MessageEvent outputEvent;

            if ((message.DestinationID != this.ID) && (message.DestinationID != 0xffff))
                return;

            if (this.isSink) return;

            // ---- NOTE, NEARLY SAME CODE AS "processQueryMessage"
                if (this.nextHop != int.MaxValue)           // If a next hop exists...
                    message.DestinationID = this.nextHop;   // set the destination ID to the next hop address
                else
                    message.DestinationID = 0xffff;         // otherwise flood <-- this is not efficient!!!
                outputEvent = new MessageEvent(message);    // create a new event
                outputEvent.Referrer = this;

                outputTimer = new NodeTimerEvent();
                outputTimer.Event = outputEvent;
                outputTimer.node = this;
                // Wait up to 2 seconds before sending (stand-off time).
                outputTimer.Time = this.EventMgr.CurrentClock + 2 * this.randomizer.NextDouble();
                this.EventMgr.AddEvent(outputTimer);
        }
        public void Initialize()
        {
            Notify(GenerateStaticReport());

            FloodingQueryMessage message = new FloodingQueryMessage(this.id, 0xffff,
                FloodingQueryMessage.MessageType.hello);  // All new nodes create a hello message to be broadcast
            message.SourceLoc = this.Location;
            MessageEvent initialEvent = new MessageEvent(message); // An event is created with the message
            initialEvent.Referrer = this;
            // Initial Hello randomly occurs 0 - 10 minutes after deployment:

            // Create a timer event for the first Hello packet
            NodeTimerEvent helloTimerEvent = new NodeTimerEvent();
            helloTimerEvent.Event = initialEvent;
            helloTimerEvent.node = this;
            helloTimerEvent.Time = this.EventMgr.CurrentClock + this.randomizer.NextDouble() * 10;

            // Add timer to the Event Queue
            this.EventMgr.AddEvent(helloTimerEvent);

            // If this node is a Sink, add a Timer (Query) event to the event queue, starting in 0 - 5 seconds.
            if (this.IsSink)
            {
                // Create the Query Message
                message = new FloodingQueryMessage(this.id, 0xffff, FloodingQueryMessage.MessageType.query,
                    CurrentMessageID, this.id);
                message.SourceLoc = this.Location;
                // Create the MessageEvent
                MessageEvent QueryEvent = new MessageEvent(message);
                QueryEvent.Referrer = this;

                // Create the Timer event
                NodeTimerEvent queryTimerEvent = new NodeTimerEvent();
                queryTimerEvent.Event = QueryEvent;
                queryTimerEvent.node = this;
                queryTimerEvent.Time = this.EventMgr.CurrentClock + this.randomizer.NextDouble() * 5;

                // Add the TimerEvent to the Event Queue
                this.EventMgr.AddEvent(queryTimerEvent);
            }
        }
        public void GenerateEvent(double time, ILocation location)
        {
            // Overloads GenerateEvent to allow the simulation to provide the time the event occurs.
            XYDoubleLocation initalCorner = (XYDoubleLocation)field[0];  // Casting to xyLocation objects. Other
            XYDoubleLocation finalCorner = (XYDoubleLocation)field[1];     // coordinate systems are not supported.

            // Generate the random center location of the event.
            eventCenter = (XYDoubleLocation)location;

            eventCenter.SetField(field);

            Notify(generateStaticReport(time, eventCenter));

            foreach (FloodingQueryNode node in nodes.NodeQueue)
            { // Find which nodes are within the effective detection area.
                if (eventCenter.Distance(node.Location) <= eventSize) // if in the event area
                {
                    FloodingQueryApplicationMessage appMsg = new FloodingQueryApplicationMessage(); // Create a new app message
                    MessageEvent msgEvent = new MessageEvent(appMsg); // create a new message event
                    msgEvent.Referrer = node; // set the referrer to the current node

                    NodeTimerEvent timerEvent = new NodeTimerEvent();   // create a timer event
                    timerEvent.Time = time;
                    timerEvent.Event = msgEvent;                        // apply the message event
                    timerEvent.node = node;
                    eventMgr.AddEvent(timerEvent);                      // add the event to the Event Queue.
                }
            }
        }