/// <summary> /// Resource price /// </summary> public ResourcePricing Price(PurchaseOrSalePricingStyleType priceType) { // find pricing that is ok; ResourcePricing price = Apsim.Children(this, typeof(ResourcePricing)).Where(a => a.Enabled & ((a as ResourcePricing).PurchaseOrSale == PurchaseOrSalePricingStyleType.Both | (a as ResourcePricing).PurchaseOrSale == priceType) && (a as ResourcePricing).TimingOK).FirstOrDefault() as ResourcePricing; // does simulation have finance ResourcesHolder resources = Apsim.Parent(this, typeof(ResourcesHolder)) as ResourcesHolder; bool financesPresent = (resources.FinanceResource() != null); if (price == null) { if (financesPresent) { string warn = "No pricing is available for [r=" + this.Parent.Name + "." + this.Name + "]"; if (Clock != null & Apsim.Children(this, typeof(ResourcePricing)).Count > 0) { warn += " in month [" + Clock.Today.ToString("MM yyyy") + "]"; } warn += "\nAdd [r=ResourcePricing] component to [r=" + this.Parent.Name + "." + this.Name + "] to include financial transactions for purchases and sales."; if (!Warnings.Exists(warn) & Summary != null) { Summary.WriteWarning(this, warn); Warnings.Add(warn); } } return(new ResourcePricing() { PricePerPacket = 0, PacketSize = 1, UseWholePackets = true }); } return(price); }
/// <summary> /// Locate the equivalent store in a market if available /// </summary> protected void FindEquivalentMarketStore() { // determine what resource types allow market transactions switch (this.GetType().Name) { case "FinanceType": case "HumanFoodStoreType": case "WaterType": case "AnimalFoodType": case "EquipmentType": case "GreenhousGasesType": case "ProductStoreType": break; default: throw new NotImplementedException($"\n[r={this.Parent.GetType().Name}] resource does not currently support transactions to and from a [m=Market]\nThis problem has arisen because a resource transaction in the code is flagged to exchange resources with the [m=Market]\nPlease contact developers for assistance."); } // if not already checked if (!equivalentMarketStoreDetermined) { // havent already found a market store if (equivalentMarketStore is null) { // is there a market Market market = FindMarket(); if (market != null) { // get the resources ResourcesHolder holder = Apsim.Child(market, typeof(ResourcesHolder)) as ResourcesHolder; if (holder != null) { object store = null; holder.ResourceTypeExists(this, out store); if (store != null) { equivalentMarketStore = store as CLEMResourceTypeBase; } } } } } }
/// <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"); } } } } } }