private void OnCLEMHerdSummary(object sender, EventArgs e) { timestep++; List <Ruminant> herd = Resources.RuminantHerd().Herd; foreach (RuminantGroup filter in herdFilters) { herd = herd.Filter(filter).ToList(); } // group by breed foreach (var breedGroup in herd.GroupBy(a => a.Breed)) { // group by herd foreach (var herdGroup in breedGroup.GroupBy(a => a.HerdName)) { // group by sex foreach (var sexGroup in herdGroup.GroupBy(a => a.Gender)) { // weaned foreach (var ageGroup in sexGroup.OrderBy(a => a.Age).GroupBy(a => Math.Truncate(a.Age / 12.0))) { ReportDetails = new HerdReportItemGeneratedEventArgs { TimeStep = timestep, Breed = breedGroup.Key, Herd = herdGroup.Key, Age = Convert.ToInt32(ageGroup.Key, CultureInfo.InvariantCulture), Sex = sexGroup.Key.ToString().Substring(0, 1), Number = ageGroup.Sum(a => a.Number), AverageWeight = ageGroup.Average(a => a.Weight), AverageWeightGain = ageGroup.Average(a => a.WeightGain), AverageIntake = ageGroup.Average(a => (a.Intake + a.MilkIntake)), //now daily/30.4; AdultEquivalents = ageGroup.Sum(a => a.AdultEquivalent) }; if (sexGroup.Key == Sex.Female) { ReportDetails.NumberPregnant = ageGroup.Cast <RuminantFemale>().Where(a => a.IsPregnant).Count(); ReportDetails.NumberLactating = ageGroup.Cast <RuminantFemale>().Where(a => a.IsLactating).Count(); ReportDetails.NumberOfBirths = ageGroup.Cast <RuminantFemale>().Sum(a => a.NumberOfBirthsThisTimestep); } else { ReportDetails.NumberPregnant = 0; ReportDetails.NumberLactating = 0; ReportDetails.NumberOfBirths = 0; } ReportItemGenerated(ReportDetails); // reset birth count if (sexGroup.Key == Sex.Female) { ageGroup.Cast <RuminantFemale>().ToList().ForEach(a => a.NumberOfBirthsThisTimestep = 0); } } } } } }
private void OnWFAnimalBuy(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); Finance Accounts = Resources.FinanceResource() as Finance; FinanceType bankAccount = Accounts.GetFirst() as FinanceType; var newRequests = ruminantHerd.PurchaseIndividuals.Where(a => a.BreedParams.Breed == BreedName).ToList(); foreach (var newgroup in newRequests.GroupBy(a => a.SaleFlag)) { double fundsAvailable = 100000000; if (bankAccount != null) { fundsAvailable = bankAccount.FundsAvailable; } double cost = 0; foreach (var newind in newgroup) { double value = 0; if (newgroup.Key == Common.HerdChangeReason.SirePurchase) { value = BreedingSirePrice; } else { RuminantValue getvalue = PriceList.Where(a => a.Age < newind.Age).OrderBy(a => a.Age).LastOrDefault(); value = getvalue.PurchaseValue * ((getvalue.Style == Common.PricingStyleType.perKg) ? newind.Weight : 1.0); } if (cost + value <= fundsAvailable) { ruminantHerd.AddRuminant(newind); cost += value; } else { break; } } if (bankAccount != null) { bankAccount.Remove(cost, this.Name, newgroup.Key.ToString()); } } }
/// <summary> /// Do reporting of individuals /// </summary> /// <returns></returns> private void ReportHerd() { // warning if the same individual is in multiple filter groups it will be entered more than once var allRumGroups = this.FindAllChildren <RuminantGroup>(); if (allRumGroups.Count() > 0) { // get all filter groups below. foreach (var fgroup in allRumGroups) { foreach (Ruminant item in Resources.RuminantHerd().Herd.Filter(fgroup)) { ReportDetails = new RuminantReportItemEventArgs(); if (item is RuminantFemale) { ReportDetails.RumObj = item as RuminantFemale; } else { ReportDetails.RumObj = item as RuminantMale; } ReportItemGenerated(ReportDetails); } } } else // no filter. Use entire herd { foreach (Ruminant item in Resources.RuminantHerd().Herd) { ReportDetails = new RuminantReportItemEventArgs(); if (item is RuminantFemale) { ReportDetails.RumObj = item as RuminantFemale; } else { ReportDetails.RumObj = item as RuminantMale; } ReportItemGenerated(ReportDetails); } } }
private void OnWFRequestFeed(object sender, EventArgs e) { if (labourLimiter > 0) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; if (herd == null && herd.Count == 0) { return; } // get month from clock int month = Clock.Today.Month; // get list from filters foreach (var child in this.Children) { if (child.GetType() == typeof(RuminantFilterGroup)) { foreach (Ruminant ind in herd.Filter(child as RuminantFilterGroup)) { RuminantFeedRequest freqest = new RuminantFeedRequest(); freqest.FeedActivity = this; freqest.Requestor = ind; freqest.Amount = 0; switch (FeedStyle) { case RuminantFeedActivityTypes.SpecifiedDailyAmount: freqest.Amount = (child as RuminantFilterGroup).MonthlyValues[month - 1] * 30.4; // * ind.Number; break; case RuminantFeedActivityTypes.ProportionOfWeight: freqest.Amount = (child as RuminantFilterGroup).MonthlyValues[month - 1] * ind.Weight * 30.4; // * ind.Number; break; case RuminantFeedActivityTypes.ProportionOfPotentialIntake: freqest.Amount = (child as RuminantFilterGroup).MonthlyValues[month - 1] * ind.PotentialIntake; // * ind.Number; break; case RuminantFeedActivityTypes.ProportionOfRemainingIntakeRequired: freqest.Amount = (child as RuminantFilterGroup).MonthlyValues[month - 1] * (ind.PotentialIntake - ind.Intake); // * ind.Number; break; default: break; } freqest.Amount *= labourLimiter; FoodSource.Remove(freqest); } } } } }
private void OnWFPotentialIntake(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; // Natural weaning takes place here before animals eat or take milk from mother. foreach (var ind in herd.Where(a => a.Weaned == false)) { if (ind.Age >= ind.BreedParams.GestationLength + 1) { ind.Wean(); } } // Calculate potential intake and reset stores foreach (var ind in herd) { // reset tallies at start of the month ind.DietDryMatterDigestibility = 0; ind.PercentNOfIntake = 0; ind.Intake = 0; ind.MilkIntake = 0; CalculatePotentialIntake(ind); } // TODO: Future cohort based run may speed up simulation // Calculate by cohort method and assign values to individuals. // Need work out what grouping should be based on Name, Breed, Gender, Weight, Parity... // This approach will not currently work as individual may have individual weights and females may be in various states of breeding. // //var cohorts = herd.GroupBy(a => new { a.BreedParams.Breed, a.Gender, a.Age, lactating = (a.DryBreeder | a.Milk) }); //foreach (var cohort in cohorts) //{ // CalculatePotentialIntake(cohort.FirstOrDefault()); // double potintake = cohort.FirstOrDefault().PotentialIntake; // foreach (var ind in cohort) // { // ind.PotentialIntake = potintake; // } //} }
private void OnCLEMHerdSummary(object sender, EventArgs e) { // warning if the same individual is in multiple filter groups it will be entered more than once ReportDetails = new RuminantReportItemEventArgs(); if (this.Children.Where(a => a.GetType() == typeof(RuminantFilterGroup)).Count() > 0) { // get all filter groups below. foreach (var fgroup in this.Children.Where(a => a.GetType() == typeof(RuminantFilterGroup))) { foreach (Ruminant item in Resources.RuminantHerd().Herd.Filter(fgroup)) { if (item.GetType() == typeof(RuminantFemale)) { ReportDetails.RumObj = item as RuminantFemale; } else { ReportDetails.RumObj = item as RuminantMale; } ReportItemGenerated(ReportDetails); } } } else // no filter. Use entire herd { foreach (Ruminant item in Resources.RuminantHerd().Herd) { if (item.GetType() == typeof(RuminantFemale)) { ReportDetails.RumObj = item as RuminantFemale; } else { ReportDetails.RumObj = item as RuminantMale; } ReportItemGenerated(ReportDetails); } } }
private void OnEndOfMonth(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; // group by breed foreach (var breedGroup in herd.GroupBy(a => a.Breed)) { // group by herd foreach (var herdGroup in breedGroup.GroupBy(a => a.HerdName)) { // group by sex foreach (var sexGroup in herdGroup.GroupBy(a => a.Gender)) { //// sucklings //var sucklings = sexGroup.Where(a => !a.Weaned); //if(sucklings.Count() > 0) //{ //} // weaned foreach (var ageGroup in sexGroup.OrderBy(a => a.Age).GroupBy(a => Math.Truncate(a.Age / 12.0))) { ReportDetails = new HerdReportItemGeneratedEventArgs(); ReportDetails.Breed = breedGroup.Key; ReportDetails.Herd = herdGroup.Key; ReportDetails.Age = Convert.ToInt32(ageGroup.Key); ReportDetails.Sex = sexGroup.Key.ToString().Substring(0, 1); ReportDetails.Number = ageGroup.Sum(a => a.Number); ReportDetails.AverageWeight = ageGroup.Average(a => a.Weight); ReportDetails.AverageWeightGain = ageGroup.Average(a => a.WeightGain); ReportDetails.AverageIntake = ageGroup.Average(a => (a.Intake)); //now daily/30.4; ReportDetails.AdultEquivalents = ageGroup.Sum(a => a.AdultEquivalent); if (sexGroup.Key == Sex.Female) { ReportDetails.NumberPregnant = ageGroup.Cast <RuminantFemale>().Where(a => a.IsPregnant).Count(); ReportDetails.NumberOfBirths = ageGroup.Cast <RuminantFemale>().Where(a => a.BirthDue).Sum(a => a.SucklingOffspring.Count()); } else { ReportDetails.NumberPregnant = 0; ReportDetails.NumberOfBirths = 0; } ReportItemGenerated(ReportDetails); } } } } }
private void Muster() { // get herd to muster RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; if (herd == null && herd.Count == 0) { return; } // get list from filters foreach (Ruminant ind in herd.Filter(this)) { // set new location ID ind.Location = pasture.Name; // check if sucklings are to be moved with mother if (MoveSucklings) { // if female if (ind.GetType() == typeof(RuminantFemale)) { RuminantFemale female = ind as RuminantFemale; // check if mother with sucklings if (female.SucklingOffspring.Count > 0) { foreach (var suckling in female.SucklingOffspring) { suckling.Location = pasture.Name; } } } } } }
/// <summary> /// Method to determine resources required for this activity in the current month /// </summary> /// <returns>List of required resource requests</returns> public override List <ResourceRequest> DetermineResourcesNeeded() { ResourceRequestList = null; double kgPerHa = grazeType.Amount / paddockActivity.Area; RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd.Where(a => a.Location == PaddockName).ToList(); if (herd.Count() > 0) { double amount = 0; // get list of all Ruminants in this paddock foreach (Ruminant ind in herd) { // Reduce potential intake based on pasture quality for the proportion consumed. // TODO: build in pasture quality intake correction // calculate intake from potential modified by pasture availability and hours grazed amount += ind.PotentialIntake * (1 - Math.Exp(-ind.BreedParams.IntakeCoefficientBiomass * kgPerHa)) * (HoursGrazed / 8); } if (ResourceRequestList == null) { ResourceRequestList = new List <ResourceRequest>(); } ResourceRequestList.Add(new ResourceRequest() { AllowTransmutation = true, Required = amount, ResourceName = "GrazeFoodStore", ResourceTypeName = this.grazeType.Name, Requestor = this.Name } ); } return(ResourceRequestList); }
private void OnWFAnimalMilking(object sender, EventArgs e) { if (ProportionToRemove > 0) { // get dry breeders RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <RuminantFemale> herd = ruminantHerd.Herd.Where(a => a.BreedParams.Name == HerdName & a.Gender == Sex.Female).Cast <RuminantFemale>().ToList(); if (SellFromManagedPaddock) { // in sepecified paddock herd = herd.Where(a => a.Location == PaddockName).ToList(); } // get dry breeders from females foreach (RuminantFemale female in herd.Where(a => a.Age - a.AgeAtLastBirth >= MonthsSinceBirth & a.PreviousConceptionRate >= MinimumConceptionBeforeSell & a.AgeAtLastBirth > 0)) { if (WholeFarm.RandomGenerator.NextDouble() <= ProportionToRemove) { // flag female ready to transport. female.SaleFlag = Common.HerdChangeReason.DryBreederSale; } } } }
private void OnWFAnimalManage(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd.Where(a => a.HerdName == HerdName).ToList(); }
/// <summary> /// Method to determine resources required for this activity in the current month /// </summary> /// <returns>List of required resource requests</returns> public override List <ResourceRequest> DetermineResourcesNeeded() { ResourceRequestList = null; RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; if (herd != null && herd.Count > 0) { // labour if (LabourRequired > 0) { if (ResourceRequestList == null) { ResourceRequestList = new List <ResourceRequest>(); } // determine head to be fed int head = 0; foreach (RuminantFilterGroup child in this.Children.Where(a => a.GetType() == typeof(RuminantFilterGroup))) { head += herd.Filter(child as RuminantFilterGroup).Count(); } ResourceRequestList.Add(new ResourceRequest() { AllowTransmutation = true, Required = Math.Ceiling(head / this.LabourHeadUnit) * this.LabourRequired, ResourceName = "Labour", ResourceTypeName = "", Requestor = this.Name, FilterSortDetails = LabourFilterList } ); } // feed double feedRequired = 0; // get zero limited month from clock int month = Clock.Today.Month - 1; // get list from filters foreach (RuminantFilterGroup child in this.Children.Where(a => a.GetType() == typeof(RuminantFilterGroup))) { foreach (Ruminant ind in herd.Filter(child as RuminantFilterGroup)) { switch (FeedStyle) { case RuminantFeedActivityTypes.SpecifiedDailyAmount: feedRequired += (child as RuminantFilterGroup).MonthlyValues[month] * 30.4; break; case RuminantFeedActivityTypes.ProportionOfWeight: feedRequired += (child as RuminantFilterGroup).MonthlyValues[month] * ind.Weight * 30.4; break; case RuminantFeedActivityTypes.ProportionOfPotentialIntake: feedRequired += (child as RuminantFilterGroup).MonthlyValues[month] * ind.PotentialIntake; break; case RuminantFeedActivityTypes.ProportionOfRemainingIntakeRequired: feedRequired += (child as RuminantFilterGroup).MonthlyValues[month] * (ind.PotentialIntake - ind.Intake); break; default: break; } } } if (ResourceRequestList == null) { ResourceRequestList = new List <ResourceRequest>(); } ResourceRequestList.Add(new ResourceRequest() { AllowTransmutation = true, Required = feedRequired, ResourceName = "AnimalFoodStore", ResourceTypeName = this.FeedTypeName, Requestor = this.Name } ); } return(ResourceRequestList); }
private void OnWFAnimalManage(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd.Where(a => a.HerdName == HerdName).ToList(); RuminantType breedParams; // get breedParams when no herd remaining if (herd.Count() == 0) { bool resourceAvailable = false; breedParams = Resources.GetResourceItem("Ruminants", HerdName, out resourceAvailable) as RuminantType; } else { breedParams = herd.FirstOrDefault().BreedParams; } // can sell off males any month as per NABSA // if we don't need this monthly, then it goes into next if statement with herd declaration // NABSA MALES - weaners, 1-2, 2-3 and 3-4 yo, we check for any male weaned and not a breeding sire. // check for sell age/weight of young males // if SellYoungFemalesLikeMales then all apply to both sexes else only males. foreach (var ind in herd.Where(a => a.Weaned & (SellFemalesLikeMales ? true : (a.Gender == Sex.Male)) & (a.Age >= SellingAge ^ a.Weight >= SellingWeight))) { bool sell = true; if (ind.GetType() == typeof(RuminantMale)) { // don't sell breeding sires. sell = !((ind as RuminantMale).BreedingSire); } if (sell) { ind.SaleFlag = Common.HerdChangeReason.AgeWeightSale; } } // if management month if (Clock.Today.Month == ManagementMonth ^ MonthlyManagement) { // Perform weaning foreach (var ind in herd.Where(a => a.Weaned == false)) { if (ind.Age >= WeaningAge ^ ind.Weight >= WeaningWeight) { ind.Wean(); } } // check for maximum age (females and males have different cutoffs) foreach (var ind in herd.Where(a => a.Age >= ((a.Gender == Sex.Female) ? MaximumBreederAge : MaximumBullAge))) { ind.SaleFlag = Common.HerdChangeReason.MaxAgeSale; } // MALES // check for breeder bulls after sale of old individuals and buy/sell int numberinherd = herd.Where(a => a.Gender == Sex.Male & a.SaleFlag == Common.HerdChangeReason.None).Cast <RuminantMale>().Where(a => a.BreedingSire).Count(); if (numberinherd > MaximumSiresKept) { // sell bulls // What rule? oldest first as they may be lost soonest int numberToRemove = MaximumSiresKept - numberinherd; foreach (var male in herd.Where(a => a.Gender == Sex.Male).Cast <RuminantMale>().Where(a => a.BreedingSire).OrderByDescending(a => a.Age).Take(numberToRemove)) { male.SaleFlag = Common.HerdChangeReason.ExcessBullSale; } } else if (numberinherd < MaximumSiresKept) { // remove young bulls from sale herd to replace breed bulls (not those sold because too old) foreach (RuminantMale male in herd.Where(a => a.Gender == Sex.Male & a.SaleFlag == Common.HerdChangeReason.AgeWeightSale).OrderByDescending(a => a.Weight)) { male.SaleFlag = Common.HerdChangeReason.None; male.BreedingSire = true; numberinherd++; if (numberinherd >= MaximumSiresKept) { break; } } // if still insufficient buy bulls. if (numberinherd < MaximumSiresKept) { int numberToBuy = Convert.ToInt32((MaximumSiresKept - numberinherd) * 0.05); for (int i = 0; i < numberToBuy; i++) { RuminantMale newbull = new RuminantMale(); newbull.Age = 48; newbull.HerdName = HerdName; newbull.BreedingSire = true; newbull.BreedParams = breedParams; newbull.Gender = Sex.Male; newbull.ID = ruminantHerd.NextUniqueID; newbull.Weight = 450; newbull.HighWeight = newbull.Weight; newbull.SaleFlag = Common.HerdChangeReason.SirePurchase; // add to purchase request list and await purchase in Buy/ Sell ruminantHerd.PurchaseIndividuals.Add(newbull); } } } // FEMALES // check for maximum number of breeders remaining after sale and buy/sell numberinherd = herd.Where(a => a.Gender == Sex.Female & a.Age >= a.BreedParams.MinimumAge1stMating & a.SaleFlag == Common.HerdChangeReason.None).Count(); if (numberinherd > MaximumBreedersKept) { // sell breeders // What rule? oldest first as they may be lost soonest // should keep pregnant females... and young... // this will currently remove pregnant females and females with suckling calf int numberToRemove = MaximumBreedersKept - numberinherd; foreach (var female in herd.Where(a => a.Gender == Sex.Female & a.Age >= a.BreedParams.MinimumAge1stMating).OrderByDescending(a => a.Age).Take(numberToRemove)) { female.SaleFlag = Common.HerdChangeReason.ExcessBreederSale; } } else { // remove young females from sale herd to replace breeders (not those sold because too old) foreach (RuminantFemale female in herd.Where(a => a.Gender == Sex.Female & a.SaleFlag == Common.HerdChangeReason.AgeWeightSale).OrderByDescending(a => a.Weight)) { female.SaleFlag = Common.HerdChangeReason.None; numberinherd++; if (numberinherd >= MaximumBreedersKept) { break; } } // if still insufficient buy breeders. if (numberinherd < MaximumBreedersKept) { int ageOfHeifer = 12; double weightOfHeifer = 260; int numberToBuy = Convert.ToInt32((MaximumBreedersKept - numberinherd) * 0.05); for (int i = 0; i < numberToBuy; i++) { RuminantFemale newheifer = new RuminantFemale(); newheifer.Age = ageOfHeifer; newheifer.HerdName = HerdName; newheifer.BreedParams = breedParams; newheifer.Gender = Sex.Female; newheifer.ID = ruminantHerd.NextUniqueID; newheifer.Weight = weightOfHeifer; newheifer.HighWeight = newheifer.Weight; newheifer.SaleFlag = Common.HerdChangeReason.HeiferPurchase; // add to purchase request list and await purchase in Buy/ Sell ruminantHerd.PurchaseIndividuals.Add(newheifer); } } } } }
private void OnStartOfSimulation(object sender, EventArgs e) { // This needs to happen after all herd creation has been performed // Therefore we use StartOfSimulation event RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd.Where(a => a.HerdName == HerdName).ToList(); // get list of females of breeding age and condition List <RuminantFemale> breedFemales = herd.Where(a => a.Gender == Sex.Female & a.Age >= a.BreedParams.MinimumAge1stMating + 12 & a.Weight >= (a.BreedParams.MinimumSize1stMating * a.StandardReferenceWeight) & a.Weight >= (a.BreedParams.CriticalCowWeight * a.StandardReferenceWeight)).OrderByDescending(a => a.Age).ToList().Cast <RuminantFemale>().ToList(); // get list of all sucking individuals List <Ruminant> sucklingList = herd.Where(a => a.Weaned == false).ToList(); if (breedFemales.Count() == 0) { if (sucklingList.Count > 0) { Summary.WriteWarning(this, String.Format("No breeding females to assign sucklings for herd ({0})", HerdName)); } return; } // gestation interval at smallest size generalised curve double minAnimalWeight = breedFemales[0].StandardReferenceWeight - ((1 - breedFemales[0].BreedParams.SRWBirth) * breedFemales[0].StandardReferenceWeight) * Math.Exp(-(breedFemales[0].BreedParams.AgeGrowthRateCoefficient * (breedFemales[0].BreedParams.MinimumAge1stMating * 30.4)) / (Math.Pow(breedFemales[0].StandardReferenceWeight, breedFemales[0].BreedParams.SRWGrowthScalar))); double IPIminsize = Math.Pow(breedFemales[0].BreedParams.InterParturitionIntervalIntercept * (minAnimalWeight / breedFemales[0].StandardReferenceWeight), breedFemales[0].BreedParams.InterParturitionIntervalCoefficient) * 30.64; // restrict minimum period between births IPIminsize = Math.Max(IPIminsize, breedFemales[0].BreedParams.GestationLength + 61); // assign calves to cows foreach (var suckling in sucklingList) { if (breedFemales.Count > 0) { breedFemales[0].DryBreeder = false; //Initialise female milk production in at birth so ready for sucklings to consume double milkTime = 15; // equivalent to mid month production double milkProduction = breedFemales[0].BreedParams.MilkPeakYield * breedFemales[0].Weight / breedFemales[0].NormalisedAnimalWeight * (Math.Pow(((milkTime + breedFemales[0].BreedParams.MilkOffsetDay) / breedFemales[0].BreedParams.MilkPeakDay), breedFemales[0].BreedParams.MilkCurveSuckling)) * Math.Exp(breedFemales[0].BreedParams.MilkCurveSuckling * (1 - (milkTime + breedFemales[0].BreedParams.MilkOffsetDay) / breedFemales[0].BreedParams.MilkPeakDay)); breedFemales[0].MilkProduction = Math.Max(milkProduction, 0.0); breedFemales[0].MilkAmount = milkProduction * 30.4; // generalised curve double IPIcurrent = Math.Pow(breedFemales[0].BreedParams.InterParturitionIntervalIntercept * (breedFemales[0].Weight / breedFemales[0].StandardReferenceWeight), breedFemales[0].BreedParams.InterParturitionIntervalCoefficient) * 30.64; // restrict minimum period between births IPIcurrent = Math.Max(IPIcurrent, breedFemales[0].BreedParams.GestationLength + 61); breedFemales[0].NumberOfBirths = Convert.ToInt32((breedFemales[0].Age - suckling.Age - breedFemales[0].BreedParams.GestationLength - breedFemales[0].BreedParams.MinimumAge1stMating) / ((IPIcurrent + IPIminsize) / 2)); //breedFemales[0].Parity = breedFemales[0].Age - suckling.Age - 9; // I removed the -9 as this would make it conception month not birth month breedFemales[0].AgeAtLastBirth = breedFemales[0].Age - suckling.Age; breedFemales[0].AgeAtLastConception = breedFemales[0].AgeAtLastBirth - breedFemales[0].BreedParams.GestationLength; // suckling mother set suckling.Mother = breedFemales[0]; // check if a twin and if so apply next individual to same mother. // otherwise remove this mother from the list if (WholeFarm.RandomGenerator.NextDouble() >= breedFemales[0].BreedParams.TwinRate) { breedFemales.RemoveAt(0); } } else { Summary.WriteWarning(this, String.Format("Insufficient breeding females to assign sucklings for herd ({0})", HerdName)); return; } } // assing values for the remaining females who haven't just bred. foreach (var female in breedFemales) { female.DryBreeder = true; // generalised curve double IPIcurrent = Math.Pow(breedFemales[0].BreedParams.InterParturitionIntervalIntercept * (breedFemales[0].Weight / breedFemales[0].StandardReferenceWeight), breedFemales[0].BreedParams.InterParturitionIntervalCoefficient) * 30.64; // restrict minimum period between births IPIcurrent = Math.Max(IPIcurrent, breedFemales[0].BreedParams.GestationLength + 61); breedFemales[0].NumberOfBirths = Convert.ToInt32((breedFemales[0].Age - breedFemales[0].BreedParams.MinimumAge1stMating) / ((IPIcurrent + IPIminsize) / 2)) - 1; female.AgeAtLastBirth = breedFemales[0].Age - 12; } // check for controlled mating settings ControlledMatings = this.Children.Where(a => a.GetType() == typeof(ControlledMatingSettings)).Cast <ControlledMatingSettings>().FirstOrDefault(); }