public async Task <IActionResult> Edit(int id, [Bind("Id,Name")] LabourType labourType) { if (id != labourType.Id) { return(NotFound()); } if (ModelState.IsValid) { try { _context.Update(labourType); await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!LabourTypeExists(labourType.Id)) { return(NotFound()); } else { throw; } } return(RedirectToAction(nameof(Index))); } return(View(labourType)); }
public async Task <IActionResult> Create([Bind("Id,Name")] LabourType labourType) { if (ModelState.IsValid) { _context.Add(labourType); await _context.SaveChangesAsync(); return(RedirectToAction(nameof(Index))); } return(View(labourType)); }
private void AddLabour(string name, Employee employee, LabourType labourType, string activity) { _dataContext.Labours.Add(new Labour { Start = DateTime.Now.AddYears(-2), Name = name, Employee = employee, LabourType = labourType, Activity = activity }); }
/// <summary> /// Creates the a model for each Labour Type /// </summary> public IEnumerable <LabourType> GetLabourTypes(Labour parent) { List <LabourType> types = new List <LabourType>(); int row = -1; foreach (string item in LabourSupply.RowNames) { row++; if (LabourSupply.GetData <string>(row, 0) != "0") { // Finds the current demographic string demo = LabourSupply.ExtraNames[row] + " " + LabourSupply.RowNames[row]; // Tries to find an age for the demographic, defaults to 20 int age = 20; LabourAges.TryGetValue(demo, out age); int gender = 0; if (LabourSupply.RowNames[row].Contains("F")) { gender = 1; } LabourType type = new LabourType(parent) { Name = demo, InitialAge = age, Gender = gender, Individuals = LabourSupply.GetData <int>(row, 0) }; types.Add(type); } } return(types.AsEnumerable()); }
/// <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); }
private string CreateHTML() { string htmlString = "<!DOCTYPE html>\n" + "<html>\n<head>\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n<style>\n" + "body {color: [FontColor]; max-width:1000px; font-size:1em; font-family: Segoe UI, Arial, sans-serif}" + "table {border-collapse: collapse; font-size:0.8em; }" + "table,th,td {border: 1px solid #aaaaaa; }" + "table th {padding:3px; color:[HeaderFontColor]; vertical-align: bottom; text-align: center;}" + "th span {-ms-writing-mode: tb-rl;-webkit-writing-mode: vertical-rl;writing-mode: vertical-rl;transform: rotate(180deg);white-space: nowrap;}" + "table td {padding:3px; }" + "td:nth-child(n+2) {text-align:center;}" + "th:nth-child(1) {text-align:left;}" + "th {background-color: Black !important; }" + "tr:nth-child(2n+3) {background:[ResRowBack] !important;}" + "tr:nth-child(2n+2) {background:[ResRowBack2] !important;}" + "td.fill {background-color: #c1946c !important;}" + "table.main {[TableBackground] }" + "table.main tr td.disabled {color: [DisabledColour]; }" + ".dot { margin:auto; display:block; height:20px; width:20px; line-height:20px; background-color:black; -moz-border-radius: 10px; border-radius: 10px; }" + ".dot1 { background-color:#F5793A; }" + ".dot2 { background-color:#A95AA1; }" + ".dot3 { background-color:#85C0F9; }" + ".dot4 { background-color:#0F2080; }" + ".warningbanner {background-color:orange; border-radius:5px 5px 0px 0px; color:white; padding:5px; font-weight:bold }" + ".warningcontent {background-color:[WarningBackground]; margin-bottom:20px; border-radius:0px 0px 5px 5px; border-color:orange; border-width:1px; border-style:none solid solid solid; padding:10px;}" + ".messagebanner {background-color:CornflowerBlue; border-radius:5px 5px 0px 0px; color:white; padding:5px; font-weight:bold }" + ".messagecontent {background-color:[MessageBackground]; margin-bottom:20px; border-radius:0px 0px 5px 5px; border-color:CornflowerBlue; border-width:1px; border-style:none solid solid solid; padding:10px;}" + "li {margin-bottom:10px;}" + "table.blank td {border: 0px none [GridColor]; }" + "table.blank {border: 0px none #009999; border-collapse: collapse; }" + "table th:first-child {text-align:left; }" + "table th:nth-child(n+2) { /* Safari */ - webkit - transform: rotate(-90deg); /* Firefox */ -moz - transform: rotate(-90deg); /* IE */ -ms - transform: rotate(-90deg); /* Opera */ -o - transform: rotate(-90deg); /* Internet Explorer */ filter: progid: DXImageTransform.Microsoft.BasicImage(rotation = 3); }" + "table td:nth-child(n+2) { text-align:center; }" + ".clearfix { overflow: auto; }" + ".namediv { float:left; vertical-align:middle; }" + ".typediv { float:right; vertical-align:middle; font-size:0.6em; }" + ".holdermain {margin: 20px 0px 20px 0px}" + ".defaultbanner {background-color:[ContDefaultBanner] !important; border-radius:5px 5px 0px 0px; color:white; padding:5px; font-weight:bold }" + ".defaultcontent {background-color:[ContDefaultBack] !important; margin-bottom:20px; border-radius:0px 0px 5px 5px; border-color:[ContDefaultBanner]; border-width:1px; border-style:none solid solid solid; padding:10px;}" + "@media print { body { -webkit - print - color - adjust: exact; }}" + ".rotate {/* FF3.5+ */ -moz - transform: rotate(-90.0deg); /* Opera 10.5 */ -o - transform: rotate(-90.0deg); /* Saf3.1+, Chrome */ -webkit - transform: rotate(-90.0deg); /* IE6,IE7 */ filter: progid: DXImageTransform.Microsoft.BasicImage(rotation = 0.083); /* IE8 */ -ms - filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=0.083)\"; /* Standard */ transform: rotate(-90.0deg);} " + "\n</style>\n</head>\n<body>"; // Start building table // apply theme based settings if (!Utility.Configuration.Settings.DarkTheme) { // light theme htmlString = htmlString.Replace("[FontColor]", "#000000"); htmlString = htmlString.Replace("[GridColor]", "Black"); htmlString = htmlString.Replace("[WarningBackground]", "#FFFFFA"); htmlString = htmlString.Replace("[MessageBackground]", "#FAFAFF"); htmlString = htmlString.Replace("[DisabledColour]", "#cccccc"); htmlString = htmlString.Replace("[TableBackground]", "background-color: white;"); htmlString = htmlString.Replace("[ContDefaultBack]", "#FAFAFA"); htmlString = htmlString.Replace("[ContDefaultBanner]", "#000"); htmlString = htmlString.Replace("[HeaderFontColor]", "white"); } else { // dark theme htmlString = htmlString.Replace("[FontColor]", "#E5E5E5"); htmlString = htmlString.Replace("[GridColor]", "#888"); htmlString = htmlString.Replace("[WarningBackground]", "rgba(255, 102, 0, 0.4)"); htmlString = htmlString.Replace("[MessageBackground]", "rgba(100, 149, 237, 0.4)"); htmlString = htmlString.Replace("[DisabledColour]", "#666666"); htmlString = htmlString.Replace("[TableBackground]", "background-color: rgba(50, 50, 50, 0.5);"); htmlString = htmlString.Replace("[ContDefaultBack]", "#282828"); htmlString = htmlString.Replace("[ContDefaultBanner]", "#686868"); htmlString = htmlString.Replace("[HeaderFontColor]", "#333333"); } // get CLEM Zone IModel clem = model as IModel; while (!(clem is ZoneCLEM)) { clem = clem.Parent; } using (StringWriter htmlWriter = new StringWriter()) { htmlWriter.WriteLine(htmlString); htmlWriter.WriteLine("\n<span style=\"font-size:0.8em; font-weight:bold\">You will need to keep refreshing this page after changing settings and selecting the LabourAllocationsReport to see changes</span><br /><br />"); htmlWriter.Write("\n<div class=\"clearfix defaultbanner\">"); htmlWriter.Write($"<div class=\"namediv\">Labour allocation summary</div>"); htmlWriter.Write($"<div class=\"typediv\">Details</div>"); htmlWriter.Write("</div>"); htmlWriter.Write("\n<div class=\"defaultcontent\">"); htmlWriter.Write($"\n<div class=\"activityentry\">Summary last created on {DateTime.Now.ToShortDateString()} at {DateTime.Now.ToShortTimeString()}<br />"); htmlWriter.WriteLine("\n</div>"); htmlWriter.WriteLine("\n</div>"); // Get Labour resources labour = clem.FindAllDescendants <Labour>().FirstOrDefault() as Labour; if (labour == null) { htmlWriter.Write("No Labour supplied in resources"); htmlWriter.Write("\n</body>\n</html>"); return(htmlWriter.ToString()); } numberLabourTypes = labour.FindAllChildren <LabourType>().Count(); if (numberLabourTypes == 0) { htmlWriter.Write("No Labour types supplied in Labour resource"); htmlWriter.Write("\n</body>\n</html>"); return(htmlWriter.ToString()); } // create labour list labourList.Clear(); foreach (LabourType lt in labour.FindAllChildren <LabourType>()) { var newLabour = new LabourType() { Parent = labour, Name = lt.Name, AgeInMonths = lt.InitialAge * 12, Sex = lt.Sex }; IndividualAttribute att = new IndividualAttribute() { StoredValue = lt.Name }; newLabour.Attributes.Add("Group", att); labourList.Add(newLabour); } // get all parents of LabourRequirement validpAtt.AddRange(ReflectionUtilities.GetAttributes(typeof(LabourRequirement), typeof(ValidParentAttribute), false).Cast <ValidParentAttribute>().ToList()); validpAtt.AddRange(ReflectionUtilities.GetAttributes(typeof(LabourRequirementNoUnitSize), typeof(ValidParentAttribute), false).Cast <ValidParentAttribute>().ToList()); validpAtt.AddRange(ReflectionUtilities.GetAttributes(typeof(LabourRequirementSimple), typeof(ValidParentAttribute), false).Cast <ValidParentAttribute>().ToList()); if (validpAtt.Count() == 0) { htmlWriter.Write("No components allow Labour Requirements to be added"); htmlWriter.Write("\n</body>\n</html>"); return(htmlWriter.ToString()); } // walk through all activities // check if LabourRequirement can be added ActivitiesHolder activities = clem.FindDescendant <ActivitiesHolder>(); if (activities == null) { htmlWriter.Write("Could not find an Activities Holder"); htmlWriter.Write("\n</body>\n</html>"); return(htmlWriter.ToString()); } using (StringWriter tableHtml = new StringWriter()) { tableHtml.WriteLine("<table class=\"main\">"); tableHtml.Write("<tr><th>Activity</th>"); foreach (LabourType lt in labour.FindAllChildren <LabourType>()) { tableHtml.Write($"<th><span>{lt.Name}</span></th>"); } tableHtml.WriteLine("</tr>"); tableHtml.WriteLine(TableRowHTML(activities)); tableHtml.WriteLine("</table>"); htmlWriter.Write(tableHtml.ToString()); } // add notes htmlWriter.WriteLine("\n<div class=\"holdermain\">"); htmlWriter.Write("\n<div class=\"clearfix messagebanner\">"); htmlWriter.Write("<div class=\"typediv\">" + "Notes" + "</div>"); htmlWriter.Write("</div>"); htmlWriter.WriteLine("\n<div class=\"messagecontent\">"); htmlWriter.WriteLine("\n<ul>"); htmlWriter.WriteLine("\n<li>Only activities capable of including a labour requirement are displayed.</li>"); htmlWriter.WriteLine("\n<li>Activities with no labour requirement provided are displayed with grey text.</li>"); htmlWriter.WriteLine("\n<li>Multiple rows of icons (circles) for a given activity show where more than one individual is required.</li>"); htmlWriter.WriteLine("\n<li>The preferential allocation of labour is displayed in the following order:" + "<table class=\"blank\">" + "<tr><td><span class=\"dot dot1 \">" + "</span></td><td>1st preference</td></tr>" + "<tr><td><span class=\"dot dot2 \">" + "</span></td><td>2nd preference</td></tr>" + "<tr><td><span class=\"dot dot3 \">" + "</span></td><td>3rd preference</td></tr>" + "<tr><td><span class=\"dot dot4 \">" + "</span></td><td>4th+ preference</td></tr>" + "</table></li>"); htmlWriter.WriteLine("\n</ul>"); htmlWriter.Write("\n</div>"); // aging note if (labour.AllowAging) { htmlWriter.WriteLine("\n<div class=\"holdermain\">"); htmlWriter.WriteLine("\n<div class=\"clearfix warningbanner\">"); htmlWriter.Write("<div class=\"typediv\">" + "Warning" + "</div>"); htmlWriter.Write("</div>"); htmlWriter.Write("\n<div class=\"warningcontent\">"); htmlWriter.Write("\n<div class=\"activityentry\">As this simulation allows aging of individuals (see Labour) these allocations may change over the duration of the simulation. "); htmlWriter.Write("\n</div>"); htmlWriter.WriteLine("\n</div>"); } htmlWriter.Write("\n</body>\n</html>"); return(htmlWriter.ToString()); } }
private string CreateMarkdown() { using (StringWriter markdownString = new StringWriter()) { // Start building table IModel clem = model.FindAncestor <ZoneCLEM>() as IModel; // Get Labour resources labour = clem.FindAllDescendants <Labour>().FirstOrDefault() as Labour; if (labour == null) { markdownString.Write("No Labour supplied in resources"); return(markdownString.ToString()); } numberLabourTypes = labour.FindAllChildren <LabourType>().Count(); if (numberLabourTypes == 0) { markdownString.Write("No Labour types supplied in Labour resource"); return(markdownString.ToString()); } labourList.Clear(); foreach (LabourType lt in labour.FindAllChildren <LabourType>()) { var newLabour = new LabourType() { Parent = labour, Name = lt.Name, AgeInMonths = lt.InitialAge * 12, Sex = lt.Sex }; IndividualAttribute att = new IndividualAttribute() { StoredValue = lt.Name }; newLabour.Attributes.Add("Group", att); labourList.Add(newLabour); } // get all parents of LabourRequirement validpAtt.AddRange(ReflectionUtilities.GetAttributes(typeof(LabourRequirement), typeof(ValidParentAttribute), false).Cast <ValidParentAttribute>().ToList()); validpAtt.AddRange(ReflectionUtilities.GetAttributes(typeof(LabourRequirementNoUnitSize), typeof(ValidParentAttribute), false).Cast <ValidParentAttribute>().ToList()); validpAtt.AddRange(ReflectionUtilities.GetAttributes(typeof(LabourRequirementSimple), typeof(ValidParentAttribute), false).Cast <ValidParentAttribute>().ToList()); if (validpAtt.Count() == 0) { markdownString.Write("No components allow Labour Requirements to be added"); return(markdownString.ToString()); } // walk through all activities // check if LabourRequirement can be added ActivitiesHolder activities = clem.FindAllDescendants <ActivitiesHolder>().FirstOrDefault() as ActivitiesHolder; if (activities == null) { markdownString.Write("Could not find an Activities Holder"); return(markdownString.ToString()); } using (StringWriter tableHeader = new StringWriter()) { using (StringWriter tableSpacer = new StringWriter()) { tableHeader.Write("| Activity"); tableSpacer.Write("| :---"); foreach (LabourType lt in labour.FindAllChildren <LabourType>()) { tableHeader.Write(" | " + lt.Name.Replace("_", " ")); tableSpacer.Write(" | :---:"); } tableHeader.Write(" | \n"); tableSpacer.Write(" | \n"); markdownString.Write(tableHeader.ToString()); markdownString.Write(tableSpacer.ToString()); } } markdownString.Write(TableRowMarkdown(activities)); // add notes markdownString.Write(" \n*** \n"); markdownString.Write("Notes \n"); markdownString.Write("- Only activities capable of including a labour requirement are displayed. \n"); markdownString.Write("- Activities with no labour requirement provided are displayed with italic text. \n"); markdownString.Write("- Multiple rows for a given activity show where more than one individual is required. \n"); markdownString.Write("- The preferential allocation of labour is identified from 1 (1st) to 5 (5th, max levels displayed) \n"); // aging note if (labour.AllowAging) { markdownString.Write(" \n*** \n"); markdownString.Write("Warnings \n"); markdownString.Write("- As this simulation allows aging of individuals (see Labour) these allocations may change over the duration of the simulation."); } markdownString.Write(" \n*** \n"); return(markdownString.ToString()); } }
/// <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); }