#include "hyra.h"

Hyra::Hyra(uint16_t &pocetOnu, int16_t _pocetAllocId)
{
	double pravdepodobnost = (double)1/401;
	std::vector<double> pAktualni;
	std::map<double, uint16_t> statistikyGrantu;
	for (int i = 0; i < pocetOnu; i++) {		
		A.push_back(0);
		T1.push_back(0);		
		for (int j = 0; j < 401; j++) {
			pAktualni.push_back(pravdepodobnost);
		}
		p.push_back(pAktualni);	
		pAktualni.clear();
		
	}
	for (int i = 0; i < pocetOnu*_pocetAllocId; i++) {
		casGenerovaniGrantuHyra.push_back(statistikyGrantu);
		alokovaneGranty.push_back(0);
	}
	a = 0.00001;
	l = 0.1;
	fixedBw = 6;	
	maxBW = 150;
	assuredBW = 125;
	pocetAllocId = _pocetAllocId;
}

void Hyra::aktualizace(uint16_t i, uint16_t k) {	
	std::vector<double> *pravdepodobnostOnu = &p.at(i);
	//zvyseni pravdepodobnosti K
	double suma=0;
	for (int j = 0; j < 400; j++)
	{
		if (j != k)
			suma += (l*(pravdepodobnostOnu->at(j) - a));
	}
	pravdepodobnostOnu->at(k) += suma;

	//snizeni zbylych pravdepodobnosti
	for (int j = 0; j < 400; j++)
	{
		if (j != k)
			pravdepodobnostOnu->at(j)-=l*(pravdepodobnostOnu->at(j)-a);
	}
}

std::vector<AllocStruc> Hyra::generujBwmapu(double _cas, std::vector<uint32_t> _obsazenostFrontOnu, std::vector<uint8_t>* _dbruNastaveno) {
	//generuje podle Status Reportingu
	uint16_t nasledujiciStartTime = 0;
	uint16_t volneGranty = 9719;
	uint16_t grantSize = 0;
	uint16_t pomocna = 0;
	uint32_t zpracovavanaObsazenostFronty = 0;
	uint16_t jizPridelenyAssuredBw = 0;
	uint8_t Flags = 1; 
	std::vector<AllocStruc> bwMap;
	for (uint16_t i = 0; i < A.size()*pocetAllocId; i++) {
		alokovaneGranty[i] = 0;
	}

	for(uint16_t i =0; i<A.size();i++){		
		if (A[i] == 0)
		{
			if (volneGranty <= 0)
				break;
			jizPridelenyAssuredBw = 0;
			for (uint16_t j = 0; j < pocetAllocId; j++) {
				if (volneGranty <= 0)
					break;
				zpracovavanaObsazenostFronty = _obsazenostFrontOnu[(i*pocetAllocId) + j];
				if (j == 0)
				{
					grantSize = fixedBw;
				}
				else if (_dbruNastaveno->at((i*pocetAllocId) + j))	
				{
					grantSize = 1;
				}
				else if (j == 1) {
					if (zpracovavanaObsazenostFronty > assuredBW)
					{
						grantSize = assuredBW;
						jizPridelenyAssuredBw += assuredBW;
					}
					else if (zpracovavanaObsazenostFronty < 1)
						grantSize = 1;
					else
					{
						grantSize = zpracovavanaObsazenostFronty;
						jizPridelenyAssuredBw += zpracovavanaObsazenostFronty;
					}
				}
					else if (j == 2)
						grantSize = 1;
					else if (j == 3)
						grantSize = 1;

					if (grantSize > volneGranty)
						grantSize = volneGranty;

					volneGranty -= grantSize;
					alokovaneGranty[(i*pocetAllocId) + j] = grantSize;				
				}
		}
	}

	for (uint16_t i = 0; i<A.size(); i++) {
		if (A[i] == 0)
		{
			if (volneGranty <= 0)
				break;
			jizPridelenyAssuredBw = 0;
			for (uint16_t j = 1; j < pocetAllocId; j++) {
				if (volneGranty <= 0)
					break;
				grantSize = alokovaneGranty[(i*pocetAllocId) + j];
				zpracovavanaObsazenostFronty = _obsazenostFrontOnu[(i*pocetAllocId) + j];
				if (_dbruNastaveno->at((i*pocetAllocId) + j))	
				{
					grantSize = 1;
				}
				else if (j == 1) {
					if (zpracovavanaObsazenostFronty > alokovaneGranty[(i*pocetAllocId) + j])
					{
						if (zpracovavanaObsazenostFronty >= maxBW)
						{
							grantSize = maxBW;
							jizPridelenyAssuredBw += maxBW;
						}
						else
						{
							grantSize += zpracovavanaObsazenostFronty;
							jizPridelenyAssuredBw += zpracovavanaObsazenostFronty;
						}

					}
					else if (zpracovavanaObsazenostFronty < 1)
						grantSize = 1;
					else
					{
						grantSize = zpracovavanaObsazenostFronty;
						jizPridelenyAssuredBw = zpracovavanaObsazenostFronty;
					}
				}			

				volneGranty += alokovaneGranty[(i*pocetAllocId) + j];

				if (grantSize > volneGranty)
					grantSize = volneGranty;
				
				volneGranty -= grantSize;
				alokovaneGranty[(i*pocetAllocId) + j] = grantSize;
			}			
		}else
			A[i] -= 1;
	}

	for (uint16_t i = 0; i < alokovaneGranty.size(); i++) {
		if(alokovaneGranty[i]>0)
		{
			Flags = 1;
			_dbruNastaveno->at(i) = 1;
		}
		else
		{
			Flags = 0;
			_dbruNastaveno->at(i) = 0;			
		}		
		grantSize = alokovaneGranty[i];

		AllocStruc aktualneGenerovanaStruktura = AllocStruc(i, Flags, nasledujiciStartTime, grantSize);
		bwMap.push_back(aktualneGenerovanaStruktura);
		nasledujiciStartTime += grantSize;
		Flags = 0;		
		casGenerovaniGrantuHyra[i].insert(std::make_pair(_cas, grantSize));
	}
	return bwMap;
}

Hyra::Hyra() {

}

Hyra::~Hyra()
{
}

void Hyra::vygenerujStatistikyBwMap() {
	for (uint16_t i=0; i < casGenerovaniGrantuHyra.size(); i++) {
		std::map<double, uint16_t>::iterator it = casGenerovaniGrantuHyra[i].begin();

		std::stringstream cestaSouboru;
		cestaSouboru << "BwMapProAllocId" << i << ".txt";
		
		std::ofstream myfile;
		myfile.open(cestaSouboru.str(), std::ofstream::out);
		if (myfile.is_open())
		{
			myfile << "casOdeslani granty\n";
			while (it != casGenerovaniGrantuHyra[i].end())
			{
						

				myfile << it->first << " " << it->second << "\n";
				it++;
			}			
		}
		else std::cout << "Soubor nelze otevrit!";
		myfile.close();
	}	
}