Commit c6bf372

mo k <mo@mokhan.ca>
2012-04-24 23:00:54
add contains to range.
1 parent c2c1fb7
src/domain/GasPlant.cs
@@ -8,6 +8,7 @@ namespace domain
   public interface IFacility 
   {
     void AcceptFlowFrom(IWell well);
+    IQuantity AvailableCapacityFor(Month month);
   }
 
   public class GasPlant : IFacility
@@ -36,6 +37,10 @@ namespace domain
       return MonthsOverAvailableCapacity(Month.Now().UpTo(new Month(2099, 12)));
     }
 
+    public virtual IQuantity AvailableCapacityFor(Month month){
+      throw new System.NotImplementedException();
+    }
+
     public IEnumerable<Month> MonthsOverAvailableCapacity(IRange<Month> months)
     {
       var results = new List<Month>();
src/domain/Production.cs
@@ -18,6 +18,16 @@ namespace domain
       return month.Equals(otherMonth);
     }
 
+    public virtual bool OccursDuring(IRange<Month> period)
+    {
+      return period.Contains(this.month);
+    }
+
+    public virtual bool IsGreaterThanAvailableAt(IFacility facility)
+    {
+      return facility.AvailableCapacityFor(this.month).IsGreaterThan(produced);
+    }
+
     public IQuantity ProductionOf<T>() where T : ICommodity, new()
     {
       return split.PercentageOf<T>(produced);
src/domain/Range.cs
@@ -13,6 +13,7 @@ namespace domain
   public interface IRange<T> where T : IComparable<T>
   {
     void Accept(Action<T> action);
+    bool Contains(T item);
   }
 
   public class Range<T> : IRange<T> where T : IComparable<T>, IIncrementable<T>
@@ -36,6 +37,11 @@ namespace domain
         next = next.Next();
       }
     }
+
+    public bool Contains(T item)
+    {
+      return start.CompareTo(item) <= 0 && end.CompareTo(item) > 0;
+    }
   }
 
   public interface IIncrementable<T>
src/domain/TypeCurve.cs
@@ -1,5 +1,6 @@
 namespace domain
 {
+  using System;
   using System.Linq;
   using System.Collections.Generic;
 
@@ -18,5 +19,9 @@ namespace domain
     {
       return production.Single(x => x.IsFor(month)).ProductionOf<Commodity>();
     }
+
+    public virtual void Accept(Action<Production> visitor)
+    {
+    }
   }
 }
src/domain/Well.cs
@@ -32,8 +32,22 @@ namespace domain
     public void FlowInto(IFacility facility)
     {
       ensure_that_this_well_is_not_already_flowing_into_a_plant();
-      this.facility = facility;
+      ensure_that_this_well_does_not_overflow_the_plant(facility);
       facility.AcceptFlowFrom(this);
+      this.facility = facility;
+    }
+
+    void ensure_that_this_well_does_not_overflow_the_plant(IFacility facility)
+    {
+      var period = initialProductionMonth.UpTo(new Month(2099, 12));
+      this.curve.Accept( production =>
+      {
+        if( production.OccursDuring(period)){
+          if(production.IsGreaterThanAvailableAt(facility)){
+            throw new Exception();
+          }
+        }
+      });
     }
 
     void ensure_that_this_well_is_not_already_flowing_into_a_plant()
src/test/RangeSpecs.cs
@@ -23,12 +23,40 @@ namespace test
       Because of = () =>
       {
         sut.Accept(x =>
-        {
-          results.Add(x);
-        });
+            {
+            results.Add(x);
+            });
       };
 
       static IList<Month> results = new List<Month>();
     }
+    public class when_a_range_contains_an_item
+    {
+      It should_return_true=()=>
+      {
+        result.ShouldBeTrue();
+      };
+
+      Because of = ()=>
+      {
+        result = sut.Contains(new Month(2012, 02));
+      };
+
+      static bool result;
+    }
+    public class when_an_item_is_before_the_range{
+      It should_return_false=()=>
+      {
+        var result = sut.Contains(new Month(2011, 12));
+        result.ShouldBeFalse();
+      };
+    }
+    public class when_an_item_is_after_the_range{
+      It should_return_false=()=>
+      {
+        var result = sut.Contains(new Month(2012, 04));
+        result.ShouldBeFalse();
+      };
+    }
   }
 }
src/test/WellSpecs.cs
@@ -3,15 +3,17 @@ namespace test
   using Machine.Specifications;
   using domain;
   using System;
+  using Rhino.Mocks;
 
   public class WellSpecs
   {
     Establish context = () =>
     {
-      var typeCurve = Mock.An<TypeCurve>();
+      typeCurve = Mock.An<TypeCurve>();
       sut = new Well(Month.Now(), 100m.Percent(), typeCurve );
     };
     static IWell sut;
+    static TypeCurve typeCurve;
 
     public class when_flowing_a_gas_well_into_a_gas_plant
     {
@@ -35,6 +37,39 @@ namespace test
         };
       }
 
+      public class when_the_plant_would_overflow_if_it_accepted_flow_from_this_well
+      {
+        It should_not_let_you_flow_this_well_into_the_facility=()=>
+        {
+          exception.ShouldNotBeNull();
+        };
+
+        Establish context = ()=>
+        {
+          var jan2013 = 2013.January();
+          var feb2013 = 2013.February();
+          typeCurve
+            .Stub(x => x.Accept( Arg<Action<Production>>.Is.Anything ))
+            .WhenCalled(x => 
+            {
+              var splits = new CommoditySplits();
+              splits.SplitFor<Gas>(100m.Percent());
+              var action = x.Arguments[0] as Action<Production>;
+              action(new Production(jan2013,100m.BOED(),splits ));
+              action(new Production(feb2013, 91m.BOED(), splits));
+            });
+          gasPlant.Stub(x => x.AvailableCapacityFor(jan2013)).Return(100m.BOED());
+          gasPlant.Stub(x => x.AvailableCapacityFor(feb2013)).Return(90m.BOED());
+        };
+
+        Because of = ()=>
+        {
+          exception = Catch.Exception(()=> sut.FlowInto(gasPlant));
+        };
+
+        static Exception exception;
+      }
+
       public class when_a_well_is_already_flowing_into_a_facility 
       {
         It should_not_allow_you_to_flow_into_another_plant=()=>