///<summary>Reloads all data for form.</summary> private void RefreshData() { _listHashes = BugSubmissionHashes.GetMany(datePicker.GetDateTimeFrom(), datePicker.GetDateTimeTo()); _dictBugSubsByHashNum = BugSubmissions.GetForHashNums(_listHashes.Select(x => x.BugSubmissionHashNum).ToList()); _dictBugs = Bugs.GetMany(_listHashes.Select(x => x.BugId).Where(x => x != 0).ToList()).ToDictionary(key => key.BugId); _dictPatients = RegistrationKeys.GetPatientsByKeys(_dictBugSubsByHashNum.Values.SelectMany(x => x.Select(y => y.RegKey)).ToList()); }
private void FillGridMain() { string[] searchTokens = textSearch.Text.ToLower().Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries); long[] userNums = new long[0]; JobCategory[] jobCats = new JobCategory[0]; JobPhase[] jobPhases = new JobPhase[0]; long[] jobPriorities = new long[0]; if (listBoxUsers.SelectedIndices.Count > 0 && !listBoxUsers.SelectedIndices.Contains(0)) { userNums = listBoxUsers.SelectedIndices.Cast <int>().Select(x => _listUsers[x - 1].UserNum).ToArray(); } if (listBoxCategory.SelectedIndices.Count > 0 && !listBoxCategory.SelectedIndices.Contains(0)) { jobCats = listBoxCategory.SelectedIndices.Cast <int>().Select(x => (JobCategory)(x - 1)).ToArray(); } if (listBoxPhases.SelectedIndices.Count > 0 && !listBoxPhases.SelectedIndices.Contains(0)) { jobPhases = listBoxPhases.SelectedIndices.Cast <int>().Select(x => (JobPhase)(x - 1)).ToArray(); } if (listBoxPriorities.SelectedIndices.Count > 0 && !listBoxPriorities.SelectedIndices.Contains(0)) { jobPriorities = listBoxPriorities.GetListSelected <Def>().Select(x => x.DefNum).ToArray(); } Action actionCloseProgress = ODProgress.Show(ODEventType.Job, typeof(JobEvent), "Getting job data..."); #region Get Missing Data //This entire section will go out to the database and get any data that is unknown based on some of the filters. //The other filters will be applied later via the cached lists. try { List <Job> listJobs = Jobs.GetForSearch(dateFrom.Value, dateTo.Value, jobPhases.ToList(), jobPriorities.ToList(), _listJobsAll.Select(x => x.JobNum).ToList()); Jobs.FillInMemoryLists(listJobs, true); _listJobsAll.AddRange(listJobs); } catch (OutOfMemoryException oome) { actionCloseProgress(); oome.DoNothing(); MsgBox.Show(this, "Not enough memory to complete the search. Please refine search filters."); return; } //Only get the feature request entries that we care about. JobEvent.Fire(ODEventType.Job, "Getting feature request data..."); List <long> listFeatureRequestNums = _listJobsAll.SelectMany(x => x.ListJobLinks) .Where(x => x.LinkType == JobLinkType.Request) .Select(x => x.FKey) .Distinct() .ToList(); //Don't download any feature requests that we already know about. listFeatureRequestNums.RemoveAll(x => x.In(_listFeatureRequestsAll.Select(y => y.FeatReqNum))); if (!listFeatureRequestNums.IsNullOrEmpty()) { _listFeatureRequestsAll.AddRange(FeatureRequests.GetAll(listFeatureRequestNums)); } //Only get the bug entries that we care about. JobEvent.Fire(ODEventType.Job, "Getting bug data..."); List <long> listBugIds = _listJobsAll.SelectMany(x => x.ListJobLinks) .Where(x => x.LinkType == JobLinkType.Bug) .Select(x => x.FKey) .Distinct() .ToList(); //Don't download any bugs that we already know about. listBugIds.RemoveAll(x => x.In(_listBugsAll.Select(y => y.BugId))); if (!listBugIds.IsNullOrEmpty()) { _listBugsAll.AddRange(Bugs.GetMany(listBugIds)); } #endregion JobEvent.Fire(ODEventType.Job, "Filling grid..."); gridMain.BeginUpdate(); gridMain.ListGridColumns.Clear(); gridMain.ListGridColumns.Add(new GridColumn("Job\r\nNum", 50, GridSortingStrategy.AmountParse)); gridMain.ListGridColumns.Add(new GridColumn("Priority", 50, HorizontalAlignment.Center)); gridMain.ListGridColumns.Add(new GridColumn("Phase", 85)); gridMain.ListGridColumns.Add(new GridColumn("Category", 80)); gridMain.ListGridColumns.Add(new GridColumn("Job Title", -1)); gridMain.ListGridColumns.Add(new GridColumn("Version", 80)); gridMain.ListGridColumns.Add(new GridColumn("Est. Version", 80)); gridMain.ListGridColumns.Add(new GridColumn("Expert", 75)); gridMain.ListGridColumns.Add(new GridColumn("Engineer", 75)); gridMain.ListGridColumns.Add(new GridColumn("Est.\r\nHours", 60, GridSortingStrategy.AmountParse)); gridMain.ListGridColumns.Add(new GridColumn("Act.\r\nHours", 60, GridSortingStrategy.AmountParse)); gridMain.ListGridColumns.Add(new GridColumn("Job\r\nMatch", 45, HorizontalAlignment.Center)); gridMain.ListGridColumns.Add(new GridColumn("Bug\r\nMatch", 45, HorizontalAlignment.Center)); gridMain.ListGridColumns.Add(new GridColumn("FR\r\nMatch", 45, HorizontalAlignment.Center)); gridMain.ListGridRows.Clear(); _listJobsFiltered = new List <Job>(); foreach (Job jobCur in _listJobsAll) { if (jobCats.Length > 0 && !jobCats.Contains(jobCur.Category)) { continue; } if (jobPhases.Length > 0 && !jobPhases.Contains(jobCur.PhaseCur)) { continue; } if (jobPriorities.Length > 0 && !jobPriorities.Contains(jobCur.Priority)) { continue; } if (userNums.Length > 0 && !userNums.All(x => Jobs.GetUserNums(jobCur).Contains(x))) { continue; } if (!jobCur.DateTimeEntry.Between(dateFrom.Value, dateTo.Value)) { continue; } bool isJobMatch = false; bool isBugMatch = false; bool isFeatureReqMatch = false; if (searchTokens.Length > 0) { bool addRow = false; List <Bug> listBugs = jobCur.ListJobLinks.FindAll(x => x.LinkType == JobLinkType.Bug) .Select(x => _listBugsAll.FirstOrDefault(y => x.FKey == y.BugId)) .Where(x => x != null) .ToList(); List <FeatureRequest> listFeatures = jobCur.ListJobLinks.FindAll(x => x.LinkType == JobLinkType.Request) .Select(x => _listFeatureRequestsAll.FirstOrDefault(y => x.FKey == y.FeatReqNum)) .Where(x => x != null) .ToList(); foreach (string token in searchTokens.Distinct()) { bool isFound = false; //JOB MATCHES if (jobCur.Title.ToLower().Contains(token) || jobCur.Implementation.ToLower().Contains(token) || jobCur.Requirements.ToLower().Contains(token) || jobCur.Documentation.ToLower().Contains(token) || jobCur.JobNum.ToString().Contains(token)) { isFound = true; isJobMatch = true; } //BUG MATCHES if (!isFound || !isBugMatch) { if (listBugs.Any(x => x.Description.ToLower().Contains(token) || x.Discussion.ToLower().Contains(token))) { isFound = true; isBugMatch = true; } } //FEATURE REQUEST MATCHES if (!isFound || !isFeatureReqMatch) { if (listFeatures.Any(x => x.Description.Contains(token) || x.FeatReqNum.ToString().ToLower().Contains(token))) { isFound = true; isFeatureReqMatch = true; } } addRow = isFound; if (!isFound) { break; //stop looking for additional tokens, we didn't find this one. } } if (!addRow) { continue; //we did not find one of the search terms. } } _listJobsFiltered.Add(jobCur); Def jobPriority = _listJobPriorities.FirstOrDefault(y => y.DefNum == jobCur.Priority); GridRow row = new GridRow(); row.Cells.Add(jobCur.JobNum.ToString()); row.Cells.Add(new GridCell(jobPriority.ItemName) { ColorBackG = jobPriority.ItemColor, ColorText = (jobCur.Priority == _listJobPriorities.FirstOrDefault(y => y.ItemValue.Contains("Urgent")).DefNum) ? Color.White : Color.Black, }); row.Cells.Add(jobCur.PhaseCur.ToString()); row.Cells.Add(jobCur.Category.ToString()); row.Cells.Add(jobCur.Title); row.Cells.Add(jobCur.JobVersion.ToString()); row.Cells.Add(jobCur.ProposedVersion.ToString()); row.Cells.Add(Userods.GetName(jobCur.UserNumExpert)); row.Cells.Add(Userods.GetName(jobCur.UserNumEngineer)); row.Cells.Add(jobCur.HoursEstimate.ToString()); row.Cells.Add(jobCur.HoursActual.ToString()); row.Cells.Add(isJobMatch ? "X" : ""); row.Cells.Add(isBugMatch ? "X" : ""); row.Cells.Add(new GridCell(isFeatureReqMatch ? "X" : "") { ColorBackG = _listFeatureRequestsAll.Count == 0 ? Control.DefaultBackColor : Color.Empty }); row.Tag = jobCur; gridMain.ListGridRows.Add(row); } gridMain.EndUpdate(); actionCloseProgress(); }
///<summary></summary> public static bool TryAssociateSimilarBugSubmissions(List <BugSubmission> listAllSubs, Point pointFormLocaiton) { List <BugSubmission> listUnattachedSubs = listAllSubs.Where(x => x.BugId == 0).ToList(); if (listUnattachedSubs.Count == 0) { MsgBox.Show("FormBugSubmissions", "All submissions are associated to bugs already."); return(false); } //Dictionary where key is a BugId and the value is list of submissions associated to that BugID. //StackTraces are unique and if there are duplicate stack trace entries we select the one with the newest version. Dictionary <long, List <BugSubmission> > dictAttachedSubs = listAllSubs.Where(x => x.BugId != 0) .GroupBy(x => x.BugId) .ToDictionary(x => x.Key, x => x.GroupBy(y => y.ExceptionStackTrace) //Sub dictionary of unique ExceptionStackStraces as the key and the value is the submission from the highest version. .ToDictionary(y => y.Key, y => y.OrderByDescending(z => new Version(z.Info.DictPrefValues[PrefName.ProgramVersion])).First()) .Values.ToList() ); Dictionary <long, List <BugSubmission> > dictSimilarBugSubs = new Dictionary <long, List <BugSubmission> >(); List <long> listOrderedKeys = dictAttachedSubs.Keys.OrderByDescending(x => x).ToList(); foreach (long key in listOrderedKeys) //Loop through submissions that are already attached to bugs { dictSimilarBugSubs[key] = new List <BugSubmission>(); foreach (BugSubmission sub in dictAttachedSubs[key]) //Loop through the unique exception text from the submission with thie highest reported version. { List <BugSubmission> listSimilarBugSubs = listUnattachedSubs.Where(x => x.ExceptionStackTrace == sub.ExceptionStackTrace//Find submissions that are not attached to bugs with identical ExceptionStackTrace ).ToList(); if (listSimilarBugSubs.Count == 0) { continue; //All submissions with this stack trace are attached to a bug. } listUnattachedSubs.RemoveAll(x => listSimilarBugSubs.Contains(x)); dictSimilarBugSubs[key].AddRange(listSimilarBugSubs); } } if (dictSimilarBugSubs.All(x => x.Value.Count == 0)) { MsgBox.Show("FormBugSubmissions", "All similar submissions are already attached to bugs. No action needed."); return(false); } dictSimilarBugSubs = dictSimilarBugSubs.Where(x => x.Value.Count != 0).ToDictionary(x => x.Key, x => x.Value); bool isAutoAssign = (MsgBox.Show("FormBugSubmissions", MsgBoxButtons.YesNo, "Click Yes to auto attach duplicate submissions to bugs with identical stack traces?" + "\r\nClick No to manually validate all groupings found.")); List <long> listBugIds = listAllSubs.Where(x => x.BugId != 0).Select(x => x.BugId).ToList(); List <JobLink> listLinks = JobLinks.GetManyForType(JobLinkType.Bug, listBugIds); List <Bug> listBugs = Bugs.GetMany(listBugIds); foreach (KeyValuePair <long, List <BugSubmission> > pair in dictSimilarBugSubs) { Bug bugFixed = listBugs.FirstOrDefault(x => x.BugId == pair.Key && !string.IsNullOrEmpty(x.VersionsFixed)); if (bugFixed != null) { List <BugSubmission> listIssueSubs = pair.Value.Where(x => new Version(x.Info.DictPrefValues[PrefName.ProgramVersion]) >= new Version(bugFixed.VersionsFixed.Split(';').Last())).ToList(); if (listIssueSubs.Count > 0) { MsgBox.Show("FormBugSubmissions", "There appears to be a submission on a version that is newer than the previous fixed bug version (BugId: " + POut.Long(bugFixed.BugId) + "). " + "These will be excluded."); //TODO: Allow user to view these excluded submissions somehow. pair.Value.RemoveAll(x => listIssueSubs.Contains(x)); if (pair.Value.Count == 0) { continue; } } } if (!isAutoAssign) { FormBugSubmissions formGroupBugSubs = new FormBugSubmissions(viewMode: FormBugSubmissionMode.ValidationMode); formGroupBugSubs.ListViewedSubs = pair.Value; //Add unnattached submissions to grid formGroupBugSubs.ListViewedSubs.AddRange(dictAttachedSubs[pair.Key]); //Add already attached submissions to grid formGroupBugSubs.StartPosition = FormStartPosition.Manual; Point newLoc = pointFormLocaiton; newLoc.X += 10; //Offset newLoc.Y += 10; formGroupBugSubs.Location = newLoc; if (formGroupBugSubs.ShowDialog() != DialogResult.OK) { continue; } } BugSubmissions.UpdateBugIds(pair.Key, pair.Value.Select(x => x.BugSubmissionNum).ToList()); } MsgBox.Show("FormBugSubmissions", "Done."); return(true); }
public static bool TryAssociateSimilarBugSubmissions(Point pointFormLocaiton) { List <BugSubmission> listAllSubs = BugSubmissions.GetAll(); List <BugSubmission> listUnattachedSubs = listAllSubs.Where(x => x.BugId == 0).ToList(); if (listUnattachedSubs.Count == 0) { MsgBox.Show("FormBugSubmissions", "All submissions are associated to bugs already."); return(false); } //Dictionary where key is a BugId and the value is list of submissions associated to that BugID. //StackTraces are unique and if there are duplicate stack trace entries we select the one with the newest version. Dictionary <long, List <BugSubmission> > dictAttachedSubs = listAllSubs.Where(x => x.BugId != 0) .GroupBy(x => x.BugId) .ToDictionary(x => x.Key, x => x.GroupBy(y => y.ExceptionStackTrace) //Sub dictionary of unique ExceptionStackStraces as the key and the value is the submission from the highest version. .ToDictionary(y => y.Key, y => y.OrderByDescending(z => new Version(z.Info.DictPrefValues[PrefName.ProgramVersion])).First()) .Values.ToList() ); Dictionary <long, List <BugSubmission> > dictSimilarBugSubs = new Dictionary <long, List <BugSubmission> >(); List <long> listOrderedKeys = dictAttachedSubs.Keys.OrderByDescending(x => x).ToList(); foreach (long key in listOrderedKeys) //Loop through submissions that are already attached to bugs { dictSimilarBugSubs[key] = new List <BugSubmission>(); foreach (BugSubmission sub in dictAttachedSubs[key]) //Loop through the unique exception text from the submission with thie highest reported version. { List <BugSubmission> listSimilarBugSubs = listUnattachedSubs.Where(x => x.ExceptionStackTrace == sub.ExceptionStackTrace//Find submissions that are not attached to bugs with identical ExceptionStackTrace ).ToList(); if (listSimilarBugSubs.Count == 0) { continue; //All submissions with this stack trace are attached to a bug. } listUnattachedSubs.RemoveAll(x => listSimilarBugSubs.Contains(x)); dictSimilarBugSubs[key].AddRange(listSimilarBugSubs); } } if (dictSimilarBugSubs.All(x => x.Value.Count == 0)) { MsgBox.Show("FormBugSubmissions", "All similar submissions are already attached to bugs. No action needed."); return(false); } dictSimilarBugSubs = dictSimilarBugSubs.Where(x => x.Value.Count != 0).ToDictionary(x => x.Key, x => x.Value); bool isAutoAssign = (MsgBox.Show("FormBugSubmissions", MsgBoxButtons.YesNo, "Click Yes to auto attach duplicate submissions to bugs with identical stack traces?" + "\r\nClick No to manually validate all groupings found.")); List <long> listBugIds = listAllSubs.Where(x => x.BugId != 0).Select(x => x.BugId).ToList(); List <JobLink> listLinks = JobLinks.GetManyForType(JobLinkType.Bug, listBugIds); List <Bug> listBugs = Bugs.GetMany(listBugIds); StringBuilder issueSubmissionPrompt = new StringBuilder(); foreach (KeyValuePair <long, List <BugSubmission> > pair in dictSimilarBugSubs) { Bug bugFixed = listBugs.FirstOrDefault(x => x.BugId == pair.Key && !string.IsNullOrEmpty(x.VersionsFixed)); if (bugFixed != null) { List <BugSubmission> listIssueSubs = pair.Value.Where(x => new Version(x.Info.DictPrefValues[PrefName.ProgramVersion]) >= new Version(bugFixed.VersionsFixed.Split(';').Last())).ToList(); if (listIssueSubs.Count > 0) { List <JobLink> listBugJobLinks = listLinks.FindAll(x => x.FKey == bugFixed.BugId); List <Job> listBugJobs = Jobs.GetMany(listBugJobLinks.Select(x => x.JobNum).ToList()); if (issueSubmissionPrompt.Length == 0) { issueSubmissionPrompt.AppendLine("The following completed jobs have submissions from newer versions then the jobs reported fixed version: "); } listBugJobs.ForEach(x => issueSubmissionPrompt.AppendLine("- " + " (" + x.Category.ToString().Substring(0, 1) + x.JobNum + ")" + x.Title)); pair.Value.RemoveAll(x => listIssueSubs.Contains(x)); if (pair.Value.Count == 0) { continue; } } } if (!isAutoAssign) { FormBugSubmissions formGroupBugSubs = new FormBugSubmissions(viewMode: FormBugSubmissionMode.ValidationMode); formGroupBugSubs.ListViewedSubs = pair.Value; //Add unnattached submissions to grid formGroupBugSubs.ListViewedSubs.AddRange(dictAttachedSubs[pair.Key]); //Add already attached submissions to grid formGroupBugSubs.StartPosition = FormStartPosition.Manual; Point newLoc = pointFormLocaiton; newLoc.X += 10; //Offset newLoc.Y += 10; formGroupBugSubs.Location = newLoc; if (formGroupBugSubs.ShowDialog() != DialogResult.OK) { continue; } } BugSubmissions.UpdateBugIds(pair.Key, pair.Value.Select(x => x.BugSubmissionNum).ToList()); } string msg = ""; dictSimilarBugSubs.Keys.ToList().FindAll(x => dictSimilarBugSubs[x].Count > 0) .ForEach(x => msg += "Bug: " + x + " Found submissions: " + dictSimilarBugSubs[x].Count + "\r\n"); msg += issueSubmissionPrompt.ToString(); new MsgBoxCopyPaste(msg) { Text = "Done" }.ShowDialog(); return(true); }