File size: 3,339 Bytes
2130399
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
""" Generic Base Class for interfacing with a soar agent's input/output links

A Connector can be added to a SoarClient and can handle input/output 
    while taking care of specific SML calls and event registering
"""

from __future__ import print_function
 
import traceback, sys

class AgentConnector(object):
    """ Base Class for handling input/output for a soar agent

    Input:
        on_input_phase will be automatically called before each input phase

    Output:
        call add_output_command to add the name of an output-link command to look for
        on_output_event will then be called if such a command is added by the agent

    Look at LanguageConnector for an example of an AgentConnector used in practice
    """
    def __init__(self, client):
        """ Initialize the Connector (but won't register event handlers until connect)

        client should be an instance of SoarClient
        """
        self.client = client
        self.connected = False
        self.output_handler_ids = { }


    def add_output_command(self, command_name):
        """ Will cause the connector to handle commands with the given name on the output-link """
        if self.connected:
            self.output_handler_ids[command_name] = self.client.agent.AddOutputHandler(
                    command_name, AgentConnector._output_event_handler, self)
        else:
            self.output_handler_ids[command_name] = -1

    def connect(self):
        """ Adds event handlers, automatically called by the SoarClient """
        if self.connected:
            return

        for command_name in self.output_handler_ids:
            self.output_handler_ids[command_name] = self.client.agent.AddOutputHandler(
                    command_name, AgentConnector._output_event_handler, self)

        self.connected = True

    def disconnect(self):
        """ Removes event handlers, automatically called by the SoarClient """
        if not self.connected:
            return

        for command_name in self.output_handler_ids:
            self.client.agent.RemoveOutputHandler(self.output_handler_ids[command_name])
            self.output_handler_ids[command_name] = -1

        self.connected = False

    def on_init_soar(self):
        """ Override to handle an init-soar event (remove references to SML objects """
        pass

    def on_input_phase(self, input_link):
        """ Override to update working memory, automatically called before each input phase """
        pass

    def on_output_event(self, command_name, root_id):
        """ Override to handle output commands with the given name (added by add_output_command) 

        root_id is the root Identifier of the command (e.g. (<output-link> ^command_name <root_id>)
        """
        pass

    @staticmethod
    def _output_event_handler(self, agent_name, att_name, wme):
        """ OutputHandler callback for when a command is put on the output link """
        try:
            if wme.IsJustAdded() and wme.IsIdentifier():
                root_id = wme.ConvertToIdentifier()
                self.on_output_event(att_name, root_id)
        except:
            self.client.print_handler("ERROR IN OUTPUT EVENT HANDLER")
            self.client.print_handler(traceback.format_exc())
            self.client.print_handler("--------- END ---------------")