/// <summary> /// Method to determine resources required for this activity in the current month /// </summary> /// <returns>A list of resource requests</returns> public override List <ResourceRequest> GetResourcesNeededForActivity() { List <ResourceRequest> requestList = null; if (AmountHarvested > 0) { FoodResourcePacket packet = new FoodResourcePacket() { Amount = AmountHarvested, PercentN = pasture.Nitrogen, DMD = pasture.EstimateDMD(pasture.Nitrogen) }; requestList = new List <ResourceRequest>() { new ResourceRequest() { ActivityModel = this, AdditionalDetails = this, Category = "Cut and carry", Required = AmountHarvested, Resource = pasture, } }; } return(requestList); }
/// <summary> /// Method used to perform activity if it can occur as soon as resources are available. /// </summary> public override void DoActivity() { FoodResourcePacket packet = new FoodResourcePacket() { Amount = AmountHarvested, PercentN = pasture.Nitrogen, DMD = pasture.EstimateDMD(pasture.Nitrogen) }; foodstore.Add(packet, this, "", "Cut and carry"); }
private void OnCLEMDoCutAndCarry(object sender, EventArgs e) { int year = Clock.Today.Year; int month = Clock.Today.Month; if (NextHarvest != null) { //if this month is a harvest month for this crop if ((year == NextHarvest.HarvestDate.Year) && (month == NextHarvest.HarvestDate.Month)) { if (this.TimingOK) { double totalamount; if (IsTreeCrop) { totalamount = NextHarvest.AmtKg * TreesPerHa * parentManagementActivity.Area * UnitsToHaConverter * (PercentKept / 100); } else { totalamount = NextHarvest.AmtKg * parentManagementActivity.Area * UnitsToHaConverter * (PercentKept / 100); } if (totalamount > 0) { //if Npct column was not in the file if (double.IsNaN(NextHarvest.Npct)) { //Add without adding any new nitrogen. //The nitrogen value for this feed item in the store remains the same. LinkedResourceItem.Add(totalamount, this.Name, "Harvest"); } else { FoodResourcePacket packet = new FoodResourcePacket() { Amount = totalamount, PercentN = NextHarvest.Npct }; LinkedResourceItem.Add(packet, this.Name, "Harvest"); } } SetStatusSuccess(); } HarvestData.RemoveAt(0); } } }
private void OnCLEMDoCutAndCarry(object sender, EventArgs e) { int year = Clock.Today.Year; int month = Clock.Today.Month; //nb. we are relying on the fact that the HarvestData list is sorted by date. CropDataType nextHarvest = HarvestData.FirstOrDefault(); if (nextHarvest != null) { //if this month is a harvest month for this crop if ((year == nextHarvest.Year) && (month == nextHarvest.Month)) { double totalamount; if (IsTreeCrop) { totalamount = nextHarvest.AmtKg * TreesPerHa * cropLand.Area * unitsToHaConverter * (PercentKept / 100); } else { totalamount = nextHarvest.AmtKg * cropLand.Area * unitsToHaConverter * (PercentKept / 100); } switch (Store) { case StoresForCrops.HumanFoodStore: if (totalamount > 0) { //TODO: check that there is no N provided with grain LinkedHumanFoodItem.Add(totalamount, this.Name, "Harvest"); } break; case StoresForCrops.AnimalFoodStore: if (totalamount > 0) { //if Npct column was not in the file if (nextHarvest.Npct == double.NaN) { //Add without adding any new nitrogen. //The nitrogen value for this feed item in the store remains the same. LinkedAnimalFoodItem.Add(totalamount, this.Name, "Harvest"); } else { FoodResourcePacket packet = new FoodResourcePacket() { Amount = totalamount, PercentN = nextHarvest.Npct }; LinkedAnimalFoodItem.Add(packet, this.Name, "Harvest"); } } break; case StoresForCrops.ProductStore: if (totalamount > 0) { LinkedProductItem.Add(totalamount, this.Name, "Harvest"); } break; default: throw new Exception(String.Format("Store {0} is not supported for {1}", Enum.GetName(typeof(StoresForCrops), Store), this.Name)); } //Now remove the first item from the harvest data list because it has happened. //This causes a problem for the children of this model //because of a race condition that occurs if user sets MthsBeforeHarvest = 0 //for any of the children of this model. //Then because this model and children are all executing on the harvest month and //this executes first and it removes the harvest from the harvest list, //then the chidren never get the Clock.Today == harvest date (aka costdate). //So to fix this problem, in the children we store the next harvest date (aka costdate) //in a global variable and don't update its value //until after we have done the Clock.Today == harvest date (aka costdate) comparison. HarvestData.RemoveAt(0); } } }
public override void DoActivity() { //Go through amount received and put it into the animals intake with quality measures. if (ResourceRequestList != null) { List <Ruminant> herd = this.CurrentHerd(false).Where(a => a.Location == this.GrazeFoodStoreModel.Name && a.HerdName == this.RuminantTypeModel.Name).ToList(); if (herd.Count() > 0) { // Get total amount // assumes animals will stop eating at potential intake if they have been feed before grazing. // hours grazed is not adjusted for this reduced feeding. Used to be 1.2 * Potential double totalDesired = 0; double totalEaten = 0; // sucklings totalDesired = herd.Where(a => !a.Weaned).Sum(a => a.PotentialIntake - a.Intake); totalEaten = herd.Where(a => !a.Weaned).Sum(a => a.PotentialIntake - a.Intake); // weaned totalDesired += herd.Where(a => a.Weaned).Sum(a => Math.Min(a.PotentialIntake - a.Intake, a.PotentialIntake * PotentialIntakePastureQualityLimiter * (HoursGrazed / 8))); totalEaten += herd.Where(a => a.Weaned).Sum(a => Math.Min(a.PotentialIntake - a.Intake, a.PotentialIntake * PotentialIntakePastureQualityLimiter * (1 - Math.Exp(-a.BreedParams.IntakeCoefficientBiomass * this.GrazeFoodStoreModel.TonnesPerHectareStartOfTimeStep * 1000)) * (HoursGrazed / 8))); totalEaten *= GrazingCompetitionLimiter; // take resource if (totalEaten > 0) { ResourceRequest request = new ResourceRequest() { ActivityModel = this, AdditionalDetails = this, Reason = RuminantTypeModel.Name + " grazing", Required = totalEaten, Resource = GrazeFoodStoreModel as IResourceType }; GrazeFoodStoreModel.Remove(request); FoodResourcePacket food = new FoodResourcePacket() { DMD = ((RuminantActivityGrazePastureHerd)request.AdditionalDetails).DMD, PercentN = ((RuminantActivityGrazePastureHerd)request.AdditionalDetails).N }; double shortfall = request.Provided / request.Required; // allocate to individuals foreach (Ruminant ind in herd) { double eaten; if (ind.Weaned) { eaten = ind.PotentialIntake * PotentialIntakePastureQualityLimiter * (HoursGrazed / 8); } else { eaten = ind.PotentialIntake - ind.Intake; } food.Amount = eaten * GrazingCompetitionLimiter * shortfall; ind.AddIntake(food); } Status = ActivityStatus.Success; // if insufficent provided or no pasture (nothing eaten) use totalNeededifPasturePresent if (GrazingCompetitionLimiter < 1) { request.Available = request.Provided; // display all that was given request.Required = totalDesired; request.ResourceType = typeof(GrazeFoodStore); request.ResourceTypeName = GrazeFoodStoreModel.Name; ResourceRequestEventArgs rre = new ResourceRequestEventArgs() { Request = request }; OnShortfallOccurred(rre); if (this.OnPartialResourcesAvailableAction == OnPartialResourcesAvailableActionTypes.ReportErrorAndStop) { throw new ApsimXException(this, "Insufficient pasture available for grazing in paddock (" + GrazeFoodStoreModel.Name + ") in " + Clock.Today.Month.ToString() + "\\" + Clock.Today.Year.ToString()); } this.Status = ActivityStatus.Partial; } } else { Status = ActivityStatus.NotNeeded; } } } else { if (Status != ActivityStatus.Partial && Status != ActivityStatus.Critical) { Status = ActivityStatus.NotNeeded; } } }
/// <summary> /// Method used to perform activity if it can occur as soon as resources are available. /// </summary> public override void DoActivity() { List <Ruminant> herd = CurrentHerd(false); if (herd != null && herd.Count > 0) { // calculate feed limit double feedLimit = 0.0; double wastage = 1.0 - this.ProportionTramplingWastage; double dailyAmountShortfall = 1.0; ResourceRequest feedRequest = ResourceRequestList.Where(a => a.ResourceType == typeof(AnimalFoodStore)).FirstOrDefault(); FoodResourcePacket details = new FoodResourcePacket(); if (feedRequest != null) { details = feedRequest.AdditionalDetails as FoodResourcePacket; feedLimit = Math.Min(1.0, feedRequest.Provided / feedRequest.Required); } // feed animals int month = Clock.Today.Month - 1; if (feedRequest == null || (feedRequest.Required == 0 | feedRequest.Available == 0)) { Status = ActivityStatus.NotNeeded; return; } // if feed style is fixed daily amount compare amount received against herd requirement. // this produces a reduction from potential intake for each individual. if (FeedStyle == RuminantFeedActivityTypes.SpecifiedDailyAmount) { double herdRequirement = 0; foreach (Model child in this.Children.Where(a => a.GetType().ToString().Contains("RuminantFeedGroup"))) { herdRequirement += herd.Filter(child).Sum(a => a.PotentialIntake - a.Intake); } dailyAmountShortfall = Math.Min(1.0, (feedRequest.Provided * wastage) / herdRequirement); } // get list from filters foreach (Model child in this.Children.Where(a => a.GetType().ToString().Contains("RuminantFeedGroup"))) { double value = 0; if (child is RuminantFeedGroup) { value = (child as RuminantFeedGroup).Value; } else { value = (child as RuminantFeedGroupMonthly).MonthlyValues[month]; } foreach (Ruminant ind in herd.Filter(child)) { switch (FeedStyle) { case RuminantFeedActivityTypes.SpecifiedDailyAmount: details.Amount = (ind.PotentialIntake - ind.Intake); details.Amount *= dailyAmountShortfall; ind.AddIntake(details); break; case RuminantFeedActivityTypes.SpecifiedDailyAmountPerIndividual: details.Amount = value * 30.4; // * ind.Number; details.Amount *= feedLimit * wastage; ind.AddIntake(details); break; case RuminantFeedActivityTypes.ProportionOfWeight: details.Amount = value * ind.Weight * 30.4; // * ind.Number; details.Amount *= feedLimit * wastage; ind.AddIntake(details); break; case RuminantFeedActivityTypes.ProportionOfPotentialIntake: details.Amount = value * ind.PotentialIntake; // * ind.Number; details.Amount *= feedLimit * wastage; ind.AddIntake(details); break; case RuminantFeedActivityTypes.ProportionOfRemainingIntakeRequired: details.Amount = value * (ind.PotentialIntake - ind.Intake); // * ind.Number; details.Amount *= feedLimit * wastage; ind.AddIntake(details); break; default: throw new Exception("Feed style used [" + FeedStyle + "] not implemented in [" + this.Name + "]"); } } } SetStatusSuccess(); } }
/// <summary> /// Method used to perform activity if it can occur as soon as resources are available. /// </summary> public override void DoActivity() { int year = Clock.Today.Year; int month = Clock.Today.Month; AmountHarvested = 0; AmountAvailableForHarvest = 0; if (NextHarvest != null) { //if this month is a harvest month for this crop if ((year == NextHarvest.HarvestDate.Year) && (month == NextHarvest.HarvestDate.Month)) { if (this.TimingOK) { if (IsTreeCrop) { AmountHarvested = NextHarvest.AmtKg * TreesPerHa * parentManagementActivity.Area * UnitsToHaConverter * ProportionKept; } else { AmountHarvested = NextHarvest.AmtKg * parentManagementActivity.Area * UnitsToHaConverter * ProportionKept; } AmountAvailableForHarvest = AmountHarvested; // reduce amount by limiter if present. if (limiter != null) { double canBeCarried = limiter.GetAmountAvailable(Clock.Today.Month); AmountHarvested = Math.Max(AmountHarvested, canBeCarried); // now modify by labour limits as this is the amount labour was calculated for. double labourLimit = this.LabourLimitProportion; AmountHarvested *= labourLimit; if (labourLimit < 1) { this.Status = ActivityStatus.Partial; } // now limit further by fees not paid double financeLimit = this.LimitProportion(typeof(Finance)); limiter.AddWeightCarried(AmountHarvested); } if (AmountHarvested > 0) { double percentN = 0; // if no nitrogen provided form file if (double.IsNaN(NextHarvest.Npct)) { if (LinkedResourceItem.GetType() == typeof(GrazeFoodStoreType)) { // grazed pasture with no N read assumes the green biomass N content percentN = (LinkedResourceItem as GrazeFoodStoreType).GreenNitrogen; } } else { percentN = NextHarvest.Npct; } if (percentN == 0) { //Add without adding any new nitrogen. //The nitrogen value for this feed item in the store remains the same. LinkedResourceItem.Add(AmountHarvested, this, addReason); } else { FoodResourcePacket packet = new FoodResourcePacket() { Amount = AmountHarvested, PercentN = percentN }; if (LinkedResourceItem.GetType() == typeof(GrazeFoodStoreType)) { packet.DMD = (LinkedResourceItem as GrazeFoodStoreType).EstimateDMD(packet.PercentN); } LinkedResourceItem.Add(packet, this, addReason); } SetStatusSuccess(); } else { if (Status == ActivityStatus.Success) { Status = ActivityStatus.NotNeeded; } } } } else { this.Status = ActivityStatus.NotNeeded; } } else { this.Status = ActivityStatus.NotNeeded; } }
/// <summary> /// Method used to perform activity if it can occur as soon as resources are available. /// </summary> public override void DoActivity() { List <Ruminant> herd = CurrentHerd(false); if (herd != null && herd.Count > 0) { double feedLimit = 0.0; ResourceRequest feedRequest = ResourceRequestList.Where(a => a.ResourceType == typeof(AnimalFoodStore)).LastOrDefault(); FoodResourcePacket details = new FoodResourcePacket(); if (feedRequest != null) { details = feedRequest.AdditionalDetails as FoodResourcePacket; feedLimit = Math.Min(1.0, feedRequest.Provided / feedRequest.Required); } // feed animals if (feedRequest == null || (feedRequest.Required == 0 | feedRequest.Available == 0)) { Status = ActivityStatus.NotNeeded; return; } // get list from filters foreach (IFilterGroup child in Children.Where(a => a.GetType().ToString().Contains("RuminantFeedGroup"))) { double value = 0; if (child is RuminantFeedGroup) { value = (child as RuminantFeedGroup).Value; } else { value = (child as RuminantFeedGroupMonthly).MonthlyValues[Clock.Today.Month - 1]; } foreach (Ruminant ind in herd.FilterRuminants(child)) { switch (FeedStyle) { case RuminantFeedActivityTypes.SpecifiedDailyAmount: case RuminantFeedActivityTypes.ProportionOfFeedAvailable: details.Amount = ((ind.PotentialIntake * (usingPotentialintakeMultiplier ? ind.BreedParams.OverfeedPotentialIntakeModifier : 1)) - ind.Intake); details.Amount *= feedLimit; break; case RuminantFeedActivityTypes.SpecifiedDailyAmountPerIndividual: details.Amount = value * 30.4; details.Amount *= feedLimit; break; case RuminantFeedActivityTypes.ProportionOfWeight: details.Amount = value * ind.Weight * 30.4; details.Amount *= feedLimit; break; case RuminantFeedActivityTypes.ProportionOfPotentialIntake: details.Amount = value * ind.PotentialIntake; details.Amount *= feedLimit; break; case RuminantFeedActivityTypes.ProportionOfRemainingIntakeRequired: details.Amount = value * (ind.PotentialIntake - ind.Intake); details.Amount *= feedLimit; break; default: throw new Exception("Feed style used [" + FeedStyle + "] not implemented in [" + this.Name + "]"); } // check amount meets intake limits if (usingPotentialintakeMultiplier) { if (details.Amount > (ind.PotentialIntake + (Math.Max(0, ind.BreedParams.OverfeedPotentialIntakeModifier - 1) * overfeedProportion * ind.PotentialIntake)) - ind.Intake) { details.Amount = (ind.PotentialIntake + (Math.Max(0, ind.BreedParams.OverfeedPotentialIntakeModifier - 1) * overfeedProportion * ind.PotentialIntake)) - ind.Intake; } } ind.AddIntake(details); } } SetStatusSuccess(); } else { Status = ActivityStatus.NotNeeded; } }
/// <inheritdoc/> public override void DoActivity() { IEnumerable <Ruminant> herd = CurrentHerd(false); if (herd != null && herd.Any()) { double feedLimit = 0.0; ResourceRequest feedRequest = ResourceRequestList.Where(a => a.ResourceType == typeof(AnimalFoodStore)).LastOrDefault(); FoodResourcePacket details = new FoodResourcePacket(); if (feedRequest != null) { details = feedRequest.AdditionalDetails as FoodResourcePacket; feedLimit = Math.Min(1.0, feedRequest.Provided / feedRequest.Required); } // feed animals if (feedRequest == null | (feedRequest?.Required == 0 | feedRequest?.Available == 0) | APSIM.Shared.Utilities.MathUtilities.FloatsAreEqual(feedLimit, 0.0)) { Status = ActivityStatus.NotNeeded; return; } // get list from filters foreach (var child in Children.OfType <FilterGroup <Ruminant> >()) { double value = 0; if (child is RuminantFeedGroup rfg) { value = rfg.Value; } else if (child is RuminantFeedGroupMonthly rfgm) { value = rfgm.MonthlyValues[clock.Today.Month - 1]; } else { continue; } foreach (Ruminant ind in child.Filter(herd)) { switch (FeedStyle) { case RuminantFeedActivityTypes.SpecifiedDailyAmount: case RuminantFeedActivityTypes.ProportionOfFeedAvailable: details.Amount = ((ind.PotentialIntake * (usingPotentialIntakeMultiplier ? ind.BreedParams.OverfeedPotentialIntakeModifier : 1)) - ind.Intake); details.Amount *= feedLimit; break; case RuminantFeedActivityTypes.SpecifiedDailyAmountPerIndividual: details.Amount = value * 30.4; details.Amount *= feedLimit; break; case RuminantFeedActivityTypes.ProportionOfWeight: details.Amount = value * ind.Weight * 30.4; details.Amount *= feedLimit; break; case RuminantFeedActivityTypes.ProportionOfPotentialIntake: details.Amount = value * ind.PotentialIntake; details.Amount *= feedLimit; break; case RuminantFeedActivityTypes.ProportionOfRemainingIntakeRequired: details.Amount = value * (ind.PotentialIntake - ind.Intake); details.Amount *= feedLimit; break; default: throw new Exception($"FeedStyle [{FeedStyle}] is not supported in [a={Name}]"); } // check amount meets intake limits if (usingPotentialIntakeMultiplier) { if (details.Amount > (ind.PotentialIntake + (Math.Max(0, ind.BreedParams.OverfeedPotentialIntakeModifier - 1) * overfeedProportion * ind.PotentialIntake)) - ind.Intake) { details.Amount = (ind.PotentialIntake + (Math.Max(0, ind.BreedParams.OverfeedPotentialIntakeModifier - 1) * overfeedProportion * ind.PotentialIntake)) - ind.Intake; } } ind.AddIntake(details); } } SetStatusSuccess(); } else { Status = ActivityStatus.NotNeeded; } }
/// <inheritdoc/> public override List <ResourceRequest> GetResourcesNeededForActivity() { var herd = CurrentHerd(false); feedEstimated = 0; feedToSatisfy = 0; feedToOverSatisfy = 0; bool singleFeedAmountsCalculated = false; // get list from filters foreach (var child in FindAllChildren <FilterGroup <Ruminant> >()) { double value = 0; if (child is RuminantFeedGroup rfg) { value = rfg.Value; } else if (child is RuminantFeedGroupMonthly rfgm) { value = rfgm.MonthlyValues[clock.Today.Month - 1]; } else { continue; } bool countNeeded = false; bool weightNeeded = false; switch (FeedStyle) { case RuminantFeedActivityTypes.SpecifiedDailyAmount: countNeeded = true; break; case RuminantFeedActivityTypes.SpecifiedDailyAmountPerIndividual: countNeeded = true; break; case RuminantFeedActivityTypes.ProportionOfWeight: weightNeeded = true; break; case RuminantFeedActivityTypes.ProportionOfPotentialIntake: break; case RuminantFeedActivityTypes.ProportionOfRemainingIntakeRequired: break; case RuminantFeedActivityTypes.ProportionOfFeedAvailable: countNeeded = true; break; default: break; } var selectedIndividuals = child.Filter(herd).GroupBy(i => 1).Select(a => new { Count = countNeeded ? a.Count() : 0, Weight = weightNeeded ? a.Sum(b => b.Weight) : 0, Intake = a.Sum(b => b.Intake), PotentialIntake = a.Sum(b => b.PotentialIntake), IntakeMultiplier = usingPotentialIntakeMultiplier ? a.FirstOrDefault().BreedParams.OverfeedPotentialIntakeModifier : 1 }).ToList(); if (selectedIndividuals.Count > 0) { var selectedIndividualsDetails = selectedIndividuals.FirstOrDefault(); switch (FeedStyle) { case RuminantFeedActivityTypes.SpecifiedDailyAmount: usingPotentialIntakeMultiplier = true; if (!singleFeedAmountsCalculated && selectedIndividualsDetails.Count > 0) { feedEstimated += value * 30.4; singleFeedAmountsCalculated = true; } break; case RuminantFeedActivityTypes.SpecifiedDailyAmountPerIndividual: feedEstimated += (value * 30.4) * selectedIndividualsDetails.Count; usingPotentialIntakeMultiplier = true; break; case RuminantFeedActivityTypes.ProportionOfWeight: usingPotentialIntakeMultiplier = true; feedEstimated += value * selectedIndividualsDetails.Weight * 30.4; break; case RuminantFeedActivityTypes.ProportionOfPotentialIntake: feedEstimated += value * selectedIndividualsDetails.PotentialIntake; break; case RuminantFeedActivityTypes.ProportionOfRemainingIntakeRequired: feedEstimated += value * (selectedIndividualsDetails.PotentialIntake - selectedIndividualsDetails.Intake); break; case RuminantFeedActivityTypes.ProportionOfFeedAvailable: usingPotentialIntakeMultiplier = true; if (!singleFeedAmountsCalculated && selectedIndividualsDetails.Count > 0) { feedEstimated += value * FeedType.Amount; singleFeedAmountsCalculated = true; } break; default: throw new Exception($"FeedStyle [{FeedStyle}] is not supported in [a={Name}]"); } // get the amount that can be eaten. Does not account for individuals in multiple filters // accounts for some feeding style allowing overeating to the user declared value in ruminant feedToSatisfy += selectedIndividualsDetails.PotentialIntake - selectedIndividualsDetails.Intake; feedToOverSatisfy += selectedIndividualsDetails.PotentialIntake * selectedIndividualsDetails.IntakeMultiplier - selectedIndividualsDetails.Intake; } } if (StopFeedingWhenSatisfied) { // restrict to max intake permitted by individuals and avoid overfeed wastage feedEstimated = Math.Min(feedEstimated, Math.Max(feedToOverSatisfy, feedToSatisfy)); } if (feedEstimated > 0) { // create food resrouce packet with details FoodResourcePacket foodPacket = new FoodResourcePacket() { Amount = feedEstimated, DMD = FeedType.DMD, PercentN = FeedType.Nitrogen }; return(new List <ResourceRequest>() { new ResourceRequest() { AllowTransmutation = true, Required = feedEstimated, Resource = FeedType, ResourceType = typeof(AnimalFoodStore), ResourceTypeName = FeedTypeName, ActivityModel = this, Category = TransactionCategory, RelatesToResource = this.PredictedHerdName, AdditionalDetails = foodPacket } }); } else { return(null); } }
private void PutPastureInStore() { AmountHarvested = 0; AmountAvailableForHarvest = 0; List <Ruminant> herd = new List <Ruminant>(); if (this.TimingOK) { // determine amount to be cut and carried if (CutStyle != RuminantFeedActivityTypes.SpecifiedDailyAmount) { herd = CurrentHerd(false); } switch (CutStyle) { case RuminantFeedActivityTypes.SpecifiedDailyAmount: AmountHarvested += Supply * 30.4; break; case RuminantFeedActivityTypes.ProportionOfWeight: foreach (Ruminant ind in herd) { AmountHarvested += Supply * ind.Weight * 30.4; } break; case RuminantFeedActivityTypes.ProportionOfPotentialIntake: foreach (Ruminant ind in herd) { AmountHarvested += Supply * ind.PotentialIntake; } break; case RuminantFeedActivityTypes.ProportionOfRemainingIntakeRequired: foreach (Ruminant ind in herd) { AmountHarvested += Supply * (ind.PotentialIntake - ind.Intake); } break; default: throw new Exception(String.Format("FeedActivityType {0} is not supported in {1}", CutStyle, this.Name)); } AmountAvailableForHarvest = AmountHarvested; // reduce amount by limiter if present. if (limiter != null) { double canBeCarried = limiter.GetAmountAvailable(Clock.Today.Month); AmountHarvested = Math.Max(AmountHarvested, canBeCarried); limiter.AddWeightCarried(AmountHarvested); } double labourlimiter = 1.0; AmountHarvested *= labourlimiter; if (AmountHarvested > 0) { FoodResourcePacket packet = new FoodResourcePacket() { Amount = AmountHarvested, PercentN = pasture.Nitrogen, DMD = pasture.EstimateDMD(pasture.Nitrogen) }; // take resource ResourceRequest request = new ResourceRequest() { ActivityModel = this, AdditionalDetails = this, Category = "Cut and carry", Required = AmountHarvested, Resource = pasture }; pasture.Remove(request); foodstore.Add(packet, this, "", "Cut and carry"); } SetStatusSuccess(); } // report activity performed. ActivityPerformedEventArgs activitye = new ActivityPerformedEventArgs { Activity = this }; this.OnActivityPerformed(activitye); }
/// <summary> /// Method used to perform activity if it can occur as soon as resources are available. /// </summary> public override void DoActivity() { List <Ruminant> herd = CurrentHerd(false); if (herd != null && herd.Count > 0) { // calculate labour limit double labourLimit = 1; double labourNeeded = ResourceRequestList.Where(a => a.ResourceType == typeof(Labour)).Sum(a => a.Required); double labourProvided = ResourceRequestList.Where(a => a.ResourceType == typeof(Labour)).Sum(a => a.Provided); if (labourNeeded > 0) { labourLimit = labourProvided / labourNeeded; } // calculate feed limit double feedLimit = 0.0; double wastage = 1.0 - this.ProportionTramplingWastage; ResourceRequest feedRequest = ResourceRequestList.Where(a => a.ResourceType == typeof(AnimalFoodStore)).FirstOrDefault(); FoodResourcePacket details = new FoodResourcePacket(); if (feedRequest != null) { details = feedRequest.AdditionalDetails as FoodResourcePacket; feedLimit = Math.Min(1.0, feedRequest.Provided / feedRequest.Required); } // feed animals int month = Clock.Today.Month - 1; SetStatusSuccess(); // get list from filters foreach (RuminantFeedGroup child in Apsim.Children(this, typeof(RuminantFeedGroup))) { foreach (Ruminant ind in herd.Filter(child as RuminantFeedGroup)) { switch (FeedStyle) { case RuminantFeedActivityTypes.SpecifiedDailyAmount: details.Amount = (child as RuminantFeedGroup).MonthlyValues[month] * 30.4; details.Amount *= feedLimit * labourLimit * wastage; ind.AddIntake(details); break; case RuminantFeedActivityTypes.ProportionOfWeight: details.Amount = (child as RuminantFeedGroup).MonthlyValues[month] * ind.Weight * 30.4; // * ind.Number; details.Amount *= feedLimit * labourLimit * wastage; ind.AddIntake(details); break; case RuminantFeedActivityTypes.ProportionOfPotentialIntake: details.Amount = (child as RuminantFeedGroup).MonthlyValues[month] * ind.PotentialIntake; // * ind.Number; details.Amount *= feedLimit * labourLimit * wastage; ind.AddIntake(details); break; case RuminantFeedActivityTypes.ProportionOfRemainingIntakeRequired: details.Amount = (child as RuminantFeedGroup).MonthlyValues[month] * (ind.PotentialIntake - ind.Intake); // * ind.Number; details.Amount *= feedLimit * labourLimit * wastage; ind.AddIntake(details); break; default: break; } } } } }