private static int? GetFinishDay(
			WorkItem task,
			Dictionary<int, string> planningAssignments,
			FocusFactorCalculator focusFactorCalculator,
			Dictionary<int, Tuple<int?, int>> scheduledTasksDict)
        {
            int? result = null;
            if (scheduledTasksDict.ContainsKey(task.Id))
            {
                var blockerSchedule = scheduledTasksDict[task.Id];
                if (blockerSchedule.Item1 != null)
                    result = blockerSchedule.Item1.Value + blockerSchedule.Item2;
            }
            else
            {
                double? remaining = task.IsProposed()
                    ? task.Estimate()
                    : task.Remaining();
                if (remaining != null)
                    result = focusFactorCalculator.CalculateDaysByTime(
                        remaining.Value,
                        planningAssignments.GetAssignee(task));
            }
            return result;
        }
        private static void AppendBlockedTasks(
			IEnumerable<Tuple<WorkItem, WorkItem>> blockedTasks,
			List<Tuple<Tuple<WorkItem, WorkItem>, int>> schedule,
			DataContainer dataContainer,
			Dictionary<int, string> planningAssignments,
			FocusFactorCalculator focusFactorCalculator,
			Dictionary<int, Tuple<int?, int>> scheduledTasksDict,
			Dictionary<string, HashSet<int>> usersBlockers)
        {
            var comparer = new TaskPriorityComparer();
            foreach (var tuple in blockedTasks)
            {
                WorkItem blockedTask = tuple.Item1;
                var finishData = GetFinishDateForBlockedTask(
                    blockedTask,
                    dataContainer,
                    planningAssignments,
                    focusFactorCalculator,
                    scheduledTasksDict);
                if (finishData.Item1 == null)
                {
                    schedule.Add(new Tuple<Tuple<WorkItem, WorkItem>, int>(tuple, 0));
                }
                else
                {
                    double? remaining = tuple.Item1.IsActive()
                        ? blockedTask.Remaining()
                        : blockedTask.Estimate();
                    int taskDaysCount = remaining == null
                        ? 0
                        : focusFactorCalculator.CalculateDaysByTime(
                            remaining.Value,
                            planningAssignments.GetAssignee(tuple.Item1));
                    int startDay = 0;
                    bool added = false;
                    for (int i = 0; i < schedule.Count; i++)
                    {
                        var taskData = schedule[i];
                        if (taskData.Item1.Item1.IsActive())
                            continue;
                        if (startDay > finishData.Item1.Value && comparer.Compare(tuple, taskData.Item1) < 0)
                        {
                            schedule.Insert(i, new Tuple<Tuple<WorkItem, WorkItem>, int>(tuple, taskDaysCount));
                            added = true;
                            break;
                        }
                        startDay += taskData.Item1.Item1.IsActive()
                            ? Math.Max(taskData.Item2 - startDay, 0)
                            : taskData.Item2;
                    }
                    if (!added)
                        schedule.Add(new Tuple<Tuple<WorkItem, WorkItem>, int>(tuple, taskDaysCount));
                }

                foreach (var userBlockersPair in finishData.Item2)
                {
                    HashSet<int> blockers;
                    if (usersBlockers.ContainsKey(userBlockersPair.Key))
                    {
                        blockers = usersBlockers[userBlockersPair.Key];
                    }
                    else
                    {
                        blockers = new HashSet<int>();
                        usersBlockers.Add(userBlockersPair.Key, blockers);
                    }
                    foreach (int blockerId in userBlockersPair.Value)
                    {
                        blockers.Add(blockerId);
                    }
                }
            }
        }
        private static int GetDaysCount(
			WorkItem task,
			string user,
			Dictionary<int, Tuple<int?, int>> scheduledTasksDict,
			FreeDaysCalculator freeDaysCalculator,
			FocusFactorCalculator focusFactorCalculator)
        {
            if (task.IsActive())
            {
                DateTime? finishDate = task.FinishDate();
                int finish = scheduledTasksDict.ContainsKey(task.Id)
                    ? scheduledTasksDict[task.Id].Item2
                    : (finishDate == null
                        ? 0
                        : freeDaysCalculator.GetDaysCount(finishDate.Value, user));
                double? remaining = task.Remaining();
                if (remaining != null && remaining > 0)
                {
                    int finishByRemaining = focusFactorCalculator.CalculateDaysByTime(remaining.Value, user);
                    if (finish < finishByRemaining)
                        finish = finishByRemaining;
                }
                return finish;
            }
            double? estimate = task.Estimate();
            return estimate == null
                ? 0
                : focusFactorCalculator.CalculateDaysByTime(estimate.Value, user);
        }