updating the robocode contexts when the world state updates

In my previous posts I have moved to a position where my robot and robot engine are capable of updating the world state. Now I want to start mapping this state to other bounded contexts and I've already created the first parts of my decision making context . If I now provide the robot engine with a collection of translators, I want it to publish the world state to each context via these translators:

    public class when_told_to_publish_to_the_world_state : with_a_robot_engine
    {
        Establish context = () =>
        {
            worldState = MockRepository.GenerateStub<IWorldState>();

            firstContextTranslator = MockRepository.GenerateStub<IContextTranslator>();
            secondContextTranslator = MockRepository.GenerateStub<IContextTranslator>();
            var contextTranslators = new List<IContextTranslator> {firstContextTranslator, 
                                secondContextTranslator};

            robotEngine = new RobotEngine(worldState, contextTranslators);

            robotEngine.Initialise(robot);
            expectedGunTemperature = 891;
            worldStateUpdate = w => w.GunTemperature = expectedGunTemperature;
        };

        Because of = () => robotEngine.PublishToTheWorldState(worldStateUpdate);

        It should_update_the_world_state_accordingly = () =>
            worldState.GunTemperature.ShouldEqual(expectedGunTemperature);

        It should_have_no_pending_world_state_updates_left = () => 
            robotEngine.PendingWorldStateUpdates.Count.ShouldEqual(0);

        It should_inform_the_first_translator_of_the_world_state_change = () =>
            firstContextTranslator.AssertWasCalled(x => x.PublishAStateChange(worldState));

        It should_inform_the_second_translator_of_the_world_state_change = () =>
            secondContextTranslator.AssertWasCalled(x => x.PublishAStateChange(worldState));

        static Action<IWorldState> worldStateUpdate;
        static int expectedGunTemperature;
    }

Pretty simple stuff - a few stubs in a collection are injected into the robot engine constructor and I assert that the state change is published on each one.
The robot engine code in full with this change:

    public class RobotEngine : ImARobotEngine
    {
        readonly IManageStatistics statisticsManager;
        readonly IWorldState worldState;
        readonly IEnumerable<IContextTranslator> contextTranslators;
        ImARobot robot;

        List<Action<IWorldState>> pendingWorldStateUpdates = new List<Action<IWorldState>>();

        public RobotEngine(IWorldState worldState, 
                           IEnumerable<IContextTranslator> contextTranslators,
                           IManageStatistics statisticsManager)
        {
            this.statisticsManager = statisticsManager;
            this.worldState = worldState;
            this.contextTranslators = contextTranslators;
        }

        public ReadOnlyCollection<Action<IWorldState>> PendingWorldStateUpdates
        {
            get { return pendingWorldStateUpdates.AsReadOnly(); }
        }

        public void Initialise(ImARobot robot)
        {
            this.robot = robot;
            statisticsManager.EnsureWeStartWithCleanStatistics();
        }

        public void PublishToTheWorldState(Action<IWorldState> worldStateUpdate)
        {
            pendingWorldStateUpdates.Add(worldStateUpdate);
        }

        public void EnsureTheWorldStateIsUpToDate()
        {
            foreach(var makeAnUpdateTo in pendingWorldStateUpdates)
            {
                makeAnUpdateTo(worldState);
            }
            pendingWorldStateUpdates.RemoveAll(a => true);

            foreach (var contextTranslator in contextTranslators)
            {
                contextTranslator.PublishAStateChange(worldState);
            }
        }
    }

I'm pretty happy with this code so far - I don't yet have a mechanism for the context to push back some state changes or instructions prior to the next translator being told to publish a state change, but I'm sure that will take shape in time as I drive that with new specifications as the need arises.

The next step is to implement the context translator for the decision making context and my next post will cover this in detail.



0 comments: