@@ -87,7 +87,8 @@ def __init__(self, actionType, name, **kwargs):
8787 '''
8888
8989 # list of things that will be controlled during this action
90- self .vesselList = [] # all vessels required for the action
90+ self .assets = {} # dict of named roles for the vessel(s) or port required to perform the action
91+ self .requirements = {} # the capabilities required of each asset role assets (same keys as self.assets)
9192 self .objectList = [] # all objects that could be acted on
9293 self .dependencies = {} # list of other actions this one depends on
9394
@@ -123,6 +124,7 @@ def __init__(self, actionType, name, **kwargs):
123124 supported_objects = list (actionType ['objects' ].keys ())
124125 else :
125126 supported_objects = []
127+
126128 # Add objects to the action's object list as long as they're supported
127129 if 'objects' in kwargs :
128130 for obj in kwargs ['objects' ]:
@@ -131,7 +133,15 @@ def __init__(self, actionType, name, **kwargs):
131133 self .objectList .append (obj )
132134 else :
133135 raise Exception (f"Object type '{ objType } ' is not in the action's supported list." )
134-
136+
137+ # Create placeholders for asset roles based on the "requirements"
138+ if 'roles' in actionType :
139+ for asset , caplist in actionType ['roles' ].items ():
140+ self .assets [asset ] = None # each asset role holds a None value until assigned
141+ self .requirements [asset ] = {}
142+ for cap in caplist :
143+ self .requirements [asset ][cap ] = 0 # fill in each required metric with zero to start with?
144+
135145
136146 # Process dependencies
137147 if 'dependencies' in kwargs :
@@ -149,22 +159,61 @@ def addDependency(self, dep):
149159 # could see if already a dependency and raise a warning if so...
150160
151161
162+ def checkAsset (self , role_name , asset ):
163+ '''Checks if a specified asset has sufficient capabilities to fulfil
164+ a specified role in this action.
165+ '''
166+
167+ # Make sure role_name is valid for this action
168+ if not role_name in self .assets .keys ():
169+ raise Exception (f"The specified role name '{ role_name } ' is not a named asset role in this action." )
170+
171+ for cap , req in self .requirements ['role_name' ]:
172+ if asset .capabilities [cap ] >= req : # <<< this is pseudocode. Needs to look at capability numbers! <<<
173+ pass
174+ # so far so good
175+ else :
176+ return False # at least on capability is not met, so return False
177+
178+ return True
152179
153- def assignAssets (self , assets ):
154- pass
180+
181+ def assignAsset (self , role_name , asset ):
182+ '''Assigns a vessel or port to a certain role in the action.
183+
184+ Parameters
185+ ----------
186+ role_name : string
187+ Name of the asset role being filled (must be in the action's list)
188+ asset : Vessel or Port object
189+ The asset to be registered with the class.
190+ '''
191+
192+ # Make sure role_name is valid for this action
193+ if not role_name in self .assets .keys ():
194+ raise Exception (f"The specified role name '{ role_name } ' is not a named asset role in this action." )
195+
196+ self .assets [role_name ] = asset
197+
155198
156199 def calcDurationAndCost (self ):
157200 pass
158201
159- def evaluateAsset (self , assets ):
202+
203+ def evaluateAssets (self , assets ):
160204 '''Check whether an asset can perform the task, and if so calculate
161- the time and cost associated with using that vessel.
162- asset : vessel or port object(s)
205+ the time and cost associated with using those assets.
206+
207+ assets : dict
208+ Dictionary of role_name, asset object pairs for assignment to the action.
209+ Each asset is a vessel or port object.
163210
164211 '''
165- pass
166212
167- self .assignAssets (assets )
213+ # Assign each specified asset to its respective role
214+ for akey , aval in assets .items ():
215+ self .assignAsset (akey , aval )
216+
168217 self .calcDurationAndCost ()
169218
170219
@@ -173,7 +222,7 @@ def evaluateAsset(self, assets):
173222
174223
175224 # ----- Below are drafts of methods for use by the engine -----
176-
225+ """
177226 def begin(self):
178227 '''Take control of all objects'''
179228 for vessel in self.vesselList:
@@ -188,36 +237,36 @@ def end(self):
188237 vessel._detach_from()
189238 for object in self.objectList:
190239 object._detach_from()
191-
240+ """
192241
193242 def timestep (self ):
194243 '''Advance the simulation of this action forward one step in time.'''
195244
196245 # (this is just documenting an idea for possible future implementation)
197246 # Perform the hourly action of the task
198- '''
247+
199248 if self .type == 'tow' :
200249 # controller - make sure things are going in right direction...
201250 # (switch mode if need be)
202251 if self .mode == 0 : # gathering vessels
203- for ves in self.vesselList:
204- dr = self.r_start - ves.r
205- ves.setCourse(dr) # sets vessel velocity
252+ ves = self .assets [ 'vessel' ]
253+ dr = self .r_start - ves .r
254+ ves .setCourse (dr ) # sets vessel velocity
206255
207- # if all vessels are stopped (at the object), time to move
208- if all([ np.linalg.norm(ves.v) == 0 for ves in self.vesselList]) :
256+ # if vessel is stopped (at the object), time to move
257+ if np .linalg .norm (ves .v ) == 0 :
209258 self .mode = 1
210259
211260 if self .mode == 1 : # towing
212- for ves in self.vesselList:
213- dr = self.r_finish - ves.r
214- ves.setCourse(dr) # sets vessel velocity
261+ ves = self .assets [ 'vessel' ]
262+ dr = self .r_finish - ves .r
263+ ves .setCourse (dr ) # sets vessel velocity
215264
216265 # if all vessels are stopped (at the final location), time to end
217- if all([ np.linalg.norm(ves.v) == 0 for ves in self.vesselList]) :
266+ if np .linalg .norm (ves .v ) == 0 :
218267 self .mode = 2
219268
220269 if self .mode == 2 : # finished
221270 self .end ()
222- '''
271+
223272
0 commit comments