Пример #1
0
        /// <summary>
        /// A common method to get the labour resource requests from the activity.
        /// </summary>
        /// <returns></returns>
        protected List <ResourceRequest> GetLabourResourcesNeededForActivity()
        {
            List <ResourceRequest> labourResourceRequestList = new List <ResourceRequest>();

            foreach (LabourRequirement item in Children.Where(a => a.GetType() == typeof(LabourRequirement) | a.GetType().IsSubclassOf(typeof(LabourRequirement))))
            {
                GetDaysLabourRequiredReturnArgs daysResult = GetDaysLabourRequired(item);
                if (daysResult.DaysNeeded > 0)
                {
                    foreach (LabourFilterGroup fg in item.Children.OfType <LabourFilterGroup>())
                    {
                        int numberOfPpl = 1;
                        if (item.ApplyToAll)
                        {
                            // how many matches
                            numberOfPpl = (Resources.GetResourceGroupByType(typeof(Labour)) as Labour).Items.Filter(fg).Count();
                        }
                        for (int i = 0; i < numberOfPpl; i++)
                        {
                            labourResourceRequestList.Add(new ResourceRequest()
                            {
                                AllowTransmutation = true,
                                Required           = daysResult.DaysNeeded,
                                ResourceType       = typeof(Labour),
                                ResourceTypeName   = "",
                                ActivityModel      = this,
                                FilterDetails      = new List <object>()
                                {
                                    fg
                                },
                                Category          = daysResult.Category,
                                RelatesToResource = daysResult.RelatesToResource
                            }
                                                          );;
                        }
                    }
                }
            }
            return(labourResourceRequestList);
        }
Пример #2
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);
        }
Пример #3
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);
        }