/// <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");
        }
Esempio n. 3
0
        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);
                }
            }
        }
Esempio n. 4
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;
                }
            }
        }
Esempio n. 6
0
        /// <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;
            }
        }
Esempio n. 9
0
        /// <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;
            }
        }
Esempio n. 10
0
        /// <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);
            }
        }
Esempio n. 11
0
        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);
        }
Esempio n. 12
0
        /// <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;
                        }
                    }
                }
            }
        }