To entertain myself, I coded a new RequestBuilder object, much like the InputBuilder, but building a dictionary-list composite like the requests expect. Results were good. Herewith, my report, not contemporaneous.

Long story short, I adopted one of the tests from my InputBuilder code. It looks like this:

class TestRequestBuilder:
    def test_new_syntax_for_raw_collections(self):
        WorldEntity.next_id = 100
        world = World(10, 10)
        block_id = world.add_block(6, 5)  # 101
        batch_in = RequestBuilder() \
            .request(world.add_bot(5, 5, direction=Direction.EAST)) \
            .action('take', None) \
            .action('turn', 'SOUTH') \
            .action('step', None) \
            .action('step', None) \
            .action('drop', block_id) \
            .request(world.add_bot(7, 7)) \
            .action('step') \
            .result()
        assert len(batch_in) == 2
        rq_0 = batch_in[0]
        assert rq_0['entity'] == 102
        assert len(rq_0['actions']) == 5
        batch_out = world.process(batch_in)
        result = batch_out[0]
        assert result['location'] == Location(5, 7)
        result = batch_out[1]
        assert result['location'] == Location(8, 7)
        item = world.map.at_xy(5, 8)
        assert item.id == block_id

I started with just the assertion down to the check of len(batch_in). At first, nothing worked because there was no RequestBuilder. Then I built up this class, method by method:

class RequestBuilder:
    def __init__(self):
        self._requests = []
        self._current_request = None
        self._current_actions = None

    def request(self, identifier):
        self._current_request = { 'entity': identifier }
        self._requests.append(self._current_request)
        self._current_actions = list()
        self._current_request['actions'] = self._current_actions
        return self

    def action(self, verb, parameter=None ):
        step = {'verb': verb, 'param1': parameter}
        self._current_actions.append(step)
        return self

    def result(self):
        return self._requests

Then I changed the process method that the InputBuilder used, to use the execute:

class World:
    def process(self, world_input):
        output = []
        for request in world_input:
            requestor_id = request['entity']
            self.execute(request)
            output.append(self.fetch(requestor_id))
        return output

Basically, after I sorted out using the right names, and put the names verb and param1 in, making the individual actions little dictionaries, it “just worked”.

Summary

So, this morning I kind of took partial runs at using the systems collections, then decided not to, then decided that I should, and called it a morning after such a heavy bout of thinking. And this afternoon, replicating the style of the builder experiment, it all came together.

And, almost by accident, we now have the ability to process more than one bot’s input at a time. So, with a bit of wiring, we can probably rig up the Bot class to build one request, and the cohort class, extended, to build up a batch, and then plug cohort into the Game class.

It’s interesting how an idea won’t fit, won’t fit, and then suddenly it does fit. And when it does fit, it feels pretty good. And this feels like a very nice step along the road. Small, quick, smooth, no pressure. Nice. See you next time!