anchor.diff:  type CpuTime = CpuTime of int
   type CpuState = | Free | BusyUntil of CpuTime
   
  -type TaskState =
  -    | TaskCompleted of CpuTime
  -    | NotRun
  +type TaskState = | TaskCompleted of CpuTime
   
  -//type TaskStates = Map<Task,TaskState>
  -
  -type MachineState = | MachineState of CpuState list * Map<string,TaskState>
  +type MachineState<'T when 'T:comparison> =
  +    { Cpu: CpuState list; Tasks: Map<'T,TaskState>}
   
   [<TestFixture>]
   type ProgressTests() =
   
  -    /// Gets task duration
  -    let duration = function
  -        | Task (_,d) -> d
  -        | TaskWithDeps (_,d,_) -> d
  +    let rec exec state task getDuration getDeps =
  +        // Gets the time when thread will be available
  +        let readyAt = function
  +            | Free -> 0
  +            | BusyUntil (CpuTime x) -> x
   
  -    let task_name = function
  -        | Task (name,_)
  -        | TaskWithDeps (name,_,_) -> name
  -    
  -    /// Gets the time when thread will be available
  -    let readyAt = function
  -        | Free -> 0
  -        | BusyUntil (CpuTime x) -> x
  +        // Gets the thread that will be freed after specific moment
  +        let nearest after =
  +            let ready = function
  +                | Free -> 0
  +                | BusyUntil (CpuTime x) -> if x <= after then 0 else x
  +            List.minBy ready
   
  -    /// Updates the first item matching the criteria and returns the updated value
  -    let rec updateFirst1 predicate upd = function
  -        | [] -> None,[]
  -        | c::list when predicate c ->
  -            let updated = upd c in
  -            Some updated, updated :: list
  -        | c::list ->
  -            let result,list = (updateFirst1 predicate upd list) in
  -            result, c::list
  -
  -    /// Gets the thread that will be freed after specific moment
  -    let nearest after =
  -        let ready = function
  -            | Free -> 0
  -            | BusyUntil (CpuTime x) -> if x <= after then 0 else x
  -        List.minBy ready
  -
  -    let rec exec state task getTask =
  -        let name = task_name task
  -        let (MachineState (_,tasks)) = state
  -
  -        match tasks |> Map.tryFind name with
  +        // Updates the first item matching the criteria and returns the updated value
  +        let rec updateFirst1 predicate upd = function
  +            | [] -> None,[]
  +            | c::list when predicate c ->
  +                let updated = upd c in
  +                Some updated, updated :: list
  +            | c::list ->
  +                let result,list = (updateFirst1 predicate upd list) in
  +                result, c::list
  +        
  +        match state.Tasks |> Map.tryFind task with
           | Some result -> state,result
           | None ->
  -            let MachineState(newState,tasks), CpuTime endTime =
  -                match task with
  -                | Task _ ->              state, CpuTime 0
  -                | TaskWithDeps (_,_,deps) -> execMany state deps getTask
  -            let slot = newState |> nearest endTime
  -            let Some (BusyUntil result),newState =
  -                newState |> updateFirst1 ((=) slot) (readyAt >> (max endTime) >> ((+) (duration task)) >> CpuTime >> BusyUntil)
  -            let newTasks = tasks |> Map.add name (TaskCompleted result)
  -            MachineState (newState, newTasks), TaskCompleted result
  +            let mstate, CpuTime endTime =
  +                match getDeps task with
  +                | [] ->   state, CpuTime 0
  +                | deps -> execMany state deps getDuration getDeps
  +            let slot = mstate.Cpu |> nearest endTime
  +            let Some (BusyUntil result), newState =
  +                mstate.Cpu |> updateFirst1 ((=) slot) (readyAt >> (max endTime) >> ((+) (getDuration task)) >> CpuTime >> BusyUntil)
  +            {Cpu = newState; Tasks = mstate.Tasks |> Map.add task (TaskCompleted result)}, TaskCompleted result
   //        |> fun r ->
   //            printf "after %A" (task_name task)
   //            printf "   %A\n\n" r
   //            r
   
       // exec all deps, collect latest, allocate cpu
  -    and execMany state goals getTask =
  +    and execMany state goals getDuration getDeps =
           let machineState,endTime =
  -            goals |> List.map getTask |> List.fold (
  +            goals |> List.fold (
                   fun (prevState,prevTime) t ->
  -                    let newState,(TaskCompleted (CpuTime time)) = exec prevState t getTask in
  +                    let newState,(TaskCompleted (CpuTime time)) = exec prevState t getDuration getDeps in
                       (newState, max time prevTime)
                   ) (state,0)
   
           machineState, CpuTime endTime
   
  -    let estimate threads tasks goals =
  +    let estimate threadCount completed_tasks tasks goals =
   
  -        let pool = MachineState ((List.replicate threads Free), Map.empty)
  -        let taskMap = tasks |> List.map (fun task -> task_name task, task) |> Map.ofList
  +        let getTaskName = function
  +            | Task (name,_) -> name
  +            | TaskWithDeps (name,_,_) -> name
   
  -        let _, CpuTime endTime = execMany pool goals (fun name -> Map.find name taskMap)
  +        let getDuration = function
  +            | Task (_,d) -> d
  +            | TaskWithDeps (_,d,_) -> d
  +
  +        let tasks_map = completed_tasks |> List.map (fun t -> (t, TaskCompleted <| CpuTime 0)) |> Map.ofList
  +        let machine_state = {Cpu = (Free |> List.replicate threadCount); Tasks = tasks_map}
  +        let taskMap = tasks |> List.map (fun task -> getTaskName task, task) |> Map.ofList
  +
  +        let taskByName name = Map.find name taskMap
  +        let getDeps = function |Task _ -> [] |TaskWithDeps(_,_,deps) -> deps |> List.map taskByName
  +        let _, CpuTime endTime = execMany machine_state (goals |> List.map taskByName) getDuration getDeps
           in
           endTime
   
  
positive.code:             TaskWithDeps ("resources-ru", 3, ["strings"])
              Task ("strings", 2)
              ]
          estimate threads tasks1 ["build"]
  
negative.code:                 Task ("compile", 7)
              ]
  
          estimate threads [] tasks1 ["build"]       
  
      [<TestCase(6, Result = 11)>]
      [<TestCase(1, Result = 11)>]
  