/// <inheritdoc/> public override string ModelSummary() { using (StringWriter htmlWriter = new StringWriter()) { if (InferStartupPregnancy) { htmlWriter.Write("\r\n<div class=\"activityentry\">"); htmlWriter.Write("Pregnancy status of breeders from matings prior to simulation start will be predicted"); htmlWriter.Write("</div>"); } else { htmlWriter.Write("\r\n<div class=\"activityentry\">"); htmlWriter.Write("No pregnancy of breeders from matings prior to simulation start is inferred"); htmlWriter.Write("</div>"); } controlledMating = this.FindAllChildren <RuminantActivityControlledMating>().FirstOrDefault(); if (controlledMating is null) { htmlWriter.Write("\r\n<div class=\"activityentry\">"); htmlWriter.Write("This simulation uses natural (uncontrolled) mating that will occur when males and females of breeding condition are located together"); htmlWriter.Write("</div>"); } return(htmlWriter.ToString()); } }
private void OnCLEMInitialiseActivity(object sender, EventArgs e) { // get details from parent breeding activity controlledMatingParent = this.Parent as RuminantActivityControlledMating; if (controlledMatingParent is null) { throw new ApsimXException(this, $"Invalid parent component of [a={this.Name}]. Expecting [a=RuminantActivityControlledMating].[f=ActivityTimerBreedForMilking]"); } breedParent = controlledMatingParent.Parent as RuminantActivityBreed; breedParams = resources.FindResourceType <RuminantHerd, RuminantType>(this, breedParent.PredictedHerdBreed, OnMissingResourceActionTypes.ReportErrorAndStop, OnMissingResourceActionTypes.ReportErrorAndStop); int monthsOfMilking = Convert.ToInt32(Math.Ceiling(breedParams.MilkingDays / 30.4), CultureInfo.InvariantCulture); shortenLactationMonths = Math.Max(0, monthsOfMilking - ShortenLactationMonths); pregnancyDuration = Convert.ToInt32(breedParams.GestationLength, CultureInfo.InvariantCulture); // determine min time between conceptions with full milk production minus cut short and resting minConceiveInterval = Math.Max(0, pregnancyDuration + shortenLactationMonths + RestMonths); startBreedCycleGestationOffsett = shortenLactationMonths - pregnancyDuration; if (startBreedCycleGestationOffsett < pregnancyDuration * -1) { throw new Exception("Cannot handle condition where milking cycle starts before pregnancy"); } // get the milking period milkingsPerConceptionsCycle = Math.Ceiling((minConceiveInterval * 1.0) / monthsOfMilking); }
/// <inheritdoc/> public override string ModelSummary(bool formatForParentControl) { using (StringWriter htmlWriter = new StringWriter()) { if (InferStartupPregnancy) { htmlWriter.Write("\r\n<div class=\"activityentry\">"); htmlWriter.Write("Pregnancy status of breeders from matings prior to simulation start will be predicted"); htmlWriter.Write("</div>"); } else { htmlWriter.Write("\r\n<div class=\"activityentry\">"); htmlWriter.Write("No pregnancy of breeders from matings prior to simulation start is inferred"); htmlWriter.Write("</div>"); } controlledMating = this.FindAllChildren <RuminantActivityControlledMating>().FirstOrDefault(); if (useControlledMating) { htmlWriter.Write("\r\n<div class=\"activityentry\">"); htmlWriter.Write("Breeding uses controlled mating as outlined in the component below"); htmlWriter.Write("</div>"); } else { htmlWriter.Write("\r\n<div class=\"activityentry\">"); htmlWriter.Write("This simulation uses natural (uncontrolled) mating"); if (this.FindAllChildren <IActivityTimer>().Count() >= 1) { htmlWriter.Write(". The timer associated with this activity may restrict uncontrolled mating regardless of whether males and females of breeding condition are located together."); } else { htmlWriter.Write(" that will occur every month when males and females of breeding condition are located together."); } htmlWriter.Write("</div>"); } return(htmlWriter.ToString()); } }
private void OnCLEMInitialiseActivity(object sender, EventArgs e) { this.AllocationStyle = ResourceAllocationStyle.Manual; controlledMating = this.FindAllChildren <RuminantActivityControlledMating>().FirstOrDefault(); // Assignment of mothers was moved to RuminantHerd resource to ensure this is done even if no breeding activity is included this.InitialiseHerd(false, true); // report what is happening with timing when uncontrolled mating if (!useControlledMating & this.TimingExists) { Summary.WriteMessage(this, $"Uncontrolled/natural breeding should occur every month. The timer associated with [a={this.Name}] may restrict uncontrolled mating regardless of whether males and females of breeding condition are located together.\r\nYou can also seperate genders by moving to different paddocks to manage the timing of natural mating or add a [a=RuminantActivityControlledMating] component to define controlled mating", MessageType.Warning); } // set up pre start conception status of breeders IEnumerable <Ruminant> herd = CurrentHerd(true); // report previous pregnancies as conceptions foreach (RuminantFemale female in herd.OfType <RuminantFemale>().Where(a => a.IsPregnant)) { // report conception status changed from those assigned suckling at startup female.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(Reporting.ConceptionStatus.Conceived, female, clock.Today)); } // work out pregnancy status of initial herd if (InferStartupPregnancy) { // only initialise if herd present if (herd.Any()) { // go back (gestation - 1) months // this won't include those individuals due to give birth on day 1. int monthsAgoStart = 0 - (Convert.ToInt32(Math.Truncate(herd.FirstOrDefault().BreedParams.GestationLength), CultureInfo.InvariantCulture) - 1); int monthsAgoStop = -1; for (int i = monthsAgoStart; i <= monthsAgoStop; i++) { DateTime previousDate = clock.Today.AddMonths(i); DateTime conceiveDate = clock.Today.AddMonths(i); conceiveDate = new DateTime(conceiveDate.Year, conceiveDate.Month, DateTime.DaysInMonth(conceiveDate.Year, conceiveDate.Month)); // get list of all individuals of breeding age and condition // grouped by location var breeders = from ind in herd where (ind.Sex == Sex.Male && ind.Age + i >= ind.BreedParams.MinimumAge1stMating) || (ind.Sex == Sex.Female && ind.Age + i >= ind.BreedParams.MinimumAge1stMating && !(ind as RuminantFemale).IsPregnant ) group ind by ind.Location into grp select grp; // must be breeders to bother checking any further // must be either uncontrolled mating or the timing of controlled mating if (breeders.Count() > 0 & (!useControlledMating || this.TimingCheck(previousDate))) { int numberPossible = 0; int numberServiced = 1; double limiter = 1; List <Ruminant> maleBreeders = new List <Ruminant>(); // for each location where parts of this herd are located foreach (var location in breeders) { // uncontrolled conception if (!useControlledMating) { // check if males and females of breeding condition are together if (location.GroupBy(a => a.Sex).Count() == 2) { // servicing rate int maleCount = location.Where(a => a.Sex == Sex.Male).Count(); // get a list of males to provide attributes when incontrolled mating. if (maleCount > 0 && location.FirstOrDefault().BreedParams.IncludedAttributeInheritanceWhenMating) { maleBreeders = location.Where(a => a.Sex == Sex.Male).ToList(); } int femaleCount = location.OfType <RuminantFemale>().Count(); double matingsPossible = maleCount * location.FirstOrDefault().BreedParams.MaximumMaleMatingsPerDay * 30; double maleLimiter = Math.Min(1, matingsPossible / femaleCount); // only get non-pregnant females of breeding age at the time before the simulation included var availableBreeders = location.OfType <RuminantFemale>().Where(b => !b.IsPregnant && b.Age + i >= b.BreedParams.MinimumAge1stMating); // only get selection of these of breeders available to spread conceptions // only 15% of breeding herd of age can conceive in any month or male limited proportion whichever is smaller int count = Convert.ToInt32(Math.Ceiling(availableBreeders.Count() * Math.Min(0.15, maleLimiter)), CultureInfo.InvariantCulture); availableBreeders = availableBreeders.OrderBy(x => RandomNumberGenerator.Generator.NextDouble()).Take(count); foreach (RuminantFemale female in availableBreeders) { // calculate conception Reporting.ConceptionStatus status = Reporting.ConceptionStatus.NotMated; double conceptionRate = ConceptionRate(female, out status); if (RandomNumberGenerator.Generator.NextDouble() <= conceptionRate) { female.UpdateConceptionDetails(female.CalulateNumberOfOffspringThisPregnancy(), conceptionRate, i); female.LastMatingStyle = MatingStyle.PreSimulation; // if mandatory attributes are present in the herd, save male value with female details. if (female.BreedParams.IncludedAttributeInheritanceWhenMating) { // randomly select male as father AddMalesAttributeDetails(female, maleBreeders[RandomNumberGenerator.Generator.Next(0, maleBreeders.Count() - 1)]); } // report conception status changed female.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(Reporting.ConceptionStatus.Conceived, female, conceiveDate)); // check for perenatal mortality for (int j = i; j < monthsAgoStop; j++) { DateTime lossDate = clock.Today.AddMonths(i); lossDate = new DateTime(lossDate.Year, lossDate.Month, DateTime.DaysInMonth(lossDate.Year, lossDate.Month)); for (int k = 0; k < female.CarryingCount; i++) { if (RandomNumberGenerator.Generator.NextDouble() < (female.BreedParams.PrenatalMortality / (female.BreedParams.GestationLength + 1))) { female.OneOffspringDies(); if (female.NumberOfOffspring == 0) { // report conception status changed when last multiple birth dies. female.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(Reporting.ConceptionStatus.Failed, female, lossDate)); } } } } } } } } // controlled conception else { numberPossible = Convert.ToInt32(limiter * location.OfType <RuminantFemale>().Count(), CultureInfo.InvariantCulture); foreach (RuminantFemale female in location.OfType <RuminantFemale>()) { if (!female.IsPregnant && (female.Age - female.AgeAtLastBirth) * 30.4 >= female.BreedParams.MinimumDaysBirthToConception) { // calculate conception Reporting.ConceptionStatus status = Reporting.ConceptionStatus.NotMated; double conceptionRate = ConceptionRate(female, out status); if (numberServiced <= numberPossible) // labour/finance limited number { if (RandomNumberGenerator.Generator.NextDouble() <= conceptionRate) { female.UpdateConceptionDetails(female.CalulateNumberOfOffspringThisPregnancy(), conceptionRate, i); female.LastMatingStyle = MatingStyle.Controlled; // if mandatory attributes are present in the herd, save male value with female details. if (female.BreedParams.IncludedAttributeInheritanceWhenMating) { // save all male attributes AddMalesAttributeDetails(female, controlledMating.SireAttributes); } // report conception status changed female.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(Reporting.ConceptionStatus.Conceived, female, conceiveDate)); // check for perenatal mortality for (int j = i; j < monthsAgoStop; j++) { DateTime lossDate = clock.Today.AddMonths(i); lossDate = new DateTime(lossDate.Year, lossDate.Month, DateTime.DaysInMonth(lossDate.Year, lossDate.Month)); for (int k = 0; k < female.CarryingCount; k++) { if (RandomNumberGenerator.Generator.NextDouble() < (female.BreedParams.PrenatalMortality / (female.BreedParams.GestationLength + 1))) { female.OneOffspringDies(); if (female.NumberOfOffspring == 0) { // report conception status changed when last multiple birth dies. female.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(Reporting.ConceptionStatus.Failed, female, lossDate)); } } } } } numberServiced++; } } } } } } } } } }