From 681f1e97f4978311d7f81512e176c63a9da1ac26 Mon Sep 17 00:00:00 2001 From: SHM Date: Tue, 23 Sep 2025 10:03:12 +0900 Subject: [PATCH] =?UTF-8?q?[=EC=84=B1=ED=98=84=EB=AA=A8]=20TestTrend=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Web.Tra/Components/Module/TitleCard.razor | 4 +- .../Web.Tra/Components/Module/TraGrid.razor | 19 +- .../Web.Tra/Components/Pages/TRA.razor | 246 +++++++++++++----- .../Web.Tra/Extended/ObjectExtended.cs | 58 ++++- .../WebClient/Web.Tra/Model/Enum/EnumTabs.cs | 2 + Projects/WebClient/Web.Tra/Model/OrderdTab.cs | 2 +- .../WebClient/Web.Tra/Model/SearchData.cs | 12 + .../WebClient/Web.Tra/Model/TestResult.cs | 1 + Projects/WebClient/Web.Tra/Model/TestTrend.cs | 44 ++++ .../Web.Tra/Services/CPXV2LogService.cs | 21 ++ 10 files changed, 337 insertions(+), 72 deletions(-) create mode 100644 Projects/WebClient/Web.Tra/Model/TestTrend.cs diff --git a/Projects/WebClient/Web.Tra/Components/Module/TitleCard.razor b/Projects/WebClient/Web.Tra/Components/Module/TitleCard.razor index e6fcf23..9832f65 100644 --- a/Projects/WebClient/Web.Tra/Components/Module/TitleCard.razor +++ b/Projects/WebClient/Web.Tra/Components/Module/TitleCard.razor @@ -1,9 +1,9 @@ - + - + @ChildContent diff --git a/Projects/WebClient/Web.Tra/Components/Module/TraGrid.razor b/Projects/WebClient/Web.Tra/Components/Module/TraGrid.razor index 568d3ec..69ec7ba 100644 --- a/Projects/WebClient/Web.Tra/Components/Module/TraGrid.razor +++ b/Projects/WebClient/Web.Tra/Components/Module/TraGrid.razor @@ -1,5 +1,5 @@ @using WebClient.Library.Model -@typeparam TDataModel +@typeparam TDataModel OnSelectRow { get; set; } [Parameter] - public EventCallback OnDoubleClickRow{ get; set; } + public EventCallback OnDoubleClickRow { get; set; } + + [Parameter] + public int ParentTabId { get; set; } [Parameter] public bool VisibleRowNo { get; set; } @@ -136,7 +139,7 @@ // var cellData = args.Data as Overview; // if (cellData is null) // return; - + // if ((args.Column.Property.ToLower().Equals("testdate") || args.Column.Property.ToLower().Equals("host")) == false) // return; @@ -189,7 +192,7 @@ // args.Attributes.Add("rowspan", rowCount); // } } - + private async Task SelectRow(TDataModel data) { await OnSelectRow.InvokeAsync(data); @@ -197,6 +200,12 @@ private async Task OnRowDoublClick(DataGridRowMouseEventArgs args) { - await OnDoubleClickRow.InvokeAsync(args.Data); + var selectRow = new SelectRow + { + Row = args.Data as IDataModel, + ParentTabID = ParentTabId + }; + + await OnDoubleClickRow.InvokeAsync(selectRow); } } diff --git a/Projects/WebClient/Web.Tra/Components/Pages/TRA.razor b/Projects/WebClient/Web.Tra/Components/Pages/TRA.razor index 8758734..e899e08 100644 --- a/Projects/WebClient/Web.Tra/Components/Pages/TRA.razor +++ b/Projects/WebClient/Web.Tra/Components/Pages/TRA.razor @@ -68,7 +68,7 @@ - + @@ -124,14 +124,14 @@ @if (tab.Key.EnumTab == EnumTabs.OverviewC1Detail || tab.Key.EnumTab == EnumTabs.OverviewC1DetailMerged) { - } @if (tab.Key.EnumTab == EnumTabs.TestHistoryC1) { - } @@ -142,7 +142,7 @@ @{ - var history = tab.Key.Parent as TestHistory; + var history = tab.Key.Parent.Parent as TestHistory; if(history.TestResult.ToLower().Contains("ok") == true) { @@ -174,7 +174,7 @@ @if(tab.Value?.Count > 0) { + HostColumnMerge="false" EnumTab="@tab.Key.EnumTab" ParentTabId="@tab.Key.Id"> } @@ -187,7 +187,7 @@ @{ - var history = tab.Key.Parent as TestSummaryInformation; + var history = tab.Key.Parent.Parent as TestSummaryInformation; @foreach (var prop in history.GetType().GetProperties()) @@ -206,13 +206,96 @@ @if (tab.Value?.Count > 0) { - + } } + + @if (tab.Key.EnumTab == EnumTabs.TestTrendC1) + { + + + + @{ + var trend = tab.Key.Parent.Parent as TestTrend; + + + @foreach (var prop in trend.TestStepInfo.GetType().GetProperties()) + { + if (prop.Name.ToLower().Contains("min") || prop.Name.ToLower().Contains("max") || prop.Name.ToLower().Contains("average")) + continue; + + + @prop.Name + + + } + + + + + + @foreach (var prop in trend.TestDataInfo.GetType().GetProperties()) + { + if (prop.Name.ToLower().Contains("min") || prop.Name.ToLower().Contains("max") || prop.Name.ToLower().Contains("average")) + continue; + + + @prop.Name + + + } + + + + + + @foreach (var prop in trend.MesuredDataAnalysis.GetType().GetProperties()) + { + + @prop.Name + + + } + + + } + + + + @if (tab.Value?.Count > 0) + { + + + + + + + new TrendPoint { Category = Convert.ToInt32(x.RowNo), Value = Convert.ToDouble(x.Value) }))" + TItem="TrendPoint" LineType="LineType.Solid" ValueProperty="Value" CategoryProperty="Category" Title="Value" Stroke="rgba(255,0,0)"> + + new TrendPoint { Category = Convert.ToInt32(x.RowNo), Value = Convert.ToDouble(x.Min) }))" + TItem="TrendPoint" LineType="LineType.Dashed" ValueProperty="Value" CategoryProperty="Category" Title="MIN" Stroke="#2196f3" > + + new TrendPoint { Category = Convert.ToInt32(x.RowNo), Value = Convert.ToDouble(x.Max) }))" + TItem="TrendPoint" LineType="LineType.Dashed" ValueProperty="Value" CategoryProperty="Category" Title="MAX" Stroke="#2196f3"> + + + + + + + + + + } + + + } @@ -285,7 +368,7 @@ new OrderdTab { Id = tabId, TabName = $"{EnumTabs.OverviewC1} ({tabId})", EnumTab = EnumTabs.OverviewC1Merged, Parent = null }, key => overviews.Cast().ToList(), (key, oldValue) => overviews.Cast().ToList()); } - + SelectedTabIndex = Tabs.Count - 1; } @@ -304,9 +387,9 @@ } } - private async Task OnDoubleClickRowOverview(IDataModel row) + private async Task OnDoubleClickRowOverview(SelectRow row) { - var selectRow = row as Overview; + var selectRow = row.Row as Overview; if(selectRow is not null) { List detailOverviews = new(); @@ -317,7 +400,7 @@ int tabId = Tabs.Max(x => x.Key.Id) + 1; Tabs.AddOrUpdate( - new OrderdTab { Id = tabId, TabName = $"{EnumTabs.OverviewC1Detail} ({tabId})", EnumTab = EnumTabs.OverviewC1Detail, Parent = row }, + new OrderdTab { Id = tabId, TabName = $"{EnumTabs.OverviewC1Detail} ({tabId})", EnumTab = EnumTabs.OverviewC1Detail, Parent = new ParentRow { TabID = row.ParentTabID, Parent = row.Row } }, key => detailOverviews.Cast().ToList(), (key, oldValue) => detailOverviews.Cast().ToList()); } else @@ -326,27 +409,27 @@ int tabId = Tabs.Max(x => x.Key.Id) + 1; Tabs.AddOrUpdate( - new OrderdTab { Id = tabId, TabName = $"{EnumTabs.OverviewC1Detail} ({tabId})", EnumTab = EnumTabs.OverviewC1DetailMerged, Parent = row }, + new OrderdTab { Id = tabId, TabName = $"{EnumTabs.OverviewC1Detail} ({tabId})", EnumTab = EnumTabs.OverviewC1DetailMerged, Parent = new ParentRow { TabID = row.ParentTabID, Parent = row.Row } }, key => detailOverviews.Cast().ToList(), (key, oldValue) => detailOverviews.Cast().ToList()); } - + tabs.Reload(); SelectedTabIndex = Tabs.Count - 1; } } - private async Task OnDoubleClickRowDetailOverview(IDataModel row) + private async Task OnDoubleClickRowDetailOverview(SelectRow row) { List histories = new(); if (IsMergePartNumberOption == false) { - histories = await CPXV2LogService.GetTestHistory(SearchDataOverviews, row); + histories = await CPXV2LogService.GetTestHistory(SearchDataOverviews, row.Row); } else { - histories = await CPXV2LogService.GetTestHistoryMerged(SearchDataOverviews, row); + histories = await CPXV2LogService.GetTestHistoryMerged(SearchDataOverviews, row.Row); } - + //test summary int ok = histories.Count(x => x.TestResult.ToLower().Contains("ok")); int ng = histories.Count(x => !x.TestResult.ToLower().Contains("ok")); @@ -355,10 +438,10 @@ double testTimeAvg = histories.Average(x => Convert.ToInt32(x.Duration)) / 1000.0; double testTimeMin = histories.Min(x => Convert.ToInt32(x.Duration)) / 1000.0; double testTimeMax = histories.Max(x => Convert.ToInt32(x.Duration)) / 1000.0; - + int tabId = Tabs.Max(x => x.Key.Id) + 1; Tabs.AddOrUpdate( - new OrderdTab { Id = tabId, TabName = $"{EnumTabs.TestHistoryC1}({tabId})", EnumTab = EnumTabs.TestHistoryC1, Parent = row , + new OrderdTab { Id = tabId, TabName = $"{EnumTabs.TestHistoryC1}({tabId})", EnumTab = EnumTabs.TestHistoryC1, Parent = new ParentRow { TabID = row.ParentTabID, Parent = row.Row } , SummaryTestResult = $"Test Result: {ok + ng} (OK:{ok}/NG:{ng}) - Ratio:{ratio.ToString("F2")}%", SummaryTestTime = $"Test Time: Average={testTimeAvg.ToString("F2")}sec Min={testTimeMin.ToString("F2")}sec Max={testTimeMax.ToString("F2")}sec" }, key => histories.Cast().ToList(), (key, oldValue) => histories.Cast().ToList()); @@ -367,26 +450,102 @@ SelectedTabIndex = Tabs.Count - 1; } - private async Task OnDoubleClickRowHistory(IDataModel row) + private async Task OnDoubleClickRowHistory(SelectRow row) { - var selectRow = row as TestHistory; + var selectRow = row.Row as TestHistory; int testStepVersion = selectRow.StepVersion; if(Int32.TryParse(SelectionStepVersion, out var inputStepVersion) == true) { testStepVersion = inputStepVersion; } - var s = await CPXV2LogService.GetTestResult(row, testStepVersion); + var s = await CPXV2LogService.GetTestResult(row.Row, testStepVersion); int tabId = Tabs.Max(x => x.Key.Id) + 1; Tabs.AddOrUpdate( - new OrderdTab { Id = tabId, TabName = $"{EnumTabs.TestResultC1}({tabId})", EnumTab = EnumTabs.TestResultC1, Parent = row }, + new OrderdTab { Id = tabId, TabName = $"{EnumTabs.TestResultC1}({tabId})", EnumTab = EnumTabs.TestResultC1, Parent = new ParentRow { TabID = row.ParentTabID, Parent = row.Row } }, key => s?.ParseTestResult?.Cast()?.ToList(), (key, oldValue) => s?.ParseTestResult?.Cast()?.ToList()); tabs.Reload(); SelectedTabIndex = Tabs.Count - 1; } + private async Task OnSummary() + { + var selectedTab = Tabs.Select(x => x.Key)?.FirstOrDefault(x => x.Id == SelectedTabIndex); + if (selectedTab is not null) + { + //history에서만 summary 사용 + if (selectedTab.EnumTab == EnumTabs.TestHistoryC1) + { + if (Tabs.TryGetValue(selectedTab, out var data) == true) + { + if (Int32.TryParse(SelectionStepVersion, out int stepVersion) == true) + { + var testHistories = data.Cast().ToList(); + var summary = await CPXV2LogService.GetTestSummary(testHistories, stepVersion); + var summaryInformation = testHistories.GetTestSummaryInformation(); + + if (summary is not null && summaryInformation is not null) + { + summaryInformation.SearchRangeStart = (DateTime)new DateTime(RequestSearch.SearchStart, TimeOnly.MinValue); + summaryInformation.SearchRangeEnd = (DateTime)new DateTime(RequestSearch.SearchEnd, TimeOnly.MaxValue); + + int tabId = Tabs.Max(x => x.Key.Id) + 1; + Tabs.AddOrUpdate( + new OrderdTab { Id = tabId, TabName = $"{EnumTabs.TestSummaryC1}({tabId})", EnumTab = EnumTabs.TestSummaryC1, Parent = new ParentRow { TabID = selectedTab.Id, Parent = summaryInformation } }, + key => summary?.ParseTestSummary?.Cast()?.ToList(), (key, oldValue) => summary?.ParseTestSummary?.Cast()?.ToList()); + + tabs.Reload(); + SelectedTabIndex = Tabs.Count - 1; + } + } + } + } + else + { + LogXnet.WriteLine("Not history", LogXLabel.Warning); + } + } + } + + private async Task OnDoubleClickRowSummary(SelectRow row) + { + var selectRow = row.Row as ParseTestSummary; + if(selectRow is not null) + { + var historyTabId = Tabs.Select(x => x.Key)?.FirstOrDefault(x => x.Id == row.ParentTabID); + var selectedTab = Tabs.Select(x => x.Key)?.FirstOrDefault(x => x.Id == historyTabId.Id); + + if (selectedTab is not null) + { + if (selectedTab.EnumTab == EnumTabs.TestHistoryC1) + { + if (Tabs.TryGetValue(selectedTab, out var data) == true) + { + if (Int32.TryParse(SelectionStepVersion, out int stepVersion) == true) + { + var testHistories = data.Cast().ToList(); + var trend = await CPXV2LogService.GetTestTrend(testHistories, stepVersion, selectRow.StepNo); + + int tabId = Tabs.Max(x => x.Key.Id) + 1; + Tabs.AddOrUpdate( + new OrderdTab { Id = tabId, TabName = $"{EnumTabs.TestTrendC1}({tabId})", EnumTab = EnumTabs.TestTrendC1, Parent = new ParentRow { TabID = selectedTab.Id, Parent = trend } }, + key => trend?.ParseTestTrend?.Cast()?.ToList(), (key, oldValue) => trend?.ParseTestTrend?.Cast()?.ToList()); + + tabs.Reload(); + SelectedTabIndex = Tabs.Count - 1; + } + } + } + else + { + LogXnet.WriteLine("Not history", LogXLabel.Warning); + } + } + } + } + private void OnClickClose(int tabId) { CloseTab(tabId); @@ -429,45 +588,6 @@ await JS.InvokeVoidAsync("open", $"/testlist/{history.ProductNo}/{history.TestCode}/{SelectionStepVersion}", "_blank"); } - private async Task OnSummary() - { - var selectedTab = Tabs.Select(x => x.Key)?.FirstOrDefault(x=>x.Id == SelectedTabIndex); - if(selectedTab is not null) - { - //history에서만 summary 사용 - if(selectedTab.EnumTab == EnumTabs.TestHistoryC1) - { - if(Tabs.TryGetValue(selectedTab, out var data) == true) - { - if(Int32.TryParse(SelectionStepVersion, out int stepVersion) == true) - { - var testHistories = data.Cast().ToList(); - var summary = await CPXV2LogService.GetTestSummary(testHistories, stepVersion); - var summaryInformation = testHistories.GetTestSummaryInformation(); - - if(summary is not null && summaryInformation is not null) - { - summaryInformation.SearchRangeStart = (DateTime)new DateTime(RequestSearch.SearchStart, TimeOnly.MinValue); - summaryInformation.SearchRangeEnd = (DateTime)new DateTime(RequestSearch.SearchEnd, TimeOnly.MaxValue); - - int tabId = Tabs.Max(x => x.Key.Id) + 1; - Tabs.AddOrUpdate( - new OrderdTab { Id = tabId, TabName = $"{EnumTabs.TestSummaryC1}({tabId})", EnumTab = EnumTabs.TestSummaryC1, Parent = summaryInformation }, - key => summary?.ParseTestSummary?.Cast()?.ToList(), (key, oldValue) => summary?.ParseTestSummary?.Cast()?.ToList()); - - tabs.Reload(); - SelectedTabIndex = Tabs.Count - 1; - } - } - } - } - else - { - LogXnet.WriteLine("Not history",LogXLabel.Warning); - } - } - } - private async Task OnExportExcel() { diff --git a/Projects/WebClient/Web.Tra/Extended/ObjectExtended.cs b/Projects/WebClient/Web.Tra/Extended/ObjectExtended.cs index 4aabe5d..361e473 100644 --- a/Projects/WebClient/Web.Tra/Extended/ObjectExtended.cs +++ b/Projects/WebClient/Web.Tra/Extended/ObjectExtended.cs @@ -2,6 +2,8 @@ using SystemX.Core.DB; using Web.Tra.Model; using SystemX.Core.Utils; +using Microsoft.AspNetCore.Mvc.Infrastructure; +using Radzen.Blazor; public static class ObjectExtend { @@ -101,6 +103,7 @@ public static class ObjectExtend //parse var parse = logData.Select(x=>x.ParseTestResult(testList)).Where(x=> x is not null && string.IsNullOrEmpty(x.MeasuredValue) == false).ToList(); testResult.ParseTestResult = parse; + testResult.No = (long)histTestResult.No; return testResult; } @@ -195,7 +198,14 @@ public static class ObjectExtend if (rows.FirstOrDefault().Dimension.ToLower() == "dez" || rows.FirstOrDefault().Dimension.ToLower() == "v" || rows.FirstOrDefault().Dimension.ToLower() == "float" || rows.FirstOrDefault().Dimension.ToLower() == "int") { - summary.Average = rows.Average(x => Convert.ToDouble(x.MeasuredValue)).ToString(); + try + { + summary.Average = rows.Average(x => Convert.ToDouble(x.MeasuredValue)).ToString(); + } + catch(Exception e) + { + summary.Average = string.Empty; + } } else { @@ -231,4 +241,50 @@ public static class ObjectExtend TestRequestsID = testHistories.FirstOrDefault().TestListReqID, }; } + + public static TestTrend ToTestTrend(this List histories, List testResult, TestSummary summary, int stepId) + { + TestTrend result = new TestTrend(); + result.ParseTestTrend = new List(); + result.TestStepInfo = summary.ParseTestSummary.Where(x=>x.StepNo == stepId)?.FirstOrDefault(); + result.TestDataInfo = histories.GetTestSummaryInformation(); + + if (histories?.Count > 0) + { + int rowNo = 0; + foreach (var history in histories.OrderBy(x=>x.TestDateTime)) + { + var r = testResult.Where(x => x.No == history.No)?.FirstOrDefault(); + if (r is not null) + { + var step = r.ParseTestResult.Where(x => x.StepNo == stepId)?.FirstOrDefault(); + if(step is not null) + { + result.ParseTestTrend.Add(new ParseTestTrend + { + RowNo = rowNo + 1, + TestTime = (DateTime)history.TestDateTime, + MO = step.MO, + ProductID = history.ProductID, + Min = step.Min, + Value = step.MeasuredValue, + Max = step.Max, + Result = step.Result, + Duration = step.Duration + }); + } + } + rowNo += 1; + } + } + + result.MesuredDataAnalysis = new MesuredDataAnalysis + { + Average = result.ParseTestTrend.Average(x => x.Value.GetType()== typeof(double) ? Convert.ToDouble(x.Value) : 0.0), + Min = result.ParseTestTrend.Min(x => x.Value.GetType() == typeof(double) ? Convert.ToDouble(x.Value) : 0.0), + Max = result.ParseTestTrend.Max(x => x.Value.GetType() == typeof(double) ? Convert.ToDouble(x.Value) : 0.0), + }; + + return result; + } } \ No newline at end of file diff --git a/Projects/WebClient/Web.Tra/Model/Enum/EnumTabs.cs b/Projects/WebClient/Web.Tra/Model/Enum/EnumTabs.cs index efa9cb6..20b4ce7 100644 --- a/Projects/WebClient/Web.Tra/Model/Enum/EnumTabs.cs +++ b/Projects/WebClient/Web.Tra/Model/Enum/EnumTabs.cs @@ -16,6 +16,8 @@ TestSummaryC1 = 50, + TestTrendC1 = 60, + TestListFile = 1000, End = 10000 diff --git a/Projects/WebClient/Web.Tra/Model/OrderdTab.cs b/Projects/WebClient/Web.Tra/Model/OrderdTab.cs index a529591..e7d3c2b 100644 --- a/Projects/WebClient/Web.Tra/Model/OrderdTab.cs +++ b/Projects/WebClient/Web.Tra/Model/OrderdTab.cs @@ -8,7 +8,7 @@ namespace Web.Tra.Model public string TabName { get; set; } public EnumTabs EnumTab { get; set; } - public IDataModel Parent { get; set; } + public ParentRow Parent { get; set; } public string SummaryTestResult { get; set; } public string SummaryTestTime { get; set; } diff --git a/Projects/WebClient/Web.Tra/Model/SearchData.cs b/Projects/WebClient/Web.Tra/Model/SearchData.cs index 8399601..a0665b4 100644 --- a/Projects/WebClient/Web.Tra/Model/SearchData.cs +++ b/Projects/WebClient/Web.Tra/Model/SearchData.cs @@ -23,4 +23,16 @@ namespace Web.Tra.Model public PROD_Group PROD_Group { get; set; } public PROD_Variant PROD_Variant { get; set; } } + + public class SelectRow() + { + public int ParentTabID { get; set; } + public IDataModel Row { get; set; } + } + + public class ParentRow() + { + public int TabID { get; set; } + public IDataModel Parent { get; set; } + } } diff --git a/Projects/WebClient/Web.Tra/Model/TestResult.cs b/Projects/WebClient/Web.Tra/Model/TestResult.cs index 22bb545..1ae5a42 100644 --- a/Projects/WebClient/Web.Tra/Model/TestResult.cs +++ b/Projects/WebClient/Web.Tra/Model/TestResult.cs @@ -10,6 +10,7 @@ namespace Web.Tra.Model public List ParseTestResult { get; set; } //test list data + public long No { get; set; } public TestList? TestList { get; set; } } diff --git a/Projects/WebClient/Web.Tra/Model/TestTrend.cs b/Projects/WebClient/Web.Tra/Model/TestTrend.cs new file mode 100644 index 0000000..1228a9c --- /dev/null +++ b/Projects/WebClient/Web.Tra/Model/TestTrend.cs @@ -0,0 +1,44 @@ +namespace Web.Tra.Model +{ + public class TestTrend : IDataModel + { + public ParseTestSummary TestStepInfo { get; set; } + public TestSummaryInformation TestDataInfo { get; set; } + + public MesuredDataAnalysis MesuredDataAnalysis { get; set; } + + public List ParseTestTrend { get; set; } + } + + public class ParseTestTrend : IDataModel + { + public int RowNo { get; set; } + public DateTime TestTime { get; set; } + public string MO { get; set; } + public string ProductID { get; set; } + public string Min { get; set; } + public string Value { get; set; } + public string Max { get; set; } + public string Result { get; set; } + public string Duration { get; set; } + } + + public class MesuredDataAnalysis : IDataModel + { + public double Average { get; set; } + public double Min { get; set; } + public double Max { get; set; } + public double Varaince { get; set; } + public double Std_Dev { get; set; } + public double Cp { get; set; } + public double Cpk { get; set; } + public double Cg { get; set; } + } + + public class TrendPoint + { + public int inex { get; set; } + public int Category { get; set; } + public double Value { get; set; } + } +} diff --git a/Projects/WebClient/Web.Tra/Services/CPXV2LogService.cs b/Projects/WebClient/Web.Tra/Services/CPXV2LogService.cs index 9df8045..b92ee03 100644 --- a/Projects/WebClient/Web.Tra/Services/CPXV2LogService.cs +++ b/Projects/WebClient/Web.Tra/Services/CPXV2LogService.cs @@ -329,6 +329,27 @@ namespace Web.Tra.Services return result; } + public async Task GetTestTrend(List histories, int stepVersion, int stepId) + { + TestTrend result = new TestTrend(); + + if (histories?.Count() > 0) + { + List getTestResults = new List(); + + //test result parse + foreach (var hist in histories) + { + getTestResults.Add(await GetTestResult(hist, stepVersion)); + } + + result = histories.ToTestTrend(getTestResults, getTestResults.ToTestSummary(), stepId); + } + + await Task.CompletedTask; + return result; + } + public bool TryParseTestCode(string testCode, out int outValue) { bool result = false;