/// <summary> /// Method used to perform activity if it can occur as soon as resources are available. /// </summary> public override void DoActivity() { Status = ActivityStatus.NotNeeded; double labourlimit = this.LabourLimitProportion; double units = 0; if (labourlimit == 1 || this.OnPartialResourcesAvailableAction == OnPartialResourcesAvailableActionTypes.UseResourcesAvailable) { units = unitsAvailableForSale * labourlimit; if (price.UseWholePackets) { units = Math.Truncate(units); } } if (units > 0) { // remove resource ResourceRequest purchaseRequest = new ResourceRequest { ActivityModel = this, Required = units * price.PacketSize, AllowTransmutation = false, Reason = "Sell " + (resourceToSell as Model).Name }; resourceToSell.Remove(purchaseRequest); // transfer money earned bankAccount.Add(units * price.PricePerPacket, this, "Sales"); SetStatusSuccess(); } }
///// <summary> ///// Determines if a shortfall in all Resources can be met by transmutation ///// </summary> //public void CanTransmutateShortfall(List<ResourceRequest> requests) //{ // List<ResourceRequest> shortfallRequests = requests.Where(a => a.Required - a.Available > 0).ToList(); // // Search through all limited resources and determine if transmutation available // foreach (ResourceRequest request in shortfallRequests) // { // // Check if transmutation would be successful // if (request.AllowTransmutation) // { // // get resource type // bool resourceAvailable = false; // IModel model = this.GetResourceItem(request.ResourceName, request.ResourceTypeName, out resourceAvailable) as IModel; // if (model != null) // { // // check if transmutations provided // foreach (Transmutation trans in model.Children.Where(a => a.GetType() == typeof(Transmutation))) // { // // check if resources available for activity and transmutation // double unitsNeeded = Math.Ceiling((request.Required - request.Available) / trans.AmountPerUnitPurchase); // foreach (TransmutationCost transcost in trans.Children.Where(a => a.GetType() == typeof(TransmutationCost))) // { // double transmutationCost = unitsNeeded * transcost.CostPerUnit; // double activityCost = requests.Where(a => a.ResourceName == transcost.ResourceName & a.ResourceTypeName == transcost.ResourceTypeName).Sum(a => a.Required); // if(transmutationCost+activityCost <= (model as IResourceType).Amount) // { // request.TransmutationSuccessful = true; // break; // } // } // } // } // } // } //} /// <summary> /// Performs the transmutation of resources into a required resource /// </summary> public void TransmutateShortfall(List <ResourceRequest> requests, bool QueryOnly) { List <ResourceRequest> shortfallRequests = requests.Where(a => a.Required > a.Available).ToList(); // Search through all limited resources and determine if transmutation available foreach (ResourceRequest request in shortfallRequests) { // Check if transmutation would be successful if (request.AllowTransmutation & (QueryOnly || request.TransmutationPossible)) { // get resource type bool resourceAvailable = false; IModel model = this.GetResourceItem(request.ResourceName, request.ResourceTypeName, out resourceAvailable) as IModel; if (model != null) { // check if transmutations provided foreach (Transmutation trans in model.Children.Where(a => a.GetType() == typeof(Transmutation))) { // check if resources available for activity and transmutation double unitsNeeded = Math.Ceiling((request.Required - request.Available) / trans.AmountPerUnitPurchase); foreach (TransmutationCost transcost in trans.Children.Where(a => a.GetType() == typeof(TransmutationCost))) { double transmutationCost = unitsNeeded * transcost.CostPerUnit; if (!QueryOnly) { //remove cost IResourceType transResource = this.GetResourceItem(transcost.ResourceName, transcost.ResourceTypeName, out resourceAvailable) as IResourceType; transResource.Remove(transmutationCost, trans.Name, trans.Parent.Name); } else { double activityCost = requests.Where(a => a.ResourceName == transcost.ResourceName & a.ResourceTypeName == transcost.ResourceTypeName).Sum(a => a.Required); IResourceType resourceToTake = this.GetResourceItem(transcost.ResourceName, transcost.ResourceTypeName, out resourceAvailable) as IResourceType; if (transmutationCost + activityCost <= resourceToTake.Amount) { request.TransmutationPossible = true; break; } } } if (!QueryOnly) { // Add resource (model as IResourceType).Add(unitsNeeded * trans.AmountPerUnitPurchase, trans.Name, ""); } } } } } }
/// <inheritdoc/> public override void DoActivity() { Status = ActivityStatus.NotNeeded; double labourlimit = this.LabourLimitProportion; double units = 0; if (labourlimit == 1 || this.OnPartialResourcesAvailableAction == OnPartialResourcesAvailableActionTypes.UseResourcesAvailable) { units = unitsAvailableForSale * labourlimit; if (price.UseWholePackets) { units = Math.Truncate(units); } } if (units > 0) { // remove resource ResourceRequest purchaseRequest = new ResourceRequest { ActivityModel = this, Required = units * price.PacketSize, AllowTransmutation = true, Category = TransactionCategory, RelatesToResource = (resourceToSell as CLEMModel).NameWithParent }; resourceToSell.Remove(purchaseRequest); // transfer money earned if (bankAccount != null) { if (price.PricePerPacket == 0) { string warn = $"No price set [0] for [r={resourceToSell.Name}] at time of transaction for [a={this.Name}]{Environment.NewLine}No financial transactions will occur.{Environment.NewLine}Ensure price is set or resource pricing file contains entries before this transaction or start of simulation."; Warnings.CheckAndWrite(warn, Summary, this, MessageType.Warning); } bankAccount.Add(units * price.PricePerPacket, this, (resourceToSell as CLEMModel).NameWithParent, TransactionCategory); if (bankAccount.EquivalentMarketStore != null) { purchaseRequest.Required = units * price.PricePerPacket; purchaseRequest.Category = TransactionCategory; purchaseRequest.RelatesToResource = (resourceToSell as CLEMModel).NameWithParent; (bankAccount.EquivalentMarketStore as FinanceType).Remove(purchaseRequest); } } SetStatusSuccess(); } }
private void OnWFRequestFeed(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; IResourceType grazeStoreType = null; if (FeedArbitratorName != "") { grazeStoreType = Arbitrators.GetByName(FeedArbitratorName) as IResourceType; } // for each paddock defined in PastureActivityManage foreach (PastureActivityManage pasture in Activities.Children.Where(a => a.GetType() == typeof(PastureActivityManage))) { if (FeedArbitratorName == "") { grazeStoreType = pasture.FeedType; } // create feeding activity for this pasture RuminantActivityGraze activity = new RuminantActivityGraze(); activity.FeedPriority = this.FeedPriority; activity.FeedType = pasture.FeedType; activity.HoursGrazed = this.HoursGrazed; activity.Name = String.Format("Graze {0}", pasture.FeedType.Name); // calculate kg per ha available double kgPerHa = pasture.FeedType.Amount / pasture.Area; if (pasture.FeedType.Amount > 0) { // get list of all Ruminants in this paddock foreach (Ruminant ind in herd.Where(a => a.Location == pasture.Name)) { RuminantFeedRequest freqest = new RuminantFeedRequest(); freqest.FeedActivity = activity; freqest.Requestor = ind; // Reduce potential intake based on pasture quality for the proportion consumed. // calculate intake from potential modified by pasture availability and hours grazed freqest.Amount = ind.PotentialIntake * (1 - Math.Exp(-ind.BreedParams.IntakeCoefficientBiomass * kgPerHa)) * (HoursGrazed / 8); grazeStoreType.Remove(freqest); } } } }
/// <summary> /// Method used to perform activity if it can occur as soon as resources are available. /// </summary> public override void DoActivity() { if (this.TimingOK) { // reduce if labour limiting double labourlimit = 1; if (ResourceRequestList != null && ResourceRequestList.Where(a => a.ResourceType == typeof(Labour)).Count() > 0) { double amountLabourNeeded = ResourceRequestList.Where(a => a.ResourceType == typeof(Labour)).Sum(a => a.Required); double amountLabourProvided = ResourceRequestList.Where(a => a.ResourceType == typeof(Labour)).Sum(a => a.Provided); if (amountLabourNeeded > 0) { if (amountLabourProvided == 0) { labourlimit = 0; } else { labourlimit = amountLabourNeeded / amountLabourProvided; } } } double units = 0; if (labourlimit == 1 || this.OnPartialResourcesAvailableAction == OnPartialResourcesAvailableActionTypes.UseResourcesAvailable) { units = UnitsAvailableForSale * labourlimit; if (SellWholeUnitsOnly) { units = Math.Truncate(units); } } if (units > 0) { // remove resource ResourceRequest purchaseRequest = new ResourceRequest(); purchaseRequest.ActivityModel = this; purchaseRequest.Required = units * UnitSize; purchaseRequest.AllowTransmutation = false; purchaseRequest.Reason = "Sales"; resourceToSell.Remove(purchaseRequest); // transfer money earned bankAccount.Add(units * UnitPrice, this.Name, "Sales"); SetStatusSuccess(); } } }
/// <summary> /// Method used to perform activity if it can occur as soon as resources are available. /// </summary> public override void DoActivity() { Status = ActivityStatus.NotNeeded; double labourlimit = this.LabourLimitProportion; double units = 0; if (labourlimit == 1 || this.OnPartialResourcesAvailableAction == OnPartialResourcesAvailableActionTypes.UseResourcesAvailable) { units = unitsAvailableForSale * labourlimit; if (price.UseWholePackets) { units = Math.Truncate(units); } } if (units > 0) { // remove resource ResourceRequest purchaseRequest = new ResourceRequest { ActivityModel = this, Required = units * price.PacketSize, AllowTransmutation = true, Category = "Sell", RelatesToResource = (resourceToSell as CLEMModel).NameWithParent }; resourceToSell.Remove(purchaseRequest); // transfer money earned if (bankAccount != null) { bankAccount.Add(units * price.PricePerPacket, this, (resourceToSell as CLEMModel).NameWithParent, "Sales"); if (bankAccount.EquivalentMarketStore != null) { purchaseRequest.Required = units * price.PricePerPacket; purchaseRequest.Category = "Sales"; purchaseRequest.RelatesToResource = (resourceToSell as CLEMModel).NameWithParent; (bankAccount.EquivalentMarketStore as FinanceType).Remove(purchaseRequest); } } SetStatusSuccess(); } }
/// <summary> /// Performs the transmutation of resources into a required resource /// </summary> public void TransmutateShortfall(List <ResourceRequest> requests, bool queryOnly) { List <ResourceRequest> shortfallRequests = requests.Where(a => a.Required > a.Available).ToList(); // Search through all limited resources and determine if transmutation available foreach (ResourceRequest request in shortfallRequests) { // Check if transmutation would be successful if (request.AllowTransmutation && (queryOnly || request.TransmutationPossible)) { // get resource type IModel model = this.GetResourceItem(request.ActivityModel, request.ResourceType, request.ResourceTypeName, OnMissingResourceActionTypes.Ignore, OnMissingResourceActionTypes.Ignore) as IModel; if (model != null) { // check if transmutations provided foreach (Transmutation trans in Apsim.Children(model, typeof(Transmutation))) { // check if resources available for activity and transmutation double unitsNeeded = Math.Ceiling((request.Required - request.Available) / trans.AmountPerUnitPurchase); foreach (ITransmutationCost transcost in Apsim.Children(trans, typeof(IModel)).Where(a => a is ITransmutationCost).Cast <ITransmutationCost>()) { double transmutationCost = unitsNeeded * transcost.CostPerUnit; // get transcost resource IResourceType transResource = null; if (transcost.ResourceType.Name != "Labour") { transResource = this.GetResourceItem(request.ActivityModel, transcost.ResourceTypeName, OnMissingResourceActionTypes.Ignore, OnMissingResourceActionTypes.Ignore) as IResourceType; } if (!queryOnly) { //remove cost // create new request for this transmutation cost ResourceRequest transRequest = new ResourceRequest(); transRequest.Reason = trans.Name + " " + trans.Parent.Name; transRequest.Required = transmutationCost; transRequest.ResourceType = transcost.ResourceType; transRequest.ActivityModel = request.ActivityModel; // used to pass request, but this is not the transmutation cost if (transcost.ResourceType.Name == "Labour") { transRequest.ResourceType = typeof(Labour); transRequest.FilterDetails = Apsim.Children(transcost as IModel, typeof(LabourFilterGroup)).ToList <object>(); CLEMActivityBase.TakeLabour(transRequest, true, transRequest.ActivityModel, this, OnPartialResourcesAvailableActionTypes.UseResourcesAvailable); } else { transResource.Remove(transRequest); } } else { double activityCost = requests.Where(a => a.ResourceType == transcost.ResourceType && a.ResourceTypeName == transcost.ResourceTypeName).Sum(a => a.Required); if (transmutationCost + activityCost <= transResource.Amount) { request.TransmutationPossible = true; break; } } } if (!queryOnly) { // Add resource (model as IResourceType).Add(unitsNeeded * trans.AmountPerUnitPurchase, trans, ""); } } } } } }
/// <summary> /// Performs the transmutation of resources into a required resource /// </summary> public void TransmutateShortfall(List <ResourceRequest> requests, bool queryOnly) { List <ResourceRequest> shortfallRequests = requests.Where(a => a.Required > a.Available).ToList(); // Search through all limited resources and determine if transmutation available foreach (ResourceRequest request in shortfallRequests) { // Check if transmutation would be successful if (request.AllowTransmutation && (queryOnly || request.TransmutationPossible)) { // get resource type IModel model = request.Resource as IModel; if (model is null) { model = this.GetResourceItem(request.ActivityModel, request.ResourceType, request.ResourceTypeName, OnMissingResourceActionTypes.Ignore, OnMissingResourceActionTypes.Ignore) as IModel; } if (model != null) { // get the resource holder to use for this request // not it is either this class or the holder for the market place required. ResourcesHolder resHolder = model.Parent.Parent as ResourcesHolder; // check if transmutations provided foreach (Transmutation trans in model.FindAllChildren <Transmutation>()) { double unitsNeeded = 0; // check if resources available for activity and transmutation foreach (ITransmutationCost transcost in trans.FindAllChildren <IModel>().Where(a => a is ITransmutationCost).Cast <ITransmutationCost>()) { double unitsize = trans.AmountPerUnitPurchase; if (transcost is TransmutationCostUsePricing) { // use pricing details if needed unitsize = (transcost as TransmutationCostUsePricing).Pricing.PacketSize; } unitsNeeded = Math.Ceiling((request.Required - request.Available) / unitsize); double transmutationCost; if (transcost is TransmutationCostUsePricing) { // use pricing details if needed transmutationCost = unitsNeeded * (transcost as TransmutationCostUsePricing).Pricing.PricePerPacket; } else { transmutationCost = unitsNeeded * transcost.CostPerUnit; } // get transcost resource IResourceType transResource = null; if (transcost.ResourceType.Name != "Labour") { transResource = resHolder.GetResourceItem(request.ActivityModel, transcost.ResourceTypeName, OnMissingResourceActionTypes.Ignore, OnMissingResourceActionTypes.Ignore) as IResourceType; } if (!queryOnly) { // remove cost // create new request for this transmutation cost ResourceRequest transRequest = new ResourceRequest { Reason = trans.Name + " " + trans.Parent.Name, Required = transmutationCost, ResourceType = transcost.ResourceType, ActivityModel = request.ActivityModel }; // used to pass request, but this is not the transmutation cost if (transcost.ResourceType.Name == "Labour") { transRequest.ResourceType = typeof(Labour); transRequest.FilterDetails = (transcost as IModel).FindAllChildren <LabourFilterGroup>().ToList <object>(); CLEMActivityBase.TakeLabour(transRequest, true, transRequest.ActivityModel, this, OnPartialResourcesAvailableActionTypes.UseResourcesAvailable); } else { transResource.Remove(transRequest); } } else { double activityCost = requests.Where(a => a.ResourceType == transcost.ResourceType && a.ResourceTypeName == transcost.ResourceTypeName).Sum(a => a.Required); if (transmutationCost + activityCost <= transResource.Amount) { request.TransmutationPossible = true; break; } } } if (!queryOnly) { // Add resource (model as IResourceType).Add(unitsNeeded * trans.AmountPerUnitPurchase, trans, "Transmutation"); } } } } } }
/// <summary> /// Method to get this time steps current required resources for this activity. /// </summary> public void GetResourcesRequired() { bool resourceAvailable = false; // determine what resources are needed ResourceRequestList = DetermineResourcesNeeded(); // no resources required or this is an Activity folder. if (ResourceRequestList == null) { return; } // check resource amounts available foreach (ResourceRequest request in ResourceRequestList) { request.Available = 0; // get resource IResourceType resource = Resources.GetResourceItem(request, out resourceAvailable) as IResourceType; if (resource != null) { // get amount available request.Available = Math.Min(resource.Amount, request.Required); } else { if (!resourceAvailable) { // if resource does not exist in simulation assume unlimited resource available // otherwise 0 will be assigned to available when no resouces match request request.Available = request.Required; } } } // are all resources available List <ResourceRequest> shortfallRequests = ResourceRequestList.Where(a => a.Required > a.Available).ToList(); int countShortfallRequests = shortfallRequests.Count(); if (countShortfallRequests > 0) { // check what transmutations can occur Resources.TransmutateShortfall(shortfallRequests, true); } // check if need to do transmutations int countTransmutationsSuccessful = shortfallRequests.Where(a => a.TransmutationPossible == true & a.AllowTransmutation).Count(); bool allTransmutationsSuccessful = (shortfallRequests.Where(a => a.TransmutationPossible == false & a.AllowTransmutation).Count() == 0); // OR at least one transmutation successful and PerformWithPartialResources if (((countShortfallRequests > 0) & (countShortfallRequests == countTransmutationsSuccessful)) ^ (countTransmutationsSuccessful > 0 & PerformWithPartialResources)) { // do transmutations. Resources.TransmutateShortfall(shortfallRequests, false); // recheck resource amounts now that resources have been topped up foreach (ResourceRequest request in ResourceRequestList) { resourceAvailable = false; // get resource request.Available = 0; IResourceType resource = Resources.GetResourceItem(request, out resourceAvailable) as IResourceType; if (resource != null) { // get amount available request.Available = Math.Max(resource.Amount, request.Required); } } } // remove activity resources // check if deficit and performWithPartial if ((ResourceRequestList.Where(a => a.Required > a.Available).Count() == 0) | PerformWithPartialResources) { foreach (ResourceRequest request in ResourceRequestList) { resourceAvailable = false; // get resource request.Provided = 0; IResourceType resource = Resources.GetResourceItem(request, out resourceAvailable) as IResourceType; if (resource != null) { // get amount available request.Provided = Math.Min(resource.Amount, request.Required); // remove resource request.Provided = resource.Remove(request.Provided, this.Name, request.Requestor); } } PerformActivity(); } }