/// <summary> /// Returns the link to the matching resource in the market place if found or creates a new clone copy for future transactions /// This allows this action to be performed once to store the link rather than at every transaction /// This functionality allows resources not in the market at the start of the simulation to be traded. /// </summary> /// <param name="resourceType">The resource type to trade</param> /// <returns>Whether the search was successful</returns> public IResourceWithTransactionType LinkToMarketResourceType(CLEMResourceTypeBase resourceType) { if (!(this.Parent is Market)) { throw new ApsimXException(this, $"Logic error in code. Trying to link a resource type [r={resourceType.Name}] from the market with the same market./nThis is a coding issue. Please contact the developers"); } // find parent group type ResourceBaseWithTransactions parent = (resourceType as Model).Parent as ResourceBaseWithTransactions; ResourceBaseWithTransactions resGroup = GetResourceGroupByType(parent.GetType()) as ResourceBaseWithTransactions; if (resGroup is null) { // add warning the market is not currently trading in this resource string zoneName = FindAncestor <Zone>().Name; string warn = $"[{zoneName}] is currently not accepting resources of type [r={parent.GetType().ToString()}]\nOnly resources groups provided in the [r=ResourceHolder] in the simulation tree will be traded."; if (!Warnings.Exists(warn) & Summary != null) { Summary.WriteWarning(this, warn); Warnings.Add(warn); } return(null); } // TODO: do some group checks. land units, currency // TODO: if market and looking for finance only return or create "Bank" // find resource type in group object resType = resGroup.GetByName((resourceType as IModel).Name) as IResourceWithTransactionType; if (resType is null) { // clone resource // too many problems with linked events to clone these objects and setup again // it will be the responsibility of the user to ensure the resources and details are in the market // resType = Apsim.Clone(resourceType); if (resType is null) { // add warning the market does not have the resource string zoneName = FindAncestor <Zone>().Name; string warn = $"The resource [r={resourceType.Parent.Name}.{resourceType.Name}] does not exist in [m={this.Parent.Name}].\nAdd resource and associated components to the market to permit trading."; if (!Warnings.Exists(warn) & Summary != null) { Summary.WriteWarning(this, warn); Warnings.Add(warn); } return(null); } else { (resType as IModel).Parent = resGroup; (resType as CLEMModel).CLEMParentName = resGroup.CLEMParentName; // add new resource type resGroup.AddNewResourceType(resType as IResourceWithTransactionType); } } return(resType as IResourceWithTransactionType); }
/// <summary> /// Returns the link to the matching resource in the market place if found or creates a new clone copy for future transactions /// This allows this action to be performed once to store the link rather than at every transaction /// This functionality allows resources not in the market at the start of the simulation to be traded. /// </summary> /// <param name="resourceType">The resource type to trade</param> /// <param name="linkToResourceType">A link to the associated resource type</param> /// <returns>Whether the search was successful</returns> public bool ResourceTypeExists(CLEMResourceTypeBase resourceType, out object linkToResourceType) { linkToResourceType = null; // find parent group type ResourceBaseWithTransactions parent = (resourceType as Model).Parent as ResourceBaseWithTransactions; ResourceBaseWithTransactions resGroup = GetResourceGroupByType(parent.GetType()) as ResourceBaseWithTransactions; if (resGroup is null) { // add warning the market is not currently trading in this resource string zoneName = Apsim.Parent(this, typeof(Zone)).Name; Warnings.Add($"[{zoneName}] is currently not accepting resources of type [r={parent.GetType().ToString()}]\nOnly resources groups provided in the [r=ResourceHolder] in the simulation tree will be traded."); return(false); } // TODO: do some group checks. land units, currency // TODO: if market and looking for finance only return or create "Bank" // find resource type in group var resType = resGroup.GetByName((resourceType as IModel).Name); if (resType is null) { // clone resource resType = resourceType.Clone as CLEMResourceTypeBase; (resType as IModel).Parent = resGroup; // wire up events resGroup.AddChildEvents(resType as IResourceWithTransactionType); } linkToResourceType = resType; return(true); }
/// <summary> /// Returns the link to the matching resource in the market place if found or creates a new clone copy for future transactions /// This allows this action to be performed once to store the link rather than at every transaction /// This functionality allows resources not in the market at the start of the simulation to be traded. /// </summary> /// <param name="resourceType">The resource type to trade</param> /// <returns>Whether the search was successful</returns> public IResourceWithTransactionType LinkToMarketResourceType(CLEMResourceTypeBase resourceType) { if (!this.Parent.GetType().Name.Contains("Market")) { throw new ApsimXException(this, "ooops"); } // find parent group type ResourceBaseWithTransactions parent = (resourceType as Model).Parent as ResourceBaseWithTransactions; ResourceBaseWithTransactions resGroup = GetResourceGroupByType(parent.GetType()) as ResourceBaseWithTransactions; if (resGroup is null) { // add warning the market is not currently trading in this resource string zoneName = Apsim.Parent(this, typeof(Zone)).Name; Warnings.Add($"[{zoneName}] is currently not accepting resources of type [r={parent.GetType().ToString()}]\nOnly resources groups provided in the [r=ResourceHolder] in the simulation tree will be traded."); return(null); } // TODO: do some group checks. land units, currency // TODO: if market and looking for finance only return or create "Bank" // find resource type in group object resType = resGroup.GetByName((resourceType as IModel).Name) as IResourceWithTransactionType; if (resType is null) { // clone resource resType = Apsim.Clone(resourceType); if (resType is null) { // add warning the market does not have the resource string zoneName = Apsim.Parent(this, typeof(Zone)).Name; Warnings.Add($"The resource [r={resourceType.Name}] does not exist in the market and the resource of type [r={resourceType.GetType().ToString()}] cannot be cloned\nAdd resource and associated components to the market."); return(null); } else { (resType as IModel).Parent = resGroup; // add new resource type resGroup.AddNewResourceType(resType as IResourceWithTransactionType); } } return(resType as IResourceWithTransactionType); }
/// <summary> /// Returns the link to the matching resource in the market place if found or creates a new clone copy for future transactions /// This allows this action to be performed once to store the link rather than at every transaction /// This functionality allows resources not in the market at the start of the simulation to be traded. /// </summary> /// <param name="resourceType">The resource type to trade</param> /// <returns>Whether the search was successful</returns> public IResourceWithTransactionType LinkToMarketResourceType(CLEMResourceTypeBase resourceType) { if (!(this.Parent is Market)) { throw new ApsimXException(this, $"Logic error in code. Trying to link a resource type [r={resourceType.Name}] from the market with the same market./nThis is a coding issue. Please contact the developers"); } // find parent group type ResourceBaseWithTransactions parent = (resourceType as Model).Parent as ResourceBaseWithTransactions; if (!(FindResource(parent.GetType()) is ResourceBaseWithTransactions resourceGroupInMarket)) { // add warning the market is not currently trading in this resource string zoneName = FindAncestor <Zone>().Name; string warn = $"[{zoneName}] is currently not accepting resources of type [r={parent.GetType().Name}]\r\nOnly resources groups provided in the [r=ResourceHolder] in the simulation tree will be traded."; Warnings.CheckAndWrite(warn, Summary, this); return(null); } // TODO: do some group checks. land units, currency // TODO: if market and looking for finance only return or create "Bank" // find resource type in group object resType = resourceGroupInMarket.FindChild <IResourceWithTransactionType>(resourceType.Name); // clone resource: too many problems with linked events to clone these objects and setup again // it will be the responsibility of the user to ensure the resources and details are in the market if (resType is null) { // add warning the market does not have the resource string warn = $"The resource [r={resourceType.Parent.Name}.{resourceType.Name}] does not exist in [m={this.Parent.Name}].\r\nAdd resource and associated components to the market to permit trading."; Warnings.CheckAndWrite(warn, Summary, this); return(null); } // TODO: create a clone of the resource and put it in the market return(resType as IResourceWithTransactionType); }
/// <summary> /// Find a resource type from type of resources and name of resource type component /// </summary> /// <typeparam name="T">Type of ResourceType to return</typeparam> /// <typeparam name="R">Type of Resource group containing resource type</typeparam> /// <param name="requestingModel">The model requesting this resource</param> /// <param name="resourceName">The name identifier NameOfResource.NameOfResourceType or simply NameOfResourceType</param> /// <param name="missingResourceAction">Action if resource group missing</param> /// <param name="missingResourceTypeAction">Action if resource type is missing</param> /// <returns>A resource type component</returns> public T FindResourceType <R, T>(IModel requestingModel, string resourceName, OnMissingResourceActionTypes missingResourceAction = OnMissingResourceActionTypes.Ignore, OnMissingResourceActionTypes missingResourceTypeAction = OnMissingResourceActionTypes.Ignore) where T : IResourceType where R : ResourceBaseWithTransactions { string[] nameParts = new string[] { "", resourceName }; if (nameParts.Last().Contains('.')) { nameParts = nameParts.Last().Split('.'); if (nameParts.Length > 2) { throw new ApsimXException(requestingModel, $"Invalid resource name identifier for [{requestingModel.Name}], expecting 'ResourceName.ResourceTypeName' or 'ResourceTypeName'. Value provided [{resourceName}]"); } } // not sure it's quickets to find the resource then look at it's children // or look through all descendents for the type and name // if we find children then we use R as a double check bool searchForAllIresourceType = false; bool resGroupNameMatch = true; T resType = default(T); ResourceBaseWithTransactions resGroup = null; if (!typeof(R).IsSubclassOf(typeof(ResourceBaseWithTransactions))) { if (nameParts.First() == "") { searchForAllIresourceType = true; } else { // find resource by name resGroup = FindChild <R>(nameParts.First()); } } else { resGroup = (nameParts.First() != "") ? FindResource <R>(nameParts.First()) : FindResource <R>(); if (resGroup == null && nameParts.First() != "") { // no resource name match so try with just the type resGroupNameMatch = false; resGroup = FindResource <R>(); } } if (searchForAllIresourceType) { resType = FindAllDescendants <T>(nameParts.Last()).FirstOrDefault(); } else { if (resGroup != null) { resType = (resGroup as IModel).FindChild <T>(nameParts.Last()); } } string errorMsg; if (resGroup == null) { errorMsg = $"Unable to locate resource group [r={typeof(R).Name}] for [a={requestingModel.Name}]"; switch (missingResourceAction) { case OnMissingResourceActionTypes.ReportErrorAndStop: throw new ApsimXException(this, errorMsg); case OnMissingResourceActionTypes.ReportWarning: Warnings.CheckAndWrite(errorMsg, Summary, this); break; default: break; } return(default(T)); } else { if (!resGroupNameMatch) { errorMsg = $"Unable to locate resource named [r={nameParts.First()}] for [a={requestingModel.Name}] but a [{typeof(R).Name}] resource was found and will be used."; Warnings.CheckAndWrite(errorMsg, Summary, this); } } if (resType as IModel is null) { errorMsg = $"Unable to locate resource type [r={nameParts.Last()}] in [r={resGroup.Name}] for [a={requestingModel.Name}]"; switch (missingResourceTypeAction) { case OnMissingResourceActionTypes.ReportErrorAndStop: throw new ApsimXException(this, errorMsg); case OnMissingResourceActionTypes.ReportWarning: Warnings.CheckAndWrite(errorMsg, Summary, this); break; default: break; } } return(resType); }