#include "model.h"

#define M_COUNT 3 
#define O_COUNT 3 
#define R_COUNT 2 

struct ddpStruct
{
	float oWeight[O_COUNT+1];
	float oAttainment[O_COUNT+1];
	float oAtRiskProp[O_COUNT+1];
	float rAPL[R_COUNT+1];
	float rAggrevatedImpact[R_COUNT+1];
	float rLikelihood[R_COUNT+1];
	float mCost[M_COUNT+1];
	float roImpact[R_COUNT+1][O_COUNT+1];
	float mrEffect[M_COUNT+1][R_COUNT+1];
};

ddpStruct *ddpData;

void setupModel(void)
{
	ddpData = (ddpStruct *) malloc(sizeof(ddpStruct));
	ddpData->mCost[1]= 11;
	ddpData->mCost[2]= 22;
	ddpData->mCost[3]= 0;
	ddpData->rAPL[1]=0.4;
	ddpData->rAPL[2]=1;
	ddpData->oWeight[1]=1;
	ddpData->oWeight[2]=2;
	ddpData->oWeight[3]=3;
	ddpData->roImpact[1][1] = 0.1;
	ddpData->roImpact[1][2] = 0.3;
	ddpData->roImpact[2][1] = 0.2;
	ddpData->mrEffect[1][1] = -0.2;
	ddpData->mrEffect[2][1] = 0.1;
	ddpData->mrEffect[3][1] = -1.7;
	ddpData->mrEffect[1][2] = 0.3;
}
void model(float *cost, float *att, float m[])
{
	float costTotal, attTotal;

	//Since these values may change in each call to this function, they cannot be set in setup function. They must be re-entered everytime here.
	ddpData->rAggrevatedImpact[1]=1;
	ddpData->rAggrevatedImpact[2]=1;
	ddpData->rLikelihood[1] = ddpData->rAPL[1];
	ddpData->rLikelihood[2] = ddpData->rAPL[2];
	
	/* Mitigation effects on Risk likelihoods */
	/* Phase 1 Mitigation effects */
	ddpData->rLikelihood[1] = minValue(1, (ddpData->rLikelihood[1] - m[1] * ddpData->mrEffect[1][1]));
	ddpData->rAggrevatedImpact[1] = ddpData->rAggrevatedImpact[1] * (1 - m[3] * (1 + ddpData->mrEffect[3][1]));
	ddpData->rLikelihood[2] = ddpData->rLikelihood[2] * (1 - m[1] * ddpData->mrEffect[1][2]);
	/* Phase 2 Mitigation effects */
	ddpData->rLikelihood[1] = ddpData->rLikelihood[1] * (1 - m[2] * ddpData->mrEffect[2][1]);
	/* Phase 3 Mitigation effects */
	/* Risk impacts on Objective attainment proportions */
	ddpData->oAtRiskProp[1] = (ddpData->rLikelihood[1] * ddpData->rAggrevatedImpact[1] * ddpData->roImpact[1][1]) + (ddpData->rLikelihood[2] * ddpData->rAggrevatedImpact[2] * ddpData->roImpact[2][1]);
	ddpData->oAtRiskProp[2] = (ddpData->rLikelihood[1] * ddpData->rAggrevatedImpact[1] * ddpData->roImpact[1][2]);
	ddpData->oAtRiskProp[3] = 0;
	/* Objective attainments */
	ddpData->oAttainment[1] = ddpData->oWeight[1] * (1 - minValue(1, ddpData->oAtRiskProp[1]));
	ddpData->oAttainment[2] = ddpData->oWeight[2] * (1 - minValue(1, ddpData->oAtRiskProp[2]));
	ddpData->oAttainment[3] = ddpData->oWeight[3] * (1 - minValue(1, ddpData->oAtRiskProp[3]));
	attTotal = ddpData->oAttainment[1] + ddpData->oAttainment[2] + ddpData->oAttainment[3];
	costTotal = m[1] * ddpData->mCost[1] + m[2] * ddpData->mCost[2] + m[3] * ddpData->mCost[3];

	*cost = costTotal;
	*att = attTotal;
}
