Commit 14e97ee

mo_khan <mo@mokhan.ca>
2009-05-25 02:00:15
cleaning up the new commanding infrastructure
1 parent d6716a2
product/project/common/ActionCommand.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace mars.rover.common
+{
+    public class ActionCommand : Command
+    {
+        readonly Action command;
+
+        public ActionCommand(Action command)
+        {
+            this.command = command;
+        }
+
+        public void run()
+        {
+            command();
+        }
+    }
+}
\ No newline at end of file
product/project/domain/NASA.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+
+namespace mars.rover.domain
+{
+    public class NASA
+    {
+        readonly Queue<Rover> rovers = new Queue<Rover>();
+        public Mars plateau { get; set; }
+
+        public void deploy(Rover rover)
+        {
+            rovers.Enqueue(rover);
+        }
+
+        public Rover waiting()
+        {
+            return rovers.Dequeue();
+        }
+    }
+}
\ No newline at end of file
product/project/presentation/infrastructure/CommandFactory.cs
@@ -0,0 +1,13 @@
+using System;
+using mars.rover.common;
+
+namespace mars.rover.presentation.infrastructure
+{
+    public class CommandFactory
+    {
+        public virtual Command create_for(Action action)
+        {
+            return new ActionCommand(action);
+        }
+    }
+}
\ No newline at end of file
product/project/presentation/infrastructure/CommandPump.cs
@@ -0,0 +1,9 @@
+using mars.rover.common;
+
+namespace mars.rover.presentation.infrastructure
+{
+    public interface CommandPump<Input> : Command
+    {
+        void run<Command>(Input input) where Command : ParameterizedCommand<Input>;
+    }
+}
\ No newline at end of file
product/project/presentation/infrastructure/SynchronousCommandProcessor.cs
@@ -0,0 +1,21 @@
+using System.Collections.Generic;
+using mars.rover.common;
+
+namespace mars.rover.presentation.infrastructure
+{
+    public class SynchronousCommandProcessor : CommandProcessor
+    {
+        readonly Queue<Command> commands = new Queue<Command>();
+
+        public void add(Command command)
+        {
+            commands.Enqueue(command);
+        }
+
+        public void run()
+        {
+            while (commands.Count > 0)
+                commands.Dequeue().run();
+        }
+    }
+}
\ No newline at end of file
product/project/presentation/infrastructure/SynchronousCommandPump.cs
@@ -0,0 +1,34 @@
+using System.Linq;
+using mars.rover.common;
+
+namespace mars.rover.presentation.infrastructure
+{
+    public class SynchronousCommandPump : CommandPump<string>
+    {
+        readonly Registry<ParameterizedCommand<string>> commands;
+        readonly CommandProcessor processor;
+        readonly CommandFactory factory;
+
+        public SynchronousCommandPump(Registry<ParameterizedCommand<string>> commands, CommandProcessor processor, CommandFactory factory)
+        {
+            this.commands = commands;
+            this.processor = processor;
+            this.factory = factory;
+        }
+
+        public virtual void run<Command>(string input) where Command : ParameterizedCommand<string>
+        {
+            processor.add(factory.create_for(() => get<Command>().run_against(input)));
+        }
+
+        ParameterizedCommand<string> get<T>()
+        {
+            return commands.First(y => y is T);
+        }
+
+        public virtual void run()
+        {
+            processor.run();
+        }
+    }
+}
\ No newline at end of file
product/project/presentation/CaptureUserInstructionsConsoleView.cs
@@ -15,7 +15,7 @@ namespace mars.rover.presentation
 
         public void attach_to(CaptureUserInstructionsPresenter presenter)
         {
-            writer.WriteLine("Enter upper right coordinates:");
+            writer.WriteLine("enter upper right coordinates:");
             presenter.provide_upper_right_coordinates(reader.ReadLine());
 
             for (var i = 0; i < 2; i++)
@@ -26,6 +26,7 @@ namespace mars.rover.presentation
                 writer.WriteLine("enter commands to navigate rover:");
                 presenter.navigate_rover_using(reader.ReadLine());
             }
+            presenter.go();
         }
 
         public void display(string location)
product/project/presentation/CaptureUserInstructionsPresenter.cs
@@ -1,25 +1,16 @@
-using System;
-using System.Linq;
-using mars.rover.common;
-using mars.rover.domain;
-using mars.rover.presentation.model;
+using mars.rover.presentation.infrastructure;
 
 namespace mars.rover.presentation
 {
     public class CaptureUserInstructionsPresenter : Presenter
     {
         readonly CaptureUserInstructionsView view;
-        readonly Registry<HeadingFactory> factories;
-        readonly Registry<Navigation> navigations;
-        Mars plateau;
-        Rover rover;
+        readonly CommandPump<string> pump;
 
-        public CaptureUserInstructionsPresenter(CaptureUserInstructionsView view, Registry<HeadingFactory> factories,
-                                                Registry<Navigation> navigations)
+        public CaptureUserInstructionsPresenter(CaptureUserInstructionsView view, CommandPump<string> pump)
         {
             this.view = view;
-            this.factories = factories;
-            this.navigations = navigations;
+            this.pump = pump;
         }
 
         public virtual void run()
@@ -29,26 +20,22 @@ namespace mars.rover.presentation
 
         public virtual void provide_upper_right_coordinates(string line)
         {
-            var coordinates = line.Split(new[] {' '});
-            plateau = new Mars(Convert.ToUInt32(coordinates[0]), Convert.ToUInt32(coordinates[1]));
+            pump.run<CreateMarsCommand>(line);
         }
 
         public virtual void deploy_rover_to(string deployment_coordinates)
         {
-            var coordinates = deployment_coordinates.Split(new[] {' '});
-            rover = new Rover(Convert.ToUInt32(coordinates[0]), Convert.ToUInt32(coordinates[1]),
-                              find_heading_for(coordinates[2]));
+            pump.run<DeployRoverCommand>(deployment_coordinates);
         }
 
         public virtual void navigate_rover_using(string navigation_commands)
         {
-            navigation_commands.each(x => navigations.First(y => y.is_satisfied_by(x)).run_against(rover));
-            view.display(rover.ToString());
+            pump.run<NavigateRoverCommand>(navigation_commands);
         }
 
-        Heading find_heading_for(string heading)
+        public void go()
         {
-            return factories.First(x => x.is_satisfied_by(heading)).create(plateau);
+            pump.run();
         }
     }
 }
\ No newline at end of file
product/project/presentation/CreateMarsCommand.cs
@@ -0,0 +1,23 @@
+using System;
+using mars.rover.common;
+using mars.rover.domain;
+
+namespace mars.rover.presentation
+{
+    public class CreateMarsCommand : ParameterizedCommand<string>
+    {
+        NASA nasa;
+
+        public CreateMarsCommand(NASA nasa)
+        {
+            this.nasa = nasa;
+        }
+
+        public void run_against(string item)
+        {
+            var coordinates = item.Split(new[] {' '});
+            var plateau = new Mars(Convert.ToUInt32(coordinates[0]), Convert.ToUInt32(coordinates[1]));
+            nasa.plateau = plateau;
+        }
+    }
+}
\ No newline at end of file
product/project/presentation/DeployRoverCommand.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Linq;
+using mars.rover.common;
+using mars.rover.domain;
+using mars.rover.presentation.model;
+
+namespace mars.rover.presentation
+{
+    public class DeployRoverCommand : ParameterizedCommand<string>
+    {
+        readonly Registry<HeadingFactory> factories;
+        readonly NASA nasa;
+
+        public DeployRoverCommand(Registry<HeadingFactory> factories, NASA nasa)
+        {
+            this.factories = factories;
+            this.nasa = nasa;
+        }
+
+        public virtual void run_against(string deployment_coordinates)
+        {
+            var coordinates = deployment_coordinates.Split(new[] {' '});
+            var rover = new Rover(Convert.ToUInt32(coordinates[0]), Convert.ToUInt32(coordinates[1]),
+                                  find_heading_for(coordinates[2]));
+            nasa.deploy(rover);
+        }
+
+        Heading find_heading_for(string heading)
+        {
+            var plateau = nasa.plateau;
+            return factories.First(x => x.is_satisfied_by(heading)).create(plateau);
+        }
+    }
+}
\ No newline at end of file
product/project/presentation/NavigateRoverCommand.cs
@@ -0,0 +1,28 @@
+using System.Linq;
+using mars.rover.common;
+using mars.rover.domain;
+using mars.rover.presentation.model;
+
+namespace mars.rover.presentation
+{
+    public class NavigateRoverCommand : ParameterizedCommand<string>
+    {
+        readonly Registry<Navigation> navigations;
+        readonly CaptureUserInstructionsView view;
+        NASA nasa;
+
+        public NavigateRoverCommand(Registry<Navigation> navigations, CaptureUserInstructionsView view, NASA nasa)
+        {
+            this.navigations = navigations;
+            this.nasa = nasa;
+            this.view = view;
+        }
+
+        public void run_against(string navigation_commands)
+        {
+            var rover = nasa.waiting();
+            navigation_commands.each(x => navigations.First(y => y.is_satisfied_by(x)).run_against(rover));
+            view.display(rover.ToString());
+        }
+    }
+}
\ No newline at end of file
product/project/Program.cs
@@ -4,6 +4,7 @@ using System.Linq;
 using mars.rover.common;
 using mars.rover.domain;
 using mars.rover.presentation;
+using mars.rover.presentation.infrastructure;
 using mars.rover.presentation.model;
 
 namespace mars.rover
@@ -24,25 +25,35 @@ namespace mars.rover
 
         static void Main(string[] args)
         {
+            var nasa = new NASA();
+            var view = new CaptureUserInstructionsConsoleView(Console.In, Console.Out);
             var program = new Program(
                 new CaptureUserInstructionsPresenter(
-                    new CaptureUserInstructionsConsoleView(Console.In, Console.Out),
-                    new DefaultRegistry<HeadingFactory>
-                        {
-                            new HeadingFactory("N", x => new North(x)),
-                            new HeadingFactory("E", x => new East(x)),
-                            new HeadingFactory("W", x => new West(x)),
-                            new HeadingFactory("S", x => new South(x)),
-                            new UnknownHeadingFactory(),
-                        },
-                    new DefaultRegistry<Navigation>
-                        {
-                            new Navigation('L', x => x.turn_left()),
-                            new Navigation('R', x => x.turn_right()),
-                            new Navigation('M', x => x.move_forward()),
-                            new UnknownNavigation(),
-                        }
-                    ));
+                    view,
+                    new SynchronousCommandPump(new DefaultRegistry<ParameterizedCommand<string>>
+                                        {
+                                            new CreateMarsCommand(nasa),
+                                            new DeployRoverCommand(
+                                                new DefaultRegistry<HeadingFactory>
+                                                    {
+                                                        new HeadingFactory("N", x => new North(x)),
+                                                        new HeadingFactory("E", x => new East(x)),
+                                                        new HeadingFactory("W", x => new West(x)),
+                                                        new HeadingFactory("S", x => new South(x)),
+                                                        new UnknownHeadingFactory(),
+                                                    },
+                                                nasa),
+                                            new NavigateRoverCommand(
+                                                new DefaultRegistry<Navigation>
+                                                    {
+                                                        new Navigation('L', x => x.turn_left()),
+                                                        new Navigation('R', x => x.turn_right()),
+                                                        new Navigation('M', x => x.move_forward()),
+                                                        new UnknownNavigation(),
+                                                    }
+                                                ,
+                                                view, nasa)
+                                        }, new SynchronousCommandProcessor(), new CommandFactory())));
             program.run_against(args.Select(x => (CommandLineArgument) x));
         }
     }
product/project/project.csproj
@@ -48,6 +48,13 @@
     <Compile Include="common\DefaultRegistry.cs" />
     <Compile Include="common\EnumerableExtensions.cs" />
     <Compile Include="common\Registry.cs" />
+    <Compile Include="common\ActionCommand.cs" />
+    <Compile Include="presentation\infrastructure\CommandFactory.cs" />
+    <Compile Include="presentation\infrastructure\CommandPump.cs" />
+    <Compile Include="presentation\infrastructure\SynchronousCommandPump.cs" />
+    <Compile Include="presentation\CreateMarsCommand.cs" />
+    <Compile Include="presentation\DeployRoverCommand.cs" />
+    <Compile Include="presentation\infrastructure\SynchronousCommandProcessor.cs" />
     <Compile Include="presentation\model\HeadingFactory.cs" />
     <Compile Include="common\CallbackCommand.cs" />
     <Compile Include="presentation\CaptureUserInstructionsConsoleView.cs" />
@@ -64,6 +71,8 @@
     <Compile Include="domain\Mars.cs" />
     <Compile Include="domain\Plateau.cs" />
     <Compile Include="presentation\model\Navigation.cs" />
+    <Compile Include="domain\NASA.cs" />
+    <Compile Include="presentation\NavigateRoverCommand.cs" />
     <Compile Include="presentation\Presenter.cs" />
     <Compile Include="presentation\CaptureUserInstructionsPresenter.cs" />
     <Compile Include="common\Specification.cs" />