#include "FirstOptScheduling.h"

FirstOptScheduling::FirstOptScheduling()
{

}

FirstOptScheduling::~FirstOptScheduling()
{

}

double FirstOptScheduling::pressureDifference(const std::vector<double>& HC, const std::vector<double>& HF)
{
	if (HC.size() != HF.size())
		return 0;

	size_t total = HC.size();
	double result = 0.0;
	for (int i = 0; i < total; i++)
	{
		result += (HC[i] - HF[i]);
	}
	return result;
}

double FirstOptScheduling::pumpPower(const PumpStruct& pumpParam)
{
	std::vector<double>  s1 =  pumpParam.mS1;
	double a = pumpParam.a;

	int total = s1.size();
	double result = 0.0;
	for (int i = 0; i < total; i++)
	{
		result += s1[i];
		// 第i个泵站的定速泵和调速泵的总数
		int columns = pumpParam.mK[i] + pumpParam.mP[i];

		double temp = 0.0; 
		for (int j = 0; j < columns; j++)
		{
			temp +=( (a*pumpParam.mNS[i][j]*pumpParam.mQS[i][j]  \
				*pumpParam.mHS[i][j])/(pumpParam.mX[i][j]*pumpParam.mY[i][j]));
		}
		temp *= pumpParam.mS2[i];
		result += temp;

	}
	return result;
}

double FirstOptScheduling::waterProductionCost(const vector<double>& Q, const vector<double>& S3)
{
	if (Q.size() != S3.size())
		return 0;

	int total = Q.size();
	double result = 0;
	for (int i = 0; i < total; i++)
	{
		result += (Q[i] * S3[i]);
	}

	return result;
}

double FirstOptScheduling::waterSupplyAndDemand(const vector<double>& Q, const double& Qd)
{
	size_t total = Q.size();
	double result = 0;
	for (int i = 0; i < total; i++)
	{
		result += Q[i];
	}

	return std::abs(result - Qd);
}

double FirstOptScheduling::objectiveFunction(float cost, const map<string, double>& monitorVals)
{
	// 适应度函数简易版
	float sum = 0.0;
	map<string, double>::const_iterator conIter = monitorVals.cbegin();
	for (; conIter != monitorVals.cend(); conIter++)
	{
		string key = conIter->first;
		double val = conIter->second;

		map<string, double>::iterator minIter = mMinMonitorVals.find(key);
		if (minIter == mMinMonitorVals.end())
			continue;

		map<string, double>::iterator maxIter = mMaxMonitorVals.find(key);
		if(maxIter == mMaxMonitorVals.end())
			continue;

		float minVal = minIter->second;
		float maxVal = maxIter->second;
		float maxMinDiff =maxVal - minVal;

		if (val < minVal)
		{
			sum += ((val - minVal ) / maxMinDiff);
		}	
		else if (val > maxVal)
		{
			sum += ((maxVal- val ) / maxMinDiff);
		}			
	}

	return 1 / (C1 + cost) * (1 + (double)sum);
}