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(); } TMyRandom randomGenerator = new TMyRandom(10); // get dry breeders from females foreach (RuminantFemale female in herd.Where(a => a.Age - a.AgeAtLastBirth >= MonthsSinceBirth & a.PreviousConceptionRate >= MinimumConceptionBeforeSell & a.AgeAtLastBirth > 0)) { if (randomGenerator.RandNo <= ProportionToRemove) { // flag female ready to transport. female.SaleFlag = Common.HerdChangeReason.DryBreederSale; } } } }
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.SpecifiedAmount: freqest.Amount = (child as RuminantFilterGroup).MonthlyValues[month - 1]; // * ind.Number; break; case RuminantFeedActivityTypes.ProportionOfWeight: freqest.Amount = (child as RuminantFilterGroup).MonthlyValues[month - 1] * ind.Weight; // * 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 OnWFAgeResources(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; // grow all individuals foreach (Ruminant ind in herd) { ind.Age++; } }
private void OnWFRequestFeed(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; IResourceType grazeStoreType = null; if (FeedArbitratorName != "") { grazeStoreType = Arbitrators.GetByName(FeedArbitratorName) as IResourceType; } // for each paddock defined in PastureActivityManage foreach (PastureActivityManage pasture in Activities.Children.Where(a => a.GetType() == typeof(PastureActivityManage))) { if (FeedArbitratorName == "") { grazeStoreType = pasture.FeedType; } // create feeding activity for this pasture RuminantActivityGraze activity = new RuminantActivityGraze(); activity.FeedPriority = this.FeedPriority; activity.FeedType = pasture.FeedType; activity.HoursGrazed = this.HoursGrazed; activity.Name = String.Format("Graze {0}", pasture.FeedType.Name); // calculate kg per ha available double kgPerHa = pasture.FeedType.Amount / pasture.Area; if (pasture.FeedType.Amount > 0) { // get list of all Ruminants in this paddock foreach (Ruminant ind in herd.Where(a => a.Location == pasture.Name)) { RuminantFeedRequest freqest = new RuminantFeedRequest(); freqest.FeedActivity = activity; freqest.Requestor = ind; // Reduce potential intake based on pasture quality for the proportion consumed. // calculate intake from potential modified by pasture availability and hours grazed freqest.Amount = ind.PotentialIntake * (1 - Math.Exp(-ind.BreedParams.IntakeCoefficientBiomass * kgPerHa)) * (HoursGrazed / 8); grazeStoreType.Remove(freqest); } } } }
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 OnWFAnimalBuy(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); Finance Accounts = Resources.FinanceResource() as Finance; FinanceType bankAccount = Accounts.GetFirst(); 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()); } } }
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 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; } } } } } }
private void OnWFAnimalSell(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); Finance Accounts = Resources.FinanceResource() as Finance; FinanceType bankAccount = Accounts.GetFirst(); int trucks = 0; double saleValue = 0; double saleWeight = 0; int head = 0; // get current untrucked list of animals flagged for sale List <Ruminant> herd = ruminantHerd.Herd.Where(a => a.SaleFlag != Common.HerdChangeReason.None & a.Breed == BreedName).OrderByDescending(a => a.Weight).ToList(); // if sale herd > min loads before allowing sale if (herd.Select(a => a.Weight / 450.0).Sum() / Number450kgPerTruck >= MinimumTrucksBeforeSelling) { // while truck to fill while (herd.Select(a => a.Weight / 450.0).Sum() / Number450kgPerTruck > MinimumLoadBeforeSelling) { bool nonloaded = true; trucks++; double load450kgs = 0; // while truck below carrying capacity load individuals foreach (var ind in herd) { if (load450kgs + (ind.Weight / 450.0) <= Number450kgPerTruck) { nonloaded = false; head++; load450kgs += ind.Weight / 450.0; RuminantValue getvalue = PriceList.Where(a => a.Age < ind.Age).OrderBy(a => a.Age).LastOrDefault(); saleValue += getvalue.SellValue * ((getvalue.Style == Common.PricingStyleType.perKg) ? ind.Weight : 1.0); saleWeight += ind.Weight; ruminantHerd.RemoveRuminant(ind); } } if (nonloaded) { Summary.WriteWarning(this, String.Format("There was a problem loading the sale truck as sale individuals did not meet the loading criteria for breed {0}", BreedName)); break; } herd = ruminantHerd.Herd.Where(a => a.SaleFlag != Common.HerdChangeReason.None & a.Breed == BreedName).OrderByDescending(a => a.Weight).ToList(); } if (trucks > 0 & bankAccount != null) { // calculate transport costs double transportCost = trucks * DistanceToMarket * CostPerKmTrucking; bankAccount.Remove(transportCost, this.Name, "Transport"); // calculate MLA fees double mlaCost = head * MLAFees; bankAccount.Remove(mlaCost, this.Name, "R&DFee"); // calculate yard fees double yardCost = head * YardFees; bankAccount.Remove(yardCost, this.Name, "YardCosts"); // calculate commission double commissionCost = saleValue * SalesCommission; bankAccount.Remove(commissionCost, this.Name, "SalesCommission"); // add and remove from bank bankAccount.Add(saleValue, this.Name, "Sales"); } } }
/// <summary> /// Create the individual ruminant animals using the Cohort parameterisations. /// </summary> /// <returns></returns> public List <Ruminant> CreateIndividuals() { List <Ruminant> Individuals = new List <Ruminant>(); IModel parentNode = Apsim.Parent(this, typeof(IModel)); RuminantType parent = parentNode as RuminantType; // get Ruminant Herd resource for unique ids RuminantHerd ruminantHerd = Resources.RuminantHerd(); parent = this.Parent as RuminantType; if (StartingNumber > 0) { //TODO: get random generator from global store with seed Random rand = new Random(); for (int i = 1; i <= StartingNumber; i++) { object ruminantBase = null; if (this.Gender == Sex.Male) { ruminantBase = new RuminantMale(); } else { ruminantBase = new RuminantFemale(); } Ruminant ruminant = ruminantBase as Ruminant; ruminant.ID = ruminantHerd.NextUniqueID; ruminant.BreedParams = parent; ruminant.Breed = parent.Breed; ruminant.HerdName = parent.Name; ruminant.Gender = Gender; ruminant.Age = StartingAge; ruminant.SaleFlag = Common.HerdChangeReason.None; if (Suckling) { ruminant.SetUnweaned(); } double u1 = rand.NextDouble(); double u2 = rand.NextDouble(); double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2); ruminant.Weight = StartingWeight + StartingWeightSD * randStdNormal; ruminant.PreviousWeight = ruminant.Weight; if (this.Gender == Sex.Female) { RuminantFemale ruminantFemale = ruminantBase as RuminantFemale; ruminantFemale.DryBreeder = true; ruminantFemale.WeightAtConception = this.StartingWeight; ruminantFemale.NumberOfBirths = 0; } Individuals.Add(ruminantBase as Ruminant); } } return(Individuals); }
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) { breedParams = Resources.GetResourceItem("Ruminants", HerdName) 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 OnWFAnimalDeath(object sender, EventArgs e) { // remove individuals that died // currently performed in the month after weight has been adjusted // and before breeding, trading, culling etc (See Clock event order) // Calculated by // critical weight & // juvenile (unweaned) death based on mothers weight & // adult weight adjusted base mortality. RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; // weight based mortality List <Ruminant> died = herd.Where(a => a.Weight < (a.HighWeight * (1.0 - a.BreedParams.ProportionOfMaxWeightToSurvive))).ToList(); // set died flag died.Select(a => { a.SaleFlag = Common.HerdChangeReason.Died; return(a); }).ToList(); ruminantHerd.RemoveRuminant(died); TMyRandom randomGenerator = new TMyRandom(10); foreach (var ind in ruminantHerd.Herd) { double mortalityRate = 0; if (!ind.Weaned) { mortalityRate = 0; if (ind.Mother.Weight < ind.BreedParams.CriticalCowWeight * ind.StandardReferenceWeight) { mortalityRate = ind.BreedParams.JuvenileMortalityMaximum; } else { mortalityRate = Math.Exp(-Math.Pow(ind.BreedParams.JuvenileMortalityCoefficient * (ind.Weight / ind.NormalisedAnimalWeight), ind.BreedParams.JuvenileMortalityExponent)) / 100; } mortalityRate += mortalityRate + ind.BreedParams.MortalityBase; mortalityRate = Math.Max(mortalityRate, ind.BreedParams.JuvenileMortalityMaximum); } else { mortalityRate = 1 - (1 - ind.BreedParams.MortalityBase) * (1 - Math.Exp(Math.Pow(-(ind.BreedParams.MortalityCoefficient * (ind.Weight / ind.NormalisedAnimalWeight - ind.BreedParams.MortalityIntercept)), ind.BreedParams.MortalityExponent))); } if (randomGenerator.RandNo <= mortalityRate) { ind.Died = true; } } died = herd.Where(a => a.Died).ToList(); died.Select(a => { a.SaleFlag = Common.HerdChangeReason.Died; return(a); }).ToList(); ruminantHerd.RemoveRuminant(died); //// mortality calculation (calculation actually calculates the survival probability) //for (int i = herd.Count; i >= 0; i--) //{ // double mortalityRate = 0; // if (!herd[i].Weaned) // { // mortalityRate = 0; // if (herd[i].Mother.Weight < herd[i].BreedParams.CriticalCowWeight * herd[i].StandardReferenceWeight) // { // mortalityRate = herd[i].BreedParams.JuvenileMortalityMaximum; // } // else // { // mortalityRate = Math.Exp(-Math.Pow(herd[i].BreedParams.JuvenileMortalityCoefficient * (herd[i].Weight / herd[i].NormalisedAnimalWeight), herd[i].BreedParams.JuvenileMortalityExponent)) / 100; // } // mortalityRate += mortalityRate + herd[i].BreedParams.MortalityBase; // mortalityRate = Math.Max(mortalityRate, herd[i].BreedParams.JuvenileMortalityMaximum); // } // else // { // mortalityRate = 1 - (1 - herd[i].BreedParams.MortalityBase) * (1 - Math.Exp(Math.Pow(-(herd[i].BreedParams.MortalityCoefficient * (herd[i].Weight / herd[i].NormalisedAnimalWeight - herd[i].BreedParams.MortalityIntercept)), herd[i].BreedParams.MortalityExponent))); // } // if (randomGenerator.RandNo <= mortalityRate) // { // herd[i].Died = true; // } //} }
private void OnWFAnimalWeightGain(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; double totalMethane = 0; // grow all weaned individuals foreach (Ruminant ind in herd.Where(a => (a.Weaned == true))) { // calculate protein concentration // Calculate diet dry matter digestibilty from the %N of the current diet intake. // Reference: Ash and McIvor //ind.DietDryMatterDigestibility = 36.7 + 9.36 * ind.PercentNOfIntake / 62.5; // Now tracked via incoming food DMD values // TODO: NABSA restricts Diet_DMD to 75% before supplements. Why? // Our flow has already taken in supplements by this stage and cannot be distinguished // Maybe this limit should be placed on some feed to limit DMD to 75% for non supp feeds // TODO: Check equation. NABSA doesn't include the 0.9 // Crude protein required generally 130g per kg of digestable feed. double crudeProteinRequired = ind.BreedParams.ProteinCoefficient * ind.DietDryMatterDigestibility / 100; // adjust for efficiency of use of protein, 90% degradable double crudeProteinSupply = (ind.PercentNOfIntake * 62.5) * 0.9; // This was proteinconcentration * 0.9 // prevent future divide by zero issues. if (crudeProteinSupply == 0.0) { crudeProteinSupply = 0.001; } double ratioSupplyRequired = Math.Min(0.3, Math.Max(1.3, crudeProteinSupply / crudeProteinRequired)); // TODO: check if we still need to apply modification to only the non-supplemented component of intake ind.Intake *= ratioSupplyRequired; ind.Intake = Math.Min(ind.Intake, ind.PotentialIntake * 1.2); // TODO: nabsa adjusts potential intake for digestability of fodder here. // I'm sure it can be done here, but prob as this is after the 1.2x cap has been performed. // calculate from the pools of fodder fed to this individual //if (0.8 - ind.BreedParams.IntakeTropicalQuality - dietDMD / 100 >= 0) //{ // ind.PotentialIntake *= ind.BreedParams.IntakeCoefficientQuality * (0.8 - ind.BreedParams.IntakeTropicalQuality - dietDMD / 100); //} // calculate energy // includes mortality and growth double methane = 0; CalculateEnergy(ind, out methane); // ? call methane produced event // or sum and produce one event for breed at end of loop totalMethane += methane; // calculate manure // ? call manure produce event // or sum and produce one event for breed at end of loop // grow wool and cashmere ind.Wool += ind.BreedParams.WoolCoefficient * ind.Intake; ind.Cashmere += ind.BreedParams.CashmereCoefficient * ind.Intake; } }
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 (randomGenerator.RandNo >= 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; } }
private void OnWFAnimalBreeding(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd.Where(a => a.BreedParams.Name == HerdName).ToList(); // get list of all individuals of breeding age and condition // grouped by location var breeders = from ind in herd where (ind.Gender == Sex.Male & ind.Age >= ind.BreedParams.MinimumAge1stMating) ^ (ind.Gender == Sex.Female & ind.Age >= ind.BreedParams.MinimumAge1stMating & ind.Weight >= (ind.BreedParams.MinimumSize1stMating * ind.StandardReferenceWeight) ) group ind by ind.Location into grp select grp; // for each location where parts of this herd are located foreach (var location in breeders) { // check for births of all pregnant females. foreach (RuminantFemale female in location.Where(a => a.Gender == Sex.Female).Cast <RuminantFemale>().ToList()) { if (female.BirthDue) { int numberOfNewborn = (female.CarryingTwins) ? 2 : 1; for (int i = 0; i < numberOfNewborn; i++) { // Determine if the offspring died during pregancy from conception to after birth // This is currently only performed at time of birth rather than monthly during pregnancy // and so does not reflect changes in female intake etc after dead of foetus. // this now occurs monthly at the ned of this breeding method. //if (randomGenerator.RandNo > female.BreedParams.PrenatalMortality) //{ object newCalf = null; bool isMale = (randomGenerator.RandNo > 0.5); if (isMale) { newCalf = new RuminantMale(); } else { newCalf = new RuminantFemale(); } Ruminant newCalfRuminant = newCalf as Ruminant; newCalfRuminant.Age = 0; newCalfRuminant.HerdName = female.HerdName; newCalfRuminant.BreedParams = female.BreedParams; newCalfRuminant.Gender = (isMale) ? Sex.Male : Sex.Female; newCalfRuminant.ID = ruminantHerd.NextUniqueID; newCalfRuminant.Location = female.Location; newCalfRuminant.Mother = female; // newCalfRuminant.Number = 1; newCalfRuminant.SetUnweaned(); // calf weight from Freer newCalfRuminant.Weight = female.BreedParams.SRWBirth * female.StandardReferenceWeight * (1 - 0.33 * (1 - female.Weight / female.StandardReferenceWeight)); newCalfRuminant.HighWeight = newCalfRuminant.Weight; newCalfRuminant.SaleFlag = Common.HerdChangeReason.Born; ruminantHerd.AddRuminant(newCalfRuminant); // add to sucklings female.SucklingOffspring.Add(newCalfRuminant); //} } female.UpdateBirthDetails(); } } // Conception // check if males and females of breeding condition are together if (location.GroupBy(a => a.Gender).Count() == 2) { // servicing rate int maleCount = location.Where(a => a.Gender == Sex.Male).Count(); int femaleCount = location.Where(a => a.Gender == Sex.Female).Count(); double matingsPossible = maleCount * location.FirstOrDefault().BreedParams.MaximumMaleMatingsPerDay * 30; double maleLimiter = Math.Max(1.0, matingsPossible / femaleCount); foreach (RuminantFemale female in location.Where(a => a.Gender == Sex.Female).Cast <RuminantFemale>().ToList()) { //TODO: ensure enough time since last calf if (!female.IsPregnant & !female.IsLactating) { // calculate conception double conceptionRate = ConceptionRate(female) * maleLimiter; if (randomGenerator.RandNo <= conceptionRate) { female.UpdateConceptionDetails(randomGenerator.RandNo > female.BreedParams.TwinRate, conceptionRate); } } } } // determine all foetus and newborn mortality. foreach (RuminantFemale female in location.Where(a => a.Gender == Sex.Female).Cast <RuminantFemale>().ToList()) { if (female.IsPregnant) { // calculate foetus and newborn mortality // total mortality / gestation months to get monthly mortality // TODO: check if need to be done before births to get last month mortality if (randomGenerator.RandNo > female.BreedParams.PrenatalMortality / female.BreedParams.GestationLength) { female.OneOffspringDies(); } } } } }
private void OnWFAnimalManage(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd.Where(a => a.HerdName == HerdName).ToList(); }