private void OnCLEMInitialiseActivity(object sender, EventArgs e) { this.InitialiseHerd(false, true); breedParams = Resources.GetResourceItem(this, typeof(RuminantHerd), this.PredictedHerdName, OnMissingResourceActionTypes.ReportErrorAndStop, OnMissingResourceActionTypes.ReportErrorAndStop) as RuminantType; // max sires if (MaximumSiresKept < 1 & MaximumSiresKept > 0) { SiresKept = Convert.ToInt32(Math.Ceiling(MaximumBreedersKept * MaximumSiresKept), CultureInfo.InvariantCulture); } else { SiresKept = Convert.ToInt32(Math.Truncate(MaximumSiresKept), CultureInfo.InvariantCulture); } if (FillBreedingMalesAtStartup) { RuminantHerd herd = Resources.RuminantHerd(); if (herd != null) { // get number in herd int numberPresent = this.CurrentHerd(false).Where(a => a.Gender == Sex.Male).Cast <RuminantMale>().Where(a => a.BreedingSire).Count(); // fill to number needed for (int i = numberPresent; i < SiresKept; i++) { RuminantMale newbull = new RuminantMale(48, Sex.Male, 450, breedParams) { Breed = this.PredictedHerdBreed, HerdName = this.PredictedHerdName, BreedingSire = true, ID = herd.NextUniqueID, PreviousWeight = 450, SaleFlag = HerdChangeReason.InitialHerd }; herd.AddRuminant(newbull, this); } } } // check GrazeFoodStoreExists grazeStore = ""; if (GrazeFoodStoreName != null && !GrazeFoodStoreName.StartsWith("Not specified")) { grazeStore = GrazeFoodStoreName.Split('.').Last(); foodStore = Resources.GetResourceItem(this, GrazeFoodStoreName, OnMissingResourceActionTypes.ReportErrorAndStop, OnMissingResourceActionTypes.ReportErrorAndStop) as GrazeFoodStoreType; } // check for managed paddocks and warn if animals placed in yards. if (grazeStore == "") { var ah = Apsim.Find(this, typeof(ActivitiesHolder)); if (Apsim.ChildrenRecursively(ah, typeof(PastureActivityManage)).Count() != 0) { Summary.WriteWarning(this, String.Format("Animals purchased by [a={0}] are currently placed in [Not specified - general yards] while a managed pasture is available. These animals will not graze until mustered and will require feeding while in yards.\nSolution: Set the [GrazeFoodStore to place purchase in] located in the properties [General].[PastureDetails]", this.Name)); } } }
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()); } } }
private void BuyWithTrucking() { // This activity will purchase animals based on available funds. RuminantHerd ruminantHerd = Resources.RuminantHerd(); int trucks = 0; int head = 0; double aESum = 0; double fundsAvailable = 0; if (bankAccount != null) { fundsAvailable = bankAccount.FundsAvailable; } double cost = 0; double shortfall = 0; bool fundsexceeded = false; // get current untrucked list of animal purchases List <Ruminant> herd = ruminantHerd.PurchaseIndividuals.Where(a => a.BreedParams.Breed == this.PredictedHerdBreed).OrderByDescending(a => a.Weight).ToList(); if (herd.Count() == 0) { return; } // if purchase herd > min loads before allowing trucking if (herd.Select(a => a.Weight / 450.0).Sum() / trucking.Number450kgPerTruck >= trucking.MinimumTrucksBeforeSelling) { // while truck to fill while (herd.Select(a => a.Weight / 450.0).Sum() / trucking.Number450kgPerTruck > trucking.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) <= trucking.Number450kgPerTruck) { nonloaded = false; head++; aESum += ind.AdultEquivalent; load450kgs += ind.Weight / 450.0; if (bankAccount != null) // perform with purchasing { double value = 0; if (ind.SaleFlag == HerdChangeReason.SirePurchase) { value = ind.BreedParams.ValueofIndividual(ind, PurchaseOrSalePricingStyleType.Purchase, RuminantFilterParameters.BreedingSire, "true"); } else { value = ind.BreedParams.ValueofIndividual(ind, PurchaseOrSalePricingStyleType.Purchase); } if (cost + value <= fundsAvailable && fundsexceeded == false) { ind.ID = ruminantHerd.NextUniqueID; ruminantHerd.AddRuminant(ind, this); ruminantHerd.PurchaseIndividuals.Remove(ind); cost += value; } else { fundsexceeded = true; shortfall += value; } } else // no financial transactions { ind.ID = ruminantHerd.NextUniqueID; ruminantHerd.AddRuminant(ind, this); ruminantHerd.PurchaseIndividuals.Remove(ind); } } } if (nonloaded) { Summary.WriteWarning(this, String.Format("There was a problem loading the purchase truck as purchase individuals did not meet the loading criteria for breed [r={0}]", this.PredictedHerdBreed)); break; } if (shortfall > 0) { break; } herd = ruminantHerd.PurchaseIndividuals.Where(a => a.BreedParams.Breed == this.PredictedHerdBreed).OrderByDescending(a => a.Weight).ToList(); } // create trucking emissions if (trucking != null && trucks > 0) { trucking.ReportEmissions(trucks, false); SetStatusSuccess(); } if (bankAccount != null && (trucks > 0 || trucking == null)) { ResourceRequest purchaseRequest = new ResourceRequest { ActivityModel = this, Required = cost, AllowTransmutation = false, Reason = this.PredictedHerdName + " purchases" }; bankAccount.Remove(purchaseRequest); // report any financial shortfall in purchases if (shortfall > 0) { purchaseRequest.Available = bankAccount.Amount; purchaseRequest.Required = cost + shortfall; purchaseRequest.Provided = cost; purchaseRequest.ResourceType = typeof(Finance); purchaseRequest.ResourceTypeName = BankAccountName; ResourceRequestEventArgs rre = new ResourceRequestEventArgs() { Request = purchaseRequest }; OnShortfallOccurred(rre); } ResourceRequest expenseRequest = new ResourceRequest { Available = bankAccount.Amount, ActivityModel = this, AllowTransmutation = false }; // calculate transport costs if (trucking != null) { expenseRequest.Required = trucks * trucking.DistanceToMarket * trucking.CostPerKmTrucking; expenseRequest.Reason = "Transport purchases"; bankAccount.Remove(expenseRequest); if (expenseRequest.Required > expenseRequest.Available) { expenseRequest.Available = bankAccount.Amount; expenseRequest.ResourceType = typeof(Finance); expenseRequest.ResourceTypeName = BankAccountName; ResourceRequestEventArgs rre = new ResourceRequestEventArgs() { Request = expenseRequest }; OnShortfallOccurred(rre); } } } } }
private void BuyWithoutTrucking() { // This activity will purchase animals based on available funds. RuminantHerd ruminantHerd = Resources.RuminantHerd(); // get current untrucked list of animal purchases List <Ruminant> herd = ruminantHerd.PurchaseIndividuals.Where(a => a.BreedParams.Breed == this.PredictedHerdBreed).ToList(); if (herd.Count() > 0) { SetStatusSuccess(); } double fundsAvailable = 0; if (bankAccount != null) { fundsAvailable = bankAccount.FundsAvailable; } double cost = 0; double shortfall = 0; bool fundsexceeded = false; foreach (var newind in herd) { if (bankAccount != null) // perform with purchasing { double value = 0; if (newind.SaleFlag == HerdChangeReason.SirePurchase) { value = newind.BreedParams.ValueofIndividual(newind, PurchaseOrSalePricingStyleType.Purchase, RuminantFilterParameters.BreedingSire, "true"); } else { value = newind.BreedParams.ValueofIndividual(newind, PurchaseOrSalePricingStyleType.Purchase); } if (cost + value <= fundsAvailable && fundsexceeded == false) { ruminantHerd.PurchaseIndividuals.Remove(newind); newind.ID = ruminantHerd.NextUniqueID; ruminantHerd.AddRuminant(newind, this); cost += value; } else { fundsexceeded = true; shortfall += value; } } else // no financial transactions { ruminantHerd.PurchaseIndividuals.Remove(newind); newind.ID = ruminantHerd.NextUniqueID; ruminantHerd.AddRuminant(newind, this); } } if (bankAccount != null) { ResourceRequest purchaseRequest = new ResourceRequest { ActivityModel = this, Required = cost, AllowTransmutation = false, Reason = this.PredictedHerdName + " purchases" }; bankAccount.Remove(purchaseRequest); // report any financial shortfall in purchases if (shortfall > 0) { purchaseRequest.Available = bankAccount.Amount; purchaseRequest.Required = cost + shortfall; purchaseRequest.Provided = cost; purchaseRequest.ResourceType = typeof(Finance); purchaseRequest.ResourceTypeName = BankAccountName; ResourceRequestEventArgs rre = new ResourceRequestEventArgs() { Request = purchaseRequest }; OnShortfallOccurred(rre); } } }
private void OnCLEMInitialiseActivity(object sender, EventArgs e) { // create local version of max breeders so we can modify without affecting user set value maxBreeders = Math.Max(this.MaximumBreedersKept, this.MinimumBreedersKept); this.InitialiseHerd(false, true); breedParams = Resources.GetResourceItem(this, typeof(RuminantHerd), this.PredictedHerdName, OnMissingResourceActionTypes.ReportErrorAndStop, OnMissingResourceActionTypes.ReportErrorAndStop) as RuminantType; decimal breederHerdSize = 0; if (AdjustBreedingFemalesAtStartup) { RuminantHerd herd = Resources.RuminantHerd(); List <Ruminant> rumHerd = this.CurrentHerd(false); if (rumHerd != null && rumHerd.Count() > 0) { int numberAdded = 0; RuminantType breedParams = rumHerd.FirstOrDefault().BreedParams; RuminantInitialCohorts cohorts = Apsim.Children(rumHerd.FirstOrDefault().BreedParams, typeof(RuminantInitialCohorts)).FirstOrDefault() as RuminantInitialCohorts; if (cohorts != null) { List <RuminantTypeCohort> cohortList = Apsim.Children(cohorts, typeof(RuminantTypeCohort)).Cast <RuminantTypeCohort>().Where(a => a.Gender == Sex.Female && (a.Age >= breedParams.MinimumAge1stMating & a.Age <= this.MaximumBreederAge)).ToList(); int initialBreeders = Convert.ToInt32(cohortList.Sum(a => a.Number)); if (initialBreeders < this.MinimumBreedersKept) { double scaleFactor = this.MinimumBreedersKept / Convert.ToDouble(initialBreeders); // add new individuals foreach (var item in cohortList) { int numberToAdd = Convert.ToInt32(Math.Round(item.Number * scaleFactor) - item.Number); foreach (var newind in item.CreateIndividuals(numberToAdd)) { newind.SaleFlag = HerdChangeReason.FillInitialHerd; herd.AddRuminant(newind, this); numberAdded++; } } if (numberAdded == 0) { throw new ApsimXException(this, $"Unable to scale breeding female population up to the maximum breeders kept at startup\nNo cohorts representing breeders were found in the initial herd structure [r=InitialCohorts] for [r={breedParams.Name}]\nAdd at least one initial cohort that meets the breeder criteria of age at first mating and max age kept"); } breederHerdSize = initialBreeders + numberAdded; } else if (initialBreeders > maxBreeders) { int reduceBy = Math.Max(0, initialBreeders - maxBreeders); // reduce initial herd size // randomly select the individuals to remove form the breeder herd List <Ruminant> breeders = rumHerd.Where(a => a.Gender == Sex.Female && a.Age > breedParams.MinimumAge1stMating && a.Age < this.MaximumBreederAge).OrderBy(x => Guid.NewGuid()).Take(reduceBy).ToList(); foreach (var item in breeders) { item.SaleFlag = HerdChangeReason.ReduceInitialHerd; herd.RemoveRuminant(item, this); reduceBy--; } if (reduceBy > 0) { // add warning string warn = $"Unable to reduce breeders at the start of the simulation to number required [{maxBreeders}] using [a={this.Name}]"; if (!Warnings.Exists(warn)) { Summary.WriteWarning(this, warn); Warnings.Add(warn); } } breederHerdSize = maxBreeders; } } else { throw new ApsimXException(this, $"Unable to adjust breeding female population to the maximum breeders kept at startup\nNo initial herd structure [r=InitialCohorts] has been provided in [r={breedParams.Name}]"); } } } // max sires if (MaximumSiresKept < 1 & MaximumSiresKept > 0) { SiresKept = Convert.ToInt32(Math.Ceiling(maxBreeders * breederHerdSize), CultureInfo.InvariantCulture); } else { SiresKept = Convert.ToInt32(Math.Truncate(MaximumSiresKept), CultureInfo.InvariantCulture); } if (AdjustBreedingMalesAtStartup) { RuminantHerd herd = Resources.RuminantHerd(); if (herd != null) { // get number in herd List <Ruminant> rumHerd = this.CurrentHerd(false); int numberPresent = rumHerd.Where(a => a.Gender == Sex.Male).Cast <RuminantMale>().Where(a => a.BreedingSire).Count(); if (numberPresent < SiresKept) { // fill to number needed for (int i = numberPresent; i < SiresKept; i++) { RuminantMale newSire = new RuminantMale(SireAgeAtPurchase, Sex.Male, 0, breedParams) { Breed = this.PredictedHerdBreed, HerdName = this.PredictedHerdName, BreedingSire = true, ID = herd.NextUniqueID, SaleFlag = HerdChangeReason.FillInitialHerd }; herd.AddRuminant(newSire, this); } } else if (numberPresent > SiresKept) { // reduce initial herd. int reduceBy = Math.Max(0, numberPresent - SiresKept); // reduce initial sire herd size // randomly select the individuals to remove form the breeder herd List <RuminantMale> sires = rumHerd.Where(a => a.Gender == Sex.Male).Cast <RuminantMale>().Where(a => a.BreedingSire).OrderBy(x => Guid.NewGuid()).Take(reduceBy).ToList(); foreach (var item in sires) { item.SaleFlag = HerdChangeReason.ReduceInitialHerd; herd.RemoveRuminant(item, this); reduceBy--; } if (reduceBy > 0) { // add warning string warn = $"Unable to reduce breeding sires at the start of the simulation to number required [{SiresKept}] using [a={this.Name}]"; if (!Warnings.Exists(warn)) { Summary.WriteWarning(this, warn); Warnings.Add(warn); } } } } } // check GrazeFoodStoreExists for breeders grazeStoreBreeders = ""; if (GrazeFoodStoreNameBreeders != null && !GrazeFoodStoreNameBreeders.StartsWith("Not specified")) { grazeStoreBreeders = GrazeFoodStoreNameBreeders.Split('.').Last(); foodStoreBreeders = Resources.GetResourceItem(this, GrazeFoodStoreNameBreeders, OnMissingResourceActionTypes.ReportErrorAndStop, OnMissingResourceActionTypes.ReportErrorAndStop) as GrazeFoodStoreType; } // check for managed paddocks and warn if breeders placed in yards. if (grazeStoreBreeders == "" && this.MaximumProportionBreedersPerPurchase > 0) { var ah = Apsim.Find(this, typeof(ActivitiesHolder)); if (Apsim.ChildrenRecursively(ah, typeof(PastureActivityManage)).Count() != 0) { Summary.WriteWarning(this, String.Format("Breeders purchased by [a={0}] are currently placed in [Not specified - general yards] while a managed pasture is available. These animals will not graze until mustered and will require feeding while in yards.\nSolution: Set the [GrazeFoodStore to place purchase in] located in the properties [General].[PastureDetails]", this.Name)); } } // check GrazeFoodStoreExists for sires grazeStoreSires = ""; if (GrazeFoodStoreNameSires != null && !GrazeFoodStoreNameSires.StartsWith("Not specified")) { grazeStoreSires = GrazeFoodStoreNameSires.Split('.').Last(); foodStoreSires = Resources.GetResourceItem(this, GrazeFoodStoreNameSires, OnMissingResourceActionTypes.ReportErrorAndStop, OnMissingResourceActionTypes.ReportErrorAndStop) as GrazeFoodStoreType; } // check for managed paddocks and warn if sires placed in yards. if (grazeStoreBreeders == "" && this.SiresKept > 0) { var ah = Apsim.Find(this, typeof(ActivitiesHolder)); if (Apsim.ChildrenRecursively(ah, typeof(PastureActivityManage)).Count() != 0) { Summary.WriteWarning(this, String.Format("Sires purchased by [a={0}] are currently placed in [Not specified - general yards] while a managed pasture is available. These animals will not graze until mustered and will require feeding while in yards.\nSolution: Set the [GrazeFoodStore to place purchase in] located in the properties [General].[PastureDetails]", this.Name)); } } }
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. object newCalf = null; bool isMale = (WholeFarm.RandomGenerator.NextDouble() > 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(); } } // uncontrolled conception if (ControlledMatings == null) { // 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; conceptionRate = Math.Min(conceptionRate, MaximumConceptionRateUncontrolled); if (WholeFarm.RandomGenerator.NextDouble() <= conceptionRate) { female.UpdateConceptionDetails(WholeFarm.RandomGenerator.NextDouble() > female.BreedParams.TwinRate, conceptionRate); } } } } } // controlled conception else if (ControlledMatings != null && ControlledMatings.IsDueDate()) { 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); if (WholeFarm.RandomGenerator.NextDouble() <= conceptionRate) { female.UpdateConceptionDetails(WholeFarm.RandomGenerator.NextDouble() > 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 (WholeFarm.RandomGenerator.NextDouble() > female.BreedParams.PrenatalMortality / female.BreedParams.GestationLength) { female.OneOffspringDies(); } } } } if (ControlledMatings != null && ControlledMatings.IsDueDate()) { } }