% EXPERIMENTREFACTOR
% This function runs an experiment and saves the results on a file in 
% the results directory.
% users: number of users
% INPUT
% rt: SLO on the average response time (the RTP80 is set at twice twice this
%     value:
% algorithm: string representing the name of the algorithm to be used, it can
%            be either "heuristic" or "fmincon"
% availability: percentage of availability (value between 0 and 1)
% seed: number that is used to initialize the random number generator
% OUTPUT
% d: allocation matrix
% cost: cost fo allocating the allocation matrix
% avgRT: mean response time
% cdfRTindex: response time percentiles indexes
% cdfRTvalue: response time percentiles values
% evaluations: number of evaluations
% time: time to computer the solution.

function [d, cost, avgRT, cdfRTindex, cdfRTvalue, evaluations, time] = ...
	experimentRefactor(users_s, profile_s, sc2_s, mg34_s, maxDup_s, availability_s, algorithm, seed_s)

	users = str2double(users_s);
	seed = str2double(seed_s);
	availability = str2double(availability_s);

	if strcmp(profile_s, 'ref')
		profile = [100;50;150;50;200];
	elseif strcmp(profile_s, 'var1')
		profile = [200;25;75;25;100];
	elseif strcmp(profile_s, 'var2')
		profile = [50;100;75;25;100];
	elseif strcmp(profile_s, 'var3')
		profile = [50;25;300;25;100];
	elseif strcmp(profile_s, 'var4')
		profile = [50;25;75;100;100];
	elseif strcmp(profile_s, 'var5')
		profile = [50;25;75;25;400];
	else
		error('bad profile');
	end
	
	if strcmp(sc2_s, 'ref')
		sc2 = [0.07704*0.5    0.07331*2    0.37879*2    0.39370*2    0.04129*2; ...
				0.07704*2    0.07331*0.5    0.37879*2    0.39370*2    0.04129*2; ...
				0.07704*2    0.07331*2    0.37879*0.5    0.39370*2    0.04129*2; ...
				0.07704*2    0.07331*2    0.37879*2    0.39370*0.5    0.04129*2; ...
				0.07704*2    0.07331*2    0.37879*2    0.39370*2    0.04129*0.5]; 
	elseif strcmp(sc2_s, 'null')
		sc2 = [];
	elseif strcmp(sc2_s, 'k1')
		sc2 = [0.07704*0.5    0.07331*2    0.37879*2    0.39370*2    0.04129*2];
	elseif strcmp(sc2_s, 'k2')
		sc2 = [0.07704*2    0.07331*0.5    0.37879*2    0.39370*2    0.04129*2];
	elseif strcmp(sc2_s, 'k3')
		sc2 = [0.07704*2    0.07331*2    0.37879*0.5    0.39370*2    0.04129*2];
	elseif strcmp(sc2_s, 'k4')
		sc2 = [0.07704*2    0.07331*2    0.37879*2    0.39370*0.5    0.04129*2];
	elseif strcmp(sc2_s, 'k5')
		sc2 = [0.07704*2    0.07331*2    0.37879*2    0.39370*2    0.04129*0.5];
	else
		error('bad sc2');
	end
	
	if strcmp(mg34_s, 'ref')
		mg34 = [3.5674    3.1954    7.6904   13.7880    2.2577];
	elseif strcmp(mg34_s, 'null')
		mg34 = [];
	else
		error('bad mg34');
	end

	if strcmp(maxDup_s, 'none')
		maxDup = [0; 10; 10; 10];
	elseif strcmp(maxDup_s, '4')
		maxDup = [0; 10; 10; 0];
	elseif strcmp(maxDup_s, '34')
		maxDup = [0; 10; 0; 0];
	elseif strcmp(maxDup_s, '234')
		maxDup = [0; 0; 0; 0];
	else
		error('bad maxDup');
	end

	global failureProbGlobal
	failureProbGlobal = 1-availability;

	c = Constraints([100 100 20 20 1000],0.8,[200 200 40 40 2000]);
					
	disp('EXPERIMENT: loading spot price traces...');
% load historical data for three eu-west machines
meu1 = Survival('price/eu-west-1.windows.m1.small.csv');
meu2 = Survival('price/eu-west-1.windows.m1.large.csv');
meu3 = Survival('price/eu-west-1.windows.m1.xlarge.csv');
meu4 = Survival('price/eu-west-1.windows.m2.xlarge.csv');
meu5 = Survival('price/eu-west-1.windows.m2.2xlarge.csv');
meu6 = Survival('price/eu-west-1.windows.m2.4xlarge.csv');

% set the on-demand-price for three eu-west machines
% use the on-demand price
odp = [inf inf inf inf inf inf];
%      0.0649 0.2588 0.5181 0.0672 0.2674 0.5350

recoverTimeHours = 810/3600;
desiredLifeHours = recoverTimeHours*(availability)/(1-availability);

	disp('EXPERIMENT: calculating minimum bid prices...');
% if strcmp(bidtype, 'ondemand')
	bid1 = meu1.calcMaxBidFromAvgLife(desiredLifeHours);
	bid2 = meu2.calcMaxBidFromAvgLife(desiredLifeHours);
	bid3 = meu3.calcMaxBidFromAvgLife(desiredLifeHours);
	bid4 = meu4.calcMaxBidFromAvgLife(desiredLifeHours);
	bid5 = meu5.calcMaxBidFromAvgLife(desiredLifeHours);
	bid6 = meu6.calcMaxBidFromAvgLife(desiredLifeHours);	
% elseif strcmp(bidtype, 'ttl')
% 	bid1 = meu1.calcMaxBidFromPercentile(0.90, desiredLife);
% 	bid2 = meu2.calcMaxBidFromPercentile(0.90, desiredLife);
% 	bid3 = meu3.calcMaxBidFromPercentile(0.90, desiredLife);
% 	bid4 = meu4.calcMaxBidFromPercentile(0.90, desiredLife);
% 	bid5 = meu5.calcMaxBidFromPercentile(0.90, desiredLife);
% 	bid6 = meu6.calcMaxBidFromPercentile(0.90, desiredLife);
%else
%	error('bidtype must be ondemand or ttl');
%end

% set the average bidding price and time to leave for three eu-west machines

disp('EXPERIMENT: calculating expected average prices...');
[~, price1] = meu1.calcAverageLife(bid1);
[~, price2] = meu2.calcAverageLife(bid2);
[~, price3] = meu3.calcAverageLife(bid3);
[~, price4] = meu4.calcAverageLife(bid4);
[~, price5] = meu5.calcAverageLife(bid5);
[~, price6] = meu6.calcAverageLife(bid6);
ttl = [desiredLifeHours desiredLifeHours desiredLifeHours ...
			desiredLifeHours desiredLifeHours desiredLifeHours];
price = [price1 price2 price3 price4 price5 price6];

% set rates and cpus
rate =  [1 2 2 3.25 3.25 3.25];
%rate = rate*ecuconv;
cpu =   [1 2 4 2    4    8];
%cpu = [1 1 1 1 1 1];
%rate = [1 4 8 6.5  13 26]; % ecu

rec = repmat(recoverTimeHours, 1, 6);

% finally create the resources
res = Resources(rate, cpu, price, odp, ttl, rec);

disp('EXPERIMENT: generating queuing network...');
% generate the queuing network
qn = QNfactory.newSPECASQN(users, profile);

% reduce the rates of the SAP ERP due to the failure
qn.rates(2:end,:) = qn.rates(2:end,:).*availability;
%qn.rates(2:end,:) = qn.rates(2:end,:)*failureProb;

if nargin == 7
	seed = 0;
end

scAlt{qn.M} = [];
mgAlt{qn.M,qn.M} = [];

scAlt{2}=sc2;
mgAlt{3,4}=mg34;

filename = strcat('./results/', users_s,'_',profile_s,'_', ...
			sc2_s, '_', mg34_s,'_', maxDup_s, '_', ...
			availability_s, '_', algorithm, '_', seed_s, '.mat');

if strcmp(algorithm, 'norefactoring')
	disp('EXPERIMENT: starting no refactoring algorithm...');
	[ d, cost, avgRT, cdfRTindex, cdfRTvalue, evaluations, time ] = ... 
		findOptimalAllocationFullLimit(qn, [], c, res, maxDup, seed);
	nrefactorings = 0;
elseif strcmp(algorithm, 'replacement')
	disp('EXPERIMENT: starting replacement algorithm...');
	[ d, cost, avgRT, cdfRTindex, cdfRTvalue, evaluations, time, nrefactorings ] = ...
		refactor(qn, scAlt, mgAlt, maxDup, 0, c, res, seed);	
elseif strcmp(algorithm, 'reassignment')
	disp('EXPERIMENT: starting reassignment algorithm...');
	[ d, cost, avgRT, cdfRTindex, cdfRTvalue, evaluations, time, nrefactorings ] = ...
		refactor(qn, [], [], maxDup, 10, c, res, seed);		
elseif strcmp(algorithm, 'full')
	disp('EXPERIMENT: starting full refactoring algorithm...');
	[ d, cost, avgRT, cdfRTindex, cdfRTvalue, evaluations, time, nrefactorings ] = ...
		refactor(qn, scAlt, mgAlt, maxDup, 10, c, res, seed);
else
	error('Algorithm not valid!');
end

disp(['EXPERIMENT: Saving the results in ' filename]);
save(filename, 'filename', 'd', 'cost', 'avgRT', 'cdfRTindex', 'cdfRTvalue', ...
	'evaluations', 'time', 'nrefactorings', 'users', 'profile', 'sc2', ...
	'mg34', 'maxDup', 'availability', 'algorithm', 'seed');

d
cost
avgRT
RT80=cdfRTvalue(cdfRTindex==0.8)
ecu=sum(sum(d))
evaluations
time
nrefactorings
%cdfRTvalue

disp(['EXPERIMENT: completed in ' num2str(time) 'seconds.']);

end % end function



