Пример #1
0
        ///<summary>Calculates the info for sprints</summary>
        private void RecalculateSprint(bool hasDateChanges = false)
        {
            DateTime dateStart = PIn.Date(textDateStart.Text);          //Min date if parse fails

            if (checkProgressMode.Checked)
            {
                dateStart = DateTime.Today.Date;
            }
            DateTime dateEnd = PIn.Date(textDateEnd.Text);          //Min date if parse fails

            if (dateStart > dateEnd)
            {
                return;
            }
            if (dateStart != DateTime.MinValue && dateEnd != DateTime.MinValue && hasDateChanges)
            {
                _listSchedules = Schedules.RefreshPeriodForEmps(dateStart, dateEnd, _listEngEmpNums);
            }
            double jobPercent             = PIn.Double(textEngJobPercent.Text);       //0 if parse fails
            double avgDevHours            = PIn.Double(textAvgDevelopmentHours.Text); //0 if parse fails
            double avgBreakHours          = PIn.Double(textBreakHours.Text);          //0 if parse fails
            double schedHoursTotal        = 0;
            double schedHoursBreaksTotal  = 0;
            double schedHoursPercentTotal = 0;
            double allocatableHours       = 0;

            foreach (Schedule sched in _listSchedules)
            {
                //Calculate actual scheduled time
                double schedHours = (sched.StopTime - sched.StartTime).TotalHours;
                schedHoursTotal += schedHours;
                //Remove average break time
                schedHours            -= avgBreakHours;
                schedHoursBreaksTotal += schedHours;
                //Multiply the scheduled time by the percentage of coding time for the jobs we care about
                schedHours              = schedHours * jobPercent;
                schedHoursPercentTotal += schedHours;
                //Add the sched hours to the allocatable hours
                allocatableHours += schedHours;
            }
            double totalAllocatedHours = 0;
            double totalCompletedHours = 0;

            foreach (Job job in _listAttachedJobs)
            {
                if (checkProgressMode.Checked && job.PhaseCur.In(JobPhase.Documentation, JobPhase.Complete, JobPhase.Cancelled))
                {
                    continue;
                }
                double estimate = job.HoursEstimate;
                if (job.HoursEstimateDevelopment == 0)
                {
                    estimate += avgDevHours;
                }
                totalAllocatedHours += estimate;
                if (checkProgressMode.Checked)
                {
                    totalAllocatedHours -= job.HoursActual;
                }
                totalCompletedHours += job.HoursActual;
            }
            textMaxHours.Text = Math.Round(allocatableHours, 0).ToString();
            //Set maximum progress bar to allocatable hours
            progressBarAllocatedHours.Maximum = PIn.Int(textMaxHours.Text);
            textAllocatedHours.Text           = Math.Round(totalAllocatedHours, 0).ToString();
            //Set value of progress bar to allocated hours
            progressBarAllocatedHours.Value = (PIn.Int(textAllocatedHours.Text) > progressBarAllocatedHours.Maximum)?progressBarAllocatedHours.Maximum:PIn.Int(textAllocatedHours.Text);
            //Update info
            textEngHours.Text   = Math.Round(schedHoursTotal).ToString();
            textAfterBreak.Text = Math.Round(schedHoursBreaksTotal).ToString();
            textRatioHours.Text = Math.Round(schedHoursPercentTotal).ToString();
            textJobNumber.Text  = _listAttachedJobs.Count.ToString();
            int days = (dateEnd - dateStart).Days;

            textDays.Text = days.ToString();
            textAvgAllocatableHours.Text = Math.Round(allocatableHours / days).ToString();
            double completionPercentage = 0;

            completionPercentage = (totalCompletedHours / totalAllocatedHours) * 100;
            if (Double.IsNaN(completionPercentage))
            {
                return;
            }
            completionPercentage               = completionPercentage > 100?100:completionPercentage;
            textCompletionPercentage.Text      = Math.Round(completionPercentage).ToString();
            progressBarCompletionPercent.Value = (int)completionPercentage;
        }
Пример #2
0
        private void FillGridEngineers(JobSprint jobSprint)
        {
            gridEngineers.BeginUpdate();
            gridEngineers.ListGridColumns.Clear();
            gridEngineers.ListGridColumns.Add(new GridColumn("Engineer", 0));
            gridEngineers.ListGridColumns.Add(new GridColumn("Scheduled Hrs", 150)
            {
                TextAlign = HorizontalAlignment.Center, SortingStrategy = GridSortingStrategy.AmountParse
            });
            gridEngineers.ListGridColumns.Add(new GridColumn("- Est. Breaks", 150)
            {
                TextAlign = HorizontalAlignment.Center, SortingStrategy = GridSortingStrategy.AmountParse
            });
            gridEngineers.ListGridColumns.Add(new GridColumn("= Hrs Total", 150)
            {
                TextAlign = HorizontalAlignment.Center, SortingStrategy = GridSortingStrategy.AmountParse
            });
            gridEngineers.ListGridColumns.Add(new GridColumn("Assigned Dev Hrs", 150)
            {
                TextAlign = HorizontalAlignment.Center, SortingStrategy = GridSortingStrategy.AmountParse
            });
            gridEngineers.ListGridColumns.Add(new GridColumn("Free Dev Hrs", 150)
            {
                TextAlign = HorizontalAlignment.Center, SortingStrategy = GridSortingStrategy.AmountParse
            });
            gridEngineers.ListGridColumns.Add(new GridColumn("Completed Hrs", 150)
            {
                TextAlign = HorizontalAlignment.Center, SortingStrategy = GridSortingStrategy.AmountParse
            });
            gridEngineers.ListGridRows.Clear();
            double          jobPercent       = jobSprint.JobPercent;
            double          avgDevHours      = jobSprint.HoursAverageDevelopment;
            double          avgBreakHours    = jobSprint.HoursAverageBreak;
            List <Schedule> listEngSchedules = Schedules.RefreshPeriodForEmps(jobSprint.DateStart, jobSprint.DateEndTarget, JobHelper.ListEngineerEmployeeNums);

            foreach (Userod userEng in JobHelper.ListEngineerUsers)
            {
                double schedHoursTotal        = 0;
                double schedHoursBreaksTotal  = 0;
                double schedHoursPercentTotal = 0;
                double allocatableHours       = 0;
                foreach (Schedule sched in listEngSchedules.FindAll(x => x.EmployeeNum == userEng.EmployeeNum))
                {
                    //Calculate actual scheduled time
                    double schedHours = (sched.StopTime - sched.StartTime).TotalHours;
                    schedHoursTotal += schedHours;
                    //Remove average break time
                    schedHours            -= avgBreakHours;
                    schedHoursBreaksTotal += schedHours;
                    //Multiply the scheduled time by the percentage of coding time for the jobs we care about
                    schedHours              = schedHours * jobPercent;
                    schedHoursPercentTotal += schedHours;
                    //Add the sched hours to the allocatable hours
                    allocatableHours += schedHours;
                }
                double totalAllocatedHours = 0;
                double totalCompletedHours = 0;
                //TODO: OwnerNum is not a good enough check here.
                //Make a method to get a sublist of jobs that legit apply to an engineer (In their writeup/development, not waiting for approval)
                List <Job> listEngJobs = _listJobsAll.FindAll(x => !x.IsApprovalNeeded &&
                                                              ((x.PhaseCur == JobPhase.Development && x.UserNumEngineer == userEng.UserNum) ||
                                                               (x.PhaseCur == JobPhase.Definition && x.UserNumExpert == userEng.UserNum)));
                foreach (Job job in listEngJobs)
                {
                    double estimate = job.HoursEstimate;
                    if (job.HoursEstimateDevelopment == 0)
                    {
                        estimate += avgDevHours;
                    }
                    totalAllocatedHours += estimate;
                    totalAllocatedHours -= job.HoursActual;
                    totalCompletedHours += job.HoursActual;
                }
                GridRow row = new GridRow()
                {
                    Tag = userEng
                };
                row.Cells.Add(userEng.UserName);
                row.Cells.Add(Math.Round(schedHoursTotal).ToString());
                row.Cells.Add(Math.Round(schedHoursTotal - schedHoursBreaksTotal).ToString());
                row.Cells.Add(Math.Round(schedHoursBreaksTotal).ToString());
                row.Cells.Add(Math.Round(totalAllocatedHours).ToString());
                double   freeHrs = Math.Round(schedHoursBreaksTotal - totalAllocatedHours);
                GridCell cell    = new GridCell(freeHrs.ToString());
                cell.ColorBackG = freeHrs < 20?Color.LightSalmon:Color.LightGreen;            //Arbitrary 20 hours.
                row.Cells.Add(cell);
                row.Cells.Add(Math.Round(totalCompletedHours).ToString());
                gridEngineers.ListGridRows.Add(row);
            }
            gridEngineers.EndUpdate();
        }
Пример #3
0
        private void butCalculate_Click(object sender, EventArgs e)
        {
            _listTopJobs.Clear();
            listEngNoJobs.Items.Clear();
            List <long> listEngNums  = listEngineers.SelectedTags <Employee>().Select(x => x.EmployeeNum).ToList();
            List <long> listUserNums = listEngNums.Select(x => Userods.GetUserByEmployeeNum(x).UserNum).ToList();
            //Get 6 months of scheduled engineering time. Arbitrary because there should be no way we have a 6 month release cycle.
            List <Schedule> listSchedules = Schedules.RefreshPeriodForEmps(DateTime.Today, DateTime.Today.AddMonths(6), listEngNums);
            //Get all the jobs according to the selected criteria.
            //No need to fill currently, but I may want to add reviews into this to improve accuracy for unfinished jobs
            List <Job> listJobs = _listJobsAll.Where(x => x.Priority.In(listPriorities.SelectedTags <Def>().Select(y => y.DefNum)) &&
                                                     x.PhaseCur.In(listPhases.SelectedTags <JobPhase>()) &&
                                                     x.Category.In(listCategories.SelectedTags <JobCategory>())).ToList();
            double   totalJobHours  = 0;
            DateTime releaseDate    = DateTime.Today;
            double   avgJobHours    = _avgJobHours;
            double   jobTimePercent = _jobTimePercent;
            double   avgBreakHours  = _avgBreakHours;

            Double.TryParse(textAvgJobHours.Text, out avgJobHours);
            Double.TryParse(textEngJobPercent.Text, out jobTimePercent);
            Double.TryParse(textBreakHours.Text, out avgBreakHours);
            gridCalculatedJobs.BeginUpdate();
            gridCalculatedJobs.Columns.Clear();
            gridCalculatedJobs.Columns.Add(new ODGridColumn("EstHrs", 0)
            {
                TextAlign = HorizontalAlignment.Center
            });
            gridCalculatedJobs.Columns.Add(new ODGridColumn("ActHrs", 0)
            {
                TextAlign = HorizontalAlignment.Center
            });
            gridCalculatedJobs.Columns.Add(new ODGridColumn("", 200));
            gridCalculatedJobs.Rows.Clear();
            foreach (Job job in listJobs)
            {
                if (job.UserNumEngineer == 0 && listUserNums.Contains(job.UserNumExpert))
                {
                    listUserNums.Remove(job.UserNumExpert);
                }
                if (job.UserNumEngineer != 0 && listUserNums.Contains(job.UserNumEngineer))
                {
                    listUserNums.Remove(job.UserNumEngineer);
                }
                //If hrsEst is 0 then use the avgJobHours as a base.
                double hrsEst = job.TimeEstimate.TotalHours == 0?avgJobHours:job.TimeEstimate.TotalHours;
                //Remove the actual hours spent on the job currently
                //If negative then just use 0 (We aren't in a dimension where negative time estimates can be used for other jobs)
                double hrsCalculated = (hrsEst - job.HoursActual) < 0?0:hrsEst - job.HoursActual;
                totalJobHours += hrsCalculated;
                if (job.PhaseCur == JobPhase.Development)
                {
                    _listTopJobs.Add(new Tuple <long, double>(job.JobNum, hrsCalculated));
                }
                gridCalculatedJobs.Rows.Add(
                    new ODGridRow(
                        new ODGridCell(job.TimeEstimate.TotalHours == 0?"0(" + _avgJobHours + ")":job.TimeEstimate.TotalHours.ToString()),
                        new ODGridCell(job.HoursActual.ToString()),
                        new ODGridCell(job.Title)
                        )
                {
                    Tag = job
                }
                    );
            }
            gridCalculatedJobs.EndUpdate();
            foreach (long engNum in listUserNums)
            {
                Userod eng = Userods.GetUser(engNum);
                listEngNoJobs.Items.Add(new ODBoxItem <Userod>(eng.UserName, eng));
            }
            try {
                _listTopJobs = _listTopJobs.OrderByDescending(x => x.Item2).Take(3).ToList();
                butJob1.Text = "#" + _listTopJobs[0].Item1.ToString() + "-" + Math.Round(_listTopJobs[0].Item2).ToString() + " hours";
                butJob2.Text = "#" + _listTopJobs[1].Item1.ToString() + "-" + Math.Round(_listTopJobs[1].Item2).ToString() + " hours";
                butJob3.Text = "#" + _listTopJobs[2].Item1.ToString() + "-" + Math.Round(_listTopJobs[2].Item2).ToString() + " hours";
            }
            catch {
                panelExtra.Visible = false;
            }
            labelJobHours.Text  = Math.Round(totalJobHours).ToString();
            labelJobNumber.Text = listJobs.Count.ToString();
            double schedHoursTotal        = 0;
            double schedHoursBreaksTotal  = 0;
            double schedHoursPercentTotal = 0;

            foreach (Schedule sched in listSchedules)
            {
                //Calculate actual scheduled time
                double schedHours = (sched.StopTime - sched.StartTime).TotalHours;
                schedHoursTotal += schedHours;
                //Remove average break time
                schedHours            -= avgBreakHours;
                schedHoursBreaksTotal += schedHours;
                //Multiply the scheduled time by the percentage of coding time for the jobs we care about
                schedHours              = schedHours * jobTimePercent;
                schedHoursPercentTotal += schedHours;
                //Remove the scheduled hours from the total job hours
                totalJobHours -= schedHours;
                if (totalJobHours < 0)
                {
                    releaseDate = sched.SchedDate;                  //Add a week as a buffer
                    break;
                }
            }
            labelEngHours.Text       = Math.Round(schedHoursTotal).ToString();
            labelAfterBreak.Text     = Math.Round(schedHoursBreaksTotal).ToString();
            labelRatioHours.Text     = Math.Round(schedHoursPercentTotal).ToString();
            labelReleaseDate.Text    = releaseDate.ToShortDateString() + " - " + releaseDate.AddDays(7).ToShortDateString();
            labelReleaseDate.Visible = true;
            panelExtra.Visible       = true;
        }