/***************************************************************************************
*	This software simulated for ARPEES, a routing protocol for Wireless Sensor Network *
*	Copyright (C) 2007 by Tran Quang Vinh (vinhtq@mail.hut.edu.vn)                     *
*	Multimedia Information NETwork Lab - MINET                                         *
*	Dept. Electronic Information Systems, Graduate School of Enginnering               *
*	Shibaura Institute of Technology, Japan.                                           *
*--------------------------------------------------------------------------------------*
*	File name: BaseStation.cpp										                   *
*	Implement the base station in the network									       *
***************************************************************************************/

#include <stdio.h>
#include <string.h>

#include <omnetpp.h>
#include "SensorNode.h"
#include "BaseStation.h"
#include "MessageType_m.h"
#include "Sensingcoverage.h"

Define_Module(BaseStation);

/**************************************************************************************/
void BaseStation::initialize()
{
	int i;
    cModule *parent = parentModule();

    this->myId = par("id");
    this->nrGates = (int) parent->par("numNodes");
    this->xpos = par("xpos");
    this->ypos = par("ypos");
    this->nrNodes = (int) parent->par("numNodes");
    this->xMax = (int) parent->par("xMax");
    this->yMax = (int) parent->par("yMax");
    this->numNodes = (int) parent->par("numNodes");
    this->resetStatus();
    this->roundsDone = 0;
    this->nrRounds = (int) parent->par("rounds");
    this->firstDead = 0;
    this->calledEnd = 0;			   //controling the type of ended simulation 
    this->halfDead = 0;                //number of node die
    this->halfDeadCtr = 0;             //control number of node die
    this->deadNodes = 0;               //
    this->oldDeadNodes = 0;
    this->P = 0.05;
    this->cHeadsRound = 0;
	//this->redunNode = 0;
	

    // Display base station
	this->setDisplayString("p=$xpos,$ypos;i=device/antennatower_l;o=blue");

    ev << "P: " << this->P <<"\n";

    for (i = 0; i < NUMBERNODES+3; i++)
    {
        advInfo[i].id = 0;
        advInfo[i].energy = 0;
        advInfo[i].status = 0;
    }

    for (i = 0; i < NUMBERROUND; i++)
    {
        this->roundTimes[i] = 0;
		this->deadRound[i] = 0;
		this->nrHeads[i]= 0;
		this->totalEnRemain[i] = 0;
		this->totalDeadNodes[i] = 0;
    }

	// schedule first sending
    ev << "BS info (ID = " << this->myId << ", Number of Gates: "
	   << this->nrGates <<", Xpos " << this->xpos << ", Ypos " << this->ypos << "\n";
    {
        cMessage *cmsg = new cMessage();
        cmsg->setKind(SMSG_INIT);
        scheduleAt(simTime(), cmsg);
    }
}
/**************************************************************************************/
// making the gates on the fly

void BaseStation::initNodes()
{
    int i;
    cModule *parent = parentModule();
    cModule *mod;
    int numNodes;
    int trRange;
    int ritems;

    numNodes = (int) parent->par("numNodes");
    ev << "BS numNodes is: " << numNodes << "\n";
    trRange = (int) parent->par("trRange");
    ev << "BS trRange is: " << trRange << "\n";

    for (i = 1; i <= simulation.lastModuleIndex(); i++)
    {
        int x, y, id;

        //scan the simulation module vector
        mod = (cModule *) simulation.module(i);

        if (strcmp(mod->name(), "node") == 0)
        {
            id = ((SensorNode *) mod)->myId;
            x =  ((SensorNode *) mod)->xpos;
            y =  ((SensorNode *) mod)->ypos;
            nodePtr[id] = ((SensorNode *) mod);

            if (id != this->myId)
            {
                cGate *g;
                char gName[32];
                int items;

                ev <<"BS: " << this->myId <<"(" << this->xpos << "," << this->ypos 
				   << ") found node : " << (id - 2) << " at(" << x << "," << y << ")\n";

                items = this->gatev.items();
                ritems = mod->gatev.items();

                ev << "items " << items << "\n";

                // make new gate here
                sprintf(gName, "O_%d", id);
                g = new cGate(gName, 'O');
                this->gatev.addAt(items, g); // position, element
                g->setOwnerModule((cModule *) this, items);
				g->displayString().setTagArg("o",1,"0"); //hide the arrow from BS to node

                // make new gate at other side
                sprintf(gName, "I_%d", this->myId);
                g = new cGate(gName, 'I');
                mod->gatev.addAt(ritems, g); // position, element
                g->setOwnerModule((cModule *) mod, ritems);
			
                //CHANNEL
                cLinkType *wless = findLink("wless");
                connect((cModule*)this,items,(cLinkType*)wless,(cModule*)mod,ritems);
            }
        }
    }
}

/**************************************************************************************/
void BaseStation::handleMessage(cMessage * msg)
{
    if (msg->isSelfMessage())
    {
        ev << "BS: got self message type " << msg->kind() << "\n";
        if (msg->kind() == SMSG_INIT)
        {
            ev << "BS: got start message\n";
            this->initNodes();
        }
    }
    else
    {// no self message
        if (((ClusterMessage *) msg)->getProto() == CL_TOBS)
        {
            double energy;
            int cluster;
            int status;
            int sender;
            int xpos, ypos;

            Status2BSMessage *statusmsg = check_and_cast<Status2BSMessage *>(msg);
            sender = statusmsg->getSrcAddress();
            energy = statusmsg->getEnergy();
            cluster = statusmsg->getCluster();
            status = statusmsg->getStatus();
            xpos = statusmsg->getXpos();
            ypos = statusmsg->getYpos();

			if (energy < 0 && this->firstDead == 0)
                this->firstDead = this->roundsDone;

            if (energy < 0 && this->halfDead == 0)
                this->halfDeadCtr++;

            if (this->roundsDone < nrRounds)
                this->roundTimes[roundsDone] = (int) simTime();

            advInfo[sender].id = sender;
            advInfo[sender].energy = energy;
            advInfo[sender].status = status;
            advInfo[sender].xpos = xpos;
            advInfo[sender].ypos = ypos;
			
			//get total energy dissipation
            if (energy > 0)
			{
				this->totalEnRemain[this->roundsDone] += energy;
			}	

			if (advInfo[sender].energy < 0)
            {
                if (((SensorNode *) nodePtr[sender])->myStatus != STATUS_DEAD)
                    this->deadNodes++;
                advInfo[sender].status = STATUS_DEAD;
                status = STATUS_DEAD; //  debug only
                
				ev << "DEAD:sender: " << sender << "id : " 
				   << ((SensorNode *) nodePtr[sender])->myId -2 << "\n";
                ((SensorNode *) nodePtr[sender])->myStatus = STATUS_DEAD;
            }
            this->nrStatusRec++;
            //ev <<"BS rec " <<this->nrStatusRec <<" nrNodes: "<<this->nrNodes <<"\n";

            // check if done
            if (this->nrStatusRec == this->nrNodes - this->oldDeadNodes)
            {
                this->oldDeadNodes += this->deadNodes;
                ev <<"node dead: " << this->deadNodes 
				   <<"all dead "  << this->oldDeadNodes << "\n";
                this->deadRound[this->roundsDone] = this->deadNodes;
				
				//stored totalDeadNodes for each round
				this->totalDeadNodes[this->roundsDone] = this->oldDeadNodes;

				//stored totalRedundanceNode for each round
				//this->totalRedundance[this->roundsDone] = this->redunNode;

				//if (this->oldDeadNodes > this->nrNodes  / 2 && this->halfDead == 0)
				if (this->oldDeadNodes > this->nrNodes  * 2 / 3 && this->halfDead == 0)
                {
                    this->halfDead = roundsDone;
                    ev << " HALF DEAD\n";
                    this->calledEnd = 2;
                    endSimulation();
                }

                if (this->roundsDone <= this->nrRounds)
                {
					ev << "BS call compute best\n";
                    // now compute best  nodes
                    createEvents();
                    resetStatus();
                }
                
				ev << "BS: call roundsDone++\n";
                this->roundsDone++;

                if (this->roundsDone > this->nrRounds)
                {
                    this->calledEnd = 1;
                    endSimulation();
                }
				
				//stored totalRedundanceNode for each round
				this->totalRedundance[this->roundsDone] = this->redunNode;
            }
            else
			{
				ev << "BS: no event, not done\n";
			}
        }
    }
	//cancelAndDelete(msg);
    delete(msg);
}

/**************************************************************************************/
void BaseStation::resetStatus()
{
    this->nrStatusRec = 0;      // number of received status
    this->deadNodes = 0;
}

/**************************************************************************************/
void BaseStation::createEvents()
{
    int i, j;
    int min = 999999999;
    int minPtr = 0;
    int sum = 0;
    double T;
    double rd;
    int bestCtr;
    double h1;
    int cHeads;
	int totalRedundance = 0;

	cModule *parent = parentModule();
    int trRange  = (int) parent->par("trRange");
	int numNodes = (int) parent->par("numNodes");
	int protocol = (int) parent->par("protocol");
	int kRequire = (int) parent->par("kRequire");

	struct _adv best[MAXEVENTS];
	for (i = 0; i < MAXEVENTS; i++)
        best[i].id = 0;

    bestCtr = 0;

  reset:
    cHeads = this->cHeadsRound;

    // seperate for reset reasons
    for (int rec = 2; rec < this->nrNodes + 2; rec++)
    {
        SensorNode *nPtr = (SensorNode *) nodePtr[rec];
    }

  restart:
    T = (double)this->P /(double)((1 - this->P *(double)((this->roundsDone) % 20)));

	h1 = (this->P * ((double) (this->cHeadsRound / 5)));
    
	if (h1 > 1)
    {
        ev <<"ERROR h1: " <<h1 <<" cHeadRound " <<this->cHeadsRound <<"\n";
        //this->calledEnd = 5;
        //endSimulation();
    }

    ev <<"round " << this->roundsDone << " cHeadsRound:" << this->cHeadsRound 
	   <<" deadNodes " <<this->deadNodes <<" T: " << T << " P: " << this->P <<"\n";

    for (rec = 2; rec < this->nrNodes + 2; rec++)
    {
        SensorNode *nPtr = (SensorNode *) nodePtr[rec];

        rd = ((double) rand() / (RAND_MAX + 1.0)); //RAND_MAX=32767

        ev <<"rd rec: " <<rec <<" cHeadsRound " <<this->cHeadsRound
           <<" T: " <<T <<" rd: " <<rd <<" LCR " <<nPtr->lastClusterRound << "\n";

        if (nPtr->myStatus != STATUS_DEAD && rd < T && nPtr->lastClusterRound == 0)
        {
            best[bestCtr].xpos = nPtr->xpos;
            best[bestCtr].ypos = nPtr->ypos;
            best[bestCtr].id = rec;
            ev << "cHead: " << rec << "\n"; //Clustrer Head ID
            bestCtr++;
            this->cHeadsRound++;
            if (bestCtr == MAXEVENTS) //MAXEVENTS = max numbers of CH
                break;
            //nPtr->lastClusterRound = this->roundsDone; // bo qua?
        }
        this->nrHeads[this->roundsDone] = bestCtr;
		//now bestCtr stores the number of CH
    }

    if (bestCtr == 0) // if no cluster, reset
    {
        int allDone = 1;

        if (this->cHeadsRound + this->deadNodes == this->numNodes)
        {
            ev << "BS: goto reset\n";
            goto reset;
        }

        // check if not all are already done!!
        for (int rec = 2; rec < this->nrNodes + 2; rec++)
        {
            SensorNode *nPtr = (SensorNode *) nodePtr[rec];

            if (nPtr->lastClusterRound == 0 && nPtr->myStatus != STATUS_DEAD)
            {
                allDone = 0;
                break;
            }
        }
        if (allDone == 0)
        {
            ev << "BS: restart\n";
            goto restart;
        }
        ev << "no cluster heads\n";
        this->calledEnd = 6;
        endSimulation();
    }

    if (this->roundsDone == this->nrRounds)
    {
        ev << "all rounds done\n";
        this->calledEnd = 0;
        endSimulation();
    }

	//select cluster head with energy efficiency
	if (protocol == 1)
	{
		for (j = 0; j < bestCtr; j++)
		{
			int oldCH = best[j].id;
			ev << "old cluster head " << j << " is " << oldCH << endl;
			
			best[j].id = selectClusterHead(oldCH);
			int chId = best[j].id;
			// get position on new cluster head
			best[j].xpos = ((SensorNode *) nodePtr[chId])->xpos;
			best[j].ypos = ((SensorNode *) nodePtr[chId])->ypos;
			
			ev << "new cluster head " << j << " have ID: " << best[j].id 
			   << "(" << best[j].xpos << "," << best[j].ypos << ")"<< endl;
		}
	}

	// now we send message to all nodes and announce their new cluster head
    {
        int head = 0;
        int tmp;
        char str[32];
		
		//xac dinh node thuoc CH nao
        for (int rec = 2; rec < this->nrNodes + 2; rec++)
        {
            SensorNode *nPtr = (SensorNode *) nodePtr[rec];
            head = 0;
            if (nPtr->myStatus != STATUS_DEAD)
            {
                ev << "rec: " << rec <<"\n";;
                min = 99999999;
                for (j = 0; j < bestCtr; j++)
                {
                    //tinh khoang cach tu node den cac CH, de tim ra CH cua node do
					tmp = (nPtr->xpos - best[j].xpos) * (nPtr->xpos - best[j].xpos) + 
						  (nPtr->ypos - best[j].ypos) * (nPtr->ypos - best[j].ypos);
                    //ev << "cmp with " << best[j].id << " gives " << (int)sqrt(tmp) << " \n";
					
					if ((int)sqrt(tmp) < trRange)
					{
						if (rec != best[j].id) //voi cac node khong phai la CH
						{
							
							if ((int)sqrt(tmp) < min)
							{
								min = (int)sqrt(tmp);
								head = best[j].id;
							}
						}
						else
						{
							head = best[j].id;
							break;
						}
					}
					else
					{
						//ev << "-> rec " << rec << " out of CH " << best[j].id << "'s range !" <<endl;
					}
                }
           }
            
			ev <<"BS: rec " << rec << " x,y " << nPtr->xpos << "," << nPtr->ypos 
			   <<" has cluster head: " << head << "\n";
            nPtr->myHead = head;
        }
////////////////////////////////////////////////////////////////////////////////////////		
	
		if (kRequire != 0)
		{
			struct _adv control[NUMBERNODES];
			int i = 0, j = 0;
			int count = 0, temp = 0;
			for (i = 0; i < NUMBERNODES; i++)
			{
				control[i].id = 0;
				control[i].hop = 0; //stored number of neighber
			}

			ev << "before round " << this->roundsDone << endl;
			for (rec = 2; rec < this->nrNodes + 2; rec++)
			{
				SensorNode *nPtr = (SensorNode *) nodePtr[rec];
				
				if (nPtr->myAction == 1)
					ev << "node: " << nPtr->myId << ", Action = " << nPtr->myAction << endl;
				if (nPtr->neighber != 0)
					ev << "node: " << nPtr->myId << ", Neighber = " << nPtr->neighber << endl;
			}
			
			// update neighbors information for this round
			for (rec = 2; rec < this->nrNodes + 2; rec++)
			{
				SensorNode *nPtr = (SensorNode *) nodePtr[rec];
				if (nPtr->myStatus != STATUS_DEAD)
				{
					nPtr->neighber = nPtr->computeNeighbor();
					// reduce energy for compute neighbor

					
					if (nPtr->myId != nPtr->myHead && nPtr->neighber >= kRequire * 3)
					{ 
						control[count].id = rec;
						control[count].hop = nPtr->neighber;
						ev << "node " << control[count].id << " has neighber: " << control[count].hop << endl; 
						count++; // total nodes have neighber > k*3
					}
					else
					{
						ev << "node " << nPtr->myId << ": neighber= " << nPtr->neighber 
						   << ", head= " << nPtr->myHead << endl;
					}
				}
			}
			
			// sort nodes by descending number of neighbers
			for(i = 0; i < count - 1; i++)
			{
				for(j = 0; j < count - i - 1; j++)
				{
					if (control[j+1].hop > control[j].hop) 
					{
						swapInt (control[j+1].id, control[j].id);
						swapInt (control[j+1].hop, control[j].hop);
					}
					else if (control[j+1].hop == control[j].hop)
					{
						if ((control[j+1].id < control[j].id))
						{
							swapInt (control[j+1].id, control[j].id);
							swapInt (control[j+1].hop, control[j].hop);
						}
					}
				}
			}
			
			// after sort
			ev << "after sort:" << endl;
			for(i = 0; i < count; i++)
			{
				ev << "node " << control[i].id << " has neighber: " << control[i].hop << endl; 
			}
			
			// call check redundance
			for(i = 0; i < count; i++)
			{
				SensorNode *nPtr = (SensorNode *) nodePtr[control[i].id];
				ev << "\nnode " << nPtr->myId << " call checkRedundance()" << endl;
				nPtr->myAction = nPtr->checkRedundance();
				// reduce energy for checking redundance

				ev << "node " << nPtr->myId << " has action status = " << nPtr->myAction << "\n \n";
			}
			
			// count number of redundance
			ev << "after round " << this->roundsDone << endl;
			for (rec = 2; rec < this->nrNodes + 2; rec++)
			{
				SensorNode *nPtr = (SensorNode *) nodePtr[rec];
				
				if (nPtr->myAction == 1)
				{
					totalRedundance++;
					ev << "node: " << nPtr->myId << ", Action = " << nPtr->myAction << endl;
				}
			}
			this->redunNode = totalRedundance;
			ev << "total redundance node: " << this->redunNode << endl;
		}

////////////////////////////////////////////////////////////////////////////////////////

		//send message to all nodes and announce their new cluster head
        for (rec = 2; rec < this->nrNodes + 2; rec++)
        {

			ClusterHeadMessage *cmsg = new ClusterHeadMessage();
            SensorNode *nPtr = (SensorNode *) nodePtr[rec];
			
			if (nPtr->myStatus != STATUS_DEAD && nPtr->myHead != 0 && nPtr->myAction == 0)
            { // this node is CH or member of CH
				ev << "send messages to nodes announcing cluster heads\n";
                cmsg->setProto(CL_TOHEAD); 
                cmsg->setSrcAddress(this->myId);
				cmsg->setCHeadArraySize(this->numNodes + 3);
                cmsg->setCHead(rec, nPtr->myHead);
                cmsg->setDestAddress(BROADCAST);
                ev << "BS: sendHEAD for " << rec << " from CH:" << nPtr->myHead << "\n";
                if (rec != 0)   // no head when dead
                {
                    sprintf(str, "O_%d", rec);
                    if (findGate(str) > 1)
                    {
                        cGate *g = gate(str);
                        if (g->isConnected())
                        {
                            //ev << this->myId << ": sToCHEAD to" << rec << "\n";
                            send((ClusterHeadMessage *) cmsg, str);
                        }
                    }
                }
            }
            
			// redundance node send message to CH to announce their status
			else if (nPtr->myStatus != STATUS_DEAD && nPtr->myAction == 1) 
			{
				ev << "node " << nPtr->myId << " : action status = " << nPtr->myStatus << endl;
				ev << "REDUNDANCE: " << rec << "\n";
				ev << "send messages to nodes announcing it is redundance node\n";
                cmsg->setProto(CL_TO_REDUN_NODE);
                cmsg->setSrcAddress(this->myId);
                cmsg->setDestAddress(BROADCAST);
                ev << "BS: send to redundance node " << rec << "\n";
                if (rec != 0)   // no head when dead
                {
                   	sprintf(str, "O_%d", rec);
                   	if (findGate(str) > 1)
                   	{
                       	cGate *g = gate(str);
                       	if (g->isConnected())
                       	{
							send((ClusterHeadMessage *) cmsg, str);
							//reduce energy
                       	}
                   	}
                }				
			}
			
			// other nodes send status to BS (for simulation only!)
			else if (nPtr->myStatus != STATUS_DEAD) // myHead = 0
			{
				//send to BS that this is free node
				ev << "Out of Range: " << rec << "\n";
				ev << "send messages to nodes announcing it is free node\n";
                cmsg->setProto(CL_TO_FREE_NODE); 
                cmsg->setSrcAddress(this->myId);
                cmsg->setDestAddress(BROADCAST);
                ev << "BS: send to free node " << rec << "\n";
                if (rec != 0)   // no head when dead
                {
                   	sprintf(str, "O_%d", rec);
                   	if (findGate(str) > 1)
                   	{
                       	cGate *g = gate(str);
                       	if (g->isConnected())
                       	{
							send((ClusterHeadMessage *) cmsg, str);
                       	}
                   	}
                }				
			}
			else
			{
				ev << "Dead node: " << rec << endl;
			}
        }
    }
    // here we can reset everything
    this->resetStatus();
} 

/**************************************************************************************/
int BaseStation::selectClusterHead(int oldCH)
{
	int i, j, rec = 0, oldId = 0;
	int newCH = 0;
	int MaxSelectCH = 0;
	int selectCH = 0;
	SensorNode *nodePtr[NUMBERNODES+3];
	cModule *mod;
	cModule *parent = parentModule();
    int trRange  = (int) parent->par("trRange");
	int protocol = (int) parent->par("protocol");
	
	struct _adv candidate[NUMBERNODES+3];
	for (i = 0; i < NUMBERNODES+3; i++)
	{
		candidate[i].id = 0;
		candidate[i].energy = 0;
		candidate[i].xpos = 0;
		candidate[i].ypos = 0;
	}
	for (j = 3; j <= simulation.lastModuleIndex(); j++)
	{
		int x = 0, y = 0, id = 0, e = 0;

		//scan the simulation module vector
		mod = (cModule *) simulation.module(j);

		if (strcmp(mod->name(), "node") == 0)
		{
			id = ((SensorNode *) mod)->myId;
			x =  ((SensorNode *) mod)->xpos;
			y =  ((SensorNode *) mod)->ypos;
			e =  ((SensorNode *) mod)->energy;
			nodePtr[id] = ((SensorNode *) mod);
		}
		
		if (id != this->myId)
		{
			candidate[rec].id = id;
			candidate[rec].energy = e;
			candidate[rec].xpos = x;
			candidate[rec].ypos = y;
		}
		// determime old CH or Event
		if (candidate[rec].id == oldCH)
		{
			oldId = rec;
			ev << "oldCH: " << candidate[oldId].id << "(" <<candidate[oldId].xpos 
			   <<"," <<candidate[oldId].ypos << ") E: " <<candidate[oldId].energy << endl;
		}
		rec++;
	}
	
	for (rec = 0; rec < simulation.lastModuleIndex() - 2; rec++)
	{
		//ev << "rec: " << candidate[rec].id << "(" << candidate[rec].xpos <<"," 
		//   << candidate[rec].ypos << ") E: " << candidate[rec].energy << endl;

		// calculate distance from event to nodes near by
		int tmp = (int)sqrt(pow((candidate[rec].xpos - candidate[oldId].xpos),2) + 
			                pow((candidate[rec].ypos - candidate[oldId].ypos),2));
		
		if ((tmp < trRange) & (candidate[rec].id != oldCH))
		{
			if (tmp <= 0) tmp = (int)trRange /2;
			
			// select routing protocol
			if (protocol == 1)		// ARPEES
			{
				selectCH = candidate[rec].energy;
			}
			/*
			else if (protocol == 3) // OEDSR
			{
				selectCH = candidate[rec].energy;
			}
			
			else if (protocol == 4) // HPEQ
			{
				selectCH = candidate[rec].energy;
			}
			
			else
			{
				ev <<"no routing protocol was selected, end simulation!";
				endSimulation();
			}
			*/
			// choose the node has maximum solution as cluster-head
			if (selectCH > MaxSelectCH)
			{
				MaxSelectCH = selectCH;
				newCH = candidate[rec].id;
			}
		}
		else
		{
			//ev << "out of event !" << endl;
		}
	}
	ev << "return newCH: " << newCH << endl;
	return newCH;
}

/************************************************************************************/
void BaseStation::finish()
{
    int i;
	double eRemain = 0.0, eDissipate = 0.0;
	int step = 10;		// record the everage values every step round
	int recordAt = 200; // record at this round
	int redun = 0;

	ev << "BS:finish() was called \n";
    recordScalar("BS:calledEnd", this->calledEnd);
    //recordScalar("BS:BS node id", this->myId);
    recordScalar("BS:roundsDone", this->roundsDone);
    recordScalar("BS:nrRounds", this->nrRounds);
    recordScalar("BS:firstDead", this->firstDead);
    //recordScalar("BS:halfDead", this->halfDead);
	//recordScalar("BS:allDeadNodes", this->oldDeadNodes);

	for (i = 0; i <= this->roundsDone; i++)
    {
        int averageEnergyRemain = this->totalEnRemain[i]/this->nrNodes;
		int averageEnergyDissipate = 2000000 - (this->totalEnRemain[i]/this->nrNodes);
		recordScalar("nrHeads", this->nrHeads[i]);
		
		eRemain += averageEnergyRemain;
		eDissipate +=  averageEnergyDissipate;
		redun += this->totalRedundance[i]; 
		step = 10;
		if (i % step == 0)
		{
			if (i == 0) step = 1;
			recordScalar("averageEnergyRemain", eRemain/step);
			recordScalar("averageEnergyDissipate", eDissipate/step);
			recordScalar("averageAliveNodes", this->nrNodes - this->totalDeadNodes[i]);
			if (i != 0)
			recordScalar("averageTotalRedundance", redun/step);
			
			eRemain = 0.0;
			eDissipate = 0.0;
			redun = 0;
		}
		recordAt = 220;
		if (i == recordAt)
		{
			recordScalar("averageEnergyRemainAtRound", averageEnergyRemain);
			recordScalar("averageEnergyDissipateAtRound", averageEnergyDissipate);
			recordScalar("averageAliveNodesAtRound", this->nrNodes - this->totalDeadNodes[i]);
			recordScalar("totalRedundanceAtRound", this->totalRedundance[i]);
		}
    }
}
/************************************************************************************/
