Example #1
0
        internal static int AddLeadTaskRow(
			DataGridView dgv,
			ViewFiltersBuilder viewFiltersBuilder,
			WorkItemInfoFiller workItemInfoFiller,
			ViewColumnsIndexes viewColumnsIndexes,
			FreeDaysCalculator freeDaysCalculator,
			FocusFactorCalculator focusFactorCalculator,
			WorkItem leadTask,
			DataContainer data,
			Dictionary<int, string> planningAssignments)
        {
            dgv.Rows.Add(new DataGridViewRow());
            var leadTaskRow = dgv.Rows[dgv.Rows.Count - 1];

            List<int> blockersIds = data.BlockersDict.ContainsKey(leadTask.Id)
                ? data.BlockersDict[leadTask.Id]
                : null;
            bool shouldCheckEstimate = workItemInfoFiller.FillLeadTaskInfo(
                viewFiltersBuilder,
                leadTask,
                leadTaskRow,
                data,
                blockersIds);

            viewFiltersBuilder.MarkLeadTaskRow(leadTaskRow);

            if (blockersIds != null)
                foreach (int blockerId in blockersIds)
                {
                    AddBlockerRow(
                        dgv,
                        viewFiltersBuilder,
                        workItemInfoFiller,
                        data,
                        planningAssignments,
                        blockerId);
                }

            if (leadTask.IsProposed())
                return ScheduleFiller.AddDatesProposed(
                    viewColumnsIndexes,
                    freeDaysCalculator,
                    focusFactorCalculator,
                    leadTask,
                    leadTaskRow,
                    viewColumnsIndexes.FirstDateColumnIndex,
                    m_proposedLtMark,
                    m_proposedLtMark,
                    shouldCheckEstimate);
            return ScheduleFiller.AddDatesActive(
                viewColumnsIndexes,
                freeDaysCalculator,
                focusFactorCalculator,
                leadTask,
                leadTaskRow,
                viewColumnsIndexes.FirstDateColumnIndex,
                m_activeLtMark,
                m_activeLtMark);
        }
        internal static Dictionary<int, Tuple<int?, int>> MakeSchedule(
			DataContainer dataContainer,
			Dictionary<int, string> planningAssignments,
			FreeDaysCalculator freeDaysCalculator,
			FocusFactorCalculator focusFactorCalculator)
        {
            var result = new Dictionary<int, Tuple<int?, int>>();
            var usersBlockersDict = new Dictionary<string, Dictionary<int, BlockerData>>();

            var usersTasksDict = SeparateByUser(dataContainer, planningAssignments);
            short i = 0;
            var numbersToUsersMapping = usersTasksDict.ToDictionary(u => ++i, u => u.Key);
            i = 0;
            var usersToNumbersMapping = usersTasksDict.Keys.ToDictionary(u => u, u => ++i);

            var usersToProcess = new List<short>(numbersToUsersMapping.Keys);
            var processedUsers = new List<short>(2*numbersToUsersMapping.Keys.Count);

            while (usersToProcess.Count > 0)
            {
                string user = numbersToUsersMapping[usersToProcess[0]];
                var blockersFromOtherUsers = ScheduleUserTasks(
                    usersTasksDict[user],
                    user,
                    freeDaysCalculator,
                    focusFactorCalculator,
                    dataContainer,
                    planningAssignments,
                    result);

                var usersToRecalculate = ProcessBlockers(
                    blockersFromOtherUsers,
                    usersBlockersDict,
                    result,
                    user);

                foreach (short userNumber in usersToRecalculate
                    .Where(usersToNumbersMapping.ContainsKey)
                    .Select(u => usersToNumbersMapping[u]))
                {
                    if (usersToProcess.Count > 0 && usersToProcess[usersToProcess.Count - 1] == userNumber)
                        continue;
                    usersToProcess.Add(userNumber);
                }
                if (usersToProcess.Count == 2*numbersToUsersMapping.Keys.Count)
                    processedUsers.RemoveAt(0);
                processedUsers.Add(usersToProcess[0]);
                usersToProcess.RemoveAt(0);

                if (CheckCycle(processedUsers))
                    throw new InvalidOperationException("Cycle blockers collision!");
            }
            return result;
        }
        internal static WorkItemVerificationResult VerifyChildrenExistance(WorkItem leadTask, DataContainer dataContainer)
        {
            if (dataContainer.LeadTaskChildrenDict.ContainsKey(leadTask.Id)
                && dataContainer.LeadTaskChildrenDict[leadTask.Id].Count > 0)
                return new WorkItemVerificationResult {Result = VerificationResult.Ok};

            return new WorkItemVerificationResult
            {
                Result = VerificationResult.Warning,
                Messages = new List<string>(1) { Messages.LeadTaskHasNoChildren() },
            };
        }
Example #4
0
        internal static Dictionary<int, string> Make(
			Dictionary<string, List<string>> usersToPlanByDiscipline,
			List<Tuple<int, string>> planningAssignments,
			DataContainer data)
        {
            var result = new Dictionary<int, string>(planningAssignments.Count);
            var usersWork = new Dictionary<string, double>();

            foreach (Tuple<int, string> assignment in planningAssignments)
            {
                WorkItem workItem = data.WiDict[assignment.Item1];
                if (!assignment.Item2.IsUnassigned())
                {
                    if (!usersWork.ContainsKey(assignment.Item2))
                        usersWork.Add(assignment.Item2, 0);
                    usersWork[assignment.Item2] += GetWork(workItem);
                    continue;
                }
                string discinpline = workItem.Discipline();
                if (!usersToPlanByDiscipline.ContainsKey(discinpline))
                    continue;
                var availableUsers = usersToPlanByDiscipline[discinpline];
                if (availableUsers.Count == 0)
                    continue;
                double min = int.MaxValue;
                bool assigned = false;
                string minUser = null;
                foreach (string availableUser in availableUsers)
                {
                    if (!usersWork.ContainsKey(availableUser))
                    {
                        usersWork.Add(availableUser, GetWork(workItem));
                        result.Add(assignment.Item1, availableUser);
                        assigned = true;
                        break;
                    }
                    if (min <= usersWork[availableUser])
                        continue;
                    min = usersWork[availableUser];
                    minUser = availableUser;
                }
                if (assigned)
                    continue;
                if (minUser != null)
                {
                    if (assignment.Item2.IsUnassigned())
                        result.Add(assignment.Item1, minUser);
                    usersWork[minUser] += GetWork(workItem);
                }
            }

            return result;
        }
Example #5
0
        private void AppendLeadTasks(DataContainer dataContainer, IEnumerable<WorkItem> leadTasks)
        {
            foreach (WorkItem leadTask in leadTasks)
            {
                var leadTaskLinkDict = WorkItemParser.ParseLinks(leadTask);

                dataContainer.LeadTaskChildrenDict.Add(
                    leadTask.Id,
                    leadTaskLinkDict.ContainsKey(WorkItemLinkType.Child)
                        ? leadTaskLinkDict[WorkItemLinkType.Child]
                        : new List<int>());

                dataContainer.WiDict.Add(leadTask.Id, leadTask);

                if (leadTaskLinkDict.ContainsKey(WorkItemLinkType.BlockedBy))
                    dataContainer.BlockersDict.Add(leadTask.Id, leadTaskLinkDict[WorkItemLinkType.BlockedBy]);
            }
        }
Example #6
0
        internal DataContainer ProcessLeadTasks(
			string tfsUrl,
			List<WorkItem> leadTasks,
			Action<int> progressReportHandler)
        {
            var result = new DataContainer
            {
                WiDict = new Dictionary<int, WorkItem>(),
                BlockersDict = new Dictionary<int, List<int>>(),
                LeadTaskChildrenDict = new Dictionary<int, List<int>>(),
            };

            AppendLeadTasks(result, leadTasks);

            using (var wiqlAccessor = new TfsWiqlAccessor(tfsUrl))
            {
                List<int> ltChildrenIds = result.LeadTaskChildrenDict.Values.SelectMany(i => i).ToList();
                AppendTasks(
                    ltChildrenIds,
                    null,
                    result,
                    wiqlAccessor,
                    progressReportHandler);

                CleanDict(
                    result.LeadTaskChildrenDict,
                    result.WiDict,
                    false,
                    true,
                    wiqlAccessor);
                CleanDict(
                    result.BlockersDict,
                    result.WiDict,
                    true,
                    false,
                    wiqlAccessor);

                InitExternalBlockers(result, wiqlAccessor);
            }

            return result;
        }
        private static Dictionary<string, HashSet<int>> ScheduleUserTasks(
			IEnumerable<Tuple<WorkItem, WorkItem>> userTasks,
			string user,
			FreeDaysCalculator freeDaysCalculator,
			FocusFactorCalculator focusFactorCalculator,
			DataContainer dataContainer,
			Dictionary<int, string> planningAssignments,
			Dictionary<int, Tuple<int?, int>> scheduledTasksDict)
        {
            var nonBlockedTasks = new List<Tuple<WorkItem, WorkItem>>();
            var activeBlockedTasks = new List<Tuple<WorkItem, WorkItem>>();
            var proposedBlockedTasks = new List<Tuple<WorkItem, WorkItem>>();
            foreach (Tuple<WorkItem, WorkItem> tuple in userTasks)
            {
                if (tuple.Item1.IsActive())
                {
                    if (!dataContainer.BlockersDict.ContainsKey(tuple.Item1.Id))
                        nonBlockedTasks.Add(tuple);
                    else
                        activeBlockedTasks.Add(tuple);
                }
                else if (tuple.Item1.IsProposed())
                {
                    if (!dataContainer.BlockersDict.ContainsKey(tuple.Item1.Id))
                        nonBlockedTasks.Add(tuple);
                    else
                        proposedBlockedTasks.Add(tuple);
                }
            }

            var schedule = AppendNonBlockedTasks(
                nonBlockedTasks,
                user,
                scheduledTasksDict,
                freeDaysCalculator,
                focusFactorCalculator);

            var result = new Dictionary<string, HashSet<int>>();

            AppendBlockedTasks(
                proposedBlockedTasks,
                schedule,
                dataContainer,
                planningAssignments,
                focusFactorCalculator,
                scheduledTasksDict,
                result);
            AppendBlockedTasks(
                activeBlockedTasks,
                schedule,
                dataContainer,
                planningAssignments,
                focusFactorCalculator,
                scheduledTasksDict,
                result);

            int currentDay = 0;
            foreach (var pair in schedule)
            {
                bool isTaskActive = pair.Item1.Item1.IsActive();
                int startDayIndex = isTaskActive ? 0 : currentDay;
                int vacationDaysCount = freeDaysCalculator.GetVacationsDaysCount(
                    user,
                    startDayIndex,
                    pair.Item2);
                scheduledTasksDict[pair.Item1.Item1.Id] = new Tuple<int?, int>(startDayIndex, pair.Item2 + vacationDaysCount);
                currentDay += vacationDaysCount;
                currentDay += isTaskActive ? Math.Max(pair.Item2 - currentDay, 0) : pair.Item2;
            }

            return result;
        }
Example #8
0
        private void InitExternalBlockers(DataContainer dataContainer, TfsWiqlAccessor wiqlAccessor)
        {
            if (dataContainer.BlockersDict.Count == 0)
                return;

            var notFound = new HashSet<int>();
            foreach (var pair in dataContainer.BlockersDict)
            {
                foreach (int blockerId in pair.Value.Where(i => !dataContainer.WiDict.ContainsKey(i)))
                {
                    notFound.Add(blockerId);
                }
            }

            if (notFound.Count == 0)
                return;

            var workItems = wiqlAccessor.QueryWorkItemsByIds(notFound, null);
            for (int i = 0; i < workItems.Count; i++)
            {
                WorkItem workItem = workItems[i];
                dataContainer.WiDict[workItem.Id] = workItem;
            }
        }
 internal static WorkItemVerificationResult VerifyNoProposedChildTask(WorkItem leadTask, DataContainer dataContainer)
 {
     if ((leadTask.IsProposed())
         && dataContainer.LeadTaskChildrenDict.ContainsKey(leadTask.Id))
     {
         foreach (int childTaskId in dataContainer.LeadTaskChildrenDict[leadTask.Id])
         {
             if (!dataContainer.WiDict.ContainsKey(childTaskId))
                 continue;
             WorkItem task = dataContainer.WiDict[childTaskId];
             if (!task.IsProposed())
                 return new WorkItemVerificationResult
                 {
                     Result = VerificationResult.Error,
                     Messages = new List<string>(1) {Messages.ProposedLeadTaskHasNotProposedChild()},
                 };
         }
     }
     return new WorkItemVerificationResult { Result = VerificationResult.Ok };
 }
Example #10
0
        private void RefreshData()
        {
            string currentUser = null;
            string currentSprint = null;
            Invoke(new Action(() =>
                {
                    loadLeadTasksButton.Enabled = false;
                    makeScheduleButton.Enabled = false;
                    refreshButton.Enabled = false;
                    if (usersFilterСomboBox.SelectedItem != null)
                        currentUser = usersFilterСomboBox.SelectedItem.ToString();
                    if (sprintFilterComboBox.SelectedItem != null)
                        currentSprint = sprintFilterComboBox.SelectedItem.ToString();
                    usersLabel.Enabled = false;
                    usersFilterСomboBox.Enabled = false;
                    scheduleDataGridView.Rows.Clear();

                    Text = GetFirstShortName();
                }));
            try
            {
                var leadTasksCollection = GetLastLeadTasks();

                var leadTasks = new List<WorkItem>(leadTasksCollection.Count);
                var oldSecond = s_stateContainer.WorkMode == WorkMode.AreaFirst ? m_config.LastIterationPaths : m_config.LastAreaPaths;
                var newSecond = new List<string>();
                foreach (WorkItem leadTask in leadTasksCollection)
                {
                    if (s_stateContainer.WorkMode != WorkMode.Query)
                    {
                        string second = s_stateContainer.GetParamForSecond(leadTask);
                        if (!oldSecond.Contains(second) && !newSecond.Contains(second))
                            newSecond.Add(second);
                        if (!s_stateContainer.IsSecondFromStateContains(second))
                            continue;
                    }
                    leadTasks.Add(leadTask);
                }
                m_lastProcessedData = s_dataFiller.ProcessLeadTasks(
                    tfsUrlTextBox.Text,
                    leadTasks,
                    ReportProgress);

                Invoke(new Action(() =>
                {
                    bool isDateChanged = scheduleDataGridView.Columns[s_viewColumnsIndexes.FirstDateColumnIndex].HeaderText != DateTime.Now.ToString("dd.MM");
                    if (isDateChanged)
                        ScheduleColumnsPresenter.InitColumns(
                            scheduleDataGridView,
                            s_viewColumnsIndexes.FirstDateColumnIndex,
                            1);
                    m_viewFiltersApplier = s_dataPresenter.PresentData(
                        m_lastProcessedData,
                        null,
                        null,
                        s_viewColumnsIndexes,
                        s_freeDaysCalculator,
                        m_focusFactorCalculator,
                        scheduleDataGridView);
                    workersComboBox.DataSource = m_viewFiltersApplier.Users;
                    vacationsButton.Enabled = m_viewFiltersApplier.Users.Count > 0;
                    var users2 = new List<string>(m_viewFiltersApplier.Users);
                    users2.Insert(0, string.Empty);
                    usersFilterСomboBox.DataSource = users2;

                    if (!string.IsNullOrEmpty(currentUser) && m_viewFiltersApplier.Users.Contains(currentUser))
                    {
                        usersFilterСomboBox.SelectedItem = currentUser;
                        m_viewFiltersApplier.FilterDataByUser(currentUser);
                    }

                    if (!string.IsNullOrEmpty(currentSprint) && m_viewFiltersApplier.Sprints.Contains(currentSprint))
                    {
                        sprintFilterComboBox.SelectedItem = currentSprint;
                        m_viewFiltersApplier.FilterDataBySprint(currentSprint);
                    }

                    usersFilterСomboBox.Enabled = true;
                    usersLabel.Enabled = true;
                    makeScheduleButton.Enabled = true;
                    loadLeadTasksButton.Enabled = true;
                    refreshButton.Enabled = true;
                    if (newSecond.Count > 0)
                    {
                        refreshButton.BackColor = Color.Yellow;
                        secondToolTip.SetToolTip(refreshButton,
                            Resources.NewItems + Environment.NewLine + string.Join(Environment.NewLine, newSecond));
                    }
                }));
            }
            catch (Exception exc)
            {
                HandleException(exc, Resources.LeadTasksParsingError);
                Invoke(
                    new Action(() =>
                    {
                        makeScheduleButton.Enabled = true;
                        loadLeadTasksButton.Enabled = true;
                        refreshButton.Enabled = true;
                    }));
            }
        }
        internal void FillTaskInfo(
			ViewFiltersBuilder viewFiltersBuilder,
			WorkItem task,
			List<WorkItem> siblings,
			WorkItem leadTask,
			DataGridViewRow taskRow,
			DataContainer data,
			Dictionary<int, string> planningAssignments,
			List<string> allUsers,
			List<int> blockerIds)
        {
            var priorityCell = taskRow.Cells[m_viewColumnsIndexes.PriorityColumnIndex];
            priorityCell.Value = task.Priority();
            priorityCell.SetColorByState(task);
            priorityCell.ToolTipText = task.State;

            var idCell = taskRow.Cells[m_viewColumnsIndexes.IdColumnIndex];
            idCell.Value = task.Id;
            var verificationResult = WorkItemVerifier.VerifyTaskPriority(task, leadTask.Priority());
            if (verificationResult.Result != VerificationResult.Ok)
            {
                idCell.SetColorByVerification(verificationResult.Result);
                idCell.ToolTipText = verificationResult.AllMessagesString;
            }
            else
            {
                verificationResult = WorkItemVerifier.VerifyTaskWithParentOnSameIteration(task, leadTask);
                if (verificationResult.Result != VerificationResult.Ok)
                {
                    idCell.SetColorByVerification(verificationResult.Result);
                    idCell.ToolTipText = verificationResult.AllMessagesString;
                }
            }

            var titleCell = taskRow.Cells[m_viewColumnsIndexes.TitleColumnIndex];
            titleCell.Value = task.Title;
            titleCell.ToolTipText = task.Discipline() + " " + task.Title;
            titleCell.Style.BackColor = priorityCell.Style.BackColor;

            var blockersCell = taskRow.Cells[m_viewColumnsIndexes.BlockersColumnIndex];
            if (blockerIds != null)
            {
                string blockerIdsStr = string.Join(",", blockerIds);
                blockersCell.Value = blockerIdsStr;

                verificationResult = WorkItemVerifier.VerifyNonChildBlockerExistance(blockerIds, siblings);
                if (verificationResult.Result == VerificationResult.Ok)
                    verificationResult = WorkItemVerifier.VerifyActiveTaskBlocking(task, blockerIds);
                if (verificationResult.Result == VerificationResult.Ok)
                {
                    blockerIdsStr = string.Join(Environment.NewLine, blockerIds.Select(b => data.WiDict[b].Title));
                    blockersCell.ToolTipText = blockerIdsStr;
                }
                else
                {
                    blockersCell.SetColorByVerification(verificationResult.Result);
                    blockersCell.ToolTipText = verificationResult.AllMessagesString;
                }
            }
            if (!string.IsNullOrEmpty(task.BlockingReason()))
            {
                if (!string.IsNullOrEmpty(blockersCell.ToolTipText))
                    blockersCell.ToolTipText += Environment.NewLine;
                else
                    blockersCell.Value = task.BlockingReason();
                blockersCell.ToolTipText += "Blocking Reason: " + task.BlockingReason();
            }

            var assignedCell = taskRow.Cells[m_viewColumnsIndexes.AssignedToColumnIndex];
            var comboBoxCell = assignedCell as DataGridViewComboBoxCell;
            if (comboBoxCell != null)
                comboBoxCell.DataSource = allUsers;
            assignedCell.Value = planningAssignments.GetAssignee(task);
            verificationResult = WorkItemVerifier.VerifyAssignation(task);
            if (verificationResult.Result != VerificationResult.Ok)
            {

                assignedCell.SetColorByVerification(verificationResult.Result);
                assignedCell.ToolTipText = verificationResult.AllMessagesString;
            }

            var workCell = taskRow.Cells[m_viewColumnsIndexes.WorkColumnIndex];
            workCell.Value = task.IsActive()
                ? task.Remaining()
                : task.Estimate();
            workCell.Style.BackColor = priorityCell.Style.BackColor;
        }
        internal bool FillLeadTaskInfo(
			ViewFiltersBuilder viewFiltersBuilder,
			WorkItem leadTask,
			DataGridViewRow leadTaskRow,
			DataContainer data,
			List<int> blockersIds)
        {
            var priorityCell = leadTaskRow.Cells[m_viewColumnsIndexes.PriorityColumnIndex];
            priorityCell.Value = leadTask.Priority();
            priorityCell.SetColorByState(leadTask);
            priorityCell.ToolTipText = leadTask.IsDevCompleted() ? WorkItemState.DevCompleted : leadTask.State;

            var iterationCell = leadTaskRow.Cells[m_viewColumnsIndexes.IterationColumnIndex];
            string iteration = leadTask.IterationPath;
            int ind = iteration.IndexOf(m_iterationSeparator);
            if (ind != -1)
                iteration = iteration.Substring(ind + 1);
            iterationCell.Value = iteration;

            var sprintCell = leadTaskRow.Cells[m_viewColumnsIndexes.SprintColumnIndex];
            sprintCell.Value = leadTask.Sprint();

            var idCell = leadTaskRow.Cells[m_viewColumnsIndexes.IdColumnIndex];
            idCell.Value = leadTask.Id;
            idCell.ToolTipText = leadTask.IterationPath;
            idCell.Style.BackColor = priorityCell.Style.BackColor;
            var verificationResult = WorkItemVerifier.VerifyChildrenExistance(leadTask, data);
            if (verificationResult.Result != VerificationResult.Ok)
            {
                idCell.SetColorByVerification(verificationResult.Result);
                idCell.ToolTipText += Environment.NewLine + verificationResult.AllMessagesString;
            }

            var docsCell = leadTaskRow.Cells[m_viewColumnsIndexes.DocsColumnIndex];
            bool result;
            verificationResult = WorkItemVerifier.VerifyDocumentsAgreement(leadTask);
            if (verificationResult.Result == VerificationResult.Ok)
            {
                docsCell.Style.BackColor = priorityCell.Style.BackColor;
                result = true;
            }
            else
            {
                docsCell.Value = verificationResult.AddidtionalData;
                docsCell.SetColorByVerification(verificationResult.Result);
                docsCell.ToolTipText = verificationResult.AllMessagesString;
                result = false;
            }

            var titleCell = leadTaskRow.Cells[m_viewColumnsIndexes.TitleColumnIndex];
            titleCell.Value = leadTask.Title;
            titleCell.Style.Font = new Font(
                titleCell.Style.Font
                    ?? titleCell.OwningColumn.DefaultCellStyle.Font
                    ?? m_dataGridView.ColumnHeadersDefaultCellStyle.Font,
                FontStyle.Underline);
            titleCell.Style.BackColor = priorityCell.Style.BackColor;

            verificationResult = WorkItemVerifier.VerifyNoProposedChildTask(leadTask, data);
            if (verificationResult.Result != VerificationResult.Ok)
            {
                priorityCell.SetColorByVerification(verificationResult.Result);
                priorityCell.ToolTipText = verificationResult.AllMessagesString;
            }

            var blockersCell = leadTaskRow.Cells[m_viewColumnsIndexes.BlockersColumnIndex];
            verificationResult = WorkItemVerifier.VerifyBlockersExistance(blockersIds);
            if (verificationResult.Result != VerificationResult.Ok)
            {
                blockersCell.SetColorByVerification(verificationResult.Result);
                blockersCell.Value = verificationResult.AllMessagesString;
            }
            if (!string.IsNullOrEmpty(leadTask.BlockingReason()))
            {
                if (!string.IsNullOrEmpty(leadTaskRow.Cells[4].ToolTipText))
                    blockersCell.ToolTipText += Environment.NewLine;
                else
                    blockersCell.Value = leadTask.BlockingReason();
                blockersCell.ToolTipText += "Blocking Reason: " + leadTask.BlockingReason();
            }

            leadTaskRow.Cells[m_viewColumnsIndexes.AssignedToColumnIndex].Value = leadTask.AssignedTo();

            return result;
        }
Example #13
0
        private void ProcessData()
        {
            s_stateContainer.LastTfsUrl = tfsUrlTextBox.Text;

            try
            {
                List<WorkItem> leadTasks = GetLeadTasks();

                m_lastProcessedData = s_dataFiller.ProcessLeadTasks(
                    s_stateContainer.LastTfsUrl,
                    leadTasks,
                    ReportProgress);
            }
            catch (Exception exc)
            {
                HandleException(exc, Resources.LeadTasksParsingError);
                Invoke(
                    new Action(() =>
                    {
                        makeScheduleButton.Enabled = true;
                        loadLeadTasksButton.Enabled = true;
                        queryTextBox.Enabled = true;
                        percentLabel.Visible = false;
                    }));
                return;
            }

            Invoke(new Action(() =>
                {
                    try
                    {
                        m_viewFiltersApplier = s_dataPresenter.PresentData(
                            m_lastProcessedData,
                            null,
                            null,
                            s_viewColumnsIndexes,
                            s_freeDaysCalculator,
                            m_focusFactorCalculator,
                            scheduleDataGridView);
                    }
                    catch (Exception exc)
                    {
                        HandleException(exc, Resources.LeadTasksParsingError);
                        Invoke(new Action(() =>
                        {
                            makeScheduleButton.Enabled = true;
                            loadLeadTasksButton.Enabled = true;
                            queryTextBox.Enabled = true;
                        }));
                        return;
                    }
                    workersComboBox.DataSource = m_viewFiltersApplier.Users.Where(u => !u.IsUnassigned()).ToList();
                    vacationsButton.Enabled = m_viewFiltersApplier.Users.Count > 0;
                    var users = new List<string>(m_viewFiltersApplier.Users);
                    users.Insert(0, string.Empty);
                    usersFilterСomboBox.DataSource = users;
                    usersFilterСomboBox.Enabled = true;
                    usersLabel.Enabled = true;
                    var sprints = new List<string>(m_viewFiltersApplier.Sprints);
                    sprints.Insert(0, string.Empty);
                    sprintFilterComboBox.DataSource = sprints;
                    sprintFilterComboBox.Enabled = true;
                    sprintLabel.Enabled = true;
                    makeScheduleButton.Enabled = true;
                    loadLeadTasksButton.Enabled = true;
                    holidaysButton.Enabled = true;
                    queryTextBox.Enabled = true;
                    refreshButton.Enabled = true;
                    planButton.Enabled = true;
                    percentLabel.Visible = false;
                    mainTabControl.SelectTab(dataTabPage);
                }));
        }
        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);
                    }
                }
            }
        }
Example #15
0
        private void AppendTasks(
			List<int> childrenIds,
			int? rootLeadTasskId,
			DataContainer dataContainer,
			TfsWiqlAccessor wiqlAccessor,
			Action<int> progressReportHandler)
        {
            if (childrenIds.Count == 0)
                return;

            var childrenTasks = wiqlAccessor.QueryWorkItemsByIds(
                childrenIds,
                progressReportHandler == null
                    ? null
                    : new Action<int>(x => progressReportHandler(LoadingPart * x / 100)));
            for (int i = 0; i < childrenTasks.Count; i++)
            {
                WorkItem task = childrenTasks[i];
                if (!dataContainer.WiDict.ContainsKey(task.Id))
                    dataContainer.WiDict.Add(task.Id, task);
                if (task.IsClosed())
                    continue;
                if (task.Type.Name != WorkItemType.Task)
                    continue;
                List<int> taskBlockersIds = WorkItemParser.GetRelationsByType(task, WorkItemLinkType.BlockedBy);
                if (taskBlockersIds.Count > 0)
                    dataContainer.BlockersDict.Add(task.Id, taskBlockersIds);

                var taskLinkDict = WorkItemParser.ParseLinks(task);
                int? currentParentLtId = rootLeadTasskId;
                if (currentParentLtId == null
                    && taskLinkDict.ContainsKey(WorkItemLinkType.Parent))
                {
                    int ltId = taskLinkDict[WorkItemLinkType.Parent][0];
                    if (dataContainer.LeadTaskChildrenDict.ContainsKey(ltId))
                        currentParentLtId = ltId;
                }
                if (currentParentLtId != null)
                {
                    var ltChildren = dataContainer.LeadTaskChildrenDict[currentParentLtId.Value];
                    if (!ltChildren.Contains(task.Id))
                        ltChildren.Add(task.Id);
                }
                if (taskLinkDict.ContainsKey(WorkItemLinkType.Child))
                    AppendTasks(
                        taskLinkDict[WorkItemLinkType.Child],
                        currentParentLtId,
                        dataContainer,
                        wiqlAccessor,
                        null);
                if (progressReportHandler != null)
                    progressReportHandler(LoadingPart + (100 - LoadingPart) * i / childrenTasks.Count);
            }
        }
        private static Tuple<int?, Dictionary<string, HashSet<int>>> GetFinishDateForBlockedTask(
			WorkItem blockedTask,
			DataContainer dataContainer,
			Dictionary<int, string> planningAssignments,
			FocusFactorCalculator focusFactorCalculator,
			Dictionary<int, Tuple<int?, int>> scheduledTasksDict)
        {
            int? finish = GetFinishDay(
                blockedTask,
                planningAssignments,
                focusFactorCalculator,
                scheduledTasksDict);

            Dictionary<string, HashSet<int>> userBlockersDict;

            if (dataContainer.BlockersDict.ContainsKey(blockedTask.Id))
            {
                userBlockersDict = new Dictionary<string, HashSet<int>>();
                foreach (int blockerId in dataContainer.BlockersDict[blockedTask.Id])
                {
                    WorkItem blocker = dataContainer.WiDict[blockerId];
                    var blockerData = GetFinishDateForBlockedTask(
                        blocker,
                        dataContainer,
                        planningAssignments,
                        focusFactorCalculator,
                        scheduledTasksDict);

                    int? currentFinish = GetFinishDay(
                        blocker,
                        planningAssignments,
                        focusFactorCalculator,
                        scheduledTasksDict);
                    currentFinish = MaxDay(currentFinish, blockerData.Item1);
                    finish = MaxDay(finish, currentFinish);

                    foreach (var blockerAssignData in blockerData.Item2)
                    {
                        if (!userBlockersDict.ContainsKey(blockerAssignData.Key))
                            userBlockersDict.Add(blockerAssignData.Key, new HashSet<int>());
                        var ids = userBlockersDict[blockerAssignData.Key];
                        foreach (int parentBlockerId in blockerAssignData.Value)
                        {
                            ids.Add(parentBlockerId);
                        }
                    }

                    string blockerAssignee = planningAssignments.GetAssignee(blocker);
                    if (userBlockersDict.ContainsKey(blockerAssignee))
                        userBlockersDict[blockerAssignee].Add(blockerId);
                    else
                        userBlockersDict.Add(blockerAssignee, new HashSet<int> {blockerId});
                }
            }
            else
            {
                userBlockersDict = new Dictionary<string, HashSet<int>>(0);
            }

            var result = new Tuple<int?, Dictionary<string, HashSet<int>>>(finish, userBlockersDict);

            return result;
        }
Example #17
0
        private static void AddBlockerRow(
			DataGridView dgv,
			ViewFiltersBuilder viewFiltersBuilder,
			WorkItemInfoFiller workItemInfoFiller,
			DataContainer data,
			Dictionary<int, string> planningAssignments,
			int blockerId)
        {
            dgv.Rows.Add(new DataGridViewRow());
            var blockerRow = dgv.Rows[dgv.Rows.Count - 1];
            WorkItem blocker = data.WiDict[blockerId];
            workItemInfoFiller.FillBlockerInfo(
                blockerRow,
                blocker,
                planningAssignments);
            viewFiltersBuilder.MarkBlockerRow(blockerRow);
        }
Example #18
0
        internal static int AddTaskRow(
			DataGridView dgv,
			ViewFiltersBuilder viewFiltersBuilder,
			WorkItemInfoFiller workItemInfoFiller,
			ViewColumnsIndexes viewColumnsIndexes,
			FreeDaysCalculator freeDaysCalculator,
			FocusFactorCalculator focusFactorCalculator,
			WorkItem task,
			List<WorkItem> siblings,
			WorkItem leadTask,
			DataContainer data,
			Dictionary<int, string> planningAssignments,
			List<string> allUsers,
			Dictionary<int, int> alreadyAdded,
			Dictionary<string, int> tasksByUser,
			Dictionary<int, Tuple<int?, int>> tasksSchedule)
        {
            if (alreadyAdded.ContainsKey(task.Id))
                return viewColumnsIndexes.FirstDateColumnIndex;

            var nextInds = new List<int>();

            List<int> blockerIds = ProcessBlockers(
                dgv,
                viewFiltersBuilder,
                workItemInfoFiller,
                viewColumnsIndexes,
                freeDaysCalculator,
                focusFactorCalculator,
                data,
                planningAssignments,
                allUsers,
                task,
                siblings,
                leadTask,
                alreadyAdded,
                nextInds,
                tasksByUser,
                tasksSchedule);

            dgv.Rows.Add(new DataGridViewRow());
            var taskRow = dgv.Rows[dgv.Rows.Count - 1];

            workItemInfoFiller.FillTaskInfo(
                viewFiltersBuilder,
                task,
                siblings,
                leadTask,
                taskRow,
                data,
                planningAssignments,
                allUsers,
                blockerIds);

            viewFiltersBuilder.MarkTaskRow(taskRow);

            if (blockerIds != null)
                foreach (int blockerId in blockerIds)
                {
                    AddBlockerRow(
                        dgv,
                        viewFiltersBuilder,
                        workItemInfoFiller,
                        data,
                        planningAssignments,
                        blockerId);
                }

            if (task.IsResolved())
            {
                alreadyAdded.Add(task.Id, viewColumnsIndexes.FirstDateColumnIndex);
                return viewColumnsIndexes.FirstDateColumnIndex;
            }

            string assignedTo = planningAssignments.GetAssignee(task);
            if (!assignedTo.IsUnassigned() && tasksByUser.ContainsKey(assignedTo))
                nextInds.Add(tasksByUser[assignedTo]);

            int maxNextInd = viewColumnsIndexes.FirstDateColumnIndex;
            if (nextInds.Count > 0)
                maxNextInd = nextInds.Max();

            string userMark = GetUserMark(assignedTo);

            Tuple<int?, int> taskSchedule = null;
            int nextInd;

            if (tasksSchedule != null && tasksSchedule.ContainsKey(task.Id))
                taskSchedule = tasksSchedule[task.Id];

            if (taskSchedule != null && taskSchedule.Item1 != null)
            {
                nextInd = ScheduleFiller.AddDatesFromSchedule(
                    viewColumnsIndexes,
                    freeDaysCalculator,
                    taskRow,
                    taskSchedule.Item1.Value,
                    taskSchedule.Item2,
                    assignedTo,
                    userMark);
            }
            else
            {
                nextInd = task.IsProposed()
                    ? ScheduleFiller.AddDatesProposed(
                        viewColumnsIndexes,
                        freeDaysCalculator,
                        focusFactorCalculator,
                        task,
                        taskRow,
                        maxNextInd,
                        assignedTo,
                        userMark,
                        true)
                    : ScheduleFiller.AddDatesActive(
                        viewColumnsIndexes,
                        freeDaysCalculator,
                        focusFactorCalculator,
                        task,
                        taskRow,
                        maxNextInd,
                        assignedTo,
                        userMark);
            }
            alreadyAdded.Add(task.Id, nextInd);
            tasksByUser[assignedTo] = nextInd;
            return nextInd;
        }
Example #19
0
        private static List<int> ProcessBlockers(
			DataGridView dgv,
			ViewFiltersBuilder viewFiltersBuilder,
			WorkItemInfoFiller workItemInfoFiller,
			ViewColumnsIndexes viewColumnsIndexes,
			FreeDaysCalculator freeDaysCalculator,
			FocusFactorCalculator focusFactorCalculator,
			DataContainer data,
			Dictionary<int, string> planningAssignments,
			List<string> allUsers,
			WorkItem task,
			List<WorkItem> childrenTasks,
			WorkItem leadTask,
			Dictionary<int, int> alreadyAdded,
			List<int> nextInds,
			Dictionary<string, int> tasksByUser,
			Dictionary<int, Tuple<int?, int>> tasksSchedule)
        {
            if (!data.BlockersDict.ContainsKey(task.Id))
                return null;

            var blockerIds = data.BlockersDict[task.Id];
            var blokers = blockerIds
                .Where(b => data.WiDict.ContainsKey(b))
                .Select(b => data.WiDict[b])
                .OrderBy(b => b.Priority())
                .ToList();
            foreach (var blocker in blokers)
            {
                if (alreadyAdded.ContainsKey(blocker.Id))
                {
                    nextInds.Add(alreadyAdded[blocker.Id]);
                    continue;
                }

                var blockerSiblingTask = childrenTasks.FirstOrDefault(t => t.Id == blocker.Id);
                if (blockerSiblingTask != null)
                {
                    int blockerNextInd = AddTaskRow(
                        dgv,
                        viewFiltersBuilder,
                        workItemInfoFiller,
                        viewColumnsIndexes,
                        freeDaysCalculator,
                        focusFactorCalculator,
                        blockerSiblingTask,
                        childrenTasks,
                        leadTask,
                        data,
                        planningAssignments,
                        allUsers,
                        alreadyAdded,
                        tasksByUser,
                        tasksSchedule);
                    nextInds.Add(blockerNextInd);
                }
            }

            return blockerIds;
        }
Example #20
0
        internal ViewFiltersApplier PresentData(
			DataContainer data,
			Dictionary<int, string> planningAssignments,
			List<string> allUsers,
			ViewColumnsIndexes viewColumnsIndexes,
			FreeDaysCalculator freeDaysCalculator,
			FocusFactorCalculator focusFactorCalculator,
			DataGridView dgv)
        {
            var tasksSchedule = WorkItemsScheduler.MakeSchedule(
                data,
                planningAssignments,
                freeDaysCalculator,
                focusFactorCalculator);

            var alreadyAdded = new Dictionary<int, int>();
            var tasksByUser = new Dictionary<string, int>();

            var resultBuilder = new ViewFiltersBuilder(dgv, viewColumnsIndexes);
            var workItemInfoFiller = new WorkItemInfoFiller(dgv, viewColumnsIndexes);

            foreach (var leadTaskChildren in data.LeadTaskChildrenDict)
            {
                var leadTask = data.WiDict[leadTaskChildren.Key];

                int nextLtInd = RowsAdder.AddLeadTaskRow(
                    dgv,
                    resultBuilder,
                    workItemInfoFiller,
                    viewColumnsIndexes,
                    freeDaysCalculator,
                    focusFactorCalculator,
                    leadTask,
                    data,
                    planningAssignments);
                int ltRowInd = dgv.Rows.Count - 1;

                var childrenTasks = leadTaskChildren.Value
                    .Where(i => data.WiDict.ContainsKey(i))
                    .Select(i => data.WiDict[i])
                    .OrderBy(i => i.Priority() ?? 999)
                    .ToList();

                if (childrenTasks.Count > 0)
                {
                    int lastTaskInd = childrenTasks
                        .Select(task =>
                            RowsAdder.AddTaskRow(
                                dgv,
                                resultBuilder,
                                workItemInfoFiller,
                                viewColumnsIndexes,
                                freeDaysCalculator,
                                focusFactorCalculator,
                                task,
                                childrenTasks,
                                leadTask,
                                data,
                                planningAssignments,
                                allUsers,
                                alreadyAdded,
                                tasksByUser,
                                tasksSchedule))
                        .Max();
                    ScheduleFiller.ColorFdOutDays(
                        viewColumnsIndexes,
                        freeDaysCalculator,
                        dgv.Rows[ltRowInd],
                        nextLtInd,
                        lastTaskInd);
                }

                var notAccessableChildren = leadTaskChildren.Value
                    .Where(i => !data.WiDict.ContainsKey(i))
                    .ToList();
                foreach (int notAccessableChildId in notAccessableChildren)
                {
                    dgv.Rows.Add(new DataGridViewRow());
                    var taskRow = dgv.Rows[dgv.Rows.Count - 1];
                    workItemInfoFiller.FillNotAccessibleTaskInfo(viewColumnsIndexes, taskRow, notAccessableChildId);
                    resultBuilder.MarkTaskRow(taskRow);
                }
            }

            return resultBuilder.Build();
        }
        private static Dictionary<string, List<Tuple<WorkItem, WorkItem>>> SeparateByUser(
			DataContainer dataContainer,
			Dictionary<int, string> planningAssignments)
        {
            var result = new Dictionary<string, List<Tuple<WorkItem, WorkItem>>>();
            foreach (var ltChildrenPair in dataContainer.LeadTaskChildrenDict)
            {
                WorkItem lt = dataContainer.WiDict[ltChildrenPair.Key];
                foreach (int childId in ltChildrenPair.Value)
                {
                    WorkItem child = dataContainer.WiDict[childId];
                    string assignee = planningAssignments.GetAssignee(child);
                    var childTuple = new Tuple<WorkItem, WorkItem>(child, lt);
                    if (!result.ContainsKey(assignee))
                        result.Add(assignee, new List<Tuple<WorkItem, WorkItem>> { childTuple });
                    else
                        result[assignee].Add(childTuple);
                }
            }
            return result;
        }