content: 
  {-# LANGUAGE RecursiveDo #-}
  
  -- Example: Analysis of a PERT-type Network 
  --
  -- It is described in different sources [1, 2]. So, this is chapter 14 of [2] and section 7.11 of [1].
  --
  -- PERT is a technique for evaluating and reviewing a project consisting of
  -- interdependent activities. A number of books have been written that describe
  -- PERT modeling and analysis procedures. A PERT network activity descriptions
  -- are given in a table stated below. All activity times will be assumed to be
  -- triangularly distributed. For ease of description, activities have been
  -- aggregated. The activities relate to power units, instrumentation, and
  -- a new assembly and involve standard types of operations.
  -- 
  -- In the following description of the project, activity numbers are given
  -- in parentheses. At the beginning of the project, three parallel activities
  -- can be performed that involve: the disassembly of power units and
  -- instrumentation (1); the installation of a new assembly (2); and
  -- the preparation for a retrofit check (3). Cleaning, inspecting, and
  -- repairing the power units (4) and calibrating the instrumentation (5)
  -- can be done only after the power units and instrumentation have been
  -- disassembled. Thus, activities 4 and 5 must follow activity 1 in the network.
  -- Following the installation of the new assembly (2) and after the instrumentation
  -- have been calibrated (5), a check of interfaces (6) and a check of
  -- the new assembly (7) can be made. The retrofit check (9) can be made
  -- after the assembly is checked (7) and the preparation for the retrofit
  -- check (3) has been completed. The assembly and test of power units (8)
  -- can be performed following the cleaning and maintenance of power units (4).
  -- The project is considered completed when all nine activities are completed.
  -- Since activities 6, 8, and 9 require the other activities to precede them,
  -- their completion signifies the end of the project. This is indicated on
  -- the network by having activities 6, 8, and 9 incident to node 6, the sink
  -- node for the project. The objective of this example is to illustrate
  -- the procedures for using Aivika to model and simulate project planning network.
  -- 
  -- Activity    Description                                  Mode Minimum Maximum Average
  -- 
  --  1          Disassemble power units and instrumentation    3      1       5       3
  --  2          Install new assembly                           6      3       9       6
  --  3          Prepare for retrofit check                    13     10      19      14
  --  4          Clean, inspect, and repair power units         9      3      12       8
  --  5          Calibrate instrumentation                      3      1       8       4
  --  6          Check interfaces                               9      8      16      11
  --  7          Check assembly                                 7      4      13       8
  --  8          Assemble and test power units                  6      3       9       6
  --  9          Retrofit check                                 3      1       8       4
  -- 
  -- Node 	Depends of Activities
  -- 
  --  1              -
  --  2              1
  --  3              2, 5
  --  4              3, 7
  --  5              4
  --  6              6, 8, 9 
  -- 
  -- Activity    Depends on Node
  -- 
  --  1              1
  --  2              1
  --  3              1
  --  4              2
  --  5              2
  --  6              3
  --  7              3
  --  8              5
  --  9              4
  -- 
  -- [1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed.
  -- [2] Труб И.И., Объектно-ориентированное моделирование на C++: Учебный курс. - СПб.: Питер, 2006
  
  import Control.Monad
  import Control.Monad.Trans
  import Control.Arrow
  
  import Data.Array
  import Data.Maybe
  import Data.Monoid
  
  import Simulation.Aivika
  
  -- | The simulation specs.
  specs = Specs { spcStartTime = 0.0,
                  spcStopTime = 1000.0,
                  spcDT = 0.1,
                  spcMethod = RungeKutta4,
                  spcGeneratorType = SimpleGenerator }
  
  model :: Simulation Results
  model = mdo
    timers' <- forM [2..5] $ \i -> newArrivalTimer
    projCompletionTimer <- newArrivalTimer
    let timers = array (2, 5) $ zip [2..] timers'
        p1 = randomTriangularProcessor 1 3 5
        p2 = randomTriangularProcessor 3 6 9
        p3 = randomTriangularProcessor 10 13 19
        p4 = randomTriangularProcessor 3 9 12
        p5 = randomTriangularProcessor 1 3 8
        p6 = randomTriangularProcessor 8 9 16
        p7 = randomTriangularProcessor 4 7 13
        p8 = randomTriangularProcessor 3 6 9
        p9 = randomTriangularProcessor 1 3 8
    let c2 = arrivalTimerProcessor (timers ! 2)
        c3 = arrivalTimerProcessor (timers ! 3)
        c4 = arrivalTimerProcessor (timers ! 4)
        c5 = arrivalTimerProcessor (timers ! 5)
        c6 = arrivalTimerProcessor projCompletionTimer
    [i1, i2, i3] <- cloneStream 3 n1
    [i4, i5] <- cloneStream 2 n2
    [i6, i7] <- cloneStream 2 n3
    let i9 = n4
        i8 = n5
    let s1 = runProcessor p1 i1
        s2 = runProcessor p2 i2
        s3 = runProcessor p3 i3
        s4 = runProcessor p4 i4
        s5 = runProcessor p5 i5
        s6 = runProcessor p6 i6
        s7 = runProcessor p7 i7
        s8 = runProcessor p8 i8
        s9 = runProcessor p9 i9
    let n1 = takeStream 1 $ randomStream $ return (0, 0)
        n2 = runProcessor c2 s1
        n3 = runProcessor c3 $ firstArrivalStream 2 (s2 <> s5)
        n4 = runProcessor c4 $ firstArrivalStream 2 (s3 <> s7)
        n5 = runProcessor c5 s4
        n6 = runProcessor c6 $ firstArrivalStream 3 (s6 <> s8 <> s9)
    runProcessInStartTime $ sinkStream n6
    return $
      results
      [resultSource
       "timers" "Timers"
       timers,
       --
       resultSource
       "projCompletion" "Project Completion Timer"
       projCompletionTimer]
  
  modelSummary :: Simulation Results
  modelSummary =
    fmap resultSummary model
  
  main =
    printSimulationResultsInStopTime
    printResultSourceInEnglish
    -- model specs
    modelSummary specs
  