-
Notifications
You must be signed in to change notification settings - Fork 0
Backend
SeleXor operates as three separate components:
- Main Server
- Vessel Database
- Web Interface
The main server performs requests that are issued by users. When a user sends a request, such as "Get 3 vessels from the US, from 2 different cities", it queries the database for the next vessel that will satisfy this request, and requests it from the Clearinghouse on the user's behalf.
The database holds information on all the vessels that are registered with the Clearinghouse. It is periodically refreshed (default every 10 minutes), and is also updated dynamically while requests are being serviced through SeleXor.
The web interface's sole purpose is to provide a GUI to interact with SeleXor. It uses Ajax to communicate with a client's machine, and relays user requests to the main selexor server.
With the way SeleXor is designed, it is possible to add new rules. There are two components to rules: the parameter preprocessor, and the rule callback. See the respective section for more information on how to define these.
Rule callbacks are functions that take a set of vessels and a dictionary of parameters, and returns a subset of those vessels that satisfy a certain condition. The only difference in terms of signature of Vessel-level and Group-level callbacks are that Group-level callbacks have one extra parameter.
def myrulecallback(
handleset, # Set(vesselhandle) The set of vessels to check.
database, # The selexor database instance to use.
invert, # True/False. Should this rule be inverted?
parameters, # The parsed parameter dictionary.
acquired_vessels # The list of currently acquired vessels. This only exists for group-level callbacks!
):
good_handles = set()
for vessel in handleset:
if is_handle_good(handle, parameters) ^ invert:
good_handles.add(handle)
return good_handles
Parameter preprocessors are functions that take a dictionary of rule parameters (generally containing string values) and returns a dictionary with parameters expected by the respective rule callback (in whatever type the callback wants). As such, preprocessors should do 3 things:
- Ensure that all required parameters exist.
- Convert the raw parameters into a form that is expected by the callback.
- Raise errors if the above conditions are not or could not be met.
Do note however, preprocessors are optional. Should you require to use a preprocessor, the template for a preprocessor is:
def myrulepreprocessor(raw_parameters):
# These should all be strings.
required_parameters = ['anint', 'astring', ...]
# Do we have all required parameters?
for required_parameter in required_parameters:
if required_parameter not in raw_parameters:
raise selexorexceptions.MissingParameter(required_parameter)
# Prepare the processed parameters
preprocessed_parameters = {}
preprocessed_parameters['myint'] = int(anint)
preprocessed_parameters['astring'] = astring
return preprocessed_parameters
After defining the above, you are now ready to tell SeleXor to use your rule. Simply add your callback and preprocessor into the _init() function in the module. For rules without preprocessors, simply ignore the last argument. To replace an existing rule, you should first deregister the rule using deregister_callback('rulename')
.
def _init():
# Other callbacks are registered before this....
register_callback('myrulename', 'myruleclassification', mycallback, myrulepreprocessor)