Пример #1
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 = callingModel.FindAllChildren <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);
        }