main
 1namespace domain
 2{
 3  using System;
 4  using System.Collections.Generic;
 5  using System.Linq;
 6  using utility;
 7
 8  public interface IWell
 9  {
10    IQuantity GrossProductionFor<Commodity>(Month month) where Commodity : ICommodity, new();
11    IQuantity NetProductionFor<Commodity>(Month month) where Commodity : ICommodity, new();
12    void FlowInto(IFacility facility);
13  }
14
15  public class Well : IWell
16  {
17    Month initialProductionMonth;
18    Percent workingInterest;
19    TypeCurve curve;
20    IFacility facility;
21
22    public Well(Month initialProductionMonth, Percent workingInterest, TypeCurve curve)
23    {
24      this.initialProductionMonth = initialProductionMonth;
25      this.workingInterest = workingInterest;
26      this.curve = curve;
27    }
28
29    public IQuantity GrossProductionFor<Commodity>(Month month) where Commodity : ICommodity, new()
30    {
31      return curve.ProductionFor<Commodity>(month);
32    }
33
34    public IQuantity NetProductionFor<Commodity>(Month month) where Commodity : ICommodity, new()
35    {
36      return workingInterest.Reduce(GrossProductionFor<Commodity>(month));
37    }
38
39    public void FlowInto(IFacility facility)
40    {
41      ensure_that_this_well_is_not_already_flowing_into_a_plant();
42      ensure_that_this_well_does_not_overflow_the_plant(facility);
43      facility.AcceptFlowFrom(this);
44      this.facility = facility;
45    }
46
47    void ensure_that_this_well_does_not_overflow_the_plant(IFacility facility)
48    {
49      var period = initialProductionMonth.UpTo(Month.Infinity);
50      this.curve.Accept( production =>
51      {
52          if( production.OccursDuring(period) && production.IsGreaterThanAvailableAt(facility))
53            throw new Exception();
54      });
55    }
56
57    void ensure_that_this_well_is_not_already_flowing_into_a_plant()
58    {
59      if(null != this.facility) throw new Exception();
60    }
61  }
62}