#include "project.h"

project::project() {
    initialize();
}

project::~project() {
}
void project::initialize() {
    //initialization

    ///////////////////////////////////////////////////////////////////////////////////
//Attribute and slope ranges. This is modified according to project files
///////////////////////////////////////////////////////////////////////////////////
	double attrangeNormTemp[] = {1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.000, -0.183, 0.08, 0.00, -0.208, 0.100, 0.00, -0.190, 0.110, -1.560, 0.073, -0.178, 2.00, 0.55, 1, 3, 0.28, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 0.112, -0.035, 0.14, 0.14, -0.048, 0.156, 0.14, -0.053, 0.176, -1.014, 0.210, -0.078, 11.0, 0.997973, 980, 3.67, 0.33};

	for (int i=0; i<2; i++) {
		for (int j=0; j<ATTN; j++) {
			attrangeNorm[i][j]= attrangeNormTemp[ATTN*i+j];
		}
	}

	//{{1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.000, -0.183, 0.08, 0.00, -0.208, 0.100, 0.00, -0.190, 0.110, -1.560, 0.073, -0.178, 2.00, 0.55, 1},{6, 6, 6, 5, 5, 5, 5, 5, 6, 6, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 0.112, -0.035, 0.14, 0.14, -0.048, 0.156, 0.14, -0.053, 0.176, -1.014, 0.210, -0.078, 11.0, 0.997973, 980}};
///////////////////////////////////////////////////////////////////////////////////

    pRSlope=0.052;
    nRSlope=-0.100;
    dfrRSlope=0.113;

    pDSlope=0.072;
    nDSlope=-0.105;
    dfrDSlope=0.132;

    pCSlope=0.072;
    nCSlope=-0.106;
    dfrCSlope=0.151;

    SFSlope=-1.265;
    posEMSlope=0.140;
    negEMSlope=-0.109;

    A=6.51;
    B=0.77;
    C=3.335;
    D=0.305;

    ksloc=100;

    for (int i=0; i<25; i++)
        attributes[i]=0;


    //defect removal schemes
    automated_analysis=0;
    peer_reviews=0;
    execution_testing_and_tools=0;

    //scale factors
    prec=0;
    flex=0;
    resl=0;
    team=0;
    pmat=0;

    //effort multipliers
    time=0;
    stor=0;
    data=0;
    pvol=0;
    ruse=0;
    rely=0;
    docu=0;
    acap=0;
    pcap=0;
    pcon=0;
    apex=0;
    plex=0;
    ltex=0;
    tool=0;
    sced=0;
    cplx=0;
    site=0;

    pCoqualRSlope=pRSlope;
    nCoqualRSlope=nRSlope;
    dfrCoqualRSlope=dfrRSlope;

    pCoqualDSlope=pDSlope;
    nCoqualDSlope=nDSlope;
    dfrCoqualDSlope=dfrDSlope;

    pCoqualCSlope=pCSlope;
    nCoqualCSlope=nCSlope;
    dfrCoqualCSlope=dfrCSlope;

    SFCocomoSlope=SFSlope;
    posEMCocomoSlope=posEMSlope;
    negEMCocomoSlope=negEMSlope;
}
//The regulated CocomoII model
double project::SFCocomo(double rating) {return (double)(rating-6)*SFCocomoSlope;}
double project::posEMCocomo(double rating) {return (double)(rating-3)*posEMCocomoSlope + 1;}
double project::negEMCocomo(double rating) {return (double)(rating-3)*negEMCocomoSlope + 1;}

//cocomoII stuff
double project::fprec() {return SFCocomo(prec);}
double project::fflex() {return SFCocomo(flex);}
double project::fresl() {return SFCocomo(resl);}
double project::fteam() {return SFCocomo(team);}
double project::fpmat() {return SFCocomo(pmat);}
double project::ftime() {return posEMCocomo(time);}
double project::fstor() {return posEMCocomo(stor);}
double project::fdata() {return posEMCocomo(data);}
double project::fpvol() {return posEMCocomo(pvol);}
double project::fruse() {return posEMCocomo(ruse);}
double project::frely() {
	int relyLB = rely + (automated_analysis-3>0? automated_analysis-3 : 0)
	+ (execution_testing_and_tools-3>0? execution_testing_and_tools-3 : 0)
	+ (peer_reviews-3>0? peer_reviews-3 : 0);
	return posEMCocomo(5>relyLB? relyLB : 5);}
double project::fcplx() {return posEMCocomo(cplx);}
double project::fdocu() {return posEMCocomo(docu);}
double project::fsced() {return negEMCocomo(sced);}
double project::facap() {return negEMCocomo(acap);}
double project::fpcap() {return negEMCocomo(pcap);}
double project::fpcon() {return negEMCocomo(pcon);}
double project::fapex() {return negEMCocomo(apex);}
double project::fltex() {return negEMCocomo(ltex);}
double project::ftool() {
	int toolLB = tool + (automated_analysis-3>0? automated_analysis-3 : 0)
		+ (execution_testing_and_tools-3>0? execution_testing_and_tools-3 : 0);
	return negEMCocomo(5>toolLB? toolLB : 5);}
double project::fsite() {return negEMCocomo(site);}
double project::fplex() {return negEMCocomo(plex);}

double project::getattnum(int attnum) {
    switch (attnum) {
        case 0: return automated_analysis; break;
        case 1: return peer_reviews; break;
        case 2: return execution_testing_and_tools; break;
        case 3: return prec; break;
        case 4: return flex; break;
        case 5: return resl; break;
        case 6: return team; break;
        case 7: return pmat; break;
        case 8: return time; break;
        case 9: return stor; break;
        case 10: return data; break;
        case 11: return pvol; break;
        case 12: return ruse; break;
        case 13: return rely; break;
        case 14: return docu; break;
        case 15: return acap; break;
        case 16: return pcap; break;
        case 17: return pcon; break;
        case 18: return apex; break;
        case 19: return plex; break;
        case 20: return ltex; break;
        case 21: return tool; break;
        case 22: return sced; break;
        case 23: return cplx; break;
        case 24: return site; break;
        //Slopes, A, B and Ksloc
        case 25: return pCoqualRSlope; break;
        case 26: return nCoqualRSlope; break;
        case 27: return dfrCoqualRSlope; break;
        case 28: return pCoqualDSlope; break;
        case 29: return nCoqualDSlope; break;
        case 30: return dfrCoqualDSlope; break;
        case 31: return pCoqualCSlope; break;
        case 32: return nCoqualCSlope; break;
        case 33: return dfrCoqualCSlope; break;
        case 34: return SFCocomoSlope; break;
        case 35: return posEMCocomoSlope; break;
        case 36: return negEMCocomoSlope; break;
        case 37: return A; break;
        case 38: return B; break;
        case 39: return ksloc; break;
        case 40: return C; break;
        case 41: return D; break;
        default: return 0.0; break;
    }
}

double project::getattnumvaleff(int attnum) {
    switch (attnum) {
        case 1: return fprec(); break;
        case 2: return fflex(); break;
        case 3: return fresl(); break;
        case 4: return fteam(); break;
        case 5: return fpmat(); break;
        case 6: return ftime(); break;
        case 7: return fstor(); break;
        case 8: return fdata(); break;
        case 9: return fpvol(); break;
        case 10: return fruse(); break;
        case 11: return frely(); break;
        case 12: return fdocu(); break;
        case 13: return facap(); break;
        case 14: return fpcap(); break;
        case 15: return fpcon(); break;
        case 16: return fapex(); break;
        case 17: return fplex(); break;
        case 18: return fltex(); break;
        case 19: return ftool(); break;
        case 20: return fsced(); break;
        case 21: return fcplx(); break;
        case 22: return fsite(); break;
        default: return 0.0; break;
    }
}

double project::getattnumvaldefR(int attnum) {
    switch (attnum) {
        case 0: return automated_analysisR(); break;
        case 1: return peer_reviewsR(); break;
        case 2: return execution_testing_and_toolsR(); break;
        case 3: return precR(); break;
        case 4: return flexR(); break;
        case 5: return reslR(); break;
        case 6: return teamR(); break;
        case 7: return pmatR(); break;
        case 8: return timeR(); break;
        case 9: return storR(); break;
        case 10: return dataR(); break;
        case 11: return pvolR(); break;
        case 12: return ruseR(); break;
        case 13: return relyR(); break;
        case 14: return docuR(); break;
        case 15: return acapR(); break;
        case 16: return pcapR(); break;
        case 17: return pconR(); break;
        case 18: return apexR(); break;
        case 19: return plexR(); break;
        case 20: return ltexR(); break;
        case 21: return toolR(); break;
        case 22: return scedR(); break;
        case 23: return cplxR(); break;
        case 24: return siteR(); break;
        default: return 0.0; break;
    }
}

double project::getattnumvaldefD(int attnum) {
    switch (attnum) {
        case 0: return automated_analysisD(); break;
        case 1: return peer_reviewsD(); break;
        case 2: return execution_testing_and_toolsD(); break;
        case 3: return precD(); break;
        case 4: return flexD(); break;
        case 5: return reslD(); break;
        case 6: return teamD(); break;
        case 7: return pmatD(); break;
        case 8: return timeD(); break;
        case 9: return storD(); break;
        case 10: return dataD(); break;
        case 11: return pvolD(); break;
        case 12: return ruseD(); break;
        case 13: return relyD(); break;
        case 14: return docuD(); break;
        case 15: return acapD(); break;
        case 16: return pcapD(); break;
        case 17: return pconD(); break;
        case 18: return apexD(); break;
        case 19: return plexD(); break;
        case 20: return ltexD(); break;
        case 21: return toolD(); break;
        case 22: return scedD(); break;
        case 23: return cplxD(); break;
        case 24: return siteD(); break;
        default: return 0.0; break;
    }
}

double project::getattnumvaldefC(int attnum) {
    switch (attnum) {
        case 0: return automated_analysisC(); break;
        case 1: return peer_reviewsC(); break;
        case 2: return execution_testing_and_toolsC(); break;
        case 3: return precC(); break;
        case 4: return flexC(); break;
        case 5: return reslC(); break;
        case 6: return teamC(); break;
        case 7: return pmatC(); break;
        case 8: return timeC(); break;
        case 9: return storC(); break;
        case 10: return dataC(); break;
        case 11: return pvolC(); break;
        case 12: return ruseC(); break;
        case 13: return relyC(); break;
        case 14: return docuC(); break;
        case 15: return acapC(); break;
        case 16: return pcapC(); break;
        case 17: return pconC(); break;
        case 18: return apexC(); break;
        case 19: return plexC(); break;
        case 20: return ltexC(); break;
        case 21: return toolC(); break;
        case 22: return scedC(); break;
        case 23: return cplxC(); break;
        case 24: return siteC(); break;
        default: return 0.0; break;
    }
}

void project::setattnum(int attnum, double rating) {
    switch (attnum) {
        case 0: sautomated_analysis(rating); break;
        case 1: speer_reviews(rating); break;
        case 2: sexecution_testing_and_tools(rating); break;
        case 3: sprec(rating); break;
        case 4: sflex(rating); break;
        case 5: sresl(rating); break;
        case 6: steam(rating); break;
        case 7: spmat(rating); break;
        case 8: stime(rating); break;
        case 9: sstor(rating); break;
        case 10: sdata(rating); break;
        case 11: spvol(rating); break;
        case 12: sruse(rating); break;
        case 13: srely(rating); break;
        case 14: sdocu(rating); break;
        case 15: sacap(rating); break;
        case 16: spcap(rating); break;
        case 17: spcon(rating); break;
        case 18: sapex(rating); break;
        case 19: splex(rating); break;
        case 20: sltex(rating); break;
        case 21: stool(rating); break;
        case 22: ssced(rating); break;
        case 23: scplx(rating); break;
        case 24: ssite(rating); break;
        //Slopes, A, B and Ksloc
        case 25: spCoqualRSlope(rating); break;
        case 26: snCoqualRSlope(rating);break;
        case 27: sdfrCoqualRSlope(rating);break;
        case 28: spCoqualDSlope(rating);break;
        case 29: snCoqualDSlope(rating);break;
        case 30: sdfrCoqualDSlope(rating);break;
        case 31: spCoqualCSlope(rating);break;
        case 32: snCoqualCSlope(rating);break;
        case 33: sdfrCoqualCSlope(rating);break;
        case 34: sSFCocomoSlope(rating);break;
        case 35: sposEMCocomoSlope(rating);break;
        case 36: snegEMCocomoSlope(rating);break;
        case 37: sA(rating); break;
        case 38: sB(rating); break;
        case 39: sKsloc(rating); break;
        case 40: sC(rating); break;
        case 41: sD(rating); break;
    }
}

double project::setatt(double rating, double min, double max) {
    if (rating > max) return max;
    else if (rating < min) return min;
    else return rating;
}

void project::sprec(double rating) {
    double min=1;double max=6;
    attributes[3]=prec=setatt(rating, min, max);
}
void project::sflex(double rating) {
    double min=1;double max=6;
    attributes[4]=flex=setatt(rating, min, max);
}
void project::sresl(double rating) {
    double min=1;double max=6;
    attributes[5]=resl=setatt(rating, min, max);
}
void project::steam(double rating) {
    double min=1;double max=6;
    attributes[6]=team=setatt(rating, min, max);
}
void project::spmat(double rating) {
    double min=1;double max=6;
    attributes[7]=pmat=setatt(rating, min, max);
}

void project::stime(double rating) {
    double min=3;double max=6;
    attributes[8]=time=setatt(rating, min, max);
}
void project::sstor(double rating) {
    double min=3;double max=6;
    attributes[9]=stor=setatt(rating, min, max);
}
void project::sdata(double rating) {
    double min=2;double max=5;
    attributes[10]=data=setatt(rating, min, max);
}
void project::spvol(double rating) {
    double min=2;double max=5;
    attributes[11]=pvol=setatt(rating, min, max);
}
void project::sruse(double rating) {
    double min=2;double max=6;
    attributes[12]=ruse=setatt(rating, min, max);
}
void project::srely(double rating) {
    double min=1;double max=5;
    attributes[13]=rely=setatt(rating, min, max);
}
void project::ssced(double rating) {
    double min=1;double max=5;
    attributes[22]=sced=setatt(rating, min, max);
}
void project::scplx(double rating) {
    double min=1;double max=6;
    attributes[23]=cplx=setatt(rating, min, max);
}
void project::sdocu(double rating) {
    double min=1;double max=5;
    attributes[14]=docu=setatt(rating, min, max);
}

void project::sacap(double rating) {
    double min=1;double max=5;
    attributes[15]=acap=setatt(rating, min, max);
}
void project::spcap(double rating) {
    double min=1;double max=5;
    attributes[16]=pcap=setatt(rating, min, max);
}
void project::spcon(double rating) {
    double min=1;double max=5;
    attributes[17]=pcon=setatt(rating, min, max);
}
void project::sapex(double rating) {
    double min=1;double max=5;
    attributes[18]=apex=setatt(rating, min, max);
}
void project::sltex(double rating) {
    double min=1;double max=5;
    attributes[20]=ltex=setatt(rating, min, max);
}
void project::stool(double rating) {
    double min=1;double max=5;
    attributes[21]=tool=setatt(rating, min, max);
}
void project::ssite(double rating) {
    double min=1;double max=6;
    attributes[24]=site=setatt(rating, min, max);
}
void project::splex(double rating) {
    double min=1;double max=5;
    attributes[19]=plex=setatt(rating, min, max);
}

void project::sautomated_analysis(double rating) {
    double min=1;double max=6;
    attributes[0]=automated_analysis=setatt(rating, min, max);
}
void project::speer_reviews(double rating) {
    double min=1;double max=6;
    attributes[1]=peer_reviews=setatt(rating, min, max);
}
void project::sexecution_testing_and_tools(double rating) {
    double min=1;double max=6;
    attributes[2]=execution_testing_and_tools=setatt(rating, min, max);
}

void project::spCoqualRSlope(double val) {attributes[25]=pCoqualRSlope=val;}
void project::snCoqualRSlope(double val) {attributes[26]=nCoqualRSlope=val;}
void project::sdfrCoqualRSlope(double val) {attributes[27]=dfrCoqualRSlope=val;}

void project::spCoqualDSlope(double val) {attributes[28]=pCoqualDSlope=val;}
void project::snCoqualDSlope(double val) {attributes[29]=nCoqualDSlope=val;}
void project::sdfrCoqualDSlope(double val) {attributes[30]=dfrCoqualDSlope=val;}

void project::spCoqualCSlope(double val) {attributes[31]=pCoqualCSlope=val;}
void project::snCoqualCSlope(double val) {attributes[32]=nCoqualCSlope=val;}
void project::sdfrCoqualCSlope(double val) {attributes[33]=dfrCoqualCSlope=val;}

void project::sSFCocomoSlope(double val) {attributes[34]=SFCocomoSlope=val;}
void project::sposEMCocomoSlope(double val) {attributes[35]=posEMCocomoSlope=val;}
void project::snegEMCocomoSlope(double val) {attributes[36]=negEMCocomoSlope=val;}

void project::sA(double val) {
	if (val==0.0) {
	    randomNum rdm;
	    attributes[37]=A=((B-(1.075-rdm.randomGenerateDouble(0.0, 0.1)))/(-0.0385135));
	    if(A<attrangeNorm[0][37]) attributes[37]=A=attrangeNorm[0][37];
	    if(A>attrangeNorm[1][37]) attributes[37]=A=attrangeNorm[1][37];
	}
	else {
		attributes[37]=A=val; sB(0.0);
	}
}
void project::sB(double val) {
	if (val==0.0) {
	    randomNum rdm;
	    attributes[38]=B=(-0.0385135*A+(1.075-rdm.randomGenerateDouble(0.0, 0.1)));
	    if(B<attrangeNorm[0][38]) attributes[38]=B=attrangeNorm[0][38];
	    if(B>attrangeNorm[1][38]) attributes[38]=B=attrangeNorm[1][38];
	}
	else {
		attributes[38]=B=val; sA(0.0);
	}
}

void project::sKsloc(double val) {attributes[39]=ksloc=val;}

void project::sC(double val) {attributes[40]=C=val;}

void project::sD(double val) {attributes[41]=D=val;}

string project::displayAttName(int attnum) {
    switch (attnum) {
        case 0: return "automated_analysis"; break;
        case 1: return "peer_reviews"; break;
        case 2: return "execution_testing_and_tools"; break;
        case 3: return "prec"; break;
        case 4: return "flex"; break;
        case 5: return "resl"; break;
        case 6: return "team"; break;
        case 7: return "pmat"; break;
        case 8: return "time"; break;
        case 9: return "stor"; break;
        case 10: return "data"; break;
        case 11: return "pvol"; break;
        case 12: return "ruse"; break;
        case 13: return "rely"; break;
        case 14: return "docu"; break;
        case 15: return "acap"; break;
        case 16: return "pcap"; break;
        case 17: return "pcon"; break;
        case 18: return "apex"; break;
        case 19: return "plex"; break;
        case 20: return "ltex"; break;
        case 21: return "tool"; break;
        case 22: return "sced"; break;
        case 23: return "cplx"; break;
        case 24: return "site"; break;
        //Slopes, A, B and Ksloc
        case 25: return "pCoqualRSlope"; break;
        case 26: return "nCoqualRSlope"; break;
        case 27: return "dfrCoqualRSlope"; break;
        case 28: return "pCoqualDSlope"; break;
        case 29: return "nCoqualDSlope"; break;
        case 30: return "dfrCoqualDSlope"; break;
        case 31: return "pCoqualCSlope"; break;
        case 32: return "nCoqualCSlope"; break;
        case 33: return "dfrCoqualCSlope"; break;
        case 34: return "SFCocomoSlope"; break;
        case 35: return "posEMCocomoSlope"; break;
        case 36: return "negEMCocomoSlope"; break;
        case 37: return "A"; break;
        case 38: return "B"; break;
        case 39: return "Ksloc"; break;
        case 40: return "C"; break;
        case 41: return "D"; break;
        default: return ""; break;
    }
}

void project::displayAtt(int attnum) {
    switch (attnum) {
        case 0: dispautomated_analysis(); break;
        case 1: disppeer_reviews(); break;
        case 2: dispexecution_testing_and_tools(); break;
        case 3: dispprec(); break;
        case 4: dispflex(); break;
        case 5: dispresl(); break;
        case 6: dispteam(); break;
        case 7: disppmat(); break;
        case 8: disptime(); break;
        case 9: dispstor(); break;
        case 10: dispdata(); break;
        case 11: disppvol(); break;
        case 12: dispruse(); break;
        case 13: disprely(); break;
        case 14: dispdocu(); break;
        case 15: dispacap(); break;
        case 16: disppcap(); break;
        case 17: disppcon(); break;
        case 18: dispapex(); break;
        case 19: dispplex(); break;
        case 20: displtex(); break;
        case 21: disptool(); break;
        case 22: dispsced(); break;
        case 23: dispcplx(); break;
        case 24: dispsite(); break;
        //Slopes, A, B and Ksloc
        case 25: disppCoqualRSlope(); break;
        case 26: dispnCoqualRSlope();break;
        case 27: dispdfrCoqualRSlope();break;
        case 28: disppCoqualDSlope();break;
        case 29: dispnCoqualDSlope();break;
        case 30: dispdfrCoqualDSlope();break;
        case 31: disppCoqualCSlope();break;
        case 32: dispnCoqualCSlope();break;
        case 33: dispdfrCoqualCSlope();break;
        case 34: dispSFCocomoSlope();break;
        case 35: dispposEMCocomoSlope();break;
        case 36: dispnegEMCocomoSlope();break;
        case 37: dispA(); break;
        case 38: dispB(); break;
        case 39: dispKsloc(); break;
        case 40: dispC(); break;
        case 41: dispD(); break;
    }
}

void project::dispprec() {cout << "prec: " << prec << endl;}
void project::dispflex() {cout << "flex: " << flex << endl;}
void project::dispresl() {cout << "resl: " << resl << endl;}
void project::dispteam() {cout << "team: " << team << endl;}
void project::disppmat() {cout << "pmat: " << pmat << endl;}

void project::disptime() {cout << "time: " << time << endl;}
void project::dispstor() {cout << "stor: " << stor << endl;}
void project::dispdata() {cout << "data: " << data << endl;}
void project::disppvol() {cout << "pvol: " << pvol << endl;}
void project::dispruse() {cout << "ruse: " << ruse << endl;}
void project::disprely() {cout << "rely: " << rely << endl;}
void project::dispdocu() {cout << "docu: " << docu << endl;}
void project::dispacap() {cout << "acap: " << acap << endl;}
void project::disppcap() {cout << "pcap: " << pcap << endl;}
void project::disppcon() {cout << "pcon: " << pcon << endl;}
void project::dispapex() {cout << "apex: " << apex << endl;}
void project::displtex() {cout << "ltex: " << ltex << endl;}
void project::disptool() {cout << "tool: " << tool << endl;}
void project::dispsced() {cout << "sced: " << sced << endl;}
void project::dispcplx() {cout << "cplx: " << cplx << endl;}
void project::dispsite() {cout << "site: " << site << endl;}
void project::dispplex() {cout << "plex: " << plex << endl;}

void project::dispautomated_analysis() {cout << "automated_analysis: " << automated_analysis << endl;}
void project::disppeer_reviews() {cout << "peer_reviews: " << peer_reviews << endl;}
void project::dispexecution_testing_and_tools() {cout << "execution_testing_and_tools: " << execution_testing_and_tools << endl;}

void project::disppCoqualRSlope() {cout << "pCoqualRSlope: " << pCoqualRSlope << endl;}
void project::dispnCoqualRSlope() {cout << "nCoqualRSlope: " << nCoqualRSlope << endl;}
void project::dispdfrCoqualRSlope() {cout << "dfrCoqualRSlope: " << dfrCoqualRSlope << endl;}
void project::disppCoqualDSlope() {cout << "pCoqualDSlope: " << pCoqualDSlope << endl;}
void project::dispnCoqualDSlope() {cout << "nCoqualDSlope: " << nCoqualDSlope << endl;}
void project::dispdfrCoqualDSlope() {cout << "dfrCoqualDSlope: " << dfrCoqualDSlope << endl;}
void project::disppCoqualCSlope() {cout << "pCoqualCSlope: " << pCoqualCSlope << endl;}
void project::dispnCoqualCSlope() {cout << "nCoqualCSlope: " << nCoqualCSlope << endl;}
void project::dispdfrCoqualCSlope() {cout << "dfrCoqualCSlope: " << dfrCoqualCSlope << endl;}
void project::dispSFCocomoSlope() {cout << "SFCocomoSlope: " << SFCocomoSlope << endl;}
void project::dispposEMCocomoSlope() {cout << "posEMCocomoSlope: " << posEMCocomoSlope << endl;}
void project::dispnegEMCocomoSlope() {cout << "negEMCocomoSlope: " << negEMCocomoSlope << endl;}
void project::dispA() {cout << "A: " << A << endl;}
void project::dispB() {cout << "B: " << B << endl;}
void project::dispKsloc() {cout << "ksloc: " << ksloc << endl;}
void project::dispC() {cout << "C: " << C << endl;}
void project::dispD() {cout << "D: " << D << endl;}

double project::effort() {
    return A*(pow(ksloc, (B+0.01*(fprec()+fflex()+fresl()+fteam()+fpmat()))))
            *(ftime()*fstor()*fdata()*fpvol()*fruse()*frely()*fdocu()*facap()*fpcap()*
            fpcon()*fapex()*fplex()*fltex()*ftool()*fsced()*fcplx()*fsite());
}

//Time to develop Model
//
double project::pmNs(){
    return (A*pow(ksloc, (B+0.01*(fprec()+fflex()+fresl()+fteam()+fpmat())))
            *(ftime()*fstor()*fdata()*fpvol()*fruse()*frely()*fdocu()*facap()*fpcap()*
            fpcon()*fapex()*fplex()*fltex()*ftool()*fcplx()*fsite()));
}

double project::scedpercent(){
    switch((int)round(sced)){
        case 1: return(75);
        case 2: return(85);
        case 3: return(100);
        case 4: return(130);
        case 5: return(160);
    }
}


double project::months(){
    return ((C*pow(pmNs(), (D+0.2*(0.01*(fprec()+fflex()+fresl()+fteam()+fpmat())))))*(scedpercent()/100));
}



//Threat model
//Threat model tables
double project::t1[5][5] = {{0, 0, 0, 1, 2},
							{0, 0, 0, 0, 1}};
double project::t2[5][6] = {{0, 0, 0, 1, 2, 4},
							{0, 0, 0, 0, 1, 2},
							{0, 0, 0, 0, 0, 1}};
double project::t3[5][5] = {{2, 1},
							{1}};
double project::t4[5][5] = {{4, 2, 1},
							{2, 1},
							{1}};
double project::t5[5][5] = {{0},
							{0},
							{1},
							{2, 1},
							{4, 2, 1}};
double project::t6[6][5] = {{0},
							{0},
							{0},
							{1},
							{2, 1},
							{4, 2, 1}};
double project::t7[5][5] = {{0},
							{0},
							{0},
							{1},
							{2, 1}};
double project::t8[6][5] = {{0},
							{0},
							{0},
							{0},
							{1},
							{2, 1}};

double project::threat() {
    double TH = (double)(sched_threat()+prod_threat()+pers_threat()+proc_threat()
    +plat_threat()+reuse_threat())/3.73;

    if (TH < 2.5) TH = 0.0000000000000001;
    return TH;
}

double project::sched_threat() {
    return (t1[(int)round(sced-1)][(int)round(rely-1)]*fsced()*frely()+t2[(int)round(sced-1)][(int)round(time-1)]*fsced()*ftime()+t1[(int)round(sced-1)][(int)round(pvol-1)]*fsced()*fpvol()+t3[(int)round(sced-1)][(int)round(tool-1)]*fsced()*ftool()+t4[(int)round(sced-1)][(int)round(acap-1)]*fsced()*facap()
            +t4[(int)round(sced-1)][(int)round(apex-1)]*fsced()*fapex()+t4[(int)round(sced-1)][(int)round(pcap-1)]*fsced()*fpcap()+t4[(int)round(sced-1)][(int)round(plex-1)]*fsced()*fplex()+t3[(int)round(sced-1)][(int)round(ltex-1)]*fsced()*fltex()+t3[(int)round(sced-1)][(int)round(pmat-1)]*fsced()*fpmat());
}

double project::prod_threat() {
    return (t5[(int)round(rely-1)][(int)round(acap-1)]*frely()*facap()+t5[(int)round(rely-1)][(int)round(pcap-1)]*frely()*fpcap()+t6[(int)round(cplx-1)][(int)round(acap-1)]*fcplx()*facap()+t6[(int)round(cplx-1)][(int)round(pcap-1)]*fcplx()*fpcap()+t6[(int)round(cplx-1)][(int)round(tool-1)]*fcplx()*ftool()
            +t5[(int)round(rely-1)][(int)round(pmat-1)]*frely()*fpmat()+t2[(int)round(sced-1)][(int)round(cplx-1)]*fsced()*fcplx()+t1[(int)round(sced-1)][(int)round(rely-1)]*fsced()*frely()+t2[(int)round(sced-1)][(int)round(time-1)]*fsced()*ftime()+t6[(int)round(ruse-1)][(int)round(apex-1)]*fruse()*fapex()
            +t6[(int)round(ruse-1)][(int)round(ltex-1)])*fruse()*fltex();
}

double project::pers_threat() {
    return (t3[(int)round(pmat-1)][(int)round(acap-1)]*fpmat()*facap()+t6[(int)round(stor-1)][(int)round(acap-1)]*fstor()*facap()+t6[(int)round(time-1)][(int)round(acap-1)]*ftime()*facap()+t3[(int)round(tool-1)][(int)round(acap-1)]*ftool()*facap()+t3[(int)round(tool-1)][(int)round(pcap-1)]*ftool()*fpcap()
            +t6[(int)round(ruse-1)][(int)round(apex-1)]*fruse()*fapex()+t6[(int)round(ruse-1)][(int)round(ltex-1)]*fruse()*fltex()+t3[(int)round(pmat-1)][(int)round(pcap-1)]*fpmat()*fpcap()+t6[(int)round(stor-1)][(int)round(pcap-1)]*fstor()*fpcap()+t6[(int)round(time-1)][(int)round(pcap-1)]*ftime()*fpcap()
            +t4[(int)round(ltex-1)][(int)round(pcap-1)]*fltex()*fpcap()+t7[(int)round(pvol-1)][(int)round(plex-1)]*fpvol()*fplex()+t4[(int)round(sced-1)][(int)round(acap-1)]*fsced()*facap()+t4[(int)round(sced-1)][(int)round(apex-1)]*fsced()*fapex()+t4[(int)round(sced-1)][(int)round(pcap-1)]*fsced()*fpcap()
            +t4[(int)round(sced-1)][(int)round(plex-1)]*fsced()*fplex()+t3[(int)round(sced-1)][(int)round(ltex-1)]*fsced()*fltex()+t5[(int)round(rely-1)][(int)round(acap-1)]*frely()*facap()+t5[(int)round(rely-1)][(int)round(pcap-1)]*frely()*fpcap()+t6[(int)round(cplx-1)][(int)round(acap-1)]*fcplx()*facap()
            +t6[(int)round(cplx-1)][(int)round(pcap-1)]*fcplx()*fpcap()+t3[(int)round(team-1)][(int)round(apex-1)]*fteam()*fapex());
}

double project::proc_threat() {
    return (t3[(int)round(tool-1)][(int)round(pmat-1)]*ftool()*fpmat()+t8[(int)round(time-1)][(int)round(tool-1)]*ftime()*ftool()+t3[(int)round(tool-1)][(int)round(pmat-1)]*ftool()*fpmat()+t3[(int)round(team-1)][(int)round(apex-1)]*fteam()*fapex()+t3[(int)round(team-1)][(int)round(sced-1)]*fteam()*fsced()
            +t3[(int)round(team-1)][(int)round(site-1)]*fteam()*fsite()+t3[(int)round(sced-1)][(int)round(tool-1)]*fsced()*ftool()+t3[(int)round(sced-1)][(int)round(pmat-1)]*fsced()*fpmat()+t6[(int)round(cplx-1)][(int)round(tool-1)]*fcplx()*ftool()+t3[(int)round(pmat-1)][(int)round(acap-1)]*fpmat()*facap()
            +t3[(int)round(tool-1)][(int)round(acap-1)]*ftool()*facap()+t3[(int)round(tool-1)][(int)round(pcap-1)]*ftool()*fpcap()+t3[(int)round(pmat-1)][(int)round(pcap-1)]*fpmat()*fpcap());
}

double project::plat_threat() {
    return (t2[(int)round(sced-1)][(int)round(time-1)]*fsced()*ftime()+t1[(int)round(sced-1)][(int)round(pvol-1)]*fsced()*fpvol()+t6[(int)round(stor-1)][(int)round(acap-1)]*fstor()*facap()+t6[(int)round(time-1)][(int)round(acap-1)]*ftime()*facap()+t6[(int)round(stor-1)][(int)round(pcap-1)]*fstor()*fpcap()
            +t7[(int)round(pvol-1)][(int)round(plex-1)]*fpvol()*fplex()+t8[(int)round(time-1)][(int)round(tool-1)]*ftime()*ftool());
}

double project::reuse_threat() {
    return (t6[(int)round(ruse-1)][(int)round(apex-1)]*fruse()*fapex()+t6[(int)round(ruse-1)][(int)round(ltex-1)]*fruse()*fltex());
}


double project::posCoqualR(double rating) {return (double)(rating-3)*pCoqualRSlope + 1;}
double project::negCoqualR(double rating) {return (double)(rating-3)*nCoqualRSlope + 1;}
double project::dfrCoqualR(double rating) {return (double)(rating-1)*dfrCoqualRSlope;}

double project::posCoqualD(double rating) {return (double)(rating-3)*pCoqualDSlope + 1;}
double project::negCoqualD(double rating) {return (double)(rating-3)*nCoqualDSlope + 1;}
double project::dfrCoqualD(double rating) {return (double)(rating-1)*dfrCoqualDSlope;}

double project::posCoqualC(double rating) {return (double)(rating-3)*pCoqualCSlope + 1;}
double project::negCoqualC(double rating) {return (double)(rating-3)*nCoqualCSlope + 1;}
double project::dfrCoqualC(double rating) {return (double)(rating-1)*dfrCoqualCSlope;}


double project::flexR() {return 1.0;}
double project::pcapR() {return 1.0;}

double project::ruseR() {return posCoqualR(ruse);}
double project::cplxR() {return posCoqualR(cplx);}
double project::timeR() {return posCoqualR(time);}
double project::storR() {return posCoqualR(stor);}
double project::pvolR() {return posCoqualR(pvol);}
double project::dataR() {return posCoqualR(data);}

double project::acapR() {return negCoqualR(acap);}
double project::pconR() {return negCoqualR(pcon);}
double project::apexR() {return negCoqualR(apex);}
double project::plexR() {return negCoqualR(plex);}
double project::ltexR() {return negCoqualR(ltex);}
double project::toolR() {return negCoqualR(tool);}
double project::siteR() {return negCoqualR(site);}
double project::scedR() {return negCoqualR(sced);}
double project::relyR() {return negCoqualR(rely);}
double project::docuR() {return negCoqualR(docu);}
double project::reslR() {return negCoqualR(resl);}
double project::teamR() {return negCoqualR(team);}
double project::pmatR() {return negCoqualR(pmat);}
double project::precR() {return negCoqualR(prec);}

double project::flexD() {return 1.0;}

double project::ruseD() {return posCoqualD(ruse);}
double project::cplxD() {return posCoqualD(cplx);}
double project::timeD() {return posCoqualD(time);}
double project::storD() {return posCoqualD(stor);}
double project::pvolD() {return posCoqualD(pvol);}
double project::dataD() {return posCoqualD(data);}

double project::acapD() {return negCoqualD(acap);}
double project::pconD() {return negCoqualD(pcon);}
double project::apexD() {return negCoqualD(apex);}
double project::plexD() {return negCoqualD(plex);}
double project::ltexD() {return negCoqualD(ltex);}
double project::toolD() {return negCoqualD(tool);}
double project::siteD() {return negCoqualD(site);}
double project::scedD() {return negCoqualD(sced);}
double project::relyD() {return negCoqualD(rely);}
double project::docuD() {return negCoqualD(docu);}
double project::reslD() {return negCoqualD(resl);}
double project::teamD() {return negCoqualD(team);}
double project::pmatD() {return negCoqualD(pmat);}
double project::precD() {return negCoqualD(prec);}
double project::pcapD() {return negCoqualD(pcap);}

double project::flexC() {return 1.0;}

double project::ruseC() {return posCoqualC(ruse);}
double project::cplxC() {return posCoqualC(cplx);}
double project::timeC() {return posCoqualC(time);}
double project::storC() {return posCoqualC(stor);}
double project::pvolC() {return posCoqualC(pvol);}
double project::dataC() {return posCoqualC(data);}

double project::acapC() {return negCoqualC(acap);}
double project::pconC() {return negCoqualC(pcon);}
double project::apexC() {return negCoqualC(apex);}
double project::plexC() {return negCoqualC(plex);}
double project::ltexC() {return negCoqualC(ltex);}
double project::toolC() {return negCoqualC(tool);}
double project::siteC() {return negCoqualC(site);}
double project::scedC() {return negCoqualC(sced);}
double project::relyC() {return negCoqualC(rely);}
double project::docuC() {return negCoqualC(docu);}
double project::reslC() {return negCoqualC(resl);}
double project::teamC() {return negCoqualC(team);}
double project::pmatC() {return negCoqualC(pmat);}
double project::precC() {return negCoqualC(prec);}
double project::pcapC() {return negCoqualC(pcap);}

double project::automated_analysisR() {
//	switch (automated_analysis) {
//		case 1: return 0.0; break;
//		case 2: return 0.0; break;
//		case 3: return 0.1; break;
//		case 4: return 0.27; break;
//		case 5: return 0.34; break;
//		case 6: return 0.4; break;
//		default: std::cout << "automated_analysis out of range\n"; return 0.0; break;
//	}

    return dfrCoqualR(automated_analysis);
}
double project::peer_reviewsR() {
//	switch (peer_reviews) {
//		case 1: return 0.0; break;
//		case 2: return 0.25; break;
//		case 3: return 0.4; break;
//		case 4: return 0.5; break;
//		case 5: return 0.58; break;
//		case 6: return 0.7; break;
//		default: std::cout << "peer_reviews out of range\n"; return 0.0; break;
//	}

    return dfrCoqualR(peer_reviews);
}
double project::execution_testing_and_toolsR() {
    return dfrCoqualR(execution_testing_and_tools);
}

double project::automated_analysisD() {
    return dfrCoqualD(automated_analysis);
}
double project::peer_reviewsD() {
    return dfrCoqualD(peer_reviews);
}
double project::execution_testing_and_toolsD() {
    return dfrCoqualD(execution_testing_and_tools);
}

double project::automated_analysisC() {
    return dfrCoqualC(automated_analysis);
}
double project::peer_reviewsC() {
    return dfrCoqualC(peer_reviews);
}
double project::execution_testing_and_toolsC() {
    return dfrCoqualC(execution_testing_and_tools);
}

double project::defectsIntroR() {
    return flexR()*pcapR()*ruseR()*cplxR()*timeR()*storR()*pvolR()*dataR()
            *acapR()*pconR()*apexR()*plexR()*ltexR()*toolR()*siteR()*scedR()*relyR()
            *docuR()*reslR()*teamR()*pmatR()*precR();
}
double project::defectsIntroD() {
    return flexD()*pcapD()*ruseD()*cplxD()*timeD()*storD()*pvolD()*dataD()
            *acapD()*pconD()*apexD()*plexD()*ltexD()*toolD()*siteD()*scedD()*relyD()
            *docuD()*reslD()*teamD()*pmatD()*precD();
}
double project::defectsIntroC() {
    return flexC()*pcapC()*ruseC()*cplxC()*timeC()*storC()*pvolC()*dataC()
            *acapC()*pconC()*apexC()*plexC()*ltexC()*toolC()*siteC()*scedC()*relyC()
            *docuC()*reslC()*teamC()*pmatC()*precC();
}

double project::defectsRemR() {
    return (1-automated_analysisR())*(1-peer_reviewsR())*(1-execution_testing_and_toolsR());
}

double project::defectsRemD() {
    return (1-automated_analysisD())*(1-peer_reviewsD())*(1-execution_testing_and_toolsD());
}

double project::defectsRemC() {
    return (1-automated_analysisC())*(1-peer_reviewsC())*(1-execution_testing_and_toolsC());
}

double project::defects() {
    return ksloc*(10*defectsIntroR()*defectsRemR()
            +20*defectsIntroD()*defectsRemD()
            +30*defectsIntroC()*defectsRemC());
}

double project::threatMutate() {
    randomNum rdm;
    double RNum;

    double tmp1 [5][5];
    double tmp2 [5][6];
    double tmp3 [5][5];
    double tmp4 [5][5];
    double tmp5 [5][5];
    double tmp6 [6][5];
    double tmp7 [5][5];
    double tmp8 [6][5];

    bool mutate[8] = {false, false, false, false, false, false, false, false};

    for (int i=0;i<8;i++) {
        RNum = rdm.randomGenerateDouble(0, 1.5);
        if (RNum > 0.5) {
            mutate[i]=true;
        }
    }


    if (mutate[0]) {
        RNum = rdm.randomGenerateDouble(0.5, 1.5);
        for (int i=0;i<5;i++) {
            for (int j=0;j<5;j++) {
                tmp1[i][j]=t1[i][j];
                t1[i][j]*=RNum;
            }
        }
    }

    if (mutate[1]) {
        RNum = rdm.randomGenerateDouble(0.5, 1.5);
        for (int i=0;i<5;i++) {
            for (int j=0;j<6;j++) {
                tmp2[i][j]=t2[i][j];
                t2[i][j]*=RNum;
            }
        }
    }

    if (mutate[2]) {
        RNum = rdm.randomGenerateDouble(0.5, 1.5);
        for (int i=0;i<5;i++) {
            for (int j=0;j<5;j++) {
                tmp3[i][j]=t3[i][j];
                t3[i][j]*=RNum;
            }
        }
    }

    if (mutate[3]) {
        RNum = rdm.randomGenerateDouble(0.5, 1.5);
        for (int i=0;i<5;i++) {
            for (int j=0;j<5;j++) {
                tmp4[i][j]=t4[i][j];
                t4[i][j]*=RNum;
            }
        }
    }

    if (mutate[4]) {
        RNum = rdm.randomGenerateDouble(0.5, 1.5);
        for (int i=0;i<5;i++) {
            for (int j=0;j<5;j++) {
                tmp5[i][j]=t5[i][j];
                t5[i][j]*=RNum;
            }
        }
    }

    if (mutate[5]) {
        RNum = rdm.randomGenerateDouble(0.5, 1.5);
        for (int i=0;i<6;i++) {
            for (int j=0;j<5;j++) {
                tmp6[i][j]=t6[i][j];
                t6[i][j]*=RNum;
            }
        }
    }

    if (mutate[6]) {
        RNum = rdm.randomGenerateDouble(0.5, 1.5);
        for (int i=0;i<5;i++) {
            for (int j=0;j<5;j++) {
                tmp7[i][j]=t7[i][j];
                t7[i][j]*=RNum;
            }
        }
    }

    if (mutate[7]) {
        RNum = rdm.randomGenerateDouble(0.5, 1.5);
        for (int i=0;i<6;i++) {
            for (int j=0;j<5;j++) {
                tmp8[i][j]=t8[i][j];
                t8[i][j]*=RNum;
            }
        }
    }

    double TH = threat();


    if (mutate[0]) {
        for (int i=0;i<5;i++) {
            for (int j=0;j<5;j++) {
                t1[i][j]=tmp1[i][j];
            }
        }

    }

    if (mutate[1]) {
        for (int i=0;i<5;i++) {
            for (int j=0;j<6;j++) {
                t2[i][j]=tmp2[i][j];
            }
        }
    }

    if (mutate[2]) {
        for (int i=0;i<5;i++) {
            for (int j=0;j<5;j++) {
                t3[i][j]=tmp3[i][j];
            }
        }
    }

    if (mutate[3]) {
        for (int i=0;i<5;i++) {
            for (int j=0;j<5;j++) {
                t4[i][j]=tmp4[i][j];
            }
        }
    }

    if (mutate[4]) {
        for (int i=0;i<5;i++) {
            for (int j=0;j<5;j++) {
                t5[i][j]=tmp5[i][j];
            }
        }
    }

    if (mutate[5]) {
        for (int i=0;i<6;i++) {
            for (int j=0;j<5;j++) {
                t6[i][j]=tmp6[i][j];
            }
        }
    }

    if (mutate[6]) {
        for (int i=0;i<5;i++) {
            for (int j=0;j<5;j++) {
                t7[i][j]=tmp7[i][j];
            }
        }
    }

    if (mutate[7]) {
        for (int i=0;i<6;i++) {
            for (int j=0;j<5;j++) {
                t8[i][j]=tmp8[i][j];
            }
        }
    }

    return TH;
}

double project::effortMutate() {

    project s = *this;

    double AttV [22] = {0};

    randomNum rdm;

    for (int i=0; i<22; i++) {
        for (int l=34; l<37; l++) {
            s.setattnum(l, rdm.randomGenerateDouble(s.attrangeNorm[0][l], s.attrangeNorm[1][l]));
        }

        AttV [i] = s.getattnumvaleff(i+1);
    }

    double SF = 0;

    for (int i=0; i<5; i++) {
        SF += AttV[i];
    }

    double EM = 1;

    for (int i=5; i<22; i++) {
        EM *= AttV[i];
    }

    double eff = 0;
    eff = s.A*(pow(s.ksloc, (s.B+(0.01*SF))))*EM;

    return eff;
}

double project::defectsMutate() {
    project s= *this;

    double AttVR [25] = {0};
    double AttVD [25] = {0};
    double AttVC [25] = {0};

    randomNum rdm;

    for (int i=0; i<25; i++) {
        for (int l=25; l<28; l++) {
            s.setattnum(l, rdm.randomGenerateDouble(s.attrangeNorm[0][l], s.attrangeNorm[1][l]));
        }

        AttVR [i] = s.getattnumvaldefR(i);
    }

    for (int i=0; i<25; i++) {
        for (int l=28; l<31; l++) {
            s.setattnum(l, rdm.randomGenerateDouble(s.attrangeNorm[0][l], s.attrangeNorm[1][l]));
        }

        AttVD [i] = s.getattnumvaldefD(i);
    }

    for (int i=0; i<25; i++) {
        for (int l=31; l<34; l++) {
            s.setattnum(l, rdm.randomGenerateDouble(s.attrangeNorm[0][l], s.attrangeNorm[1][l]));
        }

        AttVC [i] = s.getattnumvaldefC(i);
    }

    double defectsIntroR = 1;

    for (int i=3; i<25; i++) {
        defectsIntroR *= AttVR [i];
    }

    double defectsIntroD = 1;

    for (int i=3; i<25; i++) {
        defectsIntroD *= AttVD [i];
    }

    double defectsIntroC = 1;

    for (int i=3; i<25; i++) {
        defectsIntroC *= AttVC [i];
    }

    double defectsRemR = 1;

    for (int i=0; i<3; i++) {
        defectsRemR *= (1-AttVR [i]);
    }

    double defectsRemD = 1;

    for (int i=0; i<3; i++) {
        defectsRemD *= (1-AttVD [i]);
    }

    double defectsRemC = 1;

    for (int i=0; i<3; i++) {
        defectsRemC *= (1-AttVC [i]);
    }

    double def = 0;
    def = s.ksloc*((10*defectsIntroR*defectsRemR )+ (20*defectsIntroD*defectsRemD) + (30*defectsIntroC*defectsRemC));

    return def;
}

double project::monthsMutate() {
    project s= *this;

    double AttV [22] = {0};

    randomNum rdm;

    for (int i=0; i<22; i++) {
        if (i!=19) { //excluding sced
            for (int l=34; l<37; l++) {
                s.setattnum(l, rdm.randomGenerateDouble(s.attrangeNorm[0][l], s.attrangeNorm[1][l]));
            }

            AttV [i] = s.getattnumvaleff(i+1);
        }
    }

    double SF = 0;

    for (int i=0; i<5; i++) {
        SF += AttV[i];
    }

    double EMnS = 1;

    for (int i=5; i<22; i++) {
        if (i!=19) EMnS *= AttV[i]; //remove sced
    }

    double pmNs = s.A*(pow(s.ksloc, (s.B+(0.01*SF))))*EMnS;

    double mon = 0;
    mon = (s.C*(pow(pmNs, (s.D+0.2*(0.01*SF))))*(s.scedpercent()/100));

    return mon;
}
