Exemple #1
0
        private void OnSimulationCommencing(object sender, EventArgs e)
        {
            // locate FeedType resource
            bool resourceAvailable = false;

            FeedType   = Resources.GetResourceItem("AnimalFoodStore", FeedTypeName, out resourceAvailable) as IFeedType;
            FoodSource = FeedType;

            if (LabourRequired > 0)
            {
                // check for and assign labour filter group
                LabourFilterList = this.Children.Where(a => a.GetType() == typeof(LabourFilterGroup)).Cast <object>().ToList();
                // if not present assume can use any labour and report
                if (LabourFilterList == null)
                {
                    Summary.WriteWarning(this, String.Format("No labour filter details provided for feeding activity ({0}). Assuming any labour type can be used", this.Name));
                    LabourFilterGroup lfg = new LabourFilterGroup();
                    LabourFilter      lf  = new LabourFilter()
                    {
                        Operator  = FilterOperators.GreaterThanOrEqual,
                        Value     = "0",
                        Parameter = LabourFilterParameters.Age
                    };
                    lfg.Children.Add(lf);
                    LabourFilterList = new List <object>();
                    LabourFilterList.Add(lfg);
                }
            }
        }
Exemple #2
0
        public RuminantActivityGrazeAll(Node parent) : base(parent)
        {
            Name = "GrazeAll";
            OnPartialResourcesAvailableAction = 2;

            var labour = new LabourRequirement(this);
            var group  = new LabourFilterGroup(labour);
            var filter = new LabourFilter(group)
            {
                Parameter = 0,
                Operator  = 0,
                Value     = "Male"
            };

            group.Add(filter);
            labour.Add(group);
        }
Exemple #3
0
        /// <summary>
        /// Validate this object
        /// </summary>
        /// <param name="validationContext"></param>
        /// <returns></returns>
        public IEnumerable <ValidationResult> Validate(ValidationContext validationContext)
        {
            var results = new List <ValidationResult>();
            // ensure labour resource added
            Labour lab = Resources.GetResourceGroupByType(typeof(Labour)) as Labour;

            if (lab == null)
            {
                Summary.WriteWarning(this, "[a=" + this.Parent.Name + "][f=" + this.Name + "] No labour resorces in simulation. Labour requirement will be ignored.");
            }
            else
            {
                if (lab.Children.Count <= 0)
                {
                    Summary.WriteWarning(this, "[a=" + this.Parent.Name + "][f=" + this.Name + "] No labour resorce types are provided in the labour resource. Labour requirement will be ignored.");
                }
            }

            // check filter groups present
            if (this.Children.OfType <LabourFilterGroup>().Count() == 0)
            {
                Summary.WriteWarning(this, "No LabourFilterGroup is supplied with the LabourRequirement for [a=" + this.Parent.Name + "]. No labour will be used for this activity.");
            }

            // check for individual nesting.
            foreach (LabourFilterGroup fg in this.Children.OfType <LabourFilterGroup>())
            {
                LabourFilterGroup currentfg = fg;
                while (currentfg != null && currentfg.Children.OfType <LabourFilterGroup>().Count() >= 1)
                {
                    if (currentfg.Children.OfType <LabourFilterGroup>().Count() > 1)
                    {
                        string[] memberNames = new string[] { "Labour requirement" };
                        results.Add(new ValidationResult(String.Format("Invalid nested labour filter groups in [f={0}] for [a={1}]. Only one nested filter group is permitted each branch. Additional filtering will be ignored.", currentfg.Name, this.Name), memberNames));
                    }
                    currentfg = currentfg.Children.OfType <LabourFilterGroup>().FirstOrDefault();
                }
            }

            return(results);
        }
Exemple #4
0
        private void OnStartOfSimulation(object sender, EventArgs e)
        {
            // This needs to happen after all manage pasture activities have been initialised on commencing
            // Therefore we use StartOfSimulation event

            // link to pasture to muster to
            pasture = Activities.GetByName(ManagedPastureName) as PastureActivityManage;

            if (pasture == null)
            {
                Summary.WriteWarning(this, String.Format("Could not find manage pasture activity named \"{0}\" for {1}", ManagedPastureName, this.Name));
                throw new Exception(String.Format("Invalid pasture name ({0}) provided for mustering activity {1}", ManagedPastureName, this.Name));
            }

            if (LabourRequired > 0)
            {
                // check for and assign labour filter group
                LabourFilterList = this.Children.Where(a => a.GetType() == typeof(LabourFilterGroup)).Cast <object>().ToList();
                // if not present assume can use any labour and report
                if (LabourFilterList == null)
                {
                    Summary.WriteWarning(this, String.Format("No labour filter details provided for feeding activity ({0}). Assuming any labour type can be used", this.Name));
                    LabourFilterGroup lfg = new LabourFilterGroup();
                    LabourFilter      lf  = new LabourFilter()
                    {
                        Operator  = FilterOperators.GreaterThanOrEqual,
                        Value     = "0",
                        Parameter = LabourFilterParameters.Age
                    };
                    lfg.Children.Add(lf);
                    LabourFilterList = new List <object>();
                    LabourFilterList.Add(lfg);
                }
            }

            if (PerformAtStartOfSimulation)
            {
                Muster();
            }
        }
        private void OnSimulationCommencing(object sender, EventArgs e)
        {
            // check payment interval > 0
            if (BreedInterval <= 0)
            {
                Summary.WriteWarning(this, String.Format("Controlled mating interval must be greater than 1 ({0})", this.Name));
                throw new Exception(String.Format("Invalid controlled mating interval supplied for overhead {0}", this.Name));
            }

            if (MonthDue >= Clock.StartDate.Month)
            {
                NextDueDate = new DateTime(Clock.StartDate.Year, MonthDue, Clock.StartDate.Day);
            }
            else
            {
                NextDueDate = new DateTime(Clock.StartDate.Year, MonthDue, Clock.StartDate.Day);
                while (Clock.StartDate > NextDueDate)
                {
                    NextDueDate = NextDueDate.AddMonths(BreedInterval);
                }
            }

            // check for and assign labour filter group
            LabourFilterList = this.Children.Where(a => a.GetType() == typeof(LabourFilterGroup)).Cast <object>().ToList();
            // if not present assume can use any labour and report
            if (LabourFilterList == null)
            {
                Summary.WriteWarning(this, String.Format("No labour filter details provided for controlled mating settings ({0}). Assuming any labour type can be used", this.Name));
                LabourFilterGroup lfg = new LabourFilterGroup();
                LabourFilter      lf  = new LabourFilter()
                {
                    Operator  = FilterOperators.GreaterThanOrEqual,
                    Value     = "0",
                    Parameter = LabourFilterParameters.Age
                };
                lfg.Children.Add(lf);
                LabourFilterList = new List <object>();
                LabourFilterList.Add(lfg);
            }
        }
Exemple #6
0
        /// <summary>
        /// Method to determine available labour based on filters and take it if requested.
        /// </summary>
        /// <param name="request">Resource request details</param>
        /// <param name="removeFromResource">Determines if only calculating available labour or labour removed</param>
        /// <param name="callingModel">Model calling this method</param>
        /// <param name="resourceHolder">Location of resource holder</param>
        /// <param name="partialAction">Action on partial resources available</param>
        /// <returns></returns>
        public static double TakeLabour(ResourceRequest request, bool removeFromResource, IModel callingModel, ResourcesHolder resourceHolder, OnPartialResourcesAvailableActionTypes partialAction)
        {
            double            amountProvided = 0;
            double            amountNeeded   = request.Required;
            LabourFilterGroup current        = request.FilterDetails.OfType <LabourFilterGroup>().FirstOrDefault() as LabourFilterGroup;

            LabourRequirement lr;

            if (current != null)
            {
                if (current.Parent is LabourRequirement)
                {
                    lr = current.Parent as LabourRequirement;
                }
                else
                {
                    // coming from Transmutation request
                    lr = new LabourRequirement()
                    {
                        ApplyToAll       = false,
                        MaximumPerPerson = 1000,
                        MinimumPerPerson = 0
                    };
                }
            }
            else
            {
                lr = Apsim.Children(callingModel, typeof(LabourRequirement)).FirstOrDefault() as LabourRequirement;
            }

            int currentIndex = 0;

            if (current == null)
            {
                // no filtergroup provided so assume any labour
                current = new LabourFilterGroup();
            }

            request.ResourceTypeName = "Labour";
            ResourceRequest removeRequest = new ResourceRequest()
            {
                ActivityID         = request.ActivityID,
                ActivityModel      = request.ActivityModel,
                AdditionalDetails  = request.AdditionalDetails,
                AllowTransmutation = request.AllowTransmutation,
                Available          = request.Available,
                FilterDetails      = request.FilterDetails,
                Provided           = request.Provided,
                Reason             = request.Reason,
                Required           = request.Required,
                Resource           = request.Resource,
                ResourceType       = request.ResourceType,
                ResourceTypeName   = request.ResourceTypeName
            };

            // start with top most LabourFilterGroup
            while (current != null && amountProvided < amountNeeded)
            {
                List <LabourType> items = (resourceHolder.GetResourceGroupByType(request.ResourceType) as Labour).Items;
                items = items.Where(a => (a.LastActivityRequestID != request.ActivityID) || (a.LastActivityRequestID == request.ActivityID && a.LastActivityRequestAmount < lr.MaximumPerPerson)).ToList();
                items = items.Filter(current as Model);

                // search for people who can do whole task first
                while (amountProvided < amountNeeded && items.Where(a => a.LabourCurrentlyAvailableForActivity(request.ActivityID, lr.MaximumPerPerson) >= request.Required).Count() > 0)
                {
                    // get labour least available but with the amount needed
                    LabourType lt = items.Where(a => a.LabourCurrentlyAvailableForActivity(request.ActivityID, lr.MaximumPerPerson) >= request.Required).OrderBy(a => a.LabourCurrentlyAvailableForActivity(request.ActivityID, lr.MaximumPerPerson)).FirstOrDefault();

                    double amount = Math.Min(amountNeeded - amountProvided, lt.LabourCurrentlyAvailableForActivity(request.ActivityID, lr.MaximumPerPerson));

                    // limit to max allowed per person
                    amount = Math.Min(amount, lr.MaximumPerPerson);
                    // limit to min per person to do activity
                    if (amount < lr.MinimumPerPerson)
                    {
                        request.Reason = "Min labour limit";
                        return(amountProvided);
                    }

                    amountProvided        += amount;
                    removeRequest.Required = amount;
                    if (removeFromResource)
                    {
                        lt.LastActivityRequestID     = request.ActivityID;
                        lt.LastActivityRequestAmount = amount;
                        lt.Remove(removeRequest);
                        request.Provided += removeRequest.Provided;
                        request.Value    += request.Provided * lt.PayRate();
                    }
                }

                // if still needed and allow partial resource use.
                if (partialAction == OnPartialResourcesAvailableActionTypes.UseResourcesAvailable)
                {
                    if (amountProvided < amountNeeded)
                    {
                        // then search for those that meet criteria and can do part of task
                        foreach (LabourType item in items.Where(a => a.LabourCurrentlyAvailableForActivity(request.ActivityID, lr.MaximumPerPerson) >= 0).OrderByDescending(a => a.LabourCurrentlyAvailableForActivity(request.ActivityID, lr.MaximumPerPerson)))
                        {
                            if (amountProvided >= amountNeeded)
                            {
                                break;
                            }

                            double amount = Math.Min(amountNeeded - amountProvided, item.LabourCurrentlyAvailableForActivity(request.ActivityID, lr.MaximumPerPerson));

                            // limit to max allowed per person
                            amount = Math.Min(amount, lr.MaximumPerPerson);

                            // limit to min per person to do activity
                            if (amount >= lr.MinimumPerPerson)
                            {
                                amountProvided        += amount;
                                removeRequest.Required = amount;
                                if (removeFromResource)
                                {
                                    if (item.LastActivityRequestID != request.ActivityID)
                                    {
                                        item.LastActivityRequestAmount = 0;
                                    }
                                    item.LastActivityRequestID      = request.ActivityID;
                                    item.LastActivityRequestAmount += amount;
                                    item.Remove(removeRequest);
                                    request.Provided += removeRequest.Provided;
                                    request.Value    += request.Provided * item.PayRate();
                                }
                            }
                            else
                            {
                                currentIndex = request.FilterDetails.Count;
                            }
                        }
                    }
                }
                currentIndex++;
                if (current.Children.OfType <LabourFilterGroup>().Count() > 0)
                {
                    current = current.Children.OfType <LabourFilterGroup>().FirstOrDefault();
                }
                else
                {
                    current = null;
                }
            }
            // report amount gained.
            return(amountProvided);
        }
Exemple #7
0
        /// <summary>
        /// Method to determine available labour based on filters and take it if requested.
        /// </summary>
        /// <param name="request">Resource request details</param>
        /// <param name="removeFromResource">Determines if only calculating available labour or labour removed</param>
        /// <param name="callingModel">Model calling this method</param>
        /// <param name="resourceHolder">Location of resource holder</param>
        /// <param name="partialAction">Action on partial resources available</param>
        /// <returns></returns>
        public static double TakeLabour(ResourceRequest request, bool removeFromResource, IModel callingModel, ResourcesHolder resourceHolder, OnPartialResourcesAvailableActionTypes partialAction)
        {
            double            amountProvided = 0;
            double            amountNeeded   = request.Required;
            LabourFilterGroup current        = request.FilterDetails.OfType <LabourFilterGroup>().FirstOrDefault();

            LabourRequirement lr;

            if (current != null)
            {
                if (current.Parent is LabourRequirement)
                {
                    lr = current.Parent as LabourRequirement;
                }
                else
                {
                    // coming from Transmutation request
                    lr = new LabourRequirement()
                    {
                        LimitStyle       = LabourLimitType.AsDaysRequired,
                        ApplyToAll       = false,
                        MaximumPerGroup  = 10000,
                        MaximumPerPerson = 1000,
                        MinimumPerPerson = 0
                    }
                };
            }
            else
            {
                lr = callingModel.FindAllChildren <LabourRequirement>().FirstOrDefault();
            }

            lr.CalculateLimits(amountNeeded);
            amountNeeded     = Math.Min(amountNeeded, lr.MaximumDaysPerGroup);
            request.Required = amountNeeded;
            // may need to reduce request here or shortfalls will be triggered

            int currentIndex = 0;

            if (current == null)
            {
                // no filtergroup provided so assume any labour
                current = new LabourFilterGroup();
            }

            request.ResourceTypeName = "Labour";
            ResourceRequest removeRequest = new ResourceRequest()
            {
                ActivityID         = request.ActivityID,
                ActivityModel      = request.ActivityModel,
                AdditionalDetails  = request.AdditionalDetails,
                AllowTransmutation = request.AllowTransmutation,
                Available          = request.Available,
                FilterDetails      = request.FilterDetails,
                Provided           = request.Provided,
                Category           = request.Category,
                RelatesToResource  = request.RelatesToResource,
                Required           = request.Required,
                Resource           = request.Resource,
                ResourceType       = request.ResourceType,
                ResourceTypeName   = (request.Resource is null? "":(request.Resource as CLEMModel).NameWithParent)
            };

            // start with top most LabourFilterGroup
            while (current != null && amountProvided < amountNeeded)
            {
                IEnumerable <LabourType> items = resourceHolder.FindResource <Labour>().Items;
                items = items.Where(a => (a.LastActivityRequestID != request.ActivityID) || (a.LastActivityRequestID == request.ActivityID && a.LastActivityRequestAmount < lr.MaximumDaysPerPerson));
                items = current.Filter(items);

                // search for people who can do whole task first
                while (amountProvided < amountNeeded && items.Where(a => a.LabourCurrentlyAvailableForActivity(request.ActivityID, lr.MaximumDaysPerPerson) >= request.Required).Any())
                {
                    // get labour least available but with the amount needed
                    LabourType lt = items.Where(a => a.LabourCurrentlyAvailableForActivity(request.ActivityID, lr.MaximumDaysPerPerson) >= request.Required).OrderBy(a => a.LabourCurrentlyAvailableForActivity(request.ActivityID, lr.MaximumDaysPerPerson)).FirstOrDefault();

                    double amount = Math.Min(amountNeeded - amountProvided, lt.LabourCurrentlyAvailableForActivity(request.ActivityID, lr.MaximumDaysPerPerson));

                    // limit to max allowed per person
                    amount = Math.Min(amount, lr.MaximumDaysPerPerson);
                    // limit to min per person to do activity
                    if (amount < lr.MinimumPerPerson)
                    {
                        request.Category = "Min labour limit";
                        return(amountProvided);
                    }

                    amountProvided        += amount;
                    removeRequest.Required = amount;
                    if (removeFromResource)
                    {
                        lt.LastActivityRequestID     = request.ActivityID;
                        lt.LastActivityRequestAmount = amount;
                        lt.Remove(removeRequest);
                        request.Provided += removeRequest.Provided;
                        request.Value    += request.Provided * lt.PayRate();
                    }
                }

                // if still needed and allow partial resource use.
                if (partialAction == OnPartialResourcesAvailableActionTypes.UseResourcesAvailable)
                {
                    if (amountProvided < amountNeeded)
                    {
                        // then search for those that meet criteria and can do part of task
                        foreach (LabourType item in items.Where(a => a.LabourCurrentlyAvailableForActivity(request.ActivityID, lr.MaximumDaysPerPerson) >= 0).OrderByDescending(a => a.LabourCurrentlyAvailableForActivity(request.ActivityID, lr.MaximumDaysPerPerson)))
                        {
                            if (amountProvided >= amountNeeded)
                            {
                                break;
                            }

                            double amount = Math.Min(amountNeeded - amountProvided, item.LabourCurrentlyAvailableForActivity(request.ActivityID, lr.MaximumDaysPerPerson));

                            // limit to max allowed per person
                            amount = Math.Min(amount, lr.MaximumDaysPerPerson);

                            // limit to min per person to do activity
                            if (amount >= lr.MinimumDaysPerPerson)
                            {
                                amountProvided        += amount;
                                removeRequest.Required = amount;
                                if (removeFromResource)
                                {
                                    if (item.LastActivityRequestID != request.ActivityID)
                                    {
                                        item.LastActivityRequestAmount = 0;
                                    }
                                    item.LastActivityRequestID      = request.ActivityID;
                                    item.LastActivityRequestAmount += amount;
                                    item.Remove(removeRequest);
                                    request.Provided += removeRequest.Provided;
                                    request.Value    += request.Provided * item.PayRate();
                                }
                            }
                            else
                            {
                                currentIndex = request.FilterDetails.Count;
                            }
                        }
                    }
                }
                currentIndex++;
                var currentFilterGroups = current.FindAllChildren <LabourFilterGroup>();
                if (currentFilterGroups.Any())
                {
                    current = currentFilterGroups.FirstOrDefault();
                }
                else
                {
                    current = null;
                }
            }
            // report amount gained.
            return(amountProvided);
        }