#include"individual.h"

// random number generator for the class individual, as the script structure is hierachical and can_t use the one in main

random_device rdInd;
mt19937 rdgenInd(rdInd());

Individuals::Individuals(bool sx, int coordx, int coordy) {

	sex = sx;
	x = coordx;
	y = coordy;
	unmated = 1;

	disperser = 0;
	indID = 0;
	dadID = 0;
	n_off = 0;

}

Individuals::~Individuals() {

}


// define functions at the individual level

void Individuals::setgenes_ME(bool init_var, std::normal_distribution<>NormTrait,double dimorphism, double meanME, int Nloci,double threshold)
{
	
	for (int i = 0; i < Nloci; i++)
	{


		if (init_var) {

			trait.ME1.push_back(NormTrait(rdgenInd));
			trait.ME2.push_back(NormTrait(rdgenInd));

		}
		else
		{
			trait.ME1.push_back(meanME/((double)Nloci*2.0)); // fill chromosome up with alleles with value meanME
			trait.ME2.push_back(meanME/((double)Nloci*2.0));

		}

		trait.g_ME += trait.ME1[i] + trait.ME2[i];//create additive trait value

	}

	// female
	if (sex) {
		if (trait.g_ME > 0)
		{
			trait.p_ME = trait.g_ME*dimorphism; // trait is above 0, female trait is male times parameter for sexual dimorphism
		}

		else
		{
			trait.p_ME = 0; // phenotype is bound by 0
		}




	}
	else {

		if (trait.g_ME > 0)
		{
			trait.p_ME = trait.g_ME; // phenotype equals the genotype when trait is above 0
		}

		else
		{
			trait.p_ME = 0; // phenotype is bound by 0
		}
	}

	if (trait.p_ME > threshold)
	{
		trait.p_ME = threshold; // phenotype equals upper threshold when above
	}

	


}

void Individuals::setgenes_MC(bool init_var, std::normal_distribution<>NormTrait, double dimorphism, double meanME, int Nloci, double threshold)
{

	for (int i = 0; i < Nloci; i++)
	{
	

		if (init_var) {

			trait.MC1.push_back(NormTrait(rdgenInd));
			trait.MC2.push_back(NormTrait(rdgenInd));

		}
		else
		{
			trait.MC1.push_back(meanME / ((double)Nloci*2.0)); // fill chromosome up with alleles with value meanME
			trait.MC2.push_back(meanME / ((double)Nloci*2.0));

		}

		trait.g_MC += trait.MC1[i] + trait.MC2[i];//create additive trait value

	}

	// female
	if (sex) {
		if (trait.g_MC > 0)
		{
			trait.p_MC = trait.g_MC*dimorphism; // trait is above 0, female trait is male times parameter for sexual dimorphism
		}

		else
		{
			trait.p_MC = 0; // phenotype is bound by 0
		}




	}
	else {

		if (trait.g_MC > 0)
		{
			trait.p_MC = trait.g_MC; // phenotype equals the genotype when trait is above 0
		}

		else
		{
			trait.p_MC = 0; // phenotype is bound by 0
		}
	}

	if (trait.p_MC > threshold)
	{
		trait.p_MC = threshold; // phenotype equals upper threshold when above
	}


}


void Individuals::mutation_effect_ME(int L, int Nloci, normal_distribution<>effect, double dimorphism, double threshold)
{
	double muteffect;
	muteffect = effect(rdgenInd);

	if (L < Nloci * 2)
	{
		if (L < Nloci)
		{
			trait.ME1[L] += muteffect;
		}
		else {
			trait.ME2[L - Nloci] += muteffect;
		}

		trait.g_ME += muteffect;

		// expression of trait
		if (sex) {
			if (trait.g_ME > 0)
			{
				trait.p_ME = trait.g_ME*dimorphism; // trait is above 0, female trait is male times parameter for sexual dimorphism
			}

			else
			{
				trait.p_ME = 0; // phenotype is bound by 0
			}

		}
		else {

			if (trait.g_ME > 0)
			{
				trait.p_ME = trait.g_ME; // phenotype equals the genotype when trait is above 0
			}

			else
			{
				trait.p_ME = 0; // phenotype is bound by 0
			}
		}

		if (trait.p_ME > threshold)
		{
			trait.p_ME = threshold; // phenotype equals upper threshold when above
		}


	}
	
	

}
void Individuals::mutation_effect_MC(int L, int Nloci, normal_distribution<>effect, double dimorphism, double threshold)
{
	
	double muteffect;
	muteffect = effect(rdgenInd);
	
	if (L < Nloci * 2)
	{
		if (L < Nloci)
		{
			
			trait.MC1[L] += muteffect;
		}
		else {
			
			trait.MC2[L - Nloci] += muteffect;
		}

		trait.g_MC += muteffect;

		// expression of trait
		if (sex) {
			if (trait.g_MC > 0)
			{
				trait.p_MC = trait.g_MC*dimorphism; // trait is above 0, female trait is male times parameter for sexual dimorphism
			}

			else
			{
				trait.p_MC = 0; // phenotype is bound by 0
			}

		}
		else {

			if (trait.g_MC > 0)
			{
				trait.p_MC = trait.g_MC; // phenotype equals the genotype when trait is above 0
			}

			else
			{
				trait.p_MC = 0; // phenotype is bound by 0
			}
		}

		if (trait.p_MC > threshold)
		{
			trait.p_MC = threshold; // phenotype equals upper threshold when above
		}


	}


}